@godxjp/ui 9.2.0 → 11.0.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 (137) hide show
  1. package/README.md +58 -29
  2. package/dist/app/index.d.ts +1 -1
  3. package/dist/app/index.js +4 -4
  4. package/dist/{app.prop-UTc4j4nj.d.ts → app.prop-Cy6dJnU8.d.ts} +18 -40
  5. package/dist/{checkbox-ChRsR7Nk.d.ts → checkbox-em-oFM5D.d.ts} +1 -1
  6. package/dist/{chunk-LJLGABFV.js → chunk-2HXZT2WJ.js} +17 -9
  7. package/dist/{chunk-QLMXEJSY.js → chunk-3Q4A4U2P.js} +24 -1
  8. package/dist/{chunk-26CPAKUP.js → chunk-44YRPSZ7.js} +1 -2
  9. package/dist/{chunk-HB2OHB5X.js → chunk-5NCFLCM7.js} +27 -16
  10. package/dist/{chunk-FXFJF4YA.js → chunk-6CSBMMZS.js} +262 -31
  11. package/dist/{chunk-457KVJTX.js → chunk-7Q45MBFW.js} +7 -5
  12. package/dist/{chunk-O24Z3ULJ.js → chunk-BE6GJGKJ.js} +1 -1
  13. package/dist/{chunk-FVPCVZL3.js → chunk-BG5RNXTH.js} +1 -1
  14. package/dist/{chunk-AINW5WYN.js → chunk-COD66MFF.js} +1 -2
  15. package/dist/{chunk-IOGU3ZWF.js → chunk-DNGJHWJZ.js} +3 -3
  16. package/dist/{chunk-3TS3G4U3.js → chunk-EE5DKOHX.js} +3 -1
  17. package/dist/{chunk-BHV2FUOA.js → chunk-EZHHJQWQ.js} +1 -1
  18. package/dist/{chunk-G6Q32VHO.js → chunk-FAB3LMTK.js} +33 -8
  19. package/dist/{chunk-N3JPLJ3B.js → chunk-GDDCSKCB.js} +12 -5
  20. package/dist/{chunk-RLGHEV4A.js → chunk-HTG5VHU7.js} +10 -1
  21. package/dist/{chunk-R2W2FX5Q.js → chunk-I7NQ2LIL.js} +1 -9
  22. package/dist/{chunk-XQMPK4GM.js → chunk-IHRMOJXD.js} +86 -39
  23. package/dist/{chunk-TILFZBTE.js → chunk-INIIF7F7.js} +1 -4
  24. package/dist/{chunk-UIYEAUWA.js → chunk-IY347EQA.js} +2 -2
  25. package/dist/{chunk-HCM4JAC2.js → chunk-JWGLJXQU.js} +39 -11
  26. package/dist/{chunk-TO33OY4L.js → chunk-LMKUKCTN.js} +1 -1
  27. package/dist/chunk-NXVCI6YB.js +453 -0
  28. package/dist/{chunk-O2OUNXV4.js → chunk-P5KPCT6R.js} +3 -3
  29. package/dist/{chunk-6HQMUUQW.js → chunk-PDXFQS7M.js} +14 -30
  30. package/dist/{chunk-26WDEDWL.js → chunk-PUGEOUWZ.js} +32 -23
  31. package/dist/{chunk-F7PG4OEV.js → chunk-QSGW3ZWK.js} +12 -4
  32. package/dist/{chunk-E7HBHUJY.js → chunk-QVLUCB47.js} +8 -6
  33. package/dist/{chunk-25RYBC5T.js → chunk-S2IJKT3D.js} +1 -1
  34. package/dist/{chunk-OJZ6C2HM.js → chunk-SARQRCKO.js} +54 -48
  35. package/dist/chunk-T2QO2S65.js +126 -0
  36. package/dist/{chunk-6J7GRCDA.js → chunk-UNVRNJCB.js} +71 -11
  37. package/dist/{chunk-S6TBIL7J.js → chunk-USNR424B.js} +63 -44
  38. package/dist/{chunk-6YBYAEXD.js → chunk-VSM44AYE.js} +94 -24
  39. package/dist/{chunk-QWLXN6CT.js → chunk-VSUYVT2Q.js} +3 -2
  40. package/dist/{chunk-4R7QL3MW.js → chunk-X2VY4MOW.js} +14 -29
  41. package/dist/{chunk-ETLAI3QU.js → chunk-Z46J47FY.js} +73 -77
  42. package/dist/components/admin/index.d.ts +22 -12
  43. package/dist/components/admin/index.js +29 -30
  44. package/dist/components/data-display/badge.js +3 -3
  45. package/dist/components/data-display/card.d.ts +3 -3
  46. package/dist/components/data-display/card.js +1 -1
  47. package/dist/components/data-display/carousel.js +3 -1
  48. package/dist/components/data-display/index.js +55 -33
  49. package/dist/components/data-entry/calendar.d.ts +1 -1
  50. package/dist/components/data-entry/calendar.js +1 -1
  51. package/dist/components/data-entry/cascader.d.ts +1 -1
  52. package/dist/components/data-entry/cascader.js +5 -5
  53. package/dist/components/data-entry/checkbox.d.ts +2 -2
  54. package/dist/components/data-entry/checkbox.js +2 -2
  55. package/dist/components/data-entry/color-picker.d.ts +1 -1
  56. package/dist/components/data-entry/color-picker.js +3 -3
  57. package/dist/components/data-entry/date-picker.d.ts +2 -2
  58. package/dist/components/data-entry/date-picker.js +4 -4
  59. package/dist/components/data-entry/date-range-picker.d.ts +2 -2
  60. package/dist/components/data-entry/date-range-picker.js +4 -4
  61. package/dist/components/data-entry/index.d.ts +9 -25
  62. package/dist/components/data-entry/index.js +22 -26
  63. package/dist/components/data-entry/radio.d.ts +1 -1
  64. package/dist/components/data-entry/radio.js +2 -2
  65. package/dist/components/data-entry/select.d.ts +2 -2
  66. package/dist/components/data-entry/select.js +3 -4
  67. package/dist/components/data-entry/slider.d.ts +1 -1
  68. package/dist/components/data-entry/switch.d.ts +2 -2
  69. package/dist/components/data-entry/switch.js +1 -1
  70. package/dist/components/data-entry/time-input.js +2 -2
  71. package/dist/components/data-entry/time-picker.d.ts +3 -1
  72. package/dist/components/data-entry/time-picker.js +3 -3
  73. package/dist/components/data-entry/transfer.d.ts +2 -2
  74. package/dist/components/data-entry/transfer.js +5 -5
  75. package/dist/components/data-entry/tree-select.d.ts +1 -1
  76. package/dist/components/data-entry/tree-select.js +5 -5
  77. package/dist/components/data-entry/upload.d.ts +2 -2
  78. package/dist/components/data-entry/upload.js +5 -5
  79. package/dist/components/feedback/alert.js +5 -5
  80. package/dist/components/feedback/dialog.js +3 -3
  81. package/dist/components/feedback/index.d.ts +4 -4
  82. package/dist/components/feedback/index.js +9 -9
  83. package/dist/components/feedback/sheet.js +1 -1
  84. package/dist/components/layout/index.d.ts +6 -9
  85. package/dist/components/layout/index.js +6 -4
  86. package/dist/components/navigation/dropdown-menu.js +1 -1
  87. package/dist/components/navigation/index.d.ts +14 -16
  88. package/dist/components/navigation/index.js +7 -8
  89. package/dist/components/navigation/pagination.d.ts +11 -8
  90. package/dist/components/navigation/pagination.js +4 -5
  91. package/dist/components/navigation/steps.d.ts +3 -3
  92. package/dist/components/navigation/steps.js +3 -1
  93. package/dist/components/query/index.d.ts +1 -5
  94. package/dist/components/query/index.js +6 -8
  95. package/dist/components/ui/index.d.ts +5 -7
  96. package/dist/components/ui/index.js +30 -33
  97. package/dist/{data-entry.prop-CDkOajPj.d.ts → data-entry.prop-BR4vNA1j.d.ts} +7 -35
  98. package/dist/filter-bar-BxjSJJnQ.d.ts +7 -0
  99. package/dist/{inline-CDSVAN54.d.ts → flex-D_EXRFSW.d.ts} +2 -8
  100. package/dist/form/index.js +1 -1
  101. package/dist/i18n/index.d.ts +82 -10
  102. package/dist/i18n/index.js +2 -2
  103. package/dist/index.d.ts +6 -6
  104. package/dist/index.js +41 -44
  105. package/dist/lib/datetime/index.js +1 -1
  106. package/dist/{navigation.prop-8DgElO0c.d.ts → navigation.prop-DMcXkR-J.d.ts} +9 -11
  107. package/dist/{password-strength-kQkloEeo.d.ts → password-strength-DVRvXEOK.d.ts} +2 -2
  108. package/dist/props/components/index.d.ts +3 -3
  109. package/dist/props/index.d.ts +3 -3
  110. package/dist/props/index.js +1 -1
  111. package/dist/props/registry.d.ts +84 -39
  112. package/dist/props/registry.js +1 -1
  113. package/dist/{search-input-cezAxpgb.d.ts → search-input-DpqDMXcn.d.ts} +2 -4
  114. package/dist/{skeleton-uWAjSacg.d.ts → skeleton-cj9kh5wo.d.ts} +1 -3
  115. package/dist/styles/control.css +176 -41
  116. package/dist/styles/data-display-layout.css +41 -15
  117. package/dist/styles/feedback-layout.css +44 -12
  118. package/dist/styles/index.css +45 -1
  119. package/dist/styles/layout.css +18 -17
  120. package/dist/styles/navigation-layout.css +3 -1
  121. package/dist/styles/shell-layout.css +3 -3
  122. package/dist/styles/table-layout.css +13 -0
  123. package/dist/tokens/foundation.css +12 -1
  124. package/dist/tokens/semantic/layout.css +2 -2
  125. package/package.json +6 -7
  126. package/scripts/ui-audit.mjs +35 -2
  127. package/dist/chunk-6MCI7W5G.js +0 -201
  128. package/dist/chunk-CAEL2ZD2.js +0 -222
  129. package/dist/chunk-GKXPALFT.js +0 -32
  130. package/dist/chunk-JKHWLPM5.js +0 -101
  131. package/dist/chunk-KDBGFJJI.js +0 -220
  132. package/dist/components/data-entry/autocomplete.d.ts +0 -24
  133. package/dist/components/data-entry/autocomplete.js +0 -10
  134. package/dist/components/data-entry/combobox.d.ts +0 -22
  135. package/dist/components/data-entry/combobox.js +0 -6
  136. package/dist/filter-bar-B5TPUqEO.d.ts +0 -14
  137. /package/dist/{chunk-LDSLS6HE.js → chunk-7CFO5FFE.js} +0 -0
@@ -1,15 +1,16 @@
1
+ import { Flex, densityClass } from './chunk-INIIF7F7.js';
2
+ import { Checkbox } from './chunk-BE6GJGKJ.js';
1
3
  import { Button } from './chunk-M4PZNAMV.js';
2
- import { Inline, densityClass } from './chunk-TILFZBTE.js';
3
4
  import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from './chunk-4MMIMZMK.js';
4
5
  import { tableCellPaddingClass, tableRowHeightClass, controlIconSmClass } from './chunk-IBK5D2Q6.js';
5
- import { useTranslation } from './chunk-RLGHEV4A.js';
6
+ import { useTranslation } from './chunk-HTG5VHU7.js';
6
7
  import { cn } from './chunk-U7N2A7A3.js';
7
8
  import { jsx, jsxs } from 'react/jsx-runtime';
8
9
  import * as React from 'react';
9
10
  import { Layers, Layers2, ArrowUp, ArrowDown, ChevronsUpDown, MoreHorizontal } from 'lucide-react';
10
11
 
11
12
  function EmptyState({ icon: Icon, title, description, action, className }) {
12
- return /* @__PURE__ */ jsxs("div", { "data-slot": "empty-state", className: cn("ui-empty-state", className), children: [
13
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "empty-state", role: "status", className: cn("ui-empty-state", className), children: [
13
14
  Icon && /* @__PURE__ */ jsx("div", { className: "ui-empty-state-icon", children: /* @__PURE__ */ jsx(Icon, { className: "text-muted-foreground size-6", "aria-hidden": "true" }) }),
14
15
  /* @__PURE__ */ jsx("h3", { className: "ui-empty-state-title", children: title }),
15
16
  description && /* @__PURE__ */ jsx("p", { className: "ui-empty-state-description", children: description }),
@@ -139,14 +140,10 @@ DataTable.SelectAll = function DataTableSelectAll() {
139
140
  const { t } = useTranslation();
140
141
  if (!selectable) return null;
141
142
  return /* @__PURE__ */ jsx(
142
- "input",
143
+ Checkbox,
143
144
  {
144
- type: "checkbox",
145
- checked: allSelected,
146
- ref: (el) => {
147
- if (el) el.indeterminate = someSelected;
148
- },
149
- onChange: toggleSelectAll,
145
+ checked: allSelected ? true : someSelected ? "indeterminate" : false,
146
+ onCheckedChange: toggleSelectAll,
150
147
  "aria-label": t("dataTable.selectAll")
151
148
  }
152
149
  );
@@ -190,7 +187,7 @@ DataTable.DensityToggle = function DataTableDensityToggle() {
190
187
  setDensity(next);
191
188
  },
192
189
  "aria-label": t("dataTable.densitySwitch", { density: nextLabel }),
193
- children: /* @__PURE__ */ jsxs(Inline, { gap: "xs", children: [
190
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "row", wrap: true, align: "center", gap: "xs", children: [
194
191
  /* @__PURE__ */ jsx(Icon, { className: "size-4", "aria-hidden": "true" }),
195
192
  density === "compact" ? t("dataTable.densityCompact") : t("dataTable.densityComfortable")
196
193
  ] })
@@ -227,62 +224,84 @@ DataTable.Content = function DataTableContent() {
227
224
  onSortChange(void 0);
228
225
  }
229
226
  };
230
- return /* @__PURE__ */ jsx("div", { className: "ui-data-table-scroll", children: /* @__PURE__ */ jsx("div", { className: "ui-data-table-surface min-w-[640px] sm:min-w-0", children: /* @__PURE__ */ jsxs(Table, { children: [
227
+ return /* @__PURE__ */ jsx("div", { className: "ui-data-table-scroll", "aria-busy": loading, children: /* @__PURE__ */ jsx("div", { className: "ui-data-table-surface min-w-[640px] sm:min-w-0", children: /* @__PURE__ */ jsxs(Table, { children: [
231
228
  /* @__PURE__ */ jsx(TableHeader, { className: "bg-secondary sticky top-0 z-10", children: /* @__PURE__ */ jsxs(TableRow, { children: [
232
229
  selectable && /* @__PURE__ */ jsx(TableHead, { className: "w-10", children: /* @__PURE__ */ jsx(DataTable.SelectAll, {}) }),
233
- columns.map((col) => /* @__PURE__ */ jsx(
234
- TableHead,
235
- {
236
- "data-empty": !col.header || void 0,
237
- className: cn(
238
- col.width,
239
- col.align === "right" && "text-right",
240
- col.align === "center" && "text-center",
241
- col.hiddenOnMobile && "hidden md:table-cell",
242
- col.sortable && onSortChange && "cursor-pointer select-none"
243
- ),
244
- onClick: () => {
245
- onHeaderClick(col);
246
- },
247
- children: /* @__PURE__ */ jsxs("span", { className: "ui-data-table-sort-label", children: [
248
- col.header,
249
- col.sortable && onSortChange && (sort?.key === col.key ? sort.direction === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ArrowDown, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(
250
- ChevronsUpDown,
230
+ columns.map((col) => {
231
+ const isSortable = !!col.sortable && !!onSortChange;
232
+ const isActiveSort = isSortable && sort?.key === col.key;
233
+ const sortIndicator = isSortable ? isActiveSort ? sort?.direction === "asc" ? /* @__PURE__ */ jsx(ArrowUp, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ArrowDown, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(ChevronsUpDown, { className: "text-muted-foreground size-3", "aria-hidden": "true" }) : null;
234
+ const label = /* @__PURE__ */ jsxs("span", { className: "ui-data-table-sort-label", children: [
235
+ col.header,
236
+ sortIndicator
237
+ ] });
238
+ return /* @__PURE__ */ jsx(
239
+ TableHead,
240
+ {
241
+ "data-empty": !col.header || void 0,
242
+ "aria-sort": isSortable ? isActiveSort ? sort?.direction === "asc" ? "ascending" : "descending" : "none" : void 0,
243
+ className: cn(
244
+ col.width,
245
+ col.align === "right" && "text-right",
246
+ col.align === "center" && "text-center",
247
+ col.hiddenOnMobile && "hidden md:table-cell",
248
+ isSortable && "select-none"
249
+ ),
250
+ children: isSortable ? /* @__PURE__ */ jsx(
251
+ "button",
251
252
  {
252
- className: "text-muted-foreground size-3",
253
- "aria-hidden": "true"
253
+ type: "button",
254
+ className: "ui-data-table-sort-button focus-visible:ring-ring rounded-sm focus-visible:ring-2",
255
+ onClick: () => {
256
+ onHeaderClick(col);
257
+ },
258
+ children: label
254
259
  }
255
- ))
256
- ] })
257
- },
258
- col.key
259
- ))
260
+ ) : label
261
+ },
262
+ col.key
263
+ );
264
+ })
260
265
  ] }) }),
261
- /* @__PURE__ */ jsx(TableBody, { children: loading ? /* @__PURE__ */ jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx(TableCell, { colSpan: emptyColSpan, className: "h-32 text-center", children: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: t("dataTable.loading") }) }) }) : data.length === 0 ? /* @__PURE__ */ jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx(TableCell, { colSpan: emptyColSpan, className: "ui-data-table-empty", children: empty ?? /* @__PURE__ */ jsx(EmptyState, { title: t("dataTable.empty") }) }) }) : data.map((row) => {
266
+ /* @__PURE__ */ jsx(TableBody, { children: loading ? /* @__PURE__ */ jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx(TableCell, { colSpan: emptyColSpan, className: "h-32 text-center", "aria-live": "polite", children: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: t("dataTable.loading") }) }) }) : data.length === 0 ? /* @__PURE__ */ jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx(
267
+ TableCell,
268
+ {
269
+ colSpan: emptyColSpan,
270
+ className: "ui-data-table-empty",
271
+ "aria-live": "polite",
272
+ children: empty ?? /* @__PURE__ */ jsx(EmptyState, { title: t("dataTable.empty") })
273
+ }
274
+ ) }) : data.map((row) => {
262
275
  const id = getRowId(row);
263
276
  const isSelected = selected.has(id);
277
+ const isInteractiveTarget = (target) => !!target.closest("button, a, input, select, textarea, [role=menuitem]");
264
278
  return /* @__PURE__ */ jsxs(
265
279
  TableRow,
266
280
  {
267
281
  "data-state": isSelected ? "selected" : void 0,
282
+ tabIndex: onRowClick ? 0 : void 0,
268
283
  onClick: (e) => {
269
284
  const target = e.target;
270
- if (target.closest("button, a, input, select, textarea, [role=menuitem]"))
271
- return;
285
+ if (isInteractiveTarget(target)) return;
272
286
  onRowClick?.(row);
273
287
  },
288
+ onKeyDown: onRowClick ? (e) => {
289
+ if (e.key !== "Enter" && e.key !== " ") return;
290
+ if (e.target !== e.currentTarget) return;
291
+ e.preventDefault();
292
+ onRowClick?.(row);
293
+ } : void 0,
274
294
  className: cn(
275
295
  rowPadding,
276
- onRowClick && "hover:bg-muted/50 cursor-pointer",
296
+ onRowClick && "hover:bg-muted/50 focus-visible:ring-ring cursor-pointer focus-visible:ring-2 focus-visible:outline-none focus-visible:ring-inset",
277
297
  isSelected && "bg-muted/30"
278
298
  ),
279
299
  children: [
280
300
  selectable && /* @__PURE__ */ jsx(TableCell, { className: cellPadding, children: /* @__PURE__ */ jsx(
281
- "input",
301
+ Checkbox,
282
302
  {
283
- type: "checkbox",
284
303
  checked: isSelected,
285
- onChange: () => {
304
+ onCheckedChange: () => {
286
305
  toggleSelect(id);
287
306
  },
288
307
  "aria-label": t("dataTable.selectRow", { id }),
@@ -1,8 +1,8 @@
1
1
  import { Input } from './chunk-VOHTRR5X.js';
2
2
  import { Button } from './chunk-M4PZNAMV.js';
3
3
  import { Popover, PopoverTrigger, PopoverContent } from './chunk-DY5C44UP.js';
4
- import { useTranslation } from './chunk-RLGHEV4A.js';
5
- import { normalizeHhmm, isValidHhmm } from './chunk-FXFJF4YA.js';
4
+ import { useTranslation, usePickerLocales } from './chunk-HTG5VHU7.js';
5
+ import { normalizeHhmm, isValidHhmm } from './chunk-6CSBMMZS.js';
6
6
  import { cn } from './chunk-U7N2A7A3.js';
7
7
  import * as React from 'react';
8
8
  import { Clock } from 'lucide-react';
@@ -23,49 +23,97 @@ function parseHhmm(value) {
23
23
  const [h, m] = normalized.split(":").map(Number);
24
24
  return { hour: h, minute: m };
25
25
  }
26
+ function to12h(hour24) {
27
+ const h = hour24 % 12;
28
+ return h === 0 ? 12 : h;
29
+ }
30
+ function from12h(hour12, meridiem) {
31
+ const base = hour12 % 12;
32
+ return meridiem === "pm" ? base + 12 : base;
33
+ }
26
34
  function TimeColumn({
27
35
  label,
28
36
  items,
29
37
  selected,
38
+ formatItem,
30
39
  onSelect
31
40
  }) {
32
41
  const listRef = React.useRef(null);
33
42
  React.useEffect(() => {
34
43
  listRef.current?.querySelector('[data-selected="true"]')?.scrollIntoView({ block: "center" });
35
44
  }, [selected]);
45
+ const moveFocus = (index) => {
46
+ const options = listRef.current?.querySelectorAll('[role="option"]');
47
+ options?.[index]?.focus();
48
+ };
49
+ const onKeyDown = (e, index) => {
50
+ switch (e.key) {
51
+ case "ArrowDown":
52
+ e.preventDefault();
53
+ moveFocus(Math.min(items.length - 1, index + 1));
54
+ break;
55
+ case "ArrowUp":
56
+ e.preventDefault();
57
+ moveFocus(Math.max(0, index - 1));
58
+ break;
59
+ case "Home":
60
+ e.preventDefault();
61
+ moveFocus(0);
62
+ break;
63
+ case "End":
64
+ e.preventDefault();
65
+ moveFocus(items.length - 1);
66
+ break;
67
+ case "Enter":
68
+ case " ":
69
+ e.preventDefault();
70
+ onSelect(items[index]);
71
+ break;
72
+ }
73
+ };
36
74
  return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
37
75
  /* @__PURE__ */ jsx("div", { className: "text-muted-foreground border-b px-1 py-1.5 text-center text-xs font-medium", children: label }),
38
76
  /* @__PURE__ */ jsx(
39
77
  "div",
40
78
  {
41
79
  ref: listRef,
80
+ role: "listbox",
81
+ "aria-label": label,
42
82
  className: "h-52 [scrollbar-width:thin] [scrollbar-gutter:stable] overflow-y-scroll overscroll-contain p-1",
43
- children: items.map((item) => /* @__PURE__ */ jsx(
44
- "button",
45
- {
46
- type: "button",
47
- "data-selected": item === selected,
48
- className: cn(
49
- "hover:bg-accent flex w-full items-center justify-center rounded-md py-1.5 text-sm tabular-nums transition-colors",
50
- item === selected && "bg-primary text-primary-foreground hover:bg-primary/90"
51
- ),
52
- onClick: () => {
53
- onSelect(item);
83
+ children: items.map((item, index) => {
84
+ const isSelected = item === selected;
85
+ return /* @__PURE__ */ jsx(
86
+ "button",
87
+ {
88
+ type: "button",
89
+ role: "option",
90
+ "aria-selected": isSelected,
91
+ "data-selected": isSelected,
92
+ tabIndex: isSelected ? 0 : -1,
93
+ className: cn(
94
+ "hover:bg-accent flex w-full items-center justify-center rounded-md py-1.5 text-sm tabular-nums transition-colors",
95
+ isSelected && "bg-primary text-primary-foreground hover:bg-primary/90"
96
+ ),
97
+ onClick: () => {
98
+ onSelect(item);
99
+ },
100
+ onKeyDown: (e) => onKeyDown(e, index),
101
+ children: formatItem(item)
54
102
  },
55
- children: pad2(item)
56
- },
57
- item
58
- ))
103
+ item
104
+ );
105
+ })
59
106
  }
60
107
  )
61
108
  ] });
62
109
  }
63
- function TimePickerPanel({ value, minuteStep, onChange, onDone }) {
110
+ function TimePickerPanel({ value, minuteStep, use12h, onChange, onDone }) {
64
111
  const { t } = useTranslation();
65
112
  const { hour, minute } = parseHhmm(value);
66
113
  const minutes = buildMinutes(minuteStep);
67
114
  const snappedMinute = minutes.includes(minute) ? minute : minutes[0];
68
115
  const [draft, setDraft] = React.useState(value);
116
+ const meridiem = hour >= 12 ? "pm" : "am";
69
117
  React.useEffect(() => {
70
118
  setDraft(value);
71
119
  }, [value]);
@@ -79,16 +127,20 @@ function TimePickerPanel({ value, minuteStep, onChange, onDone }) {
79
127
  onChange(next);
80
128
  onDone?.();
81
129
  };
82
- return /* @__PURE__ */ jsxs("div", { className: "w-36", children: [
130
+ const hourItems = use12h ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 24 }, (_, i) => i);
131
+ const selectedHourItem = use12h ? to12h(hour) : hour;
132
+ return /* @__PURE__ */ jsxs("div", { className: use12h ? "w-52" : "w-36", children: [
83
133
  /* @__PURE__ */ jsxs("div", { className: "divide-border flex divide-x", children: [
84
134
  /* @__PURE__ */ jsx(
85
135
  TimeColumn,
86
136
  {
87
137
  label: t("dataEntry.timePicker.hour"),
88
- items: Array.from({ length: 24 }, (_, i) => i),
89
- selected: hour,
138
+ items: hourItems,
139
+ selected: selectedHourItem,
140
+ formatItem: (h) => use12h ? String(h) : pad2(h),
90
141
  onSelect: (h) => {
91
- onChange(`${pad2(h)}:${pad2(snappedMinute)}`);
142
+ const hour24 = use12h ? from12h(h, meridiem) : h;
143
+ onChange(`${pad2(hour24)}:${pad2(snappedMinute)}`);
92
144
  }
93
145
  }
94
146
  ),
@@ -98,10 +150,25 @@ function TimePickerPanel({ value, minuteStep, onChange, onDone }) {
98
150
  label: t("dataEntry.timePicker.minute"),
99
151
  items: minutes,
100
152
  selected: snappedMinute,
153
+ formatItem: (m) => pad2(m),
101
154
  onSelect: (m) => {
102
155
  commit(`${pad2(hour)}:${pad2(m)}`);
103
156
  }
104
157
  }
158
+ ),
159
+ use12h && /* @__PURE__ */ jsx(
160
+ TimeColumn,
161
+ {
162
+ label: t("dataEntry.timePicker.meridiem"),
163
+ items: [0, 1],
164
+ selected: meridiem === "pm" ? 1 : 0,
165
+ formatItem: (m) => m === 1 ? t("dataEntry.timePicker.pm") : t("dataEntry.timePicker.am"),
166
+ onSelect: (m) => {
167
+ const nextMeridiem = m === 1 ? "pm" : "am";
168
+ const hour24 = from12h(to12h(hour), nextMeridiem);
169
+ onChange(`${pad2(hour24)}:${pad2(snappedMinute)}`);
170
+ }
171
+ }
105
172
  )
106
173
  ] }),
107
174
  /* @__PURE__ */ jsx("div", { className: "border-t p-2", children: /* @__PURE__ */ jsx(
@@ -142,6 +209,8 @@ function TimePicker({
142
209
  minuteStep = 5
143
210
  }) {
144
211
  const { t } = useTranslation();
212
+ const { timeFormat } = usePickerLocales();
213
+ const use12h = timeFormat === "12h";
145
214
  const [open, setOpen] = React.useState(false);
146
215
  const [internal, setInternal] = React.useState(defaultValue ?? "");
147
216
  const isControlled = controlledValue !== void 0;
@@ -169,7 +238,7 @@ function TimePicker({
169
238
  role: "combobox",
170
239
  "aria-expanded": open,
171
240
  "aria-haspopup": "dialog",
172
- className: "pr-10 tabular-nums",
241
+ className: "pe-10 tabular-nums",
173
242
  onChange: (event) => {
174
243
  setText(event.target.value);
175
244
  const normalized = normalizeHhmm(event.target.value);
@@ -191,7 +260,7 @@ function TimePicker({
191
260
  disabled,
192
261
  tabIndex: -1,
193
262
  "aria-label": t("dataEntry.timePicker.openPicker") ?? "Open time picker",
194
- className: "text-muted-foreground absolute inset-y-0 right-0 h-full px-2 hover:bg-transparent",
263
+ className: "text-muted-foreground absolute inset-y-0 end-0 h-full px-2 hover:bg-transparent",
195
264
  children: /* @__PURE__ */ jsx(Clock, { className: "size-4 shrink-0", "aria-hidden": "true" })
196
265
  }
197
266
  ) }),
@@ -200,6 +269,7 @@ function TimePicker({
200
269
  {
201
270
  value: value || "09:00",
202
271
  minuteStep,
272
+ use12h,
203
273
  onChange: (next) => {
204
274
  setValue(next);
205
275
  setText(next);
@@ -14,13 +14,13 @@ var toggleVariants = cva("ui-toggle", {
14
14
  },
15
15
  size: {
16
16
  sm: "ui-toggle-sm",
17
- default: "ui-toggle-default-size",
17
+ md: "ui-toggle-default-size",
18
18
  lg: "ui-toggle-lg"
19
19
  }
20
20
  },
21
21
  defaultVariants: {
22
22
  variant: "default",
23
- size: "default"
23
+ size: "md"
24
24
  }
25
25
  });
26
26
  var Toggle = React2.forwardRef(({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx(
@@ -131,6 +131,7 @@ function PasswordStrength({
131
131
  "data-state": checks[rule] ? "passed" : "failed",
132
132
  children: [
133
133
  checks[rule] ? /* @__PURE__ */ jsx(Check, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(X, { "aria-hidden": "true" }),
134
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: checks[rule] ? "Passed: " : "Failed: " }),
134
135
  /* @__PURE__ */ jsx("span", { children: labelForRule(rule) })
135
136
  ]
136
137
  },
@@ -1,4 +1,4 @@
1
- import { formatDate, translateCurrent } from './chunk-FXFJF4YA.js';
1
+ import { formatDate, getSyncedLocale, translateCurrent } from './chunk-6CSBMMZS.js';
2
2
 
3
3
  // src/lib/format.ts
4
4
  function formatDateTime(value, options) {
@@ -10,38 +10,23 @@ function formatDateLong(value, options) {
10
10
  function formatRelative(value, options) {
11
11
  return formatDate(value, { ...options, kind: "relative" });
12
12
  }
13
- function formatBytes(n) {
13
+ function formatBytes(n, locale = getSyncedLocale()) {
14
14
  if (n == null) return "\u2014";
15
- if (n < 1024) return `${n} B`;
16
- if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
17
- if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
18
- return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
15
+ const num = (digits, scaled) => new Intl.NumberFormat(locale, {
16
+ minimumFractionDigits: digits,
17
+ maximumFractionDigits: digits
18
+ }).format(scaled);
19
+ if (n < 1024) return `${num(0, n)} B`;
20
+ if (n < 1024 * 1024) return `${num(1, n / 1024)} KB`;
21
+ if (n < 1024 * 1024 * 1024) return `${num(1, n / 1024 / 1024)} MB`;
22
+ return `${num(2, n / 1024 / 1024 / 1024)} GB`;
19
23
  }
20
- function formatCurrency(amountMinor, currency) {
24
+ function formatCurrency(amountMinor, currency, locale = getSyncedLocale()) {
21
25
  if (amountMinor == null || !currency) return "\u2014";
22
- const zeroDecimal = [
23
- "JPY",
24
- "VND",
25
- "KRW",
26
- "CLP",
27
- "ISK",
28
- "BIF",
29
- "DJF",
30
- "GNF",
31
- "KMF",
32
- "RWF",
33
- "XAF",
34
- "XOF",
35
- "XPF"
36
- ];
37
- const minorUnitDigits = zeroDecimal.includes(currency.toUpperCase()) ? 0 : 2;
26
+ const formatter = new Intl.NumberFormat(locale, { style: "currency", currency });
27
+ const minorUnitDigits = formatter.resolvedOptions().maximumFractionDigits ?? 2;
38
28
  const major = amountMinor / Math.pow(10, minorUnitDigits);
39
- return new Intl.NumberFormat("en-US", {
40
- style: "currency",
41
- currency,
42
- minimumFractionDigits: minorUnitDigits,
43
- maximumFractionDigits: minorUnitDigits
44
- }).format(major);
29
+ return formatter.format(major);
45
30
  }
46
31
  function shortId(id) {
47
32
  if (!id) return "\u2014";