mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-13 13:45:53 +00:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ae64ba919 | ||
|
|
6e94a7c65b | ||
|
|
44e20b2b5f | ||
|
|
d109c2e295 | ||
|
|
0feffad278 | ||
|
|
3be412643f | ||
|
|
6d8c4ceb16 | ||
|
|
40b7d84224 | ||
|
|
4511c654f9 | ||
|
|
547a681878 | ||
|
|
cad80d533d | ||
|
|
f485420ba9 | ||
|
|
ac61235a48 | ||
|
|
61bd1db8b9 | ||
|
|
5992a97ef9 | ||
|
|
157070c922 | ||
|
|
14e39f665f | ||
|
|
2f77a0b849 | ||
|
|
c3af020b81 | ||
|
|
19460b899b | ||
|
|
3cf12c82bf | ||
|
|
adf86b2896 | ||
|
|
7b96fe3cb4 | ||
|
|
9a58c3a35a | ||
|
|
876c248a8e |
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
@@ -1026,6 +1026,36 @@ public class ExpressionParserTests
|
||||
Assert.True(func(new Person { BirthDate = DateTime.Parse("5/5/2000 12:00:00 AM") }));
|
||||
}
|
||||
|
||||
class EmployeeWithHireDate
|
||||
{
|
||||
public DateTime? HireDate { get; set; }
|
||||
public DateOnly? HireDateOnly { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_SupportNullableDateTimeArrayWithSpecifyKindAndNullableProperty()
|
||||
{
|
||||
var predicate = "x => new System.DateTime?[] { DateTime.SpecifyKind(DateTime.Parse(\"2012-04-01\", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind), DateTimeKind.Unspecified) }.Contains((x.HireDate ?? null))";
|
||||
var expression = ExpressionParser.ParsePredicate<EmployeeWithHireDate>(predicate);
|
||||
var func = expression.Compile();
|
||||
|
||||
var hireDate = DateTime.SpecifyKind(DateTime.Parse("2012-04-01", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind), DateTimeKind.Unspecified);
|
||||
Assert.True(func(new EmployeeWithHireDate { HireDate = hireDate }));
|
||||
Assert.False(func(new EmployeeWithHireDate { HireDate = DateTime.Parse("2013-01-01") }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_SupportNullableDateOnlyArrayAndNullableProperty()
|
||||
{
|
||||
var predicate = "x => new System.DateOnly?[] { DateOnly.Parse(\"2012-04-01\") }.Contains((x.HireDateOnly ?? null))";
|
||||
var expression = ExpressionParser.ParsePredicate<EmployeeWithHireDate>(predicate);
|
||||
var func = expression.Compile();
|
||||
|
||||
var hireDate = DateOnly.Parse("2012-04-01");
|
||||
Assert.True(func(new EmployeeWithHireDate { HireDateOnly = hireDate }));
|
||||
Assert.False(func(new EmployeeWithHireDate { HireDateOnly = DateOnly.Parse("2013-01-01") }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Should_SupportNumericConversion()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -319,5 +319,35 @@ namespace Radzen.Blazor.Tests
|
||||
Expression<Func<TestEntity, bool>> expr = e => !e.Tags.Contains("Member");
|
||||
Assert.Equal("e => (!(e.Tags.Contains(\"Member\")))", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DefaultExpression_ReferenceType()
|
||||
{
|
||||
// Simulates the NullPropagate pattern: x.Address == null ? default(string) : x.Address.City
|
||||
var param = Expression.Parameter(typeof(TestEntity), "x");
|
||||
var address = Expression.Property(param, "Address");
|
||||
var city = Expression.Property(address, "City");
|
||||
var isNull = Expression.Equal(address, Expression.Constant(null, typeof(Address)));
|
||||
var whenNull = Expression.Default(typeof(string));
|
||||
var conditional = Expression.Condition(isNull, whenNull, city);
|
||||
var lambda = Expression.Lambda<Func<TestEntity, string>>(conditional, param);
|
||||
|
||||
Assert.Equal("x => ((x.Address == null) ? null : x.Address.City)", _serializer.Serialize(lambda));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DefaultExpression_ValueType()
|
||||
{
|
||||
// Simulates a conditional with a default value type
|
||||
var param = Expression.Parameter(typeof(TestEntity), "x");
|
||||
var address = Expression.Property(param, "Address");
|
||||
var age = Expression.Property(param, "Age");
|
||||
var isNull = Expression.Equal(address, Expression.Constant(null, typeof(Address)));
|
||||
var whenNull = Expression.Default(typeof(int));
|
||||
var conditional = Expression.Condition(isNull, whenNull, age);
|
||||
var lambda = Expression.Lambda<Func<TestEntity, int>>(conditional, param);
|
||||
|
||||
Assert.Equal("x => ((x.Address == null) ? default(int) : x.Age)", _serializer.Serialize(lambda));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.AllowResetPassword, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"Forgot password?</button>", component.Markup);
|
||||
Assert.Contains(@$"Forgot password?</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -134,7 +134,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.ResetPasswordText, "Test");
|
||||
});
|
||||
|
||||
Assert.Contains(@$"Test</button>", component.Markup);
|
||||
Assert.Contains(@$"Test</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -195,7 +195,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.Register, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-secondary").Click();
|
||||
component.Find(".rz-secondary.rz-variant-flat").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
@@ -215,7 +215,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.ResetPassword, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find("button.rz-link").Click();
|
||||
component.Find(".rz-secondary.rz-variant-text").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
@@ -234,7 +234,7 @@ namespace Radzen.Blazor.Tests
|
||||
parameters.Add(p => p.ResetPassword, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find("button.rz-link").Click();
|
||||
component.Find(".rz-secondary.rz-variant-text").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
|
||||
@@ -105,12 +105,10 @@ namespace Radzen.Blazor
|
||||
throw new ArgumentException($"Property {propertyName} does not exist");
|
||||
}
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if(PropertyAccess.IsDateOnly(property))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return PropertyAccess.IsDate(property);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
@@ -1086,6 +1086,10 @@ namespace Radzen
|
||||
selectedItems.Clear();
|
||||
}
|
||||
}
|
||||
else if (internalValue == null && Multiple && selectedItems.Count > 0)
|
||||
{
|
||||
selectedItems.Clear();
|
||||
}
|
||||
|
||||
SelectItemFromValue(internalValue);
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Radzen;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
#else
|
||||
/// <summary>
|
||||
/// Enables "onmouseenter" and "onmouseleave" event support in Blazor. Not for public use.
|
||||
/// </summary>
|
||||
[EventHandler("onmouseenter", typeof(EventArgs), true, true)]
|
||||
[EventHandler("onmouseleave", typeof(EventArgs), true, true)]
|
||||
public static class EventHandlers
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -414,6 +414,11 @@ public class ExpressionParser
|
||||
return ParseStaticMemberAccess(type, parameter);
|
||||
}
|
||||
|
||||
if (TryParseQualifiedType(out var qualifiedType))
|
||||
{
|
||||
return ParseStaticMemberAccess(qualifiedType, parameter);
|
||||
}
|
||||
|
||||
if (Peek(1).Type == TokenType.OpenParen)
|
||||
{
|
||||
Advance(1);
|
||||
@@ -542,19 +547,10 @@ public class ExpressionParser
|
||||
else
|
||||
{
|
||||
Type? elementType = null;
|
||||
var nullable = false;
|
||||
|
||||
if (token.Type == TokenType.Identifier)
|
||||
if (TryParseQualifiedArrayType(out var parsedElementType))
|
||||
{
|
||||
var typeName = token.Value;
|
||||
elementType = GetWellKnownType(typeName);
|
||||
Advance(1);
|
||||
|
||||
if (Peek().Type == TokenType.QuestionMark)
|
||||
{
|
||||
nullable = true;
|
||||
Advance(1);
|
||||
}
|
||||
elementType = parsedElementType;
|
||||
}
|
||||
|
||||
Expect(TokenType.OpenBracket);
|
||||
@@ -585,11 +581,6 @@ public class ExpressionParser
|
||||
elementType = elements.Count > 0 ? elements[0].Type : typeof(object);
|
||||
}
|
||||
|
||||
if (nullable)
|
||||
{
|
||||
elementType = typeof(Nullable<>).MakeGenericType(elementType);
|
||||
}
|
||||
|
||||
return Expression.NewArrayInit(elementType, elements.Select(e => ConvertIfNeeded(e, elementType)));
|
||||
}
|
||||
default:
|
||||
@@ -653,7 +644,7 @@ public class ExpressionParser
|
||||
{
|
||||
var name = typeName.ToString();
|
||||
|
||||
var type = GetWellKnownType(name) ?? typeResolver?.Invoke(name) ?? throw new InvalidOperationException($"Could not resolve type: {typeName}");
|
||||
var type = ResolveType(name) ?? throw new InvalidOperationException($"Could not resolve type: {typeName}");
|
||||
|
||||
if (nullable && type.IsValueType)
|
||||
{
|
||||
@@ -729,6 +720,156 @@ public class ExpressionParser
|
||||
return Expression.Call(null, method, arguments);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to parse a qualified type name (e.g. System.DateTime or System.DateTime?) and returns the resolved type.
|
||||
/// Advances position past the type name. The next token will be . for member access or [ for array.
|
||||
/// Uses backtracking to find the longest resolvable type prefix (e.g. System.DateTime in System.DateTime.SpecifyKind).
|
||||
/// </summary>
|
||||
private bool TryParseQualifiedType(out Type type)
|
||||
{
|
||||
type = null!;
|
||||
|
||||
var token = Peek();
|
||||
if (token.Type != TokenType.Identifier)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var startPosition = position;
|
||||
var parts = new List<string> { token.Value };
|
||||
Advance(1);
|
||||
|
||||
while (Peek().Type == TokenType.Dot)
|
||||
{
|
||||
Advance(1);
|
||||
token = Peek();
|
||||
if (token.Type != TokenType.Identifier)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
parts.Add(token.Value);
|
||||
Advance(1);
|
||||
}
|
||||
|
||||
var nullable = false;
|
||||
if (Peek().Type == TokenType.QuestionMark)
|
||||
{
|
||||
nullable = true;
|
||||
Advance(1);
|
||||
}
|
||||
|
||||
for (var i = parts.Count; i >= 1; i--)
|
||||
{
|
||||
var typeName = string.Join(".", parts.Take(i));
|
||||
var resolvedType = ResolveType(typeName);
|
||||
if (resolvedType != null)
|
||||
{
|
||||
if (nullable && resolvedType.IsValueType)
|
||||
{
|
||||
resolvedType = typeof(Nullable<>).MakeGenericType(resolvedType);
|
||||
}
|
||||
|
||||
position = startPosition;
|
||||
var tokensToConsume = (i * 2) - 1 + (nullable ? 1 : 0);
|
||||
for (var t = 0; t < tokensToConsume; t++)
|
||||
{
|
||||
Advance(1);
|
||||
}
|
||||
|
||||
type = resolvedType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
position = startPosition;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to parse a qualified array element type (e.g. System.DateTime? or DateTime) before [].
|
||||
/// Advances position past the type name to the [. Returns the element type for the array.
|
||||
/// </summary>
|
||||
private bool TryParseQualifiedArrayType(out Type? elementType)
|
||||
{
|
||||
elementType = null;
|
||||
|
||||
var token = Peek();
|
||||
if (token.Type != TokenType.Identifier)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var startPosition = position;
|
||||
var parts = new List<string> { token.Value };
|
||||
Advance(1);
|
||||
|
||||
while (Peek().Type == TokenType.Dot)
|
||||
{
|
||||
Advance(1);
|
||||
token = Peek();
|
||||
if (token.Type != TokenType.Identifier)
|
||||
{
|
||||
position = startPosition;
|
||||
return false;
|
||||
}
|
||||
parts.Add(token.Value);
|
||||
Advance(1);
|
||||
}
|
||||
|
||||
var nullable = false;
|
||||
if (Peek().Type == TokenType.QuestionMark)
|
||||
{
|
||||
nullable = true;
|
||||
Advance(1);
|
||||
}
|
||||
|
||||
if (Peek().Type != TokenType.OpenBracket)
|
||||
{
|
||||
position = startPosition;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = parts.Count; i >= 1; i--)
|
||||
{
|
||||
var typeName = string.Join(".", parts.Take(i));
|
||||
var resolvedType = ResolveType(typeName);
|
||||
if (resolvedType != null)
|
||||
{
|
||||
if (nullable && resolvedType.IsValueType)
|
||||
{
|
||||
resolvedType = typeof(Nullable<>).MakeGenericType(resolvedType);
|
||||
}
|
||||
elementType = resolvedType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
position = startPosition;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a type name using well-known types, the optional type resolver, or by searching loaded assemblies.
|
||||
/// This allows any type from loaded assemblies to be resolved without hardcoding.
|
||||
/// </summary>
|
||||
private Type? ResolveType(string typeName)
|
||||
{
|
||||
return GetWellKnownType(typeName)
|
||||
?? typeResolver?.Invoke(typeName)
|
||||
?? ResolveTypeFromAssemblies(typeName);
|
||||
}
|
||||
|
||||
private static Type? ResolveTypeFromAssemblies(string typeName)
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a => a.GetTypes())
|
||||
.FirstOrDefault(t =>
|
||||
{
|
||||
var fullName = t.FullName;
|
||||
return fullName != null && fullName.Replace("+", ".", StringComparison.Ordinal) == typeName;
|
||||
});
|
||||
}
|
||||
|
||||
private static Type? GetWellKnownType(string typeName)
|
||||
{
|
||||
return typeName switch
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
@@ -272,6 +272,21 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitDefault(DefaultExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
if (!node.Type.IsValueType || Nullable.GetUnderlyingType(node.Type) != null)
|
||||
{
|
||||
_sb.Append("null");
|
||||
}
|
||||
else
|
||||
{
|
||||
_sb.Append(CultureInfo.InvariantCulture, $"default({node.Type.DisplayName(true).Replace("+", ".", StringComparison.Ordinal)})");
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps an ExpressionType to its corresponding C# operator.
|
||||
/// </summary>
|
||||
|
||||
@@ -115,12 +115,10 @@ public static class PropertyAccess
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#if NET6_0_OR_GREATER
|
||||
if (type == typeof(DateOnly))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -134,12 +132,10 @@ public static class PropertyAccess
|
||||
if (source == null) return false;
|
||||
var type = source.IsGenericType ? source.GetGenericArguments()[0] : source;
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if (type == typeof(DateOnly))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -151,9 +147,7 @@ public static class PropertyAccess
|
||||
public static object? DateOnlyFromDateTime(DateTime source)
|
||||
{
|
||||
object? result = null;
|
||||
#if NET6_0_OR_GREATER
|
||||
result = DateOnly.FromDateTime(source);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,7 @@ namespace Radzen
|
||||
private readonly NavigationManager navigationManager;
|
||||
private readonly ThemeService themeService;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
private readonly IDisposable? registration;
|
||||
#endif
|
||||
private readonly QueryStringThemeServiceOptions? options;
|
||||
private readonly PropertyInfo? hasAttachedJSRuntimeProperty;
|
||||
|
||||
@@ -74,7 +72,6 @@ namespace Radzen
|
||||
|
||||
themeService.ThemeChanged += OnThemeChanged;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
try
|
||||
{
|
||||
registration = navigationManager.RegisterLocationChangingHandler(OnLocationChanging);
|
||||
@@ -86,14 +83,12 @@ namespace Radzen
|
||||
// avoid calling NavigateTo which would cause a 302 redirect during prerendering.
|
||||
themeService.ThemeChanged -= OnThemeChanged;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private bool RequiresChange((string? theme, bool? wcag, bool? rightToLeft) state) =>
|
||||
(state.theme != null && !string.Equals(themeService.Theme, state.theme, StringComparison.OrdinalIgnoreCase)) ||
|
||||
themeService.Wcag != state.wcag || themeService.RightToLeft != state.rightToLeft;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
private ValueTask OnLocationChanging(LocationChangingContext context)
|
||||
{
|
||||
var state = GetStateFromQueryString(context.TargetLocation);
|
||||
@@ -107,7 +102,6 @@ namespace Radzen
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
#endif
|
||||
|
||||
private (string? theme, bool? wcag, bool? rightToLeft) GetStateFromQueryString(string uri)
|
||||
{
|
||||
@@ -158,9 +152,7 @@ namespace Radzen
|
||||
{
|
||||
themeService.ThemeChanged -= OnThemeChanged;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
registration?.Dispose();
|
||||
#endif
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
<PropertyGroup>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
@@ -11,7 +11,7 @@
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageId>Radzen.Blazor</PackageId>
|
||||
<Product>Radzen.Blazor</Product>
|
||||
<Version>9.0.1</Version>
|
||||
<Version>9.0.4</Version>
|
||||
<Copyright>Radzen Ltd.</Copyright>
|
||||
<Authors>Radzen Ltd.</Authors>
|
||||
<Description>Radzen Blazor is the most sophisticated free UI component library for Blazor, featuring 100+ native components including DataGrid, Scheduler, Charts, and advanced theming with full support for Material Design and Fluent UI.</Description>
|
||||
@@ -36,8 +36,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DartSassBuilder" Version="1.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.25" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net6.0'" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Condition="'$(TargetFramework)' == 'net7.0'" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Condition="'$(TargetFramework)' == 'net8.0'" Version="8.0.0" />
|
||||
|
||||
@@ -326,8 +326,6 @@ namespace Radzen
|
||||
|
||||
debouncer?.Dispose();
|
||||
debouncer = null;
|
||||
reference?.Dispose();
|
||||
reference = null;
|
||||
|
||||
if (IsJSRuntimeAvailable && JSRuntime != null && !string.IsNullOrEmpty(UniqueID))
|
||||
{
|
||||
@@ -346,6 +344,9 @@ namespace Radzen
|
||||
JSRuntime.InvokeVoid("Radzen.removeMouseLeave", UniqueID);
|
||||
}
|
||||
}
|
||||
|
||||
reference?.Dispose();
|
||||
reference = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -10,9 +10,7 @@ namespace Radzen.Blazor
|
||||
/// RadzenDataFilter component.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">The type of the item.</typeparam>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenDataFilter<TItem> : RadzenComponent
|
||||
{
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -83,9 +83,7 @@ namespace Radzen.Blazor
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenDataGrid<TItem> : PagedDataBoundComponent<TItem> where TItem : notnull
|
||||
{
|
||||
private static readonly string[] DefaultGroupProperty = new string[] { "it" };
|
||||
@@ -3647,6 +3645,15 @@ namespace Radzen.Blazor
|
||||
|
||||
_value = null;
|
||||
Data = null;
|
||||
_view = null;
|
||||
_groupedPagedView = null;
|
||||
|
||||
if (Query != null)
|
||||
{
|
||||
Query.GetFilter = null;
|
||||
Query.Filters = null;
|
||||
Query.Sorts = null;
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Collections;
|
||||
@@ -188,76 +188,80 @@ namespace Radzen.Blazor
|
||||
if (Grid != null)
|
||||
{
|
||||
Grid.AddColumn(this);
|
||||
SetColumnDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
var canSetFilterPropertyType = (FilterMode ?? Grid.FilterMode) == Radzen.FilterMode.CheckBoxList && FilterTemplate == null;
|
||||
private void SetColumnDefaults()
|
||||
{
|
||||
var canSetFilterPropertyType = (FilterMode ?? Grid.FilterMode) == Radzen.FilterMode.CheckBoxList && FilterTemplate == null;
|
||||
|
||||
if (canSetFilterPropertyType)
|
||||
if (canSetFilterPropertyType)
|
||||
{
|
||||
if (Type == null)
|
||||
{
|
||||
if (Type == null)
|
||||
{
|
||||
var fp = GetFilterProperty();
|
||||
var pt = !string.IsNullOrEmpty(fp) ?
|
||||
PropertyAccess.GetPropertyType(typeof(TItem), fp) : typeof(object);
|
||||
var fp = GetFilterProperty();
|
||||
var pt = !string.IsNullOrEmpty(fp) ?
|
||||
PropertyAccess.GetPropertyType(typeof(TItem), fp) : typeof(object);
|
||||
|
||||
_filterPropertyType = typeof(IEnumerable<>).MakeGenericType(pt!);
|
||||
}
|
||||
|
||||
if (GetFilterOperator() == FilterOperator.Equals)
|
||||
{
|
||||
SetFilterOperator(FilterOperator.Contains);
|
||||
}
|
||||
|
||||
Grid.FilterPopupRenderMode = PopupRenderMode.OnDemand;
|
||||
_filterPropertyType = typeof(IEnumerable<>).MakeGenericType(pt!);
|
||||
}
|
||||
|
||||
var property = GetFilterProperty();
|
||||
|
||||
if (!string.IsNullOrEmpty(property) && Type == null)
|
||||
{
|
||||
_propertyType = PropertyAccess.GetPropertyType(typeof(TItem), property);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(property) && Type == null && !canSetFilterPropertyType)
|
||||
{
|
||||
_filterPropertyType = _propertyType;
|
||||
}
|
||||
|
||||
if (_filterPropertyType == null)
|
||||
{
|
||||
_filterPropertyType = Type;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(Property))
|
||||
{
|
||||
propertyValueGetter = PropertyAccess.Getter<TItem, object>(Property);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Property) && (typeof(TItem).IsGenericType && typeof(IDictionary<,>).IsAssignableFrom(typeof(TItem).GetGenericTypeDefinition()) ||
|
||||
typeof(IDictionary).IsAssignableFrom(typeof(TItem)) || typeof(System.Data.DataRow).IsAssignableFrom(typeof(TItem))))
|
||||
{
|
||||
propertyValueGetter = PropertyAccess.Getter<TItem, object>(Property);
|
||||
}
|
||||
|
||||
if (_filterPropertyType == typeof(string) && filterOperator != FilterOperator.Custom && filterOperator == null && _filterOperator == null)
|
||||
if (GetFilterOperator() == FilterOperator.Equals)
|
||||
{
|
||||
SetFilterOperator(FilterOperator.Contains);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Property) && !string.IsNullOrEmpty(FilterProperty))
|
||||
UniqueID = $"{Property}.{FilterProperty}"; // To be sure the column uniqueID is unique even when filtering on sub property.
|
||||
else
|
||||
UniqueID = !string.IsNullOrEmpty(Property) ? Property : FilterProperty;
|
||||
|
||||
if (UseDisplayName && !string.IsNullOrEmpty(Property))
|
||||
Grid.FilterPopupRenderMode = PopupRenderMode.OnDemand;
|
||||
}
|
||||
|
||||
var property = GetFilterProperty();
|
||||
|
||||
if (!string.IsNullOrEmpty(property) && Type == null)
|
||||
{
|
||||
_propertyType = PropertyAccess.GetPropertyType(typeof(TItem), property);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(property) && Type == null && !canSetFilterPropertyType)
|
||||
{
|
||||
_filterPropertyType = _propertyType;
|
||||
}
|
||||
|
||||
if (_filterPropertyType == null)
|
||||
{
|
||||
_filterPropertyType = Type;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(Property))
|
||||
{
|
||||
propertyValueGetter = PropertyAccess.Getter<TItem, object>(Property);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Property) && (typeof(TItem).IsGenericType && typeof(IDictionary<,>).IsAssignableFrom(typeof(TItem).GetGenericTypeDefinition()) ||
|
||||
typeof(IDictionary).IsAssignableFrom(typeof(TItem)) || typeof(System.Data.DataRow).IsAssignableFrom(typeof(TItem))))
|
||||
{
|
||||
propertyValueGetter = PropertyAccess.Getter<TItem, object>(Property);
|
||||
}
|
||||
|
||||
if (_filterPropertyType == typeof(string) && filterOperator != FilterOperator.Custom && filterOperator == null && _filterOperator == null)
|
||||
{
|
||||
SetFilterOperator(FilterOperator.Contains);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Property) && !string.IsNullOrEmpty(FilterProperty))
|
||||
UniqueID = $"{Property}.{FilterProperty}"; // To be sure the column uniqueID is unique even when filtering on sub property.
|
||||
else
|
||||
UniqueID = !string.IsNullOrEmpty(Property) ? Property : FilterProperty;
|
||||
|
||||
if (UseDisplayName && !string.IsNullOrEmpty(Property))
|
||||
{
|
||||
var propInfo = typeof(TItem).GetProperty(Property);
|
||||
if (propInfo != null)
|
||||
{
|
||||
var propInfo = typeof(TItem).GetProperty(Property);
|
||||
if (propInfo != null)
|
||||
var displayAttr = propInfo.GetCustomAttributes(typeof(DisplayAttribute), true)
|
||||
.FirstOrDefault() as DisplayAttribute;
|
||||
if (displayAttr?.Name != null)
|
||||
{
|
||||
var displayAttr = propInfo.GetCustomAttributes(typeof(DisplayAttribute), true)
|
||||
.FirstOrDefault() as DisplayAttribute;
|
||||
if (displayAttr?.Name != null)
|
||||
{
|
||||
Title = displayAttr.Name;
|
||||
}
|
||||
Title = displayAttr.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1353,7 +1357,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
public virtual void ClearFilters()
|
||||
{
|
||||
var fo = FilterOperator == FilterOperator.Custom
|
||||
var fo = GetFilterOperator() == FilterOperator.Custom
|
||||
? FilterOperator.Custom
|
||||
: typeof(System.Collections.IEnumerable).IsAssignableFrom(FilterPropertyType)
|
||||
? !string.IsNullOrEmpty(FilterProperty) && FilterProperty != Property ? FilterOperator.In : FilterOperator.Contains
|
||||
@@ -1373,6 +1377,7 @@ namespace Radzen.Blazor
|
||||
|
||||
LogicalFilterOperator = default(LogicalFilterOperator);
|
||||
|
||||
SetColumnDefaults();
|
||||
}
|
||||
|
||||
FilterOperator? _filterOperator;
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
@(!string.IsNullOrEmpty(Column.FormatString) ? string.Format(Column.FormatProvider ?? Grid?.Culture ?? CultureInfo.CurrentCulture, Column.FormatString, context ?? string.Empty) : Convert.ToString(context, Grid?.Culture ?? CultureInfo.CurrentCulture))
|
||||
@(!string.IsNullOrEmpty(Column.FormatString) ? string.Format(Column.FormatProvider ?? Grid?.Culture ?? CultureInfo.CurrentCulture, Column.FormatString, context ?? string.Empty) : Convert.ToString(context ?? string.Empty, Grid?.Culture ?? CultureInfo.CurrentCulture))
|
||||
}
|
||||
</Template>
|
||||
</RadzenListBox>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -35,9 +35,7 @@ namespace Radzen.Blazor
|
||||
/// </RadzenDataList>
|
||||
/// </code>
|
||||
/// </example>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenDataList<TItem> : PagedDataBoundComponent<TItem>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
@@ -356,13 +356,11 @@ namespace Radzen.Blazor
|
||||
|
||||
UpdateYearsAndMonths(Min, Max);
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if (typeof(TValue) == typeof(TimeOnly) || typeof(TValue) == typeof(TimeOnly?))
|
||||
{
|
||||
TimeOnly = true;
|
||||
ShowTime = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void UpdateYearsAndMonths(DateTime? min, DateTime? max)
|
||||
@@ -541,7 +539,6 @@ namespace Radzen.Blazor
|
||||
_value = dtEnum;
|
||||
_dateTimeValue = selectedDates.LastOrDefault();
|
||||
}
|
||||
#if NET6_0_OR_GREATER
|
||||
else if (value is IEnumerable<DateTime?> ndtEnum)
|
||||
{
|
||||
selectedDates = ndtEnum.Where(d => d.HasValue && d.Value != default(DateTime))
|
||||
@@ -552,19 +549,6 @@ namespace Radzen.Blazor
|
||||
_value = ndtEnum;
|
||||
_dateTimeValue = selectedDates.LastOrDefault();
|
||||
}
|
||||
#else
|
||||
else if (value is IEnumerable<System.Nullable<DateTime>> ndtEnum)
|
||||
{
|
||||
selectedDates = ndtEnum.Where(d => d.HasValue && d.Value != default(DateTime))
|
||||
.Select(d => DateTime.SpecifyKind(d.Value.Date, Kind))
|
||||
.Distinct()
|
||||
.OrderBy(d => d)
|
||||
.ToList();
|
||||
_value = ndtEnum;
|
||||
_dateTimeValue = selectedDates.LastOrDefault();
|
||||
}
|
||||
#endif
|
||||
#if NET6_0_OR_GREATER
|
||||
else if (value is IEnumerable<DateOnly> doEnum)
|
||||
{
|
||||
selectedDates = doEnum.Select(d => d.ToDateTime(System.TimeOnly.MinValue, Kind).Date)
|
||||
@@ -574,7 +558,6 @@ namespace Radzen.Blazor
|
||||
_value = doEnum;
|
||||
_dateTimeValue = selectedDates.LastOrDefault();
|
||||
}
|
||||
#endif
|
||||
else if (value is IEnumerable<DateTimeOffset?> dtoEnum)
|
||||
{
|
||||
selectedDates = dtoEnum.Where(o => o.HasValue)
|
||||
@@ -600,7 +583,6 @@ namespace Radzen.Blazor
|
||||
_value = dtoEnum;
|
||||
_dateTimeValue = selectedDates.LastOrDefault();
|
||||
}
|
||||
#if NET6_0_OR_GREATER
|
||||
else if (value is IEnumerable<DateOnly?> doNullableEnum)
|
||||
{
|
||||
selectedDates = doNullableEnum.Where(d => d.HasValue)
|
||||
@@ -623,7 +605,6 @@ namespace Radzen.Blazor
|
||||
_value = toNullableEnum;
|
||||
_dateTimeValue = selectedDates.LastOrDefault();
|
||||
}
|
||||
#endif
|
||||
else if (value is DateTime dt && dt != default(DateTime))
|
||||
{
|
||||
selectedDates = new List<DateTime> { DateTime.SpecifyKind(dt.Date, Kind) };
|
||||
@@ -665,7 +646,6 @@ namespace Radzen.Blazor
|
||||
{
|
||||
_dateTimeValue = DateTime.SpecifyKind(dateTime, Kind);
|
||||
}
|
||||
#if NET6_0_OR_GREATER
|
||||
else if (value is DateOnly dateOnly)
|
||||
{
|
||||
_dateTimeValue = dateOnly.ToDateTime(System.TimeOnly.MinValue, Kind);
|
||||
@@ -675,7 +655,6 @@ namespace Radzen.Blazor
|
||||
_dateTimeValue = new DateTime(CurrentDate.Year, CurrentDate.Month, CurrentDate.Day, timeOnly.Hour, timeOnly.Minute, timeOnly.Second, timeOnly.Millisecond, Kind);
|
||||
_currentDate = _dateTimeValue.Value;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_dateTimeValue = null;
|
||||
@@ -690,7 +669,6 @@ namespace Radzen.Blazor
|
||||
|
||||
private static object? ConvertToTValue(object? value)
|
||||
{
|
||||
#if NET6_0_OR_GREATER
|
||||
var typeofTValue = typeof(TValue);
|
||||
if (value is DateTime dt)
|
||||
{
|
||||
@@ -705,7 +683,6 @@ namespace Radzen.Blazor
|
||||
return (TValue)value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1385,18 +1362,10 @@ namespace Radzen.Blazor
|
||||
}
|
||||
newValue = list;
|
||||
}
|
||||
#if NET6_0_OR_GREATER
|
||||
else if (typeof(IEnumerable<DateTime?>).IsAssignableFrom(typeofTValue))
|
||||
{
|
||||
newValue = selectedDates.Select(d => (DateTime?)d).ToList();
|
||||
}
|
||||
#else
|
||||
else if (typeof(System.Collections.Generic.IEnumerable<System.Nullable<DateTime>>).IsAssignableFrom(typeofTValue))
|
||||
{
|
||||
newValue = selectedDates.Select(d => (DateTime?)d).ToList();
|
||||
}
|
||||
#endif
|
||||
#if NET6_0_OR_GREATER
|
||||
else if (typeof(IEnumerable<DateOnly>).IsAssignableFrom(typeofTValue))
|
||||
{
|
||||
newValue = selectedDates.Select(d => DateOnly.FromDateTime(d)).ToList();
|
||||
@@ -1409,7 +1378,6 @@ namespace Radzen.Blazor
|
||||
{
|
||||
newValue = selectedDates.Select(d => (TimeOnly?)new TimeOnly(d.Hour, d.Minute, d.Second, d.Millisecond)).ToList();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
newValue = selectedDates.ToList();
|
||||
|
||||
@@ -127,7 +127,12 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
@RenderFilter()
|
||||
<div class="rz-dropdown-filter-container">
|
||||
<input aria-label="@SearchAriaLabel" id="@SearchID" @ref="@search" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" placeholder="@(FilterPlaceholder ?? string.Empty)" class="rz-dropdown-filter rz-inputtext" autocomplete="@FilterAutoCompleteType" aria-autocomplete="none" type="text"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@(searchText ?? string.Empty)"
|
||||
@oninput="@OnFilterInput" />
|
||||
<span class="notranslate rz-dropdown-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (Multiple && (AllowSelectAll || AllowFiltering || HeaderTemplate != null))
|
||||
@@ -164,7 +169,7 @@
|
||||
<input id="@SearchID" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" class="rz-inputtext" role="textbox" type="text"
|
||||
onclick="Radzen.preventDefaultAndStopPropagation(event)" aria-label="@SearchAriaLabel"
|
||||
@ref="@search" @oninput="@OnFilterInput"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@searchText" autocomplete="@FilterAutoCompleteType" />
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@(searchText ?? string.Empty)" autocomplete="@FilterAutoCompleteType" />
|
||||
<span class="notranslate rz-multiselect-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
}
|
||||
@@ -203,31 +208,3 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
internal RenderFragment RenderFilter()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return __builder => {
|
||||
<text>
|
||||
<div class="rz-dropdown-filter-container">
|
||||
<input aria-label="@SearchAriaLabel" id="@SearchID" @ref="@search" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" placeholder="@FilterPlaceholder" class="rz-dropdown-filter rz-inputtext" autocomplete="@FilterAutoCompleteType" aria-autocomplete="none" type="text"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress"
|
||||
@bind:event="oninput" @bind:get="searchText" @bind:set="@(args => OnFilterInput(new ChangeEventArgs(){ Value = args }))" />
|
||||
<span class="notranslate rz-dropdown-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
</text>
|
||||
};
|
||||
#else
|
||||
return __builder => {
|
||||
<text>
|
||||
<div class="rz-dropdown-filter-container">
|
||||
<input aria-label="@SearchAriaLabel" id="@SearchID" @ref="@search" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" placeholder="@FilterPlaceholder" class="rz-dropdown-filter rz-inputtext" autocomplete="@FilterAutoCompleteType" aria-autocomplete="none" type="text"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@searchText"
|
||||
@oninput="@OnFilterInput" />
|
||||
<span class="notranslate rz-dropdown-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
</text>
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,9 @@
|
||||
else
|
||||
{
|
||||
<div class="rz-lookup-search">
|
||||
@RenderFilter()
|
||||
<input aria-label="@SearchAriaLabel" class="rz-lookup-search-input" id="@SearchID" @ref="@search" tabindex="0" placeholder="@(SearchTextPlaceholder ?? string.Empty)"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@(searchText ?? string.Empty)" style="@(ShowSearch ? "" : "margin-right:0px;")"
|
||||
@oninput="@OnFilterInput" />
|
||||
@if (ShowSearch)
|
||||
{
|
||||
<button tabindex="0" class="rz-button rz-button-md rz-button-icon-only rz-primary" type="button"
|
||||
@@ -206,25 +208,3 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
internal RenderFragment RenderFilter()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return __builder => {
|
||||
<text>
|
||||
<input aria-label="@SearchAriaLabel" class="rz-lookup-search-input" id="@SearchID" @ref="@search" tabindex="0" placeholder="@SearchTextPlaceholder"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" style="@(ShowSearch ? "" : "margin-right:0px;")"
|
||||
@bind:event="oninput" @bind:get="searchText" @bind:set=@(args => OnFilterInput(new ChangeEventArgs(){ Value = args }))" />
|
||||
</text>
|
||||
};
|
||||
#else
|
||||
return __builder => {
|
||||
<text>
|
||||
<input aria-label="@SearchAriaLabel" class="rz-lookup-search-input" id="@SearchID" @ref="@search" tabindex="0" placeholder="@SearchTextPlaceholder"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@searchText" style="@(ShowSearch ? "" : "margin-right:0px;")"
|
||||
@oninput="@OnFilterInput" />
|
||||
</text>
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1016,6 +1016,26 @@ namespace Radzen.Blazor
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnFilterInput(ChangeEventArgs args)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(args);
|
||||
|
||||
searchText = $"{args.Value}";
|
||||
|
||||
if (FilterAsYouType)
|
||||
{
|
||||
await SearchTextChanged.InvokeAsync(searchText);
|
||||
|
||||
if (ResetSelectedIndexOnFilter)
|
||||
{
|
||||
selectedIndex = -1;
|
||||
}
|
||||
|
||||
Debounce(DebounceFilter, FilterDelay);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the filter event.
|
||||
/// </summary>
|
||||
|
||||
@@ -10,7 +10,7 @@ Disabled = itemArgs.Disabled;
|
||||
{
|
||||
<li class="@GetComponentCssClass("rz-multiselect")" role="option" tabindex="-1"
|
||||
aria-label="@(DropDown?.GetItemOrValueFromProperty(Item!, DropDown?.TextProperty ?? string.Empty) ?? "")"
|
||||
aria-selected="@(DropDown?.IsSelected(Item) == true)"
|
||||
aria-selected="@(DropDown?.IsSelected(Item) == true ? "true" : "false")"
|
||||
aria-disabled="@(Disabled || DropDown?.Disabled == true ? "true" : "false")"
|
||||
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
|
||||
@onclick:preventDefault @onclick="args=>SelectItem(args,true)"
|
||||
@@ -36,7 +36,7 @@ else
|
||||
{
|
||||
<li role="option" class="@GetComponentCssClass("rz-dropdown")" tabindex="-1"
|
||||
aria-label="@(DropDown?.GetItemOrValueFromProperty(Item, DropDown?.TextProperty ?? "") ?? "")"
|
||||
aria-selected="@(DropDown?.IsSelected(Item) == true)"
|
||||
aria-selected="@(DropDown?.IsSelected(Item) == true ? "true" : "false")"
|
||||
aria-disabled="@(Disabled || DropDown?.Disabled == true ? "true" : "false")"
|
||||
@onmousedown:preventDefault @onmousedown="args=>SelectItem(args,false)"
|
||||
@onclick:preventDefault @onclick="args=>SelectItem(args,true)"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -7,9 +7,7 @@ namespace Radzen.Blazor
|
||||
/// <summary>
|
||||
/// RadzenDropZoneContainer component.
|
||||
/// </summary>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenDropZoneContainer<TItem> : RadzenComponentWithChildren
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -43,7 +43,9 @@
|
||||
@if (AllowFiltering)
|
||||
{
|
||||
<div class="rz-listbox-filter-container">
|
||||
@RenderFilter()
|
||||
<input id="@SearchID" @ref="@search" disabled="@Disabled" class="rz-inputtext" role="textbox" type="text" placeholder="@(Placeholder ?? string.Empty)"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@(searchText ?? string.Empty)" @onkeydown:stopPropagation="true"
|
||||
@oninput="@OnFilterInput" aria-label="@SearchAriaLabel" />
|
||||
<span class="notranslate rz-listbox-filter-icon rzi rzi-search"></span>
|
||||
</div>
|
||||
}
|
||||
@@ -60,25 +62,4 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@code {
|
||||
internal RenderFragment RenderFilter()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return __builder => {
|
||||
<text>
|
||||
<input id="@SearchID" @ref="@search" disabled="@Disabled" class="rz-inputtext" role="textbox" type="text" placeholder="@Placeholder"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" @onkeydown:stopPropagation="true"
|
||||
@bind:event="oninput" @bind:get="searchText" @bind:set=@(args => OnFilterInput(new ChangeEventArgs(){ Value = args }))" aria-label="@SearchAriaLabel" />
|
||||
</text>
|
||||
};
|
||||
#else
|
||||
return __builder => {
|
||||
<text>
|
||||
<input id="@SearchID" @ref="@search" disabled="@Disabled" class="rz-inputtext" role="textbox" type="text" placeholder="@Placeholder"
|
||||
@onchange="@OnFilter" @onkeydown="@OnFilterKeyPress" value="@searchText" @onkeydown:stopPropagation="true"
|
||||
@oninput="@OnFilterInput" aria-label="@SearchAriaLabel" />
|
||||
</text>
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
@if (itemArgs?.Visible == true)
|
||||
{
|
||||
Disabled = itemArgs.Disabled;
|
||||
<li class="@GetComponentCssClass()" role="option" aria-selected="@(ListBox?.IsSelected(Item) == true)" tabindex="-1"
|
||||
<li class="@GetComponentCssClass()" role="option" aria-selected="@(ListBox?.IsSelected(Item) == true ? "true" : "false")" tabindex="-1"
|
||||
aria-label="@PropertyAccess.GetItemOrValueFromProperty(Item, ListBox?.TextProperty)" @onclick="@SelectItem"
|
||||
aria-disabled="@(Disabled || ListBox?.Disabled == true ? "true" : "false")"
|
||||
@attributes="@(itemArgs?.Attributes.Any() == true ? itemArgs.Attributes : Attributes)">
|
||||
|
||||
@@ -33,18 +33,18 @@
|
||||
<RadzenStack style="margin-top:1rem;" Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.End" Gap="0.5rem">
|
||||
@if(ShowLoginButton)
|
||||
{
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Primary" ButtonType="ButtonType.Submit" Text=@LoginText Click=@OnLogin />
|
||||
<RadzenButton ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Primary" Text=@LoginText Click=@OnLogin />
|
||||
}
|
||||
@if (AllowResetPassword)
|
||||
{
|
||||
<button type="button" class="rz-link" @onclick=@OnReset>@ResetPasswordText</button>
|
||||
<RadzenButton ButtonType="ButtonType.Button" ButtonStyle="ButtonStyle.Secondary" Variant="Variant.Text" Text=@ResetPasswordText Click=@OnReset />
|
||||
}
|
||||
</RadzenStack>
|
||||
@if (AllowRegister)
|
||||
{
|
||||
<div class="rz-register">
|
||||
@RegisterMessageText
|
||||
<RadzenButton ButtonType="ButtonType.Button" Variant="Variant.Flat" ButtonStyle="ButtonStyle.Secondary" Shade="Shade.Lighter" Text=@RegisterText Click=@OnRegister />
|
||||
<RadzenButton ButtonType="ButtonType.Button" ButtonStyle="ButtonStyle.Secondary" Variant="Variant.Flat" Shade="Shade.Lighter" Text=@RegisterText Click=@OnRegister />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -80,11 +80,11 @@
|
||||
<div class="rz-form-input-wrapper rz-login-buttons">
|
||||
@if (ShowLoginButton)
|
||||
{
|
||||
<RadzenButton ButtonStyle="ButtonStyle.Primary" ButtonType="ButtonType.Submit" Text=@LoginText Click=@OnLogin />
|
||||
<RadzenButton ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Primary" Text=@LoginText Click=@OnLogin />
|
||||
}
|
||||
@if (AllowResetPassword)
|
||||
{
|
||||
<button type="button" class="rz-link" @onclick=@OnReset>@ResetPasswordText</button>
|
||||
<RadzenButton ButtonType="ButtonType.Button" ButtonStyle="ButtonStyle.Secondary" Variant="Variant.Text" Text=@ResetPasswordText Click=@OnReset />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,7 +93,7 @@
|
||||
{
|
||||
<div class="rz-register">
|
||||
@RegisterMessageText
|
||||
<RadzenButton ButtonType="ButtonType.Button" Variant="Variant.Flat" ButtonStyle="ButtonStyle.Secondary" Shade="Shade.Lighter" Text=@RegisterText Click=@OnRegister />
|
||||
<RadzenButton ButtonType="ButtonType.Button" ButtonStyle="ButtonStyle.Secondary" Variant="Variant.Flat" Shade="Shade.Lighter" Text=@RegisterText Click=@OnRegister />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@using Radzen
|
||||
@using Radzen
|
||||
@using Microsoft.JSInterop
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using System.Globalization
|
||||
@@ -8,7 +8,12 @@
|
||||
@if (Visible)
|
||||
{
|
||||
<span @ref="@Element" style="@Style" @attributes="Attributes" class="@GetCssClass()" id="@GetId()">
|
||||
@RenderInput()
|
||||
<input @ref="@input" inputmode="decimal" @attributes="InputAttributes" type="text" name="@Name" disabled="@Disabled" readonly="@ReadOnly"
|
||||
class="@GetInputCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@Name"
|
||||
placeholder="@CurrentPlaceholder" autocomplete="@AutoCompleteAttribute" aria-autocomplete="@AriaAutoCompleteAttribute" @bind:get="FormattedValue" @bind:set="SetValue"
|
||||
onkeypress="Radzen.numericKeyPress(event, @IsInteger().ToString().ToLower(), '@Culture.NumberFormat.NumberDecimalSeparator')"
|
||||
onblur="@GetOnInput()" onpaste="@GetOnPaste()" maxlength="@MaxLength"
|
||||
@onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation />
|
||||
@if (ShowUpDown)
|
||||
{
|
||||
<button aria-label=@UpAriaLabel type="button" class="rz-numeric-button rz-numeric-up rz-button" tabindex="-1"
|
||||
@@ -21,32 +26,4 @@
|
||||
</button>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
@code {
|
||||
internal RenderFragment RenderInput()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return __builder => {
|
||||
<text>
|
||||
<input @ref="@input" inputmode="decimal" @attributes="InputAttributes" type="text" name="@Name" disabled="@Disabled" readonly="@ReadOnly"
|
||||
class="@GetInputCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@Name"
|
||||
placeholder="@CurrentPlaceholder" autocomplete="@AutoCompleteAttribute" aria-autocomplete="@AriaAutoCompleteAttribute" @bind:get="FormattedValue" @bind:set="SetValue"
|
||||
onkeypress="Radzen.numericKeyPress(event, @IsInteger().ToString().ToLower(), '@Culture.NumberFormat.NumberDecimalSeparator')"
|
||||
onblur="@GetOnInput()" onpaste="@GetOnPaste()" maxlength="@MaxLength"
|
||||
@onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation />
|
||||
</text>
|
||||
};
|
||||
#else
|
||||
return __builder => {
|
||||
<text>
|
||||
<input @ref="@input" inputmode="decimal" @attributes="InputAttributes" type="text" name="@Name" disabled="@Disabled" readonly="@ReadOnly"
|
||||
class="@GetInputCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")" id="@Name"
|
||||
placeholder="@CurrentPlaceholder" autocomplete="@AutoCompleteAttribute" aria-autocomplete="@AriaAutoCompleteAttribute" value="@FormattedValue" @onchange="@OnChange"
|
||||
onkeypress="Radzen.numericKeyPress(event, @IsInteger().ToString().ToLower(), '@Culture.NumberFormat.NumberDecimalSeparator')"
|
||||
onblur="@GetOnInput()" onpaste="@GetOnPaste()" maxlength="@MaxLength"
|
||||
@onkeydown="@(args => OnKeyPress(args))" @onkeydown:preventDefault=preventKeyPress @onkeydown:stopPropagation />
|
||||
</text>
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,6 @@ namespace Radzen.Blazor
|
||||
_ => false
|
||||
};
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
private TNum SumFloating<TNum>(TNum value1, TNum value2)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value1);
|
||||
@@ -174,7 +173,6 @@ namespace Radzen.Blazor
|
||||
|
||||
return newValue;
|
||||
}
|
||||
#endif
|
||||
|
||||
async System.Threading.Tasks.Task UpdateValueWithStep(bool stepUp)
|
||||
{
|
||||
@@ -186,7 +184,6 @@ namespace Radzen.Blazor
|
||||
var step = string.IsNullOrEmpty(Step) || Step == "any" ? 1 : decimal.Parse(Step.Replace(",", ".", StringComparison.Ordinal), System.Globalization.CultureInfo.InvariantCulture);
|
||||
TValue? newValue;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (IsNumericType(Value))
|
||||
{
|
||||
// cannot call UpdateValueWithStepNumeric directly because TValue is not value type constrained
|
||||
@@ -196,7 +193,6 @@ namespace Radzen.Blazor
|
||||
newValue = dynamicWrapper(Value, stepUp, step);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
var valueToUpdate = ConvertToDecimal(Value);
|
||||
|
||||
|
||||
@@ -38,9 +38,7 @@ namespace Radzen.Blazor
|
||||
/// </RadzenPivotDataGrid>
|
||||
/// </code>
|
||||
/// </example>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public partial class RadzenPivotDataGrid<TItem> : PagedDataBoundComponent<TItem>
|
||||
{
|
||||
private class RowHeaderCell
|
||||
|
||||
@@ -29,9 +29,7 @@ namespace Radzen.Blazor
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
#if NET6_0_OR_GREATER
|
||||
[CascadingTypeParameter(nameof(TItem))]
|
||||
#endif
|
||||
public class RadzenTemplateForm<TItem> : RadzenComponent, IRadzenForm
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,32 +1,14 @@
|
||||
@using Radzen
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@inherits FormComponent<string>
|
||||
@if (Visible)
|
||||
{
|
||||
if (Immediate)
|
||||
{
|
||||
@RenderImmediateTextArea()
|
||||
<textarea @ref="@Element" id="@GetId()" disabled="@Disabled" readonly="@ReadOnly" name="@Name" rows="@Rows" cols="@Cols" style="@Style" @attributes="Attributes" class="@GetCssClass()"
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" @bind:get="@Value" @bind:set="@SetValue" @bind:event="oninput" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"></textarea>
|
||||
}
|
||||
else
|
||||
{
|
||||
<textarea @ref="@Element" id="@GetId()" disabled="@Disabled" readonly="@ReadOnly" name="@Name" rows="@Rows" cols="@Cols" style="@Style" @attributes="Attributes" class="@GetCssClass()"
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" value="@Value" @onchange="@OnChange" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"></textarea>
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" value="@Value" @onchange="@OnChange" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"></textarea>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
internal RenderFragment RenderImmediateTextArea()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return __builder => {
|
||||
<textarea @ref="@Element" id="@GetId()" disabled="@Disabled" readonly="@ReadOnly" name="@Name" rows="@Rows" cols="@Cols" style="@Style" @attributes="Attributes" class="@GetCssClass()"
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" @bind:get="@Value" @bind:set="@SetValue" @bind:event="oninput" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"></textarea>
|
||||
};
|
||||
#else
|
||||
return __builder => {
|
||||
<textarea @ref="@Element" id="@GetId()" disabled="@Disabled" readonly="@ReadOnly" name="@Name" rows="@Rows" cols="@Cols" style="@Style" @attributes="Attributes" class="@GetCssClass()"
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" value="@Value" @oninput="@OnChange" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"></textarea>
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,14 @@
|
||||
@inherits FormComponentWithAutoComplete<string>
|
||||
@inherits FormComponentWithAutoComplete<string>
|
||||
@if (Visible)
|
||||
{
|
||||
if (Immediate)
|
||||
{
|
||||
@RenderImmediateInput()
|
||||
<input @ref="@Element" id="@GetId()" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" autocomplete="@AutoCompleteAttribute" aria-autocomplete="@AriaAutoCompleteAttribute" @bind:get="@Value" @bind:set="@SetValue" @bind:event="oninput"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input @ref="@Element" id="@GetId()" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" autocomplete="@AutoCompleteAttribute" aria-autocomplete="@AriaAutoCompleteAttribute" value="@Value" @onchange="@OnChange" />
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
internal RenderFragment RenderImmediateInput()
|
||||
{
|
||||
#if NET7_0_OR_GREATER
|
||||
return __builder => {
|
||||
<input @ref="@Element" id="@GetId()" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" autocomplete="@AutoCompleteAttribute" aria-autocomplete="@AriaAutoCompleteAttribute" @bind:get="@Value" @bind:set="@SetValue" @bind:event="oninput"/>
|
||||
};
|
||||
#else
|
||||
return __builder => {
|
||||
<input @ref="@Element" id="@GetId()" disabled="@Disabled" readonly="@ReadOnly" name="@Name" style="@Style" @attributes="Attributes" class="@GetCssClass()" tabindex="@(Disabled ? "-1" : $"{TabIndex}")"
|
||||
placeholder="@CurrentPlaceholder" maxlength="@MaxLength" autocomplete="@AutoCompleteAttribute" aria-autocomplete="@AriaAutoCompleteAttribute" value="@Value" @oninput="@OnChange" />
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@using Radzen
|
||||
@using Radzen
|
||||
@using Radzen.Blazor.Rendering
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using System.Linq.Expressions
|
||||
@@ -88,11 +88,9 @@
|
||||
@RenderUnitField(TimeSpanUnit.Millisecond, MillisecondsUnitText, "ms", UnconfirmedValue.Milliseconds, MillisecondsStep ?? "", "000")
|
||||
|
||||
@{
|
||||
#if NET7_0_OR_GREATER
|
||||
{
|
||||
@RenderUnitField(TimeSpanUnit.Microsecond, MicrosecondsUnitText, "us", UnconfirmedValue.Microseconds, MicrosecondsStep ?? "", "000")
|
||||
}
|
||||
#endif
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
@@ -240,13 +240,11 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string? MillisecondsStep { get; set; }
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Specifies the step of the microseconds field in the picker panel.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string? MicrosecondsStep { get; set; }
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region Parameters: panel texts
|
||||
@@ -310,13 +308,11 @@ namespace Radzen.Blazor
|
||||
[Parameter]
|
||||
public string MillisecondsUnitText { get; set; } = "Milliseconds";
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Specifies the microseconds label text.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string MicrosecondsUnitText { get; set; } = "Microseconds";
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region Parameters: other config
|
||||
@@ -764,9 +760,7 @@ namespace Radzen.Blazor
|
||||
TimeSpanUnit.Minute => TimeSpan.FromMinutes(value),
|
||||
TimeSpanUnit.Second => TimeSpan.FromSeconds(value),
|
||||
TimeSpanUnit.Millisecond => TimeSpan.FromMilliseconds(value),
|
||||
#if NET7_0_OR_GREATER
|
||||
TimeSpanUnit.Microsecond => TimeSpan.FromMicroseconds(value),
|
||||
#endif
|
||||
_ => TimeSpan.Zero,
|
||||
};
|
||||
private static int GetTimeSpanUnitValue(TimeSpanUnit unit, TimeSpan timeSpan)
|
||||
@@ -777,9 +771,7 @@ namespace Radzen.Blazor
|
||||
TimeSpanUnit.Minute => timeSpan.Minutes,
|
||||
TimeSpanUnit.Second => timeSpan.Seconds,
|
||||
TimeSpanUnit.Millisecond => timeSpan.Milliseconds,
|
||||
#if NET7_0_OR_GREATER
|
||||
TimeSpanUnit.Microsecond => timeSpan.Microseconds,
|
||||
#endif
|
||||
_ => 0,
|
||||
};
|
||||
private static readonly Dictionary<TimeSpanUnit, int> _timeUnitMaxAbsoluteValues = new()
|
||||
@@ -788,10 +780,8 @@ namespace Radzen.Blazor
|
||||
{ TimeSpanUnit.Hour, 23 },
|
||||
{ TimeSpanUnit.Minute, 59 },
|
||||
{ TimeSpanUnit.Second, 59 },
|
||||
{ TimeSpanUnit.Millisecond, 999 }
|
||||
#if NET7_0_OR_GREATER
|
||||
, { TimeSpanUnit.Microsecond, 999 }
|
||||
#endif
|
||||
{ TimeSpanUnit.Millisecond, 999 },
|
||||
{ TimeSpanUnit.Microsecond, 999 }
|
||||
};
|
||||
private static readonly Dictionary<TimeSpanUnit, int> _timeUnitZeroValues = Enum
|
||||
.GetValues<TimeSpanUnit>()
|
||||
@@ -853,14 +843,12 @@ namespace Radzen.Blazor
|
||||
}
|
||||
timeUnitMaxValues[TimeSpanUnit.Millisecond] = 0;
|
||||
|
||||
#if NET7_0_OR_GREATER
|
||||
if (boundary.Microseconds != 0)
|
||||
{
|
||||
timeUnitMaxValues[TimeSpanUnit.Microsecond] = Math.Abs(boundary.Microseconds);
|
||||
return timeUnitMaxValues;
|
||||
}
|
||||
timeUnitMaxValues[TimeSpanUnit.Microsecond] = 0;
|
||||
#endif
|
||||
|
||||
return timeUnitMaxValues;
|
||||
}
|
||||
|
||||
@@ -28,13 +28,10 @@ public enum TimeSpanUnit
|
||||
/// <summary>
|
||||
/// Millisecond.
|
||||
/// </summary>
|
||||
Millisecond = 4
|
||||
#if NET7_0_OR_GREATER
|
||||
,
|
||||
Millisecond = 4,
|
||||
/// <summary>
|
||||
/// Microsecond.
|
||||
/// </summary>
|
||||
Microsecond = 5
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -251,11 +251,20 @@ $button-sizes: map-merge(
|
||||
&.rz-shade-darker { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-darker); color: var(--rz-#{$style}-darker); }
|
||||
}
|
||||
@else {
|
||||
&.rz-shade-lighter { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-lighter); color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-light { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-light); color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-default { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}); color: var(--rz-#{$style}); }
|
||||
&.rz-shade-dark { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-dark); color: var(--rz-#{$style}-dark); }
|
||||
&.rz-shade-darker { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-darker); color: var(--rz-#{$style}-darker); }
|
||||
// Fluent/Standard dark specific text color overrides for secondary only
|
||||
@if ($fluent == true or $standard == true) and $theme-dark == true and $style == 'secondary' {
|
||||
&.rz-shade-lighter { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-lighter); color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-light { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-light); color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-default { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}); color: var(--rz-on-#{$style}); }
|
||||
&.rz-shade-dark { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-dark); color: var(--rz-#{$style}-dark); }
|
||||
&.rz-shade-darker { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-darker); color: var(--rz-#{$style}-darker); }
|
||||
} @else {
|
||||
&.rz-shade-lighter { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-lighter); color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-light { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-light); color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-default { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}); color: var(--rz-#{$style}); }
|
||||
&.rz-shade-dark { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-dark); color: var(--rz-#{$style}-dark); }
|
||||
&.rz-shade-darker { box-shadow: inset 0 0 0 var(--rz-border-width) var(--rz-#{$style}-darker); color: var(--rz-#{$style}-darker); }
|
||||
}
|
||||
}
|
||||
background-color: transparent;
|
||||
|
||||
@@ -302,11 +311,20 @@ $button-sizes: map-merge(
|
||||
&.rz-shade-dark { color: var(--rz-#{$style}-dark); }
|
||||
&.rz-shade-darker { color: var(--rz-#{$style}-darker); }
|
||||
} @else {
|
||||
&.rz-shade-lighter { color: var(--rz-#{$style}-lighter); }
|
||||
&.rz-shade-light { color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-default { color: var(--rz-#{$style}); }
|
||||
&.rz-shade-dark { color: var(--rz-#{$style}-dark); }
|
||||
&.rz-shade-darker { color: var(--rz-#{$style}-darker); }
|
||||
// Fluent/Standard dark specific text color overrides for secondary only
|
||||
@if ($fluent == true or $standard == true) and $theme-dark == true and $style == 'secondary' {
|
||||
&.rz-shade-lighter { color: var(--rz-#{$style}-lighter); }
|
||||
&.rz-shade-light { color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-default { color: var(--rz-on-#{$style}); }
|
||||
&.rz-shade-dark { color: var(--rz-#{$style}-dark); }
|
||||
&.rz-shade-darker { color: var(--rz-#{$style}-darker); }
|
||||
} @else {
|
||||
&.rz-shade-lighter { color: var(--rz-#{$style}-lighter); }
|
||||
&.rz-shade-light { color: var(--rz-#{$style}-light); }
|
||||
&.rz-shade-default { color: var(--rz-#{$style}); }
|
||||
&.rz-shade-dark { color: var(--rz-#{$style}-dark); }
|
||||
&.rz-shade-darker { color: var(--rz-#{$style}-darker); }
|
||||
}
|
||||
}
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
color: var(--rz-link-color);
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font: inherit;
|
||||
|
||||
.rz-link-disabled {
|
||||
pointer-events: none;
|
||||
|
||||
@@ -92,6 +92,7 @@ window.Radzen = {
|
||||
var handler = function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
try {
|
||||
ref.invokeMethodAsync('RadzenComponent.RaiseContextMenu',
|
||||
{
|
||||
ClientX: e.clientX,
|
||||
@@ -105,6 +106,7 @@ window.Radzen = {
|
||||
Button: e.button,
|
||||
Buttons: e.buttons,
|
||||
});
|
||||
} catch { }
|
||||
return false;
|
||||
};
|
||||
Radzen[id + 'contextmenu'] = handler;
|
||||
@@ -115,7 +117,7 @@ window.Radzen = {
|
||||
var el = document.getElementById(id);
|
||||
if (el) {
|
||||
var handler = function (e) {
|
||||
ref.invokeMethodAsync('RadzenComponent.RaiseMouseEnter');
|
||||
try { ref.invokeMethodAsync('RadzenComponent.RaiseMouseEnter'); } catch { }
|
||||
};
|
||||
Radzen[id + 'mouseenter'] = handler;
|
||||
el.addEventListener('mouseenter', handler, false);
|
||||
@@ -125,7 +127,7 @@ window.Radzen = {
|
||||
var el = document.getElementById(id);
|
||||
if (el) {
|
||||
var handler = function (e) {
|
||||
ref.invokeMethodAsync('RadzenComponent.RaiseMouseLeave');;
|
||||
try { ref.invokeMethodAsync('RadzenComponent.RaiseMouseLeave'); } catch { }
|
||||
};
|
||||
Radzen[id + 'mouseleave'] = handler;
|
||||
el.addEventListener('mouseleave', handler, false);
|
||||
@@ -254,9 +256,9 @@ window.Radzen = {
|
||||
});
|
||||
|
||||
Radzen[id].instance.addListener('click', function (e) {
|
||||
Radzen[id].invokeMethodAsync('RadzenGoogleMap.OnMapClick', {
|
||||
try { Radzen[id].invokeMethodAsync('RadzenGoogleMap.OnMapClick', {
|
||||
Position: {Lat: e.latLng.lat(), Lng: e.latLng.lng()}
|
||||
});
|
||||
}); } catch { }
|
||||
});
|
||||
|
||||
Radzen.updateMap(id, apiKey, zoom, center, markers, options, fitBoundsToMarkersOnUpdate, language);
|
||||
@@ -302,11 +304,11 @@ window.Radzen = {
|
||||
});
|
||||
|
||||
marker.addListener('click', function (e) {
|
||||
Radzen[id].invokeMethodAsync('RadzenGoogleMap.OnMarkerClick', {
|
||||
try { Radzen[id].invokeMethodAsync('RadzenGoogleMap.OnMarkerClick', {
|
||||
Title: marker.title,
|
||||
Label: marker.content.innerText,
|
||||
Position: marker.position
|
||||
});
|
||||
}); } catch { }
|
||||
});
|
||||
|
||||
marker.setMap(Radzen[id].instance);
|
||||
@@ -392,7 +394,7 @@ window.Radzen = {
|
||||
var code = Radzen[id].inputs.map(i => i.value).join('').trim();
|
||||
hidden.value = code;
|
||||
|
||||
ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', code);
|
||||
try { ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', code); } catch { }
|
||||
|
||||
Radzen[id].inputs[Radzen[id].inputs.length - 1].focus();
|
||||
}
|
||||
@@ -432,7 +434,7 @@ window.Radzen = {
|
||||
var value = Radzen[id].inputs.map(i => i.value).join('').trim();
|
||||
hidden.value = value;
|
||||
|
||||
ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', value);
|
||||
try { ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', value); } catch { }
|
||||
|
||||
var index = Radzen[id].inputs.indexOf(e.currentTarget);
|
||||
if (index < Radzen[id].inputs.length - 1) {
|
||||
@@ -448,7 +450,7 @@ window.Radzen = {
|
||||
var value = Radzen[id].inputs.map(i => i.value).join('').trim();
|
||||
hidden.value = value;
|
||||
|
||||
ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', value);
|
||||
try { ref.invokeMethodAsync('RadzenSecurityCode.OnValueChange', value); } catch { }
|
||||
|
||||
var index = Radzen[id].inputs.indexOf(e.currentTarget);
|
||||
if (index > 0) {
|
||||
@@ -510,11 +512,11 @@ window.Radzen = {
|
||||
newValue >= min &&
|
||||
newValue <= max
|
||||
) {
|
||||
slider.invokeMethodAsync(
|
||||
try { slider.invokeMethodAsync(
|
||||
'RadzenSlider.OnValueChange',
|
||||
newValue,
|
||||
!!slider.isMin
|
||||
);
|
||||
); } catch { }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -546,11 +548,11 @@ window.Radzen = {
|
||||
var newValue = percent * (max - min) + min;
|
||||
var oldValue = range ? value[slider.isMin ? 0 : 1] : value;
|
||||
if (newValue >= min && newValue <= max && newValue != oldValue) {
|
||||
slider.invokeMethodAsync(
|
||||
try { slider.invokeMethodAsync(
|
||||
'RadzenSlider.OnValueChange',
|
||||
newValue,
|
||||
!!slider.isMin
|
||||
);
|
||||
); } catch { }
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -840,7 +842,7 @@ window.Radzen = {
|
||||
|
||||
uploadComponent.files = Array.from(fileInput.files);
|
||||
uploadComponent.localFiles = files;
|
||||
uploadComponent.invokeMethodAsync('RadzenUpload.OnChange', files);
|
||||
try { uploadComponent.invokeMethodAsync('RadzenUpload.OnChange', files); } catch { }
|
||||
}
|
||||
|
||||
for (var i = 0; i < fileInput.files.length; i++) {
|
||||
@@ -913,7 +915,7 @@ window.Radzen = {
|
||||
Radzen.uploadComponents && Radzen.uploadComponents[fileInput.id];
|
||||
if (uploadComponent) {
|
||||
var progress = parseInt((e.loaded / e.total) * 100);
|
||||
uploadComponent.invokeMethodAsync(
|
||||
try { uploadComponent.invokeMethodAsync(
|
||||
'RadzenUpload.OnProgress',
|
||||
progress,
|
||||
e.loaded,
|
||||
@@ -925,7 +927,7 @@ window.Radzen = {
|
||||
cancelled = true;
|
||||
xhr.abort();
|
||||
}
|
||||
});
|
||||
}); } catch { }
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -936,27 +938,27 @@ window.Radzen = {
|
||||
Radzen.uploadComponents && Radzen.uploadComponents[fileInput.id];
|
||||
if (uploadComponent) {
|
||||
if (status === 0 || (status >= 200 && status < 400)) {
|
||||
uploadComponent.invokeMethodAsync(
|
||||
try { uploadComponent.invokeMethodAsync(
|
||||
'RadzenUpload.OnComplete',
|
||||
xhr.responseText,
|
||||
cancelled
|
||||
);
|
||||
); } catch { }
|
||||
} else {
|
||||
uploadComponent.invokeMethodAsync(
|
||||
try { uploadComponent.invokeMethodAsync(
|
||||
'RadzenUpload.OnError',
|
||||
xhr.responseText
|
||||
);
|
||||
); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
uploadComponent.invokeMethodAsync('GetHeaders').then(function (headers) {
|
||||
try { uploadComponent.invokeMethodAsync('GetHeaders').then(function (headers) {
|
||||
xhr.open(method, url, true);
|
||||
for (var name in headers) {
|
||||
xhr.setRequestHeader(name, headers[name]);
|
||||
}
|
||||
xhr.send(data);
|
||||
});
|
||||
}); } catch { }
|
||||
},
|
||||
getCookie: function (name) {
|
||||
var value = '; ' + decodeURIComponent(document.cookie);
|
||||
@@ -1236,6 +1238,12 @@ window.Radzen = {
|
||||
rect.width = x ? rect.width + 20 : rect.width;
|
||||
rect.height = y ? rect.height + 20 : rect.height;
|
||||
|
||||
var isRTL = Radzen.isRTL(popup);
|
||||
|
||||
if (isRTL && (position == 'bottom' || position == 'top')) {
|
||||
left = parentRect.right - rect.width;
|
||||
}
|
||||
|
||||
var smartPosition = !position || position == 'bottom';
|
||||
|
||||
if (smartPosition && top + rect.height > window.innerHeight && parentRect.top > rect.height) {
|
||||
@@ -1276,6 +1284,24 @@ window.Radzen = {
|
||||
}
|
||||
}
|
||||
|
||||
if (smartPosition && isRTL && left < 0 && window.innerWidth > rect.width) {
|
||||
left = !position ? 0 : rect.left;
|
||||
|
||||
if (position) {
|
||||
top = y || parentRect.top;
|
||||
var tooltipContent = popup.children[0];
|
||||
var tooltipContentClassName = 'rz-' + position + '-tooltip-content';
|
||||
if (tooltipContent.classList.contains(tooltipContentClassName)) {
|
||||
tooltipContent.classList.remove(tooltipContentClassName);
|
||||
tooltipContent.classList.add('rz-right-tooltip-content');
|
||||
position = 'right';
|
||||
if (instance && callback) {
|
||||
try { instance.invokeMethodAsync(callback, position); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (smartPosition) {
|
||||
if (position) {
|
||||
top = top + 20;
|
||||
@@ -1294,7 +1320,7 @@ window.Radzen = {
|
||||
|
||||
if (position == 'top') {
|
||||
top = parentRect.top - rect.height + 5;
|
||||
left = parentRect.left;
|
||||
left = isRTL ? parentRect.right - rect.width : parentRect.left;
|
||||
}
|
||||
|
||||
popup.style.zIndex = 2000;
|
||||
@@ -1643,11 +1669,13 @@ window.Radzen = {
|
||||
dialog.offsetWidth = e[0].target.offsetWidth;
|
||||
dialog.offsetHeight = e[0].target.offsetHeight;
|
||||
|
||||
try {
|
||||
dialog.invokeMethodAsync(
|
||||
'RadzenDialog.OnResize',
|
||||
e[0].target.offsetWidth,
|
||||
e[0].target.offsetHeight
|
||||
);
|
||||
} catch { }
|
||||
}
|
||||
};
|
||||
Radzen.dialogResizer = new ResizeObserver(dialogResize).observe(lastDialog.parentElement);
|
||||
@@ -1668,7 +1696,7 @@ window.Radzen = {
|
||||
lastDialog.parentElement.style.left = left + 'px';
|
||||
lastDialog.parentElement.style.top = top + 'px';
|
||||
|
||||
dialog.invokeMethodAsync('RadzenDialog.OnDrag', top, left);
|
||||
try { dialog.invokeMethodAsync('RadzenDialog.OnDrag', top, left); } catch { }
|
||||
};
|
||||
|
||||
var stop = function () {
|
||||
@@ -1775,7 +1803,7 @@ window.Radzen = {
|
||||
var lastDialog = dialogs[dialogs.length - 1];
|
||||
|
||||
if (lastDialog && lastDialog.options && lastDialog.options.closeDialogOnEsc) {
|
||||
Radzen.dialogService.invokeMethodAsync('DialogService.Close', null);
|
||||
try { Radzen.dialogService.invokeMethodAsync('DialogService.Close', null); } catch { }
|
||||
|
||||
if (dialogs.length <= 1) {
|
||||
document.removeEventListener('keydown', Radzen.closePopupOrDialog);
|
||||
@@ -1962,7 +1990,7 @@ window.Radzen = {
|
||||
ref.resizeHandler = function () {
|
||||
var rect = ref.getBoundingClientRect();
|
||||
|
||||
instance.invokeMethodAsync('Resize', rect.width, rect.height);
|
||||
try { instance.invokeMethodAsync('Resize', rect.width, rect.height); } catch { }
|
||||
};
|
||||
|
||||
if (window.ResizeObserver) {
|
||||
@@ -1983,7 +2011,7 @@ window.Radzen = {
|
||||
var rect = ref.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left;
|
||||
var y = e.clientY - rect.top;
|
||||
instance.invokeMethodAsync('MouseMove', x, y);
|
||||
try { instance.invokeMethodAsync('MouseMove', x, y); } catch { }
|
||||
}
|
||||
}, 100);
|
||||
ref.mouseEnterHandler = function () {
|
||||
@@ -1994,14 +2022,14 @@ window.Radzen = {
|
||||
return;
|
||||
}
|
||||
inside = false;
|
||||
instance.invokeMethodAsync('MouseMove', -1, -1);
|
||||
try { instance.invokeMethodAsync('MouseMove', -1, -1); } catch { }
|
||||
};
|
||||
ref.clickHandler = function (e) {
|
||||
var rect = ref.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left;
|
||||
var y = e.clientY - rect.top;
|
||||
if (!e.target.closest('.rz-marker')) {
|
||||
instance.invokeMethodAsync('Click', x, y);
|
||||
try { instance.invokeMethodAsync('Click', x, y); } catch { }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2025,7 +2053,7 @@ window.Radzen = {
|
||||
ref.resizeHandler = function () {
|
||||
var rect = ref.getBoundingClientRect();
|
||||
|
||||
instance.invokeMethodAsync('Resize', rect.width, rect.height);
|
||||
try { instance.invokeMethodAsync('Resize', rect.width, rect.height); } catch { }
|
||||
};
|
||||
|
||||
window.addEventListener('resize', ref.resizeHandler);
|
||||
@@ -2074,7 +2102,7 @@ window.Radzen = {
|
||||
mediaQuery: function(query, instance) {
|
||||
if (instance) {
|
||||
function callback(event) {
|
||||
instance.invokeMethodAsync('OnChange', event.matches)
|
||||
try { instance.invokeMethodAsync('OnChange', event.matches); } catch { }
|
||||
};
|
||||
var query = matchMedia(query);
|
||||
this.mediaQueries[instance._id] = function() {
|
||||
@@ -2092,7 +2120,7 @@ window.Radzen = {
|
||||
},
|
||||
createEditor: function (ref, uploadUrl, paste, instance, shortcuts) {
|
||||
ref.inputListener = function () {
|
||||
instance.invokeMethodAsync('OnChange', ref.innerHTML);
|
||||
try { instance.invokeMethodAsync('OnChange', ref.innerHTML); } catch { }
|
||||
};
|
||||
ref.keydownListener = function (e) {
|
||||
var key = '';
|
||||
@@ -2109,7 +2137,7 @@ window.Radzen = {
|
||||
|
||||
if (shortcuts.includes(key)) {
|
||||
e.preventDefault();
|
||||
instance.invokeMethodAsync('ExecuteShortcutAsync', key);
|
||||
try { instance.invokeMethodAsync('ExecuteShortcutAsync', key); } catch { }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2135,7 +2163,7 @@ window.Radzen = {
|
||||
|
||||
ref.selectionChangeListener = function () {
|
||||
if (document.activeElement == ref) {
|
||||
instance.invokeMethodAsync('OnSelectionChange');
|
||||
try { instance.invokeMethodAsync('OnSelectionChange'); } catch { }
|
||||
}
|
||||
};
|
||||
ref.handleInsert = function (e, transfer, hasDelegate) {
|
||||
@@ -2163,36 +2191,36 @@ window.Radzen = {
|
||||
var result = JSON.parse(xhr.responseText);
|
||||
var html = '<img src="' + result.url + '">';
|
||||
if (hasDelegate) {
|
||||
instance.invokeMethodAsync('OnPaste', html)
|
||||
try { instance.invokeMethodAsync('OnPaste', html)
|
||||
.then(function (html) {
|
||||
document.execCommand("insertHTML", false, html);
|
||||
});
|
||||
}); } catch { }
|
||||
} else {
|
||||
document.execCommand("insertHTML", false, '<img src="' + result.url + '">');
|
||||
}
|
||||
instance.invokeMethodAsync('OnUploadComplete', xhr.responseText);
|
||||
try { instance.invokeMethodAsync('OnUploadComplete', xhr.responseText); } catch { }
|
||||
} else {
|
||||
instance.invokeMethodAsync('OnError', xhr.responseText);
|
||||
try { instance.invokeMethodAsync('OnError', xhr.responseText); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
instance.invokeMethodAsync('GetHeaders').then(function (headers) {
|
||||
try { instance.invokeMethodAsync('GetHeaders').then(function (headers) {
|
||||
xhr.open('POST', uploadUrl, true);
|
||||
for (var name in headers) {
|
||||
xhr.setRequestHeader(name, headers[name]);
|
||||
}
|
||||
xhr.send(data);
|
||||
});
|
||||
}); } catch { }
|
||||
} else {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
var html = '<img src="' + e.target.result + '">';
|
||||
|
||||
if (hasDelegate) {
|
||||
instance.invokeMethodAsync('OnPaste', html)
|
||||
try { instance.invokeMethodAsync('OnPaste', html)
|
||||
.then(function (html) {
|
||||
document.execCommand("insertHTML", false, html);
|
||||
});
|
||||
}); } catch { }
|
||||
} else {
|
||||
document.execCommand("insertHTML", false, html);
|
||||
}
|
||||
@@ -2217,11 +2245,11 @@ window.Radzen = {
|
||||
data = data.substring(startIndex + startMarker.length, endIndex).trim();
|
||||
}
|
||||
|
||||
instance.invokeMethodAsync('OnPaste', data)
|
||||
try { instance.invokeMethodAsync('OnPaste', data)
|
||||
.then(ref.focus())
|
||||
.then(function (html) {
|
||||
document.execCommand("insertHTML", false, html);
|
||||
});
|
||||
}); } catch { }
|
||||
}
|
||||
ref.pasteListener = function (e) {
|
||||
ref.handleInsert(e, e.clipboardData, paste);
|
||||
@@ -2318,11 +2346,11 @@ window.Radzen = {
|
||||
return { left: 0, top: 0, width: 0, height: 0 };
|
||||
}
|
||||
ref.mouseMoveHandler = function (e) {
|
||||
instance.invokeMethodAsync(handler, { clientX: e.clientX, clientY: e.clientY });
|
||||
try { instance.invokeMethodAsync(handler, { clientX: e.clientX, clientY: e.clientY }); } catch { }
|
||||
};
|
||||
ref.touchMoveHandler = function (e) {
|
||||
if (e.targetTouches[0] && ref.contains(e.targetTouches[0].target)) {
|
||||
instance.invokeMethodAsync(handler, { clientX: e.targetTouches[0].clientX, clientY: e.targetTouches[0].clientY });
|
||||
try { instance.invokeMethodAsync(handler, { clientX: e.targetTouches[0].clientX, clientY: e.targetTouches[0].clientY }); } catch { }
|
||||
}
|
||||
};
|
||||
ref.mouseUpHandler = function (e) {
|
||||
@@ -2428,11 +2456,11 @@ window.Radzen = {
|
||||
var cell = el.parentNode.parentNode;
|
||||
if (!cell) return;
|
||||
if (Radzen[el]) {
|
||||
grid.invokeMethodAsync(
|
||||
try { grid.invokeMethodAsync(
|
||||
'RadzenGrid.OnColumnResized',
|
||||
columnIndex,
|
||||
cell.getBoundingClientRect().width
|
||||
);
|
||||
); } catch { }
|
||||
el.style.width = null;
|
||||
document.removeEventListener('mousemove', Radzen[el].mouseMoveHandler);
|
||||
document.removeEventListener('mouseup', Radzen[el].mouseUpHandler);
|
||||
@@ -2452,11 +2480,11 @@ window.Radzen = {
|
||||
width: cell.getBoundingClientRect().width,
|
||||
mouseUpHandler: function (e) {
|
||||
if (Radzen[el]) {
|
||||
grid.invokeMethodAsync(
|
||||
try { grid.invokeMethodAsync(
|
||||
'RadzenGrid.OnColumnResized',
|
||||
columnIndex,
|
||||
cell.getBoundingClientRect().width
|
||||
);
|
||||
); } catch { }
|
||||
el.style.width = null;
|
||||
document.removeEventListener('mousemove', Radzen[el].mouseMoveHandler);
|
||||
document.removeEventListener('mouseup', Radzen[el].mouseUpHandler);
|
||||
@@ -2578,13 +2606,13 @@ window.Radzen = {
|
||||
paneNextLength: isFinite(paneNextLength) ? paneNextLength : 0,
|
||||
mouseUpHandler: function(e) {
|
||||
if (Radzen[el]) {
|
||||
splitter.invokeMethodAsync(
|
||||
try { splitter.invokeMethodAsync(
|
||||
'RadzenSplitter.OnPaneResized',
|
||||
parseInt(pane.getAttribute('data-index')),
|
||||
parseFloat(pane.style.flexBasis),
|
||||
paneNext ? parseInt(paneNext.getAttribute('data-index')) : null,
|
||||
paneNext ? parseFloat(paneNext.style.flexBasis) : null
|
||||
);
|
||||
); } catch { }
|
||||
|
||||
document.removeEventListener('pointerup', Radzen[el].mouseUpHandler);
|
||||
document.removeEventListener('pointermove', Radzen[el].mouseMoveHandler);
|
||||
@@ -2595,9 +2623,9 @@ window.Radzen = {
|
||||
mouseMoveHandler: function(e) {
|
||||
if (Radzen[el]) {
|
||||
|
||||
splitter.invokeMethodAsync(
|
||||
try { splitter.invokeMethodAsync(
|
||||
'RadzenSplitter.OnPaneResizing'
|
||||
);
|
||||
); } catch { }
|
||||
|
||||
var spacePerc = Radzen[el].panePerc + Radzen[el].paneNextPerc;
|
||||
var spaceLength = Radzen[el].paneLength + Radzen[el].paneNextLength;
|
||||
@@ -2712,10 +2740,10 @@ window.Radzen = {
|
||||
let current = event.results[event.results.length - 1][0]
|
||||
let result = current.transcript;
|
||||
|
||||
componentRef.invokeMethodAsync("OnResult", result);
|
||||
try { componentRef.invokeMethodAsync("OnResult", result); } catch { }
|
||||
};
|
||||
radzenRecognition.onend = function (event) {
|
||||
componentRef.invokeMethodAsync("StopRecording");
|
||||
try { componentRef.invokeMethodAsync("StopRecording"); } catch { }
|
||||
radzenRecognition = null;
|
||||
};
|
||||
radzenRecognition.start();
|
||||
@@ -2825,7 +2853,7 @@ window.Radzen = {
|
||||
currentSelector = match;
|
||||
if (!this.selectedNavigationSelector || (match === this.selectedNavigationSelector)) {
|
||||
this.navigateTo(currentSelector, false);
|
||||
ref.invokeMethodAsync('ScrollIntoView', currentSelector);
|
||||
try { ref.invokeMethodAsync('ScrollIntoView', currentSelector); } catch { }
|
||||
}
|
||||
}
|
||||
// clear selected navigation selector after scroll completes
|
||||
@@ -2867,7 +2895,7 @@ window.Radzen = {
|
||||
createDraggable: function(element, ref, onDragStart) {
|
||||
function handleDragStart(e) {
|
||||
e.dataTransfer.setData('', e.target.id);
|
||||
ref.invokeMethodAsync(onDragStart);
|
||||
try { ref.invokeMethodAsync(onDragStart); } catch { }
|
||||
}
|
||||
element.draggable = true;
|
||||
element.addEventListener('dragstart', handleDragStart);
|
||||
@@ -2887,7 +2915,7 @@ Radzen.registerFabMenu = function(element, dotnet){
|
||||
}
|
||||
const handler = function(e){
|
||||
if(!element.contains(e.target)){
|
||||
dotnet.invokeMethodAsync('CloseAsync');
|
||||
try { dotnet.invokeMethodAsync('CloseAsync'); } catch { }
|
||||
}
|
||||
};
|
||||
element.__rzOutsideClickHandler = handler;
|
||||
|
||||
172
RadzenBlazorDemos.Host/CanonicalRedirectMiddleware.cs
Normal file
172
RadzenBlazorDemos.Host/CanonicalRedirectMiddleware.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace RadzenBlazorDemos.Host;
|
||||
|
||||
/// <summary>
|
||||
/// Redirects legacy and non-canonical demo routes to canonical routes.
|
||||
/// </summary>
|
||||
public static class CanonicalRedirectMiddleware
|
||||
{
|
||||
private static readonly FrozenDictionary<string, string> StaticRedirects = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["/buttons"] = "/button",
|
||||
["/docs"] = "/",
|
||||
["/docs/guides/components/aichat.html"] = "/aichat",
|
||||
["/docs/guides/components/accordion.html"] = "/accordion",
|
||||
["/docs/guides/components/arcgauge.html"] = "/arc-gauge",
|
||||
["/docs/guides/components/autocomplete.html"] = "/autocomplete",
|
||||
["/docs/guides/components/badge.html"] = "/badge",
|
||||
["/docs/guides/components/barcode.html"] = "/barcode",
|
||||
["/docs/guides/components/breadcrumb.html"] = "/breadcrumb",
|
||||
["/docs/guides/components/button.html"] = "/button",
|
||||
["/docs/guides/components/carousel.html"] = "/carousel",
|
||||
["/docs/guides/components/chart.html"] = "/chart-series",
|
||||
["/docs/guides/components/chat.html"] = "/chat",
|
||||
["/docs/guides/components/checkbox.html"] = "/checkbox",
|
||||
["/docs/guides/components/checkboxlist.html"] = "/checkboxlist",
|
||||
["/docs/guides/components/colorpicker.html"] = "/colorpicker",
|
||||
["/docs/guides/components/comparevalidator.html"] = "/comparevalidator",
|
||||
["/docs/guides/components/contextmenu.html"] = "/contextmenu",
|
||||
["/docs/guides/components/datalist.html"] = "/datalist",
|
||||
["/docs/guides/components/datagrid.html"] = "/datagrid",
|
||||
["/docs/guides/components/datepicker.html"] = "/datepicker",
|
||||
["/docs/guides/components/dialog.html"] = "/dialog",
|
||||
["/docs/guides/components/dropdown.html"] = "/dropdown",
|
||||
["/docs/guides/components/dropdowndatagrid.html"] = "/dropdown-datagrid",
|
||||
["/docs/guides/components/emailvalidator.html"] = "/emailvalidator",
|
||||
["/docs/guides/components/fieldset.html"] = "/fieldset",
|
||||
["/docs/guides/components/fileinput.html"] = "/fileinput",
|
||||
["/docs/guides/getting-started/context-menu.html"] = "/get-started",
|
||||
["/docs/guides/getting-started/dialog.html"] = "/get-started",
|
||||
["/docs/guides/getting-started/notification.html"] = "/get-started",
|
||||
["/docs/guides/getting-started/tooltip.html"] = "/get-started",
|
||||
["/docs/guides/getting-started/use-component.html"] = "/get-started",
|
||||
["/docs/guides/components/googlemap.html"] = "/googlemap",
|
||||
["/docs/guides/components/gravatar.html"] = "/gravatar",
|
||||
["/docs/guides/components/htmleditor.html"] = "/html-editor",
|
||||
["/docs/guides/components/icon.html"] = "/icon",
|
||||
["/docs/guides/components/image.html"] = "/image",
|
||||
["/docs/guides/index.html"] = "/get-started",
|
||||
["/docs/guides/components/label.html"] = "/label",
|
||||
["/docs/guides/components/lengthvalidator.html"] = "/lengthvalidator",
|
||||
["/docs/guides/components/link.html"] = "/link",
|
||||
["/docs/guides/components/listbox.html"] = "/listbox",
|
||||
["/docs/guides/components/login.html"] = "/login",
|
||||
["/docs/guides/components/mask.html"] = "/mask",
|
||||
["/docs/guides/components/media-query.html"] = "/media-query",
|
||||
["/docs/guides/components/menu.html"] = "/menu",
|
||||
["/docs/guides/components/notification.html"] = "/notification",
|
||||
["/docs/guides/components/numeric.html"] = "/numeric",
|
||||
["/docs/guides/components/numericrangevalidator.html"] = "/numericrangevalidator",
|
||||
["/docs/guides/components/panel.html"] = "/panel",
|
||||
["/docs/guides/components/panelmenu.html"] = "/panelmenu",
|
||||
["/docs/guides/components/pager.html"] = "/pager",
|
||||
["/docs/guides/components/password.html"] = "/password",
|
||||
["/docs/guides/components/profilemenu.html"] = "/profile-menu",
|
||||
["/docs/guides/components/progressbar.html"] = "/progressbar",
|
||||
["/docs/guides/components/qrcode.html"] = "/qrcode",
|
||||
["/docs/guides/components/radiobuttonlist.html"] = "/radiobuttonlist",
|
||||
["/docs/guides/components/radialgauge.html"] = "/radial-gauge",
|
||||
["/docs/guides/components/rating.html"] = "/rating",
|
||||
["/docs/guides/components/regexvalidator.html"] = "/regexvalidator",
|
||||
["/docs/guides/components/requiredvalidator.html"] = "/requiredvalidator",
|
||||
["/docs/guides/components/scheduler.html"] = "/scheduler",
|
||||
["/docs/guides/components/selectbar.html"] = "/selectbar",
|
||||
["/docs/guides/components/slider.html"] = "/slider",
|
||||
["/docs/guides/components/splitbutton.html"] = "/splitbutton",
|
||||
["/docs/guides/components/splitter.html"] = "/splitter",
|
||||
["/docs/guides/components/ssrsviewer.html"] = "/ssrsviewer",
|
||||
["/docs/guides/components/steps.html"] = "/steps",
|
||||
["/docs/guides/components/switch.html"] = "/switch",
|
||||
["/docs/guides/components/tabs.html"] = "/tabs",
|
||||
["/docs/guides/components/templateform.html"] = "/templateform",
|
||||
["/docs/guides/components/textarea.html"] = "/textarea",
|
||||
["/docs/guides/components/textbox.html"] = "/textbox",
|
||||
["/docs/guides/components/timespanpicker.html"] = "/timespanpicker",
|
||||
["/docs/guides/components/tooltip.html"] = "/tooltip",
|
||||
["/docs/guides/components/tree.html"] = "/tree",
|
||||
["/docs/guides/components/upload.html"] = "/example-upload"
|
||||
}.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static IApplicationBuilder UseCanonicalRedirects(this IApplicationBuilder app)
|
||||
{
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
var path = NormalizePath(context.Request.Path.Value ?? string.Empty);
|
||||
|
||||
if (TryResolveTarget(path, out var targetPath))
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status301MovedPermanently;
|
||||
context.Response.Headers.Location = targetPath + context.Request.QueryString;
|
||||
context.Response.Headers.CacheControl = "public, max-age=86400";
|
||||
return;
|
||||
}
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
private static bool TryResolveTarget(string path, out string targetPath)
|
||||
{
|
||||
if (StaticRedirects.TryGetValue(path, out targetPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TryMapOptionalSegment(path, "/getting-started", "/get-started", out targetPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TryMapOptionalSegment(path, "/docs/guides/getting-started/installation.html", "/get-started", out targetPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
targetPath = string.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string NormalizePath(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return "/";
|
||||
}
|
||||
|
||||
return path.TrimEnd('/') switch
|
||||
{
|
||||
"" => "/",
|
||||
var normalized => normalized
|
||||
};
|
||||
}
|
||||
|
||||
private static bool TryMapOptionalSegment(string path, string sourceBasePath, string targetBasePath, out string targetPath)
|
||||
{
|
||||
if (path.Equals(sourceBasePath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
targetPath = targetBasePath;
|
||||
return true;
|
||||
}
|
||||
|
||||
var prefix = sourceBasePath + "/";
|
||||
if (path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var suffix = path[prefix.Length..];
|
||||
if (!suffix.Contains('/'))
|
||||
{
|
||||
targetPath = targetBasePath + "/" + suffix;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
targetPath = string.Empty;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -229,10 +229,8 @@ namespace RadzenBlazorDemos
|
||||
if (underlyingType == typeof(System.Guid) || underlyingType == typeof(System.DateTimeOffset))
|
||||
return true;
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if (underlyingType == typeof(System.DateOnly) || underlyingType == typeof(System.TimeOnly))
|
||||
return true;
|
||||
#endif
|
||||
var typeCode = Type.GetTypeCode(underlyingType);
|
||||
|
||||
switch (typeCode)
|
||||
|
||||
@@ -15,6 +15,7 @@ using System.IO;
|
||||
using Radzen;
|
||||
using RadzenBlazorDemos;
|
||||
using RadzenBlazorDemos.Data;
|
||||
using RadzenBlazorDemos.Host;
|
||||
using RadzenBlazorDemos.Services;
|
||||
using RadzenBlazorDemos.Host.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@@ -134,6 +135,8 @@ if (!app.Environment.IsDevelopment())
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
app.UseCanonicalRedirects();
|
||||
app.UseTrailingSlashRedirect();
|
||||
app.UseAntiforgery();
|
||||
app.MapGet("/llms.txt", () =>
|
||||
{
|
||||
|
||||
32
RadzenBlazorDemos.Host/TrailingSlashMiddleware.cs
Normal file
32
RadzenBlazorDemos.Host/TrailingSlashMiddleware.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
namespace RadzenBlazorDemos.Host;
|
||||
|
||||
/// <summary>
|
||||
/// Middleware that removes trailing slashes from URLs with a 301 permanent redirect.
|
||||
/// This prevents duplicate content issues where both /pricing and /pricing/ serve the same page.
|
||||
/// </summary>
|
||||
public static class TrailingSlashMiddleware
|
||||
{
|
||||
public static IApplicationBuilder UseTrailingSlashRedirect(this IApplicationBuilder app)
|
||||
{
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
var path = context.Request.Path.Value;
|
||||
|
||||
if (path != "/" && path?.EndsWith('/') == true)
|
||||
{
|
||||
var newPath = path.TrimEnd('/') + context.Request.QueryString;
|
||||
|
||||
context.Response.StatusCode = 301;
|
||||
context.Response.Headers.Location = newPath;
|
||||
context.Response.Headers.CacheControl = "public, max-age=86400";
|
||||
return;
|
||||
}
|
||||
|
||||
await next();
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,44 @@ namespace RadzenBlazorDemos.Tools;
|
||||
|
||||
class Program
|
||||
{
|
||||
// Pages that are not component documentation (marketing, meta, showcases).
|
||||
// These produce noisy content (testimonials, repeated CTAs, sample dashboards)
|
||||
// that pollutes search results when used with a RAG system.
|
||||
static readonly HashSet<string> ExcludedPages = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"AccessibilityPage", // Generic WCAG/ARIA info, no component-specific content
|
||||
"AI",
|
||||
"Changelog",
|
||||
"Dashboard",
|
||||
"DashboardPage",
|
||||
"GetStarted", // Installation steps, not component documentation
|
||||
"Index",
|
||||
"NotFound",
|
||||
"Playground",
|
||||
"SupportPage",
|
||||
"ThemeServicePage", // Theme persistence setup steps, not component demos
|
||||
"ThemesPage",
|
||||
};
|
||||
|
||||
// Filename prefixes that match non-documentation showcase pages.
|
||||
static readonly string[] ExcludedPrefixes = ["Templates", "UIBlocks"];
|
||||
|
||||
static bool IsExcluded(string filePath)
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(filePath);
|
||||
|
||||
if (ExcludedPages.Contains(name))
|
||||
return true;
|
||||
|
||||
foreach (var prefix in ExcludedPrefixes)
|
||||
{
|
||||
if (name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int Main(string[] args)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
@@ -41,7 +79,7 @@ class Program
|
||||
static void Generate(string outputPath, string pagesPath, string servicesPath, string modelsPath)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
|
||||
sb.AppendLine("# Radzen Blazor Components - Demo Application");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("This file contains all demo pages and examples from the Radzen Blazor Components demo application.");
|
||||
@@ -49,16 +87,16 @@ class Program
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("## Table of Contents");
|
||||
sb.AppendLine();
|
||||
|
||||
|
||||
// Collect all demo files
|
||||
var allPages = Directory.GetFiles(pagesPath, "*.razor", SearchOption.AllDirectories)
|
||||
.Where(f => !Path.GetFileName(f).StartsWith("_"))
|
||||
.ToList();
|
||||
|
||||
|
||||
// Separate main pages (with @page directive) from example components
|
||||
var mainPages = new List<string>();
|
||||
var examplePages = new List<string>();
|
||||
|
||||
|
||||
foreach (var page in allPages)
|
||||
{
|
||||
var content = File.ReadAllText(page, Encoding.UTF8);
|
||||
@@ -72,25 +110,28 @@ class Program
|
||||
examplePages.Add(page);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort main pages ascending by filename
|
||||
mainPages = mainPages.OrderBy(p => Path.GetFileName(p)).ToList();
|
||||
|
||||
// Keep all pages for content generation (sorted ascending)
|
||||
var pages = allPages.OrderBy(p => Path.GetFileName(p)).ToList();
|
||||
|
||||
|
||||
// Sort main pages ascending by filename and apply exclusions
|
||||
mainPages = mainPages
|
||||
.Where(p => !IsExcluded(p))
|
||||
.OrderBy(p => Path.GetFileName(p)).ToList();
|
||||
|
||||
// Only main pages (with @page directive) get their own sections.
|
||||
// Example sub-components are embedded as code snippets via <RadzenExample>.
|
||||
var pages = mainPages;
|
||||
|
||||
var pageCs = Directory.GetFiles(pagesPath, "*.cs", SearchOption.AllDirectories)
|
||||
.OrderBy(f => Path.GetFileName(f))
|
||||
.ToList();
|
||||
|
||||
|
||||
var services = !string.IsNullOrEmpty(servicesPath) && Directory.Exists(servicesPath)
|
||||
? Directory.GetFiles(servicesPath, "*.cs", SearchOption.AllDirectories).OrderBy(f => Path.GetFileName(f)).ToList()
|
||||
: Enumerable.Empty<string>();
|
||||
|
||||
|
||||
var models = !string.IsNullOrEmpty(modelsPath) && Directory.Exists(modelsPath)
|
||||
? Directory.GetFiles(modelsPath, "*.cs", SearchOption.AllDirectories).OrderBy(f => Path.GetFileName(f)).ToList()
|
||||
: Enumerable.Empty<string>();
|
||||
|
||||
|
||||
// Generate table of contents - only include main pages
|
||||
sb.AppendLine("### Demo Pages");
|
||||
foreach (var page in mainPages)
|
||||
@@ -99,7 +140,7 @@ class Program
|
||||
var fileName = Path.GetFileNameWithoutExtension(page);
|
||||
sb.AppendLine($"- [{fileName}](#{SanitizeAnchor(fileName)}) - `{relativePath}`");
|
||||
}
|
||||
|
||||
|
||||
if (pageCs.Any())
|
||||
{
|
||||
sb.AppendLine();
|
||||
@@ -110,28 +151,36 @@ class Program
|
||||
sb.AppendLine($"- [{fileName}](#{SanitizeAnchor(fileName)}-code-behind)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("---");
|
||||
sb.AppendLine();
|
||||
|
||||
|
||||
// Add demo pages
|
||||
sb.AppendLine("## Demo Pages");
|
||||
sb.AppendLine();
|
||||
|
||||
|
||||
foreach (var page in pages)
|
||||
{
|
||||
var relativePath = Path.GetRelativePath(pagesPath, page).Replace('\\', '/');
|
||||
var fileName = Path.GetFileNameWithoutExtension(page);
|
||||
var fileContent = File.ReadAllText(page, Encoding.UTF8);
|
||||
var extractedContent = ExtractDescriptionsAndExamples(fileContent, page);
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(extractedContent))
|
||||
continue;
|
||||
|
||||
// Add explicit HTML anchor to ensure TOC links work across all markdown parsers
|
||||
var anchor = SanitizeAnchor(fileName);
|
||||
sb.AppendLine($"<a id=\"{anchor}\"></a>");
|
||||
|
||||
// Skip sections that produce negligible content — these are typically
|
||||
// sub-component pages whose rendered placeholder text leaked through
|
||||
// (e.g. "km/h", "Value is:", single comma).
|
||||
var textOnly = Regex.Replace(extractedContent, @"```[\s\S]*?```", ""); // strip code blocks
|
||||
textOnly = Regex.Replace(textOnly, @"^#{1,6}\s+.*$", "", RegexOptions.Multiline); // strip headings
|
||||
textOnly = Regex.Replace(textOnly, @"^\*\*Path:\*\*.*$", "", RegexOptions.Multiline); // strip path
|
||||
textOnly = Regex.Replace(textOnly, @"^Example:$", "", RegexOptions.Multiline); // strip "Example:" labels
|
||||
textOnly = textOnly.Trim();
|
||||
if (textOnly.Length < 20)
|
||||
continue;
|
||||
|
||||
sb.AppendLine($"### {fileName}");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"**Path:** `{relativePath}`");
|
||||
@@ -141,21 +190,19 @@ class Program
|
||||
sb.AppendLine("---");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
|
||||
// Add C# code-behind files
|
||||
if (pageCs.Any())
|
||||
{
|
||||
sb.AppendLine("## Code-Behind Files");
|
||||
sb.AppendLine();
|
||||
|
||||
|
||||
foreach (var csFile in pageCs)
|
||||
{
|
||||
var relativePath = Path.GetRelativePath(pagesPath, csFile).Replace('\\', '/');
|
||||
var fileName = Path.GetFileNameWithoutExtension(csFile);
|
||||
var fileContent = File.ReadAllText(csFile, Encoding.UTF8);
|
||||
|
||||
var codeBehindAnchor = SanitizeAnchor($"{fileName}-code-behind");
|
||||
sb.AppendLine($"<a id=\"{codeBehindAnchor}\"></a>");
|
||||
|
||||
sb.AppendLine($"### {fileName} (Code-Behind)");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"**Path:** `{relativePath}`");
|
||||
@@ -168,19 +215,19 @@ class Program
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add services
|
||||
if (services.Any())
|
||||
{
|
||||
sb.AppendLine("## Services");
|
||||
sb.AppendLine();
|
||||
|
||||
|
||||
foreach (var service in services)
|
||||
{
|
||||
var relativePath = Path.GetRelativePath(servicesPath, service).Replace('\\', '/');
|
||||
var fileName = Path.GetFileNameWithoutExtension(service);
|
||||
var fileContent = File.ReadAllText(service, Encoding.UTF8);
|
||||
|
||||
|
||||
sb.AppendLine($"### {fileName}");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"**Path:** `{relativePath}`");
|
||||
@@ -193,19 +240,19 @@ class Program
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add models
|
||||
if (models.Any())
|
||||
{
|
||||
sb.AppendLine("## Data Models");
|
||||
sb.AppendLine();
|
||||
|
||||
|
||||
foreach (var model in models)
|
||||
{
|
||||
var relativePath = Path.GetRelativePath(modelsPath, model).Replace('\\', '/');
|
||||
var fileName = Path.GetFileNameWithoutExtension(model);
|
||||
var fileContent = File.ReadAllText(model, Encoding.UTF8);
|
||||
|
||||
|
||||
sb.AppendLine($"### {fileName}");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"**Path:** `{relativePath}`");
|
||||
@@ -218,7 +265,7 @@ class Program
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write to file
|
||||
var outputDir = Path.GetDirectoryName(outputPath);
|
||||
if (!string.IsNullOrEmpty(outputDir))
|
||||
@@ -232,13 +279,13 @@ class Program
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return "";
|
||||
|
||||
|
||||
// Markdown heading anchors are generated by:
|
||||
// 1. Convert to lowercase
|
||||
// 2. Replace spaces and special chars with hyphens
|
||||
// 3. Remove multiple consecutive hyphens
|
||||
// 4. Trim hyphens from start/end
|
||||
|
||||
|
||||
var anchor = text.ToLower()
|
||||
.Replace(" ", "-")
|
||||
.Replace("_", "-")
|
||||
@@ -268,13 +315,13 @@ class Program
|
||||
.Replace("`", "")
|
||||
.Replace("'", "")
|
||||
.Replace("\"", "");
|
||||
|
||||
|
||||
// Remove multiple consecutive hyphens
|
||||
anchor = Regex.Replace(anchor, @"-+", "-");
|
||||
|
||||
|
||||
// Trim hyphens from start and end
|
||||
anchor = anchor.Trim('-');
|
||||
|
||||
|
||||
return anchor;
|
||||
}
|
||||
|
||||
@@ -282,40 +329,56 @@ class Program
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
var pagesDirectory = Path.GetDirectoryName(pagePath) ?? "";
|
||||
|
||||
var seenText = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
// Remove @code blocks entirely
|
||||
razorContent = Regex.Replace(razorContent,
|
||||
@"@code\s*\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}",
|
||||
"",
|
||||
razorContent = Regex.Replace(razorContent,
|
||||
@"@code\s*\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}",
|
||||
"",
|
||||
RegexOptions.Singleline | RegexOptions.IgnoreCase);
|
||||
|
||||
// Remove @page, @inject, @layout directives
|
||||
razorContent = Regex.Replace(razorContent,
|
||||
@"@(page|inject|layout|using|namespace|implements)[^\r\n]*",
|
||||
"",
|
||||
|
||||
// Remove @page, @inject, @layout directives.
|
||||
// Use \b word boundary so @page doesn't match @pageSizeOptions, etc.
|
||||
razorContent = Regex.Replace(razorContent,
|
||||
@"@(page|inject|layout|using|namespace|implements)\b[^\r\n]*",
|
||||
"",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
|
||||
|
||||
// Split content into lines to process sequentially
|
||||
var lines = razorContent.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
|
||||
|
||||
|
||||
var skipUntilNextHeading = false;
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
|
||||
|
||||
// Check for RadzenText
|
||||
if (line.Contains("<RadzenText"))
|
||||
{
|
||||
var textContent = ExtractRadzenTextContent(lines, ref i);
|
||||
if (!string.IsNullOrWhiteSpace(textContent.Content))
|
||||
if (!string.IsNullOrWhiteSpace(textContent.Content) && seenText.Add(textContent.Content))
|
||||
{
|
||||
// Format as heading if it's a heading style
|
||||
// Skip sections that produce no useful component documentation:
|
||||
// - "Keyboard Navigation": shortcuts rendered by <KeyboardNavigationDataGrid>
|
||||
// from C# data, can't be extracted — leaves a generic placeholder sentence.
|
||||
// - "Radzen Blazor Studio": IDE-specific content, not component API docs.
|
||||
if (textContent.IsHeading && (
|
||||
textContent.Content.Contains("Keyboard Navigation") ||
|
||||
textContent.Content.Contains("Radzen Blazor Studio")))
|
||||
{
|
||||
skipUntilNextHeading = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (textContent.IsHeading)
|
||||
{
|
||||
skipUntilNextHeading = false;
|
||||
result.AppendLine();
|
||||
result.AppendLine(textContent.Content);
|
||||
result.AppendLine();
|
||||
}
|
||||
else
|
||||
else if (!skipUntilNextHeading)
|
||||
{
|
||||
result.AppendLine(textContent.Content);
|
||||
}
|
||||
@@ -324,6 +387,9 @@ class Program
|
||||
// Check for RadzenExample
|
||||
else if (line.Contains("<RadzenExample"))
|
||||
{
|
||||
if (skipUntilNextHeading)
|
||||
continue;
|
||||
|
||||
var exampleContent = ExtractRadzenExampleContent(lines, ref i, pagesDirectory);
|
||||
if (!string.IsNullOrWhiteSpace(exampleContent))
|
||||
{
|
||||
@@ -336,7 +402,7 @@ class Program
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result.ToString().Trim();
|
||||
}
|
||||
|
||||
@@ -344,36 +410,37 @@ class Program
|
||||
{
|
||||
var fullTag = new StringBuilder();
|
||||
var depth = 0;
|
||||
|
||||
|
||||
// Collect the complete RadzenText tag (may span multiple lines)
|
||||
for (int i = index; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
fullTag.AppendLine(line);
|
||||
|
||||
|
||||
// Count opening and closing tags
|
||||
var openMatches = Regex.Matches(line, @"<RadzenText", RegexOptions.IgnoreCase);
|
||||
var closeMatches = Regex.Matches(line, @"</RadzenText>", RegexOptions.IgnoreCase);
|
||||
|
||||
|
||||
depth += openMatches.Count - closeMatches.Count;
|
||||
|
||||
|
||||
if (closeMatches.Count > 0 && depth == 0)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var tagContent = fullTag.ToString();
|
||||
|
||||
// Extract attributes - check both TextStyle and TagName for heading detection
|
||||
|
||||
// Only treat RadzenText as a heading when it has an explicit TextStyle.
|
||||
// TagName (e.g. TagName="TagName.H2") is just an HTML rendering hint used
|
||||
// for visual styling (marketing text, testimonials, CTAs) and does NOT
|
||||
// indicate a semantic documentation heading.
|
||||
var textStyleMatch = Regex.Match(tagContent, @"TextStyle=""TextStyle\.(H[2-6])""", RegexOptions.IgnoreCase);
|
||||
var tagNameMatch = Regex.Match(tagContent, @"TagName=""TagName\.(H[1-6])""", RegexOptions.IgnoreCase);
|
||||
|
||||
|
||||
bool isHeading = false;
|
||||
int headingLevel = 0;
|
||||
|
||||
// Prefer TextStyle for heading level, but also check TagName
|
||||
|
||||
if (textStyleMatch.Success)
|
||||
{
|
||||
var hMatch = Regex.Match(textStyleMatch.Groups[1].Value, @"H(\d)");
|
||||
@@ -383,67 +450,74 @@ class Program
|
||||
isHeading = headingLevel >= 2 && headingLevel <= 6;
|
||||
}
|
||||
}
|
||||
|
||||
// If no TextStyle heading but TagName suggests heading, use that
|
||||
if (!isHeading && tagNameMatch.Success)
|
||||
{
|
||||
var hMatch = Regex.Match(tagNameMatch.Groups[1].Value, @"H(\d)");
|
||||
if (hMatch.Success)
|
||||
{
|
||||
var tagLevel = int.Parse(hMatch.Groups[1].Value);
|
||||
if (tagLevel >= 2 && tagLevel <= 6)
|
||||
{
|
||||
headingLevel = tagLevel;
|
||||
isHeading = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Extract inner content
|
||||
var contentMatch = Regex.Match(tagContent, @"<RadzenText[^>]*>([\s\S]*?)</RadzenText>", RegexOptions.IgnoreCase);
|
||||
if (!contentMatch.Success)
|
||||
return (string.Empty, false);
|
||||
|
||||
|
||||
var content = contentMatch.Groups[1].Value.Trim();
|
||||
|
||||
|
||||
// Convert <code> tags to markdown inline code BEFORE converting links
|
||||
content = ConvertCodeTagsToMarkdown(content);
|
||||
|
||||
// Convert RadzenLink to markdown links BEFORE removing HTML tags
|
||||
content = ConvertRadzenLinksToMarkdown(content);
|
||||
|
||||
|
||||
// For headings, strip RadzenLink elements entirely (CTA buttons are not heading text).
|
||||
// For non-headings, convert them to markdown links.
|
||||
if (isHeading)
|
||||
content = Regex.Replace(content, @"<RadzenLink[^>]*/\s*>|<RadzenLink[^>]*>[\s\S]*?</RadzenLink>", "", RegexOptions.IgnoreCase);
|
||||
else
|
||||
content = ConvertRadzenLinksToMarkdown(content);
|
||||
|
||||
// Remove all HTML tags (except markdown links which are already converted)
|
||||
content = Regex.Replace(content, @"<[^>]+>", "");
|
||||
|
||||
// Remove @ expressions
|
||||
content = Regex.Replace(content, @"@[A-Za-z0-9_.()]+", "");
|
||||
|
||||
|
||||
// Remove Razor/C# expressions: @(...), @variable, $"...", ?.Member, etc.
|
||||
content = Regex.Replace(content, @"@\([^)]*\)", ""); // @(...) expressions
|
||||
content = Regex.Replace(content, @"@[A-Za-z0-9_.()]+", ""); // @variable references
|
||||
content = Regex.Replace(content, @"\$""[^""]*""", ""); // $"..." string interpolations
|
||||
content = Regex.Replace(content, @"\?\.\w+", ""); // ?.Member null-conditional access
|
||||
|
||||
// Clean up whitespace
|
||||
content = Regex.Replace(content, @"\s+", " ").Trim();
|
||||
|
||||
// Format as heading if needed
|
||||
|
||||
// Skip content that looks like leaked C#/Razor rather than documentation text.
|
||||
// Indicators: unbalanced parentheses, remaining code artifacts like => or {}.
|
||||
if (content.Contains("=>") || content.Contains("FilterOperator") || content.Contains("FilterValue"))
|
||||
return (string.Empty, false);
|
||||
|
||||
// Format as heading if needed.
|
||||
// Markdown heading budget:
|
||||
// # = document title
|
||||
// ## = major sections (Demo Pages, Code-Behind)
|
||||
// ### = page name (AccordionPage)
|
||||
// #### = component heading (Accordion)
|
||||
// ##### = sub-feature (Accordion with single expand)
|
||||
// ###### = detail
|
||||
if (isHeading && !string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
// Map heading levels: H2 -> ####, H4 -> ####, H5 -> #####, H6 -> ######
|
||||
int markdownLevel = 4; // Default to ####
|
||||
if (headingLevel == 4) markdownLevel = 4; // H4 -> ####
|
||||
else if (headingLevel == 5) markdownLevel = 5; // H5 -> #####
|
||||
else if (headingLevel == 6) markdownLevel = 6; // H6 -> ######
|
||||
else if (headingLevel == 2) markdownLevel = 4; // H2 -> ####
|
||||
|
||||
int markdownLevel = headingLevel switch
|
||||
{
|
||||
2 => 4, // H2 -> #### component heading
|
||||
3 => 5, // H3 -> ##### sub-feature
|
||||
4 => 5, // H4 -> ##### sub-feature
|
||||
5 => 6, // H5 -> ###### detail
|
||||
6 => 6, // H6 -> ###### detail
|
||||
_ => 4
|
||||
};
|
||||
|
||||
content = new string('#', markdownLevel) + " " + content;
|
||||
}
|
||||
|
||||
|
||||
return (content, isHeading);
|
||||
}
|
||||
|
||||
static string ConvertCodeTagsToMarkdown(string content)
|
||||
{
|
||||
// Match <code>...</code> tags
|
||||
var codeMatches = Regex.Matches(content,
|
||||
@"<code>([\s\S]*?)</code>",
|
||||
var codeMatches = Regex.Matches(content,
|
||||
@"<code>([\s\S]*?)</code>",
|
||||
RegexOptions.IgnoreCase);
|
||||
|
||||
|
||||
// Process in reverse to maintain indices
|
||||
var matchesArray = new Match[codeMatches.Count];
|
||||
for (int i = 0; i < codeMatches.Count; i++)
|
||||
@@ -454,25 +528,25 @@ class Program
|
||||
{
|
||||
var match = matchesArray[i];
|
||||
var codeContent = match.Groups[1].Value.Trim();
|
||||
|
||||
|
||||
// Remove nested HTML tags from code content
|
||||
codeContent = Regex.Replace(codeContent, @"<[^>]+>", "");
|
||||
|
||||
|
||||
// Clean up @("@bind-Selected") to @bind-Selected (remove extra quotes and parentheses)
|
||||
// Match: @("...") pattern and extract the content inside quotes
|
||||
// Pattern: @("@bind-Selected") -> @bind-Selected
|
||||
// Use non-verbatim string to avoid quote escaping issues
|
||||
codeContent = Regex.Replace(codeContent, "@\\(\"([^\"]+)\"\\)", "$1");
|
||||
codeContent = Regex.Replace(codeContent, "@\\('([^']+)'\\)", "$1");
|
||||
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(codeContent))
|
||||
{
|
||||
var markdownCode = $"`{codeContent}`";
|
||||
content = content.Substring(0, match.Index) + markdownCode +
|
||||
content = content.Substring(0, match.Index) + markdownCode +
|
||||
content.Substring(match.Index + match.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -480,12 +554,12 @@ class Program
|
||||
{
|
||||
// Handle both self-closing and opening/closing RadzenLink tags
|
||||
// Match the entire tag first, then extract attributes
|
||||
|
||||
|
||||
// Pattern for self-closing: <RadzenLink ... />
|
||||
var selfClosingPattern = @"<RadzenLink([^>]*?)\s*/>";
|
||||
// Pattern for opening/closing: <RadzenLink ...>...</RadzenLink>
|
||||
var openClosePattern = @"<RadzenLink([^>]*?)>([\s\S]*?)</RadzenLink>";
|
||||
|
||||
|
||||
// Process self-closing tags
|
||||
var selfClosingMatches = Regex.Matches(content, selfClosingPattern, RegexOptions.IgnoreCase);
|
||||
var selfClosingArray = new Match[selfClosingMatches.Count];
|
||||
@@ -498,16 +572,16 @@ class Program
|
||||
var match = selfClosingArray[i];
|
||||
var attributes = match.Groups[1].Value;
|
||||
var (path, text) = ExtractLinkAttributes(attributes, "");
|
||||
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
string linkText = !string.IsNullOrWhiteSpace(text) ? text : path;
|
||||
var markdownLink = $"[{linkText}]({path})";
|
||||
content = content.Substring(0, match.Index) + markdownLink +
|
||||
content = content.Substring(0, match.Index) + markdownLink +
|
||||
content.Substring(match.Index + match.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Process opening/closing tags
|
||||
var linkMatches = Regex.Matches(content, openClosePattern, RegexOptions.IgnoreCase);
|
||||
var matchesArray = new Match[linkMatches.Count];
|
||||
@@ -521,21 +595,21 @@ class Program
|
||||
var attributes = match.Groups[1].Value;
|
||||
var innerContent = match.Groups[2].Value.Trim();
|
||||
var (path, text) = ExtractLinkAttributes(attributes, innerContent);
|
||||
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
string linkText = !string.IsNullOrWhiteSpace(text) ? text :
|
||||
string linkText = !string.IsNullOrWhiteSpace(text) ? text :
|
||||
(!string.IsNullOrWhiteSpace(innerContent) ? Regex.Replace(innerContent, @"<[^>]+>", "").Trim() : path);
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(linkText))
|
||||
linkText = path;
|
||||
|
||||
|
||||
var markdownLink = $"[{linkText}]({path})";
|
||||
content = content.Substring(0, match.Index) + markdownLink +
|
||||
content = content.Substring(0, match.Index) + markdownLink +
|
||||
content.Substring(match.Index + match.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -543,27 +617,27 @@ class Program
|
||||
{
|
||||
string path = "";
|
||||
string text = "";
|
||||
|
||||
|
||||
// Extract Path attribute (can be in any order)
|
||||
var pathMatch = Regex.Match(attributes, @"Path=[""]?([^""\s>]+)[""]?", RegexOptions.IgnoreCase);
|
||||
if (pathMatch.Success)
|
||||
{
|
||||
path = pathMatch.Groups[1].Value;
|
||||
}
|
||||
|
||||
|
||||
// Extract Text attribute
|
||||
var textMatch = Regex.Match(attributes, @"Text=[""]?([^""]+)[""]?", RegexOptions.IgnoreCase);
|
||||
if (textMatch.Success)
|
||||
{
|
||||
text = textMatch.Groups[1].Value.Trim();
|
||||
}
|
||||
|
||||
|
||||
// If no Text attribute and there's inner content, use that
|
||||
if (string.IsNullOrWhiteSpace(text) && !string.IsNullOrWhiteSpace(innerContent))
|
||||
{
|
||||
text = Regex.Replace(innerContent, @"<[^>]+>", "").Trim();
|
||||
}
|
||||
|
||||
|
||||
return (path, text);
|
||||
}
|
||||
|
||||
@@ -571,48 +645,48 @@ class Program
|
||||
{
|
||||
var fullTag = new StringBuilder();
|
||||
var depth = 0;
|
||||
|
||||
|
||||
// Collect the complete RadzenExample tag
|
||||
for (int i = index; i < lines.Length; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
fullTag.AppendLine(line);
|
||||
|
||||
|
||||
var openMatches = Regex.Matches(line, @"<RadzenExample", RegexOptions.IgnoreCase);
|
||||
var closeMatches = Regex.Matches(line, @"</RadzenExample>", RegexOptions.IgnoreCase);
|
||||
|
||||
|
||||
depth += openMatches.Count - closeMatches.Count;
|
||||
|
||||
|
||||
if (closeMatches.Count > 0 && depth == 0)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var tagContent = fullTag.ToString();
|
||||
|
||||
|
||||
// Extract Example attribute
|
||||
var exampleMatch = Regex.Match(tagContent, @"Example=[""]?([^""\s>]+)[""]?", RegexOptions.IgnoreCase);
|
||||
if (exampleMatch.Success)
|
||||
{
|
||||
var exampleName = exampleMatch.Groups[1].Value.Trim();
|
||||
var exampleFilePath = Path.Combine(pagesDirectory, $"{exampleName}.razor");
|
||||
|
||||
|
||||
if (File.Exists(exampleFilePath))
|
||||
{
|
||||
var exampleContent = File.ReadAllText(exampleFilePath, Encoding.UTF8);
|
||||
return CleanExampleFile(exampleContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fallback: extract inline content
|
||||
var inlineMatch = Regex.Match(tagContent, @"<RadzenExample[^>]*>([\s\S]*?)</RadzenExample>", RegexOptions.IgnoreCase);
|
||||
if (inlineMatch.Success)
|
||||
{
|
||||
return CleanExampleContent(inlineMatch.Groups[1].Value);
|
||||
}
|
||||
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
@@ -620,21 +694,21 @@ class Program
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
return string.Empty;
|
||||
|
||||
|
||||
var result = content;
|
||||
|
||||
|
||||
// Remove all HTML tags (including <strong>, <code>, <Radzen*>, etc.)
|
||||
result = Regex.Replace(result, @"<[^>]+>", "");
|
||||
|
||||
|
||||
// Remove @ expressions (like @variable, @ExampleService)
|
||||
result = Regex.Replace(result, @"@[A-Za-z0-9_.()]+", "");
|
||||
|
||||
|
||||
// Clean up multiple spaces but preserve single newlines for readability
|
||||
result = Regex.Replace(result, @"[ \t]+", " ");
|
||||
|
||||
|
||||
// Clean up multiple newlines (max 2 consecutive)
|
||||
result = Regex.Replace(result, @"(\r?\n){3,}", Environment.NewLine + Environment.NewLine);
|
||||
|
||||
|
||||
return result.Trim();
|
||||
}
|
||||
|
||||
@@ -642,21 +716,21 @@ class Program
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
return string.Empty;
|
||||
|
||||
|
||||
var result = content;
|
||||
|
||||
|
||||
// Remove nested RadzenExample tags if any
|
||||
result = Regex.Replace(result,
|
||||
@"<RadzenExample[^>]*>[\s\S]*?</RadzenExample>",
|
||||
"",
|
||||
result = Regex.Replace(result,
|
||||
@"<RadzenExample[^>]*>[\s\S]*?</RadzenExample>",
|
||||
"",
|
||||
RegexOptions.IgnoreCase);
|
||||
|
||||
|
||||
// Trim each line and remove empty lines
|
||||
var lines = result.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)
|
||||
.Select(l => l.Trim())
|
||||
.Where(l => !string.IsNullOrWhiteSpace(l))
|
||||
.ToList();
|
||||
|
||||
|
||||
return string.Join(Environment.NewLine, lines);
|
||||
}
|
||||
|
||||
@@ -664,24 +738,20 @@ class Program
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
return string.Empty;
|
||||
|
||||
|
||||
var result = content;
|
||||
|
||||
// Remove @code blocks
|
||||
result = Regex.Replace(result,
|
||||
@"@code\s*\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}",
|
||||
"",
|
||||
RegexOptions.Singleline | RegexOptions.IgnoreCase);
|
||||
|
||||
// Remove @using, @inject, @page directives
|
||||
result = Regex.Replace(result,
|
||||
@"@(using|inject|page|layout|namespace|implements)[^\r\n]*",
|
||||
"",
|
||||
|
||||
// Remove @using, @inject, @page directives (but NOT @code blocks — they contain
|
||||
// essential C# code that users need to understand the examples).
|
||||
// Use \b word boundary so @page doesn't match @pageSizeOptions, @pageIndex, etc.
|
||||
result = Regex.Replace(result,
|
||||
@"@(using|inject|page|layout|namespace|implements)\b[^\r\n]*",
|
||||
"",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
|
||||
|
||||
// Clean up multiple blank lines
|
||||
result = Regex.Replace(result, @"(\r?\n\s*){3,}", Environment.NewLine + Environment.NewLine);
|
||||
|
||||
|
||||
return result.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/aichat"
|
||||
@page "/docs/guides/components/aichat.html"
|
||||
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/accordion"
|
||||
@page "/docs/guides/components/accordion.html"
|
||||
@page "/accordion"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Accordion
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/arc-gauge"
|
||||
@page "/docs/guides/components/arcgauge.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Radzen Blazor Arc Gauge
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/autocomplete"
|
||||
@page "/docs/guides/components/autocomplete.html"
|
||||
@page "/autocomplete"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
AutoComplete
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/badge"
|
||||
@page "/docs/guides/components/badge.html"
|
||||
@page "/badge"
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Badge
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/barcode"
|
||||
@page "/docs/guides/components/barcode.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Barcode
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/breadcrumb"
|
||||
@page "/docs/guides/components/breadcrumb.html"
|
||||
@page "/breadcrumb"
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
BreadCrumb
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
@page "/buttons"
|
||||
@page "/button"
|
||||
@page "/docs/guides/components/button.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Button
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/carousel"
|
||||
@page "/docs/guides/components/carousel.html"
|
||||
@page "/carousel"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Carousel
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/chart-series"
|
||||
@page "/docs/guides/components/chart.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Radzen Blazor Chart
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/chat"
|
||||
@page "/docs/guides/components/chat.html"
|
||||
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/checkboxlist"
|
||||
@page "/docs/guides/components/checkboxlist.html"
|
||||
@page "/checkboxlist"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
CheckBoxList
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/checkbox"
|
||||
@page "/docs/guides/components/checkbox.html"
|
||||
@page "/checkbox"
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
CheckBox
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/colorpicker"
|
||||
@page "/docs/guides/components/colorpicker.html"
|
||||
@page "/colorpicker"
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
ColorPicker
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/comparevalidator"
|
||||
@page "/docs/guides/components/comparevalidator.html"
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
CompareValidator
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/contextmenu"
|
||||
@page "/docs/guides/components/contextmenu.html"
|
||||
@page "/contextmenu"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
ContextMenu
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/datagrid"
|
||||
@page "/docs/guides/components/datagrid.html"
|
||||
@page "/datagrid"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
DataGrid
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/datalist"
|
||||
@page "/docs/guides/components/datalist.html"
|
||||
@page "/datalist"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
DataList
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/datepicker"
|
||||
@page "/docs/guides/components/datepicker.html"
|
||||
@page "/datepicker"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
DatePicker
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/dialog"
|
||||
@page "/docs/guides/components/dialog.html"
|
||||
@page "/dialog"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Dialog
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/dropdown-datagrid"
|
||||
@page "/docs/guides/components/dropdowndatagrid.html"
|
||||
@page "/dropdown-datagrid"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
DropDownDataGrid
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/dropdown"
|
||||
@page "/docs/guides/components/dropdown.html"
|
||||
@page "/dropdown"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
DropDown
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/emailvalidator"
|
||||
@page "/docs/guides/components/emailvalidator.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
EmailValidator
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/fieldset"
|
||||
@page "/docs/guides/components/fieldset.html"
|
||||
@page "/fieldset"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Fieldset
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/fileinput"
|
||||
@page "/docs/guides/components/fileinput.html"
|
||||
@page "/fileinput"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
FileInput
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
@inject NavigationManager NavigationManager
|
||||
@page "/get-started/{version?}"
|
||||
@page "/getting-started/{version?}"
|
||||
@page "/docs/guides/getting-started/installation.html/{version?}"
|
||||
@page "/docs/guides/getting-started/use-component.html"
|
||||
@page "/docs/guides/getting-started/context-menu.html"
|
||||
@page "/docs/guides/getting-started/dialog.html"
|
||||
@page "/docs/guides/getting-started/notification.html"
|
||||
@page "/docs/guides/getting-started/tooltip.html"
|
||||
@page "/docs/guides/index.html"
|
||||
|
||||
<PageTitle>Get Started | Free UI Components by Radzen</PageTitle>
|
||||
<HeadContent>
|
||||
<meta name="description" content="How to get started with the Radzen Blazor Component library.">
|
||||
@@ -28,7 +19,7 @@ More info is available in the <RadzenLink Text="rendering mode article" Path="ht
|
||||
</RadzenAlert>
|
||||
<RadzenAlert AlertStyle="AlertStyle.Info" Variant="Variant.Flat" Shade="Shade.Lighter" AllowClose="false" class="rz-mb-12">
|
||||
If you have upgraded your application to .NET 8 .NET 9 or .NET 10 follow the getting started instructions for the version you initially used - e.g.
|
||||
<RadzenLink Path="get-started/net7-server" Text=".NET 7" /> or <RadzenLink Path="get-started/net6-server" Text=".NET 6"/>.
|
||||
<RadzenLink Path="get-started/net7-server" Text=".NET 7" />.
|
||||
These instructions assume the new application layout which uses rendering modes and was introduced with .NET 8.
|
||||
</RadzenAlert>
|
||||
@Installation(CurrentVersion)
|
||||
@@ -83,26 +74,6 @@ These instructions assume the new application layout which uses rendering modes
|
||||
@Additional(CurrentVersion)
|
||||
</div>
|
||||
</RadzenTabsItem>
|
||||
<RadzenTabsItem Text=".NET 6 Server">
|
||||
<div class="rz-p-0 rz-p-sm-2 rz-px-lg-12">
|
||||
@Installation(CurrentVersion)
|
||||
@Import(CurrentVersion)
|
||||
@IncludeTheme(("_Layout.cshtml", "ServerPrerendered", CurrentVersion))
|
||||
@IncludeJavaScript(("_Layout.cshtml", CurrentVersion))
|
||||
@UseComponent(CurrentVersion)
|
||||
@Additional(CurrentVersion)
|
||||
</div>
|
||||
</RadzenTabsItem>
|
||||
<RadzenTabsItem Text=".NET 6 WebAssembly (hosted)">
|
||||
<div class="rz-p-0 rz-p-sm-2 rz-px-lg-12">
|
||||
@Installation(CurrentVersion)
|
||||
@Import(CurrentVersion)
|
||||
@IncludeTheme(("_Layout.cshtml", "WebAssemblyPrerendered", CurrentVersion))
|
||||
@IncludeJavaScript(("_Layout.cshtml", CurrentVersion))
|
||||
@UseComponent(CurrentVersion)
|
||||
@Additional(CurrentVersion)
|
||||
</div>
|
||||
</RadzenTabsItem>
|
||||
<RadzenTabsItem Text="WebAssembly (standalone)">
|
||||
<div class="rz-p-0 rz-p-sm-2 rz-px-lg-12">
|
||||
@Installation(CurrentVersion)
|
||||
@@ -152,7 +123,7 @@ These instructions assume the new application layout which uses rendering modes
|
||||
</RadzenTabs>
|
||||
|
||||
@code {
|
||||
private static readonly string[] versions = ["net9", "net7-server", "net7-wasm", "net6-server", "net6-wasm", "wasm", "csp"];
|
||||
private static readonly string[] versions = ["net9", "net7-server", "net7-wasm", "wasm", "csp"];
|
||||
|
||||
private int selectedIndex = 0;
|
||||
|
||||
@@ -166,6 +137,10 @@ These instructions assume the new application layout which uses rendering modes
|
||||
base.OnParametersSet();
|
||||
|
||||
selectedIndex = Array.IndexOf(versions, CurrentVersion);
|
||||
if (selectedIndex < 0)
|
||||
{
|
||||
selectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTabChange(int index)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/googlemap"
|
||||
@page "/docs/guides/components/googlemap.html"
|
||||
@page "/googlemap"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
GoogleMap
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/gravatar"
|
||||
@page "/docs/guides/components/gravatar.html"
|
||||
@page "/gravatar"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Gravatar
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/html-editor"
|
||||
@page "/docs/guides/components/htmleditor.html"
|
||||
@page "/html-editor"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
HtmlEditor
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/icon"
|
||||
@page "/docs/guides/components/icon.html"
|
||||
@page "/icon"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Icon
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/image"
|
||||
@page "/docs/guides/components/image.html"
|
||||
@page "/image"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Image
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
@layout HomeLayout
|
||||
@page "/"
|
||||
@page "/docs/"
|
||||
@inject ExampleService ExampleService
|
||||
@inject NotificationService NotificationService
|
||||
@inject DialogService DialogService
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/label"
|
||||
@page "/docs/guides/components/label.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Label
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/lengthvalidator"
|
||||
@page "/docs/guides/components/lengthvalidator.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
LengthValidator
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/link"
|
||||
@page "/docs/guides/components/link.html"
|
||||
@page "/link"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Link
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/listbox"
|
||||
@page "/docs/guides/components/listbox.html"
|
||||
@page "/listbox"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
ListBox
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/login"
|
||||
@page "/docs/guides/components/login.html"
|
||||
@page "/login"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Login
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/mask"
|
||||
@page "/docs/guides/components/mask.html"
|
||||
@page "/mask"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Mask
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/media-query"
|
||||
@page "/docs/guides/components/media-query.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
MediaQuery
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/menu"
|
||||
@page "/docs/guides/components/menu.html"
|
||||
@page "/menu"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Menu
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/notification"
|
||||
@page "/docs/guides/components/notification.html"
|
||||
@page "/notification"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Notification
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/numeric"
|
||||
@page "/docs/guides/components/numeric.html"
|
||||
@page "/numeric"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Numeric
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/numericrangevalidator"
|
||||
@page "/docs/guides/components/numericrangevalidator.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
NumericRangeValidator
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/pager"
|
||||
@page "/docs/guides/components/pager.html"
|
||||
@page "/pager"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Pager
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/panelmenu"
|
||||
@page "/docs/guides/components/panelmenu.html"
|
||||
@page "/panelmenu"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
PanelMenu
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/panel"
|
||||
@page "/docs/guides/components/panel.html"
|
||||
@page "/panel"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Panel
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/password"
|
||||
@page "/docs/guides/components/password.html"
|
||||
@page "/password"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Password
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/profile-menu"
|
||||
@page "/docs/guides/components/profilemenu.html"
|
||||
@page "/profile-menu"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
ProfileMenu
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/progressbar"
|
||||
@page "/docs/guides/components/progressbar.html"
|
||||
@page "/progressbar"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
ProgressBar
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/qrcode"
|
||||
@page "/docs/guides/components/qrcode.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
QRCode
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/radial-gauge"
|
||||
@page "/docs/guides/components/radialgauge.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Radzen Blazor Radial Gauge
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/radiobuttonlist"
|
||||
@page "/docs/guides/components/radiobuttonlist.html"
|
||||
@page "/radiobuttonlist"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
RadioButtonList
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/rating"
|
||||
@page "/docs/guides/components/rating.html"
|
||||
@page "/rating"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Rating
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/regexvalidator"
|
||||
@page "/docs/guides/components/regexvalidator.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
RegexValidator
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/requiredvalidator"
|
||||
@page "/docs/guides/components/requiredvalidator.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
RequiredValidator
|
||||
</RadzenText>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/ssrsviewer"
|
||||
@page "/docs/guides/components/ssrsviewer.html"
|
||||
@page "/ssrsviewer"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
SSRS Viewer
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@page "/scheduler"
|
||||
@page "/docs/guides/components/scheduler.html"
|
||||
|
||||
<RadzenText TextStyle="TextStyle.H2" TagName="TagName.H1" class="rz-pt-8">
|
||||
Scheduler
|
||||
</RadzenText>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user