You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Components/Components/Radio/Radio.razor.cs

227 lines
6.5 KiB

2 years ago
using Connected.Annotations;
using Connected.Extensions;
using Connected.Services;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace Connected.Components;
public partial class Radio<T> : UIComponent, IDisposable
{
[CascadingParameter(Name = "RightToLeft")] public bool RightToLeft { get; set; }
protected string Classname =>
new CssBuilder("mud-radio")
.AddClass($"mud-disabled", Disabled)
.AddClass($"mud-radio-content-placement-{ConvertPlacement(Placement).ToDescriptionString()}")
.AddClass(Class)
.Build();
protected string ButtonClassname =>
new CssBuilder("mud-button-root mud-icon-button")
.AddClass($"mud-ripple mud-ripple-radio", !DisableRipple && !Disabled)
.AddClass($"mud-{Color.ToDescriptionString()}-text hover:mud-{Color.ToDescriptionString()}-hover", UnCheckedColor == null || (UnCheckedColor != null && Checked == true))
.AddClass($"mud-{UnCheckedColor?.ToDescriptionString()}-text hover:mud-{UnCheckedColor?.ToDescriptionString()}-hover", UnCheckedColor != null && Checked == false)
.AddClass($"mud-radio-dense", Dense)
.AddClass($"mud-disabled", Disabled)
.AddClass($"mud-checked", Checked)
.AddClass("mud-error-text", RadioGroup?.HasErrors)
.Build();
protected string RadioIconsClassNames =>
new CssBuilder("mud-radio-icons")
.AddClass($"mud-checked", Checked)
.Build();
protected string IconClassName =>
new CssBuilder("mud-icon-root mud-svg-icon")
.AddClass($"mud-icon-size-{Size.ToDescriptionString()}")
.Build();
protected string CheckedIconClassName =>
new CssBuilder("mud-icon-root mud-svg-icon mud-radio-icon-checked")
.AddClass($"mud-icon-size-{Size.ToDescriptionString()}")
.Build();
protected string ChildSpanClassName =>
new CssBuilder("mud-radio-content mud-typography mud-typography-body1")
.AddClass("mud-error-text", RadioGroup.HasErrors)
.Build();
private IRadioGroup _parent;
/// <summary>
/// The parent Radio Group
/// </summary>
[CascadingParameter]
internal IRadioGroup ParentGroup
{
get => _parent;
set
{
_parent = value;
if (_parent == null)
return;
_parent.CheckGenericTypeMatch(this);
//MudRadioGroup<T>?.Add(this);
}
}
internal RadioGroup<T> RadioGroup => (RadioGroup<T>)ParentGroup;
private Placement ConvertPlacement(Placement placement)
{
return placement switch
{
Placement.Left => RightToLeft ? Placement.End : Placement.Start,
Placement.Right => RightToLeft ? Placement.Start : Placement.End,
_ => placement
};
}
/// <summary>
/// The color of the component. It supports the theme colors.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Appearance)]
public ThemeColor Color { get; set; } = ThemeColor.Default;
/// <summary>
/// The base color of the component in its none active/unchecked state. It supports the theme colors.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Appearance)]
public ThemeColor? UnCheckedColor { get; set; } = null;
/// <summary>
/// The position of the child content.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Behavior)]
public Placement Placement { get; set; } = Placement.End;
/// <summary>
/// The value to associate to the button.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Behavior)]
public T Option { get; set; }
/// <summary>
/// If true, compact padding will be applied.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Appearance)]
public bool Dense { get; set; }
/// <summary>
/// The Size of the component.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Appearance)]
public Size Size { get; set; } = Size.Medium;
/// <summary>
/// If true, disables ripple effect.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Appearance)]
public bool DisableRipple { get; set; }
/// <summary>
/// If true, the button will be disabled.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Behavior)]
public bool Disabled { get; set; }
/// <summary>
/// Child content of component.
/// </summary>
[Parameter]
[Category(CategoryTypes.Radio.Behavior)]
public RenderFragment ChildContent { get; set; }
internal bool Checked { get; private set; }
internal void SetChecked(bool value)
{
if (Checked != value)
{
Checked = value;
StateHasChanged();
}
}
public void Select()
{
RadioGroup?.SetSelectedRadioAsync(this).AndForget();
}
internal Task OnClick()
{
if (RadioGroup != null)
return RadioGroup.SetSelectedRadioAsync(this);
return Task.CompletedTask;
}
protected internal void HandleKeyDown(KeyboardEventArgs obj)
{
if (Disabled)
return;
switch (obj.Key)
{
case "Enter":
case "NumpadEnter":
case " ":
Select();
break;
case "Backspace":
RadioGroup.Reset();
break;
}
}
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
if (RadioGroup != null)
await RadioGroup.RegisterRadioAsync(this);
}
public void Dispose()
{
RadioGroup?.UnregisterRadio(this);
_keyInterceptor?.Dispose();
}
private IKeyInterceptor _keyInterceptor;
[Inject] private IKeyInterceptorFactory _keyInterceptorFactory { get; set; }
private string _elementId = "radio" + Guid.NewGuid().ToString().Substring(0, 8);
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_keyInterceptor = _keyInterceptorFactory.Create();
await _keyInterceptor.Connect(_elementId, new KeyInterceptorOptions()
{
//EnableLogging = true,
TargetClass = "mud-button-root",
Keys = {
new KeyOptions { Key=" ", PreventDown = "key+none", PreventUp = "key+none" }, // prevent scrolling page
new KeyOptions { Key="Enter", PreventDown = "key+none" },
new KeyOptions { Key="NumpadEnter", PreventDown = "key+none" },
new KeyOptions { Key="Backspace", PreventDown = "key+none" },
},
});
}
await base.OnAfterRenderAsync(firstRender);
}
}