diff --git a/samples/Blazor.Toolkit.Samples.Client/Layout/MainLayout.razor b/samples/Blazor.Toolkit.Samples.Client/Layout/MainLayout.razor index 7873fec..cc97438 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Layout/MainLayout.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Layout/MainLayout.razor @@ -1,5 +1,7 @@ @inherits LayoutComponentBase @implements IAsyncDisposable +@using Blazor.Toolkit.Samples.Client.Services +@inject SampleService SampleService @using Microsoft.AspNetCore.Components.Web @using Syncfusion.Blazor.Toolkit.Buttons @@ -160,8 +162,10 @@
- - @Body + + + @Body +
@@ -268,6 +272,15 @@ // Register this instance with the helper await JS.InvokeVoidAsync("responsiveBlazor.register", _dotNetRef); + + // Initialize device detection immediately + try + { + bool isDevice = await JS.InvokeAsync("isDevice"); + UpdateDeviceMode(isDevice); + } + catch { } + try { var currentTheme = await JS.InvokeAsync("mainLayout.initTheme"); @@ -288,10 +301,33 @@ } } + // JSInvokable: receives device mode and tablet status updates from JavaScript + [JSInvokable] + public void UpdateDeviceMode(bool isDevice) + { + SampleService.IsDevice = isDevice; + + // Update screen size based on device detection + var newSize = isDevice ? ScreenSize.Mobile : ScreenSize.Desktop; + + if (newSize != CurrentScreen) + { + CurrentScreen = newSize; + if (CurrentScreen == ScreenSize.Desktop) + { + OverlayLeftIsOpen = false; + } + InvokeAsync(StateHasChanged); + } + } + // JSInvokable: receives width and updates internal screen size state. [JSInvokable] public Task NotifyResize(int width) { + bool isDevice = width <= 640; + SampleService.IsDevice = isDevice; + // Determine new logical screen size var newSize = width <= 640 ? ScreenSize.Mobile : (width <= 1024 ? ScreenSize.Tablet : ScreenSize.Desktop); // Only trigger a render when the logical size changes to minimize re-renders diff --git a/samples/Blazor.Toolkit.Samples.Client/Layout/NavMenu.razor b/samples/Blazor.Toolkit.Samples.Client/Layout/NavMenu.razor index 17ff2db..9e21ad5 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Layout/NavMenu.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Layout/NavMenu.razor @@ -292,7 +292,7 @@ Selection and Highlight
  • - Animation + Animation
  • diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/AreaChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/AreaChart.razor index 9e27ff3..823268a 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/AreaChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/AreaChart.razor @@ -21,7 +21,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -242,7 +242,7 @@ - + @@ -330,7 +330,7 @@ - + @@ -405,7 +405,7 @@ - +
    @@ -490,7 +490,7 @@ - + @@ -544,7 +544,7 @@ - + @@ -611,7 +611,7 @@ - + @@ -708,7 +708,7 @@ - + @@ -777,7 +777,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/SplineAreaChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/SplineAreaChart.razor index 2917bd4..1db1df7 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/SplineAreaChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/SplineAreaChart.razor @@ -20,7 +20,7 @@ - + @@ -97,7 +97,7 @@ - + @@ -156,7 +156,7 @@ - +
    @@ -239,7 +239,7 @@ - +
    @@ -308,7 +308,7 @@ - + @@ -378,7 +378,7 @@ - + @@ -463,7 +463,7 @@ - + @@ -513,7 +513,7 @@ - +
    diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/StepAreaChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/StepAreaChart.razor index 34206c8..733094e 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/StepAreaChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AreaCharts/StepAreaChart.razor @@ -17,7 +17,7 @@ - + @@ -85,7 +85,7 @@ - + @@ -161,7 +161,7 @@ - + @@ -221,7 +221,7 @@ - + @@ -317,7 +317,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisCustomization.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisCustomization.razor index 8e0486a..1f32370 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisCustomization.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisCustomization.razor @@ -22,7 +22,7 @@ - + @@ -89,7 +89,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -218,7 +218,7 @@ - + @@ -286,7 +286,7 @@ - + @@ -349,7 +349,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisLabels.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisLabels.razor index 1a9480d..9bd793d 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisLabels.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/AxisLabels.razor @@ -24,7 +24,7 @@ - + @@ -136,7 +136,7 @@ - + @@ -201,7 +201,7 @@ - + @@ -283,7 +283,7 @@ - + @@ -370,7 +370,7 @@ - + @@ -438,7 +438,7 @@ - + @@ -503,7 +503,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/CategoryAxis.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/CategoryAxis.razor index 49c8626..b9f383e 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/CategoryAxis.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/CategoryAxis.razor @@ -26,7 +26,7 @@ - + @@ -89,7 +89,7 @@ - + @@ -182,7 +182,7 @@ - + @@ -247,7 +247,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/DateTimeAxis.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/DateTimeAxis.razor index 57ffc24..bc519c5 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/DateTimeAxis.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/DateTimeAxis.razor @@ -24,7 +24,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -285,7 +285,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/LogAxis.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/LogAxis.razor index 1134a03..5091651 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/LogAxis.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/LogAxis.razor @@ -22,7 +22,7 @@ - + @@ -88,7 +88,7 @@ - + @@ -152,7 +152,7 @@ - + @@ -218,7 +218,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/NumericAxis.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/NumericAxis.razor index 1c8d470..48685ef 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/NumericAxis.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/AxisConfiguration/NumericAxis.razor @@ -24,7 +24,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -171,7 +171,7 @@ - + @@ -282,7 +282,7 @@ - + @@ -349,7 +349,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/BubbleAndScatterCharts/ScatterChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/BubbleAndScatterCharts/ScatterChart.razor index 0430a5c..11d1ffc 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/BubbleAndScatterCharts/ScatterChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/BubbleAndScatterCharts/ScatterChart.razor @@ -14,7 +14,7 @@ - + @@ -47,7 +47,7 @@

    Data labels display the values of data points directly on the scatter Chart. They help users quickly understand exact values without relying on tooltips and automatically adjust to avoid overlapping, improving readability in analytical and reporting views. To display data labels, add the ChartDataLabel component inside the ChartMarker and set its Visible property to true.

    - + @@ -83,7 +83,7 @@

    The point shape in a Blazor Scatter Chart can be customized using marker shapes such as circle, diamond, rectangle, or triangle. Custom shapes help differentiate multiple series and improve visual clarity when comparing datasets in the same Chart. You can set the shape using the Shape property in the ChartMarker.

    - + @@ -161,7 +161,7 @@

    The scatter series can be customized using properties like fill color and opacity. These options help visually distinguish datasets, highlight trends, and align the Chart’s appearance with the application’s theme. Customize the series by setting properties like Fill and Opacity within the ChartSeries component.

    - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Annotation.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Annotation.razor index 53a7eca..723e2aa 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Annotation.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Annotation.razor @@ -18,7 +18,7 @@ - + - + - + - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/DataLabel.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/DataLabel.razor index 1edc961..01b7199 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/DataLabel.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/DataLabel.razor @@ -18,7 +18,7 @@ - + @@ -234,7 +234,7 @@ - + @@ -355,7 +355,7 @@ - + @@ -486,7 +486,7 @@ - + @@ -592,7 +592,7 @@ - + @@ -726,7 +726,7 @@ - + @@ -930,7 +930,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Legend.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Legend.razor index de7f296..4882f48 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Legend.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Legend.razor @@ -1,6 +1,8 @@ @page "/charts/legend" @using Syncfusion.Blazor.Toolkit.Charts @using ValueType = Syncfusion.Blazor.Toolkit.ValueType +@using Blazor.Toolkit.Samples.Client.Services +@inject SampleService SampleService Blazor Chart Legend Demo | Syncfusion Toolkit @@ -15,7 +17,7 @@ - + @@ -105,7 +107,7 @@ - + @@ -162,7 +164,7 @@ - + @@ -220,7 +222,7 @@ - + @@ -279,7 +281,7 @@ + Location="@LegendLocation"> @@ -298,7 +300,7 @@ - + @@ -367,7 +369,7 @@ - + @@ -440,7 +442,7 @@ - + @@ -504,7 +506,7 @@ - + @@ -589,7 +591,7 @@ - +
    @@ -681,7 +683,7 @@ - + @@ -756,7 +758,7 @@ - + @@ -801,13 +803,19 @@ [CascadingParameter] private Theme CurrentTheme { get; set; } = Theme.Fluent; + [CascadingParameter] + public bool IsDevice { get; set; } + private Theme _currentTheme = Theme.Fluent; private string _prevThemeName = string.Empty; + private ChartLocation LegendLocation; + protected override void OnInitialized() { _currentTheme = CurrentTheme; + LegendLocation = IsDevice ? new ChartLocation { X = 80, Y = 80} : new ChartLocation { X = 400, Y = 80}; } protected override void OnParametersSet() @@ -823,6 +831,8 @@ { _currentTheme = CurrentTheme; } + // Update legend location when IsDevice changes + LegendLocation = IsDevice ? new ChartLocation { X = 80, Y = 80} : new ChartLocation { X = 400, Y = 80}; } private bool IsDarkTheme => CurrentTheme.ToString().Contains("Dark") || CurrentTheme.ToString().Contains("HighContrast"); diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Marker.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Marker.razor index fd575fb..ac4afc9 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Marker.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Marker.razor @@ -17,7 +17,7 @@ - + @@ -192,7 +192,7 @@ - +
    @@ -383,7 +383,7 @@ - + @@ -517,7 +517,7 @@ - + @@ -681,7 +681,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Stripline.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Stripline.razor index a6bf126..5f318fc 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Stripline.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Stripline.razor @@ -26,7 +26,7 @@ - + @@ -86,7 +86,7 @@ - + @@ -177,7 +177,7 @@ - + @@ -548,7 +548,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Trendline.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Trendline.razor index 2559728..36b96ab 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Trendline.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ChartElements/Trendline.razor @@ -14,7 +14,7 @@ - + @@ -176,7 +176,7 @@ - + @@ -347,7 +347,7 @@ - + - + - + - + - + - + - + + + @@ -1395,7 +1397,9 @@ Height=""7"" Shape=""ChartShape.Circle"" Fill=""#7C4DFF""> - + + + @code { private Theme _currentTheme = Theme.Fluent; + private bool IsDarkTheme => _currentTheme.ToString().Contains(""Dark"") || _currentTheme.ToString().Contains(""HighContrast""); + private string TextColor => IsDarkTheme ? ""#E6EEF8"" : ""#0B1F3B""; public ListDataLabelData = new () { new () { Year = ""2015"", Sales = 0.55 }, @@ -1464,7 +1470,7 @@ - + - + @@ -79,7 +79,7 @@ - + @@ -156,7 +156,7 @@ - + @@ -215,7 +215,7 @@ - + @@ -280,7 +280,7 @@ - + @@ -361,7 +361,7 @@ - + @@ -425,7 +425,7 @@

    A grouped Bar Chart places bars next to each other for each category, making it easy to compare multiple series values directly without stacking. You can group series by using the GroupName property in ChartSeries.

    - + @@ -535,7 +535,7 @@ - + @@ -582,7 +582,7 @@ - + @@ -647,7 +647,7 @@

    Customizing bar spacing and width controls the gap and thickness of bars, improving readability and optimizing the visual balance of the chart layout. You can customize the bar spacing and width using the ColumnSpacing and ColumnWidth properties in ChartSeries.

    - +
    @@ -735,7 +735,7 @@ - +
    @@ -789,7 +789,7 @@ - + @@ -870,7 +870,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ColumnAndBarCharts/ColumnChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ColumnAndBarCharts/ColumnChart.razor index 34bf6b0..92d71d6 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ColumnAndBarCharts/ColumnChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/ColumnAndBarCharts/ColumnChart.razor @@ -15,7 +15,7 @@

    - + @@ -59,7 +59,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -133,7 +133,7 @@

    - + @@ -165,7 +165,7 @@ - + @@ -199,7 +199,7 @@ - + @@ -231,7 +231,7 @@ - + @@ -265,7 +265,7 @@

    - + @@ -293,7 +293,7 @@

    - +
    @@ -327,7 +327,7 @@

    - + @@ -371,7 +371,7 @@

    - + @@ -443,7 +443,7 @@

    - +

    @@ -471,7 +471,7 @@

    - + @@ -499,7 +499,7 @@

    - + @@ -528,7 +528,7 @@

    - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/Crosshair.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/Crosshair.razor index eb90160..c32af7d 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/Crosshair.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/Crosshair.razor @@ -16,7 +16,7 @@

    - + @@ -77,7 +77,7 @@

    - + @@ -139,7 +139,7 @@

    - + @@ -201,7 +201,7 @@

    - +
    @@ -262,7 +262,7 @@

    - + @@ -321,7 +321,7 @@

    - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/Tooltip.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/Tooltip.razor index 8a54d7e..85d55e3 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/Tooltip.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/Tooltip.razor @@ -14,7 +14,7 @@ - + @@ -76,7 +76,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -214,7 +214,7 @@ - + @@ -273,7 +273,7 @@ - + @@ -328,7 +328,7 @@

    - + @@ -427,7 +427,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/ZoomingAndPanning.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/ZoomingAndPanning.razor index c38c757..05aa1cd 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/ZoomingAndPanning.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/Interactivity/ZoomingAndPanning.razor @@ -16,7 +16,7 @@ - + @@ -56,7 +56,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -140,7 +140,7 @@ - + @@ -190,7 +190,7 @@

    - + @@ -270,7 +270,7 @@

    - + @@ -323,7 +323,7 @@

    - + @@ -372,7 +372,7 @@

    - +
    diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/LineChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/LineChart.razor index 5eb7c86..1b12734 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/LineChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/LineChart.razor @@ -20,7 +20,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -158,7 +158,7 @@ - + @@ -238,7 +238,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -360,7 +360,7 @@ - +
    @@ -432,7 +432,7 @@ - + @@ -473,7 +473,7 @@ - + @@ -537,7 +537,7 @@ - + @@ -620,7 +620,7 @@ - + @@ -680,7 +680,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SplineChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SplineChart.razor index 269156b..2029a9a 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SplineChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SplineChart.razor @@ -25,7 +25,7 @@ - + @@ -113,7 +113,7 @@ - + @@ -189,7 +189,7 @@ - + @@ -278,7 +278,7 @@ - + @@ -366,7 +366,7 @@ - + @@ -419,7 +419,7 @@ - + - + @@ -590,7 +590,7 @@ - + @@ -658,7 +658,7 @@ - + diff --git a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SteplineChart.razor b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SteplineChart.razor index a31cf11..b2b1bd7 100644 --- a/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SteplineChart.razor +++ b/samples/Blazor.Toolkit.Samples.Client/Pages/Components/Charts/LineCharts/SteplineChart.razor @@ -24,7 +24,7 @@ - + @@ -89,7 +89,7 @@ - + @@ -250,7 +250,7 @@ - + - + diff --git a/samples/Blazor.Toolkit.Samples.Client/wwwroot/device.js b/samples/Blazor.Toolkit.Samples.Client/wwwroot/device.js new file mode 100644 index 0000000..1d88483 --- /dev/null +++ b/samples/Blazor.Toolkit.Samples.Client/wwwroot/device.js @@ -0,0 +1,3 @@ +window.isDevice = function() { + return document.body.offsetWidth <= 640; +}; diff --git a/samples/Blazor.Toolkit.Samples/Components/App.razor b/samples/Blazor.Toolkit.Samples/Components/App.razor index 2fc7909..c1f36b2 100644 --- a/samples/Blazor.Toolkit.Samples/Components/App.razor +++ b/samples/Blazor.Toolkit.Samples/Components/App.razor @@ -57,6 +57,7 @@ + diff --git a/samples/Blazor.Toolkit.Samples/Program.cs b/samples/Blazor.Toolkit.Samples/Program.cs index 9ec58ab..de9dcb5 100644 --- a/samples/Blazor.Toolkit.Samples/Program.cs +++ b/samples/Blazor.Toolkit.Samples/Program.cs @@ -1,10 +1,10 @@ +using System.Globalization; using Blazor.Toolkit.Samples.Client.Services; using Blazor.Toolkit.Samples.Components; using Microsoft.AspNetCore.Localization; using Microsoft.Extensions.Localization; using Syncfusion.Blazor.Toolkit; using Syncfusion.Blazor.Toolkit.Popups; -using System.Globalization; var builder = WebApplication.CreateBuilder(args); @@ -26,6 +26,7 @@ }); builder.Services.AddScoped(); +builder.Services.AddScoped(); // Register RenderModeService for components that need to switch render mode builder.Services.AddScoped(); // Make HttpContext available to components during server prerender diff --git a/src/Components/Charts/Chart/Renderer/SeriesRenderers/DatalabelRenderer/DataLabelRenderer.cs b/src/Components/Charts/Chart/Renderer/SeriesRenderers/DatalabelRenderer/DataLabelRenderer.cs index 17e28db..2dfbaaf 100644 --- a/src/Components/Charts/Chart/Renderer/SeriesRenderers/DatalabelRenderer/DataLabelRenderer.cs +++ b/src/Components/Charts/Chart/Renderer/SeriesRenderers/DatalabelRenderer/DataLabelRenderer.cs @@ -327,9 +327,11 @@ private double CalculatePathActualPosition(double y, Rect rect, bool isminus, Ch bool isBottom = position == ChartLabelPosition.Bottom; ChartLabelPosition[] Test = [ChartLabelPosition.Outer, ChartLabelPosition.Top, ChartLabelPosition.Bottom, ChartLabelPosition.Middle, ChartLabelPosition.Auto]; int positionIndex = Array.IndexOf(Test, position); + string? originalFontBackground = _fontBackground; // capture "transparent" while (isOverLap && positionIndex < 4) { + _fontBackground = originalFontBackground; y_Location = CalculatePathPosition(y, rect, isminus, GetPosition(positionIndex), series, point, size, labelIndex); Rect labelRect = ChartHelper.CalculateRect(new ChartEventLocation(_locationX, y_Location), size, _margin); @@ -651,8 +653,8 @@ private void CreateDataLabelTemplate(ChartSeries series, ChartDataLabel dataLabe posY = (SeriesRenderer?.ClipRect?.Y ?? 0) + rect.Y; string left = Convert.ToString(posX, _culture) + "px"; string top = Convert.ToString(posY, _culture) + "px"; - Color rgbValue = Color.FromName(_fontBackground ?? string.Empty); - string color = string.IsNullOrEmpty(dataLabel.Font.Color) ? dataLabel.Font.Color : (Math.Round(Convert.ToDouble(((rgbValue.R * 299) + (rgbValue.G * 587) + (rgbValue.B * 114)) / 1000, _culture), 1) >= 128 ? "black" : "white"); + double templateContrast = CalculateLuminanceContrast(_fontBackground ?? string.Empty); + string color = string.IsNullOrEmpty(dataLabel.Font.Color) ? dataLabel.Font.Color : (templateContrast >= 128 ? "black" : "white"); bool isAnimation = ((series.Animation.Enable && SyncfusionService?._options.Animation == GlobalAnimationMode.Default) || (SyncfusionService?._options.Animation == GlobalAnimationMode.Enable)) && Owner is not null && Owner._shouldAnimateSeries; string visibility = !(pointTemplateSize.Count > 0) ? "hidden" : isAnimation ? "hidden" : "visible"; string id; @@ -1208,7 +1210,8 @@ private void RenderFinalTextLabel(Point point, int pointIndex, int labelIndex, R } /// - /// Calculates the luminance contrast ratio for a background color. + /// Calculates the luminance contrast ratio for a background color, accounting for + /// semi-transparent (rgba) colors by blending them with the chart background. /// /// The background color as a string (name, hex, or rgb). /// @@ -1217,10 +1220,50 @@ private void RenderFinalTextLabel(Point point, int pointIndex, int labelIndex, R /// private double CalculateLuminanceContrast(string backgroundColor) { - Color rgbValue = ChartHelper.GetRBGValue(backgroundColor); + string effectiveColor = GetEffectiveBackgroundColor(backgroundColor); + Color rgbValue = ChartHelper.GetRBGValue(effectiveColor); return Math.Round(Convert.ToDouble(((rgbValue.R * 299) + (rgbValue.G * 587) + (rgbValue.B * 114)) / 1000, _culture), 1); } + /// + /// Returns the effective opaque color for a background, blending semi-transparent + /// (rgba with alpha < 1) colors with the chart background to produce the actual + /// visible color the text will be rendered over. + /// + /// The background color string, possibly rgba. + /// + /// A hex color string representing the effective opaque color; non-rgba values are returned unchanged. + /// + private string GetEffectiveBackgroundColor(string backgroundColor) + { + if (string.IsNullOrEmpty(backgroundColor) || !backgroundColor.StartsWith("rgba", StringComparison.InvariantCulture)) + { + return backgroundColor ?? string.Empty; + } + + int left = backgroundColor.IndexOf('(', StringComparison.InvariantCulture); + int right = backgroundColor.IndexOf(')', StringComparison.InvariantCulture); + if (left < 0 || right < 0) + { + return backgroundColor; + } + + string[] parts = backgroundColor.Substring(left + 1, right - left - 1).Split(','); + if (parts.Length < 4 || !double.TryParse(parts[3].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double alpha) || alpha >= 1.0) + { + return backgroundColor; + } + + Color chartBg = ChartHelper.GetRBGValue(_chartBackground ?? "white"); + int r = int.Parse(parts[0], CultureInfo.InvariantCulture); + int g = int.Parse(parts[1], CultureInfo.InvariantCulture); + int b = int.Parse(parts[2], CultureInfo.InvariantCulture); + int effectiveR = (int)Math.Round((r * alpha) + (chartBg.R * (1 - alpha)), MidpointRounding.AwayFromZero); + int effectiveG = (int)Math.Round((g * alpha) + (chartBg.G * (1 - alpha)), MidpointRounding.AwayFromZero); + int effectiveB = (int)Math.Round((b * alpha) + (chartBg.B * (1 - alpha)), MidpointRounding.AwayFromZero); + return $"#{effectiveR:x2}{effectiveG:x2}{effectiveB:x2}"; + } + /// /// Calculates the final position and rotation parameters for a data label. /// diff --git a/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/BarSeriesRenderer.cs b/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/BarSeriesRenderer.cs index a5ae0a3..baa6c38 100644 --- a/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/BarSeriesRenderer.cs +++ b/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/BarSeriesRenderer.cs @@ -53,7 +53,7 @@ private void ProcessPoint(int index, DoubleRange sideBySideInfo, double origin, Point previousPoint = index - 1 > -1 ? Points[index - 1] : null!; Point nextPoint = index + 1 < Points.Count ? Points[index + 1] : null!; - if (pointBar.Visible && ChartHelper.WithInRange(previousPoint, pointBar, nextPoint, XAxisRenderer)) + if (pointBar.Visible && ChartHelper.WithInRange(previousPoint, pointBar, nextPoint, XAxisRenderer) && ChartHelper.IsCurrentPointWithinVisibleRange(pointBar, XAxisRenderer)) { Rect rect = GetRectangle(pointBar.XValue + sideBySideInfo.Start, pointBar.YValue, pointBar.XValue + sideBySideInfo.End, origin); rect = GetColumnWidthInPixelRect(rect); diff --git a/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/ColumnSeriesRenderer.cs b/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/ColumnSeriesRenderer.cs index cc7f4b3..0ed5784 100644 --- a/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/ColumnSeriesRenderer.cs +++ b/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/ColumnSeriesRenderer.cs @@ -35,7 +35,7 @@ private void CalculateColumnPathOption() Point previousPoint = i - 1 > -1 ? Points?[i - 1] ?? null! : null!; Point nextPoint = i + 1 < Points?.Count ? Points[i + 1] : null!; - if (point.Visible && ChartHelper.WithInRange(previousPoint, point, nextPoint, XAxisRenderer)) + if (point.Visible && ChartHelper.WithInRange(previousPoint, point, nextPoint, XAxisRenderer) && ChartHelper.IsCurrentPointWithinVisibleRange(point, XAxisRenderer)) { Rect rect = GetRectangle(point.XValue + sideBySideInfo.Start, point.YValue, point.XValue + sideBySideInfo.End, origin); if (rect is not null && rect.Width < 1) diff --git a/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/StackingBarSeriesRenderer.cs b/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/StackingBarSeriesRenderer.cs index dbd829d..601ac1e 100644 --- a/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/StackingBarSeriesRenderer.cs +++ b/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/StackingBarSeriesRenderer.cs @@ -123,7 +123,7 @@ internal void CalculateColumnPathOption() Point previousPoint = pointColumn.Index - 1 > -1 ? Points?[pointColumn.Index - 1] ?? null! : null!; Point nextPoint = pointColumn.Index + 1 < Points?.Count ? Points[pointColumn.Index + 1] : null!; - if (pointColumn.Visible && ChartHelper.WithInRange(previousPoint, pointColumn, nextPoint, Series?.Renderer.XAxisRenderer ?? null!) && Series?.Renderer.StackedValues is not null) + if (pointColumn.Visible && ChartHelper.WithInRange(previousPoint, pointColumn, nextPoint, Series?.Renderer.XAxisRenderer ?? null!) && ChartHelper.IsCurrentPointWithinVisibleRange(pointColumn, Series?.Renderer.XAxisRenderer ?? null!) && Series?.Renderer.StackedValues is not null) { double startValue = GetStackingStartValue(pointColumn.Index, GetVisibleSeriesIndex()); Rect rect = GetRectangle(pointColumn.XValue + sideBySideInfo.Start, (!Series.Visible && Series._isLegendClicked) ? startValue : Series.Renderer.StackedValues.EndValues[pointColumn.Index], pointColumn.XValue + sideBySideInfo.End, (!Series.Visible && Series._isLegendClicked) ? startValue : Series.Renderer.StackedValues.StartValues[pointColumn.Index]); diff --git a/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/StackingColumnSeriesRenderer.cs b/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/StackingColumnSeriesRenderer.cs index 89256fc..3d0705b 100644 --- a/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/StackingColumnSeriesRenderer.cs +++ b/src/Components/Charts/Chart/Renderer/SeriesRenderers/SeriesTypeRenderers/StackingColumnSeriesRenderer.cs @@ -120,7 +120,7 @@ internal void CalculateColumnPathOption() Point previousPoint = pointColumn.Index - 1 > -1 ? Points?[pointColumn.Index - 1] ?? null! : null!; Point nextPoint = pointColumn.Index + 1 < Points?.Count ? Points[pointColumn.Index + 1] : null!; - if (pointColumn.Visible && ChartHelper.WithInRange(previousPoint, pointColumn, nextPoint ?? null!, Series?.Renderer.XAxisRenderer ?? null!) && Series?.Renderer.StackedValues is not null) + if (pointColumn.Visible && ChartHelper.WithInRange(previousPoint, pointColumn, nextPoint ?? null!, Series?.Renderer.XAxisRenderer ?? null!) && ChartHelper.IsCurrentPointWithinVisibleRange(pointColumn, Series?.Renderer.XAxisRenderer ?? null!) && Series?.Renderer.StackedValues is not null) { double startValue = GetStackingStartValue(pointColumn.Index, GetVisibleSeriesIndex()); Rect rect = GetRectangle(pointColumn.XValue + sideBySideInfo.Start, (!Series.Visible && Series._isLegendClicked) ? startValue : Series.Renderer.StackedValues.EndValues[pointColumn.Index], pointColumn.XValue + sideBySideInfo.End, (!Series.Visible && Series._isLegendClicked) ? startValue : Series.Renderer.StackedValues.StartValues[pointColumn.Index]); diff --git a/src/Components/Charts/Common/ChartUtils/ChartHelper.cs b/src/Components/Charts/Common/ChartUtils/ChartHelper.cs index 7135fa0..9f099ed 100644 --- a/src/Components/Charts/Common/ChartUtils/ChartHelper.cs +++ b/src/Components/Charts/Common/ChartUtils/ChartHelper.cs @@ -1,12 +1,12 @@ +using System.Collections.ObjectModel; +using System.Drawing; using System.Dynamic; +using System.Globalization; using System.Text.Json; using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Components.Rendering; -using System.Drawing; -using System.Globalization; using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Rendering; using Syncfusion.Blazor.Toolkit.Internal; -using System.Collections.ObjectModel; namespace Syncfusion.Blazor.Toolkit.Charts.Internal { @@ -1002,6 +1002,51 @@ internal static bool WithInRange(Point previousPoint, Point currentPoint, Point || (nextX >= xStart && nextX <= xEnd) || (xStart >= previousX && xStart <= nextX); } + /// + /// Determines whether the supplied point's own X value lies within the visible range of the X-axis. + /// + /// + /// Unlike , which returns true when any + /// of the previous / current / next points is in range (correct for line/area edge interpolation), this + /// helper returns true only when the current point's own X value is within the visible axis range. + /// It is used by the column-family renderers (Column, Bar, StackingColumn, StackingBar) to avoid emitting + /// SVG path elements for off-range points whose column would otherwise clip outside the visible chart area + /// when Minimum/Maximum are configured. + /// + /// When the user has explicitly set and + /// (a fixed range — see ), the range padding logic still + /// expands outward by the between-ticks padding so that the + /// first/last visible categories are rendered with their full column width. That padding would otherwise + /// cause adjacent off-range points (e.g. the category just below Minimum or just above Maximum) to pass an + /// in-range check based on alone. To keep the DOM clean, when + /// the axis is a fixed range this helper checks against the user-configured Minimum/Maximum instead of the + /// padded visible range, so columns strictly outside [Minimum, Maximum] are never rendered. + /// + /// + /// The point whose own X value is being tested. + /// The X-axis renderer containing visible range information. + /// true only when the current point's own X value falls within the visible axis range; otherwise, false. + internal static bool IsCurrentPointWithinVisibleRange(Point currentPoint, ChartAxisRenderer xAxis) + { + double currentX = xAxis.GetPointValue(currentPoint.XValue); + double xStart, xEnd; + + if (xAxis.IsFixedRange()) + { + // The user has explicitly restricted the visible categories via Minimum/Maximum. Use those exact + // bounds (not the padded VisibleRange) so off-range adjacent points stay out of the DOM. + xStart = Math.Floor(Convert.ToDouble(xAxis.Axis?.Minimum, null)); + xEnd = Math.Ceiling(Convert.ToDouble(xAxis.Axis?.Maximum, null)); + } + else + { + xStart = Math.Floor(xAxis.VisibleRange.Start); + xEnd = Math.Ceiling(xAxis.VisibleRange.End); + } + + return currentX >= xStart && currentX <= xEnd; + } + /// /// Appends path animation elements to the chart's animation collection. /// diff --git a/src/wwwroot/scripts/chart.js b/src/wwwroot/scripts/chart.js index ec8f440..dd4e0c4 100644 --- a/src/wwwroot/scripts/chart.js +++ b/src/wwwroot/scripts/chart.js @@ -852,6 +852,10 @@ const SfChart = (function () { else if (chart.toggleVisibility && chart.enableHighlight) { chart.isLegendHighlighting = false; chart.prevHighlightedSeriesIndex = -1; + const elements = Array.from(document.getElementsByClassName(chart.unSelected)); + elements.forEach(element => { + removeSvgClass(element, element.getAttribute('class')); + }); storeToggledLegendIndexes(target, chart, e); } } @@ -1136,7 +1140,8 @@ const SfChart = (function () { let currentPoint = e.target; targetElement.removeAttribute('tabindex'); targetElement.blur(); - if (e.code === 'ArrowRight' || e.code === 'ArrowLeft') { + const seriesCollection = document.getElementById(this.element.id + 'SeriesCollection').querySelectorAll('[id*="SeriesGroup"]'); + if ((e.code === 'ArrowRight' || e.code === 'ArrowLeft') && seriesCollection.length > 1) { const seriesIndexes = []; for (let i = 0; i < groupElement.children.length; i++) { if (groupElement.children[parseInt(i.toString(), 10)].id.indexOf('SeriesGroup') > -1) { @@ -1179,7 +1184,7 @@ const SfChart = (function () { } } else { - this.currentPointIndex += e.code === 'ArrowUp' ? 1 : -1; + this.currentPointIndex += e.code === 'ArrowUp' ? 1 : (e.code === 'ArrowDown' ? -1 : 0); pointIndex = parseInt(targetId.split('_Series_')[1].replace('_Symbol', '').split('_Point_')[1], 10); currentSeries = getCurrentSeries(this, targetId, this.currentSeriesIndex); groupElement = getElement(this.element.id + (targetId.indexOf('_TrendLine_') > -1 ? 'TrendLineSeriesGroup' : 'SeriesGroup') + this.currentSeriesIndex); @@ -1269,7 +1274,7 @@ const SfChart = (function () { removeElement(this.element.id + '_Series_' + parseInt(this.seriesPathElement.id.split('_Series_')[1].split('_PointIndex_')[0], 10) + '_Point_' + parseInt(this.seriesPathElement.id.split('_Series_')[1].replace('_Symbol', '').split('_PointIndex_')[1], 10) + '_Trackball_1'); this.seriesPathElement = null; } - if (currentSeries.points[parseInt(pointIndex.toString(), 10)]) { + if (currentSeries.points[parseInt(pointIndex.toString(), 10)] && (e.code == 'ArrowUp' || e.code == 'ArrowDown') ) { this.seriesPathElement = this.userInteractionBase.svgRenderer.drawPath({ 'id': targetId, 'stroke-width': 2, @@ -1317,9 +1322,11 @@ const SfChart = (function () { } }); } - tooltipMousemovehandler(this); + if (currentSeries.enableTooltip) { + tooltipMousemovehandler(this); + } crosshairMousemoveHandler(this); - if (this.markerExplodeBase.markerExploded) { + if (this.markerExplodeBase.markerExploded && currentSeries.marker.vS) { markerMove(this, false); } } @@ -3999,7 +4006,7 @@ export function getData(chart) { mouseY = series.y_Axis.isAxisInverse ? mouseY - markerHeight : mouseY + markerHeight; } } - if (series.visible && !sfBlazorToolkit.base.isNullOrUndefined(series.clipRect) && svgbase.withInAreaBounds(mouseX, mouseY, new svgbase.Rect(series.clipRect.x - (!series.chartIsTransposed ? series.x_Axis.plotOffset / 2 : 0), series.clipRect.y - (series.chartIsTransposed ? series.x_Axis.plotOffset / 2 : 0), series.clipRect.w, series.clipRect.h), width, height)) { + if (series.visible && (!chart.isChartKeyDown || series.index === chart.currentSeriesIndex) && !sfBlazorToolkit.base.isNullOrUndefined(series.clipRect) && svgbase.withInAreaBounds(mouseX, mouseY, new svgbase.Rect(series.clipRect.x - (!series.chartIsTransposed ? series.x_Axis.plotOffset / 2 : 0), series.clipRect.y - (series.chartIsTransposed ? series.x_Axis.plotOffset / 2 : 0), series.clipRect.w, series.clipRect.h), width, height)) { point = getRectPoint(series, series.clipRect, mouseX, mouseY, chart); } if (point) {