@matthieumordrel/chart-studio 0.1.0

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 (160) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +371 -0
  3. package/dist/core/chart-capabilities.d.ts +60 -0
  4. package/dist/core/chart-capabilities.d.ts.map +1 -0
  5. package/dist/core/chart-capabilities.js +55 -0
  6. package/dist/core/chart-capabilities.js.map +1 -0
  7. package/dist/core/colors.d.ts +25 -0
  8. package/dist/core/colors.d.ts.map +1 -0
  9. package/dist/core/colors.js +55 -0
  10. package/dist/core/colors.js.map +1 -0
  11. package/dist/core/config-utils.d.ts +43 -0
  12. package/dist/core/config-utils.d.ts.map +1 -0
  13. package/dist/core/config-utils.js +81 -0
  14. package/dist/core/config-utils.js.map +1 -0
  15. package/dist/core/date-utils.d.ts +29 -0
  16. package/dist/core/date-utils.d.ts.map +1 -0
  17. package/dist/core/date-utils.js +59 -0
  18. package/dist/core/date-utils.js.map +1 -0
  19. package/dist/core/define-chart-schema.d.ts +105 -0
  20. package/dist/core/define-chart-schema.d.ts.map +1 -0
  21. package/dist/core/define-chart-schema.js +45 -0
  22. package/dist/core/define-chart-schema.js.map +1 -0
  23. package/dist/core/formatting.d.ts +47 -0
  24. package/dist/core/formatting.d.ts.map +1 -0
  25. package/dist/core/formatting.js +397 -0
  26. package/dist/core/formatting.js.map +1 -0
  27. package/dist/core/index.d.ts +17 -0
  28. package/dist/core/index.d.ts.map +1 -0
  29. package/dist/core/index.js +13 -0
  30. package/dist/core/index.js.map +1 -0
  31. package/dist/core/infer-columns.d.ts +6 -0
  32. package/dist/core/infer-columns.d.ts.map +1 -0
  33. package/dist/core/infer-columns.js +513 -0
  34. package/dist/core/infer-columns.js.map +1 -0
  35. package/dist/core/metric-utils.d.ts +43 -0
  36. package/dist/core/metric-utils.d.ts.map +1 -0
  37. package/dist/core/metric-utils.js +142 -0
  38. package/dist/core/metric-utils.js.map +1 -0
  39. package/dist/core/pipeline-data-points.d.ts +23 -0
  40. package/dist/core/pipeline-data-points.d.ts.map +1 -0
  41. package/dist/core/pipeline-data-points.js +236 -0
  42. package/dist/core/pipeline-data-points.js.map +1 -0
  43. package/dist/core/pipeline-helpers.d.ts +38 -0
  44. package/dist/core/pipeline-helpers.d.ts.map +1 -0
  45. package/dist/core/pipeline-helpers.js +98 -0
  46. package/dist/core/pipeline-helpers.js.map +1 -0
  47. package/dist/core/pipeline.d.ts +70 -0
  48. package/dist/core/pipeline.d.ts.map +1 -0
  49. package/dist/core/pipeline.js +157 -0
  50. package/dist/core/pipeline.js.map +1 -0
  51. package/dist/core/types.d.ts +1109 -0
  52. package/dist/core/types.d.ts.map +1 -0
  53. package/dist/core/types.js +15 -0
  54. package/dist/core/types.js.map +1 -0
  55. package/dist/core/use-chart-options.d.ts +66 -0
  56. package/dist/core/use-chart-options.d.ts.map +1 -0
  57. package/dist/core/use-chart-options.js +5 -0
  58. package/dist/core/use-chart-options.js.map +1 -0
  59. package/dist/core/use-chart-resolvers.d.ts +14 -0
  60. package/dist/core/use-chart-resolvers.d.ts.map +1 -0
  61. package/dist/core/use-chart-resolvers.js +42 -0
  62. package/dist/core/use-chart-resolvers.js.map +1 -0
  63. package/dist/core/use-chart.d.ts +47 -0
  64. package/dist/core/use-chart.d.ts.map +1 -0
  65. package/dist/core/use-chart.js +266 -0
  66. package/dist/core/use-chart.js.map +1 -0
  67. package/dist/index.d.ts +36 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +36 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/ui/chart-axis-ticks.d.ts +35 -0
  72. package/dist/ui/chart-axis-ticks.d.ts.map +1 -0
  73. package/dist/ui/chart-axis-ticks.js +80 -0
  74. package/dist/ui/chart-axis-ticks.js.map +1 -0
  75. package/dist/ui/chart-canvas.d.ts +22 -0
  76. package/dist/ui/chart-canvas.d.ts.map +1 -0
  77. package/dist/ui/chart-canvas.js +338 -0
  78. package/dist/ui/chart-canvas.js.map +1 -0
  79. package/dist/ui/chart-context.d.ts +89 -0
  80. package/dist/ui/chart-context.d.ts.map +1 -0
  81. package/dist/ui/chart-context.js +129 -0
  82. package/dist/ui/chart-context.js.map +1 -0
  83. package/dist/ui/chart-date-range-badge.d.ts +14 -0
  84. package/dist/ui/chart-date-range-badge.d.ts.map +1 -0
  85. package/dist/ui/chart-date-range-badge.js +31 -0
  86. package/dist/ui/chart-date-range-badge.js.map +1 -0
  87. package/dist/ui/chart-date-range-panel.d.ts +25 -0
  88. package/dist/ui/chart-date-range-panel.d.ts.map +1 -0
  89. package/dist/ui/chart-date-range-panel.js +126 -0
  90. package/dist/ui/chart-date-range-panel.js.map +1 -0
  91. package/dist/ui/chart-date-range.d.ts +14 -0
  92. package/dist/ui/chart-date-range.d.ts.map +1 -0
  93. package/dist/ui/chart-date-range.js +38 -0
  94. package/dist/ui/chart-date-range.js.map +1 -0
  95. package/dist/ui/chart-debug.d.ts +10 -0
  96. package/dist/ui/chart-debug.d.ts.map +1 -0
  97. package/dist/ui/chart-debug.js +127 -0
  98. package/dist/ui/chart-debug.js.map +1 -0
  99. package/dist/ui/chart-dropdown.d.ts +35 -0
  100. package/dist/ui/chart-dropdown.d.ts.map +1 -0
  101. package/dist/ui/chart-dropdown.js +77 -0
  102. package/dist/ui/chart-dropdown.js.map +1 -0
  103. package/dist/ui/chart-filters-panel.d.ts +19 -0
  104. package/dist/ui/chart-filters-panel.d.ts.map +1 -0
  105. package/dist/ui/chart-filters-panel.js +47 -0
  106. package/dist/ui/chart-filters-panel.js.map +1 -0
  107. package/dist/ui/chart-filters.d.ts +12 -0
  108. package/dist/ui/chart-filters.d.ts.map +1 -0
  109. package/dist/ui/chart-filters.js +27 -0
  110. package/dist/ui/chart-filters.js.map +1 -0
  111. package/dist/ui/chart-group-by-selector.d.ts +8 -0
  112. package/dist/ui/chart-group-by-selector.d.ts.map +1 -0
  113. package/dist/ui/chart-group-by-selector.js +20 -0
  114. package/dist/ui/chart-group-by-selector.js.map +1 -0
  115. package/dist/ui/chart-metric-panel.d.ts +18 -0
  116. package/dist/ui/chart-metric-panel.d.ts.map +1 -0
  117. package/dist/ui/chart-metric-panel.js +119 -0
  118. package/dist/ui/chart-metric-panel.js.map +1 -0
  119. package/dist/ui/chart-metric-selector.d.ts +10 -0
  120. package/dist/ui/chart-metric-selector.d.ts.map +1 -0
  121. package/dist/ui/chart-metric-selector.js +28 -0
  122. package/dist/ui/chart-metric-selector.js.map +1 -0
  123. package/dist/ui/chart-select.d.ts +25 -0
  124. package/dist/ui/chart-select.d.ts.map +1 -0
  125. package/dist/ui/chart-select.js +36 -0
  126. package/dist/ui/chart-select.js.map +1 -0
  127. package/dist/ui/chart-source-switcher.d.ts +16 -0
  128. package/dist/ui/chart-source-switcher.d.ts.map +1 -0
  129. package/dist/ui/chart-source-switcher.js +32 -0
  130. package/dist/ui/chart-source-switcher.js.map +1 -0
  131. package/dist/ui/chart-time-bucket-selector.d.ts +9 -0
  132. package/dist/ui/chart-time-bucket-selector.d.ts.map +1 -0
  133. package/dist/ui/chart-time-bucket-selector.js +26 -0
  134. package/dist/ui/chart-time-bucket-selector.js.map +1 -0
  135. package/dist/ui/chart-toolbar-overflow.d.ts +29 -0
  136. package/dist/ui/chart-toolbar-overflow.d.ts.map +1 -0
  137. package/dist/ui/chart-toolbar-overflow.js +110 -0
  138. package/dist/ui/chart-toolbar-overflow.js.map +1 -0
  139. package/dist/ui/chart-toolbar.d.ts +45 -0
  140. package/dist/ui/chart-toolbar.d.ts.map +1 -0
  141. package/dist/ui/chart-toolbar.js +45 -0
  142. package/dist/ui/chart-toolbar.js.map +1 -0
  143. package/dist/ui/chart-type-selector.d.ts +8 -0
  144. package/dist/ui/chart-type-selector.d.ts.map +1 -0
  145. package/dist/ui/chart-type-selector.js +23 -0
  146. package/dist/ui/chart-type-selector.js.map +1 -0
  147. package/dist/ui/chart-x-axis-selector.d.ts +8 -0
  148. package/dist/ui/chart-x-axis-selector.d.ts.map +1 -0
  149. package/dist/ui/chart-x-axis-selector.js +15 -0
  150. package/dist/ui/chart-x-axis-selector.js.map +1 -0
  151. package/dist/ui/index.d.ts +25 -0
  152. package/dist/ui/index.d.ts.map +1 -0
  153. package/dist/ui/index.js +24 -0
  154. package/dist/ui/index.js.map +1 -0
  155. package/dist/ui/theme.css +62 -0
  156. package/dist/ui/toolbar-types.d.ts +43 -0
  157. package/dist/ui/toolbar-types.d.ts.map +1 -0
  158. package/dist/ui/toolbar-types.js +51 -0
  159. package/dist/ui/toolbar-types.js.map +1 -0
  160. package/package.json +76 -0
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Build the visible runtime option list after applying config restrictions.
3
+ *
4
+ * The pipeline is always:
5
+ * 1. start from runtime-valid options
6
+ * 2. if `allowed` exists, keep only allowed entries in declared order
7
+ * 3. if `hidden` exists, subtract hidden entries
8
+ *
9
+ * When `fallbackToBaseIfEmpty` is enabled, required controls can recover their
10
+ * base runtime options if the config leaves nothing selectable for the active
11
+ * source. This recovery is intentionally separate from default resolution.
12
+ */
13
+ function restrictConfiguredCollection(items, config, getKey, fallbackToBaseIfEmpty) {
14
+ const keyedItems = new Map(items.map(item => [getKey(item), item]));
15
+ const allowedKeys = config?.allowed;
16
+ const hiddenKeys = config?.hidden ? new Set(config.hidden) : undefined;
17
+ const orderedItems = allowedKeys
18
+ ? allowedKeys.flatMap(allowedKey => {
19
+ const match = keyedItems.get(allowedKey);
20
+ return match ? [match] : [];
21
+ })
22
+ : [...items];
23
+ const visibleItems = hiddenKeys
24
+ ? orderedItems.filter(item => !hiddenKeys.has(getKey(item)))
25
+ : orderedItems;
26
+ if (fallbackToBaseIfEmpty && visibleItems.length === 0) {
27
+ return [...items];
28
+ }
29
+ return visibleItems;
30
+ }
31
+ /**
32
+ * Restrict an ID-keyed option list with `allowed`/`hidden`.
33
+ *
34
+ * When `fallbackToBaseIfEmpty` is enabled, required controls keep their base
35
+ * runtime options even if the config does not match the active source.
36
+ */
37
+ export function restrictConfiguredIdOptions(options, config, fallbackToBaseIfEmpty = false) {
38
+ return restrictConfiguredCollection(options, config, option => option.id, fallbackToBaseIfEmpty);
39
+ }
40
+ /**
41
+ * Resolve one ID-based selection against the current option list.
42
+ */
43
+ export function resolveConfiguredIdSelection(currentValue, options, configuredDefault, fallbackValue, preferFirstAvailable = true) {
44
+ if (currentValue && options.some(option => option.id === currentValue)) {
45
+ return currentValue;
46
+ }
47
+ if (configuredDefault && options.some(option => option.id === configuredDefault)) {
48
+ return configuredDefault;
49
+ }
50
+ if (preferFirstAvailable) {
51
+ return options[0]?.id ?? fallbackValue;
52
+ }
53
+ return fallbackValue;
54
+ }
55
+ /**
56
+ * Restrict a primitive option list with `allowed`/`hidden`.
57
+ */
58
+ export function restrictConfiguredValues(values, config, fallbackToBaseIfEmpty = false) {
59
+ return restrictConfiguredCollection(values, config, value => value, fallbackToBaseIfEmpty);
60
+ }
61
+ /**
62
+ * Resolve one primitive selection against the current option list.
63
+ */
64
+ export function resolveConfiguredValue(currentValue, values, configuredDefault) {
65
+ if (values.includes(currentValue)) {
66
+ return currentValue;
67
+ }
68
+ if (configuredDefault && values.includes(configuredDefault)) {
69
+ return configuredDefault;
70
+ }
71
+ return values[0] ?? currentValue;
72
+ }
73
+ /**
74
+ * Ordered time buckets exposed by the headless API.
75
+ */
76
+ export const TIME_BUCKET_ORDER = ['day', 'week', 'month', 'quarter', 'year'];
77
+ /**
78
+ * Ordered chart types exposed by the headless API.
79
+ */
80
+ export const CHART_TYPE_ORDER = ['bar', 'line', 'area', 'pie', 'donut'];
81
+ //# sourceMappingURL=config-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-utils.js","sourceRoot":"","sources":["../../src/core/config-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Date range utilities for chart-studio.
3
+ *
4
+ * Pure functions for filtering data by date range and computing
5
+ * the min/max date range from a dataset.
6
+ */
7
+ import type { DateColumn, DateRangeFilter } from './types.js';
8
+ /**
9
+ * Filter data by a date range on a specific date column.
10
+ * Both bounds are inclusive (to is extended to end of day).
11
+ *
12
+ * @param data - Raw data items
13
+ * @param dateColumn - The date column to filter on
14
+ * @param filter - Date range filter with from/to bounds
15
+ * @returns Filtered data items within the date range
16
+ */
17
+ export declare function filterByDateRange<T>(data: readonly T[], dateColumn: DateColumn<T>, filter: DateRangeFilter): T[];
18
+ /**
19
+ * Compute the min/max date range from data for a given date column.
20
+ *
21
+ * @param data - Data items to scan
22
+ * @param dateColumn - The date column to extract dates from
23
+ * @returns Object with min and max dates (both null if no valid dates)
24
+ */
25
+ export declare function computeDateRange<T>(data: readonly T[], dateColumn: DateColumn<T>): {
26
+ min: Date | null;
27
+ max: Date | null;
28
+ };
29
+ //# sourceMappingURL=date-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-utils.d.ts","sourceRoot":"","sources":["../../src/core/date-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAE,eAAe,EAAC,MAAM,YAAY,CAAA;AAE3D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,EACzB,MAAM,EAAE,eAAe,GACtB,CAAC,EAAE,CAeL;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GACxB;IAAC,GAAG,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,IAAI,GAAG,IAAI,CAAA;CAAC,CActC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Date range utilities for chart-studio.
3
+ *
4
+ * Pure functions for filtering data by date range and computing
5
+ * the min/max date range from a dataset.
6
+ */
7
+ /**
8
+ * Filter data by a date range on a specific date column.
9
+ * Both bounds are inclusive (to is extended to end of day).
10
+ *
11
+ * @param data - Raw data items
12
+ * @param dateColumn - The date column to filter on
13
+ * @param filter - Date range filter with from/to bounds
14
+ * @returns Filtered data items within the date range
15
+ */
16
+ export function filterByDateRange(data, dateColumn, filter) {
17
+ const { from, to } = filter;
18
+ if (!from && !to)
19
+ return [...data];
20
+ const toEnd = to ? new Date(to.getFullYear(), to.getMonth(), to.getDate(), 23, 59, 59, 999) : null;
21
+ return data.filter((item) => {
22
+ const raw = dateColumn.accessor(item);
23
+ if (raw == null)
24
+ return false;
25
+ const d = new Date(raw);
26
+ if (Number.isNaN(d.getTime()))
27
+ return false;
28
+ if (from && d < from)
29
+ return false;
30
+ if (toEnd && d > toEnd)
31
+ return false;
32
+ return true;
33
+ });
34
+ }
35
+ /**
36
+ * Compute the min/max date range from data for a given date column.
37
+ *
38
+ * @param data - Data items to scan
39
+ * @param dateColumn - The date column to extract dates from
40
+ * @returns Object with min and max dates (both null if no valid dates)
41
+ */
42
+ export function computeDateRange(data, dateColumn) {
43
+ let min = null;
44
+ let max = null;
45
+ for (const item of data) {
46
+ const raw = dateColumn.accessor(item);
47
+ if (raw == null)
48
+ continue;
49
+ const d = new Date(raw);
50
+ if (Number.isNaN(d.getTime()))
51
+ continue;
52
+ if (!min || d < min)
53
+ min = d;
54
+ if (!max || d > max)
55
+ max = d;
56
+ }
57
+ return { min, max };
58
+ }
59
+ //# sourceMappingURL=date-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-utils.js","sourceRoot":"","sources":["../../src/core/date-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAkB,EAClB,UAAyB,EACzB,MAAuB;IAEvB,MAAM,EAAC,IAAI,EAAE,EAAE,EAAC,GAAG,MAAM,CAAA;IACzB,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;IAElC,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAElG,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC1B,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACrC,IAAI,GAAG,IAAI,IAAI;YAAE,OAAO,KAAK,CAAA;QAC7B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAA6B,CAAC,CAAA;QACjD,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,KAAK,CAAA;QAC3C,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI;YAAE,OAAO,KAAK,CAAA;QAClC,IAAI,KAAK,IAAI,CAAC,GAAG,KAAK;YAAE,OAAO,KAAK,CAAA;QACpC,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAkB,EAClB,UAAyB;IAEzB,IAAI,GAAG,GAAgB,IAAI,CAAA;IAC3B,IAAI,GAAG,GAAgB,IAAI,CAAA;IAE3B,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACrC,IAAI,GAAG,IAAI,IAAI;YAAE,SAAQ;QACzB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAA6B,CAAC,CAAA;QACjD,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAAE,SAAQ;QACvC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG;YAAE,GAAG,GAAG,CAAC,CAAA;QAC5B,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG;YAAE,GAAG,GAAG,CAAC,CAAA;IAC9B,CAAC;IAED,OAAO,EAAC,GAAG,EAAE,GAAG,EAAC,CAAA;AACnB,CAAC"}
@@ -0,0 +1,105 @@
1
+ import type { ChartTypeConfig, DefinedChartSchema, ExactShape, FiltersConfig, GroupByConfig, MetricConfig, ResolvedFilterColumnIdFromSchema, ResolvedGroupByColumnIdFromSchema, ResolvedMetricColumnIdFromSchema, ResolvedXAxisColumnIdFromSchema, SchemaColumnsValidationShape, TimeBucketConfig, XAxisConfig } from './types.js';
2
+ type SchemaFromSections<T, TColumns extends Record<string, unknown> | undefined, TXAxis, TGroupBy, TFilters, TMetric, TChartType, TTimeBucket> = {
3
+ columns?: Extract<TColumns, Record<string, unknown> | undefined>;
4
+ xAxis?: Extract<TXAxis, XAxisConfig<ResolvedXAxisColumnIdFromSchema<T, {
5
+ columns?: TColumns;
6
+ }>> | undefined>;
7
+ groupBy?: Extract<TGroupBy, GroupByConfig<ResolvedGroupByColumnIdFromSchema<T, {
8
+ columns?: TColumns;
9
+ }>> | undefined>;
10
+ filters?: Extract<TFilters, FiltersConfig<ResolvedFilterColumnIdFromSchema<T, {
11
+ columns?: TColumns;
12
+ }>> | undefined>;
13
+ metric?: Extract<TMetric, MetricConfig<ResolvedMetricColumnIdFromSchema<T, {
14
+ columns?: TColumns;
15
+ }>> | undefined>;
16
+ chartType?: Extract<TChartType, ChartTypeConfig | undefined>;
17
+ timeBucket?: Extract<TTimeBucket, TimeBucketConfig | undefined>;
18
+ };
19
+ type DefineChartSchemaInput<T, TColumns extends Record<string, unknown> | undefined, TXAxis, TGroupBy, TFilters, TMetric, TChartType, TTimeBucket> = {
20
+ /**
21
+ * Shape the available chart columns.
22
+ *
23
+ * This is usually the most important part of the schema. Use it to:
24
+ * - rename inferred raw fields with `label`
25
+ * - force a field to a specific `type`
26
+ * - apply `format` or `formatter`
27
+ * - remove a raw field with `false`
28
+ * - add brand new derived columns with `kind: 'derived'`
29
+ */
30
+ columns?: TColumns & ExactShape<SchemaColumnsValidationShape<T, NoInfer<TColumns>>, NoInfer<TColumns>>;
31
+ /**
32
+ * Restrict which resolved columns may be selected on the X-axis.
33
+ *
34
+ * Use this when you want to expose only a subset of possible X-axis fields.
35
+ */
36
+ xAxis?: TXAxis & ExactShape<XAxisConfig<ResolvedXAxisColumnIdFromSchema<T, {
37
+ columns?: TColumns;
38
+ }>>, NoInfer<TXAxis>>;
39
+ /**
40
+ * Restrict which resolved columns may be used to split the chart into series.
41
+ *
42
+ * This powers grouped / multi-series charts.
43
+ */
44
+ groupBy?: TGroupBy & ExactShape<GroupByConfig<ResolvedGroupByColumnIdFromSchema<T, {
45
+ columns?: TColumns;
46
+ }>>, NoInfer<TGroupBy>>;
47
+ /**
48
+ * Restrict which resolved columns appear in the filters UI.
49
+ *
50
+ * Only category and boolean-like columns are eligible here.
51
+ */
52
+ filters?: TFilters & ExactShape<FiltersConfig<ResolvedFilterColumnIdFromSchema<T, {
53
+ columns?: TColumns;
54
+ }>>, NoInfer<TFilters>>;
55
+ /**
56
+ * Restrict which metrics and aggregate combinations remain selectable.
57
+ *
58
+ * Use this when you want to curate the metric dropdown rather than exposing
59
+ * every available numeric aggregate.
60
+ */
61
+ metric?: TMetric & ExactShape<MetricConfig<ResolvedMetricColumnIdFromSchema<T, {
62
+ columns?: TColumns;
63
+ }>>, NoInfer<TMetric>>;
64
+ /** Restrict which chart renderers are available to the user. */
65
+ chartType?: TChartType & ExactShape<ChartTypeConfig, NoInfer<TChartType>>;
66
+ /**
67
+ * Restrict which time buckets remain available for date X-axes.
68
+ *
69
+ * Example: allow only `'month'` and `'quarter'`.
70
+ */
71
+ timeBucket?: TTimeBucket & ExactShape<TimeBucketConfig, NoInfer<TTimeBucket>>;
72
+ };
73
+ /**
74
+ * Define one explicit chart schema with strict exact-object checking.
75
+ *
76
+ * The schema is the single advanced authoring surface for chart-studio:
77
+ * `columns` can override or exclude inferred raw fields and also define derived
78
+ * columns, while the top-level control sections restrict the public chart
79
+ * contract.
80
+ *
81
+ * Typical shape:
82
+ *
83
+ * ```ts
84
+ * const schema = defineChartSchema<Row>()({
85
+ * columns: {
86
+ * createdAt: {type: 'date', label: 'Created'},
87
+ * revenue: {type: 'number', format: 'currency'},
88
+ * margin: {
89
+ * kind: 'derived',
90
+ * type: 'number',
91
+ * label: 'Margin',
92
+ * format: 'percent',
93
+ * accessor: row => row.profit / row.revenue,
94
+ * },
95
+ * },
96
+ * xAxis: {allowed: ['createdAt']},
97
+ * metric: {
98
+ * allowed: [{kind: 'aggregate', columnId: 'revenue', aggregate: 'sum'}],
99
+ * },
100
+ * })
101
+ * ```
102
+ */
103
+ export 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>>;
104
+ export {};
105
+ //# sourceMappingURL=define-chart-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-chart-schema.d.ts","sourceRoot":"","sources":["../../src/core/define-chart-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Define one explicit chart schema with strict exact-object checking.
3
+ *
4
+ * The schema is the single advanced authoring surface for chart-studio:
5
+ * `columns` can override or exclude inferred raw fields and also define derived
6
+ * columns, while the top-level control sections restrict the public chart
7
+ * contract.
8
+ *
9
+ * Typical shape:
10
+ *
11
+ * ```ts
12
+ * const schema = defineChartSchema<Row>()({
13
+ * columns: {
14
+ * createdAt: {type: 'date', label: 'Created'},
15
+ * revenue: {type: 'number', format: 'currency'},
16
+ * margin: {
17
+ * kind: 'derived',
18
+ * type: 'number',
19
+ * label: 'Margin',
20
+ * format: 'percent',
21
+ * accessor: row => row.profit / row.revenue,
22
+ * },
23
+ * },
24
+ * xAxis: {allowed: ['createdAt']},
25
+ * metric: {
26
+ * allowed: [{kind: 'aggregate', columnId: 'revenue', aggregate: 'sum'}],
27
+ * },
28
+ * })
29
+ * ```
30
+ */
31
+ export function defineChartSchema() {
32
+ /**
33
+ * Brand one schema object while preserving its literal types.
34
+ *
35
+ * This is what lets the schema stay both strongly typed and editor-friendly
36
+ * when it is later passed to `useChart(...)`.
37
+ */
38
+ return function defineSchema(schema) {
39
+ return {
40
+ ...schema,
41
+ __chartSchemaBrand: 'chart-schema-definition',
42
+ };
43
+ };
44
+ }
45
+ //# sourceMappingURL=define-chart-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-chart-schema.js","sourceRoot":"","sources":["../../src/core/define-chart-schema.ts"],"names":[],"mappings":"AAkGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,iBAAiB;IAC/B;;;;;OAKG;IACH,OAAO,SAAS,YAAY,CAS1B,MAAyG;QAKzG,OAAO;YACL,GAAG,MAAM;YACT,kBAAkB,EAAE,yBAAyB;SAI9C,CAAA;IACH,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { ChartColumn, ColumnFormat, TimeBucket } from './types.js';
2
+ /** Formatting surfaces exposed by the chart UI. */
3
+ export type ChartValueSurface = 'axis' | 'tooltip' | 'data-label' | 'raw';
4
+ /** Numeric extent used to choose sensible default precision. */
5
+ export type NumericRange = {
6
+ min: number;
7
+ max: number;
8
+ };
9
+ type FormatColumnLike<T> = {
10
+ type: ChartColumn<T>['type'];
11
+ format?: ColumnFormat;
12
+ formatter?: ChartColumn<T>['formatter'];
13
+ trueLabel?: string;
14
+ falseLabel?: string;
15
+ };
16
+ type FormatValueOptions<T> = {
17
+ column: FormatColumnLike<T>;
18
+ surface: ChartValueSurface;
19
+ timeBucket?: TimeBucket;
20
+ numericRange?: NumericRange | null;
21
+ locale?: string;
22
+ item?: T;
23
+ };
24
+ /**
25
+ * Build a numeric range from chart values.
26
+ */
27
+ export declare function createNumericRange(values: readonly number[]): NumericRange | null;
28
+ /**
29
+ * Decide whether an axis should keep decimal ticks for the current visible
30
+ * numeric values.
31
+ */
32
+ export declare function shouldAllowDecimalTicks(values: readonly number[]): boolean;
33
+ /**
34
+ * Format one chart value for a specific UI surface.
35
+ */
36
+ export declare function formatChartValue<T>(value: string | number | boolean | Date | null | undefined, options: FormatValueOptions<T>): string;
37
+ /**
38
+ * Format a date bucket label from the machine-friendly pipeline key.
39
+ */
40
+ export declare function formatTimeBucketLabel(key: string, bucket: TimeBucket, surface: ChartValueSurface, locale?: string): string;
41
+ /**
42
+ * Format the Y-axis or label width estimate with the same surface rules used in
43
+ * the visible chart.
44
+ */
45
+ export declare function formatNumericSurfaceValue(value: number, surface: ChartValueSurface, numericRange?: NumericRange | null, format?: ColumnFormat, formatter?: ChartColumn<unknown>['formatter'], locale?: string): string;
46
+ export {};
47
+ //# sourceMappingURL=formatting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../src/core/formatting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAE,YAAY,EAA2C,UAAU,EAAC,MAAM,YAAY,CAAA;AAE9G,mDAAmD;AACnD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,KAAK,CAAA;AAEzE,gEAAgE;AAChE,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAuBD,KAAK,gBAAgB,CAAC,CAAC,IAAI;IACzB,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IAC5B,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,SAAS,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,KAAK,kBAAkB,CAAC,CAAC,IAAI;IAC3B,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAC3B,OAAO,EAAE,iBAAiB,CAAA;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,CAAC,CAAA;CACT,CAAA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,GAAG,IAAI,CAcjF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAY1E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,EAC1D,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC7B,MAAM,CAyBR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,iBAAiB,EAC1B,MAAM,SAAU,GACf,MAAM,CAkBR;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,iBAAiB,EAC1B,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,EAClC,MAAM,CAAC,EAAE,YAAY,EACrB,SAAS,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,EAC7C,MAAM,SAAU,GACf,MAAM,CAWR"}