cortena-ui 1.3.0 → 1.4.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.
- package/README.md +74 -3
- package/dist/a2ui/catalogue-doc.d.ts +44 -0
- package/dist/a2ui/catalogue-doc.js +169 -0
- package/dist/a2ui/catalogue-doc.js.map +1 -0
- package/dist/a2ui/catalogue.d.ts +44 -0
- package/dist/a2ui/catalogue.js +942 -0
- package/dist/a2ui/catalogue.js.map +1 -0
- package/dist/a2ui/index.d.ts +7 -0
- package/dist/a2ui/message.d.ts +232 -0
- package/dist/a2ui/message.js +365 -0
- package/dist/a2ui/message.js.map +1 -0
- package/dist/a2ui/renderer.d.ts +46 -0
- package/dist/a2ui/renderer.js +252 -0
- package/dist/a2ui/renderer.js.map +1 -0
- package/dist/a2ui/views.d.ts +80 -0
- package/dist/a2ui/views.js +596 -0
- package/dist/a2ui/views.js.map +1 -0
- package/dist/a2ui.d.ts +8 -0
- package/dist/a2ui.js +7 -0
- package/dist/chart.d.ts +9 -0
- package/dist/chart.js +9 -0
- package/dist/components/accordion.d.ts +22 -0
- package/dist/components/accordion.js +63 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert.d.ts +15 -0
- package/dist/components/alert.js +64 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/avatar.d.ts +18 -0
- package/dist/components/avatar.js +40 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.d.ts +12 -0
- package/dist/components/badge.js +47 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/breadcrumb.d.ts +71 -0
- package/dist/components/breadcrumb.js +123 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/button-link.d.ts +28 -0
- package/dist/components/button-link.js +24 -0
- package/dist/components/button-link.js.map +1 -0
- package/dist/components/button.d.ts +24 -0
- package/dist/components/button.js +65 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/calendar.d.ts +28 -0
- package/dist/components/calendar.js +123 -0
- package/dist/components/calendar.js.map +1 -0
- package/dist/components/card.d.ts +32 -0
- package/dist/components/card.js +57 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/chart/chart.d.ts +71 -0
- package/dist/components/chart/chart.js +167 -0
- package/dist/components/chart/chart.js.map +1 -0
- package/dist/components/chart/container.d.ts +88 -0
- package/dist/components/chart/container.js +189 -0
- package/dist/components/chart/container.js.map +1 -0
- package/dist/components/chart/data.js +128 -0
- package/dist/components/chart/data.js.map +1 -0
- package/dist/components/chart/index.d.ts +9 -0
- package/dist/components/chart/index.js +10 -0
- package/dist/components/chart/nivo-charts.js +225 -0
- package/dist/components/chart/nivo-charts.js.map +1 -0
- package/dist/components/chart/nivo-lazy.js +50 -0
- package/dist/components/chart/nivo-lazy.js.map +1 -0
- package/dist/components/chart/nivo-theme.d.ts +156 -0
- package/dist/components/chart/nivo-theme.js +161 -0
- package/dist/components/chart/nivo-theme.js.map +1 -0
- package/dist/components/chart/recharts-charts.js +276 -0
- package/dist/components/chart/recharts-charts.js.map +1 -0
- package/dist/components/chart/recharts-lazy.js +58 -0
- package/dist/components/chart/recharts-lazy.js.map +1 -0
- package/dist/components/chart/recharts-parts.d.ts +10 -0
- package/dist/components/chart/recharts-parts.js +25 -0
- package/dist/components/chart/recharts-parts.js.map +1 -0
- package/dist/components/chart/tokens.d.ts +62 -0
- package/dist/components/chart/tokens.js +192 -0
- package/dist/components/chart/tokens.js.map +1 -0
- package/dist/components/chart/types.d.ts +114 -0
- package/dist/components/chart/types.js +27 -0
- package/dist/components/chart/types.js.map +1 -0
- package/dist/components/checkbox.d.ts +20 -0
- package/dist/components/checkbox.js +24 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/chip.d.ts +17 -0
- package/dist/components/chip.js +47 -0
- package/dist/components/chip.js.map +1 -0
- package/dist/components/combobox.d.ts +76 -0
- package/dist/components/combobox.js +201 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/command.d.ts +50 -0
- package/dist/components/command.js +117 -0
- package/dist/components/command.js.map +1 -0
- package/dist/components/data-table/data-table.d.ts +65 -0
- package/dist/components/data-table/data-table.js +588 -0
- package/dist/components/data-table/data-table.js.map +1 -0
- package/dist/components/data-table/export.d.ts +23 -0
- package/dist/components/data-table/export.js +95 -0
- package/dist/components/data-table/export.js.map +1 -0
- package/dist/components/data-table/features.d.ts +66 -0
- package/dist/components/data-table/features.js +103 -0
- package/dist/components/data-table/features.js.map +1 -0
- package/dist/components/data-table/index.d.ts +8 -0
- package/dist/components/data-table/parts.d.ts +79 -0
- package/dist/components/data-table/parts.js +400 -0
- package/dist/components/data-table/parts.js.map +1 -0
- package/dist/components/data-table/system-columns.js +84 -0
- package/dist/components/data-table/system-columns.js.map +1 -0
- package/dist/components/data-table/types.d.ts +172 -0
- package/dist/components/data-table/use-data-table.d.ts +19 -0
- package/dist/components/data-table/use-data-table.js +171 -0
- package/dist/components/data-table/use-data-table.js.map +1 -0
- package/dist/components/data-table/use-server-source.js +200 -0
- package/dist/components/data-table/use-server-source.js.map +1 -0
- package/dist/components/date-field.d.ts +54 -0
- package/dist/components/date-field.js +235 -0
- package/dist/components/date-field.js.map +1 -0
- package/dist/components/date-picker.d.ts +42 -0
- package/dist/components/date-picker.js +125 -0
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/dialog.d.ts +36 -0
- package/dist/components/dialog.js +97 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/dropdown-menu.d.ts +54 -0
- package/dist/components/dropdown-menu.js +191 -0
- package/dist/components/dropdown-menu.js.map +1 -0
- package/dist/components/dropzone.d.ts +48 -0
- package/dist/components/dropzone.js +185 -0
- package/dist/components/dropzone.js.map +1 -0
- package/dist/components/empty-state.d.ts +22 -0
- package/dist/components/empty-state.js +46 -0
- package/dist/components/empty-state.js.map +1 -0
- package/dist/components/error-banner.d.ts +17 -0
- package/dist/components/error-banner.js +52 -0
- package/dist/components/error-banner.js.map +1 -0
- package/dist/components/field.d.ts +64 -0
- package/dist/components/field.js +133 -0
- package/dist/components/field.js.map +1 -0
- package/dist/components/form.d.ts +37 -0
- package/dist/components/form.js +103 -0
- package/dist/components/form.js.map +1 -0
- package/dist/components/input.d.ts +17 -0
- package/dist/components/input.js +26 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/kbd.d.ts +11 -0
- package/dist/components/kbd.js +20 -0
- package/dist/components/kbd.js.map +1 -0
- package/dist/components/label.d.ts +14 -0
- package/dist/components/label.js +28 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/loading-skeleton.d.ts +22 -0
- package/dist/components/loading-skeleton.js +123 -0
- package/dist/components/loading-skeleton.js.map +1 -0
- package/dist/components/markdown.d.ts +44 -0
- package/dist/components/markdown.js +231 -0
- package/dist/components/markdown.js.map +1 -0
- package/dist/components/page-header.d.ts +26 -0
- package/dist/components/page-header.js +53 -0
- package/dist/components/page-header.js.map +1 -0
- package/dist/components/popover.d.ts +29 -0
- package/dist/components/popover.js +74 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/progress.d.ts +22 -0
- package/dist/components/progress.js +49 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/radio-group.d.ts +20 -0
- package/dist/components/radio-group.js +29 -0
- package/dist/components/radio-group.js.map +1 -0
- package/dist/components/scroll-area.d.ts +25 -0
- package/dist/components/scroll-area.js +39 -0
- package/dist/components/scroll-area.js.map +1 -0
- package/dist/components/section-card.d.ts +29 -0
- package/dist/components/section-card.js +55 -0
- package/dist/components/section-card.js.map +1 -0
- package/dist/components/segmented.d.ts +27 -0
- package/dist/components/segmented.js +32 -0
- package/dist/components/segmented.js.map +1 -0
- package/dist/components/select.d.ts +62 -0
- package/dist/components/select.js +97 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/separator.d.ts +19 -0
- package/dist/components/separator.js +23 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/sheet.d.ts +35 -0
- package/dist/components/sheet.js +131 -0
- package/dist/components/sheet.js.map +1 -0
- package/dist/components/skeleton.d.ts +12 -0
- package/dist/components/skeleton.js +22 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/sortable-list.d.ts +67 -0
- package/dist/components/sortable-list.js +206 -0
- package/dist/components/sortable-list.js.map +1 -0
- package/dist/components/spinner.d.ts +29 -0
- package/dist/components/spinner.js +34 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/status-dot.d.ts +26 -0
- package/dist/components/status-dot.js +47 -0
- package/dist/components/status-dot.js.map +1 -0
- package/dist/components/switch.d.ts +21 -0
- package/dist/components/switch.js +21 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/tabs.d.ts +24 -0
- package/dist/components/tabs.js +60 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/textarea.d.ts +19 -0
- package/dist/components/textarea.js +47 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/toast.d.ts +47 -0
- package/dist/components/toast.js +106 -0
- package/dist/components/toast.js.map +1 -0
- package/dist/components/toolbar.d.ts +19 -0
- package/dist/components/toolbar.js +45 -0
- package/dist/components/toolbar.js.map +1 -0
- package/dist/components/tooltip.d.ts +28 -0
- package/dist/components/tooltip.js +59 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/core.d.ts +44 -0
- package/dist/core.js +44 -0
- package/dist/data-table.d.ts +9 -0
- package/dist/data-table.js +7 -0
- package/dist/form.d.ts +7 -0
- package/dist/form.js +7 -0
- package/dist/hooks/use-cortena-theme.d.ts +98 -0
- package/dist/hooks/use-cortena-theme.js +145 -0
- package/dist/hooks/use-cortena-theme.js.map +1 -0
- package/dist/index.d.ts +75 -2678
- package/dist/index.js +66 -8598
- package/dist/lib/cn.d.ts +10 -0
- package/dist/lib/cn.js +15 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/lib/render.d.ts +23 -0
- package/dist/lib/render.js +20 -0
- package/dist/lib/render.js.map +1 -0
- package/dist/lib/shakeable.js +39 -0
- package/dist/lib/shakeable.js.map +1 -0
- package/dist/markdown.d.ts +3 -0
- package/dist/markdown.js +3 -0
- package/dist/sortable-list.d.ts +3 -0
- package/dist/sortable-list.js +3 -0
- package/package.json +37 -14
- package/src/a2ui/catalogue.ts +140 -103
- package/src/a2ui/views.tsx +5 -2
- package/src/components/alert.tsx +1 -1
- package/src/components/badge.tsx +1 -1
- package/src/components/button.tsx +1 -1
- package/src/components/chart/chart.tsx +72 -25
- package/src/components/chart/container.tsx +24 -39
- package/src/components/chart/index.tsx +4 -2
- package/src/components/chart/nivo-charts.tsx +41 -13
- package/src/components/chart/nivo-lazy.tsx +52 -0
- package/src/components/chart/recharts-charts.tsx +98 -3
- package/src/components/chart/recharts-lazy.tsx +72 -0
- package/src/components/chart/recharts-parts.tsx +34 -0
- package/src/components/chart/tokens.ts +1 -1
- package/src/components/chart/types.ts +14 -0
- package/src/components/chip.tsx +1 -1
- package/src/components/combobox.tsx +2 -2
- package/src/components/data-table/export.ts +18 -2
- package/src/components/data-table/features.ts +77 -45
- package/src/components/data-table/parts.tsx +15 -0
- package/src/components/data-table/use-data-table.ts +7 -2
- package/src/components/data-table/use-server-source.ts +17 -4
- package/src/components/date-field.tsx +1 -1
- package/src/components/error-banner.tsx +1 -1
- package/src/components/field.tsx +2 -2
- package/src/components/form.tsx +2 -2
- package/src/components/input.tsx +1 -1
- package/src/components/label.tsx +1 -1
- package/src/components/markdown.tsx +5 -4
- package/src/components/sheet.tsx +2 -2
- package/src/components/sortable-list.tsx +2 -2
- package/src/components/textarea.tsx +1 -1
- package/src/components/toast.tsx +1 -1
- package/src/entries/a2ui.ts +11 -0
- package/src/entries/chart.ts +10 -0
- package/src/entries/core.ts +91 -0
- package/src/entries/data-table.ts +9 -0
- package/src/entries/form.ts +24 -0
- package/src/entries/markdown.ts +9 -0
- package/src/entries/sortable-list.ts +13 -0
- package/src/index.ts +32 -98
- package/src/lib/shakeable.ts +33 -0
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { vizSeries } from "cortena-design/tokens";
|
|
5
|
+
//#region src/components/chart/tokens.ts
|
|
6
|
+
/**
|
|
7
|
+
* Token plumbing for the chart engines.
|
|
8
|
+
*
|
|
9
|
+
* Recharts draws SVG, so it can take `var(--ds-viz-1)` verbatim and the
|
|
10
|
+
* browser resolves it. Nivo cannot: its canvas renderer hands colours to a
|
|
11
|
+
* 2D context, and its SVG renderer runs colours through d3-color for label and
|
|
12
|
+
* border derivation, and neither understands `var()`. So every Nivo value is
|
|
13
|
+
* read from the `--ds-*` custom property at runtime and handed over as a
|
|
14
|
+
* concrete hex. Nothing in this file is a literal; on the server (no DOM) the
|
|
15
|
+
* `var()` form is returned so SSR markup still resolves in the browser.
|
|
16
|
+
*/
|
|
17
|
+
/** Number of categorical series colours the design system defines (`--ds-viz-1..n`). */
|
|
18
|
+
const VIZ_SERIES_COUNT = vizSeries.length;
|
|
19
|
+
/** `var(--ds-viz-N)` for a zero-based series index, wrapping past the palette. */
|
|
20
|
+
function vizVar(index) {
|
|
21
|
+
const n = VIZ_SERIES_COUNT;
|
|
22
|
+
return `var(--ds-viz-${(index % n + n) % n + 1})`;
|
|
23
|
+
}
|
|
24
|
+
/** The categorical palette as `var()` references, in series order. */
|
|
25
|
+
const vizSeriesVars = /* @__PURE__ */ Array.from({ length: VIZ_SERIES_COUNT }, (_, i) => vizVar(i));
|
|
26
|
+
function hasDom() {
|
|
27
|
+
return typeof document !== "undefined" && typeof getComputedStyle === "function";
|
|
28
|
+
}
|
|
29
|
+
/** Read a custom property as the browser computes it on `el` (default: `<html>`). */
|
|
30
|
+
function readToken(name, el) {
|
|
31
|
+
if (!hasDom()) return "";
|
|
32
|
+
return getComputedStyle(el ?? document.documentElement).getPropertyValue(name).trim();
|
|
33
|
+
}
|
|
34
|
+
/** A `--ds-text-*` size (rem or px) as a pixel number, for engines that want numbers. */
|
|
35
|
+
function tokenPx(name, el) {
|
|
36
|
+
const raw = readToken(name, el);
|
|
37
|
+
if (!raw) return void 0;
|
|
38
|
+
const n = Number.parseFloat(raw);
|
|
39
|
+
if (Number.isNaN(n)) return void 0;
|
|
40
|
+
if (raw.endsWith("rem")) return n * (Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16);
|
|
41
|
+
return n;
|
|
42
|
+
}
|
|
43
|
+
let probe;
|
|
44
|
+
function hex2(n) {
|
|
45
|
+
return n.toString(16).padStart(2, "0");
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Convert any CSS colour the browser understands (oklch, color-mix, rgba…) to
|
|
49
|
+
* `#rrggbb`, by painting it into an offscreen 2D context. Alpha is composited
|
|
50
|
+
* against transparent, so translucent tokens come back opaque; chart fills
|
|
51
|
+
* never use those.
|
|
52
|
+
*/
|
|
53
|
+
function toHex(css) {
|
|
54
|
+
if (!hasDom() || !css) return void 0;
|
|
55
|
+
if (probe === void 0) probe = document.createElement("canvas").getContext("2d", { willReadFrequently: true });
|
|
56
|
+
if (!probe) return void 0;
|
|
57
|
+
probe.clearRect(0, 0, 1, 1);
|
|
58
|
+
probe.fillStyle = css;
|
|
59
|
+
probe.fillRect(0, 0, 1, 1);
|
|
60
|
+
const d = probe.getImageData(0, 0, 1, 1).data;
|
|
61
|
+
return `#${hex2(d[0] ?? 0)}${hex2(d[1] ?? 0)}${hex2(d[2] ?? 0)}`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A token as a concrete colour. Returns hex in the browser; on the server the
|
|
65
|
+
* `var()` form, which is fine for SVG markup and irrelevant for canvas.
|
|
66
|
+
*/
|
|
67
|
+
function resolveColor(token, el) {
|
|
68
|
+
return toHex(readToken(token, el)) ?? `var(${token})`;
|
|
69
|
+
}
|
|
70
|
+
/** The categorical palette resolved to concrete colours, in series order. */
|
|
71
|
+
function resolveVizSeries(el) {
|
|
72
|
+
return vizSeriesVars.map((_, i) => resolveColor(`--ds-viz-${i + 1}`, el));
|
|
73
|
+
}
|
|
74
|
+
/** Relative luminance of a `#rrggbb`, for choosing a scale direction. */
|
|
75
|
+
function luminance(hex) {
|
|
76
|
+
const c = (i) => {
|
|
77
|
+
const v = Number.parseInt(hex.slice(i, i + 2), 16) / 255;
|
|
78
|
+
return v <= .03928 ? v / 12.92 : ((v + .055) / 1.055) ** 2.4;
|
|
79
|
+
};
|
|
80
|
+
return .2126 * c(1) + .7152 * c(3) + .0722 * c(5);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A label colour that reads on a given fill: the design system's ink on light
|
|
84
|
+
* fills, its white on dark ones. Nivo cells and arcs paint their labels with
|
|
85
|
+
* this so a value on a deep sequential cell stays legible.
|
|
86
|
+
*/
|
|
87
|
+
function contrastLabel(el) {
|
|
88
|
+
const ink = resolveColor("--ds-base-text-ink", el);
|
|
89
|
+
const white = resolveColor("--ds-base-white", el);
|
|
90
|
+
return (fill) => {
|
|
91
|
+
const hex = fill.startsWith("#") && fill.length === 7 ? fill : toHex(fill);
|
|
92
|
+
return hex && luminance(hex) < .3 ? white : ink;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** True when the resolved `--ds-background` is dark, whatever set the theme (attribute or OS). */
|
|
96
|
+
function isDarkSurface(el) {
|
|
97
|
+
const bg = toHex(readToken("--ds-background", el));
|
|
98
|
+
return bg ? luminance(bg) < .4 : false;
|
|
99
|
+
}
|
|
100
|
+
/** Linear interpolation through a list of hex stops; `t` in [0, 1]. */
|
|
101
|
+
function piecewiseHex(stops) {
|
|
102
|
+
const rgb = stops.map((h) => [
|
|
103
|
+
1,
|
|
104
|
+
3,
|
|
105
|
+
5
|
|
106
|
+
].map((i) => Number.parseInt(h.slice(i, i + 2), 16)));
|
|
107
|
+
return (t) => {
|
|
108
|
+
const pos = Math.min(1, Math.max(0, Number.isNaN(t) ? 0 : t)) * (rgb.length - 1);
|
|
109
|
+
const i = Math.max(0, Math.min(rgb.length - 2, Math.floor(pos)));
|
|
110
|
+
const f = pos - i;
|
|
111
|
+
const a = rgb[i] ?? [
|
|
112
|
+
0,
|
|
113
|
+
0,
|
|
114
|
+
0
|
|
115
|
+
];
|
|
116
|
+
const b = rgb[i + 1] ?? a;
|
|
117
|
+
const mix = (k) => Math.round((a[k] ?? 0) + ((b[k] ?? 0) - (a[k] ?? 0)) * f);
|
|
118
|
+
return `#${hex2(mix(0))}${hex2(mix(1))}${hex2(mix(2))}`;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Sequential and diverging scales from the tokens.
|
|
123
|
+
*
|
|
124
|
+
* The token set has only the eight categorical `--ds-viz-*` colours and no
|
|
125
|
+
* sequential ramp, so the sequential scale is derived from the
|
|
126
|
+
* `--ds-primary-100..900` ladder: light surfaces run 100 → 700 (pale to deep),
|
|
127
|
+
* dark surfaces run 900 → 400 (deep to bright), so low values sit near the
|
|
128
|
+
* background in both themes. The diverging scale runs `--ds-viz-5` (rose)
|
|
129
|
+
* through the theme's neutral (`--ds-neutral-200` light, `--ds-neutral-700`
|
|
130
|
+
* dark) to `--ds-viz-1` (blue).
|
|
131
|
+
*/
|
|
132
|
+
function chartScales(el) {
|
|
133
|
+
const dark = isDarkSurface(el);
|
|
134
|
+
const sequential = (dark ? [
|
|
135
|
+
"--ds-primary-900",
|
|
136
|
+
"--ds-primary-800",
|
|
137
|
+
"--ds-primary-600",
|
|
138
|
+
"--ds-primary-400"
|
|
139
|
+
] : [
|
|
140
|
+
"--ds-primary-100",
|
|
141
|
+
"--ds-primary-300",
|
|
142
|
+
"--ds-primary-500",
|
|
143
|
+
"--ds-primary-700"
|
|
144
|
+
]).map((t) => resolveColor(t, el));
|
|
145
|
+
const diverging = [
|
|
146
|
+
"--ds-viz-5",
|
|
147
|
+
dark ? "--ds-neutral-700" : "--ds-neutral-200",
|
|
148
|
+
"--ds-viz-1"
|
|
149
|
+
].map((t) => resolveColor(t, el));
|
|
150
|
+
const sequentialInterpolator = piecewiseHex(sequential);
|
|
151
|
+
return {
|
|
152
|
+
sequential,
|
|
153
|
+
diverging,
|
|
154
|
+
sequentialInterpolator,
|
|
155
|
+
divergingInterpolator: piecewiseHex(diverging),
|
|
156
|
+
sequentialSteps: (n) => Array.from({ length: n }, (_, i) => sequentialInterpolator(n === 1 ? 1 : i / (n - 1))),
|
|
157
|
+
empty: resolveColor("--ds-muted", el),
|
|
158
|
+
surface: resolveColor("--ds-background", el)
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A counter that bumps whenever the theme may have changed: the `data-theme`
|
|
163
|
+
* or `class` attribute on `<html>`, or the OS colour scheme. Resolved token
|
|
164
|
+
* values are memoised on it so Nivo re-reads them on a flip.
|
|
165
|
+
*/
|
|
166
|
+
function useThemeVersion() {
|
|
167
|
+
const [version, setVersion] = useState(0);
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
if (!hasDom()) return;
|
|
170
|
+
const bump = () => setVersion((v) => v + 1);
|
|
171
|
+
const observer = new MutationObserver(bump);
|
|
172
|
+
observer.observe(document.documentElement, {
|
|
173
|
+
attributes: true,
|
|
174
|
+
attributeFilter: [
|
|
175
|
+
"data-theme",
|
|
176
|
+
"class",
|
|
177
|
+
"style"
|
|
178
|
+
]
|
|
179
|
+
});
|
|
180
|
+
const media = window.matchMedia?.("(prefers-color-scheme: dark)");
|
|
181
|
+
media?.addEventListener?.("change", bump);
|
|
182
|
+
return () => {
|
|
183
|
+
observer.disconnect();
|
|
184
|
+
media?.removeEventListener?.("change", bump);
|
|
185
|
+
};
|
|
186
|
+
}, []);
|
|
187
|
+
return version;
|
|
188
|
+
}
|
|
189
|
+
//#endregion
|
|
190
|
+
export { VIZ_SERIES_COUNT, chartScales, contrastLabel, isDarkSurface, piecewiseHex, readToken, resolveColor, resolveVizSeries, toHex, tokenPx, useThemeVersion, vizSeriesVars, vizVar };
|
|
191
|
+
|
|
192
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","names":[],"sources":["../../../src/components/chart/tokens.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { vizSeries } from \"cortena-design/tokens\";\n\n/**\n * Token plumbing for the chart engines.\n *\n * Recharts draws SVG, so it can take `var(--ds-viz-1)` verbatim and the\n * browser resolves it. Nivo cannot: its canvas renderer hands colours to a\n * 2D context, and its SVG renderer runs colours through d3-color for label and\n * border derivation, and neither understands `var()`. So every Nivo value is\n * read from the `--ds-*` custom property at runtime and handed over as a\n * concrete hex. Nothing in this file is a literal; on the server (no DOM) the\n * `var()` form is returned so SSR markup still resolves in the browser.\n */\n\n/** Number of categorical series colours the design system defines (`--ds-viz-1..n`). */\nexport const VIZ_SERIES_COUNT = vizSeries.length;\n\n/** `var(--ds-viz-N)` for a zero-based series index, wrapping past the palette. */\nexport function vizVar(index: number): string {\n const n = VIZ_SERIES_COUNT;\n return `var(--ds-viz-${(((index % n) + n) % n) + 1})`;\n}\n\n/** The categorical palette as `var()` references, in series order. */\nexport const vizSeriesVars: readonly string[] = /* @__PURE__ */ Array.from({ length: VIZ_SERIES_COUNT }, (_, i) =>\n vizVar(i),\n);\n\nfunction hasDom(): boolean {\n return typeof document !== \"undefined\" && typeof getComputedStyle === \"function\";\n}\n\n/** Read a custom property as the browser computes it on `el` (default: `<html>`). */\nexport function readToken(name: string, el?: Element | null): string {\n if (!hasDom()) return \"\";\n return getComputedStyle(el ?? document.documentElement).getPropertyValue(name).trim();\n}\n\n/** A `--ds-text-*` size (rem or px) as a pixel number, for engines that want numbers. */\nexport function tokenPx(name: string, el?: Element | null): number | undefined {\n const raw = readToken(name, el);\n if (!raw) return undefined;\n const n = Number.parseFloat(raw);\n if (Number.isNaN(n)) return undefined;\n if (raw.endsWith(\"rem\")) {\n const root = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n return n * root;\n }\n return n;\n}\n\nlet probe: CanvasRenderingContext2D | null | undefined;\n\nfunction hex2(n: number): string {\n return n.toString(16).padStart(2, \"0\");\n}\n\n/**\n * Convert any CSS colour the browser understands (oklch, color-mix, rgba…) to\n * `#rrggbb`, by painting it into an offscreen 2D context. Alpha is composited\n * against transparent, so translucent tokens come back opaque; chart fills\n * never use those.\n */\nexport function toHex(css: string): string | undefined {\n if (!hasDom() || !css) return undefined;\n if (probe === undefined) {\n probe = document.createElement(\"canvas\").getContext(\"2d\", { willReadFrequently: true });\n }\n if (!probe) return undefined;\n probe.clearRect(0, 0, 1, 1);\n probe.fillStyle = css;\n probe.fillRect(0, 0, 1, 1);\n const d = probe.getImageData(0, 0, 1, 1).data;\n return `#${hex2(d[0] ?? 0)}${hex2(d[1] ?? 0)}${hex2(d[2] ?? 0)}`;\n}\n\n/**\n * A token as a concrete colour. Returns hex in the browser; on the server the\n * `var()` form, which is fine for SVG markup and irrelevant for canvas.\n */\nexport function resolveColor(token: string, el?: Element | null): string {\n return toHex(readToken(token, el)) ?? `var(${token})`;\n}\n\n/** The categorical palette resolved to concrete colours, in series order. */\nexport function resolveVizSeries(el?: Element | null): string[] {\n return vizSeriesVars.map((_, i) => resolveColor(`--ds-viz-${i + 1}`, el));\n}\n\n/** Relative luminance of a `#rrggbb`, for choosing a scale direction. */\nfunction luminance(hex: string): number {\n const c = (i: number) => {\n const v = Number.parseInt(hex.slice(i, i + 2), 16) / 255;\n return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;\n };\n return 0.2126 * c(1) + 0.7152 * c(3) + 0.0722 * c(5);\n}\n\n/**\n * A label colour that reads on a given fill: the design system's ink on light\n * fills, its white on dark ones. Nivo cells and arcs paint their labels with\n * this so a value on a deep sequential cell stays legible.\n */\nexport function contrastLabel(el?: Element | null): (fill: string) => string {\n const ink = resolveColor(\"--ds-base-text-ink\", el);\n const white = resolveColor(\"--ds-base-white\", el);\n return (fill: string) => {\n const hex = fill.startsWith(\"#\") && fill.length === 7 ? fill : toHex(fill);\n return hex && luminance(hex) < 0.3 ? white : ink;\n };\n}\n\n/** True when the resolved `--ds-background` is dark, whatever set the theme (attribute or OS). */\nexport function isDarkSurface(el?: Element | null): boolean {\n const bg = toHex(readToken(\"--ds-background\", el));\n return bg ? luminance(bg) < 0.4 : false;\n}\n\n/** Linear interpolation through a list of hex stops; `t` in [0, 1]. */\nexport function piecewiseHex(stops: string[]): (t: number) => string {\n const rgb = stops.map((h) => [1, 3, 5].map((i) => Number.parseInt(h.slice(i, i + 2), 16)));\n return (t: number) => {\n const clamped = Math.min(1, Math.max(0, Number.isNaN(t) ? 0 : t));\n const pos = clamped * (rgb.length - 1);\n const i = Math.max(0, Math.min(rgb.length - 2, Math.floor(pos)));\n const f = pos - i;\n const a = rgb[i] ?? [0, 0, 0];\n const b = rgb[i + 1] ?? a;\n const mix = (k: number) => Math.round((a[k] ?? 0) + ((b[k] ?? 0) - (a[k] ?? 0)) * f);\n return `#${hex2(mix(0))}${hex2(mix(1))}${hex2(mix(2))}`;\n };\n}\n\nexport interface ChartScales {\n /** Low → high, as concrete hex stops. */\n sequential: string[];\n /** Negative → neutral → positive, as concrete hex stops. */\n diverging: string[];\n /** Interpolators over the stops, `t` in [0, 1], for Nivo's `interpolator` configs. */\n sequentialInterpolator: (t: number) => string;\n divergingInterpolator: (t: number) => string;\n /** `n` evenly spaced sequential swatches, for quantised fills like the calendar. */\n sequentialSteps: (n: number) => string[];\n /** Fill for cells with no value. */\n empty: string;\n /** The chart's surface (`--ds-background`), for the gaps between cells and arcs. */\n surface: string;\n}\n\n/**\n * Sequential and diverging scales from the tokens.\n *\n * The token set has only the eight categorical `--ds-viz-*` colours and no\n * sequential ramp, so the sequential scale is derived from the\n * `--ds-primary-100..900` ladder: light surfaces run 100 → 700 (pale to deep),\n * dark surfaces run 900 → 400 (deep to bright), so low values sit near the\n * background in both themes. The diverging scale runs `--ds-viz-5` (rose)\n * through the theme's neutral (`--ds-neutral-200` light, `--ds-neutral-700`\n * dark) to `--ds-viz-1` (blue).\n */\nexport function chartScales(el?: Element | null): ChartScales {\n const dark = isDarkSurface(el);\n const seqTokens = dark\n ? [\"--ds-primary-900\", \"--ds-primary-800\", \"--ds-primary-600\", \"--ds-primary-400\"]\n : [\"--ds-primary-100\", \"--ds-primary-300\", \"--ds-primary-500\", \"--ds-primary-700\"];\n const sequential = seqTokens.map((t) => resolveColor(t, el));\n const diverging = [\"--ds-viz-5\", dark ? \"--ds-neutral-700\" : \"--ds-neutral-200\", \"--ds-viz-1\"].map(\n (t) => resolveColor(t, el),\n );\n const sequentialInterpolator = piecewiseHex(sequential);\n const divergingInterpolator = piecewiseHex(diverging);\n return {\n sequential,\n diverging,\n sequentialInterpolator,\n divergingInterpolator,\n sequentialSteps: (n) =>\n Array.from({ length: n }, (_, i) => sequentialInterpolator(n === 1 ? 1 : i / (n - 1))),\n empty: resolveColor(\"--ds-muted\", el),\n surface: resolveColor(\"--ds-background\", el),\n };\n}\n\n/**\n * A counter that bumps whenever the theme may have changed: the `data-theme`\n * or `class` attribute on `<html>`, or the OS colour scheme. Resolved token\n * values are memoised on it so Nivo re-reads them on a flip.\n */\nexport function useThemeVersion(): number {\n const [version, setVersion] = useState(0);\n useEffect(() => {\n if (!hasDom()) return;\n const bump = () => setVersion((v) => v + 1);\n const observer = new MutationObserver(bump);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"data-theme\", \"class\", \"style\"],\n });\n const media = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n media?.addEventListener?.(\"change\", bump);\n return () => {\n observer.disconnect();\n media?.removeEventListener?.(\"change\", bump);\n };\n }, []);\n return version;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/components/chart/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Chart types and the data shape each one expects.
|
|
6
|
+
*
|
|
7
|
+
* Engine per type (see cortena-docs/cortenaUI&Design/03-charting.md):
|
|
8
|
+
*
|
|
9
|
+
* | type | engine |
|
|
10
|
+
* | -------------------------------------------------------- | ------------------------- |
|
|
11
|
+
* | bar, line, area, pie, donut, scatter, radar, funnel | Recharts (static import) |
|
|
12
|
+
* | heatmap, calendar, treemap, sunburst | Nivo (lazy, per package) |
|
|
13
|
+
*
|
|
14
|
+
* Data shapes (the webchat renderer's legacy shapes are all accepted):
|
|
15
|
+
*
|
|
16
|
+
* - **bar**, **radar**: `ChartRow[]` — one object per category with a string
|
|
17
|
+
* category key (`indexBy`, inferred as the first string field) and one
|
|
18
|
+
* numeric field per series (`keys`, inferred as every numeric field).
|
|
19
|
+
* `[{ month: "Jan", revenue: 12, cost: 8 }, …]`. The series shape below is
|
|
20
|
+
* also accepted and pivoted.
|
|
21
|
+
* - **line**, **area**: `ChartSeries[]` — `[{ id: "revenue", data: [{ x, y }] }]`
|
|
22
|
+
* (the Nivo line shape the webchat emits). `ChartRow[]` is also accepted.
|
|
23
|
+
* - **pie**, **donut**, **funnel**: `ChartSlice[]` — `[{ id, label?, value }]`.
|
|
24
|
+
* - **scatter** (alias `scatterplot`): `ChartSeries[]` — one series per group.
|
|
25
|
+
* - **heatmap**: `ChartSeries[]` — Nivo heatmap shape, `[{ id: row, data: [{ x: column, y: value }] }]` —
|
|
26
|
+
* or `ChartMatrix`, the categorical form a correlation / confusion matrix
|
|
27
|
+
* already has: `{ rows, columns, values }` with `values[r][c]` at
|
|
28
|
+
* `rows[r] × columns[c]`.
|
|
29
|
+
* - **calendar**: `ChartDay[]` — `[{ day: "2026-01-31", value }]`; `from`/`to`
|
|
30
|
+
* default to the data's range.
|
|
31
|
+
* - **treemap**, **sunburst**: `ChartTree` — Nivo tree, `{ id, children?: [...], value? }`
|
|
32
|
+
* (`name` is accepted in place of `id`).
|
|
33
|
+
*/
|
|
34
|
+
export type ChartType = "bar" | "line" | "area" | "pie" | "donut" | "scatter" | "scatterplot" | "radar" | "funnel" | "heatmap" | "calendar" | "treemap" | "sunburst";
|
|
35
|
+
/** The engine that draws a given type. */
|
|
36
|
+
export type ChartEngine = "recharts" | "nivo";
|
|
37
|
+
/** Nivo renderer; only the Nivo types honour it (Recharts is SVG only). */
|
|
38
|
+
export type ChartRenderer = "svg" | "canvas";
|
|
39
|
+
/** One category with a numeric value per series. */
|
|
40
|
+
export type ChartRow = Record<string, string | number | null | undefined>;
|
|
41
|
+
/** One series of points; x may be a category or a number, y a number. */
|
|
42
|
+
export interface ChartPoint {
|
|
43
|
+
x: string | number;
|
|
44
|
+
y: number | null;
|
|
45
|
+
}
|
|
46
|
+
export interface ChartSeries {
|
|
47
|
+
id: string | number;
|
|
48
|
+
data: ChartPoint[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* What to write on each arc of a pie or donut.
|
|
52
|
+
*
|
|
53
|
+
* `percent` is the default for both, because the question a reader asks of a
|
|
54
|
+
* pie is almost always "what share is that", and reading it off the legend
|
|
55
|
+
* slice by slice is the work the chart was supposed to do for them. `value`
|
|
56
|
+
* writes the number itself, through `valueFormatter` when one is given. `none`
|
|
57
|
+
* leaves the arcs bare for a chart that is decorative or has its own labelling.
|
|
58
|
+
*
|
|
59
|
+
* Arcs too thin to hold their text are left unlabelled whatever this says; see
|
|
60
|
+
* `ARC_LABEL_MIN_FRACTION` in recharts-charts.tsx.
|
|
61
|
+
*/
|
|
62
|
+
export type ChartLabels = "none" | "value" | "percent";
|
|
63
|
+
/** One slice of a pie, donut or funnel. */
|
|
64
|
+
export interface ChartSlice {
|
|
65
|
+
id: string | number;
|
|
66
|
+
label?: string;
|
|
67
|
+
value: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A categorical matrix: `values[r][c]` is the cell at `rows[r]` × `columns[c]`.
|
|
71
|
+
* The shape a correlation matrix, a confusion matrix or a day × hour grid is
|
|
72
|
+
* already in, so it needs no pivot at the call site. Short rows are padded
|
|
73
|
+
* with `null` (drawn as the empty colour) rather than treated as zero.
|
|
74
|
+
*/
|
|
75
|
+
export interface ChartMatrix {
|
|
76
|
+
rows: string[];
|
|
77
|
+
columns: string[];
|
|
78
|
+
values: Array<Array<number | null | undefined>>;
|
|
79
|
+
}
|
|
80
|
+
/** One day of a calendar heatmap. */
|
|
81
|
+
export interface ChartDay {
|
|
82
|
+
day: string;
|
|
83
|
+
value: number;
|
|
84
|
+
}
|
|
85
|
+
/** A Nivo tree node for treemap and sunburst. */
|
|
86
|
+
export interface ChartTree {
|
|
87
|
+
id?: string | number;
|
|
88
|
+
name?: string;
|
|
89
|
+
value?: number;
|
|
90
|
+
children?: ChartTree[];
|
|
91
|
+
[key: string]: unknown;
|
|
92
|
+
}
|
|
93
|
+
/** The data type accepted for each chart type. */
|
|
94
|
+
export type ChartDataFor<T extends ChartType> = T extends "bar" | "radar" ? ChartRow[] | ChartSeries[] : T extends "line" | "area" ? ChartSeries[] | ChartRow[] : T extends "pie" | "donut" | "funnel" ? ChartSlice[] : T extends "heatmap" ? ChartSeries[] | ChartMatrix : T extends "scatter" | "scatterplot" ? ChartSeries[] : T extends "calendar" ? ChartDay[] : T extends "treemap" | "sunburst" ? ChartTree : never;
|
|
95
|
+
/**
|
|
96
|
+
* Per-series presentation, keyed by series id (the `keys` of a row chart, the
|
|
97
|
+
* `id` of a series or slice). Colours default to `var(--ds-viz-1..n)` in key
|
|
98
|
+
* order, so the same category index gets the same colour in every app; set
|
|
99
|
+
* `color` only to pin a category to a semantic colour, and then only to a
|
|
100
|
+
* token (`var(--ds-success)`), never a literal.
|
|
101
|
+
*/
|
|
102
|
+
export type ChartConfig = Record<string, {
|
|
103
|
+
label?: React.ReactNode;
|
|
104
|
+
icon?: React.ComponentType;
|
|
105
|
+
color?: string;
|
|
106
|
+
}>;
|
|
107
|
+
/** Which continuous scale a heatmap or calendar uses. */
|
|
108
|
+
export type ChartScale = "sequential" | "diverging";
|
|
109
|
+
export declare const RECHARTS_TYPES: ReadonlySet<ChartType>;
|
|
110
|
+
export declare const NIVO_TYPES: ReadonlySet<ChartType>;
|
|
111
|
+
/** The engine the package uses for a chart type. */
|
|
112
|
+
export declare function chartEngine(type: ChartType): ChartEngine;
|
|
113
|
+
//#endregion
|
|
114
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//#region src/components/chart/types.ts
|
|
3
|
+
const RECHARTS_TYPES = /* @__PURE__ */ new Set([
|
|
4
|
+
"bar",
|
|
5
|
+
"line",
|
|
6
|
+
"area",
|
|
7
|
+
"pie",
|
|
8
|
+
"donut",
|
|
9
|
+
"scatter",
|
|
10
|
+
"scatterplot",
|
|
11
|
+
"radar",
|
|
12
|
+
"funnel"
|
|
13
|
+
]);
|
|
14
|
+
const NIVO_TYPES = /* @__PURE__ */ new Set([
|
|
15
|
+
"heatmap",
|
|
16
|
+
"calendar",
|
|
17
|
+
"treemap",
|
|
18
|
+
"sunburst"
|
|
19
|
+
]);
|
|
20
|
+
/** The engine the package uses for a chart type. */
|
|
21
|
+
function chartEngine(type) {
|
|
22
|
+
return NIVO_TYPES.has(type) ? "nivo" : "recharts";
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { NIVO_TYPES, RECHARTS_TYPES, chartEngine };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../src/components/chart/types.ts"],"sourcesContent":["import type * as React from \"react\";\n\n/**\n * Chart types and the data shape each one expects.\n *\n * Engine per type (see cortena-docs/cortenaUI&Design/03-charting.md):\n *\n * | type | engine |\n * | -------------------------------------------------------- | ------------------------- |\n * | bar, line, area, pie, donut, scatter, radar, funnel | Recharts (static import) |\n * | heatmap, calendar, treemap, sunburst | Nivo (lazy, per package) |\n *\n * Data shapes (the webchat renderer's legacy shapes are all accepted):\n *\n * - **bar**, **radar**: `ChartRow[]` — one object per category with a string\n * category key (`indexBy`, inferred as the first string field) and one\n * numeric field per series (`keys`, inferred as every numeric field).\n * `[{ month: \"Jan\", revenue: 12, cost: 8 }, …]`. The series shape below is\n * also accepted and pivoted.\n * - **line**, **area**: `ChartSeries[]` — `[{ id: \"revenue\", data: [{ x, y }] }]`\n * (the Nivo line shape the webchat emits). `ChartRow[]` is also accepted.\n * - **pie**, **donut**, **funnel**: `ChartSlice[]` — `[{ id, label?, value }]`.\n * - **scatter** (alias `scatterplot`): `ChartSeries[]` — one series per group.\n * - **heatmap**: `ChartSeries[]` — Nivo heatmap shape, `[{ id: row, data: [{ x: column, y: value }] }]` —\n * or `ChartMatrix`, the categorical form a correlation / confusion matrix\n * already has: `{ rows, columns, values }` with `values[r][c]` at\n * `rows[r] × columns[c]`.\n * - **calendar**: `ChartDay[]` — `[{ day: \"2026-01-31\", value }]`; `from`/`to`\n * default to the data's range.\n * - **treemap**, **sunburst**: `ChartTree` — Nivo tree, `{ id, children?: [...], value? }`\n * (`name` is accepted in place of `id`).\n */\nexport type ChartType =\n | \"bar\"\n | \"line\"\n | \"area\"\n | \"pie\"\n | \"donut\"\n | \"scatter\"\n | \"scatterplot\"\n | \"radar\"\n | \"funnel\"\n | \"heatmap\"\n | \"calendar\"\n | \"treemap\"\n | \"sunburst\";\n\n/** The engine that draws a given type. */\nexport type ChartEngine = \"recharts\" | \"nivo\";\n\n/** Nivo renderer; only the Nivo types honour it (Recharts is SVG only). */\nexport type ChartRenderer = \"svg\" | \"canvas\";\n\n/** One category with a numeric value per series. */\nexport type ChartRow = Record<string, string | number | null | undefined>;\n\n/** One series of points; x may be a category or a number, y a number. */\nexport interface ChartPoint {\n x: string | number;\n y: number | null;\n}\nexport interface ChartSeries {\n id: string | number;\n data: ChartPoint[];\n}\n\n/**\n * What to write on each arc of a pie or donut.\n *\n * `percent` is the default for both, because the question a reader asks of a\n * pie is almost always \"what share is that\", and reading it off the legend\n * slice by slice is the work the chart was supposed to do for them. `value`\n * writes the number itself, through `valueFormatter` when one is given. `none`\n * leaves the arcs bare for a chart that is decorative or has its own labelling.\n *\n * Arcs too thin to hold their text are left unlabelled whatever this says; see\n * `ARC_LABEL_MIN_FRACTION` in recharts-charts.tsx.\n */\nexport type ChartLabels = \"none\" | \"value\" | \"percent\";\n\n/** One slice of a pie, donut or funnel. */\nexport interface ChartSlice {\n id: string | number;\n label?: string;\n value: number;\n}\n\n/**\n * A categorical matrix: `values[r][c]` is the cell at `rows[r]` × `columns[c]`.\n * The shape a correlation matrix, a confusion matrix or a day × hour grid is\n * already in, so it needs no pivot at the call site. Short rows are padded\n * with `null` (drawn as the empty colour) rather than treated as zero.\n */\nexport interface ChartMatrix {\n rows: string[];\n columns: string[];\n values: Array<Array<number | null | undefined>>;\n}\n\n/** One day of a calendar heatmap. */\nexport interface ChartDay {\n day: string;\n value: number;\n}\n\n/** A Nivo tree node for treemap and sunburst. */\nexport interface ChartTree {\n id?: string | number;\n name?: string;\n value?: number;\n children?: ChartTree[];\n [key: string]: unknown;\n}\n\n/** The data type accepted for each chart type. */\nexport type ChartDataFor<T extends ChartType> = T extends \"bar\" | \"radar\"\n ? ChartRow[] | ChartSeries[]\n : T extends \"line\" | \"area\"\n ? ChartSeries[] | ChartRow[]\n : T extends \"pie\" | \"donut\" | \"funnel\"\n ? ChartSlice[]\n : T extends \"heatmap\"\n ? ChartSeries[] | ChartMatrix\n : T extends \"scatter\" | \"scatterplot\"\n ? ChartSeries[]\n : T extends \"calendar\"\n ? ChartDay[]\n : T extends \"treemap\" | \"sunburst\"\n ? ChartTree\n : never;\n\n/**\n * Per-series presentation, keyed by series id (the `keys` of a row chart, the\n * `id` of a series or slice). Colours default to `var(--ds-viz-1..n)` in key\n * order, so the same category index gets the same colour in every app; set\n * `color` only to pin a category to a semantic colour, and then only to a\n * token (`var(--ds-success)`), never a literal.\n */\nexport type ChartConfig = Record<\n string,\n {\n label?: React.ReactNode;\n icon?: React.ComponentType;\n color?: string;\n }\n>;\n\n/** Which continuous scale a heatmap or calendar uses. */\nexport type ChartScale = \"sequential\" | \"diverging\";\n\nexport const RECHARTS_TYPES: ReadonlySet<ChartType> = new Set<ChartType>([\n \"bar\",\n \"line\",\n \"area\",\n \"pie\",\n \"donut\",\n \"scatter\",\n \"scatterplot\",\n \"radar\",\n \"funnel\",\n]);\n\nexport const NIVO_TYPES: ReadonlySet<ChartType> = new Set<ChartType>([\n \"heatmap\",\n \"calendar\",\n \"treemap\",\n \"sunburst\",\n]);\n\n/** The engine the package uses for a chart type. */\nexport function chartEngine(type: ChartType): ChartEngine {\n return NIVO_TYPES.has(type) ? \"nivo\" : \"recharts\";\n}\n"],"mappings":";;AAsJA,MAAa,iCAAyC,IAAI,IAAe;CACvE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAa,6BAAqC,IAAI,IAAe;CACnE;CACA;CACA;CACA;AACF,CAAC;;AAGD,SAAgB,YAAY,MAA8B;CACxD,OAAO,WAAW,IAAI,IAAI,IAAI,SAAS;AACzC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Checkbox } from "@base-ui/react/checkbox";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
//#region src/components/checkbox.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Checkbox.
|
|
7
|
+
*
|
|
8
|
+
* Base UI renders a `<span role="checkbox">` with a hidden `<input>` beside
|
|
9
|
+
* it, so it submits with forms and takes `checked`/`defaultChecked`. The
|
|
10
|
+
* indicator only mounts while checked or indeterminate; the icon inside it is
|
|
11
|
+
* a lucide Check, or a Minus when `indeterminate` is set.
|
|
12
|
+
*
|
|
13
|
+
* The 16px box takes half the small radius: the 8px ladder step would round
|
|
14
|
+
* it into a circle.
|
|
15
|
+
*/
|
|
16
|
+
export interface CheckboxProps extends React.ComponentProps<typeof Checkbox.Root> {}
|
|
17
|
+
declare function Checkbox$1({ className, indeterminate, ...props }: CheckboxProps): React.JSX.Element;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { Checkbox$1 as Checkbox };
|
|
20
|
+
//# sourceMappingURL=checkbox.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { Check, Minus } from "lucide-react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import { Checkbox } from "@base-ui/react/checkbox";
|
|
7
|
+
//#region src/components/checkbox.tsx
|
|
8
|
+
function Checkbox$1({ className, indeterminate, ...props }) {
|
|
9
|
+
return /* @__PURE__ */ jsx(Checkbox.Root, {
|
|
10
|
+
"data-slot": "checkbox",
|
|
11
|
+
indeterminate,
|
|
12
|
+
className: cn("peer inline-flex size-4 shrink-0 items-center justify-center rounded-[calc(var(--ds-radius-sm)/2)] border", "border-[var(--ds-input)] bg-[var(--ds-background)]", "transition-[background-color,border-color,box-shadow] duration-[var(--ds-duration-fast)] ease-[var(--ds-ease-out)]", "outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--ds-ring)]/40", "data-[checked]:border-[var(--ds-primary)] data-[checked]:bg-[var(--ds-primary)] data-[checked]:text-[color:var(--ds-primary-foreground)]", "data-[indeterminate]:border-[var(--ds-primary)] data-[indeterminate]:bg-[var(--ds-primary)] data-[indeterminate]:text-[color:var(--ds-primary-foreground)]", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", "aria-invalid:border-[var(--ds-destructive)] aria-invalid:ring-[3px] aria-invalid:ring-[var(--ds-destructive)]/20", className),
|
|
13
|
+
...props,
|
|
14
|
+
children: /* @__PURE__ */ jsx(Checkbox.Indicator, {
|
|
15
|
+
"data-slot": "checkbox-indicator",
|
|
16
|
+
className: "flex items-center justify-center text-current [&_svg]:size-3.5 [&_svg]:shrink-0",
|
|
17
|
+
children: indeterminate ? /* @__PURE__ */ jsx(Minus, { strokeWidth: 3 }) : /* @__PURE__ */ jsx(Check, { strokeWidth: 3 })
|
|
18
|
+
})
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { Checkbox$1 as Checkbox };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=checkbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox.js","names":["Checkbox","BaseCheckbox"],"sources":["../../src/components/checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { Check, Minus } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Checkbox.\n *\n * Base UI renders a `<span role=\"checkbox\">` with a hidden `<input>` beside\n * it, so it submits with forms and takes `checked`/`defaultChecked`. The\n * indicator only mounts while checked or indeterminate; the icon inside it is\n * a lucide Check, or a Minus when `indeterminate` is set.\n *\n * The 16px box takes half the small radius: the 8px ladder step would round\n * it into a circle.\n */\nexport interface CheckboxProps extends React.ComponentProps<typeof BaseCheckbox.Root> {}\n\nfunction Checkbox({ className, indeterminate, ...props }: CheckboxProps) {\n return (\n <BaseCheckbox.Root\n data-slot=\"checkbox\"\n indeterminate={indeterminate}\n className={cn(\n \"peer inline-flex size-4 shrink-0 items-center justify-center rounded-[calc(var(--ds-radius-sm)/2)] border\",\n \"border-[var(--ds-input)] bg-[var(--ds-background)]\",\n \"transition-[background-color,border-color,box-shadow] duration-[var(--ds-duration-fast)] ease-[var(--ds-ease-out)]\",\n \"outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--ds-ring)]/40\",\n \"data-[checked]:border-[var(--ds-primary)] data-[checked]:bg-[var(--ds-primary)] data-[checked]:text-[color:var(--ds-primary-foreground)]\",\n \"data-[indeterminate]:border-[var(--ds-primary)] data-[indeterminate]:bg-[var(--ds-primary)] data-[indeterminate]:text-[color:var(--ds-primary-foreground)]\",\n \"data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n \"aria-invalid:border-[var(--ds-destructive)] aria-invalid:ring-[3px] aria-invalid:ring-[var(--ds-destructive)]/20\",\n className,\n )}\n {...props}\n >\n <BaseCheckbox.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"flex items-center justify-center text-current [&_svg]:size-3.5 [&_svg]:shrink-0\"\n >\n {indeterminate ? <Minus strokeWidth={3} /> : <Check strokeWidth={3} />}\n </BaseCheckbox.Indicator>\n </BaseCheckbox.Root>\n );\n}\n\nexport { Checkbox };\n"],"mappings":";;;;;;;AAoBA,SAASA,WAAS,EAAE,WAAW,eAAe,GAAG,SAAwB;CACvE,OACE,oBAACC,SAAa,MAAd;EACE,aAAU;EACK;EACf,WAAW,GACT,6GACA,sDACA,sHACA,gFACA,4IACA,8JACA,kEACA,oHACA,SACF;EACA,GAAI;EAEJ,UAAA,oBAACA,SAAa,WAAd;GACE,aAAU;GACV,WAAU;GAET,UAAA,gBAAgB,oBAAC,OAAD,EAAO,aAAa,EAAI,CAAA,IAAI,oBAAC,OAAD,EAAO,aAAa,EAAI,CAAA;EAC/C,CAAA;CACP,CAAA;AAEvB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { VariantProps } from "class-variance-authority";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
//#region src/components/chip.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Chip — a pill for filters, tags and selected values. Unlike Badge it keeps
|
|
7
|
+
* sentence case and the body font.
|
|
8
|
+
*/
|
|
9
|
+
declare const chipVariants: (props?: ({
|
|
10
|
+
variant?: "default" | "outline" | "accent" | null | undefined;
|
|
11
|
+
size?: "default" | "sm" | null | undefined;
|
|
12
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
|
+
export interface ChipProps extends React.ComponentProps<"span">, VariantProps<typeof chipVariants> {}
|
|
14
|
+
declare function Chip({ className, variant, size, ...props }: ChipProps): React.JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Chip, chipVariants };
|
|
17
|
+
//# sourceMappingURL=chip.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
//#region src/components/chip.tsx
|
|
7
|
+
/**
|
|
8
|
+
* Chip — a pill for filters, tags and selected values. Unlike Badge it keeps
|
|
9
|
+
* sentence case and the body font.
|
|
10
|
+
*/
|
|
11
|
+
const chipVariants = /* @__PURE__ */ cva([
|
|
12
|
+
"inline-flex items-center gap-1.5 whitespace-nowrap border font-medium",
|
|
13
|
+
"rounded-[var(--ds-radius-full)]",
|
|
14
|
+
"transition-[background-color,border-color,color]",
|
|
15
|
+
"duration-[var(--ds-duration-fast)] ease-[var(--ds-ease-out)]",
|
|
16
|
+
"[&_svg]:shrink-0"
|
|
17
|
+
], {
|
|
18
|
+
variants: {
|
|
19
|
+
variant: {
|
|
20
|
+
default: "bg-[var(--ds-hover)] border-[var(--ds-border-subtle)] text-[color:var(--ds-muted-foreground)]",
|
|
21
|
+
accent: "bg-[var(--ds-primary-soft)] border-[var(--ds-ring)] text-[color:var(--ds-primary)]",
|
|
22
|
+
outline: "bg-transparent border-[var(--ds-border)] text-[color:var(--ds-muted-foreground)]"
|
|
23
|
+
},
|
|
24
|
+
size: {
|
|
25
|
+
default: "px-2.5 py-1 text-[length:var(--ds-text-caption)] [&_svg]:size-3.5",
|
|
26
|
+
sm: "px-2 py-0.5 text-[length:var(--ds-text-caption-sm)] [&_svg]:size-3"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
variant: "default",
|
|
31
|
+
size: "default"
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
function Chip({ className, variant, size, ...props }) {
|
|
35
|
+
return /* @__PURE__ */ jsx("span", {
|
|
36
|
+
"data-slot": "chip",
|
|
37
|
+
className: cn(chipVariants({
|
|
38
|
+
variant,
|
|
39
|
+
size
|
|
40
|
+
}), className),
|
|
41
|
+
...props
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { Chip, chipVariants };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=chip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chip.js","names":[],"sources":["../../src/components/chip.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\n/**\n * Chip — a pill for filters, tags and selected values. Unlike Badge it keeps\n * sentence case and the body font.\n */\nconst chipVariants = /* @__PURE__ */ cva(\n [\n \"inline-flex items-center gap-1.5 whitespace-nowrap border font-medium\",\n \"rounded-[var(--ds-radius-full)]\",\n \"transition-[background-color,border-color,color]\",\n \"duration-[var(--ds-duration-fast)] ease-[var(--ds-ease-out)]\",\n \"[&_svg]:shrink-0\",\n ],\n {\n variants: {\n variant: {\n default:\n \"bg-[var(--ds-hover)] border-[var(--ds-border-subtle)] text-[color:var(--ds-muted-foreground)]\",\n accent: \"bg-[var(--ds-primary-soft)] border-[var(--ds-ring)] text-[color:var(--ds-primary)]\",\n outline:\n \"bg-transparent border-[var(--ds-border)] text-[color:var(--ds-muted-foreground)]\",\n },\n size: {\n default: \"px-2.5 py-1 text-[length:var(--ds-text-caption)] [&_svg]:size-3.5\",\n sm: \"px-2 py-0.5 text-[length:var(--ds-text-caption-sm)] [&_svg]:size-3\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nexport interface ChipProps\n extends React.ComponentProps<\"span\">, VariantProps<typeof chipVariants> {}\n\nfunction Chip({ className, variant, size, ...props }: ChipProps) {\n return (\n <span data-slot=\"chip\" className={cn(chipVariants({ variant, size }), className)} {...props} />\n );\n}\n\nexport { Chip, chipVariants };\n"],"mappings":";;;;;;;;;;AAUA,MAAM,eAA+B,oBACnC;CACE;CACA;CACA;CACA;CACA;AACF,GACA;CACE,UAAU;EACR,SAAS;GACP,SACE;GACF,QAAQ;GACR,SACE;EACJ;EACA,MAAM;GACJ,SAAS;GACT,IAAI;EACN;CACF;CACA,iBAAiB;EACf,SAAS;EACT,MAAM;CACR;AACF,CACF;AAKA,SAAS,KAAK,EAAE,WAAW,SAAS,MAAM,GAAG,SAAoB;CAC/D,OACE,oBAAC,QAAD;EAAM,aAAU;EAAO,WAAW,GAAG,aAAa;GAAE;GAAS;EAAK,CAAC,GAAG,SAAS;EAAG,GAAI;CAAQ,CAAA;AAElG"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Combobox } from "@base-ui/react/combobox";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
//#region src/components/combobox.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Combobox: a filterable text input with a listbox popup, on Base UI.
|
|
7
|
+
*
|
|
8
|
+
* Give the Root `items` (an array, or `[{ value, label }]`) and render the
|
|
9
|
+
* list with `<ComboboxList>{(item) => <ComboboxItem value={item} />}</ComboboxList>`;
|
|
10
|
+
* Base UI filters `items` against the input as the user types. Without
|
|
11
|
+
* `items` nothing is filtered and `ComboboxEmpty` never shows.
|
|
12
|
+
*
|
|
13
|
+
* - `ComboboxInput` is our `Input` with a trailing open/close trigger and,
|
|
14
|
+
* with `clearable`, an X button that clears the value.
|
|
15
|
+
* - `ComboboxContent` composes Portal + Positioner + Popup + List so
|
|
16
|
+
* consumers write one element; positioning props go to the Positioner.
|
|
17
|
+
* - Multiple selection: set `multiple` on the Root and wrap `ComboboxValue`
|
|
18
|
+
* (rendering a `ComboboxChip` per value) plus `ComboboxInput` in
|
|
19
|
+
* `ComboboxChips`. Inside `ComboboxChips` the input drops its own frame;
|
|
20
|
+
* the chips container carries the field look and anchors the popup.
|
|
21
|
+
* - `useComboboxFilter` is Base UI's `useFilter` for external filtering via
|
|
22
|
+
* `filteredItems`.
|
|
23
|
+
*
|
|
24
|
+
* `onValueChange` receives `(value, eventDetails)`; `onInputValueChange`
|
|
25
|
+
* reports the typed text.
|
|
26
|
+
*/
|
|
27
|
+
declare function Combobox$1<Value, Multiple extends boolean | undefined = false, Item = Value>(props: Combobox.Root.Props<Value, Multiple, Item>): import("react").JSX.Element;
|
|
28
|
+
declare function ComboboxTrigger({ className, children, ...props }: Combobox.Trigger.Props): import("react").JSX.Element;
|
|
29
|
+
declare function ComboboxClear({ className, children, ...props }: Combobox.Clear.Props): import("react").JSX.Element;
|
|
30
|
+
export interface ComboboxInputProps extends Combobox.Input.Props {
|
|
31
|
+
/** Show an X button that clears the selection while there is one. */
|
|
32
|
+
clearable?: boolean;
|
|
33
|
+
/** Class for the wrapper that holds the input and its buttons. */
|
|
34
|
+
wrapperClassName?: string;
|
|
35
|
+
}
|
|
36
|
+
declare function ComboboxInput({ className, clearable, wrapperClassName, ...props }: ComboboxInputProps): import("react").JSX.Element;
|
|
37
|
+
declare function ComboboxValue(props: Combobox.Value.Props): import("react").JSX.Element;
|
|
38
|
+
export interface ComboboxChipsProps extends Combobox.Chips.Props {
|
|
39
|
+
/** Class for the inner chip row; `className` styles the field frame. */
|
|
40
|
+
chipsClassName?: string;
|
|
41
|
+
}
|
|
42
|
+
declare function ComboboxChips({ className, chipsClassName, children, ...props }: ComboboxChipsProps): import("react").JSX.Element;
|
|
43
|
+
export interface ComboboxChipProps extends Combobox.Chip.Props {
|
|
44
|
+
/** Hide the remove button. */
|
|
45
|
+
removable?: boolean;
|
|
46
|
+
}
|
|
47
|
+
declare function ComboboxChip({ className, children, removable, ...props }: ComboboxChipProps): import("react").JSX.Element;
|
|
48
|
+
type PositionerProps = Pick<Combobox.Positioner.Props, "side" | "align" | "sideOffset" | "alignOffset" | "anchor" | "collisionBoundary" | "collisionPadding" | "collisionAvoidance" | "sticky" | "positionMethod">;
|
|
49
|
+
export interface ComboboxContentProps extends Omit<Combobox.Popup.Props, "children">, PositionerProps {
|
|
50
|
+
/** Items, or a render function called per filtered item (needs `items` on the Root). */
|
|
51
|
+
children?: Combobox.List.Props["children"];
|
|
52
|
+
/**
|
|
53
|
+
* Shown (via `ComboboxEmpty`, above the list) when nothing matches the query.
|
|
54
|
+
* Needs `items` on the Root.
|
|
55
|
+
*/
|
|
56
|
+
empty?: ReactNode;
|
|
57
|
+
/** Class for the inner List element. */
|
|
58
|
+
listClassName?: string;
|
|
59
|
+
/** Keep the popup mounted in the DOM while hidden. */
|
|
60
|
+
keepMounted?: boolean;
|
|
61
|
+
/** Where to portal the popup; defaults to `<body>`. */
|
|
62
|
+
container?: Combobox.Portal.Props["container"];
|
|
63
|
+
}
|
|
64
|
+
declare function ComboboxContent({ className, children, empty, listClassName, side, align, sideOffset, alignOffset, anchor, collisionBoundary, collisionPadding, collisionAvoidance, sticky, positionMethod, keepMounted, container, ...props }: ComboboxContentProps): import("react").JSX.Element;
|
|
65
|
+
declare function ComboboxItem({ className, children, ...props }: Combobox.Item.Props): import("react").JSX.Element;
|
|
66
|
+
/** Renders per filtered item; use inside a `ComboboxGroup` given `items`, or for a flat list pass a function as `ComboboxContent` children instead. */
|
|
67
|
+
declare function ComboboxCollection(props: Combobox.Collection.Props): import("react").JSX.Element;
|
|
68
|
+
declare function ComboboxEmpty({ className, ...props }: Combobox.Empty.Props): import("react").JSX.Element;
|
|
69
|
+
declare function ComboboxStatus({ className, ...props }: Combobox.Status.Props): import("react").JSX.Element;
|
|
70
|
+
declare function ComboboxGroup({ className, ...props }: Combobox.Group.Props): import("react").JSX.Element;
|
|
71
|
+
declare function ComboboxGroupLabel({ className, ...props }: Combobox.GroupLabel.Props): import("react").JSX.Element;
|
|
72
|
+
declare function ComboboxSeparator({ className, ...props }: Combobox.Separator.Props): import("react").JSX.Element;
|
|
73
|
+
declare const useComboboxFilter: typeof Combobox.useFilter;
|
|
74
|
+
//#endregion
|
|
75
|
+
export { Combobox$1 as Combobox, ComboboxChip, ComboboxChips, ComboboxClear, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, ComboboxItem, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, useComboboxFilter };
|
|
76
|
+
//# sourceMappingURL=combobox.d.ts.map
|