@zentauri-ui/zentauri-components 1.7.6 → 1.7.7

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 (49) hide show
  1. package/README.md +4 -2
  2. package/cli/registry.json +1 -0
  3. package/dist/chunk-GRJFGIZC.mjs +417 -0
  4. package/dist/chunk-GRJFGIZC.mjs.map +1 -0
  5. package/dist/chunk-QHEHBC6M.js +421 -0
  6. package/dist/chunk-QHEHBC6M.js.map +1 -0
  7. package/dist/design-system/index.d.ts +1 -0
  8. package/dist/design-system/index.d.ts.map +1 -1
  9. package/dist/design-system/tree-view.d.ts +66 -0
  10. package/dist/design-system/tree-view.d.ts.map +1 -0
  11. package/dist/ui/tree-view/animated/animations.d.ts +6 -0
  12. package/dist/ui/tree-view/animated/animations.d.ts.map +1 -0
  13. package/dist/ui/tree-view/animated/index.d.ts +5 -0
  14. package/dist/ui/tree-view/animated/index.d.ts.map +1 -0
  15. package/dist/ui/tree-view/animated/tree-view-animated.d.ts +6 -0
  16. package/dist/ui/tree-view/animated/tree-view-animated.d.ts.map +1 -0
  17. package/dist/ui/tree-view/animated/types.d.ts +6 -0
  18. package/dist/ui/tree-view/animated/types.d.ts.map +1 -0
  19. package/dist/ui/tree-view/animated.js +53 -0
  20. package/dist/ui/tree-view/animated.js.map +1 -0
  21. package/dist/ui/tree-view/animated.mjs +50 -0
  22. package/dist/ui/tree-view/animated.mjs.map +1 -0
  23. package/dist/ui/tree-view/index.d.ts +5 -0
  24. package/dist/ui/tree-view/index.d.ts.map +1 -0
  25. package/dist/ui/tree-view/tree-view-base.d.ts +15 -0
  26. package/dist/ui/tree-view/tree-view-base.d.ts.map +1 -0
  27. package/dist/ui/tree-view/tree-view.d.ts +6 -0
  28. package/dist/ui/tree-view/tree-view.d.ts.map +1 -0
  29. package/dist/ui/tree-view/types.d.ts +61 -0
  30. package/dist/ui/tree-view/types.d.ts.map +1 -0
  31. package/dist/ui/tree-view/variants.d.ts +9 -0
  32. package/dist/ui/tree-view/variants.d.ts.map +1 -0
  33. package/dist/ui/tree-view.js +27 -0
  34. package/dist/ui/tree-view.js.map +1 -0
  35. package/dist/ui/tree-view.mjs +14 -0
  36. package/dist/ui/tree-view.mjs.map +1 -0
  37. package/package.json +1 -1
  38. package/src/design-system/index.ts +1 -0
  39. package/src/design-system/tree-view.ts +113 -0
  40. package/src/ui/tree-view/animated/animations.ts +13 -0
  41. package/src/ui/tree-view/animated/index.ts +6 -0
  42. package/src/ui/tree-view/animated/tree-view-animated.tsx +52 -0
  43. package/src/ui/tree-view/animated/types.ts +6 -0
  44. package/src/ui/tree-view/index.ts +13 -0
  45. package/src/ui/tree-view/tree-view-base.tsx +496 -0
  46. package/src/ui/tree-view/tree-view.test.tsx +136 -0
  47. package/src/ui/tree-view/tree-view.tsx +9 -0
  48. package/src/ui/tree-view/types.ts +68 -0
  49. package/src/ui/tree-view/variants.ts +32 -0
package/README.md CHANGED
@@ -36,6 +36,7 @@ Published artifacts live under `dist/`. Imports use **per-entry subpaths**: `@ze
36
36
  | `src/ui/buttons/button.test.tsx` | 41 |
37
37
  | `src/ui/inputs/input.test.tsx` | 40 |
38
38
  | `src/ui/otp-input/otp-input.test.tsx` | 10 |
39
+ | `src/ui/tree-view/tree-view.test.tsx` | 10 |
39
40
  | `src/ui/card/card.test.tsx` | 7 |
40
41
  | `src/ui/checkbox/checkbox.test.tsx` | 6 |
41
42
  | `src/ui/popover/popover.test.tsx` | 4 |
@@ -111,7 +112,7 @@ Only a subset of UI areas publish a `/animated` entry (see **Components**). Some
111
112
 
112
113
  Published motion entries (same `<name>` as the base UI folder):
113
114
 
114
- `accordion`, `alert`, `avatar`, `badge`, `buttons`, `card`, `checkbox`, `divider`, `drawer`, `empty-state`, `inputs`, `modal`, `popover`, `progress`, `radio-group`, `skeleton`, `spinner`, `table`, `tabs`, `toast`, `toggle`, `tooltip`
115
+ `accordion`, `alert`, `avatar`, `badge`, `buttons`, `card`, `checkbox`, `divider`, `drawer`, `empty-state`, `inputs`, `modal`, `popover`, `progress`, `radio-group`, `skeleton`, `spinner`, `table`, `tabs`, `toast`, `toggle`, `tooltip`, `tree-view`
115
116
 
116
117
  **Spinner:** only the motion entry is built—import from `@zentauri-ui/zentauri-components/ui/spinner/animated` (there is no separate `ui/spinner` static bundle).
117
118
 
@@ -163,6 +164,7 @@ Import static primitives from `@zentauri-ui/zentauri-components/ui/<subpath>` wh
163
164
  | Toast | `toast` | `toast/animated` |
164
165
  | Toggle | `toggle` | `toggle/animated` |
165
166
  | Tooltip | `tooltip` | `tooltip/animated` |
167
+ | Tree view | `tree-view` | `tree-view/animated` |
166
168
  | Typography | `typography` | — |
167
169
 
168
170
  ## Typography
@@ -665,7 +667,7 @@ From this package directory in the monorepo:
665
667
 
666
668
  - `pnpm build` (or `npm run build`) — production bundle via `tsup` (Rollup treeshake + `scripts/prepend-use-client.mjs` via `onSuccess` so each UI entry under `dist/ui/`, the chart entry under `dist/charts/`, and `dist/ui/<name>/animated.*` starts with `"use client"` where needed)
667
669
  - `pnpm dev` — `tsup` watch mode (same `onSuccess` hook after each rebuild)
668
- - `pnpm test` / `pnpm test:watch` — **Vitest** and **Testing Library** unit tests // covered 399 test cases in total
670
+ - `pnpm test` / `pnpm test:watch` — **Vitest** and **Testing Library** unit tests // covered 409 test cases in total
669
671
  - **`pnpm run generate:registry`** — runs `scripts/generate-registry.mjs`, which reads **`uiComponentNames`**, **`chartEntryNames`**, and **`hooksEntryNames`** from `tsup.config.ts`, merges in **`spinner`**, applies fixed **`nameAliases`**, and writes **`cli/registry.json`** (`components` + `hooks`). Run this after adding or renaming UI/chart areas or hook entries so the CLI stays in sync (the script prints counts).
670
672
 
671
673
  ## Github Release log
package/cli/registry.json CHANGED
@@ -43,6 +43,7 @@
43
43
  "toast",
44
44
  "toggle",
45
45
  "tooltip",
46
+ "tree-view",
46
47
  "typography"
47
48
  ],
48
49
  "hooks": [
@@ -0,0 +1,417 @@
1
+ import { cn } from './chunk-4D54YOL6.mjs';
2
+ import { cva } from 'class-variance-authority';
3
+ import { createContext, useState, useMemo, useCallback, useRef, useContext } from 'react';
4
+ import { FaChevronRight } from 'react-icons/fa6';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ // src/design-system/tree-view.ts
8
+ var zuiTreeViewBase = "w-full text-[color:var(--zui-tree-view-fg,oklch(20.8%_0.042_265.755))] dark:text-[color:var(--zui-tree-view-fg-dark,oklch(92.9%_0.013_255.508))]";
9
+ var zuiTreeViewAppearances = {
10
+ default: "rounded-xl border border-[color:var(--zui-tree-view-default-border,#0000001a)] dark:border-[color:var(--zui-tree-view-default-border-dark,#ffffff1a)] p-2",
11
+ outline: "rounded-xl border border-[color:var(--zui-tree-view-outline-border,#00000026)] dark:border-[color:var(--zui-tree-view-outline-border-dark,#ffffff26)] p-2",
12
+ ghost: "p-1",
13
+ card: "rounded-xl border border-[color:var(--zui-tree-view-card-border,#0000001a)] dark:border-[color:var(--zui-tree-view-card-border-dark,#ffffff1a)] bg-[var(--zui-tree-view-card-bg,#0000000d)] dark:bg-[var(--zui-tree-view-card-bg-dark,#00000099)] p-3",
14
+ separated: "rounded-xl border border-[color:var(--zui-tree-view-separated-border,#0000001a)] dark:border-[color:var(--zui-tree-view-separated-border-dark,#ffffff1a)] bg-[var(--zui-tree-view-separated-bg,oklch(98.4%_0.003_247.858_/_0.4))] dark:bg-[var(--zui-tree-view-separated-bg-dark,oklch(12.9%_0.042_264.695_/_0.4))] p-3",
15
+ sky: "rounded-xl border border-[color:var(--zui-tree-view-sky-border,oklch(44.3%_0.11_240.79))] dark:border-[color:var(--zui-tree-view-sky-border-dark,oklch(58.8%_0.158_241.966))] p-2",
16
+ rose: "rounded-xl border border-[color:var(--zui-tree-view-rose-border,oklch(45.5%_0.188_13.697))] dark:border-[color:var(--zui-tree-view-rose-border-dark,oklch(58.6%_0.253_17.585))] p-2",
17
+ purple: "rounded-xl border border-[color:var(--zui-tree-view-purple-border,oklch(43.8%_0.218_303.724))] dark:border-[color:var(--zui-tree-view-purple-border-dark,oklch(55.8%_0.288_302.321))] p-2",
18
+ pink: "rounded-xl border border-[color:var(--zui-tree-view-pink-border,oklch(45.9%_0.187_3.815))] dark:border-[color:var(--zui-tree-view-pink-border-dark,oklch(59.2%_0.249_0.584))] p-2",
19
+ orange: "rounded-xl border border-[color:var(--zui-tree-view-orange-border,oklch(47%_0.157_37.304))] dark:border-[color:var(--zui-tree-view-orange-border-dark,oklch(64.6%_0.222_41.116))] p-2",
20
+ yellow: "rounded-xl border border-[color:var(--zui-tree-view-yellow-border,oklch(47.6%_0.114_61.907))] dark:border-[color:var(--zui-tree-view-yellow-border-dark,oklch(68.1%_0.162_75.834))] p-2",
21
+ teal: "rounded-xl border border-[color:var(--zui-tree-view-teal-border,oklch(43.7%_0.078_188.216))] dark:border-[color:var(--zui-tree-view-teal-border-dark,oklch(60%_0.118_184.704))] p-2",
22
+ indigo: "rounded-xl border border-[color:var(--zui-tree-view-indigo-border,oklch(39.8%_0.195_277.366))] dark:border-[color:var(--zui-tree-view-indigo-border-dark,oklch(51.1%_0.262_276.966))] p-2",
23
+ emerald: "rounded-xl border border-[color:var(--zui-tree-view-emerald-border,oklch(43.2%_0.095_166.913))] dark:border-[color:var(--zui-tree-view-emerald-border-dark,oklch(59.6%_0.145_163.225))] p-2",
24
+ "gradient-blue": "rounded-xl border border-[color:var(--zui-tree-view-gradient-blue-border,oklch(42.4%_0.199_265.638))] dark:border-[color:var(--zui-tree-view-gradient-blue-border-dark,oklch(54.6%_0.245_262.881))] p-2",
25
+ "gradient-green": "rounded-xl border border-[color:var(--zui-tree-view-gradient-green-border,oklch(44.8%_0.119_151.328))] dark:border-[color:var(--zui-tree-view-gradient-green-border-dark,oklch(62.7%_0.194_149.214))] p-2",
26
+ "gradient-red": "rounded-xl border border-[color:var(--zui-tree-view-gradient-red-border,oklch(44.4%_0.177_26.899))] dark:border-[color:var(--zui-tree-view-gradient-red-border-dark,oklch(57.7%_0.245_27.325))] p-2",
27
+ "gradient-yellow": "rounded-xl border border-[color:var(--zui-tree-view-gradient-yellow-border,oklch(47.6%_0.114_61.907))] dark:border-[color:var(--zui-tree-view-gradient-yellow-border-dark,oklch(68.1%_0.162_75.834))] p-2",
28
+ "gradient-purple": "rounded-xl border border-[color:var(--zui-tree-view-gradient-purple-border,oklch(43.8%_0.218_303.724))] dark:border-[color:var(--zui-tree-view-gradient-purple-border-dark,oklch(55.8%_0.288_302.321))] p-2",
29
+ "gradient-teal": "rounded-xl border border-[color:var(--zui-tree-view-gradient-teal-border,oklch(43.7%_0.078_188.216))] dark:border-[color:var(--zui-tree-view-gradient-teal-border-dark,oklch(60%_0.118_184.704))] p-2",
30
+ "gradient-indigo": "rounded-xl border border-[color:var(--zui-tree-view-gradient-indigo-border,oklch(39.8%_0.195_277.366))] dark:border-[color:var(--zui-tree-view-gradient-indigo-border-dark,oklch(51.1%_0.262_276.966))] p-2",
31
+ "gradient-pink": "rounded-xl border border-[color:var(--zui-tree-view-gradient-pink-border,oklch(45.9%_0.187_3.815))] dark:border-[color:var(--zui-tree-view-gradient-pink-border-dark,oklch(59.2%_0.249_0.584))] p-2",
32
+ "gradient-orange": "rounded-xl border border-[color:var(--zui-tree-view-gradient-orange-border,oklch(47%_0.157_37.304))] dark:border-[color:var(--zui-tree-view-gradient-orange-border-dark,oklch(64.6%_0.222_41.116))] p-2"
33
+ };
34
+ var zuiTreeViewSizes = {
35
+ sm: "text-xs",
36
+ md: "text-sm",
37
+ lg: "text-base"
38
+ };
39
+ var zuiTreeViewItemBase = "relative flex w-full items-center gap-2 rounded-lg pr-2 text-left font-medium outline-none transition select-none cursor-pointer hover:bg-[var(--zui-tree-view-item-hover,#0000000d)] dark:hover:bg-[var(--zui-tree-view-item-hover-dark,#ffffff0d)] focus-visible:ring-2 focus-visible:ring-[var(--zui-tree-view-ring-focus,#0000004d)] dark:focus-visible:ring-[var(--zui-tree-view-ring-focus-dark,#ffffff4d)] data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50";
40
+ var zuiTreeViewItemSizes = {
41
+ sm: "py-1 text-xs",
42
+ md: "py-1.5 text-sm",
43
+ lg: "py-2 text-base"
44
+ };
45
+ var zuiTreeViewItemAppearances = {
46
+ default: "data-[selected=true]:bg-[var(--zui-tree-view-selected,#0000000f)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff14)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]",
47
+ outline: "data-[selected=true]:bg-[var(--zui-tree-view-selected,#0000000f)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff14)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]",
48
+ ghost: "data-[selected=true]:bg-[var(--zui-tree-view-selected,#0000000f)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff14)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]",
49
+ card: "data-[selected=true]:bg-[var(--zui-tree-view-selected,#00000014)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff1f)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]",
50
+ separated: "data-[selected=true]:bg-[var(--zui-tree-view-selected,#00000014)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff1f)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]",
51
+ sky: "data-[selected=true]:bg-[var(--zui-tree-view-sky-selected,oklch(95.1%_0.026_236.824))] dark:data-[selected=true]:bg-[var(--zui-tree-view-sky-selected-dark,oklch(58.8%_0.158_241.966_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-sky-selected-fg,oklch(44.3%_0.11_240.79))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-sky-selected-fg-dark,oklch(82.8%_0.111_230.318))]",
52
+ rose: "data-[selected=true]:bg-[var(--zui-tree-view-rose-selected,oklch(94.1%_0.03_12.58))] dark:data-[selected=true]:bg-[var(--zui-tree-view-rose-selected-dark,oklch(58.6%_0.253_17.585_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-rose-selected-fg,oklch(45.5%_0.188_13.697))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-rose-selected-fg-dark,oklch(81%_0.117_11.638))]",
53
+ purple: "data-[selected=true]:bg-[var(--zui-tree-view-purple-selected,oklch(94.6%_0.033_307.174))] dark:data-[selected=true]:bg-[var(--zui-tree-view-purple-selected-dark,oklch(55.8%_0.288_302.321_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-purple-selected-fg,oklch(43.8%_0.218_303.724))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-purple-selected-fg-dark,oklch(82.7%_0.119_306.383))]",
54
+ pink: "data-[selected=true]:bg-[var(--zui-tree-view-pink-selected,oklch(94.8%_0.028_342.258))] dark:data-[selected=true]:bg-[var(--zui-tree-view-pink-selected-dark,oklch(59.2%_0.249_0.584_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-pink-selected-fg,oklch(45.9%_0.187_3.815))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-pink-selected-fg-dark,oklch(82.3%_0.12_346.018))]",
55
+ orange: "data-[selected=true]:bg-[var(--zui-tree-view-orange-selected,oklch(95.4%_0.038_75.164))] dark:data-[selected=true]:bg-[var(--zui-tree-view-orange-selected-dark,oklch(64.6%_0.222_41.116_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-orange-selected-fg,oklch(47%_0.157_37.304))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-orange-selected-fg-dark,oklch(83.7%_0.128_66.29))]",
56
+ yellow: "data-[selected=true]:bg-[var(--zui-tree-view-yellow-selected,oklch(97.3%_0.071_103.193))] dark:data-[selected=true]:bg-[var(--zui-tree-view-yellow-selected-dark,oklch(68.1%_0.162_75.834_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-yellow-selected-fg,oklch(47.6%_0.114_61.907))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-yellow-selected-fg-dark,oklch(90.5%_0.182_98.111))]",
57
+ teal: "data-[selected=true]:bg-[var(--zui-tree-view-teal-selected,oklch(95.3%_0.051_180.801))] dark:data-[selected=true]:bg-[var(--zui-tree-view-teal-selected-dark,oklch(60%_0.118_184.704_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-teal-selected-fg,oklch(43.7%_0.078_188.216))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-teal-selected-fg-dark,oklch(85.5%_0.138_181.071))]",
58
+ indigo: "data-[selected=true]:bg-[var(--zui-tree-view-indigo-selected,oklch(93%_0.034_272.788))] dark:data-[selected=true]:bg-[var(--zui-tree-view-indigo-selected-dark,oklch(51.1%_0.262_276.966_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-indigo-selected-fg,oklch(39.8%_0.195_277.366))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-indigo-selected-fg-dark,oklch(78.5%_0.115_274.713))]",
59
+ emerald: "data-[selected=true]:bg-[var(--zui-tree-view-emerald-selected,oklch(95%_0.052_163.051))] dark:data-[selected=true]:bg-[var(--zui-tree-view-emerald-selected-dark,oklch(59.6%_0.145_163.225_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-emerald-selected-fg,oklch(43.2%_0.095_166.913))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-emerald-selected-fg-dark,oklch(84.5%_0.143_164.978))]",
60
+ "gradient-blue": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-blue-from,oklch(80.9%_0.105_251.813))] data-[selected=true]:to-[var(--zui-tree-view-gradient-blue-to,oklch(82.7%_0.119_306.383))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-blue-from-dark,oklch(54.6%_0.245_262.881))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-blue-to-dark,oklch(55.8%_0.288_302.321))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]",
61
+ "gradient-green": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-green-from,oklch(87.1%_0.15_154.449))] data-[selected=true]:to-[var(--zui-tree-view-gradient-green-to,oklch(89.7%_0.196_126.665))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-green-from-dark,oklch(62.7%_0.194_149.214))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-green-to-dark,oklch(64.8%_0.2_131.684))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]",
62
+ "gradient-red": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-red-from,oklch(80.8%_0.114_19.571))] data-[selected=true]:to-[var(--zui-tree-view-gradient-red-to,oklch(82.3%_0.12_346.018))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-red-from-dark,oklch(57.7%_0.245_27.325))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-red-to-dark,oklch(59.2%_0.249_0.584))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]",
63
+ "gradient-yellow": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-yellow-from,oklch(90.5%_0.182_98.111))] data-[selected=true]:to-[var(--zui-tree-view-gradient-yellow-to,oklch(83.7%_0.128_66.29))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-yellow-from-dark,oklch(68.1%_0.162_75.834))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-yellow-to-dark,oklch(64.6%_0.222_41.116))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]",
64
+ "gradient-purple": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-purple-from,oklch(82.7%_0.119_306.383))] data-[selected=true]:to-[var(--zui-tree-view-gradient-purple-to,oklch(82.3%_0.12_346.018))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-purple-from-dark,oklch(55.8%_0.288_302.321))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-purple-to-dark,oklch(59.2%_0.249_0.584))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]",
65
+ "gradient-teal": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-teal-from,oklch(85.5%_0.138_181.071))] data-[selected=true]:to-[var(--zui-tree-view-gradient-teal-to,oklch(86.5%_0.127_207.078))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-teal-from-dark,oklch(60%_0.118_184.704))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-teal-to-dark,oklch(60.9%_0.126_221.723))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]",
66
+ "gradient-indigo": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-indigo-from,oklch(78.5%_0.115_274.713))] data-[selected=true]:to-[var(--zui-tree-view-gradient-indigo-to,oklch(82.7%_0.119_306.383))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-indigo-from-dark,oklch(51.1%_0.262_276.966))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-indigo-to-dark,oklch(55.8%_0.288_302.321))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]",
67
+ "gradient-pink": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-pink-from,oklch(82.3%_0.12_346.018))] data-[selected=true]:to-[var(--zui-tree-view-gradient-pink-to,oklch(81%_0.117_11.638))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-pink-from-dark,oklch(59.2%_0.249_0.584))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-pink-to-dark,oklch(58.6%_0.253_17.585))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]",
68
+ "gradient-orange": "data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-orange-from,oklch(83.7%_0.128_66.29))] data-[selected=true]:to-[var(--zui-tree-view-gradient-orange-to,oklch(80.8%_0.114_19.571))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-orange-from-dark,oklch(64.6%_0.222_41.116))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-orange-to-dark,oklch(57.7%_0.245_27.325))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]"
69
+ };
70
+ var zuiTreeViewChevron = "inline-flex h-5 w-5 shrink-0 items-center justify-center rounded text-[color:var(--zui-tree-view-chevron,oklch(55.5%_0.041_257.417))] dark:text-[color:var(--zui-tree-view-chevron-dark,oklch(70.4%_0.04_256.788))] transition-transform duration-200 data-[expanded=true]:rotate-90";
71
+ var zuiTreeViewIcon = "inline-flex shrink-0 items-center justify-center text-[color:var(--zui-tree-view-icon,oklch(55.5%_0.041_257.417))] dark:text-[color:var(--zui-tree-view-icon-dark,oklch(70.4%_0.04_256.788))]";
72
+ var zuiTreeViewGuide = "border-l border-[color:var(--zui-tree-view-guide,#0000001a)] dark:border-[color:var(--zui-tree-view-guide-dark,#ffffff1a)]";
73
+
74
+ // src/ui/tree-view/variants.ts
75
+ var treeViewVariants = cva(zuiTreeViewBase, {
76
+ variants: {
77
+ appearance: zuiTreeViewAppearances,
78
+ size: zuiTreeViewSizes
79
+ },
80
+ defaultVariants: {
81
+ appearance: "default",
82
+ size: "md"
83
+ }
84
+ });
85
+ var treeViewItemVariants = cva(zuiTreeViewItemBase, {
86
+ variants: {
87
+ appearance: zuiTreeViewItemAppearances,
88
+ size: zuiTreeViewItemSizes
89
+ },
90
+ defaultVariants: {
91
+ appearance: "default",
92
+ size: "md"
93
+ }
94
+ });
95
+ var TreeViewContext = createContext(null);
96
+ function useTreeViewContext(component) {
97
+ const ctx = useContext(TreeViewContext);
98
+ if (!ctx) {
99
+ throw new Error(`${component} must be used within <TreeView>`);
100
+ }
101
+ return ctx;
102
+ }
103
+ function flattenVisible(nodes, isExpanded, level = 1, parentId = null, acc = []) {
104
+ for (const node of nodes) {
105
+ acc.push({ node, level, parentId });
106
+ if (node.children?.length && isExpanded(node.id)) {
107
+ flattenVisible(node.children, isExpanded, level + 1, node.id, acc);
108
+ }
109
+ }
110
+ return acc;
111
+ }
112
+ function StaticTreeGroup({ open, children }) {
113
+ if (!open) {
114
+ return null;
115
+ }
116
+ return /* @__PURE__ */ jsx("ul", { role: "group", "data-slot": "tree-view-group", className: "m-0 list-none p-0", children });
117
+ }
118
+ function TreeItemNode({
119
+ node,
120
+ level,
121
+ chevronIcon
122
+ }) {
123
+ const {
124
+ isExpanded,
125
+ selectedId,
126
+ activeId,
127
+ GroupComponent,
128
+ registerItem,
129
+ appearance,
130
+ size,
131
+ toggleExpanded,
132
+ selectNode,
133
+ onItemKeyDown,
134
+ renderNode,
135
+ showGuides
136
+ } = useTreeViewContext("TreeItem");
137
+ const hasChildren = Boolean(node.children?.length);
138
+ const expanded = hasChildren && isExpanded(node.id);
139
+ const selected = selectedId === node.id;
140
+ const active = activeId === node.id;
141
+ const disabled = Boolean(node.disabled);
142
+ const Group = GroupComponent;
143
+ return /* @__PURE__ */ jsxs("li", { role: "none", "data-slot": "tree-view-item", children: [
144
+ /* @__PURE__ */ jsxs(
145
+ "div",
146
+ {
147
+ role: "treeitem",
148
+ ref: (el) => registerItem(node.id, el),
149
+ "aria-expanded": hasChildren ? expanded : void 0,
150
+ "aria-selected": selected,
151
+ "aria-level": level,
152
+ "aria-disabled": disabled || void 0,
153
+ "data-slot": "tree-view-item-row",
154
+ "data-node-id": node.id,
155
+ "data-selected": selected,
156
+ "data-active": active,
157
+ "data-disabled": disabled,
158
+ tabIndex: active ? 0 : -1,
159
+ style: { paddingLeft: `${(level - 1) * 1.25 + 0.5}rem` },
160
+ className: treeViewItemVariants({
161
+ appearance,
162
+ size
163
+ }),
164
+ onClick: () => {
165
+ if (disabled) {
166
+ return;
167
+ }
168
+ if (hasChildren) {
169
+ toggleExpanded(node.id);
170
+ }
171
+ selectNode(node);
172
+ },
173
+ onKeyDown: onItemKeyDown,
174
+ children: [
175
+ hasChildren ? /* @__PURE__ */ jsx(
176
+ "span",
177
+ {
178
+ "data-slot": "tree-view-chevron",
179
+ "data-expanded": expanded,
180
+ className: zuiTreeViewChevron,
181
+ children: chevronIcon || /* @__PURE__ */ jsx(FaChevronRight, {})
182
+ }
183
+ ) : (
184
+ // Leaf nodes reserve chevron space to keep labels vertically aligned
185
+ // with sibling branches that do have disclosure icons.
186
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "inline-flex h-5 w-5 shrink-0" })
187
+ ),
188
+ node.icon ? /* @__PURE__ */ jsx("span", { "data-slot": "tree-view-icon", className: zuiTreeViewIcon, children: node.icon }) : null,
189
+ /* @__PURE__ */ jsx("span", { "data-slot": "tree-view-label", className: "truncate", children: renderNode ? renderNode({
190
+ node,
191
+ depth: level,
192
+ isExpanded: expanded,
193
+ isSelected: selected
194
+ }) : node.label })
195
+ ]
196
+ }
197
+ ),
198
+ hasChildren ? /* @__PURE__ */ jsx(Group, { open: expanded, level, children: /* @__PURE__ */ jsx(
199
+ "ol",
200
+ {
201
+ className: cn(showGuides && zuiTreeViewGuide, showGuides && "ml-5"),
202
+ children: node.children?.map((child) => (
203
+ // Recursion preserves each child's depth so ARIA levels,
204
+ // indentation, and guide spacing all stay in sync.
205
+ /* @__PURE__ */ jsx(TreeItemNode, { node: child, level: level + 1 }, child.id)
206
+ ))
207
+ }
208
+ ) }) : null
209
+ ] });
210
+ }
211
+ function TreeViewBase({
212
+ data = [],
213
+ defaultExpanded,
214
+ expanded,
215
+ onExpandedChange,
216
+ defaultSelected,
217
+ selected,
218
+ onSelect,
219
+ renderNode,
220
+ showGuides = false,
221
+ appearance = "default",
222
+ size = "md",
223
+ className,
224
+ GroupComponent = StaticTreeGroup,
225
+ ...rest
226
+ }) {
227
+ const isExpandedControlled = expanded !== void 0;
228
+ const isSelectedControlled = selected !== void 0;
229
+ const [expandedUncontrolled, setExpandedUncontrolled] = useState(
230
+ defaultExpanded ?? []
231
+ );
232
+ const [selectedUncontrolled, setSelectedUncontrolled] = useState(defaultSelected);
233
+ const expandedIds = isExpandedControlled ? expanded ?? [] : expandedUncontrolled;
234
+ const selectedId = isSelectedControlled ? selected : selectedUncontrolled;
235
+ const expandedSet = useMemo(() => new Set(expandedIds), [expandedIds]);
236
+ const isExpanded = useCallback(
237
+ (id) => expandedSet.has(id),
238
+ [expandedSet]
239
+ );
240
+ const commitExpanded = useCallback(
241
+ (next) => {
242
+ if (!isExpandedControlled) {
243
+ setExpandedUncontrolled(next);
244
+ }
245
+ onExpandedChange?.(next);
246
+ },
247
+ [isExpandedControlled, onExpandedChange]
248
+ );
249
+ const setExpanded = useCallback(
250
+ (id, open) => {
251
+ const has = expandedSet.has(id);
252
+ if (open === has) {
253
+ return;
254
+ }
255
+ const next = open ? [...expandedIds, id] : expandedIds.filter((entry) => entry !== id);
256
+ commitExpanded(next);
257
+ },
258
+ [commitExpanded, expandedIds, expandedSet]
259
+ );
260
+ const toggleExpanded = useCallback(
261
+ (id) => {
262
+ setExpanded(id, !expandedSet.has(id));
263
+ },
264
+ [expandedSet, setExpanded]
265
+ );
266
+ const itemRefs = useRef(/* @__PURE__ */ new Map());
267
+ const registerItem = useCallback((id, el) => {
268
+ if (el) {
269
+ itemRefs.current.set(id, el);
270
+ } else {
271
+ itemRefs.current.delete(id);
272
+ }
273
+ }, []);
274
+ const visible = useMemo(
275
+ () => flattenVisible(data, isExpanded),
276
+ [data, isExpanded]
277
+ );
278
+ const firstEnabledId = useMemo(
279
+ () => visible.find((entry) => !entry.node.disabled)?.node.id,
280
+ [visible]
281
+ );
282
+ const [activeIdState, setActiveIdState] = useState(
283
+ void 0
284
+ );
285
+ const isSelectedVisible = selectedId !== void 0 && visible.some((entry) => entry.node.id === selectedId);
286
+ const activeId = activeIdState && visible.some((entry) => entry.node.id === activeIdState) ? activeIdState : isSelectedVisible ? selectedId : firstEnabledId;
287
+ const focusItem = useCallback((id) => {
288
+ setActiveIdState(id);
289
+ itemRefs.current.get(id)?.focus();
290
+ }, []);
291
+ const selectNode = useCallback(
292
+ (node) => {
293
+ if (node.disabled) {
294
+ return;
295
+ }
296
+ setActiveIdState(node.id);
297
+ if (!isSelectedControlled) {
298
+ setSelectedUncontrolled(node.id);
299
+ }
300
+ onSelect?.(node);
301
+ },
302
+ [isSelectedControlled, onSelect]
303
+ );
304
+ const onItemKeyDown = useCallback(
305
+ (event) => {
306
+ const currentId = event.currentTarget.dataset.nodeId ?? activeId;
307
+ const index = visible.findIndex((entry) => entry.node.id === currentId);
308
+ const current = visible[index];
309
+ if (index === -1 || !current) {
310
+ return;
311
+ }
312
+ const moveTo = (target) => {
313
+ const clamped = Math.max(0, Math.min(visible.length - 1, target));
314
+ const next = visible[clamped];
315
+ if (next) {
316
+ focusItem(next.node.id);
317
+ }
318
+ };
319
+ switch (event.key) {
320
+ case "ArrowDown":
321
+ event.preventDefault();
322
+ moveTo(index + 1);
323
+ break;
324
+ case "ArrowUp":
325
+ event.preventDefault();
326
+ moveTo(index - 1);
327
+ break;
328
+ case "Home":
329
+ event.preventDefault();
330
+ moveTo(0);
331
+ break;
332
+ case "End":
333
+ event.preventDefault();
334
+ moveTo(visible.length - 1);
335
+ break;
336
+ case "ArrowRight": {
337
+ event.preventDefault();
338
+ const hasChildren = Boolean(current.node.children?.length);
339
+ if (hasChildren && !isExpanded(current.node.id)) {
340
+ setExpanded(current.node.id, true);
341
+ } else if (hasChildren) {
342
+ moveTo(index + 1);
343
+ }
344
+ break;
345
+ }
346
+ case "ArrowLeft": {
347
+ event.preventDefault();
348
+ const hasChildren = Boolean(current.node.children?.length);
349
+ if (hasChildren && isExpanded(current.node.id)) {
350
+ setExpanded(current.node.id, false);
351
+ } else if (current.parentId) {
352
+ focusItem(current.parentId);
353
+ }
354
+ break;
355
+ }
356
+ case "Enter":
357
+ case " ":
358
+ event.preventDefault();
359
+ selectNode(current.node);
360
+ break;
361
+ }
362
+ },
363
+ [activeId, focusItem, isExpanded, selectNode, setExpanded, visible]
364
+ );
365
+ const ctx = useMemo(
366
+ () => ({
367
+ appearance: appearance ?? "default",
368
+ size: size ?? "md",
369
+ showGuides,
370
+ GroupComponent,
371
+ isExpanded,
372
+ toggleExpanded,
373
+ setExpanded,
374
+ selectedId,
375
+ activeId,
376
+ selectNode,
377
+ registerItem,
378
+ onItemKeyDown,
379
+ renderNode
380
+ }),
381
+ [
382
+ activeId,
383
+ appearance,
384
+ GroupComponent,
385
+ isExpanded,
386
+ onItemKeyDown,
387
+ registerItem,
388
+ renderNode,
389
+ selectNode,
390
+ selectedId,
391
+ setExpanded,
392
+ showGuides,
393
+ size,
394
+ toggleExpanded
395
+ ]
396
+ );
397
+ return /* @__PURE__ */ jsx(TreeViewContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
398
+ "ul",
399
+ {
400
+ role: "tree",
401
+ "data-slot": "tree-view",
402
+ "aria-label": rest["aria-label"],
403
+ "aria-labelledby": rest["aria-labelledby"],
404
+ className: cn(
405
+ treeViewVariants({ appearance, size }),
406
+ "list-none",
407
+ className
408
+ ),
409
+ children: data.map((node) => /* @__PURE__ */ jsx(TreeItemNode, { node, level: 1 }, node.id))
410
+ }
411
+ ) });
412
+ }
413
+ TreeViewBase.displayName = "TreeView";
414
+
415
+ export { TreeViewBase, treeViewItemVariants, treeViewVariants };
416
+ //# sourceMappingURL=chunk-GRJFGIZC.mjs.map
417
+ //# sourceMappingURL=chunk-GRJFGIZC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/design-system/tree-view.ts","../src/ui/tree-view/variants.ts","../src/ui/tree-view/tree-view-base.tsx"],"names":[],"mappings":"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","file":"chunk-GRJFGIZC.mjs","sourcesContent":["export const zuiTreeViewBase =\n \"w-full text-[color:var(--zui-tree-view-fg,oklch(20.8%_0.042_265.755))] dark:text-[color:var(--zui-tree-view-fg-dark,oklch(92.9%_0.013_255.508))]\";\n\nexport const zuiTreeViewAppearances = {\n default:\n \"rounded-xl border border-[color:var(--zui-tree-view-default-border,#0000001a)] dark:border-[color:var(--zui-tree-view-default-border-dark,#ffffff1a)] p-2\",\n outline:\n \"rounded-xl border border-[color:var(--zui-tree-view-outline-border,#00000026)] dark:border-[color:var(--zui-tree-view-outline-border-dark,#ffffff26)] p-2\",\n ghost: \"p-1\",\n card: \"rounded-xl border border-[color:var(--zui-tree-view-card-border,#0000001a)] dark:border-[color:var(--zui-tree-view-card-border-dark,#ffffff1a)] bg-[var(--zui-tree-view-card-bg,#0000000d)] dark:bg-[var(--zui-tree-view-card-bg-dark,#00000099)] p-3\",\n separated:\n \"rounded-xl border border-[color:var(--zui-tree-view-separated-border,#0000001a)] dark:border-[color:var(--zui-tree-view-separated-border-dark,#ffffff1a)] bg-[var(--zui-tree-view-separated-bg,oklch(98.4%_0.003_247.858_/_0.4))] dark:bg-[var(--zui-tree-view-separated-bg-dark,oklch(12.9%_0.042_264.695_/_0.4))] p-3\",\n sky: \"rounded-xl border border-[color:var(--zui-tree-view-sky-border,oklch(44.3%_0.11_240.79))] dark:border-[color:var(--zui-tree-view-sky-border-dark,oklch(58.8%_0.158_241.966))] p-2\",\n rose: \"rounded-xl border border-[color:var(--zui-tree-view-rose-border,oklch(45.5%_0.188_13.697))] dark:border-[color:var(--zui-tree-view-rose-border-dark,oklch(58.6%_0.253_17.585))] p-2\",\n purple:\n \"rounded-xl border border-[color:var(--zui-tree-view-purple-border,oklch(43.8%_0.218_303.724))] dark:border-[color:var(--zui-tree-view-purple-border-dark,oklch(55.8%_0.288_302.321))] p-2\",\n pink: \"rounded-xl border border-[color:var(--zui-tree-view-pink-border,oklch(45.9%_0.187_3.815))] dark:border-[color:var(--zui-tree-view-pink-border-dark,oklch(59.2%_0.249_0.584))] p-2\",\n orange:\n \"rounded-xl border border-[color:var(--zui-tree-view-orange-border,oklch(47%_0.157_37.304))] dark:border-[color:var(--zui-tree-view-orange-border-dark,oklch(64.6%_0.222_41.116))] p-2\",\n yellow:\n \"rounded-xl border border-[color:var(--zui-tree-view-yellow-border,oklch(47.6%_0.114_61.907))] dark:border-[color:var(--zui-tree-view-yellow-border-dark,oklch(68.1%_0.162_75.834))] p-2\",\n teal: \"rounded-xl border border-[color:var(--zui-tree-view-teal-border,oklch(43.7%_0.078_188.216))] dark:border-[color:var(--zui-tree-view-teal-border-dark,oklch(60%_0.118_184.704))] p-2\",\n indigo:\n \"rounded-xl border border-[color:var(--zui-tree-view-indigo-border,oklch(39.8%_0.195_277.366))] dark:border-[color:var(--zui-tree-view-indigo-border-dark,oklch(51.1%_0.262_276.966))] p-2\",\n emerald:\n \"rounded-xl border border-[color:var(--zui-tree-view-emerald-border,oklch(43.2%_0.095_166.913))] dark:border-[color:var(--zui-tree-view-emerald-border-dark,oklch(59.6%_0.145_163.225))] p-2\",\n \"gradient-blue\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-blue-border,oklch(42.4%_0.199_265.638))] dark:border-[color:var(--zui-tree-view-gradient-blue-border-dark,oklch(54.6%_0.245_262.881))] p-2\",\n \"gradient-green\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-green-border,oklch(44.8%_0.119_151.328))] dark:border-[color:var(--zui-tree-view-gradient-green-border-dark,oklch(62.7%_0.194_149.214))] p-2\",\n \"gradient-red\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-red-border,oklch(44.4%_0.177_26.899))] dark:border-[color:var(--zui-tree-view-gradient-red-border-dark,oklch(57.7%_0.245_27.325))] p-2\",\n \"gradient-yellow\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-yellow-border,oklch(47.6%_0.114_61.907))] dark:border-[color:var(--zui-tree-view-gradient-yellow-border-dark,oklch(68.1%_0.162_75.834))] p-2\",\n \"gradient-purple\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-purple-border,oklch(43.8%_0.218_303.724))] dark:border-[color:var(--zui-tree-view-gradient-purple-border-dark,oklch(55.8%_0.288_302.321))] p-2\",\n \"gradient-teal\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-teal-border,oklch(43.7%_0.078_188.216))] dark:border-[color:var(--zui-tree-view-gradient-teal-border-dark,oklch(60%_0.118_184.704))] p-2\",\n \"gradient-indigo\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-indigo-border,oklch(39.8%_0.195_277.366))] dark:border-[color:var(--zui-tree-view-gradient-indigo-border-dark,oklch(51.1%_0.262_276.966))] p-2\",\n \"gradient-pink\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-pink-border,oklch(45.9%_0.187_3.815))] dark:border-[color:var(--zui-tree-view-gradient-pink-border-dark,oklch(59.2%_0.249_0.584))] p-2\",\n \"gradient-orange\":\n \"rounded-xl border border-[color:var(--zui-tree-view-gradient-orange-border,oklch(47%_0.157_37.304))] dark:border-[color:var(--zui-tree-view-gradient-orange-border-dark,oklch(64.6%_0.222_41.116))] p-2\",\n} as const;\n\nexport const zuiTreeViewSizes = {\n sm: \"text-xs\",\n md: \"text-sm\",\n lg: \"text-base\",\n} as const;\n\nexport const zuiTreeViewItemBase =\n \"relative flex w-full items-center gap-2 rounded-lg pr-2 text-left font-medium outline-none transition select-none cursor-pointer hover:bg-[var(--zui-tree-view-item-hover,#0000000d)] dark:hover:bg-[var(--zui-tree-view-item-hover-dark,#ffffff0d)] focus-visible:ring-2 focus-visible:ring-[var(--zui-tree-view-ring-focus,#0000004d)] dark:focus-visible:ring-[var(--zui-tree-view-ring-focus-dark,#ffffff4d)] data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50\";\n\nexport const zuiTreeViewItemSizes = {\n sm: \"py-1 text-xs\",\n md: \"py-1.5 text-sm\",\n lg: \"py-2 text-base\",\n} as const;\n\nexport const zuiTreeViewItemAppearances = {\n default:\n \"data-[selected=true]:bg-[var(--zui-tree-view-selected,#0000000f)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff14)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]\",\n outline:\n \"data-[selected=true]:bg-[var(--zui-tree-view-selected,#0000000f)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff14)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]\",\n ghost:\n \"data-[selected=true]:bg-[var(--zui-tree-view-selected,#0000000f)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff14)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]\",\n card: \"data-[selected=true]:bg-[var(--zui-tree-view-selected,#00000014)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff1f)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]\",\n separated:\n \"data-[selected=true]:bg-[var(--zui-tree-view-selected,#00000014)] dark:data-[selected=true]:bg-[var(--zui-tree-view-selected-dark,#ffffff1f)] data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg,oklch(20.8%_0.042_265.755))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-selected-fg-dark,#ffffff)]\",\n sky: \"data-[selected=true]:bg-[var(--zui-tree-view-sky-selected,oklch(95.1%_0.026_236.824))] dark:data-[selected=true]:bg-[var(--zui-tree-view-sky-selected-dark,oklch(58.8%_0.158_241.966_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-sky-selected-fg,oklch(44.3%_0.11_240.79))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-sky-selected-fg-dark,oklch(82.8%_0.111_230.318))]\",\n rose: \"data-[selected=true]:bg-[var(--zui-tree-view-rose-selected,oklch(94.1%_0.03_12.58))] dark:data-[selected=true]:bg-[var(--zui-tree-view-rose-selected-dark,oklch(58.6%_0.253_17.585_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-rose-selected-fg,oklch(45.5%_0.188_13.697))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-rose-selected-fg-dark,oklch(81%_0.117_11.638))]\",\n purple:\n \"data-[selected=true]:bg-[var(--zui-tree-view-purple-selected,oklch(94.6%_0.033_307.174))] dark:data-[selected=true]:bg-[var(--zui-tree-view-purple-selected-dark,oklch(55.8%_0.288_302.321_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-purple-selected-fg,oklch(43.8%_0.218_303.724))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-purple-selected-fg-dark,oklch(82.7%_0.119_306.383))]\",\n pink: \"data-[selected=true]:bg-[var(--zui-tree-view-pink-selected,oklch(94.8%_0.028_342.258))] dark:data-[selected=true]:bg-[var(--zui-tree-view-pink-selected-dark,oklch(59.2%_0.249_0.584_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-pink-selected-fg,oklch(45.9%_0.187_3.815))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-pink-selected-fg-dark,oklch(82.3%_0.12_346.018))]\",\n orange:\n \"data-[selected=true]:bg-[var(--zui-tree-view-orange-selected,oklch(95.4%_0.038_75.164))] dark:data-[selected=true]:bg-[var(--zui-tree-view-orange-selected-dark,oklch(64.6%_0.222_41.116_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-orange-selected-fg,oklch(47%_0.157_37.304))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-orange-selected-fg-dark,oklch(83.7%_0.128_66.29))]\",\n yellow:\n \"data-[selected=true]:bg-[var(--zui-tree-view-yellow-selected,oklch(97.3%_0.071_103.193))] dark:data-[selected=true]:bg-[var(--zui-tree-view-yellow-selected-dark,oklch(68.1%_0.162_75.834_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-yellow-selected-fg,oklch(47.6%_0.114_61.907))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-yellow-selected-fg-dark,oklch(90.5%_0.182_98.111))]\",\n teal: \"data-[selected=true]:bg-[var(--zui-tree-view-teal-selected,oklch(95.3%_0.051_180.801))] dark:data-[selected=true]:bg-[var(--zui-tree-view-teal-selected-dark,oklch(60%_0.118_184.704_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-teal-selected-fg,oklch(43.7%_0.078_188.216))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-teal-selected-fg-dark,oklch(85.5%_0.138_181.071))]\",\n indigo:\n \"data-[selected=true]:bg-[var(--zui-tree-view-indigo-selected,oklch(93%_0.034_272.788))] dark:data-[selected=true]:bg-[var(--zui-tree-view-indigo-selected-dark,oklch(51.1%_0.262_276.966_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-indigo-selected-fg,oklch(39.8%_0.195_277.366))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-indigo-selected-fg-dark,oklch(78.5%_0.115_274.713))]\",\n emerald:\n \"data-[selected=true]:bg-[var(--zui-tree-view-emerald-selected,oklch(95%_0.052_163.051))] dark:data-[selected=true]:bg-[var(--zui-tree-view-emerald-selected-dark,oklch(59.6%_0.145_163.225_/_0.16))] data-[selected=true]:text-[color:var(--zui-tree-view-emerald-selected-fg,oklch(43.2%_0.095_166.913))] dark:data-[selected=true]:text-[color:var(--zui-tree-view-emerald-selected-fg-dark,oklch(84.5%_0.143_164.978))]\",\n \"gradient-blue\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-blue-from,oklch(80.9%_0.105_251.813))] data-[selected=true]:to-[var(--zui-tree-view-gradient-blue-to,oklch(82.7%_0.119_306.383))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-blue-from-dark,oklch(54.6%_0.245_262.881))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-blue-to-dark,oklch(55.8%_0.288_302.321))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n \"gradient-green\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-green-from,oklch(87.1%_0.15_154.449))] data-[selected=true]:to-[var(--zui-tree-view-gradient-green-to,oklch(89.7%_0.196_126.665))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-green-from-dark,oklch(62.7%_0.194_149.214))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-green-to-dark,oklch(64.8%_0.2_131.684))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n \"gradient-red\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-red-from,oklch(80.8%_0.114_19.571))] data-[selected=true]:to-[var(--zui-tree-view-gradient-red-to,oklch(82.3%_0.12_346.018))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-red-from-dark,oklch(57.7%_0.245_27.325))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-red-to-dark,oklch(59.2%_0.249_0.584))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n \"gradient-yellow\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-yellow-from,oklch(90.5%_0.182_98.111))] data-[selected=true]:to-[var(--zui-tree-view-gradient-yellow-to,oklch(83.7%_0.128_66.29))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-yellow-from-dark,oklch(68.1%_0.162_75.834))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-yellow-to-dark,oklch(64.6%_0.222_41.116))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n \"gradient-purple\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-purple-from,oklch(82.7%_0.119_306.383))] data-[selected=true]:to-[var(--zui-tree-view-gradient-purple-to,oklch(82.3%_0.12_346.018))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-purple-from-dark,oklch(55.8%_0.288_302.321))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-purple-to-dark,oklch(59.2%_0.249_0.584))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n \"gradient-teal\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-teal-from,oklch(85.5%_0.138_181.071))] data-[selected=true]:to-[var(--zui-tree-view-gradient-teal-to,oklch(86.5%_0.127_207.078))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-teal-from-dark,oklch(60%_0.118_184.704))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-teal-to-dark,oklch(60.9%_0.126_221.723))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n \"gradient-indigo\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-indigo-from,oklch(78.5%_0.115_274.713))] data-[selected=true]:to-[var(--zui-tree-view-gradient-indigo-to,oklch(82.7%_0.119_306.383))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-indigo-from-dark,oklch(51.1%_0.262_276.966))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-indigo-to-dark,oklch(55.8%_0.288_302.321))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n \"gradient-pink\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-pink-from,oklch(82.3%_0.12_346.018))] data-[selected=true]:to-[var(--zui-tree-view-gradient-pink-to,oklch(81%_0.117_11.638))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-pink-from-dark,oklch(59.2%_0.249_0.584))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-pink-to-dark,oklch(58.6%_0.253_17.585))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n \"gradient-orange\":\n \"data-[selected=true]:bg-linear-to-r data-[selected=true]:from-[var(--zui-tree-view-gradient-orange-from,oklch(83.7%_0.128_66.29))] data-[selected=true]:to-[var(--zui-tree-view-gradient-orange-to,oklch(80.8%_0.114_19.571))] dark:data-[selected=true]:from-[var(--zui-tree-view-gradient-orange-from-dark,oklch(64.6%_0.222_41.116))] dark:data-[selected=true]:to-[var(--zui-tree-view-gradient-orange-to-dark,oklch(57.7%_0.245_27.325))] data-[selected=true]:text-[color:var(--zui-tree-view-gradient-fg,#ffffff)]\",\n} as const;\n\nexport const zuiTreeViewChevron =\n \"inline-flex h-5 w-5 shrink-0 items-center justify-center rounded text-[color:var(--zui-tree-view-chevron,oklch(55.5%_0.041_257.417))] dark:text-[color:var(--zui-tree-view-chevron-dark,oklch(70.4%_0.04_256.788))] transition-transform duration-200 data-[expanded=true]:rotate-90\";\n\nexport const zuiTreeViewIcon =\n \"inline-flex shrink-0 items-center justify-center text-[color:var(--zui-tree-view-icon,oklch(55.5%_0.041_257.417))] dark:text-[color:var(--zui-tree-view-icon-dark,oklch(70.4%_0.04_256.788))]\";\n\nexport const zuiTreeViewGuide =\n \"border-l border-[color:var(--zui-tree-view-guide,#0000001a)] dark:border-[color:var(--zui-tree-view-guide-dark,#ffffff1a)]\";\n","import { cva } from \"class-variance-authority\";\n\nimport {\n zuiTreeViewAppearances,\n zuiTreeViewBase,\n zuiTreeViewItemAppearances,\n zuiTreeViewItemBase,\n zuiTreeViewItemSizes,\n zuiTreeViewSizes,\n} from \"../../design-system/tree-view\";\n\nexport const treeViewVariants = cva(zuiTreeViewBase, {\n variants: {\n appearance: zuiTreeViewAppearances,\n size: zuiTreeViewSizes,\n },\n defaultVariants: {\n appearance: \"default\",\n size: \"md\",\n },\n});\n\nexport const treeViewItemVariants = cva(zuiTreeViewItemBase, {\n variants: {\n appearance: zuiTreeViewItemAppearances,\n size: zuiTreeViewItemSizes,\n },\n defaultVariants: {\n appearance: \"default\",\n size: \"md\",\n },\n});\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"../../lib/utils\";\nimport {\n zuiTreeViewChevron,\n zuiTreeViewGuide,\n zuiTreeViewIcon,\n} from \"../../design-system/tree-view\";\n\nimport type {\n TreeGroupProps,\n TreeNode,\n TreeViewBaseProps,\n TreeViewCtx,\n} from \"./types\";\nimport { treeViewItemVariants, treeViewVariants } from \"./variants\";\nimport { FaChevronRight } from \"react-icons/fa6\";\n\nconst TreeViewContext = createContext<TreeViewCtx | null>(null);\n\n/**\n * Reads the shared tree-view state from context and fails early when a tree item\n * is rendered outside the TreeView provider. The component name keeps the error\n * message actionable for consumers composing custom tree-view pieces.\n */\nfunction useTreeViewContext(component: string): TreeViewCtx {\n const ctx = useContext(TreeViewContext);\n if (!ctx) {\n throw new Error(`${component} must be used within <TreeView>`);\n }\n return ctx;\n}\n\ntype FlatNode = { node: TreeNode; level: number; parentId: string | null };\n\n/**\n * Converts the nested tree into a flat list of the nodes that are currently\n * visible. Keyboard navigation works against this list so ArrowUp/ArrowDown can\n * move through the rendered rows in visual order without walking the nested\n * structure on every key press.\n *\n * The same accumulator is passed through recursive calls to avoid creating and\n * merging many intermediate arrays for large trees.\n */\nfunction flattenVisible(\n nodes: TreeNode[],\n isExpanded: (id: string) => boolean,\n level = 1,\n parentId: string | null = null,\n acc: FlatNode[] = [],\n): FlatNode[] {\n for (const node of nodes) {\n acc.push({ node, level, parentId });\n if (node.children?.length && isExpanded(node.id)) {\n flattenVisible(node.children, isExpanded, level + 1, node.id, acc);\n }\n }\n return acc;\n}\n\n/**\n * Default non-animated group wrapper. Animated tree variants can replace this\n * component through GroupComponent while the recursive TreeItemNode rendering\n * remains shared.\n */\nfunction StaticTreeGroup({ open, children }: TreeGroupProps) {\n if (!open) {\n return null;\n }\n return (\n <ul role=\"group\" data-slot=\"tree-view-group\" className=\"m-0 list-none p-0\">\n {children}\n </ul>\n );\n}\n\nfunction TreeItemNode({\n node,\n level,\n chevronIcon,\n}: {\n node: TreeNode;\n level: number;\n chevronIcon?: React.ReactNode;\n}) {\n const {\n isExpanded,\n selectedId,\n activeId,\n GroupComponent,\n registerItem,\n appearance,\n size,\n toggleExpanded,\n selectNode,\n onItemKeyDown,\n renderNode,\n showGuides,\n } = useTreeViewContext(\"TreeItem\");\n\n // These derived flags keep the JSX readable and mirror the ARIA state applied\n // to each row below.\n const hasChildren = Boolean(node.children?.length);\n const expanded = hasChildren && isExpanded(node.id);\n const selected = selectedId === node.id;\n const active = activeId === node.id;\n const disabled = Boolean(node.disabled);\n\n // GroupComponent is intentionally resolved from context so the base tree can\n // be reused by static and animated implementations without duplicating item\n // rendering logic.\n const Group = GroupComponent;\n\n return (\n <li role=\"none\" data-slot=\"tree-view-item\">\n <div\n role=\"treeitem\"\n // Register the focusable row so keyboard navigation can imperatively\n // focus the next visible item after the active id changes.\n ref={(el) => registerItem(node.id, el)}\n aria-expanded={hasChildren ? expanded : undefined}\n aria-selected={selected}\n aria-level={level}\n aria-disabled={disabled || undefined}\n data-slot=\"tree-view-item-row\"\n data-node-id={node.id}\n data-selected={selected}\n data-active={active}\n data-disabled={disabled}\n tabIndex={active ? 0 : -1}\n // Each level indents by a fixed step. The root still gets a small inset\n // so chevrons and labels align with surrounding UI.\n style={{ paddingLeft: `${(level - 1) * 1.25 + 0.5}rem` }}\n className={treeViewItemVariants({\n appearance: appearance,\n size: size,\n })}\n onClick={() => {\n // Disabled rows are rendered for context but should not toggle,\n // select, or receive active focus from pointer interaction.\n if (disabled) {\n return;\n }\n\n // Clicking a parent both toggles disclosure and selects the row,\n // matching the same selection behavior as leaf nodes.\n if (hasChildren) {\n toggleExpanded(node.id);\n }\n selectNode(node);\n }}\n onKeyDown={onItemKeyDown}\n >\n {hasChildren ? (\n <span\n data-slot=\"tree-view-chevron\"\n data-expanded={expanded}\n className={zuiTreeViewChevron}\n >\n {chevronIcon || <FaChevronRight />}\n </span>\n ) : (\n // Leaf nodes reserve chevron space to keep labels vertically aligned\n // with sibling branches that do have disclosure icons.\n <span aria-hidden className=\"inline-flex h-5 w-5 shrink-0\" />\n )}\n {node.icon ? (\n <span data-slot=\"tree-view-icon\" className={zuiTreeViewIcon}>\n {node.icon}\n </span>\n ) : null}\n <span data-slot=\"tree-view-label\" className=\"truncate\">\n {renderNode\n ? renderNode({\n node,\n depth: level,\n isExpanded: expanded,\n isSelected: selected,\n })\n : node.label}\n </span>\n </div>\n {hasChildren ? (\n <Group open={expanded} level={level}>\n <ol\n className={cn(showGuides && zuiTreeViewGuide, showGuides && \"ml-5\")}\n >\n {node.children?.map((child) => (\n // Recursion preserves each child's depth so ARIA levels,\n // indentation, and guide spacing all stay in sync.\n <TreeItemNode key={child.id} node={child} level={level + 1} />\n ))}\n </ol>\n </Group>\n ) : null}\n </li>\n );\n}\n\nexport function TreeViewBase({\n data = [],\n defaultExpanded,\n expanded,\n onExpandedChange,\n defaultSelected,\n selected,\n onSelect,\n renderNode,\n showGuides = false,\n appearance = \"default\",\n size = \"md\",\n className,\n GroupComponent = StaticTreeGroup,\n ...rest\n}: TreeViewBaseProps & {\n GroupComponent?: TreeViewCtx[\"GroupComponent\"];\n}) {\n // Mirror common React controlled/uncontrolled patterns. When a controlled prop\n // is provided, internal state is treated as read-only fallback state and every\n // change is reported through the matching callback.\n const isExpandedControlled = expanded !== undefined;\n const isSelectedControlled = selected !== undefined;\n\n const [expandedUncontrolled, setExpandedUncontrolled] = useState<string[]>(\n defaultExpanded ?? [],\n );\n const [selectedUncontrolled, setSelectedUncontrolled] = useState<\n string | undefined\n >(defaultSelected);\n\n const expandedIds = isExpandedControlled\n ? (expanded ?? [])\n : expandedUncontrolled;\n const selectedId = isSelectedControlled ? selected : selectedUncontrolled;\n\n // A Set gives O(1) lookup for expansion checks. This is used in render, the\n // flattening utility, and keyboard navigation, so memoizing it prevents\n // rebuilding the lookup unless the expanded ids actually change.\n const expandedSet = useMemo(() => new Set(expandedIds), [expandedIds]);\n\n const isExpanded = useCallback(\n (id: string) => expandedSet.has(id),\n [expandedSet],\n );\n\n // Centralizes the \"commit\" step so controlled and uncontrolled expansion\n // updates always notify consumers consistently.\n const commitExpanded = useCallback(\n (next: string[]) => {\n if (!isExpandedControlled) {\n setExpandedUncontrolled(next);\n }\n onExpandedChange?.(next);\n },\n [isExpandedControlled, onExpandedChange],\n );\n\n const setExpanded = useCallback(\n (id: string, open: boolean) => {\n const has = expandedSet.has(id);\n\n // Avoid sending duplicate updates when the requested state already\n // matches the current expansion state.\n if (open === has) {\n return;\n }\n\n const next = open\n ? [...expandedIds, id]\n : expandedIds.filter((entry) => entry !== id);\n commitExpanded(next);\n },\n [commitExpanded, expandedIds, expandedSet],\n );\n\n const toggleExpanded = useCallback(\n (id: string) => {\n setExpanded(id, !expandedSet.has(id));\n },\n [expandedSet, setExpanded],\n );\n\n // Stores mounted treeitem rows by node id. The Map is held in a ref because\n // focus targets change over time without needing to trigger React renders.\n const itemRefs = useRef(new Map<string, HTMLDivElement>());\n const registerItem = useCallback((id: string, el: HTMLDivElement | null) => {\n if (el) {\n itemRefs.current.set(id, el);\n } else {\n itemRefs.current.delete(id);\n }\n }, []);\n\n // Only expanded branches are included. This becomes the single source of truth\n // for roving focus and Home/End/Arrow navigation.\n const visible = useMemo(\n () => flattenVisible(data, isExpanded),\n [data, isExpanded],\n );\n\n // Used as a safe fallback for tab focus when nothing has been selected or when\n // the selected/active item is hidden by a collapsed parent.\n const firstEnabledId = useMemo(\n () => visible.find((entry) => !entry.node.disabled)?.node.id,\n [visible],\n );\n\n const [activeIdState, setActiveIdState] = useState<string | undefined>(\n undefined,\n );\n\n // A selected item can become hidden when an ancestor is collapsed. In that\n // case it should not keep the roving tab stop; focus falls back below.\n const isSelectedVisible =\n selectedId !== undefined &&\n visible.some((entry) => entry.node.id === selectedId);\n\n // Roving tabindex chooses a single keyboard tab stop: prefer the last active\n // visible item, then the selected visible item, then the first enabled row.\n const activeId =\n activeIdState && visible.some((entry) => entry.node.id === activeIdState)\n ? activeIdState\n : isSelectedVisible\n ? selectedId\n : firstEnabledId;\n\n // Updates logical focus state and then focuses the mounted row when available.\n // Optional chaining handles cases where React has not mounted the row yet.\n const focusItem = useCallback((id: string) => {\n setActiveIdState(id);\n itemRefs.current.get(id)?.focus();\n }, []);\n\n const selectNode = useCallback(\n (node: TreeNode) => {\n // Selection ignores disabled nodes from both pointer and keyboard paths.\n if (node.disabled) {\n return;\n }\n\n setActiveIdState(node.id);\n if (!isSelectedControlled) {\n setSelectedUncontrolled(node.id);\n }\n onSelect?.(node);\n },\n [isSelectedControlled, onSelect],\n );\n\n const onItemKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n // Prefer the DOM row id because the event always originates from a\n // treeitem. activeId is a fallback for unusual composed event paths.\n const currentId = (event.currentTarget.dataset.nodeId ??\n activeId) as string;\n const index = visible.findIndex((entry) => entry.node.id === currentId);\n const current = visible[index];\n if (index === -1 || !current) {\n return;\n }\n\n const moveTo = (target: number) => {\n // Clamp so repeated ArrowUp/ArrowDown at the edges keeps focus on the\n // first or last visible item instead of producing an invalid index.\n const clamped = Math.max(0, Math.min(visible.length - 1, target));\n const next = visible[clamped];\n if (next) {\n focusItem(next.node.id);\n }\n };\n\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n moveTo(index + 1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n moveTo(index - 1);\n break;\n case \"Home\":\n event.preventDefault();\n moveTo(0);\n break;\n case \"End\":\n event.preventDefault();\n moveTo(visible.length - 1);\n break;\n case \"ArrowRight\": {\n event.preventDefault();\n const hasChildren = Boolean(current.node.children?.length);\n\n // Right arrow first opens a closed branch. If it is already open,\n // focus moves to the next visible row, which is the first child.\n if (hasChildren && !isExpanded(current.node.id)) {\n setExpanded(current.node.id, true);\n } else if (hasChildren) {\n moveTo(index + 1);\n }\n break;\n }\n case \"ArrowLeft\": {\n event.preventDefault();\n const hasChildren = Boolean(current.node.children?.length);\n\n // Left arrow closes an open branch. From a leaf or already-closed\n // branch, it moves focus back to the parent row when there is one.\n if (hasChildren && isExpanded(current.node.id)) {\n setExpanded(current.node.id, false);\n } else if (current.parentId) {\n focusItem(current.parentId);\n }\n break;\n }\n case \"Enter\":\n case \" \":\n event.preventDefault();\n // Enter and Space select the current row. Parent expansion remains on\n // the arrow keys so keyboard users have predictable disclosure control.\n selectNode(current.node);\n break;\n default:\n break;\n }\n },\n [activeId, focusItem, isExpanded, selectNode, setExpanded, visible],\n );\n\n // Memoize the context payload so recursive items only re-render when the tree\n // state or rendering options they consume actually change.\n const ctx = useMemo<TreeViewCtx>(\n () => ({\n appearance: appearance ?? \"default\",\n size: size ?? \"md\",\n showGuides,\n GroupComponent,\n isExpanded,\n toggleExpanded,\n setExpanded,\n selectedId,\n activeId,\n selectNode,\n registerItem,\n onItemKeyDown,\n renderNode,\n }),\n [\n activeId,\n appearance,\n GroupComponent,\n isExpanded,\n onItemKeyDown,\n registerItem,\n renderNode,\n selectNode,\n selectedId,\n setExpanded,\n showGuides,\n size,\n toggleExpanded,\n ],\n );\n\n return (\n <TreeViewContext.Provider value={ctx}>\n <ul\n role=\"tree\"\n data-slot=\"tree-view\"\n aria-label={rest[\"aria-label\"]}\n aria-labelledby={rest[\"aria-labelledby\"]}\n className={cn(\n treeViewVariants({ appearance, size }),\n \"list-none\",\n className,\n )}\n >\n {data.map((node) => (\n <TreeItemNode key={node.id} node={node} level={1} />\n ))}\n </ul>\n </TreeViewContext.Provider>\n );\n}\n\nTreeViewBase.displayName = \"TreeView\";\n\nexport { useTreeViewContext };\n"]}