@godxjp/ui 9.1.0 → 10.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 (145) 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-DnIXFzLi.d.ts → app.prop-Cy6dJnU8.d.ts} +18 -35
  5. package/dist/aspect-ratio-CZZJd9Km.d.ts +9 -0
  6. package/dist/{checkbox-ChRsR7Nk.d.ts → checkbox-em-oFM5D.d.ts} +1 -1
  7. package/dist/{chunk-LJLGABFV.js → chunk-2HXZT2WJ.js} +17 -9
  8. package/dist/{chunk-QLMXEJSY.js → chunk-3Q4A4U2P.js} +24 -1
  9. package/dist/{chunk-26CPAKUP.js → chunk-44YRPSZ7.js} +1 -2
  10. package/dist/{chunk-HB2OHB5X.js → chunk-5NCFLCM7.js} +27 -16
  11. package/dist/{chunk-FXFJF4YA.js → chunk-6CSBMMZS.js} +262 -31
  12. package/dist/{chunk-ZRRLOOBX.js → chunk-6HHSU6RG.js} +8 -6
  13. package/dist/{chunk-INSF6K3Y.js → chunk-7Q45MBFW.js} +7 -5
  14. package/dist/{chunk-O24Z3ULJ.js → chunk-BE6GJGKJ.js} +1 -1
  15. package/dist/{chunk-5D42MFB4.js → chunk-BG5RNXTH.js} +71 -2
  16. package/dist/{chunk-AINW5WYN.js → chunk-COD66MFF.js} +1 -2
  17. package/dist/{chunk-IOGU3ZWF.js → chunk-DNGJHWJZ.js} +3 -3
  18. package/dist/{chunk-3TS3G4U3.js → chunk-EE5DKOHX.js} +3 -1
  19. package/dist/{chunk-KXOAZGPA.js → chunk-EQZP53KI.js} +33 -8
  20. package/dist/{chunk-BHV2FUOA.js → chunk-EZHHJQWQ.js} +1 -1
  21. package/dist/{chunk-N3JPLJ3B.js → chunk-GDDCSKCB.js} +12 -5
  22. package/dist/{chunk-RLGHEV4A.js → chunk-HTG5VHU7.js} +10 -1
  23. package/dist/{chunk-R2W2FX5Q.js → chunk-I7NQ2LIL.js} +1 -9
  24. package/dist/{chunk-XQMPK4GM.js → chunk-IHRMOJXD.js} +86 -39
  25. package/dist/{chunk-TILFZBTE.js → chunk-INIIF7F7.js} +1 -4
  26. package/dist/{chunk-UIYEAUWA.js → chunk-IY347EQA.js} +2 -2
  27. package/dist/{chunk-HCM4JAC2.js → chunk-JWGLJXQU.js} +39 -11
  28. package/dist/{chunk-TO33OY4L.js → chunk-LMKUKCTN.js} +1 -1
  29. package/dist/chunk-NXVCI6YB.js +453 -0
  30. package/dist/{chunk-JBHXILI4.js → chunk-O6DQZYNI.js} +63 -44
  31. package/dist/{chunk-O2OUNXV4.js → chunk-P5KPCT6R.js} +3 -3
  32. package/dist/{chunk-56NYZNVY.js → chunk-PDXFQS7M.js} +112 -49
  33. package/dist/{chunk-F7PG4OEV.js → chunk-QSGW3ZWK.js} +12 -4
  34. package/dist/{chunk-25RYBC5T.js → chunk-S2IJKT3D.js} +1 -1
  35. package/dist/{chunk-OJZ6C2HM.js → chunk-SARQRCKO.js} +54 -48
  36. package/dist/chunk-T2QO2S65.js +126 -0
  37. package/dist/{chunk-442ULAA6.js → chunk-TGNBXS7H.js} +142 -62
  38. package/dist/{chunk-6J7GRCDA.js → chunk-UNVRNJCB.js} +71 -11
  39. package/dist/{chunk-6YBYAEXD.js → chunk-VSM44AYE.js} +94 -24
  40. package/dist/chunk-VSUYVT2Q.js +163 -0
  41. package/dist/{chunk-4R7QL3MW.js → chunk-X2VY4MOW.js} +14 -29
  42. package/dist/{chunk-FRU44GA2.js → chunk-XK3M3VRR.js} +16 -2
  43. package/dist/{chunk-6YK3IJXW.js → chunk-Z46J47FY.js} +73 -77
  44. package/dist/components/admin/index.d.ts +23 -13
  45. package/dist/components/admin/index.js +29 -30
  46. package/dist/components/data-display/badge.js +3 -3
  47. package/dist/components/data-display/card.d.ts +3 -3
  48. package/dist/components/data-display/card.js +1 -1
  49. package/dist/components/data-display/carousel.js +3 -1
  50. package/dist/components/data-display/index.js +55 -33
  51. package/dist/components/data-entry/calendar.d.ts +1 -1
  52. package/dist/components/data-entry/calendar.js +1 -1
  53. package/dist/components/data-entry/cascader.d.ts +1 -1
  54. package/dist/components/data-entry/cascader.js +5 -5
  55. package/dist/components/data-entry/checkbox.d.ts +2 -2
  56. package/dist/components/data-entry/checkbox.js +2 -2
  57. package/dist/components/data-entry/color-picker.d.ts +1 -1
  58. package/dist/components/data-entry/color-picker.js +3 -3
  59. package/dist/components/data-entry/date-picker.d.ts +2 -2
  60. package/dist/components/data-entry/date-picker.js +4 -4
  61. package/dist/components/data-entry/date-range-picker.d.ts +2 -2
  62. package/dist/components/data-entry/date-range-picker.js +4 -4
  63. package/dist/components/data-entry/index.d.ts +9 -25
  64. package/dist/components/data-entry/index.js +22 -26
  65. package/dist/components/data-entry/radio.d.ts +1 -1
  66. package/dist/components/data-entry/radio.js +2 -2
  67. package/dist/components/data-entry/select.d.ts +2 -2
  68. package/dist/components/data-entry/select.js +3 -4
  69. package/dist/components/data-entry/slider.d.ts +1 -1
  70. package/dist/components/data-entry/switch.d.ts +2 -2
  71. package/dist/components/data-entry/switch.js +1 -1
  72. package/dist/components/data-entry/time-input.js +2 -2
  73. package/dist/components/data-entry/time-picker.d.ts +3 -1
  74. package/dist/components/data-entry/time-picker.js +3 -3
  75. package/dist/components/data-entry/transfer.d.ts +2 -2
  76. package/dist/components/data-entry/transfer.js +5 -5
  77. package/dist/components/data-entry/tree-select.d.ts +1 -1
  78. package/dist/components/data-entry/tree-select.js +5 -5
  79. package/dist/components/data-entry/upload.d.ts +2 -2
  80. package/dist/components/data-entry/upload.js +5 -5
  81. package/dist/components/feedback/alert.js +5 -5
  82. package/dist/components/feedback/dialog.d.ts +20 -1
  83. package/dist/components/feedback/dialog.js +3 -3
  84. package/dist/components/feedback/index.d.ts +10 -18
  85. package/dist/components/feedback/index.js +9 -9
  86. package/dist/components/feedback/sheet.js +1 -1
  87. package/dist/components/layout/index.d.ts +27 -15
  88. package/dist/components/layout/index.js +7 -5
  89. package/dist/components/navigation/dropdown-menu.js +1 -1
  90. package/dist/components/navigation/index.d.ts +15 -17
  91. package/dist/components/navigation/index.js +7 -8
  92. package/dist/components/navigation/pagination.d.ts +25 -4
  93. package/dist/components/navigation/pagination.js +4 -5
  94. package/dist/components/navigation/steps.d.ts +3 -3
  95. package/dist/components/navigation/steps.js +3 -1
  96. package/dist/components/query/index.d.ts +1 -5
  97. package/dist/components/query/index.js +6 -8
  98. package/dist/components/ui/index.d.ts +13 -12
  99. package/dist/components/ui/index.js +30 -32
  100. package/dist/{data-entry.prop-CDkOajPj.d.ts → data-entry.prop-BR4vNA1j.d.ts} +7 -35
  101. package/dist/filter-bar-BxjSJJnQ.d.ts +7 -0
  102. package/dist/{inline-DCqn4O29.d.ts → flex-D_EXRFSW.d.ts} +2 -8
  103. package/dist/form/index.js +1 -1
  104. package/dist/i18n/index.d.ts +82 -10
  105. package/dist/i18n/index.js +2 -2
  106. package/dist/index.d.ts +7 -7
  107. package/dist/index.js +41 -44
  108. package/dist/{layout.prop-DwJKI6ka.d.ts → layout.prop-JE2TcRyL.d.ts} +8 -2
  109. package/dist/lib/datetime/index.js +1 -1
  110. package/dist/{navigation.prop-8DgElO0c.d.ts → navigation.prop-DMcXkR-J.d.ts} +9 -11
  111. package/dist/{toggle-group-BulJgKh3.d.ts → password-strength-DVRvXEOK.d.ts} +24 -3
  112. package/dist/props/components/index.d.ts +4 -4
  113. package/dist/props/index.d.ts +4 -4
  114. package/dist/props/index.js +1 -1
  115. package/dist/props/registry.d.ts +84 -39
  116. package/dist/props/registry.js +1 -1
  117. package/dist/{search-input-cezAxpgb.d.ts → search-input-DpqDMXcn.d.ts} +2 -4
  118. package/dist/{skeleton-uWAjSacg.d.ts → skeleton-cj9kh5wo.d.ts} +1 -3
  119. package/dist/styles/control.css +176 -41
  120. package/dist/styles/data-display-layout.css +41 -15
  121. package/dist/styles/data-entry-layout.css +71 -0
  122. package/dist/styles/feedback-layout.css +44 -12
  123. package/dist/styles/index.css +45 -1
  124. package/dist/styles/layout.css +66 -17
  125. package/dist/styles/navigation-layout.css +3 -1
  126. package/dist/styles/shell-layout.css +3 -3
  127. package/dist/styles/table-layout.css +13 -0
  128. package/dist/tokens/foundation.css +12 -1
  129. package/dist/tokens/semantic/layout.css +2 -2
  130. package/dist/tooltip-Bf2KjRy8.d.ts +14 -0
  131. package/package.json +7 -7
  132. package/scripts/ui-audit.mjs +31 -2
  133. package/dist/aspect-ratio-DGoYrOry.d.ts +0 -6
  134. package/dist/chunk-CAEL2ZD2.js +0 -222
  135. package/dist/chunk-FYM3MJSK.js +0 -59
  136. package/dist/chunk-GKXPALFT.js +0 -32
  137. package/dist/chunk-JKHWLPM5.js +0 -101
  138. package/dist/chunk-KDBGFJJI.js +0 -220
  139. package/dist/chunk-VN72SWHX.js +0 -189
  140. package/dist/components/data-entry/autocomplete.d.ts +0 -24
  141. package/dist/components/data-entry/autocomplete.js +0 -10
  142. package/dist/components/data-entry/combobox.d.ts +0 -22
  143. package/dist/components/data-entry/combobox.js +0 -6
  144. package/dist/filter-bar-BycYH10i.d.ts +0 -14
  145. /package/dist/{chunk-LDSLS6HE.js → chunk-7CFO5FFE.js} +0 -0
package/README.md CHANGED
@@ -1,10 +1,15 @@
1
1
  # @godxjp/ui
2
2
 
3
3
  The shared React UI framework for every godx surface (admin, agency portal,
4
- handheld). Built on shadcn + Radix UI + Tailwind CSS v4.
4
+ handheld). Built on shadcn + Radix UI + Tailwind CSS v4. **~98 components**, fully catalogued.
5
5
 
6
- Location: `packages/godx-ui/` (linked into the app as a `file:` dependency at
7
- `@godxjp/ui`).
6
+ - 📦 **npm:** `@godxjp/ui` (published) · MCP server `@godxjp/ui-mcp`
7
+ - 🌐 **Live preview / catalog:** **https://godx-jp.github.io/godxjp-ui/** (components · tokens · props)
8
+ - 🤖 **Agents:** the `@godxjp/ui-mcp` server exposes the full catalog (`get_component`, `list_primitives`, `search_components`) so coding agents use the real API instead of hand-rolling.
9
+
10
+ ```bash
11
+ npm i @godxjp/ui
12
+ ```
8
13
 
9
14
  ---
10
15
 
@@ -22,6 +27,11 @@ infrastructure, which means two things are non-negotiable:
22
27
  logic, no product copy, no raw colors. Those are **consumer-layer** concerns — they
23
28
  must never leak into this package. The framework ships **its own theme**, so a
24
29
  consumer imports the styles and needs **zero** extra theme configuration.
30
+ - **The root export is runtime-neutral.** Importing `@godxjp/ui` (or its primitive
31
+ subpaths) forces **no** foreign runtime — React Router, TanStack Query, react-hook-form
32
+ and the i18n singleton live ONLY on their adapter subpaths (`./form`, `./query`, `./app`).
33
+ A CI guard (`pnpm check:core-isolation`) traces the root dist graph and fails the build if
34
+ an adapter ever leaks into the root barrel.
25
35
 
26
36
  > Deciding whether a component belongs here vs. app-level? Use the
27
37
  > **`godx-ui-component-placement`** skill.
@@ -33,17 +43,17 @@ Full contributor rules: **[docs/DEVELOPMENT.md](./docs/DEVELOPMENT.md)**.
33
43
  ## Architecture (bottom-up)
34
44
 
35
45
  ```
36
- src/tokens/ Design tokens — the single source of values
37
- foundation.css :root + .dark: colors, fonts, type scale, spacing, radius, wa-iro
38
- primitives/ Per-domain primitive tokens (card, table, control, badge, …)
46
+ src/tokens/ Design tokens — 3-tier: primitive semantic → component
47
+ foundation.css primitive :root + .dark: raw palette, fonts, type scale, spacing, radius, wa-iro
48
+ semantic/ UI-role aliases (--primary, --destructive, --muted, …)
49
+ components/ per-component tokens (--card-*, --badge-*, …) aliasing semantic/primitive
39
50
  src/styles/ CSS that styles components by [data-slot]; density.css = the one density knob
40
51
  index.css Entry: fontsource → tailwindcss → @theme (token→utility map) → *-layout.css
41
52
  src/components/ React components by group (data-display, data-entry, layout, feedback, …)
42
- src/props/ Prop type system: vocabulary/ (atomic) + components/ + registry.ts
43
- src/lib/ cn(), control-styles, variants
44
- examples/ *.preview.tsx — Storybook-style stories
45
- docs/primitives/ <component>/index.tsx demo + examples/ + generated .md
46
- preview/ The preview app (vite, :6008) rendering examples + docs
53
+ src/props/ Prop type system: vocabulary/ (atomic) + components/ + registry.ts (NORMATIVE, CI-checked)
54
+ src/lib/ cn(), control-styles, variants, hooks
55
+ examples/ *.preview.tsx — Storybook-style stories (rendered by the preview app + Pages site)
56
+ preview/ The preview app (vite, :6008) also deployed to GitHub Pages
47
57
  ```
48
58
 
49
59
  A value is defined **once** as a CSS var (`--primary`), mapped to a utility in the
@@ -55,19 +65,25 @@ Components emit `data-slot` / `data-*`; the look lives in `styles/*-layout.css`.
55
65
 
56
66
  ## Component groups
57
67
 
58
- | Group | Import | Examples |
59
- | ------------------ | ------------------------- | ------------------------------------------------------------------------------- |
60
- | **Layout** | `@godxjp/ui/layout` | `PageContainer`, `Stack`, `Inline`, `ResponsiveGrid` |
61
- | **General** | `@godxjp/ui/general` | `Button` |
62
- | **Data Entry** | `@godxjp/ui/data-entry` | `Input`, `Select`, `FormField`, `DatePicker`, `Switch` |
63
- | **Data Display** | `@godxjp/ui/data-display` | `Table`, `DataTable`, `Card`, `Badge`, `KeyValueGrid`, `Timeline`, `EmptyState` |
64
- | **Feedback** | `@godxjp/ui/feedback` | `Dialog`, `Sheet`, `Toast`, `Skeleton`, `Alert` |
65
- | **Query** | `@godxjp/ui/query` | `DataState`, `InfiniteQueryState`, `PrefetchLink`, `MutationFeedback` |
66
- | **Navigation** | `@godxjp/ui/navigation` | `Tabs`, `FilterBar`, `DropdownMenu`, `Steps`, `Pagination`, `LocalePicker` |
67
- | **App** | `@godxjp/ui/app` | `AppProvider`, `useDateTime` |
68
- | **Datetime** | `@godxjp/ui/datetime` | `formatDate` (mandatory for display) |
69
- | **shadcn paths** | `@godxjp/ui/ui` | Thin re-exports for shadcn-style imports |
70
- | **Admin (legacy)** | `@godxjp/ui/admin` | Compound admin exports |
68
+ | Group | Import | Examples |
69
+ | ------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
70
+ | **Layout** | `@godxjp/ui/layout` | `Flex` (+ `Stack`/`Inline`), `PageContainer`, `ResponsiveGrid`, `AppShell`, `Sidebar`, `Separator`, `AspectRatio`, `Resizable` |
71
+ | **General** | `@godxjp/ui/general` | `Button` |
72
+ | **Data Entry** | `@godxjp/ui/data-entry` | `Input`, `Select`, `FormField`, `Field`, `DatePicker`, `TimePicker`, `Combobox`, `Switch`, `Toggle`, `Upload`, `Cascader`, `TreeSelect`, `ColorPicker`, `Slider`, `PasswordInput`, `PasswordStrength`, `InputOTP`, `Rating`, `TagInput` |
73
+ | **Data Display** | `@godxjp/ui/data-display` | `Table`, `DataTable`, `Card`, `StatCard`, `Badge`, `Avatar`, `Descriptions`, `Timeline`, `EmptyState`, `Progress`, `Accordion`, `HoverCard`, `Carousel`, `Popover`, `Collapsible` |
74
+ | **Feedback** | `@godxjp/ui/feedback` | `Dialog`, `AlertDialog`, `Sheet` (side), `Drawer` (bottom-sheet), `Toast`, `Skeleton`, `Alert`, `Tooltip` |
75
+ | **Query** | `@godxjp/ui/query` | `DataState`, `InfiniteQueryState`, `PrefetchLink` (adapter subpath — pulls TanStack Query) |
76
+ | **Navigation** | `@godxjp/ui/navigation` | `Tabs`, `Toolbar` (+ `FilterBar`), `DropdownMenu`, `ContextMenu`, `Menubar`, `NavigationMenu`, `Steps`, `Pagination`, `Breadcrumb`, `LocalePicker` |
77
+ | **App** | `@godxjp/ui/app` | `AppProvider`, `useDateTime` (adapter — i18n/datetime singleton) |
78
+ | **Datetime** | `@godxjp/ui/datetime` | `formatDate` (mandatory for display) |
79
+ | **Form** | `@godxjp/ui/form` | `useZodForm`, `FormRoot` (adapter subpath — pulls react-hook-form) |
80
+ | **Hooks** | `@godxjp/ui/hooks` | `useIsMobile`, `useMediaQuery` |
81
+ | **shadcn paths** | `@godxjp/ui/ui` | Thin re-exports for shadcn-style imports (tree-shakeable) |
82
+ | **Admin (legacy)** | `@godxjp/ui/admin` | Compound admin exports |
83
+
84
+ > **Renamed in 8.0** (thin aliases kept): `Stack`/`Inline`→`Flex`, `KeyValueGrid`→`Descriptions`,
85
+ > `ProgressMeter`→`Progress`, `CardStat`→`StatCard`, `FilterBar`→`Toolbar`, `ChoiceField`→`Field`,
86
+ > `SkeletonCard`→`SkeletonStat`. `StatusBadge`→`Badge` (`status`/`tone`), `DialogConfirm`/`Dialog mode="confirm"`→`AlertDialog`.
71
87
 
72
88
  ---
73
89
 
@@ -123,15 +139,25 @@ control + table heights together.
123
139
 
124
140
  ```bash
125
141
  pnpm preview # preview app → http://localhost:6008 (fixed port, kills stale)
126
- pnpm preview:build # static build — the integration test for examples + docs
127
- pnpm docs:sync-primitives # regenerate docs/primitives/**/*.md from source
128
- pnpm typecheck && pnpm audit && pnpm test
129
- pnpm check:mcp-sync # MCP registry ↔ library export drift guard (also in verify)
142
+ pnpm preview:build # static build — also what deploys to GitHub Pages
143
+ pnpm verify # typecheck · lint · format · the 5 guards · test
130
144
  pnpm release --ui <patch|minor|major> --mcp <…|skip> # publish lib + MCP in lockstep
131
145
  ```
132
146
 
147
+ **Five CI guards** (wired into `verify` / `verify:release`) keep the library honest:
148
+
149
+ | Guard | Enforces |
150
+ | ----------------------- | -------------------------------------------------------------------- |
151
+ | `check:prop-vocabulary` | every public `*Prop` field maps to the registry (no ad-hoc props) |
152
+ | `check:token-tiers` | 3-tier tokens; no domain/raw-palette tokens in component CSS |
153
+ | `check:mcp-sync` | every MCP catalog entry is a real export (no stale agent guidance) |
154
+ | `check:mcp-orphans` | every public component HAS a catalog entry (catalog can't rot) |
155
+ | `check:core-isolation` | the root export pulls no foreign runtime (adapters stay on subpaths) |
156
+
133
157
  This repo ships two packages — `@godxjp/ui` (this dir) and `@godxjp/ui-mcp` (`mcp/`). They keep
134
158
  separate version lines but release together via `pnpm release`; see DEVELOPMENT.md §6.
159
+ The **preview app auto-deploys to [GitHub Pages](https://godx-jp.github.io/godxjp-ui/)** on every push to `main`
160
+ (`.github/workflows/preview-pages.yml`) — which doubles as the CI gate for `preview:build`.
135
161
 
136
162
  → **[docs/DEVELOPMENT.md](./docs/DEVELOPMENT.md)** is the contributor guideline (the
137
163
  boundary, the layers, how to add/extend a component, verification).
@@ -139,7 +165,10 @@ boundary, the layers, how to add/extend a component, verification).
139
165
  ## Docs index
140
166
 
141
167
  - [docs/DEVELOPMENT.md](./docs/DEVELOPMENT.md) — contributor guideline (start here to edit the package)
168
+ - [docs/STANDARDS-vocabulary-tokens.md](./docs/STANDARDS-vocabulary-tokens.md) — the 22 vocabulary + token rules (CI-enforced)
169
+ - [docs/roadmap/post-7.0.0.md](./docs/roadmap/post-7.0.0.md) — shipped log (7.0→9.2) + key decisions
142
170
  - [docs/COMPONENTS.md](./docs/COMPONENTS.md) · [docs/TOKENS.md](./docs/TOKENS.md) · [docs/SPACING.md](./docs/SPACING.md)
143
171
  - [docs/PROPS-VOCABULARY.md](./docs/PROPS-VOCABULARY.md) · [docs/PROPS-REGISTRY.md](./docs/PROPS-REGISTRY.md)
144
172
  - [docs/DATETIME.md](./docs/DATETIME.md) · [docs/FORMS.md](./docs/FORMS.md) · [docs/TESTING.md](./docs/TESTING.md)
145
- - MCP: **godxjp-ui-mcp** (`.mcp.json`)
173
+ - **Architecture decisions** under `debate/*/04-Decision.md` (ADRs from the design debates)
174
+ - MCP: **godxjp-ui-mcp** (`.mcp.json`) — live catalog for agents
@@ -5,7 +5,7 @@ import * as date_fns from 'date-fns';
5
5
  import { Locale } from 'date-fns';
6
6
  import { vi } from 'react-day-picker/locale';
7
7
  import * as react_jsx_runtime from 'react/jsx-runtime';
8
- import { a as AppProviderProp, A as AppContextValue } from '../app.prop-DnIXFzLi.js';
8
+ import { a as AppProviderProp, A as AppContextValue } from '../app.prop-Cy6dJnU8.js';
9
9
  import { j as formatDate, a as FormatDateOptions } from '../format-date-ByyZoqI5.js';
10
10
  export { F as FormatDateKind, b as FormatDatetimeOptions, d as detectFormatDateKind, f as formatAppDate, c as formatAppDateLong, e as formatAppDateTime, g as formatAppRelative, h as formatAppTime, i as formatCalendarDate, k as formatTimeOfDay, m as isFormatDateValue } from '../format-date-ByyZoqI5.js';
11
11
  export { getDatetimeContext, isValidHhmm, normalizeHhmm, parseDateInput, syncDatetimeContext } from '../lib/datetime/index.js';
package/dist/app/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { useAppContext } from '../chunk-RLGHEV4A.js';
2
- export { APP_LOCALES, APP_REQUEST_HEADER_LOCALE, APP_REQUEST_HEADER_TIMEZONE, APP_TIMEZONE_OPTIONS, APP_TIMEZONE_PRESET, APP_TIME_FORMAT_OPTIONS, AppProvider, DEFAULT_STORAGE_KEY, TIMEZONE_ALIASES, formatTimezoneDisplayLabel, getAllIanaTimezones, getAppRequestHeaders, getBrowserTimezone, getTimeFormatLabel, getTimezoneCityName, getTimezoneLabel, getTimezoneOffsetLabel, isKnownAppTimezone, isValidIanaTimezone, readStoredPreferences, resetAppRequestHeaders, resetIanaTimezoneCacheForTests, resolveDefaultTimeFormat, resolveDefaultTimezone, resolveTimezoneForIntl, resolveTimezonePickerOptions, syncAppRequestHeaders, useAppContext, useAppDateFormat, useAppLocale, useAppTimeFormat, useAppTimezone, useOptionalAppContext, usePickerLocales, useTranslation, writeStoredPreferences } from '../chunk-RLGHEV4A.js';
3
- import { formatDate } from '../chunk-FXFJF4YA.js';
4
- export { APP_DATE_FORMATS, APP_DATE_FORMAT_OPTIONS, APP_LOCALE_CONFIG, APP_REQUEST_HEADER_DATE_FORMAT, APP_REQUEST_HEADER_TIME_FORMAT, APP_TIME_FORMATS, detectFormatDateKind, formatAppDate, formatAppDateLong, formatAppDateTime, formatAppRelative, formatAppTime, formatCalendarDate, formatDate, formatTimeOfDay, getDateFnsLocale, getDateFormatLabel, getDatePattern, getDateTimePattern, getDatetimeContext, getDayPickerLocale, getTimePattern, isAppDateFormat, isAppLocale, isAppTimeFormat, isFormatDateValue, isValidHhmm, normalizeHhmm, parseDateInput, resolveDefaultDateFormat, syncDatetimeContext } from '../chunk-FXFJF4YA.js';
1
+ import { useAppContext } from '../chunk-HTG5VHU7.js';
2
+ export { APP_LOCALES, APP_REQUEST_HEADER_LOCALE, APP_REQUEST_HEADER_TIMEZONE, APP_TIMEZONE_OPTIONS, APP_TIMEZONE_PRESET, APP_TIME_FORMAT_OPTIONS, AppProvider, DEFAULT_STORAGE_KEY, TIMEZONE_ALIASES, formatTimezoneDisplayLabel, getAllIanaTimezones, getAppRequestHeaders, getBrowserTimezone, getTimeFormatLabel, getTimezoneCityName, getTimezoneLabel, getTimezoneOffsetLabel, isKnownAppTimezone, isValidIanaTimezone, readStoredPreferences, resetAppRequestHeaders, resetIanaTimezoneCacheForTests, resolveDefaultTimeFormat, resolveDefaultTimezone, resolveTimezoneForIntl, resolveTimezonePickerOptions, syncAppRequestHeaders, useAppContext, useAppDateFormat, useAppLocale, useAppTimeFormat, useAppTimezone, useOptionalAppContext, usePickerLocales, useTranslation, writeStoredPreferences } from '../chunk-HTG5VHU7.js';
3
+ import { formatDate } from '../chunk-6CSBMMZS.js';
4
+ export { APP_DATE_FORMATS, APP_DATE_FORMAT_OPTIONS, APP_LOCALE_CONFIG, APP_REQUEST_HEADER_DATE_FORMAT, APP_REQUEST_HEADER_TIME_FORMAT, APP_TIME_FORMATS, detectFormatDateKind, formatAppDate, formatAppDateLong, formatAppDateTime, formatAppRelative, formatAppTime, formatCalendarDate, formatDate, formatTimeOfDay, getDateFnsLocale, getDateFormatLabel, getDatePattern, getDateTimePattern, getDatetimeContext, getDayPickerLocale, getTimePattern, isAppDateFormat, isAppLocale, isAppTimeFormat, isFormatDateValue, isValidHhmm, normalizeHhmm, parseDateInput, resolveDefaultDateFormat, syncDatetimeContext } from '../chunk-6CSBMMZS.js';
5
5
  import { useMemo } from 'react';
6
6
 
7
7
  function useFormatting() {
@@ -1,7 +1,7 @@
1
1
  import { Locale } from 'date-fns';
2
2
  import { DayPickerProps } from 'react-day-picker';
3
3
  import { h as AppLocale, l as AppTimezoneDefault, k as AppTimezone, j as AppTimeFormat, g as AppDateFormat, i as AppRequestHeaders } from './types-mvzYGrma.js';
4
- import { C as ChildrenProp, a as ClassNameProp, c as DisabledProp, I as IdProp, V as ValueProp, g as OnValueChangeProp } from './shared.prop-BsNSXeqD.js';
4
+ import { C as ChildrenProp, a as ClassNameProp, c as DisabledProp, I as IdProp, N as NameProp, V as ValueProp, g as OnValueChangeProp } from './shared.prop-BsNSXeqD.js';
5
5
 
6
6
  /** App shell prop types — @see docs/COMPONENTS.md#app */
7
7
 
@@ -21,7 +21,7 @@ type AppProviderProp = {
21
21
  /** Initial date display format. `"locale"` derives from `defaultLocale`. Default: `"locale"`. */
22
22
  defaultDateFormat?: AppDateFormat | "locale";
23
23
  /**
24
- * IANA ids shown in `TimezonePicker`.
24
+ * IANA ids offered by the timezone-picker recipe (`useAppContext().timezoneOptions`).
25
25
  * Omit for the full IANA list; set to restrict (e.g. `APP_TIMEZONE_PRESET`).
26
26
  */
27
27
  timezoneOptions?: readonly AppTimezone[];
@@ -34,40 +34,23 @@ type AppProviderProp = {
34
34
  onTimeFormatChange?: (timeFormat: AppTimeFormat) => void;
35
35
  onDateFormatChange?: (dateFormat: AppDateFormat) => void;
36
36
  };
37
- /** @see LocalePicker */
38
- type LocalePickerProp = {
37
+ /** Which AppProvider setting the {@link AppSettingPicker} reads/writes. */
38
+ type AppSettingKind = "locale" | "timezone" | "dateFormat" | "timeFormat";
39
+ /**
40
+ * @see AppSettingPicker — one provider-bound Select for any single AppProvider setting.
41
+ * Replaces the former Locale/Timezone/Date-format/Time-format pickers; pick the target
42
+ * via `kind`. Bound to `<AppProvider>` by default; pass value + onValueChange to control.
43
+ */
44
+ type AppSettingPickerProp = {
45
+ kind: AppSettingKind;
39
46
  className?: ClassNameProp;
40
47
  disabled?: DisabledProp;
41
48
  id?: IdProp;
42
- /** Controlled value; default reads/writes AppProvider. */
43
- value?: ValueProp<AppLocale>;
44
- onValueChange?: OnValueChangeProp<AppLocale>;
45
- };
46
- /** @see TimezonePicker */
47
- type TimezonePickerProp = {
48
- className?: ClassNameProp;
49
- disabled?: DisabledProp;
50
- id?: IdProp;
51
- value?: ValueProp<AppTimezone>;
52
- onValueChange?: OnValueChangeProp<AppTimezone>;
53
- /** Override AppProvider list; omit to use context or full IANA. */
54
- options?: readonly AppTimezone[];
55
- };
56
- /** @see TimeFormatPicker */
57
- type TimeFormatPickerProp = {
58
- className?: ClassNameProp;
59
- disabled?: DisabledProp;
60
- id?: IdProp;
61
- value?: ValueProp<AppTimeFormat>;
62
- onValueChange?: OnValueChangeProp<AppTimeFormat>;
63
- };
64
- /** @see DateFormatPicker */
65
- type DateFormatPickerProp = {
66
- className?: ClassNameProp;
67
- disabled?: DisabledProp;
68
- id?: IdProp;
69
- value?: ValueProp<AppDateFormat>;
70
- onValueChange?: OnValueChangeProp<AppDateFormat>;
49
+ /** Form field name — submits the selected value with the form. */
50
+ name?: NameProp;
51
+ /** Controlled value; default reads/writes the matching AppProvider context. */
52
+ value?: ValueProp<string>;
53
+ onValueChange?: OnValueChangeProp<string>;
71
54
  };
72
55
  /** Value exposed by `useAppContext`. */
73
56
  type AppContextValue = {
@@ -79,7 +62,7 @@ type AppContextValue = {
79
62
  dateFnsLocale: Locale;
80
63
  dayPickerLocale: NonNullable<DayPickerProps["locale"]>;
81
64
  requestHeaders: AppRequestHeaders;
82
- /** Configured picker list; `undefined` → full IANA in TimezonePicker. */
65
+ /** Configured timezone list; `undefined` → full IANA in the timezone-picker recipe. */
83
66
  timezoneOptions?: readonly AppTimezone[];
84
67
  setLocale: (locale: AppLocale) => void;
85
68
  setTimezone: (timezone: AppTimezone) => void;
@@ -87,4 +70,4 @@ type AppContextValue = {
87
70
  setDateFormat: (dateFormat: AppDateFormat) => void;
88
71
  };
89
72
 
90
- export type { AppContextValue as A, DateFormatPickerProp as D, LocalePickerProp as L, TimeFormatPickerProp as T, AppProviderProp as a, TimezonePickerProp as b };
73
+ export type { AppContextValue as A, AppProviderProp as a, AppSettingKind as b, AppSettingPickerProp as c };
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
3
+ import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio';
4
+
5
+ declare const Separator: React.ForwardRefExoticComponent<Omit<SeparatorPrimitive.SeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
6
+
7
+ declare const AspectRatio: React.ForwardRefExoticComponent<Omit<AspectRatioPrimitive.AspectRatioProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
8
+
9
+ export { AspectRatio as A, Separator as S };
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { c as CheckboxGroupProp } from './data-entry.prop-CDkOajPj.js';
4
+ import { c as CheckboxGroupProp } from './data-entry.prop-BR4vNA1j.js';
5
5
 
6
6
  declare function CheckboxGroup({ value: controlledValue, defaultValue, onValueChange, options, orientation, disabled, name, className, children, }: CheckboxGroupProp): react_jsx_runtime.JSX.Element;
7
7
 
@@ -1,9 +1,9 @@
1
- import { Calendar } from './chunk-IOGU3ZWF.js';
1
+ import { Calendar } from './chunk-DNGJHWJZ.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';
5
- import { useTranslation, usePickerLocales } from './chunk-RLGHEV4A.js';
6
- import { toIsoDate, parseDateInput } from './chunk-FXFJF4YA.js';
5
+ import { useTranslation, usePickerLocales } from './chunk-HTG5VHU7.js';
6
+ import { toIsoDate, parseDateInput } from './chunk-6CSBMMZS.js';
7
7
  import { cn } from './chunk-U7N2A7A3.js';
8
8
  import * as React from 'react';
9
9
  import { CalendarIcon } from 'lucide-react';
@@ -11,7 +11,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
11
11
 
12
12
  var ISO_HINT = "yyyy-mm-dd";
13
13
  function DatePicker({
14
- value,
14
+ value: valueProp,
15
+ defaultValue,
15
16
  onValueChange,
16
17
  placeholder,
17
18
  disabled,
@@ -25,6 +26,13 @@ function DatePicker({
25
26
  const { t } = useTranslation();
26
27
  const { dayPickerLocale } = usePickerLocales(localeProp);
27
28
  const [open, setOpen] = React.useState(false);
29
+ const isControlled = React.useRef(valueProp !== void 0).current;
30
+ const [internalValue, setInternalValue] = React.useState(defaultValue);
31
+ const value = isControlled ? valueProp : internalValue;
32
+ const emit = (next) => {
33
+ if (!isControlled) setInternalValue(next);
34
+ onValueChange?.(next);
35
+ };
28
36
  const [text, setText] = React.useState(() => toIsoDate(value));
29
37
  React.useEffect(() => {
30
38
  setText(toIsoDate(value));
@@ -33,12 +41,12 @@ function DatePicker({
33
41
  const commit = (raw) => {
34
42
  const trimmed = raw.trim();
35
43
  if (trimmed === "") {
36
- onValueChange?.(void 0);
44
+ emit(void 0);
37
45
  return;
38
46
  }
39
47
  const parsed = parseDateInput(trimmed);
40
48
  if (parsed) {
41
- onValueChange?.(parsed);
49
+ emit(parsed);
42
50
  }
43
51
  };
44
52
  return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
@@ -55,7 +63,7 @@ function DatePicker({
55
63
  role: "combobox",
56
64
  "aria-expanded": open,
57
65
  "aria-haspopup": "dialog",
58
- className: "pr-10",
66
+ className: "pe-10",
59
67
  onChange: (event) => {
60
68
  setText(event.target.value);
61
69
  commit(event.target.value);
@@ -76,7 +84,7 @@ function DatePicker({
76
84
  disabled,
77
85
  tabIndex: -1,
78
86
  "aria-label": t("dataEntry.datePicker.openCalendar") ?? "Open calendar",
79
- className: "text-muted-foreground absolute inset-y-0 right-0 h-full px-2 hover:bg-transparent",
87
+ className: "text-muted-foreground absolute inset-y-0 end-0 h-full px-2 hover:bg-transparent",
80
88
  children: /* @__PURE__ */ jsx(CalendarIcon, { className: "size-4 shrink-0", "aria-hidden": "true" })
81
89
  }
82
90
  ) }),
@@ -86,7 +94,7 @@ function DatePicker({
86
94
  mode: "single",
87
95
  selected: value,
88
96
  onSelect: (date) => {
89
- onValueChange?.(date);
97
+ emit(date);
90
98
  setText(toIsoDate(date));
91
99
  setOpen(false);
92
100
  },
@@ -1,4 +1,4 @@
1
- import { normalizeHhmm, isValidHhmm } from './chunk-FXFJF4YA.js';
1
+ import { normalizeHhmm, isValidHhmm } from './chunk-6CSBMMZS.js';
2
2
  import { cn } from './chunk-U7N2A7A3.js';
3
3
  import * as React from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -24,6 +24,14 @@ function maskTime(raw) {
24
24
  if (digits.length <= 2) return digits;
25
25
  return `${digits.slice(0, 2)}:${digits.slice(2)}`;
26
26
  }
27
+ function stepTime(value, deltaMinutes) {
28
+ const normalized = normalizeHhmm(value) ?? "00:00";
29
+ const [hourText, minuteText] = normalized.split(":");
30
+ const total = (Number(hourText) * 60 + Number(minuteText) + deltaMinutes + 24 * 60) % (24 * 60);
31
+ const hour = Math.floor(total / 60);
32
+ const minute = total % 60;
33
+ return `${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
34
+ }
27
35
  function TimeInput({
28
36
  value: controlledValue,
29
37
  defaultValue = "",
@@ -66,6 +74,7 @@ function TimeInput({
66
74
  },
67
75
  [isControlled, onValueChange, safeStep, value]
68
76
  );
77
+ const valid = isValidHhmm(value);
69
78
  return /* @__PURE__ */ jsx(
70
79
  "input",
71
80
  {
@@ -74,6 +83,11 @@ function TimeInput({
74
83
  value: displayValue,
75
84
  "data-slot": "time-input",
76
85
  className: cn("ui-time-input", className),
86
+ role: "spinbutton",
87
+ "aria-valuemin": 0,
88
+ "aria-valuemax": 24 * 60 - 1,
89
+ "aria-valuenow": valid ? Number(value.slice(0, 2)) * 60 + Number(value.slice(3, 5)) : void 0,
90
+ "aria-valuetext": valid ? value : void 0,
77
91
  "aria-invalid": displayValue !== "" && !isValidHhmm(displayValue) ? "true" : void 0,
78
92
  placeholder: placeholder ?? "HH:mm",
79
93
  inputMode: "numeric",
@@ -104,6 +118,15 @@ function TimeInput({
104
118
  onKeyDown: (event) => {
105
119
  if (event.key === "Enter") {
106
120
  commit(event.currentTarget.value, true);
121
+ } else if (event.key === "ArrowUp" || event.key === "ArrowDown") {
122
+ event.preventDefault();
123
+ const base = isValidHhmm(displayValue) ? displayValue : value || "00:00";
124
+ const next = stepTime(base, event.key === "ArrowUp" ? safeStep : -safeStep);
125
+ setDisplayValue(next);
126
+ if (!isControlled) {
127
+ setInternal(next);
128
+ }
129
+ onValueChange?.(next);
107
130
  }
108
131
  props.onKeyDown?.(event);
109
132
  }
@@ -11,11 +11,10 @@ function Field({ id, label, description, className, children }) {
11
11
  ] })
12
12
  ] });
13
13
  }
14
- var ChoiceField = Field;
15
14
 
16
15
  // src/components/data-entry/choice-option.ts
17
16
  function choiceGroupClassName(_orientation = "vertical", className) {
18
17
  return cn("ui-choice-group", className);
19
18
  }
20
19
 
21
- export { ChoiceField, Field, choiceGroupClassName };
20
+ export { Field, choiceGroupClassName };
@@ -1,10 +1,10 @@
1
1
  import { normalizeTreeOptions, formatPathLabels, getNodeByPath, filterTreeOptions, pathsEqual, pathKey } from './chunk-SMLKNECP.js';
2
- import { Checkbox } from './chunk-O24Z3ULJ.js';
3
2
  import { Command, CommandInput } from './chunk-HTEL5DQI.js';
3
+ import { Checkbox } from './chunk-BE6GJGKJ.js';
4
4
  import { Button } from './chunk-M4PZNAMV.js';
5
5
  import { Popover, PopoverTrigger, PopoverContent } from './chunk-DY5C44UP.js';
6
6
  import { ScrollArea, ScrollBar } from './chunk-3KPEZ5CF.js';
7
- import { useTranslation } from './chunk-RLGHEV4A.js';
7
+ import { useTranslation } from './chunk-HTG5VHU7.js';
8
8
  import { cn } from './chunk-U7N2A7A3.js';
9
9
  import * as React from 'react';
10
10
  import { X, ChevronsUpDown, Check, ChevronRight } from 'lucide-react';
@@ -117,17 +117,24 @@ function Cascader({
117
117
  /* @__PURE__ */ jsx("div", { className: "flex max-h-[min(280px,50vh)]", children: columns.map((col, colIndex) => /* @__PURE__ */ jsx(
118
118
  "ul",
119
119
  {
120
- className: "min-w-[9rem] border-r last:border-r-0",
120
+ role: "listbox",
121
+ "aria-orientation": "vertical",
122
+ "aria-multiselectable": multiple ? true : void 0,
123
+ className: "min-w-[9rem] border-e last:border-e-0",
121
124
  onMouseLeave: expandTrigger === "hover" ? () => setActivePath(activePath.slice(0, colIndex)) : void 0,
122
125
  children: col.map((node) => {
123
126
  const path = [...activePath.slice(0, colIndex), node.value];
124
127
  const hasChildren = (node.children?.length ?? 0) > 0 && node.isLeaf !== true;
125
128
  const active = activePath[colIndex] === node.value;
126
129
  const selected = multiple ? pathInValues(path, multiValue) : pathsEqual(path, singleValue);
127
- return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
130
+ return /* @__PURE__ */ jsx("li", { role: "none", children: /* @__PURE__ */ jsxs(
128
131
  "button",
129
132
  {
130
133
  type: "button",
134
+ role: "option",
135
+ "aria-selected": selected,
136
+ "aria-haspopup": hasChildren ? "menu" : void 0,
137
+ "aria-expanded": hasChildren ? active : void 0,
131
138
  disabled: node.disabled,
132
139
  className: cn(
133
140
  "flex w-full items-center gap-1 px-3 py-2 text-sm outline-none",
@@ -143,13 +150,13 @@ function Cascader({
143
150
  {
144
151
  checked: selected,
145
152
  disabled: node.disabled,
146
- className: "mr-1",
153
+ className: "me-1",
147
154
  "aria-hidden": true,
148
155
  tabIndex: -1
149
156
  }
150
157
  ),
151
- !multiple && selected && /* @__PURE__ */ jsx(Check, { className: "mr-1 size-4 shrink-0", "aria-hidden": "true" }),
152
- /* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-left", children: node.label }),
158
+ !multiple && selected && /* @__PURE__ */ jsx(Check, { className: "me-1 size-4 shrink-0", "aria-hidden": "true" }),
159
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-start", children: node.label }),
153
160
  hasChildren && /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 shrink-0 opacity-50", "aria-hidden": "true" })
154
161
  ]
155
162
  }
@@ -177,13 +184,15 @@ function Cascader({
177
184
  ),
178
185
  children: [
179
186
  /* @__PURE__ */ jsx("span", { className: "truncate", children: displayLabel ?? resolvedPlaceholder }),
180
- /* @__PURE__ */ jsxs("span", { className: "ml-2 flex shrink-0 items-center gap-1", children: [
187
+ /* @__PURE__ */ jsxs("span", { className: "ms-2 flex shrink-0 items-center gap-1", children: [
181
188
  allowClear && displayLabel && !disabled && /* @__PURE__ */ jsx(
182
- X,
189
+ "button",
183
190
  {
184
- className: "size-4 opacity-50 hover:opacity-100",
185
- "aria-hidden": "true",
186
- onClick: clearValue
191
+ type: "button",
192
+ "aria-label": t("dataEntry.cascader.clear"),
193
+ className: "flex size-4 items-center justify-center rounded-sm opacity-50 hover:opacity-100 focus-visible:opacity-100",
194
+ onClick: clearValue,
195
+ children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
187
196
  }
188
197
  ),
189
198
  /* @__PURE__ */ jsx(ChevronsUpDown, { className: "size-4 opacity-50", "aria-hidden": "true" })
@@ -205,13 +214,15 @@ function Cascader({
205
214
  onValueChange: setSearch
206
215
  }
207
216
  ) }) }),
208
- isSearching ? /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[min(300px,50vh)]", children: /* @__PURE__ */ jsx("div", { className: "p-1", 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 }) => {
217
+ isSearching ? /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[min(300px,50vh)]", children: /* @__PURE__ */ jsx("div", { className: "p-1", role: "listbox", "aria-multiselectable": multiple ? true : void 0, 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 }) => {
209
218
  const label = labels.join(" / ");
210
219
  const selected = multiple ? pathInValues(path, multiValue) : pathsEqual(path, singleValue);
211
220
  return /* @__PURE__ */ jsxs(
212
221
  "button",
213
222
  {
214
223
  type: "button",
224
+ role: "option",
225
+ "aria-selected": selected,
215
226
  className: cn(
216
227
  "flex w-full items-center rounded-sm px-2 py-1.5 text-sm outline-none",
217
228
  "hover:bg-accent hover:text-accent-foreground",
@@ -219,17 +230,17 @@ function Cascader({
219
230
  ),
220
231
  onClick: () => handleSelectNode({ value: path.at(-1)}, path),
221
232
  children: [
222
- multiple ? /* @__PURE__ */ jsx(Checkbox, { checked: selected, className: "mr-2", "aria-hidden": true, tabIndex: -1 }) : /* @__PURE__ */ jsx(
233
+ multiple ? /* @__PURE__ */ jsx(Checkbox, { checked: selected, className: "me-2", "aria-hidden": true, tabIndex: -1 }) : /* @__PURE__ */ jsx(
223
234
  Check,
224
235
  {
225
236
  className: cn(
226
- "mr-2 size-4 shrink-0",
237
+ "me-2 size-4 shrink-0",
227
238
  selected ? "opacity-100" : "opacity-0"
228
239
  ),
229
240
  "aria-hidden": "true"
230
241
  }
231
242
  ),
232
- /* @__PURE__ */ jsx("span", { className: "truncate text-left", children: label })
243
+ /* @__PURE__ */ jsx("span", { className: "truncate text-start", children: label })
233
244
  ]
234
245
  },
235
246
  pathKey(path)