@orchidsoftware/charts 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/LICENSE +21 -0
  3. package/README.md +122 -0
  4. package/dist/core/Chart.js +1 -0
  5. package/dist/core/Chart.js.map +1 -0
  6. package/dist/core/ChartData.js +1 -0
  7. package/dist/core/ChartData.js.map +1 -0
  8. package/dist/core/ChartDefinition.js +1 -0
  9. package/dist/core/ChartDefinition.js.map +1 -0
  10. package/dist/core/ChartSelection.js +1 -0
  11. package/dist/core/ChartSelection.js.map +1 -0
  12. package/dist/core/ChartTooltip.js +1 -0
  13. package/dist/core/ChartTooltip.js.map +1 -0
  14. package/dist/core/InteractionController.js +1 -0
  15. package/dist/core/InteractionController.js.map +1 -0
  16. package/dist/core/NormalizeAnnotations.js +1 -0
  17. package/dist/core/NormalizeAnnotations.js.map +1 -0
  18. package/dist/core/Options.js +1 -0
  19. package/dist/core/Options.js.map +1 -0
  20. package/dist/core/builders/Builder.js +1 -0
  21. package/dist/core/builders/Builder.js.map +1 -0
  22. package/dist/core/builders/BuilderArguments.js +1 -0
  23. package/dist/core/builders/BuilderArguments.js.map +1 -0
  24. package/dist/core/builders/BuilderScopes.js +1 -0
  25. package/dist/core/builders/BuilderScopes.js.map +1 -0
  26. package/dist/core/builders/BuilderState.js +1 -0
  27. package/dist/core/builders/BuilderState.js.map +1 -0
  28. package/dist/core/builders/BuilderValidation.js +1 -0
  29. package/dist/core/builders/BuilderValidation.js.map +1 -0
  30. package/dist/core/builders/CartesianBuilders.js +1 -0
  31. package/dist/core/builders/CartesianBuilders.js.map +1 -0
  32. package/dist/core/builders/CompositionBuilders.js +1 -0
  33. package/dist/core/builders/CompositionBuilders.js.map +1 -0
  34. package/dist/core/builders/TemporalBuilders.js +1 -0
  35. package/dist/core/builders/TemporalBuilders.js.map +1 -0
  36. package/dist/index.js +1 -0
  37. package/dist/renderers/ChartRendering.js +1 -0
  38. package/dist/renderers/ChartRendering.js.map +1 -0
  39. package/dist/renderers/LegendRenderer.js +1 -0
  40. package/dist/renderers/LegendRenderer.js.map +1 -0
  41. package/dist/renderers/SvgSurface.js +1 -0
  42. package/dist/renderers/SvgSurface.js.map +1 -0
  43. package/dist/renderers/cartesian/CartesianAxesRenderer.js +1 -0
  44. package/dist/renderers/cartesian/CartesianAxesRenderer.js.map +1 -0
  45. package/dist/renderers/cartesian/CartesianInspectorRenderer.js +1 -0
  46. package/dist/renderers/cartesian/CartesianInspectorRenderer.js.map +1 -0
  47. package/dist/renderers/cartesian/CartesianLayout.js +1 -0
  48. package/dist/renderers/cartesian/CartesianLayout.js.map +1 -0
  49. package/dist/renderers/cartesian/CartesianRendering.js +1 -0
  50. package/dist/renderers/cartesian/CartesianRendering.js.map +1 -0
  51. package/dist/renderers/cartesian/CartesianSeriesRendering.js +1 -0
  52. package/dist/renderers/cartesian/CartesianSeriesRendering.js.map +1 -0
  53. package/dist/renderers/composition/AggregationRendering.js +1 -0
  54. package/dist/renderers/composition/AggregationRendering.js.map +1 -0
  55. package/dist/renderers/composition/Composition.js +1 -0
  56. package/dist/renderers/composition/Composition.js.map +1 -0
  57. package/dist/renderers/composition/PolarAreaRendering.js +1 -0
  58. package/dist/renderers/composition/PolarAreaRendering.js.map +1 -0
  59. package/dist/renderers/composition/RadarRendering.js +1 -0
  60. package/dist/renderers/composition/RadarRendering.js.map +1 -0
  61. package/dist/renderers/temporal/HeatmapRendering.js +1 -0
  62. package/dist/renderers/temporal/HeatmapRendering.js.map +1 -0
  63. package/dist/renderers/temporal/TimesheetLayout.js +1 -0
  64. package/dist/renderers/temporal/TimesheetLayout.js.map +1 -0
  65. package/dist/renderers/temporal/TimesheetRendering.js +1 -0
  66. package/dist/renderers/temporal/TimesheetRendering.js.map +1 -0
  67. package/dist/support/Constants.js +1 -0
  68. package/dist/support/Constants.js.map +1 -0
  69. package/dist/support/Dom.js +1 -0
  70. package/dist/support/Dom.js.map +1 -0
  71. package/dist/support/Normalize.js +2 -0
  72. package/dist/support/Normalize.js.map +1 -0
  73. package/dist/support/Validation.js +1 -0
  74. package/dist/support/Validation.js.map +1 -0
  75. package/dist/support/geometry/CartesianGeometry.js +1 -0
  76. package/dist/support/geometry/CartesianGeometry.js.map +1 -0
  77. package/dist/support/geometry/Scale.js +1 -0
  78. package/dist/support/geometry/Scale.js.map +1 -0
  79. package/dist/support/geometry/SectorGeometry.js +1 -0
  80. package/dist/support/geometry/SectorGeometry.js.map +1 -0
  81. package/dist/support/presentation/Formatting.js +1 -0
  82. package/dist/support/presentation/Formatting.js.map +1 -0
  83. package/dist/support/presentation/Presentation.js +1 -0
  84. package/dist/support/presentation/Presentation.js.map +1 -0
  85. package/dist/support/presentation/Time.js +1 -0
  86. package/dist/support/presentation/Time.js.map +1 -0
  87. package/docs/api-reference.md +322 -0
  88. package/docs/bar.md +110 -0
  89. package/docs/bubble.md +76 -0
  90. package/docs/chart-types.md +35 -0
  91. package/docs/customization.md +178 -0
  92. package/docs/donut.md +55 -0
  93. package/docs/exporting.md +87 -0
  94. package/docs/frameworks.md +203 -0
  95. package/docs/getting-started.md +121 -0
  96. package/docs/heatmap.md +95 -0
  97. package/docs/line.md +148 -0
  98. package/docs/mixed.md +114 -0
  99. package/docs/percentage.md +48 -0
  100. package/docs/pie.md +58 -0
  101. package/docs/polar-area.md +46 -0
  102. package/docs/radar.md +49 -0
  103. package/docs/readme.md +37 -0
  104. package/docs/scatter.md +83 -0
  105. package/docs/timesheet.md +125 -0
  106. package/docs/updates-and-interaction.md +124 -0
  107. package/package.json +133 -0
  108. package/src/index.d.ts +481 -0
  109. package/src/styles.css +350 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Options.js","names":[],"sources":["../../src/core/Options.js"],"sourcesContent":["import {\n AGGREGATION_TYPES,\n ChartOrientation,\n ChartType,\n CHART_ORIENTATIONS,\n DEFAULT_COLORS,\n DEFAULT_PAD_ANGLE,\n TYPES,\n Y_AXIS_POSITIONS,\n} from \"../support/Constants.js\";\nimport { measureParentWidth } from \"../support/Dom.js\";\nimport { isChoice, isNonEmptyText, isNumberAtLeast, isRecord, unknownKey } from \"../support/Validation.js\";\n\nconst DEFAULT_CHART_HEIGHT = 320;\nconst DEFAULT_STROKE_WIDTH = 2;\nconst DEFAULT_TIMESHEET_TASK_COUNT = 4;\nconst FULL_CIRCLE_DEGREES = 360;\nconst MINIMUM_TIMESHEET_HEIGHT = 220;\nconst TIMESHEET_FRAME_HEIGHT = 52;\nconst TIMESHEET_ROW_HEIGHT = 40;\n\nconst CSS_VARIABLE_PREFIX_LENGTH = 4;\n\nconst ANNOTATION_COLOR_PROPERTIES = Object.freeze([\n \"color\",\n \"labelColor\",\n]);\n\nconst ALLOWED_OPTIONS = Object.freeze([\n \"area\",\n \"ariaLabel\",\n \"axes\",\n \"axisFormatValue\",\n \"colors\",\n \"cornerRadius\",\n \"countLabel\",\n \"data\",\n \"description\",\n \"dots\",\n \"dotSize\",\n \"formatDate\",\n \"formatDuration\",\n \"gradient\",\n \"formatLabel\",\n \"formatTick\",\n \"formatValue\",\n \"grid\",\n \"height\",\n \"legend\",\n \"line\",\n \"maxSlices\",\n \"onSelect\",\n \"orientation\",\n \"padAngle\",\n \"radius\",\n \"smooth\",\n \"stacked\",\n \"startAngle\",\n \"strokeWidth\",\n \"title\",\n \"tooltip\",\n \"tooltipFormatDate\",\n \"tooltipFormatDuration\",\n \"tooltipFormatLabel\",\n \"tooltipFormatValue\",\n \"type\",\n \"valueLabels\",\n \"width\",\n \"yAxisPosition\",\n]);\n\n/**\n * Validates one optional renderer radius.\n *\n * @param {unknown} value - Optional radius supplied by renderer configuration.\n * @param {string} name - Human-readable option name used in validation errors.\n * @returns {void} Missing and non-negative finite radii are accepted.\n * @throws {TypeError} When a supplied radius is negative or non-finite.\n */\nfunction validateRadius(value, name) {\n if (value !== undefined && !isNumberAtLeast(value, 0)) {\n throw new TypeError(`${name} must be a non-negative finite number`);\n }\n}\n\n/**\n * Validates configuration values drawn from closed vocabularies.\n *\n * @param {object} options - Structurally valid chart options.\n * @returns {void} Choice validation completes without transforming input.\n * @throws {TypeError} When orientation or axis placement is unsupported.\n */\nfunction validateChoices(options) {\n if (options.orientation && !isChoice(options.orientation, CHART_ORIENTATIONS)) {\n throw new TypeError(\"Bar orientation must be vertical or horizontal\");\n }\n\n if (options.yAxisPosition && !isChoice(options.yAxisPosition, Y_AXIS_POSITIONS)) {\n throw new TypeError(\"Y-axis position must be left or right\");\n }\n}\n\n/**\n * Validates angles and radii shared by renderer families.\n *\n * @param {object} options - Structurally valid chart options.\n * @returns {void} Geometry validation completes without transforming input.\n * @throws {TypeError} When an angle or radius is outside its supported range.\n */\nfunction validateGeometry(options) {\n if (isInvalidPadAngle(options.padAngle)) {\n throw new TypeError(\"Pad angle must be a finite number from 0 up to 360 degrees\");\n }\n\n for (const [\n value,\n name,\n ] of [\n [\n options.radius,\n \"Radius\",\n ],\n [\n options.cornerRadius,\n \"Corner radius\",\n ],\n ]) {\n validateRadius(value, name);\n }\n}\n\n/**\n * Detects unsupported optional sector padding.\n *\n * @param {unknown} value - Optional padding angle in degrees.\n * @returns {boolean} True when a supplied angle is non-finite or outside one circle.\n */\nfunction isInvalidPadAngle(value) {\n if (value === undefined) {\n return false;\n }\n\n if (!isNumberAtLeast(value, 0)) {\n return true;\n }\n\n return value >= FULL_CIRCLE_DEGREES;\n}\n\n/**\n * Rejects unsupported choices and invalid renderer geometry.\n *\n * @param {object} options - Candidate public chart options.\n * @returns {void} Validation returns only when the complete contract is satisfied.\n * @throws {TypeError} When a name, type, choice, angle, or radius is invalid.\n */\nfunction validateChartOptions(options) {\n if (!isRecord(options)) {\n throw new TypeError(\"Chart options must be an object\");\n }\n\n const unknownOption = unknownKey(options, ALLOWED_OPTIONS);\n\n if (unknownOption) {\n throw new TypeError(`Unsupported chart option: ${unknownOption}`);\n }\n\n if (!TYPES.includes(options.type)) {\n throw new TypeError(`Chart type must be one of: ${TYPES.join(\", \")}`);\n }\n\n validateChoices(options);\n validateGeometry(options);\n}\n\n/**\n * Resolves visibility, accessibility, and orientation defaults.\n *\n * @param {object} options - Validated caller options.\n * @returns {object} Complete presentation choices for every renderer.\n */\nfunction presentationOptions(options) {\n return Object.freeze({\n axes: options.axes ?? true,\n grid: options.grid ?? true,\n valueLabels: options.valueLabels ?? true,\n legend: shouldShowLegend(options),\n tooltip: options.tooltip ?? true,\n orientation: options.orientation ?? ChartOrientation.VERTICAL,\n ariaLabel: options.ariaLabel ?? options.title ?? `${options.type} chart`,\n });\n}\n\n/**\n * Resolves the legend default while preserving the timesheet contract.\n *\n * @param {object} options - Validated chart options.\n * @returns {boolean} Whether the selected chart family displays a legend.\n */\nfunction shouldShowLegend(options) {\n if (options.type === ChartType.TIMESHEET) {\n return false;\n }\n\n if (options.legend !== undefined) {\n return options.legend;\n }\n\n if (\n [\n ...AGGREGATION_TYPES,\n ChartType.POLAR_AREA,\n ChartType.HEATMAP,\n ].includes(options.type)\n ) {\n return true;\n }\n\n return options.data.datasets.length >= 2;\n}\n\n/**\n * Resolves responsive width and chart-family-specific height defaults.\n *\n * @param {Element} host - Chart host used for responsive width measurement.\n * @param {object} options - Validated caller options.\n * @returns {{width: number, height: number}} Candidate dimensions for final validation.\n */\nfunction chartDimensions(host, options) {\n const taskCount = options.data?.tasks?.length ?? DEFAULT_TIMESHEET_TASK_COUNT;\n\n const timesheetHeight = Math.max(\n MINIMUM_TIMESHEET_HEIGHT,\n taskCount * TIMESHEET_ROW_HEIGHT + TIMESHEET_FRAME_HEIGHT,\n );\n\n const defaultHeight = options.type === ChartType.TIMESHEET ? timesheetHeight : DEFAULT_CHART_HEIGHT;\n\n return {\n width: options.width ?? measureParentWidth(host),\n height: options.height ?? defaultHeight,\n };\n}\n\n/**\n * Validates and normalizes configuration in one obvious entry point.\n *\n * @param {Element} host - Resolved chart host used for responsive dimensions.\n * @param {import(\"../index.js\").ChartOptions} options - Candidate public chart configuration.\n * @returns {{options: object, hasCustomColors: boolean}} Renderer-ready options and palette provenance.\n * @throws {TypeError} When the configuration cannot produce a chart.\n */\nfunction normalizeChartOptions(host, options) {\n validateChartOptions(options);\n validateChartColors(host, options);\n\n const normalized = {\n colors: options.colors\n ? [\n ...options.colors,\n ]\n : DEFAULT_COLORS,\n strokeWidth: DEFAULT_STROKE_WIDTH,\n padAngle: options.padAngle ?? DEFAULT_PAD_ANGLE,\n ...options,\n ...presentationOptions(options),\n ...chartDimensions(host, options),\n };\n\n if (\n [\n normalized.width,\n normalized.height,\n ].some((value) => !isNumberAtLeast(value, Number.EPSILON))\n ) {\n throw new TypeError(\"Chart width and height must be positive finite numbers\");\n }\n\n if (!Array.isArray(normalized.colors) || normalized.colors.length === 0) {\n throw new TypeError(\"Chart colors must be a non-empty array\");\n }\n\n return {\n options: normalized,\n hasCustomColors: options.colors !== undefined,\n };\n}\n\n/**\n * Validates every palette and explicit input color in the parent CSS context.\n *\n * @param {Element} host - Chart parent supplying custom-property values.\n * @param {object} input - Options or update data containing color fields.\n * @returns {void} Every supplied color is supported by the browser.\n */\nfunction validateChartColors(host, input) {\n const colors = collectColors(input);\n\n for (const color of colors) {\n validateCssColor(host, color);\n }\n}\n\n/**\n * Adds explicitly supplied color fields from one public record collection.\n *\n * @param {unknown[]} colors - Accumulator receiving explicit color values.\n * @param {unknown} records - Candidate dataset, annotation, or task collection.\n * @param {string[]} properties - Color fields supported by the record schema.\n * @returns {void} Missing and malformed collections add no colors.\n */\nfunction appendRecordColors(colors, records, properties) {\n if (!Array.isArray(records)) {\n return;\n }\n\n for (const record of records) {\n if (!isRecord(record)) {\n continue;\n }\n\n for (const property of properties) {\n if (Object.hasOwn(record, property)) {\n colors.push(record[property]);\n }\n }\n }\n}\n\n/**\n * Collects colors only from fields declared by the public chart-data schemas.\n *\n * Numeric point collections are intentionally never traversed: colors can be\n * supplied by palettes, datasets, annotations, and timesheet tasks only.\n *\n * @param {unknown} input - Complete chart options or one public update payload.\n * @returns {unknown[]} Explicit color values awaiting browser validation.\n */\nfunction collectColors(input) {\n if (!isRecord(input)) {\n return [];\n }\n\n const colors = [];\n\n if (Array.isArray(input.colors)) {\n colors.push(...input.colors);\n }\n\n const hasData = input.data && typeof input.data === \"object\";\n const data = hasData ? input.data : input;\n\n appendRecordColors(colors, data.datasets, [\n \"color\",\n ]);\n appendRecordColors(colors, data.markers, ANNOTATION_COLOR_PROPERTIES);\n appendRecordColors(colors, data.regions, ANNOTATION_COLOR_PROPERTIES);\n appendRecordColors(colors, data.tasks, [\n \"color\",\n ]);\n\n return colors;\n}\n\n/**\n * Resolves CSS variables and verifies one browser-supported color.\n *\n * @param {Element} host - Parent supplying custom properties.\n * @param {unknown} value - Candidate CSS color.\n * @returns {void} Supported colors pass unchanged.\n */\nfunction validateCssColor(host, value) {\n if (!isNonEmptyText(value)) {\n throw new TypeError(\"Color must be a non-empty supported CSS color\");\n }\n\n const color = resolvedColor(host, value.trim());\n const isSupported = globalThis.CSS?.supports?.(\"color\", color) ?? supportsStyleColor(color);\n\n if (!isSupported) {\n throw new TypeError(`Unsupported CSS color: ${value}`);\n }\n}\n\n/**\n * Resolves one leading var() expression against the chart parent.\n *\n * @param {Element} host - Parent supplying custom properties.\n * @param {string} value - Candidate color expression.\n * @returns {string} Resolved color or unresolved original value.\n */\nfunction resolvedColor(host, value) {\n if (!value.startsWith(\"var(\") || !value.endsWith(\")\")) {\n return value;\n }\n\n const [\n name,\n ...fallbackParts\n ] = value.slice(CSS_VARIABLE_PREFIX_LENGTH, -1).split(\",\");\n\n const resolved = getComputedStyle(host).getPropertyValue(name.trim()).trim();\n const fallback = fallbackParts.join(\",\").trim();\n const candidate = resolved || fallback;\n\n if (!candidate) {\n throw new TypeError(`Unresolved CSS color variable: ${name.trim()}`);\n }\n\n return candidate;\n}\n\n/**\n * Uses detached style parsing when CSS.supports is unavailable.\n *\n * @param {string} color - Resolved candidate color.\n * @returns {boolean} Whether the browser accepts the declaration.\n */\nfunction supportsStyleColor(color) {\n const probe = document.createElement(\"span\");\n probe.style.color = color;\n\n return probe.style.color !== \"\";\n}\n\nexport { normalizeChartOptions, validateChartColors, validateChartOptions };\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{builderState as t,initializeBuilder as i}from"./BuilderState.js";import{AxisBuilder as o,SeriesTooltipBuilder as e,runScope as r}from"./BuilderScopes.js";import{lineDataset as n,markerInput as s,regionInput as a}from"./BuilderArguments.js";var p=class{constructor(t,o,e){i(this,{parent:t,type:o,mount:e})}title(i){return t(this).option("title",i)}description(i){return t(this).option("description",i)}ariaLabel(i){return t(this).option("ariaLabel",i)}width(i){return t(this).option("width",i)}height(i){return t(this).option("height",i)}colors(i){return t(this).option("colors",i)}tooltip(i){if("function"!=typeof i)return t(this).explicitOption("tooltip",i);const o={};r(new e(o),i);const n=t(this);return n.explicitOption("tooltip",!0),void 0!==o.formatLabel&&n.option("tooltipFormatLabel",o.formatLabel),void 0!==o.tooltipValue&&n.option("tooltipFormatValue",o.tooltipValue),this}onSelect(i){return t(this).option("onSelect",i)}render(){const i=t(this),{parent:o,options:e,mount:r}=i.compile(),n=r(o,e);return i.consume(),n}},l=class extends p{legend(i){return t(this).explicitOption("legend",i)}labels(i){return t(this).labels(i)}formatValue(i){return t(this).option("formatValue",i)}formatLabel(i){return t(this).option("formatLabel",i)}},u=class extends l{axes(i){return t(this).explicitOption("axes",i)}grid(i){return t(this).explicitOption("grid",i)}valueLabels(i){return t(this).explicitOption("valueLabels",i)}frameless(i=!0){return t(this).option("frameless",i)}yAxis(i){const e={};r(new o(e),i);const n=t(this);return void 0!==e.position&&n.option("yAxisPosition",e.position),void 0!==e.axisValue&&n.option("axisFormatValue",e.axisValue),this}marker(i,o,e){return t(this).append("markers",s(i,o,e))}region(i,o,e){return t(this).append("regions",a(i,o,e))}},h=class extends u{dataset(i,o,e){return t(this).dataset(n(i,o,e))}smooth(i=!0){return t(this).option("smooth",i)}dots(i){return t(this).explicitOption("dots",i)}dotSize(i){return t(this).option("dotSize",i)}line(i){return t(this).option("line",i)}area(i=!0){return t(this).option("area",i)}gradient(i=!0){return t(this).option("gradient",i)}strokeWidth(i){return t(this).option("strokeWidth",i)}};export{u as CartesianChartBuilder,p as CommonChartBuilder,h as LineChartBuilder,l as SeriesChartBuilder};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Builder.js","names":[],"sources":["../../../src/core/builders/Builder.js"],"sourcesContent":["import { lineDataset, markerInput, regionInput } from \"./BuilderArguments.js\";\nimport { AxisBuilder, SeriesTooltipBuilder, runScope } from \"./BuilderScopes.js\";\nimport { builderState, initializeBuilder } from \"./BuilderState.js\";\n\n/**\n * Owns common chart authoring state without resolving DOM until `render()`.\n */\nclass CommonChartBuilder {\n /**\n * Creates a fresh single-use builder for one internal chart type.\n *\n * @param {string | Element} parent - Deferred chart host reference.\n * @param {string} type - Internal renderer type.\n * @param {(parent: string | Element, options: object) => object} mount - Mounted chart factory.\n */\n constructor(parent, type, mount) {\n initializeBuilder(this, { parent, type, mount });\n }\n\n /**\n * Sets a visible chart heading.\n *\n * @param {string} value - Human-readable chart title.\n * @returns {this} Current builder.\n */\n title(value) {\n return builderState(this).option(\"title\", value);\n }\n\n /**\n * Sets accessible descriptive text.\n *\n * @param {string} value - Concise chart description.\n * @returns {this} Current builder.\n */\n description(value) {\n return builderState(this).option(\"description\", value);\n }\n\n /**\n * Overrides the generated accessible name.\n *\n * @param {string} value - Accessible chart label.\n * @returns {this} Current builder.\n */\n ariaLabel(value) {\n return builderState(this).option(\"ariaLabel\", value);\n }\n\n /**\n * Fixes chart width instead of following the parent.\n *\n * @param {number} value - Width in CSS pixels.\n * @returns {this} Current builder.\n */\n width(value) {\n return builderState(this).option(\"width\", value);\n }\n\n /**\n * Chooses chart height in CSS pixels.\n *\n * @param {number} value - Positive finite height.\n * @returns {this} Current builder.\n */\n height(value) {\n return builderState(this).option(\"height\", value);\n }\n\n /**\n * Chooses the ordered whole-chart palette.\n *\n * @param {readonly string[]} values - Non-empty CSS color palette.\n * @returns {this} Current builder.\n */\n colors(values) {\n return builderState(this).option(\"colors\", values);\n }\n\n /**\n * Configures tooltip visibility or scoped formatting.\n *\n * @param {boolean | ((tooltip: SeriesTooltipBuilder) => void)} value - Visibility switch or tooltip configurator.\n * @returns {this} Current builder.\n */\n tooltip(value) {\n if (typeof value !== \"function\") {\n return builderState(this).explicitOption(\"tooltip\", value);\n }\n\n const tooltip = {};\n runScope(new SeriesTooltipBuilder(tooltip), value);\n const state = builderState(this);\n state.explicitOption(\"tooltip\", true);\n\n if (tooltip.formatLabel !== undefined) {\n state.option(\"tooltipFormatLabel\", tooltip.formatLabel);\n }\n\n if (tooltip.tooltipValue !== undefined) {\n state.option(\"tooltipFormatValue\", tooltip.tooltipValue);\n }\n\n return this;\n }\n\n /**\n * Enables persistent selection and registers its callback.\n *\n * @param {(selection: object | undefined) => void} callback - Selection observer.\n * @returns {this} Current builder.\n */\n onSelect(callback) {\n return builderState(this).option(\"onSelect\", callback);\n }\n\n /**\n * Validates, mounts, and consumes this builder after a successful commit.\n *\n * @returns {import(\"./Chart.js\").default} Mounted chart lifecycle façade.\n */\n render() {\n const state = builderState(this);\n const { parent, options, mount } = state.compile();\n const chart = mount(parent, options);\n state.consume();\n\n return chart;\n }\n}\n\n/**\n * Adds ordered category and dataset authoring to a common chart builder.\n */\nclass SeriesChartBuilder extends CommonChartBuilder {\n /**\n * Chooses legend visibility instead of the dataset-count convention.\n *\n * @param {boolean} visible - Whether the legend is displayed.\n * @returns {this} Current builder.\n */\n legend(visible) {\n return builderState(this).explicitOption(\"legend\", visible);\n }\n\n /**\n * Replaces category labels with a defensive copy.\n *\n * @param {readonly string[]} values - Ordered category labels.\n * @returns {this} Current builder.\n */\n labels(values) {\n return builderState(this).labels(values);\n }\n\n /**\n * Formats chart values for display surfaces.\n *\n * @param {(value: number, context: object) => string} formatter - Synchronous value formatter.\n * @returns {this} Current builder.\n */\n formatValue(formatter) {\n return builderState(this).option(\"formatValue\", formatter);\n }\n\n /**\n * Formats category labels for display surfaces.\n *\n * @param {(label: string | number, context: object) => string} formatter - Synchronous label formatter.\n * @returns {this} Current builder.\n */\n formatLabel(formatter) {\n return builderState(this).option(\"formatLabel\", formatter);\n }\n}\n\n/**\n * Adds Cartesian presentation conventions shared by product-series charts.\n */\nclass CartesianChartBuilder extends SeriesChartBuilder {\n /**\n * Chooses axes visibility.\n *\n * @param {boolean} visible - Whether axes are displayed.\n * @returns {this} Current builder.\n */\n axes(visible) {\n return builderState(this).explicitOption(\"axes\", visible);\n }\n\n /**\n * Chooses grid visibility.\n *\n * @param {boolean} visible - Whether grid lines are displayed.\n * @returns {this} Current builder.\n */\n grid(visible) {\n return builderState(this).explicitOption(\"grid\", visible);\n }\n\n /**\n * Chooses visible value-label presentation.\n *\n * @param {boolean} visible - Whether value labels are displayed.\n * @returns {this} Current builder.\n */\n valueLabels(visible) {\n return builderState(this).explicitOption(\"valueLabels\", visible);\n }\n\n /**\n * Applies or removes the compact product-chart presentation convention.\n *\n * @param {boolean} [isEnabled=true] - Whether frameless defaults apply.\n * @returns {this} Current builder.\n */\n frameless(isEnabled = true) {\n return builderState(this).option(\"frameless\", isEnabled);\n }\n\n /**\n * Configures the value axis inside an automatically expiring scope.\n *\n * @param {(axis: AxisBuilder) => void} configure - Value-axis configurator.\n * @returns {this} Current builder.\n */\n yAxis(configure) {\n const axis = {};\n runScope(new AxisBuilder(axis), configure);\n const state = builderState(this);\n\n if (axis.position !== undefined) {\n state.option(\"yAxisPosition\", axis.position);\n }\n\n if (axis.axisValue !== undefined) {\n state.option(\"axisFormatValue\", axis.axisValue);\n }\n\n return this;\n }\n\n /**\n * Appends one value marker using positional or object grammar.\n *\n * @param {unknown} first - Label or advanced marker input.\n * @param {unknown} [second] - Marker value or configurator.\n * @param {unknown} [third] - Marker color or configurator.\n * @returns {this} Current builder.\n */\n marker(first, second, third) {\n return builderState(this).append(\"markers\", markerInput(first, second, third));\n }\n\n /**\n * Appends one value region using positional or object grammar.\n *\n * @param {unknown} first - Label or advanced region input.\n * @param {unknown} [second] - Numeric range or configurator.\n * @param {unknown} [third] - Region color or configurator.\n * @returns {this} Current builder.\n */\n region(first, second, third) {\n return builderState(this).append(\"regions\", regionInput(first, second, third));\n }\n}\n\n/**\n * Implements the complete chart-wide LineChart fluent vocabulary.\n */\nclass LineChartBuilder extends CartesianChartBuilder {\n /**\n * Appends one line dataset using shorthand, named, or object grammar.\n *\n * @param {unknown} first - Values, name, or dataset input.\n * @param {unknown} [second] - Values, color, or configurator.\n * @param {unknown} [third] - Named dataset color or configurator.\n * @returns {this} Current builder.\n */\n dataset(first, second, third) {\n return builderState(this).dataset(lineDataset(first, second, third));\n }\n\n /**\n * Chooses line smoothing for every dataset unless locally overridden.\n *\n * @param {boolean} [isEnabled=true] - Whether smoothing is enabled.\n * @returns {this} Current builder.\n */\n smooth(isEnabled = true) {\n return builderState(this).option(\"smooth\", isEnabled);\n }\n\n /**\n * Chooses point visibility for every line dataset.\n *\n * @param {boolean} visible - Whether points are displayed.\n * @returns {this} Current builder.\n */\n dots(visible) {\n return builderState(this).explicitOption(\"dots\", visible);\n }\n\n /**\n * Chooses point radius for every line dataset.\n *\n * @param {number} value - Dot radius in CSS pixels.\n * @returns {this} Current builder.\n */\n dotSize(value) {\n return builderState(this).option(\"dotSize\", value);\n }\n\n /**\n * Chooses stroke visibility for every line dataset.\n *\n * @param {boolean} visible - Whether line strokes are displayed.\n * @returns {this} Current builder.\n */\n line(visible) {\n return builderState(this).option(\"line\", visible);\n }\n\n /**\n * Enables a solid area for every line dataset.\n *\n * @param {boolean} [isEnabled=true] - Whether area fills are enabled.\n * @returns {this} Current builder.\n */\n area(isEnabled = true) {\n return builderState(this).option(\"area\", isEnabled);\n }\n\n /**\n * Enables a gradient area for every line dataset.\n *\n * @param {boolean | object} [isEnabled=true] - Gradient switch or opacity endpoints.\n * @returns {this} Current builder.\n */\n gradient(isEnabled = true) {\n return builderState(this).option(\"gradient\", isEnabled);\n }\n\n /**\n * Chooses stroke width for every line dataset.\n *\n * @param {number} value - Stroke width in CSS pixels.\n * @returns {this} Current builder.\n */\n strokeWidth(value) {\n return builderState(this).option(\"strokeWidth\", value);\n }\n}\n\nexport { CartesianChartBuilder, CommonChartBuilder, LineChartBuilder, SeriesChartBuilder };\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{copyBuilderValue as t}from"./BuilderState.js";import{LineDatasetBuilder as n,MarkerBuilder as o,RegionBuilder as e,runScope as r}from"./BuilderScopes.js";function i(n,o){const e=function(n,o,e){let r;return"string"==typeof n&&(r=function(n,o,e){const r={name:n,values:t(o)};return"string"==typeof e&&(r.color=e),{dataset:r,configure:"function"==typeof e?e:void 0}}(n,o,e)),Array.isArray(n)&&(r=function(n,o){const e={values:t(n)};return"string"==typeof o&&(e.color=o),{dataset:e,configure:"function"==typeof o?o:void 0}}(n,o)),r||(r={dataset:t(n),configure:"function"==typeof o?o:void 0}),r}(...n);return e.configure&&r(new o(e.dataset),e.configure),e.dataset}function f(t,o,e){return i([t,o,e],n)}function u(n,e,i){const f="string"==typeof n,u=f?{label:n,value:e}:t(n),c=f?i:e;return f&&"string"==typeof i&&(u.color=i),"function"==typeof c&&r(new o(u),c),u}function c(n,o,i){const f="string"==typeof n,u=f?{label:n,range:t(o)}:t(n),c=f?i:o;return f&&"string"==typeof i&&(u.color=i),"function"==typeof c&&r(new e(u),c),u}export{i as configuredDataset,f as lineDataset,u as markerInput,c as regionInput};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuilderArguments.js","names":[],"sources":["../../../src/core/builders/BuilderArguments.js"],"sourcesContent":["import { LineDatasetBuilder, MarkerBuilder, RegionBuilder, runScope } from \"./BuilderScopes.js\";\nimport { copyBuilderValue } from \"./BuilderState.js\";\n\n/**\n * Resolves one named positional dataset call.\n *\n * @param {string} name - Human-readable legend label.\n * @param {unknown} values - Ordered numeric payload copied into the series.\n * @param {unknown} colorOrConfigure - Optional color or scoped configurator.\n * @returns {{dataset: object, configure?: (scope: LineDatasetBuilder) => void}} Detached named dataset arguments.\n */\nfunction namedDatasetArguments(name, values, colorOrConfigure) {\n const dataset = { name, values: copyBuilderValue(values) };\n\n if (typeof colorOrConfigure === \"string\") {\n dataset.color = colorOrConfigure;\n }\n\n const configure = typeof colorOrConfigure === \"function\" ? colorOrConfigure : undefined;\n\n return {\n dataset,\n configure,\n };\n}\n\n/**\n * Resolves one unnamed shorthand dataset call.\n *\n * @param {unknown[]} values - Ordered numeric values for one series.\n * @param {unknown} colorOrConfigure - Optional color or scoped configurator.\n * @returns {{dataset: object, configure?: (scope: LineDatasetBuilder) => void}} Detached unnamed dataset arguments.\n */\nfunction unnamedDatasetArguments(values, colorOrConfigure) {\n const dataset = { values: copyBuilderValue(values) };\n\n if (typeof colorOrConfigure === \"string\") {\n dataset.color = colorOrConfigure;\n }\n\n const configure = typeof colorOrConfigure === \"function\" ? colorOrConfigure : undefined;\n\n return {\n dataset,\n configure,\n };\n}\n\n/**\n * Creates a configured dataset record from positional or object grammar.\n *\n * @param {unknown} first - Values, name, or advanced dataset input.\n * @param {unknown} second - Values, color, or configurator.\n * @param {unknown} third - Color or configurator for a named dataset.\n * @returns {object} Completed detached dataset record.\n */\nfunction datasetArguments(first, second, third) {\n let result;\n\n if (typeof first === \"string\") {\n result = namedDatasetArguments(first, second, third);\n }\n\n if (Array.isArray(first)) {\n result = unnamedDatasetArguments(first, second);\n }\n\n if (!result) {\n result = {\n dataset: copyBuilderValue(first),\n configure: typeof second === \"function\" ? second : undefined,\n };\n }\n\n return result;\n}\n\n/**\n * Creates a configured dataset record with the requested capability scope.\n *\n * @param {unknown[]} inputs - Public dataset method arguments.\n * @param {new (record: object) => object} Scope - Type-specific callback builder.\n * @returns {object} Completed detached dataset record.\n */\nfunction configuredDataset(inputs, Scope) {\n const result = datasetArguments(...inputs);\n\n if (result.configure) {\n runScope(new Scope(result.dataset), result.configure);\n }\n\n return result.dataset;\n}\n\n/**\n * Creates a configured line dataset using line-only callback capabilities.\n *\n * @param {unknown} first - Values, name, or advanced dataset input.\n * @param {unknown} second - Values, color, or configurator.\n * @param {unknown} third - Color or configurator for a named dataset.\n * @returns {object} Completed detached line dataset.\n */\nfunction lineDataset(first, second, third) {\n return configuredDataset(\n [\n first,\n second,\n third,\n ],\n LineDatasetBuilder,\n );\n}\n\n/**\n * Creates a marker record from positional or object grammar.\n *\n * @param {unknown} first - Label or advanced marker input.\n * @param {unknown} second - Marker value or configurator.\n * @param {unknown} third - Color or configurator for a positional marker.\n * @returns {object} Completed detached marker record.\n */\nfunction markerInput(first, second, third) {\n const isPositional = typeof first === \"string\";\n const marker = isPositional ? { label: first, value: second } : copyBuilderValue(first);\n const callbackCandidate = isPositional ? third : second;\n\n if (isPositional && typeof third === \"string\") {\n marker.color = third;\n }\n\n if (typeof callbackCandidate === \"function\") {\n runScope(new MarkerBuilder(marker), callbackCandidate);\n }\n\n return marker;\n}\n\n/**\n * Creates a region record from positional or object grammar.\n *\n * @param {unknown} first - Label or advanced region input.\n * @param {unknown} second - Numeric range or configurator.\n * @param {unknown} third - Color or configurator for a positional region.\n * @returns {object} Completed detached region record.\n */\nfunction regionInput(first, second, third) {\n const isPositional = typeof first === \"string\";\n const region = isPositional ? { label: first, range: copyBuilderValue(second) } : copyBuilderValue(first);\n const callbackCandidate = isPositional ? third : second;\n\n if (isPositional && typeof third === \"string\") {\n region.color = third;\n }\n\n if (typeof callbackCandidate === \"function\") {\n runScope(new RegionBuilder(region), callbackCandidate);\n }\n\n return region;\n}\n\nexport { configuredDataset, lineDataset, markerInput, regionInput };\n"],"mappings":"iKAoFA,SAAS,EAAkB,EAAQ,GACjC,MAAM,EA7BR,SAA0B,EAAO,EAAQ,GACvC,IAAI,EAiBJ,MAfqB,iBAAV,IACT,EAjDJ,SAA+B,EAAM,EAAQ,GAC3C,MAAM,EAAU,CAAE,OAAM,OAAQ,EAAiB,IAQjD,MANgC,iBAArB,IACT,EAAQ,MAAQ,GAKX,CACL,UACA,UAJ4C,mBAArB,EAAkC,OAAmB,EAMhF,CAoCa,CAAsB,EAAO,EAAQ,IAG5C,MAAM,QAAQ,KAChB,EA/BJ,SAAiC,EAAQ,GACvC,MAAM,EAAU,CAAE,OAAQ,EAAiB,IAQ3C,MANgC,iBAArB,IACT,EAAQ,MAAQ,GAKX,CACL,UACA,UAJ4C,mBAArB,EAAkC,OAAmB,EAMhF,CAkBa,CAAwB,EAAO,IAGrC,IACH,EAAS,CACP,QAAS,EAAiB,GAC1B,UAA6B,mBAAX,EAAwB,OAAS,IAIhD,CACT,CAUiB,IAAoB,GAMnC,OAJI,EAAO,WACT,EAAS,IAAI,EAAM,EAAO,SAAU,EAAO,WAGtC,EAAO,OAChB,CAUA,SAAS,EAAY,EAAO,EAAQ,GAClC,OAAO,EACL,CACE,EACA,EACA,GAEF,EAEJ,CAUA,SAAS,EAAY,EAAO,EAAQ,GAClC,MAAM,EAAgC,iBAAV,EACtB,EAAS,EAAe,CAAE,MAAO,EAAO,MAAO,GAAW,EAAiB,GAC3E,EAAoB,EAAe,EAAQ,EAUjD,OARI,GAAiC,iBAAV,IACzB,EAAO,MAAQ,GAGgB,mBAAtB,GACT,EAAS,IAAI,EAAc,GAAS,GAG/B,CACT,CAUA,SAAS,EAAY,EAAO,EAAQ,GAClC,MAAM,EAAgC,iBAAV,EACtB,EAAS,EAAe,CAAE,MAAO,EAAO,MAAO,EAAiB,IAAY,EAAiB,GAC7F,EAAoB,EAAe,EAAQ,EAUjD,OARI,GAAiC,iBAAV,IACzB,EAAO,MAAQ,GAGgB,mBAAtB,GACT,EAAS,IAAI,EAAc,GAAS,GAG/B,CACT"}
@@ -0,0 +1 @@
1
+ import{validateBoolean as t,validateDash as r,validateFunction as e,validateGradient as i,validateLabelPosition as s,validateLineStyle as o,validateNumber as a,validateOpacity as n,validatePosition as h,validateText as l}from"./BuilderValidation.js";import{copyBuilderValue as u}from"./BuilderState.js";var c=/* @__PURE__ */new WeakMap,d=/* @__PURE__ */new Set(["color","opacity","labelPosition","labelColor","includeInDomain","formatLabel","width","lineStyle","dash"]),m=/* @__PURE__ */new Set(["formatDate","formatDuration"]),p=class{#t;#r;#e=!0;constructor({record:t,name:r}){this.#t=t,this.#r=r}write(t,r){this.#i(),this.#t[t]=u(r)}expire(){this.#e=!1}#i(){if(!this.#e)throw new TypeError(`${this.#r} scope has expired`)}};function f(t,r){c.set(t,new p(r))}function w(t,r){const e=c.get(t);if(!e)throw new TypeError(`${r} scope has expired`);return e}function D(t,r,e){let i="Builder";d.has(r)&&(i="Annotation"),m.has(r)&&(i="Tooltip"),w(t,i).write(r,e)}var b=class{constructor(t){f(this,{record:t,name:"Dataset"})}color(t){return l(t,"color"),w(this,"Dataset").write("color",t),this}opacity(t){return n(t,"opacity"),w(this,"Dataset").write("opacity",t),this}formatValue(t){return e(t,"formatValue"),D(this,"formatValue",t),this}},x=class extends b{gradient(t=!0){return i(t),D(this,"gradient",t),this}smooth(r=!0){return t(r,"smooth"),D(this,"smooth",r),this}dots(r){return t(r,"dots"),D(this,"dots",r),this}dotSize(t){return a(t,"dotSize",0),D(this,"dotSize",t),this}line(r){return t(r,"line"),D(this,"line",r),this}area(r=!0){return t(r,"area"),D(this,"area",r),this}strokeWidth(t){return a(t,"strokeWidth",0),D(this,"strokeWidth",t),this}},y=class extends b{radius(t){return a(t,"radius",0),D(this,"radius",t),this}},V=class{constructor(t){f(this,{record:t,name:"Tooltip"})}formatLabel(t){return e(t,"formatLabel"),w(this,"Tooltip").write("formatLabel",t),this}formatValue(t){return e(t,"tooltipValue"),D(this,"tooltipValue",t),this}},S=class{constructor(t){f(this,{record:t,name:"Y-axis"})}position(t){return h(t),D(this,"position",t),this}formatValue(t){return e(t,"axisValue"),D(this,"axisValue",t),this}},v=class{constructor(t,r){f(this,{record:t,name:r})}color(t){return l(t,"color"),D(this,"color",t),this}opacity(t){return n(t,"opacity"),D(this,"opacity",t),this}labelPosition(t){return s(t),D(this,"labelPosition",t),this}labelColor(t){return l(t,"labelColor"),D(this,"labelColor",t),this}includeInDomain(r){return t(r,"includeInDomain"),D(this,"includeInDomain",r),this}formatLabel(t){return e(t,"formatLabel"),D(this,"formatLabel",t),this}},L=class extends v{constructor(t){super(t,"Marker")}width(t){return a(t,"width",0),D(this,"width",t),this}lineStyle(t){return o(t),D(this,"lineStyle",t),this}dash(t){return r(t),D(this,"dash",t),this}},T=class extends v{constructor(t){super(t,"Region")}},k=class{constructor(t,r){f(this,{record:t,name:r})}formatDate(t){return e(t,"formatDate"),D(this,"formatDate",t),this}},g=class extends k{constructor(t){super(t,"Heatmap tooltip")}formatValue(t){return e(t,"formatValue"),w(this,"Heatmap tooltip").write("formatValue",t),this}},B=class extends k{constructor(t){super(t,"Timesheet tooltip")}formatDuration(t){return e(t,"formatDuration"),D(this,"formatDuration",t),this}};function C(t,r){try{r(t)}finally{w(t,"Builder").expire()}}export{S as AxisBuilder,y as BarDatasetBuilder,b as DatasetBuilder,g as HeatmapTooltipBuilder,x as LineDatasetBuilder,L as MarkerBuilder,T as RegionBuilder,V as SeriesTooltipBuilder,B as TimesheetTooltipBuilder,C as runScope};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuilderScopes.js","names":["#record","#name","#assertActive","#active"],"sources":["../../../src/core/builders/BuilderScopes.js"],"sourcesContent":["import { copyBuilderValue } from \"./BuilderState.js\";\nimport {\n validateBoolean,\n validateDash,\n validateFunction,\n validateGradient,\n validateLabelPosition,\n validateLineStyle,\n validateNumber,\n validateOpacity,\n validatePosition,\n validateText,\n} from \"./BuilderValidation.js\";\n\nconst records = new WeakMap();\n\nconst ANNOTATION_PROPERTIES = new Set([\n \"color\",\n \"opacity\",\n \"labelPosition\",\n \"labelColor\",\n \"includeInDomain\",\n \"formatLabel\",\n \"width\",\n \"lineStyle\",\n \"dash\",\n]);\n\nconst TOOLTIP_PROPERTIES = new Set([\n \"formatDate\",\n \"formatDuration\",\n]);\n\n/**\n * Owns one callback scope's record and lifetime.\n */\nclass ScopeState {\n #record;\n #name;\n #active = true;\n\n /**\n * Creates active state for one callback scope.\n *\n * @param {object} definition - Scope record and public name.\n * @param {object} definition.record - Detached record being configured.\n * @param {string} definition.name - Public scope name used by expiry errors.\n */\n constructor({ record, name }) {\n this.#record = record;\n this.#name = name;\n }\n\n /**\n * Writes a copied value while this scope remains active.\n *\n * @param {string} name - Record property being configured.\n * @param {unknown} value - Caller-controlled property value.\n * @returns {void} The record is updated in place.\n */\n write(name, value) {\n this.#assertActive();\n this.#record[name] = copyBuilderValue(value);\n }\n\n /**\n * Prevents every subsequent write through this callback scope.\n *\n * @returns {void} The scope becomes permanently inactive.\n */\n expire() {\n this.#active = false;\n }\n\n /**\n * Rejects access after the callback has finished.\n *\n * @returns {void} Active scopes continue unchanged.\n * @throws {TypeError} When the callback scope has expired.\n */\n #assertActive() {\n if (!this.#active) {\n throw new TypeError(`${this.#name} scope has expired`);\n }\n }\n}\n\n/**\n * Attaches fresh private state to a callback scope.\n *\n * @param {object} scope - Callback-only builder.\n * @param {object} definition - Scope record and public name.\n * @returns {void} The scope becomes active.\n */\nfunction initializeScope(scope, definition) {\n records.set(scope, new ScopeState(definition));\n}\n\n/**\n * Reads callback state or reproduces the public expiry failure.\n *\n * @param {object} scope - Callback-only builder.\n * @param {string} fallbackName - Public name for invalid receivers.\n * @returns {ScopeState} Active private scope state.\n * @throws {TypeError} When the receiver is not an active scope.\n */\nfunction scopeState(scope, fallbackName) {\n const state = records.get(scope);\n\n if (!state) {\n throw new TypeError(`${fallbackName} scope has expired`);\n }\n\n return state;\n}\n\n/**\n * Writes one copied value into an active callback record.\n *\n * @param {object} scope - Active callback builder.\n * @param {string} name - Record property being configured.\n * @param {unknown} value - Caller-controlled property value.\n * @returns {void} The callback value becomes the local override.\n */\nfunction writeScopeValue(scope, name, value) {\n let fallbackName = \"Builder\";\n\n if (ANNOTATION_PROPERTIES.has(name)) {\n fallbackName = \"Annotation\";\n }\n\n if (TOOLTIP_PROPERTIES.has(name)) {\n fallbackName = \"Tooltip\";\n }\n\n scopeState(scope, fallbackName).write(name, value);\n}\n\n/**\n * Common dataset configuration shared by every series family.\n */\nclass DatasetBuilder {\n /**\n * Creates a callback-only dataset builder.\n *\n * @param {object} record - Detached dataset being configured.\n */\n constructor(record) {\n initializeScope(this, { record, name: \"Dataset\" });\n }\n\n /**\n * Chooses the dataset's explicit color.\n *\n * @param {string} value - Supported CSS color.\n * @returns {this} Active dataset scope.\n */\n color(value) {\n validateText(value, \"color\");\n scopeState(this, \"Dataset\").write(\"color\", value);\n\n return this;\n }\n\n /**\n * Chooses dataset opacity.\n *\n * @param {number} value - Opacity from zero through one.\n * @returns {this} Active dataset scope.\n */\n opacity(value) {\n validateOpacity(value, \"opacity\");\n scopeState(this, \"Dataset\").write(\"opacity\", value);\n\n return this;\n }\n\n /**\n * Formats this dataset's displayed values.\n *\n * @param {(value: number, context: object) => string} formatter - Synchronous display formatter.\n * @returns {this} Active dataset scope.\n */\n formatValue(formatter) {\n validateFunction(formatter, \"formatValue\");\n writeScopeValue(this, \"formatValue\", formatter);\n\n return this;\n }\n}\n\n/**\n * Adds line-only dataset conventions to the common callback scope.\n */\nclass LineDatasetBuilder extends DatasetBuilder {\n /**\n * Enables or configures the dataset's gradient area.\n *\n * @param {boolean | object} [isEnabled=true] - Gradient switch or opacity endpoints.\n * @returns {this} Active line dataset scope.\n */\n gradient(isEnabled = true) {\n validateGradient(isEnabled);\n writeScopeValue(this, \"gradient\", isEnabled);\n\n return this;\n }\n\n /**\n * Chooses curve smoothing for this dataset.\n *\n * @param {boolean} [isEnabled=true] - Whether smoothing is enabled.\n * @returns {this} Active line dataset scope.\n */\n smooth(isEnabled = true) {\n validateBoolean(isEnabled, \"smooth\");\n writeScopeValue(this, \"smooth\", isEnabled);\n\n return this;\n }\n\n /**\n * Chooses dot visibility for this dataset.\n *\n * @param {boolean} visible - Whether points are drawn.\n * @returns {this} Active line dataset scope.\n */\n dots(visible) {\n validateBoolean(visible, \"dots\");\n writeScopeValue(this, \"dots\", visible);\n\n return this;\n }\n\n /**\n * Chooses the dot radius for this dataset.\n *\n * @param {number} value - Dot radius in CSS pixels.\n * @returns {this} Active line dataset scope.\n */\n dotSize(value) {\n validateNumber(value, \"dotSize\", 0);\n writeScopeValue(this, \"dotSize\", value);\n\n return this;\n }\n\n /**\n * Chooses line visibility while retaining other marks.\n *\n * @param {boolean} visible - Whether the line stroke is drawn.\n * @returns {this} Active line dataset scope.\n */\n line(visible) {\n validateBoolean(visible, \"line\");\n writeScopeValue(this, \"line\", visible);\n\n return this;\n }\n\n /**\n * Enables or disables a solid area fill.\n *\n * @param {boolean} [isEnabled=true] - Whether an area is drawn.\n * @returns {this} Active line dataset scope.\n */\n area(isEnabled = true) {\n validateBoolean(isEnabled, \"area\");\n writeScopeValue(this, \"area\", isEnabled);\n\n return this;\n }\n\n /**\n * Chooses this dataset's stroke width.\n *\n * @param {number} value - Stroke width in CSS pixels.\n * @returns {this} Active line dataset scope.\n */\n strokeWidth(value) {\n validateNumber(value, \"strokeWidth\", 0);\n writeScopeValue(this, \"strokeWidth\", value);\n\n return this;\n }\n}\n\n/**\n * Adds bar-only corner radius to the common dataset scope.\n */\nclass BarDatasetBuilder extends DatasetBuilder {\n /**\n * Chooses corner radius for this bar dataset.\n *\n * @param {number} value - Radius in CSS pixels.\n * @returns {this} Active bar dataset scope.\n */\n radius(value) {\n validateNumber(value, \"radius\", 0);\n writeScopeValue(this, \"radius\", value);\n\n return this;\n }\n}\n\n/**\n * Configures chart tooltip display formatting inside one callback.\n */\nclass SeriesTooltipBuilder {\n /**\n * Creates a callback-only tooltip builder.\n *\n * @param {object} record - Detached tooltip configuration.\n */\n constructor(record) {\n initializeScope(this, { record, name: \"Tooltip\" });\n }\n\n /**\n * Formats category labels shown by the tooltip.\n *\n * @param {(label: string | number, context: object) => string} formatter - Synchronous label formatter.\n * @returns {this} Active tooltip scope.\n */\n formatLabel(formatter) {\n validateFunction(formatter, \"formatLabel\");\n scopeState(this, \"Tooltip\").write(\"formatLabel\", formatter);\n\n return this;\n }\n\n /**\n * Formats numeric values shown by the tooltip.\n *\n * @param {(value: number, context: object) => string} formatter - Synchronous value formatter.\n * @returns {this} Active tooltip scope.\n */\n formatValue(formatter) {\n validateFunction(formatter, \"tooltipValue\");\n writeScopeValue(this, \"tooltipValue\", formatter);\n\n return this;\n }\n}\n\n/**\n * Configures the Cartesian value axis inside one callback.\n */\nclass AxisBuilder {\n /**\n * Creates a callback-only axis builder.\n *\n * @param {object} record - Detached axis configuration.\n */\n constructor(record) {\n initializeScope(this, { record, name: \"Y-axis\" });\n }\n\n /**\n * Places the value axis on the requested side.\n *\n * @param {\"left\" | \"right\"} value - Logical axis position.\n * @returns {this} Active axis scope.\n */\n position(value) {\n validatePosition(value);\n writeScopeValue(this, \"position\", value);\n\n return this;\n }\n\n /**\n * Formats numeric value-axis ticks.\n *\n * @param {(value: number, context: object) => string} formatter - Synchronous tick formatter.\n * @returns {this} Active axis scope.\n */\n formatValue(formatter) {\n validateFunction(formatter, \"axisValue\");\n writeScopeValue(this, \"axisValue\", formatter);\n\n return this;\n }\n}\n\n/**\n * Common annotation presentation shared by markers and regions.\n */\nclass AnnotationBuilder {\n /**\n * Creates one callback-only annotation builder.\n *\n * @param {object} record - Detached annotation input.\n * @param {string} name - Public scope name used by expiry errors.\n */\n constructor(record, name) {\n initializeScope(this, { record, name });\n }\n\n /**\n * Chooses the annotation's primary color.\n *\n * @param {string} value - Supported CSS color.\n * @returns {this} Active annotation scope.\n */\n color(value) {\n validateText(value, \"color\");\n writeScopeValue(this, \"color\", value);\n\n return this;\n }\n\n /**\n * Chooses annotation opacity.\n *\n * @param {number} value - Opacity from zero through one.\n * @returns {this} Active annotation scope.\n */\n opacity(value) {\n validateOpacity(value, \"opacity\");\n writeScopeValue(this, \"opacity\", value);\n\n return this;\n }\n\n /**\n * Places the annotation label along its visual extent.\n *\n * @param {\"start\" | \"center\" | \"end\"} value - Logical label position.\n * @returns {this} Active annotation scope.\n */\n labelPosition(value) {\n validateLabelPosition(value);\n writeScopeValue(this, \"labelPosition\", value);\n\n return this;\n }\n\n /**\n * Chooses annotation label color independently from its geometry.\n *\n * @param {string} value - Supported CSS color.\n * @returns {this} Active annotation scope.\n */\n labelColor(value) {\n validateText(value, \"labelColor\");\n writeScopeValue(this, \"labelColor\", value);\n\n return this;\n }\n\n /**\n * Chooses whether annotation values expand automatic domains.\n *\n * @param {boolean} isIncluded - Whether the annotation participates in domain calculation.\n * @returns {this} Active annotation scope.\n */\n includeInDomain(isIncluded) {\n validateBoolean(isIncluded, \"includeInDomain\");\n writeScopeValue(this, \"includeInDomain\", isIncluded);\n\n return this;\n }\n\n /**\n * Formats visible and accessible annotation labels.\n *\n * @param {(...values: unknown[]) => string} formatter - Synchronous label formatter.\n * @returns {this} Active annotation scope.\n */\n formatLabel(formatter) {\n validateFunction(formatter, \"formatLabel\");\n writeScopeValue(this, \"formatLabel\", formatter);\n\n return this;\n }\n}\n\n/**\n * Configures line-specific marker presentation.\n */\nclass MarkerBuilder extends AnnotationBuilder {\n /**\n * Creates an active marker callback scope.\n *\n * @param {object} record - Detached marker input.\n */\n constructor(record) {\n super(record, \"Marker\");\n }\n\n /**\n * Chooses marker stroke width.\n *\n * @param {number} value - Width in non-scaling CSS pixels.\n * @returns {this} Active marker scope.\n */\n width(value) {\n validateNumber(value, \"width\", 0);\n writeScopeValue(this, \"width\", value);\n\n return this;\n }\n\n /**\n * Chooses a named marker line pattern.\n *\n * @param {\"solid\" | \"dashed\" | \"dotted\"} value - Built-in line pattern.\n * @returns {this} Active marker scope.\n */\n lineStyle(value) {\n validateLineStyle(value);\n writeScopeValue(this, \"lineStyle\", value);\n\n return this;\n }\n\n /**\n * Chooses an explicit marker dash pattern.\n *\n * @param {readonly number[]} pattern - Alternating dash and gap lengths.\n * @returns {this} Active marker scope.\n */\n dash(pattern) {\n validateDash(pattern);\n writeScopeValue(this, \"dash\", pattern);\n\n return this;\n }\n}\n\n/**\n * Configures range-region presentation.\n */\nclass RegionBuilder extends AnnotationBuilder {\n /**\n * Creates an active region callback scope.\n *\n * @param {object} record - Detached region input.\n */\n constructor(record) {\n super(record, \"Region\");\n }\n}\n\n/**\n * Configures date formatting shared by temporal tooltips.\n */\nclass DateTooltipBuilder {\n /**\n * Creates an active date-aware tooltip scope.\n *\n * @param {object} record - Detached tooltip formatter record.\n * @param {string} name - Public scope name used by expiry errors.\n */\n constructor(record, name) {\n initializeScope(this, { record, name });\n }\n\n /**\n * Formats calendar dates shown by the tooltip.\n *\n * @param {(date: Date) => string} formatter - Synchronous date formatter.\n * @returns {this} Active temporal tooltip scope.\n */\n formatDate(formatter) {\n validateFunction(formatter, \"formatDate\");\n writeScopeValue(this, \"formatDate\", formatter);\n\n return this;\n }\n}\n\n/**\n * Configures heatmap date and count formatting.\n */\nclass HeatmapTooltipBuilder extends DateTooltipBuilder {\n /**\n * Creates an active heatmap tooltip scope.\n *\n * @param {object} record - Detached tooltip formatter record.\n */\n constructor(record) {\n super(record, \"Heatmap tooltip\");\n }\n\n /**\n * Formats heatmap counts shown by the tooltip.\n *\n * @param {(value: number, context: object) => string} formatter - Synchronous value formatter.\n * @returns {this} Active heatmap tooltip scope.\n */\n formatValue(formatter) {\n validateFunction(formatter, \"formatValue\");\n scopeState(this, \"Heatmap tooltip\").write(\"formatValue\", formatter);\n\n return this;\n }\n}\n\n/**\n * Configures timesheet dates and durations shown by the tooltip.\n */\nclass TimesheetTooltipBuilder extends DateTooltipBuilder {\n /**\n * Creates an active timesheet tooltip scope.\n *\n * @param {object} record - Detached tooltip formatter record.\n */\n constructor(record) {\n super(record, \"Timesheet tooltip\");\n }\n\n /**\n * Formats task durations shown by the tooltip.\n *\n * @param {(milliseconds: number) => string} formatter - Synchronous duration formatter.\n * @returns {this} Active timesheet tooltip scope.\n */\n formatDuration(formatter) {\n validateFunction(formatter, \"formatDuration\");\n writeScopeValue(this, \"formatDuration\", formatter);\n\n return this;\n }\n}\n\n/**\n * Invokes a scoped configurator and expires its builder on every exit path.\n *\n * @param {object} scope - Callback-only builder.\n * @param {(scope: object) => void} configure - User configurator.\n * @returns {void} Callback return values are deliberately ignored.\n */\nfunction runScope(scope, configure) {\n try {\n configure(scope);\n } finally {\n scopeState(scope, \"Builder\").expire();\n }\n}\n\nexport {\n AxisBuilder,\n BarDatasetBuilder,\n DatasetBuilder,\n HeatmapTooltipBuilder,\n LineDatasetBuilder,\n MarkerBuilder,\n RegionBuilder,\n SeriesTooltipBuilder,\n TimesheetTooltipBuilder,\n runScope,\n};\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{validateBuilderOption as t,validateLabels as e}from"./BuilderValidation.js";var s=/* @__PURE__ */new Set(["pie","donut","percentage","polar-area"]),r=/* @__PURE__ */new Set(["line","bar","scatter","mixed","bubble"]),a=/* @__PURE__ */new Set(["heatmap","timesheet"]),i=/* @__PURE__ */new WeakMap;function n(t){return t instanceof Date?new Date(t.valueOf()):Array.isArray(t)?t.map(t=>n(t)):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).map(([t,e])=>[t,n(e)])):t}var o=class{#t;#e;#s;#r;#a=!1;#i={};#n=/* @__PURE__ */new Set;#o={datasets:[]};constructor(t,{parent:e,type:s,mount:r}){this.#t=t,this.#e=e,this.#s=s,this.#r=r}assertActive(){if(this.#a)throw new TypeError("Chart builder has already been rendered")}option(e,s){return this.assertActive(),t(e,s),this.#i[e]=n(s),this.#t}explicitOption(t,e){return this.option(t,e),this.#n.add(t),this.#t}labels(t){return this.assertActive(),e(t),this.#o.labels=n(t),this.#t}data(t,e){return this.assertActive(),this.#o[t]=n(e),this.#t}append(t,e){return this.assertActive(),this.#o[t]??=[],this.#o[t].push(n(e)),this.#t}dataset(t){if(this.assertActive(),s.has(this.#s)&&this.#o.datasets.length>0)throw new TypeError(`${this.#s} accepts exactly one dataset`);return this.#o.datasets.push(t),this.#t}compile(){this.assertActive();const t=function(t,e){const s={...e};if(!0===s.frameless)for(const r of["axes","grid","valueLabels","legend","tooltip","dots"])t.has(r)||(s[r]=!1);return delete s.frameless,s}(this.#n,this.#i);return void 0!==t.startAngle&&(t.startAngle=(t.startAngle%360+360)%360),t.type=this.#s,t.data=function(t,e){if(r.has(e))return t;const s={...t};return Reflect.deleteProperty(s,"markers"),Reflect.deleteProperty(s,"regions"),a.has(e)&&Reflect.deleteProperty(s,"datasets"),s}(this.#o,this.#s),{parent:this.#e,options:t,mount:this.#r}}consume(){this.assertActive(),this.#a=!0}};function h(t,e){i.set(t,new o(t,e))}function p(t){const e=i.get(t);if(!e)throw new TypeError("Chart builder has already been rendered");return e.assertActive(),e}export{p as builderState,n as copyBuilderValue,h as initializeBuilder};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuilderState.js","names":["#owner","#parent","#type","#mount","#consumed","#options","#explicit","#data"],"sources":["../../../src/core/builders/BuilderState.js"],"sourcesContent":["import { validateBuilderOption, validateLabels } from \"./BuilderValidation.js\";\n\nconst FULL_CIRCLE_DEGREES = 360;\n\nconst COMPOSITION_TYPES = new Set([\n \"pie\",\n \"donut\",\n \"percentage\",\n \"polar-area\",\n]);\n\nconst CARTESIAN_TYPES = new Set([\n \"line\",\n \"bar\",\n \"scatter\",\n \"mixed\",\n \"bubble\",\n]);\n\nconst TEMPORAL_TYPES = new Set([\n \"heatmap\",\n \"timesheet\",\n]);\n\nconst states = new WeakMap();\n\n/**\n * Copies caller-owned authoring data while retaining formatter callbacks by reference.\n *\n * @param {unknown} value - Value crossing the fluent authoring boundary.\n * @returns {unknown} Independent arrays, records, and dates suitable for builder state.\n */\nfunction copyBuilderValue(value) {\n if (value instanceof Date) {\n return new Date(value.valueOf());\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => copyBuilderValue(item));\n }\n\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value).map(\n ([\n key,\n item,\n ]) => [\n key,\n copyBuilderValue(item),\n ],\n ),\n );\n }\n\n return value;\n}\n\n/**\n * Applies presentation defaults without overriding explicit choices.\n *\n * @param {Set<string>} explicit - Options selected explicitly by the caller.\n * @param {object} source - Detached builder options.\n * @returns {object} Compiled presentation options.\n */\nfunction presentationOptions(explicit, source) {\n const options = { ...source };\n\n if (options.frameless === true) {\n for (const setting of [\n \"axes\",\n \"grid\",\n \"valueLabels\",\n \"legend\",\n \"tooltip\",\n \"dots\",\n ]) {\n if (!explicit.has(setting)) {\n options[setting] = false;\n }\n }\n }\n\n delete options.frameless;\n\n return options;\n}\n\n/**\n * Removes authoring collections unsupported by the selected chart family.\n *\n * @param {object} source - Detached builder data.\n * @param {string} type - Requested chart type.\n * @returns {object} Data accepted by the selected renderer.\n */\nfunction familyData(source, type) {\n if (CARTESIAN_TYPES.has(type)) {\n return source;\n }\n\n const data = { ...source };\n Reflect.deleteProperty(data, \"markers\");\n Reflect.deleteProperty(data, \"regions\");\n\n if (TEMPORAL_TYPES.has(type)) {\n Reflect.deleteProperty(data, \"datasets\");\n }\n\n return data;\n}\n\n/**\n * Owns mutable fluent-authoring state and its single-use lifecycle.\n */\nclass BuilderState {\n #owner;\n #parent;\n #type;\n #mount;\n #consumed = false;\n #options = {};\n #explicit = new Set();\n #data = { datasets: [] };\n\n /**\n * Creates private state for one public builder.\n *\n * @param {object} owner - Public fluent builder returned by writes.\n * @param {object} definition - Builder rendering definition.\n * @param {object} definition.parent - Chart factory receiving compiled options.\n * @param {string} definition.type - Requested chart type.\n * @param {Element|string} definition.mount - Chart mount target.\n */\n constructor(owner, { parent, type, mount }) {\n this.#owner = owner;\n this.#parent = parent;\n this.#type = type;\n this.#mount = mount;\n }\n\n /**\n * Rejects access after successful rendering.\n *\n * @returns {void} Active builders continue unchanged.\n * @throws {TypeError} When this builder was consumed.\n */\n assertActive() {\n if (this.#consumed) {\n throw new TypeError(\"Chart builder has already been rendered\");\n }\n }\n\n /**\n * Validates and records one chart option.\n *\n * @param {string} name - Internal option name.\n * @param {unknown} value - Caller-controlled option value.\n * @returns {object} Public fluent builder.\n */\n option(name, value) {\n this.assertActive();\n validateBuilderOption(name, value);\n this.#options[name] = copyBuilderValue(value);\n\n return this.#owner;\n }\n\n /**\n * Records an option that must win over presentation defaults.\n *\n * @param {string} name - Internal option name.\n * @param {unknown} value - Caller-controlled option value.\n * @returns {object} Public fluent builder.\n */\n explicitOption(name, value) {\n this.option(name, value);\n this.#explicit.add(name);\n\n return this.#owner;\n }\n\n /**\n * Validates and records category labels.\n *\n * @param {unknown} values - Candidate label collection.\n * @returns {object} Public fluent builder.\n */\n labels(values) {\n this.assertActive();\n validateLabels(values);\n this.#data.labels = copyBuilderValue(values);\n\n return this.#owner;\n }\n\n /**\n * Records one chart-family data value.\n *\n * @param {string} name - Data property name.\n * @param {unknown} value - Caller-controlled data value.\n * @returns {object} Public fluent builder.\n */\n data(name, value) {\n this.assertActive();\n this.#data[name] = copyBuilderValue(value);\n\n return this.#owner;\n }\n\n /**\n * Appends one value to an authoring collection.\n *\n * @param {string} collection - Data collection name.\n * @param {unknown} value - Caller-controlled collection item.\n * @returns {object} Public fluent builder.\n */\n append(collection, value) {\n this.assertActive();\n this.#data[collection] ??= [];\n this.#data[collection].push(copyBuilderValue(value));\n\n return this.#owner;\n }\n\n /**\n * Adds a configured dataset under family cardinality rules.\n *\n * @param {object} dataset - Detached dataset record.\n * @returns {object} Public fluent builder.\n * @throws {TypeError} When a composition chart already has a dataset.\n */\n dataset(dataset) {\n this.assertActive();\n if (COMPOSITION_TYPES.has(this.#type) && this.#data.datasets.length > 0) {\n throw new TypeError(`${this.#type} accepts exactly one dataset`);\n }\n\n this.#data.datasets.push(dataset);\n\n return this.#owner;\n }\n\n /**\n * Compiles current authoring state into one renderer request.\n *\n * @returns {object} Parent factory, mount target, and normalized options.\n */\n compile() {\n this.assertActive();\n const options = presentationOptions(this.#explicit, this.#options);\n\n if (options.startAngle !== undefined) {\n options.startAngle =\n ((options.startAngle % FULL_CIRCLE_DEGREES) + FULL_CIRCLE_DEGREES) % FULL_CIRCLE_DEGREES;\n }\n\n options.type = this.#type;\n options.data = familyData(this.#data, this.#type);\n\n return {\n parent: this.#parent,\n options,\n mount: this.#mount,\n };\n }\n\n /**\n * Marks this builder as successfully rendered.\n *\n * @returns {void} Later fluent calls fail permanently.\n */\n consume() {\n this.assertActive();\n this.#consumed = true;\n }\n}\n\n/**\n * Attaches fresh private state to a public builder.\n *\n * @param {object} builder - Public fluent builder.\n * @param {object} definition - Builder rendering definition.\n * @returns {void} The builder becomes active.\n */\nfunction initializeBuilder(builder, definition) {\n states.set(builder, new BuilderState(builder, definition));\n}\n\n/**\n * Reads live builder state and rejects every operation after successful rendering.\n *\n * @param {object} builder - Builder whose authoring state is required.\n * @returns {object} Mutable module-private builder state.\n * @throws {TypeError} When the builder has already produced a mounted chart.\n */\nfunction builderState(builder) {\n const state = states.get(builder);\n\n if (!state) {\n throw new TypeError(\"Chart builder has already been rendered\");\n }\n\n state.assertActive();\n\n return state;\n}\n\nexport { builderState, copyBuilderValue, initializeBuilder };\n"],"mappings":"mFAEA,IAEM,iBAAoB,IAAI,IAAI,CAChC,MACA,QACA,aACA,eAGI,iBAAkB,IAAI,IAAI,CAC9B,OACA,MACA,UACA,QACA,WAGI,iBAAiB,IAAI,IAAI,CAC7B,UACA,cAGI,iBAAS,IAAI,QAQnB,SAAS,EAAiB,GACxB,OAAI,aAAiB,KACZ,IAAI,KAAK,EAAM,WAGpB,MAAM,QAAQ,GACT,EAAM,IAAK,GAAS,EAAiB,IAG1C,GAA0B,iBAAV,EACX,OAAO,YACZ,OAAO,QAAQ,GAAO,IAAA,EAElB,EACA,KACI,CACJ,EACA,EAAiB,MAMlB,CACT,CA0DA,IAAM,EAAN,MACE,GACA,GACA,GACA,GACA,IAAY,EACZ,GAAW,CAAC,EACZ,kBAAY,IAAI,IAChB,GAAQ,CAAE,SAAU,IAWpB,WAAA,CAAY,GAAO,OAAE,EAAA,KAAQ,EAAA,MAAM,IACjC,MAAKA,EAAS,EACd,MAAKC,EAAU,EACf,MAAKC,EAAQ,EACb,MAAKC,EAAS,CAChB,CAQA,YAAA,GACE,GAAI,MAAKC,EACP,MAAM,IAAI,UAAU,0CAExB,CASA,MAAA,CAAO,EAAM,GAKX,OAJA,KAAK,eACL,EAAsB,EAAM,GAC5B,MAAKC,EAAS,GAAQ,EAAiB,GAEhC,MAAKL,CACd,CASA,cAAA,CAAe,EAAM,GAInB,OAHA,KAAK,OAAO,EAAM,GAClB,MAAKM,EAAU,IAAI,GAEZ,MAAKN,CACd,CAQA,MAAA,CAAO,GAKL,OAJA,KAAK,eACL,EAAe,GACf,MAAKO,EAAM,OAAS,EAAiB,GAE9B,MAAKP,CACd,CASA,IAAA,CAAK,EAAM,GAIT,OAHA,KAAK,eACL,MAAKO,EAAM,GAAQ,EAAiB,GAE7B,MAAKP,CACd,CASA,MAAA,CAAO,EAAY,GAKjB,OAJA,KAAK,eACL,MAAKO,EAAM,KAAgB,GAC3B,MAAKA,EAAM,GAAY,KAAK,EAAiB,IAEtC,MAAKP,CACd,CASA,OAAA,CAAQ,GAEN,GADA,KAAK,eACD,EAAkB,IAAI,MAAKE,IAAU,MAAKK,EAAM,SAAS,OAAS,EACpE,MAAM,IAAI,UAAU,GAAG,MAAKL,iCAK9B,OAFA,MAAKK,EAAM,SAAS,KAAK,GAElB,MAAKP,CACd,CAOA,OAAA,GACE,KAAK,eACL,MAAM,EAxLV,SAA6B,EAAU,GACrC,MAAM,EAAU,IAAK,GAErB,IAA0B,IAAtB,EAAQ,UACL,IAAA,MAAM,IAAW,CACpB,OACA,OACA,cACA,SACA,UACA,QAEK,EAAS,IAAI,KAChB,EAAQ,IAAW,GAOzB,cAFO,EAAQ,UAER,CACT,CAmKoB,CAAoB,MAAKM,EAAW,MAAKD,GAUzD,YAR2B,IAAvB,EAAQ,aACV,EAAQ,YACJ,EAAQ,WA3PU,cA8PxB,EAAQ,KAAO,MAAKH,EACpB,EAAQ,KAlKZ,SAAoB,EAAQ,GAC1B,GAAI,EAAgB,IAAI,GACtB,OAAO,EAGT,MAAM,EAAO,IAAK,GAQlB,OAPA,QAAQ,eAAe,EAAM,WAC7B,QAAQ,eAAe,EAAM,WAEzB,EAAe,IAAI,IACrB,QAAQ,eAAe,EAAM,YAGxB,CACT,CAoJmB,CAAW,MAAKK,EAAO,MAAKL,GAEpC,CACL,OAAQ,MAAKD,EACb,UACA,MAAO,MAAKE,EAEhB,CAOA,OAAA,GACE,KAAK,eACL,MAAKC,GAAY,CACnB,GAUF,SAAS,EAAkB,EAAS,GAClC,EAAO,IAAI,EAAS,IAAI,EAAa,EAAS,GAChD,CASA,SAAS,EAAa,GACpB,MAAM,EAAQ,EAAO,IAAI,GAEzB,IAAK,EACH,MAAM,IAAI,UAAU,2CAKtB,OAFA,EAAM,eAEC,CACT"}
@@ -0,0 +1 @@
1
+ import{isBoolean as e,isChoice as t,isNonEmptyText as r,isNumberAtLeast as o,isOpacity as n,isRecord as i,unknownKey as a}from"../../support/Validation.js";var s=/* @__PURE__ */new Set(["title","description","ariaLabel","countLabel"]),u=/* @__PURE__ */new Set(["width","height"]),f=/* @__PURE__ */new Set(["dotSize","strokeWidth","radius","cornerRadius"]),l=/* @__PURE__ */new Set(["smooth","dots","line","area","frameless","axes","grid","valueLabels","legend","tooltip","stacked"]),p=/* @__PURE__ */new Set(["onSelect","formatLabel","formatValue","formatDate","formatDuration","formatTick","axisFormatValue","tooltipFormatDate","tooltipFormatDuration","tooltipFormatLabel","tooltipFormatValue"]);function m(e,t){if(!r(e))throw new TypeError(`${t} must be a non-empty string`)}function w(e,t,r){if(!o(e,r))throw new TypeError(`${t} must be a finite number of at least ${r}`)}function b(t,r){if(!e(t))throw new TypeError(`${r} must be a boolean`)}function c(e,t){if("function"!=typeof e)throw new TypeError(`${t} must be a function`)}function h(e,t){s.has(e)&&m(t,e),u.has(e)&&w(t,e,Number.EPSILON),f.has(e)&&w(t,e,0),l.has(e)&&b(t,e),p.has(e)&&c(t,e),function(e,t){if("colors"===e&&function(e){if(!Array.isArray(e)||0===e.length)throw new TypeError("colors must be a non-empty array");for(const t of e)m(t,"color")}(t),!("maxSlices"!==e||Number.isSafeInteger(t)&&o(t,1)))throw new TypeError("maxSlices must be a positive integer");if("startAngle"===e&&!Number.isFinite(t))throw new TypeError("startAngle must be a finite number");if("padAngle"===e&&function(e){return!Number.isFinite(e)||e<0||e>=360}(t))throw new TypeError("padAngle must be a finite number from 0 up to 360");"gradient"===e&&y(t)}(e,t)}function y(e){if("boolean"==typeof e)return;if(!i(e))throw new TypeError("gradient must be a boolean or GradientOptions object");const t=a(e,["fromOpacity","toOpacity"]);if(t)throw new TypeError(`Unsupported gradient option: ${t}`);for(const r of Object.values(e))if(w(r,"gradient opacity",0),!n(r))throw new TypeError("gradient opacity must be from 0 through 1")}function d(e){if(!Array.isArray(e))throw new TypeError("labels must be an array");for(const t of e)m(t,"label")}function g(e){if(!i(e)||0===Object.keys(e).length)throw new TypeError("points must contain at least one entry");if(Object.values(e).some(e=>!Number.isFinite(e)))throw new TypeError("heatmap point values must be finite numbers")}function E(e){if(!i(e))throw new TypeError("task must be an object or positional task arguments");const t=a(e,/* @__PURE__ */new Set(["label","start","end","group","color"]));if(t)throw new TypeError(`Unsupported task key: ${t}`);m(e.label,"task label"),void 0!==e.group&&m(e.group,"task group")}function T(e,t){if(w(e,t,0),!n(e))throw new TypeError(`${t} must be from 0 through 1`)}function S(e){if(!t(e,["left","right"]))throw new TypeError("position must be left or right")}function v(e){if(!t(e,["solid","dashed","dotted"]))throw new TypeError("lineStyle must be solid, dashed, or dotted")}function k(e){if(!t(e,["start","center","end"]))throw new TypeError("labelPosition must be start, center, or end")}function A(e){if(!Array.isArray(e)||0===e.length)throw new TypeError("dash must be a non-empty array");if(e.some(e=>!Number.isFinite(e)||e<0)||e.every(e=>0===e))throw new TypeError("dash values must be non-negative with at least one positive value")}export{b as validateBoolean,h as validateBuilderOption,A as validateDash,c as validateFunction,y as validateGradient,g as validateHeatmapPoints,k as validateLabelPosition,d as validateLabels,v as validateLineStyle,w as validateNumber,T as validateOpacity,S as validatePosition,E as validateTask,m as validateText};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuilderValidation.js","names":[],"sources":["../../../src/core/builders/BuilderValidation.js"],"sourcesContent":["import {\n isBoolean,\n isChoice,\n isNonEmptyText,\n isNumberAtLeast,\n isOpacity,\n isRecord,\n unknownKey,\n} from \"../../support/Validation.js\";\n\nconst STRING_OPTIONS = new Set([\n \"title\",\n \"description\",\n \"ariaLabel\",\n \"countLabel\",\n]);\n\nconst POSITIVE_OPTIONS = new Set([\n \"width\",\n \"height\",\n]);\n\nconst NON_NEGATIVE_OPTIONS = new Set([\n \"dotSize\",\n \"strokeWidth\",\n \"radius\",\n \"cornerRadius\",\n]);\n\nconst BOOLEAN_OPTIONS = new Set([\n \"smooth\",\n \"dots\",\n \"line\",\n \"area\",\n \"frameless\",\n \"axes\",\n \"grid\",\n \"valueLabels\",\n \"legend\",\n \"tooltip\",\n \"stacked\",\n]);\n\nconst FUNCTION_OPTIONS = new Set([\n \"onSelect\",\n \"formatLabel\",\n \"formatValue\",\n \"formatDate\",\n \"formatDuration\",\n \"formatTick\",\n \"axisFormatValue\",\n \"tooltipFormatDate\",\n \"tooltipFormatDuration\",\n \"tooltipFormatLabel\",\n \"tooltipFormatValue\",\n]);\n\nconst FULL_CIRCLE_DEGREES = 360;\n\n/**\n * Requires a non-empty user-facing string.\n *\n * @param {unknown} value - Candidate label or text.\n * @param {string} name - Public concept named in failures.\n * @returns {void} Valid text passes unchanged.\n */\nfunction validateText(value, name) {\n if (!isNonEmptyText(value)) {\n throw new TypeError(`${name} must be a non-empty string`);\n }\n}\n\n/**\n * Requires a finite numeric value within a lower bound.\n *\n * @param {unknown} value - Candidate number.\n * @param {string} name - Public concept named in failures.\n * @param {number} minimum - Inclusive lower bound.\n * @returns {void} Valid numbers pass unchanged.\n */\nfunction validateNumber(value, name, minimum) {\n if (!isNumberAtLeast(value, minimum)) {\n throw new TypeError(`${name} must be a finite number of at least ${minimum}`);\n }\n}\n\n/**\n * Requires an actual boolean rather than accepting truthy values.\n *\n * @param {unknown} value - Candidate switch.\n * @param {string} name - Public method name.\n * @returns {void} Boolean values pass unchanged.\n */\nfunction validateBoolean(value, name) {\n if (!isBoolean(value)) {\n throw new TypeError(`${name} must be a boolean`);\n }\n}\n\n/**\n * Requires a synchronous formatter or callback function.\n *\n * @param {unknown} value - Candidate callback.\n * @param {string} name - Public concept named in failures.\n * @returns {void} Functions pass unchanged.\n */\nfunction validateFunction(value, name) {\n if (typeof value !== \"function\") {\n throw new TypeError(`${name} must be a function`);\n }\n}\n\n/**\n * Validates independently decidable chart-level fluent arguments.\n *\n * @param {string} name - Internal option name matching the public concept.\n * @param {unknown} value - Candidate option value.\n * @returns {void} Valid values may be copied into builder state.\n */\nfunction validateBuilderOption(name, value) {\n if (STRING_OPTIONS.has(name)) {\n validateText(value, name);\n }\n\n if (POSITIVE_OPTIONS.has(name)) {\n validateNumber(value, name, Number.EPSILON);\n }\n\n if (NON_NEGATIVE_OPTIONS.has(name)) {\n validateNumber(value, name, 0);\n }\n\n if (BOOLEAN_OPTIONS.has(name)) {\n validateBoolean(value, name);\n }\n\n if (FUNCTION_OPTIONS.has(name)) {\n validateFunction(value, name);\n }\n\n validateSpecialOption(name, value);\n}\n\n/**\n * Validates structured and bounded chart-level options.\n *\n * @param {string} name - Internal option name.\n * @param {unknown} value - Candidate option value.\n * @returns {void} Valid special options pass unchanged.\n */\nfunction validateSpecialOption(name, value) {\n if (name === \"colors\") {\n validateColors(value);\n }\n\n if (name === \"maxSlices\" && (!Number.isSafeInteger(value) || !isNumberAtLeast(value, 1))) {\n throw new TypeError(\"maxSlices must be a positive integer\");\n }\n\n if (name === \"startAngle\" && !Number.isFinite(value)) {\n throw new TypeError(\"startAngle must be a finite number\");\n }\n\n if (name === \"padAngle\" && isInvalidPadAngle(value)) {\n throw new TypeError(\"padAngle must be a finite number from 0 up to 360\");\n }\n\n if (name === \"gradient\") {\n validateGradient(value);\n }\n}\n\n/**\n * Detects a value outside the supported sector-gap interval.\n *\n * @param {unknown} value - Candidate angular gap.\n * @returns {boolean} Whether the value is not finite or outside one circle.\n */\nfunction isInvalidPadAngle(value) {\n return !Number.isFinite(value) || value < 0 || value >= FULL_CIRCLE_DEGREES;\n}\n\n/**\n * Validates the palette's immediate structural contract.\n *\n * @param {unknown} values - Candidate color collection.\n * @returns {void} A non-empty string palette passes for render-time CSS checks.\n */\nfunction validateColors(values) {\n if (!Array.isArray(values) || values.length === 0) {\n throw new TypeError(\"colors must be a non-empty array\");\n }\n\n for (const value of values) {\n validateText(value, \"color\");\n }\n}\n\n/**\n * Validates gradient switches and opacity endpoints.\n *\n * @param {unknown} value - Boolean switch or endpoint record.\n * @returns {void} Supported gradient values pass unchanged.\n */\nfunction validateGradient(value) {\n if (typeof value === \"boolean\") {\n return;\n }\n\n if (!isRecord(value)) {\n throw new TypeError(\"gradient must be a boolean or GradientOptions object\");\n }\n\n const unknown = unknownKey(value, [\n \"fromOpacity\",\n \"toOpacity\",\n ]);\n\n if (unknown) {\n throw new TypeError(`Unsupported gradient option: ${unknown}`);\n }\n\n for (const endpoint of Object.values(value)) {\n validateNumber(endpoint, \"gradient opacity\", 0);\n if (!isOpacity(endpoint)) {\n throw new TypeError(\"gradient opacity must be from 0 through 1\");\n }\n }\n}\n\n/**\n * Validates category labels at the fluent call boundary.\n *\n * @param {unknown} labels - Candidate ordered labels.\n * @returns {void} A copied array can safely enter builder state.\n */\nfunction validateLabels(labels) {\n if (!Array.isArray(labels)) {\n throw new TypeError(\"labels must be an array\");\n }\n\n for (const label of labels) {\n validateText(label, \"label\");\n }\n}\n\n/**\n * Validates a non-empty heatmap point record.\n *\n * @param {unknown} value - Candidate date-to-count record.\n * @returns {void} Finite point collections pass unchanged.\n */\nfunction validateHeatmapPoints(value) {\n if (!isRecord(value) || Object.keys(value).length === 0) {\n throw new TypeError(\"points must contain at least one entry\");\n }\n\n if (Object.values(value).some((point) => !Number.isFinite(point))) {\n throw new TypeError(\"heatmap point values must be finite numbers\");\n }\n}\n\n/**\n * Validates the structured form of a timesheet task.\n *\n * @param {unknown} value - Candidate task record.\n * @returns {void} Supported task fields pass unchanged.\n */\nfunction validateTask(value) {\n if (!isRecord(value)) {\n throw new TypeError(\"task must be an object or positional task arguments\");\n }\n\n const allowed = new Set([\n \"label\",\n \"start\",\n \"end\",\n \"group\",\n \"color\",\n ]);\n\n const unknown = unknownKey(value, allowed);\n\n if (unknown) {\n throw new TypeError(`Unsupported task key: ${unknown}`);\n }\n\n validateText(value.label, \"task label\");\n if (value.group !== undefined) {\n validateText(value.group, \"task group\");\n }\n}\n\n/**\n * Validates one opacity value against its closed interval.\n *\n * @param {unknown} value - Candidate opacity.\n * @param {string} name - Public property name.\n * @returns {void} Values from zero through one pass unchanged.\n */\nfunction validateOpacity(value, name) {\n validateNumber(value, name, 0);\n if (!isOpacity(value)) {\n throw new TypeError(`${name} must be from 0 through 1`);\n }\n}\n\n/**\n * Validates a value-axis position.\n *\n * @param {unknown} value - Candidate logical side.\n * @returns {void} Supported positions pass unchanged.\n */\nfunction validatePosition(value) {\n if (\n !isChoice(value, [\n \"left\",\n \"right\",\n ])\n ) {\n throw new TypeError(\"position must be left or right\");\n }\n}\n\n/**\n * Validates a named annotation line pattern.\n *\n * @param {unknown} value - Candidate line style.\n * @returns {void} Supported styles pass unchanged.\n */\nfunction validateLineStyle(value) {\n if (\n !isChoice(value, [\n \"solid\",\n \"dashed\",\n \"dotted\",\n ])\n ) {\n throw new TypeError(\"lineStyle must be solid, dashed, or dotted\");\n }\n}\n\n/**\n * Validates an annotation label position.\n *\n * @param {unknown} value - Candidate logical position.\n * @returns {void} Supported positions pass unchanged.\n */\nfunction validateLabelPosition(value) {\n if (\n !isChoice(value, [\n \"start\",\n \"center\",\n \"end\",\n ])\n ) {\n throw new TypeError(\"labelPosition must be start, center, or end\");\n }\n}\n\n/**\n * Validates one explicit marker dash sequence.\n *\n * @param {unknown} value - Candidate dash and gap lengths.\n * @returns {void} A usable non-negative pattern passes unchanged.\n */\nfunction validateDash(value) {\n if (!Array.isArray(value) || value.length === 0) {\n throw new TypeError(\"dash must be a non-empty array\");\n }\n\n if (value.some((part) => !Number.isFinite(part) || part < 0) || value.every((part) => part === 0)) {\n throw new TypeError(\"dash values must be non-negative with at least one positive value\");\n }\n}\n\nexport {\n validateBoolean,\n validateBuilderOption,\n validateDash,\n validateFunction,\n validateGradient,\n validateHeatmapPoints,\n validateLabelPosition,\n validateLabels,\n validateLineStyle,\n validateNumber,\n validateOpacity,\n validatePosition,\n validateTask,\n validateText,\n};\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{validateBoolean as t}from"./BuilderValidation.js";import{builderState as r}from"./BuilderState.js";import{BarDatasetBuilder as e,DatasetBuilder as s,LineDatasetBuilder as a}from"./BuilderScopes.js";import{configuredDataset as i}from"./BuilderArguments.js";import{CartesianChartBuilder as o}from"./Builder.js";var n=class extends o{dataset(t,s,a){return r(this).dataset(i([t,s,a],e))}horizontal(e=!0){return t(e,"horizontal"),r(this).option("orientation",e?"horizontal":"vertical")}stacked(t=!0){return r(this).option("stacked",t)}radius(t){return r(this).option("radius",t)}},d=class extends o{dataset(t,e,a){return r(this).dataset(i([t,e,a],s))}dots(t){return r(this).explicitOption("dots",t)}},c=class extends o{line(t,e,s){const o=i([t,e,s],a);return r(this).dataset({...o,chartType:"line"})}bar(t,s,a){const o=i([t,s,a],e);return r(this).dataset({...o,chartType:"bar"})}scatter(t,e,a){const o=i([t,e,a],s);return r(this).dataset({...o,chartType:"scatter"})}dataset(t,o){const n={line:a,bar:e,scatter:s}[t?.chartType];if(!n)throw new TypeError("Mixed dataset chartType must be line, bar, or scatter");return r(this).dataset(i([t,o],n))}gradient(t=!0){return r(this).option("gradient",t)}};export{n as BarChartBuilder,c as MixedChartBuilder,d as ScatterChartBuilder};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CartesianBuilders.js","names":[],"sources":["../../../src/core/builders/CartesianBuilders.js"],"sourcesContent":["import { CartesianChartBuilder } from \"./Builder.js\";\nimport { configuredDataset } from \"./BuilderArguments.js\";\nimport { BarDatasetBuilder, DatasetBuilder, LineDatasetBuilder } from \"./BuilderScopes.js\";\nimport { builderState } from \"./BuilderState.js\";\nimport { validateBoolean } from \"./BuilderValidation.js\";\n\n/**\n * Adds bar orientation, stacking, and radius conventions to Cartesian authoring.\n */\nclass BarChartBuilder extends CartesianChartBuilder {\n /**\n * Appends one bar dataset with a bar-specific callback scope.\n *\n * @param {unknown} first - Values, name, or advanced dataset input.\n * @param {unknown} [second] - Values, color, or configurator.\n * @param {unknown} [third] - Named dataset color or configurator.\n * @returns {this} Current builder.\n */\n dataset(first, second, third) {\n return builderState(this).dataset(\n configuredDataset(\n [\n first,\n second,\n third,\n ],\n BarDatasetBuilder,\n ),\n );\n }\n\n /**\n * Chooses horizontal bar orientation.\n *\n * @param {boolean} [isEnabled=true] - Whether bars grow horizontally.\n * @returns {this} Current builder.\n */\n horizontal(isEnabled = true) {\n validateBoolean(isEnabled, \"horizontal\");\n\n return builderState(this).option(\"orientation\", isEnabled ? \"horizontal\" : \"vertical\");\n }\n\n /**\n * Chooses stacked rather than grouped bars.\n *\n * @param {boolean} [isEnabled=true] - Whether datasets stack at each category.\n * @returns {this} Current builder.\n */\n stacked(isEnabled = true) {\n return builderState(this).option(\"stacked\", isEnabled);\n }\n\n /**\n * Chooses whole-chart bar corner radius.\n *\n * @param {number} value - Radius in CSS pixels.\n * @returns {this} Current builder.\n */\n radius(value) {\n return builderState(this).option(\"radius\", value);\n }\n}\n\n/**\n * Authors independently positioned scatter datasets.\n */\nclass ScatterChartBuilder extends CartesianChartBuilder {\n /**\n * Appends one scatter dataset with common dataset capabilities.\n *\n * @param {unknown} first - Values, name, or advanced dataset input.\n * @param {unknown} [second] - Values, color, or configurator.\n * @param {unknown} [third] - Named dataset color or configurator.\n * @returns {this} Current builder.\n */\n dataset(first, second, third) {\n return builderState(this).dataset(\n configuredDataset(\n [\n first,\n second,\n third,\n ],\n DatasetBuilder,\n ),\n );\n }\n\n /**\n * Chooses scatter-dot visibility.\n *\n * @param {boolean} visible - Whether scatter marks are displayed.\n * @returns {this} Current builder.\n */\n dots(visible) {\n return builderState(this).explicitOption(\"dots\", visible);\n }\n}\n\n/**\n * Authors explicitly typed datasets for the mixed Cartesian grammar.\n */\nclass MixedChartBuilder extends CartesianChartBuilder {\n /**\n * Appends a line dataset without requiring an object type tag.\n *\n * @param {string} name - Human-readable series name.\n * @param {readonly number[]} values - Ordered line values.\n * @param {string | ((dataset: LineDatasetBuilder) => void)} [colorOrConfigure] - Local line presentation.\n * @returns {this} Current builder.\n */\n line(name, values, colorOrConfigure) {\n const dataset = configuredDataset(\n [\n name,\n values,\n colorOrConfigure,\n ],\n LineDatasetBuilder,\n );\n\n return builderState(this).dataset({ ...dataset, chartType: \"line\" });\n }\n\n /**\n * Appends a bar dataset without requiring an object type tag.\n *\n * @param {string} name - Human-readable series name.\n * @param {readonly number[]} values - Ordered bar values.\n * @param {string | ((dataset: BarDatasetBuilder) => void)} [colorOrConfigure] - Local bar presentation.\n * @returns {this} Current builder.\n */\n bar(name, values, colorOrConfigure) {\n const dataset = configuredDataset(\n [\n name,\n values,\n colorOrConfigure,\n ],\n BarDatasetBuilder,\n );\n\n return builderState(this).dataset({ ...dataset, chartType: \"bar\" });\n }\n\n /**\n * Appends a scatter dataset without requiring an object type tag.\n *\n * @param {string} name - Human-readable series name.\n * @param {readonly unknown[]} values - Ordered scatter coordinates.\n * @param {string | ((dataset: DatasetBuilder) => void)} [colorOrConfigure] - Local scatter presentation.\n * @returns {this} Current builder.\n */\n scatter(name, values, colorOrConfigure) {\n const dataset = configuredDataset(\n [\n name,\n values,\n colorOrConfigure,\n ],\n DatasetBuilder,\n );\n\n return builderState(this).dataset({ ...dataset, chartType: \"scatter\" });\n }\n\n /**\n * Appends an advanced object dataset whose type selects callback capabilities.\n *\n * @param {object} input - Dataset input containing a required chart type.\n * @param {(dataset: object) => void} [configure] - Type-specific local configurator.\n * @returns {this} Current builder.\n */\n dataset(input, configure) {\n const scopes = { line: LineDatasetBuilder, bar: BarDatasetBuilder, scatter: DatasetBuilder };\n const Scope = scopes[input?.chartType];\n\n if (!Scope) {\n throw new TypeError(\"Mixed dataset chartType must be line, bar, or scatter\");\n }\n\n return builderState(this).dataset(\n configuredDataset(\n [\n input,\n configure,\n ],\n Scope,\n ),\n );\n }\n\n /**\n * Enables gradient areas for every eligible mixed line dataset.\n *\n * @param {boolean | object} [isEnabled=true] - Gradient switch or opacity endpoints.\n * @returns {this} Current builder.\n */\n gradient(isEnabled = true) {\n return builderState(this).option(\"gradient\", isEnabled);\n }\n}\n\nexport { BarChartBuilder, MixedChartBuilder, ScatterChartBuilder };\n"],"mappings":"4TASA,IAAM,EAAN,cAA8B,EAS5B,OAAA,CAAQ,EAAO,EAAQ,GACrB,OAAO,EAAa,MAAM,QACxB,EACE,CACE,EACA,EACA,GAEF,GAGN,CAQA,UAAA,CAAW,GAAY,GAGrB,OAFA,EAAgB,EAAW,cAEpB,EAAa,MAAM,OAAO,cAAe,EAAY,aAAe,WAC7E,CAQA,OAAA,CAAQ,GAAY,GAClB,OAAO,EAAa,MAAM,OAAO,UAAW,EAC9C,CAQA,MAAA,CAAO,GACL,OAAO,EAAa,MAAM,OAAO,SAAU,EAC7C,GAMI,EAAN,cAAkC,EAShC,OAAA,CAAQ,EAAO,EAAQ,GACrB,OAAO,EAAa,MAAM,QACxB,EACE,CACE,EACA,EACA,GAEF,GAGN,CAQA,IAAA,CAAK,GACH,OAAO,EAAa,MAAM,eAAe,OAAQ,EACnD,GAMI,EAAN,cAAgC,EAS9B,IAAA,CAAK,EAAM,EAAQ,GACjB,MAAM,EAAU,EACd,CACE,EACA,EACA,GAEF,GAGF,OAAO,EAAa,MAAM,QAAQ,IAAK,EAAS,UAAW,QAC7D,CAUA,GAAA,CAAI,EAAM,EAAQ,GAChB,MAAM,EAAU,EACd,CACE,EACA,EACA,GAEF,GAGF,OAAO,EAAa,MAAM,QAAQ,IAAK,EAAS,UAAW,OAC7D,CAUA,OAAA,CAAQ,EAAM,EAAQ,GACpB,MAAM,EAAU,EACd,CACE,EACA,EACA,GAEF,GAGF,OAAO,EAAa,MAAM,QAAQ,IAAK,EAAS,UAAW,WAC7D,CASA,OAAA,CAAQ,EAAO,GAEb,MAAM,EAAQ,CADG,KAAM,EAAoB,IAAK,EAAmB,QAAS,GACvD,GAAO,WAE5B,IAAK,EACH,MAAM,IAAI,UAAU,yDAGtB,OAAO,EAAa,MAAM,QACxB,EACE,CACE,EACA,GAEF,GAGN,CAQA,QAAA,CAAS,GAAY,GACnB,OAAO,EAAa,MAAM,OAAO,WAAY,EAC/C"}
@@ -0,0 +1 @@
1
+ import{builderState as t}from"./BuilderState.js";import{DatasetBuilder as r}from"./BuilderScopes.js";import{configuredDataset as s}from"./BuilderArguments.js";import{SeriesChartBuilder as e}from"./Builder.js";var i=class extends e{dataset(e,i,n){return t(this).dataset(s([e,i,n],r))}},n=class extends i{maxSlices(r){return t(this).option("maxSlices",r)}startAngle(r){return t(this).option("startAngle",r)}padAngle(r){return t(this).option("padAngle",r)}cornerRadius(r){return t(this).option("cornerRadius",r)}},o=class extends i{maxSlices(r){return t(this).option("maxSlices",r)}radius(r){return t(this).option("radius",r)}},a=class extends i{padAngle(r){return t(this).option("padAngle",r)}cornerRadius(r){return t(this).option("cornerRadius",r)}},d=class extends i{strokeWidth(r){return t(this).option("strokeWidth",r)}};export{o as PercentageChartBuilder,a as PolarAreaChartBuilder,d as RadarChartBuilder,n as SectorChartBuilder};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompositionBuilders.js","names":[],"sources":["../../../src/core/builders/CompositionBuilders.js"],"sourcesContent":["import { SeriesChartBuilder } from \"./Builder.js\";\nimport { configuredDataset } from \"./BuilderArguments.js\";\nimport { DatasetBuilder } from \"./BuilderScopes.js\";\nimport { builderState } from \"./BuilderState.js\";\n\n/**\n * Adds one-or-more numeric dataset authoring to radial and composition charts.\n */\nclass NumericSeriesBuilder extends SeriesChartBuilder {\n /**\n * Appends one numeric dataset with common local presentation.\n *\n * @param {unknown} first - Values, name, or advanced dataset input.\n * @param {unknown} [second] - Values, color, or configurator.\n * @param {unknown} [third] - Named dataset color or configurator.\n * @returns {this} Current builder.\n */\n dataset(first, second, third) {\n return builderState(this).dataset(\n configuredDataset(\n [\n first,\n second,\n third,\n ],\n DatasetBuilder,\n ),\n );\n }\n}\n\n/**\n * Authors pie and donut sector conventions shared by both circular forms.\n */\nclass SectorChartBuilder extends NumericSeriesBuilder {\n /**\n * Limits visible slices and combines the remainder.\n *\n * @param {number} value - Positive maximum slice count.\n * @returns {this} Current builder.\n */\n maxSlices(value) {\n return builderState(this).option(\"maxSlices\", value);\n }\n\n /**\n * Rotates the first sector around the circle.\n *\n * @param {number} degrees - Finite clockwise angle in degrees.\n * @returns {this} Current builder.\n */\n startAngle(degrees) {\n return builderState(this).option(\"startAngle\", degrees);\n }\n\n /**\n * Chooses angular spacing between sectors.\n *\n * @param {number} degrees - Finite gap angle below one circle.\n * @returns {this} Current builder.\n */\n padAngle(degrees) {\n return builderState(this).option(\"padAngle\", degrees);\n }\n\n /**\n * Chooses sector corner radius.\n *\n * @param {number} value - Non-negative radius in CSS pixels.\n * @returns {this} Current builder.\n */\n cornerRadius(value) {\n return builderState(this).option(\"cornerRadius\", value);\n }\n}\n\n/**\n * Authors a compact percentage composition strip.\n */\nclass PercentageChartBuilder extends NumericSeriesBuilder {\n /**\n * Limits visible segments and combines the remainder.\n *\n * @param {number} value - Positive maximum segment count.\n * @returns {this} Current builder.\n */\n maxSlices(value) {\n return builderState(this).option(\"maxSlices\", value);\n }\n\n /**\n * Chooses percentage-segment corner radius.\n *\n * @param {number} value - Non-negative radius in CSS pixels.\n * @returns {this} Current builder.\n */\n radius(value) {\n return builderState(this).option(\"radius\", value);\n }\n}\n\n/**\n * Authors radius-encoded polar-area sectors.\n */\nclass PolarAreaChartBuilder extends NumericSeriesBuilder {\n /**\n * Chooses angular spacing between polar sectors.\n *\n * @param {number} degrees - Finite gap angle below one circle.\n * @returns {this} Current builder.\n */\n padAngle(degrees) {\n return builderState(this).option(\"padAngle\", degrees);\n }\n\n /**\n * Chooses polar-sector corner radius.\n *\n * @param {number} value - Non-negative radius in CSS pixels.\n * @returns {this} Current builder.\n */\n cornerRadius(value) {\n return builderState(this).option(\"cornerRadius\", value);\n }\n}\n\n/**\n * Authors comparable radial radar datasets.\n */\nclass RadarChartBuilder extends NumericSeriesBuilder {\n /**\n * Chooses radar polygon stroke width.\n *\n * @param {number} value - Non-negative width in CSS pixels.\n * @returns {this} Current builder.\n */\n strokeWidth(value) {\n return builderState(this).option(\"strokeWidth\", value);\n }\n}\n\nexport { PercentageChartBuilder, PolarAreaChartBuilder, RadarChartBuilder, SectorChartBuilder };\n"],"mappings":"iNAQA,IAAM,EAAN,cAAmC,EASjC,OAAA,CAAQ,EAAO,EAAQ,GACrB,OAAO,EAAa,MAAM,QACxB,EACE,CACE,EACA,EACA,GAEF,GAGN,GAMI,EAAN,cAAiC,EAO/B,SAAA,CAAU,GACR,OAAO,EAAa,MAAM,OAAO,YAAa,EAChD,CAQA,UAAA,CAAW,GACT,OAAO,EAAa,MAAM,OAAO,aAAc,EACjD,CAQA,QAAA,CAAS,GACP,OAAO,EAAa,MAAM,OAAO,WAAY,EAC/C,CAQA,YAAA,CAAa,GACX,OAAO,EAAa,MAAM,OAAO,eAAgB,EACnD,GAMI,EAAN,cAAqC,EAOnC,SAAA,CAAU,GACR,OAAO,EAAa,MAAM,OAAO,YAAa,EAChD,CAQA,MAAA,CAAO,GACL,OAAO,EAAa,MAAM,OAAO,SAAU,EAC7C,GAMI,EAAN,cAAoC,EAOlC,QAAA,CAAS,GACP,OAAO,EAAa,MAAM,OAAO,WAAY,EAC/C,CAQA,YAAA,CAAa,GACX,OAAO,EAAa,MAAM,OAAO,eAAgB,EACnD,GAMI,EAAN,cAAgC,EAO9B,WAAA,CAAY,GACV,OAAO,EAAa,MAAM,OAAO,cAAe,EAClD"}
@@ -0,0 +1 @@
1
+ import{validateHeatmapPoints as t,validateTask as o}from"./BuilderValidation.js";import{builderState as i}from"./BuilderState.js";import{HeatmapTooltipBuilder as r,TimesheetTooltipBuilder as a,runScope as e}from"./BuilderScopes.js";import{CommonChartBuilder as n}from"./Builder.js";var s=class extends n{range(t,o){const r=i(this);return r.data("start",t),r.data("end",o)}radius(t){return i(this).option("radius",t)}},p=class extends s{points(o){return t(o),i(this).data("points",o)}countLabel(t){return i(this).option("countLabel",t)}tooltip(t){if("function"!=typeof t)return i(this).explicitOption("tooltip",t);const o={};e(new r(o),t);const a=i(this);return a.explicitOption("tooltip",!0),void 0!==o.formatDate&&a.option("tooltipFormatDate",o.formatDate),void 0!==o.formatValue&&a.option("tooltipFormatValue",o.formatValue),this}},l=class extends s{task(t,r,a){if(arguments.length>3)throw new TypeError("task accepts an object or label, start, and end");const e="string"==typeof t?{label:t,start:r,end:a}:t;return o(e),i(this).append("tasks",e)}axes(t){return i(this).option("axes",t)}grid(t){return i(this).option("grid",t)}valueLabels(t){return i(this).option("valueLabels",t)}formatDate(t){return i(this).option("formatDate",t)}formatDuration(t){return i(this).option("formatDuration",t)}formatTick(t){return i(this).option("formatTick",t)}tooltip(t){if("function"!=typeof t)return i(this).explicitOption("tooltip",t);const o={};e(new a(o),t);const r=i(this);return r.explicitOption("tooltip",!0),void 0!==o.formatDate&&r.option("tooltipFormatDate",o.formatDate),void 0!==o.formatDuration&&r.option("tooltipFormatDuration",o.formatDuration),this}};export{p as HeatmapChartBuilder,l as TimesheetChartBuilder};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemporalBuilders.js","names":[],"sources":["../../../src/core/builders/TemporalBuilders.js"],"sourcesContent":["import { CommonChartBuilder } from \"./Builder.js\";\nimport { HeatmapTooltipBuilder, TimesheetTooltipBuilder, runScope } from \"./BuilderScopes.js\";\nimport { builderState } from \"./BuilderState.js\";\nimport { validateHeatmapPoints, validateTask } from \"./BuilderValidation.js\";\n\nconst MAXIMUM_POSITIONAL_TASK_ARGUMENTS = 3;\n\n/**\n * Authors calendar heatmap points and intensity presentation.\n */\nclass RangedChartBuilder extends CommonChartBuilder {\n /**\n * Chooses an explicit range for a temporal chart.\n *\n * @param {Date | string | number} start - First visible temporal value.\n * @param {Date | string | number} end - Last visible temporal value.\n * @returns {this} Current builder.\n */\n range(start, end) {\n const state = builderState(this);\n state.data(\"start\", start);\n\n return state.data(\"end\", end);\n }\n\n /**\n * Chooses the family-specific mark corner radius.\n *\n * @param {number} value - Non-negative radius in CSS pixels.\n * @returns {this} Current builder.\n */\n radius(value) {\n return builderState(this).option(\"radius\", value);\n }\n}\n\n/**\n * Authors calendar heatmap points and intensity presentation.\n */\nclass HeatmapChartBuilder extends RangedChartBuilder {\n /**\n * Replaces keyed daily activity values.\n *\n * @param {Readonly<Record<string | number, number>>} values - Calendar keys and finite counts.\n * @returns {this} Current builder.\n */\n points(values) {\n validateHeatmapPoints(values);\n\n return builderState(this).data(\"points\", values);\n }\n\n /**\n * Names the unit appended to heatmap counts.\n *\n * @param {string} value - Human-readable count unit.\n * @returns {this} Current builder.\n */\n countLabel(value) {\n return builderState(this).option(\"countLabel\", value);\n }\n\n /**\n * Configures tooltip visibility or heatmap formatting.\n *\n * @param {boolean | ((tooltip: HeatmapTooltipBuilder) => void)} value - Visibility switch or formatter scope.\n * @returns {this} Current builder.\n */\n tooltip(value) {\n if (typeof value !== \"function\") {\n return builderState(this).explicitOption(\"tooltip\", value);\n }\n\n const tooltip = {};\n runScope(new HeatmapTooltipBuilder(tooltip), value);\n const state = builderState(this);\n state.explicitOption(\"tooltip\", true);\n\n if (tooltip.formatDate !== undefined) {\n state.option(\"tooltipFormatDate\", tooltip.formatDate);\n }\n\n if (tooltip.formatValue !== undefined) {\n state.option(\"tooltipFormatValue\", tooltip.formatValue);\n }\n\n return this;\n }\n}\n\n/**\n * Authors task intervals for product planning views.\n */\nclass TimesheetChartBuilder extends RangedChartBuilder {\n /**\n * Appends a task using concise positional or advanced object grammar.\n *\n * @param {string | object} input - Task label or complete task input.\n * @param {Date | string | number} [start] - Positional task start.\n * @param {Date | string | number} [end] - Positional task end.\n * @returns {this} Current builder.\n */\n task(input, start, end) {\n if (arguments.length > MAXIMUM_POSITIONAL_TASK_ARGUMENTS) {\n throw new TypeError(\"task accepts an object or label, start, and end\");\n }\n\n const task = typeof input === \"string\" ? { label: input, start, end } : input;\n validateTask(task);\n\n return builderState(this).append(\"tasks\", task);\n }\n\n /**\n * Chooses axis visibility.\n *\n * @param {boolean} visible - Whether the time axis is displayed.\n * @returns {this} Current builder.\n */\n axes(visible) {\n return builderState(this).option(\"axes\", visible);\n }\n\n /**\n * Chooses timeline-grid visibility.\n *\n * @param {boolean} visible - Whether time and row guides are displayed.\n * @returns {this} Current builder.\n */\n grid(visible) {\n return builderState(this).option(\"grid\", visible);\n }\n\n /**\n * Chooses task-label visibility.\n *\n * @param {boolean} visible - Whether task labels are displayed.\n * @returns {this} Current builder.\n */\n valueLabels(visible) {\n return builderState(this).option(\"valueLabels\", visible);\n }\n\n /**\n * Formats task dates across timesheet display surfaces.\n *\n * @param {(date: Date) => string} formatter - Synchronous date formatter.\n * @returns {this} Current builder.\n */\n formatDate(formatter) {\n return builderState(this).option(\"formatDate\", formatter);\n }\n\n /**\n * Formats task durations across timesheet display surfaces.\n *\n * @param {(milliseconds: number) => string} formatter - Synchronous duration formatter.\n * @returns {this} Current builder.\n */\n formatDuration(formatter) {\n return builderState(this).option(\"formatDuration\", formatter);\n }\n\n /**\n * Formats bottom-axis tick dates.\n *\n * @param {(date: Date) => string} formatter - Synchronous tick formatter.\n * @returns {this} Current builder.\n */\n formatTick(formatter) {\n return builderState(this).option(\"formatTick\", formatter);\n }\n\n /**\n * Configures tooltip visibility or task formatting.\n *\n * @param {boolean | ((tooltip: TimesheetTooltipBuilder) => void)} value - Visibility switch or formatter scope.\n * @returns {this} Current builder.\n */\n tooltip(value) {\n if (typeof value !== \"function\") {\n return builderState(this).explicitOption(\"tooltip\", value);\n }\n\n const tooltip = {};\n runScope(new TimesheetTooltipBuilder(tooltip), value);\n const state = builderState(this);\n state.explicitOption(\"tooltip\", true);\n\n if (tooltip.formatDate !== undefined) {\n state.option(\"tooltipFormatDate\", tooltip.formatDate);\n }\n\n if (tooltip.formatDuration !== undefined) {\n state.option(\"tooltipFormatDuration\", tooltip.formatDuration);\n }\n\n return this;\n }\n}\n\nexport { HeatmapChartBuilder, TimesheetChartBuilder };\n"],"mappings":"0RAKA,IAKM,EAAN,cAAiC,EAQ/B,KAAA,CAAM,EAAO,GACX,MAAM,EAAQ,EAAa,MAG3B,OAFA,EAAM,KAAK,QAAS,GAEb,EAAM,KAAK,MAAO,EAC3B,CAQA,MAAA,CAAO,GACL,OAAO,EAAa,MAAM,OAAO,SAAU,EAC7C,GAMI,EAAN,cAAkC,EAOhC,MAAA,CAAO,GAGL,OAFA,EAAsB,GAEf,EAAa,MAAM,KAAK,SAAU,EAC3C,CAQA,UAAA,CAAW,GACT,OAAO,EAAa,MAAM,OAAO,aAAc,EACjD,CAQA,OAAA,CAAQ,GACN,GAAqB,mBAAV,EACT,OAAO,EAAa,MAAM,eAAe,UAAW,GAGtD,MAAM,EAAU,CAAC,EACjB,EAAS,IAAI,EAAsB,GAAU,GAC7C,MAAM,EAAQ,EAAa,MAW3B,OAVA,EAAM,eAAe,WAAW,QAEL,IAAvB,EAAQ,YACV,EAAM,OAAO,oBAAqB,EAAQ,iBAGhB,IAAxB,EAAQ,aACV,EAAM,OAAO,qBAAsB,EAAQ,aAGtC,IACT,GAMI,EAAN,cAAoC,EASlC,IAAA,CAAK,EAAO,EAAO,GACjB,GAAI,UAAU,OAlGwB,EAmGpC,MAAM,IAAI,UAAU,mDAGtB,MAAM,EAAwB,iBAAV,EAAqB,CAAE,MAAO,EAAO,QAAO,OAAQ,EAGxE,OAFA,EAAa,GAEN,EAAa,MAAM,OAAO,QAAS,EAC5C,CAQA,IAAA,CAAK,GACH,OAAO,EAAa,MAAM,OAAO,OAAQ,EAC3C,CAQA,IAAA,CAAK,GACH,OAAO,EAAa,MAAM,OAAO,OAAQ,EAC3C,CAQA,WAAA,CAAY,GACV,OAAO,EAAa,MAAM,OAAO,cAAe,EAClD,CAQA,UAAA,CAAW,GACT,OAAO,EAAa,MAAM,OAAO,aAAc,EACjD,CAQA,cAAA,CAAe,GACb,OAAO,EAAa,MAAM,OAAO,iBAAkB,EACrD,CAQA,UAAA,CAAW,GACT,OAAO,EAAa,MAAM,OAAO,aAAc,EACjD,CAQA,OAAA,CAAQ,GACN,GAAqB,mBAAV,EACT,OAAO,EAAa,MAAM,eAAe,UAAW,GAGtD,MAAM,EAAU,CAAC,EACjB,EAAS,IAAI,EAAwB,GAAU,GAC/C,MAAM,EAAQ,EAAa,MAW3B,OAVA,EAAM,eAAe,WAAW,QAEL,IAAvB,EAAQ,YACV,EAAM,OAAO,oBAAqB,EAAQ,iBAGb,IAA3B,EAAQ,gBACV,EAAM,OAAO,wBAAyB,EAAQ,gBAGzC,IACT"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{BarChart as o,BubbleChart as r,DonutChart as i,HeatmapChart as t,LineChart as e,MixedChart as f,PercentageChart as m,PieChart as n,PolarAreaChart as p,RadarChart as a,ScatterChart as c,TimesheetChart as h}from"./core/ChartDefinition.js";export{o as BarChart,r as BubbleChart,i as DonutChart,t as HeatmapChart,e as LineChart,f as MixedChart,m as PercentageChart,n as PieChart,p as PolarAreaChart,a as RadarChart,c as ScatterChart,h as TimesheetChart};
@@ -0,0 +1 @@
1
+ import e from"./SvgSurface.js";function t(t,r){if("function"!=typeof r)throw new TypeError("Chart render implementation must be a function");const{element:n,...o}=t;r({chart:Object.freeze(o),surface:new e(n)})}export{t as renderChart};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartRendering.js","names":[],"sources":["../../src/renderers/ChartRendering.js"],"sourcesContent":["import SvgSurface from \"./SvgSurface.js\";\n\n/**\n * Renders one validated snapshot through its chart-family strategy.\n *\n * @param {object} snapshot - Validated chart state and owned SVG surface.\n * @param {(rendering: object) => void} render - Family renderer selected by the public definition.\n * @returns {void} Chart content and any shared series legend are appended.\n * @throws {TypeError} When no renderer class is registered for the type.\n */\nfunction renderChart(snapshot, render) {\n if (typeof render !== \"function\") {\n throw new TypeError(\"Chart render implementation must be a function\");\n }\n\n const { element, ...chartState } = snapshot;\n const chart = Object.freeze(chartState);\n const surface = new SvgSurface(element);\n\n render({ chart, surface });\n}\n\nexport { renderChart };\n"],"mappings":"+BAUA,SAAS,EAAY,EAAU,GAC7B,GAAsB,mBAAX,EACT,MAAM,IAAI,UAAU,kDAGtB,MAAM,QAAE,KAAY,GAAe,EAInC,EAAO,CAAE,MAHK,OAAO,OAAO,GAGZ,QAAA,IAFI,EAAW,IAGjC"}
@@ -0,0 +1 @@
1
+ import{labelElement as t,svg as e}from"../support/Dom.js";import{legendLayout as s}from"../support/presentation/Presentation.js";var a=class{#t;#e;constructor({chart:t,surface:e}){this.#t=t,this.#e=e}render(){!this.#t.options.legend||this.#t.datasets.length<2||this.renderItems(this.#t.datasets.map(t=>({label:t.name,color:t.color})),16)}renderItems(a,r){const{labelOffset:c,positions:o}=s(this.#t.options.width,a),i=e("g",{class:"charts2-legend-group","aria-label":"Legend"});for(const[s,l]of a.entries()){const{labelMaxWidth:a,x:n,yOffset:h}=o[s],d=r+h;i.append(e("circle",{cx:n+4,cy:d-4,r:4,fill:l.color,class:"charts2-legend-swatch charts2-series-swatch","aria-hidden":"true"})),i.append(t({value:l.label,attributes:{x:n+c,y:d,class:"charts2-legend"},measurement:{maxWidth:a}}))}this.#e.append(i)}};export{a as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LegendRenderer.js","names":["#chart","#surface"],"sources":["../../src/renderers/LegendRenderer.js"],"sourcesContent":["import { SERIES_SWATCH_DIAMETER } from \"../support/Constants.js\";\nimport { svg, labelElement } from \"../support/Dom.js\";\nimport { legendLayout } from \"../support/presentation/Presentation.js\";\n\nconst DEFAULT_LEGEND_BASELINE = 16;\n\n/**\n * Renders shared series and item legends from measured layout policies.\n */\nexport default class LegendRenderer {\n #chart;\n #surface;\n\n /**\n * Creates a renderer bound to one frozen render snapshot.\n *\n * @param {object} rendering - Collaborators for one legend pass.\n * @param {object} rendering.chart - Frozen chart data and options.\n * @param {import(\"./SvgSurface.js\").default} rendering.surface - Owned SVG drawing surface.\n */\n constructor({ chart, surface }) {\n this.#chart = chart;\n this.#surface = surface;\n }\n\n /**\n * Calculates and renders a wrapped legend for datasets that expose series.\n *\n * @returns {void} Legend content is appended when enabled and meaningful.\n */\n render() {\n if (!this.#chart.options.legend || this.#chart.datasets.length < 2) {\n return;\n }\n\n this.renderItems(\n this.#chart.datasets.map((dataset) => ({ label: dataset.name, color: dataset.color })),\n DEFAULT_LEGEND_BASELINE,\n );\n }\n\n /**\n * Renders precomputed legend entries at a shared first-row baseline.\n *\n * @param {Array<{label: string, color: string}>} items - Ordered series labels and colors.\n * @param {number} baseline - Vertical baseline of the first legend row.\n * @returns {void} Positioned legend groups are appended to the chart SVG.\n */\n renderItems(items, baseline) {\n const { labelOffset, positions } = legendLayout(this.#chart.options.width, items);\n const group = svg(\"g\", { class: \"charts2-legend-group\", \"aria-label\": \"Legend\" });\n\n for (const [\n index,\n item,\n ] of items.entries()) {\n const { labelMaxWidth, x, yOffset } = positions[index];\n const y = baseline + yOffset;\n group.append(\n svg(\"circle\", {\n cx: x + SERIES_SWATCH_DIAMETER / 2,\n cy: y - SERIES_SWATCH_DIAMETER / 2,\n r: SERIES_SWATCH_DIAMETER / 2,\n fill: item.color,\n class: \"charts2-legend-swatch charts2-series-swatch\",\n \"aria-hidden\": \"true\",\n }),\n );\n group.append(\n labelElement({\n value: item.label,\n attributes: { x: x + labelOffset, y, class: \"charts2-legend\" },\n measurement: { maxWidth: labelMaxWidth },\n }),\n );\n }\n\n this.#surface.append(group);\n }\n}\n"],"mappings":"iIAIA,IAKqB,EAArB,MACE,GACA,GASA,WAAA,EAAY,MAAE,EAAA,QAAO,IACnB,MAAKA,EAAS,EACd,MAAKC,EAAW,CAClB,CAOA,MAAA,IACO,MAAKD,EAAO,QAAQ,QAAU,MAAKA,EAAO,SAAS,OAAS,GAIjE,KAAK,YACH,MAAKA,EAAO,SAAS,IAAK,IAAA,CAAe,MAAO,EAAQ,KAAM,MAAO,EAAQ,SAhCnD,GAmC9B,CASA,WAAA,CAAY,EAAO,GACjB,MAAM,YAAE,EAAA,UAAa,GAAc,EAAa,MAAKA,EAAO,QAAQ,MAAO,GACrE,EAAQ,EAAI,IAAK,CAAE,MAAO,uBAAwB,aAAc,WAEtE,IAAK,MACH,EACA,KACG,EAAM,UAAW,CACpB,MAAM,cAAE,EAAA,EAAe,EAAA,QAAG,GAAY,EAAU,GAC1C,EAAI,EAAW,EACrB,EAAM,OACJ,EAAI,SAAU,CACZ,GAAI,EAAA,EACJ,GAAI,EAAA,EACJ,EAAA,EACA,KAAM,EAAK,MACX,MAAO,8CACP,cAAe,UAGnB,EAAM,OACJ,EAAa,CACX,MAAO,EAAK,MACZ,WAAY,CAAE,EAAG,EAAI,EAAa,IAAG,MAAO,kBAC5C,YAAa,CAAE,SAAU,KAG/B,CAEA,MAAKC,EAAS,OAAO,EACvB"}
@@ -0,0 +1 @@
1
+ import{markMetadata as t,svg as o,titled as r}from"../support/Dom.js";var s=class{#t;constructor(t){this.#t=t}append(t,r={}){const s="string"==typeof t?o(t,r):t;return this.#t.append(s),s}mark(s,e,{dataset:n,point:i,title:p}){const a=r(t(o(s,e),n,i),p);return this.#t.append(a),a}text(t,r){const s=o("text",r);return s.textContent=String(t),this.#t.append(s),s}attribute(t,o){this.#t.setAttribute(t,String(o))}styles(t){Object.assign(this.#t.style,t)}};export{s as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SvgSurface.js","names":["#root"],"sources":["../../src/renderers/SvgSurface.js"],"sourcesContent":["import { markMetadata, svg, titled } from \"../support/Dom.js\";\n\n/**\n * Owns append-only access to the SVG root used during one rendering pass.\n */\nexport default class SvgSurface {\n #root;\n\n /**\n * Captures the SVG element owned by the chart lifecycle.\n *\n * @param {SVGSVGElement} root - Existing chart SVG that receives rendered nodes.\n */\n constructor(root) {\n this.#root = root;\n }\n\n /**\n * Appends either an existing SVG node or a newly created element.\n *\n * @param {SVGElement | string} node - Existing node or SVG tag name.\n * @param {Record<string, string | number>} [attributes={}] - Attributes used when a tag name is supplied.\n * @returns {SVGElement} Appended SVG element.\n */\n append(node, attributes = {}) {\n const element = typeof node === \"string\" ? svg(node, attributes) : node;\n this.#root.append(element);\n\n return element;\n }\n\n /**\n * Creates and appends one interactive data mark with source metadata.\n *\n * @param {string} name - SVG tag name for the mark.\n * @param {Record<string, string | number>} attributes - Visual and geometric attributes.\n * @param {object} metadata - Source coordinates and accessible title.\n * @param {number} metadata.dataset - Zero-based dataset position.\n * @param {number} metadata.point - Zero-based point position.\n * @param {string} metadata.title - Accessible description and tooltip fallback.\n * @returns {SVGElement} Appended interactive mark.\n */\n mark(name, attributes, { dataset, point, title }) {\n const element = titled(markMetadata(svg(name, attributes), dataset, point), title);\n this.#root.append(element);\n\n return element;\n }\n\n /**\n * Creates and appends one text node with explicit content.\n *\n * @param {unknown} value - Content converted to text.\n * @param {Record<string, string | number>} attributes - SVG positioning and presentation attributes.\n * @returns {SVGElement} Appended text element.\n */\n text(value, attributes) {\n const element = svg(\"text\", attributes);\n element.textContent = String(value);\n this.#root.append(element);\n\n return element;\n }\n\n /**\n * Updates one attribute on the owned SVG root.\n *\n * @param {string} name - Root attribute name.\n * @param {string | number} value - Serializable attribute value.\n * @returns {void} The existing root is updated in place.\n */\n attribute(name, value) {\n this.#root.setAttribute(name, String(value));\n }\n\n /**\n * Applies a bounded set of inline styles to the owned SVG root.\n *\n * @param {Record<string, string>} properties - CSS property names and values.\n * @returns {void} Root style declarations are updated in place.\n */\n styles(properties) {\n Object.assign(this.#root.style, properties);\n }\n}\n"],"mappings":"sEAKA,IAAqB,EAArB,MACE,GAOA,WAAA,CAAY,GACV,MAAKA,EAAQ,CACf,CASA,MAAA,CAAO,EAAM,EAAa,CAAC,GACzB,MAAM,EAA0B,iBAAT,EAAoB,EAAI,EAAM,GAAc,EAGnE,OAFA,MAAKA,EAAM,OAAO,GAEX,CACT,CAaA,IAAA,CAAK,EAAM,GAAY,QAAE,EAAA,MAAS,EAAA,MAAO,IACvC,MAAM,EAAU,EAAO,EAAa,EAAI,EAAM,GAAa,EAAS,GAAQ,GAG5E,OAFA,MAAKA,EAAM,OAAO,GAEX,CACT,CASA,IAAA,CAAK,EAAO,GACV,MAAM,EAAU,EAAI,OAAQ,GAI5B,OAHA,EAAQ,YAAc,OAAO,GAC7B,MAAKA,EAAM,OAAO,GAEX,CACT,CASA,SAAA,CAAU,EAAM,GACd,MAAKA,EAAM,aAAa,EAAM,OAAO,GACvC,CAQA,MAAA,CAAO,GACL,OAAO,OAAO,MAAKA,EAAM,MAAO,EAClC"}
@@ -0,0 +1 @@
1
+ import{ChartType as t}from"../../support/Constants.js";import{labelElement as e,measuredTextWidth as a,wrappedLabelElement as i}from"../../support/Dom.js";import{formatContext as s,formatValue as o,formatterText as r}from"../../support/presentation/Formatting.js";import{requireFiniteNumber as n}from"../../support/Normalize.js";function l(t,e){return 0===t?"first":t===e-1?"last":"middle"}var h=class{#t;#e;#a;constructor({chart:t,layout:e,surface:a}){this.#t=t,this.#e=e,this.#a=a}renderBackground(){this.#t.options.grid&&this.#i(),this.#s(),this.#o(),this.#t.options.axes&&this.#r()}renderForeground(){this.#n(),this.#l(),this.#t.options.valueLabels&&(this.#h(),this.#c())}#s(){const{bottom:t,left:e,right:a,top:i}=this.#e.frame,s=this.#t.source.yRegions;for(const o of s){const[s,r]=o.range;n(s,"Region start"),n(r,"Region end");const l=this.#e.valueAt(s),h=this.#e.valueAt(r);if(!o.includeInDomain&&!this.#u(l,h))continue;const c=this.#d(l),u=this.#d(h),d=this.#e.isHorizontal?{x:Math.min(c,u),y:i,width:Math.abs(u-c),height:t-i}:{x:e,y:Math.min(c,u),width:a-e,height:Math.abs(u-c)};this.#a.append("rect",{...d,fill:o.color,opacity:o.opacity,class:"charts2-region","aria-hidden":"true"})}}#o(){const{bottom:t,left:e,right:a,top:i}=this.#e.frame,s=this.#t.source.yMarkers;for(const o of s){n(o.value,"Marker value");const s=this.#e.valueAt(o.value);if(!o.includeInDomain&&!this.#m(s))continue;const r=this.#e.isHorizontal?{x1:s,y1:i,x2:s,y2:t}:{x1:e,y1:s,x2:a,y2:s};this.#a.append("line",{...r,stroke:o.color,opacity:o.opacity,"stroke-width":o.width,"stroke-dasharray":o.dash.join(" "),"vector-effect":"non-scaling-stroke",class:"charts2-marker"})}}#n(){const t=this.#t.source.yRegions;for(const e of t){const t=e.range.map(t=>this.#e.valueAt(t));if(!e.includeInDomain&&!this.#u(...t))continue;const a=e.formatLabel?r(e.formatLabel(e.label,Object.freeze([...e.range]),s(this.#t.options,"accessibility")),"Region label"):e.label;this.#y({kind:"region",label:a,placement:this.#b("region",e.labelPosition,t),annotation:e})}}#l(){const t=this.#t.source.yMarkers;for(const e of t){const t=this.#e.valueAt(e.value);if(!e.includeInDomain&&!this.#m(t))continue;const a=e.formatLabel?r(e.formatLabel(e.label,e.value,s(this.#t.options,"accessibility")),"Marker label"):e.label;this.#y({kind:"marker",label:a,placement:this.#b("marker",e.labelPosition,[t]),annotation:e})}}#y({kind:t,label:e,placement:i,annotation:s}){const o=a(e,12)+2,r=this.#x(i.x,i.anchor,o);this.#a.text(e,{x:r,y:i.y,"text-anchor":"start","dominant-baseline":"middle",style:`fill: ${s.labelColor}`,class:`charts2-annotation charts2-${t}-label`})}#x(t,e,a){return"end"===e?t-a:"middle"===e?t-a/2:t}#b(t,e,a){const{bottom:i,left:s,right:o,top:r}=this.#e.frame,n=a.map(t=>this.#d(t)),l=n.reduce((t,e)=>t+e,0)/n.length;if(this.#e.isHorizontal){const a=this.#f([i-9,(r+i)/2,r+9],e);if("region"===t)return{x:l,y:a,anchor:"middle"};const n=l>(s+o)/2;return{x:l+(n?-6:6),y:a,anchor:n?"end":"start"}}const h=this.#f([s+8,(s+o)/2,o-8],e),c=this.#f(["start","middle","end"],e);return"region"===t?{x:h,y:l,anchor:c}:{x:h,y:Math.max(r+9,l-6-9),anchor:c}}#f([t,e,a],i){return"start"===i?t:"center"===i?e:a}#m(t){const{maximum:e,minimum:a}=this.#g();return t>=a&&t<=e}#u(t,e){const{maximum:a,minimum:i}=this.#g();return Math.max(t,e)>=i&&Math.min(t,e)<=a}#d(t){const{maximum:e,minimum:a}=this.#g();return Math.min(e,Math.max(a,t))}#g(){const{bottom:t,left:e,right:a,top:i}=this.#e.frame;return this.#e.isHorizontal?{minimum:e,maximum:a}:{minimum:i,maximum:t}}#h(){const{bottom:t,left:e,right:a}=this.#e.frame,i=this.#e.values,s=this.#e.isHorizontal?i.ticks:i.ticks.toReversed();for(const r of s){const i=this.#e.valueAt(r),s=this.#e.isHorizontal?{x:i,y:t+this.#e.frame.padding-7,class:"charts2-label charts2-value-label","text-anchor":"middle"}:{x:this.#e.isYAxisRight?a+5:e-5,y:i+3,class:"charts2-label charts2-value-label","text-anchor":this.#e.isYAxisRight?"start":"end"};this.#a.text(o(this.#t.options,r,{target:"axis"}),s)}}#i(){const{bottom:t,left:e,right:a,top:i}=this.#e.frame,s=this.#e.isHorizontal?this.#e.values.ticks:this.#e.values.ticks.toReversed();for(const o of s){const s=this.#e.valueAt(o),r=this.#e.isHorizontal?{x1:s,y1:i,x2:s,y2:t,class:"charts2-grid charts2-grid-vertical"}:{x1:e,y1:s,x2:a,y2:s,class:"charts2-grid charts2-grid-horizontal"};this.#a.append("line",{...r,"data-tick":o,"aria-hidden":"true"})}}#r(){const{bottom:t,left:e,right:a,top:i}=this.#e.frame,s=this.#e.isYAxisRight?a:e,o=this.#e.isHorizontal?{x1:s,y1:i,x2:s,y2:t,class:"charts2-axis charts2-y-axis"}:{x1:e,y1:t,x2:a,y2:t,class:"charts2-axis charts2-x-axis"};this.#a.append("line",o)}#c(){0!==this.#t.labels.length&&(this.#e.isHorizontal?this.#p():this.#v())}#p(){const{bottom:t,left:e,right:a,top:s}=this.#e.frame,o=(t-s)/this.#t.labels.length;for(const[r,n]of this.#e.categories.labels.entries()){const t=i({value:n,attributes:{x:this.#e.isYAxisRight?a+4:e-4,y:s+(r+.5)*o+3,class:"charts2-label","text-anchor":this.#e.isYAxisRight?"start":"end"},maxWidth:this.#e.categories.gutter-4-4,originalValue:this.#t.labels[r]});this.#a.append(t)}}#v(){const{height:a,left:i,right:s}=this.#e.frame,o=this.#e.type!==t.LINE,r=o?this.#t.labels.length:this.#t.labels.length-1,n=(s-i)/Math.max(1,r),l=Math.max(1,Math.ceil(36/Math.max(1,n))),h=[];for(let t=0;t<this.#t.labels.length;t+=l)h.push(t);const c=this.#t.labels.length-1;h.at(-1)!==c&&(h.pop(),h.push(c));for(const[t,u]of h.entries()){const i=o?this.#L({visibleIndexes:h,visibleIndex:t,index:u}):this.#A({visibleIndexes:h,visibleIndex:t,index:u,step:n}),s=this.#e.categories.labels[u],r=Array.isArray(s)?s.join(" "):s,l=e({value:r,attributes:{x:i.x,y:a-7,class:"charts2-label","text-anchor":i.anchor},measurement:{maxWidth:i.width,fontSize:9},originalValue:this.#t.labels[u]});this.#a.append(l)}}#L({visibleIndexes:t,visibleIndex:e,index:a}){const{left:i,right:s}=this.#e.frame,o=this.#e.categoryAt(a);if(1===t.length)return{x:o,anchor:"middle",width:s-i};const r=0===e?i:(this.#e.categoryAt(t[e-1])+o)/2,n=e===t.length-1?s:(o+this.#e.categoryAt(t[e+1]))/2;return{x:o,anchor:"middle",width:Math.max(24,2*Math.min(o-r,n-o)-8)}}#A({visibleIndexes:t,visibleIndex:e,index:a,step:i}){const{left:s,right:o}=this.#e.frame;if(1===t.length)return{x:s,anchor:"start",width:o-s};const r=s+a*i,n=e>0?s+t[e-1]*i:s,h=e<t.length-1?s+t[e+1]*i:o;return this.#M({position:r,previousPosition:n,nextPosition:h,edge:l(e,t.length)})||{x:r,anchor:"middle",width:Math.max(24,Math.min(r-n,h-r)-8)}}#M({position:t,previousPosition:e,nextPosition:a,edge:i}){const{left:s,right:o}=this.#e.frame;return"first"===i?{x:s,anchor:"start",width:Math.max(24,(a-t)/2-4)}:"last"===i?{x:o,anchor:"end",width:Math.max(24,(t-e)/2-4)}:null}};export{h as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CartesianAxesRenderer.js","names":["#chart","#layout","#surface","#renderGrid","#renderRegions","#renderMarkerLines","#renderAxis","#renderRegionLabels","#renderMarkerLabels","#renderValueLabels","#renderCategoryLabels","#overlapsPlot","#boundedValuePosition","#insidePlot","#renderAnnotationLabel","#annotationLabelAttributes","#annotationLabelLeft","#placementCoordinate","#valueAxisBounds","#renderHorizontalLabels","#renderVerticalLabels","#centeredLabelPlacement","#verticalLabelPlacement","#edgeVerticalLabelPlacement"],"sources":["../../../src/renderers/cartesian/CartesianAxesRenderer.js"],"sourcesContent":["import {\n ChartType,\n HORIZONTAL_LABEL_EDGE_INSET,\n HORIZONTAL_LABEL_GAP,\n VALUE_LABEL_GAP,\n} from \"../../support/Constants.js\";\nimport { labelElement, measuredTextWidth, wrappedLabelElement } from \"../../support/Dom.js\";\nimport { requireFiniteNumber } from \"../../support/Normalize.js\";\nimport { formatContext, formatterText, formatValue } from \"../../support/presentation/Formatting.js\";\n\nconst ANNOTATION_EDGE_INSET = 8;\nconst ANNOTATION_MARKER_GAP = 6;\nconst ANNOTATION_FONT_SIZE = 12;\nconst ANNOTATION_TAG_HEIGHT = 18;\nconst VALUE_LABEL_BASELINE_OFFSET = 7;\nconst VALUE_LABEL_CENTER_OFFSET = 3;\nconst CATEGORY_MIDPOINT = 0.5;\nconst CATEGORY_LABEL_BASELINE_OFFSET = 3;\nconst TARGET_CATEGORY_LABEL_SPACING = 36;\nconst CATEGORY_LABEL_BOTTOM_OFFSET = 7;\nconst MINIMUM_CATEGORY_LABEL_WIDTH = 24;\nconst CATEGORY_LABEL_SIDE_GAP = 4;\nconst CATEGORY_LABEL_TOTAL_GAP = 8;\n\n/**\n * Names a visible category label's relationship to the viewport edges.\n *\n * @param {number} index - Position in the sampled visible-label collection.\n * @param {number} count - Number of visible category labels.\n * @returns {\"first\" | \"middle\" | \"last\"} Edge-aware placement role.\n */\nfunction verticalLabelEdge(index, count) {\n if (index === 0) {\n return \"first\";\n }\n\n return index === count - 1 ? \"last\" : \"middle\";\n}\n\n/**\n * Renders Cartesian axes, annotations, grid lines, and labels.\n */\nexport default class CartesianAxesRenderer {\n #chart;\n #layout;\n #surface;\n\n /**\n * Binds normalized chart state to one immutable Cartesian layout snapshot.\n *\n * @param {object} state - Collaborators required for one axes pass.\n * @param {object} state.chart - Frozen chart data and options.\n * @param {object} state.layout - Scales, bounds, and renderer flags resolved by `CartesianRenderer`.\n * @param {import(\"../SvgSurface.js\").default} state.surface - Owned SVG drawing surface.\n */\n constructor({ chart, layout, surface }) {\n this.#chart = chart;\n this.#layout = layout;\n this.#surface = surface;\n }\n\n /**\n * Renders grid, configured regions, and the primary axis behind data marks.\n *\n * @returns {void} Background Cartesian presentation is appended to the chart SVG.\n */\n renderBackground() {\n if (this.#chart.options.grid) {\n this.#renderGrid();\n }\n\n this.#renderRegions();\n this.#renderMarkerLines();\n if (this.#chart.options.axes) {\n this.#renderAxis();\n }\n }\n\n /**\n * Renders markers and labels over data marks.\n *\n * @returns {void} Foreground Cartesian presentation is appended to the chart SVG.\n */\n renderForeground() {\n this.#renderRegionLabels();\n this.#renderMarkerLabels();\n if (this.#chart.options.valueLabels) {\n this.#renderValueLabels();\n this.#renderCategoryLabels();\n }\n }\n\n /**\n * Renders configured value ranges behind Cartesian data marks.\n *\n * @returns {void} Region rectangles are appended to the chart SVG.\n */\n // eslint-disable-next-line max-lines-per-function -- Array layout lines do not add behavior.\n #renderRegions() {\n const { bottom, left, right, top } = this.#layout.frame;\n const regions = this.#chart.source.yRegions;\n\n for (const region of regions) {\n const [\n rangeStart,\n rangeEnd,\n ] = region.range;\n\n requireFiniteNumber(rangeStart, \"Region start\");\n requireFiniteNumber(rangeEnd, \"Region end\");\n const start = this.#layout.valueAt(rangeStart);\n const end = this.#layout.valueAt(rangeEnd);\n\n if (!region.includeInDomain && !this.#overlapsPlot(start, end)) {\n continue;\n }\n\n const boundedStart = this.#boundedValuePosition(start);\n const boundedEnd = this.#boundedValuePosition(end);\n\n const attributes = this.#layout.isHorizontal\n ? {\n x: Math.min(boundedStart, boundedEnd),\n y: top,\n width: Math.abs(boundedEnd - boundedStart),\n height: bottom - top,\n }\n : {\n x: left,\n y: Math.min(boundedStart, boundedEnd),\n width: right - left,\n height: Math.abs(boundedEnd - boundedStart),\n };\n\n this.#surface.append(\"rect\", {\n ...attributes,\n fill: region.color,\n opacity: region.opacity,\n class: \"charts2-region\",\n \"aria-hidden\": \"true\",\n });\n }\n }\n\n /**\n * Renders configured reference lines over Cartesian data marks.\n *\n * @returns {void} Marker lines and optional labels are appended to the chart SVG.\n */\n #renderMarkerLines() {\n const { bottom, left, right, top } = this.#layout.frame;\n const markers = this.#chart.source.yMarkers;\n\n for (const marker of markers) {\n requireFiniteNumber(marker.value, \"Marker value\");\n const position = this.#layout.valueAt(marker.value);\n\n if (!marker.includeInDomain && !this.#insidePlot(position)) {\n continue;\n }\n\n const attributes = this.#layout.isHorizontal\n ? { x1: position, y1: top, x2: position, y2: bottom }\n : { x1: left, y1: position, x2: right, y2: position };\n\n this.#surface.append(\"line\", {\n ...attributes,\n stroke: marker.color,\n opacity: marker.opacity,\n \"stroke-width\": marker.width,\n \"stroke-dasharray\": marker.dash.join(\" \"),\n \"vector-effect\": \"non-scaling-stroke\",\n class: \"charts2-marker\",\n });\n }\n }\n\n /**\n * Renders region labels after datasets in stable call order.\n *\n * @returns {void} Visible region labels remain inside the plot.\n */\n #renderRegionLabels() {\n const regions = this.#chart.source.yRegions;\n\n for (const region of regions) {\n const positions = region.range.map((value) => this.#layout.valueAt(value));\n\n if (!region.includeInDomain && !this.#overlapsPlot(...positions)) {\n continue;\n }\n\n const label = region.formatLabel\n ? formatterText(\n region.formatLabel(\n region.label,\n Object.freeze([\n ...region.range,\n ]),\n formatContext(this.#chart.options, \"accessibility\"),\n ),\n \"Region label\",\n )\n : region.label;\n\n this.#renderAnnotationLabel({\n kind: \"region\",\n label,\n placement: this.#annotationLabelAttributes(\"region\", region.labelPosition, positions),\n annotation: region,\n });\n }\n }\n\n /**\n * Renders marker labels after region labels in stable call order.\n *\n * @returns {void} Visible marker labels remain inside the plot.\n */\n #renderMarkerLabels() {\n const markers = this.#chart.source.yMarkers;\n\n for (const marker of markers) {\n const position = this.#layout.valueAt(marker.value);\n\n if (!marker.includeInDomain && !this.#insidePlot(position)) {\n continue;\n }\n\n const label = marker.formatLabel\n ? formatterText(\n marker.formatLabel(\n marker.label,\n marker.value,\n formatContext(this.#chart.options, \"accessibility\"),\n ),\n \"Marker label\",\n )\n : marker.label;\n\n this.#renderAnnotationLabel({\n kind: \"marker\",\n label,\n placement: this.#annotationLabelAttributes(\"marker\", marker.labelPosition, [\n position,\n ]),\n annotation: marker,\n });\n }\n }\n\n /**\n * Renders one visually secondary annotation label without a surrounding container.\n *\n * @param {object} tag - Complete static annotation presentation.\n * @param {\"marker\" | \"region\"} tag.kind - Annotation role used for semantic styling.\n * @param {string} tag.label - Visible annotation text.\n * @param {object} tag.placement - Static anchor coordinates and alignment.\n * @param {object} tag.annotation - Normalized marker or region presentation.\n * @returns {void} The annotation text is appended to the surface.\n */\n #renderAnnotationLabel({ kind, label, placement, annotation }) {\n const textWidth = measuredTextWidth(label, ANNOTATION_FONT_SIZE) + 2;\n const left = this.#annotationLabelLeft(placement.x, placement.anchor, textWidth);\n\n this.#surface.text(label, {\n x: left,\n y: placement.y,\n \"text-anchor\": \"start\",\n \"dominant-baseline\": \"middle\",\n style: `fill: ${annotation.labelColor}`,\n class: `charts2-annotation charts2-${kind}-label`,\n });\n }\n\n /**\n * Converts a logical text anchor into the label's physical left edge.\n *\n * @param {number} x - Static anchor coordinate.\n * @param {\"start\" | \"middle\" | \"end\"} anchor - Logical alignment.\n * @param {number} width - Measured label width.\n * @returns {number} Left edge preserving the requested alignment.\n */\n #annotationLabelLeft(x, anchor, width) {\n if (anchor === \"end\") {\n return x - width;\n }\n\n return anchor === \"middle\" ? x - width / 2 : x;\n }\n\n /**\n * Resolves one logical annotation-label position for either orientation.\n *\n * @param {\"marker\" | \"region\"} kind - Annotation semantic controlling value-axis placement.\n * @param {\"start\" | \"center\" | \"end\"} placement - Logical category-axis placement.\n * @param {number[]} values - One marker coordinate or two region coordinates.\n * @returns {object} Bounded SVG text attributes.\n */\n // eslint-disable-next-line max-lines-per-function -- Array layout lines do not add behavior.\n #annotationLabelAttributes(kind, placement, values) {\n const { bottom, left, right, top } = this.#layout.frame;\n const boundedValues = values.map((value) => this.#boundedValuePosition(value));\n const value = boundedValues.reduce((sum, item) => sum + item, 0) / boundedValues.length;\n\n if (this.#layout.isHorizontal) {\n const y = this.#placementCoordinate(\n [\n bottom - ANNOTATION_TAG_HEIGHT / 2,\n (top + bottom) / 2,\n top + ANNOTATION_TAG_HEIGHT / 2,\n ],\n placement,\n );\n\n if (kind === \"region\") {\n return {\n x: value,\n y,\n anchor: \"middle\",\n };\n }\n\n const isNearRightEdge = value > (left + right) / 2;\n\n return {\n x: value + (isNearRightEdge ? -ANNOTATION_MARKER_GAP : ANNOTATION_MARKER_GAP),\n y,\n anchor: isNearRightEdge ? \"end\" : \"start\",\n };\n }\n\n const x = this.#placementCoordinate(\n [\n left + ANNOTATION_EDGE_INSET,\n (left + right) / 2,\n right - ANNOTATION_EDGE_INSET,\n ],\n placement,\n );\n\n const anchor = this.#placementCoordinate(\n [\n \"start\",\n \"middle\",\n \"end\",\n ],\n placement,\n );\n\n if (kind === \"region\") {\n return {\n x,\n y: value,\n anchor,\n };\n }\n\n return {\n x,\n y: Math.max(top + ANNOTATION_TAG_HEIGHT / 2, value - ANNOTATION_MARKER_GAP - ANNOTATION_TAG_HEIGHT / 2),\n anchor,\n };\n }\n\n /**\n * Maps a logical annotation placement without coupling it to one orientation.\n *\n * @param {unknown[]} values - Physical values for start, center, and end.\n * @param {string} placement - Logical placement.\n * @returns {unknown} Selected physical value.\n */\n #placementCoordinate(\n [\n start,\n center,\n end,\n ],\n placement,\n ) {\n if (placement === \"start\") {\n return start;\n }\n\n return placement === \"center\" ? center : end;\n }\n\n /**\n * Tests a value-axis coordinate against the current plot bounds.\n *\n * @param {number} position - Scaled value-axis position.\n * @returns {boolean} Whether the position falls inside the plot.\n */\n #insidePlot(position) {\n const { maximum, minimum } = this.#valueAxisBounds();\n\n return position >= minimum && position <= maximum;\n }\n\n /**\n * Tests whether a scaled interval intersects the plot.\n *\n * @param {number} start - First scaled endpoint.\n * @param {number} end - Second scaled endpoint.\n * @returns {boolean} Whether any portion of the interval is visible.\n */\n #overlapsPlot(start, end) {\n const { maximum, minimum } = this.#valueAxisBounds();\n\n return Math.max(start, end) >= minimum && Math.min(start, end) <= maximum;\n }\n\n /**\n * Clamps one value-axis coordinate to the plot.\n *\n * @param {number} position - Scaled value-axis coordinate.\n * @returns {number} Coordinate inside the plot bounds.\n */\n #boundedValuePosition(position) {\n const { maximum, minimum } = this.#valueAxisBounds();\n\n return Math.min(maximum, Math.max(minimum, position));\n }\n\n /**\n * Resolves the physical value-axis interval for the active orientation.\n *\n * @returns {{minimum: number, maximum: number}} Ascending plot bounds.\n */\n #valueAxisBounds() {\n const { bottom, left, right, top } = this.#layout.frame;\n\n if (this.#layout.isHorizontal) {\n return {\n minimum: left,\n maximum: right,\n };\n }\n\n return {\n minimum: top,\n maximum: bottom,\n };\n }\n\n /**\n * Places formatted numeric labels along the active value axis.\n *\n * @returns {void} Tick labels are appended to the chart SVG.\n */\n #renderValueLabels() {\n const { bottom, left, right } = this.#layout.frame;\n const scaleValues = this.#layout.values;\n const values = this.#layout.isHorizontal ? scaleValues.ticks : scaleValues.ticks.toReversed();\n\n for (const value of values) {\n const position = this.#layout.valueAt(value);\n\n const attributes = this.#layout.isHorizontal\n ? {\n x: position,\n y: bottom + this.#layout.frame.padding - VALUE_LABEL_BASELINE_OFFSET,\n class: \"charts2-label charts2-value-label\",\n \"text-anchor\": \"middle\",\n }\n : {\n x: this.#layout.isYAxisRight ? right + VALUE_LABEL_GAP : left - VALUE_LABEL_GAP,\n y: position + VALUE_LABEL_CENTER_OFFSET,\n class: \"charts2-label charts2-value-label\",\n \"text-anchor\": this.#layout.isYAxisRight ? \"start\" : \"end\",\n };\n\n this.#surface.text(formatValue(this.#chart.options, value, { target: \"axis\" }), attributes);\n }\n }\n\n /**\n * Draws guides only for the visible value-axis ticks.\n *\n * @returns {void} Major grid lines are appended to the chart SVG.\n */\n #renderGrid() {\n const { bottom, left, right, top } = this.#layout.frame;\n\n const orderedTicks = this.#layout.isHorizontal\n ? this.#layout.values.ticks\n : this.#layout.values.ticks.toReversed();\n\n for (const value of orderedTicks) {\n const position = this.#layout.valueAt(value);\n\n const attributes = this.#layout.isHorizontal\n ? { x1: position, y1: top, x2: position, y2: bottom, class: \"charts2-grid charts2-grid-vertical\" }\n : { x1: left, y1: position, x2: right, y2: position, class: \"charts2-grid charts2-grid-horizontal\" };\n\n this.#surface.append(\"line\", {\n ...attributes,\n \"data-tick\": value,\n \"aria-hidden\": \"true\",\n });\n }\n }\n\n /**\n * Draws the single visible baseline appropriate to chart orientation.\n *\n * @returns {void} One x- or y-axis line is appended to the chart SVG.\n */\n #renderAxis() {\n const { bottom, left, right, top } = this.#layout.frame;\n const axisX = this.#layout.isYAxisRight ? right : left;\n\n const attributes = this.#layout.isHorizontal\n ? { x1: axisX, y1: top, x2: axisX, y2: bottom, class: \"charts2-axis charts2-y-axis\" }\n : { x1: left, y1: bottom, x2: right, y2: bottom, class: \"charts2-axis charts2-x-axis\" };\n\n this.#surface.append(\"line\", attributes);\n }\n\n /**\n * Places bounded category labels along the active category axis.\n *\n * @returns {void} Category labels are appended to the chart SVG.\n */\n #renderCategoryLabels() {\n if (this.#chart.labels.length === 0) {\n return;\n }\n\n if (this.#layout.isHorizontal) {\n this.#renderHorizontalLabels();\n\n return;\n }\n\n this.#renderVerticalLabels();\n }\n\n /**\n * Places wrapped labels beside horizontal bar rows.\n *\n * @returns {void} Horizontal category labels are appended to the chart SVG.\n */\n #renderHorizontalLabels() {\n const { bottom, left, right, top } = this.#layout.frame;\n const step = (bottom - top) / this.#chart.labels.length;\n\n for (const [\n index,\n value,\n ] of this.#layout.categories.labels.entries()) {\n const text = wrappedLabelElement({\n value,\n attributes: {\n x: this.#layout.isYAxisRight ? right + HORIZONTAL_LABEL_GAP : left - HORIZONTAL_LABEL_GAP,\n y: top + (index + CATEGORY_MIDPOINT) * step + CATEGORY_LABEL_BASELINE_OFFSET,\n class: \"charts2-label\",\n \"text-anchor\": this.#layout.isYAxisRight ? \"start\" : \"end\",\n },\n maxWidth: this.#layout.categories.gutter - HORIZONTAL_LABEL_EDGE_INSET - HORIZONTAL_LABEL_GAP,\n originalValue: this.#chart.labels[index],\n });\n\n this.#surface.append(text);\n }\n }\n\n /**\n * Places sampled, edge-aware labels below a vertical category axis.\n *\n * @returns {void} Vertical category labels are appended to the chart SVG.\n */\n // eslint-disable-next-line max-lines-per-function -- Array layout lines do not add behavior.\n #renderVerticalLabels() {\n const { height, left, right } = this.#layout.frame;\n const shouldCenterCategories = this.#layout.type !== ChartType.LINE;\n const intervals = shouldCenterCategories ? this.#chart.labels.length : this.#chart.labels.length - 1;\n const step = (right - left) / Math.max(1, intervals);\n const stride = Math.max(1, Math.ceil(TARGET_CATEGORY_LABEL_SPACING / Math.max(1, step)));\n const visibleIndexes = [];\n\n for (let index = 0; index < this.#chart.labels.length; index += stride) {\n visibleIndexes.push(index);\n }\n\n const lastIndex = this.#chart.labels.length - 1;\n\n if (visibleIndexes.at(-1) !== lastIndex) {\n visibleIndexes.pop();\n visibleIndexes.push(lastIndex);\n }\n\n for (const [\n visibleIndex,\n index,\n ] of visibleIndexes.entries()) {\n const placement = shouldCenterCategories\n ? this.#centeredLabelPlacement({ visibleIndexes, visibleIndex, index })\n : this.#verticalLabelPlacement({ visibleIndexes, visibleIndex, index, step });\n\n const formatted = this.#layout.categories.labels[index];\n const value = Array.isArray(formatted) ? formatted.join(\" \") : formatted;\n\n const text = labelElement({\n value,\n attributes: {\n x: placement.x,\n y: height - CATEGORY_LABEL_BOTTOM_OFFSET,\n class: \"charts2-label\",\n \"text-anchor\": placement.anchor,\n },\n measurement: { maxWidth: placement.width, fontSize: 9 },\n originalValue: this.#chart.labels[index],\n });\n\n this.#surface.append(text);\n }\n }\n\n /**\n * Centers a category label on the same slot or point used by its mark.\n *\n * @param {object} state - Visible indexes and the current sampled label.\n * @param {number[]} state.visibleIndexes - Ordered source indexes that remain visible.\n * @param {number} state.visibleIndex - Position in the sampled visible collection.\n * @param {number} state.index - Source category index.\n * @returns {{x: number, anchor: string, width: number}} Bounded centered label placement.\n */\n #centeredLabelPlacement({ visibleIndexes, visibleIndex, index }) {\n const { left: plotLeft, right: plotRight } = this.#layout.frame;\n const position = this.#layout.categoryAt(index);\n\n if (visibleIndexes.length === 1) {\n return {\n x: position,\n anchor: \"middle\",\n width: plotRight - plotLeft,\n };\n }\n\n const previousBoundary =\n visibleIndex === 0\n ? plotLeft\n : (this.#layout.categoryAt(visibleIndexes[visibleIndex - 1]) + position) / 2;\n\n const nextBoundary =\n visibleIndex === visibleIndexes.length - 1\n ? plotRight\n : (position + this.#layout.categoryAt(visibleIndexes[visibleIndex + 1])) / 2;\n\n return {\n x: position,\n anchor: \"middle\",\n width: Math.max(\n MINIMUM_CATEGORY_LABEL_WIDTH,\n 2 * Math.min(position - previousBoundary, nextBoundary - position) - CATEGORY_LABEL_TOTAL_GAP,\n ),\n };\n }\n\n /**\n * Calculates alignment and width for one sampled vertical category label.\n *\n * @param {object} state - Visible indexes, current positions, and horizontal step.\n * @param {number[]} state.visibleIndexes - Ordered category indexes selected for display.\n * @param {number} state.visibleIndex - Position within the displayed-index collection.\n * @param {number} state.index - Original category index represented by the label.\n * @param {number} state.step - Horizontal distance between adjacent categories.\n * @returns {{x: number, anchor: string, width: number}} Edge-aware label placement.\n */\n #verticalLabelPlacement({ visibleIndexes, visibleIndex, index, step }) {\n const { left: plotLeft, right: plotRight } = this.#layout.frame;\n\n if (visibleIndexes.length === 1) {\n return {\n x: plotLeft,\n anchor: \"start\",\n width: plotRight - plotLeft,\n };\n }\n\n const position = plotLeft + index * step;\n const previousPosition = visibleIndex > 0 ? plotLeft + visibleIndexes[visibleIndex - 1] * step : plotLeft;\n\n const nextPosition =\n visibleIndex < visibleIndexes.length - 1\n ? plotLeft + visibleIndexes[visibleIndex + 1] * step\n : plotRight;\n\n const edgePlacement = this.#edgeVerticalLabelPlacement({\n position,\n previousPosition,\n nextPosition,\n edge: verticalLabelEdge(visibleIndex, visibleIndexes.length),\n });\n\n if (edgePlacement) {\n return edgePlacement;\n }\n\n return {\n x: position,\n anchor: \"middle\",\n width: Math.max(\n MINIMUM_CATEGORY_LABEL_WIDTH,\n Math.min(position - previousPosition, nextPosition - position) - CATEGORY_LABEL_TOTAL_GAP,\n ),\n };\n }\n\n /**\n * Resolves the asymmetric placement used by the first and last category labels.\n *\n * @param {object} geometry - Current and neighboring sampled positions.\n * @param {number} geometry.position - Current label position.\n * @param {number} geometry.previousPosition - Previous sampled label position.\n * @param {number} geometry.nextPosition - Next sampled label position.\n * @param {\"first\" | \"middle\" | \"last\"} geometry.edge - Position within the sampled collection.\n * @returns {{x: number, anchor: string, width: number} | null} Edge placement or null for middle labels.\n */\n #edgeVerticalLabelPlacement({ position, previousPosition, nextPosition, edge }) {\n const { left: plotLeft, right: plotRight } = this.#layout.frame;\n\n if (edge === \"first\") {\n return {\n x: plotLeft,\n anchor: \"start\",\n width: Math.max(\n MINIMUM_CATEGORY_LABEL_WIDTH,\n (nextPosition - position) / 2 - CATEGORY_LABEL_SIDE_GAP,\n ),\n };\n }\n\n if (edge === \"last\") {\n return {\n x: plotRight,\n anchor: \"end\",\n width: Math.max(\n MINIMUM_CATEGORY_LABEL_WIDTH,\n (position - previousPosition) / 2 - CATEGORY_LABEL_SIDE_GAP,\n ),\n };\n }\n\n return null;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import{markMetadata as t,svg as a,titled as s}from"../../support/Dom.js";import{formatLabel as r,formatValue as e}from"../../support/presentation/Formatting.js";var o=class{#t;#a;#s;constructor({chart:t,layout:a,surface:s}){this.#t=t,this.#a=a,this.#s=s}render(){for(let e=0;e<this.#a.categories.count;e+=1){const o=this.#t.labels[e],i=r(this.#t.options,o,{target:"tooltip",index:e}),n=this.#r(e),c=t(a("rect",{...this.#a.inspectorAt(e),fill:"transparent",class:"charts2-x-hit charts2-mark"}),-1,e);Object.assign(c.dataset,{tooltipHeading:String(i),tooltipItems:JSON.stringify(n)});const l=n.map(t=>`${t.name}: ${t.value}`).join(" · ");this.#s.append(s(c,`${i} — ${l}`))}}#r(t){return this.#t.datasets.map((a,s)=>{const r=a.points[t],o=e(this.#t.options,r.y,{target:"tooltip",dataset:a,datasetIndex:s,datasetName:a.name,index:t,label:this.#t.labels[t],point:r}),i=void 0===r.r?"":`, size ${r.r}`;return{name:a.name,value:`${o}${i}`,color:a.color}})}};export{o as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CartesianInspectorRenderer.js","names":["#chart","#layout","#surface","#itemsAt"],"sources":["../../../src/renderers/cartesian/CartesianInspectorRenderer.js"],"sourcesContent":["import { markMetadata, svg, titled } from \"../../support/Dom.js\";\nimport { formatLabel, formatValue } from \"../../support/presentation/Formatting.js\";\n\n/**\n * Renders category-sized interaction targets for dense Cartesian series.\n */\nexport default class CartesianInspectorRenderer {\n #chart;\n #layout;\n #surface;\n\n /**\n * Binds normalized chart state to one immutable Cartesian layout snapshot.\n *\n * @param {object} state - Collaborators required for one inspector pass.\n * @param {object} state.chart - Frozen chart data and options.\n * @param {object} state.layout - Scales and bounds resolved by `CartesianRenderer`.\n * @param {import(\"../SvgSurface.js\").default} state.surface - Owned SVG drawing surface.\n */\n constructor({ chart, layout, surface }) {\n this.#chart = chart;\n this.#layout = layout;\n this.#surface = surface;\n }\n\n /**\n * Appends one accessible interaction target for every category.\n *\n * @returns {void} Inspector targets and structured tooltip metadata are appended.\n */\n render() {\n for (let index = 0; index < this.#layout.categories.count; index += 1) {\n const rawLabel = this.#chart.labels[index];\n const label = formatLabel(this.#chart.options, rawLabel, { target: \"tooltip\", index });\n const items = this.#itemsAt(index);\n\n const hitTarget = markMetadata(\n svg(\"rect\", {\n ...this.#layout.inspectorAt(index),\n fill: \"transparent\",\n class: \"charts2-x-hit charts2-mark\",\n }),\n -1,\n index,\n );\n\n Object.assign(hitTarget.dataset, {\n tooltipHeading: String(label),\n tooltipItems: JSON.stringify(items),\n });\n const summary = items.map((item) => `${item.name}: ${item.value}`).join(\" · \");\n this.#surface.append(titled(hitTarget, `${label} — ${summary}`));\n }\n }\n\n /**\n * Presents every available series value at one category index.\n *\n * @param {number} index - Category index shared by all datasets.\n * @returns {Array<object>} Existing values formatted as tooltip rows.\n */\n #itemsAt(index) {\n return this.#chart.datasets.map((dataset, datasetIndex) => {\n const point = dataset.points[index];\n\n const formattedValue = formatValue(this.#chart.options, point.y, {\n target: \"tooltip\",\n dataset,\n datasetIndex,\n datasetName: dataset.name,\n index,\n label: this.#chart.labels[index],\n point,\n });\n\n const size = point.r === undefined ? \"\" : `, size ${point.r}`;\n\n return {\n name: dataset.name,\n value: `${formattedValue}${size}`,\n color: dataset.color,\n };\n });\n }\n}\n"],"mappings":"iKAMA,IAAqB,EAArB,MACE,GACA,GACA,GAUA,WAAA,EAAY,MAAE,EAAA,OAAO,EAAA,QAAQ,IAC3B,MAAKA,EAAS,EACd,MAAKC,EAAU,EACf,MAAKC,EAAW,CAClB,CAOA,MAAA,GACE,IAAK,IAAI,EAAQ,EAAG,EAAQ,MAAKD,EAAQ,WAAW,MAAO,GAAS,EAAG,CACrE,MAAM,EAAW,MAAKD,EAAO,OAAO,GAC9B,EAAQ,EAAY,MAAKA,EAAO,QAAS,EAAU,CAAE,OAAQ,UAAW,UACxE,EAAQ,MAAKG,EAAS,GAEtB,EAAY,EAChB,EAAI,OAAQ,IACP,MAAKF,EAAQ,YAAY,GAC5B,KAAM,cACN,MAAO,gCAET,EACA,GAGF,OAAO,OAAO,EAAU,QAAS,CAC/B,eAAgB,OAAO,GACvB,aAAc,KAAK,UAAU,KAE/B,MAAM,EAAU,EAAM,IAAK,GAAS,GAAG,EAAK,SAAS,EAAK,SAAS,KAAK,OACxE,MAAKC,EAAS,OAAO,EAAO,EAAW,GAAG,OAAW,KACvD,CACF,CAQA,EAAA,CAAS,GACP,OAAO,MAAKF,EAAO,SAAS,IAAA,CAAK,EAAS,KACxC,MAAM,EAAQ,EAAQ,OAAO,GAEvB,EAAiB,EAAY,MAAKA,EAAO,QAAS,EAAM,EAAG,CAC/D,OAAQ,UACR,UACA,eACA,YAAa,EAAQ,KACrB,QACA,MAAO,MAAKA,EAAO,OAAO,GAC1B,UAGI,OAAmB,IAAZ,EAAM,EAAkB,GAAK,UAAU,EAAM,IAE1D,MAAO,CACL,KAAM,EAAQ,KACd,MAAO,GAAG,IAAiB,IAC3B,MAAO,EAAQ,QAGrB"}
@@ -0,0 +1 @@
1
+ import{ChartOrientation as t,ChartType as s,YAxisPosition as e}from"../../support/Constants.js";import{extent as i,niceValueScale as a,scale as o}from"../../support/geometry/Scale.js";import{formatCategoryLabel as r,horizontalCategoryPadding as n,legendLayout as h,verticalValuePadding as c}from"../../support/presentation/Presentation.js";var l=class{#t;#s;#e;#i;#a;#o;constructor(t){this.#t=t;const s=this.#r();this.#n(s),this.orientation=s.orientation,this.type=s.type,this.isHorizontal=s.isHorizontal,this.isYAxisRight=s.isYAxisRight,this.usesInspector=s.usesInspector,this.showsIndividualMarks=s.count<=40,this.frame=Object.freeze(s.frame),this.categories=Object.freeze({labels:s.labels,count:s.count,gutter:s.gutter}),this.values=Object.freeze(s.values),this.bars=Object.freeze({datasets:s.barDatasets,isStacked:s.isStacked}),this.#o=this.#h(),Object.freeze(this)}#n(t){const s={points:t.points,values:t.values},e={count:t.count,orientation:t.orientation,isHorizontal:t.isHorizontal,hasBars:t.barDatasets.length>0,type:t.type},i=this.#c(t.frame,s,e);this.#s=i.x,this.#e=i.y,this.#a=i.value,this.#i=i.pointX}pointAt(t,s){return{x:this.#i(t,s),y:this.#e(t.y)}}categoryAt(t){return this.#i(this.#t.datasets[0].points[t],t)}xAt(t){return this.#s(t)}yAt(t){return this.#e(t)}valueAt(t){return this.#a(t)}barFor(s,{category:e,series:i,base:a}){const{bottom:o,left:r,right:n,top:h}=this.frame,c=(this.orientation===t.VERTICAL?n-r:o-h)/this.categories.count,l=this.bars.isStacked?1:Math.max(1,this.bars.datasets.length),p=Math.max(2,.64*c/l),u=(c-p*l)/2,d=(this.bars.isStacked?0:i)*p;if(this.isHorizontal){const t=this.valueAt(a),i=this.valueAt(a+s.y);return{x:Math.min(t,i),y:h+e*c+u+d,width:Math.abs(i-t),height:p,thickness:p}}const g=this.yAt(a),m=this.yAt(a+s.y);return{x:r+e*c+u+d,y:Math.min(g,m),width:p,height:Math.abs(m-g),thickness:p}}inspectorAt(t){return this.#o[t]}#r(){const{height:t,orientation:s,type:e,width:i}=this.#t.options,a=this.#l({orientation:s,type:e,width:i}),o=this.#p({...a,type:e,width:i}),r={width:i,height:t,padding:a.padding,top:a.top,right:i-(a.isYAxisRight?o.gutter:a.padding),bottom:t-a.padding,left:a.isYAxisRight?a.padding:o.gutter},n=this.#u(e)&&o.count<=64;return{orientation:s,type:e,...a,...o,frame:r,usesInspector:n}}#l({orientation:i,type:a,width:o}){const n=!this.#t.options.axes&&!this.#t.options.grid&&!this.#t.options.valueLabels,h=n?Math.max(this.#t.options.strokeWidth,1):28;return{isFrameless:n,padding:h,top:h+20*Math.max(0,this.#d(o)-1),isHorizontal:a===s.BAR&&i===t.HORIZONTAL,labels:this.#t.labels.map((t,s)=>r(this.#t.options,t,s)),isYAxisRight:this.#t.options.yAxisPosition===e.RIGHT}}#p(t){const s=this.#t.datasets.flatMap(t=>t.points),e=Math.max(...this.#t.datasets.map(t=>t.points.length)),i=this.#g(t.type),a=Boolean(this.#t.options.stacked),o=this.#m(s,{datasets:i,isStacked:a},t);return{points:s,count:e,barDatasets:i,isStacked:a,values:o,gutter:this.#y(t.labels,o,t)}}#c(e,a,r){const n=a.points.map(t=>t.x),h=r.hasBars||r.type===s.LINE?i(n):this.#f(n),c=t=>o(t,h,[e.left,e.right]),l=t=>o(t,a.values.domain,[e.bottom,e.top]);let p=l;r.isHorizontal&&(p=t=>o(t,a.values.domain,[e.left,e.right]));const u=(e.right-e.left)/r.count;let d=t=>c(t.x);return r.orientation===t.VERTICAL&&r.hasBars&&(d=(t,s)=>(t=>e.left+(t+.5)*u)(s)),{x:c,y:l,value:p,pointX:d}}#f(t){const s=[...new Set(t)].toSorted((t,s)=>t-s);if(s.length<2)return i(s);const e=s[0],a=s[1],o=s.at(-1);return[e-(a-e)/2,o+(o-s.at(-2))/2]}#d(t){if(!this.#t.options.legend||this.#t.datasets.length<2)return 0;const s=this.#t.datasets.map(t=>({label:t.name,color:t.color}));return h(t,s).rows}#g(t){return this.#t.datasets.filter(e=>t===s.BAR||t===s.AXIS_MIXED&&e.chartType===s.BAR)}#m(t,e,o){const r=e.isStacked?function(t){const s=Math.max(...t.map(t=>t.points.length)),e=[];for(let i=0;i<s;i+=1){let s=0,a=0;for(const e of t){const t=e.points[i].y;t>0&&(s+=t),t<0&&(a+=t)}e.push(s,a)}return e}(e.datasets):[],n=this.#b();let h=[...t.map(t=>t.y),...r,...n,0];return o.isFrameless&&o.type===s.LINE&&(h=t.map(t=>t.y)),o.isFrameless?{domain:i(h),ticks:[]}:a(h)}#b(){return[...this.#t.source.yMarkers.filter(t=>t.includeInDomain).map(t=>t.value),...this.#t.source.yRegions.filter(t=>t.includeInDomain).flatMap(t=>t.range)]}#y(t,s,e){return e.isHorizontal&&this.#t.labels.length>0?n(t,e.width):e.isFrameless?e.padding:c(s.ticks,e.padding)}#u(t){if(t===s.AXIS_MIXED)return"function"!=typeof this.#t.options.onSelect&&this.#t.datasets.every(t=>[s.LINE,s.BAR].includes(t.chartType));if([s.SCATTER,s.BUBBLE].includes(t)){if("function"==typeof this.#t.options.onSelect)return!1;const[t,...s]=this.#t.datasets;return s.every(s=>s.points.length===t.points.length&&s.points.every((s,e)=>s.x===t.points[e].x))}return[s.LINE,s.BAR].includes(t)}#h(){const{bottom:t,left:s,right:e,top:i}=this.frame,a=Array.from({length:this.categories.count},(s,e)=>this.isHorizontal?i+(e+.5)*(t-i)/this.categories.count:this.categoryAt(e));return Object.freeze(a.map((o,r)=>{let n=(a[r-1]+o)/2,h=(o+a[r+1])/2;0===r&&(n=this.isHorizontal?i:s),r===a.length-1&&(h=this.isHorizontal?t:e);const c=this.isHorizontal?{x:s,y:n,width:e-s,height:Math.max(1,h-n)}:{x:n,y:i,width:Math.max(1,h-n),height:t-i};return Object.freeze(c)}))}};export{l as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CartesianLayout.js","names":["#chart","#resolveState","#bindScales","#inspectorBands","#resolveInspectorBands","#scalesFor","#x","#y","#valuePosition","#pointX","#presentationState","#dataState","#supportsInspector","#legendRows","#barDatasets","#valueScale","#valueGutter","#paddedXDomain","#annotationValues"],"sources":["../../../src/renderers/cartesian/CartesianLayout.js"],"sourcesContent":["import {\n ChartOrientation,\n ChartType,\n LEGEND_ROW_HEIGHT,\n MAX_INDIVIDUAL_LINE_POINTS,\n MAX_X_INSPECTOR_POINTS,\n YAxisPosition,\n} from \"../../support/Constants.js\";\nimport { extent, niceValueScale, scale } from \"../../support/geometry/Math.js\";\nimport {\n formatCategoryLabel,\n horizontalCategoryPadding,\n legendLayout,\n verticalValuePadding,\n} from \"../../support/presentation/Presentation.js\";\n\nconst BAR_SLOT_RATIO = 0.64;\nconst PENULTIMATE_INDEX = -2;\nconst STANDARD_FRAME_PADDING = 28;\nconst SLOT_MIDPOINT = 0.5;\n\n/**\n * Sums positive and negative stacked values independently for scale calculation.\n *\n * @param {Array<object>} datasets - Normalized bar datasets sharing category positions.\n * @returns {number[]} Signed stack totals across every category.\n */\nfunction stackedBarValues(datasets) {\n const pointCount = Math.max(...datasets.map((dataset) => dataset.points.length));\n const totals = [];\n\n for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {\n let positive = 0;\n let negative = 0;\n\n for (const dataset of datasets) {\n const value = dataset.points[pointIndex].y;\n\n if (value > 0) {\n positive += value;\n }\n\n if (value < 0) {\n negative += value;\n }\n }\n\n totals.push(positive, negative);\n }\n\n return totals;\n}\n\n/**\n * Owns the immutable geometry shared by Cartesian rendering collaborators.\n */\nexport default class CartesianLayout {\n #chart;\n #x;\n #y;\n #pointX;\n #valuePosition;\n #inspectorBands;\n\n /**\n * Resolves chart geometry once and freezes the public layout vocabulary.\n *\n * @param {object} chart - Frozen Cartesian data and options for one render.\n */\n constructor(chart) {\n this.#chart = chart;\n const state = this.#resolveState();\n\n this.#bindScales(state);\n\n this.orientation = state.orientation;\n this.type = state.type;\n this.isHorizontal = state.isHorizontal;\n this.isYAxisRight = state.isYAxisRight;\n this.usesInspector = state.usesInspector;\n this.showsIndividualMarks = state.count <= MAX_INDIVIDUAL_LINE_POINTS;\n this.frame = Object.freeze(state.frame);\n this.categories = Object.freeze({ labels: state.labels, count: state.count, gutter: state.gutter });\n this.values = Object.freeze(state.values);\n this.bars = Object.freeze({ datasets: state.barDatasets, isStacked: state.isStacked });\n this.#inspectorBands = this.#resolveInspectorBands();\n Object.freeze(this);\n }\n\n /**\n * Binds internal scale functions from resolved layout state.\n *\n * @param {object} state - Resolved Cartesian frame and data collections.\n * @returns {void} Private scale functions are assigned for the snapshot.\n */\n #bindScales(state) {\n const scaleData = { points: state.points, values: state.values };\n\n const categoryScale = {\n count: state.count,\n orientation: state.orientation,\n isHorizontal: state.isHorizontal,\n hasBars: state.barDatasets.length > 0,\n type: state.type,\n };\n\n const scales = this.#scalesFor(state.frame, scaleData, categoryScale);\n this.#x = scales.x;\n this.#y = scales.y;\n this.#valuePosition = scales.value;\n this.#pointX = scales.pointX;\n }\n\n /**\n * Maps one normalized point to Cartesian screen coordinates.\n *\n * @param {{x: number, y: number}} point - Normalized Cartesian point.\n * @param {number} index - Category position used by slot-based charts.\n * @returns {{x: number, y: number}} Screen-space point.\n */\n pointAt(point, index) {\n return {\n x: this.#pointX(point, index),\n y: this.#y(point.y),\n };\n }\n\n /**\n * Maps one category index to its horizontal screen coordinate.\n *\n * @param {number} index - Zero-based category position.\n * @returns {number} Screen-space category coordinate.\n */\n categoryAt(index) {\n return this.#pointX(this.#chart.datasets[0].points[index], index);\n }\n\n /**\n * Maps a continuous x-domain value to the horizontal plot range.\n *\n * @param {number} value - Normalized x-domain value.\n * @returns {number} Horizontal screen coordinate.\n */\n xAt(value) {\n return this.#x(value);\n }\n\n /**\n * Maps a numeric value to the vertical plot range.\n *\n * @param {number} value - Normalized y-domain value.\n * @returns {number} Vertical screen coordinate.\n */\n yAt(value) {\n return this.#y(value);\n }\n\n /**\n * Maps a value onto the active horizontal or vertical value axis.\n *\n * @param {number} value - Normalized numeric value.\n * @returns {number} Screen coordinate on the active value axis.\n */\n valueAt(value) {\n return this.#valuePosition(value);\n }\n\n /**\n * Resolves one grouped or stacked bar without exposing slot calculations.\n *\n * @param {{y: number}} point - Normalized bar point.\n * @param {object} placement - Source position and signed stack base.\n * @param {number} placement.category - Zero-based category position.\n * @param {number} placement.series - Position within bar-rendered datasets.\n * @param {number} placement.base - Signed value accumulated before this segment.\n * @returns {{x: number, y: number, width: number, height: number, thickness: number}} Bar rectangle and visible thickness.\n */\n barFor(point, { category, series, base }) {\n const { bottom, left, right, top } = this.frame;\n const available = this.orientation === ChartOrientation.VERTICAL ? right - left : bottom - top;\n const slot = available / this.categories.count;\n const groupCount = this.bars.isStacked ? 1 : Math.max(1, this.bars.datasets.length);\n const thickness = Math.max(2, (slot * BAR_SLOT_RATIO) / groupCount);\n const groupOffset = (slot - thickness * groupCount) / 2;\n const datasetOffset = (this.bars.isStacked ? 0 : series) * thickness;\n\n if (this.isHorizontal) {\n const zero = this.valueAt(base);\n const value = this.valueAt(base + point.y);\n\n return {\n x: Math.min(zero, value),\n y: top + category * slot + groupOffset + datasetOffset,\n width: Math.abs(value - zero),\n height: thickness,\n thickness,\n };\n }\n\n const zero = this.yAt(base);\n const value = this.yAt(base + point.y);\n\n return {\n x: left + category * slot + groupOffset + datasetOffset,\n y: Math.min(zero, value),\n width: thickness,\n height: Math.abs(value - zero),\n thickness,\n };\n }\n\n /**\n * Returns the precomputed interaction rectangle for one category.\n *\n * @param {number} index - Zero-based category position.\n * @returns {object | undefined} SVG rectangle attributes or undefined outside the layout.\n */\n inspectorAt(index) {\n return this.#inspectorBands[index];\n }\n\n /**\n * Resolves frame, collections, and policy flags before scale binding.\n *\n * @returns {object} Internal Cartesian layout state.\n */\n #resolveState() {\n const { height, orientation, type, width } = this.#chart.options;\n const presentation = this.#presentationState({ orientation, type, width });\n const data = this.#dataState({ ...presentation, type, width });\n\n const frame = {\n width,\n height,\n padding: presentation.padding,\n top: presentation.top,\n right: width - (presentation.isYAxisRight ? data.gutter : presentation.padding),\n bottom: height - presentation.padding,\n left: presentation.isYAxisRight ? presentation.padding : data.gutter,\n };\n\n const supportsInspector = this.#supportsInspector(type);\n\n const usesInspector = supportsInspector && data.count <= MAX_X_INSPECTOR_POINTS;\n\n return {\n orientation,\n type,\n ...presentation,\n ...data,\n frame,\n usesInspector,\n };\n }\n\n /**\n * Resolves presentation flags and formatted categories.\n *\n * @param {object} source - Orientation, type, and viewport width.\n * @param {string} source.orientation - Direction used for bar category slots.\n * @param {string} source.type - Current Cartesian chart type.\n * @param {number} source.width - Total chart width.\n * @returns {object} Frame padding, legend offset, axis direction, and labels.\n */\n #presentationState({ orientation, type, width }) {\n const isFrameless =\n !this.#chart.options.axes && !this.#chart.options.grid && !this.#chart.options.valueLabels;\n\n const padding = isFrameless ? Math.max(this.#chart.options.strokeWidth, 1) : STANDARD_FRAME_PADDING;\n const top = padding + Math.max(0, this.#legendRows(width) - 1) * LEGEND_ROW_HEIGHT;\n const isHorizontal = type === ChartType.BAR && orientation === ChartOrientation.HORIZONTAL;\n\n const labels = this.#chart.labels.map((label, index) =>\n formatCategoryLabel(this.#chart.options, label, index),\n );\n\n const isYAxisRight = this.#chart.options.yAxisPosition === YAxisPosition.RIGHT;\n\n return {\n isFrameless,\n padding,\n top,\n isHorizontal,\n labels,\n isYAxisRight,\n };\n }\n\n /**\n * Resolves flattened points, bar policy, value scale, and label gutter.\n *\n * @param {object} state - Presentation state plus chart type and width.\n * @returns {object} Collections and scale data needed by the layout.\n */\n #dataState(state) {\n const points = this.#chart.datasets.flatMap((dataset) => dataset.points);\n const count = Math.max(...this.#chart.datasets.map((dataset) => dataset.points.length));\n const barDatasets = this.#barDatasets(state.type);\n const isStacked = Boolean(this.#chart.options.stacked);\n const values = this.#valueScale(points, { datasets: barDatasets, isStacked }, state);\n const gutter = this.#valueGutter(state.labels, values, state);\n\n return {\n points,\n count,\n barDatasets,\n isStacked,\n values,\n gutter,\n };\n }\n\n /**\n * Creates bound scale functions from resolved immutable state.\n *\n * @param {object} frame - Plot boundaries.\n * @param {object} data - Flattened points and value scale.\n * @param {object} category - Category count, direction, and slot policy.\n * @returns {object} Bound x, y, value, and point-position functions.\n */\n // eslint-disable-next-line max-lines-per-function -- Returned-object layout lines do not add behavior.\n #scalesFor(frame, data, category) {\n const xValues = data.points.map((point) => point.x);\n const keepsEdgeDomain = category.hasBars || category.type === ChartType.LINE;\n const xDomain = keepsEdgeDomain ? extent(xValues) : this.#paddedXDomain(xValues);\n\n const x = (value) =>\n scale(value, xDomain, [\n frame.left,\n frame.right,\n ]);\n\n const y = (value) =>\n scale(value, data.values.domain, [\n frame.bottom,\n frame.top,\n ]);\n\n let value = y;\n\n if (category.isHorizontal) {\n value = (entry) =>\n scale(entry, data.values.domain, [\n frame.left,\n frame.right,\n ]);\n }\n\n const slot = (frame.right - frame.left) / category.count;\n const center = (index) => frame.left + (index + SLOT_MIDPOINT) * slot;\n const hasCategorySlots = category.orientation === ChartOrientation.VERTICAL && category.hasBars;\n let pointX = (point) => x(point.x);\n\n if (hasCategorySlots) {\n pointX = (_point, index) => center(index);\n }\n\n return {\n x,\n y,\n value,\n pointX,\n };\n }\n\n /**\n * Adds half of each outer neighbor interval to an independent x-domain.\n *\n * Line charts intentionally keep their endpoints on the plot boundary,\n * while point-based charts need room for complete outer inspection cells.\n *\n * @param {number[]} values - X coordinates from every rendered dataset.\n * @returns {[number, number]} Domain including both outer half intervals.\n */\n #paddedXDomain(values) {\n const ordered = [\n ...new Set(values),\n ].toSorted((left, right) => left - right);\n\n if (ordered.length < 2) {\n return extent(ordered);\n }\n\n const first = ordered[0];\n const second = ordered[1];\n const last = ordered.at(-1);\n const previous = ordered.at(PENULTIMATE_INDEX);\n\n return [\n first - (second - first) / 2,\n last + (last - previous) / 2,\n ];\n }\n\n /**\n * Counts wrapped legend rows that shift the plotting area.\n *\n * @param {number} width - Available chart width in pixels.\n * @returns {number} Number of visible legend rows.\n */\n #legendRows(width) {\n if (!this.#chart.options.legend || this.#chart.datasets.length < 2) {\n return 0;\n }\n\n const items = this.#chart.datasets.map((dataset) => ({ label: dataset.name, color: dataset.color }));\n\n return legendLayout(width, items).rows;\n }\n\n /**\n * Selects datasets participating in grouped or stacked bars.\n *\n * @param {string} type - Current Cartesian chart type.\n * @returns {Array<object>} Ordered bar-rendered datasets.\n */\n #barDatasets(type) {\n return this.#chart.datasets.filter((dataset) => {\n if (type === ChartType.BAR) {\n return true;\n }\n\n if (type !== ChartType.AXIS_MIXED) {\n return false;\n }\n\n return dataset.chartType === ChartType.BAR;\n });\n }\n\n /**\n * Resolves a value domain that includes zero and signed stacks when required.\n *\n * @param {Array<object>} points - Flattened normalized points.\n * @param {object} bars - Bar datasets and stacking policy.\n * @param {object} presentation - Frameless flag and chart type.\n * @returns {{domain: [number, number], ticks: number[]}} Numeric domain and visible ticks.\n */\n #valueScale(points, bars, presentation) {\n const stackValues = bars.isStacked ? stackedBarValues(bars.datasets) : [];\n const annotationValues = this.#annotationValues();\n let data = [\n ...points.map((point) => point.y),\n ...stackValues,\n ...annotationValues,\n 0,\n ];\n\n if (presentation.isFrameless && presentation.type === ChartType.LINE) {\n data = points.map((point) => point.y);\n }\n\n return presentation.isFrameless ? { domain: extent(data), ticks: [] } : niceValueScale(data);\n }\n\n /**\n * Collects opted-in marker values and region endpoints for automatic domains.\n *\n * @returns {number[]} Ordered annotation values participating in the scale.\n */\n #annotationValues() {\n const markers = this.#chart.source.yMarkers\n .filter((marker) => marker.includeInDomain)\n .map((marker) => marker.value);\n\n const regions = this.#chart.source.yRegions\n .filter((region) => region.includeInDomain)\n .flatMap((region) => region.range);\n\n return [\n ...markers,\n ...regions,\n ];\n }\n\n /**\n * Reserves horizontal space for category or numeric labels.\n *\n * @param {Array<string | string[]>} labels - Formatted category labels.\n * @param {object} values - Value domain and ticks.\n * @param {object} presentation - Orientation, frame, and viewport policy.\n * @returns {number} Horizontal label gutter in pixels.\n */\n #valueGutter(labels, values, presentation) {\n if (presentation.isHorizontal && this.#chart.labels.length > 0) {\n return horizontalCategoryPadding(labels, presentation.width);\n }\n\n return presentation.isFrameless\n ? presentation.padding\n : verticalValuePadding(values.ticks, presentation.padding);\n }\n\n /**\n * Determines whether every series shares category inspector geometry.\n *\n * @param {string} type - Current Cartesian chart type.\n * @returns {boolean} True when a shared category inspector is valid.\n */\n // eslint-disable-next-line max-lines-per-function -- Array layout lines do not add behavior.\n #supportsInspector(type) {\n if (type === ChartType.AXIS_MIXED) {\n return (\n typeof this.#chart.options.onSelect !== \"function\" &&\n this.#chart.datasets.every((dataset) =>\n [\n ChartType.LINE,\n ChartType.BAR,\n ].includes(dataset.chartType),\n )\n );\n }\n\n if (\n [\n ChartType.SCATTER,\n ChartType.BUBBLE,\n ].includes(type)\n ) {\n if (typeof this.#chart.options.onSelect === \"function\") {\n return false;\n }\n\n const [\n firstDataset,\n ...otherDatasets\n ] = this.#chart.datasets;\n\n return otherDatasets.every(\n (dataset) =>\n dataset.points.length === firstDataset.points.length &&\n dataset.points.every((point, index) => point.x === firstDataset.points[index].x),\n );\n }\n\n return [\n ChartType.LINE,\n ChartType.BAR,\n ].includes(type);\n }\n\n /**\n * Precomputes category-sized interaction rectangles for constant-time lookup.\n *\n * @returns {Array<object>} Frozen inspector rectangle attributes.\n */\n #resolveInspectorBands() {\n const { bottom, left, right, top } = this.frame;\n\n const centers = Array.from({ length: this.categories.count }, (_, index) => {\n if (this.isHorizontal) {\n return top + ((index + SLOT_MIDPOINT) * (bottom - top)) / this.categories.count;\n }\n\n return this.categoryAt(index);\n });\n\n return Object.freeze(\n centers.map((center, index) => {\n let start = (centers[index - 1] + center) / 2;\n let end = (center + centers[index + 1]) / 2;\n\n if (index === 0) {\n start = this.isHorizontal ? top : left;\n }\n\n if (index === centers.length - 1) {\n end = this.isHorizontal ? bottom : right;\n }\n\n const rectangle = this.isHorizontal\n ? { x: left, y: start, width: right - left, height: Math.max(1, end - start) }\n : { x: start, y: top, width: Math.max(1, end - start), height: bottom - top };\n\n return Object.freeze(rectangle);\n }),\n );\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import r from"../LegendRenderer.js";import e from"./CartesianAxesRenderer.js";import t from"./CartesianInspectorRenderer.js";import n from"./CartesianLayout.js";import{renderBarSeries as s,renderLineSeries as o,renderMixedSeries as i,renderPointSeries as c}from"./CartesianSeriesRendering.js";var a=class{#r;#e;#t;constructor({chart:r,surface:e},t){this.#r=r,this.#e=e,this.#t=t}render(){const r=new n(this.#r),s={chart:this.#r,layout:r,surface:this.#e},o=new e(s);o.renderBackground(),this.#t(s),o.renderForeground();const i=this.#r.options.tooltip||"function"==typeof this.#r.options.onSelect;r.usesInspector&&i&&new t(s).render()}};function f(e,t){new a(e,t).render(),new r(e).render()}function h(r){f(r,o)}function u(r){f(r,s)}function d(r){f(r,c)}function p(r){f(r,i)}export{u as renderBarChart,h as renderLineChart,p as renderMixedChart,d as renderPointChart};