From 0d9a651a57a4a4938e4b40cf44c504e20d1eeaf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Mon, 22 Dec 2025 20:18:34 +0300 Subject: [PATCH 1/9] Migrate to Mud 9 and .NET 10 --- .../wwwroot/CodeBeam.MudBlazor.Extensions.xml | 98 +++---- .../CodeBeam.MudBlazor.Extensions.Docs.csproj | 2 +- .../Examples/StepperExtendedExample3.razor | 2 +- .../Components/SelectExtendedTests.cs | 6 +- .../Mocks/MockScrollServices.cs | 2 + .../Base/Identifier.cs | 44 +++ .../Base/MudBaseInputExtended.cs | 252 +++++++++++++----- .../CodeBeam.MudBlazor.Extensions.csproj | 21 +- .../ChipField/MudChipField.razor.cs | 8 +- .../CodeInput/MudCodeInput.razor.cs | 10 +- .../Components/ComboBox/MudComboBox.razor | 2 +- .../Components/ComboBox/MudComboBox.razor.cs | 39 +-- .../ComboBox/MudComboBoxItem.razor.cs | 6 +- .../MudDateWheelPicker.razor.cs | 23 +- .../Components/FontPicker/MudFontPicker.razor | 2 +- .../InputExtended/MudInputExtended.razor | 28 +- .../InputExtended/MudInputExtended.razor.cs | 63 ++--- .../ListExtended/MudListExtended.razor.cs | 23 +- .../PasswordField/MudPasswordField.razor | 2 - .../RangeSlider/MudRangeSlider.razor | 4 +- .../RangeSlider/MudRangeSlider.razor.cs | 4 +- .../SelectExtended/MudSelectExtended.razor | 4 +- .../SelectExtended/MudSelectExtended.razor.cs | 30 +-- .../MudSelectItemExtended.razor.cs | 2 +- .../SignaturePad/MudSignaturePad.razor.cs | 2 +- .../MudTextFieldExtended.razor.cs | 5 +- .../Components/Wheel/MudWheel.razor | 6 +- .../Components/Wheel/MudWheel.razor.cs | 15 +- 28 files changed, 395 insertions(+), 310 deletions(-) create mode 100644 CodeBeam.MudBlazor.Extensions/Base/Identifier.cs diff --git a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml index 8ebe757d..26c53a5a 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml +++ b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml @@ -4,12 +4,37 @@ CodeBeam.MudBlazor.Extensions + + + Provides methods to create unique identifiers with optional prefixes. + + + + + Creates a unique identifier with the specified prefix. + + The prefix to prepend to the unique identifier. + A unique identifier string with the specified prefix. + prefixdb54bcd0 + + + + Creates a unique identifier. + + A unique identifier string. + adb54bcd0 + The extended base input fundamentals. + + + + + @@ -47,6 +72,14 @@ Fires on change. + + + The ID of the input element. + + + When set takes precedence over any internally generated IDs. + + Set the text-align on the component. @@ -272,11 +305,6 @@ Fired when the element changes internally its text value. - - - - - @@ -347,31 +375,13 @@ Value change hook for descendants. Called when Value needs to be refreshed from current Text property. - - - - - - - - - - - - - - - Conversion format parameter for ToString(), can be used for formatting primitive types, DateTimes and TimeSpans + The format applied to values. - - - - - - - + + This property is passed into the ToString() method of the property, such as formatting int, float, DateTime and TimeSpan values. + @@ -392,16 +402,6 @@ - - - - - - - - - - @@ -1594,11 +1594,6 @@ - - - - - @@ -2149,20 +2144,6 @@ - - - - - - - - - - - - - - Forces input height to fit the text content. @@ -4518,6 +4499,11 @@ + + + Internal method for MudSelectItem to access the converted string value. + + Represents an option of a select or multi-select. To be used inside MudSelect. diff --git a/CodeBeam.MudBlazor.Extensions.Docs/CodeBeam.MudBlazor.Extensions.Docs.csproj b/CodeBeam.MudBlazor.Extensions.Docs/CodeBeam.MudBlazor.Extensions.Docs.csproj index 155590d5..29b75f64 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs/CodeBeam.MudBlazor.Extensions.Docs.csproj +++ b/CodeBeam.MudBlazor.Extensions.Docs/CodeBeam.MudBlazor.Extensions.Docs.csproj @@ -14,7 +14,7 @@ - + diff --git a/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/StepperExtended/Examples/StepperExtendedExample3.razor b/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/StepperExtended/Examples/StepperExtendedExample3.razor index 38301538..c0e88eb0 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/StepperExtended/Examples/StepperExtendedExample3.razor +++ b/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/StepperExtended/Examples/StepperExtendedExample3.razor @@ -161,7 +161,7 @@ private async Task BeforeFinishedAsync() { - var result = await DialogService.ShowMessageBox( + var result = await DialogService.ShowMessageBoxAsync( "Confirm", "All steps are completed. Do you want to finish?", yesText: "Finish", diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs index f9ca958c..13ec29f9 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs @@ -863,7 +863,7 @@ public async Task TextField_Should_Validate_Data_Attribute_Fail() select.Value.Should().Be("Quux"); select.Text.Should().Be("Quux"); // check validity - await comp.InvokeAsync(() => select.Validate()); + await comp.InvokeAsync(() => select.ValidateAsync()); select.ValidationErrors.Should().NotBeEmpty(); select.ValidationErrors.Should().HaveCount(1); select.ValidationErrors[0].Should().Be("Should not be longer than 3"); @@ -882,7 +882,7 @@ public async Task TextField_Should_Validate_Data_Attribute_Success() select.Value.Should().Be("Qux"); select.Text.Should().Be("Qux"); // check validity - await comp.InvokeAsync(() => select.Validate()); + await comp.InvokeAsync(() => select.ValidateAsync()); select.ValidationErrors.Should().BeEmpty(); } #endregion @@ -896,7 +896,7 @@ public async Task Select_Should_SetRequiredTrue() var comp = Context.RenderComponent(); var select = comp.FindComponent>().Instance; select.Required.Should().BeTrue(); - await comp.InvokeAsync(() => select.Validate()); + await comp.InvokeAsync(() => select.ValidateAsync()); select.ValidationErrors.First().Should().Be("Required"); } diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Mocks/MockScrollServices.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Mocks/MockScrollServices.cs index 3ceed471..19ab6529 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Mocks/MockScrollServices.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Mocks/MockScrollServices.cs @@ -65,6 +65,8 @@ public class MockScrollManager : IScrollManager public ValueTask ScrollToYearAsync(string elementId) => ValueTask.CompletedTask; public ValueTask UnlockScrollAsync(string elementId, string cssClass) => ValueTask.CompletedTask; + + public ValueTask ScrollToVirtualizedItemAsync(string containerId, int itemIndex, double itemHeight, string targetItemId, ScrollBehavior scrollBehavior = ScrollBehavior.Auto) => ValueTask.CompletedTask; } public class MockScrollManagerExtended : IScrollManagerExtended diff --git a/CodeBeam.MudBlazor.Extensions/Base/Identifier.cs b/CodeBeam.MudBlazor.Extensions/Base/Identifier.cs new file mode 100644 index 00000000..56a1282d --- /dev/null +++ b/CodeBeam.MudBlazor.Extensions/Base/Identifier.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MudExtensions.Base +{ + /// + /// Provides methods to create unique identifiers with optional prefixes. + /// + internal static class Identifier + { + private const string Chars = "abcdefghijklmnopqrstuvwxyz0123456789"; + private const int CharsLength = 35; + private const int RandomStringLength = 8; + + /// + /// Creates a unique identifier with the specified prefix. + /// + /// The prefix to prepend to the unique identifier. + /// A unique identifier string with the specified prefix. + /// prefixdb54bcd0 + internal static string Create(ReadOnlySpan prefix) + { + Span identifierSpan = stackalloc char[prefix.Length + RandomStringLength]; + prefix.CopyTo(identifierSpan); + for (var i = 0; i < RandomStringLength; i++) + { + var index = Random.Shared.Next(CharsLength); + identifierSpan[prefix.Length + i] = Chars[index]; + } + + return identifierSpan.ToString(); + } + + /// + /// Creates a unique identifier. + /// + /// A unique identifier string. + /// adb54bcd0 + internal static string Create() => Create(['a']); + } +} diff --git a/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs b/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs index 4582098f..2a20f997 100644 --- a/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs +++ b/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs @@ -1,8 +1,9 @@ -using System.Globalization; -using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using MudBlazor; +using MudBlazor.State; using MudBlazor.Utilities; +using MudExtensions.Base; namespace MudExtensions { @@ -14,11 +15,49 @@ public abstract class MudBaseInputExtended : MudFormComponent { private bool _isDirty; private bool _validated; + protected bool _isFocused; + protected bool _forceTextUpdate; + protected string? InputElementId => _inputIdState.Value; + private string? _userAttributesId = Identifier.Create("mudinputextended"); + private readonly string _componentId = Identifier.Create("mudinputextended"); /// /// /// - protected MudBaseInputExtended() : base(new DefaultConverter()) { } + protected virtual bool SkipUpdateProcessOnSetParameters { get; set; } + + private readonly ParameterState _textState; + private readonly ParameterState _valueState; + private readonly ParameterState _formatState; + private readonly ParameterState _inputIdState; + + /// + /// + /// + protected MudBaseInputExtended() + { + Converter = new DefaultConverter + { + Culture = GetCulture, + Format = GetFormat + }; + + using var registerScope = CreateRegisterScope(); + _textState = registerScope.RegisterParameter(nameof(Text)) + .WithParameter(() => Text) + .WithEventCallback(() => TextChanged) + .WithChangeHandler(OnTextParameterChangedAsync); + _valueState = registerScope.RegisterParameter(nameof(Value)) + .WithParameter(() => Value) + .WithEventCallback(() => ValueChanged) + .WithChangeHandler(OnValueParameterChangedAsync); + _formatState = registerScope.RegisterParameter(nameof(Format)) + .WithParameter(() => Format) + .WithChangeHandler(OnCultureAndFormatChangedAsync); + _inputIdState = registerScope.RegisterParameter(nameof(InputId)) + .WithParameter(() => InputId) + .WithChangeHandler(UpdateInputIdStateAsync); + } [CascadingParameter(Name = "ParentDisabled")] private bool ParentDisabled { get; set; } [CascadingParameter(Name = "ParentReadOnly")] private bool ParentReadOnly { get; set; } @@ -59,6 +98,16 @@ protected MudBaseInputExtended() : base(new DefaultConverter()) { } /// [Parameter] public EventCallback OnChange { get; set; } + /// + /// The ID of the input element. + /// + /// + /// When set takes precedence over any internally generated IDs. + /// + [Parameter, ParameterState] + [Category(CategoryTypes.FormComponent.Behavior)] + public string? InputId { get; set; } + /// /// Set the text-align on the component. /// @@ -162,7 +211,7 @@ protected MudBaseInputExtended() : base(new DefaultConverter()) { } /// [Parameter] [Category(CategoryTypes.FormComponent.Behavior)] - public bool ShrinkLabel { get; set; } = MudGlobal.InputDefaults.ShrinkLabel; + public bool ShrinkLabel { get; set; } /// /// The color of the adornment if used. It supports the theme colors. @@ -188,14 +237,14 @@ protected MudBaseInputExtended() : base(new DefaultConverter()) { } /// [Parameter] [Category(CategoryTypes.FormComponent.Appearance)] - public Variant Variant { get; set; } = MudGlobal.InputDefaults.Variant; + public Variant Variant { get; set; } = Variant.Text; /// /// Will adjust vertical spacing. /// [Parameter] [Category(CategoryTypes.FormComponent.Appearance)] - public Margin Margin { get; set; } = MudGlobal.InputDefaults.Margin; + public Margin Margin { get; set; } = Margin.None; /// /// The short hint displayed in the input before the user enters a value. @@ -316,26 +365,26 @@ protected virtual async Task SetTextAsync(string? text, bool updateValue = true) /// protected virtual Task UpdateTextPropertyAsync(bool updateValue) { - return SetTextAsync(Converter.Set(Value), updateValue); + return SetTextAndUpdateValueAsync(ConvertSet(ReadValue), updateValue); } /// /// Focus to the element. /// /// The ValueTask - public virtual ValueTask FocusAsync() { return new ValueTask(); } + public virtual ValueTask FocusAsync() => ValueTask.CompletedTask; /// /// Blur from the element. /// /// - public virtual ValueTask BlurAsync() { return new ValueTask(); } + public virtual ValueTask BlurAsync() => ValueTask.CompletedTask; /// /// Focus and select all text. /// /// - public virtual ValueTask SelectAsync() { return new ValueTask(); } + public virtual ValueTask SelectAsync() => ValueTask.CompletedTask; /// /// Focus and select partial text with given positions. @@ -343,7 +392,7 @@ protected virtual Task UpdateTextPropertyAsync(bool updateValue) /// /// /// - public virtual ValueTask SelectRangeAsync(int pos1, int pos2) { return new ValueTask(); } + public virtual ValueTask SelectRangeAsync(int pos1, int pos2) => ValueTask.CompletedTask; /// /// Fired when the text value changes. @@ -359,12 +408,7 @@ protected virtual Task UpdateTextPropertyAsync(bool updateValue) /// Fired when the element changes internally its text value. /// [Parameter] - public EventCallback OnInternalInputChanged { get; set; } - - /// - /// - /// - protected bool _isFocused; + public EventCallback OnInternalInputChanged { get; set; } /// /// @@ -487,62 +531,31 @@ protected virtual async Task SetValueAsync(T? value, bool updateText = true, boo /// protected virtual Task UpdateValuePropertyAsync(bool updateText) { - return SetValueAsync(Converter.Get(Text), updateText); + return SetValueAndUpdateTextAsync(ConvertGet(ReadText), updateText); } /// - /// - /// - /// - /// - protected override bool SetConverter(MudBlazor.Converter value) - { - var changed = base.SetConverter(value); - if (changed) - UpdateTextPropertyAsync(false).CatchAndLog(); // refresh only Text property from current Value - - return changed; - } - - /// - /// + /// The format applied to values. /// - /// - /// - protected override bool SetCulture(CultureInfo value) - { - var changed = base.SetCulture(value); - if (changed) - UpdateTextPropertyAsync(false).CatchAndLog(); // refresh only Text property from current Value + /// + /// This property is passed into the ToString() method of the property, such as formatting int, float, DateTime and TimeSpan values. + /// + [Parameter, ParameterState] + [Category(CategoryTypes.FormComponent.Behavior)] + public string? Format { get; set; } - return changed; - } + protected override string? GetFormat() => _formatState.Value; - /// - /// Conversion format parameter for ToString(), can be used for formatting primitive types, DateTimes and TimeSpans - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public string? Format + protected override async Task OnCultureAndFormatChangedAsync() { - get => ((Converter)Converter).Format; - set => SetFormat(value); + await base.OnCultureAndFormatChangedAsync(); + await UpdateTextPropertyAsync(false); } - /// - /// - /// - /// - /// - protected virtual bool SetFormat(string? value) + protected override async Task OnConverterChangedAsync() { - var changed = Format != value; - if (changed) - { - ((Converter)Converter).Format = value; - UpdateTextPropertyAsync(false).CatchAndLog(); // refresh only Text property from current Value - } - return changed; + await base.OnConverterChangedAsync(); + await UpdateTextPropertyAsync(false); } /// @@ -594,14 +607,6 @@ public virtual async Task ForceRender(bool forceTextUpdate) await UpdateTextPropertyAsync(false); StateHasChanged(); } - /// - /// - /// - protected bool _forceTextUpdate; - /// - /// - /// - protected virtual bool SkipUpdateProcessOnSetParameters { get; set; } /// /// @@ -679,6 +684,111 @@ protected override async Task ResetValueAsync() [CascadingParameter(Name = "SubscribeToParentFormExtended")] internal bool SubscribeToParentFormExtended { get; set; } = true; + private async Task UpdateInputIdStateAsync() + { + if (_inputIdState.Value is not null) + { + return; + } + + if (_userAttributesId is not null) + { + await _inputIdState.SetValueAsync(_userAttributesId); + return; + } + + await _inputIdState.SetValueAsync(_componentId); + } + + private async Task OnValueParameterChangedAsync(ParameterChangedEventArgs arg) + { + _isDirty = true; + _validated = false; + + // When Value changes from parent, update Text from Value + // But only if Text is not also being set in the same parameter update + // Check ParameterView to see if Text is also present + if (!arg.ParameterView.Contains(nameof(Text))) + { + // Always update text when Value changes (TextUpdateSuppression removed) + _forceTextUpdate = false; + await UpdateTextPropertyAsync(false); + } + } + + private async Task OnTextParameterChangedAsync(ParameterChangedEventArgs arg) + { + _validated = false; + + if (!string.IsNullOrEmpty(arg.Value)) + { + Touched = true; + } + + // When Text changes from parent, update Value from Text using UpdateValuePropertyAsync + // But only if Value is not also being set in the same parameter update + // Check ParameterView to see if Value is also present + if (!arg.ParameterView.Contains(nameof(Value))) + { + await UpdateValuePropertyAsync(updateText: false); + } + } + + protected internal string? ReadText => _textState.Value; + protected Task SetTextAsync(string? text) => _textState.SetValueAsync(text); + + protected virtual async Task SetValueAndUpdateTextAsync(T? value, bool updateText = true, bool force = false) + { + var valueChanged = !EqualityComparer.Default.Equals(ReadValue, value); + + if (!valueChanged && !force) + { + return; + } + + _isDirty = true; + _validated = false; + + // Use ParameterState to set Value instead of direct assignment + // This ensures proper parameter lifecycle management + await _valueState.SetValueAsync(value); + + // If force is true but value hasn't changed, ParameterState won't fire the callback + // so we need to manually invoke it to maintain backward compatibility + if (force && !valueChanged) + { + await ValueChanged.InvokeAsync(value); + } + + if (updateText) + { + await UpdateTextPropertyAsync(false); + } + + FieldChanged(value); + await BeginValidateAsync(); + } + + protected virtual async Task SetTextAndUpdateValueAsync(string? text, bool updateValue = true) + { + if (ReadText == text) + { + return; + } + + _validated = false; + + if (!string.IsNullOrEmpty(text)) + { + Touched = true; + } + + await _textState.SetValueAsync(text); + if (updateValue) + { + await UpdateValuePropertyAsync(false); + } + } } internal static class ParameterViewExtensions diff --git a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj index d27beca4..e3debb8e 100644 --- a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj +++ b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj @@ -1,11 +1,11 @@  - net8.0;net9.0 + net8.0;net9.0;net10.0 enable enable MIT - 8.3.0 + 9.0.0-preview.1 CodeBeam.MudBlazor.Extensions CodeBeam CodeBeam @@ -26,19 +26,24 @@ - + - - + + + + + + + @@ -55,9 +60,9 @@ --> - + diff --git a/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor.cs index 55c93987..ece33ee1 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor.cs @@ -125,10 +125,10 @@ protected internal async Task HandleKeyDown(KeyboardEventArgs args) var result = args.Key; if (result.Equals(Delimiter, StringComparison.InvariantCultureIgnoreCase) && _internalValue != null) { - if (AllowSameValues == false && Values?.Contains(Converter.Set(_internalValue) ?? string.Empty) == true) + if (AllowSameValues == false && Values?.Contains(base.ConvertSet(_internalValue) ?? string.Empty) == true) { await Task.Delay(10); - _internalValue = Converter.Get(Converter.Set(_internalValue)?.Replace(result, null).ToString()); + _internalValue = base.ConvertGet(base.ConvertSet(_internalValue)?.Replace(result, null).ToString()); await SetValueAsync(_internalValue); StateHasChanged(); return; @@ -137,7 +137,7 @@ protected internal async Task HandleKeyDown(KeyboardEventArgs args) StateHasChanged(); } - if (args.Key == "Backspace" && string.IsNullOrEmpty(Converter.Set(_internalValue)) && Values != null && Values.Any() && BackspaceChipRemoval == true) + if (args.Key == "Backspace" && string.IsNullOrEmpty(base.ConvertSet(_internalValue)) && Values != null && Values.Any() && BackspaceChipRemoval == true) { Values.RemoveAt(Values.Count - 1); await ValuesChanged.InvokeAsync(Values); @@ -172,7 +172,7 @@ protected async Task SetChips() { Values = new(); } - Values.Add(Converter.Set(_internalValue) ?? ""); + Values.Add(base.ConvertSet(_internalValue) ?? ""); await ValuesChanged.InvokeAsync(Values); if (RuntimeLocation.IsServerSide) { diff --git a/CodeBeam.MudBlazor.Extensions/Components/CodeInput/MudCodeInput.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/CodeInput/MudCodeInput.razor.cs index 3b601c50..0aded2b7 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/CodeInput/MudCodeInput.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/CodeInput/MudCodeInput.razor.cs @@ -16,7 +16,7 @@ public partial class MudCodeInput : MudFormComponent /// /// MudCodeInput constructor. /// - public MudCodeInput() : base(new DefaultConverter()) + public MudCodeInput() { using var registerScope = CreateRegisterScope(); _theValue = registerScope.RegisterParameter(nameof(Value)) @@ -218,7 +218,7 @@ protected async Task CheckFocus(int count) _skipRefocus = false; return; } - string str = Converter.Set(_theValue.Value) ?? string.Empty; + string str = base.ConvertSet(_theValue.Value) ?? string.Empty; await _elementReferences[str.Length].FocusAsync(); } @@ -288,7 +288,7 @@ public async Task SetValue() result += val; } - await _theValue.SetValueAsync(Converter.Get(result)); + await _theValue.SetValueAsync(base.ConvertGet(result)); } /// @@ -298,12 +298,12 @@ public async Task SetValue() /// public async Task SetValueFromOutside(T? value) { - string? val = Converter.Set(value); + string? val = base.ConvertSet(value); if (_count.Value < val?.Length) { val = val.Substring(0, _count.Value); } - await _theValue.SetValueAsync(Converter.Get(val)); + await _theValue.SetValueAsync(base.ConvertGet(val)); for (int i = 0; i < _count.Value; i++) { if (i < val?.Length) diff --git a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor index 5373e35d..be56b2a9 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor @@ -56,7 +56,7 @@ { foreach (var item in CollectionsMarshal.AsSpan(collection)) { - } } diff --git a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs index eed46bbf..ba3037bd 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs @@ -31,7 +31,7 @@ public MudComboBox() /// protected internal void SetSearchString(T value) { - _searchString = Converter.Set(value); + _searchString = base.ConvertSet(value); } internal string? _searchString { get; set; } @@ -521,7 +521,7 @@ protected async Task SyncMultiselectionValues(bool singleToMultiselection) } else { - if (Value is string && string.IsNullOrWhiteSpace(Converter.Set(Value))) + if (Value is string && string.IsNullOrWhiteSpace(base.ConvertSet(Value))) { SelectedValues = new HashSet(); } @@ -536,7 +536,7 @@ protected async Task SyncMultiselectionValues(bool singleToMultiselection) else { await SetValueAsync(SelectedValues.LastOrDefault(), false); - _searchString = Converter.Set(SelectedValues.LastOrDefault()); + _searchString = base.ConvertSet(SelectedValues.LastOrDefault()); } } @@ -566,20 +566,7 @@ public IEqualityComparer? Comparer /// [Parameter] [Category(CategoryTypes.FormComponent.ListBehavior)] - public Func? ToStringFunc - { - get => _toStringFunc; - set - { - if (_toStringFunc == value) - return; - _toStringFunc = value; - Converter = new Converter - { - SetFunc = _toStringFunc ?? (x => x?.ToString()), - }; - } - } + public Func? ToStringFunc { get; set; } #endregion @@ -652,13 +639,13 @@ protected Task UpdateDataVisualiserTextAsync() { if (!Strict && !Items.Select(x => x.Value).Contains(val)) { - textList.Add(ToStringFunc != null ? ToStringFunc(val) : Converter.Set(val)); + textList.Add(ToStringFunc != null ? ToStringFunc(val) : base.ConvertSet(val)); continue; } var item = Items.FirstOrDefault(x => x != null && (x.Value == null ? val == null : Comparer != null ? Comparer.Equals(x.Value, val) : x.Value.Equals(val))); if (item != null) { - textList.Add(!string.IsNullOrWhiteSpace(item.Text) ? item.Text : Converter.Set(item.Value)); + textList.Add(!string.IsNullOrWhiteSpace(item.Text) ? item.Text : base.ConvertSet(item.Value)); } } } @@ -688,8 +675,8 @@ protected Task UpdateDataVisualiserTextAsync() { var item = Items?.FirstOrDefault(x => Value == null ? x.Value == null : Comparer != null ? Comparer.Equals(Value, x.Value) : Value.Equals(x.Value)); _dataVisualiserText = item is null - ? Converter.Set(Value) - : (!string.IsNullOrWhiteSpace(item.Text) ? item.Text : Converter.Set(item.Value)); + ? base.ConvertSet(Value) + : (!string.IsNullOrWhiteSpace(item.Text) ? item.Text : base.ConvertSet(item.Value)); return Task.CompletedTask; } @@ -708,7 +695,7 @@ protected async Task UpdateComboBoxValueAsync(T? value, bool updateText = true, await SetValueAsync(value, updateText, force); if (updateSearchString) { - _searchString = Converter.Set(Value); + _searchString = base.ConvertSet(Value); await _inputReference.SetText(_searchString); } } @@ -806,7 +793,7 @@ protected override async Task OnParametersSetAsync() await ForceUpdateItems(); if (MultiSelection == false) { - _searchString = Converter.Set(Value); + _searchString = base.ConvertSet(Value); if (_inputReference != null) { await _inputReference?.SetText(_searchString); @@ -1049,7 +1036,7 @@ protected internal async Task HandleOnBlur(FocusEventArgs obj) if (Strict) { // Check if the user-provided search string is an exact (case-insensitive) match against an item in the collection. - var item = Items.FirstOrDefault(x => Converter.Set(x.Value)?.Equals(_searchString, StringComparison.OrdinalIgnoreCase) == true); + var item = Items.FirstOrDefault(x => base.ConvertSet(x.Value)?.Equals(_searchString, StringComparison.OrdinalIgnoreCase) == true); if (item is not null) await ToggleOption(item, true); @@ -1074,7 +1061,7 @@ protected internal async Task HandleOnBlur(FocusEventArgs obj) } } else - await UpdateComboBoxValueAsync(Converter.Get(_searchString), updateText: true, updateSearchString: true); + await UpdateComboBoxValueAsync(base.ConvertGet(_searchString), updateText: true, updateSearchString: true); } await OnBlurredAsync(obj); @@ -1547,7 +1534,7 @@ public async Task ActivateFirstItem(string? firstLetter = null) // Get a collection of items that start with "firstLetter". - var items = Items.Where(x => Converter?.Set(x.Value)?.StartsWith(firstLetter, StringComparison.OrdinalIgnoreCase) == true).ToList(); + var items = Items.Where(x => base.ConvertSet(x.Value)?.StartsWith(firstLetter, StringComparison.OrdinalIgnoreCase) == true).ToList(); if (!items.Any()) { if (_lastActivatedItem is not null) diff --git a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBoxItem.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBoxItem.razor.cs index b6ee6759..c06329bd 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBoxItem.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBoxItem.razor.cs @@ -155,12 +155,12 @@ protected string? DisplayString { if (converter == null) return Value?.ToString(); - return converter.Set(Value); + return converter.Convert(Value); } if (converter == null) return $"{(string.IsNullOrWhiteSpace(Text) ? Value : Text)}"; - return !string.IsNullOrWhiteSpace(Text) ? Text : converter.Set(Value); + return !string.IsNullOrWhiteSpace(Text) ? Text : converter.Convert(Value); } } @@ -259,7 +259,7 @@ protected bool IsEligible() } else { - if (MudComboBox?.Converter?.Set(Value)?.Contains(MudComboBox._searchString ?? string.Empty, StringComparison.OrdinalIgnoreCase) == true) + if (MudComboBox?.Converter?.Convert(Value)?.Contains(MudComboBox._searchString ?? string.Empty, StringComparison.OrdinalIgnoreCase) == true) return true; } diff --git a/CodeBeam.MudBlazor.Extensions/Components/DateWheelPicker/MudDateWheelPicker.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/DateWheelPicker/MudDateWheelPicker.razor.cs index 063bfd78..bbd6c957 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/DateWheelPicker/MudDateWheelPicker.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/DateWheelPicker/MudDateWheelPicker.razor.cs @@ -3,6 +3,7 @@ using MudBlazor; using MudBlazor.Utilities; using MudExtensions.Utilities; +using System.Globalization; namespace MudExtensions { @@ -11,6 +12,11 @@ namespace MudExtensions /// public partial class MudDateWheelPicker : MudBaseInput { + MudDateWheelPicker() + { + Converter = Conversions.From((DateTime? x) => x?.ToString(DateFormat), x => DateTime.TryParseExact(x, DateFormat, null, DateTimeStyles.None, out DateTime dt) ? dt : null); + } + /// /// /// @@ -19,17 +25,6 @@ public partial class MudDateWheelPicker : MudBaseInput .AddClass(Class) .Build(); DateTime dt; - /// - /// - /// - protected override void OnInitialized() - { - Converter = new MudBlazor.Converter() - { - SetFunc = x => x?.ToString(DateFormat), - GetFunc = x => DateTime.TryParseExact(x, DateFormat, null, System.Globalization.DateTimeStyles.None, out dt) ? dt : null, - }; - } /// /// @@ -300,11 +295,11 @@ protected async Task UpdateValueAsync(bool updateText = true) var _backUpValue = Value; try { - await SetValueAsync(new DateTime(_year, _month, _day, _hour, _minute, _second), updateText); + await SetValueAndUpdateTextAsync(new DateTime(_year, _month, _day, _hour, _minute, _second), updateText); } catch { - await SetValueAsync(_backUpValue, updateText); + await SetValueAndUpdateTextAsync(_backUpValue, updateText); } } @@ -360,7 +355,7 @@ public async Task CloseMenu(bool submit) /// protected async Task HandleOnBlur() { - await SetTextAsync(InputReference.Text, true); + await SetTextAndUpdateValueAsync(InputReference.Text, true); } /// diff --git a/CodeBeam.MudBlazor.Extensions/Components/FontPicker/MudFontPicker.razor b/CodeBeam.MudBlazor.Extensions/Components/FontPicker/MudFontPicker.razor index 21f8dadc..f6eecf60 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/FontPicker/MudFontPicker.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/FontPicker/MudFontPicker.razor @@ -2,7 +2,7 @@ @inherits MudAutocomplete diff --git a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor index 7c807d45..a8d99f72 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor @@ -18,18 +18,19 @@ @ref="ElementReference" rows="@Lines" @attributes="UserAttributes" + id="@InputElementId" type="@InputTypeString" placeholder="@Placeholder" - disabled=@Disabled - readonly="@ReadOnly" + disabled="@GetDisabledState()" + readonly="@GetReadOnlyState" inputmode="@InputMode.ToString()" - @oninput="OnInputHandler" - @onchange="OnChangeHandler" + @bind:event="@(Immediate ? "oninput" : "onchange")" + @bind:get="@_internalText" + @bind:set="@OnInputOrOnChangeAsync" @onblur="@OnBlurredAsync" @onkeydown="@InvokeKeyDownAsync" @onkeyup="@InvokeKeyUpAsync" @onpaste="@OnPaste" - value="@_internalText" maxlength="@MaxLength" @onkeydown:preventDefault="@KeyDownPreventDefault" @onkeyup:preventDefault="@KeyUpPreventDefault" @@ -37,10 +38,9 @@ @onwheel="@OnMouseWheel" aria-invalid="@Error.ToString().ToLower()" aria-describedby="@ErrorId"> - @Text + @ReadText @*Note: double mouse wheel handlers needed for Firefox because it doesn't know onmousewheel*@ - @*note: the value="@_internalText" is absolutely essential here. the inner html @Text is needed by tests checking it*@ } else { @@ -59,10 +59,11 @@ : MudBaseInputExtended /// /// protected string? Classname => MudInputCssHelperExtended.GetClassname(this, - () => HasNativeHtmlPlaceholder() || ShrinkLabel == true || !string.IsNullOrEmpty(Text) || !string.IsNullOrWhiteSpace(Placeholder) || !string.IsNullOrEmpty(Converter.Set(Value))); + () => HasNativeHtmlPlaceholder() || ShrinkLabel == true || !string.IsNullOrEmpty(Text) || !string.IsNullOrWhiteSpace(Placeholder) || !string.IsNullOrEmpty(base.ConvertSet(Value))); /// /// @@ -114,49 +114,38 @@ protected override async Task OnAfterRenderAsync(bool firstRender) /// protected string? InputTypeString => InputType.ToDescriptionString(); - /// - /// - /// - /// - /// - protected Task OnInputHandler(ChangeEventArgs args) + private async Task OnInputOrOnChangeAsync(string? input) { - if (!Immediate) - return Task.CompletedTask; - _isFocused = true; - OnInput.InvokeAsync(); - if (AutoSize) + if (Immediate) { - if (JSRuntime != null) - { - JSRuntime.InvokeVoidAsync("auto_size", ElementReference); - } + await OnInputHandler(input); + await OnInput.InvokeAsync(input); + } + else + { + await OnChangeHandler(input); + await OnChange.InvokeAsync(input); + } + + if (AutoSize && JSRuntime != null) + { + await JSRuntime.InvokeVoidAsync("auto_size", ElementReference); } - return SetTextAsync(args?.Value as string); } - /// - /// - /// - /// - /// - protected async Task OnChangeHandler(ChangeEventArgs args) + protected async Task OnInputHandler(string? args) { - _internalText = args?.Value as string; + _isFocused = true; + _internalText = args; await OnInternalInputChanged.InvokeAsync(args); - if (!Immediate) - { - await SetTextAsync(args?.Value as string); - if (AutoSize) - { - if (JSRuntime != null) - { - await JSRuntime.InvokeVoidAsync("auto_size", ElementReference); - } - } - - await OnChange.InvokeAsync(); - } + await SetTextAndUpdateValueAsync(args); + } + + protected async Task OnChangeHandler(string? args) + { + _internalText = args; + await OnInternalInputChanged.InvokeAsync(args); + await SetTextAndUpdateValueAsync(args); } /// diff --git a/CodeBeam.MudBlazor.Extensions/Components/ListExtended/MudListExtended.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/ListExtended/MudListExtended.razor.cs index 3dc8d33c..71ebdc4a 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ListExtended/MudListExtended.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/ListExtended/MudListExtended.razor.cs @@ -116,7 +116,7 @@ public partial class MudListExtended : MudComponentBase, IDisposable /// [Parameter] [Category(CategoryTypes.List.Behavior)] - public DefaultConverter Converter { get; set; } = new DefaultConverter(); + public IConverter Converter { get; set; } = new DefaultConverter(); private IEqualityComparer? _comparer; /// @@ -148,20 +148,7 @@ public IEqualityComparer? Comparer /// [Parameter] [Category(CategoryTypes.FormComponent.ListBehavior)] - public Func? ToStringFunc - { - get => _toStringFunc; - set - { - if (_toStringFunc == value) - return; - _toStringFunc = value; - Converter = new DefaultConverter - { - SetFunc = _toStringFunc ?? (x => x?.ToString()), - }; - } - } + public Func? ToStringFunc { get; set; } /// /// Predefined enumerable items. If its not null, creates list items automatically. @@ -529,7 +516,7 @@ public T? SelectedValue get => _selectedValue; set { - if (Converter.Set(_selectedValue) != Converter.Set(default(T)) && !_firstRendered) + if (Converter.Convert(_selectedValue) != Converter.Convert(default(T)) && !_firstRendered) { return; } @@ -1490,7 +1477,7 @@ public async Task ActiveFirstItem(string? startChar = null) } // find first item that starts with the letter - var possibleItems = items.Where(x => (x.Text ?? Converter.Set(x.Value) ?? "").StartsWith(startChar, StringComparison.CurrentCultureIgnoreCase)).ToList(); + var possibleItems = items.Where(x => (x.Text ?? Converter.Convert(x.Value) ?? "").StartsWith(startChar, StringComparison.CurrentCultureIgnoreCase)).ToList(); if (possibleItems == null || !possibleItems.Any()) { DeactiveAllItems(items); @@ -1695,7 +1682,7 @@ protected internal ValueTask ScrollToMiddleAsync(MudListItemExtended? item) return ItemCollection.Where(x => SearchFunc.Invoke(x, _searchString)).ToList(); } - return ItemCollection.Where(x => Converter?.Set(x)?.Contains(_searchString, StringComparison.InvariantCultureIgnoreCase) == true).ToList(); + return ItemCollection.Where(x => Converter.Convert(x)?.Contains(_searchString, StringComparison.InvariantCultureIgnoreCase) == true).ToList(); } /// diff --git a/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor b/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor index 0b74349d..5328c164 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor @@ -27,7 +27,6 @@ Label="@Label" Style="@Style" Variant="@Variant" - TextUpdateSuppression="@TextUpdateSuppression" Value="@Text" ValueChanged="(s) => SetTextAsync(s)" Placeholder="@Placeholder" @@ -43,7 +42,6 @@ Margin="@Margin" OnBlur="@OnBlurredAsync" OnKeyDown="@InvokeKeyDownAsync" - OnInternalInputChanged="OnChange" OnKeyUp="@InvokeKeyUpAsync" KeyDownPreventDefault="KeyDownPreventDefault" KeyUpPreventDefault="KeyUpPreventDefault" diff --git a/CodeBeam.MudBlazor.Extensions/Components/RangeSlider/MudRangeSlider.razor b/CodeBeam.MudBlazor.Extensions/Components/RangeSlider/MudRangeSlider.razor index 793078b7..ca3eb897 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/RangeSlider/MudRangeSlider.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/RangeSlider/MudRangeSlider.razor @@ -31,13 +31,13 @@ @if (Range) { - @SliderValueLabel(upperLeft, string.IsNullOrEmpty(UpperLabelText) ? _upperValue.Value.ToString() : UpperLabelText) } - @SliderValueLabel(left, string.IsNullOrEmpty(LabelText) ? _value.Value.ToString() : LabelText) diff --git a/CodeBeam.MudBlazor.Extensions/Components/RangeSlider/MudRangeSlider.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/RangeSlider/MudRangeSlider.razor.cs index 33ebce26..986936ef 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/RangeSlider/MudRangeSlider.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/RangeSlider/MudRangeSlider.razor.cs @@ -253,7 +253,7 @@ private async Task OnSlideableLowerMaxChanged() /// [Parameter] [Category(CategoryTypes.Slider.Behavior)] - public Converter Converter { get; set; } = new DefaultConverter() { Culture = CultureInfo.InvariantCulture }; + public IConverter Converter { get; set; } = new DefaultConverter(); /// /// Fires when value changed. @@ -293,7 +293,7 @@ protected string? DisplayText { get { - if (!Range) return Converter.Set(_value.Value); + if (!Range) return Converter.Convert(_value.Value); //if both lower and upper are not set then it is any if ((Convert.ToDouble(_value.Value) == Convert.ToDouble(Min)) && diff --git a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor index eea67e89..7f8fb9c7 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor @@ -61,14 +61,14 @@ { foreach (var item in ItemCollection.Where(x => SelectedValues?.Contains(x) == true)) { - + } } else { foreach (var item in Items?.Where(x => SelectedValues?.Contains(x.Value) == true) ?? new List>()) { - + } } diff --git a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor.cs index 2f9adb1c..38199400 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor.cs @@ -507,20 +507,7 @@ public IEqualityComparer? Comparer /// [Parameter] [Category(CategoryTypes.FormComponent.ListBehavior)] - public Func? ToStringFunc - { - get => _toStringFunc; - set - { - if (_toStringFunc == value) - return; - _toStringFunc = value; - Converter = new Converter - { - SetFunc = _toStringFunc ?? (x => x?.ToString()), - }; - } - } + public Func? ToStringFunc { get; set; } /// /// If true, a null item will be added to the list (Only for ItemCollection). @@ -701,7 +688,7 @@ protected override Task UpdateTextPropertyAsync(bool updateValue) var collectionValue = ItemCollection.FirstOrDefault(x => x != null && (Comparer != null ? Comparer.Equals(x, val) : x.Equals(val))); if (collectionValue != null) { - textList.Add(Converter.Set(collectionValue)); + textList.Add(base.ConvertSet(collectionValue)); } } } @@ -711,13 +698,13 @@ protected override Task UpdateTextPropertyAsync(bool updateValue) { if (!Strict && !Items.Select(x => x.Value).Contains(val)) { - textList.Add(ToStringFunc != null ? ToStringFunc(val) : Converter.Set(val)); + textList.Add(ToStringFunc != null ? ToStringFunc(val) : base.ConvertSet(val)); continue; } var item = Items.FirstOrDefault(x => x != null && (x.Value == null ? val == null : Comparer != null ? Comparer.Equals(x.Value, val) : x.Value.Equals(val))); if (item != null) { - textList.Add(!string.IsNullOrEmpty(item.Text) ? item.Text : Converter.Set(item.Value)); + textList.Add(!string.IsNullOrEmpty(item.Text) ? item.Text : base.ConvertSet(item.Value)); } } } @@ -743,9 +730,9 @@ protected override Task UpdateTextPropertyAsync(bool updateValue) var item = Items?.FirstOrDefault(x => Value == null ? x.Value == null : Comparer != null ? Comparer.Equals(Value, x.Value) : Value.Equals(x.Value)); if (item == null) { - return SetTextAsync(Converter.Set(Value), false); + return SetTextAsync(base.ConvertSet(Value), false); } - return SetTextAsync((!string.IsNullOrEmpty(item.Text) ? item.Text : Converter.Set(item.Value)), updateValue: updateValue); + return SetTextAsync((!string.IsNullOrEmpty(item.Text) ? item.Text : base.ConvertSet(item.Value)), updateValue: updateValue); } } @@ -1332,5 +1319,10 @@ public bool GetOpenState() { return _isOpen; } + + /// + /// Internal method for MudSelectItem to access the converted string value. + /// + internal string? ConvertValueToString(T? value) => ConvertSet(value); } } diff --git a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectItemExtended.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectItemExtended.razor.cs index 18626005..80b0498a 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectItemExtended.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectItemExtended.razor.cs @@ -164,7 +164,7 @@ protected string? DisplayString var converter = MudSelectExtended?.Converter; if (converter == null) return $"{(string.IsNullOrEmpty(Text) ? Value : Text)}"; - return !string.IsNullOrEmpty(Text) ? Text : converter.Set(Value); + return !string.IsNullOrEmpty(Text) ? Text : converter.Convert(Value); } } diff --git a/CodeBeam.MudBlazor.Extensions/Components/SignaturePad/MudSignaturePad.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/SignaturePad/MudSignaturePad.razor.cs index c917975b..5f2d67e6 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/SignaturePad/MudSignaturePad.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/SignaturePad/MudSignaturePad.razor.cs @@ -157,7 +157,7 @@ record JsOptionsStructRecord(decimal LineWidth, string LineCap, string LineJoin, /// /// [Parameter] - public Variant Variant { get; set; } = MudGlobal.InputDefaults.Variant; + public Variant Variant { get; set; } = Variant.Text; /// /// diff --git a/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor.cs index 9f5208b5..ffc058da 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using MudBlazor; +using MudBlazor.Extensions; using MudBlazor.Utilities; namespace MudExtensions @@ -203,10 +204,10 @@ protected override Task SetValueAsync(T? value, bool updateText = true, bool for { if (_mask != null) { - var textValue = Converter.Set(value); + var textValue = Converter.Convert(value); _mask.SetText(textValue); textValue = Mask?.GetCleanText(); - value = Converter.Get(textValue); + value = Converter.ConvertBack(textValue); } return base.SetValueAsync(value, updateText, force); } diff --git a/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor b/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor index 0bd1daba..9c1f3cb7 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor @@ -19,7 +19,7 @@ if (0 <= index - a) {
- @(ToStringFunc != null ? ToStringFunc(ItemCollection[index - a]) : Converter.Set(ItemCollection[index - a])) + @(ToStringFunc != null ? ToStringFunc(ItemCollection[index - a]) : Converter.Convert(ItemCollection[index - a]))
} else @@ -31,7 +31,7 @@
- @(ToStringFunc != null ? ToStringFunc(ItemCollection[index]) : Converter.Set(ItemCollection[index])) + @(ToStringFunc != null ? ToStringFunc(ItemCollection[index]) : Converter.Convert(ItemCollection[index]))
@@ -42,7 +42,7 @@ if (index + a < ItemCollection?.Count) {
- @(ToStringFunc != null ? ToStringFunc(ItemCollection[index + a]) : Converter.Set(ItemCollection[index + a])) + @(ToStringFunc != null ? ToStringFunc(ItemCollection[index + a]) : Converter.Convert(ItemCollection[index + a]))
} else diff --git a/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor.cs index fd90cdb9..64260c1f 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor.cs @@ -119,20 +119,7 @@ public partial class MudWheel : MudBaseInput ///
[Parameter] [Category(CategoryTypes.FormComponent.ListBehavior)] - public Func? ToStringFunc - { - get => _toStringFunc; - set - { - if (_toStringFunc == value) - return; - _toStringFunc = value; - Converter = new Converter - { - SetFunc = _toStringFunc ?? (x => x?.ToString()), - }; - } - } + public Func? ToStringFunc { get; set; } /// /// From c6570f8b0afc23f9b16f5dfcf6fef56850706325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Tue, 23 Dec 2025 20:25:08 +0300 Subject: [PATCH 2/9] BaseInputClass Inheritance & Parameter State Implementation --- .../wwwroot/CodeBeam.MudBlazor.Extensions.xml | 382 +--------- .../Components/ChipFieldTests.cs | 7 +- .../Components/ComboboxTests.cs | 85 ++- .../Components/SelectExtendedTests.cs | 221 +++--- .../Base/MudBaseInputExtended.cs | 721 +----------------- .../Components/ChipField/MudChipField.razor | 10 +- .../Components/CodeInput/MudCodeInput.razor | 4 +- .../Components/ComboBox/MudComboBox.razor | 23 +- .../Components/ComboBox/MudComboBox.razor.cs | 52 +- .../ComboBox/MudComboBoxItem.razor.cs | 2 +- .../DateWheelPicker/MudDateWheelPicker.razor | 6 +- .../MudDateWheelPicker.razor.cs | 23 +- .../Components/FontPicker/MudFontPicker.razor | 2 +- .../MudDebouncedInputExtended.cs | 2 +- .../MudInputCssHelperExtended.cs | 2 +- .../InputExtended/MudInputExtended.razor.cs | 56 +- .../PasswordField/MudPasswordField.razor | 8 +- .../PasswordField/MudPasswordField.razor.cs | 2 +- .../SelectExtended/MudSelectExtended.razor | 32 +- .../SelectExtended/MudSelectExtended.razor.cs | 48 +- .../MudStepperExtended.razor.cs | 20 + .../MudTextFieldExtended.razor | 16 +- .../MudTextFieldExtended.razor.cs | 72 +- .../Components/Wheel/MudWheel.razor.cs | 7 +- 24 files changed, 420 insertions(+), 1383 deletions(-) diff --git a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml index 26c53a5a..c6176472 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml +++ b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml @@ -30,38 +30,11 @@ - - - - - - - - Disable input component if true. Default is false. - - - - - Get the input component is disabled or not. - - - - - - If true, the input will be read-only. - - - - - Get the input component is readonly or not. - - - Fires on input. @@ -72,65 +45,11 @@ Fires on change. - - - The ID of the input element. - - - When set takes precedence over any internally generated IDs. - - - - - Set the text-align on the component. - - - - - If true, the input will take up the full width of its container. - - - - - If true, the input will update the Value immediately on typing. - If false, the Value is updated only on Enter. - - - - - If false, the input will not have an underline. - - Gets or sets a value indicating whether the component has an adornment at the start. - - - The HelperText will be displayed below the text field. - - - - - If true, the helper text will only be visible on focus. - - - - - Icon that will be used if Adornment is set to Start or End. - - - - - Text that will be used if Adornment is set to Start or End, the Text overrides Icon. - - - - - The Adornment if used. By default, it is set to None. - - The Adornment if used. By default, it is set to None. @@ -141,287 +60,29 @@ The Adornment if used. By default, it is set to None. - - - The aria-label of the adornment. - - - - - The validation is only triggered if the user has changed the input value at least once. By default, it is false - - - - - If true shrinks label directly. - - - - - The color of the adornment if used. It supports the theme colors. - - - - - The Icon Size. - - - - - Button click event if set and Adornment used. - - - - - Variant to use. - - - - - Will adjust vertical spacing. - - - - - The short hint displayed in the input before the user enters a value. - - - - - If set, will display the counter, value 0 will display current count but no stop count. - - - - - Maximum number of characters that the input will accept - - - - - If string has value the label text will be displayed in the input, and scaled down at the top if the input has value. - - - - - If true the input will focus automatically. - - - - - A multiline input (textarea) will be shown, if set to more than one line. - - - - - The text to be displayed. - - - - - When TextUpdateSuppression is true (which is default) the text can not be updated by bindings while the component is focused in BSS (not WASM). - This solves issue #1012: Textfield swallowing chars when typing rapidly - If you need to update the input's text while it is focused you can set this parameter to false. - Note: on WASM text update suppression is not active, so this parameter has no effect. - - - - - Hints at the type of data that might be entered by the user while editing the input - - - - - The pattern attribute, when specified, is a regular expression which the input's value must match in order for the value to pass constraint validation. It must be a valid JavaScript regular expression - Not Supported in multline input - - CSS style of the child content. - - - Sync the value, values and text, calls validation manually. Useful to call after user changes value or text programmatically. - - - - - - Derived classes need to override this if they can be something other than text - - - - - - - - - - - - - Text change hook for descendants. Called when Text needs to be refreshed from current Value property. - - - - - Focus to the element. - - The ValueTask - - - - Blur from the element. - - - - - - Focus and select all text. - - - - - - Focus and select partial text with given positions. - - - - - - - - Fired when the text value changes. - - - - - Fired when the element loses focus. - - - - - Fired when the element changes internally its text value. - - - - - - - - - - - - Fired on the KeyDown event. - - - - - - - - - - - - Prevent the default action for the KeyDown event. - - If true disables paste to input component. Default is false. - - - Fired on the KeyUp event. - - - - - - - - - - - - Prevent the default action for the KeyUp event. - - - - - Fired when the Value property changes. - - - - - The value of this input element. - - - - - - - - - - - - - - Value change hook for descendants. Called when Value needs to be refreshed from current Text property. - - - - - The format applied to values. - - - This property is passed into the ToString() method of the property, such as formatting int, float, DateTime and TimeSpan values. - - - - - - - - - - - - - - - - - - - - - - + - - + - - - - - - - + @@ -2144,6 +1805,20 @@
+ + + + + + + + + + + + + + Forces input height to fit the text content. @@ -2288,6 +1963,12 @@ + + + + + + Represents a tree view which displays a snippet of JSON. @@ -5811,23 +5492,6 @@ Note: when Mask is set, TextField will ignore some properties such as Lines, Pattern or HideSpinButtons, OnKeyDown and OnKeyUp, etc. - - - - - - - - - - - - - - - - - diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs index 0229e37f..2f3ed6ec 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs @@ -1,8 +1,9 @@ -using MudExtensions.Docs.Examples; +using Bunit; using FluentAssertions; -using Bunit; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; +using MudBlazor.Extensions; +using MudExtensions.Docs.Examples; namespace MudExtensions.UnitTests.Components { @@ -20,7 +21,7 @@ public async Task ChipFieldBasicTest() field.Find("input").Input(new ChangeEventArgs() { Value = "sdfg" }); await comp.InvokeAsync(() => comp.Instance.HandleKeyDown(new KeyboardEventArgs() { Key = " " })); comp.Instance.Values.Should().BeEquivalentTo(new List { "asdf", "asd", "sdfg" }); - comp.Instance.Value.Should().BeEquivalentTo(null); + comp.Instance.GetState(x => x.Value).Should().BeEquivalentTo(null); } } } diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ComboboxTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ComboboxTests.cs index 5b53f14b..3db13777 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ComboboxTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ComboboxTests.cs @@ -10,6 +10,7 @@ using NUnit.Framework; using MudBlazor; using MudExtensions.UnitTests.Extensions; +using MudBlazor.Extensions; namespace MudExtensions.UnitTests.Components { @@ -32,9 +33,9 @@ public void ComboBox_InitialValueTest(bool multiSelection) }); var combobox = comp.FindComponent>(); - combobox.Instance.Value.Should().Be("1"); + combobox.Instance.GetState(x => x.Value).Should().Be("1"); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); - combobox.Instance.Text.Should().Be("1"); + combobox.Instance.GetState(x => x.Text).Should().Be("1"); } // Note: MudSelect doesn't guaranteed the consequences of changing SelectedValues if MultiSelection is false for now. @@ -51,9 +52,9 @@ public void ComboBox_InitialValuesTest(bool multiSelection) }); var combobox = comp.FindComponent>(); - combobox.Instance.Value.Should().Be("1"); + combobox.Instance.GetState(x => x.Value).Should().Be("1"); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); - combobox.Instance.Text.Should().Be("1"); + combobox.Instance.GetState(x => x.Text).Should().Be("1"); } [Test] @@ -62,21 +63,21 @@ public async Task ComboBox_ValueBubblingTest() var comp = Context.RenderComponent(); var combobox = comp.FindComponent>(); - combobox.Instance.Value.Should().BeNull(); - combobox.Instance.Text.Should().BeNull(); + combobox.Instance.GetState(x => x.Value).Should().BeNull(); + combobox.Instance.GetState(x => x.Text).Should().BeNull(); comp.SetParam("SelectedValue", "1"); await comp.InvokeAsync(() => combobox.Instance.ForceUpdate()); - comp.WaitForAssertion(() => combobox.Instance.Value.Should().Be("1")); + comp.WaitForAssertion(() => combobox.Instance.GetState(x => x.Value).Should().Be("1")); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); - combobox.Instance.Text.Should().Be("1"); + combobox.Instance.GetState(x => x.Text).Should().Be("1"); comp.SetParam("SelectedValue", "2"); - comp.WaitForAssertion(() => combobox.Instance.Value.Should().Be("2")); + comp.WaitForAssertion(() => combobox.Instance.GetState(x => x.Value).Should().Be("2")); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); await comp.InvokeAsync(() => combobox.Instance.ForceUpdate()); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "2" }); - combobox.Instance.Text.Should().Be("2"); + combobox.Instance.GetState(x => x.Text).Should().Be("2"); } [Test] @@ -88,18 +89,18 @@ public void ComboBox_ValueBubblingTest_MultiSelection() }); var combobox = comp.FindComponent>(); - combobox.Instance.Value.Should().BeNull(); - combobox.Instance.Text.Should().BeNullOrEmpty(); + combobox.Instance.GetState(x => x.Value).Should().BeNull(); + combobox.Instance.GetState(x => x.Text).Should().BeNullOrEmpty(); comp.SetParam("SelectedValues", new HashSet() { "1" }); - combobox.Instance.Value.Should().Be(null); + combobox.Instance.GetState(x => x.Value).Should().Be(null); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); - combobox.Instance.Text.Should().Be(null); + combobox.Instance.GetState(x => x.Text).Should().Be(null); comp.SetParam("SelectedValues", new HashSet() { "2", "1" }); - combobox.Instance.Value.Should().Be(null); + combobox.Instance.GetState(x => x.Value).Should().Be(null); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "2", "1" }); - combobox.Instance.Text.Should().Be(null); + combobox.Instance.GetState(x => x.Text).Should().Be(null); } [Test] @@ -119,14 +120,14 @@ public async Task ComboBox_ValueChangeEventCountTest() await comp.InvokeAsync(() => combobox.Instance.ForceUpdate()); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); - combobox.Instance.Value.Should().Be("1"); + combobox.Instance.GetState(x => x.Value).Should().Be("1"); // Changing value programmatically without ForceUpdate should change value, but should not fire change events // Its by design, so this part can be change if design changes await comp.InvokeAsync(() => combobox.SetParam("Value", "2")); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); - combobox.Instance.Value.Should().Be("2"); + combobox.Instance.GetState(x => x.Value).Should().Be("2"); } [Test] @@ -168,7 +169,7 @@ public async Task ComboBoxTest1() // check popover class menu.ClassList.Should().Contain("combobox-popover-class"); // check initial state - combobox.Instance.Value.Should().BeNullOrEmpty(); + combobox.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("d-none")); // click and check if it has toggled the menu input.Click(); @@ -179,7 +180,7 @@ public async Task ComboBoxTest1() items[1].Click(); // menu should be closed now comp.WaitForAssertion(() => menu.ClassList.Should().Contain("d-none")); - combobox.Instance.Value.Should().Be("2"); + combobox.Instance.GetState(x => x.Value).Should().Be("2"); // now we cheat and click the list without opening the menu ;) input.Click(); @@ -187,12 +188,12 @@ public async Task ComboBoxTest1() items = comp.FindAll("div.mud-combobox-item").ToArray(); items[0].Click(); - comp.WaitForAssertion(() => combobox.Instance.Value.Should().Be("1")); + comp.WaitForAssertion(() => combobox.Instance.GetState(x => x.Value).Should().Be("1")); //Check user on blur implementation works var @switch = comp.FindComponent>(); @switch.Instance.Value = true; await comp.InvokeAsync(() => combobox.Instance.HandleOnBlur(new FocusEventArgs())); - comp.WaitForAssertion(() => @switch.Instance.Value.Should().Be(false)); + comp.WaitForAssertion(() => @switch.Instance.GetState(x => x.Value).Should().Be(false)); } [Test] @@ -211,11 +212,11 @@ public async Task ComboBoxClearableTest() var items = comp.FindAll("div.mud-combobox-item").ToArray(); items[1].Click(); //comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => combobox.Instance.Value.Should().Be("2")); + comp.WaitForAssertion(() => combobox.Instance.GetState(x => x.Value).Should().Be("2")); comp.Find("button").Should().NotBeNull(); // Selection cleared and button removed after clicking clear button comp.Find("button").MouseDown(); - comp.WaitForAssertion(() => combobox.Instance.Value.Should().BeNullOrEmpty()); + comp.WaitForAssertion(() => combobox.Instance.GetState(x => x.Value).Should().BeNullOrEmpty()); comp.FindAll("button").Should().BeEmpty(); // Clear button click handler should have been invoked comp.Instance.ClearButtonClicked.Should().BeTrue(); @@ -255,7 +256,7 @@ public async Task ComboBox_MultiSelectEditable() var menu = comp.Find("div.mud-popover"); var input = combobox.Find("div.mud-input-control"); // check initial state - combobox.Instance.Value.Should().BeNullOrEmpty(); + combobox.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("d-none")); // click and check if it has toggled the menu @@ -285,7 +286,7 @@ public async Task ComboBox_MultiSelectTest1() var menu = comp.Find("div.mud-popover"); var input = combobox.Find("div.mud-input-control"); // check initial state - combobox.Instance.Value.Should().BeNullOrEmpty(); + combobox.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("d-none")); // click and check if it has toggled the menu @@ -356,7 +357,7 @@ public async Task ComboBoxTest_KeyboardNavigation_SingleSelect() await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = " ", Type = "keydown", })); comp.Render(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("d-none")); - comp.WaitForAssertion(() => combobox.Value.Should().Be(null)); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be(null)); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", AltKey = true, Type = "keydown", })); comp.Render(); @@ -369,28 +370,28 @@ public async Task ComboBoxTest_KeyboardNavigation_SingleSelect() await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); comp.Render(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("d-none")); - comp.WaitForAssertion(() => combobox.Value.Should().Be(null)); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be(null)); // If no item is hiligted, enter should only close popover, not select any item and value await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Escape", Type = "keydown", })); comp.Render(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("d-none")); - comp.WaitForAssertion(() => combobox.Value.Should().Be(null)); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be(null)); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.Render(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("d-none")); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().BeNull()); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().BeNull()); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("3")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("3")); //End key should not select the last disabled item await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "End", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("3")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("3")); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); @@ -398,35 +399,35 @@ public async Task ComboBoxTest_KeyboardNavigation_SingleSelect() await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.Render(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("d-none")); - comp.WaitForAssertion(() => combobox.Value.Should().Be("1")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("1")); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("2")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("2")); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Home", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("1")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("1")); //Arrow up should select still the first item await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowUp", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("3")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("3")); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "End", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("1")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("1")); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "2", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("1")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("1")); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("2")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("2")); } [Test] @@ -440,15 +441,15 @@ public async Task ComboBoxTest_KeyboardNavigation_ToggleSelect() comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("d-none")); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().BeNull()); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().BeNull()); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().Be("3")); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().Be("3")); //End key should not select the last disabled item await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => combobox.Value.Should().BeNull()); + comp.WaitForAssertion(() => combobox.GetState(x => x.Value).Should().BeNull()); } [Test] diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs index 13ec29f9..3d6ddf26 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs @@ -11,6 +11,7 @@ using static MudExtensions.UnitTests.TestComponents.SelectWithEnumTest; using MudBlazor; using MudExtensions.UnitTests.Extensions; +using MudBlazor.Extensions; namespace MudExtensions.UnitTests.Components { @@ -42,9 +43,9 @@ public void Select_InitialValueTest(bool multiSelection) }); var select = comp.FindComponent>(); - select.Instance.Value.Should().Be("1"); + select.Instance.GetState(x => x.Value).Should().Be("1"); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); - select.Instance.Text.Should().Be("1"); + select.Instance.GetState(x => x.Text).Should().Be("1"); } // Note: MudSelect doesn't guaranteed the consequences of changing SelectedValues if MultiSelection is false for now. @@ -61,9 +62,9 @@ public void Select_InitialValuesTest(bool multiSelection) }); var select = comp.FindComponent>(); - select.Instance.Value.Should().Be("1"); + select.Instance.GetState(x => x.Value).Should().Be("1"); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); - select.Instance.Text.Should().Be("1"); + select.Instance.GetState(x => x.Text).Should().Be("1"); } [Test] @@ -72,20 +73,20 @@ public async Task Select_ValueBubblingTest() var comp = Context.RenderComponent(); var select = comp.FindComponent>(); - select.Instance.Value.Should().BeNull(); - select.Instance.Text.Should().BeNull(); + select.Instance.GetState(x => x.Value).Should().BeNull(); + select.Instance.GetState(x => x.Text).Should().BeNull(); comp.SetParam("SelectedValue", "1"); await comp.InvokeAsync(() => select.Instance.ForceUpdate()); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("1")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("1")); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); - select.Instance.Text.Should().Be("1"); + select.Instance.GetState(x => x.Text).Should().Be("1"); comp.SetParam("SelectedValue", "2"); await comp.InvokeAsync(() => select.Instance.ForceUpdate()); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("2")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("2")); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "2" }); - select.Instance.Text.Should().Be("2"); + select.Instance.GetState(x => x.Text).Should().Be("2"); } [Test] @@ -97,18 +98,18 @@ public void Select_ValueBubblingTest_MultiSelection() }); var select = comp.FindComponent>(); - select.Instance.Value.Should().BeNull(); - select.Instance.Text.Should().BeNullOrEmpty(); + select.Instance.GetState(x => x.Value).Should().BeNull(); + select.Instance.GetState(x => x.Text).Should().BeNullOrEmpty(); comp.SetParam("SelectedValues", new HashSet() { "1" }); - select.Instance.Value.Should().Be("1"); + select.Instance.GetState(x => x.Value).Should().Be("1"); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); - select.Instance.Text.Should().Be("1"); + select.Instance.GetState(x => x.Text).Should().Be("1"); comp.SetParam("SelectedValues", new HashSet() { "2", "1" }); - select.Instance.Value.Should().Be("1"); + select.Instance.GetState(x => x.Value).Should().Be("1"); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "2", "1" }); - select.Instance.Text.Should().Be("2, 1"); + select.Instance.GetState(x => x.Text).Should().Be("2, 1"); } [Test] @@ -128,14 +129,14 @@ public async Task Select_ValueChangeEventCountTest() await comp.InvokeAsync(() => select.Instance.ForceUpdate()); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); - select.Instance.Value.Should().Be("1"); + select.Instance.GetState(x => x.Value).Should().Be("1"); // Changing value programmatically without ForceUpdate should change value, but should not fire change events // Its by design, so this part can be change if design changes await comp.InvokeAsync(() => select.SetParam("Value", "2")); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); - select.Instance.Value.Should().Be("2"); + select.Instance.GetState(x => x.Value).Should().Be("2"); } [Test] @@ -178,7 +179,7 @@ public async Task SelectTest1() // check popover class menu.ClassList.Should().Contain("select-popover-class"); // check initial state - select.Instance.Value.Should().BeNullOrEmpty(); + select.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); // click and check if it has toggled the menu input.Click(); @@ -189,7 +190,7 @@ public async Task SelectTest1() items[1].Click(); // menu should be closed now comp.WaitForAssertion(() => menu.ClassList.Should().NotContain("mud-popover-open")); - select.Instance.Value.Should().Be("2"); + select.Instance.GetState(x => x.Value).Should().Be("2"); // now we cheat and click the list without opening the menu ;) input.Click(); @@ -197,12 +198,12 @@ public async Task SelectTest1() items = comp.FindAll("div.mud-list-item-extended").ToArray(); items[0].Click(); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("1")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("1")); //Check user on blur implementation works var @switch = comp.FindComponent>(); @switch.Instance.Value = true; await comp.InvokeAsync(() => select.Instance.OnLostFocus(new FocusEventArgs())); - comp.WaitForAssertion(() => @switch.Instance.Value.Should().Be(false)); + comp.WaitForAssertion(() => @switch.Instance.GetState(x => x.Value).Should().Be(false)); } /// @@ -221,7 +222,7 @@ public async Task MultiSelectTest1() var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state - select.Instance.Value.Should().BeNullOrEmpty(); + select.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); // click and check if it has toggled the menu @@ -233,13 +234,13 @@ public async Task MultiSelectTest1() items[1].Click(); // menu should still be open now!! menu.ClassList.Should().Contain("mud-popover-open"); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("2")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("2")); items[0].Click(); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("2, 1")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("2, 1")); items[2].Click(); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("2, 1, 3")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("2, 1, 3")); items[0].Click(); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("2, 3")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("2, 3")); select.Instance.SelectedValues?.Count().Should().Be(2); select.Instance.SelectedValues.Should().Contain("2"); select.Instance.SelectedValues.Should().Contain("3"); @@ -283,8 +284,8 @@ public async Task SelectWithEnumTest() var select = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); - select.Instance.Value.Should().Be(default(MyEnum)); - select.Instance.Text.Should().Be(default(MyEnum).ToString()); + select.Instance.GetState(x => x.Value).Should().Be(default(MyEnum)); + select.Instance.GetState(x => x.Text).Should().Be(default(MyEnum).ToString()); comp.Find("input").Attributes["value"]?.Value.Should().Be("First"); comp.RenderCount.Should().Be(1); @@ -307,8 +308,8 @@ public void SelectUnrepresentableValueTest() // select elements needed for the test var select = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); - select.Instance.Value.Should().Be(17); - select.Instance.Text.Should().Be("17"); + select.Instance.GetState(x => x.Value).Should().Be(17); + select.Instance.GetState(x => x.Text).Should().Be("17"); comp.Find("input").Attributes["value"]?.Value.Should().Be("17"); input.Click(); comp.WaitForAssertion(() => comp.FindAll("div.mud-list-item-extended").Count.Should().BeGreaterThan(0)); @@ -317,8 +318,8 @@ public void SelectUnrepresentableValueTest() items[1].Click(); //Console.WriteLine(comp.Markup); //comp.WaitForAssertion(() => comp.Find("div.mud-input-slot").TextContent.Trim().Should().Be("Two")); - select.Instance.Value.Should().Be(2); - select.Instance.Text.Should().Be("2"); + select.Instance.GetState(x => x.Value).Should().Be(2); + select.Instance.GetState(x => x.Text).Should().Be("2"); } /// @@ -333,20 +334,20 @@ public void SelectUnrepresentableValueTest2() var select = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); - select.Instance.Value.Should().Be(17); - select.Instance.Text.Should().Be("17"); + select.Instance.GetState(x => x.Value).Should().Be(17); + select.Instance.GetState(x => x.Text).Should().Be("17"); //await Task.Delay(100); // BUT: we have a select with Strict="true" so the Text will not be shown because it is not in the list of selectable values - comp.FindComponent>().Instance.Value.Should().Be(null); + comp.FindComponent>().Instance.GetState(x => x.Value).Should().Be(null); comp.FindComponent>().Instance.InputType.Should().Be(InputType.Hidden); input.Click(); comp.WaitForAssertion(() => comp.FindAll("div.mud-list-item-extended").Count.Should().BeGreaterThan(0)); var items = comp.FindAll("div.mud-list-item-extended").ToArray(); items[1].Click(); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be(2)); - select.Instance.Text.Should().Be("2"); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be(2)); + select.Instance.GetState(x => x.Text).Should().Be("2"); //Console.WriteLine(comp.Markup); - comp.FindComponent>().Instance.Value.Should().Be("2"); + comp.FindComponent>().Instance.GetState(x => x.Value).Should().Be("2"); comp.FindComponent>().Instance.InputType.Should().Be(InputType.Hidden); // because list item has no render fragment, so we show it as text } @@ -362,8 +363,8 @@ public void SelectWithoutItemPresentersTest() var select = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); - select.Instance.Value.Should().BeTrue(); - select.Instance.Text.Should().Be("Open"); + select.Instance.GetState(x => x.Value).Should().BeTrue(); + select.Instance.GetState(x => x.Text).Should().Be("Open"); //comp.Find("div.mud-input-slot").Attributes["style"].Value.Should().Contain("display:none"); //comp.RenderCount.Should().Be(1); ////Console.WriteLine(comp.Markup); @@ -375,14 +376,14 @@ public void SelectWithoutItemPresentersTest() items[2].Click(); //comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); //comp.WaitForAssertion(() => comp.Find("div.mud-input-slot").Attributes["style"].Value.Should().Contain("display:none")); - select.Instance.Value.Should().BeFalse(); - select.Instance.Text.Should().Be("False"); + select.Instance.GetState(x => x.Value).Should().BeFalse(); + select.Instance.GetState(x => x.Text).Should().Be("False"); input.Click(); items = comp.FindAll("div.mud-list-item-extended").ToArray(); items[0].Click(); - select.Instance.Value.Should().BeNull(); - select.Instance.Text.Should().Be("Open and Closed"); + select.Instance.GetState(x => x.Value).Should().BeNull(); + select.Instance.GetState(x => x.Text).Should().Be("Open and Closed"); } [Test] @@ -396,7 +397,7 @@ public void Select_Should_FireTextChangedWithNewValue() var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state - select.Instance.Value.Should().BeNullOrEmpty(); + select.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); // click and check if it has toggled the menu input.Click(); @@ -407,8 +408,8 @@ public void Select_Should_FireTextChangedWithNewValue() items[1].Click(); // menu should be closed now comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("2")); - select.Instance.Text.Should().Be("2"); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("2")); + select.Instance.GetState(x => x.Text).Should().Be("2"); text.Should().Be("2"); //open the menu again @@ -417,8 +418,8 @@ public void Select_Should_FireTextChangedWithNewValue() items = comp.FindAll("div.mud-list-item-extended").ToArray(); items[0].Click(); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("1")); - select.Instance.Text.Should().Be("1"); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("1")); + select.Instance.GetState(x => x.Text).Should().Be("1"); text.Should().Be("1"); } @@ -451,7 +452,7 @@ public void SingleSelect_Should_FireTextChangedBeforeSelectedValuesChanged() var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state - select.Instance.Value.Should().BeNullOrEmpty(); + select.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); // click and check if it has toggled the menu input.Click(); @@ -463,8 +464,8 @@ public void SingleSelect_Should_FireTextChangedBeforeSelectedValuesChanged() items[1].Click(); // menu should be closed now comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("2")); - select.Instance.Text.Should().Be("2"); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("2")); + select.Instance.GetState(x => x.Text).Should().Be("2"); text.Should().Be("2"); selectedValuesChangedCount.Should().Be(1); textChangedCount.Should().Be(0); @@ -475,8 +476,8 @@ public void SingleSelect_Should_FireTextChangedBeforeSelectedValuesChanged() items = comp.FindAll("div.mud-list-item-extended").ToArray(); items[0].Click(); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("1")); - select.Instance.Text.Should().Be("1"); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("1")); + select.Instance.GetState(x => x.Text).Should().Be("1"); text.Should().Be("1"); string.Join(",", selectedValues ?? new List()).Should().Be("1"); comp.WaitForAssertion(() => selectedValuesChangedCount.Should().Be(3)); @@ -517,8 +518,8 @@ public void MultiSelect_Should_FireTextChangedBeforeSelectedValuesChanged() var items = comp.FindAll("div.mud-list-item-extended").ToArray(); // click list item items[1].Click(); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("2")); - select.Instance.Text.Should().Be("2"); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("2")); + select.Instance.GetState(x => x.Text).Should().Be("2"); text.Should().Be("2"); selectedValuesChangedCount.Should().Be(1); textChangedCount.Should().Be(0); @@ -528,7 +529,7 @@ public void MultiSelect_Should_FireTextChangedBeforeSelectedValuesChanged() items = comp.FindAll("div.mud-list-item-extended").ToArray(); items[0].Click(); comp.WaitForAssertion(() => select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "2", "1" })); - select.Instance.Text.Should().Be("2, 1"); + select.Instance.GetState(x => x.Text).Should().Be("2, 1"); text.Should().Be("2, 1"); string.Join(",", selectedValues ?? new List()).Should().Be("2,1"); selectedValuesChangedCount.Should().Be(3); @@ -564,7 +565,7 @@ public void Disabled_SelectItem_Should_Be_Respected() // Disabled item found twice because we have 2 shadow lists. Need to be discussed later comp.WaitForAssertion(() => comp.FindAll("div.mud-list-item-disabled-extended").Count.Should().Be(2)); comp.FindAll("div.mud-list-item-disabled-extended")[0].Click(); - comp.WaitForAssertion(() => select.Instance.Value.Should().BeNull()); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().BeNull()); } [Test] @@ -586,7 +587,7 @@ public async Task MultiSelect_ShouldCallValidationFunc() var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state - select.Instance.Value.Should().BeNullOrEmpty(); + select.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); select.Instance.SelectedValues.Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); // click and check if it has toggled the menu @@ -598,17 +599,17 @@ public async Task MultiSelect_ShouldCallValidationFunc() await comp.InvokeAsync(() => items[1].Click()); // menu should still be open now!! comp.WaitForAssertion(() => menu.ClassList.Should().Contain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("2")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("2")); comp.WaitForAssertion(() => select.Instance.SelectedValues.Should().Contain("2")); validatedValue.Should().BeEquivalentTo(new HashSet() { "2" }); items[0].Click(); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("2, 1")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("2, 1")); validatedValue.Should().BeEquivalentTo(new HashSet() { "2", "1" }); items[2].Click(); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("2, 1, 3")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("2, 1, 3")); validatedValue.Should().BeEquivalentTo(new HashSet() { "2", "1", "3" }); items[0].Click(); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("2, 3")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("2, 3")); validatedValue.Should().BeEquivalentTo(new HashSet() { "2", "3" }); //}); } @@ -633,7 +634,7 @@ public void MultiSelect_SelectAll() comp.FindAll("div.mud-list-item-extended")[0].Click(); // validate the result. all items should be selected - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("FirstA^SecondA^ThirdA")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("FirstA^SecondA^ThirdA")); validatedValue.Should().BeEquivalentTo(new HashSet() { "FirstA", "SecondA", "ThirdA"}); } @@ -703,7 +704,7 @@ public void SingleSelect_Should_CallValidationFunc() var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state - select.Instance.Value.Should().BeNullOrEmpty(); + select.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); // click and check if it has toggled the menu input.Click(); @@ -714,16 +715,16 @@ public void SingleSelect_Should_CallValidationFunc() comp.FindAll("div.mud-list-item-extended")[1].Click(); // menu should be closed now comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("2")); - select.Instance.Text.Should().Be("2"); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("2")); + select.Instance.GetState(x => x.Text).Should().Be("2"); validatedValue.Should().Be("2"); input.Click(); comp.WaitForAssertion(() => comp.FindAll("div.mud-list-item-extended").Count.Should().BeGreaterThan(0)); comp.FindAll("div.mud-list-item-extended")[0].Click(); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("1")); - select.Instance.Text.Should().Be("1"); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("1")); + select.Instance.GetState(x => x.Text).Should().Be("1"); validatedValue.Should().Be("1"); } @@ -761,7 +762,7 @@ public async Task MultiSelectTextTest() item.Click(); } - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("Empty, One, 2, 3")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("Empty, One, 2, 3")); } /// @@ -800,11 +801,11 @@ public async Task SelectClearableTest() var items = comp.FindAll("div.mud-list-item-extended").ToArray(); items[1].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("2")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("2")); comp.Find("button").Should().NotBeNull(); // Selection cleared and button removed after clicking clear button comp.Find("button").MouseDown(); - comp.WaitForAssertion(() => select.Instance.Value.Should().BeNullOrEmpty()); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().BeNullOrEmpty()); comp.FindAll("button").Should().BeEmpty(); // Clear button click handler should have been invoked comp.Instance.ClearButtonClicked.Should().BeTrue(); @@ -826,7 +827,7 @@ public void SelectReselectTest() input.Click(); comp.WaitForAssertion(() => comp.FindAll("div.mud-list-item-extended").Count.Should().BeGreaterThan(0)); - select.Instance.Value.Should().Be("Apple"); + select.Instance.GetState(x => x.Value).Should().Be("Apple"); comp.Instance.ChangeCount.Should().Be(0); // now click an item and see the value change @@ -835,7 +836,7 @@ public void SelectReselectTest() // menu should be closed now comp.WaitForAssertion(() => menu.ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("Orange")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("Orange")); comp.Instance.ChangeCount.Should().Be(1); // now click an item and see the value change @@ -844,7 +845,7 @@ public void SelectReselectTest() items = comp.FindAll("div.mud-list-item-extended").ToArray(); items[1].Click(); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("Orange")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("Orange")); comp.Instance.ChangeCount.Should().Be(1); } @@ -860,8 +861,8 @@ public async Task TextField_Should_Validate_Data_Attribute_Fail() // Select invalid option await comp.InvokeAsync(() => select.SelectOption("Quux")); // check initial state - select.Value.Should().Be("Quux"); - select.Text.Should().Be("Quux"); + select.GetState(x => x.Value).Should().Be("Quux"); + select.GetState(x => x.Text).Should().Be("Quux"); // check validity await comp.InvokeAsync(() => select.ValidateAsync()); select.ValidationErrors.Should().NotBeEmpty(); @@ -879,8 +880,8 @@ public async Task TextField_Should_Validate_Data_Attribute_Success() // Select valid option await comp.InvokeAsync(() => select.SelectOption("Qux")); // check initial state - select.Value.Should().Be("Qux"); - select.Text.Should().Be("Qux"); + select.GetState(x => x.Value).Should().Be("Qux"); + select.GetState(x => x.Text).Should().Be("Qux"); // check validity await comp.InvokeAsync(() => select.ValidateAsync()); select.ValidationErrors.Should().BeEmpty(); @@ -913,7 +914,7 @@ public async Task Select_Should_HilightSelectedValue() var input = comp.Find("div.mud-input-control"); comp.Find("div.mud-popover").ClassList.Should().Contain("select-popover-class"); - select.Instance.Value.Should().BeNullOrEmpty(); + select.Instance.GetState(x => x.Value).Should().BeNullOrEmpty(); comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open"); // open the select comp.Find("div.mud-input-control").Click(); @@ -923,7 +924,7 @@ public async Task Select_Should_HilightSelectedValue() // now click an item and see the value change comp.FindAll("div.mud-list-item-extended")[1].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("2")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("2")); // open again and check hilited option comp.Find("div.mud-input-control").Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); @@ -948,7 +949,7 @@ public void Select_Should_HilightInitiallySelectedValue() //Console.WriteLine(comp.Markup); var select = comp.FindComponent>(); comp.Find("div.mud-popover").ClassList.Should().Contain("select-popover-class"); - select.Instance.Value.Should().Be("2"); + select.Instance.GetState(x => x.Value).Should().Be("2"); comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open"); // open the select comp.Find("div.mud-input-control").Click(); @@ -960,7 +961,7 @@ public void Select_Should_HilightInitiallySelectedValue() // now click an item and see the value change comp.FindAll("div.mud-list-item-extended")[0].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("1")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("1")); // open again and check hilited option comp.Find("div.mud-input-control").Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); @@ -981,17 +982,17 @@ public async Task Select_Should_AllowReloadingItems() comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); comp.FindAll("div.mud-list-item-extended")[0].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("American Samoa")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("American Samoa")); comp.Find("div.mud-input-control").Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); comp.FindAll("div.mud-list-item-extended")[1].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("Arizona")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("Arizona")); comp.Find("div.mud-input-control").Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); comp.FindAll("div.mud-list-item-extended")[2].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("Arkansas")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("Arkansas")); // reloading! comp.Find(".reload").Click(); // check again, different values expected now @@ -999,17 +1000,17 @@ public async Task Select_Should_AllowReloadingItems() comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); comp.FindAll("div.mud-list-item-extended")[0].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("Alabama")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("Alabama")); comp.Find("div.mud-input-control").Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); comp.FindAll("div.mud-list-item-extended")[1].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("Alaska")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("Alaska")); comp.Find("div.mud-input-control").Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); comp.FindAll("div.mud-list-item-extended")[2].Click(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Instance.Value.Should().Be("American Samoa")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("American Samoa")); } [Test] @@ -1064,7 +1065,7 @@ public async Task SelectTest_KeyboardNavigation_SingleSelect() //If we didn't select an item with mouse or arrow keys yet, value should remains null. await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Value.Should().Be(null)); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be(null)); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", AltKey = true, Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); @@ -1074,61 +1075,61 @@ public async Task SelectTest_KeyboardNavigation_SingleSelect() //If dropdown is closed, arrow key should not set a value. await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); - comp.WaitForAssertion(() => select.Value.Should().Be(null)); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be(null)); // If no item is hiligted, enter should only close popover, not select any item and value await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "NumpadEnter", Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Value.Should().Be(null)); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be(null)); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowUp", Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().BeNull()); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().BeNull()); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().Be("2")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("2")); //End key should not select the last disabled item await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "End", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().Be("3")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("3")); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - comp.WaitForAssertion(() => select.Value.Should().Be("3")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("3")); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().Be("3")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("3")); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Home", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().Be("1")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("1")); //Arrow up should select still the first item await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowUp", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().Be("1")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("1")); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "End", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().Be("3")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("3")); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "2", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().Be("3")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("3")); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => select.Value.Should().Be("2")); + comp.WaitForAssertion(() => select.GetState(x => x.Value).Should().Be("2")); comp.WaitForAssertion(() => select.SelectedValues.Should().HaveCount(1)); await comp.InvokeAsync(() => select.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); @@ -1150,17 +1151,17 @@ public async Task SelectTest_KeyboardNavigation_MultiSelect() comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "a", CtrlKey = true, Type = "keydown", })); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("7 felines have been selected")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("7 felines have been selected")); await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "A", CtrlKey = true, Type = "keydown", })); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("0 feline has been selected")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("0 feline has been selected")); await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "ArrowDown", Type = "keydown", })); await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("1 feline has been selected")); + comp.WaitForAssertion(() => select.Instance.GetState(x => x.Text).Should().Be("1 feline has been selected")); await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "A", CtrlKey = true, Type = "keydown", })); - comp.WaitForAssertion(() => select.Instance.Text.Should().Be("7 felines have been selected")); + comp.WaitForAssertion(() => select.Instance.GetState("Text").Should().Be("7 felines have been selected")); await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Escape", Type = "keydown", })); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); @@ -1213,7 +1214,7 @@ public async Task SelectTest_ItemlessSelect() await comp.InvokeAsync(() => comp.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "End", Type = "keydown", })); await comp.InvokeAsync(() => comp.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => comp.Instance.SelectedValues.Should().HaveCount(0)); - comp.WaitForAssertion(() => comp.Instance.Value.Should().Be(null)); + comp.WaitForAssertion(() => comp.Instance.GetState(x => x.Value).Should().Be(null)); } [Test] @@ -1325,13 +1326,13 @@ public async Task MultiSelectAttributesOrder() var comp = Context.RenderComponent(); var select = comp.FindComponent>().Instance; select.SelectedValues?.Count().Should().Be(2); - select.Text.Should().Be("Programista, test"); + select.GetState(x => x.Text).Should().Be("Programista, test"); await comp.InvokeAsync(() => { select.SelectedValues = new List { "test" }; }); select.SelectedValues?.Count().Should().Be(1); - select.Text.Should().Be("test"); + select.GetState(x => x.Text).Should().Be("test"); } [Test] diff --git a/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs b/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs index 2a20f997..8f3601ff 100644 --- a/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs +++ b/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs @@ -11,82 +11,40 @@ namespace MudExtensions /// The extended base input fundamentals. /// /// - public abstract class MudBaseInputExtended : MudFormComponent + public abstract class MudBaseInputExtended : MudBaseInput { - private bool _isDirty; - private bool _validated; - protected bool _isFocused; - protected bool _forceTextUpdate; - protected string? InputElementId => _inputIdState.Value; private string? _userAttributesId = Identifier.Create("mudinputextended"); private readonly string _componentId = Identifier.Create("mudinputextended"); - /// - /// - /// - protected virtual bool SkipUpdateProcessOnSetParameters { get; set; } - - private readonly ParameterState _textState; - private readonly ParameterState _valueState; - private readonly ParameterState _formatState; - private readonly ParameterState _inputIdState; - /// /// /// protected MudBaseInputExtended() { - Converter = new DefaultConverter - { - Culture = GetCulture, - Format = GetFormat - }; + //Converter = new DefaultConverter + //{ + // Culture = GetCulture, + // Format = GetFormat + //}; - using var registerScope = CreateRegisterScope(); - _textState = registerScope.RegisterParameter(nameof(Text)) - .WithParameter(() => Text) - .WithEventCallback(() => TextChanged) - .WithChangeHandler(OnTextParameterChangedAsync); - _valueState = registerScope.RegisterParameter(nameof(Value)) - .WithParameter(() => Value) - .WithEventCallback(() => ValueChanged) - .WithChangeHandler(OnValueParameterChangedAsync); - _formatState = registerScope.RegisterParameter(nameof(Format)) - .WithParameter(() => Format) - .WithChangeHandler(OnCultureAndFormatChangedAsync); - _inputIdState = registerScope.RegisterParameter(nameof(InputId)) - .WithParameter(() => InputId) - .WithChangeHandler(UpdateInputIdStateAsync); + //using var registerScope = CreateRegisterScope(); + //_textState = registerScope.RegisterParameter(nameof(Text)) + // .WithParameter(() => Text) + // .WithEventCallback(() => TextChanged) + // .WithChangeHandler(OnTextParameterChangedAsync); + //_valueState = registerScope.RegisterParameter(nameof(Value)) + // .WithParameter(() => Value) + // .WithEventCallback(() => ValueChanged) + // .WithChangeHandler(OnValueParameterChangedAsync); + //_formatState = registerScope.RegisterParameter(nameof(Format)) + // .WithParameter(() => Format) + // .WithChangeHandler(OnCultureAndFormatChangedAsync); + //_inputIdState = registerScope.RegisterParameter(nameof(InputId)) + // .WithParameter(() => InputId) + // .WithChangeHandler(UpdateInputIdStateAsync); } - [CascadingParameter(Name = "ParentDisabled")] private bool ParentDisabled { get; set; } - [CascadingParameter(Name = "ParentReadOnly")] private bool ParentReadOnly { get; set; } - /// - /// Disable input component if true. Default is false. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool Disabled { get; set; } - - /// - /// Get the input component is disabled or not. - /// - /// - protected bool GetDisabledState() => Disabled || ParentDisabled; - - /// - /// If true, the input will be read-only. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool ReadOnly { get; set; } - - /// - /// Get the input component is readonly or not. - /// - /// - protected bool GetReadOnlyState() => ReadOnly || ParentReadOnly; /// /// Fires on input. @@ -98,86 +56,12 @@ protected MudBaseInputExtended() /// [Parameter] public EventCallback OnChange { get; set; } - /// - /// The ID of the input element. - /// - /// - /// When set takes precedence over any internally generated IDs. - /// - [Parameter, ParameterState] - [Category(CategoryTypes.FormComponent.Behavior)] - public string? InputId { get; set; } - - /// - /// Set the text-align on the component. - /// - [Parameter] - [Category(CategoryTypes.Text.Appearance)] - public Typo Typo { get; set; } = Typo.subtitle1; - - /// - /// If true, the input will take up the full width of its container. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Appearance)] - public bool FullWidth { get; set; } - - /// - /// If true, the input will update the Value immediately on typing. - /// If false, the Value is updated only on Enter. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool Immediate { get; set; } - - /// - /// If false, the input will not have an underline. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Appearance)] - public bool Underline { get; set; } = true; - /// /// Gets or sets a value indicating whether the component has an adornment at the start. /// [Parameter] public bool HasAdornmentStart { get; set; } - /// - /// The HelperText will be displayed below the text field. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public string? HelperText { get; set; } - - /// - /// If true, the helper text will only be visible on focus. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool HelperTextOnFocus { get; set; } - - /// - /// Icon that will be used if Adornment is set to Start or End. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public string? AdornmentIcon { get; set; } - - /// - /// Text that will be used if Adornment is set to Start or End, the Text overrides Icon. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public string? AdornmentText { get; set; } - - /// - /// The Adornment if used. By default, it is set to None. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public Adornment Adornment { get; set; } = Adornment.None; - /// /// The Adornment if used. By default, it is set to None. /// @@ -192,271 +76,12 @@ protected MudBaseInputExtended() [Category(CategoryTypes.FormComponent.Behavior)] public RenderFragment? AdornmentEnd { get; set; } - /// - /// The aria-label of the adornment. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Appearance)] - public string? AdornmentAriaLabel { get; set; } = string.Empty; - - /// - /// The validation is only triggered if the user has changed the input value at least once. By default, it is false - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool OnlyValidateIfDirty { get; set; } = false; - - /// - /// If true shrinks label directly. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool ShrinkLabel { get; set; } - - /// - /// The color of the adornment if used. It supports the theme colors. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Appearance)] - public Color AdornmentColor { get; set; } = Color.Default; - - /// - /// The Icon Size. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Appearance)] - public Size IconSize { get; set; } = Size.Medium; - - /// - /// Button click event if set and Adornment used. - /// - [Parameter] public EventCallback OnAdornmentClick { get; set; } - - /// - /// Variant to use. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Appearance)] - public Variant Variant { get; set; } = Variant.Text; - - /// - /// Will adjust vertical spacing. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Appearance)] - public Margin Margin { get; set; } = Margin.None; - - /// - /// The short hint displayed in the input before the user enters a value. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public string? Placeholder { get; set; } - - /// - /// If set, will display the counter, value 0 will display current count but no stop count. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Validation)] - public int? Counter { get; set; } - - /// - /// Maximum number of characters that the input will accept - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Validation)] - public int MaxLength { get; set; } = 524288; - - /// - /// If string has value the label text will be displayed in the input, and scaled down at the top if the input has value. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public string? Label { get; set; } - - /// - /// If true the input will focus automatically. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool AutoFocus { get; set; } - - /// - /// A multiline input (textarea) will be shown, if set to more than one line. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public int Lines { get; set; } = 1; - - /// - /// The text to be displayed. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Data)] - public string? Text { get; set; } - - /// - /// When TextUpdateSuppression is true (which is default) the text can not be updated by bindings while the component is focused in BSS (not WASM). - /// This solves issue #1012: Textfield swallowing chars when typing rapidly - /// If you need to update the input's text while it is focused you can set this parameter to false. - /// Note: on WASM text update suppression is not active, so this parameter has no effect. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool TextUpdateSuppression { get; set; } = true; - - /// - /// Hints at the type of data that might be entered by the user while editing the input - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public virtual InputMode InputMode { get; set; } = InputMode.text; - - /// - /// The pattern attribute, when specified, is a regular expression which the input's value must match in order for the value to pass constraint validation. It must be a valid JavaScript regular expression - /// Not Supported in multline input - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Validation)] - public virtual string? Pattern { get; set; } - /// /// CSS style of the child content. /// [Parameter] public string? ChildContentStyle { get; set; } - /// - /// Sync the value, values and text, calls validation manually. Useful to call after user changes value or text programmatically. - /// - /// - public virtual async Task ForceUpdate() - { - await SetValueAsync(Value, force: true); - } - - /// - /// Derived classes need to override this if they can be something other than text - /// - internal virtual InputType GetInputType() { return InputType.Text; } - - /// - /// - /// - /// - /// - /// - protected virtual async Task SetTextAsync(string? text, bool updateValue = true) - { - if (Text != text) - { - Text = text; - _validated = false; - if (!string.IsNullOrWhiteSpace(Text)) - Touched = true; - if (updateValue) - await UpdateValuePropertyAsync(false); - await TextChanged.InvokeAsync(Text); - } - } - - /// - /// Text change hook for descendants. Called when Text needs to be refreshed from current Value property. - /// - protected virtual Task UpdateTextPropertyAsync(bool updateValue) - { - return SetTextAndUpdateValueAsync(ConvertSet(ReadValue), updateValue); - } - - /// - /// Focus to the element. - /// - /// The ValueTask - public virtual ValueTask FocusAsync() => ValueTask.CompletedTask; - - /// - /// Blur from the element. - /// - /// - public virtual ValueTask BlurAsync() => ValueTask.CompletedTask; - - /// - /// Focus and select all text. - /// - /// - public virtual ValueTask SelectAsync() => ValueTask.CompletedTask; - - /// - /// Focus and select partial text with given positions. - /// - /// - /// - /// - public virtual ValueTask SelectRangeAsync(int pos1, int pos2) => ValueTask.CompletedTask; - - /// - /// Fired when the text value changes. - /// - [Parameter] public EventCallback TextChanged { get; set; } - - /// - /// Fired when the element loses focus. - /// - [Parameter] public EventCallback OnBlur { get; set; } - - /// - /// Fired when the element changes internally its text value. - /// - [Parameter] - public EventCallback OnInternalInputChanged { get; set; } - - /// - /// - /// - /// - /// - protected internal virtual async Task OnBlurredAsync(FocusEventArgs obj) - { - if (ReadOnly) - { - return; - } - - _isFocused = false; - - if (!OnlyValidateIfDirty || _isDirty) - { - Touched = true; - if (_validated) - await OnBlur.InvokeAsync(obj); - else - await BeginValidationAfterAsync(OnBlur.InvokeAsync(obj)); - } - } - - /// - /// Fired on the KeyDown event. - /// - [Parameter] public EventCallback OnKeyDown { get; set; } - - /// - /// - /// - /// - /// - protected virtual async Task InvokeKeyDownAsync(KeyboardEventArgs obj) - { - _isFocused = true; - await OnKeyDown.InvokeAsync(obj); - } - - /// - /// Prevent the default action for the KeyDown event. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool KeyDownPreventDefault { get; set; } - /// /// If true disables paste to input component. Default is false. /// @@ -464,331 +89,33 @@ protected virtual async Task InvokeKeyDownAsync(KeyboardEventArgs obj) [Category(CategoryTypes.FormComponent.Behavior)] public bool DisablePaste { get; set; } - /// - /// Fired on the KeyUp event. - /// - [Parameter] public EventCallback OnKeyUp { get; set; } - - /// - /// - /// - /// - /// - protected virtual async Task InvokeKeyUpAsync(KeyboardEventArgs obj) - { - _isFocused = true; - await OnKeyUp.InvokeAsync(obj); - } - - /// - /// Prevent the default action for the KeyUp event. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Behavior)] - public bool KeyUpPreventDefault { get; set; } - - /// - /// Fired when the Value property changes. - /// - [Parameter] - public EventCallback ValueChanged { get; set; } - - /// - /// The value of this input element. - /// - [Parameter] - [Category(CategoryTypes.FormComponent.Data)] - public T? Value - { - get => _value; - set => _value = value; - } /// /// /// - /// - /// - /// /// - protected virtual async Task SetValueAsync(T? value, bool updateText = true, bool force = false) - { - if (!EqualityComparer.Default.Equals(Value, value) || force == true) - { - _isDirty = true; - _validated = false; - Value = value; - await ValueChanged.InvokeAsync(Value); - if (updateText) - await UpdateTextPropertyAsync(false); - FieldChanged(Value); - await BeginValidateAsync(); - } - } - - /// - /// Value change hook for descendants. Called when Value needs to be refreshed from current Text property. - /// - protected virtual Task UpdateValuePropertyAsync(bool updateText) - { - return SetValueAndUpdateTextAsync(ConvertGet(ReadText), updateText); - } - - /// - /// The format applied to values. - /// - /// - /// This property is passed into the ToString() method of the property, such as formatting int, float, DateTime and TimeSpan values. - /// - [Parameter, ParameterState] - [Category(CategoryTypes.FormComponent.Behavior)] - public string? Format { get; set; } - - protected override string? GetFormat() => _formatState.Value; - protected override async Task OnCultureAndFormatChangedAsync() { await base.OnCultureAndFormatChangedAsync(); await UpdateTextPropertyAsync(false); } - protected override async Task OnConverterChangedAsync() - { - await base.OnConverterChangedAsync(); - await UpdateTextPropertyAsync(false); - } - - /// - /// - /// - /// - protected override async Task ValidateValue() - { - if (SubscribeToParentFormExtended) - { - try - { - _validated = true; - await base.ValidateValue(); - } - catch - { - - } - - } - } - - /// - /// - /// - /// - protected override async Task OnInitializedAsync() - { - await base.OnInitializedAsync(); - - // Because the way the Value setter is built, it won't cause an update if the incoming Value is - // equal to the initial value. This is why we force an update to the Text property here. - if (typeof(T) != typeof(string)) - await UpdateTextPropertyAsync(false); - - if (Label == null && For != null) - Label = For.GetLabelString(); - } - /// /// /// - /// /// - public virtual async Task ForceRender(bool forceTextUpdate) + protected override async Task OnConverterChangedAsync() { - _forceTextUpdate = true; + await base.OnConverterChangedAsync(); await UpdateTextPropertyAsync(false); - StateHasChanged(); } /// /// /// - /// /// - public override async Task SetParametersAsync(ParameterView parameters) - { - await base.SetParametersAsync(parameters); - if (SkipUpdateProcessOnSetParameters == true) - { - return; - } - var hasText = parameters.Contains(nameof(Text)); - var hasValue = parameters.Contains(nameof(Value)); + protected string? ResolveAriaDescribedBy() => GetAriaDescribedByString(); - // Refresh Value from Text - if (hasText && !hasValue) - await UpdateValuePropertyAsync(false); - - // Refresh Text from Value - if (hasValue && !hasText) - { - var updateText = true; - if (_isFocused && !_forceTextUpdate) - { - // Text update suppression, only in BSS (not in WASM). - // This is a fix for #1012 - if (RuntimeLocation.IsServerSide && TextUpdateSuppression) - updateText = false; - } - if (updateText) - { - _forceTextUpdate = false; - await UpdateTextPropertyAsync(false); - } - } - } - - /// - /// - /// - /// - /// - protected override async Task OnAfterRenderAsync(bool firstRender) - { - //Only focus automatically after the first render cycle! - if (firstRender && AutoFocus) - { - await FocusAsync(); - } - } - - /// - /// - /// - protected override void OnParametersSet() - { - if (SubscribeToParentFormExtended) - base.OnParametersSet(); - } - - /// - /// - /// - /// - protected override async Task ResetValueAsync() - { - await SetTextAsync(null, updateValue: true); - _isDirty = false; - _validated = false; - await base.ResetValueAsync(); - } - - [CascadingParameter(Name = "SubscribeToParentFormExtended")] - internal bool SubscribeToParentFormExtended { get; set; } = true; - - private async Task UpdateInputIdStateAsync() - { - if (_inputIdState.Value is not null) - { - return; - } - - if (_userAttributesId is not null) - { - await _inputIdState.SetValueAsync(_userAttributesId); - return; - } - - await _inputIdState.SetValueAsync(_componentId); - } - - private async Task OnValueParameterChangedAsync(ParameterChangedEventArgs arg) - { - _isDirty = true; - _validated = false; - - // When Value changes from parent, update Text from Value - // But only if Text is not also being set in the same parameter update - // Check ParameterView to see if Text is also present - if (!arg.ParameterView.Contains(nameof(Text))) - { - // Always update text when Value changes (TextUpdateSuppression removed) - _forceTextUpdate = false; - await UpdateTextPropertyAsync(false); - } - } - - private async Task OnTextParameterChangedAsync(ParameterChangedEventArgs arg) - { - _validated = false; - - if (!string.IsNullOrEmpty(arg.Value)) - { - Touched = true; - } - - // When Text changes from parent, update Value from Text using UpdateValuePropertyAsync - // But only if Value is not also being set in the same parameter update - // Check ParameterView to see if Value is also present - if (!arg.ParameterView.Contains(nameof(Value))) - { - await UpdateValuePropertyAsync(updateText: false); - } - } - - protected internal string? ReadText => _textState.Value; - protected Task SetTextAsync(string? text) => _textState.SetValueAsync(text); - - protected virtual async Task SetValueAndUpdateTextAsync(T? value, bool updateText = true, bool force = false) - { - var valueChanged = !EqualityComparer.Default.Equals(ReadValue, value); - - if (!valueChanged && !force) - { - return; - } - - _isDirty = true; - _validated = false; - - // Use ParameterState to set Value instead of direct assignment - // This ensures proper parameter lifecycle management - await _valueState.SetValueAsync(value); - - // If force is true but value hasn't changed, ParameterState won't fire the callback - // so we need to manually invoke it to maintain backward compatibility - if (force && !valueChanged) - { - await ValueChanged.InvokeAsync(value); - } - - if (updateText) - { - await UpdateTextPropertyAsync(false); - } - - FieldChanged(value); - await BeginValidateAsync(); - } - - protected virtual async Task SetTextAndUpdateValueAsync(string? text, bool updateValue = true) - { - if (ReadText == text) - { - return; - } - - _validated = false; - - if (!string.IsNullOrEmpty(text)) - { - Touched = true; - } - - await _textState.SetValueAsync(text); - if (updateValue) - { - await UpdateValuePropertyAsync(false); - } - } } internal static class ParameterViewExtensions diff --git a/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor b/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor index cb5a8b6f..3bf14e42 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor @@ -18,15 +18,15 @@ Style="@Style" Converter="@Converter" Counter="@Counter" - Culture="@Culture" + Culture="@GetCulture()" DebounceInterval="@DebounceInterval" Disabled="@Disabled" Underline="@Underline" - Error="@Error" - ErrorId="@ErrorId" - ErrorText="@ErrorText" + Error="@ErrorState.Value" + ErrorId="@ErrorIdState.Value" + ErrorText="@GetErrorText()" For="@For" - Format="@Format" + Format="@GetFormat()" FullWidth="@FullWidth" HelperText="@HelperText" HelperTextOnFocus="@HelperTextOnFocus" diff --git a/CodeBeam.MudBlazor.Extensions/Components/CodeInput/MudCodeInput.razor b/CodeBeam.MudBlazor.Extensions/Components/CodeInput/MudCodeInput.razor index 236325fd..dae91d6e 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/CodeInput/MudCodeInput.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/CodeInput/MudCodeInput.razor @@ -2,14 +2,14 @@ @typeparam T @inherits MudFormComponent - +
@for (int i = 0; i < Count; i++) { int a = i; }
diff --git a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor index be56b2a9..e9c7fa6f 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor @@ -11,20 +11,19 @@
+ Error="@HasErrors" ErrorText="@GetErrorText()" ErrorId="@ErrorIdState.Value" Disabled="@Disabled" @onclick="@ToggleMenu" Required="@Required" ForId="@FieldId"> @*DataVisualiserStyle="@($"min-height: 1.1876em;{(HasValue(Value) && Editable == true ? "padding-bottom: 0px" : null)}")"*@ + Disabled="@GetDisabledState()" ReadOnly="@GetReadOnlyState()" Error="@ErrorState.Value" ErrorId="@ErrorIdState.Value" + Clearable="@Clearable" ForceClearable="@(Clearable && HasValue(ReadValue))" OnClearButtonClick="@ClearButtonClickHandlerAsync" + MaxLength="@MaxLength" @attributes="UserAttributes" OnBlur="@HandleOnBlur" ShrinkLabel="@(HasValue(ReadValue) || AdornmentStart != null || _isOpen || ShrinkLabel)"> @AdornmentStart @@ -43,7 +42,7 @@
- @if (!HasValue(Value) && !string.IsNullOrWhiteSpace(Placeholder)) + @if (!HasValue(ReadValue) && !string.IsNullOrWhiteSpace(Placeholder)) { @Placeholder } @@ -51,7 +50,7 @@ { @{ - var collection = Items.Where(x => (MultiSelection ? SelectedValues?.Contains(x.Value) == true : Value?.Equals(x.Value) == true))?.ToList(); + var collection = Items.Where(x => (MultiSelection ? SelectedValues?.Contains(x.Value) == true : ReadValue?.Equals(x.Value) == true))?.ToList(); if (collection is not null) { foreach (var item in CollectionsMarshal.AsSpan(collection)) @@ -76,16 +75,16 @@ } else if (ItemTemplate is not null) { - if (Value is not null) + if (ReadValue is not null) { - @ItemTemplate(Items.FirstOrDefault(x => x.Value?.Equals(Value) == true) ?? new MudComboBoxItem()) + @ItemTemplate(Items.FirstOrDefault(x => x.Value?.Equals(ReadValue) == true) ?? new MudComboBoxItem()) } else if (!string.IsNullOrWhiteSpace(Placeholder)) { @Placeholder } } - else if (Items.FirstOrDefault(x => x?.Value?.Equals(Value) == true)?.ChildContent is not null) + else if (Items.FirstOrDefault(x => x?.Value?.Equals(ReadValue) == true)?.ChildContent is not null) { if (MultiSelection) { @@ -99,7 +98,7 @@ } else { - @Items.FirstOrDefault(x => x.Value?.Equals(Value) == true)?.ChildContent + @Items.FirstOrDefault(x => x.Value?.Equals(ReadValue) == true)?.ChildContent } } else @@ -111,7 +110,7 @@
- @if (!HasValue(Value) && !string.IsNullOrWhiteSpace(Placeholder)) + @if (!HasValue(ReadValue) && !string.IsNullOrWhiteSpace(Placeholder)) { @Placeholder } diff --git a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs index ba3037bd..ad04a6f5 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBox.razor.cs @@ -88,7 +88,7 @@ protected internal void SetSearchString(T value) new StyleBuilder() .AddStyle("height: auto") .AddStyle("min-height: 1.1876em") - .AddStyle("display", "inline", Value != null || SelectedValues?.Any() == true) + .AddStyle("display", "inline", ReadValue != null || SelectedValues?.Any() == true) .Build(); private readonly string _elementId = string.Concat("combobox_", Guid.NewGuid().ToString().AsSpan(0, 8)); @@ -515,19 +515,19 @@ protected async Task SyncMultiselectionValues(bool singleToMultiselection) { if (singleToMultiselection == true) { - if (Value == null) + if (ReadValue == null) { SelectedValues = new HashSet(); } else { - if (Value is string && string.IsNullOrWhiteSpace(base.ConvertSet(Value))) + if (ReadValue is string && string.IsNullOrWhiteSpace(base.ConvertSet(ReadValue))) { SelectedValues = new HashSet(); } else { - SelectedValues = new HashSet() { Value }; + SelectedValues = new HashSet() { ReadValue }; } } @@ -535,7 +535,7 @@ protected async Task SyncMultiselectionValues(bool singleToMultiselection) } else { - await SetValueAsync(SelectedValues.LastOrDefault(), false); + await SetValueAndUpdateTextAsync(SelectedValues.LastOrDefault(), false); _searchString = base.ConvertSet(SelectedValues.LastOrDefault()); } } @@ -673,9 +673,9 @@ protected Task UpdateDataVisualiserTextAsync() } else { - var item = Items?.FirstOrDefault(x => Value == null ? x.Value == null : Comparer != null ? Comparer.Equals(Value, x.Value) : Value.Equals(x.Value)); + var item = Items?.FirstOrDefault(x => ReadValue == null ? x.Value == null : Comparer != null ? Comparer.Equals(ReadValue, x.Value) : ReadValue.Equals(x.Value)); _dataVisualiserText = item is null - ? base.ConvertSet(Value) + ? base.ConvertSet(ReadValue) : (!string.IsNullOrWhiteSpace(item.Text) ? item.Text : base.ConvertSet(item.Value)); return Task.CompletedTask; @@ -692,10 +692,10 @@ protected Task UpdateDataVisualiserTextAsync() /// protected async Task UpdateComboBoxValueAsync(T? value, bool updateText = true, bool updateSearchString = false, bool force = false) { - await SetValueAsync(value, updateText, force); + await SetValueAndUpdateTextAsync(value, updateText, force); if (updateSearchString) { - _searchString = base.ConvertSet(Value); + _searchString = base.ConvertSet(ReadValue); await _inputReference.SetText(_searchString); } } @@ -726,9 +726,9 @@ protected override void OnInitialized() { base.OnInitialized(); UpdateIcon(); - if (!MultiSelection && Value != null) + if (!MultiSelection && ReadValue != null) { - _selectedValues = new HashSet(_comparer) { Value }; + _selectedValues = new HashSet(_comparer) { ReadValue }; } else if (MultiSelection && SelectedValues != null) { @@ -784,16 +784,16 @@ protected override async Task OnParametersSetAsync() else { DeselectAllItems(); - if (Value is not null) - Items.FirstOrDefault(x => x.Value?.Equals(Value) == true).Selected = true; + if (ReadValue is not null) + Items.FirstOrDefault(x => x.Value?.Equals(ReadValue) == true).Selected = true; } } - if ((Value == null && _oldValue != null) || (Value != null && Value.Equals(_oldValue) == false)) + if ((ReadValue == null && _oldValue != null) || (ReadValue != null && ReadValue.Equals(_oldValue) == false)) { await ForceUpdateItems(); if (MultiSelection == false) { - _searchString = base.ConvertSet(Value); + _searchString = base.ConvertSet(ReadValue); if (_inputReference != null) { await _inputReference?.SetText(_searchString); @@ -802,7 +802,7 @@ protected override async Task OnParametersSetAsync() } await UpdateDataVisualiserTextAsync(); _oldMultiselection = MultiSelection; - _oldValue = Value; + _oldValue = ReadValue; } /// @@ -1044,9 +1044,9 @@ protected internal async Task HandleOnBlur(FocusEventArgs obj) else { // Restore the previous selected item, if any. - if (Value is not null) + if (ReadValue is not null) { - item = Items.FirstOrDefault(x => x?.Value?.Equals(Value) == true); + item = Items.FirstOrDefault(x => x?.Value?.Equals(ReadValue) == true); if (item is not null) await ToggleOption(item, true); @@ -1148,7 +1148,7 @@ public async Task OpenMenu() _allSelected = GetAllSelectedState(); - _lastActivatedItem = Items.FirstOrDefault(x => x.Value?.Equals(MultiSelection ? SelectedValues.LastOrDefault() : Value) == true); + _lastActivatedItem = Items.FirstOrDefault(x => x.Value?.Equals(MultiSelection ? SelectedValues.LastOrDefault() : ReadValue) == true); if (_lastActivatedItem is not null) await ScrollToMiddleAsync(_lastActivatedItem); else @@ -1210,7 +1210,7 @@ protected internal async Task ToggleOption(MudComboBoxItem? item, bool select if (selected == false) { - if (MultiSelection == false && Value?.Equals(item.Value) == true) + if (MultiSelection == false && ReadValue?.Equals(item.Value) == true) { if (ToggleSelection) { @@ -1221,7 +1221,7 @@ protected internal async Task ToggleOption(MudComboBoxItem? item, bool select else if (MultiSelection == true && SelectedValues?.Contains(item.Value) == true) { SelectedValues = SelectedValues.Where(x => x.Equals(item.Value) == false); - await SetValueAsync(SelectedValues.LastOrDefault(), false); + await SetValueAndUpdateTextAsync(SelectedValues.LastOrDefault(), false); item.Selected = false; _allSelected = GetAllSelectedState(); } @@ -1235,7 +1235,7 @@ protected internal async Task ToggleOption(MudComboBoxItem? item, bool select } else if (SelectedValues?.Contains(item.Value) != true) { - await SetValueAsync(item.Value, false); + await SetValueAndUpdateTextAsync(item.Value, false); SelectedValues = SelectedValues.Append(item.Value); await SelectedValuesChanged.InvokeAsync(_selectedValues); _allSelected = GetAllSelectedState(); @@ -1326,7 +1326,7 @@ protected async Task ClearButtonClickHandlerAsync(MouseEventArgs e) { await UpdateComboBoxValueAsync(default); _searchString = null; - await SetTextAsync(default, false); + await SetTextAndUpdateValueAsync(default, false); _selectedValues?.Clear(); DeselectAllItems(); await BeginValidateAsync(); @@ -1344,9 +1344,9 @@ protected async Task ClearButtonClickHandlerAsync(MouseEventArgs e) /// public async Task Clear() { - await SetValueAsync(default, false); + await SetValueAndUpdateTextAsync(default, false); _searchString = null; - await SetTextAsync(default, false); + await SetTextAndUpdateValueAsync(default, false); _selectedValues?.Clear(); await BeginValidateAsync(); StateHasChanged(); @@ -1411,7 +1411,7 @@ protected async Task SelectAllItems() SelectedValues = SelectedValues.Append(item.Value); } await SelectedValuesChanged.InvokeAsync(SelectedValues); - await SetValueAsync(SelectedValues.LastOrDefault(), false); + await SetValueAndUpdateTextAsync(SelectedValues.LastOrDefault(), false); _allSelected = true; } else diff --git a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBoxItem.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBoxItem.razor.cs index c06329bd..ee0d6f82 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBoxItem.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/ComboBox/MudComboBoxItem.razor.cs @@ -43,7 +43,7 @@ public partial class MudComboBoxItem : MudComponentBase, IDisposable /// The parent select component ///
[CascadingParameter] - MudComboBox MudComboBox { get; set; } + MudComboBox MudComboBox { get; set; } = null!; /// /// Prevents the user from interacting with this item. diff --git a/CodeBeam.MudBlazor.Extensions/Components/DateWheelPicker/MudDateWheelPicker.razor b/CodeBeam.MudBlazor.Extensions/Components/DateWheelPicker/MudDateWheelPicker.razor index 4f33f99d..b321d663 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/DateWheelPicker/MudDateWheelPicker.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/DateWheelPicker/MudDateWheelPicker.razor @@ -4,13 +4,13 @@
+ Error="@HasErrors" ErrorText="@ErrorTextState.Value" ErrorId="@ErrorIdState.Value" Disabled="@Disabled" @onclick="@(Editable ? null : ToggleMenu)" Required="@Required" ForId="@FieldId"> public partial class MudDateWheelPicker : MudBaseInput { - MudDateWheelPicker() + /// + /// + /// + public MudDateWheelPicker() { Converter = Conversions.From((DateTime? x) => x?.ToString(DateFormat), x => DateTime.TryParseExact(x, DateFormat, null, DateTimeStyles.None, out DateTime dt) ? dt : null); } @@ -172,7 +175,7 @@ public partial class MudDateWheelPicker : MudBaseInput [Parameter] public DateWheelPickerLocalizedStrings LocalizedStrings { get; set; } = new(); - private string GetCounterText() => Counter == null ? string.Empty : (Counter == 0 ? (string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") : ((string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") + $" / {Counter}")); + private string GetCounterText() => Counter == null ? string.Empty : (Counter == 0 ? (string.IsNullOrEmpty(ReadText) ? "0" : $"{ReadText.Length}") : ((string.IsNullOrEmpty(ReadText) ? "0" : $"{ReadText.Length}") + $" / {Counter}")); /// /// Show clear button. @@ -292,7 +295,7 @@ public partial class MudDateWheelPicker : MudBaseInput /// protected async Task UpdateValueAsync(bool updateText = true) { - var _backUpValue = Value; + var _backUpValue = ReadValue; try { await SetValueAndUpdateTextAsync(new DateTime(_year, _month, _day, _hour, _minute, _second), updateText); @@ -480,16 +483,16 @@ private void OnYearChanged(int year) /// protected void SetWheelValues() { - if (Value == null) + if (ReadValue == null) { return; } - _day = Value.Value.Day; - _month = Value.Value.Month; - _year = Value.Value.Year; - _hour = Value.Value.Hour; - _minute = Value.Value.Minute; - _second = Value.Value.Second; + _day = ReadValue.Value.Day; + _month = ReadValue.Value.Month; + _year = ReadValue.Value.Year; + _hour = ReadValue.Value.Hour; + _minute = ReadValue.Value.Minute; + _second = ReadValue.Value.Second; RefreshDays(); } diff --git a/CodeBeam.MudBlazor.Extensions/Components/FontPicker/MudFontPicker.razor b/CodeBeam.MudBlazor.Extensions/Components/FontPicker/MudFontPicker.razor index f6eecf60..b4893ca2 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/FontPicker/MudFontPicker.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/FontPicker/MudFontPicker.razor @@ -4,7 +4,7 @@ diff --git a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudDebouncedInputExtended.cs b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudDebouncedInputExtended.cs index 515c8b76..a766ffb1 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudDebouncedInputExtended.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudDebouncedInputExtended.cs @@ -114,7 +114,7 @@ private void OnTimerTick(object? sender, ElapsedEventArgs e) private async Task OnTimerTickGuiThread() { await base.UpdateValuePropertyAsync(false); - await OnDebounceIntervalElapsed.InvokeAsync(Text); + await OnDebounceIntervalElapsed.InvokeAsync(ReadText); } private void ClearTimer(bool suppressTick = false) diff --git a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputCssHelperExtended.cs b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputCssHelperExtended.cs index 93cf3c3c..309f55a5 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputCssHelperExtended.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputCssHelperExtended.cs @@ -27,7 +27,7 @@ public static string GetClassname(MudBaseInputExtended baseInput, Func : MudBaseInputExtended /// ///
protected string? Classname => MudInputCssHelperExtended.GetClassname(this, - () => HasNativeHtmlPlaceholder() || ShrinkLabel == true || !string.IsNullOrEmpty(Text) || !string.IsNullOrWhiteSpace(Placeholder) || !string.IsNullOrEmpty(base.ConvertSet(Value))); + () => HasNativeHtmlPlaceholder() || ShrinkLabel == true || !string.IsNullOrEmpty(ReadText) || !string.IsNullOrWhiteSpace(Placeholder) || !string.IsNullOrEmpty(base.ConvertSet(ReadValue))); /// /// @@ -107,7 +106,6 @@ protected override async Task OnAfterRenderAsync(bool firstRender) /// [Parameter] public InputType InputType { get; set; } = InputType.Text; - internal override InputType GetInputType() => InputType; /// /// @@ -133,6 +131,11 @@ private async Task OnInputOrOnChangeAsync(string? input) } } + /// + /// + /// + /// + /// protected async Task OnInputHandler(string? args) { _isFocused = true; @@ -141,6 +144,11 @@ protected async Task OnInputHandler(string? args) await SetTextAndUpdateValueAsync(args); } + /// + /// + /// + /// + /// protected async Task OnChangeHandler(string? args) { _internalText = args; @@ -304,7 +312,7 @@ private void UpdateClearable(object? value) Clearable = showClearable; } - private bool GetClearable() => Clearable && ((Value is string stringValue && !string.IsNullOrWhiteSpace(stringValue)) || (Value is not string && Value is not null)); + private bool GetClearable() => Clearable && ((ReadValue is string stringValue && !string.IsNullOrWhiteSpace(stringValue)) || (ReadValue is not string && ReadValue is not null)); /// /// @@ -315,7 +323,7 @@ protected override async Task UpdateTextPropertyAsync(bool updateValue) { await base.UpdateTextPropertyAsync(updateValue); if (Clearable) - UpdateClearable(Text); + UpdateClearable(ReadText); } /// @@ -327,7 +335,7 @@ protected override async Task UpdateValuePropertyAsync(bool updateText) { await base.UpdateValuePropertyAsync(updateText); if (Clearable) - UpdateClearable(Value); + UpdateClearable(ReadValue); } /// @@ -337,7 +345,7 @@ protected override async Task UpdateValuePropertyAsync(bool updateText) /// protected virtual async Task ClearButtonClickHandlerAsync(MouseEventArgs e) { - await SetTextAsync(string.Empty, updateValue: true); + await SetTextAndUpdateValueAsync(string.Empty, updateValue: true); await ElementReference.FocusAsync(); await OnClearButtonClick.InvokeAsync(e); } @@ -354,18 +362,7 @@ public override async Task SetParametersAsync(ParameterView parameters) await base.SetParametersAsync(parameters); //if (!_isFocused || _forceTextUpdate) // _internalText = Text; - if (RuntimeLocation.IsServerSide && TextUpdateSuppression) - { - // Text update suppression, only in BSS (not in WASM). - // This is a fix for #1012 - if (!_isFocused || _forceTextUpdate) - _internalText = Text; - } - else - { - // in WASM (or in BSS with TextUpdateSuppression==false) we always update - _internalText = Text; - } + _internalText = ReadText; } /// @@ -380,12 +377,23 @@ public Task SetText(string? text) } - // Certain HTML5 inputs (dates and color) have a native placeholder - private bool HasNativeHtmlPlaceholder() + /// + /// + /// + /// + protected virtual bool HasNativeHtmlPlaceholder() { - return GetInputType() is InputType.Color or InputType.Date or InputType.DateTimeLocal or InputType.Month - or InputType.Time or InputType.Week; + return InputType switch + { + InputType.Color => true, + InputType.Date => true, + InputType.DateTimeLocal => true, + InputType.Month => true, + InputType.Time => true, + InputType.Week => true, + _ => false + }; } - } + } } diff --git a/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor b/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor index 5328c164..76c6f186 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor @@ -12,7 +12,7 @@ Class="@Classname" Error="@HasErrors" ErrorText="@GetErrorText()" - ErrorId="@ErrorId" + ErrorId="@ErrorIdState.Value" Disabled="@Disabled" Margin="@Margin" Required="@Required" @@ -27,7 +27,7 @@ Label="@Label" Style="@Style" Variant="@Variant" - Value="@Text" + Value="@ReadText" ValueChanged="(s) => SetTextAsync(s)" Placeholder="@Placeholder" Disabled=@Disabled @@ -36,8 +36,8 @@ MaxLength="@MaxLength" Adornment="@Adornment" AdornmentAriaLabel="@AdornmentAriaLabel" - Error="@Error" - ErrorId="@ErrorId" + Error="@ErrorState.Value" + ErrorId="@ErrorIdState.Value" Immediate="@Immediate" Margin="@Margin" OnBlur="@OnBlurredAsync" diff --git a/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor.cs index f14bd067..1daa6920 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/PasswordField/MudPasswordField.razor.cs @@ -52,7 +52,7 @@ public MudPasswordField() [Category(CategoryTypes.FormComponent.Behavior)] public InputType InputType { get; set; } = InputType.Text; - private string GetCounterText() => Counter == null ? string.Empty : (Counter == 0 ? (string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") : ((string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") + $" / {Counter}")); + private string GetCounterText() => Counter == null ? string.Empty : (Counter == 0 ? (string.IsNullOrEmpty(ReadText) ? "0" : $"{ReadText.Length}") : ((string.IsNullOrEmpty(ReadText) ? "0" : $"{ReadText.Length}") + $" / {Counter}")); /// /// Show clear button. diff --git a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor index 7f8fb9c7..8171eb47 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor @@ -5,16 +5,30 @@
- + @@ -43,7 +57,7 @@ } @if (ValuePresenter == ValuePresenter.Text) { - if (string.IsNullOrEmpty(Text)) + if (string.IsNullOrEmpty(ReadText)) { @Placeholder } @@ -97,7 +111,7 @@ } else { - @if (string.IsNullOrEmpty(Text)) + @if (string.IsNullOrEmpty(ReadText)) { @Placeholder } @@ -123,7 +137,7 @@ @if (ItemCollection != null || ChildContent != null) { - - ? SelectedValues SelectionChangedFromOutside?.Invoke(new HashSet(_selectedValues, _comparer)); if (!MultiSelection) { - SetValueAsync(_selectedValues.FirstOrDefault()).CatchAndLog(); + SetValueAndUpdateTextAsync(_selectedValues.FirstOrDefault()).CatchAndLog(); } else { - SetValueAsync(_selectedValues.LastOrDefault(), false).CatchAndLog(); + SetValueAndUpdateTextAsync(_selectedValues.LastOrDefault(), false).CatchAndLog(); UpdateTextPropertyAsync(false).CatchAndLog(); } @@ -644,7 +646,7 @@ protected async Task SetCustomizedTextAsync(string? text, bool updateValue = tru Func, string?>? multiSelectionTextFunc = null) { // The Text property of the control is updated - Text = multiSelectionTextFunc?.Invoke(selectedConvertedValues); + await SetTextAsync(multiSelectionTextFunc?.Invoke(selectedConvertedValues)); // The comparison is made on the multiSelectionText variable if (multiSelectionText != text) @@ -722,23 +724,23 @@ protected override Task UpdateTextPropertyAsync(bool updateValue) } else { - return SetTextAsync(string.Join(Delimiter, textList), updateValue: updateValue); + return SetTextAndUpdateValueAsync(string.Join(Delimiter, textList), updateValue: updateValue); } } else { - var item = Items?.FirstOrDefault(x => Value == null ? x.Value == null : Comparer != null ? Comparer.Equals(Value, x.Value) : Value.Equals(x.Value)); + var item = Items?.FirstOrDefault(x => ReadValue == null ? x.Value == null : Comparer != null ? Comparer.Equals(ReadValue, x.Value) : ReadValue.Equals(x.Value)); if (item == null) { - return SetTextAsync(base.ConvertSet(Value), false); + return SetTextAndUpdateValueAsync(base.ConvertSet(ReadValue), false); } - return SetTextAsync((!string.IsNullOrEmpty(item.Text) ? item.Text : base.ConvertSet(item.Value)), updateValue: updateValue); + return SetTextAndUpdateValueAsync((!string.IsNullOrEmpty(item.Text) ? item.Text : base.ConvertSet(item.Value)), updateValue: updateValue); } } private string? GetSelectTextPresenter() { - return Text; + return ReadText; } #endregion @@ -753,9 +755,9 @@ protected override void OnInitialized() { base.OnInitialized(); UpdateIcon(); - if (!MultiSelection && Value != null) + if (!MultiSelection && ReadValue != null) { - _selectedValues = new HashSet(_comparer) { Value }; + _selectedValues = new HashSet(_comparer) { ReadValue }; } else if (MultiSelection && SelectedValues != null) { @@ -809,7 +811,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) await UpdateTextPropertyAsync(false); _list?.ForceUpdateItems(); - SelectedListItem = Items.FirstOrDefault(x => x.Value != null && Value != null && x.Value.Equals(Value))?.ListItem; + SelectedListItem = Items.FirstOrDefault(x => x.Value != null && Value != null && x.Value.Equals(ReadValue))?.ListItem; StateHasChanged(); } //Console.WriteLine("Select rendered"); @@ -911,7 +913,7 @@ protected internal async Task HandleKeyDownAsync(KeyboardEventArgs obj) } else { - await _elementReference.SetText(Text); + await _elementReference.SetText(ReadText); break; } } @@ -1084,7 +1086,7 @@ public async Task SelectOption(object? obj) // CloseMenu(true) doesn't close popover in BSS await CloseMenu(); - if (EqualityComparer.Default.Equals(Value, value)) + if (EqualityComparer.Default.Equals(ReadValue, value)) { StateHasChanged(); return; @@ -1092,7 +1094,7 @@ public async Task SelectOption(object? obj) await SetValueAsync(value); //await UpdateTextPropertyAsync(false); - _elementReference.SetText(Text).CatchAndLog(); + _elementReference.SetText(ReadText).CatchAndLog(); //_selectedValues.Clear(); //_selectedValues.Add(value); } @@ -1111,7 +1113,7 @@ public override async Task ForceUpdate() await base.ForceUpdate(); if (!MultiSelection) { - SelectedValues = new HashSet(_comparer) { Value }; + SelectedValues = new HashSet(_comparer) { ReadValue }; } else { @@ -1145,14 +1147,14 @@ protected internal bool Add(MudSelectItemExtended? item) if (item.Value != null) { _valueLookup[item.Value] = item; - if (item.Value.Equals(Value) && !MultiSelection) + if (item.Value.Equals(ReadValue) && !MultiSelection) result = true; } } //UpdateSelectAllChecked(); if (!result.HasValue) { - result = item.Value?.Equals(Value); + result = item.Value?.Equals(ReadValue); } return result == true; } @@ -1204,8 +1206,8 @@ public void UnregisterShadowItem(MudSelectItemExtended? item) ///
protected async ValueTask SelectClearButtonClickHandlerAsync(MouseEventArgs e) { - await SetValueAsync(default, false); - await SetTextAsync(default, false); + await SetValueAndUpdateTextAsync(default, false); + await SetTextAndUpdateValueAsync(default, false); _selectedValues?.Clear(); SelectedListItem = null; SelectedListItems = null; @@ -1220,8 +1222,8 @@ protected async ValueTask SelectClearButtonClickHandlerAsync(MouseEventArgs e) ///
public async Task Clear() { - await SetValueAsync(default, false); - await SetTextAsync(default, false); + await SetValueAndUpdateTextAsync(default, false); + await SetTextAndUpdateValueAsync(default, false); _selectedValues?.Clear(); await BeginValidateAsync(); StateHasChanged(); @@ -1247,12 +1249,12 @@ protected bool IsValueInList { get { - if (Value == null) + if (ReadValue == null) return false; //return _shadowLookup.TryGetValue(Value, out var _); foreach (var value in Items?.Select(x => x.Value) ?? new List()) { - if (Comparer != null ? Comparer.Equals(value, Value) : value?.Equals(Value) == true) //(Converter.Set(item.Value) == Converter.Set(Value)) + if (Comparer != null ? Comparer.Equals(value, ReadValue) : value?.Equals(ReadValue) == true) //(Converter.Set(item.Value) == Converter.Set(Value)) { return true; } diff --git a/CodeBeam.MudBlazor.Extensions/Components/StepperExtended/MudStepperExtended.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/StepperExtended/MudStepperExtended.razor.cs index ce9454dc..44fb064e 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/StepperExtended/MudStepperExtended.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/StepperExtended/MudStepperExtended.razor.cs @@ -743,12 +743,25 @@ public async Task GoPreviousStepAsync(bool skipPrevent = false) #region The Obsoletes + /// + /// + /// + /// + /// + /// [Obsolete("Use GoToStepByReferenceAsync() instead.")] protected internal async Task SetActiveIndex(MudStepExtended step, bool skipPreventProcess = false) { await SetActiveStepByIndex(Steps.IndexOf(step), skipPreventProcess: skipPreventProcess); } + /// + /// + /// + /// + /// + /// + /// [Obsolete("Use GoNextAsync/GoPreviousAsync or GoToStepAsync instead.")] public async Task SetActiveIndex(int count, bool firstCompleted = false, bool skipPreventProcess = false) { @@ -817,6 +830,13 @@ public async Task SetActiveIndex(int count, bool firstCompleted = false, bool sk } } + /// + /// + /// + /// + /// + /// + /// [Obsolete("Use GoNextAsync/GoPreviousAsync or GoToStepAsync instead.")] public async Task SetActiveStepByIndex(int index, bool firstCompleted = false, bool skipPreventProcess = false) { diff --git a/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor b/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor index fba2a5c5..c8f239b4 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor @@ -12,7 +12,7 @@ Class="@Classname" Error="@HasErrors" ErrorText="@GetErrorText()" - ErrorId="@ErrorId" + ErrorId="@ErrorIdState.Value" Disabled="@Disabled" Margin="@Margin" Required="@Required" @@ -31,8 +31,7 @@ Style="@Style" Variant="@Variant" HasAdornmentStart="@((AdornmentStart != null))" - TextUpdateSuppression="@TextUpdateSuppression" - Value="@Text" + Value="@ReadText" ValueChanged="(s) => SetTextAsync(s)" Placeholder="@Placeholder" Disabled="@GetDisabledState()" @@ -40,8 +39,8 @@ ReadOnly="@GetReadOnlyState()" MaxLength="@MaxLength" IconSize="@IconSize" - Error="@Error" - ErrorId="@ErrorId" + Error="@ErrorState.Value" + ErrorId="@ErrorIdState.Value" Immediate="@Immediate" Margin="@Margin" OnInput="@OnInput" @@ -87,8 +86,7 @@ Style="@Style" Variant="@Variant" Typo="Typo" - TextUpdateSuppression="@TextUpdateSuppression" - Value="@Text" + Value="@ReadText" ValueChanged="OnMaskedValueChanged" Placeholder="@Placeholder" Disabled=@GetDisabledState() @@ -102,8 +100,8 @@ AdornmentAriaLabel="@AdornmentAriaLabel" IconSize="@IconSize" OnAdornmentClick="@OnAdornmentClick" - Error="@Error" - ErrorId="@ErrorId" + Error="@ErrorState.Value" + ErrorId="@ErrorIdState.Value" HelperText="@HelperText" Immediate="@Immediate" Margin="@Margin" OnBlur="@OnBlurredAsync" diff --git a/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor.cs index ffc058da..f150a851 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor.cs @@ -61,9 +61,7 @@ public async Task ForceAutoSize() [Category(CategoryTypes.FormComponent.Behavior)] public InputType InputType { get; set; } = InputType.Text; - internal override InputType GetInputType() => InputType; - - private string GetCounterText() => Counter == null ? string.Empty : (Counter == 0 ? (string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") : ((string.IsNullOrEmpty(Text) ? "0" : $"{Text.Length}") + $" / {Counter}")); + private string GetCounterText() => Counter == null ? string.Empty : (Counter == 0 ? (string.IsNullOrEmpty(ReadText) ? "0" : $"{ReadText.Length}") : ((string.IsNullOrEmpty(ReadText) ? "0" : $"{ReadText.Length}") + $" / {Counter}")); /// /// Show clear button. @@ -193,40 +191,40 @@ public IMask? Mask } } - /// - /// - /// - /// - /// - /// - /// - protected override Task SetValueAsync(T? value, bool updateText = true, bool force = false) - { - if (_mask != null) - { - var textValue = Converter.Convert(value); - _mask.SetText(textValue); - textValue = Mask?.GetCleanText(); - value = Converter.ConvertBack(textValue); - } - return base.SetValueAsync(value, updateText, force); - } - - /// - /// - /// - /// - /// - /// - protected override Task SetTextAsync(string? text, bool updateValue = true) - { - if (_mask != null) - { - _mask.SetText(text); - text = _mask.Text; - } - return base.SetTextAsync(text, updateValue); - } + ///// + ///// + ///// + ///// + ///// + ///// + ///// + //protected override Task SetValueAsync(T? value, bool updateText = true, bool force = false) + //{ + // if (_mask != null) + // { + // var textValue = Converter.Convert(value); + // _mask.SetText(textValue); + // textValue = Mask?.GetCleanText(); + // value = Converter.ConvertBack(textValue); + // } + // return base.SetValueAsync(value, updateText, force); + //} + + ///// + ///// + ///// + ///// + ///// + ///// + //protected override Task SetTextAsync(string? text, bool updateValue = true) + //{ + // if (_mask != null) + // { + // _mask.SetText(text); + // text = _mask.Text; + // } + // return base.SetTextAsync(text, updateValue); + //} private async Task OnMaskedValueChanged(string s) { diff --git a/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor.cs index 64260c1f..4fcfe288 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/Wheel/MudWheel.razor.cs @@ -15,7 +15,7 @@ public partial class MudWheel : MudBaseInput /// /// /// - [Inject] public IScrollManager ScrollManager { get; set; } + [Inject] public IScrollManager ScrollManager { get; set; } = null!; /// /// @@ -45,7 +45,7 @@ public partial class MudWheel : MudBaseInput /// /// protected string? OuterItemClassname(int index) => new CssBuilder($"mud-wheel-item mud-wheel-ani-{_animateGuid}") - .AddClass("wheel-item-closest", Math.Abs(ItemCollection.IndexOf(Value) - index) == 1) + .AddClass("wheel-item-closest", Math.Abs(ItemCollection.IndexOf(ReadValue) - index) == 1) .AddClass("my-1", !Dense) .AddClass("mud-disabled", Disabled) .Build(); @@ -257,6 +257,7 @@ public async Task ChangeWheel(int changeCount) _animateValue = - GetAnimateValue(); } await _animate.Refresh(); + T val = ItemCollection[index + changeCount]; await SetValueAsync(val); } @@ -274,7 +275,7 @@ public async Task RefreshAnimate() /// /// /// - protected int GetIndex() => ItemCollection.IndexOf(Value) == -1 ? 0 : ItemCollection.IndexOf(Value); + protected int GetIndex() => ItemCollection?.IndexOf(ReadValue) == -1 ? 0 : ItemCollection?.IndexOf(ReadValue) ?? 0; /// /// From b17b265f695cecb7e82dbaf69127f66a9ad821c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Tue, 23 Dec 2025 22:18:35 +0300 Subject: [PATCH 3/9] Change Scss and Js Compilers & Remove All Dependencies Except MudBlazor --- .../wwwroot/CodeBeam.MudBlazor.Extensions.xml | 31 + ...eam.MudBlazor.Extensions.JsMinifier.csproj | 13 + .../Program.cs | 38 + .../CodeBeam.MudBlazor.Extensions.csproj | 53 +- .../bundleconfig.json | 8 - .../compilerconfig.json | 6 - .../excubowebcompiler.json | 56 - CodeBeam.MudBlazor.Extensions/package.json | 6 + .../sasscompiler.json | 5 + .../wwwroot/MudExtensions.min.css | 2032 ++++++++++++++++- .../wwwroot/MudExtensions.min.js | 2 +- .../wwwroot/css/MudExtensions.css | 1856 +++++++++++++++ .../wwwroot/css/MudExtensions.css.map | 1 + .../wwwroot/css/MudExtensions.min.css | 2031 ++++++++++++++++ .../wwwroot/css/MudExtensions.min.css.map | 1 + CodeBeamMudExtensions.sln | 11 +- 16 files changed, 6040 insertions(+), 110 deletions(-) create mode 100644 CodeBeam.MudBlazor.Extensions.JsMinifier/CodeBeam.MudBlazor.Extensions.JsMinifier.csproj create mode 100644 CodeBeam.MudBlazor.Extensions.JsMinifier/Program.cs delete mode 100644 CodeBeam.MudBlazor.Extensions/bundleconfig.json delete mode 100644 CodeBeam.MudBlazor.Extensions/compilerconfig.json delete mode 100644 CodeBeam.MudBlazor.Extensions/excubowebcompiler.json create mode 100644 CodeBeam.MudBlazor.Extensions/package.json create mode 100644 CodeBeam.MudBlazor.Extensions/sasscompiler.json create mode 100644 CodeBeam.MudBlazor.Extensions/wwwroot/css/MudExtensions.css create mode 100644 CodeBeam.MudBlazor.Extensions/wwwroot/css/MudExtensions.css.map create mode 100644 CodeBeam.MudBlazor.Extensions/wwwroot/css/MudExtensions.min.css create mode 100644 CodeBeam.MudBlazor.Extensions/wwwroot/css/MudExtensions.min.css.map diff --git a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml index c6176472..f66c7e74 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml +++ b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml @@ -1250,6 +1250,11 @@ + + + + + @@ -5148,6 +5153,32 @@ to the previous step. A task that represents the asynchronous navigation operation. + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CodeBeam.MudBlazor.Extensions.JsMinifier/CodeBeam.MudBlazor.Extensions.JsMinifier.csproj b/CodeBeam.MudBlazor.Extensions.JsMinifier/CodeBeam.MudBlazor.Extensions.JsMinifier.csproj new file mode 100644 index 00000000..20863ce1 --- /dev/null +++ b/CodeBeam.MudBlazor.Extensions.JsMinifier/CodeBeam.MudBlazor.Extensions.JsMinifier.csproj @@ -0,0 +1,13 @@ + + + + net9.0 + Exe + enable + + + + + + + diff --git a/CodeBeam.MudBlazor.Extensions.JsMinifier/Program.cs b/CodeBeam.MudBlazor.Extensions.JsMinifier/Program.cs new file mode 100644 index 00000000..cf3a0286 --- /dev/null +++ b/CodeBeam.MudBlazor.Extensions.JsMinifier/Program.cs @@ -0,0 +1,38 @@ +using NUglify; +using System.Text; + +Console.WriteLine("Minifying MudExtensions.js..."); + +// Solution root +var solutionRoot = Directory.GetCurrentDirectory(); + +// Ana proje klasörü +var projectRoot = Path.Combine(solutionRoot, "CodeBeam.MudBlazor.Extensions"); + +var input = Path.Combine(projectRoot, "TScripts", "MudExtensions.js"); +var output = Path.Combine(projectRoot, "wwwroot", "MudExtensions.min.js"); + +Console.WriteLine($"IN : {input}"); +Console.WriteLine($"OUT: {output}"); + +if (!File.Exists(input)) +{ + Console.Error.WriteLine($"Input file not found: {input}"); + Environment.Exit(1); +} + +var js = File.ReadAllText(input, Encoding.UTF8); +var result = Uglify.Js(js); + +if (result.HasErrors) +{ + foreach (var error in result.Errors) + Console.Error.WriteLine(error.ToString()); + + Environment.Exit(1); +} + +Directory.CreateDirectory(Path.GetDirectoryName(output)!); +File.WriteAllText(output, result.Code!, Encoding.UTF8); + +Console.WriteLine("✔ MudExtensions.min.js generated successfully"); diff --git a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj index e3debb8e..dcb7bd12 100644 --- a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj +++ b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj @@ -5,14 +5,17 @@ enable enable MIT + README.md 9.0.0-preview.1 CodeBeam.MudBlazor.Extensions + CodeBeam.MudBlazor.Extensions CodeBeam CodeBeam MudBlazor extension components from contributors. Includes 30+ components and utilities. CodeBeam OpenSource MIT Mud_Secondary.png https://mudextensions.codebeam.org/ + git https://github.com/CodeBeamOrg/CodeBeam.MudBlazor.Extensions Blazor; MudBlazor; Component; Extension; Material3; Animate; Stepper; ComboBox; Select; List; Loading; Gallery; ChipField; Transfer; Barcode; QR; SpeedDial; RangeSlider; Teleport MudExtensions @@ -23,57 +26,34 @@ link true True + false - - - - + + all + - - - - - - - - - - - - - - - - - + + + - + + + + - - - + + - - <_ContentIncludedByDefault Remove="bundleconfig.json" /> - - <_Parameter1>CodeBeam.MudBlazor.Extensions.UnitTests @@ -81,7 +61,6 @@ - True \ diff --git a/CodeBeam.MudBlazor.Extensions/bundleconfig.json b/CodeBeam.MudBlazor.Extensions/bundleconfig.json deleted file mode 100644 index ce6e84fc..00000000 --- a/CodeBeam.MudBlazor.Extensions/bundleconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "outputFileName": "wwwroot/MudExtensions.min.js", - "inputFiles": [ - "TScripts/MudExtensions.js" - ] - } -] diff --git a/CodeBeam.MudBlazor.Extensions/compilerconfig.json b/CodeBeam.MudBlazor.Extensions/compilerconfig.json deleted file mode 100644 index 6333ac88..00000000 --- a/CodeBeam.MudBlazor.Extensions/compilerconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "outputFile": "wwwroot/MudExtensions.css", - "inputFile": "Styles/MudExtensions.scss" - } -] \ No newline at end of file diff --git a/CodeBeam.MudBlazor.Extensions/excubowebcompiler.json b/CodeBeam.MudBlazor.Extensions/excubowebcompiler.json deleted file mode 100644 index a4814956..00000000 --- a/CodeBeam.MudBlazor.Extensions/excubowebcompiler.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "Minifiers": { - "GZip": false, - "Enabled": true, - "Css": { - "CommentMode": "Important", - "ColorNames": "Hex", - "TermSemicolons": true, - "OutputMode": "SingleLine", - "IndentSize": 2 - }, - "Javascript": { - "RenameLocals": false, - "PreserveImportantComments": true, - "EvalTreatment": "Ignore", - "TermSemicolons": true, - "OutputMode": "SingleLine", - "IndentSize": 2 - } - }, - "Autoprefix": { - "Enabled": false, - "ProcessingOptions": { - "Browsers": [ - "last 4 versions" - ], - "Cascade": true, - "Add": true, - "Remove": true, - "Supports": true, - "Flexbox": "All", - "Grid": "None", - "IgnoreUnknownVersions": false, - "Stats": "", - "SourceMap": true, - "InlineSourceMap": false, - "SourceMapIncludeContents": false, - "OmitSourceMapUrl": false - } - }, - "CompilerSettings": { - "Sass": { - "IndentType": "Space", - "IndentWidth": 2, - "OutputStyle": "Nested", - "Precision": 5, - "RelativeUrls": true, - "LineFeed": "Lf", - "SourceMap": false - } - }, - "Output": { - "Preserve": true, - "Directory": "./wwwroot" - } -} diff --git a/CodeBeam.MudBlazor.Extensions/package.json b/CodeBeam.MudBlazor.Extensions/package.json new file mode 100644 index 00000000..eb140093 --- /dev/null +++ b/CodeBeam.MudBlazor.Extensions/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "devDependencies": { + "esbuild": "^0.21.5" + } +} diff --git a/CodeBeam.MudBlazor.Extensions/sasscompiler.json b/CodeBeam.MudBlazor.Extensions/sasscompiler.json new file mode 100644 index 00000000..0e362bb3 --- /dev/null +++ b/CodeBeam.MudBlazor.Extensions/sasscompiler.json @@ -0,0 +1,5 @@ +{ + "Source": "Styles", + "Output": "wwwroot", + "Minify": true +} diff --git a/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.css b/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.css index 3369be87..95c17716 100644 --- a/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.css +++ b/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.css @@ -1 +1,2031 @@ -.mud-combobox{margin:0;padding:0;position:relative;list-style:none;}.mud-combobox.mud-combobox-padding{padding-top:8px;padding-bottom:8px;}.mud-combobox-item{width:100%;display:flex;position:relative;box-sizing:border-box;text-align:start;align-items:center;padding-top:8px;padding-bottom:8px;justify-content:flex-start;text-decoration:none;outline:none;min-height:48px;}.mud-combobox-item.mud-combobox-item-comfort{padding-top:4px;padding-bottom:4px;min-height:40px;}.mud-combobox-item.mud-combobox-item-slim{padding-top:2px;padding-bottom:2px;min-height:32px;}.mud-combobox-item.mud-combobox-item-superslim{padding-top:0;padding-bottom:0;min-height:24px;}.mud-combobox-item.mud-combobox-item-disabled{color:var(--mud-palette-action-disabled) !important;cursor:default !important;pointer-events:none !important;}.mud-combobox-item.mud-combobox-item-disabled .mud-combobox-item-icon{color:var(--mud-palette-action-disabled) !important;}.mud-combobox-item-clickable{color:inherit;border:0;cursor:pointer;margin:0;outline:0;user-select:none;border-radius:0;vertical-align:middle;background-color:transparent;-webkit-appearance:none;-webkit-tap-highlight-color:transparent;transition:background-color 150ms cubic-bezier(.4,0,.2,1) 0ms;}.mud-combobox-item-clickable:hover{background-color:var(--mud-palette-action-default-hover);}.mud-combobox-item-gutters{padding-left:16px;padding-right:16px;}.mud-combobox-item-text{flex:1 1 auto;min-width:0;margin-top:4px;margin-bottom:4px;padding-inline-start:8px;padding-inline-end:8px;}.mud-combobox-item-text-inset{padding-left:56px;padding-inline-start:56px;padding-inline-end:unset;}.mud-combobox-item-icon{color:var(--mud-palette-action-default);display:inline-flex;flex-shrink:0;padding-inline-start:8px;padding-inline-end:8px;margin-inline-start:-4px;margin-inline-end:4px;}.mud-combobox-item-multiselect{max-height:32px;}.mud-combobox-item-multiselect.mud-combobox-item-multiselect-checkbox{padding-inline-end:16px;}.mud-combobox-subheader{color:var(--mud-palette-action-default);background-color:var(--mud-palette-background);font-size:.875rem;box-sizing:border-box;list-style:none;font-weight:500;padding-top:16px;padding-bottom:16px;}.mud-combobox-subheader-secondary-background{background-color:var(--mud-palette-background-gray);}.mud-combobox-subheader-gutters{padding-left:16px;padding-right:16px;}.mud-combobox-subheader-inset{padding-left:72px;padding-inline-start:72px;padding-inline-end:unset;}.mud-combobox-subheader-sticky{top:-8px;z-index:1;position:sticky;}.mud-combobox-subheader-sticky.mud-combobox-subheader-sticky-dense{top:0;}.mud-combobox-item-hilight{background-color:var(--mud-palette-background-gray);}.mud-combobox-item-hilight{background-color:var(--mud-palette-lines-default) !important;}.mud-combobox-item-bordered{border-left:4px solid var(--mud-palette-lines-default);padding-inline-start:12px;}.mud-combobox-item-bordered-primary{border-left:4px solid var(--mud-palette-primary);padding-inline-start:12px;}.mud-combobox-item-bordered-secondary{border-left:4px solid var(--mud-palette-secondary);padding-inline-start:12px;}.mud-combobox-item-bordered-tertiary{border-left:4px solid var(--mud-palette-tertiary);padding-inline-start:12px;}.mud-combobox-item-bordered-info{border-left:4px solid var(--mud-palette-info);padding-inline-start:12px;}.mud-combobox-item-bordered-success{border-left:4px solid var(--mud-palette-success);padding-inline-start:12px;}.mud-combobox-item-bordered-warning{border-left:4px solid var(--mud-palette-warning);padding-inline-start:12px;}.mud-combobox-item-bordered-error{border-left:4px solid var(--mud-palette-error);padding-inline-start:12px;}.mud-combobox-item-bordered-dark{border-left:4px solid var(--mud-palette-dark);padding-inline-start:12px;}.mud-combobox-item-nested-background{background-color:var(--mud-palette-background-gray);}.mud-combobox-item-avatar{min-width:56px;flex-shrink:0;}.mud-combobox-highlighter{background-color:transparent;font-weight:bold;text-decoration:underline;}.mud-gallery-selected-toolbox{left:0;right:0;height:56px;width:100%;background-color:rgba(0,0,0,.6);}.mud-gallery-selected-toolbox.gallery-toolbox-top{top:0;}.mud-gallery-selected-toolbox.gallery-toolbox-bottom{bottom:0;}.mud-page{display:grid;box-sizing:border-box;width:100%;}.mud-page.mud-page-height-full{min-height:100vh;}.mud-page.mud-page-height-full-without-appbar{min-height:calc(100vh - var(--mud-appbar-height));}.mud-page.mud-page-column-2{grid-template-columns:repeat(2,50%);}.mud-page.mud-page-column-3{grid-template-columns:repeat(3,33.33333%);}.mud-page.mud-page-column-4{grid-template-columns:repeat(4,25%);}.mud-page.mud-page-column-5{grid-template-columns:repeat(5,20%);}.mud-page.mud-page-column-6{grid-template-columns:repeat(6,16.66667%);}.mud-page.mud-page-column-7{grid-template-columns:repeat(7,14.28571%);}.mud-page.mud-page-column-8{grid-template-columns:repeat(8,12.5%);}.mud-page.mud-page-column-9{grid-template-columns:repeat(9,11.11111%);}.mud-page.mud-page-column-10{grid-template-columns:repeat(10,10%);}.mud-page.mud-page-column-11{grid-template-columns:repeat(11,9.09091%);}.mud-page.mud-page-column-12{grid-template-columns:repeat(12,8.33333%);}.mud-page.mud-page-row-2{grid-template-rows:repeat(2,50%);}.mud-page.mud-page-row-3{grid-template-rows:repeat(3,33.33333%);}.mud-page.mud-page-row-4{grid-template-rows:repeat(4,25%);}.mud-page.mud-page-row-5{grid-template-rows:repeat(5,20%);}.mud-page.mud-page-row-6{grid-template-rows:repeat(6,16.66667%);}.mud-page.mud-page-row-7{grid-template-rows:repeat(7,14.28571%);}.mud-page.mud-page-row-8{grid-template-rows:repeat(8,12.5%);}.mud-page.mud-page-row-9{grid-template-rows:repeat(9,11.11111%);}.mud-page.mud-page-row-10{grid-template-rows:repeat(10,10%);}.mud-page.mud-page-row-11{grid-template-rows:repeat(11,9.09091%);}.mud-page.mud-page-row-12{grid-template-rows:repeat(12,8.33333%);}.mud-section{display:inline-grid;overflow:auto;}.mud-section.mud-section-col-start-1{grid-column-start:1;}.mud-section.mud-section-col-start-2{grid-column-start:2;}.mud-section.mud-section-col-start-3{grid-column-start:3;}.mud-section.mud-section-col-start-4{grid-column-start:4;}.mud-section.mud-section-col-start-5{grid-column-start:5;}.mud-section.mud-section-col-start-6{grid-column-start:6;}.mud-section.mud-section-col-start-7{grid-column-start:7;}.mud-section.mud-section-col-start-8{grid-column-start:8;}.mud-section.mud-section-col-start-9{grid-column-start:9;}.mud-section.mud-section-col-start-10{grid-column-start:10;}.mud-section.mud-section-col-start-11{grid-column-start:11;}.mud-section.mud-section-col-start-12{grid-column-start:12;}.mud-section.mud-section-col-end-1{grid-column-end:1;}.mud-section.mud-section-col-end-2{grid-column-end:2;}.mud-section.mud-section-col-end-3{grid-column-end:3;}.mud-section.mud-section-col-end-4{grid-column-end:4;}.mud-section.mud-section-col-end-5{grid-column-end:5;}.mud-section.mud-section-col-end-6{grid-column-end:6;}.mud-section.mud-section-col-end-7{grid-column-end:7;}.mud-section.mud-section-col-end-8{grid-column-end:8;}.mud-section.mud-section-col-end-9{grid-column-end:9;}.mud-section.mud-section-col-end-10{grid-column-end:10;}.mud-section.mud-section-col-end-11{grid-column-end:11;}.mud-section.mud-section-col-end-12{grid-column-end:12;}.mud-section.mud-section-col-end-13{grid-column-end:13;}.mud-section.mud-section-row-start-1{grid-row-start:1;}.mud-section.mud-section-row-start-2{grid-row-start:2;}.mud-section.mud-section-row-start-3{grid-row-start:3;}.mud-section.mud-section-row-start-4{grid-row-start:4;}.mud-section.mud-section-row-start-5{grid-row-start:5;}.mud-section.mud-section-row-start-6{grid-row-start:6;}.mud-section.mud-section-row-start-7{grid-row-start:7;}.mud-section.mud-section-row-start-8{grid-row-start:8;}.mud-section.mud-section-row-start-9{grid-row-start:9;}.mud-section.mud-section-row-start-10{grid-row-start:10;}.mud-section.mud-section-row-start-11{grid-row-start:11;}.mud-section.mud-section-row-start-12{grid-row-start:12;}.mud-section.mud-section-row-end-1{grid-row-end:1;}.mud-section.mud-section-row-end-2{grid-row-end:2;}.mud-section.mud-section-row-end-3{grid-row-end:3;}.mud-section.mud-section-row-end-4{grid-row-end:4;}.mud-section.mud-section-row-end-5{grid-row-end:5;}.mud-section.mud-section-row-end-6{grid-row-end:6;}.mud-section.mud-section-row-end-7{grid-row-end:7;}.mud-section.mud-section-row-end-8{grid-row-end:8;}.mud-section.mud-section-row-end-9{grid-row-end:9;}.mud-section.mud-section-row-end-10{grid-row-end:10;}.mud-section.mud-section-row-end-11{grid-row-end:11;}.mud-section.mud-section-row-end-12{grid-row-end:12;}.mud-section.mud-section-row-end-13{grid-row-end:13;}.mud-popup{z-index:2000;overflow:auto;background-color:var(--mud-palette-background);min-height:var(--mud-appbar-height);}.mud-popup.mud-popup-center{height:300px;left:50%;top:50%;transform:translate(-50%,-50%);width:320px;aspect-ratio:1/1;}.mud-range-container{align-items:center;margin:20px 0;}.mud-range-container input::-webkit-slider-thumb{pointer-events:all;position:relative;z-index:1;}.mud-range-container input::-moz-range-thumb{pointer-events:all;position:relative;z-index:10;}.mud-range-container input::-moz-range-track{position:relative;z-index:-1;}.mud-range-container input:last-of-type::-moz-range-track{-moz-appearance:none;}.mud-range-container .mud-slider-input:last-of-type{position:absolute;pointer-events:none;top:0;}.mud-range-container input[type=range]::-webkit-slider-thumb{pointer-events:all;}.mud-range-display{text-align:center;}.mud-signature-pad-container{touch-action:none;}.mud-splitter{display:grid;position:relative;width:100%;}.mud-splitter-content{overflow:auto;}.mud-splitter-thumb ::-webkit-slider-runnable-track{visibility:hidden !important;height:100% !important;}.mud-splitter-thumb ::-moz-range-track{visibility:hidden !important;height:100% !important;}.mud-splitter-track{position:absolute;top:50%;transform:translateY(-50%);height:100%;}.mud-splitter-track.mud-slider{visibility:hidden !important;}.mud-splitter-track.mud-slider .mud-slider-container{height:100% !important;}.mud-splitter-track.mud-slider .mud-slider-input{top:50%;}.mud-splitter-thumb ::-webkit-slider-thumb{visibility:visible !important;appearance:none !important;-webkit-appearance:none !important;top:50% !important;transform:translateY(-50%) !important;height:100% !important;width:8px !important;border:none !important;border-radius:0 !important;cursor:ew-resize !important;}.mud-splitter-thumb-disabled ::-webkit-slider-thumb{cursor:default !important;}.mud-splitter-thumb ::-moz-range-thumb{visibility:visible !important;appearance:none !important;-moz-appearance:none !important;top:50% !important;transform:translateY(-50%) !important;height:100% !important;width:8px !important;border:none !important;border-radius:0 !important;cursor:ew-resize !important;}.mud-splitter-thumb-disabled ::-moz-range-thumb{cursor:default !important;}.mud-stepper-header-extended{min-height:62px;border-radius:var(--mud-default-borderradius);}.mud-stepper-header-extended.mud-stepper-header-non-linear-extended:hover{background-color:var(--mud-palette-action-default-hover);}.mud-stepper-badge-extended{z-index:21;}.mud-stepper-avatar-extended{z-index:20;}.mud-stepper-avatar-bg-extended{background-color:var(--mud-palette-background);}.mud-stepper-sub-inner-header-extended{grid-column-start:1;grid-column-end:-1;flex-direction:row;grid-row:1;list-style:none;display:flex;}.mud-stepper-sub-inner-header-vertical-extended{grid-row-start:1;grid-row-end:-1;flex-direction:column;grid-column:1;list-style:none;display:flex;}.mud-stepper-text-mobile-extended{grid-row:1;margin-top:22px;}.mud-stepper-text-mobile-vertical-extended{grid-column:1;margin-inline-start:22px;}.mud-stepper-step-1.horizontal{width:calc(100%/1);}.mud-stepper-step-1.vertical{height:calc(100%/1);}.mud-stepper-step-2.horizontal{width:calc(100%/2);}.mud-stepper-step-2.vertical{height:calc(100%/2);}.mud-stepper-step-3.horizontal{width:calc(100%/3);}.mud-stepper-step-3.vertical{height:calc(100%/3);}.mud-stepper-step-4.horizontal{width:calc(100%/4);}.mud-stepper-step-4.vertical{height:calc(100%/4);}.mud-stepper-step-5.horizontal{width:calc(100%/5);}.mud-stepper-step-5.vertical{height:calc(100%/5);}.mud-stepper-step-6.horizontal{width:calc(100%/6);}.mud-stepper-step-6.vertical{height:calc(100%/6);}.mud-stepper-step-7.horizontal{width:calc(100%/7);}.mud-stepper-step-7.vertical{height:calc(100%/7);}.mud-stepper-step-8.horizontal{width:calc(100%/8);}.mud-stepper-step-8.vertical{height:calc(100%/8);}.mud-stepper-step-9.horizontal{width:calc(100%/9);}.mud-stepper-step-9.vertical{height:calc(100%/9);}.mud-stepper-step-10.horizontal{width:calc(100%/10);}.mud-stepper-step-10.vertical{height:calc(100%/10);}.mud-stepper-step-11.horizontal{width:calc(100%/11);}.mud-stepper-step-11.vertical{height:calc(100%/11);}.mud-stepper-step-12.horizontal{width:calc(100%/12);}.mud-stepper-step-12.vertical{height:calc(100%/12);}.mud-stepper-grid-1.horizontal{display:grid;grid-template-columns:repeat(2,1fr);}.mud-stepper-grid-1.vertical{display:grid;grid-template-rows:repeat(2,1fr);}.mud-stepper-grid-2.horizontal{display:grid;grid-template-columns:repeat(4,1fr);}.mud-stepper-grid-2.vertical{display:grid;grid-template-rows:repeat(4,1fr);}.mud-stepper-grid-3.horizontal{display:grid;grid-template-columns:repeat(6,1fr);}.mud-stepper-grid-3.vertical{display:grid;grid-template-rows:repeat(6,1fr);}.mud-stepper-grid-4.horizontal{display:grid;grid-template-columns:repeat(8,1fr);}.mud-stepper-grid-4.vertical{display:grid;grid-template-rows:repeat(8,1fr);}.mud-stepper-grid-5.horizontal{display:grid;grid-template-columns:repeat(10,1fr);}.mud-stepper-grid-5.vertical{display:grid;grid-template-rows:repeat(10,1fr);}.mud-stepper-grid-6.horizontal{display:grid;grid-template-columns:repeat(12,1fr);}.mud-stepper-grid-6.vertical{display:grid;grid-template-rows:repeat(12,1fr);}.mud-stepper-grid-7.horizontal{display:grid;grid-template-columns:repeat(14,1fr);}.mud-stepper-grid-7.vertical{display:grid;grid-template-rows:repeat(14,1fr);}.mud-stepper-grid-8.horizontal{display:grid;grid-template-columns:repeat(16,1fr);}.mud-stepper-grid-8.vertical{display:grid;grid-template-rows:repeat(16,1fr);}.mud-stepper-grid-9.horizontal{display:grid;grid-template-columns:repeat(18,1fr);}.mud-stepper-grid-9.vertical{display:grid;grid-template-rows:repeat(18,1fr);}.mud-stepper-grid-10.horizontal{display:grid;grid-template-columns:repeat(20,1fr);}.mud-stepper-grid-10.vertical{display:grid;grid-template-rows:repeat(20,1fr);}.mud-stepper-grid-11.horizontal{display:grid;grid-template-columns:repeat(22,1fr);}.mud-stepper-grid-11.vertical{display:grid;grid-template-rows:repeat(22,1fr);}.mud-stepper-grid-12.horizontal{display:grid;grid-template-columns:repeat(24,1fr);}.mud-stepper-grid-12.vertical{display:grid;grid-template-rows:repeat(24,1fr);}.mud-stepper-grid-13.horizontal{display:grid;grid-template-columns:repeat(26,1fr);}.mud-stepper-grid-13.vertical{display:grid;grid-template-rows:repeat(26,1fr);}.mud-stepper-grid-14.horizontal{display:grid;grid-template-columns:repeat(28,1fr);}.mud-stepper-grid-14.vertical{display:grid;grid-template-rows:repeat(28,1fr);}.mud-stepper-grid-15.horizontal{display:grid;grid-template-columns:repeat(30,1fr);}.mud-stepper-grid-15.vertical{display:grid;grid-template-rows:repeat(30,1fr);}.mud-stepper-grid-16.horizontal{display:grid;grid-template-columns:repeat(32,1fr);}.mud-stepper-grid-16.vertical{display:grid;grid-template-rows:repeat(32,1fr);}.mud-stepper-grid-17.horizontal{display:grid;grid-template-columns:repeat(34,1fr);}.mud-stepper-grid-17.vertical{display:grid;grid-template-rows:repeat(34,1fr);}.mud-stepper-grid-18.horizontal{display:grid;grid-template-columns:repeat(36,1fr);}.mud-stepper-grid-18.vertical{display:grid;grid-template-rows:repeat(36,1fr);}.mud-stepper-grid-19.horizontal{display:grid;grid-template-columns:repeat(38,1fr);}.mud-stepper-grid-19.vertical{display:grid;grid-template-rows:repeat(38,1fr);}.mud-stepper-grid-20.horizontal{display:grid;grid-template-columns:repeat(40,1fr);}.mud-stepper-grid-20.vertical{display:grid;grid-template-rows:repeat(40,1fr);}.mud-stepper-grid-21.horizontal{display:grid;grid-template-columns:repeat(42,1fr);}.mud-stepper-grid-21.vertical{display:grid;grid-template-rows:repeat(42,1fr);}.mud-stepper-grid-22.horizontal{display:grid;grid-template-columns:repeat(44,1fr);}.mud-stepper-grid-22.vertical{display:grid;grid-template-rows:repeat(44,1fr);}.mud-stepper-grid-23.horizontal{display:grid;grid-template-columns:repeat(46,1fr);}.mud-stepper-grid-23.vertical{display:grid;grid-template-rows:repeat(46,1fr);}.mud-stepper-grid-24.horizontal{display:grid;grid-template-columns:repeat(48,1fr);}.mud-stepper-grid-24.vertical{display:grid;grid-template-rows:repeat(48,1fr);}.steps-1.horizontal{grid-column-start:2;grid-column-end:2;grid-row:1/-1;}.steps-1.vertical{grid-row-start:2;grid-row-end:2;grid-column:1/-1;}.steps-2.horizontal{grid-column-start:2;grid-column-end:4;grid-row:1/-1;}.steps-2.vertical{grid-row-start:2;grid-row-end:4;grid-column:1/-1;}.steps-3.horizontal{grid-column-start:2;grid-column-end:6;grid-row:1/-1;}.steps-3.vertical{grid-row-start:2;grid-row-end:6;grid-column:1/-1;}.steps-4.horizontal{grid-column-start:2;grid-column-end:8;grid-row:1/-1;}.steps-4.vertical{grid-row-start:2;grid-row-end:8;grid-column:1/-1;}.steps-5.horizontal{grid-column-start:2;grid-column-end:10;grid-row:1/-1;}.steps-5.vertical{grid-row-start:2;grid-row-end:10;grid-column:1/-1;}.steps-6.horizontal{grid-column-start:2;grid-column-end:12;grid-row:1/-1;}.steps-6.vertical{grid-row-start:2;grid-row-end:12;grid-column:1/-1;}.steps-7.horizontal{grid-column-start:2;grid-column-end:14;grid-row:1/-1;}.steps-7.vertical{grid-row-start:2;grid-row-end:14;grid-column:1/-1;}.steps-8.horizontal{grid-column-start:2;grid-column-end:16;grid-row:1/-1;}.steps-8.vertical{grid-row-start:2;grid-row-end:16;grid-column:1/-1;}.steps-9.horizontal{grid-column-start:2;grid-column-end:18;grid-row:1/-1;}.steps-9.vertical{grid-row-start:2;grid-row-end:18;grid-column:1/-1;}.steps-10.horizontal{grid-column-start:2;grid-column-end:20;grid-row:1/-1;}.steps-10.vertical{grid-row-start:2;grid-row-end:20;grid-column:1/-1;}.steps-11.horizontal{grid-column-start:2;grid-column-end:22;grid-row:1/-1;}.steps-11.vertical{grid-row-start:2;grid-row-end:22;grid-column:1/-1;}.steps-12.horizontal{grid-column-start:2;grid-column-end:24;grid-row:1/-1;}.steps-12.vertical{grid-row-start:2;grid-row-end:24;grid-column:1/-1;}.mud-stepper-progress-extended.horizontal.header-size-small{top:22px;height:2px;}.mud-stepper-progress-extended.horizontal.header-size-medium{top:30px;height:3px;}.mud-stepper-progress-extended.horizontal.header-size-large{top:38px;height:4px;}.mud-stepper-progress-extended.vertical.header-size-small{left:22px;}.mud-stepper-progress-extended.vertical.header-size-medium{left:30px;}.mud-stepper-progress-extended.vertical.header-size-large{left:38px;}.mobile.horizontal .mud-stepper-progress-extended{margin-inline-start:40px;}.mud-stepper-progress-extended{display:inline-grid;z-index:10;}.mud-stepper-progress-extended.vertical{transform:rotateX(180deg);}.mud-switch-m3{cursor:pointer;display:inline-flex;align-items:center;vertical-align:middle;margin-top:4px;margin-bottom:4px;-webkit-tap-highlight-color:transparent;}.mud-switch-m3.mud-disabled{color:var(--mud-palette-text-disabled) !important;cursor:default;}.mud-switch-m3.mud-readonly,.mud-switch-m3 .mud-readonly:hover{cursor:default;background-color:transparent !important;}.mud-switch-span-m3{width:52px;height:32px;display:inline-flex;z-index:0;position:relative;box-sizing:border-box;flex-shrink:0;vertical-align:middle;}.mud-switch-span-m3.mud-switch-child-content-m3{margin-inline-end:12px;}.mud-switch-span-m3 .mud-switch-track-m3{width:52px;height:32px;z-index:-1;transition:opacity 150ms cubic-bezier(.4,0,.2,1) 0ms,background-color 150ms cubic-bezier(.4,0,.2,1) 0ms;border-radius:30px;background-color:var(--mud-palette-background);border:2px solid;}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-default-m3{border-color:var(--mud-palette-text-primary);}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-primary-m3{border-color:var(--mud-palette-primary);}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-secondary-m3{border-color:var(--mud-palette-secondary);}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-tertiary-m3{border-color:var(--mud-palette-tertiary);}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-info-m3{border-color:var(--mud-palette-info);}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-success-m3{border-color:var(--mud-palette-success);}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-warning-m3{border-color:var(--mud-palette-warning);}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-error-m3{border-color:var(--mud-palette-error);}.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-dark-m3{border-color:var(--mud-palette-dark);}.mud-switch-base-m3{padding-top:4px;padding-bottom:4px;padding-inline-start:8px;top:0;left:0;bottom:0;color:#fafafa;z-index:1;position:absolute;transition:left 150ms cubic-bezier(.4,0,.2,1) 0ms,transform 150ms cubic-bezier(.4,0,.2,1) 0ms,background-color 250ms cubic-bezier(.4,0,.2,1) 0ms,box-shadow 250ms cubic-bezier(.4,0,.2,1) 0ms;}.mud-switch-base-m3.mud-switch-base-dense-m3{padding-inline-start:4px;}.mud-switch-base-m3.mud-checked{transform:translateX(20px);padding:4px;}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3{opacity:1;}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-default{background-color:var(--mud-palette-text-primary);}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-primary{background-color:var(--mud-palette-primary);}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-secondary{background-color:var(--mud-palette-secondary);}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-tertiary{background-color:var(--mud-palette-tertiary);}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-info{background-color:var(--mud-palette-info);}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-success{background-color:var(--mud-palette-success);}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-warning{background-color:var(--mud-palette-warning);}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-error{background-color:var(--mud-palette-error);}.mud-switch-base-m3.mud-checked+.mud-switch-track-m3.mud-dark{background-color:var(--mud-palette-dark);}.mud-switch-base-m3.mud-checked .mud-switch-thumb-m3{width:24px;height:24px;box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12);border-radius:50%;background-color:var(--mud-palette-background);}.mud-switch-base-m3:hover{background-color:var(--mud-palette-action-default-hover);}.mud-switch-base-m3.mud-switch-disabled{color:var(--mud-palette-gray-default) !important;}.mud-switch-base-m3.mud-switch-disabled+.mud-switch-track-m3{opacity:.12 !important;}.mud-switch-base-m3.mud-switch-disabled:hover,.mud-switch-base-m3.mud-switch-disabled:focus-visible{cursor:default;background-color:transparent !important;}.mud-switch-button-m3{display:flex;align-items:inherit;justify-content:inherit;}.mud-switch-button-m3 .mud-switch-input-m3{top:0;left:0;width:100%;cursor:inherit;height:100%;margin:0;opacity:0;padding:0;z-index:1;position:absolute;}.mud-switch-button-m3 .mud-switch-thumb-m3{width:16px;height:16px;box-shadow:0 2px 1px -1px rgba(0,0,0,.2),0 1px 1px 0 rgba(0,0,0,.14),0 1px 3px 0 rgba(0,0,0,.12);border-radius:50%;}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-default-m3{background-color:var(--mud-palette-text-primary);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-primary-m3{background-color:var(--mud-palette-primary);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-secondary-m3{background-color:var(--mud-palette-secondary);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-tertiary-m3{background-color:var(--mud-palette-tertiary);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-info-m3{background-color:var(--mud-palette-info);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-success-m3{background-color:var(--mud-palette-success);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-warning-m3{background-color:var(--mud-palette-warning);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-error-m3{background-color:var(--mud-palette-error);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-dark-m3{background-color:var(--mud-palette-dark);}.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-off-icon-m3{width:24px;height:24px;}.mud-wheel{overflow:hidden;min-width:0;flex-grow:1;user-select:none;-webkit-user-select:none;}.mud-wheel-item{width:100%;display:flex;align-content:center;justify-content:center;color:var(--mud-palette-text-secondary);border-radius:var(--mud-default-borderradius);}.mud-wheel-item.mud-wheel-item:hover:not(.mud-disabled){background-color:var(--mud-palette-action-default-hover);}.mud-wheel-item.wheel-item-closest{color:var(--mud-palette-text);}.mud-wheel-item.wheel-item-empty{min-height:32px !important;}.mud-wheel-item.wheel-item-empty.wheel-item-empty-dense{min-height:24px !important;}.mud-wheel-item.wheel-item-empty.wheel-item-empty:hover{background-color:unset;}.mud-wheel-item.mud-disabled{color:var(--mud-palette-text-disabled);}.middle-item{transform:scale(1.2);}.middle-item.mud-disabled{color:var(--mud-palette-text-disabled);}.mud-wheel-border{min-height:2px !important;}.mud-wheel-border.mud-wheel-border-default{background-color:var(--mud-palette-text-primary);}.mud-wheel-border.mud-wheel-border-primary{background-color:var(--mud-palette-primary);}.mud-wheel-border.wheel-border-gradient-primary{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-primary),rgba(255,0,0,0));background-color:unset;}.mud-wheel-border.mud-wheel-border-secondary{background-color:var(--mud-palette-secondary);}.mud-wheel-border.wheel-border-gradient-secondary{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-secondary),rgba(255,0,0,0));background-color:unset;}.mud-wheel-border.mud-wheel-border-tertiary{background-color:var(--mud-palette-tertiary);}.mud-wheel-border.wheel-border-gradient-tertiary{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-tertiary),rgba(255,0,0,0));background-color:unset;}.mud-wheel-border.mud-wheel-border-info{background-color:var(--mud-palette-info);}.mud-wheel-border.wheel-border-gradient-info{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-info),rgba(255,0,0,0));background-color:unset;}.mud-wheel-border.mud-wheel-border-success{background-color:var(--mud-palette-success);}.mud-wheel-border.wheel-border-gradient-success{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-success),rgba(255,0,0,0));background-color:unset;}.mud-wheel-border.mud-wheel-border-warning{background-color:var(--mud-palette-warning);}.mud-wheel-border.wheel-border-gradient-warning{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-warning),rgba(255,0,0,0));background-color:unset;}.mud-wheel-border.mud-wheel-border-error{background-color:var(--mud-palette-error);}.mud-wheel-border.wheel-border-gradient-error{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-error),rgba(255,0,0,0));background-color:unset;}.mud-wheel-border.mud-wheel-border-dark{background-color:var(--mud-palette-dark);}.mud-wheel-border.wheel-border-gradient-dark{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-dark),rgba(255,0,0,0));background-color:unset;}.mud-wheel-border.wheel-border-gradient-default{background-image:linear-gradient(to right,rgba(255,0,0,0),var(--mud-palette-text-primary),rgba(255,0,0,0));background-color:unset;}.mud-typographym3-display-large{font-family:var(--mud-typographym3-display-large-font);line-height:var(--mud-typographym3-display-large-line-height);font-size:var(--mud-typographym3-display-large-size);letter-spacing:var(--mud-typographym3-display-large-tracking);font-weight:var(--mud-typographym3-display-large-weight);}.mud-typographym3-display-medium{font-family:var(--mud-typographym3-display-medium-font);line-height:var(--mud-typographym3-display-medium-line-height);font-size:var(--mud-typographym3-display-medium-size);letter-spacing:var(--mud-typographym3-display-medium-tracking);font-weight:var(--mud-typographym3-display-medium-weight);}.mud-typographym3-display-small{font-family:var(--mud-typographym3-display-small-font);line-height:var(--mud-typographym3-display-small-line-height);font-size:var(--mud-typographym3-display-small-size);letter-spacing:var(--mud-typographym3-display-small-tracking);font-weight:var(--mud-typographym3-display-small-weight);}.mud-typographym3-headline-large{font-family:var(--mud-typographym3-headline-large-font);line-height:var(--mud-typographym3-headline-large-line-height);font-size:var(--mud-typographym3-headline-large-size);letter-spacing:var(--mud-typographym3-headline-large-tracking);font-weight:var(--mud-typographym3-headline-large-weight);}.mud-typographym3-headline-medium{font-family:var(--mud-typographym3-headline-medium-font);line-height:var(--mud-typographym3-headline-medium-line-height);font-size:var(--mud-typographym3-headline-medium-size);letter-spacing:var(--mud-typographym3-headline-medium-tracking);font-weight:var(--mud-typographym3-headline-medium-weight);}.mud-typographym3-headline-small{font-family:var(--mud-typographym3-headline-small-font);line-height:var(--mud-typographym3-headline-small-line-height);font-size:var(--mud-typographym3-headline-small-size);letter-spacing:var(--mud-typographym3-headline-small-tracking);font-weight:var(--mud-typographym3-headline-small-weight);}.mud-typographym3-title-large{font-family:var(--mud-typographym3-title-large-font);line-height:var(--mud-typographym3-title-large-line-height);font-size:var(--mud-typographym3-title-large-size);letter-spacing:var(--mud-typographym3-title-large-tracking);font-weight:var(--mud-typographym3-title-large-weight);}.mud-typographym3-title-medium{font-family:var(--mud-typographym3-title-medium-font);line-height:var(--mud-typographym3-title-medium-line-height);font-size:var(--mud-typographym3-title-medium-size);letter-spacing:var(--mud-typographym3-title-medium-tracking);font-weight:var(--mud-typographym3-title-medium-weight);}.mud-typographym3-title-small{font-family:var(--mud-typographym3-title-small-font);line-height:var(--mud-typographym3-title-small-line-height);font-size:var(--mud-typographym3-title-small-size);letter-spacing:var(--mud-typographym3-title-small-tracking);font-weight:var(--mud-typographym3-title-small-weight);}.mud-typographym3-body-large{font-family:var(--mud-typographym3-body-large-font);line-height:var(--mud-typographym3-body-large-line-height);font-size:var(--mud-typographym3-body-large-size);letter-spacing:var(--mud-typographym3-body-large-tracking);font-weight:var(--mud-typographym3-body-large-weight);}.mud-typographym3-body-medium{font-family:var(--mud-typographym3-body-medium-font);line-height:var(--mud-typographym3-body-medium-line-height);font-size:var(--mud-typographym3-body-medium-size);letter-spacing:var(--mud-typographym3-body-medium-tracking);font-weight:var(--mud-typographym3-body-medium-weight);}.mud-typographym3-body-small{font-family:var(--mud-typographym3-body-small-font);line-height:var(--mud-typographym3-body-small-line-height);font-size:var(--mud-typographym3-body-small-size);letter-spacing:var(--mud-typographym3-body-small-tracking);font-weight:var(--mud-typographym3-body-small-weight);}.mud-typographym3-label-large{font-family:var(--mud-typographym3-label-large-font);line-height:var(--mud-typographym3-label-large-line-height);font-size:var(--mud-typographym3-label-large-size);letter-spacing:var(--mud-typographym3-label-large-tracking);font-weight:var(--mud-typographym3-label-large-weight);}.mud-typographym3-label-medium{font-family:var(--mud-typographym3-label-medium-font);line-height:var(--mud-typographym3-label-medium-line-height);font-size:var(--mud-typographym3-label-medium-size);letter-spacing:var(--mud-typographym3-label-medium-tracking);font-weight:var(--mud-typographym3-label-medium-weight);}.mud-typographym3-label-small{font-family:var(--mud-typographym3-label-small-font);line-height:var(--mud-typographym3-label-small-line-height);font-size:var(--mud-typographym3-label-small-size);letter-spacing:var(--mud-typographym3-label-small-tracking);font-weight:var(--mud-typographym3-label-small-weight);}.mud-typography-display-inline{display:inline;}.mud-transfer-list-common{height:fill-available;height:-webkit-fill-available;}.mud-transfer-list-container{display:flex;flex-direction:column;flex:1 1 0%;}.mud-list-extended{margin:0;padding:0;position:relative;list-style:none;}.mud-list-extended.mud-list-padding-extended{padding-top:8px;padding-bottom:8px;}.mud-list-item-extended{width:100%;display:flex;position:relative;box-sizing:border-box;text-align:start;align-items:center;padding-top:8px;padding-bottom:8px;justify-content:flex-start;text-decoration:none;outline:none;}.mud-list-item-extended.mud-list-item-dense-extended{padding-top:4px;padding-bottom:4px;}.mud-list-item-extended.mud-list-item-disabled-extended{color:var(--mud-palette-action-disabled) !important;cursor:default !important;pointer-events:none !important;}.mud-list-item-extended.mud-list-item-disabled-extended .mud-list-item-icon-extended{color:var(--mud-palette-action-disabled) !important;}.mud-list-item-clickable-extended{color:inherit;border:0;cursor:pointer;margin:0;outline:0;user-select:none;border-radius:0;vertical-align:middle;background-color:transparent;-webkit-appearance:none;-webkit-tap-highlight-color:transparent;transition:background-color 150ms cubic-bezier(.4,0,.2,1) 0ms;}.mud-list-item-clickable-extended:hover:not(.mud-list-item-functional){background-color:var(--mud-palette-action-default-hover);}.mud-list-item-gutters-extended{padding-left:16px;padding-right:16px;}.mud-list-item-text-extended{flex:1 1 auto;min-width:0;margin-top:4px;margin-bottom:4px;padding-inline-start:8px;padding-inline-end:8px;}.mud-list-item-text-inset-extended{padding-left:56px;padding-inline-start:56px;padding-inline-end:unset;}.mud-list-item-icon-extended{color:var(--mud-palette-action-default);display:inline-flex;flex-shrink:0;padding-inline-start:8px;padding-inline-end:8px;margin-inline-start:-4px;margin-inline-end:4px;}.mud-list-item-multiselect-extended{max-height:32px;}.mud-list-item-multiselect-extended.mud-list-item-multiselect-checkbox-extended{padding-inline-end:16px;}.mud-list-subheader-extended{color:var(--mud-palette-action-default);background-color:var(--mud-palette-background);font-size:.875rem;box-sizing:border-box;list-style:none;font-weight:500;padding-top:16px;padding-bottom:16px;}.mud-list-subheader-secondary-background-extended{background-color:var(--mud-palette-background-gray);}.mud-list-subheader-gutters-extended{padding-left:16px;padding-right:16px;}.mud-list-subheader-inset-extended{padding-left:72px;padding-inline-start:72px;padding-inline-end:unset;}.mud-list-subheader-sticky-extended{top:-8px;z-index:1;position:sticky;}.mud-list-subheader-sticky-extended.mud-list-subheader-sticky-dense-extended{top:0;}.mud-list-item-hilight-extended{background-color:var(--mud-palette-background-gray);}.mud-list-item-hilight-selected{background-color:var(--mud-palette-lines-default) !important;}.mud-list-item-nested-background-extended{background-color:var(--mud-palette-background-gray);}.mud-list-item-avatar-extended{min-width:56px;flex-shrink:0;}.mud-nested-list-extended>.mud-list-item-extended{padding-left:32px;padding-inline-start:32px;padding-inline-end:unset;}.mud-select-extended{display:flex;flex-grow:1;flex-basis:0;min-width:0;position:relative;height:fit-content;}.mud-select-extended.mud-autocomplete{display:block;}.mud-select-extended.mud-autocomplete .mud-select-input-extended{cursor:text;}.mud-select-extended.mud-autocomplete .mud-input-adornment-extended{cursor:pointer;}.mud-select-extended.mud-autocomplete--with-progress .mud-select-input-extended input{padding-right:3.5rem !important;}.mud-select-extended.mud-autocomplete--with-progress .mud-input-adorned-end input{padding-right:4.5rem !important;}.mud-select-extended.mud-autocomplete--with-progress .mud-select-input-extended .mud-icon-button{display:none !important;}.mud-select-extended.mud-autocomplete--with-progress .progress-indicator-circular{position:absolute;width:100%;top:0;bottom:0;display:flex;align-items:center;justify-content:flex-end;padding-top:.25rem;padding-bottom:.25rem;padding-right:1rem;}.mud-select-extended.mud-autocomplete--with-progress .progress-indicator-circular--with-adornment{padding-right:3rem;}.mud-select-extended.mud-autocomplete--with-progress .mud-progress-linear{position:absolute;bottom:-1px;height:2px;}.mud-select-extended .mud-select-input-extended{cursor:pointer;}.mud-select-extended .mud-select-input-extended .mud-select-extended-nowrap{white-space:nowrap;}.mud-select-extended .mud-select-input-extended .mud-input-slot{overflow:hidden;text-overflow:ellipsis;}.mud-select-extended .mud-select-input-extended .mud-input-adornment-end{margin-left:0;}.mud-select-extended .mud-select-input-extended:disabled{cursor:default;}.mud-select-extended .mud-disabled .mud-select-input{cursor:default;}.mud-select-extended>.mud-form-helpertext{margin-top:-21px;}.mud-select-all-extended{margin-top:10px;border-bottom:1px solid #d3d3d3;padding-bottom:18px;}.mud-select-input-chip-extended{display:flex;flex-wrap:wrap;max-width:100%;row-gap:4px;}.mud-select-input-chip-extended.mud-select-extended-nowrap{flex-wrap:nowrap;overflow-x:hidden;}.mud-select-input-chip-extended .mud-chip{flex:0 0 auto;white-space:nowrap;}.mud-placeholder-extended{line-height:unset;}.mud-input-adornment-start-extended:not(.mud-input-text-extended){margin-inline-start:12px;}.mud-input-adornment-start-extended.mud-input-filled-extended{margin-top:16px;}.mud-input-adornment-end-extended:not(.mud-input-text-extended){margin-inline-end:12px;}.mud-no-start-adornment .mud-input-adornment-start-extended{margin-inline-start:0 !important;} \ No newline at end of file +.mud-combobox { + margin: 0; + padding: 0; + position: relative; + list-style: none; +} + +.mud-combobox.mud-combobox-padding { + padding-top: 8px; + padding-bottom: 8px; +} + +.mud-combobox-item { + width: 100%; + display: flex; + position: relative; + box-sizing: border-box; + text-align: start; + align-items: center; + padding-top: 8px; + padding-bottom: 8px; + justify-content: flex-start; + text-decoration: none; + outline: none; + min-height: 48px; +} + +.mud-combobox-item.mud-combobox-item-comfort { + padding-top: 4px; + padding-bottom: 4px; + min-height: 40px; +} + +.mud-combobox-item.mud-combobox-item-slim { + padding-top: 2px; + padding-bottom: 2px; + min-height: 32px; +} + +.mud-combobox-item.mud-combobox-item-superslim { + padding-top: 0; + padding-bottom: 0; + min-height: 24px; +} + +.mud-combobox-item.mud-combobox-item-disabled { + color: var(--mud-palette-action-disabled) !important; + cursor: default !important; + pointer-events: none !important; +} + +.mud-combobox-item.mud-combobox-item-disabled .mud-combobox-item-icon { + color: var(--mud-palette-action-disabled) !important; +} + +.mud-combobox-item-clickable { + color: inherit; + border: 0; + cursor: pointer; + margin: 0; + outline: 0; + user-select: none; + border-radius: 0; + vertical-align: middle; + background-color: transparent; + -webkit-appearance: none; + -webkit-tap-highlight-color: transparent; + transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; +} + +.mud-combobox-item-clickable:hover { + background-color: var(--mud-palette-action-default-hover); +} + +.mud-combobox-item-gutters { + padding-left: 16px; + padding-right: 16px; +} + +.mud-combobox-item-text { + flex: 1 1 auto; + min-width: 0; + margin-top: 4px; + margin-bottom: 4px; + padding-inline-start: 8px; + padding-inline-end: 8px; +} + +.mud-combobox-item-text-inset { + padding-left: 56px; + padding-inline-start: 56px; + padding-inline-end: unset; +} + +.mud-combobox-item-icon { + color: var(--mud-palette-action-default); + display: inline-flex; + flex-shrink: 0; + padding-inline-start: 8px; + padding-inline-end: 8px; + margin-inline-start: -4px; + margin-inline-end: 4px; +} + +.mud-combobox-item-multiselect { + max-height: 32px; +} + +.mud-combobox-item-multiselect.mud-combobox-item-multiselect-checkbox { + padding-inline-end: 16px; +} + +.mud-combobox-subheader { + color: var(--mud-palette-action-default); + background-color: var(--mud-palette-background); + font-size: 0.875rem; + box-sizing: border-box; + list-style: none; + font-weight: 500; + padding-top: 16px; + padding-bottom: 16px; +} + +.mud-combobox-subheader-secondary-background { + background-color: var(--mud-palette-background-gray); +} + +.mud-combobox-subheader-gutters { + padding-left: 16px; + padding-right: 16px; +} + +.mud-combobox-subheader-inset { + padding-left: 72px; + padding-inline-start: 72px; + padding-inline-end: unset; +} + +.mud-combobox-subheader-sticky { + top: -8px; + z-index: 1; + position: sticky; +} + +.mud-combobox-subheader-sticky.mud-combobox-subheader-sticky-dense { + top: 0; +} + +.mud-combobox-item-hilight { + background-color: var(--mud-palette-background-gray); +} + +.mud-combobox-item-hilight { + background-color: var(--mud-palette-lines-default) !important; +} + +.mud-combobox-item-bordered { + border-left: 4px solid var(--mud-palette-lines-default); + padding-inline-start: 12px; +} + +.mud-combobox-item-bordered-primary { + border-left: 4px solid var(--mud-palette-primary); + padding-inline-start: 12px; +} + +.mud-combobox-item-bordered-secondary { + border-left: 4px solid var(--mud-palette-secondary); + padding-inline-start: 12px; +} + +.mud-combobox-item-bordered-tertiary { + border-left: 4px solid var(--mud-palette-tertiary); + padding-inline-start: 12px; +} + +.mud-combobox-item-bordered-info { + border-left: 4px solid var(--mud-palette-info); + padding-inline-start: 12px; +} + +.mud-combobox-item-bordered-success { + border-left: 4px solid var(--mud-palette-success); + padding-inline-start: 12px; +} + +.mud-combobox-item-bordered-warning { + border-left: 4px solid var(--mud-palette-warning); + padding-inline-start: 12px; +} + +.mud-combobox-item-bordered-error { + border-left: 4px solid var(--mud-palette-error); + padding-inline-start: 12px; +} + +.mud-combobox-item-bordered-dark { + border-left: 4px solid var(--mud-palette-dark); + padding-inline-start: 12px; +} + +.mud-combobox-item-nested-background { + background-color: var(--mud-palette-background-gray); +} + +.mud-combobox-item-avatar { + min-width: 56px; + flex-shrink: 0; +} + +.mud-combobox-highlighter { + background-color: transparent; + font-weight: bold; + text-decoration: underline; +} + +.mud-gallery-selected-toolbox { + left: 0; + right: 0; + height: 56px; + width: 100%; + background-color: rgba(0, 0, 0, 0.6); +} + +.mud-gallery-selected-toolbox.gallery-toolbox-top { + top: 0; +} + +.mud-gallery-selected-toolbox.gallery-toolbox-bottom { + bottom: 0; +} + +.mud-page { + display: grid; + box-sizing: border-box; + width: 100%; +} + +.mud-page.mud-page-height-full { + min-height: 100vh; +} + +.mud-page.mud-page-height-full-without-appbar { + min-height: calc(100vh - var(--mud-appbar-height)); +} + +.mud-page.mud-page-column-2 { + grid-template-columns: repeat(2, 50%); +} + +.mud-page.mud-page-column-3 { + grid-template-columns: repeat(3, 33.33333%); +} + +.mud-page.mud-page-column-4 { + grid-template-columns: repeat(4, 25%); +} + +.mud-page.mud-page-column-5 { + grid-template-columns: repeat(5, 20%); +} + +.mud-page.mud-page-column-6 { + grid-template-columns: repeat(6, 16.66667%); +} + +.mud-page.mud-page-column-7 { + grid-template-columns: repeat(7, 14.28571%); +} + +.mud-page.mud-page-column-8 { + grid-template-columns: repeat(8, 12.5%); +} + +.mud-page.mud-page-column-9 { + grid-template-columns: repeat(9, 11.11111%); +} + +.mud-page.mud-page-column-10 { + grid-template-columns: repeat(10, 10%); +} + +.mud-page.mud-page-column-11 { + grid-template-columns: repeat(11, 9.09091%); +} + +.mud-page.mud-page-column-12 { + grid-template-columns: repeat(12, 8.33333%); +} + +.mud-page.mud-page-row-2 { + grid-template-rows: repeat(2, 50%); +} + +.mud-page.mud-page-row-3 { + grid-template-rows: repeat(3, 33.33333%); +} + +.mud-page.mud-page-row-4 { + grid-template-rows: repeat(4, 25%); +} + +.mud-page.mud-page-row-5 { + grid-template-rows: repeat(5, 20%); +} + +.mud-page.mud-page-row-6 { + grid-template-rows: repeat(6, 16.66667%); +} + +.mud-page.mud-page-row-7 { + grid-template-rows: repeat(7, 14.28571%); +} + +.mud-page.mud-page-row-8 { + grid-template-rows: repeat(8, 12.5%); +} + +.mud-page.mud-page-row-9 { + grid-template-rows: repeat(9, 11.11111%); +} + +.mud-page.mud-page-row-10 { + grid-template-rows: repeat(10, 10%); +} + +.mud-page.mud-page-row-11 { + grid-template-rows: repeat(11, 9.09091%); +} + +.mud-page.mud-page-row-12 { + grid-template-rows: repeat(12, 8.33333%); +} + +.mud-section { + display: inline-grid; + overflow: auto; +} + +.mud-section.mud-section-col-start-1 { + grid-column-start: 1; +} + +.mud-section.mud-section-col-start-2 { + grid-column-start: 2; +} + +.mud-section.mud-section-col-start-3 { + grid-column-start: 3; +} + +.mud-section.mud-section-col-start-4 { + grid-column-start: 4; +} + +.mud-section.mud-section-col-start-5 { + grid-column-start: 5; +} + +.mud-section.mud-section-col-start-6 { + grid-column-start: 6; +} + +.mud-section.mud-section-col-start-7 { + grid-column-start: 7; +} + +.mud-section.mud-section-col-start-8 { + grid-column-start: 8; +} + +.mud-section.mud-section-col-start-9 { + grid-column-start: 9; +} + +.mud-section.mud-section-col-start-10 { + grid-column-start: 10; +} + +.mud-section.mud-section-col-start-11 { + grid-column-start: 11; +} + +.mud-section.mud-section-col-start-12 { + grid-column-start: 12; +} + +.mud-section.mud-section-col-end-1 { + grid-column-end: 1; +} + +.mud-section.mud-section-col-end-2 { + grid-column-end: 2; +} + +.mud-section.mud-section-col-end-3 { + grid-column-end: 3; +} + +.mud-section.mud-section-col-end-4 { + grid-column-end: 4; +} + +.mud-section.mud-section-col-end-5 { + grid-column-end: 5; +} + +.mud-section.mud-section-col-end-6 { + grid-column-end: 6; +} + +.mud-section.mud-section-col-end-7 { + grid-column-end: 7; +} + +.mud-section.mud-section-col-end-8 { + grid-column-end: 8; +} + +.mud-section.mud-section-col-end-9 { + grid-column-end: 9; +} + +.mud-section.mud-section-col-end-10 { + grid-column-end: 10; +} + +.mud-section.mud-section-col-end-11 { + grid-column-end: 11; +} + +.mud-section.mud-section-col-end-12 { + grid-column-end: 12; +} + +.mud-section.mud-section-col-end-13 { + grid-column-end: 13; +} + +.mud-section.mud-section-row-start-1 { + grid-row-start: 1; +} + +.mud-section.mud-section-row-start-2 { + grid-row-start: 2; +} + +.mud-section.mud-section-row-start-3 { + grid-row-start: 3; +} + +.mud-section.mud-section-row-start-4 { + grid-row-start: 4; +} + +.mud-section.mud-section-row-start-5 { + grid-row-start: 5; +} + +.mud-section.mud-section-row-start-6 { + grid-row-start: 6; +} + +.mud-section.mud-section-row-start-7 { + grid-row-start: 7; +} + +.mud-section.mud-section-row-start-8 { + grid-row-start: 8; +} + +.mud-section.mud-section-row-start-9 { + grid-row-start: 9; +} + +.mud-section.mud-section-row-start-10 { + grid-row-start: 10; +} + +.mud-section.mud-section-row-start-11 { + grid-row-start: 11; +} + +.mud-section.mud-section-row-start-12 { + grid-row-start: 12; +} + +.mud-section.mud-section-row-end-1 { + grid-row-end: 1; +} + +.mud-section.mud-section-row-end-2 { + grid-row-end: 2; +} + +.mud-section.mud-section-row-end-3 { + grid-row-end: 3; +} + +.mud-section.mud-section-row-end-4 { + grid-row-end: 4; +} + +.mud-section.mud-section-row-end-5 { + grid-row-end: 5; +} + +.mud-section.mud-section-row-end-6 { + grid-row-end: 6; +} + +.mud-section.mud-section-row-end-7 { + grid-row-end: 7; +} + +.mud-section.mud-section-row-end-8 { + grid-row-end: 8; +} + +.mud-section.mud-section-row-end-9 { + grid-row-end: 9; +} + +.mud-section.mud-section-row-end-10 { + grid-row-end: 10; +} + +.mud-section.mud-section-row-end-11 { + grid-row-end: 11; +} + +.mud-section.mud-section-row-end-12 { + grid-row-end: 12; +} + +.mud-section.mud-section-row-end-13 { + grid-row-end: 13; +} + +.mud-popup { + z-index: 2000; + overflow: auto; + background-color: var(--mud-palette-background); + min-height: var(--mud-appbar-height); +} + +.mud-popup.mud-popup-center { + height: 300px; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + width: 320px; + aspect-ratio: 1/1; +} + +.mud-range-container { + align-items: center; + margin: 20px 0; +} + +.mud-range-container input::-webkit-slider-thumb { + pointer-events: all; + position: relative; + z-index: 1; +} + +.mud-range-container input::-moz-range-thumb { + pointer-events: all; + position: relative; + z-index: 10; +} + +.mud-range-container input::-moz-range-track { + position: relative; + z-index: -1; +} + +.mud-range-container input:last-of-type::-moz-range-track { + -moz-appearance: none; +} + +.mud-range-container .mud-slider-input:last-of-type { + position: absolute; + pointer-events: none; + top: 0; +} + +.mud-range-container input[type=range]::-webkit-slider-thumb { + pointer-events: all; +} + +.mud-range-display { + text-align: center; +} + +.mud-signature-pad-container { + touch-action: none; +} + +.mud-splitter { + display: grid; + position: relative; + width: 100%; +} + +.mud-splitter-content { + overflow: auto; +} + +.mud-splitter-thumb ::-webkit-slider-runnable-track { + visibility: hidden !important; + height: 100% !important; +} + +.mud-splitter-thumb ::-moz-range-track { + visibility: hidden !important; + height: 100% !important; +} + +.mud-splitter-track { + position: absolute; + top: 50%; + transform: translateY(-50%); + height: 100%; +} + +.mud-splitter-track.mud-slider { + visibility: hidden !important; +} + +.mud-splitter-track.mud-slider .mud-slider-container { + height: 100% !important; +} + +.mud-splitter-track.mud-slider .mud-slider-input { + top: 50%; +} + +.mud-splitter-thumb ::-webkit-slider-thumb { + visibility: visible !important; + appearance: none !important; + -webkit-appearance: none !important; + top: 50% !important; + transform: translateY(-50%) !important; + height: 100% !important; + width: 8px !important; + border: none !important; + border-radius: 0 !important; + cursor: ew-resize !important; +} + +.mud-splitter-thumb-disabled ::-webkit-slider-thumb { + cursor: default !important; +} + +.mud-splitter-thumb ::-moz-range-thumb { + visibility: visible !important; + appearance: none !important; + -moz-appearance: none !important; + top: 50% !important; + transform: translateY(-50%) !important; + height: 100% !important; + width: 8px !important; + border: none !important; + border-radius: 0 !important; + cursor: ew-resize !important; +} + +.mud-splitter-thumb-disabled ::-moz-range-thumb { + cursor: default !important; +} + +.mud-stepper-header-extended { + min-height: 62px; + border-radius: var(--mud-default-borderradius); +} + +.mud-stepper-header-extended.mud-stepper-header-non-linear-extended:hover { + background-color: var(--mud-palette-action-default-hover); +} + +.mud-stepper-badge-extended { + z-index: 21; +} + +.mud-stepper-avatar-extended { + z-index: 20; +} + +.mud-stepper-avatar-bg-extended { + background-color: var(--mud-palette-background); +} + +.mud-stepper-sub-inner-header-extended { + grid-column-start: 1; + grid-column-end: -1; + flex-direction: row; + grid-row: 1; + list-style: none; + display: flex; +} + +.mud-stepper-sub-inner-header-vertical-extended { + grid-row-start: 1; + grid-row-end: -1; + flex-direction: column; + grid-column: 1; + list-style: none; + display: flex; +} + +.mud-stepper-text-mobile-extended { + grid-row: 1; + margin-top: 22px; +} + +.mud-stepper-text-mobile-vertical-extended { + grid-column: 1; + margin-inline-start: 22px; +} + +.mud-stepper-step-1.horizontal { + width: 100%; +} + +.mud-stepper-step-1.vertical { + height: 100%; +} + +.mud-stepper-step-2.horizontal { + width: 50%; +} + +.mud-stepper-step-2.vertical { + height: 50%; +} + +.mud-stepper-step-3.horizontal { + width: 33.3333333333%; +} + +.mud-stepper-step-3.vertical { + height: 33.3333333333%; +} + +.mud-stepper-step-4.horizontal { + width: 25%; +} + +.mud-stepper-step-4.vertical { + height: 25%; +} + +.mud-stepper-step-5.horizontal { + width: 20%; +} + +.mud-stepper-step-5.vertical { + height: 20%; +} + +.mud-stepper-step-6.horizontal { + width: 16.6666666667%; +} + +.mud-stepper-step-6.vertical { + height: 16.6666666667%; +} + +.mud-stepper-step-7.horizontal { + width: 14.2857142857%; +} + +.mud-stepper-step-7.vertical { + height: 14.2857142857%; +} + +.mud-stepper-step-8.horizontal { + width: 12.5%; +} + +.mud-stepper-step-8.vertical { + height: 12.5%; +} + +.mud-stepper-step-9.horizontal { + width: 11.1111111111%; +} + +.mud-stepper-step-9.vertical { + height: 11.1111111111%; +} + +.mud-stepper-step-10.horizontal { + width: 10%; +} + +.mud-stepper-step-10.vertical { + height: 10%; +} + +.mud-stepper-step-11.horizontal { + width: 9.0909090909%; +} + +.mud-stepper-step-11.vertical { + height: 9.0909090909%; +} + +.mud-stepper-step-12.horizontal { + width: 8.3333333333%; +} + +.mud-stepper-step-12.vertical { + height: 8.3333333333%; +} + +.mud-stepper-grid-1.horizontal { + display: grid; + grid-template-columns: repeat(2, 1fr); +} + +.mud-stepper-grid-1.vertical { + display: grid; + grid-template-rows: repeat(2, 1fr); +} + +.mud-stepper-grid-2.horizontal { + display: grid; + grid-template-columns: repeat(4, 1fr); +} + +.mud-stepper-grid-2.vertical { + display: grid; + grid-template-rows: repeat(4, 1fr); +} + +.mud-stepper-grid-3.horizontal { + display: grid; + grid-template-columns: repeat(6, 1fr); +} + +.mud-stepper-grid-3.vertical { + display: grid; + grid-template-rows: repeat(6, 1fr); +} + +.mud-stepper-grid-4.horizontal { + display: grid; + grid-template-columns: repeat(8, 1fr); +} + +.mud-stepper-grid-4.vertical { + display: grid; + grid-template-rows: repeat(8, 1fr); +} + +.mud-stepper-grid-5.horizontal { + display: grid; + grid-template-columns: repeat(10, 1fr); +} + +.mud-stepper-grid-5.vertical { + display: grid; + grid-template-rows: repeat(10, 1fr); +} + +.mud-stepper-grid-6.horizontal { + display: grid; + grid-template-columns: repeat(12, 1fr); +} + +.mud-stepper-grid-6.vertical { + display: grid; + grid-template-rows: repeat(12, 1fr); +} + +.mud-stepper-grid-7.horizontal { + display: grid; + grid-template-columns: repeat(14, 1fr); +} + +.mud-stepper-grid-7.vertical { + display: grid; + grid-template-rows: repeat(14, 1fr); +} + +.mud-stepper-grid-8.horizontal { + display: grid; + grid-template-columns: repeat(16, 1fr); +} + +.mud-stepper-grid-8.vertical { + display: grid; + grid-template-rows: repeat(16, 1fr); +} + +.mud-stepper-grid-9.horizontal { + display: grid; + grid-template-columns: repeat(18, 1fr); +} + +.mud-stepper-grid-9.vertical { + display: grid; + grid-template-rows: repeat(18, 1fr); +} + +.mud-stepper-grid-10.horizontal { + display: grid; + grid-template-columns: repeat(20, 1fr); +} + +.mud-stepper-grid-10.vertical { + display: grid; + grid-template-rows: repeat(20, 1fr); +} + +.mud-stepper-grid-11.horizontal { + display: grid; + grid-template-columns: repeat(22, 1fr); +} + +.mud-stepper-grid-11.vertical { + display: grid; + grid-template-rows: repeat(22, 1fr); +} + +.mud-stepper-grid-12.horizontal { + display: grid; + grid-template-columns: repeat(24, 1fr); +} + +.mud-stepper-grid-12.vertical { + display: grid; + grid-template-rows: repeat(24, 1fr); +} + +.mud-stepper-grid-13.horizontal { + display: grid; + grid-template-columns: repeat(26, 1fr); +} + +.mud-stepper-grid-13.vertical { + display: grid; + grid-template-rows: repeat(26, 1fr); +} + +.mud-stepper-grid-14.horizontal { + display: grid; + grid-template-columns: repeat(28, 1fr); +} + +.mud-stepper-grid-14.vertical { + display: grid; + grid-template-rows: repeat(28, 1fr); +} + +.mud-stepper-grid-15.horizontal { + display: grid; + grid-template-columns: repeat(30, 1fr); +} + +.mud-stepper-grid-15.vertical { + display: grid; + grid-template-rows: repeat(30, 1fr); +} + +.mud-stepper-grid-16.horizontal { + display: grid; + grid-template-columns: repeat(32, 1fr); +} + +.mud-stepper-grid-16.vertical { + display: grid; + grid-template-rows: repeat(32, 1fr); +} + +.mud-stepper-grid-17.horizontal { + display: grid; + grid-template-columns: repeat(34, 1fr); +} + +.mud-stepper-grid-17.vertical { + display: grid; + grid-template-rows: repeat(34, 1fr); +} + +.mud-stepper-grid-18.horizontal { + display: grid; + grid-template-columns: repeat(36, 1fr); +} + +.mud-stepper-grid-18.vertical { + display: grid; + grid-template-rows: repeat(36, 1fr); +} + +.mud-stepper-grid-19.horizontal { + display: grid; + grid-template-columns: repeat(38, 1fr); +} + +.mud-stepper-grid-19.vertical { + display: grid; + grid-template-rows: repeat(38, 1fr); +} + +.mud-stepper-grid-20.horizontal { + display: grid; + grid-template-columns: repeat(40, 1fr); +} + +.mud-stepper-grid-20.vertical { + display: grid; + grid-template-rows: repeat(40, 1fr); +} + +.mud-stepper-grid-21.horizontal { + display: grid; + grid-template-columns: repeat(42, 1fr); +} + +.mud-stepper-grid-21.vertical { + display: grid; + grid-template-rows: repeat(42, 1fr); +} + +.mud-stepper-grid-22.horizontal { + display: grid; + grid-template-columns: repeat(44, 1fr); +} + +.mud-stepper-grid-22.vertical { + display: grid; + grid-template-rows: repeat(44, 1fr); +} + +.mud-stepper-grid-23.horizontal { + display: grid; + grid-template-columns: repeat(46, 1fr); +} + +.mud-stepper-grid-23.vertical { + display: grid; + grid-template-rows: repeat(46, 1fr); +} + +.mud-stepper-grid-24.horizontal { + display: grid; + grid-template-columns: repeat(48, 1fr); +} + +.mud-stepper-grid-24.vertical { + display: grid; + grid-template-rows: repeat(48, 1fr); +} + +.steps-1.horizontal { + grid-column-start: 2; + grid-column-end: 2; + grid-row: 1/-1; +} + +.steps-1.vertical { + grid-row-start: 2; + grid-row-end: 2; + grid-column: 1/-1; +} + +.steps-2.horizontal { + grid-column-start: 2; + grid-column-end: 4; + grid-row: 1/-1; +} + +.steps-2.vertical { + grid-row-start: 2; + grid-row-end: 4; + grid-column: 1/-1; +} + +.steps-3.horizontal { + grid-column-start: 2; + grid-column-end: 6; + grid-row: 1/-1; +} + +.steps-3.vertical { + grid-row-start: 2; + grid-row-end: 6; + grid-column: 1/-1; +} + +.steps-4.horizontal { + grid-column-start: 2; + grid-column-end: 8; + grid-row: 1/-1; +} + +.steps-4.vertical { + grid-row-start: 2; + grid-row-end: 8; + grid-column: 1/-1; +} + +.steps-5.horizontal { + grid-column-start: 2; + grid-column-end: 10; + grid-row: 1/-1; +} + +.steps-5.vertical { + grid-row-start: 2; + grid-row-end: 10; + grid-column: 1/-1; +} + +.steps-6.horizontal { + grid-column-start: 2; + grid-column-end: 12; + grid-row: 1/-1; +} + +.steps-6.vertical { + grid-row-start: 2; + grid-row-end: 12; + grid-column: 1/-1; +} + +.steps-7.horizontal { + grid-column-start: 2; + grid-column-end: 14; + grid-row: 1/-1; +} + +.steps-7.vertical { + grid-row-start: 2; + grid-row-end: 14; + grid-column: 1/-1; +} + +.steps-8.horizontal { + grid-column-start: 2; + grid-column-end: 16; + grid-row: 1/-1; +} + +.steps-8.vertical { + grid-row-start: 2; + grid-row-end: 16; + grid-column: 1/-1; +} + +.steps-9.horizontal { + grid-column-start: 2; + grid-column-end: 18; + grid-row: 1/-1; +} + +.steps-9.vertical { + grid-row-start: 2; + grid-row-end: 18; + grid-column: 1/-1; +} + +.steps-10.horizontal { + grid-column-start: 2; + grid-column-end: 20; + grid-row: 1/-1; +} + +.steps-10.vertical { + grid-row-start: 2; + grid-row-end: 20; + grid-column: 1/-1; +} + +.steps-11.horizontal { + grid-column-start: 2; + grid-column-end: 22; + grid-row: 1/-1; +} + +.steps-11.vertical { + grid-row-start: 2; + grid-row-end: 22; + grid-column: 1/-1; +} + +.steps-12.horizontal { + grid-column-start: 2; + grid-column-end: 24; + grid-row: 1/-1; +} + +.steps-12.vertical { + grid-row-start: 2; + grid-row-end: 24; + grid-column: 1/-1; +} + +.mud-stepper-progress-extended.horizontal.header-size-small { + top: 22px; + height: 2px; +} + +.mud-stepper-progress-extended.horizontal.header-size-medium { + top: 30px; + height: 3px; +} + +.mud-stepper-progress-extended.horizontal.header-size-large { + top: 38px; + height: 4px; +} + +.mud-stepper-progress-extended.vertical.header-size-small { + left: 22px; +} + +.mud-stepper-progress-extended.vertical.header-size-medium { + left: 30px; +} + +.mud-stepper-progress-extended.vertical.header-size-large { + left: 38px; +} + +.mobile.horizontal .mud-stepper-progress-extended { + margin-inline-start: 40px; +} + +.mud-stepper-progress-extended { + display: inline-grid; + z-index: 10; +} + +.mud-stepper-progress-extended.vertical { + transform: rotateX(180deg); +} + +.mud-switch-m3 { + cursor: pointer; + display: inline-flex; + align-items: center; + vertical-align: middle; + margin-top: 4px; + margin-bottom: 4px; + -webkit-tap-highlight-color: transparent; +} + +.mud-switch-m3.mud-disabled { + color: var(--mud-palette-text-disabled) !important; + cursor: default; +} + +.mud-switch-m3.mud-readonly, .mud-switch-m3 .mud-readonly:hover { + cursor: default; + background-color: transparent !important; +} + +.mud-switch-span-m3 { + width: 52px; + height: 32px; + display: inline-flex; + z-index: 0; + position: relative; + box-sizing: border-box; + flex-shrink: 0; + vertical-align: middle; +} + +.mud-switch-span-m3.mud-switch-child-content-m3 { + margin-inline-end: 12px; +} + +.mud-switch-span-m3 .mud-switch-track-m3 { + width: 52px; + height: 32px; + z-index: -1; + transition: opacity 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; + border-radius: 30px; + background-color: var(--mud-palette-background); + border: 2px solid; +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-default-m3 { + border-color: var(--mud-palette-text-primary); +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-primary-m3 { + border-color: var(--mud-palette-primary); +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-secondary-m3 { + border-color: var(--mud-palette-secondary); +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-tertiary-m3 { + border-color: var(--mud-palette-tertiary); +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-info-m3 { + border-color: var(--mud-palette-info); +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-success-m3 { + border-color: var(--mud-palette-success); +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-warning-m3 { + border-color: var(--mud-palette-warning); +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-error-m3 { + border-color: var(--mud-palette-error); +} + +.mud-switch-span-m3 .mud-switch-track-m3.mud-switch-track-dark-m3 { + border-color: var(--mud-palette-dark); +} + +.mud-switch-base-m3 { + padding-top: 4px; + padding-bottom: 4px; + padding-inline-start: 8px; + top: 0; + left: 0; + bottom: 0; + color: #fafafa; + z-index: 1; + position: absolute; + transition: left 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; +} + +.mud-switch-base-m3.mud-switch-base-dense-m3 { + padding-inline-start: 4px; +} + +.mud-switch-base-m3.mud-checked { + transform: translateX(20px); + padding: 4px; +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3 { + opacity: 1; +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-default { + background-color: var(--mud-palette-text-primary); +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-primary { + background-color: var(--mud-palette-primary); +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-secondary { + background-color: var(--mud-palette-secondary); +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-tertiary { + background-color: var(--mud-palette-tertiary); +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-info { + background-color: var(--mud-palette-info); +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-success { + background-color: var(--mud-palette-success); +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-warning { + background-color: var(--mud-palette-warning); +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-error { + background-color: var(--mud-palette-error); +} + +.mud-switch-base-m3.mud-checked + .mud-switch-track-m3.mud-dark { + background-color: var(--mud-palette-dark); +} + +.mud-switch-base-m3.mud-checked .mud-switch-thumb-m3 { + width: 24px; + height: 24px; + box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12); + border-radius: 50%; + background-color: var(--mud-palette-background); +} + +.mud-switch-base-m3:hover { + background-color: var(--mud-palette-action-default-hover); +} + +.mud-switch-base-m3.mud-switch-disabled { + color: var(--mud-palette-gray-default) !important; +} + +.mud-switch-base-m3.mud-switch-disabled + .mud-switch-track-m3 { + opacity: 0.12 !important; +} + +.mud-switch-base-m3.mud-switch-disabled:hover, .mud-switch-base-m3.mud-switch-disabled:focus-visible { + cursor: default; + background-color: transparent !important; +} + +.mud-switch-button-m3 { + display: flex; + align-items: inherit; + justify-content: inherit; +} + +.mud-switch-button-m3 .mud-switch-input-m3 { + top: 0; + left: 0; + width: 100%; + cursor: inherit; + height: 100%; + margin: 0; + opacity: 0; + padding: 0; + z-index: 1; + position: absolute; +} + +.mud-switch-button-m3 .mud-switch-thumb-m3 { + width: 16px; + height: 16px; + box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12); + border-radius: 50%; +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-default-m3 { + background-color: var(--mud-palette-text-primary); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-primary-m3 { + background-color: var(--mud-palette-primary); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-secondary-m3 { + background-color: var(--mud-palette-secondary); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-tertiary-m3 { + background-color: var(--mud-palette-tertiary); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-info-m3 { + background-color: var(--mud-palette-info); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-success-m3 { + background-color: var(--mud-palette-success); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-warning-m3 { + background-color: var(--mud-palette-warning); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-error-m3 { + background-color: var(--mud-palette-error); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-dark-m3 { + background-color: var(--mud-palette-dark); +} + +.mud-switch-button-m3 .mud-switch-thumb-m3.mud-switch-thumb-off-icon-m3 { + width: 24px; + height: 24px; +} + +.mud-wheel { + overflow: hidden; + min-width: 0; + flex-grow: 1; + user-select: none; + -webkit-user-select: none; +} + +.mud-wheel-item { + width: 100%; + display: flex; + align-content: center; + justify-content: center; + color: var(--mud-palette-text-secondary); + border-radius: var(--mud-default-borderradius); +} + +.mud-wheel-item.mud-wheel-item:hover:not(.mud-disabled) { + background-color: var(--mud-palette-action-default-hover); +} + +.mud-wheel-item.wheel-item-closest { + color: var(--mud-palette-text); +} + +.mud-wheel-item.wheel-item-empty { + min-height: 32px !important; +} + +.mud-wheel-item.wheel-item-empty.wheel-item-empty-dense { + min-height: 24px !important; +} + +.mud-wheel-item.wheel-item-empty.wheel-item-empty:hover { + background-color: unset; +} + +.mud-wheel-item.mud-disabled { + color: var(--mud-palette-text-disabled); +} + +.middle-item { + transform: scale(1.2); +} + +.middle-item.mud-disabled { + color: var(--mud-palette-text-disabled); +} + +.mud-wheel-border { + min-height: 2px !important; +} + +.mud-wheel-border.mud-wheel-border-default { + background-color: var(--mud-palette-text-primary); +} + +.mud-wheel-border.mud-wheel-border-primary { + background-color: var(--mud-palette-primary); +} + +.mud-wheel-border.wheel-border-gradient-primary { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-primary), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-wheel-border.mud-wheel-border-secondary { + background-color: var(--mud-palette-secondary); +} + +.mud-wheel-border.wheel-border-gradient-secondary { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-secondary), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-wheel-border.mud-wheel-border-tertiary { + background-color: var(--mud-palette-tertiary); +} + +.mud-wheel-border.wheel-border-gradient-tertiary { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-tertiary), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-wheel-border.mud-wheel-border-info { + background-color: var(--mud-palette-info); +} + +.mud-wheel-border.wheel-border-gradient-info { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-info), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-wheel-border.mud-wheel-border-success { + background-color: var(--mud-palette-success); +} + +.mud-wheel-border.wheel-border-gradient-success { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-success), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-wheel-border.mud-wheel-border-warning { + background-color: var(--mud-palette-warning); +} + +.mud-wheel-border.wheel-border-gradient-warning { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-warning), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-wheel-border.mud-wheel-border-error { + background-color: var(--mud-palette-error); +} + +.mud-wheel-border.wheel-border-gradient-error { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-error), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-wheel-border.mud-wheel-border-dark { + background-color: var(--mud-palette-dark); +} + +.mud-wheel-border.wheel-border-gradient-dark { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-dark), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-wheel-border.wheel-border-gradient-default { + background-image: linear-gradient(to right, rgba(255, 0, 0, 0), var(--mud-palette-text-primary), rgba(255, 0, 0, 0)); + background-color: unset; +} + +.mud-typographym3-display-large { + font-family: var(--mud-typographym3-display-large-font); + line-height: var(--mud-typographym3-display-large-line-height); + font-size: var(--mud-typographym3-display-large-size); + letter-spacing: var(--mud-typographym3-display-large-tracking); + font-weight: var(--mud-typographym3-display-large-weight); +} + +.mud-typographym3-display-medium { + font-family: var(--mud-typographym3-display-medium-font); + line-height: var(--mud-typographym3-display-medium-line-height); + font-size: var(--mud-typographym3-display-medium-size); + letter-spacing: var(--mud-typographym3-display-medium-tracking); + font-weight: var(--mud-typographym3-display-medium-weight); +} + +.mud-typographym3-display-small { + font-family: var(--mud-typographym3-display-small-font); + line-height: var(--mud-typographym3-display-small-line-height); + font-size: var(--mud-typographym3-display-small-size); + letter-spacing: var(--mud-typographym3-display-small-tracking); + font-weight: var(--mud-typographym3-display-small-weight); +} + +.mud-typographym3-headline-large { + font-family: var(--mud-typographym3-headline-large-font); + line-height: var(--mud-typographym3-headline-large-line-height); + font-size: var(--mud-typographym3-headline-large-size); + letter-spacing: var(--mud-typographym3-headline-large-tracking); + font-weight: var(--mud-typographym3-headline-large-weight); +} + +.mud-typographym3-headline-medium { + font-family: var(--mud-typographym3-headline-medium-font); + line-height: var(--mud-typographym3-headline-medium-line-height); + font-size: var(--mud-typographym3-headline-medium-size); + letter-spacing: var(--mud-typographym3-headline-medium-tracking); + font-weight: var(--mud-typographym3-headline-medium-weight); +} + +.mud-typographym3-headline-small { + font-family: var(--mud-typographym3-headline-small-font); + line-height: var(--mud-typographym3-headline-small-line-height); + font-size: var(--mud-typographym3-headline-small-size); + letter-spacing: var(--mud-typographym3-headline-small-tracking); + font-weight: var(--mud-typographym3-headline-small-weight); +} + +.mud-typographym3-title-large { + font-family: var(--mud-typographym3-title-large-font); + line-height: var(--mud-typographym3-title-large-line-height); + font-size: var(--mud-typographym3-title-large-size); + letter-spacing: var(--mud-typographym3-title-large-tracking); + font-weight: var(--mud-typographym3-title-large-weight); +} + +.mud-typographym3-title-medium { + font-family: var(--mud-typographym3-title-medium-font); + line-height: var(--mud-typographym3-title-medium-line-height); + font-size: var(--mud-typographym3-title-medium-size); + letter-spacing: var(--mud-typographym3-title-medium-tracking); + font-weight: var(--mud-typographym3-title-medium-weight); +} + +.mud-typographym3-title-small { + font-family: var(--mud-typographym3-title-small-font); + line-height: var(--mud-typographym3-title-small-line-height); + font-size: var(--mud-typographym3-title-small-size); + letter-spacing: var(--mud-typographym3-title-small-tracking); + font-weight: var(--mud-typographym3-title-small-weight); +} + +.mud-typographym3-body-large { + font-family: var(--mud-typographym3-body-large-font); + line-height: var(--mud-typographym3-body-large-line-height); + font-size: var(--mud-typographym3-body-large-size); + letter-spacing: var(--mud-typographym3-body-large-tracking); + font-weight: var(--mud-typographym3-body-large-weight); +} + +.mud-typographym3-body-medium { + font-family: var(--mud-typographym3-body-medium-font); + line-height: var(--mud-typographym3-body-medium-line-height); + font-size: var(--mud-typographym3-body-medium-size); + letter-spacing: var(--mud-typographym3-body-medium-tracking); + font-weight: var(--mud-typographym3-body-medium-weight); +} + +.mud-typographym3-body-small { + font-family: var(--mud-typographym3-body-small-font); + line-height: var(--mud-typographym3-body-small-line-height); + font-size: var(--mud-typographym3-body-small-size); + letter-spacing: var(--mud-typographym3-body-small-tracking); + font-weight: var(--mud-typographym3-body-small-weight); +} + +.mud-typographym3-label-large { + font-family: var(--mud-typographym3-label-large-font); + line-height: var(--mud-typographym3-label-large-line-height); + font-size: var(--mud-typographym3-label-large-size); + letter-spacing: var(--mud-typographym3-label-large-tracking); + font-weight: var(--mud-typographym3-label-large-weight); +} + +.mud-typographym3-label-medium { + font-family: var(--mud-typographym3-label-medium-font); + line-height: var(--mud-typographym3-label-medium-line-height); + font-size: var(--mud-typographym3-label-medium-size); + letter-spacing: var(--mud-typographym3-label-medium-tracking); + font-weight: var(--mud-typographym3-label-medium-weight); +} + +.mud-typographym3-label-small { + font-family: var(--mud-typographym3-label-small-font); + line-height: var(--mud-typographym3-label-small-line-height); + font-size: var(--mud-typographym3-label-small-size); + letter-spacing: var(--mud-typographym3-label-small-tracking); + font-weight: var(--mud-typographym3-label-small-weight); +} + +.mud-typography-display-inline { + display: inline; +} + +.mud-transfer-list-common { + height: fill-available; + height: -webkit-fill-available; +} + +.mud-transfer-list-container { + display: flex; + flex-direction: column; + flex: 1 1 0%; +} + +.mud-list-extended { + margin: 0; + padding: 0; + position: relative; + list-style: none; +} + +.mud-list-extended.mud-list-padding-extended { + padding-top: 8px; + padding-bottom: 8px; +} + +.mud-list-item-extended { + width: 100%; + display: flex; + position: relative; + box-sizing: border-box; + text-align: start; + align-items: center; + padding-top: 8px; + padding-bottom: 8px; + justify-content: flex-start; + text-decoration: none; + outline: none; +} + +.mud-list-item-extended.mud-list-item-dense-extended { + padding-top: 4px; + padding-bottom: 4px; +} + +.mud-list-item-extended.mud-list-item-disabled-extended { + color: var(--mud-palette-action-disabled) !important; + cursor: default !important; + pointer-events: none !important; +} + +.mud-list-item-extended.mud-list-item-disabled-extended .mud-list-item-icon-extended { + color: var(--mud-palette-action-disabled) !important; +} + +.mud-list-item-clickable-extended { + color: inherit; + border: 0; + cursor: pointer; + margin: 0; + outline: 0; + user-select: none; + border-radius: 0; + vertical-align: middle; + background-color: transparent; + -webkit-appearance: none; + -webkit-tap-highlight-color: transparent; + transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; +} + +.mud-list-item-clickable-extended:hover:not(.mud-list-item-functional) { + background-color: var(--mud-palette-action-default-hover); +} + +.mud-list-item-gutters-extended { + padding-left: 16px; + padding-right: 16px; +} + +.mud-list-item-text-extended { + flex: 1 1 auto; + min-width: 0; + margin-top: 4px; + margin-bottom: 4px; + padding-inline-start: 8px; + padding-inline-end: 8px; +} + +.mud-list-item-text-inset-extended { + padding-left: 56px; + padding-inline-start: 56px; + padding-inline-end: unset; +} + +.mud-list-item-icon-extended { + color: var(--mud-palette-action-default); + display: inline-flex; + flex-shrink: 0; + padding-inline-start: 8px; + padding-inline-end: 8px; + margin-inline-start: -4px; + margin-inline-end: 4px; +} + +.mud-list-item-multiselect-extended { + max-height: 32px; +} + +.mud-list-item-multiselect-extended.mud-list-item-multiselect-checkbox-extended { + padding-inline-end: 16px; +} + +.mud-list-subheader-extended { + color: var(--mud-palette-action-default); + background-color: var(--mud-palette-background); + font-size: 0.875rem; + box-sizing: border-box; + list-style: none; + font-weight: 500; + padding-top: 16px; + padding-bottom: 16px; +} + +.mud-list-subheader-secondary-background-extended { + background-color: var(--mud-palette-background-gray); +} + +.mud-list-subheader-gutters-extended { + padding-left: 16px; + padding-right: 16px; +} + +.mud-list-subheader-inset-extended { + padding-left: 72px; + padding-inline-start: 72px; + padding-inline-end: unset; +} + +.mud-list-subheader-sticky-extended { + top: -8px; + z-index: 1; + position: sticky; +} + +.mud-list-subheader-sticky-extended.mud-list-subheader-sticky-dense-extended { + top: 0; +} + +.mud-list-item-hilight-extended { + background-color: var(--mud-palette-background-gray); +} + +.mud-list-item-hilight-selected { + background-color: var(--mud-palette-lines-default) !important; +} + +.mud-list-item-nested-background-extended { + background-color: var(--mud-palette-background-gray); +} + +.mud-list-item-avatar-extended { + min-width: 56px; + flex-shrink: 0; +} + +.mud-nested-list-extended > .mud-list-item-extended { + padding-left: 32px; + padding-inline-start: 32px; + padding-inline-end: unset; +} + +.mud-select-extended { + display: flex; + flex-grow: 1; + flex-basis: 0; + min-width: 0; + position: relative; + height: fit-content; +} + +.mud-select-extended.mud-autocomplete { + display: block; +} + +.mud-select-extended.mud-autocomplete .mud-select-input-extended { + cursor: text; +} + +.mud-select-extended.mud-autocomplete .mud-input-adornment-extended { + cursor: pointer; +} + +.mud-select-extended.mud-autocomplete--with-progress .mud-select-input-extended input { + padding-right: 3.5rem !important; +} + +.mud-select-extended.mud-autocomplete--with-progress .mud-input-adorned-end input { + padding-right: 4.5rem !important; +} + +.mud-select-extended.mud-autocomplete--with-progress .mud-select-input-extended .mud-icon-button { + display: none !important; +} + +.mud-select-extended.mud-autocomplete--with-progress .progress-indicator-circular { + position: absolute; + width: 100%; + top: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: flex-end; + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-right: 1rem; +} + +.mud-select-extended.mud-autocomplete--with-progress .progress-indicator-circular--with-adornment { + padding-right: 3rem; +} + +.mud-select-extended.mud-autocomplete--with-progress .mud-progress-linear { + position: absolute; + bottom: -1px; + height: 2px; +} + +.mud-select-extended .mud-select-input-extended { + cursor: pointer; +} + +.mud-select-extended .mud-select-input-extended .mud-select-extended-nowrap { + white-space: nowrap; +} + +.mud-select-extended .mud-select-input-extended .mud-input-slot { + overflow: hidden; + text-overflow: ellipsis; +} + +.mud-select-extended .mud-select-input-extended .mud-input-adornment-end { + margin-left: 0; +} + +.mud-select-extended .mud-select-input-extended:disabled { + cursor: default; +} + +.mud-select-extended .mud-disabled .mud-select-input { + cursor: default; +} + +.mud-select-extended > .mud-form-helpertext { + margin-top: -21px; +} + +.mud-select-all-extended { + margin-top: 10px; + border-bottom: 1px solid #d3d3d3; + padding-bottom: 18px; +} + +.mud-select-input-chip-extended { + display: flex; + flex-wrap: wrap; + max-width: 100%; + row-gap: 4px; +} + +.mud-select-input-chip-extended.mud-select-extended-nowrap { + flex-wrap: nowrap; + overflow-x: hidden; +} + +.mud-select-input-chip-extended .mud-chip { + flex: 0 0 auto; + white-space: nowrap; +} + +.mud-placeholder-extended { + line-height: unset; +} + +.mud-input-adornment-start-extended:not(.mud-input-text-extended) { + margin-inline-start: 12px; +} + +.mud-input-adornment-start-extended.mud-input-filled-extended { + margin-top: 16px; +} + +.mud-input-adornment-end-extended:not(.mud-input-text-extended) { + margin-inline-end: 12px; +} + +.mud-no-start-adornment .mud-input-adornment-start-extended { + margin-inline-start: 0 !important; +} + +/*# sourceMappingURL=MudExtensions.min.css.map */ diff --git a/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.js b/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.js index f2289153..c132301f 100644 --- a/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.js +++ b/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.js @@ -1 +1 @@ -function auto_size(n){n.style.height="5px";n.style.height=n.scrollHeight+4+"px"}function getcss(n,t){const i=document.querySelector(n);return i.style.getPropertyValue(t)}function setcss(n,t,i){const r=document.querySelectorAll(n);for(let n=0;n{const i=document.querySelector(t);return i?(i.appendChild(n),"ok"):"not found"},removeFromDOM:n=>{n&&n.__internalId!==null&&n.remove()}};class MudSignaturePadManager{constructor(){this.pads=[]}addPad(n,t,i){const r=new MudSignaturePad(n,t,i);r.init();this.pads.push(r)}togglePadEraser(n){const t=this.getPad(n);t&&t.toggleEraser()}disposePad(n){const t=this.getPad(n);t&&t.dispose()}clearPad(n){const t=this.getPad(n);t&&t.clear(!0)}downloadPadImage(n){const t=this.getPad(n);t&&t.download()}getBase64(n){const t=this.getPad(n);if(t)return t.getBase64()}updatePadOptions(n,t){const i=this.getPad(n);i&&i.setOptions(t)}updatePadImage(n,t){const i=this.getPad(n);i&&(t.startsWith("data:image/png;base64,")||(t=`data:image/png;base64,${t}`),i.updateImage(t))}setCanvasSize(n){const t=this.getPad(n);t&&t.updateCanvasSize()}getPad(n){return this.pads.find(t=>t.canvas.id===n.id)||null}}class MudSignaturePad{constructor(n,t,i){this.canvas=t;this.options=i;this.isMouseDown=!1;this.isErasing=!1;this.memCanvas=document.createElement("canvas");this.points=[];this.dotnetRef=n;this.onPointerDown=this.handlePointerDown.bind(this);this.onPointerMove=this.handlePointerMove.bind(this);this.onPointerUp=this.handlePointerUp.bind(this);this.onPointerLeave=this.stopDrawing.bind(this)}get ctx(){return this.canvas.getContext("2d")}get memCtx(){return this.memCanvas.getContext("2d")}init(){this.setCanvasSize();this.setOptions(this.options);this.canvas.addEventListener("pointerdown",this.onPointerDown,{passive:!1});this.canvas.addEventListener("pointermove",this.onPointerMove,{passive:!1});this.canvas.addEventListener("pointerup",this.onPointerUp,{passive:!1});this.canvas.addEventListener("pointerleave",this.onPointerLeave);this.canvas.style.touchAction="none";this.setPencilCursor()}dispose(){this.canvas.removeEventListener("pointerdown",this.onPointerDown);this.canvas.removeEventListener("pointermove",this.onPointerMove);this.canvas.removeEventListener("pointerup",this.onPointerUp);this.canvas.removeEventListener("pointerleave",this.onPointerLeave)}setCanvasSize(){const t=this.canvas.parentElement;if(t){const n=t.getBoundingClientRect();this.canvas.width=n.width;this.canvas.height=n.height;this.memCanvas.width=n.width;this.memCanvas.height=n.height}}updateCanvasSize(){const t=this.canvas.parentElement;if(t){const i=t.getBoundingClientRect(),r=i.width,u=i.height,n=document.createElement("canvas");n.width=this.canvas.width;n.height=this.canvas.height;const f=n.getContext("2d");f.drawImage(this.canvas,0,0);this.canvas.width=r;this.canvas.height=u;this.memCanvas.width=r;this.memCanvas.height=u;this.ctx.drawImage(n,0,0);this.memCtx.drawImage(n,0,0)}}getBase64(){return this.canvas.toDataURL()}updateImage(n){this.clear(!0);const t=new Image;t.onload=()=>{this.ctx.drawImage(t,0,0),this.memCtx.drawImage(t,0,0)};t.src=n}download(){const n=document.createElement("a");n.download="signature.png";n.href=this.getBase64();n.click();n.remove()}clear(n){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);n&&this.memCtx.clearRect(0,0,this.canvas.width,this.canvas.height)}setOptions(n){this.options=n;const t=t=>{t.lineWidth=n.lineWidth,t.lineJoin=n.lineJoin,t.lineCap=n.lineCap,t.strokeStyle=n.strokeStyle};t(this.ctx);t(this.memCtx)}toggleEraser(){this.isErasing=!this.isErasing;this.isErasing?this.setEraserCursor():this.setPencilCursor()}setPencilCursor(){this.canvas.style.cursor="url('_content/CodeBeam.MudBlazor.Extensions/pencil.cur'), auto"}setEraserCursor(){this.canvas.style.cursor="url('_content/CodeBeam.MudBlazor.Extensions/eraser.cur'), auto"}handlePointerDown(n){n.preventDefault();this.isMouseDown=!0;const{offsetX:t,offsetY:i}=n;this.points=[{x:t,y:i}]}handlePointerMove(n){if(this.isMouseDown){n.preventDefault();const{offsetX:t,offsetY:i}=n;this.isErasing?this.ctx.clearRect(t-10,i-10,23,23):(this.clear(),this.ctx.drawImage(this.memCanvas,0,0),this.points.push({x:t,y:i}),this.drawPoints(this.ctx,this.points))}}handlePointerUp(n){n.preventDefault();this.stopDrawing()}stopDrawing(){this.isMouseDown&&(this.isMouseDown=!1,this.memCtx.clearRect(0,0,this.memCanvas.width,this.memCanvas.height),this.memCtx.drawImage(this.canvas,0,0),this.points=[])}drawPoints(n,t){if(!(t.length<2)){if(t.length<6){const i=t[0];n.beginPath();n.lineWidth=this.options.lineWidth;n.strokeStyle=this.options.strokeStyle;n.arc(i.x,i.y,n.lineWidth/2,0,Math.PI*2,!0);n.fill();n.closePath();this.pushUpdateToBlazorComponent();return}n.beginPath();n.moveTo(t[0].x,t[0].y);for(let i=1;i{const i=document.querySelector(t);return i?(i.appendChild(n),"ok"):"not found"},removeFromDOM:n=>{n&&n.__internalId!==null&&n.remove()}};class MudSignaturePadManager{constructor(){this.pads=[]}addPad(n,t,i){const r=new MudSignaturePad(n,t,i);r.init();this.pads.push(r)}togglePadEraser(n){const t=this.getPad(n);t&&t.toggleEraser()}disposePad(n){const t=this.getPad(n);t&&t.dispose()}clearPad(n){const t=this.getPad(n);t&&t.clear(!0)}downloadPadImage(n){const t=this.getPad(n);t&&t.download()}getBase64(n){const t=this.getPad(n);if(t)return t.getBase64()}updatePadOptions(n,t){const i=this.getPad(n);i&&i.setOptions(t)}updatePadImage(n,t){const i=this.getPad(n);i&&(t.startsWith("data:image/png;base64,")||(t=`data:image/png;base64,${t}`),i.updateImage(t))}setCanvasSize(n){const t=this.getPad(n);t&&t.updateCanvasSize()}getPad(n){return this.pads.find(t=>t.canvas.id===n.id)||null}}class MudSignaturePad{constructor(n,t,i){this.canvas=t;this.options=i;this.isMouseDown=!1;this.isErasing=!1;this.memCanvas=document.createElement("canvas");this.points=[];this.dotnetRef=n;this.onPointerDown=this.handlePointerDown.bind(this);this.onPointerMove=this.handlePointerMove.bind(this);this.onPointerUp=this.handlePointerUp.bind(this);this.onPointerLeave=this.stopDrawing.bind(this)}get ctx(){return this.canvas.getContext("2d")}get memCtx(){return this.memCanvas.getContext("2d")}init(){this.setCanvasSize();this.setOptions(this.options);this.canvas.addEventListener("pointerdown",this.onPointerDown,{passive:!1});this.canvas.addEventListener("pointermove",this.onPointerMove,{passive:!1});this.canvas.addEventListener("pointerup",this.onPointerUp,{passive:!1});this.canvas.addEventListener("pointerleave",this.onPointerLeave);this.canvas.style.touchAction="none";this.setPencilCursor()}dispose(){this.canvas.removeEventListener("pointerdown",this.onPointerDown);this.canvas.removeEventListener("pointermove",this.onPointerMove);this.canvas.removeEventListener("pointerup",this.onPointerUp);this.canvas.removeEventListener("pointerleave",this.onPointerLeave)}setCanvasSize(){const t=this.canvas.parentElement;if(t){const n=t.getBoundingClientRect();this.canvas.width=n.width;this.canvas.height=n.height;this.memCanvas.width=n.width;this.memCanvas.height=n.height}}updateCanvasSize(){const t=this.canvas.parentElement;if(t){const i=t.getBoundingClientRect(),r=i.width,u=i.height,n=document.createElement("canvas");n.width=this.canvas.width;n.height=this.canvas.height;const f=n.getContext("2d");f.drawImage(this.canvas,0,0);this.canvas.width=r;this.canvas.height=u;this.memCanvas.width=r;this.memCanvas.height=u;this.ctx.drawImage(n,0,0);this.memCtx.drawImage(n,0,0)}}getBase64(){return this.canvas.toDataURL()}updateImage(n){this.clear(!0);const t=new Image;t.onload=()=>{this.ctx.drawImage(t,0,0),this.memCtx.drawImage(t,0,0)};t.src=n}download(){const n=document.createElement("a");n.download="signature.png";n.href=this.getBase64();n.click();n.remove()}clear(n){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);n&&this.memCtx.clearRect(0,0,this.canvas.width,this.canvas.height)}setOptions(n){this.options=n;const t=t=>{t.lineWidth=n.lineWidth,t.lineJoin=n.lineJoin,t.lineCap=n.lineCap,t.strokeStyle=n.strokeStyle};t(this.ctx);t(this.memCtx)}toggleEraser(){this.isErasing=!this.isErasing;this.isErasing?this.setEraserCursor():this.setPencilCursor()}setPencilCursor(){this.canvas.style.cursor="url('_content/CodeBeam.MudBlazor.Extensions/pencil.cur'), auto"}setEraserCursor(){this.canvas.style.cursor="url('_content/CodeBeam.MudBlazor.Extensions/eraser.cur'), auto"}handlePointerDown(n){n.preventDefault();this.isMouseDown=!0;const{offsetX:t,offsetY:i}=n;this.points=[{x:t,y:i}]}handlePointerMove(n){if(this.isMouseDown){n.preventDefault();const{offsetX:t,offsetY:i}=n;this.isErasing?this.ctx.clearRect(t-10,i-10,23,23):(this.clear(),this.ctx.drawImage(this.memCanvas,0,0),this.points.push({x:t,y:i}),this.drawPoints(this.ctx,this.points))}}handlePointerUp(n){n.preventDefault();this.stopDrawing()}stopDrawing(){this.isMouseDown&&(this.isMouseDown=!1,this.memCtx.clearRect(0,0,this.memCanvas.width,this.memCanvas.height),this.memCtx.drawImage(this.canvas,0,0),this.points=[])}drawPoints(n,t){if(!(t.length<2)){if(t.length<6){const i=t[0];n.beginPath();n.lineWidth=this.options.lineWidth;n.strokeStyle=this.options.strokeStyle;n.arc(i.x,i.y,n.lineWidth/2,0,Math.PI*2,!0);n.fill();n.closePath();this.pushUpdateToBlazorComponent();return}n.beginPath();n.moveTo(t[0].x,t[0].y);for(let i=1;i - - - - - - - - - - True diff --git a/CodeBeam.MudBlazor.Extensions.Docs.Server/CodeBeam.MudBlazor.Extensions.Docs.Server.csproj b/CodeBeam.MudBlazor.Extensions.Docs.Server/CodeBeam.MudBlazor.Extensions.Docs.Server.csproj index 2ec13cd3..a576311e 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs.Server/CodeBeam.MudBlazor.Extensions.Docs.Server.csproj +++ b/CodeBeam.MudBlazor.Extensions.Docs.Server/CodeBeam.MudBlazor.Extensions.Docs.Server.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable MudExtensions.Docs.Server diff --git a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/CodeBeam.MudBlazor.Extensions.Docs.Wasm.csproj b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/CodeBeam.MudBlazor.Extensions.Docs.Wasm.csproj index 868b8e66..aa373855 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/CodeBeam.MudBlazor.Extensions.Docs.Wasm.csproj +++ b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/CodeBeam.MudBlazor.Extensions.Docs.Wasm.csproj @@ -1,15 +1,15 @@  - net9.0 + net10.0 enable enable MudExtensions.Docs.Wasm - - + + + MudExtensions.UnitTests - + + - - + - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/BunitTest.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/BunitTest.cs index 328c0aea..f74a1a85 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/BunitTest.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/BunitTest.cs @@ -12,7 +12,7 @@ namespace MudExtensions.UnitTests.Components { public abstract class BunitTest { - protected Bunit.TestContext Context { get; private set; } + protected BunitContext Context { get; private set; } [SetUp] public virtual void Setup() diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs index 2f3ed6ec..309f5e24 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs @@ -1,5 +1,5 @@ using Bunit; -using FluentAssertions; +using AwesomeAssertions; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using MudBlazor.Extensions; @@ -13,7 +13,7 @@ public class ChipFieldTests : BunitTest [Test] public async Task ChipFieldBasicTest() { - var comp = Context.RenderComponent>(opt => + var comp = Context.Render>(opt => { opt.Add(a => a.Values, new List { "asdf", "asd" }); }); diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ComboboxTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ComboboxTests.cs index 3db13777..b2110ab8 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ComboboxTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ComboboxTests.cs @@ -4,10 +4,8 @@ using Bunit; using MudExtensions.UnitTests.TestComponents; -using FluentAssertions; +using AwesomeAssertions; using Microsoft.AspNetCore.Components.Web; -using MudExtensions; -using NUnit.Framework; using MudBlazor; using MudExtensions.UnitTests.Extensions; using MudBlazor.Extensions; @@ -26,7 +24,7 @@ public class ComboBoxTests : BunitTest //[TestCase(true)] public void ComboBox_InitialValueTest(bool multiSelection) { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.SelectedValue, "1"); x.Add(c => c.MultiSelection, multiSelection); @@ -45,7 +43,7 @@ public void ComboBox_InitialValueTest(bool multiSelection) [TestCase(true)] public void ComboBox_InitialValuesTest(bool multiSelection) { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.SelectedValues, new HashSet() { "1" }); x.Add(c => c.MultiSelection, multiSelection); @@ -60,19 +58,19 @@ public void ComboBox_InitialValuesTest(bool multiSelection) [Test] public async Task ComboBox_ValueBubblingTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var combobox = comp.FindComponent>(); combobox.Instance.GetState(x => x.Value).Should().BeNull(); combobox.Instance.GetState(x => x.Text).Should().BeNull(); - comp.SetParam("SelectedValue", "1"); + comp.Render(p => p.Add(x => x.SelectedValue, "1")); await comp.InvokeAsync(() => combobox.Instance.ForceUpdate()); comp.WaitForAssertion(() => combobox.Instance.GetState(x => x.Value).Should().Be("1")); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); combobox.Instance.GetState(x => x.Text).Should().Be("1"); - comp.SetParam("SelectedValue", "2"); + comp.Render(p => p.Add(x => x.SelectedValue, "2")); comp.WaitForAssertion(() => combobox.Instance.GetState(x => x.Value).Should().Be("2")); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); await comp.InvokeAsync(() => combobox.Instance.ForceUpdate()); @@ -83,7 +81,7 @@ public async Task ComboBox_ValueBubblingTest() [Test] public void ComboBox_ValueBubblingTest_MultiSelection() { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.MultiSelection, true); }); @@ -92,12 +90,12 @@ public void ComboBox_ValueBubblingTest_MultiSelection() combobox.Instance.GetState(x => x.Value).Should().BeNull(); combobox.Instance.GetState(x => x.Text).Should().BeNullOrEmpty(); - comp.SetParam("SelectedValues", new HashSet() { "1" }); + comp.Render(p => p.Add(x => x.SelectedValues, new HashSet() { "1" })); combobox.Instance.GetState(x => x.Value).Should().Be(null); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); combobox.Instance.GetState(x => x.Text).Should().Be(null); - comp.SetParam("SelectedValues", new HashSet() { "2", "1" }); + comp.Render(p => p.Add(x => x.SelectedValues, new HashSet() { "2", "1" })); combobox.Instance.GetState(x => x.Value).Should().Be(null); combobox.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "2", "1" }); combobox.Instance.GetState(x => x.Text).Should().Be(null); @@ -106,7 +104,7 @@ public void ComboBox_ValueBubblingTest_MultiSelection() [Test] public async Task ComboBox_ValueChangeEventCountTest() { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.MultiSelection, false); }); @@ -116,7 +114,7 @@ public async Task ComboBox_ValueChangeEventCountTest() comp.Instance.ValueChangeCount.Should().Be(0); comp.Instance.ValuesChangeCount.Should().Be(0); - await comp.InvokeAsync(() => combobox.SetParam("Value", "1")); + await comp.InvokeAsync(() => combobox.Render(p => p.Add(x => x.Value, "1"))); await comp.InvokeAsync(() => combobox.Instance.ForceUpdate()); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); @@ -124,7 +122,7 @@ public async Task ComboBox_ValueChangeEventCountTest() // Changing value programmatically without ForceUpdate should change value, but should not fire change events // Its by design, so this part can be change if design changes - await comp.InvokeAsync(() => combobox.SetParam("Value", "2")); + await comp.InvokeAsync(() => combobox.Render(p => p.Add(x => x.Value, "2"))); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); combobox.Instance.GetState(x => x.Value).Should().Be("2"); @@ -133,7 +131,7 @@ public async Task ComboBox_ValueChangeEventCountTest() [Test] public async Task ComboBox_ValueChangeEventCountTest_MultiSelection() { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.MultiSelection, true); }); @@ -142,13 +140,13 @@ public async Task ComboBox_ValueChangeEventCountTest_MultiSelection() comp.Instance.ValueChangeCount.Should().Be(0); comp.Instance.ValuesChangeCount.Should().Be(0); - await comp.InvokeAsync(() => combobox.SetParam("SelectedValues", new HashSet() { "1" })); + await comp.InvokeAsync(() => combobox.Render(p => p.Add(x => x.SelectedValues, new HashSet() { "1" }))); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(0)); comp.WaitForAssertion(() => comp.Instance.ValuesChangeCount.Should().Be(1)); // Setting same value should not fire events - await comp.InvokeAsync(() => combobox.SetParam("SelectedValues", new HashSet() { "1" })); + await comp.InvokeAsync(() => combobox.Render(p => p.Add(x => x.SelectedValues, new HashSet() { "1" }))); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(0)); comp.Instance.ValuesChangeCount.Should().Be(1); } @@ -159,7 +157,7 @@ public async Task ComboBox_ValueChangeEventCountTest_MultiSelection() [Test] public async Task ComboBoxTest1() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // select elements needed for the test @@ -199,7 +197,7 @@ public async Task ComboBoxTest1() [Test] public async Task ComboBoxClearableTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var combobox = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); @@ -225,7 +223,7 @@ public async Task ComboBoxClearableTest() [Test] public void MultiSelect_SelectAll() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // select element needed for the test var combobox = comp.FindComponent>(); var menu = comp.Find("div.mud-popover"); @@ -248,7 +246,7 @@ public void MultiSelect_SelectAll() [Test] public async Task ComboBox_MultiSelectEditable() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html Console.WriteLine(comp.Markup); // select elements needed for the test @@ -278,7 +276,7 @@ public async Task ComboBox_MultiSelectEditable() [Test] public async Task ComboBox_MultiSelectTest1() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html Console.WriteLine(comp.Markup); // select elements needed for the test @@ -336,7 +334,7 @@ await comp.InvokeAsync(() => [Test] public async Task ComboBoxTest_KeyboardNavigation_SingleSelect() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // select elements needed for the test @@ -433,7 +431,7 @@ public async Task ComboBoxTest_KeyboardNavigation_SingleSelect() [Test] public async Task ComboBoxTest_KeyboardNavigation_ToggleSelect() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var combobox = comp.FindComponent>().Instance; combobox.ToggleSelection = true; await comp.InvokeAsync(() => combobox.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); @@ -455,7 +453,7 @@ public async Task ComboBoxTest_KeyboardNavigation_ToggleSelect() [Test] public async Task ComboBoxTest_KeyboardNavigation_MultiSelect() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var combobox = comp.FindComponent>(); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("d-none")); @@ -500,11 +498,11 @@ public async Task ComboBoxTest_KeyboardNavigation_MultiSelect() await comp.InvokeAsync(() => combobox.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => combobox.Instance.SelectedValues.Should().NotContain("Tiger")); - combobox.SetParam("Disabled", true); + await comp.InvokeAsync(() => combobox.Render(p => p.Add(x => x.Disabled, true))); await comp.InvokeAsync(() => combobox.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => combobox.Instance.SelectedValues.Should().NotContain("Tiger")); - combobox.SetParam("Disabled", false); + await comp.InvokeAsync(() => combobox.Render(p => p.Add(x => x.Disabled, false))); //Test the keyup event await comp.InvokeAsync(() => combobox.Instance.HandleKeyUpAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keyup", })); comp.WaitForAssertion(() => combobox.Instance.SelectedValues.Should().NotContain("Tiger")); diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ListExtendedTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ListExtendedTests.cs index bd58d064..515503b3 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ListExtendedTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ListExtendedTests.cs @@ -3,10 +3,9 @@ using Bunit; using MudExtensions.UnitTests.TestComponents; -using FluentAssertions; +using AwesomeAssertions; using Microsoft.AspNetCore.Components.Web; using MudBlazor; -using MudBlazor.Extensions; namespace MudExtensions.UnitTests.Components { @@ -16,7 +15,7 @@ public class ListExtendedTests : BunitTest [Test] public async Task List_EventCountTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var list = comp.FindComponent>().Instance; comp.Instance.ValueChangeCount.Should().Be(0); @@ -107,7 +106,7 @@ public async Task List_EventCountTest() [Test] public async Task ListSelectionTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var list = comp.FindComponent>().Instance; list.SelectedItem.Should().Be(null); @@ -134,7 +133,7 @@ public async Task ListSelectionTest() [Test] public async Task ListMultiSelectionTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var list = comp.FindComponent>().Instance; list.SelectedItem.Should().Be(null); @@ -178,7 +177,7 @@ public async Task ListMultiSelectionTest() [Test] public async Task ListWithPreSelectedValueTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var list = comp.FindComponent>().Instance; comp.WaitForAssertion(() => comp.FindComponents>()[0].Markup.Should().Contain("mud-selected-item")); @@ -218,7 +217,7 @@ public async Task ListWithPreSelectedValueTest() [Test] public async Task List_ProgrammaticallyChangeValueAndItemTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var list = comp.FindComponent>().Instance; comp.WaitForAssertion(() => list.SelectedValue.Should().Be(1)); @@ -256,7 +255,7 @@ public async Task List_ProgrammaticallyChangeValueAndItemTest() [Test] public async Task List_KeyboardNavigationTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var list = comp.FindComponent>().Instance; @@ -331,7 +330,7 @@ public async Task List_KeyboardNavigationTest() [TestCase(Color.Dark)] public void ListColorTest(Color color) { - var comp = Context.RenderComponent(x => x.Add(c => c.Color, color)); + var comp = Context.Render(x => x.Add(c => c.Color, color)); var list = comp.FindComponent>().Instance; list.SelectedItem?.Text.Should().Be("Sparkling Water"); diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/RenderExampleTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/RenderExampleTests.cs index 6a7714d2..e2c848a4 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/RenderExampleTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/RenderExampleTests.cs @@ -1,5 +1,5 @@ using MudExtensions.Docs.Examples; -using FluentAssertions; +using AwesomeAssertions; namespace MudExtensions.UnitTests.Components { @@ -9,21 +9,21 @@ public class RenderExampleTests : BunitTest [Test] public void AnimateExampleRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void AnimateExample2RenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void DateWheelPickerExampleRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } } diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/RenderTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/RenderTests.cs index fa4ceb1c..0f606ccd 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/RenderTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/RenderTests.cs @@ -1,4 +1,4 @@ -using FluentAssertions; +using AwesomeAssertions; using MudExtensions.Docs.Pages; namespace MudExtensions.UnitTests.Components @@ -9,77 +9,77 @@ public class RenderTests : BunitTest [Test] public void ApiPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void AnimatePageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void ComboBoxPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void WheelDatePickerPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void SpeedDialPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void SplitterPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void StepperPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void ListExtendedPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void SelectExtendedPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void TextFieldExtendedPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } [Test] public void TransferListPageRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Markup.Should().NotBeNullOrEmpty(); } } diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs index 3d6ddf26..459a4ba8 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/SelectExtendedTests.cs @@ -4,7 +4,7 @@ using Bunit; using MudExtensions.UnitTests.TestComponents; -using FluentAssertions; +using AwesomeAssertions; using Microsoft.AspNetCore.Components.Web; using MudExtensions; using NUnit.Framework; @@ -24,7 +24,7 @@ public class SelectExtendedTests : BunitTest [Test] public void SelectLabelFor() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var label = comp.FindAll(".mud-input-label"); label[0].Attributes.GetNamedItem("for")?.Value.Should().Be("selectLabelTest"); } @@ -36,7 +36,7 @@ public void SelectLabelFor() //[TestCase(true)] public void Select_InitialValueTest(bool multiSelection) { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.SelectedValue, "1"); x.Add(c => c.MultiSelection, multiSelection); @@ -55,7 +55,7 @@ public void Select_InitialValueTest(bool multiSelection) [TestCase(true)] public void Select_InitialValuesTest(bool multiSelection) { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.SelectedValues, new HashSet() { "1" }); x.Add(c => c.MultiSelection, multiSelection); @@ -70,19 +70,19 @@ public void Select_InitialValuesTest(bool multiSelection) [Test] public async Task Select_ValueBubblingTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>(); select.Instance.GetState(x => x.Value).Should().BeNull(); select.Instance.GetState(x => x.Text).Should().BeNull(); - comp.SetParam("SelectedValue", "1"); + comp.Render(p => p.Add(x => x.SelectedValue, "1")); await comp.InvokeAsync(() => select.Instance.ForceUpdate()); comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("1")); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); select.Instance.GetState(x => x.Text).Should().Be("1"); - comp.SetParam("SelectedValue", "2"); + comp.Render(p => p.Add(x => x.SelectedValue, "2")); await comp.InvokeAsync(() => select.Instance.ForceUpdate()); comp.WaitForAssertion(() => select.Instance.GetState(x => x.Value).Should().Be("2")); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "2" }); @@ -92,7 +92,7 @@ public async Task Select_ValueBubblingTest() [Test] public void Select_ValueBubblingTest_MultiSelection() { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.MultiSelection, true); }); @@ -101,12 +101,12 @@ public void Select_ValueBubblingTest_MultiSelection() select.Instance.GetState(x => x.Value).Should().BeNull(); select.Instance.GetState(x => x.Text).Should().BeNullOrEmpty(); - comp.SetParam("SelectedValues", new HashSet() { "1" }); + comp.Render(p => p.Add(x => x.SelectedValues, new HashSet() { "1" })); select.Instance.GetState(x => x.Value).Should().Be("1"); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "1" }); select.Instance.GetState(x => x.Text).Should().Be("1"); - comp.SetParam("SelectedValues", new HashSet() { "2", "1" }); + comp.Render(p => p.Add(x => x.SelectedValues, new HashSet() { "2", "1" })); select.Instance.GetState(x => x.Value).Should().Be("1"); select.Instance.SelectedValues.Should().BeEquivalentTo(new HashSet() { "2", "1" }); select.Instance.GetState(x => x.Text).Should().Be("2, 1"); @@ -115,7 +115,7 @@ public void Select_ValueBubblingTest_MultiSelection() [Test] public async Task Select_ValueChangeEventCountTest() { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.MultiSelection, false); }); @@ -125,7 +125,7 @@ public async Task Select_ValueChangeEventCountTest() comp.Instance.ValueChangeCount.Should().Be(0); comp.Instance.ValuesChangeCount.Should().Be(0); - await comp.InvokeAsync(() => select.SetParam("Value", "1")); + await comp.InvokeAsync(() => select.Render(p => p.Add(x => x.Value, "1"))); await comp.InvokeAsync(() => select.Instance.ForceUpdate()); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); @@ -133,7 +133,7 @@ public async Task Select_ValueChangeEventCountTest() // Changing value programmatically without ForceUpdate should change value, but should not fire change events // Its by design, so this part can be change if design changes - await comp.InvokeAsync(() => select.SetParam("Value", "2")); + await comp.InvokeAsync(() => select.Render(p => p.Add(x => x.Value, "2"))); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); select.Instance.GetState(x => x.Value).Should().Be("2"); @@ -142,7 +142,7 @@ public async Task Select_ValueChangeEventCountTest() [Test] public async Task Select_ValueChangeEventCountTest_MultiSelection() { - var comp = Context.RenderComponent(x => + var comp = Context.Render(x => { x.Add(c => c.MultiSelection, true); }); @@ -153,12 +153,12 @@ public async Task Select_ValueChangeEventCountTest_MultiSelection() comp.Instance.ItemChangeCount.Should().Be(0); comp.Instance.ItemsChangeCount.Should().Be(0); - await comp.InvokeAsync(() => select.SetParam("SelectedValues", new HashSet() { "1" })); + await comp.InvokeAsync(() => select.Render(p => p.Add(x => x.SelectedValues, new HashSet() { "1" }))); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); // Setting same value should not fire events - await comp.InvokeAsync(() => select.SetParam("SelectedValues", new HashSet() { "1" })); + await comp.InvokeAsync(() => select.Render(p => p.Add(x => x.SelectedValues, new HashSet() { "1" }))); comp.WaitForAssertion(() => comp.Instance.ValueChangeCount.Should().Be(1)); comp.Instance.ValuesChangeCount.Should().Be(1); } @@ -169,7 +169,7 @@ public async Task Select_ValueChangeEventCountTest_MultiSelection() [Test] public async Task SelectTest1() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // select elements needed for the test @@ -214,7 +214,7 @@ public async Task MultiSelectTest1() { //await ImproveChanceOfSuccess(async () => //{ - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html Console.WriteLine(comp.Markup); // select elements needed for the test @@ -278,7 +278,7 @@ await comp.InvokeAsync(() => [Test] public async Task SelectWithEnumTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); // select elements needed for the test var select = comp.FindComponent>(); @@ -304,7 +304,7 @@ public async Task SelectWithEnumTest() [Test] public void SelectUnrepresentableValueTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // select elements needed for the test var select = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); @@ -328,7 +328,7 @@ public void SelectUnrepresentableValueTest() [Test] public void SelectUnrepresentableValueTest2() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); // select elements needed for the test var select = comp.FindComponent>(); @@ -357,7 +357,7 @@ public void SelectUnrepresentableValueTest2() [Test] public void SelectWithoutItemPresentersTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); // select elements needed for the test var select = comp.FindComponent>(); @@ -389,11 +389,11 @@ public void SelectWithoutItemPresentersTest() [Test] public void Select_Should_FireTextChangedWithNewValue() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var select = comp.FindComponent>(); string? text = null; - select.SetCallback(s => s.TextChanged, x => text = x); + select.SetParametersAndRenderAsync(parameters => parameters.Add(s => s.TextChanged, (Action)(x => text = x))); var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state @@ -431,7 +431,7 @@ public void Select_Should_FireTextChangedWithNewValue() [Test] public void SingleSelect_Should_FireTextChangedBeforeSelectedValuesChanged() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var select = comp.FindComponent>(); string? text = null; @@ -439,16 +439,16 @@ public void SingleSelect_Should_FireTextChangedBeforeSelectedValuesChanged() var eventCounter = 0; var textChangedCount = 0; var selectedValuesChangedCount = 0; - select.SetCallback(s => s.TextChanged, x => - { - textChangedCount = eventCounter++; - text = x; - }); - select.SetCallback(s => s.SelectedValuesChanged, x => - { - selectedValuesChangedCount = eventCounter++; - selectedValues = x; - }); + select.SetParametersAndRenderAsync(parameters => parameters.Add(s => s.TextChanged, (Action)(x => + { + textChangedCount = eventCounter++; + text = x; + }))); + select.SetParametersAndRenderAsync(parameters => parameters.Add(s => s.SelectedValuesChanged, (Action>)(x => + { + selectedValuesChangedCount = eventCounter++; + selectedValues = x; + }))); var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state @@ -492,7 +492,7 @@ public void SingleSelect_Should_FireTextChangedBeforeSelectedValuesChanged() [Test] public void MultiSelect_Should_FireTextChangedBeforeSelectedValuesChanged() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var select = comp.FindComponent>(); string? text = null; @@ -500,17 +500,17 @@ public void MultiSelect_Should_FireTextChangedBeforeSelectedValuesChanged() var eventCounter = 0; var textChangedCount = 0; var selectedValuesChangedCount = 0; - select.SetParam(s => s.MultiSelection, true); - select.SetCallback(s => s.TextChanged, x => - { - textChangedCount = eventCounter++; - text = x; - }); - select.SetCallback(s => s.SelectedValuesChanged, x => - { - selectedValuesChangedCount = eventCounter++; - selectedValues = x; - }); + select.Render(p => p.Add(x => x.MultiSelection, true)); + select.SetParametersAndRenderAsync(parameters => parameters.Add(s => s.TextChanged, (Action)(x => + { + textChangedCount = eventCounter++; + text = x; + }))); + select.SetParametersAndRenderAsync(parameters => parameters.Add(s => s.SelectedValuesChanged, (Action>)(x => + { + selectedValuesChangedCount = eventCounter++; + selectedValues = x; + }))); var selectElement = comp.Find("div.mud-input-control"); selectElement.Click(); @@ -539,11 +539,11 @@ public void MultiSelect_Should_FireTextChangedBeforeSelectedValuesChanged() [Test] public async Task Select_Should_Not_FireOnBlur() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var select = comp.FindComponent>(); var eventCounter = 0; - select.SetCallback(s => s.OnBlur, x => eventCounter++); + await select.SetParametersAndRenderAsync(parameters => parameters.Add(s => s.OnBlur, () => eventCounter++)); await comp.InvokeAsync(async () => { await select.Instance.OpenMenu(); @@ -555,7 +555,7 @@ await comp.InvokeAsync(async () => [Test] public void Disabled_SelectItem_Should_Be_Respected() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>(); //Console.WriteLine(comp.Markup); @@ -573,17 +573,18 @@ public async Task MultiSelect_ShouldCallValidationFunc() { //await ImproveChanceOfSuccess(async () => //{ - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // select elements needed for the test var select = comp.FindComponent>(); IEnumerable? validatedValue = null; - select.SetParam(x => x.Validation, new Func(value => - { - validatedValue = select.Instance.SelectedValues; - return true; - })); + select.Render(p => p.Add(x => x.Validation, + new Func(value => + { + validatedValue = select.Instance.SelectedValues; + return true; + }))); var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state @@ -617,15 +618,16 @@ public async Task MultiSelect_ShouldCallValidationFunc() [Test] public void MultiSelect_SelectAll() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // select element needed for the test var select = comp.FindComponent>(); IEnumerable? validatedValue = null; - select.SetParam(x => x.Validation, (object)new Func(value => - { - validatedValue = select.Instance.SelectedValues; // NOTE: select does only update the value for T string - return true; - })); + select.Render(p => p.Add(x => x.Validation, + (object)new Func(value => + { + validatedValue = select.Instance.SelectedValues; // NOTE: select does only update the value for T string + return true; + }))); var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // Open the menu @@ -641,7 +643,7 @@ public void MultiSelect_SelectAll() [Test] public void MultiSelect_SelectAll2() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // select element needed for the test var select = comp.FindComponent>(); var menu = comp.Find("div.mud-popover"); @@ -676,7 +678,7 @@ public void MultiSelect_SelectAll2() [Test] public void MultiSelect_SelectAll3() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // select element needed for the test var select = comp.FindComponent>(); var menu = comp.Find("div.mud-popover"); @@ -692,15 +694,16 @@ public void MultiSelect_SelectAll3() [Test] public void SingleSelect_Should_CallValidationFunc() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var select = comp.FindComponent>(); string? validatedValue = null; - select.SetParam(x => x.Validation, (object)new Func(value => - { - validatedValue = value; // NOTE: select does only update the value for T string - return true; - })); + select.Render(p => p.Add(x => x.Validation, + (object)new Func(value => + { + validatedValue = value; // NOTE: select does only update the value for T string + return true; + }))); var menu = comp.Find("div.mud-popover"); var input = comp.Find("div.mud-input-control"); // check initial state @@ -736,7 +739,7 @@ public void SingleSelect_Should_CallValidationFunc() [Test] public async Task MultiSelect_Initial_Values() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); @@ -750,7 +753,7 @@ public async Task MultiSelect_Initial_Values() [Test] public async Task MultiSelectTextTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>(); await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter" })); @@ -773,7 +776,7 @@ public async Task MultiSelectTextTest() [Test] public async Task MultiSelectCustomizedTextTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // Select the input of the select var input = comp.Find("input"); @@ -788,7 +791,7 @@ public async Task MultiSelectCustomizedTextTest() [Test] public async Task SelectClearableTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); @@ -817,7 +820,7 @@ public async Task SelectClearableTest() [Test] public void SelectReselectTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // select elements needed for the test @@ -854,7 +857,7 @@ public void SelectReselectTest() [Test] public async Task TextField_Should_Validate_Data_Attribute_Fail() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var selectcomp = comp.FindComponent>(); var select = selectcomp.Instance; @@ -873,7 +876,7 @@ public async Task TextField_Should_Validate_Data_Attribute_Fail() [Test] public async Task TextField_Should_Validate_Data_Attribute_Success() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); //Console.WriteLine(comp.Markup); var selectcomp = comp.FindComponent>(); var select = selectcomp.Instance; @@ -894,7 +897,7 @@ public async Task TextField_Should_Validate_Data_Attribute_Success() [Test] public async Task Select_Should_SetRequiredTrue() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>().Instance; select.Required.Should().BeTrue(); await comp.InvokeAsync(() => select.ValidateAsync()); @@ -907,7 +910,7 @@ public async Task Select_Should_SetRequiredTrue() [Test] public async Task Select_Should_HilightSelectedValue() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); var select = comp.FindComponent>(); @@ -932,7 +935,8 @@ public async Task Select_Should_HilightSelectedValue() comp.WaitForAssertion(() => comp.FindAll("div.mud-selected-item").Count.Should().Be(1)); comp.FindAll("div.mud-list-item-extended")[1].ToMarkup().Should().Contain("mud-selected-item"); await comp.InvokeAsync(() => select.Instance.CloseMenu()); - select.SetParam(nameof(MudSelectExtended.Value), null); + //select.SetParam(nameof(MudSelectExtended.Value), null); + select.Render(p => p.Add(x => x.Value, null)); await comp.InvokeAsync(() => select.Instance.OpenMenu()); // no option should be hilited comp.WaitForAssertion(() => comp.FindAll("div.mud-selected-item").Count.Should().Be(0)); @@ -944,7 +948,7 @@ public async Task Select_Should_HilightSelectedValue() [Test] public void Select_Should_HilightInitiallySelectedValue() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); var select = comp.FindComponent>(); @@ -975,7 +979,7 @@ public void Select_Should_HilightInitiallySelectedValue() [Test] public async Task Select_Should_AllowReloadingItems() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>(); // normal, without reloading comp.Find("div.mud-input-control").Click(); @@ -1016,7 +1020,7 @@ public async Task Select_Should_AllowReloadingItems() [Test] public async Task SelectTest_ToggleOpenCloseMenuMethods() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // select elements needed for the test @@ -1026,18 +1030,18 @@ public async Task SelectTest_ToggleOpenCloseMenuMethods() await comp.InvokeAsync(() => select.Instance.ToggleMenu()); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); - select.SetParam("Disabled", true); + select.Render(p => p.Add(x => x.Disabled, true)); await comp.InvokeAsync(() => select.Instance.ToggleMenu()); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().Contain("mud-popover-open")); //Try to add null item and check the value should not changed. await comp.InvokeAsync(() => select.Instance.Add(null)); comp.WaitForAssertion(() => select.Instance._items.Count.Should().Be(4)); - select.SetParam("Disabled", false); + select.Render(p => p.Add(x => x.Disabled, false)); await comp.InvokeAsync(() => select.Instance.ToggleMenu()); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); - select.SetParam("Disabled", true); + select.Render(p => p.Add(x => x.Disabled, true)); await comp.InvokeAsync(() => select.Instance.ToggleMenu()); comp.WaitForAssertion(() => comp.Find("div.mud-popover").ClassList.Should().NotContain("mud-popover-open")); @@ -1048,7 +1052,7 @@ public async Task SelectTest_ToggleOpenCloseMenuMethods() [Test] public async Task SelectTest_KeyboardNavigation_SingleSelect() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // select elements needed for the test @@ -1141,7 +1145,7 @@ public async Task SelectTest_KeyboardNavigation_SingleSelect() [Test] public async Task SelectTest_KeyboardNavigation_MultiSelect() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // select elements needed for the test @@ -1185,11 +1189,11 @@ public async Task SelectTest_KeyboardNavigation_MultiSelect() await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => select.Instance.SelectedValues.Should().Contain("Tiger")); - select.SetParam("Disabled", true); + select.Render(p => p.Add(x => x.Disabled, true)); await comp.InvokeAsync(() => select.Instance.HandleKeyDownAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keydown", })); comp.WaitForAssertion(() => select.Instance.SelectedValues.Should().Contain("Tiger")); - select.SetParam("Disabled", false); + select.Render(p => p.Add(x => x.Disabled, false)); //Test the keyup event await comp.InvokeAsync(() => select.Instance.HandleKeyUpAsync(new KeyboardEventArgs() { Key = "Enter", Type = "keyup", })); comp.WaitForAssertion(() => select.Instance.SelectedValues.Should().Contain("Tiger")); @@ -1203,7 +1207,7 @@ public async Task SelectTest_KeyboardNavigation_MultiSelect() [Test] public async Task SelectTest_ItemlessSelect() { - var comp = Context.RenderComponent>(); + var comp = Context.Render>(); // print the generated html //Console.WriteLine(comp.Markup); @@ -1220,7 +1224,7 @@ public async Task SelectTest_ItemlessSelect() [Test] public void Select_OnCloseValueTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>(); comp.Find("input").Click(); @@ -1242,7 +1246,7 @@ public void Select_OnCloseValueTest() [Test] public void MultiSelectWithCustomComparerTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); // print the generated html //Console.WriteLine(comp.Markup); // Click select button @@ -1266,14 +1270,14 @@ public void MultiSelectWithCustomComparerTest() [Test] public void Select_Item_Collection_Should_Match_Number_Of_Select_Options() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var sut = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); input.Click(); comp.WaitForAssertion(() => comp.FindAll("div.mud-list-item-extended").Count.Should().BeGreaterThan(0)); - sut.Instance.Items.Should().HaveCountGreaterOrEqualTo(4); + sut.Instance.Items.Should().HaveCountGreaterThanOrEqualTo(4); } // TODO: look at this test that failed after #164 @@ -1323,7 +1327,7 @@ public void Select_Item_Collection_Should_Match_Number_Of_Select_Options() [Test] public async Task MultiSelectAttributesOrder() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>().Instance; select.SelectedValues?.Count().Should().Be(2); select.GetState(x => x.Text).Should().Be("Programista, test"); @@ -1338,7 +1342,7 @@ await comp.InvokeAsync(() => [Test] public void Select_Should_NotOpen_WhenDisabled() { - var comp = Context.RenderComponent(parameters => + var comp = Context.Render(parameters => { parameters.Add(p => p.Disabled, true); }); @@ -1355,7 +1359,7 @@ public void Select_Should_NotOpen_WhenDisabled() public void Select_Should_NotOpen_WhenParentDisabled() { // Use a test component that wraps the select in a disabled parent - var comp = Context.RenderComponent(); + var comp = Context.Render(); var select = comp.FindComponent>(); var input = comp.Find("div.mud-input-control"); diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/StepperTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/StepperTests.cs index 19e7052d..ee49e77b 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/StepperTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/StepperTests.cs @@ -1,5 +1,5 @@ using Bunit; -using FluentAssertions; +using AwesomeAssertions; using Microsoft.AspNetCore.Components; using MudBlazor; using MudExtensions; @@ -13,7 +13,7 @@ public class StepperTests : BunitTest [Test] public void StepperRenderTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); comp.Instance.Steps.Count.Should().Be(0); } @@ -22,20 +22,20 @@ public async Task StepperPreventStepChangeDirectionIsForwardWhenCompletingStepOn { // Arrange var lastStepChangeDirection = StepChangeDirection.None; - int _targetIndex = 0; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>((direction, targetIndex) => + var targetIndex = -1; + + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, + new Func>((direction, index) => { lastStepChangeDirection = direction; - _targetIndex = targetIndex; + targetIndex = index; return Task.FromResult(false); - }) - ) + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + Context.Render(parameters => parameters + .AddCascadingValue(stepper.Instance) ); // Act @@ -50,20 +50,20 @@ public async Task StepperPreventStepChangeDirectionIsForwardWhenSkippingStepOneO { // Arrange var lastStepChangeDirection = StepChangeDirection.None; - int _targetIndex = 0; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>((direction, targetIndex) => + var targetIndex = -1; + + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, + new Func>((direction, index) => { lastStepChangeDirection = direction; - _targetIndex = targetIndex; + targetIndex = index; return Task.FromResult(false); - }) - ) + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + Context.Render(parameters => parameters + .AddCascadingValue(stepper.Instance) ); // Act @@ -77,26 +77,24 @@ public async Task StepperPreventStepChangeDirectionIsForwardWhenSkippingStepOneO public async Task StepperPreventStepChangeDirectionIsForwardWhenChangingFromStepOneToStepTwoTest() { var lastStepChangeDirection = StepChangeDirection.None; - int capturedTargetIndex = -1; + var capturedTargetIndex = -1; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>( - (direction, targetIndex) => - { - lastStepChangeDirection = direction; - capturedTargetIndex = targetIndex; - return Task.FromResult(false); - }) - ) + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, + new Func>((direction, targetIndex) => + { + lastStepChangeDirection = direction; + capturedTargetIndex = targetIndex; + return Task.FromResult(false); + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); - var step1 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepByReferenceAsync(step0.Instance); @@ -110,27 +108,24 @@ public async Task StepperPreventStepChangeDirectionIsForwardWhenChangingFromStep public async Task StepperPreventStepChangeDirectionIsBackwardWhenChangingFromStepTwoToStepOneTest() { var lastStepChangeDirection = StepChangeDirection.None; - int capturedTargetIndex = -1; + var capturedTargetIndex = -1; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>( - (direction, targetIndex) => - { - lastStepChangeDirection = direction; - capturedTargetIndex = targetIndex; - return Task.FromResult(false); - }) - ) + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, + new Func>((direction, targetIndex) => + { + lastStepChangeDirection = direction; + capturedTargetIndex = targetIndex; + return Task.FromResult(false); + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); - var step1 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepByReferenceAsync(step1.Instance); @@ -145,20 +140,17 @@ public async Task StepperPreventStepChangeDirectionIsNoneWhenChangingToTheSameSt { var lastStepChangeDirection = StepChangeDirection.None; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>( - (direction, targetIndex) => - { - lastStepChangeDirection = direction; - return Task.FromResult(false); - }) - ) + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, + new Func>((direction, targetIndex) => + { + lastStepChangeDirection = direction; + return Task.FromResult(false); + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepByReferenceAsync(step0.Instance); @@ -172,24 +164,21 @@ public async Task StepperPreventStepChangeIsInvokedWhenCompletingActiveStepTest( { var preventStepChangeWasInvoked = false; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>( - (direction, targetIndex) => - { - preventStepChangeWasInvoked = true; - return Task.FromResult(false); - }) - ) + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, + new Func>((direction, targetIndex) => + { + preventStepChangeWasInvoked = true; + return Task.FromResult(false); + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); - var step1 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepByReferenceAsync(step0.Instance); @@ -203,23 +192,21 @@ public async Task StepperPreventStepChangeIsInvokedWhenSkippingActiveStepTest() { var preventStepChangeWasInvoked = false; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>( - (direction, targetIndex) => - { - preventStepChangeWasInvoked = true; - return Task.FromResult(false); - }) - ) + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, + new Func>((direction, targetIndex) => + { + preventStepChangeWasInvoked = true; + return Task.FromResult(false); + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); - var step1 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepByReferenceAsync(step0.Instance); @@ -233,28 +220,29 @@ public async Task StepperPreventStepChangeIsNotInvokedWhenCompletingNonActiveSte { var preventStepChangeWasInvoked = false; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, new Func>((direction, targetIndex) => { preventStepChangeWasInvoked = true; return Task.FromResult(false); - }) - ) + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.Order), 0) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.Order, 0) ); - var step1 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.Order), 1) + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.Order, 1) ); + // step 0'ı aktif yap (prevent'i bilinçli bypass ediyoruz) await stepper.Instance.GoToStepAsync(0, skipPrevent: true); + + // aktif olmayan step (step1) complete ediliyor await stepper.Instance.CompleteStep(1); preventStepChangeWasInvoked.Should().BeFalse(); @@ -265,30 +253,29 @@ public async Task StepperPreventStepChangeIsNotInvokedWhenSkippingNonActiveStepT { var preventStepChangeWasInvoked = false; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), + var stepper = Context.Render(parameters => parameters + .Add(p => p.PreventStepChangeAsync, new Func>((direction, targetIndex) => { preventStepChangeWasInvoked = true; return Task.FromResult(false); - }) - ) + })) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.Order), 0) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.Order, 0) ); - var step1 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.Order), 1) + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.Order, 1) ); + // Aktif step'i ayarla (prevent'i bypass ederek) await stepper.Instance.GoToStepAsync(0, skipPrevent: true); - int indexOfStep1 = stepper.Instance.Steps.IndexOf(step1.Instance); + var indexOfStep1 = stepper.Instance.Steps.IndexOf(step1.Instance); await stepper.Instance.SkipStep(indexOfStep1); preventStepChangeWasInvoked.Should().BeFalse(); @@ -297,21 +284,21 @@ public async Task StepperPreventStepChangeIsNotInvokedWhenSkippingNonActiveStepT [Test] public async Task StepperActiveIndexIsNotChangedWhenCompletingNonActiveStepTest() { - var stepper = Context.RenderComponent(); + var stepper = Context.Render(); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); - var step1 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepByReferenceAsync(step0.Instance, skipPrevent: true); - int activeBefore = stepper.Instance.ActiveIndex; + var activeBefore = stepper.Instance.ActiveIndex; - int step1Index = stepper.Instance.Steps.IndexOf(step1.Instance); + var step1Index = stepper.Instance.Steps.IndexOf(step1.Instance); await stepper.Instance.CompleteStep(step1Index, moveToNextStep: true); stepper.Instance.ActiveIndex.Should().Be(activeBefore); @@ -320,20 +307,21 @@ public async Task StepperActiveIndexIsNotChangedWhenCompletingNonActiveStepTest( [Test] public async Task StepperActiveIndexIsNotChangedWhenSkippingNonActiveStepTest() { - var stepper = Context.RenderComponent(); + var stepper = Context.Render(); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); - var step1 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepByReferenceAsync(step0.Instance, skipPrevent: true); - int activeBefore = stepper.Instance.ActiveIndex; - int step1Index = stepper.Instance.Steps.IndexOf(step1.Instance); + var activeBefore = stepper.Instance.ActiveIndex; + var step1Index = stepper.Instance.Steps.IndexOf(step1.Instance); + await stepper.Instance.SkipStep(step1Index, moveToNextStep: true); stepper.Instance.ActiveIndex.Should().Be(activeBefore); @@ -342,7 +330,7 @@ public async Task StepperActiveIndexIsNotChangedWhenSkippingNonActiveStepTest() [Test] public async Task StepperCheckChangeCountTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var stepper = comp.FindComponent(); comp.Instance.CheckChangeCount.Should().Be(0); @@ -357,35 +345,42 @@ public async Task StepperCheckChangeCountTest() [Test] public async Task StepperNavigationIsBlockedWhenPreventReturnsTrueTest() { - // Arrange - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>((_, __) => Task.FromResult(true)) - ) + var stepper = Context.Render(p => p + .Add(s => s.PreventStepChangeAsync, + new Func>((_, __) => Task.FromResult(true))) ); - var step0 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); - var step1 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); await stepper.Instance.GoToStepAsync(0); await stepper.Instance.GoToStepAsync(1); - stepper.Instance.ActiveIndex.Should().Be(stepper.Instance.Steps.IndexOf(step0.Instance)); + stepper.Instance.ActiveIndex + .Should() + .Be(stepper.Instance.Steps.IndexOf(step0.Instance)); } [Test] public async Task StepperGoNextIsBlockedWhenPreventReturnsTrueTest() { - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), - new Func>((_, __) => Task.FromResult(true)) - ) + var stepper = Context.Render(p => p + .Add(s => s.PreventStepChangeAsync, + new Func>((_, __) => Task.FromResult(true))) ); - var step0 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); - var step1 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); await stepper.Instance.GoToStepAsync(0); await stepper.Instance.GoNextStepAsync(); @@ -396,13 +391,19 @@ public async Task StepperGoNextIsBlockedWhenPreventReturnsTrueTest() [Test] public async Task StepperNavigatesToResultStepWhenAllStepsCompletedTest() { - var stepper = Context.RenderComponent(); + var stepper = Context.Render(); + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); - var step0 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); - var step1 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); - var resultStep = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter("IsResultStep", true) + var resultStep = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.IsResultStep, true) ); await stepper.Instance.GoToStepAsync(0); @@ -418,19 +419,22 @@ public async Task StepperCallsBeforeFinishedWhenCompletingLastRemainingStepTest( { bool beforeCalled = false; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.BeforeFinishedAsync), + var stepper = Context.Render(p => p + .Add(s => s.BeforeFinishedAsync, new Func>(() => { beforeCalled = true; return Task.FromResult(true); - }) - ) + })) ); - var step0 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); - var step1 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); await stepper.Instance.GoToStepAsync(0); await stepper.Instance.CompleteStep(0); @@ -442,18 +446,20 @@ public async Task StepperCallsBeforeFinishedWhenCompletingLastRemainingStepTest( [Test] public async Task StepperCallsOnFinishedWhenCompletingLastRemainingStepTest() { - // Arrange bool finishedCalled = false; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.OnFinished), - EventCallback.Factory.Create(this, () => finishedCalled = true) - ) + var stepper = Context.Render(p => p + .Add(s => s.OnFinished, + EventCallback.Factory.Create(this, () => finishedCalled = true)) ); - var step0 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); - var step1 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); await stepper.Instance.GoToStepAsync(0); await stepper.Instance.CompleteStep(0); @@ -467,19 +473,22 @@ public async Task StepperGoByIndexComputesDirectionCorrectlyTest() { StepChangeDirection? captured = null; - var stepper = Context.RenderComponent( - ComponentParameterFactory.Parameter( - nameof(MudStepperExtended.PreventStepChangeAsync), + var stepper = Context.Render(p => p + .Add(s => s.PreventStepChangeAsync, new Func>((dir, _) => { captured = dir; return Task.FromResult(false); - }) - ) + })) ); - var step0 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); - var step1 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); await stepper.Instance.GoToStepAsync(0); await stepper.Instance.GoByIndexAsync(1); @@ -490,9 +499,15 @@ public async Task StepperGoByIndexComputesDirectionCorrectlyTest() [Test] public async Task StepperSetsStatusContinuedWhenNavigatingToUnstartedStepTest() { - var stepper = Context.RenderComponent(); - var step0 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); - var step1 = Context.RenderComponent(ComponentParameterFactory.CascadingValue(stepper.Instance)); + var stepper = Context.Render(); + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); + + var step1 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + ); await stepper.Instance.GoToStepAsync(0); await stepper.Instance.GoToStepAsync(1); @@ -503,13 +518,15 @@ public async Task StepperSetsStatusContinuedWhenNavigatingToUnstartedStepTest() [Test] public async Task StepperGoesToIntroStepWhenIntroExists() { - var stepper = Context.RenderComponent(); - var intro = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.IsIntroStep), true) + var stepper = Context.Render(); + + var intro = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.IsIntroStep, true) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepAsync(-1); @@ -520,9 +537,10 @@ public async Task StepperGoesToIntroStepWhenIntroExists() [Test] public async Task StepperNegativeIndexGoesToZeroWhenNoIntroStepExists() { - var stepper = Context.RenderComponent(); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + var stepper = Context.Render(); + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepAsync(-1); @@ -533,13 +551,15 @@ public async Task StepperNegativeIndexGoesToZeroWhenNoIntroStepExists() [Test] public async Task StepperResetReturnsToIntroStep() { - var stepper = Context.RenderComponent(); - var intro = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.IsIntroStep), true) + var stepper = Context.Render(); + + var intro = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.IsIntroStep, true) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepAsync(0); @@ -551,17 +571,18 @@ public async Task StepperResetReturnsToIntroStep() [Test] public async Task StepperNextFromIntroGoesToFirstStep() { - var stepper = Context.RenderComponent(); - var intro = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.IsIntroStep), true) + var stepper = Context.Render(); + + var intro = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.IsIntroStep, true) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepAsync(-1); - await stepper.Instance.GoNextStepAsync(true); stepper.Instance.ActiveIndex.Should().Be(0); @@ -570,13 +591,15 @@ public async Task StepperNextFromIntroGoesToFirstStep() [Test] public async Task StepperPreviousFromFirstStepGoesToIntroWhenExists() { - var stepper = Context.RenderComponent(); - var intro = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.IsIntroStep), true) + var stepper = Context.Render(); + + var intro = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.IsIntroStep, true) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepAsync(0); @@ -588,13 +611,15 @@ public async Task StepperPreviousFromFirstStepGoesToIntroWhenExists() [Test] public async Task StepperCannotSkipIntroStep() { - var stepper = Context.RenderComponent(); - var intro = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.IsIntroStep), true) + var stepper = Context.Render(); + + var intro = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.IsIntroStep, true) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); await stepper.Instance.GoToStepAsync(-1); @@ -607,22 +632,28 @@ public async Task StepperCannotSkipIntroStep() [Test] public async Task StepperIntroThenResultStepFlowIsCorrect() { - var stepper = Context.RenderComponent(); - var intro = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.IsIntroStep), true) + var stepper = Context.Render(); + + var intro = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.IsIntroStep, true) ); - var step0 = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance) + + var step0 = Context.Render(p => p + .AddCascadingValue(stepper.Instance) ); - var result = Context.RenderComponent( - ComponentParameterFactory.CascadingValue(stepper.Instance), - ComponentParameterFactory.Parameter(nameof(MudStepExtended.IsResultStep), true) + + var result = Context.Render(p => p + .AddCascadingValue(stepper.Instance) + .Add(s => s.IsResultStep, true) ); await stepper.Instance.GoToStepAsync(-1); await stepper.Instance.GoNextStepAsync(true); - await stepper.Instance.CompleteStep(stepper.Instance.Steps.IndexOf(step0.Instance), true); + await stepper.Instance.CompleteStep( + stepper.Instance.Steps.IndexOf(step0.Instance), + moveToNextStep: true + ); stepper.Instance.ActiveIndex.Should().Be(1); } diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/TransferListTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/TransferListTests.cs index f0a5ddad..ea3ad074 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/TransferListTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/TransferListTests.cs @@ -1,5 +1,5 @@ using Bunit; -using FluentAssertions; +using AwesomeAssertions; using MudExtensions.UnitTests.TestComponents; namespace MudExtensions.UnitTests.Components @@ -10,7 +10,7 @@ public class TransferListTests : BunitTest [Test] public async Task TransferListTransferAllTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var transferList = comp.FindComponent>(); transferList.Instance.StartCollection.Should().Contain("Turkey"); transferList.Instance.StartCollection.Should().NotContain("China"); diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/WatchTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/WatchTests.cs index d129f062..88a39eb4 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/WatchTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/WatchTests.cs @@ -1,5 +1,5 @@ using Bunit; -using FluentAssertions; +using AwesomeAssertions; using MudExtensions.UnitTests.TestComponents; namespace MudExtensions.UnitTests.Components @@ -10,7 +10,7 @@ public class WatchTests : BunitTest [Test] public void WatchInitialValueTest() { - var comp = Context.RenderComponent(); + var comp = Context.Render(); var watch = comp.FindComponent(); watch.Instance.Value.Should().Be(new TimeSpan(1, 0, 0)); } diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Extensions/IRenderedComponentExtensions.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Extensions/IRenderedComponentExtensions.cs index 9cb0798c..6015c6f8 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Extensions/IRenderedComponentExtensions.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Extensions/IRenderedComponentExtensions.cs @@ -1,46 +1,154 @@  #pragma warning disable 8632 -using System; -using System.Linq.Expressions; using Bunit; +using Bunit.Rendering; using Microsoft.AspNetCore.Components; +using Microsoft.Extensions.DependencyInjection; +using System.Linq.Expressions; +using System.Reflection; +using System.Collections; +using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; namespace MudExtensions.UnitTests.Extensions { public static class IRenderedComponentExtensions { - public static void SetParam(this IRenderedComponentBase self, string name, object value) where T : IComponent + /// + /// Render the component under test again with the provided . + /// + /// The rendered component to re-render with new parameters. + /// Parameters to pass to the component upon rendered. + /// The type of the component. + public static async Task SetParametersAndRenderAsync(this IRenderedComponent renderedComponent, ParameterView parameters) + where TComponent : IComponent { - self.SetParametersAndRender(ComponentParameter.CreateParameter(name, value)); + ArgumentNullException.ThrowIfNull(renderedComponent); + + var renderer = renderedComponent.Services.GetRequiredService().Renderer; + + try + { + await BunitRendererAccessors.SetDirectParametersAsync(renderer, renderedComponent, parameters); + } + catch (AggregateException e) when (e.InnerExceptions.Count == 1) + { + ExceptionDispatchInfo.Capture(e.InnerExceptions[0]).Throw(); + } } - public static void SetParam(this IRenderedComponentBase self, Expression> exp, object value) where T : IComponent + /// + /// Render the component under test again with the provided parameters from the . + /// + /// The rendered component to re-render with new parameters. + /// An action that receives a . + /// The type of the component. + public static Task SetParametersAndRenderAsync(this IRenderedComponent renderedComponent, Action> parameterBuilder) + where TComponent : IComponent { - var name = (exp.Body as MemberExpression ?? (MemberExpression)((UnaryExpression)exp.Body).Operand).Member.Name; - self.SetParametersAndRender(ComponentParameter.CreateParameter(name, value)); + var builder = new ComponentParameterCollectionBuilder(parameterBuilder); + var parameters = ComponentParameterCollectionBuilderAccessors.Build(builder); + + var parameterView = ToParameterView(parameters); + + return renderedComponent.SetParametersAndRenderAsync(parameterView); + } + + private static ParameterView ToParameterView(object parameters) + { + var parameterView = ParameterView.Empty; + + if (ComponentParameterCollectionAccessors.GetCount(parameters) > 0) + { + var paramDict = new Dictionary(StringComparer.Ordinal); + + var enumerator = ComponentParameterCollectionAccessors.GetEnumerator(parameters); + while (enumerator.MoveNext()) + { + var param = enumerator.Current; + if (param is null) + continue; + + if (ComponentParameterRefAccessors.GetIsCascadingValue(param)) + throw new InvalidOperationException("Cannot provide cascading values here."); + + var name = ComponentParameterRefAccessors.GetName(param); + if (name is null) + throw new InvalidOperationException("Parameter name is required."); + + var value = ComponentParameterRefAccessors.GetValue(param); + paramDict.Add(name, value); + } + + parameterView = ParameterView.FromDictionary(paramDict); + } + + return parameterView; } - public static void SetCascadingValue(this IRenderedComponentBase self, Expression> exp, object value) where T : IComponent + private static class ComponentParameterCollectionBuilderAccessors where TComponent : IComponent { - var name = (exp.Body as MemberExpression ?? (MemberExpression)((UnaryExpression)exp.Body).Operand).Member.Name; - self.SetParametersAndRender(ComponentParameter.CreateCascadingValue(name, value)); + // Accessors for Build (internal method) + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "Build")] + [return: UnsafeAccessorType("Bunit.ComponentParameterCollection, bunit")] + public static extern object Build(ComponentParameterCollectionBuilder builder); } - public static void SetCascadingValue(this IRenderedComponentBase self, string name, object value) where T : IComponent + // Accessors for ComponentParameterCollection (internal type) + private static class ComponentParameterCollectionAccessors { - self.SetParametersAndRender(ComponentParameter.CreateCascadingValue(name, value)); + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "System.Collections.IEnumerable.GetEnumerator")] + public static extern IEnumerator GetEnumerator([UnsafeAccessorType("Bunit.ComponentParameterCollection, bunit")] object collection); + + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_Count")] + public static extern int GetCount([UnsafeAccessorType("Bunit.ComponentParameterCollection, bunit")] object collection); } - public static void SetCallback(this IRenderedComponentBase self, string name, Action callback) where T : IComponent + private static class BunitRendererAccessors { - self.SetParametersAndRender(ComponentParameter.CreateParameter(name, new EventCallback(null, callback))); + [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "SetDirectParametersAsync")] + public static extern Task SetDirectParametersAsync(BunitRenderer renderer, IRenderedComponent renderedComponent, ParameterView parameters) where TComponent : IComponent; } - public static void SetCallback(this IRenderedComponentBase self, Expression>> exp, Action callback) where T : IComponent + private static class ComponentParameterRefAccessors { - var name = (exp.Body as MemberExpression ?? (MemberExpression)((UnaryExpression)exp.Body).Operand).Member.Name; - self.SetParametersAndRender(ComponentParameter.CreateParameter(name, new EventCallback(null, callback))); + private static readonly Type _componentParameterType = Type.GetType("Bunit.ComponentParameter, bunit", throwOnError: true)!; + + public static readonly Func GetName; + public static readonly Func GetValue; + public static readonly Func GetIsCascadingValue; + + static ComponentParameterRefAccessors() + { + var nameProp = _componentParameterType.GetProperty("Name", BindingFlags.Instance | BindingFlags.Public); + var valueProp = _componentParameterType.GetProperty("Value", BindingFlags.Instance | BindingFlags.Public); + var isCascadingProp = _componentParameterType.GetProperty("IsCascadingValue", BindingFlags.Instance | BindingFlags.Public); + + GetName = BuildGetter(nameProp); + GetValue = BuildGetter(valueProp); + GetIsCascadingValue = BuildGetter(isCascadingProp); + } + + private static Func BuildGetter(PropertyInfo? property) + { + ArgumentNullException.ThrowIfNull(property); + var objParam = Expression.Parameter(typeof(object), "obj"); + + // Convert object -> actual struct type + var typed = Expression.Convert(objParam, _componentParameterType); + + // Access property + var propertyAccess = Expression.Property(typed, property); + + // Convert return type if necessary + var converted = Expression.Convert(propertyAccess, typeof(T)); + + // Compile lambda: (object obj) => ((ComponentParameter)obj).Property + var lambda = Expression.Lambda>(converted, objParam); + return lambda.Compile(); + } } } + } diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Extensions/NodePrintExtensions.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Extensions/NodePrintExtensions.cs new file mode 100644 index 00000000..8adb720f --- /dev/null +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Extensions/NodePrintExtensions.cs @@ -0,0 +1,65 @@ +using AngleSharp; +using AngleSharp.Dom; +using AngleSharp.Html; + +namespace MudExtensions.UnitTests.Extensions +{ + internal static class NodePrintExtensions + { + /// + /// Writes the serialization of the node guided by the formatter. + /// + /// The nodes to serialize. + /// The output target of the serialization. + /// The formatter to use. + public static void ToHtml(this IEnumerable nodes, TextWriter writer, IMarkupFormatter formatter) + { + ArgumentNullException.ThrowIfNull(nodes); + + foreach (var node in nodes) + { + node.ToHtml(writer, formatter); + } + } + + /// + /// Uses the to generate a HTML markup string + /// from a . + /// + public static string ToMarkup(this IEnumerable nodes) + { + ArgumentNullException.ThrowIfNull(nodes); + using var sw = new StringWriter(); + var formatter = new PrettyMarkupFormatter + { + NewLine = Environment.NewLine, + + Indentation = " ", + }; + + nodes.ToHtml(sw, formatter); + + return sw.ToString(); + } + + /// + /// Uses the to generate a HTML markup + /// from a . + /// + public static string ToMarkup(this IMarkupFormattable markupFormattable) + { + ArgumentNullException.ThrowIfNull(markupFormattable); + using var sw = new StringWriter(); + + var formatter = new PrettyMarkupFormatter + { + NewLine = Environment.NewLine, + Indentation = " ", + }; + + markupFormattable.ToHtml(sw, formatter); + + return sw.ToString(); + } + } +} From 36c2306ed5a48943d30a9e0bc3ccf4f684f89f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Wed, 24 Dec 2025 20:31:34 +0300 Subject: [PATCH 5/9] Fix ChipField Test --- .../wwwroot/CodeBeam.MudBlazor.Extensions.xml | 13 +- .../Components/ChipFieldTests.cs | 2 +- .../Base/MudBaseInputExtended.cs | 46 +++++-- .../Components/ChipField/MudChipField.razor | 1 + .../ChipField/MudChipField.razor.cs | 125 ++++++++++++++---- .../InputExtended/MudInputExtended.razor | 3 + .../InputExtended/MudInputExtended.razor.cs | 13 +- .../SelectExtended/MudSelectExtended.razor.cs | 28 ++-- .../MudTextFieldExtended.razor | 5 +- .../TScripts/MudExtensions.js | 18 +++ .../Utilities/MudBeforeInputEventArgs.cs | 35 +++++ .../Utilities/MudBeforeInputJsDto.cs | 9 ++ .../wwwroot/MudExtensions.min.js | 2 +- 13 files changed, 230 insertions(+), 70 deletions(-) create mode 100644 CodeBeam.MudBlazor.Extensions/Utilities/MudBeforeInputEventArgs.cs create mode 100644 CodeBeam.MudBlazor.Extensions/Utilities/MudBeforeInputJsDto.cs diff --git a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml index f66c7e74..b85b9271 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml +++ b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml @@ -4164,19 +4164,18 @@ - + - Fixes issue #4328 - Returns true when MultiSelection is true and it has selected values(Since Value property is not used when MultiSelection=true + - - True when component has a value + + - + - + diff --git a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs index 309f5e24..77f8b43f 100644 --- a/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs +++ b/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ChipFieldTests.cs @@ -19,7 +19,7 @@ public async Task ChipFieldBasicTest() }); var field = comp.FindComponent>(); field.Find("input").Input(new ChangeEventArgs() { Value = "sdfg" }); - await comp.InvokeAsync(() => comp.Instance.HandleKeyDown(new KeyboardEventArgs() { Key = " " })); + await comp.InvokeAsync(() => comp.Instance.HandleBeforeInput(new MudBeforeInputEventArgs() { Data = " ", InputType = "insert" })); comp.Instance.Values.Should().BeEquivalentTo(new List { "asdf", "asd", "sdfg" }); comp.Instance.GetState(x => x.Value).Should().BeEquivalentTo(null); } diff --git a/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs b/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs index 8f3601ff..3013ed1e 100644 --- a/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs +++ b/CodeBeam.MudBlazor.Extensions/Base/MudBaseInputExtended.cs @@ -1,8 +1,7 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; +using Microsoft.JSInterop; using MudBlazor; -using MudBlazor.State; -using MudBlazor.Utilities; using MudExtensions.Base; namespace MudExtensions @@ -21,11 +20,11 @@ public abstract class MudBaseInputExtended : MudBaseInput /// protected MudBaseInputExtended() { - //Converter = new DefaultConverter - //{ - // Culture = GetCulture, - // Format = GetFormat - //}; + Converter = new DefaultConverter + { + Culture = GetCulture, + Format = GetFormat + }; //using var registerScope = CreateRegisterScope(); //_textState = registerScope.RegisterParameter(nameof(Text)) @@ -56,6 +55,9 @@ protected MudBaseInputExtended() /// [Parameter] public EventCallback OnChange { get; set; } + [Parameter] + public EventCallback OnBeforeInput { get; set; } + /// /// Gets or sets a value indicating whether the component has an adornment at the start. /// @@ -89,6 +91,15 @@ protected MudBaseInputExtended() [Category(CategoryTypes.FormComponent.Behavior)] public bool DisablePaste { get; set; } + protected async Task InvokeBeforeInputAsync(MudBeforeInputEventArgs args) + { + _isFocused = true; + await OnBeforeInputAsync(args); + + if (OnBeforeInput.HasDelegate) + await OnBeforeInput.InvokeAsync(args); + } + /// /// @@ -116,13 +127,22 @@ protected override async Task OnConverterChangedAsync() /// protected string? ResolveAriaDescribedBy() => GetAriaDescribedByString(); - } - - internal static class ParameterViewExtensions - { - public static bool Contains(this ParameterView view, string parameterName) + [JSInvokable("OnBeforeInput")] + public async Task OnBeforeInputFromJs(MudBeforeInputJsDto dto) { - return view.TryGetValue(parameterName, out var _); + var args = new MudBeforeInputEventArgs + { + Data = dto.Data, + InputType = dto.InputType, + IsComposing = dto.IsComposing + }; + + await InvokeBeforeInputAsync(args); + return args.PreventDefault; } + + protected virtual Task OnBeforeInputAsync(MudBeforeInputEventArgs args) => Task.CompletedTask; + + } } diff --git a/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor b/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor index 3bf14e42..f15417c2 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor @@ -7,6 +7,7 @@ Immediate="true" OnKeyDown="HandleKeyDown" OnKeyUp="HandleKeyUp" + OnBeforeInput="@HandleBeforeInput" OnBlur="@(async() => await OnBlur.InvokeAsync())" OnClearButtonClick="@(async() => await OnClearButtonClick.InvokeAsync())" OnDebounceIntervalElapsed="@(async() => await OnDebounceIntervalElapsed.InvokeAsync())" diff --git a/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor.cs index ece33ee1..1a709c8d 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/ChipField/MudChipField.razor.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using MudBlazor; +using MudBlazor.State; using MudBlazor.Utilities; namespace MudExtensions @@ -11,6 +12,16 @@ namespace MudExtensions /// public partial class MudChipField : MudTextFieldExtended { + public MudChipField() + { + using var registerScope = CreateRegisterScope(); + _valuesState = registerScope.RegisterParameter?>(nameof(Values)) + .WithParameter(() => Values) + .WithEventCallback(() => ValuesChanged); + } + + private readonly ParameterState?> _valuesState; + /// /// Protected classes. /// @@ -41,7 +52,7 @@ public partial class MudChipField : MudTextFieldExtended /// Fires when values changed /// [Parameter] - public EventCallback> ValuesChanged { get; set; } + public EventCallback?> ValuesChanged { get; set; } /// /// If false, pressing delimeter key has no effect if the value is already in values. Default is false. @@ -122,28 +133,28 @@ public partial class MudChipField : MudTextFieldExtended /// protected internal async Task HandleKeyDown(KeyboardEventArgs args) { - var result = args.Key; - if (result.Equals(Delimiter, StringComparison.InvariantCultureIgnoreCase) && _internalValue != null) - { - if (AllowSameValues == false && Values?.Contains(base.ConvertSet(_internalValue) ?? string.Empty) == true) - { - await Task.Delay(10); - _internalValue = base.ConvertGet(base.ConvertSet(_internalValue)?.Replace(result, null).ToString()); - await SetValueAsync(_internalValue); - StateHasChanged(); - return; - } - await SetChips(); - StateHasChanged(); - } + //var result = args.Key; + //if (result.Equals(Delimiter, StringComparison.InvariantCultureIgnoreCase) && _internalValue != null) + //{ + // if (AllowSameValues == false && _valuesState.Value?.Contains(base.ConvertSet(_internalValue) ?? string.Empty) == true) + // { + // await Task.Delay(10); + // _internalValue = base.ConvertGet(base.ConvertSet(_internalValue)?.Replace(result, null).ToString()); + // await SetValueAsync(_internalValue); + // StateHasChanged(); + // return; + // } + // await SetChips(); + // StateHasChanged(); + //} - if (args.Key == "Backspace" && string.IsNullOrEmpty(base.ConvertSet(_internalValue)) && Values != null && Values.Any() && BackspaceChipRemoval == true) - { - Values.RemoveAt(Values.Count - 1); - await ValuesChanged.InvokeAsync(Values); - } - await Task.Delay(10); - await SetValueAsync(_internalValue); + //if (args.Key == "Backspace" && string.IsNullOrEmpty(base.ConvertSet(_internalValue)) && _valuesState.Value != null && _valuesState.Value.Any() && BackspaceChipRemoval == true) + //{ + // _valuesState.Value.RemoveAt(_valuesState.Value.Count - 1); + // await ValuesChanged.InvokeAsync(_valuesState.Value); + //} + //await Task.Delay(10); + //await SetValueAsync(_internalValue); await OnKeyDown.InvokeAsync(args); } @@ -157,6 +168,62 @@ protected async Task HandleKeyUp(KeyboardEventArgs args) await OnKeyUp.InvokeAsync(args); } + protected internal async Task HandleBeforeInput(MudBeforeInputEventArgs args) + { + if (args.IsComposing) + { + return; + } + + if (args.IsInsert && args.Data == Delimiter && _internalValue is not null) + { + args.PreventDefault = true; + var currentText = base.ConvertSet(_internalValue); + + if (!string.IsNullOrEmpty(currentText)) + { + if (!AllowSameValues && _valuesState.Value?.Contains(currentText) == true) + { + return; + } + + await SetChips(); + } + return; + } + + if (args.IsDeleteBackward && string.IsNullOrEmpty(base.ConvertSet(_internalValue)) && _valuesState.Value is { Count: > 0 } && BackspaceChipRemoval) + { + args.PreventDefault = true; + + _valuesState.Value.RemoveAt(_valuesState.Value.Count - 1); + await ValuesChanged.InvokeAsync(_valuesState.Value); + + return; + } + + if (args.IsPaste && !string.IsNullOrEmpty(args.Data)) + { + args.PreventDefault = true; + + var parts = args.Data + .Split(Delimiter, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + if (_valuesState.Value == null) + await _valuesState.SetValueAsync(new List()); + + foreach (var part in parts) + { + if (AllowSameValues || !_valuesState.Value.Contains(part)) + { + _valuesState.Value.Add(part); + } + } + + await ValuesChanged.InvokeAsync(_valuesState.Value); + } + } + /// /// /// @@ -168,12 +235,12 @@ protected async Task SetChips() return; } - if (Values == null) + if (_valuesState.Value == null) { - Values = new(); + await _valuesState.SetValueAsync(new List()); } - Values.Add(base.ConvertSet(_internalValue) ?? ""); - await ValuesChanged.InvokeAsync(Values); + _valuesState.Value.Add(base.ConvertSet(_internalValue) ?? ""); + await ValuesChanged.InvokeAsync(_valuesState.Value); if (RuntimeLocation.IsServerSide) { await _textFieldExtendedReference.BlurAsync(); @@ -183,6 +250,8 @@ protected async Task SetChips() await Task.Delay((int)DebounceInterval + 10); } await _textFieldExtendedReference.Clear(); + _internalValue = default; + await _textFieldExtendedReference.ValueChanged.InvokeAsync(_internalValue); if (RuntimeLocation.IsServerSide) { await _textFieldExtendedReference.FocusAsync(); @@ -200,8 +269,8 @@ public async Task Closed(MudChip chip) { return; } - Values?.Remove(chip.Text ?? ""); - await ValuesChanged.InvokeAsync(Values); + _valuesState.Value?.Remove(chip.Text ?? ""); + await ValuesChanged.InvokeAsync(_valuesState.Value); await _textFieldExtendedReference.FocusAsync(); } diff --git a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor index a8d99f72..607837fd 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor @@ -30,6 +30,7 @@ @onblur="@OnBlurredAsync" @onkeydown="@InvokeKeyDownAsync" @onkeyup="@InvokeKeyUpAsync" + @onbeforeinput="@InvokeBeforeInputAsync" @onpaste="@OnPaste" maxlength="@MaxLength" @onkeydown:preventDefault="@KeyDownPreventDefault" @@ -72,6 +73,7 @@ pattern="@Pattern" @onkeydown="@InvokeKeyDownAsync" @onkeyup="@InvokeKeyUpAsync" + @onbeforeinput="@InvokeBeforeInputAsync" maxlength="@MaxLength" @onkeydown:preventDefault="KeyDownPreventDefault" @onkeyup:preventDefault="@KeyUpPreventDefault" @@ -99,6 +101,7 @@ pattern="@Pattern" @onkeydown="@InvokeKeyDownAsync" @onkeyup="@InvokeKeyUpAsync" + @onbeforeinput="@InvokeBeforeInputAsync" maxlength="@MaxLength" @onkeydown:preventDefault="KeyDownPreventDefault" @onkeyup:preventDefault="@KeyUpPreventDefault" diff --git a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor.cs index fa6ce985..14e201fd 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/InputExtended/MudInputExtended.razor.cs @@ -12,7 +12,7 @@ namespace MudExtensions /// public partial class MudInputExtended : MudBaseInputExtended { - [Inject] IJSRuntime? JSRuntime { get; set; } + [Inject] IJSRuntime JSRuntime { get; set; } = null!; /// /// @@ -70,6 +70,9 @@ public partial class MudInputExtended : MudBaseInputExtended .AddClass("d-none", !(InputType == InputType.Hidden && ChildContent != null && ShowVisualiser == false)) .Build(); + private bool _beforeInputAttached; + private DotNetObjectReference>? _dotNetRef; + /// /// /// @@ -88,6 +91,14 @@ protected override async Task OnAfterRenderAsync(bool firstRender) } StateHasChanged(); } + + if (!_beforeInputAttached) + { + _beforeInputAttached = true; + _dotNetRef = DotNetObjectReference.Create(this); + + await JSRuntime.InvokeVoidAsync("mudBeforeInput.attach", ElementReference, _dotNetRef); + } } } diff --git a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor.cs b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor.cs index 09a1c3c0..80a48962 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor.cs +++ b/CodeBeam.MudBlazor.Extensions/Components/SelectExtended/MudSelectExtended.razor.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using MudBlazor; +using MudBlazor.Extensions; using MudBlazor.Services; using MudBlazor.State; using MudBlazor.Utilities; @@ -811,7 +812,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) await UpdateTextPropertyAsync(false); _list?.ForceUpdateItems(); - SelectedListItem = Items.FirstOrDefault(x => x.Value != null && Value != null && x.Value.Equals(ReadValue))?.ListItem; + SelectedListItem = Items.FirstOrDefault(x => x.Value != null && ReadValue != null && x.Value.Equals(ReadValue))?.ListItem; StateHasChanged(); } //Console.WriteLine("Select rendered"); @@ -1064,7 +1065,7 @@ public async Task SelectOption(int index) await CloseMenu(); return; } - await SelectOption(_items[index].Value); + await SelectOption(_items[index].GetState(x => x.Value)); } /// @@ -1283,20 +1284,6 @@ public void CheckGenericTypeMatch(object select_item) throw new GenericTypeMismatchException("MudSelectExtended", "MudSelectItemExtended", typeof(T), itemT); } - /// - /// Fixes issue #4328 - /// Returns true when MultiSelection is true and it has selected values(Since Value property is not used when MultiSelection=true - /// - /// - /// True when component has a value - protected override bool HasValue(T? value) - { - if (MultiSelection) - return SelectedValues?.Count() > 0; - else - return base.HasValue(value); - } - /// /// /// @@ -1312,7 +1299,14 @@ protected async Task ChipClosed(MudChip? chip) SelectedValues = SelectedValues.Where(x => x?.Equals(chip.Value) == false); await SelectedValuesChanged.InvokeAsync(SelectedValues); } - + + /// + /// + /// + /// + /// + protected override bool HasValue(T? value) => MultiSelection ? SelectedValues?.Any() == true : base.HasValue(value); + /// /// returns the value of the internal property _isOpen /// diff --git a/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor b/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor index c8f239b4..2d0e9e79 100644 --- a/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor +++ b/CodeBeam.MudBlazor.Extensions/Components/TextFieldExtended/MudTextFieldExtended.razor @@ -16,7 +16,7 @@ Disabled="@Disabled" Margin="@Margin" Required="@Required" - ForId="@FieldId"> + ForId="@InputElementId"> @if (_mask == null) @@ -32,7 +32,7 @@ Variant="@Variant" HasAdornmentStart="@((AdornmentStart != null))" Value="@ReadText" - ValueChanged="(s) => SetTextAsync(s)" + ValueChanged="(s) => SetTextAndUpdateValueAsync(s)" Placeholder="@Placeholder" Disabled="@GetDisabledState()" Underline="@Underline" @@ -48,6 +48,7 @@ OnKeyDown="@InvokeKeyDownAsync" OnInternalInputChanged="OnChanged" OnKeyUp="@InvokeKeyUpAsync" + OnBeforeInput="@InvokeBeforeInputAsync" KeyDownPreventDefault="KeyDownPreventDefault" KeyUpPreventDefault="KeyUpPreventDefault" HideSpinButtons="true" diff --git a/CodeBeam.MudBlazor.Extensions/TScripts/MudExtensions.js b/CodeBeam.MudBlazor.Extensions/TScripts/MudExtensions.js index 2641a287..8d667481 100644 --- a/CodeBeam.MudBlazor.Extensions/TScripts/MudExtensions.js +++ b/CodeBeam.MudBlazor.Extensions/TScripts/MudExtensions.js @@ -321,3 +321,21 @@ class MudSignaturePad { } window.mudSignaturePad = new MudSignaturePadManager(); + +window.mudBeforeInput = { + attach: (element, dotNetRef) => { + if (!element) return; + + element.addEventListener("beforeinput", e => { + dotNetRef.invokeMethodAsync("OnBeforeInput", { + data: e.data, + inputType: e.inputType, + isComposing: e.isComposing + }).then(prevent => { + if (prevent === true) { + e.preventDefault(); + } + }); + }); + } +}; diff --git a/CodeBeam.MudBlazor.Extensions/Utilities/MudBeforeInputEventArgs.cs b/CodeBeam.MudBlazor.Extensions/Utilities/MudBeforeInputEventArgs.cs new file mode 100644 index 00000000..99b10ec1 --- /dev/null +++ b/CodeBeam.MudBlazor.Extensions/Utilities/MudBeforeInputEventArgs.cs @@ -0,0 +1,35 @@ +namespace MudExtensions +{ + public sealed class MudBeforeInputEventArgs + { + /// + /// Text that will be inserted. Null for delete actions. + /// + public string? Data { get; init; } + + /// + /// Type of input action (insertText, deleteContentBackward, insertFromPaste, etc.) + /// + public string InputType { get; init; } = string.Empty; + + /// + /// True when IME composition is active (Chinese, Japanese, etc.) + /// + public bool IsComposing { get; init; } + + /// + /// Set true to prevent the input from happening. + /// + public bool PreventDefault { get; set; } + + public bool IsInsert => InputType.StartsWith("insert", StringComparison.Ordinal); + + public bool IsDeleteBackward => InputType == "deleteContentBackward"; + + public bool IsDeleteForward => InputType == "deleteContentForward"; + + public bool IsPaste => InputType == "insertFromPaste"; + + public bool IsEnter => InputType == "insertLineBreak"; + } +} diff --git a/CodeBeam.MudBlazor.Extensions/Utilities/MudBeforeInputJsDto.cs b/CodeBeam.MudBlazor.Extensions/Utilities/MudBeforeInputJsDto.cs new file mode 100644 index 00000000..f92c23a2 --- /dev/null +++ b/CodeBeam.MudBlazor.Extensions/Utilities/MudBeforeInputJsDto.cs @@ -0,0 +1,9 @@ +namespace MudExtensions +{ + public sealed class MudBeforeInputJsDto + { + public string? Data { get; set; } + public string? InputType { get; set; } + public bool IsComposing { get; set; } + } +} diff --git a/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.js b/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.js index c132301f..6b8df282 100644 --- a/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.js +++ b/CodeBeam.MudBlazor.Extensions/wwwroot/MudExtensions.min.js @@ -1 +1 @@ -function auto_size(n){n.style.height="5px";n.style.height=n.scrollHeight+4+"px"}function getcss(n,t){const i=document.querySelector(n);return i.style.getPropertyValue(t)}function setcss(n,t,i){const r=document.querySelectorAll(n);for(let n=0;n{const i=document.querySelector(t);return i?(i.appendChild(n),"ok"):"not found"},removeFromDOM:n=>{n&&n.__internalId!==null&&n.remove()}};class MudSignaturePadManager{constructor(){this.pads=[]}addPad(n,t,i){const r=new MudSignaturePad(n,t,i);r.init();this.pads.push(r)}togglePadEraser(n){const t=this.getPad(n);t&&t.toggleEraser()}disposePad(n){const t=this.getPad(n);t&&t.dispose()}clearPad(n){const t=this.getPad(n);t&&t.clear(!0)}downloadPadImage(n){const t=this.getPad(n);t&&t.download()}getBase64(n){const t=this.getPad(n);if(t)return t.getBase64()}updatePadOptions(n,t){const i=this.getPad(n);i&&i.setOptions(t)}updatePadImage(n,t){const i=this.getPad(n);i&&(t.startsWith("data:image/png;base64,")||(t=`data:image/png;base64,${t}`),i.updateImage(t))}setCanvasSize(n){const t=this.getPad(n);t&&t.updateCanvasSize()}getPad(n){return this.pads.find(t=>t.canvas.id===n.id)||null}}class MudSignaturePad{constructor(n,t,i){this.canvas=t;this.options=i;this.isMouseDown=!1;this.isErasing=!1;this.memCanvas=document.createElement("canvas");this.points=[];this.dotnetRef=n;this.onPointerDown=this.handlePointerDown.bind(this);this.onPointerMove=this.handlePointerMove.bind(this);this.onPointerUp=this.handlePointerUp.bind(this);this.onPointerLeave=this.stopDrawing.bind(this)}get ctx(){return this.canvas.getContext("2d")}get memCtx(){return this.memCanvas.getContext("2d")}init(){this.setCanvasSize();this.setOptions(this.options);this.canvas.addEventListener("pointerdown",this.onPointerDown,{passive:!1});this.canvas.addEventListener("pointermove",this.onPointerMove,{passive:!1});this.canvas.addEventListener("pointerup",this.onPointerUp,{passive:!1});this.canvas.addEventListener("pointerleave",this.onPointerLeave);this.canvas.style.touchAction="none";this.setPencilCursor()}dispose(){this.canvas.removeEventListener("pointerdown",this.onPointerDown);this.canvas.removeEventListener("pointermove",this.onPointerMove);this.canvas.removeEventListener("pointerup",this.onPointerUp);this.canvas.removeEventListener("pointerleave",this.onPointerLeave)}setCanvasSize(){const t=this.canvas.parentElement;if(t){const n=t.getBoundingClientRect();this.canvas.width=n.width;this.canvas.height=n.height;this.memCanvas.width=n.width;this.memCanvas.height=n.height}}updateCanvasSize(){const t=this.canvas.parentElement;if(t){const i=t.getBoundingClientRect(),r=i.width,u=i.height,n=document.createElement("canvas");n.width=this.canvas.width;n.height=this.canvas.height;const f=n.getContext("2d");f.drawImage(this.canvas,0,0);this.canvas.width=r;this.canvas.height=u;this.memCanvas.width=r;this.memCanvas.height=u;this.ctx.drawImage(n,0,0);this.memCtx.drawImage(n,0,0)}}getBase64(){return this.canvas.toDataURL()}updateImage(n){this.clear(!0);const t=new Image;t.onload=()=>{this.ctx.drawImage(t,0,0),this.memCtx.drawImage(t,0,0)};t.src=n}download(){const n=document.createElement("a");n.download="signature.png";n.href=this.getBase64();n.click();n.remove()}clear(n){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);n&&this.memCtx.clearRect(0,0,this.canvas.width,this.canvas.height)}setOptions(n){this.options=n;const t=t=>{t.lineWidth=n.lineWidth,t.lineJoin=n.lineJoin,t.lineCap=n.lineCap,t.strokeStyle=n.strokeStyle};t(this.ctx);t(this.memCtx)}toggleEraser(){this.isErasing=!this.isErasing;this.isErasing?this.setEraserCursor():this.setPencilCursor()}setPencilCursor(){this.canvas.style.cursor="url('_content/CodeBeam.MudBlazor.Extensions/pencil.cur'), auto"}setEraserCursor(){this.canvas.style.cursor="url('_content/CodeBeam.MudBlazor.Extensions/eraser.cur'), auto"}handlePointerDown(n){n.preventDefault();this.isMouseDown=!0;const{offsetX:t,offsetY:i}=n;this.points=[{x:t,y:i}]}handlePointerMove(n){if(this.isMouseDown){n.preventDefault();const{offsetX:t,offsetY:i}=n;this.isErasing?this.ctx.clearRect(t-10,i-10,23,23):(this.clear(),this.ctx.drawImage(this.memCanvas,0,0),this.points.push({x:t,y:i}),this.drawPoints(this.ctx,this.points))}}handlePointerUp(n){n.preventDefault();this.stopDrawing()}stopDrawing(){this.isMouseDown&&(this.isMouseDown=!1,this.memCtx.clearRect(0,0,this.memCanvas.width,this.memCanvas.height),this.memCtx.drawImage(this.canvas,0,0),this.points=[])}drawPoints(n,t){if(!(t.length<2)){if(t.length<6){const i=t[0];n.beginPath();n.lineWidth=this.options.lineWidth;n.strokeStyle=this.options.strokeStyle;n.arc(i.x,i.y,n.lineWidth/2,0,Math.PI*2,!0);n.fill();n.closePath();this.pushUpdateToBlazorComponent();return}n.beginPath();n.moveTo(t[0].x,t[0].y);for(let i=1;i{const i=document.querySelector(t);return i?(i.appendChild(n),"ok"):"not found"},removeFromDOM:n=>{n&&n.__internalId!==null&&n.remove()}};class MudSignaturePadManager{constructor(){this.pads=[]}addPad(n,t,i){const r=new MudSignaturePad(n,t,i);r.init();this.pads.push(r)}togglePadEraser(n){const t=this.getPad(n);t&&t.toggleEraser()}disposePad(n){const t=this.getPad(n);t&&t.dispose()}clearPad(n){const t=this.getPad(n);t&&t.clear(!0)}downloadPadImage(n){const t=this.getPad(n);t&&t.download()}getBase64(n){const t=this.getPad(n);if(t)return t.getBase64()}updatePadOptions(n,t){const i=this.getPad(n);i&&i.setOptions(t)}updatePadImage(n,t){const i=this.getPad(n);i&&(t.startsWith("data:image/png;base64,")||(t=`data:image/png;base64,${t}`),i.updateImage(t))}setCanvasSize(n){const t=this.getPad(n);t&&t.updateCanvasSize()}getPad(n){return this.pads.find(t=>t.canvas.id===n.id)||null}}class MudSignaturePad{constructor(n,t,i){this.canvas=t;this.options=i;this.isMouseDown=!1;this.isErasing=!1;this.memCanvas=document.createElement("canvas");this.points=[];this.dotnetRef=n;this.onPointerDown=this.handlePointerDown.bind(this);this.onPointerMove=this.handlePointerMove.bind(this);this.onPointerUp=this.handlePointerUp.bind(this);this.onPointerLeave=this.stopDrawing.bind(this)}get ctx(){return this.canvas.getContext("2d")}get memCtx(){return this.memCanvas.getContext("2d")}init(){this.setCanvasSize();this.setOptions(this.options);this.canvas.addEventListener("pointerdown",this.onPointerDown,{passive:!1});this.canvas.addEventListener("pointermove",this.onPointerMove,{passive:!1});this.canvas.addEventListener("pointerup",this.onPointerUp,{passive:!1});this.canvas.addEventListener("pointerleave",this.onPointerLeave);this.canvas.style.touchAction="none";this.setPencilCursor()}dispose(){this.canvas.removeEventListener("pointerdown",this.onPointerDown);this.canvas.removeEventListener("pointermove",this.onPointerMove);this.canvas.removeEventListener("pointerup",this.onPointerUp);this.canvas.removeEventListener("pointerleave",this.onPointerLeave)}setCanvasSize(){const t=this.canvas.parentElement;if(t){const n=t.getBoundingClientRect();this.canvas.width=n.width;this.canvas.height=n.height;this.memCanvas.width=n.width;this.memCanvas.height=n.height}}updateCanvasSize(){const t=this.canvas.parentElement;if(t){const i=t.getBoundingClientRect(),r=i.width,u=i.height,n=document.createElement("canvas");n.width=this.canvas.width;n.height=this.canvas.height;const f=n.getContext("2d");f.drawImage(this.canvas,0,0);this.canvas.width=r;this.canvas.height=u;this.memCanvas.width=r;this.memCanvas.height=u;this.ctx.drawImage(n,0,0);this.memCtx.drawImage(n,0,0)}}getBase64(){return this.canvas.toDataURL()}updateImage(n){this.clear(!0);const t=new Image;t.onload=()=>{this.ctx.drawImage(t,0,0),this.memCtx.drawImage(t,0,0)};t.src=n}download(){const n=document.createElement("a");n.download="signature.png";n.href=this.getBase64();n.click();n.remove()}clear(n){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);n&&this.memCtx.clearRect(0,0,this.canvas.width,this.canvas.height)}setOptions(n){this.options=n;const t=t=>{t.lineWidth=n.lineWidth,t.lineJoin=n.lineJoin,t.lineCap=n.lineCap,t.strokeStyle=n.strokeStyle};t(this.ctx);t(this.memCtx)}toggleEraser(){this.isErasing=!this.isErasing;this.isErasing?this.setEraserCursor():this.setPencilCursor()}setPencilCursor(){this.canvas.style.cursor="url('_content/CodeBeam.MudBlazor.Extensions/pencil.cur'), auto"}setEraserCursor(){this.canvas.style.cursor="url('_content/CodeBeam.MudBlazor.Extensions/eraser.cur'), auto"}handlePointerDown(n){n.preventDefault();this.isMouseDown=!0;const{offsetX:t,offsetY:i}=n;this.points=[{x:t,y:i}]}handlePointerMove(n){if(this.isMouseDown){n.preventDefault();const{offsetX:t,offsetY:i}=n;this.isErasing?this.ctx.clearRect(t-10,i-10,23,23):(this.clear(),this.ctx.drawImage(this.memCanvas,0,0),this.points.push({x:t,y:i}),this.drawPoints(this.ctx,this.points))}}handlePointerUp(n){n.preventDefault();this.stopDrawing()}stopDrawing(){this.isMouseDown&&(this.isMouseDown=!1,this.memCtx.clearRect(0,0,this.memCanvas.width,this.memCanvas.height),this.memCtx.drawImage(this.canvas,0,0),this.points=[])}drawPoints(n,t){if(!(t.length<2)){if(t.length<6){const i=t[0];n.beginPath();n.lineWidth=this.options.lineWidth;n.strokeStyle=this.options.strokeStyle;n.arc(i.x,i.y,n.lineWidth/2,0,Math.PI*2,!0);n.fill();n.closePath();this.pushUpdateToBlazorComponent();return}n.beginPath();n.moveTo(t[0].x,t[0].y);for(let i=1;i{n&&n.addEventListener("beforeinput",n=>{t.invokeMethodAsync("OnBeforeInput",{data:n.data,inputType:n.inputType,isComposing:n.isComposing}).then(t=>{t===!0&&n.preventDefault()})})}} \ No newline at end of file From 4eb21de10508a97b737bcc771561b61e28a973ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Wed, 24 Dec 2025 20:40:26 +0300 Subject: [PATCH 6/9] Try Fix JsMinifier --- .../wwwroot/CodeBeam.MudBlazor.Extensions.xml | 20 ++++++++++++++++ .../Program.cs | 24 +++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml index b85b9271..8d768b6d 100644 --- a/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml +++ b/CodeBeam.MudBlazor.Extensions.Docs.Wasm/wwwroot/CodeBeam.MudBlazor.Extensions.xml @@ -6493,6 +6493,26 @@ Localized strings for MudStepper + + + Text that will be inserted. Null for delete actions. + + + + + Type of input action (insertText, deleteContentBackward, insertFromPaste, etc.) + + + + + True when IME composition is active (Chinese, Japanese, etc.) + + + + + Set true to prevent the input from happening. + + Supports id and class selection. Use "#idName" for id selectors (ex. ) or ".idName" for class selectors (ex. ). Leave it null or empty to effect all scrollbars. diff --git a/CodeBeam.MudBlazor.Extensions.JsMinifier/Program.cs b/CodeBeam.MudBlazor.Extensions.JsMinifier/Program.cs index cf3a0286..287f8bdb 100644 --- a/CodeBeam.MudBlazor.Extensions.JsMinifier/Program.cs +++ b/CodeBeam.MudBlazor.Extensions.JsMinifier/Program.cs @@ -3,12 +3,28 @@ Console.WriteLine("Minifying MudExtensions.js..."); -// Solution root -var solutionRoot = Directory.GetCurrentDirectory(); +// Bulunduğumuz dizinden yukarı doğru çık +var current = Directory.GetCurrentDirectory(); +string? solutionRoot = null; -// Ana proje klasörü -var projectRoot = Path.Combine(solutionRoot, "CodeBeam.MudBlazor.Extensions"); +while (current != null) +{ + if (Directory.Exists(Path.Combine(current, "CodeBeam.MudBlazor.Extensions"))) + { + solutionRoot = current; + break; + } + current = Directory.GetParent(current)?.FullName; +} + +if (solutionRoot == null) +{ + Console.Error.WriteLine("Solution root not found."); + Environment.Exit(1); +} + +var projectRoot = Path.Combine(solutionRoot, "CodeBeam.MudBlazor.Extensions"); var input = Path.Combine(projectRoot, "TScripts", "MudExtensions.js"); var output = Path.Combine(projectRoot, "wwwroot", "MudExtensions.min.js"); From 436a19ce97cabd70fb29ae65404d8df32813a549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Wed, 24 Dec 2025 20:51:24 +0300 Subject: [PATCH 7/9] Try CI Fix --- .../CodeBeam.MudBlazor.Extensions.csproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj index dcb7bd12..e4a97fa9 100644 --- a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj +++ b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj @@ -29,6 +29,14 @@ false + + true + + + + false + + From fe5862b2970b5d194c15ee5a3fc35ecdf605521e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Wed, 24 Dec 2025 20:55:58 +0300 Subject: [PATCH 8/9] Try CI Fix 2 --- .../CodeBeam.MudBlazor.Extensions.csproj | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj index e4a97fa9..50854a37 100644 --- a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj +++ b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj @@ -27,10 +27,7 @@ true True false - - - - true + false From 13a9f1a98757ec569130b8e767ce3534507865f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Wed, 24 Dec 2025 21:01:50 +0300 Subject: [PATCH 9/9] Try CI Fix 3 --- .../CodeBeam.MudBlazor.Extensions.csproj | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj index 50854a37..35b4be08 100644 --- a/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj +++ b/CodeBeam.MudBlazor.Extensions/CodeBeam.MudBlazor.Extensions.csproj @@ -27,11 +27,6 @@ true True false - false - - - - false @@ -40,19 +35,16 @@ - + - - - - +