@matthieumordrel/chart-studio 0.2.0 → 0.2.2

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 +1 -1
  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
@@ -1,118 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
3
- import { ArrowDownToLine, ArrowUpToLine, Divide, Hash, Sigma } from 'lucide-react';
4
- import { DEFAULT_METRIC, isAggregateMetric } from '../core/metric-utils.js';
5
- import { useChartContext } from './chart-context.js';
6
- const AGGREGATE_OPTIONS = [
7
- { fn: 'sum', label: 'Sum', shortLabel: 'Sum', icon: _jsx(Sigma, { className: "h-3.5 w-3.5 shrink-0" }) },
8
- {
9
- fn: 'avg',
10
- label: 'Average',
11
- shortLabel: 'Avg',
12
- icon: _jsx(Divide, { className: "h-3.5 w-3.5 shrink-0" }),
13
- },
14
- {
15
- fn: 'min',
16
- label: 'Minimum',
17
- shortLabel: 'Min',
18
- icon: _jsx(ArrowDownToLine, { className: "h-3.5 w-3.5 shrink-0" }),
19
- },
20
- {
21
- fn: 'max',
22
- label: 'Maximum',
23
- shortLabel: 'Max',
24
- icon: _jsx(ArrowUpToLine, { className: "h-3.5 w-3.5 shrink-0" }),
25
- },
26
- ];
27
- /** Aggregates where the "Exclude zeros" toggle is relevant */
28
- const ZERO_TOGGLE_AGGREGATES = new Set(['avg', 'min', 'max']);
29
- // ---------------------------------------------------------------------------
30
- // Helpers
31
- // ---------------------------------------------------------------------------
32
- /**
33
- * Extract number columns from the chart column list.
34
- */
35
- function getNumberColumns(columns) {
36
- return columns.filter((column) => column.type === 'number');
37
- }
38
- /**
39
- * Group the allowed aggregate metrics by number column while preserving column order.
40
- */
41
- function getMetricColumnGroups(availableMetrics, columns) {
42
- const aggregateMap = new Map();
43
- for (const metric of availableMetrics) {
44
- if (metric.kind !== 'aggregate') {
45
- continue;
46
- }
47
- const aggregates = aggregateMap.get(metric.columnId) ?? new Set();
48
- aggregates.add(metric.aggregate);
49
- aggregateMap.set(metric.columnId, aggregates);
50
- }
51
- return getNumberColumns(columns)
52
- .filter(column => aggregateMap.has(column.id))
53
- .map(column => ({
54
- columnId: column.id,
55
- label: column.label,
56
- aggregates: [...(aggregateMap.get(column.id) ?? new Set())],
57
- }));
58
- }
59
- // ---------------------------------------------------------------------------
60
- // Sub-components
61
- // ---------------------------------------------------------------------------
62
- /** A single number column section with aggregate buttons + optional zero toggle. */
63
- function MetricColumnGroup({ group, isActiveColumn, activeAggregate, includeZeros, onSelectAggregate, onToggleZeros, }) {
64
- const isZeroToggleEnabled = isActiveColumn && activeAggregate !== null && ZERO_TOGGLE_AGGREGATES.has(activeAggregate);
65
- const isZeroToggleDisabled = isActiveColumn && activeAggregate === 'sum';
66
- return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: group.label }), isActiveColumn && (_jsxs("button", { onClick: isZeroToggleDisabled ? undefined : onToggleZeros, className: `flex items-center gap-1.5 text-[10px] transition-colors ${isZeroToggleDisabled
67
- ? 'cursor-not-allowed text-muted-foreground/30'
68
- : 'text-muted-foreground hover:text-foreground'}`, disabled: isZeroToggleDisabled, title: isZeroToggleDisabled
69
- ? 'Not applicable for Sum'
70
- : 'Exclude zero values from calculation', children: [_jsx("div", { className: `flex h-3 w-3 shrink-0 items-center justify-center rounded-sm border transition-colors ${isZeroToggleEnabled && !includeZeros
71
- ? 'border-primary bg-primary'
72
- : isZeroToggleDisabled
73
- ? 'border-muted-foreground/20'
74
- : 'border-muted-foreground/30'}`, children: isZeroToggleEnabled && !includeZeros && (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "8", height: "8", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) })) }), "Excl. zeros"] }))] }), _jsx("div", { className: "grid grid-cols-2 gap-1.5", children: AGGREGATE_OPTIONS.filter(opt => group.aggregates.includes(opt.fn)).map((opt) => {
75
- const isActive = isActiveColumn && activeAggregate === opt.fn;
76
- return (_jsxs("button", { onClick: () => onSelectAggregate(opt.fn), className: `inline-flex h-8 items-center justify-center gap-2 rounded-md border text-xs transition-colors ${isActive
77
- ? 'border-primary/50 bg-primary/10 font-medium text-primary'
78
- : 'border-transparent bg-muted/50 text-muted-foreground hover:bg-muted hover:text-foreground'}`, title: opt.label, children: [opt.icon, opt.shortLabel] }, opt.fn));
79
- }) })] }));
80
- }
81
- // ---------------------------------------------------------------------------
82
- // Main component
83
- // ---------------------------------------------------------------------------
84
- /**
85
- * Metric panel content (no popover wrapper).
86
- *
87
- * @property onClose - Optional callback when user makes a definitive selection (e.g. "Count")
88
- * @property className - Additional CSS classes
89
- */
90
- export function ChartMetricPanel({ onClose, className }) {
91
- const { metric, setMetric, columns, availableMetrics } = useChartContext();
92
- const countMetricEnabled = useMemo(() => availableMetrics.some(candidate => candidate.kind === 'count'), [availableMetrics]);
93
- const metricColumnGroups = useMemo(() => getMetricColumnGroups(availableMetrics, columns), [availableMetrics, columns]);
94
- const isCount = metric.kind === 'count';
95
- const includeZeros = isAggregateMetric(metric) ? (metric.includeZeros ?? true) : true;
96
- const handleSelectCount = () => {
97
- if (!countMetricEnabled) {
98
- return;
99
- }
100
- setMetric(DEFAULT_METRIC);
101
- onClose?.();
102
- };
103
- const handleSelectAggregate = (columnId, fn) => {
104
- setMetric({
105
- kind: 'aggregate',
106
- columnId,
107
- aggregate: fn,
108
- includeZeros: isAggregateMetric(metric) && metric.columnId === columnId ? includeZeros : true,
109
- });
110
- };
111
- const handleToggleZeros = () => {
112
- if (!isAggregateMetric(metric)) {
113
- return;
114
- }
115
- setMetric({ ...metric, includeZeros: !includeZeros });
116
- };
117
- return (_jsxs("div", { className: className, children: [countMetricEnabled && (_jsxs("button", { onClick: handleSelectCount, className: `flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-xs transition-colors ${isCount ? 'bg-primary/10 font-medium text-primary' : 'text-foreground hover:bg-muted'}`, children: [_jsx("div", { className: `flex h-6 w-6 items-center justify-center rounded-md ${isCount ? 'bg-primary/15 text-primary' : 'bg-muted text-muted-foreground'}`, children: _jsx(Hash, { className: "h-3.5 w-3.5" }) }), _jsxs("div", { children: [_jsx("div", { className: "font-medium", children: "Count" }), _jsx("div", { className: "text-[10px] text-muted-foreground", children: "Number of items" })] })] })), countMetricEnabled && metricColumnGroups.length > 0 && _jsx("div", { className: "my-4 border-t border-border" }), _jsx("div", { className: "space-y-4", children: metricColumnGroups.map((group) => (_jsx(MetricColumnGroup, { group: group, isActiveColumn: isAggregateMetric(metric) && metric.columnId === group.columnId, activeAggregate: isAggregateMetric(metric) && metric.columnId === group.columnId ? metric.aggregate : null, includeZeros: includeZeros, onSelectAggregate: (fn) => handleSelectAggregate(group.columnId, fn), onToggleZeros: handleToggleZeros }, group.columnId))) })] }));
118
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Metric selector — trigger button + popover wrapping ChartMetricPanel.
3
- *
4
- * Follows the same dropdown pattern as ChartFilters / ChartDateRange.
5
- */
6
- /** Styled popover to select the Y-axis metric with grouped aggregate buttons. */
7
- export declare function ChartMetricSelector({ className }: {
8
- className?: string;
9
- }): import("react/jsx-runtime").JSX.Element | null;
10
- //# sourceMappingURL=chart-metric-selector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-metric-selector.d.ts","sourceRoot":"","sources":["../../src/ui/chart-metric-selector.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,EAAC,SAAS,EAAC,EAAE;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,kDAiDpE"}
@@ -1,27 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Metric selector — trigger button + popover wrapping ChartMetricPanel.
4
- *
5
- * Follows the same dropdown pattern as ChartFilters / ChartDateRange.
6
- */
7
- import { useRef, useState } from 'react';
8
- import { ChevronDown, TrendingUpDown } from 'lucide-react';
9
- import { getMetricLabel, isAggregateMetric } from '../core/metric-utils.js';
10
- import { useChartContext } from './chart-context.js';
11
- import { ChartDropdownPanel } from './chart-dropdown.js';
12
- import { ChartMetricPanel } from './chart-metric-panel.js';
13
- /** Styled popover to select the Y-axis metric with grouped aggregate buttons. */
14
- export function ChartMetricSelector({ className }) {
15
- const { metric, availableMetrics, columns } = useChartContext();
16
- const [isOpen, setIsOpen] = useState(false);
17
- const triggerRef = useRef(null);
18
- if (availableMetrics.length <= 1)
19
- return null;
20
- const isCount = metric.kind === 'count';
21
- const isActive = !isCount;
22
- const includeZeros = isAggregateMetric(metric) ? (metric.includeZeros ?? true) : true;
23
- const label = getMetricLabel(metric, columns);
24
- return (_jsxs("div", { className: className, children: [_jsxs("button", { ref: triggerRef, onClick: () => setIsOpen(!isOpen), className: `inline-flex h-7 items-center gap-1.5 rounded-lg border px-2.5 text-xs font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20 ${isActive
25
- ? 'border-primary/30 bg-primary/5 text-primary shadow-sm shadow-primary/5 hover:bg-primary/8'
26
- : 'border-border/50 bg-background text-muted-foreground shadow-sm hover:border-border hover:bg-muted/30 hover:shadow hover:text-foreground'}`, "aria-label": "Metric", children: [_jsx(TrendingUpDown, { className: "h-3 w-3" }), _jsx("span", { children: label }), isActive && !includeZeros && (_jsx("span", { className: "rounded bg-muted px-1 py-px text-[9px] font-normal text-muted-foreground", children: "excl. 0" })), _jsx(ChevronDown, { className: `h-3 w-3 text-muted-foreground/50 transition-transform ${isOpen ? 'rotate-180' : ''}` })] }), _jsx(ChartDropdownPanel, { isOpen: isOpen, onClose: () => setIsOpen(false), triggerRef: triggerRef, width: 288, className: "p-4", children: _jsx(ChartMetricPanel, { onClose: () => setIsOpen(false) }) })] }));
27
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * Custom select dropdown — premium replacement for native <select> elements.
3
- * Uses fixed positioning so the options list works correctly even inside
4
- * overflow-hidden containers (e.g. the toolbar overflow panel).
5
- */
6
- /**
7
- * Premium styled select dropdown with highlight-only selection styling.
8
- *
9
- * @property value - Currently selected value
10
- * @property options - Array of { value, label } options
11
- * @property onChange - Callback when selection changes
12
- * @property ariaLabel - Accessible label for the trigger
13
- * @property className - Additional CSS classes
14
- */
15
- export declare function ChartSelect<T extends string>({ value, options, onChange, ariaLabel, className, }: {
16
- value: T;
17
- options: ReadonlyArray<{
18
- value: T;
19
- label: string;
20
- }>;
21
- onChange: (value: T) => void;
22
- ariaLabel?: string;
23
- className?: string;
24
- }): import("react/jsx-runtime").JSX.Element;
25
- //# sourceMappingURL=chart-select.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-select.d.ts","sourceRoot":"","sources":["../../src/ui/chart-select.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,EAC5C,KAAK,EACL,OAAO,EACP,QAAQ,EACR,SAAS,EACT,SAAS,GACV,EAAE;IACD,KAAK,EAAE,CAAC,CAAA;IACR,OAAO,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,CAAA;IACjD,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,2CAuDA"}
@@ -1,35 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Custom select dropdown — premium replacement for native <select> elements.
4
- * Uses fixed positioning so the options list works correctly even inside
5
- * overflow-hidden containers (e.g. the toolbar overflow panel).
6
- */
7
- import { useRef, useState } from 'react';
8
- import { ChevronDown } from 'lucide-react';
9
- import { ChartDropdownPanel } from './chart-dropdown.js';
10
- /**
11
- * Premium styled select dropdown with highlight-only selection styling.
12
- *
13
- * @property value - Currently selected value
14
- * @property options - Array of { value, label } options
15
- * @property onChange - Callback when selection changes
16
- * @property ariaLabel - Accessible label for the trigger
17
- * @property className - Additional CSS classes
18
- */
19
- export function ChartSelect({ value, options, onChange, ariaLabel, className, }) {
20
- const [isOpen, setIsOpen] = useState(false);
21
- const triggerRef = useRef(null);
22
- const selected = options.find((o) => o.value === value);
23
- /** Toggle the dropdown. */
24
- const handleToggle = () => {
25
- setIsOpen((current) => !current);
26
- };
27
- /** Select an option and close the dropdown. */
28
- const handleSelect = (optionValue) => {
29
- onChange(optionValue);
30
- setIsOpen(false);
31
- };
32
- return (_jsxs("div", { className: className, children: [_jsxs("button", { ref: triggerRef, onClick: handleToggle, className: "inline-flex h-7 items-center gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 text-xs font-medium text-foreground shadow-sm transition-all hover:border-border hover:bg-muted/30 hover:shadow focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20", "aria-label": ariaLabel, children: [_jsx("span", { className: "truncate", children: selected?.label ?? value }), _jsx(ChevronDown, { className: `h-3 w-3 shrink-0 text-muted-foreground/60 transition-transform ${isOpen ? 'rotate-180' : ''}` })] }), _jsx(ChartDropdownPanel, { isOpen: isOpen, onClose: () => setIsOpen(false), triggerRef: triggerRef, minWidth: "trigger", className: "p-1", children: options.map((option) => (_jsx("button", { onClick: () => handleSelect(option.value), className: `flex w-full items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs transition-colors ${option.value === value
33
- ? 'bg-primary/8 font-medium text-primary'
34
- : 'text-foreground hover:bg-muted/60'}`, children: _jsx("span", { className: "truncate", children: option.label }) }, option.value))) })] }));
35
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-source-switcher.d.ts","sourceRoot":"","sources":["../../src/ui/chart-source-switcher.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAAC,SAAS,EAAC,EAAE;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,2CA+BpE"}
@@ -1,31 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Data source control — adapts based on single vs multi-source.
4
- *
5
- * Single source: read-only badge showing source label + record count.
6
- * Multi source: dropdown to switch between data sources.
7
- */
8
- import { Database } from 'lucide-react';
9
- import { useChartContext } from './chart-context.js';
10
- import { ChartSelect } from './chart-select.js';
11
- /** Format a number with locale-aware separators (e.g. 1,247). */
12
- function formatCount(n) {
13
- return n.toLocaleString('en-US');
14
- }
15
- /**
16
- * Data source display/switcher.
17
- *
18
- * - Single source → read-only badge: "[icon] Jobs · 1,247 records"
19
- * - Multi source → dropdown to switch between sources
20
- */
21
- export function ChartSourceSwitcher({ className }) {
22
- const { hasMultipleSources, sources, activeSourceId, setActiveSource, recordCount } = useChartContext();
23
- // Single source — read-only info badge
24
- if (!hasMultipleSources) {
25
- const label = sources[0]?.label ?? 'Unnamed Source';
26
- return (_jsxs("div", { className: `inline-flex items-center gap-1.5 whitespace-nowrap text-xs text-muted-foreground ${className ?? ''}`, children: [_jsx(Database, { className: "h-3 w-3 shrink-0" }), _jsx("span", { className: "font-medium text-foreground", children: label }), _jsx("span", { className: "text-muted-foreground/40", children: "\u00B7" }), _jsxs("span", { children: [formatCount(recordCount), " records"] })] }));
27
- }
28
- // Multi source — dropdown select
29
- const options = sources.map((source) => ({ value: source.id, label: `Source: ${source.label}` }));
30
- return (_jsx(ChartSelect, { value: activeSourceId, options: options, onChange: (v) => setActiveSource(v), ariaLabel: "Data source", className: className }));
31
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * Time bucket selector — premium custom dropdown.
3
- * Only renders when the X-axis is a date column.
4
- */
5
- /** Custom dropdown to select time granularity. */
6
- export declare function ChartTimeBucketSelector({ className }: {
7
- className?: string;
8
- }): import("react/jsx-runtime").JSX.Element | null;
9
- //# sourceMappingURL=chart-time-bucket-selector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-time-bucket-selector.d.ts","sourceRoot":"","sources":["../../src/ui/chart-time-bucket-selector.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,kDAAkD;AAClD,wBAAgB,uBAAuB,CAAC,EAAC,SAAS,EAAC,EAAE;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,kDAkBxE"}
@@ -1,25 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * Time bucket selector — premium custom dropdown.
4
- * Only renders when the X-axis is a date column.
5
- */
6
- import { CHART_TYPE_CONFIG } from '../core/chart-capabilities.js';
7
- import { useChartContext } from './chart-context.js';
8
- import { ChartSelect } from './chart-select.js';
9
- /** Labels for each time bucket. */
10
- const BUCKET_LABELS = {
11
- day: 'Day',
12
- week: 'Week',
13
- month: 'Month',
14
- quarter: 'Quarter',
15
- year: 'Year',
16
- };
17
- /** Custom dropdown to select time granularity. */
18
- export function ChartTimeBucketSelector({ className }) {
19
- const { chartType, isTimeSeries, timeBucket, setTimeBucket, availableTimeBuckets } = useChartContext();
20
- if (!isTimeSeries || !CHART_TYPE_CONFIG[chartType].supportsTimeBucketing || availableTimeBuckets.length === 0) {
21
- return null;
22
- }
23
- const options = availableTimeBuckets.map((bucket) => ({ value: bucket, label: BUCKET_LABELS[bucket] }));
24
- return (_jsx(ChartSelect, { value: timeBucket, options: options, onChange: setTimeBucket, ariaLabel: "Time granularity", className: className }));
25
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * Overflow menu for toolbar controls — Notion-inspired configuration panel.
3
- *
4
- * Renders an ellipsis button that opens a panel with all non-pinned controls.
5
- * Simple controls (selects, toggle buttons) render inline in rows.
6
- * Complex controls (metric, filters, date range) show as clickable rows that
7
- * navigate to a full-page detail view within the panel (Notion-style drill-down).
8
- */
9
- import type { ControlId } from './toolbar-types.js';
10
- /**
11
- * Props for ChartToolbarOverflow.
12
- *
13
- * @property pinned - Controls shown outside the overflow (excluded from menu)
14
- * @property hidden - Controls completely hidden everywhere
15
- * @property className - Additional CSS classes
16
- */
17
- type ChartToolbarOverflowProps = {
18
- pinned: ReadonlySet<ControlId>;
19
- hidden: ReadonlySet<ControlId>;
20
- className?: string;
21
- };
22
- /**
23
- * Ellipsis overflow menu with Notion-style drill-down navigation.
24
- * Main view shows all controls. Clicking a complex control replaces
25
- * the panel content with that control's detail page + back button.
26
- */
27
- export declare function ChartToolbarOverflow({ pinned, hidden, className }: ChartToolbarOverflowProps): import("react/jsx-runtime").JSX.Element | null;
28
- export {};
29
- //# sourceMappingURL=chart-toolbar-overflow.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-toolbar-overflow.d.ts","sourceRoot":"","sources":["../../src/ui/chart-toolbar-overflow.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,OAAO,KAAK,EAAC,SAAS,EAAiB,MAAM,oBAAoB,CAAA;AAMjE;;;;;;GAMG;AACH,KAAK,yBAAyB,GAAG;IAC/B,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,CAAA;IAC9B,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAC,EAAE,yBAAyB,kDAgE1F"}
@@ -1,109 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- /**
3
- * Overflow menu for toolbar controls — Notion-inspired configuration panel.
4
- *
5
- * Renders an ellipsis button that opens a panel with all non-pinned controls.
6
- * Simple controls (selects, toggle buttons) render inline in rows.
7
- * Complex controls (metric, filters, date range) show as clickable rows that
8
- * navigate to a full-page detail view within the panel (Notion-style drill-down).
9
- */
10
- import { useRef, useState } from 'react';
11
- import { ArrowLeft, ChevronRight, Ellipsis, Eraser } from 'lucide-react';
12
- import { getMetricLabel } from '../core/metric-utils.js';
13
- import { useChartContext } from './chart-context.js';
14
- import { ChartDropdownPanel } from './chart-dropdown.js';
15
- import { ChartDateRangePanel, resolvePresetLabel } from './chart-date-range-panel.js';
16
- import { ChartFiltersPanel } from './chart-filters-panel.js';
17
- import { ChartMetricPanel } from './chart-metric-panel.js';
18
- import { CONTROL_IDS, CONTROL_REGISTRY, SECTIONS } from './toolbar-types.js';
19
- /** Controls that drill-down into a detail page instead of rendering inline. */
20
- const COMPLEX_CONTROLS = new Set(['metric', 'filters', 'dateRange']);
21
- /**
22
- * Ellipsis overflow menu with Notion-style drill-down navigation.
23
- * Main view shows all controls. Clicking a complex control replaces
24
- * the panel content with that control's detail page + back button.
25
- */
26
- export function ChartToolbarOverflow({ pinned, hidden, className }) {
27
- const [isOpen, setIsOpen] = useState(false);
28
- /** null = main menu, ControlId = detail page for that control */
29
- const [activePage, setActivePage] = useState(null);
30
- const triggerRef = useRef(null);
31
- // Collect overflow controls (not pinned, not hidden) grouped by section
32
- const sectionGroups = SECTIONS.map((section) => {
33
- const controls = CONTROL_IDS.filter((id) => {
34
- if (pinned.has(id) || hidden.has(id))
35
- return false;
36
- return CONTROL_REGISTRY[id].section === section.id;
37
- });
38
- return { section, controls };
39
- }).filter((g) => g.controls.length > 0);
40
- if (sectionGroups.length === 0)
41
- return null;
42
- const handleClose = () => {
43
- setIsOpen(false);
44
- setActivePage(null);
45
- };
46
- const handleToggle = () => {
47
- if (isOpen) {
48
- handleClose();
49
- return;
50
- }
51
- setIsOpen(true);
52
- };
53
- return (_jsxs("div", { className: className, children: [_jsx("button", { ref: triggerRef, onClick: handleToggle, className: `inline-flex h-7 w-7 items-center justify-center rounded-md border transition-colors ${isOpen
54
- ? 'border-primary/50 bg-primary/10 text-primary'
55
- : 'border-border bg-background text-muted-foreground hover:bg-muted hover:text-foreground'}`, "aria-label": "Chart settings", children: _jsx(Ellipsis, { className: "h-4 w-4" }) }), _jsx(ChartDropdownPanel, { isOpen: isOpen, onClose: handleClose, triggerRef: triggerRef, align: "right", width: 320, repositionKey: activePage ?? 'main', className: "flex min-h-[280px] max-h-[min(480px,80vh)] flex-col", children: activePage === null ? (_jsx(MainMenu, { sectionGroups: sectionGroups, onNavigate: setActivePage })) : (_jsx(DetailPage, { controlId: activePage, onBack: () => setActivePage(null) })) })] }));
56
- }
57
- // ---------------------------------------------------------------------------
58
- // Main menu view
59
- // ---------------------------------------------------------------------------
60
- /** Main menu showing all controls organized by section. */
61
- function MainMenu({ sectionGroups, onNavigate, }) {
62
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "border-b border-border px-4 py-3", children: [_jsx("div", { className: "text-xs font-semibold text-foreground", children: "Chart configuration" }), _jsx("div", { className: "mt-0.5 text-[10px] text-muted-foreground", children: "Customize how your data is displayed" })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-2", onWheel: (e) => e.stopPropagation(), children: sectionGroups.map(({ section, controls }, groupIdx) => (_jsxs("div", { children: [groupIdx > 0 && _jsx("div", { className: "mx-2 my-1.5 border-t border-border" }), _jsxs("div", { className: "px-2 pb-1 pt-2", children: [_jsx("div", { className: "mb-2 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children: section.label }), _jsx("div", { className: "space-y-1", children: controls.map((id) => COMPLEX_CONTROLS.has(id) ? (_jsx(ComplexControlRow, { controlId: id, onNavigate: () => onNavigate(id) }, id)) : (_jsx(SimpleControlRow, { controlId: id }, id))) })] })] }, section.id))) })] }));
63
- }
64
- // ---------------------------------------------------------------------------
65
- // Detail page view (drill-down)
66
- // ---------------------------------------------------------------------------
67
- /** Full-page detail view for a complex control, with back navigation. */
68
- function DetailPage({ controlId, onBack }) {
69
- const entry = CONTROL_REGISTRY[controlId];
70
- const { filters, clearAllFilters } = useChartContext();
71
- const filterActiveCount = controlId === 'filters' ? [...filters.values()].reduce((sum, set) => sum + set.size, 0) : 0;
72
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2.5", children: [_jsx("button", { onClick: onBack, className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", "aria-label": "Back", children: _jsx(ArrowLeft, { className: "h-3.5 w-3.5" }) }), controlId === 'filters' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "min-w-0 flex-1 truncate text-xs font-semibold text-foreground", children: [filterActiveCount > 0 && (_jsxs("span", { className: "text-muted-foreground", children: [filterActiveCount, " filter", filterActiveCount !== 1 ? 's' : '', " active \u00B7", ' '] })), "Filters"] }), filterActiveCount > 0 && (_jsx("button", { onClick: () => clearAllFilters(), className: "shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", "aria-label": "Clear all filters", children: _jsx(Eraser, { className: "h-3.5 w-3.5" }) }))] })) : (_jsx("div", { className: "text-xs font-semibold text-foreground", children: entry.label }))] }), _jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-3", onWheel: (e) => e.stopPropagation(), children: [controlId === 'metric' && _jsx(ChartMetricPanel, {}), controlId === 'filters' && _jsx(ChartFiltersPanel, { showHeader: false }), controlId === 'dateRange' && _jsx(ChartDateRangePanel, {})] })] }));
73
- }
74
- // ---------------------------------------------------------------------------
75
- // Control rows
76
- // ---------------------------------------------------------------------------
77
- /**
78
- * A simple control row — label on the left, component on the right.
79
- * Used for selects and toggle buttons that work inline without popovers.
80
- */
81
- function SimpleControlRow({ controlId }) {
82
- const entry = CONTROL_REGISTRY[controlId];
83
- const Component = entry.component;
84
- return (_jsxs("div", { className: "flex items-center gap-3 rounded-lg px-1 py-1.5", children: [_jsx("div", { className: "shrink-0 text-xs text-muted-foreground", children: entry.label }), _jsx("div", { className: "ml-auto flex min-w-0 items-center", children: _jsx(Component, {}) })] }));
85
- }
86
- /**
87
- * A clickable row for complex controls — navigates to detail page on click.
88
- * Shows the control label, current value summary, and a chevron.
89
- */
90
- function ComplexControlRow({ controlId, onNavigate, }) {
91
- const entry = CONTROL_REGISTRY[controlId];
92
- return (_jsxs("button", { onClick: onNavigate, className: "flex w-full items-center gap-3 rounded-lg px-2 py-2 text-left transition-colors hover:bg-muted/50", children: [_jsx("div", { className: "shrink-0 text-xs text-muted-foreground", children: entry.label }), _jsx("div", { className: "ml-auto truncate text-xs text-foreground", children: _jsx(ControlSummary, { controlId: controlId }) }), _jsx(ChevronRight, { className: "h-3 w-3 shrink-0 text-muted-foreground" })] }));
93
- }
94
- /** Summary text for a complex control in the main menu. */
95
- function ControlSummary({ controlId }) {
96
- const { metric, columns, filters, dateRangeFilter } = useChartContext();
97
- switch (controlId) {
98
- case 'metric':
99
- return _jsx("span", { children: getMetricLabel(metric, columns) });
100
- case 'filters': {
101
- const count = [...filters.values()].reduce((sum, set) => sum + set.size, 0);
102
- return _jsx("span", { children: count > 0 ? `${count} active` : 'None' });
103
- }
104
- case 'dateRange':
105
- return _jsx("span", { children: resolvePresetLabel(dateRangeFilter) });
106
- default:
107
- return null;
108
- }
109
- }
@@ -1,45 +0,0 @@
1
- /**
2
- * Composable, configurable toolbar with pinned controls and an ellipsis
3
- * overflow menu — inspired by Notion's clean database view toolbar.
4
- *
5
- * Default behavior: the date range stays pinned so the active time window is
6
- * always visible, while the remaining controls live inside the overflow menu.
7
- * Developers can pin additional controls to the toolbar row and hide others.
8
- *
9
- * @example
10
- * ```tsx
11
- * // Date range pinned by default, everything else in overflow
12
- * <ChartToolbar />
13
- *
14
- * // Pin chart type and group-by to the toolbar row
15
- * <ChartToolbar pinned={['chartType', 'groupBy']} />
16
- *
17
- * // Hide time bucket and x-axis entirely
18
- * <ChartToolbar hidden={['timeBucket', 'xAxis']} />
19
- *
20
- * // Combine both
21
- * <ChartToolbar pinned={['chartType', 'metric']} hidden={['source']} />
22
- * ```
23
- */
24
- import type { ControlId } from './toolbar-types.js';
25
- /**
26
- * Props for ChartToolbar.
27
- *
28
- * @property className - Additional CSS classes for the toolbar container
29
- * @property pinned - Control IDs to always show in the toolbar row (outside the overflow menu)
30
- * @property hidden - Control IDs to completely hide (not in toolbar, not in overflow)
31
- */
32
- type ChartToolbarProps = {
33
- className?: string;
34
- pinned?: readonly ControlId[];
35
- hidden?: readonly ControlId[];
36
- };
37
- /**
38
- * Composable toolbar with pinned controls and an ellipsis overflow menu.
39
- *
40
- * Controls are rendered in registry order. Each sub-component still
41
- * auto-hides when not relevant (e.g. time bucket only shows for date X-axis).
42
- */
43
- export declare function ChartToolbar({ className, pinned, hidden, }: ChartToolbarProps): import("react/jsx-runtime").JSX.Element;
44
- export {};
45
- //# sourceMappingURL=chart-toolbar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-toolbar.d.ts","sourceRoot":"","sources":["../../src/ui/chart-toolbar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,oBAAoB,CAAA;AAKjD;;;;;;GAMG;AACH,KAAK,iBAAiB,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IAC7B,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;CAC9B,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,MAAgC,EAChC,MAAW,GACZ,EAAE,iBAAiB,2CAoBnB"}
@@ -1,44 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Composable, configurable toolbar with pinned controls and an ellipsis
4
- * overflow menu — inspired by Notion's clean database view toolbar.
5
- *
6
- * Default behavior: the date range stays pinned so the active time window is
7
- * always visible, while the remaining controls live inside the overflow menu.
8
- * Developers can pin additional controls to the toolbar row and hide others.
9
- *
10
- * @example
11
- * ```tsx
12
- * // Date range pinned by default, everything else in overflow
13
- * <ChartToolbar />
14
- *
15
- * // Pin chart type and group-by to the toolbar row
16
- * <ChartToolbar pinned={['chartType', 'groupBy']} />
17
- *
18
- * // Hide time bucket and x-axis entirely
19
- * <ChartToolbar hidden={['timeBucket', 'xAxis']} />
20
- *
21
- * // Combine both
22
- * <ChartToolbar pinned={['chartType', 'metric']} hidden={['source']} />
23
- * ```
24
- */
25
- import { useMemo } from 'react';
26
- import { ChartToolbarOverflow } from './chart-toolbar-overflow.js';
27
- import { CONTROL_IDS, CONTROL_REGISTRY } from './toolbar-types.js';
28
- const DEFAULT_PINNED_CONTROLS = ['dateRange'];
29
- /**
30
- * Composable toolbar with pinned controls and an ellipsis overflow menu.
31
- *
32
- * Controls are rendered in registry order. Each sub-component still
33
- * auto-hides when not relevant (e.g. time bucket only shows for date X-axis).
34
- */
35
- export function ChartToolbar({ className, pinned = DEFAULT_PINNED_CONTROLS, hidden = [], }) {
36
- const pinnedSet = useMemo(() => new Set(pinned), [pinned]);
37
- const hiddenSet = useMemo(() => new Set(hidden), [hidden]);
38
- // Pinned controls in registry order
39
- const pinnedControls = CONTROL_IDS.filter((id) => pinnedSet.has(id) && !hiddenSet.has(id));
40
- return (_jsxs("div", { className: `flex items-start justify-between gap-2 ${className ?? ''}`, children: [_jsx("div", { className: "flex min-w-0 flex-1 flex-wrap items-center gap-2", children: pinnedControls.map((id) => {
41
- const Component = CONTROL_REGISTRY[id].component;
42
- return _jsx(Component, {}, id);
43
- }) }), _jsx(ChartToolbarOverflow, { pinned: pinnedSet, hidden: hiddenSet, className: "shrink-0 self-start" })] }));
44
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Chart type selector — inline toggle buttons for bar/line/area/pie/donut.
3
- */
4
- /** Inline toggle buttons to select the chart type. */
5
- export declare function ChartTypeSelector({ className }: {
6
- className?: string;
7
- }): import("react/jsx-runtime").JSX.Element | null;
8
- //# sourceMappingURL=chart-type-selector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-type-selector.d.ts","sourceRoot":"","sources":["../../src/ui/chart-type-selector.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAcH,sDAAsD;AACtD,wBAAgB,iBAAiB,CAAC,EAAC,SAAS,EAAC,EAAE;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,kDA+BlE"}
@@ -1,22 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useChartContext } from './chart-context.js';
3
- /** Labels for each chart type. */
4
- const CHART_TYPE_LABELS = {
5
- bar: 'Bar',
6
- line: 'Line',
7
- area: 'Area',
8
- pie: 'Pie',
9
- donut: 'Donut',
10
- };
11
- /** Inline toggle buttons to select the chart type. */
12
- export function ChartTypeSelector({ className }) {
13
- const { chartType, setChartType, availableChartTypes } = useChartContext();
14
- if (availableChartTypes.length <= 1)
15
- return null;
16
- return (_jsx("div", { className: `inline-flex items-center rounded-lg border border-border/50 bg-muted/50 p-0.5 shadow-sm ${className ?? ''}`, role: "tablist", "aria-label": "Chart type", children: availableChartTypes.map((type) => {
17
- const isActive = type === chartType;
18
- return (_jsx("button", { role: "tab", "aria-selected": isActive, onClick: () => setChartType(type), className: `rounded-md px-2.5 py-1 text-xs font-medium transition-all ${isActive
19
- ? 'bg-background text-foreground shadow-sm'
20
- : 'text-muted-foreground hover:bg-background/50 hover:text-foreground'}`, children: CHART_TYPE_LABELS[type] }, type));
21
- }) }));
22
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * X-axis selector — premium custom dropdown for choosing which column drives the X-axis.
3
- */
4
- /** Custom dropdown to select the X-axis column. */
5
- export declare function ChartXAxisSelector({ className }: {
6
- className?: string;
7
- }): import("react/jsx-runtime").JSX.Element | null;
8
- //# sourceMappingURL=chart-x-axis-selector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chart-x-axis-selector.d.ts","sourceRoot":"","sources":["../../src/ui/chart-x-axis-selector.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAKH,mDAAmD;AACnD,wBAAgB,kBAAkB,CAAC,EAAC,SAAS,EAAC,EAAE;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,kDAgBnE"}
@@ -1,14 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * X-axis selector — premium custom dropdown for choosing which column drives the X-axis.
4
- */
5
- import { useChartContext } from './chart-context.js';
6
- import { ChartSelect } from './chart-select.js';
7
- /** Custom dropdown to select the X-axis column. */
8
- export function ChartXAxisSelector({ className }) {
9
- const { xAxisId, setXAxis, availableXAxes } = useChartContext();
10
- if (availableXAxes.length <= 1)
11
- return null;
12
- const options = availableXAxes.map((col) => ({ value: col.id, label: `X-axis: ${col.label}` }));
13
- return (_jsx(ChartSelect, { value: xAxisId ?? '', options: options, onChange: (v) => setXAxis(v), ariaLabel: "X-axis", className: className }));
14
- }