@dreamtree-org/twreact-ui 1.3.8 → 1.3.10

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 (109) hide show
  1. package/DESIGN.md +11 -3
  2. package/README.md +9 -1
  3. package/ai-skills/dreamtree-ui.md +2 -2
  4. package/dist/ai-schema.json +19 -8
  5. package/dist/charts/index.js +69 -24
  6. package/dist/components/blocks/AppShell.d.ts.map +1 -1
  7. package/dist/components/charts/chartTheme.d.ts +2 -5
  8. package/dist/components/charts/chartTheme.d.ts.map +1 -1
  9. package/dist/components/core/Accordion.d.ts.map +1 -1
  10. package/dist/components/core/ColorPicker.d.ts.map +1 -1
  11. package/dist/components/core/DatePicker.d.ts.map +1 -1
  12. package/dist/components/core/Form.d.ts.map +1 -1
  13. package/dist/components/core/Input.d.ts.map +1 -1
  14. package/dist/components/core/PriceRangePicker.d.ts +0 -29
  15. package/dist/components/core/PriceRangePicker.d.ts.map +1 -1
  16. package/dist/components/core/Radio.d.ts.map +1 -1
  17. package/dist/components/core/Rate.d.ts.map +1 -1
  18. package/dist/components/core/RoundedTag.d.ts.map +1 -1
  19. package/dist/components/core/Table/ColumnMenu.d.ts.map +1 -1
  20. package/dist/components/core/Table/Pagination.d.ts.map +1 -1
  21. package/dist/components/core/Table/Table.d.ts.map +1 -1
  22. package/dist/components/core/Table/TableRow.d.ts.map +1 -1
  23. package/dist/components/core/Table/helpers.d.ts +2 -0
  24. package/dist/components/core/Table/helpers.d.ts.map +1 -1
  25. package/dist/components/core/Table/useClickOutside.d.ts +5 -2
  26. package/dist/components/core/Table/useClickOutside.d.ts.map +1 -1
  27. package/dist/components/core/Tabs.d.ts.map +1 -1
  28. package/dist/components/core/TextToSpeech.d.ts +2 -7
  29. package/dist/components/core/TextToSpeech.d.ts.map +1 -1
  30. package/dist/components/core/Tooltip.d.ts.map +1 -1
  31. package/dist/components/feedback/Alert.d.ts.map +1 -1
  32. package/dist/components/feedback/Dialog.d.ts.map +1 -1
  33. package/dist/components/feedback/Toast.d.ts.map +1 -1
  34. package/dist/components/navigation/Sidebar.d.ts.map +1 -1
  35. package/dist/components/utility/Avatar.d.ts.map +1 -1
  36. package/dist/components/utility/Carousel.d.ts.map +1 -1
  37. package/dist/components/utility/Portal.d.ts +6 -0
  38. package/dist/components/utility/Portal.d.ts.map +1 -0
  39. package/dist/esm/components/blocks/AppShell.js +24 -18
  40. package/dist/esm/components/charts/CartesianChart.js +2 -1
  41. package/dist/esm/components/charts/DonutChart.js +2 -1
  42. package/dist/esm/components/charts/Sparkline.js +2 -1
  43. package/dist/esm/components/charts/chartTheme.js +1 -22
  44. package/dist/esm/components/core/Accordion.js +40 -9
  45. package/dist/esm/components/core/Button.js +8 -8
  46. package/dist/esm/components/core/ColorPicker.js +19 -7
  47. package/dist/esm/components/core/DatePicker.js +97 -58
  48. package/dist/esm/components/core/Form.js +35 -8
  49. package/dist/esm/components/core/Input.js +3 -1
  50. package/dist/esm/components/core/PriceRangePicker.js +205 -218
  51. package/dist/esm/components/core/Radio.js +36 -6
  52. package/dist/esm/components/core/Rate.js +41 -50
  53. package/dist/esm/components/core/RoundedTag.js +25 -8
  54. package/dist/esm/components/core/Table/ColumnMenu.js +2 -4
  55. package/dist/esm/components/core/Table/Pagination.js +15 -18
  56. package/dist/esm/components/core/Table/Table.js +11 -5
  57. package/dist/esm/components/core/Table/TableRow.js +2 -2
  58. package/dist/esm/components/core/Table/helpers.js +33 -1
  59. package/dist/esm/components/core/Tabs.js +6 -5
  60. package/dist/esm/components/core/TextToSpeech.js +121 -28
  61. package/dist/esm/components/core/Tooltip.js +100 -28
  62. package/dist/esm/components/feedback/Alert.js +21 -11
  63. package/dist/esm/components/feedback/Dialog.js +44 -100
  64. package/dist/esm/components/feedback/Toast.js +24 -5
  65. package/dist/esm/components/navigation/Sidebar.js +13 -61
  66. package/dist/esm/components/utility/Avatar.js +23 -10
  67. package/dist/esm/components/utility/Carousel.js +34 -17
  68. package/dist/esm/components/utility/Pagination.js +2 -2
  69. package/dist/esm/hooks/useClickOutside.js +51 -0
  70. package/dist/esm/hooks/useFocusTrap.js +10 -2
  71. package/dist/esm/hooks/useMediaQuery.js +61 -0
  72. package/dist/esm/hooks/useReducedMotion.js +17 -0
  73. package/dist/esm/hooks/useScrollLock.js +76 -9
  74. package/dist/esm/hooks/useTheme.js +6 -1
  75. package/dist/esm/utils/position.js +6 -0
  76. package/dist/hooks/useClickOutside.d.ts +14 -0
  77. package/dist/hooks/useClickOutside.d.ts.map +1 -0
  78. package/dist/hooks/useFloatingPosition.d.ts +37 -0
  79. package/dist/hooks/useFloatingPosition.d.ts.map +1 -0
  80. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  81. package/dist/hooks/useMediaQuery.d.ts +22 -0
  82. package/dist/hooks/useMediaQuery.d.ts.map +1 -0
  83. package/dist/hooks/usePresence.d.ts +16 -0
  84. package/dist/hooks/usePresence.d.ts.map +1 -0
  85. package/dist/hooks/usePresentation.d.ts +9 -0
  86. package/dist/hooks/usePresentation.d.ts.map +1 -0
  87. package/dist/hooks/useReducedMotion.d.ts +10 -0
  88. package/dist/hooks/useReducedMotion.d.ts.map +1 -0
  89. package/dist/hooks/useScrollLock.d.ts +11 -1
  90. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  91. package/dist/hooks/useTheme.d.ts.map +1 -1
  92. package/dist/index.css +1 -1
  93. package/dist/index.esm.css +1 -1
  94. package/dist/index.esm.js +1719 -1201
  95. package/dist/index.js +1718 -1200
  96. package/dist/tokens/tailwind3-preset.cjs +101 -8
  97. package/dist/tokens/theme.css +27 -0
  98. package/dist/tokens/tokens.json +175 -0
  99. package/dist/tokens/vars.css +2 -0
  100. package/dist/types/index.d.ts +8 -2
  101. package/dist/types/index.d.ts.map +1 -1
  102. package/dist/utils/position.d.ts.map +1 -1
  103. package/dist/utils/touchTarget.d.ts +1 -0
  104. package/dist/utils/touchTarget.d.ts.map +1 -1
  105. package/mcp/catalog.snapshot.json +83 -53
  106. package/package.json +2 -1
  107. package/tokens/lib.cjs +35 -0
  108. package/tokens/tokens.json +58 -2
  109. package/dist/esm/components/core/Table/useClickOutside.js +0 -26
package/DESIGN.md CHANGED
@@ -37,7 +37,11 @@ typography:
37
37
  rounded:
38
38
  control: 8px
39
39
  card: 12px
40
+ sheet: 16px
40
41
  pill: 9999px
42
+ elevation: [xs, sm, md, lg, xl, overlay]
43
+ zIndex: { base: 0, sticky: 20, dropdown: 30, overlay: 40, modal: 50, popover: 60, toast: 70, tooltip: 80 }
44
+ motion: { fast: 120ms, base: 200ms, slow: 320ms }
41
45
  spacing:
42
46
  grid: 4px
43
47
  steps: [4, 8, 12, 16, 20, 24, 32]
@@ -81,9 +85,12 @@ Every Dreamtree product screen, and every prototype generated by Dreamtree Studi
81
85
  ## 3. Type, space and shape
82
86
 
83
87
  - Font: Inter. Numbers in tables and KPIs use `tabular-nums`.
84
- - Scale: page title `text-2xl font-semibold`, section title `text-base font-semibold`, body `text-sm`, caption `text-xs text-muted`, KPI `text-3xl font-semibold`. For tiny labels use `text-micro`, never `text-[10px]` or `text-[11px]`.
88
+ - Scale: use the role classes `text-page-title`, `text-section-title` (both semibold), `text-body`, `text-caption text-muted` and `text-kpi` (semibold). The older `text-2xl font-semibold` / `text-base` / `text-sm` / `text-xs` / `text-3xl` spellings are equivalent. For tiny labels use `text-micro`, never `text-[10px]` or `text-[11px]`. Code and ids use `font-mono`.
89
+ - Elevation: `shadow-xs` … `shadow-xl`, and `shadow-overlay` for dialogs, sheets, popovers and menus. Shadows deepen automatically in dark mode.
90
+ - Layers: `z-sticky`, `z-dropdown`, `z-overlay`, `z-modal`, `z-popover`, `z-toast`, `z-tooltip`. Never `z-50` or an inline `zIndex`.
91
+ - Motion: `duration-fast` (120 ms), `duration-base` (200 ms), `duration-slow` (320 ms) with `ease-standard`, `ease-emphasized` or `ease-spring-out`. Keyframes: `animate-fade-in` / `animate-fade-out`, `animate-scale-in` / `animate-scale-out`, `animate-slide-up`, `animate-slide-down` / `animate-slide-down-out`, `animate-sheet-in` / `animate-sheet-out`. Always pair one with `motion-reduce:animate-none` (e.g. `animate-sheet-in motion-reduce:animate-none`).
85
92
  - **No arbitrary values** (`w-[312px]`, `text-[13px]`, `p-[7px]`). Use the Tailwind scale on a 4 px grid: steps 1, 2, 3, 4, 5, 6, 8.
86
- - Radius: `rounded-control` (8 px) for buttons, inputs and menus; `rounded-card` (12 px) for cards and dialogs; `rounded-full` for pills and badges.
93
+ - Radius: `rounded-control` (8 px) for buttons, inputs and menus; `rounded-card` (12 px) for cards and dialogs; `rounded-sheet` (16 px) for bottom-sheet top corners; `rounded-pill` (or `rounded-full`) for pills and badges.
87
94
  - Sentence case everywhere ("Add obligation", not "Add Obligation").
88
95
 
89
96
  ## 4. Page anatomy
@@ -107,9 +114,10 @@ Every Dreamtree product screen, and every prototype generated by Dreamtree Studi
107
114
  ## 7. Responsive and accessible
108
115
 
109
116
  - No horizontal page scroll at **390 px**. Below `lg` the shell becomes a top bar with a drawer. Wide tables scroll inside their card.
110
- - Tap targets are at least 40 px. Every control has a visible label. Focus is visible (`focus:ring-2 focus:ring-primary-500 focus:ring-offset-2`).
117
+ - Tap targets are at least **44 px** on touch screens (Apple HIG; WCAG 2.5.5). Icon-only controls grow to 44×44 on `pointer: coarse` and keep their compact size with a mouse. Pressables shrink slightly while pressed (`active:scale-[0.97]`, off under reduced motion). Every control has a visible label. Focus is visible for keyboard users (`focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2`); a mouse click doesn't leave a ring.
111
118
  - Text contrast is at least 4.5:1. Status is never shown by colour alone: badges carry words.
112
119
  - Respect `prefers-reduced-motion`.
120
+ - Phones: pages use `viewport-fit=cover`; bars that touch a screen edge pad with `pt-safe` / `pb-safe` / `px-safe` (or `inset-safe`). Full-height layouts use `min-h-dvh` / `h-dvh`, never `100vh`. Text fields render at 16 px on touch screens so iOS doesn't zoom on focus.
113
121
 
114
122
  ## 8. Data and content
115
123
 
package/README.md CHANGED
@@ -881,7 +881,7 @@ module.exports = {
881
881
  @source "../node_modules/@dreamtree-org/twreact-ui/dist/index.esm.js";
882
882
  ```
883
883
 
884
- The palettes are `primary`, `secondary`, `success`, `warning`, `error`, `info` and `gray` (steps 50–950), so `bg-info-50` / `text-info-600` work out of the box; `info` is for informational and scheduled states that are not the brand accent. This adds semantic utilities next to the palettes: `bg-surface`, `bg-background`, `text-foreground`, `text-muted`, `border-line`, `bg-shell`, `text-micro`, `rounded-control` and `rounded-card`. Add a brand by creating `tokens/brands/<name>.json`; it overrides only the steps and roles you list.
884
+ The palettes are `primary`, `secondary`, `success`, `warning`, `error`, `info` and `gray` (steps 50–950), so `bg-info-50` / `text-info-600` work out of the box; `info` is for informational and scheduled states that are not the brand accent. This adds semantic utilities next to the palettes: `bg-surface`, `bg-background`, `text-foreground`, `text-muted`, `border-line`, `bg-shell`, `text-micro`, `rounded-control` and `rounded-card`. Non-colour scales come from the same file: type roles (`text-page-title`, `text-section-title`, `text-body`, `text-caption`, `text-kpi`), `rounded-sheet` / `rounded-pill`, `font-mono`, elevation (`shadow-xs` … `shadow-xl`, `shadow-overlay`; deeper in dark mode via `--dt-shadow-strength`), z-layers (`z-sticky`, `z-dropdown`, `z-overlay`, `z-modal`, `z-popover`, `z-toast`, `z-tooltip`) and motion (`duration-fast|base|slow`, `ease-standard|emphasized|spring-out`). The Tailwind 3 preset and Tailwind 4 theme include them. Add a brand by creating `tokens/brands/<name>.json`; it overrides only the steps and roles you list.
885
885
 
886
886
  **Design rules:** [`DESIGN.md`](DESIGN.md) is the rule set for product screens and AI agents: tokens only, blocks first, loading, empty and error states, 390 px, no native dialogs. It is generated from the tokens (`npm run build:tokens`).
887
887
 
@@ -889,6 +889,10 @@ The palettes are `primary`, `secondary`, `success`, `warning`, `error`, `info` a
889
889
 
890
890
  **SSR:** `Tabs`, `Tooltip` and `Switch` generate ids with `React.useId()`, so server-rendered pages (Next.js) hydrate without mismatches. The `/charts` components do the same for their SVG ids, and they render token colours and reduced-motion state the way the server did until hydration finishes.
891
891
 
892
+ ## Mobile and touch
893
+
894
+ The stylesheet ships a phone baseline: no tap highlight, no iOS zoom when a field is focused (text fields are 16px on touch screens; add `dt-keep-font-size` to opt one out), `color-scheme` that follows the theme, and no rubber-band overscroll on `body` (add `dt-overscroll-auto` to `<html>` to keep pull-to-refresh). Pad edge bars with `pt-safe` / `pb-safe` / `px-safe` / `inset-safe` — they need `<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">` — and size full-height layouts with `min-h-dvh` instead of `100vh`. Touch targets grow to 44px on coarse pointers.
895
+
892
896
  ## Dark Mode
893
897
 
894
898
  Enable dark mode with the built-in theme provider:
@@ -905,8 +909,12 @@ function App() {
905
909
  }
906
910
  ```
907
911
 
912
+ `ThemeProvider` sets `data-theme`, the `.dark` class and `color-scheme` on `<html>`, so `dark:` utilities work whether your `tailwind.config.js` uses `darkMode: 'class'` or a `[data-theme="dark"]` selector.
913
+
908
914
  Surfaces such as `Card`, `Sidebar`, `Navbar`, `Table`, `FootNav` and `Dropdown` use the semantic `bg-surface` / `bg-background` / `border-line` / `text-foreground` / `text-muted` tokens, which switch under `.dark` (or `[data-theme="dark"]`). Re-theme them by overriding the `--dt-surface`, `--dt-background`, `--dt-line`, … variables.
909
915
 
916
+ > **Accessibility fixes (1.4.x):** Radio groups keep a single selection when uncontrolled, Rate and DatePicker use one tab stop with arrow-key focus, Dialog/Sidebar/AppShell drawers share one focus trap and scroll lock, Toast announces via `role="status"`, Alert's dismiss button is labelled, and Input shows a visible focus ring in its default state. No props changed.
917
+
910
918
  ## Examples
911
919
 
912
920
  ### Complete Form Example
@@ -131,7 +131,7 @@ The library exports four kinds of things from `@dreamtree-org/twreact-ui`:
131
131
  | Hook | Purpose |
132
132
  | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
133
133
  | `useTheme` | Read/write the current theme (`light | dark`); pairs with `<ThemeProvider>`. Throws if used outside the provider. |
134
- | `ThemeProvider` | Provider that persists theme to `localStorage` (`dreamtree-theme`) and toggles `data-theme` on `<html>`. |
134
+ | `ThemeProvider` | Provider that persists theme to `localStorage` (`dreamtree-theme`) and toggles `data-theme` and the `.dark` class on `<html>`. |
135
135
  | `useApi` | Thin axios wrapper. Returns `{data, error, loading, lastRequest, fetchData, fetchApi, fetchApiWith}`. Accepts `BASE_URL`, `DEFAULT_HEADERS`, `apiMap`. |
136
136
  | `useMixins` | Bridge between component state, Redux store, and an in-memory cache. Power-user hook — prefer local React state for new code. |
137
137
 
@@ -320,7 +320,7 @@ function ThemeToggle() {
320
320
 
321
321
  `useTheme` MUST be called inside `<ThemeProvider>`; otherwise it throws.
322
322
  `<ThemeProvider>` persists to `localStorage` (`dreamtree-theme`) and
323
- toggles `data-theme` on `<html>`.
323
+ toggles `data-theme` and the `.dark` class on `<html>`.
324
324
 
325
325
  ### useApi
326
326
 
@@ -728,7 +728,8 @@
728
728
  },
729
729
  "label": {
730
730
  "type": "string",
731
- "required": false
731
+ "required": false,
732
+ "default": "\"Pick a color\""
732
733
  }
733
734
  }
734
735
  },
@@ -1195,7 +1196,8 @@
1195
1196
  },
1196
1197
  "onSubmit": {
1197
1198
  "type": "(data: any) => void",
1198
- "required": false
1199
+ "required": false,
1200
+ "default": "Promise<void>"
1199
1201
  },
1200
1202
  "defaultValues": {
1201
1203
  "type": "Record",
@@ -1800,7 +1802,7 @@
1800
1802
  "colorClass": {
1801
1803
  "type": "string",
1802
1804
  "required": false,
1803
- "default": "\"bg-pink-500\""
1805
+ "default": "\"bg-primary-600\""
1804
1806
  },
1805
1807
  "ariaLabel": {
1806
1808
  "type": "string",
@@ -2164,8 +2166,7 @@
2164
2166
  },
2165
2167
  "ariaLabel": {
2166
2168
  "type": "string",
2167
- "required": false,
2168
- "default": "\"tag\""
2169
+ "required": false
2169
2170
  },
2170
2171
  "avatarPosition": {
2171
2172
  "type": "enum",
@@ -3118,7 +3119,7 @@
3118
3119
  "TextToSpeech": {
3119
3120
  "group": "core",
3120
3121
  "import": "@dreamtree-org/twreact-ui",
3121
- "forwardRef": false,
3122
+ "forwardRef": true,
3122
3123
  "props": {
3123
3124
  "text": {
3124
3125
  "type": "string",
@@ -3140,6 +3141,16 @@
3140
3141
  "required": false,
3141
3142
  "default": "() => {}"
3142
3143
  },
3144
+ "onError": {
3145
+ "type": "(error: Error) => void",
3146
+ "required": false,
3147
+ "default": "() => {}"
3148
+ },
3149
+ "disabled": {
3150
+ "type": "boolean",
3151
+ "required": false,
3152
+ "default": "false"
3153
+ },
3143
3154
  "renderButton": {
3144
3155
  "type": "(state: TextToSpeechState) => ReactNode",
3145
3156
  "required": false
@@ -3347,12 +3358,12 @@
3347
3358
  "textClass": {
3348
3359
  "type": "string",
3349
3360
  "required": false,
3350
- "default": "\"text-black\""
3361
+ "default": "\"text-foreground\""
3351
3362
  },
3352
3363
  "bgClass": {
3353
3364
  "type": "string",
3354
3365
  "required": false,
3355
- "default": "\"bg-white\""
3366
+ "default": "\"bg-surface\""
3356
3367
  },
3357
3368
  "portal": {
3358
3369
  "type": "boolean",
@@ -174,10 +174,75 @@ var ChartFrame = /*#__PURE__*/React__default.default.forwardRef(function ChartFr
174
174
  }));
175
175
  });
176
176
 
177
- /** `true` when the user asked the OS for reduced motion. */
178
- function prefersReducedMotion() {
179
- if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
180
- return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
177
+ // Internal (not exported). SSR-safe media-query subscription.
178
+ function getMediaQueryList(query) {
179
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return null;
180
+ return window.matchMedia(query) || null;
181
+ }
182
+ /**
183
+ * Subscribes `onChange` to a MediaQueryList's change events. Uses
184
+ * `addEventListener` where available and falls back to the deprecated
185
+ * `addListener` (Safari < 14). Returns the unsubscribe function.
186
+ */
187
+ function subscribeMediaQuery(query, onChange) {
188
+ var mql = getMediaQueryList(query);
189
+ if (!mql) return function () {};
190
+ if (typeof mql.addEventListener === "function") {
191
+ mql.addEventListener("change", onChange);
192
+ return function () {
193
+ var _mql$removeEventListe;
194
+ return (_mql$removeEventListe = mql.removeEventListener) === null || _mql$removeEventListe === void 0 ? void 0 : _mql$removeEventListe.call(mql, "change", onChange);
195
+ };
196
+ }
197
+ if (typeof mql.addListener === "function") {
198
+ mql.addListener(onChange);
199
+ return function () {
200
+ var _mql$removeListener;
201
+ return (_mql$removeListener = mql.removeListener) === null || _mql$removeListener === void 0 ? void 0 : _mql$removeListener.call(mql, onChange);
202
+ };
203
+ }
204
+ return function () {};
205
+ }
206
+ /**
207
+ * `true` while `query` matches; follows changes live.
208
+ *
209
+ * On the server (and while hydrating) it returns `defaultValue`, so server and
210
+ * client markup agree; the real value is applied right after hydration. Without
211
+ * `window.matchMedia` it always returns `defaultValue`.
212
+ *
213
+ * @param {string} query - a CSS media query, e.g. "(max-width: 639px)".
214
+ * @param {{ defaultValue?: boolean }} [options]
215
+ * @returns {boolean}
216
+ */
217
+ function useMediaQuery(query) {
218
+ var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
219
+ _ref$defaultValue = _ref.defaultValue,
220
+ defaultValue = _ref$defaultValue === void 0 ? false : _ref$defaultValue;
221
+ var subscribe = React.useCallback(function (onChange) {
222
+ return subscribeMediaQuery(query, onChange);
223
+ }, [query]);
224
+ var getSnapshot = function getSnapshot() {
225
+ var mql = getMediaQueryList(query);
226
+ return mql ? Boolean(mql.matches) : defaultValue;
227
+ };
228
+ var getServerSnapshot = function getServerSnapshot() {
229
+ return defaultValue;
230
+ };
231
+ return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
232
+ }
233
+
234
+ // Internal (not exported). Shared by the charts and the overlay primitives.
235
+ var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
236
+ /**
237
+ * `true` while the user asks the OS for reduced motion; follows changes live.
238
+ * `false` on the server and while hydrating, so the first render matches.
239
+ *
240
+ * @returns {boolean}
241
+ */
242
+ function useReducedMotion() {
243
+ return useMediaQuery(REDUCED_MOTION_QUERY, {
244
+ defaultValue: false
245
+ });
181
246
  }
182
247
 
183
248
  var CHART_PALETTES = ["primary", "secondary", "success", "warning", "error", "info", "gray"];
@@ -267,26 +332,6 @@ function useChartTheme(categories, colors) {
267
332
  series: seriesColors(categories, colors, live)
268
333
  };
269
334
  }
270
- function subscribeReducedMotion(onChange) {
271
- var _query$addEventListen;
272
- if (typeof window === "undefined" || typeof window.matchMedia !== "function") return function () {};
273
- var query = window.matchMedia("(prefers-reduced-motion: reduce)");
274
- (_query$addEventListen = query.addEventListener) === null || _query$addEventListen === void 0 || _query$addEventListen.call(query, "change", onChange);
275
- return function () {
276
- var _query$removeEventLis;
277
- return (_query$removeEventLis = query.removeEventListener) === null || _query$removeEventLis === void 0 ? void 0 : _query$removeEventLis.call(query, "change", onChange);
278
- };
279
- }
280
- var serverReducedMotion = function serverReducedMotion() {
281
- return false;
282
- };
283
- /**
284
- * `true` while the user asks the OS for reduced motion; follows changes live.
285
- * `false` on the server and while hydrating, so the first render matches.
286
- */
287
- function useReducedMotion() {
288
- return React.useSyncExternalStore(subscribeReducedMotion, prefersReducedMotion, serverReducedMotion);
289
- }
290
335
  var defaultValueFormatter = function defaultValueFormatter(value) {
291
336
  return typeof value === "number" ? value.toLocaleString() : value == null ? "" : String(value);
292
337
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../../src/components/blocks/AppShell.jsx"],"names":[],"mappings":";AAmDA,kFAgEG;kBAnH6D,OAAO"}
1
+ {"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../../src/components/blocks/AppShell.jsx"],"names":[],"mappings":";AAqDA,kFA+EG;kBApIkD,OAAO"}
@@ -18,11 +18,6 @@ export function useChartTheme(categories: any, colors: any): {
18
18
  };
19
19
  series: any;
20
20
  };
21
- /**
22
- * `true` while the user asks the OS for reduced motion; follows changes live.
23
- * `false` on the server and while hydrating, so the first render matches.
24
- */
25
- export function useReducedMotion(): boolean;
26
21
  /**
27
22
  * A per-instance id for the SVG defs recharts draws (clip paths). recharts 2
28
23
  * falls back to a module-level counter, which differs between the server and the
@@ -30,7 +25,9 @@ export function useReducedMotion(): boolean;
30
25
  * is safe inside `url(#…)`.
31
26
  */
32
27
  export function useChartId(): string;
28
+ export { useReducedMotion };
33
29
  export const CHART_PALETTES: string[];
34
30
  export const DEFAULT_CHART_COLORS: string[];
35
31
  export function defaultValueFormatter(value: any): string;
32
+ import { useReducedMotion } from "../../hooks/useReducedMotion";
36
33
  //# sourceMappingURL=chartTheme.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chartTheme.d.ts","sourceRoot":"","sources":["../../../src/components/charts/chartTheme.js"],"names":[],"mappings":"AAgBA,sGAAsG;AACtG,oDAGC;AAgBD;;;;GAIG;AACH,8DAGC;AAED,gFAGC;AAwBD;;;;GAIG;AACH;;;;;EAIC;AAWD;;;GAGG;AACH,4CAEC;AAKD;;;;;GAKG;AACH,qCAEC;AA7GD,sCAAsG;AAEtG,4CAA4G;AAgGrG,0DACkF"}
1
+ {"version":3,"file":"chartTheme.d.ts","sourceRoot":"","sources":["../../../src/components/charts/chartTheme.js"],"names":[],"mappings":"AAmBA,sGAAsG;AACtG,oDAGC;AAgBD;;;;GAIG;AACH,8DAGC;AAED,gFAGC;AAwBD;;;;GAIG;AACH;;;;;EAIC;AAKD;;;;;GAKG;AACH,qCAEC;;AA5FD,sCAAsG;AAEtG,4CAA4G;AA+ErG,0DACkF;iCAvFxD,8BAA8B"}
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/core/Accordion.jsx"],"names":[],"mappings":";AAIA;;;;GAIG;AAEH,mFA+OG;kBAzP8E,OAAO"}
1
+ {"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/core/Accordion.jsx"],"names":[],"mappings":";AAKA;;;;GAIG;AAEH,mFA+QG;kBA1RqF,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"ColorPicker.d.ts","sourceRoot":"","sources":["../../../src/components/core/ColorPicker.jsx"],"names":[],"mappings":";AA0FA,qFAkKG;kBA5PkD,OAAO"}
1
+ {"version":3,"file":"ColorPicker.d.ts","sourceRoot":"","sources":["../../../src/components/core/ColorPicker.jsx"],"names":[],"mappings":";AA0FA,qFAiLG;kBA3QyD,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../src/components/core/DatePicker.jsx"],"names":[],"mappings":";AA8BA,oFA+dE;kBArfK,OAAO"}
1
+ {"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../src/components/core/DatePicker.jsx"],"names":[],"mappings":";AAgCA,oFAqhBE;kBA7iBK,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../../src/components/core/Form.jsx"],"names":[],"mappings":";AAwCA,8EA2hBG;kBAnkB6D,OAAO"}
1
+ {"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../../src/components/core/Form.jsx"],"names":[],"mappings":";AAuDA,8EAyiBG;kBAhmB6D,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/core/Input.jsx"],"names":[],"mappings":";AAIA,+EA+NG;kBAnOqE,OAAO"}
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/core/Input.jsx"],"names":[],"mappings":";AAIA,+EAmOG;kBAvOqE,OAAO"}
@@ -1,33 +1,4 @@
1
1
  export default PriceRangePicker;
2
- /**
3
- * PriceRangeSlider - UI library component (Tailwind)
4
- *
5
- * Props
6
- * - min: number (default 0)
7
- * - max: number (default 1000)
8
- * - step: number (default 1)
9
- * - minGap: number (minimum distance between thumbs, default 5)
10
- * - value: { min: number, max: number } | null (controlled)
11
- * - defaultValue: { min: number, max: number } (uncontrolled initial)
12
- * - onChange: (value) => void
13
- * - onFinalChange: (value) => void // called on mouseup/touchend or Enter in inputs
14
- * - showInputs: boolean (default true)
15
- * - showTooltips: boolean (default true)
16
- * - disabled: boolean
17
- * - presets: Array<{ id: string|number, label: string, value: {min:number,max:number} }>
18
- * - formatValue: (n) => string (formatting callback, default: n => n)
19
- * - className: string (container custom classes)
20
- * - size: 'sm' | 'md' | 'lg' (affects thumb size & spacing)
21
- * - colorClass: Tailwind class for active track/thumb, default 'bg-pink-500'
22
- * - ariaLabel: string
23
- *
24
- * Usage notes
25
- * - Controlled mode: pass `value` and handle updates via onChange.
26
- * - Uncontrolled mode: omit `value` and use `defaultValue`.
27
- *
28
- * Accessibility
29
- * - Inputs are labelled and thumbs are keyboard-focusable
30
- */
31
2
  declare const PriceRangePicker: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
32
3
  import React from "react";
33
4
  //# sourceMappingURL=PriceRangePicker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PriceRangePicker.d.ts","sourceRoot":"","sources":["../../../src/components/core/PriceRangePicker.jsx"],"names":[],"mappings":";AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,0FA8TG;kBA/V6D,OAAO"}
1
+ {"version":3,"file":"PriceRangePicker.d.ts","sourceRoot":"","sources":["../../../src/components/core/PriceRangePicker.jsx"],"names":[],"mappings":";AAqCA,0FAoQG;kBAzSqE,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/core/Radio.jsx"],"names":[],"mappings":";AAYA,+EAsIG;kBAjJgD,OAAO"}
1
+ {"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/core/Radio.jsx"],"names":[],"mappings":";AAmBA,+EAwKG;kBAnLI,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Rate.d.ts","sourceRoot":"","sources":["../../../src/components/core/Rate.jsx"],"names":[],"mappings":";AA0CA,8EAuJG;kBAhMyC,OAAO"}
1
+ {"version":3,"file":"Rate.d.ts","sourceRoot":"","sources":["../../../src/components/core/Rate.jsx"],"names":[],"mappings":";AA2CA,8EAyJG;kBAnMiD,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"RoundedTag.d.ts","sourceRoot":"","sources":["../../../src/components/core/RoundedTag.jsx"],"names":[],"mappings":";AAGA,oFAoIG;kBAvI+B,OAAO"}
1
+ {"version":3,"file":"RoundedTag.d.ts","sourceRoot":"","sources":["../../../src/components/core/RoundedTag.jsx"],"names":[],"mappings":";AAIA,oFAgKG;kBApK+B,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnMenu.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/ColumnMenu.jsx"],"names":[],"mappings":";AAKA;;GAEG;AACH;;;;;;4CAmCC"}
1
+ {"version":3,"file":"ColumnMenu.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/ColumnMenu.jsx"],"names":[],"mappings":";AAMA;;GAEG;AACH;;;;;;4CAmCC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/Pagination.jsx"],"names":[],"mappings":"AAiBA;;;;;4CAkDC;AAGD;;;;;;4CA4HC"}
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/Pagination.jsx"],"names":[],"mappings":"AAoBA;;;;;4CAkDC;AAGD;;;;;;4CAmIC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/Table.jsx"],"names":[],"mappings":";AA8CA,+EAkhDG;kBAvjDI,OAAO"}
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/Table.jsx"],"names":[],"mappings":";AA8CA,+EA8gDG;kBAnjDI,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"TableRow.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/TableRow.jsx"],"names":[],"mappings":";AAYA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4CA+RC"}
1
+ {"version":3,"file":"TableRow.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/TableRow.jsx"],"names":[],"mappings":";AAaA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4CA+RC"}
@@ -18,4 +18,6 @@ export function resolveActions(actions: any[] | Function, row: object, index: nu
18
18
  inlineActions: any[];
19
19
  menuActions: any[];
20
20
  };
21
+ export const DEFAULT_HOVER_CLASS: string;
22
+ export function getHoverClass(rowHover: any): any;
21
23
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/helpers.js"],"names":[],"mappings":"AAGO,8DAMN;AAOM;;;;;;;;;;;EAKN;AAaM,8EACqE;AAMrE,qDAGG;AAcH,8EAmBN;AAuBM,wCALI,gBAAc,OACd,MAAM,SACN,MAAM,GACJ;IAAE,aAAa,QAAQ;IAAC,WAAW,QAAO;CAAE,CAyBxD"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/helpers.js"],"names":[],"mappings":"AAGO,8DAMN;AAOM;;;;;;;;;;;EAKN;AAaM,8EACqE;AAMrE,qDAGG;AAcH,8EAmBN;AAuBM,wCALI,gBAAc,OACd,MAAM,SACN,MAAM,GACJ;IAAE,aAAa,QAAQ;IAAC,WAAW,QAAO;CAAE,CAyBxD;AAgBD,yCAAqE;AAU9D,kDAUN"}
@@ -1,8 +1,11 @@
1
1
  /**
2
- * Custom hook to detect clicks outside of specified refs
2
+ * Legacy shim — the implementation lives in `src/hooks/useClickOutside.js`.
3
+ * Kept at this path (and with the old positional signature) because
4
+ * `core/Table/index.js` re-exports it.
5
+ *
3
6
  * @param {Array} refs - Array of React refs to check
4
7
  * @param {boolean} isActive - Whether the hook should be active
5
- * @param {Function} onClickOutside - Callback when click is detected outside
8
+ * @param {Function} onClickOutside - Callback when a press lands outside
6
9
  */
7
10
  export function useClickOutside(refs: any[], isActive: boolean, onClickOutside: Function): void;
8
11
  export default useClickOutside;
@@ -1 +1 @@
1
- {"version":3,"file":"useClickOutside.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/useClickOutside.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,uDAHW,OAAO,kCAiBjB"}
1
+ {"version":3,"file":"useClickOutside.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/useClickOutside.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,uDAHW,OAAO,kCAKjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/core/Tabs.jsx"],"names":[],"mappings":"AA0GA;;;4CAuBC;AAGD;;;;;;;;4CAkHC;AAGD;;;4CAcC;AAED;;;;;mDA8BC;;AAnPD,8EAiDG;kBA7FI,OAAO"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/core/Tabs.jsx"],"names":[],"mappings":"AA0GA;;;4CAuBC;AAGD;;;;;;;;4CAmHC;AAGD;;;4CAcC;AAED;;;;;mDAyBC;;AA/OD,8EAiDG;kBA7FI,OAAO"}
@@ -1,9 +1,4 @@
1
1
  export default TextToSpeech;
2
- declare function TextToSpeech({ text, rate, pitch, onSpeak, renderButton, }: {
3
- text?: string | undefined;
4
- rate?: number | undefined;
5
- pitch?: number | undefined;
6
- onSpeak?: (() => void) | undefined;
7
- renderButton: any;
8
- }): import("react/jsx-runtime").JSX.Element;
2
+ declare const TextToSpeech: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
3
+ import React from "react";
9
4
  //# sourceMappingURL=TextToSpeech.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TextToSpeech.d.ts","sourceRoot":"","sources":["../../../src/components/core/TextToSpeech.jsx"],"names":[],"mappings":";AAEA;;;;;;4CA4CC"}
1
+ {"version":3,"file":"TextToSpeech.d.ts","sourceRoot":"","sources":["../../../src/components/core/TextToSpeech.jsx"],"names":[],"mappings":";AAgBA,sFA6IE;kBA7J0E,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/core/Tooltip.jsx"],"names":[],"mappings":";AAoCA;;;;;;;;;;;;;;;;GAgBG;AACH,iFAqVG;kBAjYI,OAAO"}
1
+ {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/core/Tooltip.jsx"],"names":[],"mappings":";AAwDA;;;;;;;;;;;;;;;;GAgBG;AACH,iFAwZG;kBAxdI,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Alert.jsx"],"names":[],"mappings":";AAIA,+EAwFG;kBA5Fe,OAAO"}
1
+ {"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Alert.jsx"],"names":[],"mappings":";AASA,+EA0FG;kBAnGe,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Dialog.jsx"],"names":[],"mappings":";AAoCA,gFA0JG;kBA9LsC,OAAO"}
1
+ {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Dialog.jsx"],"names":[],"mappings":";AAUA,gFA6GG;kBAvH6C,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Toast.jsx"],"names":[],"mappings":";AAmDA,8EA4NG;AA6CH,2FAOC;AA6CD;;;;4CAkBC;;;;AAMD;;;;;;;;;;;;EAIC;kBA5Y+G,OAAO"}
1
+ {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Toast.jsx"],"names":[],"mappings":";AA4DA,8EAgOG;AA+CH,2FAOC;AA6CD;;;;4CAkBC;;;;AAMD;;;;;;;;;;;;EAIC;kBA3Z+G,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/Sidebar.jsx"],"names":[],"mappings":";AAiGA;;;;;;;;;;;;;;;;;GAiBG;AACH,iFA2kBG;kBAtrBI,OAAO"}
1
+ {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/Sidebar.jsx"],"names":[],"mappings":";AAkFA;;;;;;;;;;;;;;;;;GAiBG;AACH,iFAohBG;kBAhnBI,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Avatar.jsx"],"names":[],"mappings":";AAIA,gFA6GG;kBAjHe,OAAO"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Avatar.jsx"],"names":[],"mappings":";AAIA,gFAoHG;kBAxHe,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"Carousel.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Carousel.jsx"],"names":[],"mappings":"AAIA,iFAsFE;;kBA1FgB,OAAO"}
1
+ {"version":3,"file":"Carousel.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Carousel.jsx"],"names":[],"mappings":"AAUA,iFAoGE;;kBA9GgB,OAAO"}
@@ -0,0 +1,6 @@
1
+ export default Portal;
2
+ declare function Portal({ container, children }: {
3
+ container: any;
4
+ children: any;
5
+ }): import("react").ReactPortal | null;
6
+ //# sourceMappingURL=Portal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Portal.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Portal.jsx"],"names":[],"mappings":";AAcA;;;uCAOC"}
@@ -1,9 +1,11 @@
1
1
  'use client';
2
2
  import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2, createForOfIteratorHelper as _createForOfIteratorHelper } from '../../_virtual/_rollupPluginBabelHelpers.js';
3
3
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
4
- import React, { useState, useRef, useCallback, useEffect } from 'react';
4
+ import React, { useState, useRef, useCallback } from 'react';
5
5
  import { X, Menu } from 'lucide-react';
6
6
  import { cn } from '../../utils/cn.js';
7
+ import { useFocusTrap } from '../../hooks/useFocusTrap.js';
8
+ import { useScrollLock } from '../../hooks/useScrollLock.js';
7
9
 
8
10
  var _excluded = ["brand", "nav", "sidebarFooter", "topbar", "pageTitle", "linkAs", "children", "className"];
9
11
  // Extracted from procurementpro/components/app-shell.tsx (12 of 13 products hand-roll a shell).
@@ -105,23 +107,22 @@ var AppShell = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
105
107
  open = _useState2[0],
106
108
  setOpen = _useState2[1];
107
109
  var menuButton = useRef(null);
110
+ var drawer = useRef(null);
108
111
  var close = useCallback(function () {
109
112
  return setOpen(false);
110
113
  }, []);
111
- useEffect(function () {
112
- if (!open) return undefined;
113
- var onKey = function onKey(e) {
114
- if (e.key === 'Escape') {
115
- var _menuButton$current;
116
- setOpen(false);
117
- (_menuButton$current = menuButton.current) === null || _menuButton$current === void 0 || _menuButton$current.focus();
118
- }
119
- };
120
- document.addEventListener('keydown', onKey);
121
- return function () {
122
- return document.removeEventListener('keydown', onKey);
123
- };
124
- }, [open]);
114
+ // Mobile drawer is a modal dialog: focus moves in, Tab is trapped, Escape
115
+ // closes, focus returns to the menu button, and the page behind is locked.
116
+ useScrollLock(open);
117
+ useFocusTrap(drawer, {
118
+ active: open,
119
+ onEscape: function onEscape() {
120
+ var _menuButton$current;
121
+ close();
122
+ // Some browsers (Safari) don't focus a clicked button, so the opener may be <body>.
123
+ (_menuButton$current = menuButton.current) === null || _menuButton$current === void 0 || _menuButton$current.focus();
124
+ }
125
+ });
125
126
  var sidebar = jsxs(Fragment, {
126
127
  children: [jsxs("div", {
127
128
  className: "flex items-center justify-between px-5 pb-4 pt-5 text-white",
@@ -134,7 +135,8 @@ var AppShell = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
134
135
  onClick: close,
135
136
  "aria-label": "Close navigation",
136
137
  children: jsx(X, {
137
- className: "h-5 w-5"
138
+ className: "h-5 w-5",
139
+ "aria-hidden": "true"
138
140
  })
139
141
  })]
140
142
  }), jsx(NavList, {
@@ -165,8 +167,12 @@ var AppShell = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
165
167
  onClick: close,
166
168
  "aria-hidden": "true"
167
169
  }), jsx("aside", {
168
- className: "absolute inset-y-0 left-0 flex w-72 max-w-[85%] flex-col bg-shell",
169
- "aria-label": "Sidebar",
170
+ ref: drawer,
171
+ role: "dialog",
172
+ "aria-modal": "true",
173
+ "aria-label": "Navigation",
174
+ tabIndex: -1,
175
+ className: "absolute inset-y-0 left-0 flex w-72 max-w-[85%] flex-col bg-shell focus:outline-none",
170
176
  children: sidebar
171
177
  })]
172
178
  }), jsxs("div", {
@@ -4,7 +4,8 @@ import { jsx, jsxs } from 'react/jsx-runtime';
4
4
  import React from 'react';
5
5
  import { ResponsiveContainer, AreaChart, BarChart, LineChart, CartesianGrid, XAxis, YAxis, Tooltip, Bar, Area, Line } from 'recharts';
6
6
  import { ChartFrame, ChartTooltipContent } from './ChartFrame.js';
7
- import { useChartTheme, useReducedMotion, useChartId, defaultValueFormatter } from './chartTheme.js';
7
+ import { useChartTheme, useChartId, defaultValueFormatter } from './chartTheme.js';
8
+ import { useReducedMotion } from '../../hooks/useReducedMotion.js';
8
9
 
9
10
  var _excluded = ["kind", "data", "index", "categories", "colors", "valueFormatter", "xAxisFormatter", "height", "showLegend", "showTooltip", "showXAxis", "showYAxis", "showGrid", "yAxisWidth", "curveType", "stacked", "horizontal", "showDots", "connectNulls", "animate", "title", "description", "emptyState", "accessibleTable", "className"];
10
11
  var ROOTS = {