@matthieumordrel/chart-studio 0.2.1 → 0.2.3

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 (175) hide show
  1. package/README.md +24 -0
  2. package/dist/core/chart-capabilities.d.mts +48 -0
  3. package/dist/core/chart-capabilities.mjs +55 -0
  4. package/dist/core/{colors.d.ts → colors.d.mts} +5 -3
  5. package/dist/core/colors.mjs +55 -0
  6. package/dist/core/config-utils.mjs +79 -0
  7. package/dist/core/date-utils.mjs +49 -0
  8. package/dist/core/define-chart-schema.d.mts +106 -0
  9. package/dist/core/define-chart-schema.mjs +47 -0
  10. package/dist/core/formatting.mjs +349 -0
  11. package/dist/core/infer-columns.d.mts +9 -0
  12. package/dist/core/infer-columns.mjs +481 -0
  13. package/dist/core/metric-utils.d.mts +13 -0
  14. package/dist/core/metric-utils.mjs +121 -0
  15. package/dist/core/pipeline-data-points.mjs +212 -0
  16. package/dist/core/pipeline-helpers.mjs +85 -0
  17. package/dist/core/{pipeline.d.ts → pipeline.d.mts} +21 -24
  18. package/dist/core/pipeline.mjs +153 -0
  19. package/dist/core/types.d.mts +957 -0
  20. package/dist/core/use-chart-options.d.mts +64 -0
  21. package/dist/core/use-chart-options.mjs +7 -0
  22. package/dist/core/use-chart-resolvers.mjs +34 -0
  23. package/dist/core/{use-chart.d.ts → use-chart.d.mts} +12 -9
  24. package/dist/core/use-chart.mjs +299 -0
  25. package/dist/index.d.mts +10 -0
  26. package/dist/index.mjs +8 -0
  27. package/dist/ui/chart-axis-ticks.mjs +65 -0
  28. package/dist/ui/{chart-canvas.d.ts → chart-canvas.d.mts} +13 -6
  29. package/dist/ui/chart-canvas.mjs +461 -0
  30. package/dist/ui/chart-context.d.mts +92 -0
  31. package/dist/ui/chart-context.mjs +112 -0
  32. package/dist/ui/{chart-date-range-badge.d.ts → chart-date-range-badge.d.mts} +10 -4
  33. package/dist/ui/chart-date-range-badge.mjs +49 -0
  34. package/dist/ui/chart-date-range-panel.d.mts +18 -0
  35. package/dist/ui/chart-date-range-panel.mjs +208 -0
  36. package/dist/ui/{chart-date-range.d.ts → chart-date-range.d.mts} +10 -4
  37. package/dist/ui/chart-date-range.mjs +67 -0
  38. package/dist/ui/chart-debug.d.mts +17 -0
  39. package/dist/ui/chart-debug.mjs +169 -0
  40. package/dist/ui/chart-dropdown.mjs +92 -0
  41. package/dist/ui/{chart-filters-panel.d.ts → chart-filters-panel.d.mts} +12 -5
  42. package/dist/ui/chart-filters-panel.mjs +132 -0
  43. package/dist/ui/{chart-filters.d.ts → chart-filters.d.mts} +10 -4
  44. package/dist/ui/chart-filters.mjs +48 -0
  45. package/dist/ui/chart-group-by-selector.d.mts +14 -0
  46. package/dist/ui/chart-group-by-selector.mjs +29 -0
  47. package/dist/ui/{chart-metric-panel.d.ts → chart-metric-panel.d.mts} +12 -5
  48. package/dist/ui/chart-metric-panel.mjs +172 -0
  49. package/dist/ui/chart-metric-selector.d.mts +16 -0
  50. package/dist/ui/chart-metric-selector.mjs +50 -0
  51. package/dist/ui/chart-select.mjs +62 -0
  52. package/dist/ui/{chart-source-switcher.d.ts → chart-source-switcher.d.mts} +10 -4
  53. package/dist/ui/chart-source-switcher.mjs +54 -0
  54. package/dist/ui/chart-time-bucket-selector.d.mts +15 -0
  55. package/dist/ui/chart-time-bucket-selector.mjs +34 -0
  56. package/dist/ui/chart-toolbar-overflow.d.mts +28 -0
  57. package/dist/ui/chart-toolbar-overflow.mjs +209 -0
  58. package/dist/ui/chart-toolbar.d.mts +29 -0
  59. package/dist/ui/chart-toolbar.mjs +56 -0
  60. package/dist/ui/chart-type-selector.d.mts +14 -0
  61. package/dist/ui/chart-type-selector.mjs +33 -0
  62. package/dist/ui/chart-x-axis-selector.d.mts +14 -0
  63. package/dist/ui/chart-x-axis-selector.mjs +25 -0
  64. package/dist/ui/index.d.mts +19 -0
  65. package/dist/ui/index.mjs +18 -0
  66. package/dist/ui/toolbar-types.d.mts +7 -0
  67. package/dist/ui/toolbar-types.mjs +83 -0
  68. package/package.json +11 -10
  69. package/dist/core/chart-capabilities.d.ts +0 -60
  70. package/dist/core/chart-capabilities.d.ts.map +0 -1
  71. package/dist/core/chart-capabilities.js +0 -54
  72. package/dist/core/colors.d.ts.map +0 -1
  73. package/dist/core/colors.js +0 -54
  74. package/dist/core/config-utils.d.ts +0 -43
  75. package/dist/core/config-utils.d.ts.map +0 -1
  76. package/dist/core/config-utils.js +0 -80
  77. package/dist/core/date-utils.d.ts +0 -29
  78. package/dist/core/date-utils.d.ts.map +0 -1
  79. package/dist/core/date-utils.js +0 -58
  80. package/dist/core/define-chart-schema.d.ts +0 -105
  81. package/dist/core/define-chart-schema.d.ts.map +0 -1
  82. package/dist/core/define-chart-schema.js +0 -44
  83. package/dist/core/formatting.d.ts +0 -47
  84. package/dist/core/formatting.d.ts.map +0 -1
  85. package/dist/core/formatting.js +0 -396
  86. package/dist/core/index.d.ts +0 -17
  87. package/dist/core/index.d.ts.map +0 -1
  88. package/dist/core/index.js +0 -12
  89. package/dist/core/infer-columns.d.ts +0 -6
  90. package/dist/core/infer-columns.d.ts.map +0 -1
  91. package/dist/core/infer-columns.js +0 -512
  92. package/dist/core/metric-utils.d.ts +0 -43
  93. package/dist/core/metric-utils.d.ts.map +0 -1
  94. package/dist/core/metric-utils.js +0 -141
  95. package/dist/core/pipeline-data-points.d.ts +0 -23
  96. package/dist/core/pipeline-data-points.d.ts.map +0 -1
  97. package/dist/core/pipeline-data-points.js +0 -235
  98. package/dist/core/pipeline-helpers.d.ts +0 -38
  99. package/dist/core/pipeline-helpers.d.ts.map +0 -1
  100. package/dist/core/pipeline-helpers.js +0 -97
  101. package/dist/core/pipeline.d.ts.map +0 -1
  102. package/dist/core/pipeline.js +0 -156
  103. package/dist/core/types.d.ts +0 -1109
  104. package/dist/core/types.d.ts.map +0 -1
  105. package/dist/core/types.js +0 -14
  106. package/dist/core/use-chart-options.d.ts +0 -66
  107. package/dist/core/use-chart-options.d.ts.map +0 -1
  108. package/dist/core/use-chart-options.js +0 -4
  109. package/dist/core/use-chart-resolvers.d.ts +0 -14
  110. package/dist/core/use-chart-resolvers.d.ts.map +0 -1
  111. package/dist/core/use-chart-resolvers.js +0 -41
  112. package/dist/core/use-chart.d.ts.map +0 -1
  113. package/dist/core/use-chart.js +0 -265
  114. package/dist/index.d.ts +0 -36
  115. package/dist/index.d.ts.map +0 -1
  116. package/dist/index.js +0 -35
  117. package/dist/ui/chart-axis-ticks.d.ts +0 -35
  118. package/dist/ui/chart-axis-ticks.d.ts.map +0 -1
  119. package/dist/ui/chart-axis-ticks.js +0 -79
  120. package/dist/ui/chart-canvas.d.ts.map +0 -1
  121. package/dist/ui/chart-canvas.js +0 -337
  122. package/dist/ui/chart-context.d.ts +0 -89
  123. package/dist/ui/chart-context.d.ts.map +0 -1
  124. package/dist/ui/chart-context.js +0 -128
  125. package/dist/ui/chart-date-range-badge.d.ts.map +0 -1
  126. package/dist/ui/chart-date-range-badge.js +0 -30
  127. package/dist/ui/chart-date-range-panel.d.ts +0 -25
  128. package/dist/ui/chart-date-range-panel.d.ts.map +0 -1
  129. package/dist/ui/chart-date-range-panel.js +0 -125
  130. package/dist/ui/chart-date-range.d.ts.map +0 -1
  131. package/dist/ui/chart-date-range.js +0 -37
  132. package/dist/ui/chart-debug.d.ts +0 -10
  133. package/dist/ui/chart-debug.d.ts.map +0 -1
  134. package/dist/ui/chart-debug.js +0 -126
  135. package/dist/ui/chart-dropdown.d.ts +0 -35
  136. package/dist/ui/chart-dropdown.d.ts.map +0 -1
  137. package/dist/ui/chart-dropdown.js +0 -76
  138. package/dist/ui/chart-filters-panel.d.ts.map +0 -1
  139. package/dist/ui/chart-filters-panel.js +0 -46
  140. package/dist/ui/chart-filters.d.ts.map +0 -1
  141. package/dist/ui/chart-filters.js +0 -26
  142. package/dist/ui/chart-group-by-selector.d.ts +0 -8
  143. package/dist/ui/chart-group-by-selector.d.ts.map +0 -1
  144. package/dist/ui/chart-group-by-selector.js +0 -19
  145. package/dist/ui/chart-metric-panel.d.ts.map +0 -1
  146. package/dist/ui/chart-metric-panel.js +0 -118
  147. package/dist/ui/chart-metric-selector.d.ts +0 -10
  148. package/dist/ui/chart-metric-selector.d.ts.map +0 -1
  149. package/dist/ui/chart-metric-selector.js +0 -27
  150. package/dist/ui/chart-select.d.ts +0 -25
  151. package/dist/ui/chart-select.d.ts.map +0 -1
  152. package/dist/ui/chart-select.js +0 -35
  153. package/dist/ui/chart-source-switcher.d.ts.map +0 -1
  154. package/dist/ui/chart-source-switcher.js +0 -31
  155. package/dist/ui/chart-time-bucket-selector.d.ts +0 -9
  156. package/dist/ui/chart-time-bucket-selector.d.ts.map +0 -1
  157. package/dist/ui/chart-time-bucket-selector.js +0 -25
  158. package/dist/ui/chart-toolbar-overflow.d.ts +0 -29
  159. package/dist/ui/chart-toolbar-overflow.d.ts.map +0 -1
  160. package/dist/ui/chart-toolbar-overflow.js +0 -109
  161. package/dist/ui/chart-toolbar.d.ts +0 -45
  162. package/dist/ui/chart-toolbar.d.ts.map +0 -1
  163. package/dist/ui/chart-toolbar.js +0 -44
  164. package/dist/ui/chart-type-selector.d.ts +0 -8
  165. package/dist/ui/chart-type-selector.d.ts.map +0 -1
  166. package/dist/ui/chart-type-selector.js +0 -22
  167. package/dist/ui/chart-x-axis-selector.d.ts +0 -8
  168. package/dist/ui/chart-x-axis-selector.d.ts.map +0 -1
  169. package/dist/ui/chart-x-axis-selector.js +0 -14
  170. package/dist/ui/index.d.ts +0 -25
  171. package/dist/ui/index.d.ts.map +0 -1
  172. package/dist/ui/index.js +0 -23
  173. package/dist/ui/toolbar-types.d.ts +0 -43
  174. package/dist/ui/toolbar-types.d.ts.map +0 -1
  175. package/dist/ui/toolbar-types.js +0 -50
package/README.md CHANGED
@@ -364,6 +364,30 @@ If you are importing the package source directly in a local playground or monore
364
364
 
365
365
  If your app already uses shadcn-style tokens, also make sure tokens such as `background`, `foreground`, `muted`, `border`, `popover`, `primary`, `ring`, and optionally `chart-1` through `chart-5` are defined in your theme.
366
366
 
367
+ ## On the Radar
368
+
369
+ These are known limitations and areas being considered for future versions. None of these are committed — they represent directions the library may grow based on real usage.
370
+
371
+ ### Renderer flexibility
372
+
373
+ The UI layer currently only supports Recharts. If you want to use ECharts, Plotly, or another renderer, you can use the headless core but lose the built-in toolbar and canvas composition. A renderer adapter pattern for `<ChartCanvas>` could make the UI layer renderer-agnostic.
374
+
375
+ ### Richer aggregation
376
+
377
+ The pipeline supports sum, avg, min, and max. Derived columns can access multiple fields of a single row (e.g. `row.revenue - row.cost`), but there is no support yet for metrics that depend on other rows or on aggregated results — things like "% of total", running totals, percentiles, or post-aggregation ratios (e.g. total revenue / total orders).
378
+
379
+ ### Chart interactivity
380
+
381
+ There is currently no built-in support for drill-down, click-to-filter, brush selection, or linked charts. The headless state can be wired manually to achieve some of these, but first-class interactivity primitives would make this significantly easier.
382
+
383
+ ### Multi-dataset composition
384
+
385
+ Each chart instance operates on a single flat dataset. Overlaying series from different schemas (e.g. revenue on the left Y-axis and headcount on the right) would require separate chart instances today. Dual-axis and cross-dataset composition are not yet supported.
386
+
387
+ ### The double-call schema syntax
388
+
389
+ `defineChartSchema<Row>()()` uses a double function call as a workaround for TypeScript's lack of partial type argument inference. This lets you provide the row type explicitly while the column IDs are inferred automatically. It works well but can surprise newcomers — this will be revisited if TypeScript adds native support for partial inference.
390
+
367
391
  ## Release
368
392
 
369
393
  - `bun run release:check`
@@ -0,0 +1,48 @@
1
+ //#region src/core/chart-capabilities.d.ts
2
+ /**
3
+ * X-axis kinds understood by chart-studio when validating chart types.
4
+ */
5
+ type ChartAxisType = 'date' | 'category' | 'boolean';
6
+ /**
7
+ * Declarative chart-type capability matrix.
8
+ *
9
+ * Centralizing these rules keeps UI controls and state validation aligned as
10
+ * more chart types are added later.
11
+ */
12
+ type ChartTypeCapabilities = {
13
+ supportedXAxisTypes: readonly ChartAxisType[];
14
+ supportsGrouping: boolean;
15
+ supportsTimeBucketing: boolean;
16
+ };
17
+ /**
18
+ * Capabilities for each supported chart type.
19
+ */
20
+ declare const CHART_TYPE_CONFIG: {
21
+ readonly bar: {
22
+ readonly supportedXAxisTypes: readonly ["date", "category", "boolean"];
23
+ readonly supportsGrouping: true;
24
+ readonly supportsTimeBucketing: true;
25
+ };
26
+ readonly line: {
27
+ readonly supportedXAxisTypes: readonly ["date"];
28
+ readonly supportsGrouping: true;
29
+ readonly supportsTimeBucketing: true;
30
+ };
31
+ readonly area: {
32
+ readonly supportedXAxisTypes: readonly ["date"];
33
+ readonly supportsGrouping: true;
34
+ readonly supportsTimeBucketing: true;
35
+ };
36
+ readonly pie: {
37
+ readonly supportedXAxisTypes: readonly ["category", "boolean"];
38
+ readonly supportsGrouping: false;
39
+ readonly supportsTimeBucketing: false;
40
+ };
41
+ readonly donut: {
42
+ readonly supportedXAxisTypes: readonly ["category", "boolean"];
43
+ readonly supportsGrouping: false;
44
+ readonly supportsTimeBucketing: false;
45
+ };
46
+ };
47
+ //#endregion
48
+ export { CHART_TYPE_CONFIG, ChartAxisType, ChartTypeCapabilities };
@@ -0,0 +1,55 @@
1
+ import { CHART_TYPE_ORDER } from "./config-utils.mjs";
2
+ //#region src/core/chart-capabilities.ts
3
+ /**
4
+ * Capabilities for each supported chart type.
5
+ */
6
+ const CHART_TYPE_CONFIG = {
7
+ bar: {
8
+ supportedXAxisTypes: [
9
+ "date",
10
+ "category",
11
+ "boolean"
12
+ ],
13
+ supportsGrouping: true,
14
+ supportsTimeBucketing: true
15
+ },
16
+ line: {
17
+ supportedXAxisTypes: ["date"],
18
+ supportsGrouping: true,
19
+ supportsTimeBucketing: true
20
+ },
21
+ area: {
22
+ supportedXAxisTypes: ["date"],
23
+ supportsGrouping: true,
24
+ supportsTimeBucketing: true
25
+ },
26
+ pie: {
27
+ supportedXAxisTypes: ["category", "boolean"],
28
+ supportsGrouping: false,
29
+ supportsTimeBucketing: false
30
+ },
31
+ donut: {
32
+ supportedXAxisTypes: ["category", "boolean"],
33
+ supportsGrouping: false,
34
+ supportsTimeBucketing: false
35
+ }
36
+ };
37
+ /**
38
+ * Whether a chart type can represent the current chart state.
39
+ */
40
+ function isChartTypeAvailable(chartType, availability) {
41
+ const { hasGroupBy, xAxisType } = availability;
42
+ if (xAxisType === null) return false;
43
+ const capabilities = CHART_TYPE_CONFIG[chartType];
44
+ if (!capabilities.supportedXAxisTypes.includes(xAxisType)) return false;
45
+ if (hasGroupBy && !capabilities.supportsGrouping) return false;
46
+ return true;
47
+ }
48
+ /**
49
+ * Chart types valid for the current axis + feature combination.
50
+ */
51
+ function getAvailableChartTypes(availability) {
52
+ return CHART_TYPE_ORDER.filter((chartType) => isChartTypeAvailable(chartType, availability));
53
+ }
54
+ //#endregion
55
+ export { CHART_TYPE_CONFIG, getAvailableChartTypes };
@@ -1,3 +1,4 @@
1
+ //#region src/core/colors.d.ts
1
2
  /**
2
3
  * Color assignment for chart series.
3
4
  *
@@ -12,7 +13,7 @@
12
13
  * @param useShadcn - Whether to use shadcn CSS variables (default: true)
13
14
  * @returns CSS color value
14
15
  */
15
- export declare function getSeriesColor(index: number, useShadcn?: boolean): string;
16
+ declare function getSeriesColor(index: number, useShadcn?: boolean): string;
16
17
  /**
17
18
  * Generate a color map for a list of group labels.
18
19
  * Assigns colors deterministically based on array order.
@@ -21,5 +22,6 @@ export declare function getSeriesColor(index: number, useShadcn?: boolean): stri
21
22
  * @param useShadcn - Whether to use shadcn CSS variables (default: true)
22
23
  * @returns Map from group label to CSS color
23
24
  */
24
- export declare function buildColorMap(groups: string[], useShadcn?: boolean): Map<string, string>;
25
- //# sourceMappingURL=colors.d.ts.map
25
+ declare function buildColorMap(groups: string[], useShadcn?: boolean): Map<string, string>;
26
+ //#endregion
27
+ export { buildColorMap, getSeriesColor };
@@ -0,0 +1,55 @@
1
+ //#region src/core/colors.ts
2
+ /**
3
+ * Color assignment for chart series.
4
+ *
5
+ * Uses shadcn chart CSS variables (`--chart-1` through `--chart-5`) by default.
6
+ * Falls back to a built-in OKLCH palette when CSS variables are not available.
7
+ */
8
+ /** Fallback palette using OKLCH for perceptually uniform colors. */
9
+ const FALLBACK_COLORS = [
10
+ "oklch(0.65 0.15 250)",
11
+ "oklch(0.65 0.15 350)",
12
+ "oklch(0.65 0.15 200)",
13
+ "oklch(0.65 0.15 70)",
14
+ "oklch(0.65 0.15 150)",
15
+ "oklch(0.65 0.15 30)",
16
+ "oklch(0.65 0.15 300)",
17
+ "oklch(0.65 0.15 120)",
18
+ "oklch(0.65 0.12 170)",
19
+ "oklch(0.65 0.12 220)"
20
+ ];
21
+ /** Shadcn chart CSS variables (5 colors) with safe fallbacks. */
22
+ const SHADCN_CHART_COLORS = [
23
+ `var(--chart-1, var(--cs-chart-1, hsl(245 72% 57%)))`,
24
+ `var(--chart-2, var(--cs-chart-2, hsl(271 72% 55%)))`,
25
+ `var(--chart-3, var(--cs-chart-3, hsl(330 68% 54%)))`,
26
+ `var(--chart-4, var(--cs-chart-4, hsl(170 65% 38%)))`,
27
+ `var(--chart-5, var(--cs-chart-5, hsl(30 90% 54%)))`
28
+ ];
29
+ /**
30
+ * Get a color for the Nth series.
31
+ * Cycles through the palette when index exceeds palette length.
32
+ *
33
+ * @param index - Zero-based series index
34
+ * @param useShadcn - Whether to use shadcn CSS variables (default: true)
35
+ * @returns CSS color value
36
+ */
37
+ function getSeriesColor(index, useShadcn = true) {
38
+ const palette = useShadcn ? SHADCN_CHART_COLORS : FALLBACK_COLORS;
39
+ return palette[index % palette.length];
40
+ }
41
+ /**
42
+ * Generate a color map for a list of group labels.
43
+ * Assigns colors deterministically based on array order.
44
+ *
45
+ * @param groups - Array of group labels
46
+ * @param useShadcn - Whether to use shadcn CSS variables (default: true)
47
+ * @returns Map from group label to CSS color
48
+ */
49
+ function buildColorMap(groups, useShadcn = true) {
50
+ const map = /* @__PURE__ */ new Map();
51
+ for (let i = 0; i < groups.length; i++) map.set(groups[i], getSeriesColor(i, useShadcn));
52
+ return map;
53
+ }
54
+ //#endregion
55
+ export { buildColorMap, getSeriesColor };
@@ -0,0 +1,79 @@
1
+ //#region src/core/config-utils.ts
2
+ /**
3
+ * Build the visible runtime option list after applying config restrictions.
4
+ *
5
+ * The pipeline is always:
6
+ * 1. start from runtime-valid options
7
+ * 2. if `allowed` exists, keep only allowed entries in declared order
8
+ * 3. if `hidden` exists, subtract hidden entries
9
+ *
10
+ * When `fallbackToBaseIfEmpty` is enabled, required controls can recover their
11
+ * base runtime options if the config leaves nothing selectable for the active
12
+ * source. This recovery is intentionally separate from default resolution.
13
+ */
14
+ function restrictConfiguredCollection(items, config, getKey, fallbackToBaseIfEmpty) {
15
+ const keyedItems = new Map(items.map((item) => [getKey(item), item]));
16
+ const allowedKeys = config?.allowed;
17
+ const hiddenKeys = config?.hidden ? new Set(config.hidden) : void 0;
18
+ const orderedItems = allowedKeys ? allowedKeys.flatMap((allowedKey) => {
19
+ const match = keyedItems.get(allowedKey);
20
+ return match ? [match] : [];
21
+ }) : [...items];
22
+ const visibleItems = hiddenKeys ? orderedItems.filter((item) => !hiddenKeys.has(getKey(item))) : orderedItems;
23
+ if (fallbackToBaseIfEmpty && visibleItems.length === 0) return [...items];
24
+ return visibleItems;
25
+ }
26
+ /**
27
+ * Restrict an ID-keyed option list with `allowed`/`hidden`.
28
+ *
29
+ * When `fallbackToBaseIfEmpty` is enabled, required controls keep their base
30
+ * runtime options even if the config does not match the active source.
31
+ */
32
+ function restrictConfiguredIdOptions(options, config, fallbackToBaseIfEmpty = false) {
33
+ return restrictConfiguredCollection(options, config, (option) => option.id, fallbackToBaseIfEmpty);
34
+ }
35
+ /**
36
+ * Resolve one ID-based selection against the current option list.
37
+ */
38
+ function resolveConfiguredIdSelection(currentValue, options, configuredDefault, fallbackValue, preferFirstAvailable = true) {
39
+ if (currentValue && options.some((option) => option.id === currentValue)) return currentValue;
40
+ if (configuredDefault && options.some((option) => option.id === configuredDefault)) return configuredDefault;
41
+ if (preferFirstAvailable) return options[0]?.id ?? fallbackValue;
42
+ return fallbackValue;
43
+ }
44
+ /**
45
+ * Restrict a primitive option list with `allowed`/`hidden`.
46
+ */
47
+ function restrictConfiguredValues(values, config, fallbackToBaseIfEmpty = false) {
48
+ return restrictConfiguredCollection(values, config, (value) => value, fallbackToBaseIfEmpty);
49
+ }
50
+ /**
51
+ * Resolve one primitive selection against the current option list.
52
+ */
53
+ function resolveConfiguredValue(currentValue, values, configuredDefault) {
54
+ if (values.includes(currentValue)) return currentValue;
55
+ if (configuredDefault && values.includes(configuredDefault)) return configuredDefault;
56
+ return values[0] ?? currentValue;
57
+ }
58
+ /**
59
+ * Ordered time buckets exposed by the headless API.
60
+ */
61
+ const TIME_BUCKET_ORDER = [
62
+ "day",
63
+ "week",
64
+ "month",
65
+ "quarter",
66
+ "year"
67
+ ];
68
+ /**
69
+ * Ordered chart types exposed by the headless API.
70
+ */
71
+ const CHART_TYPE_ORDER = [
72
+ "bar",
73
+ "line",
74
+ "area",
75
+ "pie",
76
+ "donut"
77
+ ];
78
+ //#endregion
79
+ export { CHART_TYPE_ORDER, TIME_BUCKET_ORDER, resolveConfiguredIdSelection, resolveConfiguredValue, restrictConfiguredIdOptions, restrictConfiguredValues };
@@ -0,0 +1,49 @@
1
+ //#region src/core/date-utils.ts
2
+ /**
3
+ * Filter data by a date range on a specific date column.
4
+ * Both bounds are inclusive (to is extended to end of day).
5
+ *
6
+ * @param data - Raw data items
7
+ * @param dateColumn - The date column to filter on
8
+ * @param filter - Date range filter with from/to bounds
9
+ * @returns Filtered data items within the date range
10
+ */
11
+ function filterByDateRange(data, dateColumn, filter) {
12
+ const { from, to } = filter;
13
+ if (!from && !to) return [...data];
14
+ const toEnd = to ? new Date(to.getFullYear(), to.getMonth(), to.getDate(), 23, 59, 59, 999) : null;
15
+ return data.filter((item) => {
16
+ const raw = dateColumn.accessor(item);
17
+ if (raw == null) return false;
18
+ const d = new Date(raw);
19
+ if (Number.isNaN(d.getTime())) return false;
20
+ if (from && d < from) return false;
21
+ if (toEnd && d > toEnd) return false;
22
+ return true;
23
+ });
24
+ }
25
+ /**
26
+ * Compute the min/max date range from data for a given date column.
27
+ *
28
+ * @param data - Data items to scan
29
+ * @param dateColumn - The date column to extract dates from
30
+ * @returns Object with min and max dates (both null if no valid dates)
31
+ */
32
+ function computeDateRange(data, dateColumn) {
33
+ let min = null;
34
+ let max = null;
35
+ for (const item of data) {
36
+ const raw = dateColumn.accessor(item);
37
+ if (raw == null) continue;
38
+ const d = new Date(raw);
39
+ if (Number.isNaN(d.getTime())) continue;
40
+ if (!min || d < min) min = d;
41
+ if (!max || d > max) max = d;
42
+ }
43
+ return {
44
+ min,
45
+ max
46
+ };
47
+ }
48
+ //#endregion
49
+ export { computeDateRange, filterByDateRange };
@@ -0,0 +1,106 @@
1
+ import { ChartTypeConfig, DefinedChartSchema, ExactShape, FiltersConfig, GroupByConfig, MetricConfig, ResolvedFilterColumnIdFromSchema, ResolvedGroupByColumnIdFromSchema, ResolvedMetricColumnIdFromSchema, ResolvedXAxisColumnIdFromSchema, SchemaColumnsValidationShape, TimeBucketConfig, XAxisConfig } from "./types.mjs";
2
+
3
+ //#region src/core/define-chart-schema.d.ts
4
+ type SchemaFromSections<T, TColumns extends Record<string, unknown> | undefined, TXAxis, TGroupBy, TFilters, TMetric, TChartType, TTimeBucket> = {
5
+ columns?: Extract<TColumns, Record<string, unknown> | undefined>;
6
+ xAxis?: Extract<TXAxis, XAxisConfig<ResolvedXAxisColumnIdFromSchema<T, {
7
+ columns?: TColumns;
8
+ }>> | undefined>;
9
+ groupBy?: Extract<TGroupBy, GroupByConfig<ResolvedGroupByColumnIdFromSchema<T, {
10
+ columns?: TColumns;
11
+ }>> | undefined>;
12
+ filters?: Extract<TFilters, FiltersConfig<ResolvedFilterColumnIdFromSchema<T, {
13
+ columns?: TColumns;
14
+ }>> | undefined>;
15
+ metric?: Extract<TMetric, MetricConfig<ResolvedMetricColumnIdFromSchema<T, {
16
+ columns?: TColumns;
17
+ }>> | undefined>;
18
+ chartType?: Extract<TChartType, ChartTypeConfig | undefined>;
19
+ timeBucket?: Extract<TTimeBucket, TimeBucketConfig | undefined>;
20
+ };
21
+ type DefineChartSchemaInput<T, TColumns extends Record<string, unknown> | undefined, TXAxis, TGroupBy, TFilters, TMetric, TChartType, TTimeBucket> = {
22
+ /**
23
+ * Shape the available chart columns.
24
+ *
25
+ * This is usually the most important part of the schema. Use it to:
26
+ * - rename inferred raw fields with `label`
27
+ * - force a field to a specific `type`
28
+ * - apply `format` or `formatter`
29
+ * - remove a raw field with `false`
30
+ * - add brand new derived columns with `kind: 'derived'`
31
+ */
32
+ columns?: TColumns & ExactShape<SchemaColumnsValidationShape<T, NoInfer<TColumns>>, NoInfer<TColumns>>;
33
+ /**
34
+ * Restrict which resolved columns may be selected on the X-axis.
35
+ *
36
+ * Use this when you want to expose only a subset of possible X-axis fields.
37
+ */
38
+ xAxis?: TXAxis & ExactShape<XAxisConfig<ResolvedXAxisColumnIdFromSchema<T, {
39
+ columns?: TColumns;
40
+ }>>, NoInfer<TXAxis>>;
41
+ /**
42
+ * Restrict which resolved columns may be used to split the chart into series.
43
+ *
44
+ * This powers grouped / multi-series charts.
45
+ */
46
+ groupBy?: TGroupBy & ExactShape<GroupByConfig<ResolvedGroupByColumnIdFromSchema<T, {
47
+ columns?: TColumns;
48
+ }>>, NoInfer<TGroupBy>>;
49
+ /**
50
+ * Restrict which resolved columns appear in the filters UI.
51
+ *
52
+ * Only category and boolean-like columns are eligible here.
53
+ */
54
+ filters?: TFilters & ExactShape<FiltersConfig<ResolvedFilterColumnIdFromSchema<T, {
55
+ columns?: TColumns;
56
+ }>>, NoInfer<TFilters>>;
57
+ /**
58
+ * Restrict which metrics and aggregate combinations remain selectable.
59
+ *
60
+ * Use this when you want to curate the metric dropdown rather than exposing
61
+ * every available numeric aggregate.
62
+ */
63
+ metric?: TMetric & ExactShape<MetricConfig<ResolvedMetricColumnIdFromSchema<T, {
64
+ columns?: TColumns;
65
+ }>>, NoInfer<TMetric>>; /** Restrict which chart renderers are available to the user. */
66
+ chartType?: TChartType & ExactShape<ChartTypeConfig, NoInfer<TChartType>>;
67
+ /**
68
+ * Restrict which time buckets remain available for date X-axes.
69
+ *
70
+ * Example: allow only `'month'` and `'quarter'`.
71
+ */
72
+ timeBucket?: TTimeBucket & ExactShape<TimeBucketConfig, NoInfer<TTimeBucket>>;
73
+ };
74
+ /**
75
+ * Define one explicit chart schema with strict exact-object checking.
76
+ *
77
+ * The schema is the single advanced authoring surface for chart-studio:
78
+ * `columns` can override or exclude inferred raw fields and also define derived
79
+ * columns, while the top-level control sections restrict the public chart
80
+ * contract.
81
+ *
82
+ * Typical shape:
83
+ *
84
+ * ```ts
85
+ * const schema = defineChartSchema<Row>()({
86
+ * columns: {
87
+ * createdAt: {type: 'date', label: 'Created'},
88
+ * revenue: {type: 'number', format: 'currency'},
89
+ * margin: {
90
+ * kind: 'derived',
91
+ * type: 'number',
92
+ * label: 'Margin',
93
+ * format: 'percent',
94
+ * accessor: row => row.profit / row.revenue,
95
+ * },
96
+ * },
97
+ * xAxis: {allowed: ['createdAt']},
98
+ * metric: {
99
+ * allowed: [{kind: 'aggregate', columnId: 'revenue', aggregate: 'sum'}],
100
+ * },
101
+ * })
102
+ * ```
103
+ */
104
+ declare function defineChartSchema<T>(): <const TColumns extends Record<string, unknown> | undefined = undefined, const TXAxis = undefined, const TGroupBy = undefined, const TFilters = undefined, const TMetric = undefined, const TChartType = undefined, const TTimeBucket = undefined>(schema: DefineChartSchemaInput<T, TColumns, TXAxis, TGroupBy, TFilters, TMetric, TChartType, TTimeBucket>) => DefinedChartSchema<T, SchemaFromSections<T, TColumns, TXAxis, TGroupBy, TFilters, TMetric, TChartType, TTimeBucket>>;
105
+ //#endregion
106
+ export { defineChartSchema };
@@ -0,0 +1,47 @@
1
+ //#region src/core/define-chart-schema.ts
2
+ /**
3
+ * Define one explicit chart schema with strict exact-object checking.
4
+ *
5
+ * The schema is the single advanced authoring surface for chart-studio:
6
+ * `columns` can override or exclude inferred raw fields and also define derived
7
+ * columns, while the top-level control sections restrict the public chart
8
+ * contract.
9
+ *
10
+ * Typical shape:
11
+ *
12
+ * ```ts
13
+ * const schema = defineChartSchema<Row>()({
14
+ * columns: {
15
+ * createdAt: {type: 'date', label: 'Created'},
16
+ * revenue: {type: 'number', format: 'currency'},
17
+ * margin: {
18
+ * kind: 'derived',
19
+ * type: 'number',
20
+ * label: 'Margin',
21
+ * format: 'percent',
22
+ * accessor: row => row.profit / row.revenue,
23
+ * },
24
+ * },
25
+ * xAxis: {allowed: ['createdAt']},
26
+ * metric: {
27
+ * allowed: [{kind: 'aggregate', columnId: 'revenue', aggregate: 'sum'}],
28
+ * },
29
+ * })
30
+ * ```
31
+ */
32
+ function defineChartSchema() {
33
+ /**
34
+ * Brand one schema object while preserving its literal types.
35
+ *
36
+ * This is what lets the schema stay both strongly typed and editor-friendly
37
+ * when it is later passed to `useChart(...)`.
38
+ */
39
+ return function defineSchema(schema) {
40
+ return {
41
+ ...schema,
42
+ __chartSchemaBrand: "chart-schema-definition"
43
+ };
44
+ };
45
+ }
46
+ //#endregion
47
+ export { defineChartSchema };