diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChartDocumentation.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChartDocumentation.razor
index 441b7f087..e7896311b 100644
--- a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChartDocumentation.razor
+++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChartDocumentation.razor
@@ -54,6 +54,9 @@
+
+
+
@code {
private const string pageUrl = RouteConstants.Demos_LineChart_Documentation;
private const string pageTitle = "Blazor Line Chart";
diff --git a/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_08_Plugins.razor b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_08_Plugins.razor
new file mode 100644
index 000000000..6bb9bf85b
--- /dev/null
+++ b/BlazorBootstrap.Demo.RCL/Components/Pages/Charts/LineCharts/LineChart_Demo_08_Plugins.razor
@@ -0,0 +1,203 @@
+@using System.Text.Json.Serialization
+
+
+
+This line chart has the Zoom (built-in), Annotations (built-in), DragData (locally defined) and Crosshair (anonymous) plugins enabled.
+
+
+
+
+
+
+@code {
+ private LineChart lineChart = default!;
+ private LineChartOptions lineChartOptions = default!;
+ private ChartData chartData = default!;
+
+ protected override void OnInitialized()
+ {
+ var colors = ColorUtility.CategoricalTwelveColors;
+ var labels = new List { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
+ var datasets = new List();
+
+ var dataset1 = new LineChartDataset
+ {
+ Label = "Windows",
+ Data = new List { 7265791, 5899643, 6317759, 6315641, 5338211, 8496306, 7568556, 8538933, 8274297, 8657298, 7548388, 7764845 },
+ BorderWidth = 2,
+ HoverBorderWidth = 4,
+ BackgroundColor = colors[ 0 ],
+ BorderColor = colors[ 0 ],
+ };
+ datasets.Add( dataset1 );
+
+ var dataset2 = new LineChartDataset
+ {
+ Label = "macOS",
+ Data = new List { 1809499, 1816642, 2122410, 1809499, 1850793, 1846743, 1954797, 2391313, 1983430, 2469918, 2633303, 2821149 },
+ BorderWidth = 2,
+ HoverBorderWidth = 4,
+ BackgroundColor = colors[ 1 ],
+ BorderColor = colors[ 1 ],
+ };
+ datasets.Add( dataset2 );
+
+ var dataset3 = new LineChartDataset
+ {
+ Label = "Other",
+ Data = new List { 1081241, 1100363, 1118136, 1073255, 1120315, 1395736, 1488788, 1489466, 1489947, 1414739, 1735811, 1820171 },
+ BorderWidth = 2,
+ HoverBorderWidth = 4,
+ BackgroundColor = colors[ 2 ],
+ BorderColor = colors[ 2 ],
+ };
+ datasets.Add( dataset3 );
+
+ chartData = new ChartData { Labels = labels, Datasets = datasets };
+
+ lineChartOptions = new();
+ lineChartOptions.Responsive = true;
+ lineChartOptions.Interaction = new Interaction { Mode = InteractionMode.Index };
+
+ lineChartOptions.Scales.X!.Title = new ChartAxesTitle { Text = "2019", Display = true };
+ lineChartOptions.Scales.Y!.Title = new ChartAxesTitle { Text = "Visitors", Display = true };
+
+ lineChartOptions.Plugins.Title!.Text = "Operating system";
+ lineChartOptions.Plugins.Title.Display = true;
+
+ EnableDragDataPlugin();
+ EnableZoomPlugin();
+ EnableAnnotationsPlugin();
+ EnableCrosshairsPlugin();
+ }
+
+ [JsonSourceGenerationOptions( DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase )]
+ public class DragDataPlugin : ChartPlugin
+ {
+ public bool? DragX { get; set; }
+ public bool? DragY { get; set; }
+ public bool? ShowTooltip { get; set; }
+ }
+
+ private void EnableDragDataPlugin()
+ {
+ // Example of a plugin class deriving from ChartPlugin that is defined locally
+ lineChartOptions.Plugins.Add( "dragData", new DragDataPlugin() { DragX = true, ShowTooltip = false } );
+
+ // Alternative way to access the plugin:
+ var plugin = lineChartOptions.Plugins.Get();
+ plugin.ShowTooltip = true;
+ }
+
+ private void EnableAnnotationsPlugin()
+ {
+ // Example of the built-in Annotation plugin class.
+ var annotations = new ChartPluginsAnnotation()
+ {
+ Annotations = new List()
+ };
+
+ foreach( LineChartDataset dataset in chartData.Datasets )
+ {
+ var average = dataset.Data.Average();
+ annotations.Annotations.Add( new LineAnnotation()
+ {
+ BorderColor = dataset.BorderColor,
+ BorderDash = [ 2, 2 ],
+ YMin = average,
+ YMax = average
+ } );
+ }
+
+ annotations.Annotations.Add( new BoxAnnotation()
+ {
+ XMin = 3.5,
+ XMax = 8.75,
+ YMin = 1250000,
+ YMax = 4750000,
+ BorderWidth = 2,
+ BorderColor = "gray",
+ BorderDash = [ 1, 1 ],
+ BackgroundColor = "rgba(255, 255, 0, 0.1)",
+ ShadowOffsetX = 5,
+ ShadowOffsetY = 5
+ } );
+
+ lineChartOptions.Plugins.Add( "annotation", annotations );
+ }
+
+ private void EnableZoomPlugin()
+ {
+ // Example of the built-in Zoom plugin class.
+ var zoom = new ChartPluginsZoom()
+ {
+ Zoom = new()
+ {
+ Wheel = new()
+ {
+ Enabled = true
+ },
+ Pinch = new()
+ {
+ Enabled = true
+ },
+ Mode = ZoomMode.Y,
+ ScaleMode = ZoomMode.XY,
+ },
+ Pan = new()
+ {
+ Enabled = true,
+ Mode = ZoomMode.XY
+ },
+ Limits = new()
+ {
+ X = new() { MinimumIsOriginal = true, MaximumIsOriginal = true, MinRange = 1.0 },
+ Y = new() { MinimumIsOriginal = true, MaximumIsOriginal = true, MinRange = 1.0 }
+ }
+ };
+
+ lineChartOptions.Plugins.Add( "zoom", zoom );
+ }
+
+ private void EnableCrosshairsPlugin()
+ {
+ // Example of an anonymous plugin class, i.e. one that does not derive from ChartPlugin.
+ // Note that you cannot .Get() or .TryGet() it later.
+ // Demo configuration taken directly from https://github.com/abelheinsbroek/chartjs-plugin-crosshair
+ var crossHairs = new
+ {
+ line = new
+ {
+ color = "#F66",
+ width = 1,
+ },
+ sync = new
+ {
+ enabled = true,
+ group = 1,
+ suppressTooltips = false
+ },
+ zoom = new
+ {
+ enabled = true,
+ zoomboxBackgroundColor = "rgba(66,133,244,0.2)",
+ zoomboxBorderColor = "#48F",
+ zoomButtonText = "Reset Zoom",
+ zoomButtonClass = "reset-zoom",
+ }
+ };
+
+ lineChartOptions.Plugins.AddObject( "crosshairs", crossHairs );
+ }
+
+
+ protected override async Task OnAfterRenderAsync( bool firstRender )
+ {
+ if( firstRender )
+ {
+ await lineChart.InitializeAsync( chartData, lineChartOptions );
+ }
+ await base.OnAfterRenderAsync( firstRender );
+ }
+
+}
\ No newline at end of file
diff --git a/blazorbootstrap/Enums/DrawTime.cs b/blazorbootstrap/Enums/DrawTime.cs
new file mode 100644
index 000000000..cfcd6b05b
--- /dev/null
+++ b/blazorbootstrap/Enums/DrawTime.cs
@@ -0,0 +1,24 @@
+namespace BlazorBootstrap;
+
+public enum DrawTime
+{
+ ///
+ /// Occurs before any drawing takes place
+ ///
+ BeforeDraw,
+
+ ///
+ /// Occurs after drawing of axes, but before datasets
+ ///
+ BeforeDatasetsDraw,
+
+ ///
+ /// Occurs after drawing of datasets but before items such as the tooltip
+ ///
+ AfterDatasetsDraw,
+
+ ///
+ /// After other drawing is completed.
+ ///
+ AfterDraw
+}
diff --git a/blazorbootstrap/Enums/PointStyle.cs b/blazorbootstrap/Enums/PointStyle.cs
new file mode 100644
index 000000000..f64a9a773
--- /dev/null
+++ b/blazorbootstrap/Enums/PointStyle.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BlazorBootstrap;
+
+public enum PointStyle
+{
+ Circle,
+ Cross,
+ CrossRot,
+ Dash,
+ Line,
+ Rect,
+ RectRounded,
+ RectRot,
+ Star,
+ Triangle
+}
diff --git a/blazorbootstrap/Models/Charts/ChartPlugins/ChartPlugins.Annotations.cs b/blazorbootstrap/Models/Charts/ChartPlugins/ChartPlugins.Annotations.cs
new file mode 100644
index 000000000..6f6fca420
--- /dev/null
+++ b/blazorbootstrap/Models/Charts/ChartPlugins/ChartPlugins.Annotations.cs
@@ -0,0 +1,671 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BlazorBootstrap;
+
+public abstract class Annotation
+{
+ ///
+ /// The type of the annotation
+ ///
+ public abstract string Type { get; }
+
+ ///
+ /// TRUE
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public bool? AdjustScaleRange { get; set; }
+ ///
+ /// options.color
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BackgroundColor { get; set; }
+ ///
+ /// options.color
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderColor { get; set; }
+ ///
+ /// []
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public List? BorderDash { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderDashOffset { get; set; }
+ ///
+ /// 'transparent'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderShadowColor { get; set; }
+ ///
+ /// TRUE
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public bool? Display { get; set; }
+ ///
+ /// 'afterDatasetsDraw'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public DrawTime? DrawTime { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public bool? Init { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? Id { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? ShadowBlur { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? ShadowOffsetX { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? ShadowOffsetY { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? XMax { get; set; }
+
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? XMin { get; set; }
+
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? XScaleID { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? YMin { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? YMax { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? YScaleID { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Z { get; set; }
+
+}
+
+public class LineAnnotation : Annotation
+{
+ public override string Type => "line";
+
+ ///
+ /// The border width, defaults to 2.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderWidth { get; set; }
+
+ ///
+ /// Whether or not a quadratic Bézier curve is drawn.
+ /// Defaults to
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public bool? Curve { get; set; }
+
+ ///
+ /// End two of the line when a single scale is specified.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? EndValue { get; set; }
+
+ ///
+ /// Defines options for the line annotation label.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public ChartAnnotationLabel? Label { get; set; }
+
+ ///
+ /// ID of the scale in single scale mode. If unset, xScaleID and yScaleID are used.
+ /// If scaleID is set, then value and endValue must also be set to indicate the endpoints of the line. The
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? ScaleID { get; set; }
+
+ ///
+ /// End one of the line when a single scale is specified.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Value { get; set; }
+
+ ///
+ /// If curve is enabled, it configures the control point to drawn the curve, calculated in pixels.
+ /// It can be set by a string in percentage format 'number%' which are representing the percentage of the distance between the start and end point from the center.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? ControlPoint { get; set; }
+
+}
+
+public class ChartAnnotationLabel
+{
+ ///
+ /// Background color of the label container.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string BackgroundColor { get; set; }
+
+ ///
+ /// The color of shadow of the box where the label is located. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string BackgroundShadowColor { get; set; }
+
+ ///
+ /// Cap style of the border.
+ /// Supported values are 'butt', 'round', and 'square'.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderCapStyle { get; set; }
+
+ ///
+ /// The border line color.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderColor { get; set; }
+
+ ///
+ /// Length and spacing of dashes. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public List? BorderDash { get; set; }
+
+ ///
+ /// Offset for border line dashes. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderDashOffset { get; set; }
+
+ ///
+ /// Border line join style. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderJoinStyle { get; set; }
+
+ ///
+ /// Radius of label box corners in pixels.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderRadius { get; set; }
+
+ ///
+ /// The color of border shadow of the box where the label is located. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderShadowColor { get; set; }
+
+ ///
+ /// The border line width (in pixels).
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderWidth { get; set; }
+
+ ///
+ /// Text color.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public List? Color { get; set; }
+
+ ///
+ /// The content to show in the label
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string Content { get; set; }
+
+ ///
+ /// Whether or not the label is shown.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public bool? Display { get; set; }
+
+ ///
+ /// See drawTime. Defaults to the line annotation draw time if unset.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public DrawTime? DrawTime { get; set; }
+
+ ///
+ /// Label font.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? Font { get; set; }
+
+ ///
+ /// Overrides the height of the image or canvas element. Could be set in pixel by a number, or in percentage of current height of image or canvas element by a string. If undefined, uses the height of the image or canvas element. It is used only when the content is an image or canvas element.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? Height { get; set; }
+
+ ///
+ /// Overrides the opacity of the image or canvas element. Could be set a number in the range 0.0 to 1.0, inclusive. If undefined, uses the opacity of the image or canvas element. It is used only when the content is an image or canvas element.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Opacity { get; set; }
+
+ ///
+ /// The padding to add around the text label.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? Padding { get; set; }
+
+ ///
+ /// Anchor position of label on line. Possible options are: 'start', 'center', 'end'. It can be set by a string in percentage format 'number%' which are representing the percentage on the width of the line where the label will be located.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public Alignment? Position { get; set; }
+
+ ///
+ /// Rotation of label, in degrees, or 'auto' to use the degrees of the line.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Rotation { get; set; }
+
+ ///
+ /// The amount of blur applied to shadow of the box where the label is located. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? ShadowBlur { get; set; }
+
+ ///
+ /// The distance that shadow, of the box where the label is located, will be offset horizontally. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? ShadowOffsetX { get; set; }
+
+ ///
+ /// The distance that shadow, of the box where the label is located, will be offset vertically. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? ShadowOffsetY { get; set; }
+
+ ///
+ /// Text alignment of label content when there's more than one line. Possible options are: 'start', 'center', 'end'.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public TitleAlignment? TextAlign { get; set; }
+
+ ///
+ /// The color of the stroke around the text.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? TextStrokeColor { get; set; }
+
+ ///
+ /// Stroke width around the text.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? TextStrokeWidth { get; set; }
+
+ ///
+ /// Overrides the width of the image or canvas element. Could be set in pixel by a number, or in percentage of current width of image or canvas element by a string. If undefined, uses the width of the image or canvas element. It is used only when the content is an image or canvas element.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? Width { get; set; }
+
+ ///
+ /// Adjustment along x-axis (left-right) of label relative to computed position. Negative values move the label left, positive right.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? XAdjust { get; set; }
+
+ ///
+ /// Adjustment along y-axis (top-bottom) of label relative to computed position. Negative values move the label up, positive down.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? YAdjust { get; set; }
+
+ ///
+ /// It determines the drawing stack level of the label element, with same drawTime.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Z { get; set; }
+
+
+}
+
+public class BoxAnnotation : Annotation
+{
+ public override string Type => "box";
+
+ ///
+ /// 'transparent'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BackgroundShadowColor { get; set; }
+ ///
+ /// 'butt'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderCapStyle { get; set; }
+ ///
+ /// 'miter'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderJoinStyle { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? BorderRadius { get; set; }
+ ///
+ /// 1
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderWidth { get; set; }
+ ///
+ ///
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public ChartAnnotationLabel? Label { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Rotation { get; set; }
+}
+
+
+public class EllipseAnnotation : Annotation
+{
+ public override string Type => "ellipse";
+
+ ///
+ /// 'transparent'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BackgroundShadowColor { get; set; }
+ ///
+ /// 1
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderWidth { get; set; }
+ ///
+ ///
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public ChartAnnotationLabel? label { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Rotation { get; set; }
+}
+
+public class LabelAnnotation : Annotation
+{
+ public override string Type => "label";
+
+ ///
+ /// The color of shadow of the box where the label is located. See MDN
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string BackgroundShadowColor { get; set; }
+
+ ///
+ /// Cap style of the border.
+ /// Supported values are 'butt', 'round', and 'square'.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderCapStyle { get; set; }
+
+ ///
+ /// 'miter'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderJoinStyle { get; set; }
+
+ ///
+ /// Radius of label box corners in pixels.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderRadius { get; set; }
+
+ ///
+ /// The border line width (in pixels).
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderWidth { get; set; }
+
+ ///
+ /// Text color.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public List? Color { get; set; }
+
+ ///
+ /// The content to show in the label
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string Content { get; set; }
+
+ ///
+ /// Label font.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? Font { get; set; }
+
+ ///
+ /// Overrides the height of the image or canvas element. Could be set in pixel by a number, or in percentage of current height of image or canvas element by a string. If undefined, uses the height of the image or canvas element. It is used only when the content is an image or canvas element.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? Height { get; set; }
+
+ ///
+ /// Overrides the opacity of the image or canvas element. Could be set a number in the range 0.0 to 1.0, inclusive. If undefined, uses the opacity of the image or canvas element. It is used only when the content is an image or canvas element.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Opacity { get; set; }
+
+ ///
+ /// The padding to add around the text label.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? Padding { get; set; }
+
+ ///
+ /// Anchor position of label on line. Possible options are: 'start', 'center', 'end'. It can be set by a string in percentage format 'number%' which are representing the percentage on the width of the line where the label will be located.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public Alignment? Position { get; set; }
+
+ ///
+ /// Rotation of label, in degrees, or 'auto' to use the degrees of the line.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Rotation { get; set; }
+
+ ///
+ /// Text alignment of label content when there's more than one line. Possible options are: 'start', 'center', 'end'.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public TitleAlignment? TextAlign { get; set; }
+
+ ///
+ /// The color of the stroke around the text.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? TextStrokeColor { get; set; }
+
+ ///
+ /// Stroke width around the text.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? TextStrokeWidth { get; set; }
+
+ ///
+ /// Overrides the width of the image or canvas element. Could be set in pixel by a number, or in percentage of current width of image or canvas element by a string. If undefined, uses the width of the image or canvas element. It is used only when the content is an image or canvas element.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? Width { get; set; }
+
+ ///
+ /// Adjustment along x-axis (left-right) of label relative to computed position. Negative values move the label left, positive right.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? XAdjust { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? XValue { get; set; }
+
+ ///
+ /// Adjustment along y-axis (top-bottom) of label relative to computed position. Negative values move the label up, positive down.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? YAdjust { get; set; }
+
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? YValue { get; set; }
+}
+
+
+public class PointAnnotation : Annotation
+{
+ public override string Type => "point";
+
+ ///
+ /// 'transparent'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BackgroundShadowColor { get; set; }
+ ///
+ /// 1
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderWidth { get; set; }
+ ///
+ /// 'circle'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public PointStyle? PointStyle { get; set; }
+ ///
+ /// 10
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Radius { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Rotation { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? XAdjust { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? XValue { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? YAdjust { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? YValue { get; set; }
+}
+
+public class PolygonAnnotation : Annotation
+{
+ public override string Type => "polygon";
+
+ ///
+ /// 'transparent'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BackgroundShadowColor { get; set; }
+ ///
+ /// 'butt'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderCapStyle { get; set; }
+ ///
+ /// 'miter'
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderJoinStyle { get; set; }
+ ///
+ /// 1
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderWidth { get; set; }
+ ///
+ /// {radius: 0}
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public PointAnnotation? Point { get; set; }
+ ///
+ /// 10
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Radius { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Rotation { get; set; }
+ ///
+ /// 3
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Sides { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? XAdjust { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? XValue { get; set; }
+ ///
+ /// 0
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? YAdjust { get; set; }
+ ///
+ /// undefined
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public object? YValue { get; set; }
+
+}
+
diff --git a/blazorbootstrap/Models/Charts/ChartPlugins/ChartPlugins.Zoom.cs b/blazorbootstrap/Models/Charts/ChartPlugins/ChartPlugins.Zoom.cs
new file mode 100644
index 000000000..0726e07cd
--- /dev/null
+++ b/blazorbootstrap/Models/Charts/ChartPlugins/ChartPlugins.Zoom.cs
@@ -0,0 +1,272 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BlazorBootstrap;
+
+public enum ZoomMode
+{
+ None,
+ X,
+ Y,
+ XY
+}
+
+public enum ModifierKey
+{
+ None,
+ Ctrl,
+ Alt,
+ Shift,
+ Meta
+}
+
+public class ZoomLimitAxisOptions
+{
+ ///
+ /// Minimum allowed value for scale.min
+ ///
+ [JsonIgnore]
+ public double? Min { get; set; }
+
+ [JsonIgnore]
+ public bool? MinimumIsOriginal { get; set; }
+
+ [JsonInclude]
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonPropertyName( "min" )]
+ private string? minText => MinimumIsOriginal.GetValueOrDefault() ? "original" : Min?.ToString();
+
+ ///
+ /// Maximum allowed value for scale.max
+ ///
+ [JsonIgnore]
+ public double? Max { get; set; }
+
+ [JsonIgnore]
+ public bool? MaximumIsOriginal { get; set; }
+
+ [JsonInclude]
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonPropertyName( "max" )]
+ private string? maxText => MaximumIsOriginal.GetValueOrDefault() ? "original" : Max?.ToString();
+
+ ///
+ /// Minimum allowed range (max - min). This defines the max zoom level.
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonPropertyName( "minRange" )]
+ public double? MinRange { get; set; }
+}
+
+public class DragOptions
+{
+ ///
+ /// Enable drag-to-zoom
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public bool? Enabled { get; set; }
+
+ ///
+ /// Fill color
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BackgroundColor { get; set; }
+
+ ///
+ /// Stroke color
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public string? BorderColor { get; set; }
+
+ ///
+ /// Stroke width
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? BorderWidth { get; set; }
+
+ ///
+ /// When the dragging box is dran on the chart
+ ///
+ [JsonIgnore]
+ public DrawTime? DrawTime { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "drawTime" )]
+ private string? DrawTimeText => DrawTime?.ToString().ToLower();
+
+ ///
+ /// Minimal zoom distance required before actually applying zoom
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Threshold { get; set; }
+
+ ///
+ /// Modifier key required for drag-to-zoom
+ ///
+ [JsonIgnore]
+ public ModifierKey? ModifierKey { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "modifierKey" )]
+ private string? ModifierKeyText => ( ModifierKey == BlazorBootstrap.ModifierKey.None ) ? string.Empty : ModifierKey?.ToString().ToLower();
+}
+
+public class PinchOptions
+{
+ ///
+ /// /// Enable zooming via pinch gesture
+ /// ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public bool? Enabled { get; set; }
+}
+
+public class PanOptions
+{///
+ /// Enable panning
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public bool? Enabled { get; set; }
+
+ ///
+ /// Allowed panning directions
+ ///
+ [JsonIgnore]
+ public ZoomMode? Mode { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "mode" )]
+ private string? ModeText => ( Mode == ZoomMode.None ) ? string.Empty : Mode?.ToString().ToLower();
+
+ ///
+ /// Modifier key required for panning with mouse
+ ///
+ [JsonIgnore]
+ public ModifierKey? ModifierKey { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "modifierKey" )]
+ private string? ModifierKeyText => ( ModifierKey == BlazorBootstrap.ModifierKey.None ) ? string.Empty : ModifierKey?.ToString().ToLower();
+
+ ///
+ /// Enable panning over a scale for that axis (regardless of mode)
+ ///
+ [JsonIgnore]
+ public ZoomMode? ScaleMode { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "scaleMode" )]
+ private string? ScaleModeText => ( ScaleMode == ZoomMode.None ) ? string.Empty : ScaleMode?.ToString().ToLower();
+
+ ///
+ /// Enable panning over a scale for that axis (but only if mode is also enabled), and disables panning along that axis otherwise. Deprecated.
+ ///
+ [JsonIgnore]
+ public ZoomMode? OverScaleMode { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "overScaleMode" )]
+ private string? OverScaleModeText => ( OverScaleMode == ZoomMode.None ) ? string.Empty : OverScaleMode?.ToString().ToLower();
+
+ ///
+ /// Minimal pan distance required before actually applying pan
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public double? Threshold { get; set; }
+}
+
+public class ZoomLimitOptions
+{
+ public ZoomLimitAxisOptions X { get; set; } = new();
+ public ZoomLimitAxisOptions Y { get; set; } = new();
+
+}
+
+public class ZoomOptions
+{
+ ///
+ /// Options of the mouse wheel behavior
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public WheelOptions? Wheel { get; set; }
+
+ ///
+ /// Options of the drag-to-zoom behavior
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public DragOptions? Drag { get; set; }
+
+ ///
+ /// Options of the pinch behavior
+ ///
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ public PinchOptions? Pinch { get; set; }
+
+ ///
+ /// Allowed zoom directions
+ ///
+ [JsonIgnore]
+ public ZoomMode? Mode { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "mode" )]
+ private string? ModeText => ( Mode == ZoomMode.None ) ? string.Empty : Mode?.ToString().ToLower();
+
+ ///
+ /// Which of the enabled zooming directions should only be available when the mouse cursor is over a scale for that axis
+ ///
+ [JsonIgnore]
+ public ZoomMode? ScaleMode { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "scaleMode" )]
+ private string? ScaleModeText => ( ScaleMode == ZoomMode.None ) ? string.Empty : ScaleMode?.ToString().ToLower();
+
+ ///
+ /// Allowed zoom directions when the mouse cursor is over a scale for that axis (but only if mode is also enabled), and disables zooming along that axis otherwise. Deprecated; use scaleMode instead.
+ ///
+ [JsonIgnore]
+ public ZoomMode? OverScaleMode { get; set; }
+
+ [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
+ [JsonInclude]
+ [JsonPropertyName( "overScaleMode" )]
+ private string? OverScaleModeText => ( OverScaleMode == ZoomMode.None ) ? string.Empty : OverScaleMode?.ToString().ToLower();
+
+}
+
+public class WheelOptions
+{
+ ///