using System; using System.Text.Json; using System.Threading.Tasks; using AntDesign.JsInterop; using Microsoft.AspNetCore.Components; using OneOf; namespace AntDesign { public class DropdownButton : Dropdown { /// /// Option to fit button width to its parent width /// [Parameter] public new bool Block { get => base.Block; set => base.Block = value; } /// /// Fully customizable button. /// [Parameter] public new Func ButtonsRender { get => base.ButtonsRender; set => base.ButtonsRender = value; } /// /// Allows to set each button's css class either to the same string /// or separately. /// [Parameter] public OneOf ButtonsClass { get => _buttonsClass; set { _buttonsClass = value; _buttonsClass.Switch( single => { ChangeButtonClass(single, single); }, both => { ChangeButtonClass(both.LeftButton, both.RightButton); }); } } /// /// Allows to set each button's style either to the same string /// or separately. /// [Parameter] public OneOf ButtonsStyle { get => _buttonsStyle; set { _buttonsStyle = value; _buttonsStyle.Switch( single => { ChangeButtonStyles(single, single); }, both => { ChangeButtonStyles(both.LeftButton, both.RightButton); }); } } /// /// Set the danger status of button /// [Parameter] public bool Danger { get => _danger; set { _danger = value; ChangeButtonDanger(value); } } /// /// Used in situations with complex background, home pages usually. /// [Parameter] public bool Ghost { get => _ghost; set { _ghost = value; ChangeButtonGhost(value); } } private string _icon = "ellipsis"; /// /// Icon that will be rendered in the right /// button. /// [Parameter] public string Icon { get => _icon; set { _icon = value; ChangeRightButtonIcon(value); } } /// /// Indicates if loading icon is going to be included. /// If set to true, then dropdown will not be active. /// [Parameter] public bool Loading { get => _loading; set { _loading = value; ChangeButtonLoading(value); } } private string _size = AntSizeLDSType.Default; /// /// Button size. /// [Parameter] public string Size { get => _size; set { _size = value; ChangeButtonSize(value); } } /// /// Allows to set each button's type either to the same string /// or separately. Use AntDesign.ButtonType helper class. /// [Parameter] public OneOf Type { get => _buttonsType; set { _buttonsType = value; _buttonsType.Switch( single => { ChangeButtonType(single, single); }, both => { ChangeButtonType(both.LeftButton, both.RightButton); }); } } private bool _loading; private bool _danger; private bool _ghost = false; private OneOf _buttonsStyle; private OneOf _buttonsClass; private OneOf _buttonsType = ButtonType.Default; public DropdownButton() => IsButton = true; protected override void OnInitialized() { string prefixCls = "ant-btn"; ClassMapper.Clear(); Placement = Placement.BottomRight; base.OnInitialized(); ClassMapper.If($"{prefixCls}-block", () => Block); } /// /// Force overlay trigger to be attached to wrapping element of /// the right button. Right button has to be wrapped, /// because overlay will be looking for first child /// element of the overlay trigger to calculate the overlay position. /// If the right button was the trigger, then its first child /// would be the icon/ellipsis and the overlay would have been /// rendered too high. /// /// /// protected override Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { Ref = RefBack.Current; DomEventListener.AddExclusive(Ref, "click", OnUnboundClick); DomEventListener.AddExclusive(Ref, "mouseover", OnUnboundMouseEnter); DomEventListener.AddExclusive(Ref, "mouseout", OnUnboundMouseLeave); DomEventListener.AddExclusive(Ref, "focusin", OnUnboundFocusIn); DomEventListener.AddExclusive(Ref, "focusout", OnUnboundFocusOut); DomEventListener.AddExclusive(Ref, "contextmenu", OnContextMenu, true); } return base.OnAfterRenderAsync(firstRender); } protected override void Dispose(bool disposing) { DomEventListener.DisposeExclusive(); base.Dispose(disposing); } internal override async Task Show(int? overlayLeft = null, int? overlayTop = null) { if (!Loading) { await _overlay.Show(overlayLeft, overlayTop); } } } }