using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using AntDesign.JsInterop; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using Microsoft.JSInterop; using OneOf; namespace AntDesign { public partial class Mentions { [Parameter] public bool AutoFocus { get; set; } [Parameter] public bool Disable { get; set; } [Parameter] public bool Readonly { get; set; } [Parameter] public string Prefix { get; set; } = "@,#"; //“@,#” [Parameter] public string Split { get; set; } = " "; [Parameter] public string DefaultValue { get; set; } [Parameter] public string Placeholder { get; set; } [Parameter] public string Value { get; set; } [Parameter] public string Placement { get; set; } = "bottom"; [Parameter] public int Rows { get; set; } = 1; [Parameter] public bool Loading { get; set; } = false; [Parameter] public RenderFragment ChildContent { get; set; } [Parameter] public EventCallback ValueChange { get; set; } [Parameter] public EventCallback OnFocus { get; set; } [Parameter] public EventCallback OnBlur { get; set; } [Parameter] public EventCallback OnSearch { get; set; } [Parameter] public RenderFragment NoFoundContent { get; set; } public Dictionary Attributes { get; set; } [Inject] private DomEventService DomEventService { get; set; } internal List LstOriginalOptions { get; set; } = new List(); private string DropdownStyle { get; set; } private bool Focused { get; set; } private bool ShowSuggestions { get; set; } private void SetClassMap() { var prefixCls = "ant-mentions"; this.ClassMapper.Clear() .Add(prefixCls) .If($"{prefixCls}-disable", () => this.Disable) .If($"{prefixCls}-focused", () => this.Focused) .If($"{prefixCls}-rtl", () => RTL) ; } protected override void OnInitialized() { base.OnInitialized(); SetClassMap(); if (string.IsNullOrEmpty(Value)) { Value = DefaultValue; } //DomEventService.AddEventListener(Ref, "keyup", OnTextAreaKeyup); // DomEventService.AddEventListener(Ref, "onmouseup", OnTextAreaMouseUp); } internal bool FirstTime { get; set; } = true; protected override Task OnFirstAfterRenderAsync() { base.OnFirstAfterRenderAsync(); FirstTime = false; return Task.CompletedTask; } /// /// After Press keyUP, if a key is prefix, to popup the suggestion /// /// /// private async Task OnKeyUp(KeyboardEventArgs args) { if (args == null) return; if (Prefix.Contains(args.Key, StringComparison.Ordinal)) { await SetDropdownStyle(); ShowSuggestions = Prefix.Contains(args.Key, StringComparison.Ordinal); await InvokeStateHasChangedAsync(); } if (!string.IsNullOrEmpty(Value)) { var suggestions = this.Value.Split(Split); } await ValueChange.InvokeAsync(this.Value); } private async Task OnKeyDown(KeyboardEventArgs args) { await InvokeStateHasChangedAsync(); } private DotNetObjectReference _reference; private const string ReferenceName = "mentions"; protected async Task SetDropdownStyle() { if (_reference == null) { _reference = DotNetObjectReference.Create(this); } //get current dom element infomation var domRect = await JsInvokeAsync(JSInteropConstants.GetCursorXY, Ref, _reference); var left = Math.Round(domRect[0]); var top = Math.Round(domRect[1]); //DropdownStyle = $"display:inline-flex;position:fixed;top:{top}px;left:{left}px;transform:translate({cursorPoint.x}px, {cursorPoint.y}0px);"; DropdownStyle = $"display:inline-flex;position:fixed;top:{top}px;left:{left}px;transform:translate(0px, 0px);"; } /// /// open or close the list of Suggestion /// /// /// internal async Task ShowSuggestion(bool show) { ShowSuggestions = show; await InvokeStateHasChangedAsync(); } internal async Task GetSuggestion() { } /// /// /// /// /// internal async Task OnOptionClick(MentionsOption opt) { // update to status of all of suggestion to un-selected state foreach (var item in LstOriginalOptions) { item.Selected = false; } // when the suggestion clicked is not null and enable, then change the value of textarea. if (opt != null && !opt.Disable) { if (string.IsNullOrEmpty(this.Value)) { this.Value = opt.Value + this.Split; } else { this.Value = this.Value + opt.Value + this.Split; } } ShowSuggestions = false; await InvokeStateHasChangedAsync(); } private void OnKeyPress(KeyboardEventArgs args) { Console.WriteLine(args.Key); if (args == null) return; if (ValueChange.HasDelegate) ValueChange.InvokeAsync(args.Code); return; } protected override Task OnParametersSetAsync() { return base.OnParametersSetAsync(); } /// /// return a new list of mentionsOption, when all item included the specificed text /// /// /// private List IsIncluded(string textValue) { if (string.IsNullOrEmpty(textValue)) { return LstOriginalOptions; } List lst = new List(); foreach (var item in LstOriginalOptions) { if (item.Value.Contains(textValue, StringComparison.Ordinal)) { lst.Add(item); } } return lst; } public void RemoveOption(MentionsOption option) { LstOriginalOptions.Remove(option); } public void AddOption(MentionsOption option) { if (option == null) return; var opt = LstOriginalOptions.Find(x => x.Value == option.Value); if (opt == null) { LstOriginalOptions.Add(option); } } internal async void Onfocus(FocusEventArgs args) { if (args == null) return; Focused = true; if (OnFocus.HasDelegate) await OnFocus.InvokeAsync(args); await FocusAsync(Ref); StateHasChanged(); } internal async void Onblur(FocusEventArgs args) { if (args == null) return; Focused = false; if (OnBlur.HasDelegate) await OnBlur.InvokeAsync(args); await JsInvokeAsync(JSInteropConstants.Blur, Ref); StateHasChanged(); } [JSInvokable] public void CloseMentionsDropDown() { ShowSuggestions = false; StateHasChanged(); } protected override void Dispose(bool disposing) { _reference = null; _ = JsInvokeAsync(JSInteropConstants.DisposeObj, ReferenceName); base.Dispose(disposing); } } }