@seed-ship/mcp-ui-solid 6.23.0 → 6.25.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 (172) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/README.md +154 -2
  3. package/dist/components/ActionGroupRenderer.cjs +6 -6
  4. package/dist/components/ActionGroupRenderer.cjs.map +1 -1
  5. package/dist/components/ActionGroupRenderer.js +6 -6
  6. package/dist/components/ActionGroupRenderer.js.map +1 -1
  7. package/dist/components/AutocompleteDropdown.cjs +6 -6
  8. package/dist/components/AutocompleteDropdown.cjs.map +1 -1
  9. package/dist/components/AutocompleteDropdown.js +6 -6
  10. package/dist/components/AutocompleteDropdown.js.map +1 -1
  11. package/dist/components/AutocompleteFormField.cjs +6 -5
  12. package/dist/components/AutocompleteFormField.cjs.map +1 -1
  13. package/dist/components/AutocompleteFormField.d.ts.map +1 -1
  14. package/dist/components/AutocompleteFormField.js +6 -5
  15. package/dist/components/AutocompleteFormField.js.map +1 -1
  16. package/dist/components/ChartJSRenderer.cjs +406 -70
  17. package/dist/components/ChartJSRenderer.cjs.map +1 -1
  18. package/dist/components/ChartJSRenderer.d.ts.map +1 -1
  19. package/dist/components/ChartJSRenderer.js +407 -71
  20. package/dist/components/ChartJSRenderer.js.map +1 -1
  21. package/dist/components/ChatPrompt.cjs +5 -5
  22. package/dist/components/ChatPrompt.cjs.map +1 -1
  23. package/dist/components/ChatPrompt.js +5 -5
  24. package/dist/components/ChatPrompt.js.map +1 -1
  25. package/dist/components/ComponentToolbar.cjs +5 -5
  26. package/dist/components/ComponentToolbar.cjs.map +1 -1
  27. package/dist/components/ComponentToolbar.js +5 -5
  28. package/dist/components/ComponentToolbar.js.map +1 -1
  29. package/dist/components/DegradedFallback.cjs +35 -3
  30. package/dist/components/DegradedFallback.cjs.map +1 -1
  31. package/dist/components/DegradedFallback.d.ts +7 -0
  32. package/dist/components/DegradedFallback.d.ts.map +1 -1
  33. package/dist/components/DegradedFallback.js +35 -3
  34. package/dist/components/DegradedFallback.js.map +1 -1
  35. package/dist/components/ExpandableWrapper.cjs +10 -7
  36. package/dist/components/ExpandableWrapper.cjs.map +1 -1
  37. package/dist/components/ExpandableWrapper.d.ts.map +1 -1
  38. package/dist/components/ExpandableWrapper.js +10 -7
  39. package/dist/components/ExpandableWrapper.js.map +1 -1
  40. package/dist/components/FormFieldRenderer.cjs +13 -12
  41. package/dist/components/FormFieldRenderer.cjs.map +1 -1
  42. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  43. package/dist/components/FormFieldRenderer.js +13 -12
  44. package/dist/components/FormFieldRenderer.js.map +1 -1
  45. package/dist/components/FormRenderer.cjs +1 -1
  46. package/dist/components/FormRenderer.cjs.map +1 -1
  47. package/dist/components/FormRenderer.js +1 -1
  48. package/dist/components/FormRenderer.js.map +1 -1
  49. package/dist/components/GenerativeUIErrorBoundary.cjs +1 -1
  50. package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
  51. package/dist/components/GenerativeUIErrorBoundary.js +1 -1
  52. package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
  53. package/dist/components/GhostText.cjs +2 -2
  54. package/dist/components/GhostText.cjs.map +1 -1
  55. package/dist/components/GhostText.js +2 -2
  56. package/dist/components/GhostText.js.map +1 -1
  57. package/dist/components/GraphRenderer.cjs +100 -29
  58. package/dist/components/GraphRenderer.cjs.map +1 -1
  59. package/dist/components/GraphRenderer.d.ts +1 -1
  60. package/dist/components/GraphRenderer.d.ts.map +1 -1
  61. package/dist/components/GraphRenderer.js +100 -29
  62. package/dist/components/GraphRenderer.js.map +1 -1
  63. package/dist/components/MissingValue.cjs +43 -0
  64. package/dist/components/MissingValue.cjs.map +1 -0
  65. package/dist/components/MissingValue.d.ts +27 -0
  66. package/dist/components/MissingValue.d.ts.map +1 -0
  67. package/dist/components/MissingValue.js +43 -0
  68. package/dist/components/MissingValue.js.map +1 -0
  69. package/dist/components/ModalRenderer.cjs +39 -31
  70. package/dist/components/ModalRenderer.cjs.map +1 -1
  71. package/dist/components/ModalRenderer.d.ts.map +1 -1
  72. package/dist/components/ModalRenderer.js +40 -32
  73. package/dist/components/ModalRenderer.js.map +1 -1
  74. package/dist/components/PortalDropdownMenu.cjs +6 -3
  75. package/dist/components/PortalDropdownMenu.cjs.map +1 -1
  76. package/dist/components/PortalDropdownMenu.d.ts.map +1 -1
  77. package/dist/components/PortalDropdownMenu.js +7 -4
  78. package/dist/components/PortalDropdownMenu.js.map +1 -1
  79. package/dist/components/ScratchpadPanel.cjs +38 -44
  80. package/dist/components/ScratchpadPanel.cjs.map +1 -1
  81. package/dist/components/ScratchpadPanel.d.ts.map +1 -1
  82. package/dist/components/ScratchpadPanel.js +38 -44
  83. package/dist/components/ScratchpadPanel.js.map +1 -1
  84. package/dist/components/UIResourceRenderer.cjs +255 -217
  85. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  86. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  87. package/dist/components/UIResourceRenderer.js +255 -217
  88. package/dist/components/UIResourceRenderer.js.map +1 -1
  89. package/dist/components/chart-data-table.cjs +30 -5
  90. package/dist/components/chart-data-table.cjs.map +1 -1
  91. package/dist/components/chart-data-table.d.ts +18 -1
  92. package/dist/components/chart-data-table.d.ts.map +1 -1
  93. package/dist/components/chart-data-table.js +30 -5
  94. package/dist/components/chart-data-table.js.map +1 -1
  95. package/dist/components/chart-missing-plugin.cjs +194 -0
  96. package/dist/components/chart-missing-plugin.cjs.map +1 -0
  97. package/dist/components/chart-missing-plugin.d.ts +129 -0
  98. package/dist/components/chart-missing-plugin.d.ts.map +1 -0
  99. package/dist/components/chart-missing-plugin.js +194 -0
  100. package/dist/components/chart-missing-plugin.js.map +1 -0
  101. package/dist/context/MCPUIStringsContext.cjs +12 -1
  102. package/dist/context/MCPUIStringsContext.cjs.map +1 -1
  103. package/dist/context/MCPUIStringsContext.d.ts +62 -0
  104. package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
  105. package/dist/context/MCPUIStringsContext.js +12 -1
  106. package/dist/context/MCPUIStringsContext.js.map +1 -1
  107. package/dist/services/component-registry.cjs +9 -2
  108. package/dist/services/component-registry.cjs.map +1 -1
  109. package/dist/services/component-registry.d.ts.map +1 -1
  110. package/dist/services/component-registry.js +9 -2
  111. package/dist/services/component-registry.js.map +1 -1
  112. package/dist/services/validation.cjs +31 -8
  113. package/dist/services/validation.cjs.map +1 -1
  114. package/dist/services/validation.d.ts.map +1 -1
  115. package/dist/services/validation.js +31 -8
  116. package/dist/services/validation.js.map +1 -1
  117. package/dist/types/index.d.ts +14 -2
  118. package/dist/types/index.d.ts.map +1 -1
  119. package/dist/utils/degraded-projections.cjs +19 -3
  120. package/dist/utils/degraded-projections.cjs.map +1 -1
  121. package/dist/utils/degraded-projections.d.ts +22 -2
  122. package/dist/utils/degraded-projections.d.ts.map +1 -1
  123. package/dist/utils/degraded-projections.js +19 -3
  124. package/dist/utils/degraded-projections.js.map +1 -1
  125. package/dist/utils/math-markdown.cjs +1 -1
  126. package/dist/utils/math-markdown.cjs.map +1 -1
  127. package/dist/utils/math-markdown.js +1 -1
  128. package/dist/utils/math-markdown.js.map +1 -1
  129. package/dist/utils/missing-value.cjs +60 -0
  130. package/dist/utils/missing-value.cjs.map +1 -0
  131. package/dist/utils/missing-value.d.ts +79 -0
  132. package/dist/utils/missing-value.d.ts.map +1 -0
  133. package/dist/utils/missing-value.js +60 -0
  134. package/dist/utils/missing-value.js.map +1 -0
  135. package/dist/utils/theme.cjs +91 -0
  136. package/dist/utils/theme.cjs.map +1 -0
  137. package/dist/utils/theme.d.ts +11 -0
  138. package/dist/utils/theme.d.ts.map +1 -0
  139. package/dist/utils/theme.js +91 -0
  140. package/dist/utils/theme.js.map +1 -0
  141. package/docs/SECURITY-DEPENDENCIES.md +81 -0
  142. package/docs/THEMING.md +205 -0
  143. package/package.json +7 -5
  144. package/src/components/ActionGroupRenderer.tsx +6 -6
  145. package/src/components/AutocompleteDropdown.tsx +17 -17
  146. package/src/components/AutocompleteFormField.tsx +10 -9
  147. package/src/components/ChartJSRenderer.tsx +609 -212
  148. package/src/components/ChatPrompt.tsx +16 -16
  149. package/src/components/ComponentToolbar.tsx +5 -5
  150. package/src/components/DegradedFallback.tsx +33 -11
  151. package/src/components/ExpandableWrapper.tsx +15 -11
  152. package/src/components/FormFieldRenderer.tsx +52 -51
  153. package/src/components/FormRenderer.tsx +12 -12
  154. package/src/components/GenerativeUIErrorBoundary.tsx +6 -6
  155. package/src/components/GhostText.tsx +7 -7
  156. package/src/components/GraphRenderer.tsx +83 -67
  157. package/src/components/MissingValue.tsx +61 -0
  158. package/src/components/ModalRenderer.tsx +11 -5
  159. package/src/components/PortalDropdownMenu.tsx +6 -2
  160. package/src/components/ScratchpadPanel.tsx +144 -141
  161. package/src/components/UIResourceRenderer.tsx +143 -110
  162. package/src/components/chart-data-table.ts +50 -6
  163. package/src/components/chart-missing-plugin.ts +336 -0
  164. package/src/context/MCPUIStringsContext.tsx +76 -0
  165. package/src/services/component-registry.ts +10 -2
  166. package/src/services/validation.ts +44 -9
  167. package/src/styles/autocomplete.css +53 -53
  168. package/src/types/index.ts +13 -1
  169. package/src/utils/degraded-projections.ts +44 -4
  170. package/src/utils/math-markdown.ts +1 -1
  171. package/src/utils/missing-value.ts +127 -0
  172. package/src/utils/theme.ts +101 -0
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const formatString = require("../utils/format-string.cjs");
4
+ const missingValue = require("../utils/missing-value.cjs");
4
5
  const CHART_DATA_TABLE_LABELS = {
5
6
  series: "Series",
6
7
  point: "Point",
@@ -8,7 +9,8 @@ const CHART_DATA_TABLE_LABELS = {
8
9
  seriesName: "Series {n}",
9
10
  x: "x",
10
11
  y: "y",
11
- r: "r"
12
+ r: "r",
13
+ withUnit: "{label} ({unit})"
12
14
  };
13
15
  function tableCell(value) {
14
16
  if (value == null) return "";
@@ -26,6 +28,9 @@ function isPoint(value) {
26
28
  function chartToDataTable(params, labels) {
27
29
  var _a, _b;
28
30
  const l = { ...CHART_DATA_TABLE_LABELS, ...labels };
31
+ const unit = typeof params.unit === "string" && params.unit !== "" ? params.unit : void 0;
32
+ const unitTemplate = l.withUnit ?? CHART_DATA_TABLE_LABELS.withUnit;
33
+ const withUnit = (label) => unit === void 0 ? label : formatString.formatMCPUIString(unitTemplate, { label, unit });
29
34
  const datasets = ((_a = params.data) == null ? void 0 : _a.datasets) ?? [];
30
35
  const dataLabels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
31
36
  const pointData = params.type === "scatter" || params.type === "bubble" || datasets.some((dataset) => {
@@ -43,10 +48,11 @@ function chartToDataTable(params, labels) {
43
48
  l.point,
44
49
  ...hasLabels ? [l.label] : [],
45
50
  l.x,
46
- l.y,
51
+ withUnit(l.y),
47
52
  ...hasRadius ? [l.r] : []
48
53
  ];
49
54
  const rows2 = [];
55
+ const missing2 = [];
50
56
  datasets.forEach((dataset, datasetIndex) => {
51
57
  const series = dataset.label || formatString.formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });
52
58
  (dataset.data ?? []).forEach((value, pointIndex) => {
@@ -59,9 +65,18 @@ function chartToDataTable(params, labels) {
59
65
  tableCell(point.y),
60
66
  ...hasRadius ? [tableCell(point.r)] : []
61
67
  ]);
68
+ const yMissing = missingValue.isMissingChartValue(isPoint(value) ? point.y : value);
69
+ missing2.push([
70
+ false,
71
+ false,
72
+ ...hasLabels ? [false] : [],
73
+ false,
74
+ yMissing,
75
+ ...hasRadius ? [false] : []
76
+ ]);
62
77
  });
63
78
  });
64
- return { columns: columns2, rows: rows2 };
79
+ return { columns: columns2, rows: rows2, missing: missing2 };
65
80
  }
66
81
  const rowCount = Math.max(
67
82
  dataLabels.length,
@@ -74,10 +89,11 @@ function chartToDataTable(params, labels) {
74
89
  const columns = [
75
90
  l.label,
76
91
  ...datasets.map(
77
- (dataset, index) => dataset.label || formatString.formatMCPUIString(l.seriesName, { n: index + 1 })
92
+ (dataset, index) => withUnit(dataset.label || formatString.formatMCPUIString(l.seriesName, { n: index + 1 }))
78
93
  )
79
94
  ];
80
95
  const rows = [];
96
+ const missing = [];
81
97
  for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
82
98
  rows.push([
83
99
  tableCell(dataLabels[rowIndex] ?? rowIndex + 1),
@@ -86,8 +102,17 @@ function chartToDataTable(params, labels) {
86
102
  return tableCell((_a2 = dataset.data) == null ? void 0 : _a2[rowIndex]);
87
103
  })
88
104
  ]);
105
+ missing.push([
106
+ false,
107
+ ...datasets.map(
108
+ (dataset) => {
109
+ var _a2, _b2;
110
+ return rowIndex < (((_a2 = dataset.data) == null ? void 0 : _a2.length) ?? 0) && missingValue.isMissingChartValue((_b2 = dataset.data) == null ? void 0 : _b2[rowIndex]);
111
+ }
112
+ )
113
+ ]);
89
114
  }
90
- return { columns, rows };
115
+ return { columns, rows, missing };
91
116
  }
92
117
  exports.CHART_DATA_TABLE_LABELS = CHART_DATA_TABLE_LABELS;
93
118
  exports.chartToDataTable = chartToDataTable;
@@ -1 +1 @@
1
- {"version":3,"file":"chart-data-table.cjs","sources":["../../src/components/chart-data-table.ts"],"sourcesContent":["import { formatMCPUIString } from '../utils/format-string';\n\n/**\n * Column headers and series names of the accessible chart data table.\n *\n * `chartToDataTable` is a pure helper with no access to `MCPUIStrings`, so\n * the wording is injected: it takes an optional trailing `labels` partial,\n * which `ChartJSRenderer` feeds from `useMCPUIStrings()`. Left out, the\n * English defaults below apply — the pre-v6.20.0 behaviour.\n *\n * `x` / `y` / `r` stay untranslated on purpose: they are the Chart.js point\n * property NAMES the cells mirror, not prose.\n *\n * @since v6.20.0\n */\nexport interface ChartDataTableLabels {\n /** Series column of the per-point table. */\n series: string;\n /** Point-index column of the per-point table. */\n point: string;\n /** Label column (categorical table, and per-point table when labelled). */\n label: string;\n /** Fallback dataset name. Template — `{n}`. */\n seriesName: string;\n /** Chart.js point property names — machine tokens, rarely overridden. */\n x: string;\n y: string;\n r: string;\n}\n\n/** English defaults for {@link ChartDataTableLabels}. */\nexport const CHART_DATA_TABLE_LABELS: ChartDataTableLabels = {\n series: 'Series',\n point: 'Point',\n label: 'Label',\n seriesName: 'Series {n}',\n x: 'x',\n y: 'y',\n r: 'r',\n};\n\nexport interface ChartDataTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\ninterface ChartDatasetLike {\n label?: string;\n data?: unknown[];\n}\n\nexport interface ChartDataLike {\n type?: string;\n data?: {\n labels?: Array<string | number>;\n datasets?: ChartDatasetLike[];\n };\n}\n\nfunction tableCell(value: unknown): string | number {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPoint(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n ('x' in value || 'y' in value || 'r' in value)\n );\n}\n\n/**\n * Project Chart.js data into an accessible table without flattening point\n * coordinates. Categorical charts use a compact wide table; scatter, bubble,\n * and object-valued line charts use one row per point so x/y/r remain distinct.\n */\nexport function chartToDataTable(\n params: ChartDataLike,\n labels?: Partial<ChartDataTableLabels>\n): ChartDataTable {\n const l: ChartDataTableLabels = { ...CHART_DATA_TABLE_LABELS, ...labels };\n const datasets = params.data?.datasets ?? [];\n const dataLabels = params.data?.labels ?? [];\n const pointData =\n params.type === 'scatter' ||\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some(isPoint));\n\n if (pointData) {\n const hasLabels = dataLabels.length > 0;\n const hasRadius =\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));\n const columns = [\n l.series,\n l.point,\n ...(hasLabels ? [l.label] : []),\n l.x,\n l.y,\n ...(hasRadius ? [l.r] : []),\n ];\n const rows: Array<Array<string | number>> = [];\n\n datasets.forEach((dataset, datasetIndex) => {\n const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });\n (dataset.data ?? []).forEach((value, pointIndex) => {\n const point = isPoint(value) ? value : { y: value };\n rows.push([\n series,\n pointIndex + 1,\n ...(hasLabels ? [tableCell(dataLabels[pointIndex])] : []),\n tableCell(point.x),\n tableCell(point.y),\n ...(hasRadius ? [tableCell(point.r)] : []),\n ]);\n });\n });\n\n return { columns, rows };\n }\n\n const rowCount = Math.max(\n dataLabels.length,\n ...datasets.map((dataset) => dataset.data?.length ?? 0),\n 0\n );\n const columns = [\n l.label,\n ...datasets.map(\n (dataset, index) => dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 })\n ),\n ];\n const rows: Array<Array<string | number>> = [];\n\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n rows.push([\n tableCell(dataLabels[rowIndex] ?? rowIndex + 1),\n ...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),\n ]);\n }\n\n return { columns, rows };\n}\n"],"names":["_a","columns","rows","formatMCPUIString"],"mappings":"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"}
1
+ {"version":3,"file":"chart-data-table.cjs","sources":["../../src/components/chart-data-table.ts"],"sourcesContent":["import { formatMCPUIString } from '../utils/format-string';\nimport { isMissingChartValue } from '../utils/missing-value';\n\n/**\n * Column headers and series names of the accessible chart data table.\n *\n * `chartToDataTable` is a pure helper with no access to `MCPUIStrings`, so\n * the wording is injected: it takes an optional trailing `labels` partial,\n * which `ChartJSRenderer` feeds from `useMCPUIStrings()`. Left out, the\n * English defaults below apply — the pre-v6.20.0 behaviour.\n *\n * `x` / `y` / `r` stay untranslated on purpose: they are the Chart.js point\n * property NAMES the cells mirror, not prose.\n *\n * @since v6.20.0\n */\nexport interface ChartDataTableLabels {\n /** Series column of the per-point table. */\n series: string;\n /** Point-index column of the per-point table. */\n point: string;\n /** Label column (categorical table, and per-point table when labelled). */\n label: string;\n /** Fallback dataset name. Template — `{n}`. */\n seriesName: string;\n /** Chart.js point property names — machine tokens, rarely overridden. */\n x: string;\n y: string;\n r: string;\n /**\n * A value column header followed by the chart's `unit`. Template — `{label}`,\n * `{unit}`. Only applied when the chart has a unit. Optional so that a\n * complete labels table written for 6.20.0–6.23.0 still type-checks.\n * @since v6.24.0\n */\n withUnit?: string;\n}\n\n/** English defaults for {@link ChartDataTableLabels}. */\nexport const CHART_DATA_TABLE_LABELS: Required<ChartDataTableLabels> = {\n series: 'Series',\n point: 'Point',\n label: 'Label',\n seriesName: 'Series {n}',\n x: 'x',\n y: 'y',\n r: 'r',\n withUnit: '{label} ({unit})',\n};\n\nexport interface ChartDataTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n /**\n * Same shape as `rows`: `true` for a VALUE cell whose source entry is\n * missing (`null` / non-finite, or a point whose `y` is). A slot past the\n * end of a shorter or empty dataset has no entry and is not flagged. Label,\n * series, point-index, `x` and `r` cells are never missing. `rows` itself\n * still holds `''` there. @since v6.24.0\n */\n missing: boolean[][];\n}\n\ninterface ChartDatasetLike {\n label?: string;\n data?: unknown[];\n}\n\nexport interface ChartDataLike {\n type?: string;\n /** Unit of the values: appended to the value column headers. @since v6.24.0 */\n unit?: string;\n data?: {\n labels?: Array<string | number>;\n datasets?: ChartDatasetLike[];\n };\n}\n\nfunction tableCell(value: unknown): string | number {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPoint(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n ('x' in value || 'y' in value || 'r' in value)\n );\n}\n\n/**\n * Project Chart.js data into an accessible table without flattening point\n * coordinates. Categorical charts use a compact wide table; scatter, bubble,\n * and object-valued line charts use one row per point so x/y/r remain distinct.\n */\nexport function chartToDataTable(\n params: ChartDataLike,\n labels?: Partial<ChartDataTableLabels>\n): ChartDataTable {\n const l: ChartDataTableLabels = { ...CHART_DATA_TABLE_LABELS, ...labels };\n const unit = typeof params.unit === 'string' && params.unit !== '' ? params.unit : undefined;\n const unitTemplate = l.withUnit ?? CHART_DATA_TABLE_LABELS.withUnit;\n const withUnit = (label: string) =>\n unit === undefined ? label : formatMCPUIString(unitTemplate, { label, unit });\n const datasets = params.data?.datasets ?? [];\n const dataLabels = params.data?.labels ?? [];\n const pointData =\n params.type === 'scatter' ||\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some(isPoint));\n\n if (pointData) {\n const hasLabels = dataLabels.length > 0;\n const hasRadius =\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));\n const columns = [\n l.series,\n l.point,\n ...(hasLabels ? [l.label] : []),\n l.x,\n withUnit(l.y),\n ...(hasRadius ? [l.r] : []),\n ];\n const rows: Array<Array<string | number>> = [];\n const missing: boolean[][] = [];\n\n datasets.forEach((dataset, datasetIndex) => {\n const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });\n (dataset.data ?? []).forEach((value, pointIndex) => {\n const point = isPoint(value) ? value : { y: value };\n rows.push([\n series,\n pointIndex + 1,\n ...(hasLabels ? [tableCell(dataLabels[pointIndex])] : []),\n tableCell(point.x),\n tableCell(point.y),\n ...(hasRadius ? [tableCell(point.r)] : []),\n ]);\n // Only the y cell can be missing; a bare entry is its own y.\n const yMissing = isMissingChartValue(isPoint(value) ? point.y : value);\n missing.push([\n false,\n false,\n ...(hasLabels ? [false] : []),\n false,\n yMissing,\n ...(hasRadius ? [false] : []),\n ]);\n });\n });\n\n return { columns, rows, missing };\n }\n\n const rowCount = Math.max(\n dataLabels.length,\n ...datasets.map((dataset) => dataset.data?.length ?? 0),\n 0\n );\n const columns = [\n l.label,\n ...datasets.map((dataset, index) =>\n withUnit(dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 }))\n ),\n ];\n const rows: Array<Array<string | number>> = [];\n const missing: boolean[][] = [];\n\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n rows.push([\n tableCell(dataLabels[rowIndex] ?? rowIndex + 1),\n ...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),\n ]);\n // Only an ENTRY can be missing: a slot past the end of a shorter (or\n // empty) dataset has no entry, and renders as before (an empty cell).\n missing.push([\n false,\n ...datasets.map(\n (dataset) =>\n rowIndex < (dataset.data?.length ?? 0) && isMissingChartValue(dataset.data?.[rowIndex])\n ),\n ]);\n }\n\n return { columns, rows, missing };\n}\n"],"names":["formatMCPUIString","_a","columns","rows","missing","isMissingChartValue","_b"],"mappings":"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"}
@@ -24,12 +24,27 @@ export interface ChartDataTableLabels {
24
24
  x: string;
25
25
  y: string;
26
26
  r: string;
27
+ /**
28
+ * A value column header followed by the chart's `unit`. Template — `{label}`,
29
+ * `{unit}`. Only applied when the chart has a unit. Optional so that a
30
+ * complete labels table written for 6.20.0–6.23.0 still type-checks.
31
+ * @since v6.24.0
32
+ */
33
+ withUnit?: string;
27
34
  }
28
35
  /** English defaults for {@link ChartDataTableLabels}. */
29
- export declare const CHART_DATA_TABLE_LABELS: ChartDataTableLabels;
36
+ export declare const CHART_DATA_TABLE_LABELS: Required<ChartDataTableLabels>;
30
37
  export interface ChartDataTable {
31
38
  columns: string[];
32
39
  rows: Array<Array<string | number>>;
40
+ /**
41
+ * Same shape as `rows`: `true` for a VALUE cell whose source entry is
42
+ * missing (`null` / non-finite, or a point whose `y` is). A slot past the
43
+ * end of a shorter or empty dataset has no entry and is not flagged. Label,
44
+ * series, point-index, `x` and `r` cells are never missing. `rows` itself
45
+ * still holds `''` there. @since v6.24.0
46
+ */
47
+ missing: boolean[][];
33
48
  }
34
49
  interface ChartDatasetLike {
35
50
  label?: string;
@@ -37,6 +52,8 @@ interface ChartDatasetLike {
37
52
  }
38
53
  export interface ChartDataLike {
39
54
  type?: string;
55
+ /** Unit of the values: appended to the value column headers. @since v6.24.0 */
56
+ unit?: string;
40
57
  data?: {
41
58
  labels?: Array<string | number>;
42
59
  datasets?: ChartDatasetLike[];
@@ -1 +1 @@
1
- {"version":3,"file":"chart-data-table.d.ts","sourceRoot":"","sources":["../../src/components/chart-data-table.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,yDAAyD;AACzD,eAAO,MAAM,uBAAuB,EAAE,oBAQrC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;CACrC;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;KAC/B,CAAC;CACH;AAsBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EACrB,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACrC,cAAc,CA+DhB"}
1
+ {"version":3,"file":"chart-data-table.d.ts","sourceRoot":"","sources":["../../src/components/chart-data-table.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,yDAAyD;AACzD,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,oBAAoB,CASlE,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IACpC;;;;;;OAMG;IACH,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;CACtB;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;KAC/B,CAAC;CACH;AAsBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EACrB,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACrC,cAAc,CAwFhB"}
@@ -1,4 +1,5 @@
1
1
  import { formatMCPUIString } from "../utils/format-string.js";
2
+ import { isMissingChartValue } from "../utils/missing-value.js";
2
3
  const CHART_DATA_TABLE_LABELS = {
3
4
  series: "Series",
4
5
  point: "Point",
@@ -6,7 +7,8 @@ const CHART_DATA_TABLE_LABELS = {
6
7
  seriesName: "Series {n}",
7
8
  x: "x",
8
9
  y: "y",
9
- r: "r"
10
+ r: "r",
11
+ withUnit: "{label} ({unit})"
10
12
  };
11
13
  function tableCell(value) {
12
14
  if (value == null) return "";
@@ -24,6 +26,9 @@ function isPoint(value) {
24
26
  function chartToDataTable(params, labels) {
25
27
  var _a, _b;
26
28
  const l = { ...CHART_DATA_TABLE_LABELS, ...labels };
29
+ const unit = typeof params.unit === "string" && params.unit !== "" ? params.unit : void 0;
30
+ const unitTemplate = l.withUnit ?? CHART_DATA_TABLE_LABELS.withUnit;
31
+ const withUnit = (label) => unit === void 0 ? label : formatMCPUIString(unitTemplate, { label, unit });
27
32
  const datasets = ((_a = params.data) == null ? void 0 : _a.datasets) ?? [];
28
33
  const dataLabels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
29
34
  const pointData = params.type === "scatter" || params.type === "bubble" || datasets.some((dataset) => {
@@ -41,10 +46,11 @@ function chartToDataTable(params, labels) {
41
46
  l.point,
42
47
  ...hasLabels ? [l.label] : [],
43
48
  l.x,
44
- l.y,
49
+ withUnit(l.y),
45
50
  ...hasRadius ? [l.r] : []
46
51
  ];
47
52
  const rows2 = [];
53
+ const missing2 = [];
48
54
  datasets.forEach((dataset, datasetIndex) => {
49
55
  const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });
50
56
  (dataset.data ?? []).forEach((value, pointIndex) => {
@@ -57,9 +63,18 @@ function chartToDataTable(params, labels) {
57
63
  tableCell(point.y),
58
64
  ...hasRadius ? [tableCell(point.r)] : []
59
65
  ]);
66
+ const yMissing = isMissingChartValue(isPoint(value) ? point.y : value);
67
+ missing2.push([
68
+ false,
69
+ false,
70
+ ...hasLabels ? [false] : [],
71
+ false,
72
+ yMissing,
73
+ ...hasRadius ? [false] : []
74
+ ]);
60
75
  });
61
76
  });
62
- return { columns: columns2, rows: rows2 };
77
+ return { columns: columns2, rows: rows2, missing: missing2 };
63
78
  }
64
79
  const rowCount = Math.max(
65
80
  dataLabels.length,
@@ -72,10 +87,11 @@ function chartToDataTable(params, labels) {
72
87
  const columns = [
73
88
  l.label,
74
89
  ...datasets.map(
75
- (dataset, index) => dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 })
90
+ (dataset, index) => withUnit(dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 }))
76
91
  )
77
92
  ];
78
93
  const rows = [];
94
+ const missing = [];
79
95
  for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
80
96
  rows.push([
81
97
  tableCell(dataLabels[rowIndex] ?? rowIndex + 1),
@@ -84,8 +100,17 @@ function chartToDataTable(params, labels) {
84
100
  return tableCell((_a2 = dataset.data) == null ? void 0 : _a2[rowIndex]);
85
101
  })
86
102
  ]);
103
+ missing.push([
104
+ false,
105
+ ...datasets.map(
106
+ (dataset) => {
107
+ var _a2, _b2;
108
+ return rowIndex < (((_a2 = dataset.data) == null ? void 0 : _a2.length) ?? 0) && isMissingChartValue((_b2 = dataset.data) == null ? void 0 : _b2[rowIndex]);
109
+ }
110
+ )
111
+ ]);
87
112
  }
88
- return { columns, rows };
113
+ return { columns, rows, missing };
89
114
  }
90
115
  export {
91
116
  CHART_DATA_TABLE_LABELS,
@@ -1 +1 @@
1
- {"version":3,"file":"chart-data-table.js","sources":["../../src/components/chart-data-table.ts"],"sourcesContent":["import { formatMCPUIString } from '../utils/format-string';\n\n/**\n * Column headers and series names of the accessible chart data table.\n *\n * `chartToDataTable` is a pure helper with no access to `MCPUIStrings`, so\n * the wording is injected: it takes an optional trailing `labels` partial,\n * which `ChartJSRenderer` feeds from `useMCPUIStrings()`. Left out, the\n * English defaults below apply — the pre-v6.20.0 behaviour.\n *\n * `x` / `y` / `r` stay untranslated on purpose: they are the Chart.js point\n * property NAMES the cells mirror, not prose.\n *\n * @since v6.20.0\n */\nexport interface ChartDataTableLabels {\n /** Series column of the per-point table. */\n series: string;\n /** Point-index column of the per-point table. */\n point: string;\n /** Label column (categorical table, and per-point table when labelled). */\n label: string;\n /** Fallback dataset name. Template — `{n}`. */\n seriesName: string;\n /** Chart.js point property names — machine tokens, rarely overridden. */\n x: string;\n y: string;\n r: string;\n}\n\n/** English defaults for {@link ChartDataTableLabels}. */\nexport const CHART_DATA_TABLE_LABELS: ChartDataTableLabels = {\n series: 'Series',\n point: 'Point',\n label: 'Label',\n seriesName: 'Series {n}',\n x: 'x',\n y: 'y',\n r: 'r',\n};\n\nexport interface ChartDataTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\ninterface ChartDatasetLike {\n label?: string;\n data?: unknown[];\n}\n\nexport interface ChartDataLike {\n type?: string;\n data?: {\n labels?: Array<string | number>;\n datasets?: ChartDatasetLike[];\n };\n}\n\nfunction tableCell(value: unknown): string | number {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPoint(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n ('x' in value || 'y' in value || 'r' in value)\n );\n}\n\n/**\n * Project Chart.js data into an accessible table without flattening point\n * coordinates. Categorical charts use a compact wide table; scatter, bubble,\n * and object-valued line charts use one row per point so x/y/r remain distinct.\n */\nexport function chartToDataTable(\n params: ChartDataLike,\n labels?: Partial<ChartDataTableLabels>\n): ChartDataTable {\n const l: ChartDataTableLabels = { ...CHART_DATA_TABLE_LABELS, ...labels };\n const datasets = params.data?.datasets ?? [];\n const dataLabels = params.data?.labels ?? [];\n const pointData =\n params.type === 'scatter' ||\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some(isPoint));\n\n if (pointData) {\n const hasLabels = dataLabels.length > 0;\n const hasRadius =\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));\n const columns = [\n l.series,\n l.point,\n ...(hasLabels ? [l.label] : []),\n l.x,\n l.y,\n ...(hasRadius ? [l.r] : []),\n ];\n const rows: Array<Array<string | number>> = [];\n\n datasets.forEach((dataset, datasetIndex) => {\n const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });\n (dataset.data ?? []).forEach((value, pointIndex) => {\n const point = isPoint(value) ? value : { y: value };\n rows.push([\n series,\n pointIndex + 1,\n ...(hasLabels ? [tableCell(dataLabels[pointIndex])] : []),\n tableCell(point.x),\n tableCell(point.y),\n ...(hasRadius ? [tableCell(point.r)] : []),\n ]);\n });\n });\n\n return { columns, rows };\n }\n\n const rowCount = Math.max(\n dataLabels.length,\n ...datasets.map((dataset) => dataset.data?.length ?? 0),\n 0\n );\n const columns = [\n l.label,\n ...datasets.map(\n (dataset, index) => dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 })\n ),\n ];\n const rows: Array<Array<string | number>> = [];\n\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n rows.push([\n tableCell(dataLabels[rowIndex] ?? rowIndex + 1),\n ...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),\n ]);\n }\n\n return { columns, rows };\n}\n"],"names":["_a","columns","rows"],"mappings":"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"}
1
+ {"version":3,"file":"chart-data-table.js","sources":["../../src/components/chart-data-table.ts"],"sourcesContent":["import { formatMCPUIString } from '../utils/format-string';\nimport { isMissingChartValue } from '../utils/missing-value';\n\n/**\n * Column headers and series names of the accessible chart data table.\n *\n * `chartToDataTable` is a pure helper with no access to `MCPUIStrings`, so\n * the wording is injected: it takes an optional trailing `labels` partial,\n * which `ChartJSRenderer` feeds from `useMCPUIStrings()`. Left out, the\n * English defaults below apply — the pre-v6.20.0 behaviour.\n *\n * `x` / `y` / `r` stay untranslated on purpose: they are the Chart.js point\n * property NAMES the cells mirror, not prose.\n *\n * @since v6.20.0\n */\nexport interface ChartDataTableLabels {\n /** Series column of the per-point table. */\n series: string;\n /** Point-index column of the per-point table. */\n point: string;\n /** Label column (categorical table, and per-point table when labelled). */\n label: string;\n /** Fallback dataset name. Template — `{n}`. */\n seriesName: string;\n /** Chart.js point property names — machine tokens, rarely overridden. */\n x: string;\n y: string;\n r: string;\n /**\n * A value column header followed by the chart's `unit`. Template — `{label}`,\n * `{unit}`. Only applied when the chart has a unit. Optional so that a\n * complete labels table written for 6.20.0–6.23.0 still type-checks.\n * @since v6.24.0\n */\n withUnit?: string;\n}\n\n/** English defaults for {@link ChartDataTableLabels}. */\nexport const CHART_DATA_TABLE_LABELS: Required<ChartDataTableLabels> = {\n series: 'Series',\n point: 'Point',\n label: 'Label',\n seriesName: 'Series {n}',\n x: 'x',\n y: 'y',\n r: 'r',\n withUnit: '{label} ({unit})',\n};\n\nexport interface ChartDataTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n /**\n * Same shape as `rows`: `true` for a VALUE cell whose source entry is\n * missing (`null` / non-finite, or a point whose `y` is). A slot past the\n * end of a shorter or empty dataset has no entry and is not flagged. Label,\n * series, point-index, `x` and `r` cells are never missing. `rows` itself\n * still holds `''` there. @since v6.24.0\n */\n missing: boolean[][];\n}\n\ninterface ChartDatasetLike {\n label?: string;\n data?: unknown[];\n}\n\nexport interface ChartDataLike {\n type?: string;\n /** Unit of the values: appended to the value column headers. @since v6.24.0 */\n unit?: string;\n data?: {\n labels?: Array<string | number>;\n datasets?: ChartDatasetLike[];\n };\n}\n\nfunction tableCell(value: unknown): string | number {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPoint(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n ('x' in value || 'y' in value || 'r' in value)\n );\n}\n\n/**\n * Project Chart.js data into an accessible table without flattening point\n * coordinates. Categorical charts use a compact wide table; scatter, bubble,\n * and object-valued line charts use one row per point so x/y/r remain distinct.\n */\nexport function chartToDataTable(\n params: ChartDataLike,\n labels?: Partial<ChartDataTableLabels>\n): ChartDataTable {\n const l: ChartDataTableLabels = { ...CHART_DATA_TABLE_LABELS, ...labels };\n const unit = typeof params.unit === 'string' && params.unit !== '' ? params.unit : undefined;\n const unitTemplate = l.withUnit ?? CHART_DATA_TABLE_LABELS.withUnit;\n const withUnit = (label: string) =>\n unit === undefined ? label : formatMCPUIString(unitTemplate, { label, unit });\n const datasets = params.data?.datasets ?? [];\n const dataLabels = params.data?.labels ?? [];\n const pointData =\n params.type === 'scatter' ||\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some(isPoint));\n\n if (pointData) {\n const hasLabels = dataLabels.length > 0;\n const hasRadius =\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));\n const columns = [\n l.series,\n l.point,\n ...(hasLabels ? [l.label] : []),\n l.x,\n withUnit(l.y),\n ...(hasRadius ? [l.r] : []),\n ];\n const rows: Array<Array<string | number>> = [];\n const missing: boolean[][] = [];\n\n datasets.forEach((dataset, datasetIndex) => {\n const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });\n (dataset.data ?? []).forEach((value, pointIndex) => {\n const point = isPoint(value) ? value : { y: value };\n rows.push([\n series,\n pointIndex + 1,\n ...(hasLabels ? [tableCell(dataLabels[pointIndex])] : []),\n tableCell(point.x),\n tableCell(point.y),\n ...(hasRadius ? [tableCell(point.r)] : []),\n ]);\n // Only the y cell can be missing; a bare entry is its own y.\n const yMissing = isMissingChartValue(isPoint(value) ? point.y : value);\n missing.push([\n false,\n false,\n ...(hasLabels ? [false] : []),\n false,\n yMissing,\n ...(hasRadius ? [false] : []),\n ]);\n });\n });\n\n return { columns, rows, missing };\n }\n\n const rowCount = Math.max(\n dataLabels.length,\n ...datasets.map((dataset) => dataset.data?.length ?? 0),\n 0\n );\n const columns = [\n l.label,\n ...datasets.map((dataset, index) =>\n withUnit(dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 }))\n ),\n ];\n const rows: Array<Array<string | number>> = [];\n const missing: boolean[][] = [];\n\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n rows.push([\n tableCell(dataLabels[rowIndex] ?? rowIndex + 1),\n ...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),\n ]);\n // Only an ENTRY can be missing: a slot past the end of a shorter (or\n // empty) dataset has no entry, and renders as before (an empty cell).\n missing.push([\n false,\n ...datasets.map(\n (dataset) =>\n rowIndex < (dataset.data?.length ?? 0) && isMissingChartValue(dataset.data?.[rowIndex])\n ),\n ]);\n }\n\n return { columns, rows, missing };\n}\n"],"names":["_a","columns","rows","missing","_b"],"mappings":"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"}
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const formatString = require("../utils/format-string.cjs");
4
+ const missingValue = require("../utils/missing-value.cjs");
5
+ const MISSING_BAR_STUB_LENGTH = 12;
6
+ const MISSING_BAR_FALLBACK_COLOR = "#9ca3af";
7
+ const NO_DATA_TEXT_COLOR = "#6b7280";
8
+ const STUB_DASH = [4, 3];
9
+ const POINT_CHART_TYPES = /* @__PURE__ */ new Set(["scatter", "bubble"]);
10
+ function isStackedChart(options) {
11
+ var _a, _b, _c, _d;
12
+ return Boolean(((_b = (_a = options == null ? void 0 : options.scales) == null ? void 0 : _a.x) == null ? void 0 : _b.stacked) || ((_d = (_c = options == null ? void 0 : options.scales) == null ? void 0 : _c.y) == null ? void 0 : _d.stacked));
13
+ }
14
+ function missingNoteKind(chartType, options) {
15
+ if (chartType === "bar") return isStackedChart(options) ? "omitted" : "bars";
16
+ if (chartType === "scatter" || chartType === "bubble") return "omitted";
17
+ return "gaps";
18
+ }
19
+ function withDatasetsNoGapSpan(data) {
20
+ const datasets = Array.isArray(data == null ? void 0 : data.datasets) ? data.datasets : null;
21
+ if (!datasets) return data;
22
+ return {
23
+ ...data,
24
+ datasets: datasets.map(
25
+ (dataset) => dataset !== null && typeof dataset === "object" ? { ...dataset, spanGaps: false } : dataset
26
+ )
27
+ };
28
+ }
29
+ function createMissingLegendGenerator(base, fullyMissing, getStrings) {
30
+ return function generateLabels(chart) {
31
+ const items = base.call(this, chart);
32
+ if (!Array.isArray(items)) return items;
33
+ return items.map((item) => {
34
+ const index = item == null ? void 0 : item.datasetIndex;
35
+ if (typeof index !== "number" || !fullyMissing[index]) return item;
36
+ const text = typeof item.text === "string" ? item.text : String(item.text ?? "");
37
+ return {
38
+ ...item,
39
+ text: formatString.formatMCPUIString(getStrings().chartLegendNoData, { series: text })
40
+ };
41
+ });
42
+ };
43
+ }
44
+ function isMissingTooltipItem(item) {
45
+ var _a, _b, _c, _d;
46
+ if (item === null || item === void 0) return false;
47
+ if (item.raw === null || item.raw === void 0 || missingValue.isMissingChartValue(item.raw)) return true;
48
+ const parsed = item.parsed;
49
+ if (parsed !== null && typeof parsed === "object") {
50
+ const chartType = (_b = (_a = item.chart) == null ? void 0 : _a.config) == null ? void 0 : _b.type;
51
+ const valueKey = chartType === "radar" ? "r" : ((_d = (_c = item.chart) == null ? void 0 : _c.options) == null ? void 0 : _d.indexAxis) === "y" ? "x" : "y";
52
+ if (valueKey in parsed && parsed[valueKey] === null) return true;
53
+ }
54
+ return false;
55
+ }
56
+ function createTooltipLabel(getStrings, unit, chartType) {
57
+ const applyUnit = unit !== void 0 && !POINT_CHART_TYPES.has(chartType ?? "");
58
+ return function label(item) {
59
+ var _a, _b;
60
+ const strings = getStrings();
61
+ const prefixLabel = ((_a = this == null ? void 0 : this.options) == null ? void 0 : _a.mode) === "dataset" ? item == null ? void 0 : item.label : (_b = item == null ? void 0 : item.dataset) == null ? void 0 : _b.label;
62
+ const prefix = typeof prefixLabel === "string" && prefixLabel !== "" ? `${prefixLabel}: ` : "";
63
+ if (isMissingTooltipItem(item)) return `${prefix}${strings.missingValue}`;
64
+ const formatted = item == null ? void 0 : item.formattedValue;
65
+ if (formatted === null || formatted === void 0) return prefix;
66
+ const value = applyUnit ? formatString.formatMCPUIString(strings.chartValueWithUnit, { value: formatted, unit }) : String(formatted);
67
+ return `${prefix}${value}`;
68
+ };
69
+ }
70
+ function applyUnitAxisTitle(options, chartType, unit) {
71
+ var _a, _b, _c;
72
+ if (unit === void 0) return;
73
+ if (chartType !== "bar" && chartType !== "line" && !POINT_CHART_TYPES.has(chartType ?? "")) {
74
+ return;
75
+ }
76
+ const horizontal = (chartType === "bar" || chartType === "line") && (options == null ? void 0 : options.indexAxis) === "y";
77
+ const axis = horizontal ? "x" : "y";
78
+ if (((_b = (_a = options.scales) == null ? void 0 : _a[axis]) == null ? void 0 : _b.title) !== void 0) return;
79
+ options.scales = {
80
+ ...options.scales,
81
+ [axis]: { ...(_c = options.scales) == null ? void 0 : _c[axis], title: { display: true, text: unit } }
82
+ };
83
+ }
84
+ function colorAt(color, index) {
85
+ if (typeof color === "string" && color !== "") return color;
86
+ if (Array.isArray(color) && color.length > 0) {
87
+ const picked = color[index % color.length];
88
+ return typeof picked === "string" && picked !== "" ? picked : void 0;
89
+ }
90
+ return void 0;
91
+ }
92
+ function drawMissingBarStubs(chart) {
93
+ var _a, _b;
94
+ const ctx = chart == null ? void 0 : chart.ctx;
95
+ const area = chart == null ? void 0 : chart.chartArea;
96
+ const datasets = (_a = chart == null ? void 0 : chart.data) == null ? void 0 : _a.datasets;
97
+ if (!ctx || !area || !Array.isArray(datasets)) return;
98
+ const left = area.left;
99
+ const top = area.top;
100
+ const right = area.right ?? left + (area.width ?? 0);
101
+ const bottom = area.bottom ?? top + (area.height ?? 0);
102
+ let saved = false;
103
+ datasets.forEach((dataset, datasetIndex) => {
104
+ var _a2, _b2, _c, _d, _e, _f, _g;
105
+ const meta = (_a2 = chart.getDatasetMeta) == null ? void 0 : _a2.call(chart, datasetIndex);
106
+ if (!meta) return;
107
+ const isBar = meta.type === "bar" || ((_c = (_b2 = meta.controller) == null ? void 0 : _b2.constructor) == null ? void 0 : _c.id) === "bar";
108
+ if (!isBar) return;
109
+ if (((_e = (_d = meta.vScale) == null ? void 0 : _d.options) == null ? void 0 : _e.stacked) || ((_g = (_f = meta.iScale) == null ? void 0 : _f.options) == null ? void 0 : _g.stacked)) return;
110
+ if (typeof chart.isDatasetVisible === "function" && !chart.isDatasetVisible(datasetIndex)) {
111
+ return;
112
+ }
113
+ const values = Array.isArray(dataset == null ? void 0 : dataset.data) ? dataset.data : [];
114
+ const elements = Array.isArray(meta.data) ? meta.data : [];
115
+ values.forEach((value, index) => {
116
+ var _a3;
117
+ if (!missingValue.isMissingChartValue(value)) return;
118
+ const element = elements[index];
119
+ if (!element) return;
120
+ const props = ((_a3 = element.getProps) == null ? void 0 : _a3.call(element, ["x", "y", "base", "width", "height"], true)) ?? element;
121
+ const { x, y, base, width, height } = props;
122
+ if (![x, y, base].every((n) => Number.isFinite(n))) return;
123
+ const horizontal = element.horizontal === true;
124
+ const thickness = horizontal ? height : width;
125
+ if (!Number.isFinite(thickness) || thickness <= 0) return;
126
+ let rect;
127
+ if (horizontal) {
128
+ const dir = base < (left + right) / 2 ? 1 : -1;
129
+ rect = [Math.min(base, base + dir * MISSING_BAR_STUB_LENGTH), y - thickness / 2, MISSING_BAR_STUB_LENGTH, thickness];
130
+ } else {
131
+ const dir = base > (top + bottom) / 2 ? -1 : 1;
132
+ rect = [x - thickness / 2, Math.min(base, base + dir * MISSING_BAR_STUB_LENGTH), thickness, MISSING_BAR_STUB_LENGTH];
133
+ }
134
+ if (!saved) {
135
+ ctx.save();
136
+ ctx.beginPath();
137
+ ctx.rect(left, top, right - left, bottom - top);
138
+ ctx.clip();
139
+ saved = true;
140
+ }
141
+ ctx.strokeStyle = colorAt(dataset == null ? void 0 : dataset.borderColor, index) ?? MISSING_BAR_FALLBACK_COLOR;
142
+ ctx.lineWidth = 1;
143
+ ctx.setLineDash(STUB_DASH);
144
+ ctx.strokeRect(...rect);
145
+ });
146
+ });
147
+ if (saved) {
148
+ (_b = ctx.setLineDash) == null ? void 0 : _b.call(ctx, []);
149
+ ctx.restore();
150
+ }
151
+ }
152
+ function drawNoDataText(chart, text, fontFamily, color) {
153
+ const ctx = chart == null ? void 0 : chart.ctx;
154
+ const area = chart == null ? void 0 : chart.chartArea;
155
+ if (!ctx || !area || !text) return;
156
+ const cx = (area.left + (area.right ?? area.left + (area.width ?? 0))) / 2;
157
+ const cy = (area.top + (area.bottom ?? area.top + (area.height ?? 0))) / 2;
158
+ ctx.save();
159
+ ctx.font = `12px ${fontFamily || "sans-serif"}`;
160
+ ctx.fillStyle = color || NO_DATA_TEXT_COLOR;
161
+ ctx.textAlign = "center";
162
+ ctx.textBaseline = "middle";
163
+ ctx.fillText(text, cx, cy);
164
+ ctx.restore();
165
+ }
166
+ function createMissingValuesPlugin(options) {
167
+ return {
168
+ id: "mcpuiMissingValues",
169
+ afterDatasetsDraw(chart) {
170
+ var _a, _b;
171
+ try {
172
+ drawMissingBarStubs(chart);
173
+ if (options.allMissing) {
174
+ drawNoDataText(chart, options.getNoDataText(), (_a = options.getFontFamily) == null ? void 0 : _a.call(options), (_b = options.getTextColor) == null ? void 0 : _b.call(options));
175
+ }
176
+ } catch {
177
+ }
178
+ }
179
+ };
180
+ }
181
+ exports.MISSING_BAR_FALLBACK_COLOR = MISSING_BAR_FALLBACK_COLOR;
182
+ exports.MISSING_BAR_STUB_LENGTH = MISSING_BAR_STUB_LENGTH;
183
+ exports.NO_DATA_TEXT_COLOR = NO_DATA_TEXT_COLOR;
184
+ exports.applyUnitAxisTitle = applyUnitAxisTitle;
185
+ exports.createMissingLegendGenerator = createMissingLegendGenerator;
186
+ exports.createMissingValuesPlugin = createMissingValuesPlugin;
187
+ exports.createTooltipLabel = createTooltipLabel;
188
+ exports.drawMissingBarStubs = drawMissingBarStubs;
189
+ exports.drawNoDataText = drawNoDataText;
190
+ exports.isMissingTooltipItem = isMissingTooltipItem;
191
+ exports.isStackedChart = isStackedChart;
192
+ exports.missingNoteKind = missingNoteKind;
193
+ exports.withDatasetsNoGapSpan = withDatasetsNoGapSpan;
194
+ //# sourceMappingURL=chart-missing-plugin.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-missing-plugin.cjs","sources":["../../src/components/chart-missing-plugin.ts"],"sourcesContent":["/**\n * Missing values in a Chart.js chart (v6.24.0) — everything the renderer adds\n * to its Chart.js config when a payload says a value is MISSING (`null`).\n *\n * The rule: absence is never zero. Chart.js already keeps the slot of a `null`\n * (no label dropped) and draws nothing for it; what it does not do is make the\n * absence READABLE. A null bar is a zero-height bar that is skipped when\n * drawn, a null line point is a hole the line may bridge (`spanGaps`), and the\n * legend, tooltip and axis know nothing of either. This module supplies:\n *\n * - {@link createMissingValuesPlugin} — a PER-CHART plugin (never\n * `Chart.register`ed, so it can leak into no other chart) that outlines a\n * dashed stub where a bar should have been (not on stacked or overlaid\n * bars, whose baseline belongs to another series), and says \"no data\" on a\n * chart with nothing to draw;\n * - {@link createMissingLegendGenerator} — marks a fully-missing series in the\n * legend;\n * - {@link createTooltipLabel} — names a missing value, and appends the unit;\n * - {@link withDatasetsNoGapSpan} — the shallow-cloned data with\n * `spanGaps: false`;\n * - {@link applyUnitAxisTitle} — the unit as the value axis title.\n *\n * Runtime-free on purpose (no `solid-js`, no `chart.js` import): the renderer\n * hands in the Chart.js pieces it loaded and the chrome strings (lazily, as\n * getters, so a late locale change is honoured at draw time). Every function\n * is defensive — a drawing hook that throws would blank the whole chart.\n *\n * Chart.js 4.5.1 facts this relies on (verified in `dist/chart.js`):\n * - a bar whose parsed value is `null` gets `base = head = vScale.getBasePixel()`\n * and no `skip` flag (BarController.updateElements), and `BarController.draw`\n * skips it (`getParsed(i)[vScale.axis] !== null`) — so nothing is painted;\n * - the bar element still carries its true index-axis thickness (`width` for a\n * vertical bar, `height` for a horizontal one).\n */\n\nimport type { MCPUIStrings } from '../context/MCPUIStringsContext';\nimport { formatMCPUIString } from '../utils/format-string';\nimport { isMissingChartValue } from '../utils/missing-value';\n\ntype Strings = Required<MCPUIStrings>;\n\n/** Length, in px along the value axis, of the dashed stub of a missing bar. */\nexport const MISSING_BAR_STUB_LENGTH = 12;\n/** Stroke of the stub when the dataset names no border colour. */\nexport const MISSING_BAR_FALLBACK_COLOR = '#9ca3af';\n/** Colour of the centred \"no data\" text. */\nexport const NO_DATA_TEXT_COLOR = '#6b7280';\nconst STUB_DASH = [4, 3];\n\n/** Chart types whose value axis is `y` and whose points are `{x, y}`. */\nconst POINT_CHART_TYPES = new Set(['scatter', 'bubble']);\n\n/**\n * The category of convention line a chart shows under its canvas:\n * `'gaps'` (a line breaks), `'bars'` (a dashed outline stands in for the\n * bar) or `'omitted'` (nothing is drawn: scatter, bubble, stacked bars).\n */\nexport type MissingNoteKind = 'gaps' | 'bars' | 'omitted';\n\n/**\n * Whether a bar chart's bars are stacked or overlaid (`stacked` on either\n * axis). A missing bar there has no slot of its own at the baseline — the\n * baseline belongs to the series below — so no dashed outline is drawn.\n */\nexport function isStackedChart(options: any): boolean {\n return Boolean(options?.scales?.x?.stacked || options?.scales?.y?.stacked);\n}\n\n/** Which convention note a chart gets: how ITS missing values are drawn. */\nexport function missingNoteKind(chartType: string | undefined, options?: any): MissingNoteKind {\n if (chartType === 'bar') return isStackedChart(options) ? 'omitted' : 'bars';\n if (chartType === 'scatter' || chartType === 'bubble') return 'omitted';\n return 'gaps';\n}\n\n// ─── Data ──────────────────────────────────────────────────────────────────\n\n/**\n * Chart.js data with every dataset shallow-cloned and `spanGaps: false`, so a\n * line breaks at a missing value instead of joining its neighbours. Never\n * mutates its input; `labels` and every other key are carried by reference.\n */\nexport function withDatasetsNoGapSpan<D extends { datasets?: unknown }>(data: D): D {\n const datasets = Array.isArray(data?.datasets) ? data.datasets : null;\n if (!datasets) return data;\n return {\n ...data,\n datasets: datasets.map((dataset: unknown) =>\n dataset !== null && typeof dataset === 'object'\n ? { ...(dataset as object), spanGaps: false }\n : dataset\n ),\n };\n}\n\n// ─── Legend ────────────────────────────────────────────────────────────────\n\ntype LegendGenerator = (chart: any) => any[];\n\n/**\n * Wraps a Chart.js legend label generator so a fully-missing dataset reads\n * `\"{series} (no data)\"` (`strings.chartLegendNoData`). Every other item is\n * passed through untouched.\n */\nexport function createMissingLegendGenerator(\n base: LegendGenerator,\n fullyMissing: readonly boolean[],\n getStrings: () => Strings\n): LegendGenerator {\n return function generateLabels(this: unknown, chart: any) {\n const items = base.call(this, chart);\n if (!Array.isArray(items)) return items;\n return items.map((item) => {\n const index = item?.datasetIndex;\n if (typeof index !== 'number' || !fullyMissing[index]) return item;\n const text = typeof item.text === 'string' ? item.text : String(item.text ?? '');\n return {\n ...item,\n text: formatMCPUIString(getStrings().chartLegendNoData, { series: text }),\n };\n });\n };\n}\n\n// ─── Tooltip ───────────────────────────────────────────────────────────────\n\n/** Whether a Chart.js tooltip item stands for a missing value. */\nexport function isMissingTooltipItem(item: any): boolean {\n if (item === null || item === undefined) return false;\n if (item.raw === null || item.raw === undefined || isMissingChartValue(item.raw)) return true;\n const parsed = item.parsed;\n if (parsed !== null && typeof parsed === 'object') {\n const chartType = item.chart?.config?.type;\n const valueKey =\n chartType === 'radar' ? 'r' : item.chart?.options?.indexAxis === 'y' ? 'x' : 'y';\n if (valueKey in parsed && parsed[valueKey] === null) return true;\n }\n return false;\n}\n\n/**\n * Tooltip `label` callback: names a missing value (`\"{series}: Missing\n * value\"`) and, with a `unit`, appends it to a present one. Otherwise it is\n * Chart.js's default composition (dataset label, `\": \"`, formatted value) —\n * including its `mode: 'dataset'` branch, which prefixes the CATEGORY label\n * instead, since every item of that tooltip belongs to the same dataset.\n * Hence a regular function: Chart.js calls it with the tooltip as `this`.\n *\n * `unit` is left off scatter and bubble tooltips: their formatted value is the\n * pair `(x, y)`, to which one unit does not belong.\n */\nexport function createTooltipLabel(\n getStrings: () => Strings,\n unit: string | undefined,\n chartType: string | undefined\n): (this: any, item: any) => string {\n const applyUnit = unit !== undefined && !POINT_CHART_TYPES.has(chartType ?? '');\n return function label(this: any, item: any) {\n const strings = getStrings();\n const prefixLabel = this?.options?.mode === 'dataset' ? item?.label : item?.dataset?.label;\n const prefix = typeof prefixLabel === 'string' && prefixLabel !== '' ? `${prefixLabel}: ` : '';\n\n if (isMissingTooltipItem(item)) return `${prefix}${strings.missingValue}`;\n\n const formatted = item?.formattedValue;\n if (formatted === null || formatted === undefined) return prefix;\n const value = applyUnit\n ? formatMCPUIString(strings.chartValueWithUnit, { value: formatted, unit: unit as string })\n : String(formatted);\n return `${prefix}${value}`;\n };\n}\n\n// ─── Axis ──────────────────────────────────────────────────────────────────\n\n/**\n * Sets the chart's `unit` as the title of its value axis, in place on the\n * `options` object the renderer just built (never on the payload's).\n *\n * Only bar, line, scatter and bubble have a value axis to title. The value\n * axis is `y`, or `x` when the index axis is `y` (a horizontal bar or line).\n * An existing `scales[axis].title` is the payload's own word and is kept; the\n * rest of the scale config (a `timeAxis` block sets `scales.x`) is kept too.\n */\nexport function applyUnitAxisTitle(\n options: any,\n chartType: string | undefined,\n unit: string | undefined\n): void {\n if (unit === undefined) return;\n if (chartType !== 'bar' && chartType !== 'line' && !POINT_CHART_TYPES.has(chartType ?? '')) {\n return;\n }\n const horizontal = (chartType === 'bar' || chartType === 'line') && options?.indexAxis === 'y';\n const axis = horizontal ? 'x' : 'y';\n if (options.scales?.[axis]?.title !== undefined) return;\n options.scales = {\n ...options.scales,\n [axis]: { ...options.scales?.[axis], title: { display: true, text: unit } },\n };\n}\n\n// ─── Plugin ────────────────────────────────────────────────────────────────\n\nexport interface MissingValuesPluginOptions {\n /** At least one dataset and every one of them has no observed value. */\n allMissing: boolean;\n /** Lazy: read at draw time. */\n getNoDataText: () => string;\n /** Lazy: `Chart.defaults.font.family`, when the build exposes it. */\n getFontFamily?: () => string | undefined;\n /** Lazy host theme override; omission retains the historical grey. */\n getTextColor?: () => string | undefined;\n}\n\n/** A dataset colour for entry `index`, as a string, or `undefined`. */\nfunction colorAt(color: unknown, index: number): string | undefined {\n if (typeof color === 'string' && color !== '') return color;\n if (Array.isArray(color) && color.length > 0) {\n const picked = color[index % color.length];\n return typeof picked === 'string' && picked !== '' ? picked : undefined;\n }\n return undefined;\n}\n\n/**\n * Draws a dashed outline stub for every missing bar of every visible,\n * non-stacked bar dataset, so a missing value is a visible mark, not a bar\n * that \"is\" zero.\n *\n * The stub sits on the value-axis base, as thick as the bar would have been,\n * and runs {@link MISSING_BAR_STUB_LENGTH}px toward the middle of the chart\n * area (up from a bottom baseline, down from a top one, right from a left\n * one). Clipped to the chart area.\n */\nexport function drawMissingBarStubs(chart: any): void {\n const ctx = chart?.ctx;\n const area = chart?.chartArea;\n const datasets = chart?.data?.datasets;\n if (!ctx || !area || !Array.isArray(datasets)) return;\n\n const left = area.left;\n const top = area.top;\n const right = area.right ?? left + (area.width ?? 0);\n const bottom = area.bottom ?? top + (area.height ?? 0);\n\n let saved = false;\n datasets.forEach((dataset: any, datasetIndex: number) => {\n const meta = chart.getDatasetMeta?.(datasetIndex);\n if (!meta) return;\n const isBar = meta.type === 'bar' || meta.controller?.constructor?.id === 'bar';\n if (!isBar) return;\n // Stacked or overlaid bars: the baseline under a missing segment is the\n // series below, so an outline there would point at the wrong series.\n if (meta.vScale?.options?.stacked || meta.iScale?.options?.stacked) return;\n if (typeof chart.isDatasetVisible === 'function' && !chart.isDatasetVisible(datasetIndex)) {\n return;\n }\n const values: unknown[] = Array.isArray(dataset?.data) ? dataset.data : [];\n const elements: any[] = Array.isArray(meta.data) ? meta.data : [];\n\n values.forEach((value, index) => {\n if (!isMissingChartValue(value)) return;\n const element = elements[index];\n if (!element) return;\n const props = element.getProps?.(['x', 'y', 'base', 'width', 'height'], true) ?? element;\n const { x, y, base, width, height } = props;\n if (![x, y, base].every((n) => Number.isFinite(n))) return;\n const horizontal = element.horizontal === true;\n const thickness = horizontal ? height : width;\n if (!Number.isFinite(thickness) || thickness <= 0) return;\n\n let rect: [number, number, number, number];\n if (horizontal) {\n const dir = base < (left + right) / 2 ? 1 : -1;\n rect = [Math.min(base, base + dir * MISSING_BAR_STUB_LENGTH), y - thickness / 2, MISSING_BAR_STUB_LENGTH, thickness];\n } else {\n const dir = base > (top + bottom) / 2 ? -1 : 1;\n rect = [x - thickness / 2, Math.min(base, base + dir * MISSING_BAR_STUB_LENGTH), thickness, MISSING_BAR_STUB_LENGTH];\n }\n\n if (!saved) {\n ctx.save();\n ctx.beginPath();\n ctx.rect(left, top, right - left, bottom - top);\n ctx.clip();\n saved = true;\n }\n ctx.strokeStyle = colorAt(dataset?.borderColor, index) ?? MISSING_BAR_FALLBACK_COLOR;\n ctx.lineWidth = 1;\n ctx.setLineDash(STUB_DASH);\n ctx.strokeRect(...rect);\n });\n });\n if (saved) {\n ctx.setLineDash?.([]);\n ctx.restore();\n }\n}\n\n/** Draws `text` centred in the chart area (a chart with nothing to plot). */\nexport function drawNoDataText(chart: any, text: string, fontFamily?: string, color?: string): void {\n const ctx = chart?.ctx;\n const area = chart?.chartArea;\n if (!ctx || !area || !text) return;\n const cx = (area.left + (area.right ?? area.left + (area.width ?? 0))) / 2;\n const cy = (area.top + (area.bottom ?? area.top + (area.height ?? 0))) / 2;\n ctx.save();\n ctx.font = `12px ${fontFamily || 'sans-serif'}`;\n ctx.fillStyle = color || NO_DATA_TEXT_COLOR;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(text, cx, cy);\n ctx.restore();\n}\n\n/**\n * The per-chart plugin object. Passed as `config.plugins = [plugin]`: Chart.js\n * scopes it to that one chart. Both hooks swallow their own errors — a\n * decoration must never take the chart down.\n */\nexport function createMissingValuesPlugin(options: MissingValuesPluginOptions) {\n return {\n id: 'mcpuiMissingValues',\n afterDatasetsDraw(chart: any) {\n try {\n drawMissingBarStubs(chart);\n if (options.allMissing) {\n drawNoDataText(chart, options.getNoDataText(), options.getFontFamily?.(), options.getTextColor?.());\n }\n } catch {\n // Cosmetic layer: never break the chart.\n }\n },\n };\n}\n"],"names":["formatMCPUIString","isMissingChartValue","_a","_b"],"mappings":"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"}