refactor: standardized code specification (#82)

* refactor: standardized code specification

* fix: rebase conflict
This commit is contained in:
James Yeung 2020-04-23 17:13:56 +08:00 committed by GitHub
parent 035e418072
commit cc9e2df41c
122 changed files with 2694 additions and 2327 deletions

View File

@ -1,3 +1,223 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Don't use tabs for indentation.
[*]
indent_style = space
# (Please don't specify an indent_size here; that has too many unintended consequences.)
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
insert_final_newline = true
charset = utf-8-bom
# XML project files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2
# XML config files
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
indent_size = 2
# JSON files
[*.json]
indent_size = 2
# Powershell files
[*.ps1]
indent_size = 2
# Shell script files
[*.sh]
end_of_line = lf
indent_size = 2
# Dotnet code style settings:
[*.{cs,vb}]
# IDE0055: Fix formatting
dotnet_diagnostic.IDE0055.severity = warning
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:refactoring
dotnet_style_qualification_for_property = false:refactoring
dotnet_style_qualification_for_method = false:refactoring
dotnet_style_qualification_for_event = false:refactoring
# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Suggest more modern language features when available
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
# Non-private static fields are PascalCase
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
# Non-private readonly fields are PascalCase
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style
dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly
dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case
# Constants are PascalCase
dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style
dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.required_modifiers = const
dotnet_naming_style.constant_style.capitalization = pascal_case
# Static fields are camelCase and start with s_
dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields
dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_style.static_field_style.capitalization = camel_case
dotnet_naming_style.static_field_style.required_prefix = _
# Instance fields are camelCase and start with _
dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion
dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
dotnet_naming_symbols.instance_fields.applicable_kinds = field
dotnet_naming_style.instance_field_style.capitalization = camel_case
dotnet_naming_style.instance_field_style.required_prefix = _
# Locals and parameters are camelCase
dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
dotnet_naming_style.camel_case_style.capitalization = camel_case
# Local functions are PascalCase
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_style.local_function_style.capitalization = pascal_case
# By default, name items with PascalCase
dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.all_members.applicable_kinds = *
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# error RS2008: Enable analyzer release tracking for the analyzer project containing rule '{0}'
dotnet_diagnostic.RS2008.severity = none
# IDE0073: File header
dotnet_diagnostic.IDE0073.severity = warning
file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license.\nSee the LICENSE file in the project root for more information.
# CSharp code style settings:
[*.cs]
# Newline settings
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Prefer "var" everywhere
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
# Prefer method-like constructs to have a block body
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
# Prefer property-like constructs to have an expression-body
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Suggest more modern language features when available
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = do_not_ignore
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Blocks are allowed
csharp_prefer_braces = true:silent
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
[*.cs]
# CS1591: Missing XML comment for publicly visible type or member
@ -5,3 +225,6 @@ dotnet_diagnostic.CS1591.severity = none
# IDE1006: Naming Styles
dotnet_diagnostic.IDE1006.severity = error
# CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive).
dotnet_diagnostic.CS8509.severity = error

View File

@ -108,7 +108,7 @@ WebAssembly 静态托管页面示例
<AntButton type="primary">Hello World!</AntButton>
```
## 🔨 本地开发
## ⌨️ 本地开发
- 先安装 [.NET Core SDK](https://dotnet.microsoft.com/download/dotnet-core/3.1) 3.1.201 以上版本
- 安装 Node.js只用于样式文件和互操作所需 TS 文件的构建)
@ -140,6 +140,13 @@ WebAssembly 静态托管页面示例
如果你希望参与贡献,欢迎 [Pull Request](https://github.com/ElderJames/ant-design-blazor/pulls),或给我们 [报告 Bug](https://github.com/ElderJames/ant-design-blazor/issues/new) 。
### 贡献者
感谢所有为本项目做出过贡献的朋友。
<a href="https://github.com/ElderJames/ant-design-blazor/graphs/contributors"><img src="https://opencollective.com/ant-design-blazor/contributors.svg?width=890&button=false"/></a>
## 💕 支持本项目
本项目以 MIT 协议开源,为了能得到够更好的且可持续的发展,我们期望获得更多的支持者,我们将把所得款项用于社区活动和推广。你可以通过如下任何一种方式支持我们:

View File

@ -109,7 +109,7 @@ Regularly synchronize with Official Ant Design specifications, you can check the
<AntButton type="primary">Hello World!</AntButton>
```
## 🔨 Local Development
## ⌨️ Local Development
- Install [.NET Core SDK](https://dotnet.microsoft.com/download/dotnet-core/3.1) 3.1.201 or later.
- Install Node.js (only for building style files and interoperable TypeScript files)
@ -141,6 +141,12 @@ Check out this [issue](https://github.com/ElderJames/ant-design-blazor/issues/21
If you would like to contribute, feel free to create a [Pull Request](https://github.com/ElderJames/ant-design-blazor/pulls), or give us [Bug Report](https://github.com/ElderJames/ant-design-blazor/issues/new).
### Contributors
This project exists thanks to all the people who contribute.
<a href=" "><img src="https://opencollective.com/ant-design-blazor/contributors.svg?width=890&button=false"/></a>
## 💕 Donation
This project is an MIT-licensed open source project. In order to achieve better and sustainable development of the project, we expect to gain more backers. We will use the proceeds for community operations and promotion. You can support us in any of the following ways:
@ -163,7 +169,6 @@ If you encounter any problems in the process, feel free to ask for help via foll
<img src="./docs/assets/dingtalk.jpg" width="300">
</details>
## ☀️ License
[![AntBlazor](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](https://github.com/ElderJames/ant-design-blazor/blob/master/LICENSE)

View File

@ -35,6 +35,10 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="3.1.2" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="OneOf" Version="2.1.151" />
</ItemGroup>

View File

@ -1,13 +1,13 @@
@namespace AntBlazor
@inherits AntAlertBase
@namespace AntBlazor
@inherits AntDomComponentBase
@if (!isClosed)
@if (!_isClosed)
{
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" style="@Style" Id="@Id">
@if (ShowIcon)
{
<span role="img" aria-label="@iconType" class="@($"anticon anticon-{iconType} ant-alert-icon")">
<AntIcon type="@iconType" fill="currentColor"/>
<span role="img" aria-label="@IconType" class="@($"anticon anticon-{IconType} ant-alert-icon")">
<AntIcon type="@IconType" fill="currentColor"/>
</span>
}
@if (!string.IsNullOrEmpty(Message))

View File

@ -7,57 +7,78 @@ namespace AntBlazor
/// <summary>
/// Alert component for feedback.
/// </summary>
public class AntAlertBase : AntDomComponentBase
public partial class AntAlert : AntDomComponentBase
{
/// <summary>
/// Called when close animation is finished
/// Called when close animation is finished
/// </summary>
[Parameter] public EventCallback<MouseEventArgs> AfterClose { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> AfterClose { get; set; }
/// <summary>
/// Whether to show as banner
/// </summary>
[Parameter] public bool Banner { get; set; } = false;
[Parameter]
public bool Banner { get; set; } = false;
/// <summary>
/// Whether Alert can be closed
/// Whether Alert can be closed
/// </summary>
[Parameter] public bool Closable { get; set; } = false;
[Parameter]
public bool Closable { get; set; } = false;
/// <summary>
/// Close text to show
/// Close text to show
/// </summary>
[Parameter] public string CloseText { get; set; }
[Parameter]
public string CloseText { get; set; }
/// <summary>
/// Additional content of Alert
/// Additional content of Alert
/// </summary>
[Parameter] public string Description { get; set; }
[Parameter]
public string Description { get; set; }
/// <summary>
/// Custom icon, effective when showIcon is true
/// Custom icon, effective when showIcon is true
/// </summary>
[Parameter] public string Icon { get; set; }
[Parameter]
public string Icon { get; set; }
/// <summary>
/// Content of Aler
/// </summary>
[Parameter] public string Message { get; set; }
[Parameter]
public string Message { get; set; }
/// <summary>
/// Whether to show icon.
/// </summary>
[Parameter] public bool ShowIcon { get; set; }
[Parameter]
public bool ShowIcon { get; set; }
/// <summary>
/// Type of Alert styles, options: success, info, warning, error
/// Type of Alert styles, options: success, info, warning, error
/// </summary>
[Parameter] public string Type { get; set; } = AntAlertType.Default;
[Parameter]
public string Type { get; set; } = AntAlertType.Default;
/// <summary>
/// Callback when Alert is closed.
/// </summary>
[Parameter] public EventCallback<MouseEventArgs> OnClose { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClose { get; set; }
/// <summary>
/// Additional Content
/// </summary>
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Icon to show.
/// </summary>
protected string iconType => !string.IsNullOrEmpty(Icon) ? Icon
protected string IconType => !string.IsNullOrEmpty(Icon) ? Icon
: Type == AntAlertType.Success ? "check-circle"
: Type == AntAlertType.Info ? "info-circle"
: Type == AntAlertType.Warning ? "exclamation-circle"
@ -66,11 +87,13 @@ namespace AntBlazor
/// <summary>
/// Indicator if the component is closed or not.
/// </summary>
protected bool isClosed = false;
protected bool _isClosed = false;
/// <summary>
/// Just before we close the component we set this indicator to show a closing animation.
/// </summary>
protected bool isClosing = false;
protected bool _isClosing = false;
/// <summary>
/// Sets the default classes.
/// </summary>
@ -84,7 +107,7 @@ namespace AntBlazor
.If($"{prefixName}-closable", () => Closable)
.If($"{prefixName}-banner", () => Banner)
.If($"{prefixName}-with-description", () => !string.IsNullOrEmpty(Description))
.If($"{prefixName}-slide-up-leave", () => isClosing)
.If($"{prefixName}-slide-up-leave", () => _isClosing)
;
}
@ -106,6 +129,7 @@ namespace AntBlazor
CheckBannerMode();
SetClassMap();
}
private void CheckBannerMode()
{
if (Banner && string.IsNullOrEmpty(Type))
@ -121,15 +145,16 @@ namespace AntBlazor
/// <returns></returns>
protected async Task OnCloseHandler(MouseEventArgs args)
{
isClosing = true;
_isClosing = true;
if (OnClose.HasDelegate)
{
await OnClose.InvokeAsync(args);
}
await Task.Delay(300);
isClosed = true;
_isClosed = true;
await AfterCloseHandler(args);
}
/// <summary>
/// Handles the after close callback.
/// </summary>
@ -143,5 +168,4 @@ namespace AntBlazor
}
}
}
}

View File

@ -1,19 +1,19 @@
@namespace AntBlazor
@inherits AntAvatarBase
@namespace AntBlazor
@inherits AntDomComponentBase
<span class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id" @ref="Ref">
@if (!string.IsNullOrEmpty(icon) && hasIcon)
<span class="@ClassMapper.Class" style="@Style" id="@Id" @ref="Ref">
@if (!string.IsNullOrEmpty(Icon) && _hasIcon)
{
<AntIcon type="@icon" />
<AntIcon type="@Icon" />
}
@if (!string.IsNullOrEmpty(src) && hasSrc)
@if (!string.IsNullOrEmpty(Src) && _hasSrc)
{
<img src="@src" srcset="@srcSet" alt="@alt" @onerror="ImgError" />
<img src="@Src" srcset="@SrcSet" alt="@Alt" @onerror="ImgError" />
}
@if (!string.IsNullOrEmpty(text) && hasText)
@if (!string.IsNullOrEmpty(Text) && _hasText)
{
<span class="ant-avatar-string" @ref="textEl" style="@textStyles">
@text
<span class="ant-avatar-string" @ref="TextEl" style="@_textStyles">
@Text
</span>
}
</span>
</span>

View File

@ -0,0 +1,122 @@
using System.Collections;
using System.Globalization;
using System.Threading.Tasks;
using AntBlazor.JsInterop;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace AntBlazor
{
public partial class AntAvatar : AntDomComponentBase
{
[Parameter]
public string Shape { get; set; } = null;
[Parameter]
public string Size { get; set; } = AntSizeLDSType.Default;
[Parameter]
public string Text { get; set; }
[Parameter]
public string Src { get; set; }
[Parameter]
public string SrcSet { get; set; }
[Parameter]
public string Alt { get; set; }
[Parameter]
public string Icon { get; set; }
[Parameter]
public EventCallback<ErrorEventArgs> Error { get; set; }
private bool _hasText = false;
private bool _hasSrc = true;
private bool _hasIcon = false;
private string _textStyles = "";
protected ElementReference TextEl { get; set; }
private string _prefixCls = "ant-avatar";
private readonly Hashtable _sizeMap = new Hashtable() { ["large"] = "lg", ["small"] = "sm" };
private void SetClassMap()
{
ClassMapper.Clear()
.Add(_prefixCls)
.If($"{_prefixCls}-{this._sizeMap[this.Size]}", () => _sizeMap.ContainsKey(Size))
.If($"{_prefixCls}-{this.Shape}", () => !string.IsNullOrEmpty(Shape))
.If($"{_prefixCls}-icon", () => !string.IsNullOrEmpty(Icon))
.If($"{_prefixCls}-image", () => _hasSrc)
;
}
protected override async Task OnParametersSetAsync()
{
this._hasText = string.IsNullOrEmpty(this.Src) && !string.IsNullOrEmpty(this.Text);
this._hasIcon = string.IsNullOrEmpty(this.Src) && !string.IsNullOrEmpty(this.Icon);
this._hasSrc = !string.IsNullOrEmpty(this.Src);
SetClassMap();
await CalcStringSize();
SetSizeStyle();
await base.OnParametersSetAsync();
}
protected async Task ImgError(ErrorEventArgs args)
{
await Error.InvokeAsync(args);
this._hasSrc = false;
this._hasIcon = false;
this._hasText = false;
if (!string.IsNullOrEmpty(this.Icon))
{
this._hasIcon = true;
}
else if (!string.IsNullOrEmpty(this.Text))
{
this._hasText = true;
}
this.SetClassMap();
await CalcStringSize();
SetSizeStyle();
}
private void SetSizeStyle()
{
if (decimal.TryParse(this.Size, out var pxSize))
{
string size = StyleHelper.ToCssPixel(pxSize.ToString(CultureInfo.InvariantCulture));
Style += $";width:{size};";
Style += $"height:{size};";
Style += $"line-height:{size};";
if (this._hasIcon)
{
Style += $"font-size:calc(${size} / 2)";
}
}
}
private async Task CalcStringSize()
{
if (!this._hasText)
{
return;
}
var childrenWidth = (await this.JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, this.TextEl)).offsetWidth;
var avatarWidth = (await this.JsInvokeAsync<DomRect>(JSInteropConstants.getBoundingClientRect, this.Ref)).width;
var scale = avatarWidth - 8 < childrenWidth ? (avatarWidth - 8) / childrenWidth : 1;
this._textStyles = $"transform: scale({scale}) translateX(-50%);";
if (decimal.TryParse(this.Size, out var pxSize))
{
this._textStyles += $"lineHeight:{pxSize}px;";
}
}
}
}

View File

@ -1,114 +0,0 @@
using System.Collections;
using System.Globalization;
using System.Threading.Tasks;
using AntBlazor.JsInterop;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace AntBlazor
{
public class AntAvatarBase : AntDomComponentBase
{
[Parameter] public string shape { get; set; } = null;
[Parameter] public string size { get; set; } = AntSizeLDSType.Default;
[Parameter] public string text { get; set; }
[Parameter] public string src { get; set; }
[Parameter] public string srcSet { get; set; }
[Parameter] public string alt { get; set; }
[Parameter] public string icon { get; set; }
[Parameter] public EventCallback<ErrorEventArgs> Error { get; set; }
protected bool hasText = false;
protected bool hasSrc = true;
protected bool hasIcon = false;
protected string textStyles = "";
protected ElementReference textEl { get; set; }
private string prefixCls = "ant-avatar";
private Hashtable sizeMap = new Hashtable() { ["large"] = "lg", ["small"] = "sm" };
private void SetClassMap()
{
ClassMapper.Clear()
.Add(prefixCls)
.If($"{prefixCls}-{this.sizeMap[this.size]}", () => sizeMap.ContainsKey(size))
.If($"{prefixCls}-{this.shape}", () => !string.IsNullOrEmpty(shape))
.If($"{prefixCls}-icon", () => !string.IsNullOrEmpty(icon))
.If($"{prefixCls}-image", () => hasSrc)
;
}
protected override async Task OnParametersSetAsync()
{
this.hasText = string.IsNullOrEmpty(this.src) && !string.IsNullOrEmpty(this.text);
this.hasIcon = string.IsNullOrEmpty(this.src) && !string.IsNullOrEmpty(this.icon);
this.hasSrc = !string.IsNullOrEmpty(this.src);
SetClassMap();
await calcStringSize();
setSizeStyle();
await base.OnParametersSetAsync();
}
protected async Task ImgError(ErrorEventArgs args)
{
await Error.InvokeAsync(args);
this.hasSrc = false;
this.hasIcon = false;
this.hasText = false;
if (!string.IsNullOrEmpty(this.icon))
{
this.hasIcon = true;
}
else if (!string.IsNullOrEmpty(this.text))
{
this.hasText = true;
}
this.SetClassMap();
await calcStringSize();
setSizeStyle();
}
private void setSizeStyle()
{
if (decimal.TryParse(this.size, out var pxSize))
{
string size = StyleHelper.ToCssPixel(pxSize.ToString(CultureInfo.InvariantCulture));
Style += $";width:{size};";
Style += $"height:{size};";
Style += $"line-height:{size};";
if (this.hasIcon)
{
Style += $"font-size:calc(${size} / 2)";
}
}
}
private async Task calcStringSize()
{
if (!this.hasText)
{
return;
}
var childrenWidth = (await this.JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, this.textEl)).offsetWidth;
var avatarWidth = (await this.JsInvokeAsync<DomRect>(JSInteropConstants.getBoundingClientRect, this.Ref)).width;
var scale = avatarWidth - 8 < childrenWidth ? (avatarWidth - 8) / childrenWidth : 1;
this.textStyles = $"transform: scale({scale}) translateX(-50%);";
if (decimal.TryParse(this.size, out var pxSize))
{
this.textStyles += $"lineHeight:{pxSize}px;";
}
}
}
}

View File

@ -1,7 +1,8 @@
@namespace AntBlazor
@inherits AntBackTopBase
<div class="@BackTopClassMapper.Class" @onclick="OnClick">
<div class="@BackTopContentClassMapper.Class">
<div class="@BackTopIconClassMapper.Class"></div>
</div>
</div>
@namespace AntBlazor
@inherits AntDomComponentBase
<div class="@BackTopClassMapper.Class" @onclick="OnClick">
<div class="@BackTopContentClassMapper.Class">
<div class="@BackTopIconClassMapper.Class"></div>
</div>
</div>

View File

@ -1,37 +1,32 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace AntBlazor
{
public class AntBackTopBase : AntDomComponentBase
public partial class AntBackTop : AntDomComponentBase
{
[Parameter]
public string Title { get; set; }
protected ClassMapper BackTopClassMapper { get; set; } = new ClassMapper();
protected ClassMapper BackTopContentClassMapper { get; set; } = new ClassMapper();
protected ClassMapper BackTopIconClassMapper { get; set; } = new ClassMapper();
protected ClassMapper InputClassMapper { get; set; } = new ClassMapper();
protected async Task OnClick(MouseEventArgs args)
{
await JsInvokeAsync(JSInteropConstants.backTop, "BodyConatainer");
await JsInvokeAsync(JSInteropConstants.backTop, "BodyContainer");
}
//protected async Task OnScroll(EventArgs args)
//{
// await JsInvokeAsync(JSInteropConstants.getDomInfo, Ref);
//}
protected override void OnInitialized()
{
SetClass();
base.OnInitialized();
}
protected void SetClass()
{
string prefixCls = "ant-back-top";

View File

@ -1,38 +1,38 @@
@namespace AntBlazor
@inherits AntBadgeBase
@namespace AntBlazor
@inherits AntDomComponentBase
<span class="@ClassMapper.Class" @attributes="Attributes" Id="@Id">
<span class="@ClassMapper.Class" style="@Style" @ref="Ref" Id="@Id">
@if (ChildContent != null)
@if (ChildContent != null)
{
@ChildContent
@if ((Count == 0 && ShowZero) || Count > 0)
{
@ChildContent
@if ((Count == 0 && ShowZero) || Count > 0)
{
<sup class="@($"ant-badge-count {@class}")" style="@Style" title="@DisplayCount">@DisplayCount</sup>
}
@if (Dot && Count != 0 || (Dot && ShowZero))
{
<sup class="ant-scroll-number ant-badge-dot" style="@Style"></sup>
}
<sup class="@($"ant-badge-count {Class}")" style="@Style" title="@DisplayCount">@DisplayCount</sup>
}
else
@if (Dot && Count != 0 || (Dot && ShowZero))
{
@if (!string.IsNullOrEmpty(Status))
{
<span class="@($"ant-badge-status-dot ant-badge-status-{Status}")"></span>
}
@if (!string.IsNullOrEmpty(Color))
{
<span class="@($"ant-badge-status-dot ant-badge-status-{Color}")"></span>
}
@if (!string.IsNullOrEmpty(Text))
{
<span class="ant-badge-status-text">@Text</span>
}
@if ((Count == 0 && ShowZero) || Count > 0)
{
<sup class="@($"ant-scroll-number ant-badge-count ant-badge-multiple-words {@class}")" style="@Style" title="@DisplayCount">@DisplayCount</sup>
}
<sup class="ant-scroll-number ant-badge-dot" style="@Style"></sup>
}
</span>
}
else
{
@if (!string.IsNullOrEmpty(Status))
{
<span class="@($"ant-badge-status-dot ant-badge-status-{Status}")"></span>
}
@if (!string.IsNullOrEmpty(Color))
{
<span class="@($"ant-badge-status-dot ant-badge-status-{Color}")"></span>
}
@if (!string.IsNullOrEmpty(Text))
{
<span class="ant-badge-status-text">@Text</span>
}
@if ((Count == 0 && ShowZero) || Count > 0)
{
<sup class="@($"ant-scroll-number ant-badge-count ant-badge-multiple-words {Class}")" style="@Style" title="@DisplayCount">@DisplayCount</sup>
}
}
</span>

View File

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
using System;
namespace AntBlazor
@ -6,49 +6,68 @@ namespace AntBlazor
/// <summary>
/// Small numerical value or status descriptor for UI elements.
/// </summary>
public class AntBadgeBase : AntDomComponentBase
public partial class AntBadge : AntDomComponentBase
{
/// <summary>
/// Customize Badge dot color
/// </summary>
[Parameter] public string Color { get; set; }
[Parameter]
public string Color { get; set; }
/// <summary>
/// Number to show in badge
/// </summary>
[Parameter] public int? Count { get; set; }
[Parameter]
public int? Count { get; set; }
/// <summary>
/// Whether to display a red dot instead of count
/// </summary>
[Parameter] public bool Dot { get; set; } = false;
[Parameter]
public bool Dot { get; set; } = false;
/// <summary>
/// Set offset of the badge dot, like[x, y]
/// </summary>
[Parameter] public Tuple<int, int> Offset { get; set; }
[Parameter]
public Tuple<int, int> Offset { get; set; }
/// <summary>
/// Max count to show
/// </summary>
[Parameter] public int OverflowCount { get; set; } = 99;
[Parameter]
public int OverflowCount { get; set; } = 99;
/// <summary>
/// Whether to show badge when count is zero
/// </summary>
[Parameter] public bool ShowZero { get; set; } = false;
[Parameter]
public bool ShowZero { get; set; } = false;
/// <summary>
/// Set Badge as a status dot
/// </summary>
[Parameter] public string Status { get; set; }
[Parameter]
public string Status { get; set; }
/// <summary>
/// If status is set, text sets the display text of the status dot
/// </summary>
[Parameter] public string Text { get; set; }
[Parameter]
public string Text { get; set; }
/// <summary>
/// Text to show when hovering over the badge
/// </summary>
[Parameter] public string Title { get; set; }
[Parameter]
public string Title { get; set; }
/// <summary>
/// Wrapping this item.
/// </summary>
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// Sets the default CSS classes.
/// </summary>
@ -61,12 +80,14 @@ namespace AntBlazor
.If($"{prefixName}-not-a-wrapper", () => ChildContent == null)
;
}
/// <summary>
/// Shows the Count and takes into account the OverFlowCount.
/// </summary>
protected string DisplayCount => Count > OverflowCount ? $"{OverflowCount}+"
: Count == 0 && !ShowZero ? string.Empty
: Count.ToString();
/// <summary>
/// Startup code
/// </summary>
@ -79,7 +100,7 @@ namespace AntBlazor
}
/// <summary>
/// Runs everytime a parameter is set.
/// Runs every time a parameter is set.
/// </summary>
protected override void OnParametersSet()
{
@ -87,4 +108,4 @@ namespace AntBlazor
SetClassMap();
}
}
}
}

View File

@ -1,15 +1,15 @@
@namespace AntBlazor
@inherits AntBreadcrumbBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<span class="@ClassMapper.Class" style="@Style" @attributes="Attributes" id="@Id" @ref="Ref">
<span class="@ClassMapper.Class" style="@Style" id="@Id" @ref="Ref">
@ChildContent
@if (autoGenerate)
@if (AutoGenerate)
{
foreach (var breadcrumb in _breadcrumbs)
{
<AntBreadcrumbItem>
<a href="@breadcrumb.Url" @onclick="(e)=>navigate(breadcrumb.Url, e)">@breadcrumb.Label</a>
<a href="@breadcrumb.Url" @onclick="(e)=>Navigate(breadcrumb.Url, e)">@breadcrumb.Label</a>
</AntBreadcrumbItem>
}

View File

@ -1,30 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace AntBlazor
{
public class AntBreadcrumbBase : AntDomComponentBase
public partial class AntBreadcrumb : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public bool autoGenerate { get; set; } = false;
[Parameter]
public bool AutoGenerate { get; set; } = false;
[Parameter] public string separator { get; set; } = "/";
[Parameter]
public string Separator { get; set; } = "/";
[Parameter] public string routeLabel { get; set; } = "breadcrumb";
[Parameter]
public string RouteLabel { get; set; } = "breadcrumb";
[Inject]
public NavigationManager navigationManager { get; set; }
public NavigationManager NavigationManager { get; set; }
protected BreadcrumbOption[] _breadcrumbs = { };
protected void navigate(string url, MouseEventArgs e)
protected void Navigate(string url, MouseEventArgs e)
{
navigationManager.NavigateTo(url);
NavigationManager.NavigateTo(url);
}
protected override void OnInitialized()
@ -34,7 +35,7 @@ namespace AntBlazor
base.OnInitialized();
}
private void registerRouterChange()
private void RegisterRouterChange()
{
}
}
@ -47,4 +48,4 @@ namespace AntBlazor
public string Url { get; set; }
}
}
}

View File

@ -1,9 +1,9 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<span class="@ClassMapper.Class" style="@Style" @attributes="Attributes" id="@Id" @ref="Ref">
<span class="@ClassMapper.Class" style="@Style" id="@Id" @ref="Ref">
@if (overlay != null)
@if (Overlay != null)
{
<span class="ant-breadcrumb-overlay-link" nz-dropdown [nzDropdownMenu]="nzOverlay">
<span class="ant-breadcrumb-link">
@ -19,10 +19,10 @@
</span>
}
@if (BreadCrumb.separator != null)
@if (BreadCrumb.Separator != null)
{
<span class="ant-breadcrumb-separator">
@BreadCrumb.separator
@BreadCrumb.Separator
</span>
}
@ -34,7 +34,7 @@
public RenderFragment ChildContent { get; set; }
[Parameter]
public object overlay { get; set; }
public object Overlay { get; set; }
[CascadingParameter]
public AntBreadcrumb BreadCrumb { get; set; }

View File

@ -1,15 +1,15 @@
@namespace AntBlazor
@inherits AntButtonBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<button class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id" @onclick="OnClick">
@if (loading)
<button class="@ClassMapper.Class" style="@Style" id="@Id" @onclick="OnClick" disabled="@Disabled">
@if (Loading)
{
<AntIcon type="loading"></AntIcon>
<AntIcon Type="loading"></AntIcon>
}
@if (!string.IsNullOrEmpty(icon))
@if (!string.IsNullOrEmpty(Icon))
{
<AntIcon type="@icon" Style="@iconStyle"></AntIcon>
<AntIcon Type="@Icon" Style="@IconStyle"></AntIcon>
}
@ChildContent

View File

@ -0,0 +1,115 @@
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace AntBlazor
{
public partial class AntButton : AntDomComponentBase
{
[Parameter]
public bool Block { get; set; } = false;
[Parameter]
public bool Ghost { get; set; } = false;
[Parameter]
public bool Search { get; set; } = false;
[Parameter]
public bool Loading { get; set; } = false;
[Parameter]
public string Type { get; set; } = AntButtonType.Default;
[Parameter]
public string Shape { get; set; } = null;
[Parameter]
public string Size { get; set; } = AntSizeLDSType.Default;
[Parameter]
public string Icon { get; set; }
[Parameter]
public bool Disabled { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> Onclick { get; set; }
[Inject] private NavigationManager NavigationManger { get; set; }
public IList<AntIcon> Icons { get; set; } = new List<AntIcon>();
public AntNavLink Link { get; set; }
protected string IconStyle { get; set; }
private readonly bool _isInDropdown = false;
private bool _iconOnly = false;
protected void SetClassMap()
{
string prefixName = "ant-btn";
Hashtable sizeMap = new Hashtable()
{
["large"] = "lg",
["small"] = "sm"
};
ClassMapper.Clear()
.Add("ant-btn")
.If($"{prefixName}-{this.Type}", () => !string.IsNullOrEmpty(Type))
.If($"{prefixName}-{Shape}", () => !string.IsNullOrEmpty(Shape))
.If($"{prefixName}-{sizeMap[this.Size]}", () => sizeMap.ContainsKey(Size))
.If($"{prefixName}-loading", () => Loading)
.If($"{prefixName}-icon-only", () => Icons.Count == 0 && !this.Search && !this._isInDropdown && this.ChildContent == null)
.If($"{prefixName}-background-ghost", () => Ghost)
.If($"{prefixName}-block", () => this.Block)
.If($"ant-input-search-button", () => this.Search)
;
}
protected override void OnInitialized()
{
base.OnInitialized();
if (Link != null && string.IsNullOrEmpty(this.Type))
{
this.Type = AntButtonType.Link;
}
SetClassMap();
}
protected override void OnParametersSet()
{
base.OnParametersSet();
SetClassMap();
UpdateIconDisplay(this.Loading);
if (Type == "link")
{
}
}
private void UpdateIconDisplay(bool vlaue)
{
IconStyle = $"display:{(vlaue ? "none" : "inline-block")}";
}
protected async Task OnClick(MouseEventArgs args)
{
if (Link != null)
{
NavigationManger.NavigateTo(Link.Href);
}
if (Onclick.HasDelegate)
{
await Onclick.InvokeAsync(args);
}
}
}
}

View File

@ -1,103 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace AntBlazor
{
public class AntButtonBase : AntDomComponentBase
{
[Parameter] public bool block { get; set; } = false;
[Parameter] public bool ghost { get; set; } = false;
[Parameter] public bool search { get; set; } = false;
[Parameter] public bool loading { get; set; } = false;
[Parameter] public string type { get; set; } = AntButtonType.Default;
[Parameter] public string shape { get; set; } = null;
[Parameter] public string size { get; set; } = AntSizeLDSType.Default;
[Parameter] public string icon { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> onclick { get; set; }
[Inject] private NavigationManager NavigationManger { get; set; }
public IList<AntIcon> Icons { get; set; } = new List<AntIcon>();
public AntNavLink Link { get; set; }
protected string iconStyle { get; set; }
private bool isInDropdown = false;
private bool iconOnly = false;
protected void SetClassMap()
{
string prefixName = "ant-btn";
Hashtable sizeMap = new Hashtable()
{
["large"] = "lg",
["small"] = "sm"
};
ClassMapper.Clear()
.Add("ant-btn")
.If($"{prefixName}-{this.type}", () => !string.IsNullOrEmpty(type))
.If($"{prefixName}-{shape}", () => !string.IsNullOrEmpty(shape))
.If($"{prefixName}-{sizeMap[this.size]}", () => sizeMap.ContainsKey(size))
.If($"{prefixName}-loading", () => loading)
.If($"{prefixName}-icon-only", () => Icons.Count == 0 && !this.search && !this.isInDropdown && this.ChildContent == null)
.If($"{prefixName}-background-ghost", () => ghost)
.If($"{prefixName}-block", () => this.block)
.If($"ant-input-search-button", () => this.search)
;
}
protected override void OnInitialized()
{
base.OnInitialized();
if (Link != null && string.IsNullOrEmpty(this.type))
{
this.type = AntButtonType.Link;
}
SetClassMap();
}
protected override void OnParametersSet()
{
base.OnParametersSet();
SetClassMap();
updateIconDisplay(this.loading);
if (type == "link")
{
}
}
private void updateIconDisplay(bool vlaue)
{
iconStyle = $"display:{(vlaue ? "none" : "inline-block")}";
}
protected async Task OnClick(MouseEventArgs args)
{
if (Link != null)
{
NavigationManger.NavigateTo(Link.Href);
}
if (onclick.HasDelegate)
{
await onclick.InvokeAsync(args);
}
}
}
}

View File

@ -1,8 +1,8 @@
@namespace AntBlazor
@inherits AntButtonGroupBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" style="@Style" id="@Id">
@ChildContent
</div>
</CascadingValue>

View File

@ -3,14 +3,14 @@ using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public class AntButtonGroupBase : AntDomComponentBase
public partial class AntButtonGroup : AntDomComponentBase
{
[Parameter] public RenderFragment ChildContent { get; set; }
private string _size;
[Parameter]
public string size
public string Size
{
get => _size;
set
@ -20,15 +20,15 @@ namespace AntBlazor
}
}
public IList<AntButton> Buttons = new List<AntButton>();
public IList<AntButton> _buttons = new List<AntButton>();
internal bool isInDropdown = false;
internal bool _isInDropdown = false;
public void SetClassMap()
{
var prefixName = "ant-btn-group";
ClassMapper.Clear().Add(prefixName)
.If("ant-dropdown-button", () => isInDropdown)
.If("ant-dropdown-button", () => _isInDropdown)
.If($"{prefixName}-lg", () => this._size == "large")
.If($"{prefixName}-sm", () => this._size == "small");
}
@ -39,4 +39,4 @@ namespace AntBlazor
SetClassMap();
}
}
}
}

View File

@ -1,7 +1,8 @@
@namespace AntBlazor
@inherits AntCardBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" style="@Style" id="@Id">
@if (Title != null || Extra != null || AntCardTab != null)
{
<div class="ant-card-head">
@ -34,8 +35,8 @@
</div>
}
<div class="ant-card-body" style="@bodyStyle">
@if (!loading)
<div class="ant-card-body" style="@BodyStyle">
@if (!Loading)
{
@Body
@ChildContent
@ -58,4 +59,4 @@
</ul>
}
</div>
</CascadingValue>
</CascadingValue>

View File

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public class AntCardBase : AntDomComponentBase
public partial class AntCard : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
@ -12,16 +12,16 @@ namespace AntBlazor
public RenderFragment Body { get; set; }
[Parameter]
public bool bordered { get; set; } = false;
public bool Bordered { get; set; } = false;
[Parameter]
public bool hoverable { get; set; } = false;
public bool Hoverable { get; set; } = false;
[Parameter]
public bool loading { get; set; } = false;
public bool Loading { get; set; } = false;
[Parameter]
public string bodyStyle { get; set; }
public string BodyStyle { get; set; }
[Parameter]
public RenderFragment Cover { get; set; }
@ -30,10 +30,10 @@ namespace AntBlazor
public IList<RenderFragment> Actions { get; set; } = new List<RenderFragment>();
[Parameter]
public string type { get; set; }
public string Type { get; set; }
[Parameter]
public string size { get; set; }
public string Size { get; set; }
[Parameter]
public RenderFragment Title { get; set; }
@ -44,18 +44,18 @@ namespace AntBlazor
[Parameter]
public RenderFragment AntCardTab { get; set; }
internal IList<AntCardGrid> grids { get; set; } = new List<AntCardGrid>();
internal IList<AntCardGrid> Grids { get; set; } = new List<AntCardGrid>();
protected void setClassMap()
protected void SetClassMap()
{
this.ClassMapper.Clear()
.Add("ant-card")
.If("ant-card-loading", () => loading)
.If("ant-card-bordered", () => bordered)
.If("ant-card-hoverable", () => hoverable)
.If("ant-card-small", () => size == "small")
.If("ant-card-contain-grid", () => grids.Count > 0)
.If("ant-card-type-inner", () => type == "inner")
.If("ant-card-loading", () => Loading)
.If("ant-card-bordered", () => Bordered)
.If("ant-card-hoverable", () => Hoverable)
.If("ant-card-small", () => Size == "small")
.If("ant-card-contain-grid", () => Grids.Count > 0)
.If("ant-card-type-inner", () => Type == "inner")
.If("ant-card-contain-tabs", () => AntCardTab != null)
;
}
@ -63,7 +63,7 @@ namespace AntBlazor
protected override void OnInitialized()
{
base.OnInitialized();
setClassMap();
SetClassMap();
}
}
}
}

View File

@ -1,7 +1,7 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" style="@Style" id="@Id">
@ChildContent
</div>
@ -9,13 +9,14 @@
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public bool hoverable { get; set; }
[Parameter]
public bool Hoverable { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
ClassMapper.Add("ant-card-grid")
.If("ant-card-hoverable", () => hoverable);
.If("ant-card-hoverable", () => Hoverable);
}
}

View File

@ -1,7 +1,7 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" style="@Style" id="@Id">
@if (Avatar != null)
{
<div class="ant-card-meta-avatar">
@ -27,11 +27,14 @@
@code{
[Parameter] public RenderFragment Title { get; set; }
[Parameter]
public RenderFragment Title { get; set; }
[Parameter] public RenderFragment Description { get; set; }
[Parameter]
public RenderFragment Description { get; set; }
[Parameter] public RenderFragment Avatar { get; set; }
[Parameter]
public RenderFragment Avatar { get; set; }
protected override void OnInitialized()
{
@ -39,4 +42,4 @@
ClassMapper.Add("ant-card-meta");
}
}
}

View File

@ -1,19 +1,19 @@
@namespace AntBlazor
@inherits AntCheckboxBase
@inherits AntDomComponentBase
<label class="ant-checkbox-wrapper" style="@Style" @attributes="Attributes" Id="@Id" @ref="Ref">
<label class="ant-checkbox-wrapper" style="@Style" id="@Id" @ref="Ref">
<span class="@ClassMapper.Class" style="">
<input @ref="inputElement"
value="@(value)"
checked="@(@checked)"
disabled="@(disabled)"
@onchange="@inputCheckedChange"
@attributes="@inputAttributes"
<input @ref="_inputElement"
value="@(Value)"
checked="@(Checked)"
disabled="@(Disabled)"
@onchange="@InputCheckedChange"
@attributes="@InputAttributes"
type="checkbox"
class="ant-checkbox-input" />
<span class="ant-checkbox-inner"></span>
</span>
<span @ref="contentElement">
<span @ref="_contentElement">
@ChildContent
</span>
</label>

View File

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public partial class AntCheckbox: AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
protected Action<bool> _onChange;
protected Func<object> _onTouched;
protected ElementReference _inputElement;
protected ElementReference _contentElement;
[Parameter]
public EventCallback<bool> CheckedChange { get; set; }
[Parameter]
public string Value { get; set; }
[Parameter]
public bool AutoFocus { get; set; }
[Parameter]
public bool Disabled { get; set; }
[Parameter]
public bool Indeterminate { get; set; }
[Parameter]
public bool Checked { get; set; }
[CascadingParameter]
public AntCheckboxGroup CheckboxGroup { get; set; }
protected Dictionary<string, object> InputAttributes { get; set; }
protected string _contentStyles = "";
protected override void OnParametersSet()
{
SetClass();
base.OnParametersSet();
}
protected override async Task OnInitializedAsync()
{
if (this is AntCheckbox checkbox)
{
CheckboxGroup?.CheckboxItems.Add(checkbox);
}
}
protected void SetClass()
{
var prefixName = "ant-checkbox";
ClassMapper.Clear()
.Add(prefixName)
.If($"{prefixName}-checked", () => Checked && !Indeterminate)
.If($"{prefixName}-disabled", () => Disabled)
.If($"{prefixName}-indeterminate", () => Indeterminate);
}
protected async Task InputCheckedChange(ChangeEventArgs args)
{
await InnerCheckedChange(Convert.ToBoolean(args.Value));
}
protected async Task InnerCheckedChange(bool @checked)
{
if (!this.Disabled)
{
this.Checked = @checked;
_onChange?.Invoke(this.Checked);
await this.CheckedChange.InvokeAsync(this.Checked);
CheckboxGroup?.OnCheckboxChange(this);
}
}
protected void UpdateAutoFocus()
{
if (this.AutoFocus)
{
InputAttributes.Add("autofocus", "autofocus");
}
else
{
InputAttributes.Remove("autofocus");
}
}
protected void WriteValue(bool value)
{
this.Checked = value;
}
}
}

View File

@ -1,105 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace AntBlazor
{
public class AntCheckboxBase : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
protected Action<bool> onChange;
protected Func<object> onTouched;
protected ElementReference inputElement;
protected ElementReference contentElement;
[Parameter]
public EventCallback<bool> checkedChange { get; set; }
[Parameter]
public string value { get; set; }
[Parameter]
public bool autoFocus { get; set; }
[Parameter]
public bool disabled { get; set; }
[Parameter]
public bool indeterminate { get; set; }
[Parameter]
public bool @checked { get; set; }
[CascadingParameter]
public AntCheckboxGroup CheckboxGroup { get; set; }
protected Dictionary<string, object> inputAttributes { get; set; }
protected string contentStyles = "";
protected override void OnParametersSet()
{
setClass();
base.OnParametersSet();
}
protected override async Task OnInitializedAsync()
{
if (this is AntCheckbox checkbox)
{
CheckboxGroup?.CheckboxItems.Add(checkbox);
}
await base.OnInitializedAsync();
}
protected void setClass()
{
var prefixName = "ant-checkbox";
ClassMapper.Clear()
.Add(prefixName)
.If($"{prefixName}-checked", () => @checked && !indeterminate)
.If($"{prefixName}-disabled", () => disabled)
.If($"{prefixName}-indeterminate", () => indeterminate);
}
protected async Task inputCheckedChange(ChangeEventArgs args)
{
await innerCheckedChange(Convert.ToBoolean(args.Value));
}
protected async Task innerCheckedChange(bool @checked)
{
if (!this.disabled)
{
this.@checked = @checked;
onChange?.Invoke(this.@checked);
await this.checkedChange.InvokeAsync(this.@checked);
CheckboxGroup?.OnCheckboxChange(this);
}
}
protected void updateAutoFocus()
{
if (this.autoFocus)
{
inputAttributes.Add("autofocus", "autofocus");
}
else
{
inputAttributes.Remove("autofocus");
}
}
protected void writeValue(bool value)
{
this.@checked = value;
}
}
}

View File

@ -1,18 +1,18 @@
@namespace AntBlazor
@inherits AntCheckboxGroupBase
@inherits AntDomComponentBase
<CascadingValue Value="this">
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id" @ref="Ref">
@foreach (var option in options)
{
<AntCheckbox class="ant-checkbox-group-item"
disabled="option.disabled || disabled"
checked="@(option.@checked)"
value="@option.value"
checkedChange="@onOptionChange">
<span>@option.label</span>
</AntCheckbox>
}
@ChildContent
</div>
</CascadingValue>
<CascadingValue Value="this">
<div class="@ClassMapper.Class" style="@Style" id="@Id" @ref="Ref">
@foreach (var option in Options)
{
<AntCheckbox class="ant-checkbox-group-item"
Disabled="option.Disabled || Disabled"
Checked="@(option.Checked)"
Value="@option.Value"
CheckedChange="OnOptionChange">
<span>@option.Label</span>
</AntCheckbox>
}
@ChildContent
</div>
</CascadingValue>

View File

@ -6,19 +6,19 @@ using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public class AntCheckboxGroupBase : AntDomComponentBase
public partial class AntCheckboxGroup : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public IList<AntCheckbox> CheckboxItems { get; set; } = new List<AntCheckbox>();
[Parameter] public EventCallback<object> OnChange { get; set; }
[Parameter] public EventCallback<string[]> ValueChanged { get; set; }
public Action onTouched;
public Action _onTouched;
[Parameter]
public CheckBoxOption[] options { get; set; } = Array.Empty<CheckBoxOption>();
public CheckBoxOption[] Options { get; set; } = Array.Empty<CheckBoxOption>();
[Parameter]
public IList<string> Value { get; set; } = Array.Empty<string>();
@ -27,37 +27,36 @@ namespace AntBlazor
{
foreach (var item in Value)
{
options.Where(o => o.value == item).ForEach(o => o.@checked = true);
Options.Where(o => o.Value == item).ForEach(o => o.Checked = true);
}
await base.OnParametersSetAsync();
}
[Parameter]
public bool disabled { get; set; }
public bool Disabled { get; set; }
public AntCheckboxGroupBase()
public AntCheckboxGroup()
{
ClassMapper.Add("ant-checkbox-group");
}
public async void onOptionChange(bool change)
public async void OnOptionChange(bool change)
{
await this.OnChange.InvokeAsync(this.options);
await this.ValueChanged.InvokeAsync(this.Options.Where(x => x.Checked).Select(x => x.Value).ToArray());
StateHasChanged();
}
internal async Task OnCheckboxChange(AntCheckboxBase checkboxBase)
internal async Task OnCheckboxChange(AntCheckbox checkboxBase)
{
if (checkboxBase is AntCheckbox checkbox)
{
int index = CheckboxItems.IndexOf(checkbox);
if (options[index] != null)
if (Options[index] != null)
{
options[index].@checked = checkbox.@checked;
Options[index].Checked = checkbox.Checked;
}
}
StateHasChanged();
}
}
}
}

View File

@ -7,10 +7,12 @@ namespace AntBlazor
{
public class CheckBoxOption
{
public string label { get; set; }
public string Label { get; set; }
public string value { get; set; }
public bool @checked { get; set; }
public bool disabled { get; set; }
public string Value { get; set; }
public bool Checked { get; set; }
public bool Disabled { get; set; }
}
}
}

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
@ -11,11 +11,11 @@ namespace AntBlazor
[Parameter]
public ForwardRef RefBack { get; set; }
private readonly Queue<Func<Task>> afterRenderCallQuene = new Queue<Func<Task>>();
private readonly Queue<Func<Task>> _afterRenderCallQuene = new Queue<Func<Task>>();
protected void CallAfterRender(Func<Task> action)
{
afterRenderCallQuene.Enqueue(action);
_afterRenderCallQuene.Enqueue(action);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
@ -26,10 +26,10 @@ namespace AntBlazor
await OnFirstAfterRenderAsync();
}
if (afterRenderCallQuene.Count > 0)
if (_afterRenderCallQuene.Count > 0)
{
var actions = afterRenderCallQuene.ToArray();
afterRenderCallQuene.Clear();
var actions = _afterRenderCallQuene.ToArray();
_afterRenderCallQuene.Clear();
foreach (var action in actions)
{
@ -115,4 +115,4 @@ namespace AntBlazor
#endregion Hack to fix https://github.com/aspnet/AspNetCore/issues/11159
}
}
}

View File

@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.CompilerServices;
using Microsoft.AspNetCore.Components.Rendering;
@ -17,14 +17,10 @@ namespace AntBlazor
builder.OpenElement(0, Tag);
builder.AddAttribute(1, "class", ClassMapper.Class);
builder.AddAttribute(2, "style", GenerateStyle());
builder.AddMultipleAttributes(3,
RuntimeHelpers
.TypeCheck<global::System.Collections.Generic.IEnumerable<
global::System.Collections.Generic.KeyValuePair<string, object>>>(Attributes));
builder.AddAttribute(4, "Id", Id);
builder.AddAttribute(4, "id", Id);
builder.AddElementReferenceCapture(5, (__value) => { Ref = __value; });
builder.AddContent(7, ChildContent);
builder.CloseElement();
}
}
}
}

View File

@ -1,16 +1,14 @@
using System.Collections.Generic;
using System.Runtime.InteropServices.ComTypes;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public abstract class AntDomComponentBase : AntComponentBase
{
[Parameter]
public string Id { get; set; } = IdGeneratorHelper.Generate("antBlazor_id_");
public string Id { get; set; } = IdGeneratorHelper.Generate("ant-blazor-");
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> Attributes { get; set; } = new Dictionary<string, object>();
//[Parameter(CaptureUnmatchedValues = true)]
//public Dictionary<string, object> Attributes { get; set; } = new Dictionary<string, object>();
private ElementReference _ref;
@ -35,15 +33,15 @@ namespace AntBlazor
protected AntDomComponentBase()
{
ClassMapper
.Get(() => this.@class)
.Get(() => this.Class)
.Get(() => this.AntTheme?.GetClass());
}
/// <summary>
/// Specifies one or more classnames for an DOM element.
/// Specifies one or more class names for an DOM element.
/// </summary>
[Parameter]
public string @class
public string Class
{
get => _class;
set
@ -75,4 +73,4 @@ namespace AntBlazor
private string _class;
private string _style;
}
}
}

View File

@ -12,12 +12,12 @@ namespace AntBlazor
{
public class HtmlRenderer : Renderer
{
private static readonly HashSet<string> SelfClosingElements = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
private static readonly HashSet<string> _selfClosingElements = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"
};
private static readonly Task CanceledRenderTask = Task.FromCanceled(new CancellationToken(canceled: true));
private static readonly Task _canceledRenderTask = Task.FromCanceled(new CancellationToken(canceled: true));
private readonly Func<string, string> _htmlEncoder;
@ -44,7 +44,7 @@ namespace AntBlazor
// the contract that OnAfterRender should only be called when the display has successfully been updated
// and the application is interactive. (Element and component references are populated and JavaScript interop
// is available).
return CanceledRenderTask;
return _canceledRenderTask;
}
public async Task<ComponentRenderedText> RenderComponentAsync(IComponent component, ParameterView initialParameters)
@ -189,7 +189,7 @@ namespace AntBlazor
}
else
{
if (SelfClosingElements.Contains(frame.ElementName))
if (_selfClosingElements.Contains(frame.ElementName))
{
result.Add(" />");
}
@ -292,4 +292,4 @@ namespace AntBlazor
public string ClosestSelectValueAsString { get; set; }
}
}
}
}

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Text.Json;
using Microsoft.JSInterop;
@ -7,7 +7,7 @@ namespace AntBlazor.JsInterop
{
public class DomEventService
{
private Dictionary<string, Func<object>> domEventListeners = new Dictionary<string, Func<object>>();
private Dictionary<string, Func<object>> _domEventListeners = new Dictionary<string, Func<object>>();
private readonly IJSRuntime _jsRuntime;
@ -18,7 +18,7 @@ namespace AntBlazor.JsInterop
private void AddEventListenerInternal<T>(string dom, string eventName, Action<T> callback)
{
if (!domEventListeners.ContainsKey($"{dom}-{eventName}"))
if (!_domEventListeners.ContainsKey($"{dom}-{eventName}"))
{
_jsRuntime.InvokeAsync<string>(JSInteropConstants.addDomEventListener, dom, eventName, DotNetObjectReference.Create(new Invoker<T>((p) =>
{
@ -48,17 +48,17 @@ namespace AntBlazor.JsInterop
public class Invoker<T>
{
private Action<T> action;
private Action<T> _action;
public Invoker(Action<T> invoker)
{
this.action = invoker;
this._action = invoker;
}
[JSInvokable]
public void Invoke(T param)
{
action.Invoke(param);
_action.Invoke(param);
}
}
}
}

View File

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace AntBlazor.core.JsInterop.EventArg
{
public class MouseEvent
{
public int ScreenX { get; set; }
}
}

View File

@ -1,4 +1,4 @@
export function getDom(element) {
export function getDom(element) {
if (!element) {
element = document.body;
} else if (typeof element === 'string') {
@ -44,7 +44,7 @@ export function addDomEventListener(element, eventName, invoker) {
window.addEventListener(eventName, callback);
} else {
let dom = getDom(element);
(document.querySelector(dom) as HTMLElement).addEventListener(eventName, callback);
(dom as HTMLElement).addEventListener(eventName, callback);
}
}
@ -104,4 +104,4 @@ export function log(text) {
export function BackTop(element) {
let dom = document.getElementById("BodyContainer");
dom.scrollTo(0, 0);
}
}

View File

@ -1,13 +1,13 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<span class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id" @ref="Ref">
@if (text != null || ChildContent != null)
<span class="@ClassMapper.Class" style="@Style" id="@Id" @ref="Ref">
@if (Text != null || ChildContent != null)
{
<span class="ant-divider-inner-text">
@if (text != null)
@if (Text != null)
{
@text
@Text
}
else
{
@ -22,27 +22,27 @@
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public string text { get; set; }
[Parameter] public string Text { get; set; }
/// <summary>
/// 'horizontal' | 'vertical'
/// </summary>
[Parameter] public string type { get; set; } = "horizontal";
[Parameter] public string Type { get; set; } = "horizontal";
/// <summary>
/// 'left' | 'right' | 'center'
/// </summary>
[Parameter] public string orientation { get; set; } = "center";
[Parameter] public string Orientation { get; set; } = "center";
[Parameter] public bool dashed { get; set; } = false;
[Parameter] public bool Dashed { get; set; } = false;
private void setClass()
{
ClassMapper.Clear()
.Add("ant-divider")
.Add($"ant-divider-{this.type}")
.If($"ant-divider-with-text-{this.orientation}", () => text != null || ChildContent != null)
.If("ant-divider-dashed", () => dashed)
.Add($"ant-divider-{this.Type}")
.If($"ant-divider-with-text-{this.Orientation}", () => Text != null || ChildContent != null)
.If("ant-divider-dashed", () => Dashed)
;
}

View File

@ -1,32 +1,32 @@
@namespace AntBlazor
@inherits AntDrawerBase
@namespace AntBlazor
@inherits AntDomComponentBase
<div class="@ClassMapper.Class" @ref="@Ref" style="@drawerStyle @Style" @attributes="Attributes" Id="@Id">
@if (mask)
<div class="@ClassMapper.Class" @ref="@Ref" style="@DrawerStyle @Style" id="@Id">
@if (Mask)
{
<div class="ant-drawer-mask" @onclick="_=>maskClick()" style="@maskStyle"></div>
<div class="ant-drawer-mask" @onclick="_=>MaskClick()" style="@MaskStyle"></div>
}
<div class="ant-drawer-content-wrapper @wrapClassName " style="@wrapperStyle">
<div class="ant-drawer-content-wrapper @WrapClassName " style="@WrapperStyle">
<div class="ant-drawer-content">
<div class="ant-drawer-wrapper-body" style="@(isLeftOrRight?"height:100%":"")">
@if (_title.Value != null || closable)
<div class="ant-drawer-wrapper-body" style="@(IsLeftOrRight?"height:100%":"")">
@if (_title.Value != null || Closable)
{
<div class="@TitleClassMapper.Class">
@if (_title.Value != null)
{
<div class="ant-drawer-title">
@if (titleTemplate != null)
@if (TitleTemplate != null)
{
@titleTemplate
@TitleTemplate
}
@if (string.IsNullOrEmpty(titleString))
@if (string.IsNullOrEmpty(TitleString))
{
@((MarkupString)titleString)
@((MarkupString)TitleString)
}
</div>
}
@if (closable)
@if (Closable)
{
<button onclick="_=>closeClick()" aria-label="Close" class="ant-drawer-close">
<AntIcon type="close"></AntIcon>
@ -34,11 +34,10 @@
}
</div>
}
<div class="ant-drawer-body" style="@bodyStyle">
@*<ng-template cdkPortalOutlet></ng-template>*@
<div class="ant-drawer-body" style="@BodyStyle">
@if (ContentTemplate != null)
{
@ContentString
@ContentTemplate
}
@if (string.IsNullOrEmpty(ContentString))
{

View File

@ -0,0 +1,252 @@
using System.Threading.Tasks;
using System.Timers;
using Microsoft.AspNetCore.Components;
using OneOf;
namespace AntBlazor
{
public partial class AntDrawer : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public OneOf<RenderFragment, string> Content
{
get => _content;
set
{
_content = value;
value.Switch(rf => ContentTemplate = rf, str => ContentString = str);
}
}
[Parameter]
public bool Closable { get; set; } = true;
[Parameter]
public bool MaskClosable { get; set; } = true;
[Parameter]
public bool Mask { get; set; } = true;
[Parameter]
public bool NoAnimation { get; set; } = false;
[Parameter]
public bool Keyboard { get; set; } = true;
private RenderFragment TitleTemplate { get; set; }
private string TitleString { get; set; }
private OneOf<RenderFragment, string> _title;
[Parameter]
public OneOf<RenderFragment, string> Title
{
get => _title;
set
{
_title = value;
value.Switch(rf =>
{
TitleTemplate = rf;
TitleString = null;
}, str =>
{
TitleString = str;
TitleTemplate = null;
});
}
}
/// <summary>
/// "left" | "right" | "top" | "bottom"
/// </summary>
[Parameter] public string Placement { get; set; } = "right";
[Parameter] public string MaskStyle { get; set; }
[Parameter] public string BodyStyle { get; set; }
[Parameter] public string WrapClassName { get; set; }
[Parameter] public int Width { get; set; } = 256;
[Parameter] public int Height { get; set; } = 256;
[Parameter] public int ZIndex { get; set; } = 1000;
[Parameter] public int OffsetX { get; set; } = 0;
[Parameter] public int OffsetY { get; set; } = 0;
[Parameter]
public bool Visible
{
get => this._isOpen;
set => this._isOpen = value;
}
[Parameter] public EventCallback OnViewInit { get; set; }
[Parameter] public EventCallback OnClose { get; set; }
private OneOf<RenderFragment, string> _content;
private string ContentString { get; set; }
private RenderFragment ContentTemplate { get; set; }
private bool _isOpen = default;
private string _originalPlacement;
private bool PlacementChanging { get; set; } = false;
private int _placementChangeTimeoutId = -1;
private string OffsetTransform
{
get
{
if (!this._isOpen || this.OffsetX + this.OffsetY == 0)
{
return null;
}
return Placement switch
{
"left" => $"translateX({this.OffsetX}px)",
"right" => $"translateX(-{this.OffsetX}px)",
"top" => $"translateY({this.OffsetY}px)",
"bottom" => $"translateY(-{this.OffsetY}px)",
_ => null
};
}
}
private string Transform
{
get
{
if (this._isOpen)
{
return null;
}
return this.Placement switch
{
"left" => "translateX(-100%)",
"right" => "translateX(100%)",
"top" => "translateY(-100%)",
"bottom" => "translateY(100%)",
_ => null
};
}
}
private bool IsLeftOrRight => Placement == "left" || this.Placement == "right";
private string WidthPx => this.IsLeftOrRight ? StyleHelper.ToCssPixel(this.Width) : null;
private string HeightPx => !this.IsLeftOrRight ? StyleHelper.ToCssPixel(this.Height) : null;
private ClassMapper TitleClassMapper { get; set; } = new ClassMapper();
private string WrapperStyle => $@"
{(WidthPx != null ? $"width:{WidthPx};" : "")}
{(HeightPx != null ? $"height:{HeightPx};" : "")}
{(Transform != null ? $"transform:{Transform};" : "")}
{(PlacementChanging ? "transition:none;" : "")}";
private string DrawerStyle => $@"
{(Transform != null ? $"transform:{Transform};" : "")}
{(PlacementChanging ? "transition:none;" : "")}
z-index:{ZIndex};";
private bool _isPlacementFirstChange = true;
private void SetClass()
{
var prefixCls = "ant-drawer";
this.ClassMapper.Clear()
.Add(prefixCls)
.If($"{prefixCls}-open", () => _isOpen)
.If($"{prefixCls}-{Placement}", () => Placement.IsIn("top", "bottom", "right", "left"))
;
this.TitleClassMapper.Clear()
.If("ant-drawer-header", () => _title.Value != null)
.If("ant-drawer-header-no-title", () => _title.Value != null)
;
}
protected override void OnInitialized()
{
this._originalPlacement = Placement;
this.SetClass();
base.OnInitialized();
}
protected override void OnParametersSet()
{
this.SetClass();
if (string.IsNullOrEmpty(Placement) && Placement != _originalPlacement)
{
this._originalPlacement = Placement;
_isPlacementFirstChange = false;
if (!_isPlacementFirstChange)
{
this.TriggerPlacementChangeCycleOnce();
}
}
base.OnParametersSet();
}
private Timer _timer;
private void TriggerPlacementChangeCycleOnce()
{
if (!NoAnimation)
{
this.PlacementChanging = true;
InvokeStateHasChanged();
_timer = new Timer()
{
AutoReset = false,
Interval = 300,
};
_timer.Elapsed += (_, args) =>
{
this.PlacementChanging = false;
InvokeStateHasChanged();
};
_timer.Start();
}
}
private async Task MaskClick()
{
if (this.MaskClosable && this.Mask && this.OnClose.HasDelegate)
{
await this.OnClose.InvokeAsync(this);
}
}
private async Task CloseClick()
{
if (OnClose.HasDelegate)
{
_timer?.Dispose();
await OnClose.InvokeAsync(this);
}
}
}
}

View File

@ -1,244 +0,0 @@
using System.Threading.Tasks;
using System.Timers;
using Microsoft.AspNetCore.Components;
using OneOf;
namespace AntBlazor
{
public class AntDrawerBase : AntDomComponentBase
{
[Parameter] public RenderFragment ChildContent { get; set; }
private OneOf<RenderFragment, string> _content;
protected string ContentString { get; set; }
protected RenderFragment ContentTemplate { get; set; }
[Parameter]
public OneOf<RenderFragment, string> Content
{
get => _content;
set
{
_content = value;
value.Switch(rf => ContentTemplate = rf, str => ContentString = str);
}
}
[Parameter] public bool closable { get; set; } = true;
[Parameter] public bool maskClosable { get; set; } = true;
[Parameter] public bool mask { get; set; } = true;
[Parameter] public bool noAnimation { get; set; } = false;
[Parameter] public bool keyboard { get; set; } = true;
protected RenderFragment titleTemplate { get; set; }
protected string titleString { get; set; }
protected OneOf<RenderFragment, string> _title;
[Parameter]
public OneOf<RenderFragment, string> title
{
set
{
_title = value;
value.Switch(rf =>
{
titleTemplate = rf;
titleString = null;
}, str =>
{
titleString = str;
titleTemplate = null;
});
}
}
/// <summary>
/// "left" | "right" | "top" | "bottom"
/// </summary>
[Parameter] public string placement { get; set; } = "right";
[Parameter] public string maskStyle { get; set; }
[Parameter] public string bodyStyle { get; set; }
[Parameter] public string wrapClassName { get; set; }
[Parameter] public int width { get; set; } = 256;
[Parameter] public int height { get; set; } = 256;
[Parameter] public int zIndex { get; set; } = 1000;
[Parameter] public int offsetX { get; set; } = 0;
[Parameter] public int offsetY { get; set; } = 0;
[Parameter]
public bool visible
{
get => this.isOpen;
set => this.isOpen = value;
}
[Parameter] public EventCallback onViewInit { get; set; }
[Parameter] public EventCallback onClose { get; set; }
protected bool isOpen = default;
private string originalPlacement;
private bool placementChanging { get; set; } = false;
private int placementChangeTimeoutId = -1;
protected string offsetTransform
{
get
{
if (!this.isOpen || this.offsetX + this.offsetY == 0)
{
return null;
}
return placement switch
{
"left" => $"translateX({this.offsetX}px)",
"right" => $"translateX(-{this.offsetX}px)",
"top" => $"translateY({this.offsetY}px)",
"bottom" => $"translateY(-{this.offsetY}px)",
_ => null
};
}
}
protected string transform
{
get
{
if (this.isOpen)
{
return null;
}
return this.placement switch
{
"left" => "translateX(-100%)",
"right" => "translateX(100%)",
"top" => "translateY(-100%)",
"bottom" => "translateY(100%)",
_ => null
};
}
}
protected bool isLeftOrRight => placement == "left" || this.placement == "right";
protected string _width => this.isLeftOrRight ? StyleHelper.ToCssPixel(this.width) : null;
protected string _height => !this.isLeftOrRight ? StyleHelper.ToCssPixel(this.height) : null;
protected ClassMapper TitleClassMapper { get; set; } = new ClassMapper();
protected string wrapperStyle => $@"
{(_width != null ? $"width:{_width};" : "")}
{(_height != null ? $"height:{_height};" : "")}
{(transform != null ? $"transform:{transform};" : "")}
{(placementChanging ? "transition:none;" : "")}";
protected string drawerStyle => $@"
{(transform != null ? $"transform:{transform};" : "")}
{(placementChanging ? "transition:none;" : "")}
z-index:{zIndex};";
protected void SetClass()
{
var prefixCls = "ant-drawer";
this.ClassMapper.Clear()
.Add(prefixCls)
.If($"{prefixCls}-open", () => isOpen)
.If($"{prefixCls}-{placement}", () => placement.IsIn("top", "bottom", "right", "left"))
;
this.TitleClassMapper.Clear()
.If("ant-drawer-header", () => _title.Value != null)
.If("ant-drawer-header-no-title", () => _title.Value != null)
;
}
protected override void OnInitialized()
{
this.originalPlacement = placement;
this.SetClass();
base.OnInitialized();
}
private bool isPlacementFirstChange = true;
protected override void OnParametersSet()
{
this.SetClass();
if (string.IsNullOrEmpty(placement) && placement != originalPlacement)
{
this.originalPlacement = placement;
isPlacementFirstChange = false;
if (!isPlacementFirstChange)
{
this.triggerPlacementChangeCycleOnce();
}
}
base.OnParametersSet();
}
private Timer timer;
private void triggerPlacementChangeCycleOnce()
{
if (!noAnimation)
{
this.placementChanging = true;
InvokeStateHasChanged();
timer = new Timer()
{
AutoReset = false,
Interval = 300,
};
timer.Elapsed += (_, args) =>
{
this.placementChanging = false;
InvokeStateHasChanged();
};
timer.Start();
}
}
protected async Task maskClick()
{
if (this.maskClosable && this.mask && this.onClose.HasDelegate)
{
await this.onClose.InvokeAsync(this);
}
}
protected async Task closeClick()
{
if (onClose.HasDelegate)
{
timer?.Dispose();
await onClose.InvokeAsync(this);
}
}
}
}

View File

@ -1,8 +1,7 @@
@namespace AntBlazor
@using System
@inherits AntEmptyBase
@inherits AntDomComponentBase
<div class="@ClassMapper.Class" @ref="@Ref" style="@Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" @ref="@Ref" style="@Style" id="@Id">
<div class="@(PrefixCls)-image" style="@ImageStyle">
@if (Image.IsT0 && !string.IsNullOrEmpty(Image.AsT0))
{

View File

@ -1,20 +1,24 @@
using Microsoft.AspNetCore.Components;
using OneOf;
using System;
using System.Collections.Generic;
using System.Text;
namespace AntBlazor
{
public class AntEmptyBase : AntDomComponentBase
public partial class AntEmpty : AntDomComponentBase
{
[Parameter] public string PrefixCls { get; set; } = "ant-empty";
[Parameter]
public string PrefixCls { get; set; } = "ant-empty";
/// <summary>
/// "ltr"|"rtl"
/// </summary>
[Parameter] public string Direction { get; set; } = "ltr";
[Parameter] public string ImageStyle { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter]
public string Direction { get; set; } = "ltr";
[Parameter]
public string ImageStyle { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public OneOf<string, bool, RenderFragment> Description { get; set; } = "暂无数据";
@ -34,15 +38,11 @@ namespace AntBlazor
protected override void OnInitialized()
{
this.SetClass();
base.OnInitialized();
}
protected override void OnParametersSet()
{
this.SetClass();
base.OnParametersSet();
}
}
}

View File

@ -1,6 +1,6 @@
@namespace AntBlazor
@inherits AntColBase
@namespace AntBlazor
@inherits AntDomComponentBase
<div class="@ClassMapper.Class" style="@gutterStyle @Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" style="@GutterStyle @Style" id="@Id">
@ChildContent
</div>

View File

@ -10,61 +10,75 @@ namespace AntBlazor
public class EmbeddedProperty
{
public StringNumber span { get; set; }
public StringNumber Span { get; set; }
public StringNumber pull { get; set; }
public StringNumber Pull { get; set; }
public StringNumber push { get; set; }
public StringNumber Push { get; set; }
public StringNumber offset { get; set; }
public StringNumber Offset { get; set; }
public StringNumber order { get; set; }
public StringNumber Order { get; set; }
}
public class AntColBase : AntDomComponentBase
public partial class AntCol : AntDomComponentBase
{
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public StringNumber flex { get; set; }
[Parameter]
public StringNumber Flex { get; set; }
[Parameter] public StringNumber span { get; set; }
[Parameter]
public StringNumber Span { get; set; }
[Parameter] public StringNumber order { get; set; }
[Parameter]
public StringNumber Order { get; set; }
[Parameter] public StringNumber offset { get; set; }
[Parameter]
public StringNumber Offset { get; set; }
[Parameter] public StringNumber push { get; set; }
[Parameter]
public StringNumber Push { get; set; }
[Parameter] public StringNumber pull { get; set; }
[Parameter]
public StringNumber Pull { get; set; }
[Parameter] public OneOf<int, EmbeddedProperty> xs { get; set; }
[Parameter]
public OneOf<int, EmbeddedProperty> Xs { get; set; }
[Parameter] public OneOf<int, EmbeddedProperty> sm { get; set; }
[Parameter]
public OneOf<int, EmbeddedProperty> Sm { get; set; }
[Parameter] public OneOf<int, EmbeddedProperty> md { get; set; }
[Parameter]
public OneOf<int, EmbeddedProperty> Md { get; set; }
[Parameter] public OneOf<int, EmbeddedProperty> lg { get; set; }
[Parameter]
public OneOf<int, EmbeddedProperty> Lg { get; set; }
[Parameter] public OneOf<int, EmbeddedProperty> xl { get; set; }
[Parameter]
public OneOf<int, EmbeddedProperty> Xl { get; set; }
[Parameter] public OneOf<int, EmbeddedProperty> xxl { get; set; }
[Parameter]
public OneOf<int, EmbeddedProperty> Xxl { get; set; }
[CascadingParameter] public AntRow Row { get; set; }
[CascadingParameter]
public AntRow Row { get; set; }
protected string hostFlexStyle = null;
private string _hostFlexStyle = null;
protected string gutterStyle { get; set; }
private string GutterStyle { get; set; }
internal void RowGutterChanged((int horizontalGutter, int verticalGutter) gutter)
{
gutterStyle = "";
GutterStyle = "";
if (gutter.horizontalGutter > 0)
{
gutterStyle = $"padding-left: {gutter.horizontalGutter / 2}px;padding-right: {gutter.horizontalGutter / 2}px;";
GutterStyle = $"padding-left: {gutter.horizontalGutter / 2}px;padding-right: {gutter.horizontalGutter / 2}px;";
}
if (gutter.verticalGutter > 0)
{
gutterStyle += $"padding-top: {gutter.verticalGutter / 2}px;padding-bottom: {gutter.verticalGutter / 2}px;";
GutterStyle += $"padding-top: {gutter.verticalGutter / 2}px;padding-bottom: {gutter.verticalGutter / 2}px;";
}
}
@ -73,11 +87,11 @@ namespace AntBlazor
string prefixCls = "ant-col";
this.ClassMapper.Clear()
.Add(prefixCls)
.If($"{prefixCls}-{this.span.Value}", () => this.span.Value != null)
.If($"{prefixCls}-order-{this.order.Value}", () => this.order.Value != null)
.If($"{prefixCls}-offset-{this.offset.Value}", () => this.offset.Value != null)
.If($"{prefixCls}-pull-{this.pull.Value}", () => this.pull.Value != null)
.If($"{prefixCls}-push-{this.push.Value}", () => this.push.Value != null)
.If($"{prefixCls}-{this.Span.Value}", () => this.Span.Value != null)
.If($"{prefixCls}-order-{this.Order.Value}", () => this.Order.Value != null)
.If($"{prefixCls}-offset-{this.Offset.Value}", () => this.Offset.Value != null)
.If($"{prefixCls}-pull-{this.Pull.Value}", () => this.Pull.Value != null)
.If($"{prefixCls}-push-{this.Push.Value}", () => this.Push.Value != null)
;
string[] listOfSizeInputName = { "xs", "sm", "md", "lg", "xl", "xxl" };
@ -98,29 +112,29 @@ namespace AntBlazor
}, embedded =>
{
ClassMapper
.If($"{prefixCls}-{sizeName}-order-{embedded.order.Value}", () => embedded.order.Value != null)
.If($"{prefixCls}-{sizeName}-offset-{embedded.offset.Value}", () => embedded.offset.Value != null)
.If($"{prefixCls}-{sizeName}-push-{embedded.push.Value}", () => embedded.push.Value != null)
.If($"{prefixCls}-{sizeName}-pull-{embedded.pull.Value}", () => embedded.pull.Value != null);
.If($"{prefixCls}-{sizeName}-order-{embedded.Order.Value}", () => embedded.Order.Value != null)
.If($"{prefixCls}-{sizeName}-offset-{embedded.Offset.Value}", () => embedded.Offset.Value != null)
.If($"{prefixCls}-{sizeName}-push-{embedded.Push.Value}", () => embedded.Push.Value != null)
.If($"{prefixCls}-{sizeName}-pull-{embedded.Pull.Value}", () => embedded.Pull.Value != null);
});
}
}
private void SetHostFlexStyle()
{
if (this.flex.Value == null)
if (this.Flex.Value == null)
return;
this.hostFlexStyle = this.flex.Match(str =>
this._hostFlexStyle = this.Flex.Match(str =>
{
if (Regex.Match(str, "^\\d+(\\.\\d+)?(px|em|rem|%)$").Success)
{
return $"0 0 {flex}";
return $"0 0 {Flex}";
}
return flex.AsT0;
return Flex.AsT0;
},
num => $"{flex} {flex} auto");
num => $"{Flex} {Flex} auto");
}
protected override void OnInitialized()
@ -149,4 +163,4 @@ namespace AntBlazor
base.Dispose();
}
}
}
}

View File

@ -1,8 +1,8 @@
@namespace AntBlazor
@inherits AntRowBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<div class="@ClassMapper.Class" style="@gutterStyle @Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" style="@GutterStyle @Style" id="@Id">
@ChildContent
</div>
</CascadingValue>

View File

@ -9,32 +9,37 @@ namespace AntBlazor
{
using GutterType = OneOf<int, Dictionary<string, int>, (int, int)>;
public class AntRowBase : AntDomComponentBase
public partial class AntRow : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public string type { get; set; }
[Parameter]
public string Type { get; set; }
/// <summary>
/// 'top' | 'middle' | 'bottom'
/// </summary>
[Parameter] public string align { get; set; }
[Parameter]
public string Align { get; set; }
/// <summary>
/// 'start' | 'end' | 'center' | 'space-around' | 'space-between'
/// </summary>
[Parameter] public string justify { get; set; }
[Parameter]
public string Justify { get; set; }
[Parameter] public GutterType gutter { get; set; }
[Parameter]
public GutterType Gutter { get; set; }
[Inject] public DomEventService domEventService { get; set; }
[Inject]
public DomEventService DomEventService { get; set; }
protected string gutterStyle { get; set; }
private string GutterStyle { get; set; }
public IList<AntCol> Cols { get; set; } = new List<AntCol>();
public IList<AntCol> Cols { get; } = new List<AntCol>();
public static Hashtable gridResponsiveMap = new Hashtable()
private static Hashtable _gridResponsiveMap = new Hashtable()
{
[nameof(BreakpointEnum.xs)] = "(max-width: 575px)",
[nameof(BreakpointEnum.sm)] = "(max-width: 576px)",
@ -48,18 +53,18 @@ namespace AntBlazor
{
var prefixCls = "ant-row";
ClassMapper.Add(prefixCls)
.If($"{prefixCls}-top", () => align == "top")
.If($"{prefixCls}-middle", () => align == "middle")
.If($"{prefixCls}-bottom", () => align == "bottom")
.If($"{prefixCls}-start", () => justify == "start")
.If($"{prefixCls}-end", () => justify == "end")
.If($"{prefixCls}-center", () => justify == "center")
.If($"{prefixCls}-space-around", () => justify == "space-around")
.If($"{prefixCls}-space-between", () => justify == "space-between")
.If($"{prefixCls}-top", () => Align == "top")
.If($"{prefixCls}-middle", () => Align == "middle")
.If($"{prefixCls}-bottom", () => Align == "bottom")
.If($"{prefixCls}-start", () => Justify == "start")
.If($"{prefixCls}-end", () => Justify == "end")
.If($"{prefixCls}-center", () => Justify == "center")
.If($"{prefixCls}-space-around", () => Justify == "space-around")
.If($"{prefixCls}-space-between", () => Justify == "space-between")
;
await this.setGutterStyle();
domEventService.AddEventListener<object>("window", "resize", async _ => await this.setGutterStyle());
await this.SetGutterStyle();
DomEventService.AddEventListener<object>("window", "resize", async _ => await this.SetGutterStyle());
await base.OnInitializedAsync();
}
@ -70,38 +75,39 @@ namespace AntBlazor
await base.OnParametersSetAsync();
}
private async Task setGutterStyle()
private async Task SetGutterStyle()
{
string breakPoint = null;
await typeof(BreakpointEnum).GetEnumNames().ForEachAsync(async bp =>
{
if (await JsInvokeAsync<bool>(JSInteropConstants.matchMedia, gridResponsiveMap[bp]))
if (await JsInvokeAsync<bool>(JSInteropConstants.matchMedia, _gridResponsiveMap[bp]))
{
breakPoint = bp;
}
});
var gutter = this.getGutter(breakPoint);
var gutter = this.GetGutter(breakPoint);
Cols.ForEach(x => x.RowGutterChanged(gutter));
gutterStyle = "";
GutterStyle = "";
if (gutter.horizontalGutter > 0)
{
gutterStyle = $"margin-left: -{gutter.horizontalGutter / 2}px;margin-right: -{gutter.horizontalGutter / 2}px;";
GutterStyle = $"margin-left: -{gutter.horizontalGutter / 2}px;margin-right: -{gutter.horizontalGutter / 2}px;";
}
if (gutter.verticalGutter > 0)
{
gutterStyle += $"margin-top: -{gutter.verticalGutter / 2}px;margin-bottom: -{gutter.verticalGutter / 2}px;";
GutterStyle += $"margin-top: -{gutter.verticalGutter / 2}px;margin-bottom: -{gutter.verticalGutter / 2}px;";
}
InvokeStateHasChanged();
}
private (int horizontalGutter, int verticalGutter) getGutter(string breakPoint)
private (int horizontalGutter, int verticalGutter) GetGutter(string breakPoint)
{
GutterType gutter = 0;
if (this.gutter.Value != null)
gutter = this.gutter;
if (this.Gutter.Value != null)
gutter = this.Gutter;
return gutter.Match(
num => (num, 0),
@ -120,4 +126,4 @@ namespace AntBlazor
sm,
xs
}
}
}

View File

@ -1,6 +1,6 @@
@namespace AntBlazor
@inherits AntIconBase
@namespace AntBlazor
@inherits AntDomComponentBase
<i class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id" @onclick="OnClick" type="@type">
<i class="@ClassMapper.Class" style="@Style" id="@Id" @onclick="OnClick" tabindex="@TabIndex" type="@Type">
@((MarkupString)SvgImg)
</i>
</i>

View File

@ -4,72 +4,79 @@ using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using OneOf;
namespace AntBlazor
{
public class AntIconBase : AntDomComponentBase
public partial class AntIcon : AntDomComponentBase
{
[Parameter]
public bool spin { get; set; }
public bool Spin { get; set; }
[Parameter]
public int rotate { get; set; } = 0;
public OneOf<int, string> Rotate { get; set; } = 0;
[Parameter]
public string type { get; set; }
public string Type { get; set; }
/// <summary>
/// 'fill' | 'outline' | 'twotone';
/// </summary>
[Parameter]
public string Theme { get; set; } = AntIconThemeType.Outline;
[Parameter]
public string theme { get; set; } = AntIconThemeType.Outline; //'fill' | 'outline' | 'twotone';
public string TwotoneColor { get; set; }
[Parameter]
public string twotoneColor { get; set; }
public string IconFont { get; set; }
[Parameter]
public string iconFont { get; set; }
public string Width { get; set; } = "1em";
[Parameter]
public string width { get; set; } = "1em";
public string Height { get; set; } = "1em";
[Parameter]
public string height { get; set; } = "1em";
public string Fill { get; set; } = "currentColor";
[Parameter]
public string fill { get; set; } = "currentColor";
public string TabIndex { get; set; }
[CascadingParameter]
public AntButton Button { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> onclick { get; set; }
public EventCallback<MouseEventArgs> Onclick { get; set; }
[Inject]
private HttpClient httpClient { get; set; }
private HttpClient HttpClient { get; set; }
[Inject]
private NavigationManager NavigationManager { get; set; }
private static readonly ConcurrentDictionary<string, string> SvgCache = new ConcurrentDictionary<string, string>();
private static readonly ConcurrentDictionary<string, string> _svgCache = new ConcurrentDictionary<string, string>();
protected string SvgImg { get; set; }
private string SvgImg { get; set; }
private string SvgStyle { get; set; }
private string _iconSvg;
private Uri baseUrl;
private Uri _baseUrl;
public void setClassSet()
public void SetClassSet()
{
string prefixName = "anticon";
ClassMapper.Add(prefixName)
.If($"{prefixName}-spin", () => spin || this.type == "loading");
.If($"{prefixName}-spin", () => Spin || this.Type == "loading");
SvgStyle = $"focusable=\"false\" width=\"{width}\" height=\"{height}\" fill=\"{fill}\"";
SvgStyle = $"focusable=\"false\" width=\"{Width}\" height=\"{Height}\" fill=\"{Fill}\"";
}
protected override async Task OnInitializedAsync()
{
this.setClassSet();
this.SetClassSet();
baseUrl = NavigationManager.ToAbsoluteUri(NavigationManager.BaseUri);
_baseUrl = NavigationManager.ToAbsoluteUri(NavigationManager.BaseUri);
if (this is AntIcon icon)
{
@ -89,15 +96,14 @@ namespace AntBlazor
{
try
{
if (SvgCache.TryGetValue($"{theme}-{type}", out var svg))
if (_svgCache.TryGetValue($"{Theme}-{Type}", out var svg))
{
_iconSvg = svg;
}
else
{
_iconSvg = await httpClient.GetStringAsync(new Uri(baseUrl,
$"_content/AntBlazor/icons/{theme.ToLower()}/{type.ToLower()}.svg"));
SvgCache.TryAdd($"{theme}-{type}", _iconSvg);
_iconSvg = await HttpClient.GetStringAsync(new Uri(_baseUrl, $"_content/AntBlazor/icons/{Theme.ToLower()}/{Type.ToLower()}.svg"));
_svgCache.TryAdd($"{Theme}-{Type}", _iconSvg);
}
SvgImg = _iconSvg.Insert(_iconSvg.IndexOf("svg", StringComparison.Ordinal) + 3, $" {SvgStyle} ");
@ -112,10 +118,10 @@ namespace AntBlazor
public async Task OnClick(MouseEventArgs args)
{
if (onclick.HasDelegate)
if (Onclick.HasDelegate)
{
await onclick.InvokeAsync(args);
await Onclick.InvokeAsync(args);
}
}
}
}
}

View File

@ -1,26 +1,12 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntInputComponentBase<double>
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" id="@Id">
<div class="@ClassMapper.Class" style="@Style" id="@Id">
<div class="ant-input-number-handler-wrap">
@*<span class="ant-input-number-handler ant-input-number-handler-up @(Value >= max ? "ant-input-number-handler-up-disabled" : "")" role="button" aria-disabled="false" aria-label="Increase Value" unselectable="unselectable">
<span class="anticon anticon-up ant-input-number-handler-up-inner" role="img" aria-label="up" @onclick="Increase">
<svg xmlns="http:www.w3.org/2000/svg" class="" aria-hidden="true" fill="currentColor" viewBox="64 64 896 896" focusable="false" width="1em" height="1em" data-icon="up">
<path d="M 890.5 755.3 L 537.9 269.2 c -12.8 -17.6 -39 -17.6 -51.7 0 L 133.5 755.3 A 8 8 0 0 0 140 768 h 75 c 5.1 0 9.9 -2.5 12.9 -6.6 L 512 369.8 l 284.1 391.6 c 3 4.1 7.8 6.6 12.9 6.6 h 75 c 6.5 0 10.3 -7.4 6.5 -12.7 Z" />
</svg>
</span>
</span>*@
<AntIcon class="@GetIconClass("up")" type="up" onclick="Increase" />
@*<span class="ant-input-number-handler ant-input-number-handler-down @(Value <= min ? "ant-input-number-handler-down-disabled" : "")" role="button" aria-disabled="false" aria-label="Decrease Value" unselectable="unselectable">
<span class="anticon anticon-down ant-input-number-handler-down-inner" role="img" aria-label="down" @onclick="Decrease">
<svg xmlns="http:www.w3.org/2000/svg" class="" aria-hidden="true" fill="currentColor" viewBox="64 64 896 896" focusable="false" width="1em" height="1em" data-icon="down">
<path d="M 884 256 h -75 c -5.1 0 -9.9 2.5 -12.9 6.6 L 512 654.2 L 227.9 262.6 c -3 -4.1 -7.8 -6.6 -12.9 -6.6 h -75 c -6.5 0 -10.3 7.4 -6.5 12.7 l 352.6 486.1 c 12.8 17.6 39 17.6 51.7 0 l 352.6 -486.1 c 3.9 -5.3 0.1 -12.7 -6.4 -12.7 Z" />
</svg>
</span>
</span>*@
<AntIcon class="@GetIconClass("down")" type="down" onclick="Decrease" />
<AntIcon class="@GetIconClass("up")" Type="up" Onclick="Increase" />
<AntIcon class="@GetIconClass("down")" Type="down" Onclick="Decrease" />
</div>
<div class="ant-input-number-input-wrap">
<AntInput class="ant-input-number-input" Value="@DisplayValue()" type="number" onInput="(e)=>OnInput(e)"></AntInput>
@*<input class="ant-input-number-input" role="spinbutton" aria-valuenow="3" aria-valuemin="1" aria-valuemax="10" min="1" max="10" step="1" value="3" autocomplete="off">*@
<AntInput class="ant-input-number-input" Value="@DisplayValue()" Type="number" OnInput="(e)=>OnInput(e)"></AntInput>
</div>
</div>
</div>

View File

@ -4,45 +4,20 @@ using System.Linq;
namespace AntBlazor
{
/// <summary>
/// base class for InputNumber component
/// https://ant.design/components/input-number/
/// </summary>
public partial class AntInputNumber : AntInputComponentBase<double>
{
//<div class="ant-input-number">
// <div class="ant-input-number-handler-wrap">
// <span class="ant-input-number-handler ant-input-number-handler-up " role="button" aria-disabled="false" aria-label="Increase Value" unselectable="unselectable">
// <span class="anticon anticon-up ant-input-number-handler-up-inner" role="img" aria-label="up">
// <svg xmlns = "http://www.w3.org/2000/svg" class="" aria-hidden="true" fill="currentColor" viewBox="64 64 896 896" focusable="false" width="1em" height="1em" data-icon="up">
// <path d = "M 890.5 755.3 L 537.9 269.2 c -12.8 -17.6 -39 -17.6 -51.7 0 L 133.5 755.3 A 8 8 0 0 0 140 768 h 75 c 5.1 0 9.9 -2.5 12.9 -6.6 L 512 369.8 l 284.1 391.6 c 3 4.1 7.8 6.6 12.9 6.6 h 75 c 6.5 0 10.3 -7.4 6.5 -12.7 Z" />
// </ svg >
// </ span >
// </ span >
// < span class="ant-input-number-handler ant-input-number-handler-down " role="button" aria-disabled="false" aria-label="Decrease Value" unselectable="unselectable">
// <span class="anticon anticon-down ant-input-number-handler-down-inner" role="img" aria-label="down">
// <svg xmlns = "http://www.w3.org/2000/svg" class="" aria-hidden="true" fill="currentColor" viewBox="64 64 896 896" focusable="false" width="1em" height="1em" data-icon="down">
// <path d = "M 884 256 h -75 c -5.1 0 -9.9 2.5 -12.9 6.6 L 512 654.2 L 227.9 262.6 c -3 -4.1 -7.8 -6.6 -12.9 -6.6 h -75 c -6.5 0 -10.3 7.4 -6.5 12.7 l 352.6 486.1 c 12.8 17.6 39 17.6 51.7 0 l 352.6 -486.1 c 3.9 -5.3 0.1 -12.7 -6.4 -12.7 Z" />
// </ svg >
// </ span >
// </ span >
// </ div >
// < div class="ant-input-number-input-wrap">
// <input class="ant-input-number-input" role="spinbutton" aria-valuenow="3" aria-valuemin="1" aria-valuemax="10" min="1" max="10" step="1" value="3" autocomplete="off">
// </div>
//</div>
private string _format;
protected const string PrefixCls = "ant-input-number";
[Parameter]
public Func<double, string> formatter { get; set; }
public Func<double, string> Formatter { get; set; }
[Parameter]
public Func<string, double> parser { get; set; }
public Func<string, double> Parser { get; set; }
private double _step = 1;
[Parameter]
public double step
public double Step
{
get
{
@ -59,24 +34,27 @@ namespace AntBlazor
}
[Parameter]
public double? defaultValue { get; set; }
public double? DefaultValue { get; set; }
[Parameter]
public double max { get; set; } = double.PositiveInfinity;
public double Max { get; set; } = double.PositiveInfinity;
[Parameter]
public double min { get; set; } = double.NegativeInfinity;
public double Min { get; set; } = double.NegativeInfinity;
[Parameter]
public string size { get; set; } = AntInputSize.Default;
public string Size { get; set; } = AntInputSize.Default;
[Parameter]
public bool Disabled { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
if (defaultValue.HasValue)
if (DefaultValue.HasValue)
{
Value = defaultValue.Value;
Value = DefaultValue.Value;
}
}
@ -84,9 +62,9 @@ namespace AntBlazor
{
ClassMapper.Clear()
.Add(PrefixCls)
.If($"{PrefixCls}-lg", () => size == AntInputSize.Large)
.If($"{PrefixCls}-sm", () => size == AntInputSize.Small)
.If($"{PrefixCls}-disabled", () => Attributes.TryGetValue("disabled", out object disabled) && disabled.ToString() == true.ToString());
.If($"{PrefixCls}-lg", () => Size == AntInputSize.Large)
.If($"{PrefixCls}-sm", () => Size == AntInputSize.Small)
.If($"{PrefixCls}-disabled", () => this.Disabled);
}
protected override void OnParametersSet()
@ -98,28 +76,28 @@ namespace AntBlazor
private void Increase()
{
OnInput(new ChangeEventArgs() { Value = Value + step });
OnInput(new ChangeEventArgs() { Value = Value + Step });
}
private void Decrease()
{
OnInput(new ChangeEventArgs() { Value = Value - step });
OnInput(new ChangeEventArgs() { Value = Value - Step });
}
private void OnInput(ChangeEventArgs args)
{
// TODO: handle non-number input, parser
double num;
if (parser != null)
if (Parser != null)
{
num = parser(args.Value.ToString());
num = Parser(args.Value.ToString());
}
else
{
double.TryParse(args.Value.ToString(), out num);
}
if (num >= min && num <= max)
if (num >= Min && num <= Max)
{
Value = num;
}
@ -130,11 +108,11 @@ namespace AntBlazor
string cls = string.Empty;
if (direction == "up")
{
cls = $"ant-input-number-handler ant-input-number-handler-up " + (Value >= max ? "ant-input-number-handler-up-disabled" : string.Empty);
cls = $"ant-input-number-handler ant-input-number-handler-up " + (Value >= Max ? "ant-input-number-handler-up-disabled" : string.Empty);
}
else
{
cls = $"ant-input-number-handler ant-input-number-handler-down " + (Value <= min ? "ant-input-number-handler-down-disabled" : string.Empty);
cls = $"ant-input-number-handler ant-input-number-handler-down " + (Value <= Min ? "ant-input-number-handler-down-disabled" : string.Empty);
}
return cls;
@ -142,12 +120,12 @@ namespace AntBlazor
private string DisplayValue()
{
if (formatter != null)
if (Formatter != null)
{
return formatter(Value);
return Formatter(Value);
}
return Value.ToString(_format);
}
}
}
}

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Web;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace AntBlazor
@ -18,51 +19,62 @@ namespace AntBlazor
protected string _groupWrapperClass = $"{PrefixCls}-group-wrapper";
protected string _clearIconClass;
protected EventCallbackFactory _callbackFactory = new EventCallbackFactory();
protected ElementReference inputEl { get; set; }
protected ElementReference InputEl { get; set; }
[Parameter]
public string type { get; set; } = "text";
public string Type { get; set; } = "text";
[Parameter]
public RenderFragment addOnBefore { get; set; }
public RenderFragment AddOnBefore { get; set; }
[Parameter]
public RenderFragment addOnAfter { get; set; }
public RenderFragment AddOnAfter { get; set; }
[Parameter]
public string size { get; set; } = AntInputSize.Default;
public string Size { get; set; } = AntInputSize.Default;
[Parameter]
public string placeholder { get; set; }
public string Placeholder { get; set; }
[Parameter]
public string defaultValue { get; set; }
public string DefaultValue { get; set; }
[Parameter]
public int maxLength { get; set; } = -1;
public int MaxLength { get; set; } = -1;
[Parameter]
public RenderFragment prefix { get; set; }
public bool Disabled { get; set; }
[Parameter]
public RenderFragment suffix { get; set; }
public bool AllowClear { get; set; }
[Parameter]
public EventCallback<ChangeEventArgs> onChange { get; set; }
public RenderFragment Prefix { get; set; }
[Parameter]
public EventCallback<KeyboardEventArgs> onPressEnter { get; set; }
public RenderFragment Suffix { get; set; }
[Parameter]
public EventCallback<ChangeEventArgs> onInput { get; set; }
public RenderFragment ChildContent { get; set; }
[Parameter]
public EventCallback<ChangeEventArgs> OnChange { get; set; }
[Parameter]
public EventCallback<KeyboardEventArgs> OnPressEnter { get; set; }
[Parameter]
public EventCallback<ChangeEventArgs> OnInput { get; set; }
public Dictionary<string,object> Attributes { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
if (!string.IsNullOrEmpty(defaultValue) && string.IsNullOrEmpty(Value))
if (!string.IsNullOrEmpty(DefaultValue) && string.IsNullOrEmpty(Value))
{
Value = defaultValue;
Value = DefaultValue;
}
SetClasses();
@ -71,43 +83,43 @@ namespace AntBlazor
protected virtual void SetClasses()
{
ClassMapper.Clear()
.If($"{PrefixCls}", () => type != "number")
.If($"{PrefixCls}-lg", () => size == AntInputSize.Large)
.If($"{PrefixCls}-sm", () => size == AntInputSize.Small);
.If($"{PrefixCls}", () => Type != "number")
.If($"{PrefixCls}-lg", () => Size == AntInputSize.Large)
.If($"{PrefixCls}-sm", () => Size == AntInputSize.Small);
if (Attributes is null)
{
Attributes = new System.Collections.Generic.Dictionary<string, object>();
Attributes = new Dictionary<string, object>();
}
_affixWrapperClass = $"{PrefixCls}-affix-wrapper";
_groupWrapperClass = $"{PrefixCls}-group-wrapper";
if (maxLength >= 0)
if (MaxLength >= 0)
{
Attributes?.Add("maxlength", maxLength);
Attributes?.Add("maxlength", MaxLength);
}
if (Attributes.ContainsKey("disabled"))
if (Disabled)
{
// TODO: disable element
_affixWrapperClass = string.Join(" ", _affixWrapperClass, $"{PrefixCls}-affix-wrapper-disabled");
ClassMapper.Add($"{PrefixCls}-disabled");
}
if (Attributes.ContainsKey("allowClear"))
if (AllowClear)
{
_allowClear = true;
_clearIconClass = $"{PrefixCls}-clear-icon";
ToggleClearBtn();
}
if (size == AntInputSize.Large)
if (Size == AntInputSize.Large)
{
_affixWrapperClass = string.Join(" ", _affixWrapperClass, $"{PrefixCls}-affix-wrapper-lg");
_groupWrapperClass = string.Join(" ", _groupWrapperClass, $"{PrefixCls}-group-wrapper-lg");
}
else if (size == AntInputSize.Small)
else if (Size == AntInputSize.Small)
{
_affixWrapperClass = string.Join(" ", _affixWrapperClass, $"{PrefixCls}-affix-wrapper-sm");
_groupWrapperClass = string.Join(" ", _groupWrapperClass, $"{PrefixCls}-group-wrapper-sm");
@ -128,23 +140,23 @@ namespace AntBlazor
protected async Task OnChangeAsync(ChangeEventArgs args)
{
if (onChange.HasDelegate)
if (OnChange.HasDelegate)
{
await onChange.InvokeAsync(args);
await OnChange.InvokeAsync(args);
}
}
protected async Task OnPressEnterAsync(KeyboardEventArgs args)
{
if (args.Key == "Enter" && onPressEnter.HasDelegate)
if (args.Key == "Enter" && OnPressEnter.HasDelegate)
{
await onPressEnter.InvokeAsync(args);
await OnPressEnter.InvokeAsync(args);
}
}
private void ToggleClearBtn()
{
suffix = new RenderFragment((builder) =>
Suffix = new RenderFragment((builder) =>
{
builder.OpenComponent<AntIcon>(31);
builder.AddAttribute(32, "type", "close-circle");
@ -185,9 +197,9 @@ namespace AntBlazor
ToggleClearBtn();
}
if (onInput.HasDelegate)
if (OnInput.HasDelegate)
{
await onInput.InvokeAsync(args);
await OnInput.InvokeAsync(args);
}
}
@ -197,7 +209,7 @@ namespace AntBlazor
string container = "input";
if (addOnBefore != null || addOnAfter != null)
if (AddOnBefore != null || AddOnAfter != null)
{
container = "groupWrapper";
builder.OpenElement(0, "span");
@ -207,16 +219,16 @@ namespace AntBlazor
builder.AddAttribute(4, "class", $"{PrefixCls}-wrapper {PrefixCls}-group");
}
if (addOnBefore != null)
if (AddOnBefore != null)
{
// addOnBefore
builder.OpenElement(5, "span");
builder.AddAttribute(6, "class", $"{PrefixCls}-group-addon");
builder.AddContent(7, addOnBefore);
builder.AddContent(7, AddOnBefore);
builder.CloseElement();
}
if (prefix != null || suffix != null)
if (Prefix != null || Suffix != null)
{
builder.OpenElement(8, "span");
builder.AddAttribute(9, "class", _affixWrapperClass);
@ -227,12 +239,12 @@ namespace AntBlazor
}
}
if (prefix != null)
if (Prefix != null)
{
// prefix
builder.OpenElement(11, "span");
builder.AddAttribute(12, "class", $"{PrefixCls}-prefix");
builder.AddContent(13, prefix);
builder.AddContent(13, Prefix);
builder.CloseElement();
}
@ -251,45 +263,45 @@ namespace AntBlazor
}
}
builder.AddAttribute(18, "Id", Id);
if (type != "number")
if (Type != "number")
{
builder.AddAttribute(19, "type", type);
builder.AddAttribute(19, "type", Type);
}
builder.AddAttribute(20, "placeholder", placeholder);
builder.AddAttribute(20, "placeholder", Placeholder);
builder.AddAttribute(21, "value", Value);
builder.AddAttribute(22, "onchange", _callbackFactory.Create(this, OnChangeAsync));
builder.AddAttribute(23, "onkeypress", _callbackFactory.Create(this, OnPressEnterAsync));
builder.AddAttribute(24, "oninput", _callbackFactory.Create(this, OnInputAsync));
builder.CloseElement();
if (suffix != null)
if (Suffix != null)
{
// suffix
builder.OpenElement(25, "span");
builder.AddAttribute(26, "class", $"{PrefixCls}-suffix");
builder.AddContent(27, suffix);
builder.AddContent(27, Suffix);
builder.CloseElement();
}
if (prefix != null || suffix != null)
if (Prefix != null || Suffix != null)
{
builder.CloseElement();
}
if (addOnAfter != null)
if (AddOnAfter != null)
{
// addOnAfter
builder.OpenElement(28, "span");
builder.AddAttribute(29, "class", $"{PrefixCls}-group-addon");
builder.AddContent(30, addOnAfter);
builder.AddContent(30, AddOnAfter);
builder.CloseElement();
}
if (addOnBefore != null || addOnAfter != null)
if (AddOnBefore != null || AddOnAfter != null)
{
builder.CloseElement();
builder.CloseElement();
}
}
}
}
}

View File

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
@ -10,7 +11,10 @@ namespace AntBlazor
public RenderFragment ChildContent { get; set; }
[Parameter]
public string size { get; set; }
public string Size { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> Attributes { get; set; }
protected override void OnInitialized()
{
@ -18,8 +22,8 @@ namespace AntBlazor
ClassMapper.Clear()
.Add(PrefixCls)
.If($"{PrefixCls}-lg", () => size == AntInputSize.Large)
.If($"{PrefixCls}-sm", () => size == AntInputSize.Small)
.If($"{PrefixCls}-lg", () => Size == AntInputSize.Large)
.If($"{PrefixCls}-sm", () => Size == AntInputSize.Small)
.If($"{PrefixCls}-compact", () => Attributes != null && Attributes.ContainsKey("compact"));
}
}

View File

@ -9,13 +9,13 @@ namespace AntBlazor
private string _eyeIcon;
[Parameter]
public bool visibilityToggle { get; set; } = true;
public bool VisibilityToggle { get; set; } = true;
protected override void OnInitialized()
{
base.OnInitialized();
type = "password";
Type = "password";
ToggleVisibility(new MouseEventArgs());
}
@ -24,14 +24,14 @@ namespace AntBlazor
base.SetClasses();
//ant-input-password-large ant-input-affix-wrapper ant-input-affix-wrapper-lg
ClassMapper
.If($"{PrefixCls}-password-large", () => size == AntInputSize.Large)
.If($"{PrefixCls}-password-small", () => size == AntInputSize.Small);
.If($"{PrefixCls}-password-large", () => Size == AntInputSize.Large)
.If($"{PrefixCls}-password-small", () => Size == AntInputSize.Small);
_affixWrapperClass = string.Join(" ", _affixWrapperClass, $"{PrefixCls}-password");
if (visibilityToggle)
if (VisibilityToggle)
{
suffix = new RenderFragment((builder) =>
Suffix = new RenderFragment((builder) =>
{
int i = 0;
builder.OpenElement(i++, "span");
@ -48,21 +48,21 @@ namespace AntBlazor
private void ToggleVisibility(MouseEventArgs args)
{
if (visibilityToggle)
if (VisibilityToggle)
{
if (_visible)
{
_eyeIcon = "eye";
type = "text";
Type = "text";
}
else
{
_eyeIcon = "eye-invisible";
type = "password";
Type = "password";
}
_visible = !_visible;
}
}
}
}
}

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using OneOf;
using System;
using System.Threading.Tasks;
@ -10,7 +11,11 @@ namespace AntBlazor
private bool _isSearching;
[Parameter]
public EventCallback<EventArgs> onSearch { get; set; }
public EventCallback<EventArgs> OnSearch { get; set; }
[Parameter]
public OneOf<bool, string> EnterButton { get; set; }
private int _sequence = 0;
@ -18,9 +23,9 @@ namespace AntBlazor
{
base.OnInitialized();
if (Attributes == null || !Attributes.ContainsKey("enterButton"))
if (EnterButton.Value == null)
{
suffix = new RenderFragment((builder) =>
Suffix = new RenderFragment((builder) =>
{
builder.OpenComponent<AntIcon>(35);
builder.AddAttribute(36, "class", $"{PrefixCls}-search-icon");
@ -31,12 +36,12 @@ namespace AntBlazor
}
else
{
addOnAfter = new RenderFragment((builder) =>
AddOnAfter = new RenderFragment((builder) =>
{
builder.OpenComponent<AntButton>(_sequence++);
builder.AddAttribute(_sequence++, "class", $"{PrefixCls}-search-button");
builder.AddAttribute(_sequence++, "type", "primary");
builder.AddAttribute(_sequence++, "size", size);
builder.AddAttribute(_sequence++, "size", Size);
if (_isSearching)
{
builder.AddAttribute(_sequence++, "loading", true);
@ -47,17 +52,20 @@ namespace AntBlazor
builder.AddAttribute(_sequence++, "onclick", e);
}
if (Attributes["enterButton"].ToString() == true.ToString()) // show search icon button
EnterButton.Switch(boolean =>
{
builder.AddAttribute(_sequence++, "icon", "search");
}
else // show search content button
if (boolean)
{
builder.AddAttribute(_sequence++, "icon", "search");
}
}, str =>
{
builder.AddAttribute(_sequence++, "ChildContent", new RenderFragment((b) =>
{
b.AddContent(_sequence++, Attributes["enterButton"].ToString());
b.AddContent(_sequence++, str);
}));
}
});
builder.CloseComponent();
});
@ -68,11 +76,11 @@ namespace AntBlazor
{
base.SetClasses();
if (size == AntInputSize.Large)
if (Size == AntInputSize.Large)
{
_groupWrapperClass = string.Join(" ", _groupWrapperClass, $"{PrefixCls}-search-large");
}
else if (size == AntInputSize.Small)
else if (Size == AntInputSize.Small)
{
_groupWrapperClass = string.Join(" ", _groupWrapperClass, $"{PrefixCls}-search-small");
}
@ -86,13 +94,13 @@ namespace AntBlazor
{
_isSearching = true;
StateHasChanged();
if (onSearch.HasDelegate)
if (OnSearch.HasDelegate)
{
await onSearch.InvokeAsync(EventArgs.Empty);
await OnSearch.InvokeAsync(EventArgs.Empty);
}
await Task.Delay(TimeSpan.FromSeconds(10));
_isSearching = false;
StateHasChanged();
}
}
}
}

View File

@ -2,8 +2,8 @@
@inherits AntInput
<!--TODO: minheight, maxheight, onResize-->
<textarea class="@ClassMapper.Class" style="@Style" @attributes="Attributes" id="@Id" placeholder="@placeholder" @bind="Value"
@ref="inputEl"
<textarea class="@ClassMapper.Class" style="@Style" @attributes="Attributes" id="@Id" placeholder="@Placeholder" @bind="Value"
@ref="InputEl"
@oninput="OnInputAsync"
@onkeypress="OnPressEnterAsync" />

View File

@ -128,7 +128,7 @@ namespace AntBlazor
private async Task CalculateRowHeightAsync()
{
Element element = await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, inputEl);
Element element = await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, InputEl);
element.ToString();
_hiddenWidth = $"width: {element.offsetWidth}px;";

View File

@ -1,7 +1,7 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<main class="@ClassMapper.Class" @ref="Ref" style="@Style" @attributes="Attributes" Id="@Id">
<main class="@ClassMapper.Class" @ref="Ref" style="@Style" id="@Id">
@ChildContent
</main>
@code {
@ -12,4 +12,4 @@
{
ClassMapper.Add("ant-layout-content");
}
}
}

View File

@ -1,7 +1,7 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<footer class="@ClassMapper.Class" @ref="Ref" style="@Style" @attributes="Attributes" Id="@Id">
<footer class="@ClassMapper.Class" @ref="Ref" style="@Style" id="@Id">
@ChildContent
</footer>

View File

@ -1,7 +1,7 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<header class="@ClassMapper.Class" @ref="Ref" style="@Style" @attributes="Attributes" Id="@Id">
<header class="@ClassMapper.Class" @ref="Ref" style="@Style" id="@Id">
@ChildContent
</header>
@ -19,4 +19,4 @@
.Add("ant-header");
}
}
}

View File

@ -1,9 +1,9 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<section class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<section class="@ClassMapper.Class" style="@Style" id="@Id">
@ChildContent
</section>
</CascadingValue>
@ -14,7 +14,7 @@
public RenderFragment ChildContent { get; set; }
[Parameter]
public bool hasSider { get; set; }
public bool HasSider { get; set; }
protected override void OnInitialized()
@ -22,7 +22,7 @@
base.OnInitialized();
ClassMapper
.Add("ant-layout")
.If("ant-layout-has-sider", () => hasSider);
.If("ant-layout-has-sider", () => HasSider);
}
}

View File

@ -1,16 +1,16 @@
@namespace AntBlazor
@inherits AntSiderBase
@namespace AntBlazor
@inherits AntDomComponentBase
<aside class="@ClassMapper.Class" @ref="Ref" style="@style @Style" @attributes="Attributes" Id="@Id">
<aside class="@ClassMapper.Class" @ref="Ref" style="@Style @base.Style" id="@Id">
<div class="ant-layout-sider-children">
@ChildContent
</div>
@if (isZeroTrigger)
{
<span class="ant-layout-sider-zero-width-trigger" @onclick="toggleCollapse">
@if (zeroTrigger != null)
<span class="ant-layout-sider-zero-width-trigger" @onclick="ToggleCollapse">
@if (ZeroTrigger != null)
{
@zeroTrigger
@ZeroTrigger
}
else
{
@ -22,8 +22,8 @@
@if (isSiderTrigger)
{
<div class="ant-layout-sider-trigger"
@onclick="toggleCollapse"
style="width: @widthSetting">
@onclick="ToggleCollapse"
style="width: @WidthSetting">
@siderTrigger
</div>
}
@ -31,22 +31,22 @@
@code {
bool isZeroTrigger => this.collapsible && this.siderTrigger != null && this.collapsedWidth == 0 && ((this.breakpoint != null && this.below) || this.breakpoint == null);
bool isZeroTrigger => this.Collapsible && this.siderTrigger != null && this.CollapsedWidth == 0 && ((this.Breakpoint != null && this.Below) || this.Breakpoint == null);
bool isSiderTrigger => this.collapsible && this.siderTrigger != null && this.collapsedWidth != 0;
bool isSiderTrigger => this.Collapsible && this.siderTrigger != null && this.CollapsedWidth != 0;
RenderFragment siderTrigger => trigger ?? defaultTrigger(this);
RenderFragment siderTrigger => Trigger ?? defaultTrigger(this);
public RenderFragment<AntSider> defaultTrigger = (sider) =>
@<Template>
@if (!sider.reverseArrow)
@if (!sider.ReverseArrow)
{
<AntIcon type="@(sider.collapsed ? "right" : "left")"></AntIcon>
<AntIcon type="@(sider.Collapsed ? "right" : "left")"></AntIcon>
}
else
{
<AntIcon type="@(sider.collapsed ? "left" : "right")"></AntIcon>
<AntIcon type="@(sider.Collapsed ? "left" : "right")"></AntIcon>
}
</Template>;
}
}

View File

@ -0,0 +1,116 @@
using System.Collections;
using System.Threading.Tasks;
using AntBlazor.JsInterop;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public partial class AntSider : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public string Width { get; set; } = "200";
/// <summary>
/// 'light' | 'dark'
/// </summary>
[Parameter]
public string Theme { get; set; } = "dark";
[Parameter]
public int CollapsedWidth { get; set; } = 80;
/// <summary>
/// "xs" | "sm" | "md" | "lg" | "xl" | "xxl"
/// </summary>
[Parameter]
public string Breakpoint { get; set; }
[Parameter]
public RenderFragment ZeroTrigger { get; set; }
[Parameter]
public bool ReverseArrow { get; set; } = false;
[Parameter]
public bool Collapsible { get; set; } = false;
[Parameter]
public bool Collapsed { get; set; } = false;
[Parameter]
public RenderFragment Trigger { get; set; }
[CascadingParameter]
public AntLayout Layout { get; set; }
[Parameter]
public EventCallback<bool> OnCollapsedChange { get; set; }
[Inject]
private DomEventService DomEventService { get; set; }
protected string WidthSetting => this.Collapsed ? $"{this.CollapsedWidth}px" : StyleHelper.ToCssPixel(Width);
private string FlexSetting => $"0 0 {WidthSetting}";
private string Style =>
$@"flex:{FlexSetting};
max-width:{WidthSetting};
min-width:{WidthSetting};
width:{WidthSetting};
";
private bool Below { get; set; }
private Hashtable _dimensionMap = new Hashtable()
{
["xs"] = "480px",
["sm"] = "576px",
["md"] = "768px",
["lg"] = "992px",
["xl"] = "1200px",
["xxl"] = "1600px"
};
public AntSider()
{
ClassMapper.Add("ant-layout-sider")
.If("ant-layout-sider-zero-width", () => Collapsed && CollapsedWidth == 0)
.If("ant-layout-sider-light", () => Theme == "light")
.If("ant-layout-sider-collapsed", () => Collapsed)
;
}
protected override async Task OnInitializedAsync()
{
DomEventService.AddEventListener<object>("window", "resize", async _ => await WatchMatchMedia());
await base.OnInitializedAsync();
}
protected override async Task OnFirstAfterRenderAsync()
{
await WatchMatchMedia();
await base.OnFirstAfterRenderAsync();
}
public async Task ToggleCollapse()
{
this.Collapsed = !this.Collapsed;
await OnCollapsedChange.InvokeAsync(Collapsed);
}
public async Task WatchMatchMedia()
{
if (string.IsNullOrEmpty(Breakpoint))
return;
var matchBelow = await JsInvokeAsync<bool>(JSInteropConstants.matchMedia, $"(max-width: {_dimensionMap[Breakpoint]})");
this.Below = matchBelow;
this.Collapsed = matchBelow;
await this.OnCollapsedChange.InvokeAsync(matchBelow);
}
}
}

View File

@ -1,114 +0,0 @@
using System.Collections;
using System.Threading.Tasks;
using AntBlazor.JsInterop;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public class AntSiderBase : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public string width { get; set; } = "200";
/// <summary>
/// 'light' | 'dark'
/// </summary>
[Parameter]
public string theme { get; set; } = "dark";
[Parameter]
public int collapsedWidth { get; set; } = 80;
/// <summary>
/// "xs" | "sm" | "md" | "lg" | "xl" | "xxl"
/// </summary>
[Parameter]
public string breakpoint { get; set; }
[Parameter]
public RenderFragment zeroTrigger { get; set; }
[Parameter]
public bool reverseArrow { get; set; } = false;
[Parameter]
public bool collapsible { get; set; } = false;
[Parameter]
public bool collapsed { get; set; } = false;
[Parameter]
public RenderFragment trigger { get; set; }
[CascadingParameter]
public AntLayout Layout { get; set; }
[Parameter]
public EventCallback<bool> onCollapsedChange { get; set; }
[Inject] private DomEventService domEventService { get; set; }
protected string widthSetting => this.collapsed ? $"{this.collapsedWidth}px" : StyleHelper.ToCssPixel(width);
private string flexSetting => $"0 0 {widthSetting}";
protected string style =>
$@"flex:{flexSetting};
max-width:{widthSetting};
min-width:{widthSetting};
width:{widthSetting};
";
protected bool below { get; set; }
private Hashtable dimensionMap = new Hashtable()
{
["xs"] = "480px",
["sm"] = "576px",
["md"] = "768px",
["lg"] = "992px",
["xl"] = "1200px",
["xxl"] = "1600px"
};
public AntSiderBase()
{
ClassMapper.Add("ant-layout-sider")
.If("ant-layout-sider-zero-width", () => collapsed && collapsedWidth == 0)
.If("ant-layout-sider-light", () => theme == "light")
.If("ant-layout-sider-collapsed", () => collapsed)
;
}
protected override async Task OnInitializedAsync()
{
domEventService.AddEventListener<object>("window", "resize", async _ => await watchMatchMedia());
await base.OnInitializedAsync();
}
protected override async Task OnFirstAfterRenderAsync()
{
await watchMatchMedia();
await base.OnFirstAfterRenderAsync();
}
public async Task toggleCollapse()
{
this.collapsed = !this.collapsed;
await onCollapsedChange.InvokeAsync(collapsed);
}
public async Task watchMatchMedia()
{
if (string.IsNullOrEmpty(breakpoint))
return;
var matchBelow = await JsInvokeAsync<bool>(JSInteropConstants.matchMedia, $"(max-width: {dimensionMap[breakpoint]})");
this.below = matchBelow;
this.collapsed = matchBelow;
await this.onCollapsedChange.InvokeAsync(matchBelow);
}
}
}

View File

@ -1,12 +1,8 @@
@namespace AntBlazor
@inherits AntMenuBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<ul ant-menu class="@ClassMapper.Class" @ref="Ref" style="@Style" @attributes="Attributes" Id="@Id">
<ul class="@ClassMapper.Class" @ref="Ref" style="@Style" id="@Id">
@ChildContent
</ul>
</CascadingValue>
@code {
}

View File

@ -0,0 +1,95 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public partial class AntMenu : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public int InlineIndent { get; set; } = 24;
[Parameter]
public string Theme { get; set; } = "light";//'light' | 'dark' = 'light';
[Parameter]
public AntDirectionVHIType Mode { get; set; } = AntDirectionVHIType.vertical;
[Parameter]
public bool InDropDown { get; set; } = false;
[Parameter]
public bool InlineCollapsed { get; set; } = false;
[Parameter]
public bool Selectable { get; set; }
[Parameter]
public EventCallback<AntMenuItem> Click { get; set; }
public IList<AntMenuItem> _menuItems = new List<AntMenuItem>();
public IList<AntSubMenu> _subMenus = new List<AntSubMenu>();
public IList<AntSubMenu> _openedSubMenus = new List<AntSubMenu>();
public bool IsInDropDown { get; set; }
private AntDirectionVHIType _cacheMode;
protected override void OnInitialized()
{
base.OnInitialized();
SetClassMap();
IsInDropDown = InDropDown;
_cacheMode = Mode;
}
private void SetClassMap()
{
string prefixName = IsInDropDown ? "ant-dropdown-menu" : "ant-menu";
ClassMapper.Add(prefixName)
.Add($"{prefixName}-root")
.Add($"{prefixName}-{Theme}")
.Add($"{prefixName}-{Mode}")
.If($"{prefixName}-inline-collapsed", () => InlineCollapsed);
}
protected override async Task OnParametersSetAsync()
{
base.OnParametersSet();
await UpdateInLineCollapse();
}
private async Task UpdateInLineCollapse()
{
if (_menuItems.Any())
{
if (InlineCollapsed)
{
_openedSubMenus = this._subMenus.Where(x => x.Open).ToList();
foreach (var antSubMenu in this._subMenus)
{
await antSubMenu.SetOpenState(false);
}
this.Mode = AntDirectionVHIType.vertical;
}
else
{
foreach (var subMenu in _openedSubMenus)
{
await subMenu.SetOpenState(false);
}
_openedSubMenus.Clear();
this.Mode = this._cacheMode;
}
StateHasChanged();
}
}
}
}

View File

@ -1,95 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public class AntMenuBase : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public int inlineIndent { get; set; } = 24;
[Parameter]
public string theme { get; set; } = "light";//'light' | 'dark' = 'light';
[Parameter]
public AntDirectionVHIType mode { get; set; } = AntDirectionVHIType.vertical;
[Parameter]
public bool inDropDown { get; set; } = false;
[Parameter]
public bool inlineCollapsed { get; set; } = false;
[Parameter]
public bool selectable { get; set; }
[Parameter]
public EventCallback<AntMenuItem> click { get; set; }
public IList<AntMenuItem> MenuItems = new List<AntMenuItem>();
public IList<AntSubMenu> SubMenus = new List<AntSubMenu>();
public IList<AntSubMenu> openedSubMenus = new List<AntSubMenu>();
public bool isInDropDown { get; set; }
private AntDirectionVHIType cacheMode;
protected override void OnInitialized()
{
base.OnInitialized();
SetClassMap();
isInDropDown = inDropDown;
cacheMode = mode;
}
private void SetClassMap()
{
string prefixName = isInDropDown ? "ant-dropdown-menu" : "ant-menu";
ClassMapper.Add(prefixName)
.Add($"{prefixName}-root")
.Add($"{prefixName}-{theme}")
.Add($"{prefixName}-{mode}")
.If($"{prefixName}-inline-collapsed", () => inlineCollapsed);
}
protected override async Task OnParametersSetAsync()
{
base.OnParametersSet();
await updateInLineCollapse();
}
private async Task updateInLineCollapse()
{
if (MenuItems.Any())
{
if (inlineCollapsed)
{
openedSubMenus = this.SubMenus.Where(x => x.open).ToList();
foreach (var antSubMenu in this.SubMenus)
{
await antSubMenu.SetOpenState(false);
}
this.mode = AntDirectionVHIType.vertical;
}
else
{
foreach (var subMenu in openedSubMenus)
{
await subMenu.SetOpenState(false);
}
openedSubMenus.Clear();
this.mode = this.cacheMode;
}
StateHasChanged();
}
}
}
}

View File

@ -1,12 +1,8 @@
@namespace AntBlazor
@inherits AntMenuItemBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value=this>
<li ant-menu-item class="@ClassMapper.Class" @ref="Ref" style="@Style" @attributes="Attributes" Id="@Id" @onclick="()=> Menu.click.InvokeAsync(this)">
<li class="@ClassMapper.Class" @ref="Ref" style="@Style" id="@Id" @onclick="()=> Menu.Click.InvokeAsync(this)">
@ChildContent
</li>
</CascadingValue>
@code {
}

View File

@ -4,25 +4,25 @@ using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public class AntMenuItemBase : AntDomComponentBase
public partial class AntMenuItem : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public bool disabled { get; set; } = false;
public bool Disabled { get; set; } = false;
[Parameter]
public bool selected { get; set; } = false;
public bool Selected { get; set; } = false;
[Parameter]
public int? paddingLeft { get; set; }
public int? PaddingLeft { get; set; }
[Parameter]
public bool matchRouterExact { get; set; } = false;
public bool MatchRouterExact { get; set; } = false;
[Parameter]
public bool matchRouter { get; set; } = false;
public bool MatchRouter { get; set; } = false;
[CascadingParameter]
public AntMenu Menu { get; set; }
@ -30,20 +30,20 @@ namespace AntBlazor
[CascadingParameter]
public AntSubMenu SubMenu { get; set; }
private int originalPadding;
private int _originalPadding;
private void SetClassMap()
{
string prefixName = Menu.isInDropDown ? "ant-dropdown-menu-item" : "ant-menu-item";
string prefixName = Menu.IsInDropDown ? "ant-dropdown-menu-item" : "ant-menu-item";
ClassMapper.Clear()
.Add(prefixName)
.If($"{prefixName}-selected", () => selected)
.If($"{prefixName}-disabled", () => disabled);
.If($"{prefixName}-selected", () => Selected)
.If($"{prefixName}-disabled", () => Disabled);
}
internal void SelectedChanged(bool value)
{
this.selected = value;
this.Selected = value;
}
protected override void OnInitialized()
@ -51,30 +51,26 @@ namespace AntBlazor
base.OnInitialized();
if (this is AntMenuItem item)
{
Menu?.MenuItems.Add(item);
Menu?._menuItems.Add(item);
SubMenu?.Items.Add(item);
}
if (Attributes?.TryGetValue("style", out var style) == true)
{
}
int? padding = null;
if (Menu.mode == AntDirectionVHIType.inline)
if (Menu.Mode == AntDirectionVHIType.inline)
{
if (paddingLeft != null)
if (PaddingLeft != null)
{
padding = paddingLeft;
padding = PaddingLeft;
}
else
{
int level = SubMenu?.Level + 1 ?? 1;
padding = level * this.Menu.inlineIndent;
padding = level * this.Menu.InlineIndent;
}
}
else
{
padding = originalPadding;
padding = _originalPadding;
}
if (padding != null)
@ -85,4 +81,4 @@ namespace AntBlazor
SetClassMap();
}
}
}
}

View File

@ -1,9 +1,9 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<li class="@ClassMapper.Class" @ref="Ref" style="@Style" @attributes="Attributes" Id="@Id">
<li class="@ClassMapper.Class" @ref="Ref" style="@Style" id="@Id">
<div class="@titleClassMapper.Class">
@title
@Title
</div>
@ChildContent
</li>
@ -14,7 +14,7 @@
public RenderFragment ChildContent { get; set; }
[Parameter]
public string title { get; set; }
public string Title { get; set; }
[CascadingParameter]
@ -26,13 +26,13 @@
{
base.OnInitialized();
this.titleClassMapper
.If("ant-dropdown-menu-item-group-title", () => !Menu.isInDropDown)
.If("ant-menu-item-group-title", () => !Menu.isInDropDown)
.If("ant-dropdown-menu-item-group-title", () => !Menu.IsInDropDown)
.If("ant-menu-item-group-title", () => !Menu.IsInDropDown)
;
this.ClassMapper
.If("ant-dropdown-menu-item-group", () => Menu.isInDropDown)
.If("ant-menu-item-group", () => !Menu.isInDropDown);
.If("ant-dropdown-menu-item-group", () => Menu.IsInDropDown)
.If("ant-menu-item-group", () => !Menu.IsInDropDown);
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Routing;
@ -39,6 +40,9 @@ namespace AntBlazor
[Parameter]
public NavLinkMatch Match { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> Attributes { get; set; }
[CascadingParameter]
public AntMenuItem MenuItem { get; set; }
@ -188,4 +192,4 @@ namespace AntBlazor
}
}
}
}
}

View File

@ -1,23 +1,23 @@
@namespace AntBlazor
@inherits AntSubMenuBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value=this>
<li Ant-submenu class="@ClassMapper.Class" @ref="Ref" style="@Style" @attributes="Attributes" Id="@Id">
<li class="@ClassMapper.Class" @ref="Ref" style="@Style" id="@Id">
<div class="@TitleDivClass.Class" style="@titleStyle"
@onmouseover="()=>SetMouseEnterState(true)"
@onmouseout="()=>SetMouseEnterState(false)"
@onclick="()=> ClickSubMenuTitle()">
@if (icon != null)
@if (Icon != null)
{
<AntIcon type="@icon"></AntIcon>
<AntIcon Type="@Icon"></AntIcon>
}
<span>@((MarkupString)title)</span>
<span>@((MarkupString)Title)</span>
@if (Menu.isInDropDown)
@if (Menu.IsInDropDown)
{
<span class="ant-dropdown-menu-submenu-arrow">
<AntIcon type="right" class="anticon-right ant-dropdown-menu-submenu-arrow-icon"></AntIcon>
<AntIcon Type="right" Class="anticon-right ant-dropdown-menu-submenu-arrow-icon"></AntIcon>
</span>
}
else
@ -25,24 +25,24 @@
<i class="ant-menu-submenu-arrow"></i>
}
</div>
@if (Menu.mode == AntDirectionVHIType.inline)
@if (Menu.Mode == AntDirectionVHIType.inline)
{
<ul class="@menuClassName ant-menu ant-menu-inline ant-menu-sub" style="transition: height 0.5s; @submenuStyle">
<ul class="@MenuClassName ant-menu ant-menu-inline ant-menu-sub" style="transition: height 0.5s; @submenuStyle">
@ChildContent
</ul>
}
</li>
@if (open && Menu.mode != AntDirectionVHIType.inline)
@if (Open && Menu.Mode != AntDirectionVHIType.inline)
{
<div style="position: absolute; top: 0px; left: 0px; width: 100%;">
<div class="ant-menu-submenu ant-menu-submenu-popup @PopupClassMapper.Class"
style="left:@(element.offsetLeft+element.clientWidth+10)px; top:@(element.offsetTop)px; @(isMouseHover?"":"display: none;")"
style="left:@(_element.offsetLeft+_element.clientWidth+10)px; top:@(_element.offsetTop)px; @(IsMouseHover?"":"display: none;")"
@onmouseout="()=>SetMouseEnterState(false)"
@onmouseover="()=>SetMouseEnterState(true)"
@onmouseout:stopPropagation
@onmouseover:stopPropagation>
<ul class="@menuClassName @PopupUlClassMapper.Class ant-menu-submenu-content" style="@(isMouseHover?"":"display: none;")">
<ul class="@MenuClassName @PopupUlClassMapper.Class ant-menu-submenu-content" style="@(IsMouseHover?"":"display: none;")">
@ChildContent
</ul>
</div>
@ -53,8 +53,8 @@
@code {
string titleStyle => Menu.mode == AntDirectionVHIType.inline ?
$"padding-left:{(paddingLeft ?? Level * Menu.inlineIndent)}px" : "";
string titleStyle => Menu.Mode == AntDirectionVHIType.inline ?
$"padding-left:{(PaddingLeft ?? Level * Menu.InlineIndent)}px" : "";
string submenuStyle => open ? "" : "height: 0px; overflow: hidden;";
}
string submenuStyle => Open ? "" : "height: 0px; overflow: hidden;";
}

View File

@ -0,0 +1,143 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AntBlazor.JsInterop;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public partial class AntSubMenu : AntDomComponentBase
{
public int Level { get; set; } = 1;
[CascadingParameter]
protected AntMenu Menu { get; set; }
internal IList<AntMenuItem> Items { get; set; } = new List<AntMenuItem>();
[CascadingParameter]
protected AntSubMenu ParentSubMenu { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public string MenuClassName { get; set; }
[Parameter]
public int? PaddingLeft { get; set; }
[Parameter]
public string Title { get; set; }
[Parameter]
public string Icon { get; set; }
[Parameter]
public bool Open { get; set; } = false;
[Parameter]
public bool Disabled { get; set; } = false;
[Parameter]
public EventCallback<bool> OpenChange { get; set; }
protected ClassMapper TitleDivClass { get; } = new ClassMapper();
protected ClassMapper PopupClassMapper { get; } = new ClassMapper();
protected ClassMapper PopupUlClassMapper { get; } = new ClassMapper();
private string _placement = "rightTop";
private int _triggerWidth;
private string _expandState = "collapsed";
private string[] _overlayPositions = new[] { "" };
private bool _isChildMenuSelected = false;
protected bool IsMouseHover { get; set; } = false;
private bool _hasOpened;
protected Element _element = new Element();
private void SetClassMap()
{
this._isChildMenuSelected = this.Items.Any(x => x.Selected);
string prefixName = Menu.IsInDropDown ? "ant-dropdown-menu-submenu" : "ant-menu-submenu";
ClassMapper.Clear()
.Add(prefixName)
.If($"{prefixName}-disabled", () => Disabled)
.If($"{prefixName}-open", () => this.Open)
.If($"{prefixName}-selected", () => _isChildMenuSelected)
.Add($"{prefixName}-{Menu.Mode}")
.If($"{prefixName}-active", () => IsMouseHover && !Disabled)
;
}
protected override void OnInitialized()
{
if (this is AntSubMenu subMenu)
{
this.Menu?._subMenus.Add(subMenu);
}
this.Level = this.ParentSubMenu?.Level + 1 ?? 1;
this._hasOpened = Open;
this.SetClassMap();
base.OnInitialized();
PopupClassMapper.Clear()
.If("ant-menu-light", () => Menu.Theme == "light")
.If("ant-menu-dark", () => Menu.Theme == "dark")
.If("ant-menu-submenu-placement-bottomLeft", () => Menu.Mode == AntDirectionVHIType.horizontal)
.If("ant-menu-submenu-placement-rightTop",
() => Menu.Mode == AntDirectionVHIType.vertical && _placement == "rightTop")
.If("ant-menu-submenu-placement-leftTop",
() => Menu.Mode == AntDirectionVHIType.vertical && _placement == "leftTop")
;
PopupUlClassMapper.Clear()
.If("ant-dropdown-menu", () => Menu.IsInDropDown)
.If("ant-menu", () => !Menu.IsInDropDown)
.If("ant-dropdown-menu-vertical", () => Menu.IsInDropDown)
.If("ant-menu-vertical", () => !Menu.IsInDropDown)
.If("ant-dropdown-menu-sub", () => Menu.IsInDropDown)
.If("ant-menu-sub", () => !Menu.IsInDropDown)
;
TitleDivClass
.If("ant-dropdown-menu-submenu-title", () => Menu.IsInDropDown)
.If("ant-menu-submenu-title", () => !Menu.IsInDropDown)
;
}
protected async Task SetMouseEnterState(bool value)
{
if (IsMouseHover != value)
{
this.IsMouseHover = value;
this.SetClassMap();
this._element = await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, Ref);
}
}
protected async Task ClickSubMenuTitle()
{
if (Menu.Mode == AntDirectionVHIType.inline && !Menu.IsInDropDown && !this.Disabled)
{
this.Open = !this.Open;
await OpenChange.InvokeAsync(this.Open);
this.SetClassMap();
}
}
public async Task SetOpenState(bool value)
{
this.Open = value;
this._hasOpened = value;
await OpenChange.InvokeAsync(this.Open);
StateHasChanged();
}
}
}

View File

@ -1,143 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AntBlazor.JsInterop;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public class AntSubMenuBase : AntDomComponentBase
{
public int Level { get; set; } = 1;
[CascadingParameter]
protected AntMenu Menu { get; set; }
internal IList<AntMenuItem> Items { get; set; } = new List<AntMenuItem>();
[CascadingParameter]
protected AntSubMenu ParentSubMenu { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public string menuClassName { get; set; }
[Parameter]
public int? paddingLeft { get; set; }
[Parameter]
public string title { get; set; }
[Parameter]
public string icon { get; set; }
[Parameter]
public bool open { get; set; } = false;
[Parameter]
public bool disabled { get; set; } = false;
[Parameter]
public EventCallback<bool> openChange { get; set; }
protected ClassMapper TitleDivClass { get; } = new ClassMapper();
protected ClassMapper PopupClassMapper { get; } = new ClassMapper();
protected ClassMapper PopupUlClassMapper { get; } = new ClassMapper();
private string placement = "rightTop";
private int triggerWidth;
private string expandState = "collapsed";
private string[] overlayPositions = new[] { "" };
private bool isChildMenuSelected = false;
protected bool isMouseHover { get; set; } = false;
private bool _hasOpened;
protected Element element = new Element();
private void SetClassMap()
{
this.isChildMenuSelected = this.Items.Any(x => x.selected);
string prefixName = Menu.isInDropDown ? "ant-dropdown-menu-submenu" : "ant-menu-submenu";
ClassMapper.Clear()
.Add(prefixName)
.If($"{prefixName}-disabled", () => disabled)
.If($"{prefixName}-open", () => this.open)
.If($"{prefixName}-selected", () => isChildMenuSelected)
.Add($"{prefixName}-{Menu.mode}")
.If($"{prefixName}-active", () => isMouseHover && !disabled)
;
}
protected override void OnInitialized()
{
if (this is AntSubMenu subMenu)
{
this.Menu?.SubMenus.Add(subMenu);
}
this.Level = this.ParentSubMenu?.Level + 1 ?? 1;
this._hasOpened = open;
this.SetClassMap();
base.OnInitialized();
PopupClassMapper.Clear()
.If("ant-menu-light", () => Menu.theme == "light")
.If("ant-menu-dark", () => Menu.theme == "dark")
.If("ant-menu-submenu-placement-bottomLeft", () => Menu.mode == AntDirectionVHIType.horizontal)
.If("ant-menu-submenu-placement-rightTop",
() => Menu.mode == AntDirectionVHIType.vertical && placement == "rightTop")
.If("ant-menu-submenu-placement-leftTop",
() => Menu.mode == AntDirectionVHIType.vertical && placement == "leftTop")
;
PopupUlClassMapper.Clear()
.If("ant-dropdown-menu", () => Menu.isInDropDown)
.If("ant-menu", () => !Menu.isInDropDown)
.If("ant-dropdown-menu-vertical", () => Menu.isInDropDown)
.If("ant-menu-vertical", () => !Menu.isInDropDown)
.If("ant-dropdown-menu-sub", () => Menu.isInDropDown)
.If("ant-menu-sub", () => !Menu.isInDropDown)
;
TitleDivClass
.If("ant-dropdown-menu-submenu-title", () => Menu.isInDropDown)
.If("ant-menu-submenu-title", () => !Menu.isInDropDown)
;
}
protected async Task SetMouseEnterState(bool value)
{
if (isMouseHover != value)
{
this.isMouseHover = value;
this.SetClassMap();
this.element = await JsInvokeAsync<Element>(JSInteropConstants.getDomInfo, Ref);
}
}
protected async Task ClickSubMenuTitle()
{
if (Menu.mode == AntDirectionVHIType.inline && !Menu.isInDropDown && !this.disabled)
{
this.open = !this.open;
await openChange.InvokeAsync(this.open);
this.SetClassMap();
}
}
public async Task SetOpenState(bool value)
{
this.open = value;
this._hasOpened = value;
await openChange.InvokeAsync(this.open);
StateHasChanged();
}
}
}

View File

@ -1,16 +1,16 @@
@namespace AntBlazor
@inherits AntRadioBase
@namespace AntBlazor
@inherits AntDomComponentBase
<label @onclick="OnClick" class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id" @ref="Ref">
<label @onclick="OnClick" class="@ClassMapper.Class" style="@Style" id="@Id" @ref="Ref">
<span class="@RadioClassMapper.Class">
<input type="radio"
autofocus="@AutoFocus"
class="@InputClassMapper.Class"
disabled="@disabled"
checked="@isChecked"
name="@name"
disabled="@Disabled"
checked="@IsChecked"
name="@_name"
@bind="@Value"
@ref="inputRef" />
@ref="InputRef" />
<span class="@InnerClassMapper.Class"></span>
</span>
<span>@ChildContent</span>

View File

@ -1,23 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace AntBlazor
{
public class AntRadioBase : AntDomComponentBase
public partial class AntRadio : AntDomComponentBase
{
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public string Value { get; set; }
[Parameter]
public string Value { get; set; }
// [Parameter] public bool Disabled { get; set; } = false;
[Parameter]
public bool AutoFocus { get; set; } = false;
[Parameter] public bool AutoFocus { get; set; } = false;
[Parameter]
public bool RadioButton { get; set; }
[Parameter] public bool RadioButton { get; set; }
[Parameter]
public bool Checked { get; set; }
[Parameter]
public bool Disabled { get; set; }
[CascadingParameter] public AntRadioGroup RadioGroup { get; set; }
@ -27,21 +33,17 @@ namespace AntBlazor
protected ClassMapper InnerClassMapper { get; set; } = new ClassMapper();
protected ElementReference inputRef { get; set; }
protected ElementReference InputRef { get; set; }
private Action onChange;
private Action _onChange;
private Action onTouched;
private Action _onTouched;
protected bool isChecked => _checked ?? (this.Attributes.TryGetValue("checked", out var val)
? bool.TryParse(val.ToString(), out bool _disabled) ? _disabled : true : false);
protected bool IsChecked => _checked ?? this.Checked;
protected bool? _checked { get; set; }
private bool? _checked;
internal string name { get; set; } = null;
protected bool disabled => this.Attributes.TryGetValue("disabled", out var val)
? bool.TryParse(val.ToString(), out bool _disabled) ? _disabled : true : false;
internal string _name;
protected void SetClass()
{
@ -49,18 +51,18 @@ namespace AntBlazor
ClassMapper.Clear()
.If($"{prefixCls}-wrapper", () => !RadioButton)
.If($"{prefixCls}-button-wrapper", () => RadioButton)
.If($"{prefixCls}-wrapper-checked", () => isChecked && !RadioButton)
.If($"{prefixCls}-button-wrapper-checked", () => isChecked && RadioButton)
.If($"{prefixCls}-wrapper-disabled", () => disabled && !RadioButton)
.If($"{prefixCls}-button-wrapper-disabled", () => disabled && RadioButton);
.If($"{prefixCls}-wrapper-checked", () => IsChecked && !RadioButton)
.If($"{prefixCls}-button-wrapper-checked", () => IsChecked && RadioButton)
.If($"{prefixCls}-wrapper-disabled", () => Disabled && !RadioButton)
.If($"{prefixCls}-button-wrapper-disabled", () => Disabled && RadioButton);
RadioClassMapper.Clear()
.If(prefixCls, () => !RadioButton)
.If($"{prefixCls}-checked", () => isChecked && !RadioButton)
.If($"{prefixCls}-disabled", () => disabled && !RadioButton)
.If($"{prefixCls}-checked", () => IsChecked && !RadioButton)
.If($"{prefixCls}-disabled", () => Disabled && !RadioButton)
.If($"{prefixCls}-button", () => RadioButton)
.If($"{prefixCls}-button-checked", () => isChecked && RadioButton)
.If($"{prefixCls}-button-disabled", () => disabled && RadioButton);
.If($"{prefixCls}-button-checked", () => IsChecked && RadioButton)
.If($"{prefixCls}-button-disabled", () => Disabled && RadioButton);
InputClassMapper.Clear()
.If($"{prefixCls}-input", () => !RadioButton)
@ -93,7 +95,7 @@ namespace AntBlazor
internal async Task Select()
{
if (!disabled && !isChecked)
if (!Disabled && !IsChecked)
{
this._checked = true;
}
@ -106,7 +108,7 @@ namespace AntBlazor
internal async Task UnSelect()
{
if (this.isChecked)
if (this.IsChecked)
{
this._checked = false;
}
@ -120,12 +122,12 @@ namespace AntBlazor
protected async Task Focus()
{
await JsInvokeAsync(JSInteropConstants.focus, this.inputRef);
await JsInvokeAsync(JSInteropConstants.focus, this.InputRef);
}
protected async Task Blur()
{
await JsInvokeAsync(JSInteropConstants.blur, this.inputRef);
await JsInvokeAsync(JSInteropConstants.blur, this.InputRef);
}
}
}
}

View File

@ -1,29 +1,37 @@
@namespace AntBlazor
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id" @ref="Ref">
<div class="@ClassMapper.Class" style="@Style" id="@Id" @ref="Ref">
@ChildContent
</div>
</CascadingValue>
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public bool Disabled { get; set; }
[Parameter]
public bool Disabled { get; set; }
[Parameter] public string ButtonStyle { get; set; } = "outline";
[Parameter]
public string ButtonStyle { get; set; } = "outline";
[Parameter] public string Size { get; set; } = "default";
[Parameter]
public string Size { get; set; } = "default";
[Parameter] public string Name { get; set; }
[Parameter]
public string Name { get; set; }
[Parameter] public EventCallback<string> OnChange { get; set; }
[Parameter]
public EventCallback<string> OnChange { get; set; }
[Parameter] public string Value { get; set; }
[Parameter]
public string Value { get; set; }
[Parameter] public EventCallback<string > ValueChanged { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
internal List<AntRadio> RadioItems { get; set; } = new List<AntRadio>();
@ -62,7 +70,7 @@
{
if (this.Name != null)
{
radio.name = Name;
radio._name = Name;
}
RadioItems.Add(radio);
if (this._currentValue == radio.Value)

View File

@ -1,9 +1,9 @@
@namespace AntBlazor
@inherits AntStepBase
@namespace AntBlazor
@inherits AntDomComponentBase
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<div class="ant-steps-item-container" @onclick="@OnClick" tabindex="@GetTabIndex()" @attributes="@ContainerAttributes">
<div class="@ClassMapper.Class" style="@Style"id="@Id">
<div class="ant-steps-item-container" @onclick="@OnClick" tabindex="@GetTabIndex()" @attributes="@_containerAttributes">
@if (!Last)
{
<div class="ant-steps-item-tail"></div>
@ -63,4 +63,4 @@
}
</div>
</div>
</div>
</div>

View File

@ -8,21 +8,23 @@ using System.Text;
namespace AntBlazor
{
public class AntStepBase : AntDomComponentBase
public partial class AntStep : AntDomComponentBase
{
private string _status = "wait";
private bool _isCustomStatus;
private int _groupCurrent;
protected Dictionary<string, object> ContainerAttributes = new Dictionary<string, object>();
protected Dictionary<string, object> _containerAttributes = new Dictionary<string, object>();
internal bool Clickable { get; set; }
internal bool Last { get; set; }
internal bool ShowProcessDot { get; set; }
internal string GroupStatus { get; set; } = string.Empty;
internal int GroupCurrentIndex {
internal int GroupCurrentIndex
{
get => _groupCurrent;
set {
set
{
_groupCurrent = value;
if (!_isCustomStatus)
{
@ -35,12 +37,18 @@ namespace AntBlazor
internal RenderFragment? ProgressDot { get; set; }
internal string Direction { get; set; } = "horizontal";
[CascadingParameter] AntStepsBase Parent { get; set; }
[Parameter] public string Icon { get; set; }
[Parameter] public string Status {
[CascadingParameter]
public AntSteps Parent { get; set; }
[Parameter]
public string Icon { get; set; }
[Parameter]
public string Status
{
get => _status;
set {
set
{
_status = value;
_isCustomStatus = true;
SetClassMap();
@ -51,22 +59,22 @@ namespace AntBlazor
[Parameter] public string Description { get; set; } = string.Empty;
[Parameter] public EventCallback<MouseEventArgs> OnClick { get; set; }
[Parameter] public bool Disabled { get; set; }
protected override void OnInitialized()
{
Parent.Children.Add(this);
this.Index = Parent.Children.Count - 1;
Parent._children.Add(this);
this.Index = Parent._children.Count - 1;
SetClassMap();
if (Clickable && !Disabled)
{
ContainerAttributes["role"] = "button";
_containerAttributes["role"] = "button";
}
}
public override void Dispose()
{
Parent.Children.Remove(this);
Parent._children.Remove(this);
Parent.ResetChildrenSteps();
base.Dispose();
}
@ -83,10 +91,10 @@ namespace AntBlazor
ClassMapper.Clear()
.Add(prefixName)
.If($"{prefixName}-{Status}", () => !string.IsNullOrEmpty(Status))
.If($"{prefixName}-active", () => Parent.Current==Index)
.If($"{prefixName}-active", () => Parent.Current == Index)
.If($"{prefixName}-disabled", () => Disabled)
.If($"{prefixName}-custom", () => !string.IsNullOrEmpty(Icon))
.If($"ant-steps-next-error", () => GroupStatus=="error" && Parent.Current==Index+1)
.If($"ant-steps-next-error", () => GroupStatus == "error" && Parent.Current == Index + 1)
;
}

View File

@ -1,8 +1,8 @@
@namespace AntBlazor
@inherits AntStepsBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<div class="@ClassMapper.Class" style="@Style" id="@Id">
@ChildContent
</div>
</CascadingValue>

View File

@ -5,23 +5,28 @@ using System.Threading.Tasks;
namespace AntBlazor
{
public class AntStepsBase:AntDomComponentBase
public partial class AntSteps : AntDomComponentBase
{
private bool _showProgressDot;
private RenderFragment _progressDot;
public EventHandler Handler { get; }
internal List<AntStepBase> Children = new List<AntStepBase>();
internal List<AntStep> _children = new List<AntStep>();
[Parameter] public int Current { get; set; }
[Parameter] public RenderFragment ProgressDot {
[Parameter]
public RenderFragment ProgressDot
{
get => _progressDot;
set {
set
{
_progressDot = value;
_showProgressDot = value!=null;
_showProgressDot = value != null;
ResetChildrenSteps();
}
}
}
[Parameter] public bool ShowProgressDot {
[Parameter]
public bool ShowProgressDot
{
get => _showProgressDot;
set => _showProgressDot = value;
}
@ -37,30 +42,30 @@ namespace AntBlazor
public override void Dispose()
{
foreach(AntStepBase step in Children)
foreach (var step in _children)
{
step.Dispose();
}
Children.Clear();
_children.Clear();
base.Dispose();
}
internal void ResetChildrenSteps()
{
for(int i = 0; i< Children.Count; i++)
for (int i = 0; i < _children.Count; i++)
{
Children[i].GroupStatus = this.Status;
Children[i].ShowProcessDot = this._showProgressDot;
_children[i].GroupStatus = this.Status;
_children[i].ShowProcessDot = this._showProgressDot;
//if (this.ProgressDot !=null )
//{
// Children[i].ProgressDot = this.ProgressDot;
//}
Children[i].Clickable = OnChange!=null; //TODO: Develop event emitter
Children[i].Direction = this.Direction;
Children[i].Index = i + this.StartIndex;
Children[i].GroupCurrentIndex = this.Current;
Children[i].Last = Children.Count == i + 1;
Children[i].MarkForCheck();
_children[i].Clickable = OnChange != null; //TODO: Develop event emitter
_children[i].Direction = this.Direction;
_children[i].Index = i + this.StartIndex;
_children[i].GroupCurrentIndex = this.Current;
_children[i].Last = _children.Count == i + 1;
_children[i].MarkForCheck();
}
}
@ -79,7 +84,7 @@ namespace AntBlazor
{
ResetChildrenSteps();
});
}
protected void SetClassMap()
@ -89,8 +94,8 @@ namespace AntBlazor
.Add(prefixName)
.Add(ClassName)
.If($"{prefixName}-{Direction}", () => !string.IsNullOrEmpty(Direction))
.If($"{prefixName}-label-horizontal", ()=>Direction=="horizontal")
.If($"{prefixName}-label-vertical", () => (_showProgressDot || LabelPlacement=="vertical") && Direction=="horizontal" )
.If($"{prefixName}-label-horizontal", () => Direction == "horizontal")
.If($"{prefixName}-label-vertical", () => (_showProgressDot || LabelPlacement == "vertical") && Direction == "horizontal")
.If($"{prefixName}-dot", () => _showProgressDot)
.If($"{prefixName}-small", () => Size == "small")
.If($"{prefixName}-navigation", () => Type == "navigation")

View File

@ -2,17 +2,17 @@
@inherits AntDomComponentBase
<button type="button" role="switch"
aria-checked="@isChecked"
disabled="@disabled"
aria-checked="@_isChecked"
disabled="@Disabled"
class="@ClassMapper.Class"
style="@Style"
@onclick="@OnClickHandler">
@if (loading)
@if (Loading)
{
<AntIcon type="loading" Class="@($"{prefixCls}-loading-icon")" />
}
<span class="@($"{prefixCls}-inner")">
@(isChecked ? CheckedChildren : UnCheckedChildren)
@(_isChecked ? CheckedChildren : UnCheckedChildren)
</span>
</button>
@ -24,32 +24,32 @@
{
ClassMapper.Clear()
.Add(prefixCls)
.If($"{prefixCls}-checked", () => isChecked)
.If($"{prefixCls}-disabled", () => disabled || loading)
.If($"{prefixCls}-loading", () => loading)
.If($"{prefixCls}-small", () => size.Equals("small"))
.If($"{prefixCls}-checked", () => _isChecked)
.If($"{prefixCls}-disabled", () => Disabled || Loading)
.If($"{prefixCls}-loading", () => Loading)
.If($"{prefixCls}-small", () => Size.Equals("small"))
;
return base.OnParametersSetAsync();
}
private bool isChecked = false;
private bool _isChecked = false;
[Parameter]
public bool @checked { get; set; }
public bool Checked { get; set; }
[Parameter]
public bool disabled { get; set; }
public bool Disabled { get; set; }
[Parameter]
public bool loading { get; set; }
public bool Loading { get; set; }
[Parameter]
public bool control { get; set; }
public bool Control { get; set; }
[Parameter]
public string size { get; set; } = "default";
public string Size { get; set; } = "default";
[Parameter]
@ -64,23 +64,24 @@
protected override void OnInitialized()
{
this.isChecked = @checked;
this._isChecked = Checked;
base.OnInitialized();
}
protected void OnClickHandler(MouseEventArgs ev)
{
if (!disabled && !loading&&!control)
if (!Disabled && !Loading && !Control)
{
this.updateValue(!this.isChecked);
this.updateValue(!this._isChecked);
}
}
private void updateValue(bool value)
{
if (this.isChecked != value) {
this.isChecked = value;
this.OnChange.InvokeAsync(this.isChecked);
if (this._isChecked != value)
{
this._isChecked = value;
this.OnChange.InvokeAsync(this._isChecked);
}
}

View File

@ -7,7 +7,8 @@ namespace AntBlazor
private const string PrefixCls = "ant-tabs-tab";
private AntTabs _parent;
internal ClassMapper ClassMapper = new ClassMapper();
internal ClassMapper _classMapper = new ClassMapper();
internal bool IsActive { get; set; }
[CascadingParameter]
@ -58,10 +59,10 @@ namespace AntBlazor
{
base.OnParametersSet();
ClassMapper.Clear().
_classMapper.Clear().
Add(PrefixCls)
.If($"{PrefixCls}-active", () => IsActive)
.If($"{PrefixCls}-disabled", () => Disabled);
}
}
}
}

View File

@ -4,7 +4,7 @@
@ChildContent
</CascadingValue>
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" id="@Id">
<div class="@ClassMapper.Class" style="@Style" id="@Id">
<!---->
@if (TabBarExtraContent != null)
{
@ -36,7 +36,7 @@
{
if (pane.IsActive)
{
<div @ref="_activeTabBar" tabindex="0" class="@pane.ClassMapper.Class" id="tab-@pane.Key" role="tab"
<div @ref="_activeTabBar" tabindex="0" class="@pane._classMapper.Class" id="tab-@pane.Key" role="tab"
aria-disabled="@pane.Disabled" aria-selected="true" aria-controls="tabpane-@pane.Key"
draggable="@Draggable.ToString()"
@ondragover:preventDefault
@ -125,7 +125,7 @@
{
if (pane.IsActive)
{
<div @ref="_activeTabBar" tabindex="0" class="@pane.ClassMapper.Class" id="tab-@pane.Key" role="tab"
<div @ref="_activeTabBar" tabindex="0" class="@pane._classMapper.Class" id="tab-@pane.Key" role="tab"
aria-disabled="@pane.Disabled" aria-selected="true" aria-controls="tabpane-@pane.Key"
draggable="@Draggable.ToString()"
@ondragover:preventDefault

View File

@ -1,103 +1,13 @@
@namespace AntBlazor
@using System.Text.RegularExpressions
@namespace AntBlazor
@inherits AntDomComponentBase
@if (!closed)
@if (!_closed)
{
<div class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id" @ref="Ref">
<div class="@ClassMapper.Class" style="@Style" id="@Id" @ref="Ref">
@ChildContent
@if (mode == "closeable")
@if (Mode == "closeable")
{
<AntIcon type="close" tabindex="-1" @onclick="closeTag" />
<AntIcon Type="close" TabIndex="-1" @onclick="CloseTag" />
}
</div>
}
@code {
[Parameter] public RenderFragment ChildContent { get; set; }
/// <summary>
/// 'default' | 'closeable' | 'checkable'
/// </summary>
[Parameter]
public string mode { get; set; } = "default";
[Parameter]
public string color { get; set; }
[Parameter]
public bool closable { get; set; }
[Parameter]
public bool visible { get; set; } = true;
[Parameter]
public bool @checked { get; set; }
[Parameter]
public bool noAnimation { get; set; }
[Parameter]
public EventCallback afterClose { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> onClose { get; set; }
[Parameter]
public EventCallback<bool> checkedChange { get; set; }
bool presetColor = false;
bool closed = false;
protected override Task OnInitializedAsync()
{
this.updateClassMap();
return base.OnInitializedAsync();
}
protected override void OnParametersSet()
{
this.updateClassMap();
base.OnParametersSet();
}
private bool isPresetColor(string color)
{
if (string.IsNullOrEmpty(color))
{
return false;
}
return Regex.IsMatch(color, "^(pink|red|yellow|orange|cyan|green|blue|purple|geekblue|magenta|volcano|gold|lime)(-inverse)?$");
}
private void updateClassMap()
{
this.presetColor = this.isPresetColor(this.color);
string prefix = "ant-tag";
this.ClassMapper.Clear().Add(prefix)
.If($"{prefix}-has-color", () => !string.IsNullOrEmpty(color) && !presetColor)
.If($"{prefix}-${color}", () => presetColor)
.If($"{prefix}-checkable", () => mode == "checkable")
.If($"{prefix}-checkable-checked", () => @checked)
;
}
private async Task updateCheckedStatus()
{
if (mode == "checkable")
{
this.@checked = !this.@checked;
await this.checkedChange.InvokeAsync(this.@checked);
this.updateClassMap();
}
}
private async Task closeTag(MouseEventArgs e)
{
await this.onClose.InvokeAsync(e);
this.closed = true;
}
}

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
namespace AntBlazor
{
public partial class AntTag : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
/// <summary>
/// 'default' | 'closeable' | 'checkable'
/// </summary>
[Parameter]
public string Mode { get; set; } = "default";
[Parameter]
public string Color { get; set; }
[Parameter]
public bool Closable { get; set; }
[Parameter]
public bool Visible { get; set; } = true;
[Parameter]
public bool Checked { get; set; }
[Parameter]
public bool NoAnimation { get; set; }
[Parameter]
public EventCallback AfterClose { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClose { get; set; }
[Parameter]
public EventCallback<bool> CheckedChange { get; set; }
bool _presetColor = false;
bool _closed = false;
protected override Task OnInitializedAsync()
{
this.UpdateClassMap();
return base.OnInitializedAsync();
}
protected override void OnParametersSet()
{
this.UpdateClassMap();
base.OnParametersSet();
}
private bool IsPresetColor(string color)
{
if (string.IsNullOrEmpty(color))
{
return false;
}
return Regex.IsMatch(color, "^(pink|red|yellow|orange|cyan|green|blue|purple|geekblue|magenta|volcano|gold|lime)(-inverse)?$");
}
private void UpdateClassMap()
{
this._presetColor = this.IsPresetColor(this.Color);
string prefix = "ant-tag";
this.ClassMapper.Clear().Add(prefix)
.If($"{prefix}-has-color", () => !string.IsNullOrEmpty(Color) && !_presetColor)
.If($"{prefix}-${Color}", () => _presetColor)
.If($"{prefix}-checkable", () => Mode == "checkable")
.If($"{prefix}-checkable-checked", () => Checked)
;
}
private async Task UpdateCheckedStatus()
{
if (Mode == "checkable")
{
this.Checked = !this.Checked;
await this.CheckedChange.InvokeAsync(this.Checked);
this.UpdateClassMap();
}
}
private async Task CloseTag(MouseEventArgs e)
{
await this.OnClose.InvokeAsync(e);
this._closed = true;
}
}
}

View File

@ -1,15 +1,15 @@
@namespace AntBlazor
@inherits AntTimelineBase
@namespace AntBlazor
@inherits AntDomComponentBase
<CascadingValue Value="this">
<ul class="@ClassMapper.Class" style="@Style" @attributes="Attributes" Id="@Id">
<ul class="@ClassMapper.Class" style="@Style" id="@Id">
@ChildContent
@foreach (var item in displayItems)
@foreach (var item in DisplayItems)
{
<li class="@item.Class" @ref="item.Ref" style="@item.Style" @attributes="item.Attributes" Id="@item.Id">
<li class="@item.ItemClass" @ref="item.Ref" style="@item.Style" id="@item.Id">
<div class="ant-timeline-item-tail"></div>
<div class="@item.HeadClassMapper.Class" style="@item.headStyle">
<div class="@item._headClassMapper.Class" style="@item.HeadStyle">
@if (item.Dot != null)
{
@item.Dot
@ -25,6 +25,6 @@
@code{
protected override RenderFragment LoadingDot => @<AntIcon type="loading"></AntIcon>;
private RenderFragment _loadingDot = @<AntIcon type="loading"></AntIcon>;
}

View File

@ -1,19 +1,20 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Components;
namespace AntBlazor
{
public class AntTimelineBase : AntDomComponentBase
public partial class AntTimeline : AntDomComponentBase
{
/// <summary>
/// 'left' | 'alternate' | 'right'
/// </summary>
[Parameter]
public string mode { get; set; }
public string Mode { get; set; }
[Parameter]
public bool reverse { get; set; }
public bool Reverse { get; set; }
[Parameter]
public RenderFragment Pending { get; set; }
@ -27,12 +28,12 @@ namespace AntBlazor
if (this.Pending == null) return null;
var item = new AntTimelineItem()
{
ChildContent = !isPendingBoolean ? Pending : null,
ChildContent = !_isPendingBoolean ? Pending : null,
Dot = PendingDot ?? LoadingDot,
@class = "ant-timeline-item-pending"
Class = "ant-timeline-item-pending"
};
item.setClassMap();
item.SetClassMap();
return item;
}
}
@ -43,56 +44,56 @@ namespace AntBlazor
[Parameter]
public RenderFragment ChildContent { get; set; }
protected IList<AntTimelineItem> Items = new List<AntTimelineItem>();
private IList<AntTimelineItem> _items = new List<AntTimelineItem>();
protected IList<AntTimelineItem> displayItems
protected IList<AntTimelineItem> DisplayItems
{
get
{
var pitems = PendingItem != null ? new[] { PendingItem } : new AntTimelineItem[] { };
if (reverse)
var pitems = PendingItem != null ? new[] { PendingItem } : Array.Empty<AntTimelineItem>();
if (Reverse)
{
return pitems.Concat(updateChildren(Items.Reverse())).ToList();
return pitems.Concat(UpdateChildren(_items.Reverse())).ToList();
}
else
{
return updateChildren(Items).Concat(pitems).ToList();
return UpdateChildren(_items).Concat(pitems).ToList();
}
}
}
protected bool isPendingBoolean;
private bool _isPendingBoolean;
protected override void OnInitialized()
{
setClassMap();
SetClassMap();
base.OnInitialized();
}
protected override void OnParametersSet()
{
setClassMap();
SetClassMap();
base.OnParametersSet();
}
protected void setClassMap()
protected void SetClassMap()
{
var prefix = "ant-timeline";
ClassMapper.Clear()
.Add(prefix)
.If($"{prefix}-right", () => mode == "right")
.If($"{prefix}-alternate", () => mode == "alternate")
.If($"{prefix}-right", () => Mode == "right")
.If($"{prefix}-alternate", () => Mode == "alternate")
.If($"{prefix}-pending", () => Pending != null)
.If($"{prefix}-reverse", () => reverse);
.If($"{prefix}-reverse", () => Reverse);
}
internal void AddItem(AntTimelineItem item)
{
this.Items.Add(item);
this._items.Add(item);
StateHasChanged();
}
protected IEnumerable<AntTimelineItem> updateChildren(IEnumerable<AntTimelineItem> items)
protected IEnumerable<AntTimelineItem> UpdateChildren(IEnumerable<AntTimelineItem> items)
{
if (!items.Any())
yield break;
@ -101,17 +102,17 @@ namespace AntBlazor
for (int i = 0; i < length; i++)
{
var item = items.ElementAt(i);
item.isLast = i == length - 1;
item.position =
this.mode == "left" || mode == null ? null
: this.mode == "right" ? "right"
: this.mode == "alternate" && i % 2 == 0 ? "left"
item.IsLast = i == length - 1;
item.Position =
this.Mode == "left" || Mode == null ? null
: this.Mode == "right" ? "right"
: this.Mode == "alternate" && i % 2 == 0 ? "left"
: "right";
item.setClassMap();
item.SetClassMap();
yield return item;
}
}
}
}
}

View File

@ -3,61 +3,63 @@ using System.Linq;
namespace AntBlazor
{
public class AntTimelineItem : AntDomComponentBase
public partial class AntTimelineItem : AntDomComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter] public RenderFragment Dot { get; set; }
[Parameter]
public RenderFragment Dot { get; set; }
[Parameter] public string color { get; set; } = "blue";
[Parameter]
public string Color { get; set; } = "blue";
[CascadingParameter] public AntTimeline ParentTimeline { get; set; }
internal ClassMapper HeadClassMapper = new ClassMapper();
internal ClassMapper _headClassMapper = new ClassMapper();
internal bool isLast { get; set; } = false;
internal bool IsLast { get; set; } = false;
//'left' | 'alternate' | 'right'
internal string position { get; set; } = "";
internal string Position { get; set; } = "";
internal string headStyle { get; set; } = "";
internal string HeadStyle { get; set; } = "";
internal string Class => ClassMapper.Class;
internal string ItemClass => ClassMapper.Class;
private readonly string[] defaultColors = new[] { "blue", "red", "green", "gray" };
private readonly string[] _defaultColors = new[] { "blue", "red", "green", "gray" };
protected override void OnInitialized()
{
ParentTimeline.AddItem(this);
this.tryUpdateCustomColor();
this.TryUpdateCustomColor();
base.OnInitialized();
}
protected override void OnParametersSet()
{
this.setClassMap();
this.tryUpdateCustomColor();
this.SetClassMap();
this.TryUpdateCustomColor();
base.OnParametersSet();
}
private void tryUpdateCustomColor()
private void TryUpdateCustomColor()
{
headStyle = !defaultColors.Contains(color) ? $"border-color:{color}" : "";
HeadStyle = !_defaultColors.Contains(Color) ? $"border-color:{Color}" : "";
}
internal void setClassMap()
internal void SetClassMap()
{
var prefix = "ant-timeline-item";
ClassMapper.Clear().Add(prefix)
.If($"{prefix}-right", () => position == "right")
.If($"{prefix}-left", () => position == "left")
.If($"{prefix}-last", () => isLast);
.If($"{prefix}-right", () => Position == "right")
.If($"{prefix}-left", () => Position == "left")
.If($"{prefix}-last", () => IsLast);
var headPrefix = "ant-timeline-item-head";
HeadClassMapper.Clear().Add(headPrefix)
.If($"{headPrefix}-{color}", () => defaultColors.Contains(color))
_headClassMapper.Clear().Add(headPrefix)
.If($"{headPrefix}-{Color}", () => _defaultColors.Contains(Color))
.If($"{headPrefix}-custom", () => Dot != null);
}
}
}
}

View File

@ -1,17 +1,16 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using System;
using System.Collections.Generic;
using System.Text;
namespace AntBlazor
{
public class AntParagraph : AntTypographyBase
{
[Inject]
private HtmlRenderService _service { get; set; }
private HtmlRenderService Service { get; set; }
[Parameter]
public bool code { get; set; } = false;
public bool Code { get; set; } = false;
protected override void OnInitialized()
{
@ -24,8 +23,8 @@ namespace AntBlazor
string prefixName = "ant-typography";
ClassMapper.Clear()
.Add("ant-typography")
.If($"{prefixName}-{type}", () => !string.IsNullOrEmpty(type))
.If($"{prefixName}-disabled", () => disabled);
.If($"{prefixName}-{Type}", () => !string.IsNullOrEmpty(Type))
.If($"{prefixName}-disabled", () => Disabled);
}
protected override void OnParametersSet()
@ -40,19 +39,19 @@ namespace AntBlazor
builder.OpenElement(0, "div");
builder.AddAttribute(1, "class", this.ClassMapper.Class);
builder.OpenElement(2, "span");
if (mark) builder.OpenElement(3, "mark");
if (delete) builder.OpenElement(4, "del");
if (underline) builder.OpenElement(5, "u");
if (code) builder.OpenElement(6, "code");
if (strong) builder.OpenElement(7, "strong");
if (Mark) builder.OpenElement(3, "mark");
if (Delete) builder.OpenElement(4, "del");
if (Underline) builder.OpenElement(5, "u");
if (Code) builder.OpenElement(6, "code");
if (Strong) builder.OpenElement(7, "strong");
builder.AddContent(8, ChildContent);
if (strong) builder.CloseElement();
if (code) builder.CloseElement();
if (underline) builder.CloseElement();
if (delete) builder.CloseElement();
if (mark) builder.CloseElement();
if (Strong) builder.CloseElement();
if (Code) builder.CloseElement();
if (Underline) builder.CloseElement();
if (Delete) builder.CloseElement();
if (Mark) builder.CloseElement();
builder.CloseElement();
if (copyable)
if (Copyable)
{
builder.OpenElement(9, "a");
builder.AddAttribute(10, "onclick", (Action)(async ()=> await Copy()));

View File

@ -9,7 +9,7 @@ namespace AntBlazor
public class AntText : AntTypographyBase
{
[Parameter]
public bool code { get; set; }
public bool Code { get; set; }
protected override void OnInitialized()
{
@ -22,8 +22,8 @@ namespace AntBlazor
string prefixName = "ant-typography";
ClassMapper.Clear()
.Add("ant-typography")
.If($"{prefixName}-{type}", () => !string.IsNullOrEmpty(type))
.If($"{prefixName}-disabled", () => disabled);
.If($"{prefixName}-{Type}", () => !string.IsNullOrEmpty(Type))
.If($"{prefixName}-disabled", () => Disabled);
}
protected override void OnParametersSet()
@ -39,18 +39,18 @@ namespace AntBlazor
builder.OpenElement(0, "span");
builder.AddAttribute(1, "class", this.ClassMapper.Class);
if (mark) builder.OpenElement(2, "mark");
if (delete) builder.OpenElement(3, "del");
if (underline) builder.OpenElement(4, "u");
if (code) builder.OpenElement(5, "code");
if (strong) builder.OpenElement(6, "strong");
if (Mark) builder.OpenElement(2, "mark");
if (Delete) builder.OpenElement(3, "del");
if (Underline) builder.OpenElement(4, "u");
if (Code) builder.OpenElement(5, "code");
if (Strong) builder.OpenElement(6, "strong");
builder.AddContent(6, ChildContent);
if (strong) builder.CloseElement();
if (code) builder.CloseElement();
if (underline) builder.CloseElement();
if (delete) builder.CloseElement();
if (mark) builder.CloseElement();
if (copyable)
if (Strong) builder.CloseElement();
if (Code) builder.CloseElement();
if (Underline) builder.CloseElement();
if (Delete) builder.CloseElement();
if (Mark) builder.CloseElement();
if (Copyable)
{
builder.OpenElement(7, "a");
builder.AddAttribute(8, "onclick", (Action)(async () => await Copy()));

View File

@ -9,7 +9,7 @@ namespace AntBlazor
public class AntTitle : AntTypographyBase
{
[Parameter]
public int level { get; set; } = 1;
public int Level { get; set; } = 1;
protected override void OnInitialized()
{
@ -22,8 +22,8 @@ namespace AntBlazor
string prefixName = "ant-typography";
ClassMapper.Clear()
.Add("ant-typography")
.If($"{prefixName}-{type}", () => !string.IsNullOrEmpty(type))
.If($"{prefixName}-disabled", () => disabled);
.If($"{prefixName}-{Type}", () => !string.IsNullOrEmpty(Type))
.If($"{prefixName}-disabled", () => Disabled);
}
protected override void OnParametersSet()
@ -35,18 +35,18 @@ namespace AntBlazor
{
base.BuildRenderTree(builder);
// According to Ant-Design 4.0, Fallback to 1 if level is invalid.
int localLevel = level < 1 || level > 4 ? 1 : level;
int localLevel = Level < 1 || Level > 4 ? 1 : Level;
builder.OpenElement(0, "h" + localLevel);
builder.AddAttribute(1, "class", this.ClassMapper.Class);
if (mark) builder.OpenElement(2, "mark");
if (delete) builder.OpenElement(3, "del");
if (underline) builder.OpenElement(4, "u");
if (Mark) builder.OpenElement(2, "mark");
if (Delete) builder.OpenElement(3, "del");
if (Underline) builder.OpenElement(4, "u");
builder.AddContent(5, ChildContent);
if (underline) builder.CloseElement();
if (delete) builder.CloseElement();
if (mark) builder.CloseElement();
if (copyable)
if (Underline) builder.CloseElement();
if (Delete) builder.CloseElement();
if (Mark) builder.CloseElement();
if (Copyable)
{
builder.OpenElement(6, "a");
builder.AddAttribute(7, "onclick", (Action)(async () => await Copy()));

View File

@ -1,8 +1,5 @@
using AntBlazor.typography;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace AntBlazor
@ -10,82 +7,97 @@ namespace AntBlazor
public abstract class AntTypographyBase : AntDomComponentBase
{
[Inject]
public HtmlRenderService _service { get; set; }
public HtmlRenderService Service { get; set; }
[Parameter]
public bool copyable { get; set; } = false;
public bool Copyable { get; set; } = false;
[Parameter]
public TypographyCopyableConfig copyConfig { get; set; }
public TypographyCopyableConfig CopyConfig { get; set; }
[Parameter]
public bool delete { get; set; } = false;
public bool Delete { get; set; } = false;
[Parameter]
public bool disabled { get; set; } = false;
public bool Disabled { get; set; } = false;
[Parameter]
public bool editable { get; set; } = false;
public bool Editable { get; set; } = false;
[Parameter]
public TypographyEditableConfig editConfig { get; set; }
public TypographyEditableConfig EditConfig { get; set; }
[Parameter]
public bool ellipsis { get; set; } = false;
public bool Ellipsis { get; set; } = false;
[Parameter]
public TypographyEllipsisConfig ellipsisConfig {get;set;}
public TypographyEllipsisConfig EllipsisConfig { get; set; }
[Parameter]
public bool mark { get; set; } = false;
public bool Mark { get; set; } = false;
[Parameter]
public bool underline { get; set; } = false;
public bool Underline { get; set; } = false;
[Parameter]
public bool strong { get; set; } = false;
public bool Strong { get; set; } = false;
[Parameter]
public Action onChange { get; set; }
public Action OnChange { get; set; }
[Parameter]
public string type { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
[Parameter]
public RenderFragment ChildContent { get; set; }
public async Task Copy()
{
if (!copyable)
if (!Copyable)
{
return;
}
else if (copyConfig is null)
else if (CopyConfig is null)
{
await this.JsInvokeAsync<object>(JSInteropConstants.copy, await _service.RenderAsync(ChildContent));
await this.JsInvokeAsync<object>(JSInteropConstants.copy, await Service.RenderAsync(ChildContent));
}
else if (copyConfig.onCopy is null)
else if (CopyConfig.OnCopy is null)
{
if (string.IsNullOrEmpty(copyConfig.text))
if (string.IsNullOrEmpty(CopyConfig.Text))
{
await this.JsInvokeAsync<object>(JSInteropConstants.copy, await _service.RenderAsync(ChildContent));
await this.JsInvokeAsync<object>(JSInteropConstants.copy, await Service.RenderAsync(ChildContent));
}
else
{
await this.JsInvokeAsync<object>(JSInteropConstants.copy, copyConfig.text);
await this.JsInvokeAsync<object>(JSInteropConstants.copy, CopyConfig.Text);
}
}
else
{
copyConfig.onCopy.Invoke();
CopyConfig.OnCopy.Invoke();
}
}
}
public class TypographyCopyableConfig
{
public string text { get; set; } = string.Empty;
public Action onCopy { get; set; } = null;
public string Text { get; set; } = string.Empty;
public Action OnCopy { get; set; } = null;
}
public class TypographyEditableConfig
{
public Action onStart { get; set; }
public Action<string> onChange { get; set; }
public Action OnStart { get; set; }
public Action<string> OnChange { get; set; }
}
public class TypographyEllipsisConfig
{
public string suffix { get; set; } = "...";
public int rows { get; set; }
public Action onExpand { get; set; }
public string Suffix { get; set; } = "...";
public int Rows { get; set; }
public Action OnExpand { get; set; }
}
}

View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
namespace AntBlazor.typography
namespace AntBlazor
{
public static class TextElementType
{

View File

@ -6,16 +6,16 @@ namespace AntBlazor.Docs.Localization
{
public class Resources
{
private Dictionary<string, string> keyValues = null;
private Dictionary<string, string> _keyValues = null;
public Resources(string languageContent)
{
initialize(languageContent);
Initialize(languageContent);
}
private void initialize(string languageContent)
private void Initialize(string languageContent)
{
keyValues = new Deserializer().Deserialize<Dictionary<string, string>>(languageContent).Select(k => new { Key = k.Key.ToLower(), Value = k.Value }).ToDictionary(t => t.Key, t => t.Value);
_keyValues = new Deserializer().Deserialize<Dictionary<string, string>>(languageContent).Select(k => new { Key = k.Key.ToLower(), Value = k.Value }).ToDictionary(t => t.Key, t => t.Value);
}
public string this[string key]
@ -24,7 +24,7 @@ namespace AntBlazor.Docs.Localization
{
try
{
return keyValues[key.ToLower()];
return _keyValues[key.ToLower()];
}
catch
{
@ -33,4 +33,4 @@ namespace AntBlazor.Docs.Localization
}
}
}
}
}

View File

@ -1,6 +1,6 @@
<AntTitle level="1">Alert</AntTitle>
<AntTitle Level="1">Alert</AntTitle>
<AntText>Alert component for feedback.</AntText>
<AntTitle level="2">When to use</AntTitle>
<AntTitle Level="2">When to use</AntTitle>
<AntParagraph>
<ul>
<li>When you need to show alert messages to users.</li>

View File

@ -1,14 +1,14 @@

<h3>Avatar</h3>
<AntAvatar size="large" icon="user" />
<AntAvatar icon="user" />
<AntAvatar size="small" icon="user" />
<AntAvatar Size="large" Icon="user" />
<AntAvatar Icon="user" />
<AntAvatar Size="small" Icon="user" />
<br />
<AntAvatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
<AntAvatar style=" background-color: #87d068 " icon="user" />
<AntAvatar Src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />
<AntAvatar Style="background-color: #87d068" Icon="user" />
<br/>
<AntAvatar text="USER"></AntAvatar>
<AntAvatar Text="USER"></AntAvatar>

View File

@ -1,6 +1,6 @@
<AntTitle level="1">BackTop回到顶部</AntTitle>
<AntTitle Level="1">BackTop回到顶部</AntTitle>
<AntText>返回页面顶部的操作按钮。</AntText>
<AntTitle level="2">何时使用</AntTitle>
<AntTitle Level="2">何时使用</AntTitle>
<AntParagraph>
<ul>
<li>当页面内容区域比较长时;</li>

View File

@ -1,6 +1,6 @@
<AntTitle level="1">Badge</AntTitle>
<AntTitle Level="1">Badge</AntTitle>
<AntText>Small numerical value or status descriptor for UI elements.</AntText>
<AntTitle level="2">When to use</AntTitle>
<AntTitle Level="2">When to use</AntTitle>
<AntText>Badge normally appears in proximity to notifications or user avatars with eye-catching appeal, typically displaying unread messages count.</AntText>
<br />
<h2>Examples</h2>

Some files were not shown because too many files have changed in this diff Show More