@neuronection/assistant-ui 0.2.0 → 0.3.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/CHANGELOG.md ADDED
@@ -0,0 +1,40 @@
1
+ # @neuronection/assistant-ui
2
+
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`e8a56d3`](https://github.com/neuronection/assistant-ui/commit/e8a56d33427fc2e8e03784fe7959037f24efb95a) Thanks [@constLiakos](https://github.com/constLiakos)! - Add the six components career-assistant's Phase-2 adoption needs, all shared
8
+ with health-assistant (catalog T1): `ChipInput`, `ChipList` (superset with
9
+ variants + clickable chips), `Table` (tokenized, with empty state), `RangeBar`
10
+ (with optional `label`/`valueLabel`), `ScaleSlider` (+ `scaleColorForValue`),
11
+ and `DatePicker` (Radix popover calendar with days/months/years views, min/max,
12
+ allowClear, and a roving-tabindex arrow-key day grid — an a11y upgrade over
13
+ both app copies). New dependency: `date-fns`.
14
+
15
+ ### Patch Changes
16
+
17
+ - [`e5252f2`](https://github.com/neuronection/assistant-ui/commit/e5252f26d6f8732a2f5ba4a3fe849b4df50b30c2) Thanks [@constLiakos](https://github.com/constLiakos)! - Ship CHANGELOG.md inside the published package so consuming apps (and their agents) can read what changed without visiting GitHub.
18
+
19
+ ## 0.2.0
20
+
21
+ ### Minor Changes
22
+
23
+ - [`ec2a8bf`](https://github.com/neuronection/assistant-ui/commit/ec2a8bf7d49bb96435990e9b8cca4d74fc31748b) Thanks [@constLiakos](https://github.com/constLiakos)! - Phase 1: 16 new modules for study-assistant full adoption
24
+
25
+ - PopoverButton: self-contained trigger+panel popover on Radix (hover-open, lazy children, closeSignal, controlled mode)
26
+ - InfoButton + FieldLabel: info affordances with popover help
27
+ - Menu: Radix DropdownMenu primitives (Menu, MenuItem, MenuContent…) + items-driven ActionMenu
28
+ - ContextMenu: coordinate-anchored menu with full Radix keyboard/typeahead semantics
29
+ - Combobox + ComboboxMulti: WAI-ARIA listbox pattern, grouping, async mode (onSearchChange + loading), multi-select, clearable
30
+ - FormModal: form-in-modal shell (submit/cancel/busy/disabled) on Modal primitives
31
+ - Wizard + Stepper: wizard state machine with per-step validation gates, modal and drawer variants; dots/labels steppers
32
+ - Ported from study-assistant ui/: CheckIndicator, SearchInput, ExpandableSearch, SelectionBar, ViewToggle, ErrorBanner, UndoNotice, Marquee (useMarquee/MarqueeBand/MarqueeSurface)
33
+
34
+ All components: forwardRef where DOM-emitting, semantic --as-\* tokens only, data-as hooks, English-default label props, keyboard-nav + axe tests.
35
+
36
+ ## 0.1.0
37
+
38
+ ### Minor Changes
39
+
40
+ - [`a211003`](https://github.com/neuronection/assistant-ui/commit/a211003348a5248f65a7995806500325408b6f92) Thanks [@constLiakos](https://github.com/constLiakos)! - Initial release (Phase 0): Button, Badge, Card, Modal, Popover, Tooltip + InfoTooltip, Input, Spinner, EmptyState, ConfirmationModal, Portal, ThemeScope and `cn()` — CSS-variable design tokens, precompiled `styles.css`, React 18/19 and Tailwind 3/4 compatible.
package/README.md CHANGED
@@ -65,11 +65,31 @@ without configuration. Do **not** add this package to your Tailwind
65
65
 
66
66
  ## Components
67
67
 
68
- Button, Badge, Card (+Header/Title/Description/Content/Footer), Modal
69
- (+Trigger/Header/Title/Description/Footer/Close), Popover, Tooltip +
70
- InfoTooltip, Input, Spinner, EmptyState, ConfirmationModal, Portal,
71
- ThemeScope, `cn()`. Full props in the
72
- [gallery](https://neuronection.github.io/assistant-ui/) (Ladle build).
68
+ Every module has its own entry point (`import { Menu } from
69
+ '@neuronection/assistant-ui/menu'`) and everything is re-exported from the
70
+ package root. Authoritative props for your installed version: the `.d.ts`
71
+ files in the package's `dist/`. Visual reference:
72
+ [gallery](https://neuronection.github.io/assistant-ui/).
73
+
74
+ | Module | Exports |
75
+ |---|---|
76
+ | `button` / `badge` / `card` | `Button`, `buttonVariants` · `Badge`, `badgeVariants` · `Card`, `CardHeader/Title/Description/Content/Footer` |
77
+ | `modal` / `confirmation-modal` / `form-modal` | `Modal` + parts, `modalContentVariants` · `ConfirmationModal` · `FormModal` (form-in-modal shell) |
78
+ | `popover` / `popover-button` | compound Radix `Popover` + parts · `PopoverButton` (self-contained trigger + panel, hover-open, lazy children, `closeSignal`) |
79
+ | `menu` / `context-menu` | `Menu`, `MenuTrigger/Content/Item/Separator/Label`, `ActionMenu` (items-driven) · `ContextMenu` (coordinate-anchored, `{x, y, items, onClose}`) |
80
+ | `combobox` | `Combobox`, `ComboboxMulti` — async mode (`onSearchChange` + `loading`), grouping, full keyboard nav |
81
+ | `tooltip` | `Tooltip` + parts, `InfoTooltip` |
82
+ | `wizard` | `Wizard` (steps config + `renderStep`, per-step validation gates, modal/drawer variants), `Stepper` (dots/labels) |
83
+ | `input` / `search-input` / `expandable-search` | `Input` (label/hint/error wiring) · `SearchInput` · `ExpandableSearch` |
84
+ | `chip-input` / `chip-list` | `ChipInput` (Enter/comma commit, paste-splits, Backspace-removes) · `ChipList` (variant pills, clickable, removable) |
85
+ | `date-picker` | `DatePicker` (popover calendar: days/months/years views, min/max, `allowClear`, arrow-key day grid) |
86
+ | `range-bar` / `scale-slider` | `RangeBar` (low–high band + value dot) · `ScaleSlider` (+ `scaleColorForValue`) |
87
+ | `table` | `Table` (headers/rows, built-in empty state) |
88
+ | `check-indicator` / `selection-bar` / `view-toggle` | `CheckIndicator` (tri-state) · `SelectionBar` (bulk-select bar) · `ViewToggle` (grid/list) |
89
+ | `error-banner` / `undo-notice` / `empty-state` / `spinner` | presentational feedback: alert banner with `action` slot · undo toast · `EmptyState` · `Spinner` |
90
+ | `info-button` / `field-label` | `InfoButton` (info popover) · `FieldLabel` (label + info affordance) |
91
+ | `marquee` | `useMarquee`, `MarqueeSurface`, `MarqueeBand` (rubber-band selection) |
92
+ | `portal` / `theme-scope` / `tokens` | `Portal` · `ThemeScope` · token name lists + types |
73
93
 
74
94
  API rules: controlled-first, `className` merges (never replaces), `asChild`
75
95
  where it makes sense, refs forwarded everywhere, English label props with
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+
3
+ interface ChipInputProps extends Omit<React.ComponentProps<'div'>, 'onChange'> {
4
+ value: string[];
5
+ onChange: (value: string[]) => void;
6
+ placeholder?: string;
7
+ separators?: string[];
8
+ inputLabel?: string;
9
+ removeLabel?: string;
10
+ disabled?: boolean;
11
+ }
12
+ declare const ChipInput: React.ForwardRefExoticComponent<Omit<ChipInputProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
13
+
14
+ export { ChipInput, type ChipInputProps };
@@ -0,0 +1,3 @@
1
+ export { ChipInput } from './chunk-TPLQL62V.js';
2
+ //# sourceMappingURL=chip-input.js.map
3
+ //# sourceMappingURL=chip-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chip-input.js"}
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+
3
+ type ChipVariant = 'neutral' | 'primary' | 'success' | 'warning' | 'danger';
4
+ interface ChipListProps extends React.ComponentProps<'div'> {
5
+ items: ReadonlyArray<string | null | undefined>;
6
+ onRemove?: (item: string) => void;
7
+ onItemClick?: (value: string, index: number) => void;
8
+ variant?: ChipVariant;
9
+ emptyText?: string;
10
+ showChevron?: boolean;
11
+ removeLabel?: string;
12
+ }
13
+ declare const ChipList: React.ForwardRefExoticComponent<Omit<ChipListProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
14
+
15
+ export { ChipList, type ChipListProps, type ChipVariant };
@@ -0,0 +1,3 @@
1
+ export { ChipList } from './chunk-XLD2BPTT.js';
2
+ //# sourceMappingURL=chip-list.js.map
3
+ //# sourceMappingURL=chip-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chip-list.js"}
@@ -0,0 +1,357 @@
1
+ import { Popover, PopoverTrigger, PopoverContent } from './chunk-CI56SSO2.js';
2
+ import { cn } from './chunk-BLJWR4ZV.js';
3
+ import * as React from 'react';
4
+ import { parseISO, isValid, startOfDay, startOfMonth, endOfMonth, startOfWeek, endOfWeek, addDays, format, isSameDay, isSameMonth, setMonth, setYear, subMonths, subYears, addMonths, addYears } from 'date-fns';
5
+ import { Calendar, X, ChevronLeft, ChevronDown, ChevronRight } from 'lucide-react';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+
8
+ function dayKey(date) {
9
+ return format(date, "yyyy-MM-dd");
10
+ }
11
+ var DatePicker = React.forwardRef(
12
+ function DatePicker2({
13
+ value,
14
+ onChange,
15
+ onClear,
16
+ allowClear = false,
17
+ clearLabel = "Clear",
18
+ placeholder = "Select date",
19
+ displayFormat = "dd/MM/yyyy",
20
+ minDate,
21
+ maxDate,
22
+ weekStartsOn = 1,
23
+ disabled = false,
24
+ required,
25
+ id,
26
+ name,
27
+ label = "Choose date",
28
+ prevLabel = "Previous",
29
+ nextLabel = "Next",
30
+ className,
31
+ panelClassName
32
+ }, ref) {
33
+ const autoId = React.useId();
34
+ const hiddenId = id ?? `date-picker-${autoId}`;
35
+ const [open, setOpen] = React.useState(false);
36
+ const [viewMode, setViewMode] = React.useState("days");
37
+ const [currentDate, setCurrentDate] = React.useState(() => /* @__PURE__ */ new Date());
38
+ const [focusedDay, setFocusedDay] = React.useState(() => /* @__PURE__ */ new Date());
39
+ const [yearPage, setYearPage] = React.useState(() => (/* @__PURE__ */ new Date()).getFullYear());
40
+ const gridRef = React.useRef(null);
41
+ const selectedDate = React.useMemo(() => {
42
+ if (!value) return null;
43
+ const parsed = parseISO(value);
44
+ return isValid(parsed) ? parsed : null;
45
+ }, [value]);
46
+ const isDisabled = React.useCallback(
47
+ (date) => Boolean(minDate && date < startOfDay(minDate)) || Boolean(maxDate && date > startOfDay(maxDate)),
48
+ [minDate, maxDate]
49
+ );
50
+ const handleOpenChange = (next) => {
51
+ setOpen(next);
52
+ if (next) {
53
+ const base = selectedDate ?? /* @__PURE__ */ new Date();
54
+ setCurrentDate(base);
55
+ setFocusedDay(base);
56
+ setYearPage(base.getFullYear());
57
+ setViewMode("days");
58
+ }
59
+ };
60
+ const handleSelect = (date) => {
61
+ if (isDisabled(date)) return;
62
+ onChange(format(date, "yyyy-MM-dd"));
63
+ setOpen(false);
64
+ };
65
+ const handleClear = (event) => {
66
+ event.stopPropagation();
67
+ onChange("");
68
+ onClear?.();
69
+ setOpen(false);
70
+ };
71
+ const moveFocus = (next) => {
72
+ if (isDisabled(next)) return;
73
+ setFocusedDay(next);
74
+ setCurrentDate(
75
+ (current) => isSameMonth(current, next) ? current : startOfMonth(next)
76
+ );
77
+ };
78
+ const handleGridKeyDown = (event) => {
79
+ const step = event.key === "ArrowLeft" ? -1 : event.key === "ArrowRight" ? 1 : event.key === "ArrowUp" ? -7 : event.key === "ArrowDown" ? 7 : 0;
80
+ if (step !== 0) {
81
+ event.preventDefault();
82
+ moveFocus(addDays(focusedDay, step));
83
+ return;
84
+ }
85
+ if (event.key === "PageUp" || event.key === "PageDown") {
86
+ event.preventDefault();
87
+ const direction = event.key === "PageUp" ? -1 : 1;
88
+ moveFocus(addMonths(focusedDay, direction));
89
+ return;
90
+ }
91
+ if (event.key === "Home") {
92
+ event.preventDefault();
93
+ moveFocus(startOfMonth(focusedDay));
94
+ } else if (event.key === "End") {
95
+ event.preventDefault();
96
+ moveFocus(endOfMonth(focusedDay));
97
+ }
98
+ };
99
+ React.useEffect(() => {
100
+ if (!open || viewMode !== "days") return;
101
+ const target = gridRef.current?.querySelector(
102
+ `[data-day="${dayKey(focusedDay)}"]`
103
+ );
104
+ target?.focus();
105
+ }, [open, viewMode, focusedDay]);
106
+ const monthStart = startOfMonth(currentDate);
107
+ const monthEnd = endOfMonth(monthStart);
108
+ const gridStart = startOfWeek(monthStart, { weekStartsOn });
109
+ const gridEnd = endOfWeek(monthEnd, { weekStartsOn });
110
+ const weeks = [];
111
+ let cursor = gridStart;
112
+ while (cursor <= gridEnd) {
113
+ const week = [];
114
+ for (let i = 0; i < 7; i++) {
115
+ week.push(cursor);
116
+ cursor = addDays(cursor, 1);
117
+ }
118
+ weeks.push(week);
119
+ }
120
+ const today = /* @__PURE__ */ new Date();
121
+ const weekdayStart = startOfWeek(/* @__PURE__ */ new Date(), { weekStartsOn });
122
+ const headerTitle = viewMode === "days" ? format(currentDate, "MMMM yyyy") : viewMode === "months" ? format(currentDate, "yyyy") : `${Math.floor(yearPage / 12) * 12} \u2013 ${Math.floor(yearPage / 12) * 12 + 11}`;
123
+ const handlePrev = () => {
124
+ if (viewMode === "days") setCurrentDate(subMonths(currentDate, 1));
125
+ else if (viewMode === "months") setCurrentDate(subYears(currentDate, 1));
126
+ else setYearPage(yearPage - 12);
127
+ };
128
+ const handleNext = () => {
129
+ if (viewMode === "days") setCurrentDate(addMonths(currentDate, 1));
130
+ else if (viewMode === "months") setCurrentDate(addYears(currentDate, 1));
131
+ else setYearPage(yearPage + 12);
132
+ };
133
+ const toggleViewMode = () => {
134
+ if (viewMode !== "years") setViewMode("years");
135
+ };
136
+ const navButtonClass = "cursor-pointer rounded-[var(--as-radius-sm)] p-1.5 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-muted)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]";
137
+ return /* @__PURE__ */ jsx(
138
+ "div",
139
+ {
140
+ ref,
141
+ "data-as": "date-picker",
142
+ className: cn("relative w-full", className),
143
+ children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
144
+ /* @__PURE__ */ jsxs("span", { className: "relative inline-flex w-full", children: [
145
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, disabled, children: /* @__PURE__ */ jsxs(
146
+ "button",
147
+ {
148
+ type: "button",
149
+ "aria-label": label,
150
+ className: cn(
151
+ "flex h-9 w-full items-center gap-2 rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2 text-left text-sm text-[var(--as-fg)] transition-colors hover:border-[var(--as-fg)]/30 focus-visible:border-[var(--as-focus-ring)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50",
152
+ allowClear && selectedDate && !disabled && "pr-8"
153
+ ),
154
+ children: [
155
+ /* @__PURE__ */ jsx(
156
+ Calendar,
157
+ {
158
+ className: "size-4 shrink-0 text-[var(--as-muted-fg)]",
159
+ "aria-hidden": true
160
+ }
161
+ ),
162
+ /* @__PURE__ */ jsx(
163
+ "span",
164
+ {
165
+ className: cn(
166
+ "flex-1 truncate text-left",
167
+ !selectedDate && "text-[var(--as-muted-fg)]"
168
+ ),
169
+ children: selectedDate ? format(selectedDate, displayFormat) : placeholder
170
+ }
171
+ )
172
+ ]
173
+ }
174
+ ) }),
175
+ allowClear && selectedDate && !disabled ? /* @__PURE__ */ jsx(
176
+ "button",
177
+ {
178
+ type: "button",
179
+ "aria-label": clearLabel,
180
+ onClick: handleClear,
181
+ className: "absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer rounded-full p-0.5 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-muted)] hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
182
+ children: /* @__PURE__ */ jsx(X, { className: "size-3.5", "aria-hidden": true })
183
+ }
184
+ ) : null
185
+ ] }),
186
+ /* @__PURE__ */ jsx(
187
+ "input",
188
+ {
189
+ type: "hidden",
190
+ id: hiddenId,
191
+ name: name ?? hiddenId,
192
+ value: value ?? "",
193
+ required
194
+ }
195
+ ),
196
+ /* @__PURE__ */ jsxs(
197
+ PopoverContent,
198
+ {
199
+ align: "start",
200
+ sideOffset: 4,
201
+ collisionPadding: 8,
202
+ "aria-label": label,
203
+ onOpenAutoFocus: (event) => {
204
+ event.preventDefault();
205
+ const panel = event.currentTarget;
206
+ const target = panel?.querySelector(
207
+ '[data-day][tabindex="0"]'
208
+ );
209
+ target?.focus();
210
+ },
211
+ className: cn(
212
+ "as-anim-pop z-50 w-[280px] rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] p-2 text-[var(--as-fg)] shadow-[var(--as-shadow-3)] outline-none",
213
+ panelClassName
214
+ ),
215
+ children: [
216
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between px-1 pt-1", children: [
217
+ /* @__PURE__ */ jsx(
218
+ "button",
219
+ {
220
+ type: "button",
221
+ "aria-label": prevLabel,
222
+ onClick: handlePrev,
223
+ className: navButtonClass,
224
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-5", "aria-hidden": true })
225
+ }
226
+ ),
227
+ /* @__PURE__ */ jsxs(
228
+ "button",
229
+ {
230
+ type: "button",
231
+ onClick: toggleViewMode,
232
+ className: "flex cursor-pointer items-center rounded-[var(--as-radius-sm)] px-3 py-1.5 text-sm font-semibold transition-colors hover:bg-[var(--as-muted)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
233
+ children: [
234
+ /* @__PURE__ */ jsx("span", { children: headerTitle }),
235
+ viewMode !== "years" ? /* @__PURE__ */ jsx(ChevronDown, { className: "ml-1 size-4", "aria-hidden": true }) : null
236
+ ]
237
+ }
238
+ ),
239
+ /* @__PURE__ */ jsx(
240
+ "button",
241
+ {
242
+ type: "button",
243
+ "aria-label": nextLabel,
244
+ onClick: handleNext,
245
+ className: navButtonClass,
246
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-5", "aria-hidden": true })
247
+ }
248
+ )
249
+ ] }),
250
+ viewMode === "days" ? /* @__PURE__ */ jsx("div", { className: "px-2 pb-2", children: /* @__PURE__ */ jsxs(
251
+ "div",
252
+ {
253
+ ref: gridRef,
254
+ role: "grid",
255
+ "aria-label": label,
256
+ onKeyDown: handleGridKeyDown,
257
+ children: [
258
+ /* @__PURE__ */ jsx("div", { role: "row", className: "mb-2 grid grid-cols-7 gap-1", children: Array.from({ length: 7 }, (_, i) => /* @__PURE__ */ jsx(
259
+ "div",
260
+ {
261
+ role: "columnheader",
262
+ className: "py-1 text-center text-xs font-medium text-[var(--as-muted-fg)]",
263
+ children: format(addDays(weekdayStart, i), "EEEEE")
264
+ },
265
+ i
266
+ )) }),
267
+ weeks.map((week, weekIndex) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-1", children: week.map((day) => {
268
+ const isSelected = selectedDate ? isSameDay(day, selectedDate) : false;
269
+ const isFocused = isSameDay(day, focusedDay);
270
+ const outside = !isSameMonth(day, monthStart);
271
+ const isToday = isSameDay(day, today);
272
+ const dayDisabled = isDisabled(day);
273
+ return /* @__PURE__ */ jsx(
274
+ "div",
275
+ {
276
+ role: "gridcell",
277
+ "aria-selected": isSelected,
278
+ className: "p-0",
279
+ children: /* @__PURE__ */ jsx(
280
+ "button",
281
+ {
282
+ type: "button",
283
+ "data-day": dayKey(day),
284
+ tabIndex: isFocused ? 0 : -1,
285
+ disabled: dayDisabled,
286
+ "aria-current": isToday ? "date" : void 0,
287
+ onClick: () => handleSelect(day),
288
+ className: cn(
289
+ "flex size-8 cursor-pointer items-center justify-center rounded-full text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
290
+ outside ? "text-[var(--as-muted-fg)] opacity-50" : "text-[var(--as-fg)]",
291
+ isSelected && "bg-[var(--as-primary)] font-medium text-[var(--as-primary-fg)] hover:brightness-110",
292
+ !isSelected && isToday && "bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] font-medium text-[var(--as-primary)]",
293
+ !isSelected && !dayDisabled && "hover:bg-[var(--as-muted)]",
294
+ dayDisabled && "cursor-not-allowed opacity-30 hover:bg-transparent"
295
+ ),
296
+ children: format(day, "d")
297
+ }
298
+ )
299
+ },
300
+ dayKey(day)
301
+ );
302
+ }) }, weekIndex))
303
+ ]
304
+ }
305
+ ) }) : null,
306
+ viewMode === "months" ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2 p-2", children: Array.from({ length: 12 }, (_, i) => {
307
+ const isSelected = selectedDate?.getMonth() === i && selectedDate?.getFullYear() === currentDate.getFullYear();
308
+ return /* @__PURE__ */ jsx(
309
+ "button",
310
+ {
311
+ type: "button",
312
+ onClick: () => {
313
+ setCurrentDate(setMonth(currentDate, i));
314
+ setViewMode("days");
315
+ },
316
+ className: cn(
317
+ "cursor-pointer rounded-[var(--as-radius)] py-3 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
318
+ isSelected ? "bg-[var(--as-primary)] text-[var(--as-primary-fg)]" : "text-[var(--as-fg)] hover:bg-[var(--as-muted)]"
319
+ ),
320
+ children: format(setMonth(/* @__PURE__ */ new Date(), i), "MMM")
321
+ },
322
+ i
323
+ );
324
+ }) }) : null,
325
+ viewMode === "years" ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2 p-2", children: Array.from({ length: 12 }, (_, i) => {
326
+ const year = Math.floor(yearPage / 12) * 12 + i;
327
+ const isSelected = selectedDate?.getFullYear() === year;
328
+ return /* @__PURE__ */ jsx(
329
+ "button",
330
+ {
331
+ type: "button",
332
+ onClick: () => {
333
+ setCurrentDate(setYear(currentDate, year));
334
+ setFocusedDay((current) => setYear(current, year));
335
+ setViewMode("months");
336
+ },
337
+ className: cn(
338
+ "cursor-pointer rounded-[var(--as-radius)] py-3 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
339
+ isSelected ? "bg-[var(--as-primary)] text-[var(--as-primary-fg)]" : "text-[var(--as-fg)] hover:bg-[var(--as-muted)]"
340
+ ),
341
+ children: year
342
+ },
343
+ year
344
+ );
345
+ }) }) : null
346
+ ]
347
+ }
348
+ )
349
+ ] })
350
+ }
351
+ );
352
+ }
353
+ );
354
+
355
+ export { DatePicker };
356
+ //# sourceMappingURL=chunk-2KO2YIZN.js.map
357
+ //# sourceMappingURL=chunk-2KO2YIZN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/date-picker/DatePicker.tsx"],"names":["DatePicker","CalendarIcon"],"mappings":"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","file":"chunk-2KO2YIZN.js","sourcesContent":["import * as React from 'react'\nimport {\n addDays,\n addMonths,\n addYears,\n endOfMonth,\n endOfWeek,\n format,\n isSameDay,\n isSameMonth,\n isValid,\n parseISO,\n setMonth,\n setYear,\n startOfDay,\n startOfMonth,\n startOfWeek,\n subMonths,\n subYears,\n} from 'date-fns'\nimport {\n Calendar as CalendarIcon,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n X,\n} from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from '../popover'\n\ntype ViewMode = 'days' | 'months' | 'years'\n\nexport interface DatePickerProps {\n value: string | null | undefined\n onChange: (value: string) => void\n onClear?: () => void\n allowClear?: boolean\n clearLabel?: string\n placeholder?: string\n displayFormat?: string\n minDate?: Date\n maxDate?: Date\n weekStartsOn?: 0 | 1\n disabled?: boolean\n required?: boolean\n id?: string\n name?: string\n label?: string\n prevLabel?: string\n nextLabel?: string\n className?: string\n panelClassName?: string\n}\n\nfunction dayKey(date: Date): string {\n return format(date, 'yyyy-MM-dd')\n}\n\nexport const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(\n function DatePicker(\n {\n value,\n onChange,\n onClear,\n allowClear = false,\n clearLabel = 'Clear',\n placeholder = 'Select date',\n displayFormat = 'dd/MM/yyyy',\n minDate,\n maxDate,\n weekStartsOn = 1,\n disabled = false,\n required,\n id,\n name,\n label = 'Choose date',\n prevLabel = 'Previous',\n nextLabel = 'Next',\n className,\n panelClassName,\n },\n ref,\n ) {\n const autoId = React.useId()\n const hiddenId = id ?? `date-picker-${autoId}`\n const [open, setOpen] = React.useState(false)\n const [viewMode, setViewMode] = React.useState<ViewMode>('days')\n const [currentDate, setCurrentDate] = React.useState<Date>(() => new Date())\n const [focusedDay, setFocusedDay] = React.useState<Date>(() => new Date())\n const [yearPage, setYearPage] = React.useState(() => new Date().getFullYear())\n const gridRef = React.useRef<HTMLDivElement>(null)\n\n const selectedDate = React.useMemo(() => {\n if (!value) return null\n const parsed = parseISO(value)\n return isValid(parsed) ? parsed : null\n }, [value])\n\n const isDisabled = React.useCallback(\n (date: Date) =>\n Boolean(minDate && date < startOfDay(minDate)) ||\n Boolean(maxDate && date > startOfDay(maxDate)),\n [minDate, maxDate],\n )\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next)\n if (next) {\n const base = selectedDate ?? new Date()\n setCurrentDate(base)\n setFocusedDay(base)\n setYearPage(base.getFullYear())\n setViewMode('days')\n }\n }\n\n const handleSelect = (date: Date) => {\n if (isDisabled(date)) return\n onChange(format(date, 'yyyy-MM-dd'))\n setOpen(false)\n }\n\n const handleClear = (event: React.MouseEvent) => {\n event.stopPropagation()\n onChange('')\n onClear?.()\n setOpen(false)\n }\n\n const moveFocus = (next: Date) => {\n if (isDisabled(next)) return\n setFocusedDay(next)\n setCurrentDate((current) =>\n isSameMonth(current, next) ? current : startOfMonth(next),\n )\n }\n\n const handleGridKeyDown = (event: React.KeyboardEvent) => {\n const step =\n event.key === 'ArrowLeft'\n ? -1\n : event.key === 'ArrowRight'\n ? 1\n : event.key === 'ArrowUp'\n ? -7\n : event.key === 'ArrowDown'\n ? 7\n : 0\n if (step !== 0) {\n event.preventDefault()\n moveFocus(addDays(focusedDay, step))\n return\n }\n if (event.key === 'PageUp' || event.key === 'PageDown') {\n event.preventDefault()\n const direction = event.key === 'PageUp' ? -1 : 1\n moveFocus(addMonths(focusedDay, direction))\n return\n }\n if (event.key === 'Home') {\n event.preventDefault()\n moveFocus(startOfMonth(focusedDay))\n } else if (event.key === 'End') {\n event.preventDefault()\n moveFocus(endOfMonth(focusedDay))\n }\n }\n\n React.useEffect(() => {\n if (!open || viewMode !== 'days') return\n const target = gridRef.current?.querySelector<HTMLButtonElement>(\n `[data-day=\"${dayKey(focusedDay)}\"]`,\n )\n target?.focus()\n }, [open, viewMode, focusedDay])\n\n const monthStart = startOfMonth(currentDate)\n const monthEnd = endOfMonth(monthStart)\n const gridStart = startOfWeek(monthStart, { weekStartsOn })\n const gridEnd = endOfWeek(monthEnd, { weekStartsOn })\n\n const weeks: Date[][] = []\n let cursor = gridStart\n while (cursor <= gridEnd) {\n const week: Date[] = []\n for (let i = 0; i < 7; i++) {\n week.push(cursor)\n cursor = addDays(cursor, 1)\n }\n weeks.push(week)\n }\n\n const today = new Date()\n const weekdayStart = startOfWeek(new Date(), { weekStartsOn })\n\n const headerTitle =\n viewMode === 'days'\n ? format(currentDate, 'MMMM yyyy')\n : viewMode === 'months'\n ? format(currentDate, 'yyyy')\n : `${Math.floor(yearPage / 12) * 12} – ${Math.floor(yearPage / 12) * 12 + 11}`\n\n const handlePrev = () => {\n if (viewMode === 'days') setCurrentDate(subMonths(currentDate, 1))\n else if (viewMode === 'months') setCurrentDate(subYears(currentDate, 1))\n else setYearPage(yearPage - 12)\n }\n\n const handleNext = () => {\n if (viewMode === 'days') setCurrentDate(addMonths(currentDate, 1))\n else if (viewMode === 'months') setCurrentDate(addYears(currentDate, 1))\n else setYearPage(yearPage + 12)\n }\n\n const toggleViewMode = () => {\n if (viewMode !== 'years') setViewMode('years')\n }\n\n const navButtonClass =\n 'cursor-pointer rounded-[var(--as-radius-sm)] p-1.5 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-muted)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]'\n\n return (\n <div\n ref={ref}\n data-as=\"date-picker\"\n className={cn('relative w-full', className)}\n >\n <Popover open={open} onOpenChange={handleOpenChange}>\n <span className=\"relative inline-flex w-full\">\n <PopoverTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n aria-label={label}\n className={cn(\n 'flex h-9 w-full items-center gap-2 rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2 text-left text-sm text-[var(--as-fg)] transition-colors hover:border-[var(--as-fg)]/30 focus-visible:border-[var(--as-focus-ring)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50',\n allowClear && selectedDate && !disabled && 'pr-8',\n )}\n >\n <CalendarIcon\n className=\"size-4 shrink-0 text-[var(--as-muted-fg)]\"\n aria-hidden\n />\n <span\n className={cn(\n 'flex-1 truncate text-left',\n !selectedDate && 'text-[var(--as-muted-fg)]',\n )}\n >\n {selectedDate\n ? format(selectedDate, displayFormat)\n : placeholder}\n </span>\n </button>\n </PopoverTrigger>\n {allowClear && selectedDate && !disabled ? (\n <button\n type=\"button\"\n aria-label={clearLabel}\n onClick={handleClear}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer rounded-full p-0.5 text-[var(--as-muted-fg)] transition-colors hover:bg-[var(--as-muted)] hover:text-[var(--as-fg)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n </span>\n\n <input\n type=\"hidden\"\n id={hiddenId}\n name={name ?? hiddenId}\n value={value ?? ''}\n required={required}\n />\n\n <PopoverContent\n align=\"start\"\n sideOffset={4}\n collisionPadding={8}\n aria-label={label}\n onOpenAutoFocus={(event) => {\n event.preventDefault()\n const panel = event.currentTarget as HTMLElement | null\n const target = panel?.querySelector<HTMLButtonElement>(\n '[data-day][tabindex=\"0\"]',\n )\n target?.focus()\n }}\n className={cn(\n 'as-anim-pop z-50 w-[280px] rounded-[var(--as-radius-lg)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] p-2 text-[var(--as-fg)] shadow-[var(--as-shadow-3)] outline-none',\n panelClassName,\n )}\n >\n <div className=\"mb-2 flex items-center justify-between px-1 pt-1\">\n <button\n type=\"button\"\n aria-label={prevLabel}\n onClick={handlePrev}\n className={navButtonClass}\n >\n <ChevronLeft className=\"size-5\" aria-hidden />\n </button>\n <button\n type=\"button\"\n onClick={toggleViewMode}\n className=\"flex cursor-pointer items-center rounded-[var(--as-radius-sm)] px-3 py-1.5 text-sm font-semibold transition-colors hover:bg-[var(--as-muted)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]\"\n >\n <span>{headerTitle}</span>\n {viewMode !== 'years' ? (\n <ChevronDown className=\"ml-1 size-4\" aria-hidden />\n ) : null}\n </button>\n <button\n type=\"button\"\n aria-label={nextLabel}\n onClick={handleNext}\n className={navButtonClass}\n >\n <ChevronRight className=\"size-5\" aria-hidden />\n </button>\n </div>\n\n {viewMode === 'days' ? (\n <div className=\"px-2 pb-2\">\n <div\n ref={gridRef}\n role=\"grid\"\n aria-label={label}\n onKeyDown={handleGridKeyDown}\n >\n <div role=\"row\" className=\"mb-2 grid grid-cols-7 gap-1\">\n {Array.from({ length: 7 }, (_, i) => (\n <div\n key={i}\n role=\"columnheader\"\n className=\"py-1 text-center text-xs font-medium text-[var(--as-muted-fg)]\"\n >\n {format(addDays(weekdayStart, i), 'EEEEE')}\n </div>\n ))}\n </div>\n {weeks.map((week, weekIndex) => (\n <div key={weekIndex} role=\"row\" className=\"grid grid-cols-7 gap-1\">\n {week.map((day) => {\n const isSelected = selectedDate\n ? isSameDay(day, selectedDate)\n : false\n const isFocused = isSameDay(day, focusedDay)\n const outside = !isSameMonth(day, monthStart)\n const isToday = isSameDay(day, today)\n const dayDisabled = isDisabled(day)\n return (\n <div\n key={dayKey(day)}\n role=\"gridcell\"\n aria-selected={isSelected}\n className=\"p-0\"\n >\n <button\n type=\"button\"\n data-day={dayKey(day)}\n tabIndex={isFocused ? 0 : -1}\n disabled={dayDisabled}\n aria-current={isToday ? 'date' : undefined}\n onClick={() => handleSelect(day)}\n className={cn(\n 'flex size-8 cursor-pointer items-center justify-center rounded-full text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n outside\n ? 'text-[var(--as-muted-fg)] opacity-50'\n : 'text-[var(--as-fg)]',\n isSelected &&\n 'bg-[var(--as-primary)] font-medium text-[var(--as-primary-fg)] hover:brightness-110',\n !isSelected &&\n isToday &&\n 'bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] font-medium text-[var(--as-primary)]',\n !isSelected && !dayDisabled && 'hover:bg-[var(--as-muted)]',\n dayDisabled &&\n 'cursor-not-allowed opacity-30 hover:bg-transparent',\n )}\n >\n {format(day, 'd')}\n </button>\n </div>\n )\n })}\n </div>\n ))}\n </div>\n </div>\n ) : null}\n\n {viewMode === 'months' ? (\n <div className=\"grid grid-cols-3 gap-2 p-2\">\n {Array.from({ length: 12 }, (_, i) => {\n const isSelected =\n selectedDate?.getMonth() === i &&\n selectedDate?.getFullYear() === currentDate.getFullYear()\n return (\n <button\n key={i}\n type=\"button\"\n onClick={() => {\n setCurrentDate(setMonth(currentDate, i))\n setViewMode('days')\n }}\n className={cn(\n 'cursor-pointer rounded-[var(--as-radius)] py-3 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n isSelected\n ? 'bg-[var(--as-primary)] text-[var(--as-primary-fg)]'\n : 'text-[var(--as-fg)] hover:bg-[var(--as-muted)]',\n )}\n >\n {format(setMonth(new Date(), i), 'MMM')}\n </button>\n )\n })}\n </div>\n ) : null}\n\n {viewMode === 'years' ? (\n <div className=\"grid grid-cols-3 gap-2 p-2\">\n {Array.from({ length: 12 }, (_, i) => {\n const year = Math.floor(yearPage / 12) * 12 + i\n const isSelected = selectedDate?.getFullYear() === year\n return (\n <button\n key={year}\n type=\"button\"\n onClick={() => {\n setCurrentDate(setYear(currentDate, year))\n setFocusedDay((current) => setYear(current, year))\n setViewMode('months')\n }}\n className={cn(\n 'cursor-pointer rounded-[var(--as-radius)] py-3 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n isSelected\n ? 'bg-[var(--as-primary)] text-[var(--as-primary-fg)]'\n : 'text-[var(--as-fg)] hover:bg-[var(--as-muted)]',\n )}\n >\n {year}\n </button>\n )\n })}\n </div>\n ) : null}\n </PopoverContent>\n </Popover>\n </div>\n )\n },\n)\n"]}
@@ -0,0 +1,74 @@
1
+ import { cn } from './chunk-BLJWR4ZV.js';
2
+ import * as React from 'react';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ function pct(value, domainMin, domainMax) {
6
+ if (domainMax === domainMin) return 0;
7
+ return (value - domainMin) / (domainMax - domainMin) * 100;
8
+ }
9
+ function fmt(value) {
10
+ return Number.isInteger(value) ? value.toLocaleString() : value.toFixed(1).replace(/\.0$/, "");
11
+ }
12
+ var RangeBar = React.forwardRef(
13
+ function RangeBar2({ low, high, min, max, value, unit, label, valueLabel = "You", className, ...props }, ref) {
14
+ if (!Number.isFinite(low) || !Number.isFinite(high) || high <= low) {
15
+ return null;
16
+ }
17
+ const span = high - low;
18
+ let domainMin = min ?? low - span;
19
+ let domainMax = max ?? high + span;
20
+ if (domainMin < 0 && low >= 0) {
21
+ const shift = -domainMin;
22
+ domainMin = 0;
23
+ domainMax += shift;
24
+ }
25
+ if (domainMax <= domainMin) domainMax = domainMin + span;
26
+ const left = Math.max(0, Math.min(100, pct(low, domainMin, domainMax)));
27
+ const right = Math.max(0, Math.min(100, pct(high, domainMin, domainMax)));
28
+ const valuePct = value !== null && value !== void 0 && Number.isFinite(value) ? Math.max(0, Math.min(100, pct(value, domainMin, domainMax))) : null;
29
+ return /* @__PURE__ */ jsxs(
30
+ "div",
31
+ {
32
+ ref,
33
+ "data-as": "range-bar",
34
+ className: cn("w-full", className),
35
+ ...props,
36
+ children: [
37
+ label ? /* @__PURE__ */ jsx("p", { className: "mb-1 text-xs text-[var(--as-muted-fg)]", children: label }) : null,
38
+ /* @__PURE__ */ jsxs("div", { className: "relative h-3.5 w-full rounded-full bg-[var(--as-muted)]", children: [
39
+ /* @__PURE__ */ jsx(
40
+ "div",
41
+ {
42
+ className: "absolute h-full rounded-full bg-[color-mix(in_srgb,var(--as-primary)_30%,transparent)]",
43
+ style: { left: `${left}%`, width: `${Math.max(0, right - left)}%` },
44
+ title: `${label ? `${label}: ` : ""}${fmt(low)} \u2013 ${fmt(high)}${unit ? ` ${unit}` : ""}`
45
+ }
46
+ ),
47
+ valuePct !== null ? /* @__PURE__ */ jsx(
48
+ "div",
49
+ {
50
+ className: "absolute top-1/2 size-2.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-[var(--as-surface-raised)] bg-[var(--as-primary)] shadow-[var(--as-shadow-1)]",
51
+ style: { left: `${valuePct}%` },
52
+ title: `${valueLabel}: ${fmt(value)}${unit ? ` ${unit}` : ""}`
53
+ }
54
+ ) : null
55
+ ] }),
56
+ /* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex justify-between text-[10px] text-[var(--as-muted-fg)]", children: [
57
+ /* @__PURE__ */ jsx("span", { children: fmt(domainMin) }),
58
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
59
+ fmt(low),
60
+ " \u2013 ",
61
+ fmt(high),
62
+ unit ? ` ${unit}` : ""
63
+ ] }),
64
+ /* @__PURE__ */ jsx("span", { children: fmt(domainMax) })
65
+ ] })
66
+ ]
67
+ }
68
+ );
69
+ }
70
+ );
71
+
72
+ export { RangeBar };
73
+ //# sourceMappingURL=chunk-5AVBKEDQ.js.map
74
+ //# sourceMappingURL=chunk-5AVBKEDQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/range-bar/RangeBar.tsx"],"names":["RangeBar"],"mappings":"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","file":"chunk-5AVBKEDQ.js","sourcesContent":["import * as React from 'react'\nimport { cn } from '../../lib/utils'\n\nexport interface RangeBarProps extends React.ComponentProps<'div'> {\n low: number\n high: number\n min?: number\n max?: number\n value?: number | null\n unit?: string\n label?: string\n valueLabel?: string\n}\n\nfunction pct(value: number, domainMin: number, domainMax: number): number {\n if (domainMax === domainMin) return 0\n return ((value - domainMin) / (domainMax - domainMin)) * 100\n}\n\nfunction fmt(value: number): string {\n return Number.isInteger(value)\n ? value.toLocaleString()\n : value.toFixed(1).replace(/\\.0$/, '')\n}\n\nexport const RangeBar = React.forwardRef<HTMLDivElement, RangeBarProps>(\n function RangeBar(\n { low, high, min, max, value, unit, label, valueLabel = 'You', className, ...props },\n ref,\n ) {\n if (!Number.isFinite(low) || !Number.isFinite(high) || high <= low) {\n return null\n }\n\n const span = high - low\n let domainMin = min ?? low - span\n let domainMax = max ?? high + span\n if (domainMin < 0 && low >= 0) {\n const shift = -domainMin\n domainMin = 0\n domainMax += shift\n }\n if (domainMax <= domainMin) domainMax = domainMin + span\n\n const left = Math.max(0, Math.min(100, pct(low, domainMin, domainMax)))\n const right = Math.max(0, Math.min(100, pct(high, domainMin, domainMax)))\n const valuePct =\n value !== null && value !== undefined && Number.isFinite(value)\n ? Math.max(0, Math.min(100, pct(value, domainMin, domainMax)))\n : null\n\n return (\n <div\n ref={ref}\n data-as=\"range-bar\"\n className={cn('w-full', className)}\n {...props}\n >\n {label ? (\n <p className=\"mb-1 text-xs text-[var(--as-muted-fg)]\">{label}</p>\n ) : null}\n <div className=\"relative h-3.5 w-full rounded-full bg-[var(--as-muted)]\">\n <div\n className=\"absolute h-full rounded-full bg-[color-mix(in_srgb,var(--as-primary)_30%,transparent)]\"\n style={{ left: `${left}%`, width: `${Math.max(0, right - left)}%` }}\n title={`${label ? `${label}: ` : ''}${fmt(low)} – ${fmt(high)}${unit ? ` ${unit}` : ''}`}\n />\n {valuePct !== null ? (\n <div\n className=\"absolute top-1/2 size-2.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-[var(--as-surface-raised)] bg-[var(--as-primary)] shadow-[var(--as-shadow-1)]\"\n style={{ left: `${valuePct}%` }}\n title={`${valueLabel}: ${fmt(value as number)}${unit ? ` ${unit}` : ''}`}\n />\n ) : null}\n </div>\n <div className=\"mt-0.5 flex justify-between text-[10px] text-[var(--as-muted-fg)]\">\n <span>{fmt(domainMin)}</span>\n <span className=\"font-medium\">\n {fmt(low)} – {fmt(high)}\n {unit ? ` ${unit}` : ''}\n </span>\n <span>{fmt(domainMax)}</span>\n </div>\n </div>\n )\n },\n)\n"]}