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/CheckBox/CheckBox.razor.cs

255 lines
6.6 KiB

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 CheckBox<T> : BooleanInput<T>
{
protected string Classname =>
new CssBuilder("mud-input-control-boolean-input")
.AddClass(Class)
.Build();
protected string LabelClassname =>
new CssBuilder("mud-checkbox")
.AddClass($"mud-disabled", Disabled)
.AddClass($"mud-readonly", ReadOnly)
.AddClass(LabelPosition == LabelPosition.End ? "mud-ltr" : "mud-rtl", true)
.Build();
protected string CheckBoxClassname =>
new CssBuilder("mud-button-root mud-icon-button")
.AddClass($"mud-{Color.ToDescriptionString()}-text hover:mud-{Color.ToDescriptionString()}-hover", UnCheckedColor == null || (UnCheckedColor != null && BoolValue == true))
.AddClass($"mud-{UnCheckedColor?.ToDescriptionString()}-text hover:mud-{UnCheckedColor?.ToDescriptionString()}-hover", UnCheckedColor != null && BoolValue == false)
.AddClass($"mud-checkbox-dense", Dense)
.AddClass($"mud-ripple mud-ripple-checkbox", !DisableRipple && !ReadOnly && !Disabled)
.AddClass($"mud-disabled", Disabled)
.AddClass($"mud-readonly", ReadOnly)
.Build();
/// <summary>
/// The color of the component. It supports the theme colors.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.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 text/label will be displayed next to the checkbox if set.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Behavior)]
public string Label { get; set; }
/// <summary>
/// The position of the text/label.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Behavior)]
public LabelPosition LabelPosition { get; set; } = LabelPosition.End;
/// <summary>
/// If true, the checkbox can be controlled with the keyboard.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Behavior)]
public bool KeyboardEnabled { get; set; } = true;
/// <summary>
/// If true, disables ripple effect.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Appearance)]
public bool DisableRipple { get; set; }
/// <summary>
/// If true, compact padding will be applied.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Appearance)]
public bool Dense { get; set; }
/// <summary>
/// The Size of the component.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Appearance)]
public Size Size { get; set; } = Size.Medium;
/// <summary>
/// Child content of component.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Behavior)]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Custom checked icon, leave null for default.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Appearance)]
public string CheckedIcon { get; set; } = Icons.Material.Filled.CheckBox;
/// <summary>
/// Custom unchecked icon, leave null for default.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Appearance)]
public string UncheckedIcon { get; set; } = Icons.Material.Filled.CheckBoxOutlineBlank;
/// <summary>
/// Custom indeterminate icon, leave null for default.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Appearance)]
public string IndeterminateIcon { get; set; } = Icons.Material.Filled.IndeterminateCheckBox;
/// <summary>
/// Define if the checkbox can cycle again through indeterminate status.
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Validation)]
public bool TriState { get; set; }
private string GetIcon()
{
if (BoolValue == true)
{
return CheckedIcon;
}
if (BoolValue == false)
{
return UncheckedIcon;
}
return IndeterminateIcon;
}
protected override Task OnChange(ChangeEventArgs args)
{
Modified = true;
// Apply only when TriState parameter is set to true and T is bool?
if (TriState && typeof(T) == typeof(bool?))
{
// The cycle is forced with the following steps: true, false, indeterminate, true, false, indeterminate...
if (!((bool?)(object)_value).HasValue)
{
return SetBoolValueAsync(true);
}
else
{
return ((bool?)(object)_value).Value ? SetBoolValueAsync(false) : SetBoolValueAsync(default);
}
}
else
{
return SetBoolValueAsync((bool?)args.Value);
}
}
protected void HandleKeyDown(KeyboardEventArgs obj)
{
if (Disabled || ReadOnly || !KeyboardEnabled)
return;
switch (obj.Key)
{
case "Delete":
SetBoolValueAsync(false);
break;
case "Enter":
case "NumpadEnter":
SetBoolValueAsync(true);
break;
case "Backspace":
if (TriState)
{
SetBoolValueAsync(null);
}
break;
case " ":
if (BoolValue == null)
{
SetBoolValueAsync(true);
}
else if (BoolValue == true)
{
SetBoolValueAsync(false);
}
else if (BoolValue == false)
{
if (TriState == true)
{
SetBoolValueAsync(null);
}
else
{
SetBoolValueAsync(true);
}
}
break;
}
}
private IKeyInterceptor _keyInterceptor;
[Inject] private IKeyInterceptorFactory _keyInterceptorFactory { get; set; }
private string _elementId = "checkbox" + Guid.NewGuid().ToString().Substring(0, 8);
protected override void OnInitialized()
{
base.OnInitialized();
if (Label == null && For != null)
Label = For.GetLabelString();
}
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" },
},
});
_keyInterceptor.KeyDown += HandleKeyDown;
}
await base.OnAfterRenderAsync(firstRender);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing == true)
{
if (_keyInterceptor != null)
{
_keyInterceptor.KeyDown -= HandleKeyDown;
_keyInterceptor.Dispose();
}
}
}
}