@godxjp/ui 11.0.1 → 11.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/{chunk-PGG4IM2Y.js → chunk-2HOTP7RL.js} +3 -1
  2. package/dist/{chunk-2HXZT2WJ.js → chunk-7BF7U3GG.js} +39 -18
  3. package/dist/{chunk-VSM44AYE.js → chunk-F6JGFU6O.js} +34 -13
  4. package/dist/{chunk-4S2AAMSS.js → chunk-FAB3LMTK.js} +2 -2
  5. package/dist/{chunk-DNGJHWJZ.js → chunk-FTOG7D4T.js} +4 -2
  6. package/dist/chunk-LN7GE73P.js +318 -0
  7. package/dist/{chunk-PDXFQS7M.js → chunk-Q4WWD4VV.js} +2 -4
  8. package/dist/{chunk-GDDCSKCB.js → chunk-QWALQSBS.js} +53 -19
  9. package/dist/components/admin/index.d.ts +1 -1
  10. package/dist/components/admin/index.js +18 -18
  11. package/dist/components/data-display/card.d.ts +2 -2
  12. package/dist/components/data-display/index.d.ts +1 -1
  13. package/dist/components/data-display/index.js +5 -5
  14. package/dist/components/data-entry/calendar.js +1 -1
  15. package/dist/components/data-entry/cascader.js +1 -4
  16. package/dist/components/data-entry/date-picker.js +2 -2
  17. package/dist/components/data-entry/date-range-picker.js +2 -2
  18. package/dist/components/data-entry/index.d.ts +1 -1
  19. package/dist/components/data-entry/index.js +13 -13
  20. package/dist/components/data-entry/time-picker.js +1 -1
  21. package/dist/components/data-entry/transfer.js +2 -2
  22. package/dist/components/data-entry/tree-select.js +1 -1
  23. package/dist/components/data-entry/upload.js +4 -4
  24. package/dist/components/feedback/dialog.js +2 -2
  25. package/dist/components/feedback/index.d.ts +3 -3
  26. package/dist/components/feedback/index.js +3 -3
  27. package/dist/components/layout/index.js +2 -2
  28. package/dist/components/navigation/index.js +1 -1
  29. package/dist/components/navigation/pagination.js +1 -1
  30. package/dist/components/ui/index.js +19 -19
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.js +26 -26
  33. package/dist/props/index.js +1 -1
  34. package/dist/{search-input-DpqDMXcn.d.ts → search-input-C_x-JFD3.d.ts} +3 -1
  35. package/dist/styles/control.css +14 -8
  36. package/dist/styles/data-display-layout.css +52 -2
  37. package/dist/styles/layout.css +27 -5
  38. package/dist/styles/navigation-layout.css +3 -3
  39. package/dist/styles/shell-layout.css +4 -4
  40. package/package.json +4 -3
  41. package/dist/chunk-5NCFLCM7.js +0 -255
  42. package/dist/{chunk-QHODCQDW.js → chunk-BG5RNXTH.js} +1 -1
  43. package/dist/{chunk-TGNBXS7H.js → chunk-PUGEOUWZ.js} +1 -1
  44. package/dist/{chunk-SJ77SVEK.js → chunk-USNR424B.js} +1 -1
@@ -3,8 +3,8 @@ import { Input } from './chunk-VOHTRR5X.js';
3
3
  import { Checkbox } from './chunk-BE6GJGKJ.js';
4
4
  import { Button } from './chunk-M4PZNAMV.js';
5
5
  import { ScrollArea } from './chunk-3KPEZ5CF.js';
6
- import { useTranslation } from './chunk-HTG5VHU7.js';
7
6
  import { Label } from './chunk-7PWBC4BY.js';
7
+ import { useTranslation } from './chunk-HTG5VHU7.js';
8
8
  import { useDebouncedValue } from './chunk-LFW37FGG.js';
9
9
  import { cn } from './chunk-U7N2A7A3.js';
10
10
  import * as React from 'react';
@@ -16,6 +16,7 @@ function SearchInput({
16
16
  defaultValue = "",
17
17
  placeholder,
18
18
  debounce = 250,
19
+ onValueChange,
19
20
  onSearch,
20
21
  label,
21
22
  ariaLabel,
@@ -42,6 +43,7 @@ function SearchInput({
42
43
  }, [debounced]);
43
44
  const setValue = (v) => {
44
45
  if (!isControlled) setInternal(v);
46
+ onValueChange?.(v);
45
47
  };
46
48
  return /* @__PURE__ */ jsxs("div", { className: cn("ui-search-input", className), children: [
47
49
  label !== void 0 ? /* @__PURE__ */ jsx(Label, { htmlFor: inputId, className: "ui-search-input-label", children: label }) : /* @__PURE__ */ jsx(Label, { htmlFor: inputId, className: "sr-only", children: resolvedAriaLabel }),
@@ -1,4 +1,4 @@
1
- import { Calendar } from './chunk-DNGJHWJZ.js';
1
+ import { Calendar } from './chunk-FTOG7D4T.js';
2
2
  import { Input } from './chunk-VOHTRR5X.js';
3
3
  import { Button } from './chunk-M4PZNAMV.js';
4
4
  import { Popover, PopoverTrigger, PopoverContent } from './chunk-DY5C44UP.js';
@@ -44,6 +44,7 @@ function DatePicker({
44
44
  emit(void 0);
45
45
  return;
46
46
  }
47
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) return;
47
48
  const parsed = parseDateInput(trimmed);
48
49
  if (parsed) {
49
50
  emit(parsed);
@@ -64,6 +65,17 @@ function DatePicker({
64
65
  "aria-expanded": open,
65
66
  "aria-haspopup": "dialog",
66
67
  className: "pe-10",
68
+ onClick: () => {
69
+ if (!disabled) setOpen(true);
70
+ },
71
+ onKeyDown: (event) => {
72
+ if (event.key === "ArrowDown") {
73
+ event.preventDefault();
74
+ setOpen(true);
75
+ } else if (event.key === "Escape" && open) {
76
+ setOpen(false);
77
+ }
78
+ },
67
79
  onChange: (event) => {
68
80
  setText(event.target.value);
69
81
  commit(event.target.value);
@@ -88,25 +100,34 @@ function DatePicker({
88
100
  children: /* @__PURE__ */ jsx(CalendarIcon, { className: "size-4 shrink-0", "aria-hidden": "true" })
89
101
  }
90
102
  ) }),
91
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "end", children: /* @__PURE__ */ jsx(
92
- Calendar,
103
+ /* @__PURE__ */ jsx(
104
+ PopoverContent,
93
105
  {
94
- mode: "single",
95
- selected: value,
96
- onSelect: (date) => {
97
- emit(date);
98
- setText(toIsoDate(date));
99
- setOpen(false);
100
- },
101
- locale: dayPickerLocale,
102
- disabled: [
103
- ...fromDate ? [{ before: fromDate }] : [],
104
- ...toDate ? [{ after: toDate }] : []
105
- ],
106
- startMonth: fromDate,
107
- endMonth: toDate
106
+ className: "w-auto p-0",
107
+ align: "end",
108
+ onOpenAutoFocus: (event) => event.preventDefault(),
109
+ children: /* @__PURE__ */ jsx(
110
+ Calendar,
111
+ {
112
+ mode: "single",
113
+ selected: value,
114
+ defaultMonth: value,
115
+ onSelect: (date) => {
116
+ emit(date);
117
+ setText(toIsoDate(date));
118
+ setOpen(false);
119
+ },
120
+ locale: dayPickerLocale,
121
+ disabled: [
122
+ ...fromDate ? [{ before: fromDate }] : [],
123
+ ...toDate ? [{ after: toDate }] : []
124
+ ],
125
+ startMonth: fromDate,
126
+ endMonth: toDate
127
+ }
128
+ )
108
129
  }
109
- ) })
130
+ )
110
131
  ] })
111
132
  ] });
112
133
  }
@@ -109,6 +109,7 @@ function TimeColumn({
109
109
  }
110
110
  function TimePickerPanel({ value, minuteStep, use12h, onChange, onDone }) {
111
111
  const { t } = useTranslation();
112
+ const draftId = React.useId();
112
113
  const { hour, minute } = parseHhmm(value);
113
114
  const minutes = buildMinutes(minuteStep);
114
115
  const snappedMinute = minutes.includes(minute) ? minute : minutes[0];
@@ -174,6 +175,7 @@ function TimePickerPanel({ value, minuteStep, use12h, onChange, onDone }) {
174
175
  /* @__PURE__ */ jsx("div", { className: "border-t p-2", children: /* @__PURE__ */ jsx(
175
176
  Input,
176
177
  {
178
+ id: draftId,
177
179
  value: draft,
178
180
  onChange: (e) => {
179
181
  setDraft(e.target.value);
@@ -239,6 +241,17 @@ function TimePicker({
239
241
  "aria-expanded": open,
240
242
  "aria-haspopup": "dialog",
241
243
  className: "pe-10 tabular-nums",
244
+ onClick: () => {
245
+ if (!disabled) setOpen(true);
246
+ },
247
+ onKeyDown: (event) => {
248
+ if (event.key === "ArrowDown") {
249
+ event.preventDefault();
250
+ setOpen(true);
251
+ } else if (event.key === "Escape" && open) {
252
+ setOpen(false);
253
+ }
254
+ },
242
255
  onChange: (event) => {
243
256
  setText(event.target.value);
244
257
  const normalized = normalizeHhmm(event.target.value);
@@ -264,21 +277,29 @@ function TimePicker({
264
277
  children: /* @__PURE__ */ jsx(Clock, { className: "size-4 shrink-0", "aria-hidden": "true" })
265
278
  }
266
279
  ) }),
267
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "end", children: /* @__PURE__ */ jsx(
268
- TimePickerPanel,
280
+ /* @__PURE__ */ jsx(
281
+ PopoverContent,
269
282
  {
270
- value: value || "09:00",
271
- minuteStep,
272
- use12h,
273
- onChange: (next) => {
274
- setValue(next);
275
- setText(next);
276
- },
277
- onDone: () => {
278
- setOpen(false);
279
- }
283
+ className: "w-auto p-0",
284
+ align: "end",
285
+ onOpenAutoFocus: (event) => event.preventDefault(),
286
+ children: /* @__PURE__ */ jsx(
287
+ TimePickerPanel,
288
+ {
289
+ value: value || "09:00",
290
+ minuteStep,
291
+ use12h,
292
+ onChange: (next) => {
293
+ setValue(next);
294
+ setText(next);
295
+ },
296
+ onDone: () => {
297
+ setOpen(false);
298
+ }
299
+ }
300
+ )
280
301
  }
281
- ) })
302
+ )
282
303
  ] })
283
304
  ] });
284
305
  }
@@ -1,6 +1,6 @@
1
- import { Slider } from './chunk-CRERCLIZ.js';
2
1
  import { formatBytes } from './chunk-X2VY4MOW.js';
3
- import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from './chunk-QHODCQDW.js';
2
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from './chunk-BG5RNXTH.js';
3
+ import { Slider } from './chunk-CRERCLIZ.js';
4
4
  import { Button } from './chunk-M4PZNAMV.js';
5
5
  import { controlIconClass } from './chunk-IBK5D2Q6.js';
6
6
  import { useTranslation } from './chunk-HTG5VHU7.js';
@@ -11,11 +11,12 @@ function Calendar({
11
11
  showOutsideDays = true,
12
12
  ...props
13
13
  }) {
14
+ const rangeDefaults = props.mode === "range" ? { resetOnSelect: props.resetOnSelect ?? true } : null;
14
15
  return /* @__PURE__ */ jsx(
15
16
  DayPicker,
16
17
  {
17
18
  showOutsideDays,
18
- className: cn("p-3", className),
19
+ className: cn("w-fit p-3", className),
19
20
  classNames: {
20
21
  months: cn("flex flex-col gap-4 sm:flex-row", classNames?.months),
21
22
  month: cn("relative flex flex-col gap-4", classNames?.month),
@@ -80,7 +81,8 @@ function Calendar({
80
81
  return /* @__PURE__ */ jsx(Icon, { className: cn("size-4", chevronClassName), "aria-hidden": "true" });
81
82
  }
82
83
  },
83
- ...props
84
+ ...props,
85
+ ...rangeDefaults
84
86
  }
85
87
  );
86
88
  }
@@ -0,0 +1,318 @@
1
+ import { normalizeTreeOptions, formatPathLabels, getNodeByPath, filterTreeOptions, pathsEqual, pathKey } from './chunk-SMLKNECP.js';
2
+ import { Command, CommandInput } from './chunk-HTEL5DQI.js';
3
+ import { Button } from './chunk-M4PZNAMV.js';
4
+ import { Popover, PopoverTrigger, PopoverContent } from './chunk-DY5C44UP.js';
5
+ import { ScrollArea, ScrollBar } from './chunk-3KPEZ5CF.js';
6
+ import { useTranslation } from './chunk-HTG5VHU7.js';
7
+ import { cn } from './chunk-U7N2A7A3.js';
8
+ import * as React from 'react';
9
+ import { Check, X, ChevronsUpDown, ChevronRight, Minus } from 'lucide-react';
10
+ import { jsxs, jsx } from 'react/jsx-runtime';
11
+
12
+ function pathInValues(path, values) {
13
+ return values.some((v) => pathsEqual(v, path));
14
+ }
15
+ function togglePath(values, path) {
16
+ if (pathInValues(path, values)) return values.filter((v) => !pathsEqual(v, path));
17
+ return [...values, path];
18
+ }
19
+ function CheckboxVisual({
20
+ checked,
21
+ indeterminate,
22
+ disabled,
23
+ className
24
+ }) {
25
+ const state = indeterminate ? "indeterminate" : checked ? "checked" : "unchecked";
26
+ return /* @__PURE__ */ jsx(
27
+ "span",
28
+ {
29
+ "aria-hidden": "true",
30
+ "data-slot": "checkbox",
31
+ "data-state": state,
32
+ className: cn(
33
+ "ui-checkbox inline-flex items-center justify-center",
34
+ // The shared CSS fills the box for [data-state=checked]; mirror that fill for the
35
+ // indeterminate ("some children selected") state so a partial parent reads as partial.
36
+ "data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground",
37
+ disabled && "cursor-not-allowed opacity-50",
38
+ className
39
+ ),
40
+ children: indeterminate ? /* @__PURE__ */ jsx(Minus, { className: "ui-checkbox-icon", "aria-hidden": "true" }) : checked ? /* @__PURE__ */ jsx(Check, { className: "ui-checkbox-icon", "aria-hidden": "true" }) : null
41
+ }
42
+ );
43
+ }
44
+ function aggregateCheckState(node, path, values) {
45
+ let total = 0;
46
+ let selected = 0;
47
+ const walk = (n, p) => {
48
+ const isLeaf = (n.children?.length ?? 0) === 0 || n.isLeaf === true;
49
+ if (isLeaf) {
50
+ if (n.disabled || n.disableCheckbox) return;
51
+ total += 1;
52
+ if (pathInValues(p, values)) selected += 1;
53
+ return;
54
+ }
55
+ for (const child of n.children) walk(child, [...p, child.value]);
56
+ };
57
+ for (const child of node.children ?? []) walk(child, [...path, child.value]);
58
+ if (total === 0 || selected === 0) return "none";
59
+ return selected === total ? "checked" : "indeterminate";
60
+ }
61
+ function Cascader({
62
+ options: optionsProp,
63
+ value,
64
+ defaultValue,
65
+ onValueChange,
66
+ multiple,
67
+ changeOnSelect,
68
+ showSearch,
69
+ placeholder,
70
+ disabled,
71
+ className,
72
+ id,
73
+ expandTrigger = "click",
74
+ fieldNames,
75
+ allowClear = true
76
+ }) {
77
+ const { t } = useTranslation();
78
+ const options = React.useMemo(
79
+ () => normalizeTreeOptions(optionsProp, fieldNames),
80
+ [optionsProp, fieldNames]
81
+ );
82
+ const [open, setOpen] = React.useState(false);
83
+ const [activePath, setActivePath] = React.useState([]);
84
+ const [search, setSearch] = React.useState("");
85
+ const isControlledSingle = !multiple && value !== void 0;
86
+ const isControlledMulti = multiple && value !== void 0;
87
+ const [internalSingle, setInternalSingle] = React.useState(
88
+ multiple ? [] : defaultValue ?? []
89
+ );
90
+ const [internalMulti, setInternalMulti] = React.useState(
91
+ defaultValue ?? []
92
+ );
93
+ const singleValue = isControlledSingle ? value : internalSingle;
94
+ const multiValue = isControlledMulti ? value : internalMulti;
95
+ const resolvedPlaceholder = placeholder ?? t("dataEntry.cascader.placeholder");
96
+ const displayLabel = React.useMemo(() => {
97
+ if (multiple) {
98
+ if (!multiValue.length) return null;
99
+ return multiValue.map((path) => formatPathLabels(getNodeByPath(options, path))).join(", ");
100
+ }
101
+ if (!singleValue.length) return null;
102
+ return formatPathLabels(getNodeByPath(options, singleValue));
103
+ }, [multiple, multiValue, singleValue, options]);
104
+ const setSingleValue = (path) => {
105
+ if (!isControlledSingle) setInternalSingle(path);
106
+ onValueChange?.(path, getNodeByPath(options, path));
107
+ };
108
+ const commitSingle = (path) => {
109
+ setSingleValue(path);
110
+ setOpen(false);
111
+ setActivePath([]);
112
+ setSearch("");
113
+ };
114
+ const commitMulti = (paths) => {
115
+ if (!isControlledMulti) setInternalMulti(paths);
116
+ onValueChange?.(
117
+ paths,
118
+ paths.map((p) => getNodeByPath(options, p))
119
+ );
120
+ };
121
+ const columns = React.useMemo(() => {
122
+ const cols = [options];
123
+ for (const segment of activePath) {
124
+ const col = cols.at(-1);
125
+ const node = col?.find((n) => n.value === segment);
126
+ if (node?.children?.length) cols.push(node.children);
127
+ else break;
128
+ }
129
+ return cols;
130
+ }, [options, activePath]);
131
+ const handleSelectNode = (node, path) => {
132
+ const hasChildren = (node.children?.length ?? 0) > 0 && node.isLeaf !== true;
133
+ if (multiple) {
134
+ if (hasChildren && !changeOnSelect) setActivePath(path);
135
+ else if (!node.disableCheckbox) commitMulti(togglePath(multiValue, path));
136
+ return;
137
+ }
138
+ if (hasChildren) {
139
+ if (changeOnSelect) setSingleValue(path);
140
+ setActivePath(path);
141
+ return;
142
+ }
143
+ commitSingle(path);
144
+ };
145
+ const isSearching = showSearch && search.trim().length > 0;
146
+ const searchResults = React.useMemo(
147
+ () => isSearching ? filterTreeOptions(options, search) : [],
148
+ [options, search, isSearching]
149
+ );
150
+ const handleOpenChange = (next) => {
151
+ setOpen(next);
152
+ if (next) {
153
+ setActivePath(multiple ? [] : singleValue);
154
+ } else {
155
+ setSearch("");
156
+ setActivePath([]);
157
+ }
158
+ };
159
+ const clearValue = (e) => {
160
+ e.stopPropagation();
161
+ if (multiple) commitMulti([]);
162
+ else commitSingle([]);
163
+ };
164
+ const renderCascadeColumns = () => /* @__PURE__ */ jsxs(ScrollArea, { className: "w-full", children: [
165
+ /* @__PURE__ */ jsx("div", { className: "flex max-h-[min(280px,50vh)]", children: columns.map((col, colIndex) => /* @__PURE__ */ jsx(
166
+ "ul",
167
+ {
168
+ role: "listbox",
169
+ "aria-orientation": "vertical",
170
+ "aria-multiselectable": multiple ? true : void 0,
171
+ className: "min-w-[9rem] border-e last:border-e-0",
172
+ children: col.map((node) => {
173
+ const path = [...activePath.slice(0, colIndex), node.value];
174
+ const hasChildren = (node.children?.length ?? 0) > 0 && node.isLeaf !== true;
175
+ const active = activePath[colIndex] === node.value;
176
+ const selected = multiple ? pathInValues(path, multiValue) : pathsEqual(path, singleValue);
177
+ const aggregate = multiple && hasChildren ? aggregateCheckState(node, path, multiValue) : void 0;
178
+ return /* @__PURE__ */ jsx("li", { role: "none", children: /* @__PURE__ */ jsxs(
179
+ "button",
180
+ {
181
+ type: "button",
182
+ role: "option",
183
+ "aria-selected": selected,
184
+ "aria-haspopup": hasChildren ? "menu" : void 0,
185
+ "aria-expanded": hasChildren ? active : void 0,
186
+ disabled: node.disabled,
187
+ className: cn(
188
+ "flex w-full items-center gap-1 px-3 py-2 text-sm outline-none",
189
+ "hover:bg-accent hover:text-accent-foreground",
190
+ active && "bg-accent/70 font-medium",
191
+ node.disabled && "pointer-events-none opacity-50"
192
+ ),
193
+ onMouseEnter: (
194
+ // Hover-expand: a parent opens its children column; a leaf collapses any
195
+ // deeper column but keeps its own. Never collapse on the column's mouseleave
196
+ // — moving the pointer toward the next column would strand the deeper levels
197
+ // and make a depth-3 leaf unreachable.
198
+ expandTrigger === "hover" && !node.disabled ? () => setActivePath(hasChildren ? path : path.slice(0, -1)) : void 0
199
+ ),
200
+ onClick: () => !node.disabled && handleSelectNode(node, path),
201
+ children: [
202
+ multiple && /* @__PURE__ */ jsx(
203
+ CheckboxVisual,
204
+ {
205
+ checked: aggregate ? aggregate === "checked" : selected,
206
+ indeterminate: aggregate === "indeterminate",
207
+ disabled: node.disabled || node.disableCheckbox,
208
+ className: "me-1"
209
+ }
210
+ ),
211
+ !multiple && selected && /* @__PURE__ */ jsx(Check, { className: "me-1 size-4 shrink-0", "aria-hidden": "true" }),
212
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-start", children: node.label }),
213
+ hasChildren && /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 shrink-0 opacity-50", "aria-hidden": "true" })
214
+ ]
215
+ }
216
+ ) }, node.value);
217
+ })
218
+ },
219
+ colIndex
220
+ )) }),
221
+ /* @__PURE__ */ jsx(ScrollBar, { orientation: "horizontal" })
222
+ ] });
223
+ const showClear = allowClear && displayLabel && !disabled;
224
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
225
+ /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
226
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
227
+ Button,
228
+ {
229
+ id,
230
+ type: "button",
231
+ variant: "outline",
232
+ role: "combobox",
233
+ "aria-expanded": open,
234
+ disabled,
235
+ className: cn(
236
+ "w-full justify-start font-normal",
237
+ // Reserve trailing room for the clear + chevron overlay rendered below.
238
+ showClear ? "pe-14" : "pe-9",
239
+ !displayLabel && "text-muted-foreground"
240
+ ),
241
+ children: /* @__PURE__ */ jsx("span", { className: "truncate", children: displayLabel ?? resolvedPlaceholder })
242
+ }
243
+ ) }),
244
+ /* @__PURE__ */ jsxs(
245
+ PopoverContent,
246
+ {
247
+ className: "w-auto min-w-[var(--radix-popover-trigger-width)] p-0",
248
+ align: "start",
249
+ children: [
250
+ showSearch && /* @__PURE__ */ jsx("div", { className: "border-b p-2", children: /* @__PURE__ */ jsx(Command, { shouldFilter: false, children: /* @__PURE__ */ jsx(
251
+ CommandInput,
252
+ {
253
+ placeholder: t("dataEntry.cascader.searchPlaceholder"),
254
+ value: search,
255
+ onValueChange: setSearch
256
+ }
257
+ ) }) }),
258
+ isSearching ? /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[min(300px,50vh)]", children: /* @__PURE__ */ jsx(
259
+ "div",
260
+ {
261
+ className: "p-1",
262
+ role: "listbox",
263
+ "aria-multiselectable": multiple ? true : void 0,
264
+ children: searchResults.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground py-6 text-center text-sm", children: t("dataEntry.cascader.empty") }) : searchResults.map(({ path, labels }) => {
265
+ const label = labels.join(" / ");
266
+ const selected = multiple ? pathInValues(path, multiValue) : pathsEqual(path, singleValue);
267
+ return /* @__PURE__ */ jsxs(
268
+ "button",
269
+ {
270
+ type: "button",
271
+ role: "option",
272
+ "aria-selected": selected,
273
+ className: cn(
274
+ "flex w-full items-center rounded-sm px-2 py-1.5 text-sm outline-none",
275
+ "hover:bg-accent hover:text-accent-foreground",
276
+ selected && "bg-accent/60"
277
+ ),
278
+ onClick: () => handleSelectNode({ value: path.at(-1)}, path),
279
+ children: [
280
+ multiple ? /* @__PURE__ */ jsx(CheckboxVisual, { checked: selected, className: "me-2" }) : /* @__PURE__ */ jsx(
281
+ Check,
282
+ {
283
+ className: cn(
284
+ "me-2 size-4 shrink-0",
285
+ selected ? "opacity-100" : "opacity-0"
286
+ ),
287
+ "aria-hidden": "true"
288
+ }
289
+ ),
290
+ /* @__PURE__ */ jsx("span", { className: "truncate text-start", children: label })
291
+ ]
292
+ },
293
+ pathKey(path)
294
+ );
295
+ })
296
+ }
297
+ ) }) : renderCascadeColumns()
298
+ ]
299
+ }
300
+ )
301
+ ] }),
302
+ /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute inset-y-0 end-3 flex items-center gap-1", children: [
303
+ showClear && /* @__PURE__ */ jsx(
304
+ "button",
305
+ {
306
+ type: "button",
307
+ "aria-label": t("dataEntry.cascader.clear"),
308
+ className: "pointer-events-auto flex size-4 items-center justify-center rounded-sm opacity-50 hover:opacity-100 focus-visible:opacity-100",
309
+ onClick: clearValue,
310
+ children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
311
+ }
312
+ ),
313
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "size-4 shrink-0 opacity-50", "aria-hidden": "true" })
314
+ ] })
315
+ ] });
316
+ }
317
+
318
+ export { Cascader };
@@ -48,7 +48,7 @@ var PaginationLink = React.forwardRef(
48
48
  disabled: disabled || void 0,
49
49
  "data-state": disabled ? "disabled" : void 0,
50
50
  className: cn(
51
- "ui-pagination-link ui-button--compact-icon ui-pagination-page",
51
+ "ui-pagination-link ui-pagination-page",
52
52
  isActive ? "ui-pagination-link-active" : void 0,
53
53
  disabled ? "ui-pagination-link-disabled" : void 0,
54
54
  className
@@ -63,7 +63,7 @@ PaginationLink.displayName = "PaginationLink";
63
63
  var PaginationEllipsis = ({ className, ...props }) => /* @__PURE__ */ jsx(
64
64
  "span",
65
65
  {
66
- className: cn("ui-pagination-ellipsis ui-button--compact-icon", className),
66
+ className: cn("ui-pagination-ellipsis", className),
67
67
  "aria-hidden": "true",
68
68
  role: "presentation",
69
69
  ...props,
@@ -196,7 +196,6 @@ function Pagination({
196
196
  {
197
197
  "aria-label": t("navigation.pagination.prev"),
198
198
  onClick: () => go(safeCurrent - 1),
199
- className: "ui-button--compact-icon",
200
199
  disabled: Boolean(disabled) || safeCurrent <= 1,
201
200
  children: /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true" })
202
201
  }
@@ -220,7 +219,6 @@ function Pagination({
220
219
  {
221
220
  "aria-label": t("navigation.pagination.next"),
222
221
  onClick: () => go(safeCurrent + 1),
223
- className: "ui-button--compact-icon",
224
222
  disabled: Boolean(disabled) || safeCurrent >= totalPages,
225
223
  children: /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true" })
226
224
  }
@@ -1,4 +1,4 @@
1
- import { Calendar } from './chunk-DNGJHWJZ.js';
1
+ import { Calendar } from './chunk-FTOG7D4T.js';
2
2
  import { Input } from './chunk-VOHTRR5X.js';
3
3
  import { Button } from './chunk-M4PZNAMV.js';
4
4
  import { Popover, PopoverTrigger, PopoverContent } from './chunk-DY5C44UP.js';
@@ -41,7 +41,9 @@ function DateRangePicker({
41
41
  onValueChange?.(next);
42
42
  };
43
43
  const commitEdge = (edge, raw) => {
44
- const parsed = raw.trim() === "" ? void 0 : parseDateInput(raw.trim()) ?? void 0;
44
+ const trimmed = raw.trim();
45
+ if (trimmed !== "" && !/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) return;
46
+ const parsed = trimmed === "" ? void 0 : parseDateInput(trimmed) ?? void 0;
45
47
  const next = { from: value?.from, to: value?.to, [edge]: parsed };
46
48
  emit(next.from || next.to ? next : void 0);
47
49
  };
@@ -58,6 +60,17 @@ function DateRangePicker({
58
60
  autoComplete: "off",
59
61
  "aria-label": t("dataEntry.dateRangePicker.from") ?? "From",
60
62
  className: "tabular-nums",
63
+ onClick: () => {
64
+ if (!disabled) setOpen(true);
65
+ },
66
+ onKeyDown: (event) => {
67
+ if (event.key === "ArrowDown") {
68
+ event.preventDefault();
69
+ setOpen(true);
70
+ } else if (event.key === "Escape" && open) {
71
+ setOpen(false);
72
+ }
73
+ },
61
74
  onChange: (event) => {
62
75
  setFromText(event.target.value);
63
76
  commitEdge("from", event.target.value);
@@ -80,6 +93,17 @@ function DateRangePicker({
80
93
  autoComplete: "off",
81
94
  "aria-label": t("dataEntry.dateRangePicker.to") ?? "To",
82
95
  className: "tabular-nums",
96
+ onClick: () => {
97
+ if (!disabled) setOpen(true);
98
+ },
99
+ onKeyDown: (event) => {
100
+ if (event.key === "ArrowDown") {
101
+ event.preventDefault();
102
+ setOpen(true);
103
+ } else if (event.key === "Escape" && open) {
104
+ setOpen(false);
105
+ }
106
+ },
83
107
  onChange: (event) => {
84
108
  setToText(event.target.value);
85
109
  commitEdge("to", event.target.value);
@@ -104,25 +128,35 @@ function DateRangePicker({
104
128
  children: /* @__PURE__ */ jsx(CalendarIcon, { className: "size-4 shrink-0", "aria-hidden": "true" })
105
129
  }
106
130
  ) }),
107
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "end", children: /* @__PURE__ */ jsx(
108
- Calendar,
131
+ /* @__PURE__ */ jsx(
132
+ PopoverContent,
109
133
  {
110
- mode: "range",
111
- selected: value,
112
- onSelect: (range) => {
113
- emit(range);
114
- setFromText(toIsoDate(range?.from));
115
- setToText(toIsoDate(range?.to));
116
- },
117
- locale: dayPickerLocale,
118
- disabled: [
119
- ...fromDate ? [{ before: fromDate }] : [],
120
- ...toDate ? [{ after: toDate }] : []
121
- ],
122
- startMonth: fromDate,
123
- endMonth: toDate
134
+ className: "w-auto p-0",
135
+ align: "end",
136
+ onOpenAutoFocus: (event) => event.preventDefault(),
137
+ children: /* @__PURE__ */ jsx(
138
+ Calendar,
139
+ {
140
+ mode: "range",
141
+ selected: value,
142
+ defaultMonth: value?.from,
143
+ numberOfMonths: 2,
144
+ onSelect: (range) => {
145
+ emit(range);
146
+ setFromText(toIsoDate(range?.from));
147
+ setToText(toIsoDate(range?.to));
148
+ },
149
+ locale: dayPickerLocale,
150
+ disabled: [
151
+ ...fromDate ? [{ before: fromDate }] : [],
152
+ ...toDate ? [{ after: toDate }] : []
153
+ ],
154
+ startMonth: fromDate,
155
+ endMonth: toDate
156
+ }
157
+ )
124
158
  }
125
- ) })
159
+ )
126
160
  ] })
127
161
  ] });
128
162
  }