@tetrascience-npm/tetrascience-react-ui 1.0.0-beta.162.1 → 1.0.0-beta.164.1

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.
package/dist/ui/table.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),o=require("../lib/utils.cjs");function c({className:e,containerClassName:t,variant:r,layout:n="auto",...l}){return a.jsx("div",{"data-slot":"table-container","data-variant":r,tabIndex:0,className:o.cn("relative w-full overflow-auto bg-card",r==="card"&&"rounded-lg border",t),children:a.jsx("table",{"data-slot":"table",className:o.cn("w-full caption-bottom text-sm",n==="fixed"&&"table-fixed",e),...l})})}function d({className:e,variant:t,...r}){return a.jsx("thead",{"data-slot":"table-header",className:o.cn("bg-muted/50 [&_tr]:border-b",t==="sticky"&&"sticky top-0 z-10 bg-background",e),...r})}function i({className:e,...t}){return a.jsx("tbody",{"data-slot":"table-body",className:o.cn("[&_tr:last-child]:border-0",e),...t})}function s({className:e,...t}){return a.jsx("tfoot",{"data-slot":"table-footer",className:o.cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",e),...t})}function b({className:e,...t}){return a.jsx("tr",{"data-slot":"table-row",className:o.cn("group/row border-b transition-colors hover:bg-accent/50 data-[state=selected]:bg-muted in-data-[striped]:even:bg-muted/30 in-data-[striped]:hover:bg-accent/50",e),...t})}function u({className:e,variant:t,truncate:r,...n}){return a.jsx("th",{"data-slot":"table-head",className:o.cn("h-12 px-4 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0","in-data-[density=compact]:h-8 in-data-[density=relaxed]:h-14",t==="numeric"&&"text-right",t==="action"&&"w-10",r&&"truncate",e),...n})}function m({className:e,variant:t,truncate:r,...n}){return a.jsx("td",{"data-slot":"table-cell",className:o.cn("p-4 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0","in-data-[density=compact]:py-2 in-data-[density=relaxed]:py-5",t==="numeric"&&"text-right tabular-nums",t==="action"&&"opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-within:opacity-100 transition-opacity",r&&"truncate",e),...n})}function p({className:e,...t}){return a.jsx("caption",{"data-slot":"table-caption",className:o.cn("mt-4 text-sm text-muted-foreground",e),...t})}exports.Table=c;exports.TableBody=i;exports.TableCaption=p;exports.TableCell=m;exports.TableFooter=s;exports.TableHead=u;exports.TableHeader=d;exports.TableRow=b;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),o=require("../lib/utils.cjs");function c({className:e,containerClassName:t,variant:r,layout:n="auto",...l}){return a.jsx("div",{"data-slot":"table-container","data-variant":r,tabIndex:0,className:o.cn("relative w-full overflow-auto bg-card",r==="card"&&"rounded-lg border",t),children:a.jsx("table",{"data-slot":"table",className:o.cn("w-full caption-bottom text-sm",n==="fixed"&&"table-fixed",e),...l})})}function d({className:e,variant:t,...r}){return a.jsx("thead",{"data-slot":"table-header",className:o.cn("bg-muted/50 [&_tr]:border-b",t==="sticky"&&"sticky top-0 z-10 bg-background",e),...r})}function i({className:e,...t}){return a.jsx("tbody",{"data-slot":"table-body",className:o.cn("[&_tr:last-child]:border-0",e),...t})}function s({className:e,...t}){return a.jsx("tfoot",{"data-slot":"table-footer",className:o.cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",e),...t})}function b({className:e,...t}){return a.jsx("tr",{"data-slot":"table-row",className:o.cn("group/row border-b transition-colors hover:bg-accent/50 data-[state=selected]:bg-muted in-data-[striped]:even:bg-muted/30 in-data-[striped]:hover:bg-accent/50",e),...t})}function u({className:e,variant:t,truncate:r,...n}){return a.jsx("th",{"data-slot":"table-head",className:o.cn("h-12 px-4 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0","in-data-[density=compact]:h-8 in-data-[density=relaxed]:h-14",t==="numeric"&&"text-right",t==="action"&&"w-10",r&&"truncate",e),...n})}function m({className:e,variant:t,truncate:r,...n}){return a.jsx("td",{"data-slot":"table-cell",className:o.cn("p-4 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0","in-data-[density=compact]:py-2 in-data-[density=relaxed]:py-5",t==="numeric"&&"text-right tabular-nums",t==="action"&&"opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-within:opacity-100 pointer-coarse:opacity-100 transition-opacity",r&&"truncate",e),...n})}function p({className:e,...t}){return a.jsx("caption",{"data-slot":"table-caption",className:o.cn("mt-4 text-sm text-muted-foreground",e),...t})}exports.Table=c;exports.TableBody=i;exports.TableCaption=p;exports.TableCell=m;exports.TableFooter=s;exports.TableHead=u;exports.TableHeader=d;exports.TableRow=b;
2
2
  //# sourceMappingURL=table.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"table.cjs","sources":["../../src/components/ui/table.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Table({\n className,\n containerClassName,\n variant,\n layout = \"auto\",\n ...props\n}: React.ComponentProps<\"table\"> & {\n containerClassName?: string\n variant?: \"default\" | \"card\"\n layout?: \"auto\" | \"fixed\"\n}) {\n return (\n <div\n data-slot=\"table-container\"\n data-variant={variant}\n tabIndex={0}\n className={cn(\n \"relative w-full overflow-auto bg-card\",\n variant === \"card\" && \"rounded-lg border\",\n containerClassName,\n )}\n >\n <table\n data-slot=\"table\"\n className={cn(\"w-full caption-bottom text-sm\", layout === \"fixed\" && \"table-fixed\", className)}\n {...props}\n />\n </div>\n )\n}\n\nfunction TableHeader({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"thead\"> & {\n variant?: \"default\" | \"sticky\"\n}) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\n \"bg-muted/50 [&_tr]:border-b\",\n variant === \"sticky\" && \"sticky top-0 z-10 bg-background\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n return (\n <tr\n data-slot=\"table-row\"\n className={cn(\n \"group/row border-b transition-colors hover:bg-accent/50 data-[state=selected]:bg-muted in-data-[striped]:even:bg-muted/30 in-data-[striped]:hover:bg-accent/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableHead({\n className,\n variant,\n truncate,\n ...props\n}: React.ComponentProps<\"th\"> & {\n variant?: \"default\" | \"numeric\" | \"action\"\n truncate?: boolean\n}) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0\",\n \"in-data-[density=compact]:h-8 in-data-[density=relaxed]:h-14\",\n variant === \"numeric\" && \"text-right\",\n variant === \"action\" && \"w-10\",\n truncate && \"truncate\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableCell({\n className,\n variant,\n truncate,\n ...props\n}: React.ComponentProps<\"td\"> & {\n variant?: \"default\" | \"numeric\" | \"action\"\n truncate?: boolean\n}) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n \"p-4 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\",\n \"in-data-[density=compact]:py-2 in-data-[density=relaxed]:py-5\",\n variant === \"numeric\" && \"text-right tabular-nums\",\n variant === \"action\" &&\n \"opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-within:opacity-100 transition-opacity\",\n truncate && \"truncate\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableCaption({\n className,\n ...props\n}: React.ComponentProps<\"caption\">) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n"],"names":["Table","className","containerClassName","variant","layout","props","jsx","cn","TableHeader","TableBody","TableFooter","TableRow","TableHead","truncate","TableCell","TableCaption"],"mappings":"mJAIA,SAASA,EAAM,CACb,UAAAC,EACA,mBAAAC,EACA,QAAAC,EACA,OAAAC,EAAS,OACT,GAAGC,CACL,EAIG,CACD,OACEC,EAAAA,IAAC,MAAA,CACC,YAAU,kBACV,eAAcH,EACd,SAAU,EACV,UAAWI,EAAAA,GACT,wCACAJ,IAAY,QAAU,oBACtBD,CAAA,EAGF,SAAAI,EAAAA,IAAC,QAAA,CACC,YAAU,QACV,UAAWC,EAAAA,GAAG,gCAAiCH,IAAW,SAAW,cAAeH,CAAS,EAC5F,GAAGI,CAAA,CAAA,CACN,CAAA,CAGN,CAEA,SAASG,EAAY,CACnB,UAAAP,EACA,QAAAE,EACA,GAAGE,CACL,EAEG,CACD,OACEC,EAAAA,IAAC,QAAA,CACC,YAAU,eACV,UAAWC,EAAAA,GACT,8BACAJ,IAAY,UAAY,kCACxBF,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASI,EAAU,CAAE,UAAAR,EAAW,GAAGI,GAAwC,CACzE,OACEC,EAAAA,IAAC,QAAA,CACC,YAAU,aACV,UAAWC,EAAAA,GAAG,6BAA8BN,CAAS,EACpD,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASK,EAAY,CAAE,UAAAT,EAAW,GAAGI,GAAwC,CAC3E,OACEC,EAAAA,IAAC,QAAA,CACC,YAAU,eACV,UAAWC,EAAAA,GACT,0DACAN,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASM,EAAS,CAAE,UAAAV,EAAW,GAAGI,GAAqC,CACrE,OACEC,EAAAA,IAAC,KAAA,CACC,YAAU,YACV,UAAWC,EAAAA,GACT,iKACAN,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASO,EAAU,CACjB,UAAAX,EACA,QAAAE,EACA,SAAAU,EACA,GAAGR,CACL,EAGG,CACD,OACEC,EAAAA,IAAC,KAAA,CACC,YAAU,aACV,UAAWC,EAAAA,GACT,+GACA,+DACAJ,IAAY,WAAa,aACzBA,IAAY,UAAY,OACxBU,GAAY,WACZZ,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASS,EAAU,CACjB,UAAAb,EACA,QAAAE,EACA,SAAAU,EACA,GAAGR,CACL,EAGG,CACD,OACEC,EAAAA,IAAC,KAAA,CACC,YAAU,aACV,UAAWC,EAAAA,GACT,mEACA,gEACAJ,IAAY,WAAa,0BACzBA,IAAY,UACV,uHACFU,GAAY,WACZZ,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASU,EAAa,CACpB,UAAAd,EACA,GAAGI,CACL,EAAoC,CAClC,OACEC,EAAAA,IAAC,UAAA,CACC,YAAU,gBACV,UAAWC,EAAAA,GAAG,qCAAsCN,CAAS,EAC5D,GAAGI,CAAA,CAAA,CAGV"}
1
+ {"version":3,"file":"table.cjs","sources":["../../src/components/ui/table.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Table({\n className,\n containerClassName,\n variant,\n layout = \"auto\",\n ...props\n}: React.ComponentProps<\"table\"> & {\n containerClassName?: string\n variant?: \"default\" | \"card\"\n layout?: \"auto\" | \"fixed\"\n}) {\n return (\n <div\n data-slot=\"table-container\"\n data-variant={variant}\n tabIndex={0}\n className={cn(\n \"relative w-full overflow-auto bg-card\",\n variant === \"card\" && \"rounded-lg border\",\n containerClassName,\n )}\n >\n <table\n data-slot=\"table\"\n className={cn(\"w-full caption-bottom text-sm\", layout === \"fixed\" && \"table-fixed\", className)}\n {...props}\n />\n </div>\n )\n}\n\nfunction TableHeader({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"thead\"> & {\n variant?: \"default\" | \"sticky\"\n}) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\n \"bg-muted/50 [&_tr]:border-b\",\n variant === \"sticky\" && \"sticky top-0 z-10 bg-background\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n return (\n <tr\n data-slot=\"table-row\"\n className={cn(\n \"group/row border-b transition-colors hover:bg-accent/50 data-[state=selected]:bg-muted in-data-[striped]:even:bg-muted/30 in-data-[striped]:hover:bg-accent/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableHead({\n className,\n variant,\n truncate,\n ...props\n}: React.ComponentProps<\"th\"> & {\n variant?: \"default\" | \"numeric\" | \"action\"\n truncate?: boolean\n}) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0\",\n \"in-data-[density=compact]:h-8 in-data-[density=relaxed]:h-14\",\n variant === \"numeric\" && \"text-right\",\n variant === \"action\" && \"w-10\",\n truncate && \"truncate\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableCell({\n className,\n variant,\n truncate,\n ...props\n}: React.ComponentProps<\"td\"> & {\n variant?: \"default\" | \"numeric\" | \"action\"\n truncate?: boolean\n}) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n \"p-4 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\",\n \"in-data-[density=compact]:py-2 in-data-[density=relaxed]:py-5\",\n variant === \"numeric\" && \"text-right tabular-nums\",\n // Action cells reveal on row hover/focus; on a coarse pointer (touch, no\n // hover) they always show so they stay reachable (SW-2535).\n variant === \"action\" &&\n \"opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-within:opacity-100 pointer-coarse:opacity-100 transition-opacity\",\n truncate && \"truncate\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableCaption({\n className,\n ...props\n}: React.ComponentProps<\"caption\">) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n"],"names":["Table","className","containerClassName","variant","layout","props","jsx","cn","TableHeader","TableBody","TableFooter","TableRow","TableHead","truncate","TableCell","TableCaption"],"mappings":"mJAIA,SAASA,EAAM,CACb,UAAAC,EACA,mBAAAC,EACA,QAAAC,EACA,OAAAC,EAAS,OACT,GAAGC,CACL,EAIG,CACD,OACEC,EAAAA,IAAC,MAAA,CACC,YAAU,kBACV,eAAcH,EACd,SAAU,EACV,UAAWI,EAAAA,GACT,wCACAJ,IAAY,QAAU,oBACtBD,CAAA,EAGF,SAAAI,EAAAA,IAAC,QAAA,CACC,YAAU,QACV,UAAWC,EAAAA,GAAG,gCAAiCH,IAAW,SAAW,cAAeH,CAAS,EAC5F,GAAGI,CAAA,CAAA,CACN,CAAA,CAGN,CAEA,SAASG,EAAY,CACnB,UAAAP,EACA,QAAAE,EACA,GAAGE,CACL,EAEG,CACD,OACEC,EAAAA,IAAC,QAAA,CACC,YAAU,eACV,UAAWC,EAAAA,GACT,8BACAJ,IAAY,UAAY,kCACxBF,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASI,EAAU,CAAE,UAAAR,EAAW,GAAGI,GAAwC,CACzE,OACEC,EAAAA,IAAC,QAAA,CACC,YAAU,aACV,UAAWC,EAAAA,GAAG,6BAA8BN,CAAS,EACpD,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASK,EAAY,CAAE,UAAAT,EAAW,GAAGI,GAAwC,CAC3E,OACEC,EAAAA,IAAC,QAAA,CACC,YAAU,eACV,UAAWC,EAAAA,GACT,0DACAN,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASM,EAAS,CAAE,UAAAV,EAAW,GAAGI,GAAqC,CACrE,OACEC,EAAAA,IAAC,KAAA,CACC,YAAU,YACV,UAAWC,EAAAA,GACT,iKACAN,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASO,EAAU,CACjB,UAAAX,EACA,QAAAE,EACA,SAAAU,EACA,GAAGR,CACL,EAGG,CACD,OACEC,EAAAA,IAAC,KAAA,CACC,YAAU,aACV,UAAWC,EAAAA,GACT,+GACA,+DACAJ,IAAY,WAAa,aACzBA,IAAY,UAAY,OACxBU,GAAY,WACZZ,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASS,EAAU,CACjB,UAAAb,EACA,QAAAE,EACA,SAAAU,EACA,GAAGR,CACL,EAGG,CACD,OACEC,EAAAA,IAAC,KAAA,CACC,YAAU,aACV,UAAWC,EAAAA,GACT,mEACA,gEACAJ,IAAY,WAAa,0BAGzBA,IAAY,UACV,kJACFU,GAAY,WACZZ,CAAA,EAED,GAAGI,CAAA,CAAA,CAGV,CAEA,SAASU,EAAa,CACpB,UAAAd,EACA,GAAGI,CACL,EAAoC,CAClC,OACEC,EAAAA,IAAC,UAAA,CACC,YAAU,gBACV,UAAWC,EAAAA,GAAG,qCAAsCN,CAAS,EAC5D,GAAGI,CAAA,CAAA,CAGV"}
package/dist/ui/table.js CHANGED
@@ -119,7 +119,9 @@ function f({
119
119
  "p-4 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
120
120
  "in-data-[density=compact]:py-2 in-data-[density=relaxed]:py-5",
121
121
  t === "numeric" && "text-right tabular-nums",
122
- t === "action" && "opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-within:opacity-100 transition-opacity",
122
+ // Action cells reveal on row hover/focus; on a coarse pointer (touch, no
123
+ // hover) they always show so they stay reachable (SW-2535).
124
+ t === "action" && "opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-within:opacity-100 pointer-coarse:opacity-100 transition-opacity",
123
125
  r && "truncate",
124
126
  e
125
127
  ),
@@ -1 +1 @@
1
- {"version":3,"file":"table.js","sources":["../../src/components/ui/table.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Table({\n className,\n containerClassName,\n variant,\n layout = \"auto\",\n ...props\n}: React.ComponentProps<\"table\"> & {\n containerClassName?: string\n variant?: \"default\" | \"card\"\n layout?: \"auto\" | \"fixed\"\n}) {\n return (\n <div\n data-slot=\"table-container\"\n data-variant={variant}\n tabIndex={0}\n className={cn(\n \"relative w-full overflow-auto bg-card\",\n variant === \"card\" && \"rounded-lg border\",\n containerClassName,\n )}\n >\n <table\n data-slot=\"table\"\n className={cn(\"w-full caption-bottom text-sm\", layout === \"fixed\" && \"table-fixed\", className)}\n {...props}\n />\n </div>\n )\n}\n\nfunction TableHeader({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"thead\"> & {\n variant?: \"default\" | \"sticky\"\n}) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\n \"bg-muted/50 [&_tr]:border-b\",\n variant === \"sticky\" && \"sticky top-0 z-10 bg-background\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n return (\n <tr\n data-slot=\"table-row\"\n className={cn(\n \"group/row border-b transition-colors hover:bg-accent/50 data-[state=selected]:bg-muted in-data-[striped]:even:bg-muted/30 in-data-[striped]:hover:bg-accent/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableHead({\n className,\n variant,\n truncate,\n ...props\n}: React.ComponentProps<\"th\"> & {\n variant?: \"default\" | \"numeric\" | \"action\"\n truncate?: boolean\n}) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0\",\n \"in-data-[density=compact]:h-8 in-data-[density=relaxed]:h-14\",\n variant === \"numeric\" && \"text-right\",\n variant === \"action\" && \"w-10\",\n truncate && \"truncate\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableCell({\n className,\n variant,\n truncate,\n ...props\n}: React.ComponentProps<\"td\"> & {\n variant?: \"default\" | \"numeric\" | \"action\"\n truncate?: boolean\n}) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n \"p-4 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\",\n \"in-data-[density=compact]:py-2 in-data-[density=relaxed]:py-5\",\n variant === \"numeric\" && \"text-right tabular-nums\",\n variant === \"action\" &&\n \"opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-within:opacity-100 transition-opacity\",\n truncate && \"truncate\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableCaption({\n className,\n ...props\n}: React.ComponentProps<\"caption\">) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n"],"names":["Table","className","containerClassName","variant","layout","props","jsx","cn","TableHeader","TableBody","TableFooter","TableRow","TableHead","truncate","TableCell","TableCaption"],"mappings":"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"}
1
+ {"version":3,"file":"table.js","sources":["../../src/components/ui/table.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Table({\n className,\n containerClassName,\n variant,\n layout = \"auto\",\n ...props\n}: React.ComponentProps<\"table\"> & {\n containerClassName?: string\n variant?: \"default\" | \"card\"\n layout?: \"auto\" | \"fixed\"\n}) {\n return (\n <div\n data-slot=\"table-container\"\n data-variant={variant}\n tabIndex={0}\n className={cn(\n \"relative w-full overflow-auto bg-card\",\n variant === \"card\" && \"rounded-lg border\",\n containerClassName,\n )}\n >\n <table\n data-slot=\"table\"\n className={cn(\"w-full caption-bottom text-sm\", layout === \"fixed\" && \"table-fixed\", className)}\n {...props}\n />\n </div>\n )\n}\n\nfunction TableHeader({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"thead\"> & {\n variant?: \"default\" | \"sticky\"\n}) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\n \"bg-muted/50 [&_tr]:border-b\",\n variant === \"sticky\" && \"sticky top-0 z-10 bg-background\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<\"tbody\">) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn(\"[&_tr:last-child]:border-0\", className)}\n {...props}\n />\n )\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<\"tfoot\">) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn(\n \"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableRow({ className, ...props }: React.ComponentProps<\"tr\">) {\n return (\n <tr\n data-slot=\"table-row\"\n className={cn(\n \"group/row border-b transition-colors hover:bg-accent/50 data-[state=selected]:bg-muted in-data-[striped]:even:bg-muted/30 in-data-[striped]:hover:bg-accent/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TableHead({\n className,\n variant,\n truncate,\n ...props\n}: React.ComponentProps<\"th\"> & {\n variant?: \"default\" | \"numeric\" | \"action\"\n truncate?: boolean\n}) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0\",\n \"in-data-[density=compact]:h-8 in-data-[density=relaxed]:h-14\",\n variant === \"numeric\" && \"text-right\",\n variant === \"action\" && \"w-10\",\n truncate && \"truncate\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableCell({\n className,\n variant,\n truncate,\n ...props\n}: React.ComponentProps<\"td\"> & {\n variant?: \"default\" | \"numeric\" | \"action\"\n truncate?: boolean\n}) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n \"p-4 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0\",\n \"in-data-[density=compact]:py-2 in-data-[density=relaxed]:py-5\",\n variant === \"numeric\" && \"text-right tabular-nums\",\n // Action cells reveal on row hover/focus; on a coarse pointer (touch, no\n // hover) they always show so they stay reachable (SW-2535).\n variant === \"action\" &&\n \"opacity-0 group-hover/row:opacity-100 group-focus-within/row:opacity-100 focus-within:opacity-100 pointer-coarse:opacity-100 transition-opacity\",\n truncate && \"truncate\",\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction TableCaption({\n className,\n ...props\n}: React.ComponentProps<\"caption\">) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn(\"mt-4 text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n"],"names":["Table","className","containerClassName","variant","layout","props","jsx","cn","TableHeader","TableBody","TableFooter","TableRow","TableHead","truncate","TableCell","TableCaption"],"mappings":"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"}
package/dist/ui/tree.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),J=require("@radix-ui/react-use-controllable-state"),le=require("class-variance-authority"),ie=require("lucide-react"),ce=require("react"),H=require("./tooltip.cjs"),k=require("../lib/utils.cjs");function ue(e){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const o=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,o.get?o:{enumerable:!0,get:()=>e[t]})}}return r.default=e,Object.freeze(r)}const s=ue(ce),ee=s.createContext(null),te=s.createContext(null);function re(e){const r=s.useContext(ee);if(!r)throw new Error(`\`${e}\` must be rendered inside a \`Tree\`.`);return r}const W=s.createContext(1),ne=s.createContext({posinset:1,setsize:1,lastBranchPos:0}),G=s.createContext(null),de=[];function Y(e){const r=s.useContext(G);if(!r)throw new Error(`\`${e}\` must be rendered inside a \`TreeItem\`.`);return r}function fe(){return Y("useTreeItem")}function me(e){return s.useMemo(()=>{const r=s.Children.toArray(e),t=r.filter(s.isValidElement),o=t.length,a=i=>i.props?.hasChildren===!0,c=t.reduce((i,m,p)=>a(m)?p+1:i,0);let u=0;return r.map((i,m)=>s.isValidElement(i)?(u+=1,l.jsx(ne.Provider,{value:{posinset:u,setsize:o,lastBranchPos:c},children:i},i.key??m)):i)},[e])}const _='[role="treeitem"]';function S(e){return e?[...e.querySelectorAll(_)]:[]}const pe='[role="group"], [role="tree"]';function U(e,r){return S(e).find(t=>t.dataset.treeItemId===r)}function Q(e){return e.parentElement?.closest(pe)??null}function xe(e){const r=[];for(let t=e.parentElement?.closest(_);t;)t.dataset.treeItemId&&r.unshift(t.dataset.treeItemId),t=t.parentElement?.closest(_);return r}function se(e){if(e.nodeType===Node.TEXT_NODE)return e.textContent??"";if(!(e instanceof HTMLElement)||e.getAttribute("aria-hidden")==="true")return"";let r="";for(const t of e.childNodes)r+=se(t);return r}function ge(e){const r=e.getAttribute("aria-labelledby"),t=r?e.ownerDocument.getElementById(r):null;return(t?se(t):"").trim().toLowerCase()}function he(e,r,t){const o=U(e,r);if(o)return o;for(let a=t.length-1;a>=0;a-=1){const c=U(e,t[a]);if(c)return c}return S(e)[0]}function be(e,r){const t=e?.dataset.treeItemId;!e||!t||(r(t),e.focus())}const Ie=600,Te=800;function z({event:e,setFocusedId:r},t){e.preventDefault(),be(t,r)}function Z(e,r){const t=S(e.root);z(e,t[t.indexOf(e.current)+r])}const ve={ArrowDown:e=>Z(e,1),ArrowUp:e=>Z(e,-1),ArrowRight:e=>{const{event:r,current:t,id:o,hasChildren:a,expanded:c,setExpanded:u}=e;if(a&&!c){r.preventDefault(),u(o,!0);return}c&&z(e,t.querySelector(_))},ArrowLeft:e=>{const{event:r,current:t,id:o,expanded:a,setExpanded:c}=e;if(a){r.preventDefault(),c(o,!1);return}z(e,t.parentElement?.closest(_))},Home:e=>z(e,S(e.root)[0]),End:e=>{const r=S(e.root);z(e,r[r.length-1])},Enter:e=>{e.disabled||(e.event.preventDefault(),e.activate(e.id,e.hasChildren,e.expanded))},"*":e=>{const{event:r,root:t,current:o,expandIds:a}=e;r.preventDefault();const c=Q(o)??t,u=S(c).filter(i=>Q(i)===c).filter(i=>i.dataset.treeHasChildren==="true"&&i.getAttribute("aria-expanded")!=="true").map(i=>i.dataset.treeItemId).filter(i=>!!i);u.length&&a(u)}};function ye(e){return e.key.length===1&&e.key!==" "}function Ce(e){const{event:r,root:t,current:o,typeahead:a,setTypeaheadMatch:c}=e;r.preventDefault(),clearTimeout(a.timer),clearTimeout(a.fadeTimer),a.buffer+=r.key.toLowerCase();const{buffer:u}=a,m=u.length>1&&[...u].every(h=>h===u[0])?u[0]:u;c({query:m,fading:!1}),a.timer=setTimeout(()=>{a.buffer="",c({query:m,fading:!0}),a.fadeTimer=setTimeout(()=>c(null),Te)},Ie);const p=S(t),T=p.indexOf(o);for(let h=1;h<=p.length;h+=1){const v=p[(T+h)%p.length];if(ge(v).startsWith(m)){z(e,v);return}}}function Ee({className:e,children:r,expandedIds:t,defaultExpandedIds:o,onExpandedChange:a,selectedId:c,defaultSelectedId:u=null,onSelectedChange:i,onActivate:m,expandOnSelect:p=!0,guides:T="hover",onFocus:h,onBlur:v,...D}){const R=s.useRef(null),[y,E]=J.useControllableState({prop:t,defaultProp:o??new Set,onChange:a}),[C,b]=J.useControllableState({prop:c,defaultProp:u,onChange:n=>{n!=null&&i?.(n)}}),[x,P]=s.useState(null),[w,A]=s.useState(null),[f,j]=s.useState(null),q=s.useRef([]),L=s.useRef(!1),F=s.useRef({buffer:"",timer:void 0,fadeTimer:void 0});s.useEffect(()=>()=>{clearTimeout(F.current.timer),clearTimeout(F.current.fadeTimer)},[]);const N=s.useCallback((n,g)=>{E(d=>{const I=new Set(d);return g?I.add(n):I.delete(n),I})},[E]),M=s.useCallback(n=>{E(g=>{const d=new Set(g);for(const I of n)d.add(I);return d})},[E]),K=s.useCallback((n,g,d)=>{b(n),p&&g&&N(n,!d),m?.(n)},[b,p,N,m]),O=s.useCallback(n=>{const g=R.current,d=n.target?.closest(_),I=d?.dataset.treeItemId;if(!g||!d||!I||!g.contains(d)||d!==n.currentTarget||n.ctrlKey||n.metaKey||n.altKey)return;const $=ve[n.key]??(ye(n)?Ce:void 0);$&&$({event:n,root:g,current:d,id:I,hasChildren:d.dataset.treeHasChildren==="true",expanded:d.getAttribute("aria-expanded")==="true",disabled:d.getAttribute("aria-disabled")==="true",setExpanded:N,expandIds:M,setFocusedId:P,activate:K,typeahead:F.current,setTypeaheadMatch:j})},[N,M,K]),B=s.useCallback(()=>{const n=R.current;if(!n)return;if(x==null){const X=C!=null&&!U(n,C)?S(n)[0]?.dataset.treeItemId??null:null;X!==w&&A(X);return}const g=he(n,x,q.current),d=g?.dataset.treeItemId;if(!g||!d)return;d===x?q.current=xe(g):P(d);const I=n.ownerDocument.activeElement;L.current&&(!n.contains(I)||I===n)&&g.focus()},[x,C,w]);s.useLayoutEffect(B);const V=s.useMemo(()=>({expandedIds:y??new Set,setExpanded:N,expandIds:M,selectedId:C??null,activateItem:K,focusedId:x,setFocusedId:P,entryId:w,expandOnSelect:p,guides:T,onItemKeyDown:O}),[y,N,M,C,K,x,w,p,T,O]);return l.jsx(ee.Provider,{value:V,children:l.jsx(te.Provider,{value:f,children:l.jsx(W.Provider,{value:1,children:l.jsx("div",{ref:R,"data-slot":"tree","data-guides":T,role:"tree",tabIndex:-1,onFocus:n=>{h?.(n),L.current=!0},onBlur:n=>{v?.(n),n.currentTarget.contains(n.relatedTarget)||(L.current=!1)},className:k.cn("group/tree text-foreground flex w-full flex-col text-sm","[--tree-indent:1.25rem] [--tree-guide-color:color-mix(in_oklch,var(--muted-foreground)_40%,var(--background))]",e),...D,children:l.jsx(H.TooltipProvider,{delayDuration:500,children:l.jsx(oe,{children:r})})})})})})}function oe({children:e}){return me(e)}function we({className:e,children:r,id:t,hasChildren:o=!1,disabled:a=!1,onClick:c,onFocus:u,onKeyDown:i,style:m,...p}){const{expandedIds:T,setExpanded:h,selectedId:v,activateItem:D,focusedId:R,setFocusedId:y,entryId:E,onItemKeyDown:C}=re("TreeItem"),b=s.useContext(W),{posinset:x,setsize:P,lastBranchPos:w}=s.useContext(ne),A=`${s.useId()}-label`,f=o&&T.has(t),j=v===t,q=s.useCallback(()=>{o&&h(t,!f)},[o,h,t,f]),L=s.useCallback(()=>{a||(y(t),D(t,o,f))},[a,y,t,D,o,f]),F=b===1&&x===1,N=v==null?F:v===t,M=R?R===t:E?E===t:N,O=s.useContext(G)?.trunkLevels??de,B=s.useMemo(()=>b>1&&x<w?[...O,b-1]:O,[O,b,x,w]),V=s.useMemo(()=>({id:t,labelId:A,level:b,expanded:f,hasChildren:o,selected:j,disabled:a,trunkLevels:B,toggle:q,select:L}),[t,A,b,f,o,j,a,B,q,L]);return l.jsx(G.Provider,{value:V,children:l.jsx("div",{...p,"data-slot":"tree-item","data-tree-item-id":t,"data-tree-has-children":o,"data-state":f?"expanded":"collapsed",role:"treeitem","aria-labelledby":A,"aria-expanded":o?f:void 0,"aria-level":b,"aria-posinset":x,"aria-setsize":P,"aria-selected":j,"aria-disabled":a||void 0,tabIndex:M?0:-1,onKeyDown:n=>{i?.(n),!n.defaultPrevented&&C(n)},onClick:n=>{c?.(n),!n.defaultPrevented&&n.target.closest(_)===n.currentTarget&&L()},onFocus:n=>{u?.(n),n.target===n.currentTarget&&y(t)},style:{"--tree-guide-left":`calc(var(--tree-indent) * ${b-2} + 0.6875rem)`,"--tree-elbow-run":"calc(var(--tree-indent) - 0.6875rem)","--tree-elbow-radius":"0.5rem",...m},className:k.cn("relative outline-none","focus-visible:[&>[data-slot=tree-item-label]]:border-ring focus-visible:[&>[data-slot=tree-item-label]]:shadow-focus",e),children:r})})}const ae=le.cva("flex w-full min-w-0 cursor-default items-center gap-1.5 rounded-md pr-2 text-left transition-colors select-none",{variants:{size:{sm:"h-6 text-xs",default:"h-7 text-sm",lg:"h-9 text-sm"}},defaultVariants:{size:"default"}});function je({className:e,children:r,size:t,style:o,icon:a,trailing:c,...u}){const{labelId:i,level:m,expanded:p,hasChildren:T,selected:h,disabled:v,trunkLevels:D,toggle:R}=Y("TreeItemLabel"),{guides:y}=re("TreeItemLabel"),E=s.useContext(te),C=y!=="none"&&m>1&&T,b=y!=="none"&&(C||D.length>0),x=s.useRef(null),[P,w]=s.useState(!1),A=f=>{const j=x.current;w(f&&!!j&&j.scrollWidth>j.clientWidth)};return l.jsxs("div",{...u,id:i,"data-slot":"tree-item-label",style:{paddingInlineStart:`calc(var(--tree-indent) * ${m-1} + 0.25rem)`,...o},className:k.cn(ae({size:t}),"relative border border-transparent",h?"bg-accent text-accent-foreground font-medium":"hover:bg-muted",v&&"pointer-events-none opacity-50",e),children:[b?l.jsxs("span",{"data-slot":"tree-item-guides","aria-hidden":"true",className:k.cn("pointer-events-none absolute inset-0",y==="hover"&&"opacity-0 transition-opacity group-hover/tree:opacity-100 motion-reduce:transition-none"),children:[D.map(f=>l.jsx("span",{"data-slot":"tree-item-guide-trunk",style:{left:`calc(var(--tree-indent) * ${f-1} + 0.6875rem)`},className:"absolute top-[-0.4375rem] bottom-0 w-0 border-l border-[var(--tree-guide-color)]"},f)),C?l.jsx("span",{"data-slot":"tree-item-guide-elbow",className:k.cn("absolute top-[-0.4375rem] left-[var(--tree-guide-left)] border-[var(--tree-guide-color)]","h-[calc(50%+0.4375rem)] w-[var(--tree-elbow-run)] border-b border-l","rounded-bl-[var(--tree-elbow-radius)]")}):null]}):null,T?l.jsx("span",{"data-slot":"tree-item-indicator","aria-hidden":"true",onClick:f=>{f.stopPropagation(),R()},className:"flex size-3.5 shrink-0 items-center justify-center text-muted-foreground",children:l.jsx(ie.ChevronRightIcon,{className:k.cn("size-3.5 transition-transform",p&&"rotate-90")})}):l.jsx("span",{"data-slot":"tree-item-indicator-spacer","aria-hidden":"true",className:"size-3.5 shrink-0"}),a?l.jsx("span",{"data-slot":"tree-item-icon","aria-hidden":"true",className:k.cn("flex size-4 shrink-0 items-center justify-center [&_svg]:size-4 [&_svg]:shrink-0",h?"text-accent-foreground":"text-muted-foreground"),children:a}):null,l.jsxs(H.Tooltip,{open:P,onOpenChange:A,children:[l.jsx(H.TooltipTrigger,{asChild:!0,children:l.jsx("span",{ref:x,"data-slot":"tree-item-text",className:"-mx-1 min-w-0 flex-1 truncate px-1",children:l.jsx(ke,{match:E,children:r})})}),l.jsx(H.TooltipContent,{children:r})]}),c?l.jsx("span",{"data-slot":"tree-item-trailing",className:"ml-auto flex shrink-0 items-center gap-1 [&_svg]:size-3.5",children:c}):null]})}function ke({match:e,children:r}){if(!e||typeof r!="string"||!r.toLowerCase().startsWith(e.query))return r;const{query:t,fading:o}=e;return l.jsxs(l.Fragment,{children:[l.jsx("span",{"data-slot":"tree-item-typeahead-match","data-state":o?"fading":"active",className:k.cn("rounded-sm ring-1","-mx-0.5 px-0.5","transition-[color,background-color,box-shadow] duration-700 ease-out motion-reduce:transition-none",o?"bg-transparent text-inherit ring-transparent":"bg-selected text-selected-foreground ring-selected-border"),children:r.slice(0,t.length)}),r.slice(t.length)]})}function Re({className:e,children:r,...t}){const{expanded:o,level:a}=Y("TreeItemGroup");return o?l.jsx(W.Provider,{value:a+1,children:l.jsx("div",{...t,"data-slot":"tree-item-group",role:"group",className:k.cn("flex flex-col",e),children:l.jsx(oe,{children:r})})}):null}exports.Tree=Ee;exports.TreeItem=we;exports.TreeItemGroup=Re;exports.TreeItemLabel=je;exports.treeItemLabelVariants=ae;exports.useTreeItem=fe;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),Q=require("@radix-ui/react-use-controllable-state"),ue=require("class-variance-authority"),de=require("lucide-react"),fe=require("react"),H=require("./tooltip.cjs"),T=require("../lib/utils.cjs");function me(e){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const a=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,a.get?a:{enumerable:!0,get:()=>e[t]})}}return r.default=e,Object.freeze(r)}const s=me(fe),re=s.createContext(null),ne=s.createContext(null);function se(e){const r=s.useContext(re);if(!r)throw new Error(`\`${e}\` must be rendered inside a \`Tree\`.`);return r}const B=s.createContext(1),ae=s.createContext({posinset:1,setsize:1,lastBranchPos:0}),U=s.createContext(null),pe=[];function Y(e){const r=s.useContext(U);if(!r)throw new Error(`\`${e}\` must be rendered inside a \`TreeItem\`.`);return r}function xe(){return Y("useTreeItem")}function Z(e){return e.type===ie||e.type===ce}function ge(e){return s.useMemo(()=>{const r=s.Children.toArray(e),t=r.filter(i=>s.isValidElement(i)&&!Z(i)),a=t.length,o=i=>i.props?.hasChildren===!0,c=t.reduce((i,f,p)=>o(f)?p+1:i,0);let u=0;return r.map((i,f)=>!s.isValidElement(i)||Z(i)?i:(u+=1,l.jsx(ae.Provider,{value:{posinset:u,setsize:a,lastBranchPos:c},children:i},i.key??f)))},[e])}const A='[role="treeitem"][data-tree-item-id]';function S(e){return e?[...e.querySelectorAll(A)]:[]}const he='[role="group"], [role="tree"]';function W(e,r){return S(e).find(t=>t.dataset.treeItemId===r)}function ee(e){return e.parentElement?.closest(he)??null}function be(e){const r=[];for(let t=e.parentElement?.closest(A);t;)t.dataset.treeItemId&&r.unshift(t.dataset.treeItemId),t=t.parentElement?.closest(A);return r}function oe(e){if(e.nodeType===Node.TEXT_NODE)return e.textContent??"";if(!(e instanceof HTMLElement)||e.getAttribute("aria-hidden")==="true")return"";let r="";for(const t of e.childNodes)r+=oe(t);return r}function Ie(e){const r=e.getAttribute("aria-labelledby"),t=r?e.ownerDocument.getElementById(r):null;return(t?oe(t):"").trim().toLowerCase()}function Te(e,r,t){const a=W(e,r);if(a)return a;for(let o=t.length-1;o>=0;o-=1){const c=W(e,t[o]);if(c)return c}return S(e)[0]}function ve(e,r){const t=e?.dataset.treeItemId;!e||!t||(r(t),e.focus())}const ye=600,Ce=800;function O({event:e,setFocusedId:r},t){e.preventDefault(),ve(t,r)}function te(e,r){const t=S(e.root);O(e,t[t.indexOf(e.current)+r])}const je={ArrowDown:e=>te(e,1),ArrowUp:e=>te(e,-1),ArrowRight:e=>{const{event:r,current:t,id:a,hasChildren:o,expanded:c,setExpanded:u}=e;if(o&&!c){r.preventDefault(),u(a,!0);return}c&&O(e,t.querySelector(A))},ArrowLeft:e=>{const{event:r,current:t,id:a,expanded:o,setExpanded:c}=e;if(o){r.preventDefault(),c(a,!1);return}O(e,t.parentElement?.closest(A))},Home:e=>O(e,S(e.root)[0]),End:e=>{const r=S(e.root);O(e,r[r.length-1])},Enter:e=>{e.disabled||(e.event.preventDefault(),e.activate(e.id,e.hasChildren,e.expanded))},"*":e=>{const{event:r,root:t,current:a,expandIds:o}=e;r.preventDefault();const c=ee(a)??t,u=S(c).filter(i=>ee(i)===c).filter(i=>i.dataset.treeHasChildren==="true"&&i.getAttribute("aria-expanded")!=="true").map(i=>i.dataset.treeItemId).filter(i=>!!i);u.length&&o(u)}};function we(e){return e.key.length===1&&e.key!==" "}function Ee(e){const{event:r,root:t,current:a,typeahead:o,setTypeaheadMatch:c}=e;r.preventDefault(),clearTimeout(o.timer),clearTimeout(o.fadeTimer),o.buffer+=r.key.toLowerCase();const{buffer:u}=o,f=u.length>1&&[...u].every(h=>h===u[0])?u[0]:u;c({query:f,fading:!1}),o.timer=setTimeout(()=>{o.buffer="",c({query:f,fading:!0}),o.fadeTimer=setTimeout(()=>c(null),Ce)},ye);const p=S(t),v=p.indexOf(a);for(let h=1;h<=p.length;h+=1){const y=p[(v+h)%p.length];if(Ie(y).startsWith(f)){O(e,y);return}}}function ke({className:e,children:r,expandedIds:t,defaultExpandedIds:a,onExpandedChange:o,selectedId:c,defaultSelectedId:u=null,onSelectedChange:i,onActivate:f,expandOnSelect:p=!0,guides:v="hover",onFocus:h,onBlur:y,...P}){const N=s.useRef(null),[C,w]=Q.useControllableState({prop:t,defaultProp:a??new Set,onChange:o}),[j,b]=Q.useControllableState({prop:c,defaultProp:u,onChange:n=>{n!=null&&i?.(n)}}),[x,_]=s.useState(null),[E,L]=s.useState(null),[m,k]=s.useState(null),q=s.useRef([]),D=s.useRef(!1),F=s.useRef({buffer:"",timer:void 0,fadeTimer:void 0});s.useEffect(()=>()=>{clearTimeout(F.current.timer),clearTimeout(F.current.fadeTimer)},[]);const R=s.useCallback((n,g)=>{w(d=>{const I=new Set(d);return g?I.add(n):I.delete(n),I})},[w]),z=s.useCallback(n=>{w(g=>{const d=new Set(g);for(const I of n)d.add(I);return d})},[w]),K=s.useCallback((n,g,d)=>{b(n),p&&g&&R(n,!d),f?.(n)},[b,p,R,f]),M=s.useCallback(n=>{const g=N.current,d=n.target?.closest(A),I=d?.dataset.treeItemId;if(!g||!d||!I||!g.contains(d)||d!==n.currentTarget||n.ctrlKey||n.metaKey||n.altKey)return;const G=je[n.key]??(we(n)?Ee:void 0);G&&G({event:n,root:g,current:d,id:I,hasChildren:d.dataset.treeHasChildren==="true",expanded:d.getAttribute("aria-expanded")==="true",disabled:d.getAttribute("aria-disabled")==="true",setExpanded:R,expandIds:z,setFocusedId:_,activate:K,typeahead:F.current,setTypeaheadMatch:k})},[R,z,K]),$=s.useCallback(()=>{const n=N.current;if(!n)return;if(x==null){const J=j!=null&&!W(n,j)?S(n)[0]?.dataset.treeItemId??null:null;J!==E&&L(J);return}const g=Te(n,x,q.current),d=g?.dataset.treeItemId;if(!g||!d)return;d===x?q.current=be(g):_(d);const I=n.ownerDocument.activeElement;D.current&&(!n.contains(I)||I===n)&&g.focus()},[x,j,E]);s.useLayoutEffect($);const V=s.useMemo(()=>({expandedIds:C??new Set,setExpanded:R,expandIds:z,selectedId:j??null,activateItem:K,focusedId:x,setFocusedId:_,entryId:E,expandOnSelect:p,guides:v,onItemKeyDown:M}),[C,R,z,j,K,x,E,p,v,M]);return l.jsx(re.Provider,{value:V,children:l.jsx(ne.Provider,{value:m,children:l.jsx(B.Provider,{value:1,children:l.jsx("div",{ref:N,"data-slot":"tree","data-guides":v,role:"tree",tabIndex:-1,onFocus:n=>{h?.(n),D.current=!0},onBlur:n=>{y?.(n),n.currentTarget.contains(n.relatedTarget)||(D.current=!1)},className:T.cn("group/tree text-foreground flex w-full flex-col text-sm","[--tree-indent:1.25rem] [--tree-guide-color:color-mix(in_oklch,var(--muted-foreground)_40%,var(--background))]",e),...P,children:l.jsx(H.TooltipProvider,{delayDuration:500,children:l.jsx(le,{children:r})})})})})})}function le({children:e}){return ge(e)}function Ne({className:e,children:r,id:t,hasChildren:a=!1,disabled:o=!1,onClick:c,onFocus:u,onKeyDown:i,style:f,...p}){const{expandedIds:v,setExpanded:h,selectedId:y,activateItem:P,focusedId:N,setFocusedId:C,entryId:w,onItemKeyDown:j}=se("TreeItem"),b=s.useContext(B),{posinset:x,setsize:_,lastBranchPos:E}=s.useContext(ae),L=`${s.useId()}-label`,m=a&&v.has(t),k=y===t,q=s.useCallback(()=>{a&&h(t,!m)},[a,h,t,m]),D=s.useCallback(()=>{o||(C(t),P(t,a,m))},[o,C,t,P,a,m]),F=b===1&&x===1,R=y==null?F:y===t,z=N?N===t:w?w===t:R,M=s.useContext(U)?.trunkLevels??pe,$=s.useMemo(()=>b>1&&x<E?[...M,b-1]:M,[M,b,x,E]),V=s.useMemo(()=>({id:t,labelId:L,level:b,expanded:m,hasChildren:a,selected:k,disabled:o,trunkLevels:$,toggle:q,select:D}),[t,L,b,m,a,k,o,$,q,D]);return l.jsx(U.Provider,{value:V,children:l.jsx("div",{...p,"data-slot":"tree-item","data-tree-item-id":t,"data-tree-has-children":a,"data-state":m?"expanded":"collapsed",role:"treeitem","aria-labelledby":L,"aria-expanded":a?m:void 0,"aria-level":b,"aria-posinset":x,"aria-setsize":_,"aria-selected":k,"aria-disabled":o||void 0,tabIndex:z?0:-1,onKeyDown:n=>{i?.(n),!n.defaultPrevented&&j(n)},onClick:n=>{c?.(n),!n.defaultPrevented&&n.target.closest(A)===n.currentTarget&&D()},onFocus:n=>{u?.(n),n.target===n.currentTarget&&C(t)},style:{"--tree-guide-left":`calc(var(--tree-indent) * ${b-2} + 0.6875rem)`,"--tree-elbow-run":"calc(var(--tree-indent) - 0.6875rem)","--tree-elbow-radius":"0.5rem",...f},className:T.cn("relative outline-none","focus-visible:[&>[data-slot=tree-item-label]]:border-ring focus-visible:[&>[data-slot=tree-item-label]]:shadow-focus",e),children:r})})}const X=ue.cva("flex w-full min-w-0 cursor-default items-center gap-1.5 rounded-md pr-2 text-left transition-colors select-none",{variants:{size:{sm:"h-6 text-xs",default:"h-7 text-sm",lg:"h-9 text-sm"}},defaultVariants:{size:"default"}});function Re({className:e,children:r,size:t,style:a,icon:o,trailing:c,...u}){const{labelId:i,level:f,expanded:p,hasChildren:v,selected:h,disabled:y,trunkLevels:P,toggle:N}=Y("TreeItemLabel"),{guides:C}=se("TreeItemLabel"),w=s.useContext(ne),j=C!=="none"&&f>1&&v,b=C!=="none"&&(j||P.length>0),x=s.useRef(null),[_,E]=s.useState(!1),L=m=>{const k=x.current;E(m&&!!k&&k.scrollWidth>k.clientWidth)};return l.jsxs("div",{...u,id:i,"data-slot":"tree-item-label",style:{paddingInlineStart:`calc(var(--tree-indent) * ${f-1} + 0.25rem)`,...a},className:T.cn(X({size:t}),"relative border border-transparent",h?"bg-accent text-accent-foreground font-medium":"hover:bg-muted",y&&"pointer-events-none opacity-50",e),children:[b?l.jsxs("span",{"data-slot":"tree-item-guides","aria-hidden":"true",className:T.cn("pointer-events-none absolute inset-0",C==="hover"&&"opacity-0 transition-opacity group-hover/tree:opacity-100 motion-reduce:transition-none"),children:[P.map(m=>l.jsx("span",{"data-slot":"tree-item-guide-trunk",style:{left:`calc(var(--tree-indent) * ${m-1} + 0.6875rem)`},className:"absolute top-[-0.4375rem] bottom-0 w-0 border-l border-[var(--tree-guide-color)]"},m)),j?l.jsx("span",{"data-slot":"tree-item-guide-elbow",className:T.cn("absolute top-[-0.4375rem] left-[var(--tree-guide-left)] border-[var(--tree-guide-color)]","h-[calc(50%+0.4375rem)] w-[var(--tree-elbow-run)] border-b border-l","rounded-bl-[var(--tree-elbow-radius)]")}):null]}):null,v?l.jsx("span",{"data-slot":"tree-item-indicator","aria-hidden":"true",onClick:m=>{m.stopPropagation(),N()},className:"flex size-3.5 shrink-0 items-center justify-center text-muted-foreground",children:l.jsx(de.ChevronRightIcon,{className:T.cn("size-3.5 transition-transform",p&&"rotate-90")})}):l.jsx("span",{"data-slot":"tree-item-indicator-spacer","aria-hidden":"true",className:"size-3.5 shrink-0"}),o?l.jsx("span",{"data-slot":"tree-item-icon","aria-hidden":"true",className:T.cn("flex size-4 shrink-0 items-center justify-center [&_svg]:size-4 [&_svg]:shrink-0",h?"text-accent-foreground":"text-muted-foreground"),children:o}):null,l.jsxs(H.Tooltip,{open:_,onOpenChange:L,children:[l.jsx(H.TooltipTrigger,{asChild:!0,children:l.jsx("span",{ref:x,"data-slot":"tree-item-text",className:"-mx-1 min-w-0 flex-1 truncate px-1",children:l.jsx(Se,{match:w,children:r})})}),l.jsx(H.TooltipContent,{children:r})]}),c?l.jsx("span",{"data-slot":"tree-item-trailing",className:"ml-auto flex shrink-0 items-center gap-1 [&_svg]:size-3.5",children:c}):null]})}function Se({match:e,children:r}){if(!e||typeof r!="string"||!r.toLowerCase().startsWith(e.query))return r;const{query:t,fading:a}=e;return l.jsxs(l.Fragment,{children:[l.jsx("span",{"data-slot":"tree-item-typeahead-match","data-state":a?"fading":"active",className:T.cn("rounded-sm ring-1","-mx-0.5 px-0.5","transition-[color,background-color,box-shadow] duration-700 ease-out motion-reduce:transition-none",a?"bg-transparent text-inherit ring-transparent":"bg-selected text-selected-foreground ring-selected-border"),children:r.slice(0,t.length)}),r.slice(t.length)]})}function Pe({className:e,children:r,...t}){const{expanded:a,level:o}=Y("TreeItemGroup");return a?l.jsx(B.Provider,{value:o+1,children:l.jsx("div",{...t,"data-slot":"tree-item-group",role:"group",className:T.cn("flex flex-col",e),children:l.jsx(le,{children:r})})}):null}function ie({className:e,children:r,style:t,...a}){const o=s.useContext(B);return l.jsxs("div",{...a,"data-slot":"tree-empty",role:"treeitem","aria-selected":"false",tabIndex:-1,style:{paddingInlineStart:`calc(var(--tree-indent) * ${o-1} + 0.25rem)`,...t},className:T.cn("text-muted-foreground flex h-7 w-full min-w-0 items-center gap-1.5 rounded-md border border-transparent pr-2 text-left text-sm [&_svg]:size-4 [&_svg]:shrink-0",e),children:[l.jsx("span",{"data-slot":"tree-item-indicator-spacer","aria-hidden":"true",className:"size-3.5 shrink-0"}),r]})}function ce({className:e,children:r="Load more",icon:t,size:a,style:o,onClick:c,...u}){const i=s.useContext(B);return l.jsx("div",{"data-slot":"tree-load-more",role:"treeitem","aria-selected":"false",className:"flex w-full",children:l.jsxs("button",{...u,type:"button",onClick:f=>{f.stopPropagation(),c?.(f)},style:{paddingInlineStart:`calc(var(--tree-indent) * ${i-1} + 0.25rem)`,...o},className:T.cn(X({size:a}),"text-muted-foreground border border-transparent outline-none","hover:bg-muted hover:text-foreground","focus-visible:border-ring focus-visible:shadow-focus","active:bg-accent active:text-accent-foreground",e),children:[l.jsx("span",{"data-slot":"tree-item-indicator-spacer","aria-hidden":"true",className:"size-3.5 shrink-0"}),t?l.jsx("span",{"data-slot":"tree-item-icon","aria-hidden":"true",className:"flex size-4 shrink-0 items-center justify-center [&_svg]:size-4 [&_svg]:shrink-0",children:t}):null,l.jsx("span",{className:"min-w-0 flex-1 truncate",children:r})]})})}exports.Tree=ke;exports.TreeEmpty=ie;exports.TreeItem=Ne;exports.TreeItemGroup=Pe;exports.TreeItemLabel=Re;exports.TreeLoadMore=ce;exports.treeItemLabelVariants=X;exports.useTreeItem=xe;
2
2
  //# sourceMappingURL=tree.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"tree.cjs","sources":["../../src/components/ui/tree.tsx"],"sourcesContent":["import { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { ChevronRightIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"./tooltip\";\n\nimport { cn } from \"@/lib/utils\";\n\n/* -------------------------------------------------------------------------------------------------\n * Contexts\n *\n * The tree is intentionally headless about *data*: it never fetches, never owns a node array, and\n * derives every ARIA attribute from where a `TreeItem` sits in the React tree. Four contexts carry\n * that positional information down:\n *\n * TreeContext — per-tree state (expansion, selection, roving focus) and the key handler\n * TreeLevelContext — the current depth; `Tree` seeds 1, each `TreeItemGroup` increments\n * TreeIndexContext — `aria-posinset` / `aria-setsize`, injected by whichever container renders\n * the item (`Tree` for roots, `TreeItemGroup` for children)\n * TreeItemContext — the nearest enclosing item, read by `TreeItemLabel` / `TreeItemGroup`\n * -----------------------------------------------------------------------------------------------*/\n\ntype TreeContextValue = {\n expandedIds: Set<string>;\n setExpanded: (id: string, expanded: boolean) => void;\n /** Expands several nodes in one state update — what `*` needs for a whole sibling set. */\n expandIds: (ids: string[]) => void;\n selectedId: string | null;\n /**\n * The one activation path: selection, optional expansion and `onActivate`, shared by `Enter` and\n * by clicking a node so the two never diverge.\n */\n activateItem: (id: string, hasChildren: boolean, expanded: boolean) => void;\n focusedId: string | null;\n setFocusedId: (id: string) => void;\n /**\n * Where `Tab` enters the tree before any node has been focused, when the default (the selected\n * node, else the first root) is not currently rendered. `null` means the default stands.\n */\n entryId: string | null;\n expandOnSelect: boolean;\n guides: TreeGuides;\n /** Attached to each `TreeItem` rather than to the tree root, so the node is its own key target. */\n onItemKeyDown: (event: React.KeyboardEvent<HTMLElement>) => void;\n};\n\nconst TreeContext = React.createContext<TreeContextValue | null>(null);\n\n/**\n * The typeahead highlight to show: the lower-cased query, and whether the buffer has lapsed and the\n * highlight is fading out. `null` once the fade has finished. Its own context, apart from\n * `TreeContext`, so a keystroke (and the two timer-driven fade updates after it) re-renders only the\n * labels that draw the highlight, not every `TreeItem` with its ARIA wiring.\n */\nconst TreeTypeaheadContext = React.createContext<TypeaheadMatch | null>(null);\n\nfunction useTreeContext(component: string) {\n const context = React.useContext(TreeContext);\n if (!context) {\n throw new Error(`\\`${component}\\` must be rendered inside a \\`Tree\\`.`);\n }\n return context;\n}\n\nconst TreeLevelContext = React.createContext(1);\n\ntype TreeIndexContextValue = {\n posinset: number;\n setsize: number;\n /**\n * Position of the last sibling that is itself a branch, or 0 if none are. Connectors only join a\n * folder to its subfolders, so this is where the trunk has to stop — running it to the last child\n * would leave it dangling past any trailing leaf rows.\n */\n lastBranchPos: number;\n};\n\nconst TreeIndexContext = React.createContext<TreeIndexContextValue>({\n posinset: 1,\n setsize: 1,\n lastBranchPos: 0,\n});\n\ntype TreeItemContextValue = {\n id: string;\n labelId: string;\n level: number;\n expanded: boolean;\n hasChildren: boolean;\n selected: boolean;\n disabled: boolean;\n /**\n * Parent levels whose trunk passes through this row. The row draws one vertical segment per\n * entry, so a trunk survives crossing an expanded branch's descendant rows.\n */\n trunkLevels: readonly number[];\n toggle: () => void;\n select: () => void;\n};\n\nconst TreeItemContext = React.createContext<TreeItemContextValue | null>(null);\n\n/** Stable empty set, so inheriting \"no trunks\" doesn't remake the item context every render. */\nconst NO_TRUNKS: readonly number[] = [];\n\nfunction useTreeItemContext(component: string) {\n const context = React.useContext(TreeItemContext);\n if (!context) {\n throw new Error(`\\`${component}\\` must be rendered inside a \\`TreeItem\\`.`);\n }\n return context;\n}\n\n/**\n * Reads the item's position among its siblings and whether it is currently expanded. Exposed for\n * consumers composing their own row content (badges, action buttons, counts) inside a `TreeItem`.\n */\nfunction useTreeItem() {\n return useTreeItemContext(\"useTreeItem\");\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Sibling indexing\n *\n * `aria-setsize` / `aria-posinset` need sibling counts, which only the container knows. Rather than\n * a mount-order registry (two render passes, StrictMode-sensitive, wrong under conditional\n * rendering) each container walks its own children and wraps them in an index provider. Purely\n * positional, so it is correct on the first render and under SSR.\n *\n * Caveat: every valid element child occupies a set slot, so non-item children of a group (a \"Load\n * more\" control, for instance) would be counted. That placement question is deliberately deferred\n * to SW-2542.\n * -----------------------------------------------------------------------------------------------*/\n\nfunction useIndexedTreeChildren(children: React.ReactNode) {\n return React.useMemo(() => {\n const array = React.Children.toArray(children);\n const elements = array.filter(React.isValidElement);\n const setsize = elements.length;\n\n // Which siblings are branches is read off `hasChildren` in the element's own props. A child\n // wrapped in a consumer's own component reads as a leaf, which costs a connector rather than\n // breaking anything — the alternative is a mount-order registry, and the whole point of doing\n // this positionally is to stay correct on the first render.\n const isBranch = (child: React.ReactElement) => (child.props as TreeItemProps)?.hasChildren === true;\n const lastBranchPos = elements.reduce((last, child, index) => (isBranch(child) ? index + 1 : last), 0);\n\n let posinset = 0;\n\n return array.map((child, index) => {\n if (!React.isValidElement(child)) return child;\n posinset += 1;\n return (\n <TreeIndexContext.Provider key={child.key ?? index} value={{ posinset, setsize, lastBranchPos }}>\n {child}\n </TreeIndexContext.Provider>\n );\n });\n }, [children]);\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Keyboard navigation\n *\n * Visible-node order is read from the DOM instead of a JS registry: collapsed groups are not\n * rendered at all, so `querySelectorAll('[role=\"treeitem\"]')` in document order *is* the visible\n * node sequence, and ancestor/descendant lookups are one `closest()` call. This keeps the traversal\n * correct for arbitrary consumer markup between the levels.\n * -----------------------------------------------------------------------------------------------*/\n\nconst ITEM_SELECTOR = '[role=\"treeitem\"]';\n\nfunction getVisibleItems(root: HTMLElement | null) {\n if (!root) return [];\n return [...root.querySelectorAll<HTMLElement>(ITEM_SELECTOR)];\n}\n\nconst CONTAINER_SELECTOR = '[role=\"group\"], [role=\"tree\"]';\n\nfunction findItem(root: HTMLElement, id: string) {\n return getVisibleItems(root).find((element) => element.dataset.treeItemId === id);\n}\n\n/** The `role=\"group\"` (or the tree itself) that directly contains `item`. */\nfunction getContainer(item: HTMLElement) {\n return item.parentElement?.closest<HTMLElement>(CONTAINER_SELECTOR) ?? null;\n}\n\n/** Ids of every treeitem enclosing `item`, outermost first — the trail focus retreats along. */\nfunction getAncestorIds(item: HTMLElement) {\n const ids: string[] = [];\n for (let ancestor = item.parentElement?.closest<HTMLElement>(ITEM_SELECTOR); ancestor; ) {\n if (ancestor.dataset.treeItemId) ids.unshift(ancestor.dataset.treeItemId);\n ancestor = ancestor.parentElement?.closest<HTMLElement>(ITEM_SELECTOR);\n }\n return ids;\n}\n\n/** Text content with `aria-hidden` subtrees left out — the part of a label a screen reader reads. */\nfunction getAnnouncedText(node: Node): string {\n if (node.nodeType === Node.TEXT_NODE) return node.textContent ?? \"\";\n if (!(node instanceof HTMLElement) || node.getAttribute(\"aria-hidden\") === \"true\") return \"\";\n let text = \"\";\n for (const child of node.childNodes) text += getAnnouncedText(child);\n return text;\n}\n\n/**\n * The text typeahead matches against: the node's label, resolved through `aria-labelledby` and\n * with hidden descendants dropped, so it is what a screen reader announces — a `trailing` count\n * badge joins in, an `aria-hidden` spinner or icon does not.\n */\nfunction getItemText(item: HTMLElement) {\n const labelId = item.getAttribute(\"aria-labelledby\");\n const label = labelId ? item.ownerDocument.getElementById(labelId) : null;\n return (label ? getAnnouncedText(label) : \"\").trim().toLowerCase();\n}\n\n/**\n * Where the tab stop belongs once `focusedId` may have left the DOM: the node itself if it is still\n * rendered, else its nearest surviving ancestor (collapsing a branch lands on the branch, as the\n * WAI-ARIA pattern asks), else the first visible node.\n */\nfunction resolveFocusTarget(root: HTMLElement, focusedId: string, ancestorIds: readonly string[]) {\n const target = findItem(root, focusedId);\n if (target) return target;\n for (let index = ancestorIds.length - 1; index >= 0; index -= 1) {\n const ancestor = findItem(root, ancestorIds[index]);\n if (ancestor) return ancestor;\n }\n return getVisibleItems(root)[0];\n}\n\nfunction moveFocus(element: HTMLElement | null | undefined, setFocusedId: (id: string) => void) {\n const id = element?.dataset.treeItemId;\n if (!element || !id) return;\n setFocusedId(id);\n element.focus();\n}\n\n/** How long the typeahead buffer keeps accumulating characters before it resets. */\nconst TYPEAHEAD_TIMEOUT_MS = 600;\n/**\n * How long the highlight lingers after the buffer lapses before it is removed. Deliberately past the\n * 700ms CSS transition on the pill, so removal never races the end of its own fade.\n */\nconst TYPEAHEAD_FADE_MS = 800;\n\ntype Timer = ReturnType<typeof setTimeout> | undefined;\ntype TypeaheadState = { buffer: string; timer: Timer; fadeTimer: Timer };\ntype TypeaheadMatch = { query: string; fading: boolean };\n\ntype TreeKeyEvent = {\n event: React.KeyboardEvent<HTMLElement>;\n root: HTMLElement;\n /** The `role=\"treeitem\"` element the key was pressed on. */\n current: HTMLElement;\n id: string;\n hasChildren: boolean;\n expanded: boolean;\n disabled: boolean;\n setExpanded: (id: string, expanded: boolean) => void;\n expandIds: (ids: string[]) => void;\n setFocusedId: (id: string) => void;\n activate: (id: string, hasChildren: boolean, expanded: boolean) => void;\n typeahead: TypeaheadState;\n setTypeaheadMatch: (match: TypeaheadMatch | null) => void;\n};\n\n/** Moves focus to `element`, if there is one, and claims the key press. */\nfunction navigateTo({ event, setFocusedId }: TreeKeyEvent, element: HTMLElement | null | undefined) {\n event.preventDefault();\n moveFocus(element, setFocusedId);\n}\n\nfunction stepBy(context: TreeKeyEvent, offset: number) {\n const items = getVisibleItems(context.root);\n navigateTo(context, items[items.indexOf(context.current) + offset]);\n}\n\n/**\n * `Space` is deliberately unbound: the WAI-ARIA pattern reserves it for multi-select trees, which\n * are out of scope here but should not be precluded.\n */\nconst TREE_KEY_HANDLERS: Record<string, (context: TreeKeyEvent) => void> = {\n ArrowDown: (context) => stepBy(context, 1),\n ArrowUp: (context) => stepBy(context, -1),\n ArrowRight: (context) => {\n const { event, current, id, hasChildren, expanded, setExpanded } = context;\n if (hasChildren && !expanded) {\n event.preventDefault();\n setExpanded(id, true);\n return;\n }\n if (expanded) navigateTo(context, current.querySelector<HTMLElement>(ITEM_SELECTOR));\n },\n ArrowLeft: (context) => {\n const { event, current, id, expanded, setExpanded } = context;\n if (expanded) {\n event.preventDefault();\n setExpanded(id, false);\n return;\n }\n navigateTo(context, current.parentElement?.closest<HTMLElement>(ITEM_SELECTOR));\n },\n Home: (context) => navigateTo(context, getVisibleItems(context.root)[0]),\n End: (context) => {\n const items = getVisibleItems(context.root);\n navigateTo(context, items[items.length - 1]);\n },\n Enter: (context) => {\n if (context.disabled) return;\n context.event.preventDefault();\n context.activate(context.id, context.hasChildren, context.expanded);\n },\n /** Expands every collapsed branch among the focused node's siblings, the node itself included. */\n \"*\": (context) => {\n const { event, root, current, expandIds } = context;\n event.preventDefault();\n const container = getContainer(current) ?? root;\n const ids = getVisibleItems(container)\n .filter((item) => getContainer(item) === container)\n .filter((item) => item.dataset.treeHasChildren === \"true\" && item.getAttribute(\"aria-expanded\") !== \"true\")\n .map((item) => item.dataset.treeItemId)\n .filter((id): id is string => Boolean(id));\n if (ids.length) expandIds(ids);\n },\n};\n\n/** A printable character: what feeds the typeahead buffer. (Modifiers are screened at dispatch.) */\nfunction isTypeaheadKey(event: React.KeyboardEvent) {\n return event.key.length === 1 && event.key !== \" \";\n}\n\n/**\n * Focuses the next visible node whose label starts with the characters typed so far. The buffer\n * resets after a pause; repeating one character cycles through the nodes starting with it instead\n * of looking for a label that begins with `\"ss\"`.\n */\nfunction typeaheadTo(context: TreeKeyEvent) {\n const { event, root, current, typeahead, setTypeaheadMatch } = context;\n // Claimed whether or not anything matches: a letter typed into a tree is never meant for the page.\n event.preventDefault();\n clearTimeout(typeahead.timer);\n clearTimeout(typeahead.fadeTimer);\n typeahead.buffer += event.key.toLowerCase();\n\n const { buffer } = typeahead;\n const isRepeatedChar = buffer.length > 1 && [...buffer].every((char) => char === buffer[0]);\n const query = isRepeatedChar ? buffer[0] : buffer;\n // Published so every matching label can highlight the typed prefix while the buffer is live. When\n // the buffer lapses the highlight is not yanked away: it lingers, fading, so a glance after the\n // last keystroke still shows what was matched.\n setTypeaheadMatch({ query, fading: false });\n typeahead.timer = setTimeout(() => {\n typeahead.buffer = \"\";\n setTypeaheadMatch({ query, fading: true });\n typeahead.fadeTimer = setTimeout(() => setTypeaheadMatch(null), TYPEAHEAD_FADE_MS);\n }, TYPEAHEAD_TIMEOUT_MS);\n\n // Search starts at the node after the current one and wraps, so the current node is only matched\n // as a last resort — that is what makes a repeated letter move on rather than stay put.\n const items = getVisibleItems(root);\n const start = items.indexOf(current);\n for (let offset = 1; offset <= items.length; offset += 1) {\n const candidate = items[(start + offset) % items.length];\n if (getItemText(candidate).startsWith(query)) {\n navigateTo(context, candidate);\n return;\n }\n }\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Tree\n * -----------------------------------------------------------------------------------------------*/\n\ntype TreeGuides = \"none\" | \"hover\" | \"always\";\n\ntype TreeProps = Omit<React.ComponentProps<\"div\">, \"onSelect\"> & {\n /** Expanded node ids (controlled). */\n expandedIds?: Set<string>;\n /** Initially expanded node ids (uncontrolled). */\n defaultExpandedIds?: Set<string>;\n onExpandedChange?: (expandedIds: Set<string>) => void;\n /** Selected node id (controlled). Pass `null` for \"nothing selected\". */\n selectedId?: string | null;\n /** Initially selected node id (uncontrolled). */\n defaultSelectedId?: string | null;\n onSelectedChange?: (selectedId: string) => void;\n /** Fired by `Enter` and by clicking a label — the node's default action. */\n onActivate?: (id: string) => void;\n /** Whether selecting a parent node also toggles its expansion. */\n expandOnSelect?: boolean;\n /**\n * Vertical indent guides joining each level to its parent. `\"hover\"` reveals them while the\n * pointer is anywhere over the tree, which keeps a dense tree quiet at rest but still lets you\n * trace a deep branch; `\"always\"` pins them on; `\"none\"` turns them off.\n */\n guides?: TreeGuides;\n};\n\nfunction Tree({\n className,\n children,\n expandedIds: expandedIdsProp,\n defaultExpandedIds,\n onExpandedChange,\n selectedId: selectedIdProp,\n defaultSelectedId = null,\n onSelectedChange,\n onActivate,\n expandOnSelect = true,\n guides = \"hover\",\n onFocus,\n onBlur,\n ...props\n}: TreeProps) {\n const treeRef = React.useRef<HTMLDivElement>(null);\n\n const [expandedIds, setExpandedIds] = useControllableState<Set<string>>({\n prop: expandedIdsProp,\n defaultProp: defaultExpandedIds ?? new Set<string>(),\n onChange: onExpandedChange,\n });\n const [selectedId, setSelectedId] = useControllableState<string | null>({\n prop: selectedIdProp,\n defaultProp: defaultSelectedId,\n onChange: (id) => {\n if (id != null) onSelectedChange?.(id);\n },\n });\n const [focusedId, setFocusedId] = React.useState<string | null>(null);\n const [entryId, setEntryId] = React.useState<string | null>(null);\n const [typeaheadMatch, setTypeaheadMatch] = React.useState<TypeaheadMatch | null>(null);\n // Ancestor trail of the focused node, captured when it takes focus. If a later render removes the\n // node (an ancestor collapsed, a lazy fetch swapped the subtree) this is how focus knows where to\n // retreat to instead of dropping to `body`.\n const focusedPathRef = React.useRef<string[]>([]);\n // Whether DOM focus is inside the tree. Removing a focused element fires no `blur`, so this stays\n // `true` through a removal — which is exactly the case where focus has to be restored.\n const hasFocusRef = React.useRef(false);\n const typeaheadRef = React.useRef<TypeaheadState>({ buffer: \"\", timer: undefined, fadeTimer: undefined });\n\n React.useEffect(\n () => () => {\n clearTimeout(typeaheadRef.current.timer);\n clearTimeout(typeaheadRef.current.fadeTimer);\n },\n [],\n );\n\n const setExpanded = React.useCallback(\n (id: string, expanded: boolean) => {\n setExpandedIds((current) => {\n const next = new Set(current);\n if (expanded) next.add(id);\n else next.delete(id);\n return next;\n });\n },\n [setExpandedIds],\n );\n\n const expandIds = React.useCallback(\n (ids: string[]) => {\n setExpandedIds((current) => {\n const next = new Set(current);\n for (const id of ids) next.add(id);\n return next;\n });\n },\n [setExpandedIds],\n );\n\n const activateItem = React.useCallback(\n (activatedId: string, hasChildren: boolean, expanded: boolean) => {\n setSelectedId(activatedId);\n if (expandOnSelect && hasChildren) setExpanded(activatedId, !expanded);\n onActivate?.(activatedId);\n },\n [setSelectedId, expandOnSelect, setExpanded, onActivate],\n );\n\n const handleItemKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLElement>) => {\n const root = treeRef.current;\n const current = (event.target as HTMLElement | null)?.closest<HTMLElement>(ITEM_SELECTOR);\n const id = current?.dataset.treeItemId;\n if (!root || !current || !id || !root.contains(current)) return;\n // Every ancestor `TreeItem` sees the bubbled event too; only the node it was pressed on acts\n // on it, or an unclaimed key would be handled once per level of nesting.\n if (current !== event.currentTarget) return;\n\n // A chord with Ctrl, Meta or Alt belongs to the browser or the OS (`Ctrl+ArrowDown`,\n // `Alt+Home`); the tree binds unmodified keys only. Shift is not screened — `*` needs it.\n if (event.ctrlKey || event.metaKey || event.altKey) return;\n const handler = TREE_KEY_HANDLERS[event.key] ?? (isTypeaheadKey(event) ? typeaheadTo : undefined);\n if (!handler) return;\n\n handler({\n event,\n root,\n current,\n id,\n hasChildren: current.dataset.treeHasChildren === \"true\",\n expanded: current.getAttribute(\"aria-expanded\") === \"true\",\n disabled: current.getAttribute(\"aria-disabled\") === \"true\",\n setExpanded,\n expandIds,\n setFocusedId,\n activate: activateItem,\n typeahead: typeaheadRef.current,\n setTypeaheadMatch,\n });\n },\n [setExpanded, expandIds, activateItem],\n );\n\n // Keeps the single tab stop pointing at a node that exists. Runs before paint so no frame is ever\n // committed with zero (or a vanished) `tabindex=\"0\"` node.\n const reconcileTabStop = React.useCallback(() => {\n const root = treeRef.current;\n if (!root) return;\n\n if (focusedId == null) {\n // Before the tree has been entered the tab stop is the selected node — unless it is hidden\n // inside a collapsed branch, in which case the first root node stands in or the tree would\n // have no tab stop at all. Kept apart from `focusedId` so the stand-in lapses the moment the\n // selected node is rendered again.\n const hidden = selectedId != null && !findItem(root, selectedId);\n const next = hidden ? (getVisibleItems(root)[0]?.dataset.treeItemId ?? null) : null;\n if (next !== entryId) setEntryId(next);\n return;\n }\n\n const target = resolveFocusTarget(root, focusedId, focusedPathRef.current);\n const targetId = target?.dataset.treeItemId;\n if (!target || !targetId) return;\n if (targetId === focusedId) focusedPathRef.current = getAncestorIds(target);\n else setFocusedId(targetId);\n\n // Only reclaim DOM focus if the tree had it: a programmatic collapse while the user is typing\n // elsewhere must move the tab stop, not steal focus.\n const active = root.ownerDocument.activeElement;\n if (hasFocusRef.current && (!root.contains(active) || active === root)) target.focus();\n }, [focusedId, selectedId, entryId]);\n\n // Deliberately no dependency list: whether the focused node is still rendered depends on\n // `children`, which any parent render can change, so this has to check after every commit.\n React.useLayoutEffect(reconcileTabStop);\n\n const context = React.useMemo<TreeContextValue>(\n () => ({\n expandedIds: expandedIds ?? new Set<string>(),\n setExpanded,\n expandIds,\n selectedId: selectedId ?? null,\n activateItem,\n focusedId,\n setFocusedId,\n entryId,\n expandOnSelect,\n guides,\n onItemKeyDown: handleItemKeyDown,\n }),\n [\n expandedIds,\n setExpanded,\n expandIds,\n selectedId,\n activateItem,\n focusedId,\n entryId,\n expandOnSelect,\n guides,\n handleItemKeyDown,\n ],\n );\n\n return (\n <TreeContext.Provider value={context}>\n <TreeTypeaheadContext.Provider value={typeaheadMatch}>\n <TreeLevelContext.Provider value={1}>\n <div\n ref={treeRef}\n data-slot=\"tree\"\n data-guides={guides}\n role=\"tree\"\n tabIndex={-1}\n onFocus={(event) => {\n onFocus?.(event);\n hasFocusRef.current = true;\n }}\n onBlur={(event) => {\n onBlur?.(event);\n if (!event.currentTarget.contains(event.relatedTarget)) hasFocusRef.current = false;\n }}\n // `group/tree` is what the `\"hover\"` guide mode hangs off: hovering anywhere in the tree\n // reveals every guide at once, so you can trace a branch without hunting row by row.\n //\n // `--tree-indent` is 1.25rem so that a child's chevron lands exactly on its parent's\n // icon: the icon sits 1.5rem into the content box (chevron 0.875 + gap 0.375 + the\n // 0.25rem lead-in), and the chevron sits at the lead-in, so one step must be\n // 1.5rem - 0.25rem. Indentation, the guide offsets and the elbow reach are all derived\n // from this one value — override it and the connectors follow.\n //\n // `--tree-guide-color` is deliberately *opaque*, via `color-mix`, even though it is meant\n // to look like a 40% tint. Guide segments necessarily overlap — each row's line overshoots\n // into the row above so the two meet across the label's border, and an elbow shares its\n // column with the trunk it branches from. With a semi-transparent colour every overlap\n // composites twice and shows up as a darker stretch of line. Mixing to an opaque value up\n // front makes overlapping draws idempotent, so the tree reads as one uniform hairline.\n className={cn(\n \"group/tree text-foreground flex w-full flex-col text-sm\",\n \"[--tree-indent:1.25rem] [--tree-guide-color:color-mix(in_oklch,var(--muted-foreground)_40%,var(--background))]\",\n className,\n )}\n {...props}\n >\n {/*\n Radix requires a `Tooltip.Provider` above any `Tooltip`, and the labels mount one each\n to reveal truncated text. Providing it here rather than asking consumers to wrap their\n app keeps `Tree` self-contained; nesting inside a consumer's own provider is supported,\n and the longer delay is deliberate — instant tooltips while sweeping the pointer down a\n dense tree are noise.\n */}\n <TooltipProvider delayDuration={500}>\n <TreeItemsContainer>{children}</TreeItemsContainer>\n </TooltipProvider>\n </div>\n </TreeLevelContext.Provider>\n </TreeTypeaheadContext.Provider>\n </TreeContext.Provider>\n );\n}\n\nfunction TreeItemsContainer({ children }: { children: React.ReactNode }) {\n return useIndexedTreeChildren(children);\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TreeItem\n * -----------------------------------------------------------------------------------------------*/\n\ntype TreeItemProps = React.ComponentProps<\"div\"> & {\n id: string;\n /**\n * Whether the node can be expanded. Kept explicit rather than inferred from rendered children so\n * a node whose children have not been fetched yet still reports `aria-expanded=\"false\"`.\n */\n hasChildren?: boolean;\n disabled?: boolean;\n};\n\nfunction TreeItem({\n className,\n children,\n id,\n hasChildren = false,\n disabled = false,\n onClick,\n onFocus,\n onKeyDown,\n style,\n ...props\n}: TreeItemProps) {\n const { expandedIds, setExpanded, selectedId, activateItem, focusedId, setFocusedId, entryId, onItemKeyDown } =\n useTreeContext(\"TreeItem\");\n const level = React.useContext(TreeLevelContext);\n const { posinset, setsize, lastBranchPos } = React.useContext(TreeIndexContext);\n const labelId = `${React.useId()}-label`;\n\n const expanded = hasChildren && expandedIds.has(id);\n const selected = selectedId === id;\n\n const toggle = React.useCallback(() => {\n if (hasChildren) setExpanded(id, !expanded);\n }, [hasChildren, setExpanded, id, expanded]);\n\n // Routed through the tree's `activateItem` so a click and `Enter` are the same code path —\n // notably, both fire `onActivate`.\n const select = React.useCallback(() => {\n if (disabled) return;\n setFocusedId(id);\n activateItem(id, hasChildren, expanded);\n }, [disabled, setFocusedId, id, activateItem, hasChildren, expanded]);\n\n // Roving tabindex: the focused node is the single tab stop. Before the tree has been entered it\n // is the selected node, per the WAI-ARIA pattern, or else the first root node. `Tree`'s layout\n // effect keeps this pointing at a rendered node when the focused or selected one disappears.\n const isFirstRoot = level === 1 && posinset === 1;\n const defaultEntry = selectedId == null ? isFirstRoot : selectedId === id;\n const tabbable = focusedId ? focusedId === id : entryId ? entryId === id : defaultEntry;\n\n // Guides are drawn on the row (see `TreeItemLabel`), so a row has to know every ancestor trunk\n // crossing it, not just its own parent's. The set is threaded down the tree: inherit the parent's\n // and add this row's own parent level when a later sibling folder needs the line to continue past\n // this entire subtree.\n const parentItem = React.useContext(TreeItemContext);\n const inheritedTrunkLevels = parentItem?.trunkLevels ?? NO_TRUNKS;\n const trunkLevels = React.useMemo(\n () => (level > 1 && posinset < lastBranchPos ? [...inheritedTrunkLevels, level - 1] : inheritedTrunkLevels),\n [inheritedTrunkLevels, level, posinset, lastBranchPos],\n );\n\n const itemContext = React.useMemo<TreeItemContextValue>(\n () => ({\n id,\n labelId,\n level,\n expanded,\n hasChildren,\n selected,\n disabled,\n trunkLevels,\n toggle,\n select,\n }),\n [id, labelId, level, expanded, hasChildren, selected, disabled, trunkLevels, toggle, select],\n );\n\n return (\n <TreeItemContext.Provider value={itemContext}>\n <div\n // Spread first, for the same reason as `TreeItemLabel`: every ARIA attribute below is\n // maintained by the tree and must not be overridable from props.\n {...props}\n data-slot=\"tree-item\"\n data-tree-item-id={id}\n data-tree-has-children={hasChildren}\n data-state={expanded ? \"expanded\" : \"collapsed\"}\n role=\"treeitem\"\n // The accessible name comes from the label alone. Without this, name-from-content would\n // sweep in every descendant node's text once a branch is expanded.\n aria-labelledby={labelId}\n aria-expanded={hasChildren ? expanded : undefined}\n aria-level={level}\n aria-posinset={posinset}\n aria-setsize={setsize}\n aria-selected={selected}\n aria-disabled={disabled || undefined}\n tabIndex={tabbable ? 0 : -1}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n onItemKeyDown(event);\n }}\n onClick={(event) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n // Clicks on a descendant node are that node's business — every treeitem in the ancestor\n // chain sees the bubbled event.\n if ((event.target as HTMLElement).closest(ITEM_SELECTOR) !== event.currentTarget) return;\n select();\n }}\n onFocus={(event) => {\n onFocus?.(event);\n if (event.target === event.currentTarget) setFocusedId(id);\n }}\n style={\n {\n // Inherited by the label, which draws the elbow from the same two values.\n \"--tree-guide-left\": `calc(var(--tree-indent) * ${level - 2} + 0.6875rem)`,\n // Stops 0.25rem short of the row's chevron rather than touching it, so the connector\n // reads as pointing at the row instead of welded to the glyph.\n \"--tree-elbow-run\": \"calc(var(--tree-indent) - 0.6875rem)\",\n // Shared by the elbow's corner and by where the same-column trunk picks up, so the two\n // meet exactly instead of overlapping or leaving a gap.\n \"--tree-elbow-radius\": \"0.5rem\",\n ...style,\n } as React.CSSProperties\n }\n className={cn(\n \"relative outline-none\",\n // Direct-child selectors, deliberately not `group-*/tree-item`: tree items nest, and a\n // group variant matches *any* ancestor, so a focused or selected parent painted its focus\n // ring onto every descendant row. Backgrounds live on the label for the same reason —\n // anything painted here would spread behind the whole subtree.\n \"focus-visible:[&>[data-slot=tree-item-label]]:border-ring focus-visible:[&>[data-slot=tree-item-label]]:shadow-focus\",\n className,\n )}\n >\n {children}\n </div>\n </TreeItemContext.Provider>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TreeItemLabel\n * -----------------------------------------------------------------------------------------------*/\n\nconst treeItemLabelVariants = cva(\n \"flex w-full min-w-0 cursor-default items-center gap-1.5 rounded-md pr-2 text-left transition-colors select-none\",\n {\n variants: {\n size: {\n sm: \"h-6 text-xs\",\n default: \"h-7 text-sm\",\n lg: \"h-9 text-sm\",\n },\n },\n defaultVariants: {\n size: \"default\",\n },\n },\n);\n\ntype TreeItemLabelProps = React.ComponentProps<\"div\"> &\n VariantProps<typeof treeItemLabelVariants> & {\n /**\n * Decorative leading icon, rendered between the chevron and the label text. Hidden from\n * assistive tech — the node's accessible name comes from the label text alone, so anything a\n * screen reader must convey belongs in the text, not here. Swap it on expansion (open/closed\n * folders) by reading `expanded` from `useTreeItem()` inside your own icon component.\n */\n icon?: React.ReactNode;\n /**\n * Right-aligned slot for per-node adornments — a count `Badge`, a `Spinner`, a status dot. It\n * sits inside the label, so its text joins the node's accessible name: a count reads as\n * \"Onboarding 3\", which is usually what you want. Wrap it in `aria-hidden` yourself for purely\n * decorative content such as a spinner.\n */\n trailing?: React.ReactNode;\n };\n\nfunction TreeItemLabel({ className, children, size, style, icon, trailing, ...props }: TreeItemLabelProps) {\n const { labelId, level, expanded, hasChildren, selected, disabled, trunkLevels, toggle } =\n useTreeItemContext(\"TreeItemLabel\");\n const { guides } = useTreeContext(\"TreeItemLabel\");\n const typeaheadMatch = React.useContext(TreeTypeaheadContext);\n\n // The elbow lives on the row because the label element *is* the row, so it can be sized in\n // halves of it — the curve has to land on the row's vertical centre. A connector joins a folder\n // to its subfolders, so only a branch row gets one.\n const showElbow = guides !== \"none\" && level > 1 && hasChildren;\n const showGuides = guides !== \"none\" && (showElbow || trunkLevels.length > 0);\n\n const textRef = React.useRef<HTMLSpanElement>(null);\n const [tooltipOpen, setTooltipOpen] = React.useState(false);\n\n // Truncation is measured when the tooltip would open, not tracked continuously: a\n // `ResizeObserver` per row would cost every row in a large tree for a hint almost none of them\n // need, and this answers the same question at the only moment it matters.\n const handleTooltipOpenChange = (next: boolean) => {\n const text = textRef.current;\n setTooltipOpen(next && !!text && text.scrollWidth > text.clientWidth);\n };\n\n return (\n <div\n // Spread first: the derived ARIA wiring below is authoritative. A consumer-supplied `id` would\n // otherwise break the `TreeItem` → `aria-labelledby` link that names the node.\n {...props}\n id={labelId}\n data-slot=\"tree-item-label\"\n // The row is a passive label, not a control: the parent `role=\"treeitem\"` owns focus, click\n // handling, keyboard handling and the accessible name, so a nested control would fight it.\n // `--tree-guide-left` / `--tree-elbow-run` are inherited from the `TreeItem`.\n style={{ paddingInlineStart: `calc(var(--tree-indent) * ${level - 1} + 0.25rem)`, ...style }}\n className={cn(\n treeItemLabelVariants({ size }),\n \"relative border border-transparent\",\n // Only selection paints a background — an open folder is already marked by its rotated\n // chevron, open-folder icon and the connectors running down from it.\n selected ? \"bg-accent text-accent-foreground font-medium\" : \"hover:bg-muted\",\n // From this node's own state, not an ancestor selector: `aria-disabled` is per-node, so a\n // disabled folder must not dim the contents underneath it.\n disabled && \"pointer-events-none opacity-50\",\n className,\n )}\n >\n {showGuides ? (\n // One absolutely-positioned layer owns every guide on this row, fixing two bugs at once.\n //\n // Paint order: the trunk used to be drawn by the `TreeItem`, an *ancestor* of every\n // descendant row. Those rows are positioned and paint an opaque hover/selected background\n // over anything an ancestor drew, so the trunk vanished behind whichever row you pointed\n // at. Drawn here it belongs to the row's own box, so it paints above that row's background\n // — and no sibling row can cover it, because every row draws its own segments.\n //\n // One coordinate system: `left` resolves against the nearest positioned ancestor's\n // *padding* box. The label carries `border border-transparent` for its focus ring while the\n // `TreeItem` carries none, so one `--tree-guide-left` landed 1px apart on the two elements\n // and the elbow/trunk overlap read as a 2px line. Both now share this container.\n <span\n data-slot=\"tree-item-guides\"\n aria-hidden=\"true\"\n className={cn(\n \"pointer-events-none absolute inset-0\",\n // The fade lives on the container, not on each line. Opacity on the parent renders the\n // whole layer into one buffer and composites it once, so a seam between two segments\n // can never double-expose mid-transition.\n guides === \"hover\" &&\n \"opacity-0 transition-opacity group-hover/tree:opacity-100 motion-reduce:transition-none\",\n )}\n >\n {trunkLevels.map((trunkLevel) => (\n <span\n key={trunkLevel}\n data-slot=\"tree-item-guide-trunk\"\n style={{ left: `calc(var(--tree-indent) * ${trunkLevel - 1} + 0.6875rem)` }}\n // Overshoots upward by half a chevron to cross the label's border into the row above,\n // so consecutive rows tile into one unbroken line.\n className=\"absolute top-[-0.4375rem] bottom-0 w-0 border-l border-[var(--tree-guide-color)]\"\n />\n ))}\n {showElbow ? (\n // Down the guide line, then a rounded turn right, stopping just short of this row's\n // chevron. Starts half a chevron above the row so the line emerges from under the\n // parent's chevron instead of leaving a half-row gap.\n <span\n data-slot=\"tree-item-guide-elbow\"\n className={cn(\n \"absolute top-[-0.4375rem] left-[var(--tree-guide-left)] border-[var(--tree-guide-color)]\",\n \"h-[calc(50%+0.4375rem)] w-[var(--tree-elbow-run)] border-b border-l\",\n \"rounded-bl-[var(--tree-elbow-radius)]\",\n )}\n />\n ) : null}\n </span>\n ) : null}\n {hasChildren ? (\n // A pointer-only affordance, deliberately not a `<button>`: expansion is reachable from the\n // keyboard through the parent treeitem's arrow keys, so this stays non-focusable. A focusable\n // element hidden from assistive tech is a contradiction, and inside a single-tab-stop widget\n // it would also be a second focus stop reachable by pointer.\n <span\n data-slot=\"tree-item-indicator\"\n aria-hidden=\"true\"\n onClick={(event) => {\n // Toggle from the chevron alone, without changing the selection.\n event.stopPropagation();\n toggle();\n }}\n className=\"flex size-3.5 shrink-0 items-center justify-center text-muted-foreground\"\n >\n <ChevronRightIcon className={cn(\"size-3.5 transition-transform\", expanded && \"rotate-90\")} />\n </span>\n ) : (\n <span data-slot=\"tree-item-indicator-spacer\" aria-hidden=\"true\" className=\"size-3.5 shrink-0\" />\n )}\n {icon ? (\n <span\n data-slot=\"tree-item-icon\"\n aria-hidden=\"true\"\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center [&_svg]:size-4 [&_svg]:shrink-0\",\n selected ? \"text-accent-foreground\" : \"text-muted-foreground\",\n )}\n >\n {icon}\n </span>\n ) : null}\n <Tooltip open={tooltipOpen} onOpenChange={handleTooltipOpenChange}>\n <TooltipTrigger asChild>\n <span\n ref={textRef}\n data-slot=\"tree-item-text\"\n // `truncate` clips at this span's padding box, so the typeahead pill — 2px of padding plus a\n // 1px ring outside the glyphs — needs room inside it: 4px of padding either side, with the\n // matching negative margin so the text itself does not move.\n className=\"-mx-1 min-w-0 flex-1 truncate px-1\"\n >\n <TreeItemText match={typeaheadMatch}>{children}</TreeItemText>\n </span>\n </TooltipTrigger>\n {/*\n A purely visual repair for clipped text. The trigger is a plain `span`, so it never takes\n focus and this only ever opens on hover — and the node's accessible name already carries\n the label in full, so a screen reader is not relying on it.\n */}\n <TooltipContent>{children}</TooltipContent>\n </Tooltip>\n {trailing ? (\n <span data-slot=\"tree-item-trailing\" className=\"ml-auto flex shrink-0 items-center gap-1 [&_svg]:size-3.5\">\n {trailing}\n </span>\n ) : null}\n </div>\n );\n}\n\n/**\n * The label text, with the live typeahead prefix highlighted when it matches. Only a plain-string\n * label can be split; a composed label still matches for navigation, it just gets no highlight.\n */\nfunction TreeItemText({ match, children }: { match: TypeaheadMatch | null; children: React.ReactNode }) {\n if (!match || typeof children !== \"string\" || !children.toLowerCase().startsWith(match.query)) {\n return children;\n }\n const { query, fading } = match;\n return (\n <>\n <span\n data-slot=\"tree-item-typeahead-match\"\n data-state={fading ? \"fading\" : \"active\"}\n className={cn(\n // The SW-2445 selected-state tokens: a primary tint that reads as \"this is the match\" on\n // a resting, hovered or selected row, in both themes. Plain spans, not `<mark>`, so the\n // label's accessible name is unchanged.\n \"rounded-sm ring-1\",\n // Padding either side so the ring does not hug the glyphs, with a matching negative\n // margin so the rest of the label stays put while the highlight comes and goes.\n \"-mx-0.5 px-0.5\",\n // Eased out over the fade window rather than snapped off; the span itself is removed\n // only once the transition has finished.\n \"transition-[color,background-color,box-shadow] duration-700 ease-out motion-reduce:transition-none\",\n fading\n ? \"bg-transparent text-inherit ring-transparent\"\n : \"bg-selected text-selected-foreground ring-selected-border\",\n )}\n >\n {children.slice(0, query.length)}\n </span>\n {children.slice(query.length)}\n </>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TreeItemGroup\n * -----------------------------------------------------------------------------------------------*/\n\nfunction TreeItemGroup({ className, children, ...props }: React.ComponentProps<\"div\">) {\n const { expanded, level } = useTreeItemContext(\"TreeItemGroup\");\n\n // Not rendered while collapsed: keeps collapsed subtrees out of the accessibility tree entirely,\n // and makes DOM order equal visible order for keyboard traversal.\n if (!expanded) return null;\n\n return (\n <TreeLevelContext.Provider value={level + 1}>\n <div {...props} data-slot=\"tree-item-group\" role=\"group\" className={cn(\"flex flex-col\", className)}>\n <TreeItemsContainer>{children}</TreeItemsContainer>\n </div>\n </TreeLevelContext.Provider>\n );\n}\n\nexport {\n Tree,\n TreeItem,\n TreeItemGroup,\n TreeItemLabel,\n treeItemLabelVariants,\n useTreeItem,\n type TreeGuides,\n type TreeItemLabelProps,\n type TreeItemProps,\n type TreeProps,\n};\n"],"names":["TreeContext","React","TreeTypeaheadContext","useTreeContext","component","context","TreeLevelContext","TreeIndexContext","TreeItemContext","NO_TRUNKS","useTreeItemContext","useTreeItem","useIndexedTreeChildren","children","array","elements","setsize","isBranch","child","lastBranchPos","last","index","posinset","jsx","ITEM_SELECTOR","getVisibleItems","root","CONTAINER_SELECTOR","findItem","id","element","getContainer","item","getAncestorIds","ids","ancestor","getAnnouncedText","node","text","getItemText","labelId","label","resolveFocusTarget","focusedId","ancestorIds","target","moveFocus","setFocusedId","TYPEAHEAD_TIMEOUT_MS","TYPEAHEAD_FADE_MS","navigateTo","event","stepBy","offset","items","TREE_KEY_HANDLERS","current","hasChildren","expanded","setExpanded","expandIds","container","isTypeaheadKey","typeaheadTo","typeahead","setTypeaheadMatch","buffer","query","char","start","candidate","Tree","className","expandedIdsProp","defaultExpandedIds","onExpandedChange","selectedIdProp","defaultSelectedId","onSelectedChange","onActivate","expandOnSelect","guides","onFocus","onBlur","props","treeRef","expandedIds","setExpandedIds","useControllableState","selectedId","setSelectedId","entryId","setEntryId","typeaheadMatch","focusedPathRef","hasFocusRef","typeaheadRef","next","activateItem","activatedId","handleItemKeyDown","handler","reconcileTabStop","targetId","active","cn","TooltipProvider","TreeItemsContainer","TreeItem","disabled","onClick","onKeyDown","style","onItemKeyDown","level","selected","toggle","select","isFirstRoot","defaultEntry","tabbable","inheritedTrunkLevels","trunkLevels","itemContext","treeItemLabelVariants","cva","TreeItemLabel","size","icon","trailing","showElbow","showGuides","textRef","tooltipOpen","setTooltipOpen","handleTooltipOpenChange","jsxs","trunkLevel","ChevronRightIcon","Tooltip","TooltipTrigger","TreeItemText","TooltipContent","match","fading","Fragment","TreeItemGroup"],"mappings":"qlBA+CMA,GAAcC,EAAM,cAAuC,IAAI,EAQ/DC,GAAuBD,EAAM,cAAqC,IAAI,EAE5E,SAASE,GAAeC,EAAmB,CACzC,MAAMC,EAAUJ,EAAM,WAAWD,EAAW,EAC5C,GAAI,CAACK,EACH,MAAM,IAAI,MAAM,KAAKD,CAAS,wCAAwC,EAExE,OAAOC,CACT,CAEA,MAAMC,EAAmBL,EAAM,cAAc,CAAC,EAaxCM,GAAmBN,EAAM,cAAqC,CAClE,SAAU,EACV,QAAS,EACT,cAAe,CACjB,CAAC,EAmBKO,EAAkBP,EAAM,cAA2C,IAAI,EAGvEQ,GAA+B,CAAA,EAErC,SAASC,EAAmBN,EAAmB,CAC7C,MAAMC,EAAUJ,EAAM,WAAWO,CAAe,EAChD,GAAI,CAACH,EACH,MAAM,IAAI,MAAM,KAAKD,CAAS,4CAA4C,EAE5E,OAAOC,CACT,CAMA,SAASM,IAAc,CACrB,OAAOD,EAAmB,aAAa,CACzC,CAeA,SAASE,GAAuBC,EAA2B,CACzD,OAAOZ,EAAM,QAAQ,IAAM,CACzB,MAAMa,EAAQb,EAAM,SAAS,QAAQY,CAAQ,EACvCE,EAAWD,EAAM,OAAOb,EAAM,cAAc,EAC5Ce,EAAUD,EAAS,OAMnBE,EAAYC,GAA+BA,EAAM,OAAyB,cAAgB,GAC1FC,EAAgBJ,EAAS,OAAO,CAACK,EAAMF,EAAOG,IAAWJ,EAASC,CAAK,EAAIG,EAAQ,EAAID,EAAO,CAAC,EAErG,IAAIE,EAAW,EAEf,OAAOR,EAAM,IAAI,CAACI,EAAOG,IAClBpB,EAAM,eAAeiB,CAAK,GAC/BI,GAAY,EAEVC,EAAAA,IAAChB,GAAiB,SAAjB,CAAmD,MAAO,CAAE,SAAAe,EAAU,QAAAN,EAAS,cAAAG,CAAA,EAC7E,SAAAD,CAAA,EAD6BA,EAAM,KAAOG,CAE7C,GALuCH,CAO1C,CACH,EAAG,CAACL,CAAQ,CAAC,CACf,CAWA,MAAMW,EAAgB,oBAEtB,SAASC,EAAgBC,EAA0B,CACjD,OAAKA,EACE,CAAC,GAAGA,EAAK,iBAA8BF,CAAa,CAAC,EAD1C,CAAA,CAEpB,CAEA,MAAMG,GAAqB,gCAE3B,SAASC,EAASF,EAAmBG,EAAY,CAC/C,OAAOJ,EAAgBC,CAAI,EAAE,KAAMI,GAAYA,EAAQ,QAAQ,aAAeD,CAAE,CAClF,CAGA,SAASE,EAAaC,EAAmB,CACvC,OAAOA,EAAK,eAAe,QAAqBL,EAAkB,GAAK,IACzE,CAGA,SAASM,GAAeD,EAAmB,CACzC,MAAME,EAAgB,CAAA,EACtB,QAASC,EAAWH,EAAK,eAAe,QAAqBR,CAAa,EAAGW,GACvEA,EAAS,QAAQ,cAAgB,QAAQA,EAAS,QAAQ,UAAU,EACxEA,EAAWA,EAAS,eAAe,QAAqBX,CAAa,EAEvE,OAAOU,CACT,CAGA,SAASE,GAAiBC,EAAoB,CAC5C,GAAIA,EAAK,WAAa,KAAK,UAAW,OAAOA,EAAK,aAAe,GACjE,GAAI,EAAEA,aAAgB,cAAgBA,EAAK,aAAa,aAAa,IAAM,OAAQ,MAAO,GAC1F,IAAIC,EAAO,GACX,UAAWpB,KAASmB,EAAK,WAAYC,GAAQF,GAAiBlB,CAAK,EACnE,OAAOoB,CACT,CAOA,SAASC,GAAYP,EAAmB,CACtC,MAAMQ,EAAUR,EAAK,aAAa,iBAAiB,EAC7CS,EAAQD,EAAUR,EAAK,cAAc,eAAeQ,CAAO,EAAI,KACrE,OAAQC,EAAQL,GAAiBK,CAAK,EAAI,IAAI,KAAA,EAAO,YAAA,CACvD,CAOA,SAASC,GAAmBhB,EAAmBiB,EAAmBC,EAAgC,CAChG,MAAMC,EAASjB,EAASF,EAAMiB,CAAS,EACvC,GAAIE,EAAQ,OAAOA,EACnB,QAASxB,EAAQuB,EAAY,OAAS,EAAGvB,GAAS,EAAGA,GAAS,EAAG,CAC/D,MAAMc,EAAWP,EAASF,EAAMkB,EAAYvB,CAAK,CAAC,EAClD,GAAIc,EAAU,OAAOA,CACvB,CACA,OAAOV,EAAgBC,CAAI,EAAE,CAAC,CAChC,CAEA,SAASoB,GAAUhB,EAAyCiB,EAAoC,CAC9F,MAAMlB,EAAKC,GAAS,QAAQ,WACxB,CAACA,GAAW,CAACD,IACjBkB,EAAalB,CAAE,EACfC,EAAQ,MAAA,EACV,CAGA,MAAMkB,GAAuB,IAKvBC,GAAoB,IAwB1B,SAASC,EAAW,CAAE,MAAAC,EAAO,aAAAJ,CAAA,EAA8BjB,EAAyC,CAClGqB,EAAM,eAAA,EACNL,GAAUhB,EAASiB,CAAY,CACjC,CAEA,SAASK,EAAO/C,EAAuBgD,EAAgB,CACrD,MAAMC,EAAQ7B,EAAgBpB,EAAQ,IAAI,EAC1C6C,EAAW7C,EAASiD,EAAMA,EAAM,QAAQjD,EAAQ,OAAO,EAAIgD,CAAM,CAAC,CACpE,CAMA,MAAME,GAAqE,CACzE,UAAYlD,GAAY+C,EAAO/C,EAAS,CAAC,EACzC,QAAUA,GAAY+C,EAAO/C,EAAS,EAAE,EACxC,WAAaA,GAAY,CACvB,KAAM,CAAE,MAAA8C,EAAO,QAAAK,EAAS,GAAA3B,EAAI,YAAA4B,EAAa,SAAAC,EAAU,YAAAC,GAAgBtD,EACnE,GAAIoD,GAAe,CAACC,EAAU,CAC5BP,EAAM,eAAA,EACNQ,EAAY9B,EAAI,EAAI,EACpB,MACF,CACI6B,GAAUR,EAAW7C,EAASmD,EAAQ,cAA2BhC,CAAa,CAAC,CACrF,EACA,UAAYnB,GAAY,CACtB,KAAM,CAAE,MAAA8C,EAAO,QAAAK,EAAS,GAAA3B,EAAI,SAAA6B,EAAU,YAAAC,GAAgBtD,EACtD,GAAIqD,EAAU,CACZP,EAAM,eAAA,EACNQ,EAAY9B,EAAI,EAAK,EACrB,MACF,CACAqB,EAAW7C,EAASmD,EAAQ,eAAe,QAAqBhC,CAAa,CAAC,CAChF,EACA,KAAOnB,GAAY6C,EAAW7C,EAASoB,EAAgBpB,EAAQ,IAAI,EAAE,CAAC,CAAC,EACvE,IAAMA,GAAY,CAChB,MAAMiD,EAAQ7B,EAAgBpB,EAAQ,IAAI,EAC1C6C,EAAW7C,EAASiD,EAAMA,EAAM,OAAS,CAAC,CAAC,CAC7C,EACA,MAAQjD,GAAY,CACdA,EAAQ,WACZA,EAAQ,MAAM,eAAA,EACdA,EAAQ,SAASA,EAAQ,GAAIA,EAAQ,YAAaA,EAAQ,QAAQ,EACpE,EAEA,IAAMA,GAAY,CAChB,KAAM,CAAE,MAAA8C,EAAO,KAAAzB,EAAM,QAAA8B,EAAS,UAAAI,GAAcvD,EAC5C8C,EAAM,eAAA,EACN,MAAMU,EAAY9B,EAAayB,CAAO,GAAK9B,EACrCQ,EAAMT,EAAgBoC,CAAS,EAClC,OAAQ7B,GAASD,EAAaC,CAAI,IAAM6B,CAAS,EACjD,OAAQ7B,GAASA,EAAK,QAAQ,kBAAoB,QAAUA,EAAK,aAAa,eAAe,IAAM,MAAM,EACzG,IAAKA,GAASA,EAAK,QAAQ,UAAU,EACrC,OAAQH,GAAqB,EAAQA,CAAG,EACvCK,EAAI,QAAQ0B,EAAU1B,CAAG,CAC/B,CACF,EAGA,SAAS4B,GAAeX,EAA4B,CAClD,OAAOA,EAAM,IAAI,SAAW,GAAKA,EAAM,MAAQ,GACjD,CAOA,SAASY,GAAY1D,EAAuB,CAC1C,KAAM,CAAE,MAAA8C,EAAO,KAAAzB,EAAM,QAAA8B,EAAS,UAAAQ,EAAW,kBAAAC,GAAsB5D,EAE/D8C,EAAM,eAAA,EACN,aAAaa,EAAU,KAAK,EAC5B,aAAaA,EAAU,SAAS,EAChCA,EAAU,QAAUb,EAAM,IAAI,YAAA,EAE9B,KAAM,CAAE,OAAAe,GAAWF,EAEbG,EADiBD,EAAO,OAAS,GAAK,CAAC,GAAGA,CAAM,EAAE,MAAOE,GAASA,IAASF,EAAO,CAAC,CAAC,EAC3DA,EAAO,CAAC,EAAIA,EAI3CD,EAAkB,CAAE,MAAAE,EAAO,OAAQ,EAAA,CAAO,EAC1CH,EAAU,MAAQ,WAAW,IAAM,CACjCA,EAAU,OAAS,GACnBC,EAAkB,CAAE,MAAAE,EAAO,OAAQ,EAAA,CAAM,EACzCH,EAAU,UAAY,WAAW,IAAMC,EAAkB,IAAI,EAAGhB,EAAiB,CACnF,EAAGD,EAAoB,EAIvB,MAAMM,EAAQ7B,EAAgBC,CAAI,EAC5B2C,EAAQf,EAAM,QAAQE,CAAO,EACnC,QAASH,EAAS,EAAGA,GAAUC,EAAM,OAAQD,GAAU,EAAG,CACxD,MAAMiB,EAAYhB,GAAOe,EAAQhB,GAAUC,EAAM,MAAM,EACvD,GAAIf,GAAY+B,CAAS,EAAE,WAAWH,CAAK,EAAG,CAC5CjB,EAAW7C,EAASiE,CAAS,EAC7B,MACF,CACF,CACF,CA+BA,SAASC,GAAK,CACZ,UAAAC,EACA,SAAA3D,EACA,YAAa4D,EACb,mBAAAC,EACA,iBAAAC,EACA,WAAYC,EACZ,kBAAAC,EAAoB,KACpB,iBAAAC,EACA,WAAAC,EACA,eAAAC,EAAiB,GACjB,OAAAC,EAAS,QACT,QAAAC,EACA,OAAAC,EACA,GAAGC,CACL,EAAc,CACZ,MAAMC,EAAUpF,EAAM,OAAuB,IAAI,EAE3C,CAACqF,EAAaC,CAAc,EAAIC,uBAAkC,CACtE,KAAMf,EACN,YAAaC,GAAsB,IAAI,IACvC,SAAUC,CAAA,CACX,EACK,CAACc,EAAYC,CAAa,EAAIF,uBAAoC,CACtE,KAAMZ,EACN,YAAaC,EACb,SAAWhD,GAAO,CACZA,GAAM,MAAMiD,IAAmBjD,CAAE,CACvC,CAAA,CACD,EACK,CAACc,EAAWI,CAAY,EAAI9C,EAAM,SAAwB,IAAI,EAC9D,CAAC0F,EAASC,CAAU,EAAI3F,EAAM,SAAwB,IAAI,EAC1D,CAAC4F,EAAgB5B,CAAiB,EAAIhE,EAAM,SAAgC,IAAI,EAIhF6F,EAAiB7F,EAAM,OAAiB,EAAE,EAG1C8F,EAAc9F,EAAM,OAAO,EAAK,EAChC+F,EAAe/F,EAAM,OAAuB,CAAE,OAAQ,GAAI,MAAO,OAAW,UAAW,OAAW,EAExGA,EAAM,UACJ,IAAM,IAAM,CACV,aAAa+F,EAAa,QAAQ,KAAK,EACvC,aAAaA,EAAa,QAAQ,SAAS,CAC7C,EACA,CAAA,CAAC,EAGH,MAAMrC,EAAc1D,EAAM,YACxB,CAAC4B,EAAY6B,IAAsB,CACjC6B,EAAgB/B,GAAY,CAC1B,MAAMyC,EAAO,IAAI,IAAIzC,CAAO,EAC5B,OAAIE,EAAUuC,EAAK,IAAIpE,CAAE,EACpBoE,EAAK,OAAOpE,CAAE,EACZoE,CACT,CAAC,CACH,EACA,CAACV,CAAc,CAAA,EAGX3B,EAAY3D,EAAM,YACrBiC,GAAkB,CACjBqD,EAAgB/B,GAAY,CAC1B,MAAMyC,EAAO,IAAI,IAAIzC,CAAO,EAC5B,UAAW3B,KAAMK,EAAK+D,EAAK,IAAIpE,CAAE,EACjC,OAAOoE,CACT,CAAC,CACH,EACA,CAACV,CAAc,CAAA,EAGXW,EAAejG,EAAM,YACzB,CAACkG,EAAqB1C,EAAsBC,IAAsB,CAChEgC,EAAcS,CAAW,EACrBnB,GAAkBvB,GAAaE,EAAYwC,EAAa,CAACzC,CAAQ,EACrEqB,IAAaoB,CAAW,CAC1B,EACA,CAACT,EAAeV,EAAgBrB,EAAaoB,CAAU,CAAA,EAGnDqB,EAAoBnG,EAAM,YAC7BkD,GAA4C,CAC3C,MAAMzB,EAAO2D,EAAQ,QACf7B,EAAWL,EAAM,QAA+B,QAAqB3B,CAAa,EAClFK,EAAK2B,GAAS,QAAQ,WAQ5B,GAPI,CAAC9B,GAAQ,CAAC8B,GAAW,CAAC3B,GAAM,CAACH,EAAK,SAAS8B,CAAO,GAGlDA,IAAYL,EAAM,eAIlBA,EAAM,SAAWA,EAAM,SAAWA,EAAM,OAAQ,OACpD,MAAMkD,EAAU9C,GAAkBJ,EAAM,GAAG,IAAMW,GAAeX,CAAK,EAAIY,GAAc,QAClFsC,GAELA,EAAQ,CACN,MAAAlD,EACA,KAAAzB,EACA,QAAA8B,EACA,GAAA3B,EACA,YAAa2B,EAAQ,QAAQ,kBAAoB,OACjD,SAAUA,EAAQ,aAAa,eAAe,IAAM,OACpD,SAAUA,EAAQ,aAAa,eAAe,IAAM,OACpD,YAAAG,EACA,UAAAC,EACA,aAAAb,EACA,SAAUmD,EACV,UAAWF,EAAa,QACxB,kBAAA/B,CAAA,CACD,CACH,EACA,CAACN,EAAaC,EAAWsC,CAAY,CAAA,EAKjCI,EAAmBrG,EAAM,YAAY,IAAM,CAC/C,MAAMyB,EAAO2D,EAAQ,QACrB,GAAI,CAAC3D,EAAM,OAEX,GAAIiB,GAAa,KAAM,CAMrB,MAAMsD,EADSR,GAAc,MAAQ,CAAC7D,EAASF,EAAM+D,CAAU,EACxChE,EAAgBC,CAAI,EAAE,CAAC,GAAG,QAAQ,YAAc,KAAQ,KAC3EuE,IAASN,GAASC,EAAWK,CAAI,EACrC,MACF,CAEA,MAAMpD,EAASH,GAAmBhB,EAAMiB,EAAWmD,EAAe,OAAO,EACnES,EAAW1D,GAAQ,QAAQ,WACjC,GAAI,CAACA,GAAU,CAAC0D,EAAU,OACtBA,IAAa5D,EAAWmD,EAAe,QAAU7D,GAAeY,CAAM,IACxD0D,CAAQ,EAI1B,MAAMC,EAAS9E,EAAK,cAAc,cAC9BqE,EAAY,UAAY,CAACrE,EAAK,SAAS8E,CAAM,GAAKA,IAAW9E,IAAOmB,EAAO,MAAA,CACjF,EAAG,CAACF,EAAW8C,EAAYE,CAAO,CAAC,EAInC1F,EAAM,gBAAgBqG,CAAgB,EAEtC,MAAMjG,EAAUJ,EAAM,QACpB,KAAO,CACL,YAAaqF,GAAe,IAAI,IAChC,YAAA3B,EACA,UAAAC,EACA,WAAY6B,GAAc,KAC1B,aAAAS,EACA,UAAAvD,EACA,aAAAI,EACA,QAAA4C,EACA,eAAAX,EACA,OAAAC,EACA,cAAemB,CAAA,GAEjB,CACEd,EACA3B,EACAC,EACA6B,EACAS,EACAvD,EACAgD,EACAX,EACAC,EACAmB,CAAA,CACF,EAGF,aACGpG,GAAY,SAAZ,CAAqB,MAAOK,EAC3B,SAAAkB,MAACrB,GAAqB,SAArB,CAA8B,MAAO2F,EACpC,SAAAtE,EAAAA,IAACjB,EAAiB,SAAjB,CAA0B,MAAO,EAChC,SAAAiB,EAAAA,IAAC,MAAA,CACC,IAAK8D,EACL,YAAU,OACV,cAAaJ,EACb,KAAK,OACL,SAAU,GACV,QAAU9B,GAAU,CAClB+B,IAAU/B,CAAK,EACf4C,EAAY,QAAU,EACxB,EACA,OAAS5C,GAAU,CACjBgC,IAAShC,CAAK,EACTA,EAAM,cAAc,SAASA,EAAM,aAAa,MAAe,QAAU,GAChF,EAgBA,UAAWsD,EAAAA,GACT,0DACA,iHACAjC,CAAA,EAED,GAAGY,EASJ,eAACsB,kBAAA,CAAgB,cAAe,IAC9B,SAAAnF,MAACoF,GAAA,CAAoB,SAAA9F,EAAS,CAAA,CAChC,CAAA,CAAA,CACF,CACF,EACF,EACF,CAEJ,CAEA,SAAS8F,GAAmB,CAAE,SAAA9F,GAA2C,CACvE,OAAOD,GAAuBC,CAAQ,CACxC,CAgBA,SAAS+F,GAAS,CAChB,UAAApC,EACA,SAAA3D,EACA,GAAAgB,EACA,YAAA4B,EAAc,GACd,SAAAoD,EAAW,GACX,QAAAC,EACA,QAAA5B,EACA,UAAA6B,EACA,MAAAC,EACA,GAAG5B,CACL,EAAkB,CAChB,KAAM,CAAE,YAAAE,EAAa,YAAA3B,EAAa,WAAA8B,EAAY,aAAAS,EAAc,UAAAvD,EAAW,aAAAI,EAAc,QAAA4C,EAAS,cAAAsB,GAC5F9G,GAAe,UAAU,EACrB+G,EAAQjH,EAAM,WAAWK,CAAgB,EACzC,CAAE,SAAAgB,EAAU,QAAAN,EAAS,cAAAG,GAAkBlB,EAAM,WAAWM,EAAgB,EACxEiC,EAAU,GAAGvC,EAAM,MAAA,CAAO,SAE1ByD,EAAWD,GAAe6B,EAAY,IAAIzD,CAAE,EAC5CsF,EAAW1B,IAAe5D,EAE1BuF,EAASnH,EAAM,YAAY,IAAM,CACjCwD,GAAaE,EAAY9B,EAAI,CAAC6B,CAAQ,CAC5C,EAAG,CAACD,EAAaE,EAAa9B,EAAI6B,CAAQ,CAAC,EAIrC2D,EAASpH,EAAM,YAAY,IAAM,CACjC4G,IACJ9D,EAAalB,CAAE,EACfqE,EAAarE,EAAI4B,EAAaC,CAAQ,EACxC,EAAG,CAACmD,EAAU9D,EAAclB,EAAIqE,EAAczC,EAAaC,CAAQ,CAAC,EAK9D4D,EAAcJ,IAAU,GAAK5F,IAAa,EAC1CiG,EAAe9B,GAAc,KAAO6B,EAAc7B,IAAe5D,EACjE2F,EAAW7E,EAAYA,IAAcd,EAAK8D,EAAUA,IAAY9D,EAAK0F,EAOrEE,EADaxH,EAAM,WAAWO,CAAe,GACV,aAAeC,GAClDiH,EAAczH,EAAM,QACxB,IAAOiH,EAAQ,GAAK5F,EAAWH,EAAgB,CAAC,GAAGsG,EAAsBP,EAAQ,CAAC,EAAIO,EACtF,CAACA,EAAsBP,EAAO5F,EAAUH,CAAa,CAAA,EAGjDwG,EAAc1H,EAAM,QACxB,KAAO,CACL,GAAA4B,EACA,QAAAW,EACA,MAAA0E,EACA,SAAAxD,EACA,YAAAD,EACA,SAAA0D,EACA,SAAAN,EACA,YAAAa,EACA,OAAAN,EACA,OAAAC,CAAA,GAEF,CAACxF,EAAIW,EAAS0E,EAAOxD,EAAUD,EAAa0D,EAAUN,EAAUa,EAAaN,EAAQC,CAAM,CAAA,EAG7F,OACE9F,EAAAA,IAACf,EAAgB,SAAhB,CAAyB,MAAOmH,EAC/B,SAAApG,EAAAA,IAAC,MAAA,CAGE,GAAG6D,EACJ,YAAU,YACV,oBAAmBvD,EACnB,yBAAwB4B,EACxB,aAAYC,EAAW,WAAa,YACpC,KAAK,WAGL,kBAAiBlB,EACjB,gBAAeiB,EAAcC,EAAW,OACxC,aAAYwD,EACZ,gBAAe5F,EACf,eAAcN,EACd,gBAAemG,EACf,gBAAeN,GAAY,OAC3B,SAAUW,EAAW,EAAI,GACzB,UAAYrE,GAAU,CACpB4D,IAAY5D,CAAK,EACb,CAAAA,EAAM,kBACV8D,EAAc9D,CAAK,CACrB,EACA,QAAUA,GAAU,CAClB2D,IAAU3D,CAAK,EACX,CAAAA,EAAM,kBAGLA,EAAM,OAAuB,QAAQ3B,CAAa,IAAM2B,EAAM,eACnEkE,EAAA,CACF,EACA,QAAUlE,GAAU,CAClB+B,IAAU/B,CAAK,EACXA,EAAM,SAAWA,EAAM,iBAA4BtB,CAAE,CAC3D,EACA,MACE,CAEE,oBAAqB,6BAA6BqF,EAAQ,CAAC,gBAG3D,mBAAoB,uCAGpB,sBAAuB,SACvB,GAAGF,CAAA,EAGP,UAAWP,EAAAA,GACT,wBAKA,uHACAjC,CAAA,EAGD,SAAA3D,CAAA,CAAA,EAEL,CAEJ,CAMA,MAAM+G,GAAwBC,GAAAA,IAC5B,kHACA,CACE,SAAU,CACR,KAAM,CACJ,GAAI,cACJ,QAAS,cACT,GAAI,aAAA,CACN,EAEF,gBAAiB,CACf,KAAM,SAAA,CACR,CAEJ,EAoBA,SAASC,GAAc,CAAE,UAAAtD,EAAW,SAAA3D,EAAU,KAAAkH,EAAM,MAAAf,EAAO,KAAAgB,EAAM,SAAAC,EAAU,GAAG7C,GAA6B,CACzG,KAAM,CAAE,QAAA5C,EAAS,MAAA0E,EAAO,SAAAxD,EAAU,YAAAD,EAAa,SAAA0D,EAAU,SAAAN,EAAU,YAAAa,EAAa,OAAAN,GAC9E1G,EAAmB,eAAe,EAC9B,CAAE,OAAAuE,CAAA,EAAW9E,GAAe,eAAe,EAC3C0F,EAAiB5F,EAAM,WAAWC,EAAoB,EAKtDgI,EAAYjD,IAAW,QAAUiC,EAAQ,GAAKzD,EAC9C0E,EAAalD,IAAW,SAAWiD,GAAaR,EAAY,OAAS,GAErEU,EAAUnI,EAAM,OAAwB,IAAI,EAC5C,CAACoI,EAAaC,CAAc,EAAIrI,EAAM,SAAS,EAAK,EAKpDsI,EAA2BtC,GAAkB,CACjD,MAAM3D,EAAO8F,EAAQ,QACrBE,EAAerC,GAAQ,CAAC,CAAC3D,GAAQA,EAAK,YAAcA,EAAK,WAAW,CACtE,EAEA,OACEkG,EAAAA,KAAC,MAAA,CAGE,GAAGpD,EACJ,GAAI5C,EACJ,YAAU,kBAIV,MAAO,CAAE,mBAAoB,6BAA6B0E,EAAQ,CAAC,cAAe,GAAGF,CAAA,EACrF,UAAWP,EAAAA,GACTmB,GAAsB,CAAE,KAAAG,EAAM,EAC9B,qCAGAZ,EAAW,+CAAiD,iBAG5DN,GAAY,iCACZrC,CAAA,EAGD,SAAA,CAAA2D,EAaCK,EAAAA,KAAC,OAAA,CACC,YAAU,mBACV,cAAY,OACZ,UAAW/B,EAAAA,GACT,uCAIAxB,IAAW,SACT,yFAAA,EAGH,SAAA,CAAAyC,EAAY,IAAKe,GAChBlH,EAAAA,IAAC,OAAA,CAEC,YAAU,wBACV,MAAO,CAAE,KAAM,6BAA6BkH,EAAa,CAAC,eAAA,EAG1D,UAAU,kFAAA,EALLA,CAAA,CAOR,EACAP,EAIC3G,EAAAA,IAAC,OAAA,CACC,YAAU,wBACV,UAAWkF,EAAAA,GACT,2FACA,sEACA,uCAAA,CACF,CAAA,EAEA,IAAA,CAAA,CAAA,EAEJ,KACHhD,EAKClC,EAAAA,IAAC,OAAA,CACC,YAAU,sBACV,cAAY,OACZ,QAAU4B,GAAU,CAElBA,EAAM,gBAAA,EACNiE,EAAA,CACF,EACA,UAAU,2EAEV,eAACsB,GAAAA,iBAAA,CAAiB,UAAWjC,EAAAA,GAAG,gCAAiC/C,GAAY,WAAW,CAAA,CAAG,CAAA,CAAA,QAG5F,OAAA,CAAK,YAAU,6BAA6B,cAAY,OAAO,UAAU,oBAAoB,EAE/FsE,EACCzG,EAAAA,IAAC,OAAA,CACC,YAAU,iBACV,cAAY,OACZ,UAAWkF,EAAAA,GACT,mFACAU,EAAW,yBAA2B,uBAAA,EAGvC,SAAAa,CAAA,CAAA,EAED,KACJQ,EAAAA,KAACG,EAAAA,QAAA,CAAQ,KAAMN,EAAa,aAAcE,EACxC,SAAA,CAAAhH,EAAAA,IAACqH,EAAAA,eAAA,CAAe,QAAO,GACrB,SAAArH,EAAAA,IAAC,OAAA,CACC,IAAK6G,EACL,YAAU,iBAIV,UAAU,qCAEV,SAAA7G,EAAAA,IAACsH,GAAA,CAAa,MAAOhD,EAAiB,SAAAhF,CAAA,CAAS,CAAA,CAAA,EAEnD,EAMAU,MAACuH,EAAAA,gBAAgB,SAAAjI,CAAA,CAAS,CAAA,EAC5B,EACCoH,QACE,OAAA,CAAK,YAAU,qBAAqB,UAAU,4DAC5C,WACH,EACE,IAAA,CAAA,CAAA,CAGV,CAMA,SAASY,GAAa,CAAE,MAAAE,EAAO,SAAAlI,GAAyE,CACtG,GAAI,CAACkI,GAAS,OAAOlI,GAAa,UAAY,CAACA,EAAS,cAAc,WAAWkI,EAAM,KAAK,EAC1F,OAAOlI,EAET,KAAM,CAAE,MAAAsD,EAAO,OAAA6E,CAAA,EAAWD,EAC1B,OACEP,EAAAA,KAAAS,WAAA,CACE,SAAA,CAAA1H,EAAAA,IAAC,OAAA,CACC,YAAU,4BACV,aAAYyH,EAAS,SAAW,SAChC,UAAWvC,EAAAA,GAIT,oBAGA,iBAGA,qGACAuC,EACI,+CACA,2DAAA,EAGL,SAAAnI,EAAS,MAAM,EAAGsD,EAAM,MAAM,CAAA,CAAA,EAEhCtD,EAAS,MAAMsD,EAAM,MAAM,CAAA,EAC9B,CAEJ,CAMA,SAAS+E,GAAc,CAAE,UAAA1E,EAAW,SAAA3D,EAAU,GAAGuE,GAAsC,CACrF,KAAM,CAAE,SAAA1B,EAAU,MAAAwD,GAAUxG,EAAmB,eAAe,EAI9D,OAAKgD,EAGHnC,EAAAA,IAACjB,EAAiB,SAAjB,CAA0B,MAAO4G,EAAQ,EACxC,SAAA3F,EAAAA,IAAC,MAAA,CAAK,GAAG6D,EAAO,YAAU,kBAAkB,KAAK,QAAQ,UAAWqB,KAAG,gBAAiBjC,CAAS,EAC/F,SAAAjD,EAAAA,IAACoF,GAAA,CAAoB,SAAA9F,CAAA,CAAS,CAAA,CAChC,CAAA,CACF,EAPoB,IASxB"}
1
+ {"version":3,"file":"tree.cjs","sources":["../../src/components/ui/tree.tsx"],"sourcesContent":["import { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { ChevronRightIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"./tooltip\";\n\nimport { cn } from \"@/lib/utils\";\n\n/* -------------------------------------------------------------------------------------------------\n * Contexts\n *\n * The tree is intentionally headless about *data*: it never fetches, never owns a node array, and\n * derives every ARIA attribute from where a `TreeItem` sits in the React tree. Four contexts carry\n * that positional information down:\n *\n * TreeContext — per-tree state (expansion, selection, roving focus) and the key handler\n * TreeLevelContext — the current depth; `Tree` seeds 1, each `TreeItemGroup` increments\n * TreeIndexContext — `aria-posinset` / `aria-setsize`, injected by whichever container renders\n * the item (`Tree` for roots, `TreeItemGroup` for children)\n * TreeItemContext — the nearest enclosing item, read by `TreeItemLabel` / `TreeItemGroup`\n * -----------------------------------------------------------------------------------------------*/\n\ntype TreeContextValue = {\n expandedIds: Set<string>;\n setExpanded: (id: string, expanded: boolean) => void;\n /** Expands several nodes in one state update — what `*` needs for a whole sibling set. */\n expandIds: (ids: string[]) => void;\n selectedId: string | null;\n /**\n * The one activation path: selection, optional expansion and `onActivate`, shared by `Enter` and\n * by clicking a node so the two never diverge.\n */\n activateItem: (id: string, hasChildren: boolean, expanded: boolean) => void;\n focusedId: string | null;\n setFocusedId: (id: string) => void;\n /**\n * Where `Tab` enters the tree before any node has been focused, when the default (the selected\n * node, else the first root) is not currently rendered. `null` means the default stands.\n */\n entryId: string | null;\n expandOnSelect: boolean;\n guides: TreeGuides;\n /** Attached to each `TreeItem` rather than to the tree root, so the node is its own key target. */\n onItemKeyDown: (event: React.KeyboardEvent<HTMLElement>) => void;\n};\n\nconst TreeContext = React.createContext<TreeContextValue | null>(null);\n\n/**\n * The typeahead highlight to show: the lower-cased query, and whether the buffer has lapsed and the\n * highlight is fading out. `null` once the fade has finished. Its own context, apart from\n * `TreeContext`, so a keystroke (and the two timer-driven fade updates after it) re-renders only the\n * labels that draw the highlight, not every `TreeItem` with its ARIA wiring.\n */\nconst TreeTypeaheadContext = React.createContext<TypeaheadMatch | null>(null);\n\nfunction useTreeContext(component: string) {\n const context = React.useContext(TreeContext);\n if (!context) {\n throw new Error(`\\`${component}\\` must be rendered inside a \\`Tree\\`.`);\n }\n return context;\n}\n\nconst TreeLevelContext = React.createContext(1);\n\ntype TreeIndexContextValue = {\n posinset: number;\n setsize: number;\n /**\n * Position of the last sibling that is itself a branch, or 0 if none are. Connectors only join a\n * folder to its subfolders, so this is where the trunk has to stop — running it to the last child\n * would leave it dangling past any trailing leaf rows.\n */\n lastBranchPos: number;\n};\n\nconst TreeIndexContext = React.createContext<TreeIndexContextValue>({\n posinset: 1,\n setsize: 1,\n lastBranchPos: 0,\n});\n\ntype TreeItemContextValue = {\n id: string;\n labelId: string;\n level: number;\n expanded: boolean;\n hasChildren: boolean;\n selected: boolean;\n disabled: boolean;\n /**\n * Parent levels whose trunk passes through this row. The row draws one vertical segment per\n * entry, so a trunk survives crossing an expanded branch's descendant rows.\n */\n trunkLevels: readonly number[];\n toggle: () => void;\n select: () => void;\n};\n\nconst TreeItemContext = React.createContext<TreeItemContextValue | null>(null);\n\n/** Stable empty set, so inheriting \"no trunks\" doesn't remake the item context every render. */\nconst NO_TRUNKS: readonly number[] = [];\n\nfunction useTreeItemContext(component: string) {\n const context = React.useContext(TreeItemContext);\n if (!context) {\n throw new Error(`\\`${component}\\` must be rendered inside a \\`TreeItem\\`.`);\n }\n return context;\n}\n\n/**\n * Reads the item's position among its siblings and whether it is currently expanded. Exposed for\n * consumers composing their own row content (badges, action buttons, counts) inside a `TreeItem`.\n */\nfunction useTreeItem() {\n return useTreeItemContext(\"useTreeItem\");\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Sibling indexing\n *\n * `aria-setsize` / `aria-posinset` need sibling counts, which only the container knows. Rather than\n * a mount-order registry (two render passes, StrictMode-sensitive, wrong under conditional\n * rendering) each container walks its own children and wraps them in an index provider. Purely\n * positional, so it is correct on the first render and under SSR.\n *\n * Every valid element counts as a sibling for indexing, *except* the kit's two placeholders,\n * `TreeEmpty` and `TreeLoadMore`: a consumer routinely wraps `TreeItem` in their own component (a\n * row that also wires up drag-and-drop, say), and that wrapper still needs a real posinset/setsize,\n * so indexing can't be gated on the element's `type` being `TreeItem` literally — the placeholders\n * opt out instead, explicitly, by identity (SW-2542). Any other non-item child is still counted, so\n * placeholder content belongs inside one of the two.\n * -----------------------------------------------------------------------------------------------*/\n\nfunction isPlaceholder(child: React.ReactElement) {\n return child.type === TreeEmpty || child.type === TreeLoadMore;\n}\n\nfunction useIndexedTreeChildren(children: React.ReactNode) {\n return React.useMemo(() => {\n const array = React.Children.toArray(children);\n const elements = array.filter(\n (child): child is React.ReactElement => React.isValidElement(child) && !isPlaceholder(child),\n );\n const setsize = elements.length;\n\n // Which siblings are branches is read off `hasChildren` in the element's own props. A child\n // wrapped in a consumer's own component reads as a leaf unless that wrapper forwards the prop,\n // which costs a connector rather than breaking anything — the alternative is a mount-order\n // registry, and the whole point of doing this positionally is to stay correct on first render.\n const isBranch = (child: React.ReactElement) => (child.props as TreeItemProps)?.hasChildren === true;\n const lastBranchPos = elements.reduce((last, child, index) => (isBranch(child) ? index + 1 : last), 0);\n\n let posinset = 0;\n\n return array.map((child, index) => {\n if (!React.isValidElement(child) || isPlaceholder(child)) return child;\n posinset += 1;\n return (\n <TreeIndexContext.Provider key={child.key ?? index} value={{ posinset, setsize, lastBranchPos }}>\n {child}\n </TreeIndexContext.Provider>\n );\n });\n }, [children]);\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Keyboard navigation\n *\n * Visible-node order is read from the DOM instead of a JS registry: collapsed groups are not\n * rendered at all, so `querySelectorAll(ITEM_SELECTOR)` in document order *is* the visible node\n * sequence, and ancestor/descendant lookups are one `closest()` call. This keeps the traversal\n * correct for arbitrary consumer markup between the levels.\n * -----------------------------------------------------------------------------------------------*/\n\n// `[data-tree-item-id]` excludes `TreeEmpty` and `TreeLoadMore`: both carry `role=\"treeitem\"` too\n// (so an empty `Tree`/`TreeItemGroup` still satisfies `aria-required-children`), but they are\n// placeholders, not nodes — without this, arrow-key traversal would step onto one and, having no id\n// to focus, stall there instead of moving past it to the next real item.\nconst ITEM_SELECTOR = '[role=\"treeitem\"][data-tree-item-id]';\n\nfunction getVisibleItems(root: HTMLElement | null) {\n if (!root) return [];\n return [...root.querySelectorAll<HTMLElement>(ITEM_SELECTOR)];\n}\n\nconst CONTAINER_SELECTOR = '[role=\"group\"], [role=\"tree\"]';\n\nfunction findItem(root: HTMLElement, id: string) {\n return getVisibleItems(root).find((element) => element.dataset.treeItemId === id);\n}\n\n/** The `role=\"group\"` (or the tree itself) that directly contains `item`. */\nfunction getContainer(item: HTMLElement) {\n return item.parentElement?.closest<HTMLElement>(CONTAINER_SELECTOR) ?? null;\n}\n\n/** Ids of every treeitem enclosing `item`, outermost first — the trail focus retreats along. */\nfunction getAncestorIds(item: HTMLElement) {\n const ids: string[] = [];\n for (let ancestor = item.parentElement?.closest<HTMLElement>(ITEM_SELECTOR); ancestor; ) {\n if (ancestor.dataset.treeItemId) ids.unshift(ancestor.dataset.treeItemId);\n ancestor = ancestor.parentElement?.closest<HTMLElement>(ITEM_SELECTOR);\n }\n return ids;\n}\n\n/** Text content with `aria-hidden` subtrees left out — the part of a label a screen reader reads. */\nfunction getAnnouncedText(node: Node): string {\n if (node.nodeType === Node.TEXT_NODE) return node.textContent ?? \"\";\n if (!(node instanceof HTMLElement) || node.getAttribute(\"aria-hidden\") === \"true\") return \"\";\n let text = \"\";\n for (const child of node.childNodes) text += getAnnouncedText(child);\n return text;\n}\n\n/**\n * The text typeahead matches against: the node's label, resolved through `aria-labelledby` and\n * with hidden descendants dropped, so it is what a screen reader announces — a `trailing` count\n * badge joins in, an `aria-hidden` spinner or icon does not.\n */\nfunction getItemText(item: HTMLElement) {\n const labelId = item.getAttribute(\"aria-labelledby\");\n const label = labelId ? item.ownerDocument.getElementById(labelId) : null;\n return (label ? getAnnouncedText(label) : \"\").trim().toLowerCase();\n}\n\n/**\n * Where the tab stop belongs once `focusedId` may have left the DOM: the node itself if it is still\n * rendered, else its nearest surviving ancestor (collapsing a branch lands on the branch, as the\n * WAI-ARIA pattern asks), else the first visible node.\n */\nfunction resolveFocusTarget(root: HTMLElement, focusedId: string, ancestorIds: readonly string[]) {\n const target = findItem(root, focusedId);\n if (target) return target;\n for (let index = ancestorIds.length - 1; index >= 0; index -= 1) {\n const ancestor = findItem(root, ancestorIds[index]);\n if (ancestor) return ancestor;\n }\n return getVisibleItems(root)[0];\n}\n\nfunction moveFocus(element: HTMLElement | null | undefined, setFocusedId: (id: string) => void) {\n const id = element?.dataset.treeItemId;\n if (!element || !id) return;\n setFocusedId(id);\n element.focus();\n}\n\n/** How long the typeahead buffer keeps accumulating characters before it resets. */\nconst TYPEAHEAD_TIMEOUT_MS = 600;\n/**\n * How long the highlight lingers after the buffer lapses before it is removed. Deliberately past the\n * 700ms CSS transition on the pill, so removal never races the end of its own fade.\n */\nconst TYPEAHEAD_FADE_MS = 800;\n\ntype Timer = ReturnType<typeof setTimeout> | undefined;\ntype TypeaheadState = { buffer: string; timer: Timer; fadeTimer: Timer };\ntype TypeaheadMatch = { query: string; fading: boolean };\n\ntype TreeKeyEvent = {\n event: React.KeyboardEvent<HTMLElement>;\n root: HTMLElement;\n /** The `role=\"treeitem\"` element the key was pressed on. */\n current: HTMLElement;\n id: string;\n hasChildren: boolean;\n expanded: boolean;\n disabled: boolean;\n setExpanded: (id: string, expanded: boolean) => void;\n expandIds: (ids: string[]) => void;\n setFocusedId: (id: string) => void;\n activate: (id: string, hasChildren: boolean, expanded: boolean) => void;\n typeahead: TypeaheadState;\n setTypeaheadMatch: (match: TypeaheadMatch | null) => void;\n};\n\n/** Moves focus to `element`, if there is one, and claims the key press. */\nfunction navigateTo({ event, setFocusedId }: TreeKeyEvent, element: HTMLElement | null | undefined) {\n event.preventDefault();\n moveFocus(element, setFocusedId);\n}\n\nfunction stepBy(context: TreeKeyEvent, offset: number) {\n const items = getVisibleItems(context.root);\n navigateTo(context, items[items.indexOf(context.current) + offset]);\n}\n\n/**\n * `Space` is deliberately unbound: the WAI-ARIA pattern reserves it for multi-select trees, which\n * are out of scope here but should not be precluded.\n */\nconst TREE_KEY_HANDLERS: Record<string, (context: TreeKeyEvent) => void> = {\n ArrowDown: (context) => stepBy(context, 1),\n ArrowUp: (context) => stepBy(context, -1),\n ArrowRight: (context) => {\n const { event, current, id, hasChildren, expanded, setExpanded } = context;\n if (hasChildren && !expanded) {\n event.preventDefault();\n setExpanded(id, true);\n return;\n }\n if (expanded) navigateTo(context, current.querySelector<HTMLElement>(ITEM_SELECTOR));\n },\n ArrowLeft: (context) => {\n const { event, current, id, expanded, setExpanded } = context;\n if (expanded) {\n event.preventDefault();\n setExpanded(id, false);\n return;\n }\n navigateTo(context, current.parentElement?.closest<HTMLElement>(ITEM_SELECTOR));\n },\n Home: (context) => navigateTo(context, getVisibleItems(context.root)[0]),\n End: (context) => {\n const items = getVisibleItems(context.root);\n navigateTo(context, items[items.length - 1]);\n },\n Enter: (context) => {\n if (context.disabled) return;\n context.event.preventDefault();\n context.activate(context.id, context.hasChildren, context.expanded);\n },\n /** Expands every collapsed branch among the focused node's siblings, the node itself included. */\n \"*\": (context) => {\n const { event, root, current, expandIds } = context;\n event.preventDefault();\n const container = getContainer(current) ?? root;\n const ids = getVisibleItems(container)\n .filter((item) => getContainer(item) === container)\n .filter((item) => item.dataset.treeHasChildren === \"true\" && item.getAttribute(\"aria-expanded\") !== \"true\")\n .map((item) => item.dataset.treeItemId)\n .filter((id): id is string => Boolean(id));\n if (ids.length) expandIds(ids);\n },\n};\n\n/** A printable character: what feeds the typeahead buffer. (Modifiers are screened at dispatch.) */\nfunction isTypeaheadKey(event: React.KeyboardEvent) {\n return event.key.length === 1 && event.key !== \" \";\n}\n\n/**\n * Focuses the next visible node whose label starts with the characters typed so far. The buffer\n * resets after a pause; repeating one character cycles through the nodes starting with it instead\n * of looking for a label that begins with `\"ss\"`.\n */\nfunction typeaheadTo(context: TreeKeyEvent) {\n const { event, root, current, typeahead, setTypeaheadMatch } = context;\n // Claimed whether or not anything matches: a letter typed into a tree is never meant for the page.\n event.preventDefault();\n clearTimeout(typeahead.timer);\n clearTimeout(typeahead.fadeTimer);\n typeahead.buffer += event.key.toLowerCase();\n\n const { buffer } = typeahead;\n const isRepeatedChar = buffer.length > 1 && [...buffer].every((char) => char === buffer[0]);\n const query = isRepeatedChar ? buffer[0] : buffer;\n // Published so every matching label can highlight the typed prefix while the buffer is live. When\n // the buffer lapses the highlight is not yanked away: it lingers, fading, so a glance after the\n // last keystroke still shows what was matched.\n setTypeaheadMatch({ query, fading: false });\n typeahead.timer = setTimeout(() => {\n typeahead.buffer = \"\";\n setTypeaheadMatch({ query, fading: true });\n typeahead.fadeTimer = setTimeout(() => setTypeaheadMatch(null), TYPEAHEAD_FADE_MS);\n }, TYPEAHEAD_TIMEOUT_MS);\n\n // Search starts at the node after the current one and wraps, so the current node is only matched\n // as a last resort — that is what makes a repeated letter move on rather than stay put.\n const items = getVisibleItems(root);\n const start = items.indexOf(current);\n for (let offset = 1; offset <= items.length; offset += 1) {\n const candidate = items[(start + offset) % items.length];\n if (getItemText(candidate).startsWith(query)) {\n navigateTo(context, candidate);\n return;\n }\n }\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Tree\n * -----------------------------------------------------------------------------------------------*/\n\ntype TreeGuides = \"none\" | \"hover\" | \"always\";\n\ntype TreeProps = Omit<React.ComponentProps<\"div\">, \"onSelect\"> & {\n /** Expanded node ids (controlled). */\n expandedIds?: Set<string>;\n /** Initially expanded node ids (uncontrolled). */\n defaultExpandedIds?: Set<string>;\n onExpandedChange?: (expandedIds: Set<string>) => void;\n /** Selected node id (controlled). Pass `null` for \"nothing selected\". */\n selectedId?: string | null;\n /** Initially selected node id (uncontrolled). */\n defaultSelectedId?: string | null;\n onSelectedChange?: (selectedId: string) => void;\n /** Fired by `Enter` and by clicking a label — the node's default action. */\n onActivate?: (id: string) => void;\n /** Whether selecting a parent node also toggles its expansion. */\n expandOnSelect?: boolean;\n /**\n * Vertical indent guides joining each level to its parent. `\"hover\"` reveals them while the\n * pointer is anywhere over the tree, which keeps a dense tree quiet at rest but still lets you\n * trace a deep branch; `\"always\"` pins them on; `\"none\"` turns them off.\n */\n guides?: TreeGuides;\n};\n\nfunction Tree({\n className,\n children,\n expandedIds: expandedIdsProp,\n defaultExpandedIds,\n onExpandedChange,\n selectedId: selectedIdProp,\n defaultSelectedId = null,\n onSelectedChange,\n onActivate,\n expandOnSelect = true,\n guides = \"hover\",\n onFocus,\n onBlur,\n ...props\n}: TreeProps) {\n const treeRef = React.useRef<HTMLDivElement>(null);\n\n const [expandedIds, setExpandedIds] = useControllableState<Set<string>>({\n prop: expandedIdsProp,\n defaultProp: defaultExpandedIds ?? new Set<string>(),\n onChange: onExpandedChange,\n });\n const [selectedId, setSelectedId] = useControllableState<string | null>({\n prop: selectedIdProp,\n defaultProp: defaultSelectedId,\n onChange: (id) => {\n if (id != null) onSelectedChange?.(id);\n },\n });\n const [focusedId, setFocusedId] = React.useState<string | null>(null);\n const [entryId, setEntryId] = React.useState<string | null>(null);\n const [typeaheadMatch, setTypeaheadMatch] = React.useState<TypeaheadMatch | null>(null);\n // Ancestor trail of the focused node, captured when it takes focus. If a later render removes the\n // node (an ancestor collapsed, a lazy fetch swapped the subtree) this is how focus knows where to\n // retreat to instead of dropping to `body`.\n const focusedPathRef = React.useRef<string[]>([]);\n // Whether DOM focus is inside the tree. Removing a focused element fires no `blur`, so this stays\n // `true` through a removal — which is exactly the case where focus has to be restored.\n const hasFocusRef = React.useRef(false);\n const typeaheadRef = React.useRef<TypeaheadState>({ buffer: \"\", timer: undefined, fadeTimer: undefined });\n\n React.useEffect(\n () => () => {\n clearTimeout(typeaheadRef.current.timer);\n clearTimeout(typeaheadRef.current.fadeTimer);\n },\n [],\n );\n\n const setExpanded = React.useCallback(\n (id: string, expanded: boolean) => {\n setExpandedIds((current) => {\n const next = new Set(current);\n if (expanded) next.add(id);\n else next.delete(id);\n return next;\n });\n },\n [setExpandedIds],\n );\n\n const expandIds = React.useCallback(\n (ids: string[]) => {\n setExpandedIds((current) => {\n const next = new Set(current);\n for (const id of ids) next.add(id);\n return next;\n });\n },\n [setExpandedIds],\n );\n\n const activateItem = React.useCallback(\n (activatedId: string, hasChildren: boolean, expanded: boolean) => {\n setSelectedId(activatedId);\n if (expandOnSelect && hasChildren) setExpanded(activatedId, !expanded);\n onActivate?.(activatedId);\n },\n [setSelectedId, expandOnSelect, setExpanded, onActivate],\n );\n\n const handleItemKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLElement>) => {\n const root = treeRef.current;\n const current = (event.target as HTMLElement | null)?.closest<HTMLElement>(ITEM_SELECTOR);\n const id = current?.dataset.treeItemId;\n if (!root || !current || !id || !root.contains(current)) return;\n // Every ancestor `TreeItem` sees the bubbled event too; only the node it was pressed on acts\n // on it, or an unclaimed key would be handled once per level of nesting.\n if (current !== event.currentTarget) return;\n\n // A chord with Ctrl, Meta or Alt belongs to the browser or the OS (`Ctrl+ArrowDown`,\n // `Alt+Home`); the tree binds unmodified keys only. Shift is not screened — `*` needs it.\n if (event.ctrlKey || event.metaKey || event.altKey) return;\n const handler = TREE_KEY_HANDLERS[event.key] ?? (isTypeaheadKey(event) ? typeaheadTo : undefined);\n if (!handler) return;\n\n handler({\n event,\n root,\n current,\n id,\n hasChildren: current.dataset.treeHasChildren === \"true\",\n expanded: current.getAttribute(\"aria-expanded\") === \"true\",\n disabled: current.getAttribute(\"aria-disabled\") === \"true\",\n setExpanded,\n expandIds,\n setFocusedId,\n activate: activateItem,\n typeahead: typeaheadRef.current,\n setTypeaheadMatch,\n });\n },\n [setExpanded, expandIds, activateItem],\n );\n\n // Keeps the single tab stop pointing at a node that exists. Runs before paint so no frame is ever\n // committed with zero (or a vanished) `tabindex=\"0\"` node.\n const reconcileTabStop = React.useCallback(() => {\n const root = treeRef.current;\n if (!root) return;\n\n if (focusedId == null) {\n // Before the tree has been entered the tab stop is the selected node — unless it is hidden\n // inside a collapsed branch, in which case the first root node stands in or the tree would\n // have no tab stop at all. Kept apart from `focusedId` so the stand-in lapses the moment the\n // selected node is rendered again.\n const hidden = selectedId != null && !findItem(root, selectedId);\n const next = hidden ? (getVisibleItems(root)[0]?.dataset.treeItemId ?? null) : null;\n if (next !== entryId) setEntryId(next);\n return;\n }\n\n const target = resolveFocusTarget(root, focusedId, focusedPathRef.current);\n const targetId = target?.dataset.treeItemId;\n if (!target || !targetId) return;\n if (targetId === focusedId) focusedPathRef.current = getAncestorIds(target);\n else setFocusedId(targetId);\n\n // Only reclaim DOM focus if the tree had it: a programmatic collapse while the user is typing\n // elsewhere must move the tab stop, not steal focus.\n const active = root.ownerDocument.activeElement;\n if (hasFocusRef.current && (!root.contains(active) || active === root)) target.focus();\n }, [focusedId, selectedId, entryId]);\n\n // Deliberately no dependency list: whether the focused node is still rendered depends on\n // `children`, which any parent render can change, so this has to check after every commit.\n React.useLayoutEffect(reconcileTabStop);\n\n const context = React.useMemo<TreeContextValue>(\n () => ({\n expandedIds: expandedIds ?? new Set<string>(),\n setExpanded,\n expandIds,\n selectedId: selectedId ?? null,\n activateItem,\n focusedId,\n setFocusedId,\n entryId,\n expandOnSelect,\n guides,\n onItemKeyDown: handleItemKeyDown,\n }),\n [\n expandedIds,\n setExpanded,\n expandIds,\n selectedId,\n activateItem,\n focusedId,\n entryId,\n expandOnSelect,\n guides,\n handleItemKeyDown,\n ],\n );\n\n return (\n <TreeContext.Provider value={context}>\n <TreeTypeaheadContext.Provider value={typeaheadMatch}>\n <TreeLevelContext.Provider value={1}>\n <div\n ref={treeRef}\n data-slot=\"tree\"\n data-guides={guides}\n role=\"tree\"\n tabIndex={-1}\n onFocus={(event) => {\n onFocus?.(event);\n hasFocusRef.current = true;\n }}\n onBlur={(event) => {\n onBlur?.(event);\n if (!event.currentTarget.contains(event.relatedTarget)) hasFocusRef.current = false;\n }}\n // `group/tree` is what the `\"hover\"` guide mode hangs off: hovering anywhere in the tree\n // reveals every guide at once, so you can trace a branch without hunting row by row.\n //\n // `--tree-indent` is 1.25rem so that a child's chevron lands exactly on its parent's\n // icon: the icon sits 1.5rem into the content box (chevron 0.875 + gap 0.375 + the\n // 0.25rem lead-in), and the chevron sits at the lead-in, so one step must be\n // 1.5rem - 0.25rem. Indentation, the guide offsets and the elbow reach are all derived\n // from this one value — override it and the connectors follow.\n //\n // `--tree-guide-color` is deliberately *opaque*, via `color-mix`, even though it is meant\n // to look like a 40% tint. Guide segments necessarily overlap — each row's line overshoots\n // into the row above so the two meet across the label's border, and an elbow shares its\n // column with the trunk it branches from. With a semi-transparent colour every overlap\n // composites twice and shows up as a darker stretch of line. Mixing to an opaque value up\n // front makes overlapping draws idempotent, so the tree reads as one uniform hairline.\n className={cn(\n \"group/tree text-foreground flex w-full flex-col text-sm\",\n \"[--tree-indent:1.25rem] [--tree-guide-color:color-mix(in_oklch,var(--muted-foreground)_40%,var(--background))]\",\n className,\n )}\n {...props}\n >\n {/*\n Radix requires a `Tooltip.Provider` above any `Tooltip`, and the labels mount one each\n to reveal truncated text. Providing it here rather than asking consumers to wrap their\n app keeps `Tree` self-contained; nesting inside a consumer's own provider is supported,\n and the longer delay is deliberate — instant tooltips while sweeping the pointer down a\n dense tree are noise.\n */}\n <TooltipProvider delayDuration={500}>\n <TreeItemsContainer>{children}</TreeItemsContainer>\n </TooltipProvider>\n </div>\n </TreeLevelContext.Provider>\n </TreeTypeaheadContext.Provider>\n </TreeContext.Provider>\n );\n}\n\nfunction TreeItemsContainer({ children }: { children: React.ReactNode }) {\n return useIndexedTreeChildren(children);\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TreeItem\n * -----------------------------------------------------------------------------------------------*/\n\ntype TreeItemProps = React.ComponentProps<\"div\"> & {\n id: string;\n /**\n * Whether the node can be expanded. Kept explicit rather than inferred from rendered children so\n * a node whose children have not been fetched yet still reports `aria-expanded=\"false\"`.\n */\n hasChildren?: boolean;\n disabled?: boolean;\n};\n\nfunction TreeItem({\n className,\n children,\n id,\n hasChildren = false,\n disabled = false,\n onClick,\n onFocus,\n onKeyDown,\n style,\n ...props\n}: TreeItemProps) {\n const { expandedIds, setExpanded, selectedId, activateItem, focusedId, setFocusedId, entryId, onItemKeyDown } =\n useTreeContext(\"TreeItem\");\n const level = React.useContext(TreeLevelContext);\n const { posinset, setsize, lastBranchPos } = React.useContext(TreeIndexContext);\n const labelId = `${React.useId()}-label`;\n\n const expanded = hasChildren && expandedIds.has(id);\n const selected = selectedId === id;\n\n const toggle = React.useCallback(() => {\n if (hasChildren) setExpanded(id, !expanded);\n }, [hasChildren, setExpanded, id, expanded]);\n\n // Routed through the tree's `activateItem` so a click and `Enter` are the same code path —\n // notably, both fire `onActivate`.\n const select = React.useCallback(() => {\n if (disabled) return;\n setFocusedId(id);\n activateItem(id, hasChildren, expanded);\n }, [disabled, setFocusedId, id, activateItem, hasChildren, expanded]);\n\n // Roving tabindex: the focused node is the single tab stop. Before the tree has been entered it\n // is the selected node, per the WAI-ARIA pattern, or else the first root node. `Tree`'s layout\n // effect keeps this pointing at a rendered node when the focused or selected one disappears.\n const isFirstRoot = level === 1 && posinset === 1;\n const defaultEntry = selectedId == null ? isFirstRoot : selectedId === id;\n const tabbable = focusedId ? focusedId === id : entryId ? entryId === id : defaultEntry;\n\n // Guides are drawn on the row (see `TreeItemLabel`), so a row has to know every ancestor trunk\n // crossing it, not just its own parent's. The set is threaded down the tree: inherit the parent's\n // and add this row's own parent level when a later sibling folder needs the line to continue past\n // this entire subtree.\n const parentItem = React.useContext(TreeItemContext);\n const inheritedTrunkLevels = parentItem?.trunkLevels ?? NO_TRUNKS;\n const trunkLevels = React.useMemo(\n () => (level > 1 && posinset < lastBranchPos ? [...inheritedTrunkLevels, level - 1] : inheritedTrunkLevels),\n [inheritedTrunkLevels, level, posinset, lastBranchPos],\n );\n\n const itemContext = React.useMemo<TreeItemContextValue>(\n () => ({\n id,\n labelId,\n level,\n expanded,\n hasChildren,\n selected,\n disabled,\n trunkLevels,\n toggle,\n select,\n }),\n [id, labelId, level, expanded, hasChildren, selected, disabled, trunkLevels, toggle, select],\n );\n\n return (\n <TreeItemContext.Provider value={itemContext}>\n <div\n // Spread first, for the same reason as `TreeItemLabel`: every ARIA attribute below is\n // maintained by the tree and must not be overridable from props.\n {...props}\n data-slot=\"tree-item\"\n data-tree-item-id={id}\n data-tree-has-children={hasChildren}\n data-state={expanded ? \"expanded\" : \"collapsed\"}\n role=\"treeitem\"\n // The accessible name comes from the label alone. Without this, name-from-content would\n // sweep in every descendant node's text once a branch is expanded.\n aria-labelledby={labelId}\n aria-expanded={hasChildren ? expanded : undefined}\n aria-level={level}\n aria-posinset={posinset}\n aria-setsize={setsize}\n aria-selected={selected}\n aria-disabled={disabled || undefined}\n tabIndex={tabbable ? 0 : -1}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n onItemKeyDown(event);\n }}\n onClick={(event) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n // Clicks on a descendant node are that node's business — every treeitem in the ancestor\n // chain sees the bubbled event.\n if ((event.target as HTMLElement).closest(ITEM_SELECTOR) !== event.currentTarget) return;\n select();\n }}\n onFocus={(event) => {\n onFocus?.(event);\n if (event.target === event.currentTarget) setFocusedId(id);\n }}\n style={\n {\n // Inherited by the label, which draws the elbow from the same two values.\n \"--tree-guide-left\": `calc(var(--tree-indent) * ${level - 2} + 0.6875rem)`,\n // Stops 0.25rem short of the row's chevron rather than touching it, so the connector\n // reads as pointing at the row instead of welded to the glyph.\n \"--tree-elbow-run\": \"calc(var(--tree-indent) - 0.6875rem)\",\n // Shared by the elbow's corner and by where the same-column trunk picks up, so the two\n // meet exactly instead of overlapping or leaving a gap.\n \"--tree-elbow-radius\": \"0.5rem\",\n ...style,\n } as React.CSSProperties\n }\n className={cn(\n \"relative outline-none\",\n // Direct-child selectors, deliberately not `group-*/tree-item`: tree items nest, and a\n // group variant matches *any* ancestor, so a focused or selected parent painted its focus\n // ring onto every descendant row. Backgrounds live on the label for the same reason —\n // anything painted here would spread behind the whole subtree.\n \"focus-visible:[&>[data-slot=tree-item-label]]:border-ring focus-visible:[&>[data-slot=tree-item-label]]:shadow-focus\",\n className,\n )}\n >\n {children}\n </div>\n </TreeItemContext.Provider>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TreeItemLabel\n * -----------------------------------------------------------------------------------------------*/\n\nconst treeItemLabelVariants = cva(\n \"flex w-full min-w-0 cursor-default items-center gap-1.5 rounded-md pr-2 text-left transition-colors select-none\",\n {\n variants: {\n size: {\n sm: \"h-6 text-xs\",\n default: \"h-7 text-sm\",\n lg: \"h-9 text-sm\",\n },\n },\n defaultVariants: {\n size: \"default\",\n },\n },\n);\n\ntype TreeItemLabelProps = React.ComponentProps<\"div\"> &\n VariantProps<typeof treeItemLabelVariants> & {\n /**\n * Decorative leading icon, rendered between the chevron and the label text. Hidden from\n * assistive tech — the node's accessible name comes from the label text alone, so anything a\n * screen reader must convey belongs in the text, not here. Swap it on expansion (open/closed\n * folders) by reading `expanded` from `useTreeItem()` inside your own icon component.\n */\n icon?: React.ReactNode;\n /**\n * Right-aligned slot for per-node adornments — a count `Badge`, a `Spinner`, a status dot. It\n * sits inside the label, so its text joins the node's accessible name: a count reads as\n * \"Onboarding 3\", which is usually what you want. Wrap it in `aria-hidden` yourself for purely\n * decorative content such as a spinner.\n */\n trailing?: React.ReactNode;\n };\n\nfunction TreeItemLabel({ className, children, size, style, icon, trailing, ...props }: TreeItemLabelProps) {\n const { labelId, level, expanded, hasChildren, selected, disabled, trunkLevels, toggle } =\n useTreeItemContext(\"TreeItemLabel\");\n const { guides } = useTreeContext(\"TreeItemLabel\");\n const typeaheadMatch = React.useContext(TreeTypeaheadContext);\n\n // The elbow lives on the row because the label element *is* the row, so it can be sized in\n // halves of it — the curve has to land on the row's vertical centre. A connector joins a folder\n // to its subfolders, so only a branch row gets one.\n const showElbow = guides !== \"none\" && level > 1 && hasChildren;\n const showGuides = guides !== \"none\" && (showElbow || trunkLevels.length > 0);\n\n const textRef = React.useRef<HTMLSpanElement>(null);\n const [tooltipOpen, setTooltipOpen] = React.useState(false);\n\n // Truncation is measured when the tooltip would open, not tracked continuously: a\n // `ResizeObserver` per row would cost every row in a large tree for a hint almost none of them\n // need, and this answers the same question at the only moment it matters.\n const handleTooltipOpenChange = (next: boolean) => {\n const text = textRef.current;\n setTooltipOpen(next && !!text && text.scrollWidth > text.clientWidth);\n };\n\n return (\n <div\n // Spread first: the derived ARIA wiring below is authoritative. A consumer-supplied `id` would\n // otherwise break the `TreeItem` → `aria-labelledby` link that names the node.\n {...props}\n id={labelId}\n data-slot=\"tree-item-label\"\n // The row is a passive label, not a control: the parent `role=\"treeitem\"` owns focus, click\n // handling, keyboard handling and the accessible name, so a nested control would fight it.\n // `--tree-guide-left` / `--tree-elbow-run` are inherited from the `TreeItem`.\n style={{ paddingInlineStart: `calc(var(--tree-indent) * ${level - 1} + 0.25rem)`, ...style }}\n className={cn(\n treeItemLabelVariants({ size }),\n \"relative border border-transparent\",\n // Only selection paints a background — an open folder is already marked by its rotated\n // chevron, open-folder icon and the connectors running down from it.\n selected ? \"bg-accent text-accent-foreground font-medium\" : \"hover:bg-muted\",\n // From this node's own state, not an ancestor selector: `aria-disabled` is per-node, so a\n // disabled folder must not dim the contents underneath it.\n disabled && \"pointer-events-none opacity-50\",\n className,\n )}\n >\n {showGuides ? (\n // One absolutely-positioned layer owns every guide on this row, fixing two bugs at once.\n //\n // Paint order: the trunk used to be drawn by the `TreeItem`, an *ancestor* of every\n // descendant row. Those rows are positioned and paint an opaque hover/selected background\n // over anything an ancestor drew, so the trunk vanished behind whichever row you pointed\n // at. Drawn here it belongs to the row's own box, so it paints above that row's background\n // — and no sibling row can cover it, because every row draws its own segments.\n //\n // One coordinate system: `left` resolves against the nearest positioned ancestor's\n // *padding* box. The label carries `border border-transparent` for its focus ring while the\n // `TreeItem` carries none, so one `--tree-guide-left` landed 1px apart on the two elements\n // and the elbow/trunk overlap read as a 2px line. Both now share this container.\n <span\n data-slot=\"tree-item-guides\"\n aria-hidden=\"true\"\n className={cn(\n \"pointer-events-none absolute inset-0\",\n // The fade lives on the container, not on each line. Opacity on the parent renders the\n // whole layer into one buffer and composites it once, so a seam between two segments\n // can never double-expose mid-transition.\n guides === \"hover\" &&\n \"opacity-0 transition-opacity group-hover/tree:opacity-100 motion-reduce:transition-none\",\n )}\n >\n {trunkLevels.map((trunkLevel) => (\n <span\n key={trunkLevel}\n data-slot=\"tree-item-guide-trunk\"\n style={{ left: `calc(var(--tree-indent) * ${trunkLevel - 1} + 0.6875rem)` }}\n // Overshoots upward by half a chevron to cross the label's border into the row above,\n // so consecutive rows tile into one unbroken line.\n className=\"absolute top-[-0.4375rem] bottom-0 w-0 border-l border-[var(--tree-guide-color)]\"\n />\n ))}\n {showElbow ? (\n // Down the guide line, then a rounded turn right, stopping just short of this row's\n // chevron. Starts half a chevron above the row so the line emerges from under the\n // parent's chevron instead of leaving a half-row gap.\n <span\n data-slot=\"tree-item-guide-elbow\"\n className={cn(\n \"absolute top-[-0.4375rem] left-[var(--tree-guide-left)] border-[var(--tree-guide-color)]\",\n \"h-[calc(50%+0.4375rem)] w-[var(--tree-elbow-run)] border-b border-l\",\n \"rounded-bl-[var(--tree-elbow-radius)]\",\n )}\n />\n ) : null}\n </span>\n ) : null}\n {hasChildren ? (\n // A pointer-only affordance, deliberately not a `<button>`: expansion is reachable from the\n // keyboard through the parent treeitem's arrow keys, so this stays non-focusable. A focusable\n // element hidden from assistive tech is a contradiction, and inside a single-tab-stop widget\n // it would also be a second focus stop reachable by pointer.\n <span\n data-slot=\"tree-item-indicator\"\n aria-hidden=\"true\"\n onClick={(event) => {\n // Toggle from the chevron alone, without changing the selection.\n event.stopPropagation();\n toggle();\n }}\n className=\"flex size-3.5 shrink-0 items-center justify-center text-muted-foreground\"\n >\n <ChevronRightIcon className={cn(\"size-3.5 transition-transform\", expanded && \"rotate-90\")} />\n </span>\n ) : (\n <span data-slot=\"tree-item-indicator-spacer\" aria-hidden=\"true\" className=\"size-3.5 shrink-0\" />\n )}\n {icon ? (\n <span\n data-slot=\"tree-item-icon\"\n aria-hidden=\"true\"\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center [&_svg]:size-4 [&_svg]:shrink-0\",\n selected ? \"text-accent-foreground\" : \"text-muted-foreground\",\n )}\n >\n {icon}\n </span>\n ) : null}\n <Tooltip open={tooltipOpen} onOpenChange={handleTooltipOpenChange}>\n <TooltipTrigger asChild>\n <span\n ref={textRef}\n data-slot=\"tree-item-text\"\n // `truncate` clips at this span's padding box, so the typeahead pill — 2px of padding plus a\n // 1px ring outside the glyphs — needs room inside it: 4px of padding either side, with the\n // matching negative margin so the text itself does not move.\n className=\"-mx-1 min-w-0 flex-1 truncate px-1\"\n >\n <TreeItemText match={typeaheadMatch}>{children}</TreeItemText>\n </span>\n </TooltipTrigger>\n {/*\n A purely visual repair for clipped text. The trigger is a plain `span`, so it never takes\n focus and this only ever opens on hover — and the node's accessible name already carries\n the label in full, so a screen reader is not relying on it.\n */}\n <TooltipContent>{children}</TooltipContent>\n </Tooltip>\n {trailing ? (\n <span data-slot=\"tree-item-trailing\" className=\"ml-auto flex shrink-0 items-center gap-1 [&_svg]:size-3.5\">\n {trailing}\n </span>\n ) : null}\n </div>\n );\n}\n\n/**\n * The label text, with the live typeahead prefix highlighted when it matches. Only a plain-string\n * label can be split; a composed label still matches for navigation, it just gets no highlight.\n */\nfunction TreeItemText({ match, children }: { match: TypeaheadMatch | null; children: React.ReactNode }) {\n if (!match || typeof children !== \"string\" || !children.toLowerCase().startsWith(match.query)) {\n return children;\n }\n const { query, fading } = match;\n return (\n <>\n <span\n data-slot=\"tree-item-typeahead-match\"\n data-state={fading ? \"fading\" : \"active\"}\n className={cn(\n // The SW-2445 selected-state tokens: a primary tint that reads as \"this is the match\" on\n // a resting, hovered or selected row, in both themes. Plain spans, not `<mark>`, so the\n // label's accessible name is unchanged.\n \"rounded-sm ring-1\",\n // Padding either side so the ring does not hug the glyphs, with a matching negative\n // margin so the rest of the label stays put while the highlight comes and goes.\n \"-mx-0.5 px-0.5\",\n // Eased out over the fade window rather than snapped off; the span itself is removed\n // only once the transition has finished.\n \"transition-[color,background-color,box-shadow] duration-700 ease-out motion-reduce:transition-none\",\n fading\n ? \"bg-transparent text-inherit ring-transparent\"\n : \"bg-selected text-selected-foreground ring-selected-border\",\n )}\n >\n {children.slice(0, query.length)}\n </span>\n {children.slice(query.length)}\n </>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TreeItemGroup\n * -----------------------------------------------------------------------------------------------*/\n\nfunction TreeItemGroup({ className, children, ...props }: React.ComponentProps<\"div\">) {\n const { expanded, level } = useTreeItemContext(\"TreeItemGroup\");\n\n // Not rendered while collapsed: keeps collapsed subtrees out of the accessibility tree entirely,\n // and makes DOM order equal visible order for keyboard traversal.\n if (!expanded) return null;\n\n return (\n <TreeLevelContext.Provider value={level + 1}>\n <div {...props} data-slot=\"tree-item-group\" role=\"group\" className={cn(\"flex flex-col\", className)}>\n <TreeItemsContainer>{children}</TreeItemsContainer>\n </div>\n </TreeLevelContext.Provider>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TreeEmpty\n * -----------------------------------------------------------------------------------------------*/\n\n/**\n * Placeholder row for a `Tree` (no root nodes) or a `TreeItemGroup` (a branch that is loading, came\n * back empty, or whose fetch failed) with nothing real to show (SW-2542; \"Load more\" is its sibling\n * `TreeLoadMore`, and the Storybook docs carry the full placement rationale for both). Renders as a\n * non-indexed, non-navigable `treeitem` rather than a\n * plain `<div>`: `role=\"tree\"` and `role=\"group\"` both require treeitem/group children per\n * WAI-ARIA's `aria-required-children`, so a bare paragraph would leave the container structurally\n * invalid — and some screen readers skip an invalid container's content entirely — the moment it is\n * the only child. Excluded from sibling indexing (`useIndexedTreeChildren` opts it out by identity)\n * and from keyboard traversal (`ITEM_SELECTOR` requires `data-tree-item-id`, which this does not\n * carry): there is nothing here to navigate to.\n *\n * Styled as a leaf row at this depth (read off the ambient `TreeLevelContext`, since this isn't a\n * `TreeItem` and gets no `level` of its own): the same height, inset, transparent border and\n * chevron spacer as a leaf `TreeItemLabel`, so the first child passed in lands in the icon column\n * and the next one in the text column — exactly where the node it stands in for would draw them.\n * Content is otherwise entirely up to the caller: a muted icon for an empty branch, a\n * destructive-toned one with \"Failed to load\" for an error, or a `Skeleton` pair for one still\n * loading. A skeleton-only placeholder has no text, so give it an\n * `aria-label` (\"Loading Shared\") — a `treeitem` needs an accessible name. Deliberately *not*\n * `aria-disabled`: Chromium's accessibility tree treats that as inherited by descendants (mirrored\n * by Playwright's actionability checks, which is how this was caught), so it would have made a\n * nested button unreachable by keyboard and screen readers, not just visually inert. A button inside\n * it must still stop its click from bubbling: it sits inside the enclosing `TreeItem`, whose click\n * handler walks up to the nearest treeitem and treats any unclaimed click as that node's\n * select/toggle.\n */\nfunction TreeEmpty({ className, children, style, ...props }: React.ComponentProps<\"div\">) {\n const level = React.useContext(TreeLevelContext);\n\n return (\n <div\n {...props}\n data-slot=\"tree-empty\"\n role=\"treeitem\"\n aria-selected=\"false\"\n tabIndex={-1}\n // The inset, the transparent border and the spacer below all mirror `TreeItemLabel`: drop any\n // one of them and the placeholder's icon lands in a sibling's chevron column instead of its\n // icon column.\n style={{ paddingInlineStart: `calc(var(--tree-indent) * ${level - 1} + 0.25rem)`, ...style }}\n className={cn(\n \"text-muted-foreground flex h-7 w-full min-w-0 items-center gap-1.5 rounded-md border border-transparent pr-2 text-left text-sm [&_svg]:size-4 [&_svg]:shrink-0\",\n className,\n )}\n >\n <span data-slot=\"tree-item-indicator-spacer\" aria-hidden=\"true\" className=\"size-3.5 shrink-0\" />\n {children}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------------------------------\n * TreeLoadMore\n * -----------------------------------------------------------------------------------------------*/\n\ntype TreeLoadMoreProps = Omit<React.ComponentProps<\"button\">, \"type\"> &\n VariantProps<typeof treeItemLabelVariants> & {\n /** Decorative leading icon, in the same column as a leaf `TreeItemLabel`'s `icon`. */\n icon?: React.ReactNode;\n };\n\n/**\n * \"Load more\" for a paginated branch — SW-2542's placement answer. Append it as the *last* child of\n * the `TreeItemGroup` (or `Tree`) it pages: a non-indexed `treeitem` like `TreeEmpty` (it never\n * claims a set slot from the real siblings above it, and arrow keys step past it), wrapping a real\n * `<button>` that fills the row and stays reachable in ordinary Tab order.\n *\n * The button is dressed as a leaf row rather than as a `Button`: same `treeItemLabelVariants` height\n * and radius, depth-correct inset, chevron spacer and icon column, and the same states — `bg-muted`\n * on hover, the `border-ring`/`shadow-focus` ring a keyboard-focused node shows, and while pressed\n * the `bg-accent` a clicked node settles into. Clicks stop here: an unclaimed click would bubble to\n * the enclosing `TreeItem` and select or collapse the branch being paged.\n */\nfunction TreeLoadMore({ className, children = \"Load more\", icon, size, style, onClick, ...props }: TreeLoadMoreProps) {\n const level = React.useContext(TreeLevelContext);\n\n return (\n <div data-slot=\"tree-load-more\" role=\"treeitem\" aria-selected=\"false\" className=\"flex w-full\">\n <button\n {...props}\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n onClick?.(event);\n }}\n style={{ paddingInlineStart: `calc(var(--tree-indent) * ${level - 1} + 0.25rem)`, ...style }}\n className={cn(\n treeItemLabelVariants({ size }),\n \"text-muted-foreground border border-transparent outline-none\",\n \"hover:bg-muted hover:text-foreground\",\n \"focus-visible:border-ring focus-visible:shadow-focus\",\n \"active:bg-accent active:text-accent-foreground\",\n className,\n )}\n >\n <span data-slot=\"tree-item-indicator-spacer\" aria-hidden=\"true\" className=\"size-3.5 shrink-0\" />\n {icon ? (\n <span\n data-slot=\"tree-item-icon\"\n aria-hidden=\"true\"\n className=\"flex size-4 shrink-0 items-center justify-center [&_svg]:size-4 [&_svg]:shrink-0\"\n >\n {icon}\n </span>\n ) : null}\n <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n </button>\n </div>\n );\n}\n\nexport {\n Tree,\n TreeEmpty,\n TreeItem,\n TreeItemGroup,\n TreeItemLabel,\n TreeLoadMore,\n treeItemLabelVariants,\n useTreeItem,\n type TreeGuides,\n type TreeItemLabelProps,\n type TreeItemProps,\n type TreeLoadMoreProps,\n type TreeProps,\n};\n"],"names":["TreeContext","React","TreeTypeaheadContext","useTreeContext","component","context","TreeLevelContext","TreeIndexContext","TreeItemContext","NO_TRUNKS","useTreeItemContext","useTreeItem","isPlaceholder","child","TreeEmpty","TreeLoadMore","useIndexedTreeChildren","children","array","elements","setsize","isBranch","lastBranchPos","last","index","posinset","jsx","ITEM_SELECTOR","getVisibleItems","root","CONTAINER_SELECTOR","findItem","id","element","getContainer","item","getAncestorIds","ids","ancestor","getAnnouncedText","node","text","getItemText","labelId","label","resolveFocusTarget","focusedId","ancestorIds","target","moveFocus","setFocusedId","TYPEAHEAD_TIMEOUT_MS","TYPEAHEAD_FADE_MS","navigateTo","event","stepBy","offset","items","TREE_KEY_HANDLERS","current","hasChildren","expanded","setExpanded","expandIds","container","isTypeaheadKey","typeaheadTo","typeahead","setTypeaheadMatch","buffer","query","char","start","candidate","Tree","className","expandedIdsProp","defaultExpandedIds","onExpandedChange","selectedIdProp","defaultSelectedId","onSelectedChange","onActivate","expandOnSelect","guides","onFocus","onBlur","props","treeRef","expandedIds","setExpandedIds","useControllableState","selectedId","setSelectedId","entryId","setEntryId","typeaheadMatch","focusedPathRef","hasFocusRef","typeaheadRef","next","activateItem","activatedId","handleItemKeyDown","handler","reconcileTabStop","targetId","active","cn","TooltipProvider","TreeItemsContainer","TreeItem","disabled","onClick","onKeyDown","style","onItemKeyDown","level","selected","toggle","select","isFirstRoot","defaultEntry","tabbable","inheritedTrunkLevels","trunkLevels","itemContext","treeItemLabelVariants","cva","TreeItemLabel","size","icon","trailing","showElbow","showGuides","textRef","tooltipOpen","setTooltipOpen","handleTooltipOpenChange","jsxs","trunkLevel","ChevronRightIcon","Tooltip","TooltipTrigger","TreeItemText","TooltipContent","match","fading","Fragment","TreeItemGroup"],"mappings":"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"}