mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-07-08 18:16:08 +00:00
* Remove Microsoft.CodeAnalysis. Add own C# expression parser. * Popup dialog animations (#2118) * Experiment with popup and dialog animations. * Move animations to a separate _animations.scss * Remove dialog closing animation. * Support side dialog positions. Prefix keyframes. * Use --rz-transition for animation function and duration * Reset site.css. * PanelMenu animations. * Display none is toggled a bit late. * RadzenPanel animations. * More animations. * Use transitions for panel menu. * Remove old code. * Accordion uses transitions. * Panel uses transitions. * Extract expand and collapse implementation in a separate component. * Set initial expand state earlier to prevent two renders. * Add open animation to notifications. * Handle onanimationend before toggling the animation classes. * Add menu animation. * Experiment with tree animation. * Add animations to fieldset. --------- Co-authored-by: yordanov <vasil@yordanov.info> * ExpressionSerializer and tests added (#2119) * Fix failing tests. * various components RequiresUnreferencedCode attribute added (#2120) * RequiresUnreferencedCode added to ExpressionSerializer * Update premium themes * RequiresUnreferencedCode added to ExpressionParser * FormComponentWithAutoComplete RequiresUnreferencedCode removed * Revert "FormComponentWithAutoComplete RequiresUnreferencedCode removed" This reverts commitec900a4df8. * Revert "RequiresUnreferencedCode added to ExpressionParser" This reverts commitf93b3b159b. * Revert "RequiresUnreferencedCode added to ExpressionSerializer" This reverts commit06fecec9a6. * Revert "various components RequiresUnreferencedCode attribute added (#2120)" This reverts commit2ed1a6cac1. * Remove RadzenHtml. * ExpressionSerializer FormatValue updated to use InvariantCulture * Catch potential JS interop exceptions that could occur during disposing. * Revert "Remove RadzenHtml." This reverts commit319085bf49. * SelectBar made single tab stop * RadioButtonList and CheckBoxList made single tab stop * SelectBar accessibility improved * RadioButtonList accessibility improved * CheckBoxList accessibility improved * Update radio button focus styles * Update checkbox list focus styles * Update Checkbox Radio and SelectBar focus styles * SelectBar, CheckBoxList and RadioButtonList focus state improved * Check for Multiple added * Use non-rendering event handlers for transitionend. * Rename css class rz-selectbutton to rz-selectbar and improve focus states * Fix selectbar focus outline offset * Update premium themes * Selectbar item focus styles should not be visible if the item is disabled. * CheckBoxList and RadioButtonList item focus should be visible only on keyboard input * SelectBar, CheckBoxList and RadioButtonList focus logic improved * Update animations * RadzenText margin-block should be 0 if it is in RadzenStack. Resolves #2134 * RadzenText margin-block should be 0 if it is first level child in RadzenStack * CheckBoxList focused fixed * Add toggle state classes to panel menu icon. * Update accordion styles to reflect expander changes * Add animation styles to expand arrow in Menu and ProfileMenu * Use a instead of NavLink as it seems to cause performance issues. * Set @bind-Expanded. * Revert "Set @bind-Expanded." This reverts commit 994107367bdf09043950f8bbe701eb9edefec676. * Revert "Use a instead of NavLink as it seems to cause performance issues." This reverts commit 05d5bef8f421bbeb5828ba1e9c5af6793ea3d32a. * Reduce rendering of panel menu items. * Add panel menu component. * Use ChildContent to render the toggle icon of the panel menu item. * Sync panel menu item selection in the item itself. * Rename ExpandedInternal to expanded. * Move filtering to the panel menu component. * Remove the transitionend handler to avoid a second rendering pass. * Build the assets for the net9.0 framework. * Do not trigger render when Click is used. * Panel menu keyboard navigation renders only when needed. * Focus reworked to use AsNonRenderingEventHandler * Focus the first item. * Update Panel demo * Use a more robust algorithm for month view event rendering that handles overlapping of events across a week. * Use RadzenStack in RadioButtonList * Add parsing support for `&` and `|`. * Add parsing support for `^`, `>>` and `<<`. * Simplify expression parsing tests. * Use RadzenStack in RadioButtonList and CheckBoxList * Change defaults for AlignItems and JustifyContent in RadioButtonList and CheckBoxList * Update RadioButtonList and CheckBoxList demos * Add --rz-input-border-block-end css variables to improve Fluent theme styles * Removed AsNonRenderingEventHandler from RadioButtonList and HtmlEditor focus and blur * Removed AsNonRenderingEventHandler from CheckBoxList * Simplify RadzenTable rendering. * Optimize memory usage of the ClassList utility. * Refactor RadzenButton to use ClassList. * RadzenSelectBar and RadzenSplitButton use ClassList. * Refactor RadzenBadge and RadzenAlert to use ClassList. * Refactor RadzenCard and RadzenFormField to use ClassList. * Refactor RadzenCardGroup and progress components to use ClassList. * Refactor RadzenMenu to use ClassList. * Use ClassList in RadzenBody, RadzenLayout and editor rendering components. * RadzenDialog uses ClassList. * RadzenDataGrid uses ClassList. * RadzenPager uses ClassList. * RadzenColumn uses ClassList. * Fix RadzenSplitButtonItem focused state. --------- Co-authored-by: Atanas Korchev <akorchev@gmail.com> Co-authored-by: Atanas Korchev <454726+akorchev@users.noreply.github.com> Co-authored-by: yordanov <vasil@yordanov.info> Co-authored-by: Quentin H <67709967+quintushr@users.noreply.github.com>
351 lines
12 KiB
C#
351 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using Microsoft.AspNetCore.Components;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.JSInterop;
|
|
|
|
namespace Radzen
|
|
{
|
|
/// <summary>
|
|
/// Base class of Radzen Blazor components.
|
|
/// </summary>
|
|
public class RadzenComponent : ComponentBase, IDisposable
|
|
{
|
|
/// <summary>
|
|
/// Specifies additional custom attributes that will be rendered by the component.
|
|
/// </summary>
|
|
/// <value>The attributes.</value>
|
|
[Parameter(CaptureUnmatchedValues = true)]
|
|
public IReadOnlyDictionary<string, object> Attributes { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets a reference to the HTML element rendered by the component.
|
|
/// </summary>
|
|
public ElementReference Element { get; protected internal set; }
|
|
|
|
/// <summary>
|
|
/// A callback that will be invoked when the user hovers the component. Commonly used to display a tooltip via
|
|
/// <see cref="TooltipService.Open(ElementReference, string, TooltipOptions)" />.
|
|
/// </summary>
|
|
[Parameter]
|
|
public EventCallback<ElementReference> MouseEnter { get; set; }
|
|
|
|
/// <summary>
|
|
/// A callback that will be invoked when the user moves the mouse out of the component. Commonly used to hide a tooltip via
|
|
/// <see cref="TooltipService.Close" />.
|
|
/// </summary>
|
|
[Parameter]
|
|
public EventCallback<ElementReference> MouseLeave { get; set; }
|
|
|
|
/// <summary>
|
|
/// A callback that will be invoked when the user right-clicks the component. Commonly used to display a context menu via
|
|
/// <see cref="ContextMenuService.Open(Microsoft.AspNetCore.Components.Web.MouseEventArgs, IEnumerable{ContextMenuItem}, Action{MenuItemEventArgs})" />.
|
|
/// </summary>
|
|
[Parameter]
|
|
public EventCallback<Microsoft.AspNetCore.Components.Web.MouseEventArgs> ContextMenu { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the culture used to display localizable data (numbers, dates). Set by default to <see cref="CultureInfo.CurrentCulture" />.
|
|
/// </summary>
|
|
[Parameter]
|
|
public CultureInfo Culture
|
|
{
|
|
get => culture ?? DefaultCulture ?? CultureInfo.CurrentCulture;
|
|
set => culture = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the culture set by a parent component.
|
|
/// </summary>
|
|
[CascadingParameter(Name = nameof(DefaultCulture))]
|
|
public CultureInfo DefaultCulture { get; set; }
|
|
|
|
private CultureInfo culture;
|
|
|
|
/// <summary>
|
|
/// Raises <see cref="MouseEnter" />.
|
|
/// </summary>
|
|
public async Task OnMouseEnter()
|
|
{
|
|
await MouseEnter.InvokeAsync(Element);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises <see cref="MouseLeave" />.
|
|
/// </summary>
|
|
public async Task OnMouseLeave()
|
|
{
|
|
await MouseLeave.InvokeAsync(Element);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises <see cref="ContextMenu" />.
|
|
/// </summary>
|
|
/// <param name="args">The <see cref="Microsoft.AspNetCore.Components.Web.MouseEventArgs"/> instance containing the event data.</param>
|
|
public virtual async Task OnContextMenu(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
|
|
{
|
|
await ContextMenu.InvokeAsync(args);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the inline CSS style.
|
|
/// </summary>
|
|
/// <value>The style.</value>
|
|
[Parameter]
|
|
public virtual string Style { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether this <see cref="RadzenComponent"/> is visible. Invisible components are not rendered.
|
|
/// </summary>
|
|
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public virtual bool Visible { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Gets the final CSS class rendered by the component. Combines it with a <c>class</c> custom attribute.
|
|
/// </summary>
|
|
protected string GetCssClass()
|
|
{
|
|
if (Attributes != null && Attributes.TryGetValue("class", out var @class) && !string.IsNullOrEmpty(Convert.ToString(@class)))
|
|
{
|
|
return $"{GetComponentCssClass()} {@class}";
|
|
}
|
|
|
|
return GetComponentCssClass();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the unique identifier.
|
|
/// </summary>
|
|
/// <returns>Returns the <c>id</c> attribute (if specified) or generates a random one.</returns>
|
|
protected virtual string GetId()
|
|
{
|
|
if (Attributes != null && Attributes.TryGetValue("id", out var id) && !string.IsNullOrEmpty(Convert.ToString(@id)))
|
|
{
|
|
return $"{@id}";
|
|
}
|
|
|
|
return UniqueID;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the component CSS class.
|
|
/// </summary>
|
|
protected virtual string GetComponentCssClass()
|
|
{
|
|
return "";
|
|
}
|
|
|
|
Debouncer debouncer = new Debouncer();
|
|
|
|
/// <summary>
|
|
/// Debounces the specified action.
|
|
/// </summary>
|
|
/// <param name="action">The action.</param>
|
|
/// <param name="milliseconds">The milliseconds.</param>
|
|
protected void Debounce(Func<Task> action, int milliseconds = 500)
|
|
{
|
|
debouncer.Debounce(milliseconds, action);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the unique identifier.
|
|
/// </summary>
|
|
/// <value>The unique identifier.</value>
|
|
public string UniqueID { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the js runtime.
|
|
/// </summary>
|
|
/// <value>The js runtime.</value>
|
|
[Inject]
|
|
protected IJSRuntime JSRuntime { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether <see cref="JSRuntime" /> is available.
|
|
/// </summary>
|
|
protected bool IsJSRuntimeAvailable { get; set; }
|
|
|
|
/// <summary>
|
|
/// Called by the Blazor runtime.
|
|
/// </summary>
|
|
protected override void OnInitialized()
|
|
{
|
|
UniqueID = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace("/", "-").Replace("+", "-").Substring(0, 10);
|
|
}
|
|
|
|
private bool visibleChanged = false;
|
|
private bool firstRender = true;
|
|
|
|
/// <summary>
|
|
/// Called by the Blazor runtime when parameters are set.
|
|
/// </summary>
|
|
/// <param name="parameters">The parameters.</param>
|
|
public override async Task SetParametersAsync(ParameterView parameters)
|
|
{
|
|
visibleChanged = parameters.DidParameterChange(nameof(Visible), Visible);
|
|
|
|
await base.SetParametersAsync(parameters);
|
|
|
|
if (visibleChanged && !firstRender)
|
|
{
|
|
if (Visible == false)
|
|
{
|
|
Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
private DotNetObjectReference<RadzenComponent> reference;
|
|
|
|
/// <summary>
|
|
/// Gets the reference for the current component.
|
|
/// </summary>
|
|
/// <value>The reference.</value>
|
|
protected DotNetObjectReference<RadzenComponent> Reference
|
|
{
|
|
get
|
|
{
|
|
if (reference == null)
|
|
{
|
|
reference = DotNetObjectReference.Create(this);
|
|
}
|
|
|
|
return reference;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called by the Blazor runtime.
|
|
/// </summary>
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
IsJSRuntimeAvailable = true;
|
|
|
|
this.firstRender = firstRender;
|
|
|
|
if (firstRender || visibleChanged)
|
|
{
|
|
visibleChanged = false;
|
|
|
|
if (Visible)
|
|
{
|
|
if (ContextMenu.HasDelegate)
|
|
{
|
|
await JSRuntime.InvokeVoidAsync("Radzen.addContextMenu", GetId(), Reference);
|
|
}
|
|
|
|
if (MouseEnter.HasDelegate)
|
|
{
|
|
await JSRuntime.InvokeVoidAsync("Radzen.addMouseEnter", GetId(), Reference);
|
|
}
|
|
|
|
if (MouseLeave.HasDelegate)
|
|
{
|
|
await JSRuntime.InvokeVoidAsync("Radzen.addMouseLeave", GetId(), Reference);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invoked via interop when the browser "oncontextmenu" event is raised for this component.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="Microsoft.AspNetCore.Components.Web.MouseEventArgs"/> instance containing the event data.</param>
|
|
[JSInvokable("RadzenComponent.RaiseContextMenu")]
|
|
public async System.Threading.Tasks.Task RaiseContextMenu(Microsoft.AspNetCore.Components.Web.MouseEventArgs e)
|
|
{
|
|
if (ContextMenu.HasDelegate)
|
|
{
|
|
await OnContextMenu(e);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invoked via interop when the browser "onmouseenter" event is raised for this component.
|
|
/// </summary>
|
|
[JSInvokable("RadzenComponent.RaiseMouseEnter")]
|
|
public async System.Threading.Tasks.Task RaiseMouseEnter()
|
|
{
|
|
if (MouseEnter.HasDelegate)
|
|
{
|
|
await OnMouseEnter();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invoked via interop when the browser "onmouseleave" event is raised for this component.
|
|
/// </summary>
|
|
[JSInvokable("RadzenComponent.RaiseMouseLeave")]
|
|
public async System.Threading.Tasks.Task RaiseMouseLeave()
|
|
{
|
|
if (MouseLeave.HasDelegate)
|
|
{
|
|
await OnMouseLeave();
|
|
}
|
|
}
|
|
|
|
internal bool disposed = false;
|
|
|
|
/// <summary>
|
|
/// Detaches event handlers and disposes <see cref="Reference" />.
|
|
/// </summary>
|
|
public virtual void Dispose()
|
|
{
|
|
disposed = true;
|
|
|
|
reference?.Dispose();
|
|
reference = null;
|
|
|
|
if (IsJSRuntimeAvailable)
|
|
{
|
|
if (ContextMenu.HasDelegate)
|
|
{
|
|
JSRuntime.InvokeVoid("Radzen.removeContextMenu", UniqueID);
|
|
}
|
|
|
|
if (MouseEnter.HasDelegate)
|
|
{
|
|
JSRuntime.InvokeVoid("Radzen.removeMouseEnter", UniqueID);
|
|
}
|
|
|
|
if (MouseLeave.HasDelegate)
|
|
{
|
|
JSRuntime.InvokeVoid("Radzen.removeMouseLeave", UniqueID);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the current style as a dictionary.
|
|
/// </summary>
|
|
/// <value>The current style as a dictionary of keys and values.</value>
|
|
protected IDictionary<string, string> CurrentStyle
|
|
{
|
|
get
|
|
{
|
|
var currentStyle = new Dictionary<string, string>();
|
|
|
|
if (!String.IsNullOrEmpty(Style))
|
|
{
|
|
foreach (var pair in Style.Split(';'))
|
|
{
|
|
var keyAndValue = pair.Split(':');
|
|
if (keyAndValue.Length == 2)
|
|
{
|
|
var key = keyAndValue[0].Trim();
|
|
var value = keyAndValue[1].Trim();
|
|
|
|
currentStyle[key] = value;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return currentStyle;
|
|
}
|
|
}
|
|
}
|
|
}
|