@tetrascience-npm/tetrascience-react-ui 1.0.0-beta.145.1 → 1.0.0-beta.147.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/tree.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),K=require("@radix-ui/react-use-controllable-state"),Y=require("class-variance-authority"),J=require("lucide-react"),Q=require("react"),D=require("./tooltip.cjs"),k=require("../lib/utils.cjs");function X(e){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const s=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,s.get?s:{enumerable:!0,get:()=>e[t]})}}return r.default=e,Object.freeze(r)}const n=X(Q),B=n.createContext(null);function F(e){const r=n.useContext(B);if(!r)throw new Error(`\`${e}\` must be rendered inside a \`Tree\`.`);return r}const A=n.createContext(1),G=n.createContext({posinset:1,setsize:1,lastBranchPos:0}),O=n.createContext(null),Z=[];function M(e){const r=n.useContext(O);if(!r)throw new Error(`\`${e}\` must be rendered inside a \`TreeItem\`.`);return r}function ee(){return M("useTreeItem")}function te(e){return n.useMemo(()=>{const r=n.Children.toArray(e),t=r.filter(n.isValidElement),s=t.length,l=u=>u.props?.hasChildren===!0,d=t.reduce((u,p,b)=>l(p)?b+1:u,0);let x=0;return r.map((u,p)=>n.isValidElement(u)?(x+=1,o.jsx(G.Provider,{value:{posinset:x,setsize:s,lastBranchPos:d},children:u},u.key??p)):u)},[e])}const z='[role="treeitem"]';function q(e){return e?[...e.querySelectorAll(z)]:[]}function re(e,r){const t=e?.dataset.treeItemId;!e||!t||(r(t),e.focus())}function R({event:e,setFocusedId:r},t){e.preventDefault(),re(t,r)}function $(e,r){const t=q(e.root);R(e,t[t.indexOf(e.current)+r])}const ne={ArrowDown:e=>$(e,1),ArrowUp:e=>$(e,-1),ArrowRight:e=>{const{event:r,current:t,id:s,hasChildren:l,expanded:d,setExpanded:x}=e;if(l&&!d){r.preventDefault(),x(s,!0);return}d&&R(e,t.querySelector(z))},ArrowLeft:e=>{const{event:r,current:t,id:s,expanded:l,setExpanded:d}=e;if(l){r.preventDefault(),d(s,!1);return}R(e,t.parentElement?.closest(z))},Home:e=>R(e,q(e.root)[0]),End:e=>{const r=q(e.root);R(e,r[r.length-1])},Enter:e=>{e.disabled||(e.event.preventDefault(),e.activate(e.id,e.hasChildren,e.expanded))}};function se({className:e,children:r,expandedIds:t,defaultExpandedIds:s,onExpandedChange:l,selectedId:d,defaultSelectedId:x=null,onSelectedChange:u,onActivate:p,expandOnSelect:b=!0,guides:C="hover",...E}){const S=n.useRef(null),[j,N]=K.useControllableState({prop:t,defaultProp:s??new Set,onChange:l}),[g,P]=K.useControllableState({prop:d,defaultProp:x,onChange:a=>{a!=null&&u?.(a)}}),[m,v]=n.useState(null),h=n.useCallback((a,I)=>{N(c=>{const y=new Set(c);return I?y.add(a):y.delete(a),y})},[N]),T=n.useCallback((a,I,c)=>{P(a),b&&I&&h(a,!c),p?.(a)},[P,b,h,p]),w=n.useCallback(a=>{const I=S.current,c=a.target?.closest(z),y=c?.dataset.treeItemId;if(!I||!c||!y||!I.contains(c))return;const L=ne[a.key];L&&L({event:a,root:I,current:c,id:y,hasChildren:c.dataset.treeHasChildren==="true",expanded:c.getAttribute("aria-expanded")==="true",disabled:c.getAttribute("aria-disabled")==="true",setExpanded:h,setFocusedId:v,activate:T})},[h,T]),i=n.useMemo(()=>({expandedIds:j??new Set,setExpanded:h,selectedId:g??null,activateItem:T,focusedId:m,setFocusedId:v,expandOnSelect:b,guides:C,onItemKeyDown:w}),[j,h,g,T,m,b,C,w]);return o.jsx(B.Provider,{value:i,children:o.jsx(A.Provider,{value:1,children:o.jsx("div",{ref:S,"data-slot":"tree","data-guides":C,role:"tree",tabIndex:-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),...E,children:o.jsx(D.TooltipProvider,{delayDuration:500,children:o.jsx(H,{children:r})})})})})}function H({children:e}){return te(e)}function oe({className:e,children:r,id:t,hasChildren:s=!1,disabled:l=!1,onClick:d,onFocus:x,onKeyDown:u,style:p,...b}){const{expandedIds:C,setExpanded:E,selectedId:S,activateItem:j,focusedId:N,setFocusedId:g,onItemKeyDown:P}=F("TreeItem"),m=n.useContext(A),{posinset:v,setsize:h,lastBranchPos:T}=n.useContext(G),w=`${n.useId()}-label`,i=s&&C.has(t),a=S===t,I=n.useCallback(()=>{s&&E(t,!i)},[s,E,t,i]),c=n.useCallback(()=>{l||(g(t),j(t,s,i))},[l,g,t,j,s,i]),y=N?N===t:m===1&&v===1,_=n.useContext(O)?.trunkLevels??Z,V=n.useMemo(()=>m>1&&v<T?[..._,m-1]:_,[_,m,v,T]),W=n.useMemo(()=>({id:t,labelId:w,level:m,expanded:i,hasChildren:s,selected:a,disabled:l,trunkLevels:V,toggle:I,select:c}),[t,w,m,i,s,a,l,V,I,c]);return o.jsx(O.Provider,{value:W,children:o.jsx("div",{...b,"data-slot":"tree-item","data-tree-item-id":t,"data-tree-has-children":s,"data-state":i?"expanded":"collapsed",role:"treeitem","aria-labelledby":w,"aria-expanded":s?i:void 0,"aria-level":m,"aria-posinset":v,"aria-setsize":h,"aria-selected":a,"aria-disabled":l||void 0,tabIndex:y?0:-1,onKeyDown:f=>{u?.(f),!f.defaultPrevented&&P(f)},onClick:f=>{d?.(f),!f.defaultPrevented&&f.target.closest(z)===f.currentTarget&&c()},onFocus:f=>{x?.(f),f.target===f.currentTarget&&g(t)},style:{"--tree-guide-left":`calc(var(--tree-indent) * ${m-2} + 0.6875rem)`,"--tree-elbow-run":"calc(var(--tree-indent) - 0.6875rem)","--tree-elbow-radius":"0.5rem",...p},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 U=Y.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 ae({className:e,children:r,size:t,style:s,icon:l,trailing:d,...x}){const{labelId:u,level:p,expanded:b,hasChildren:C,selected:E,disabled:S,trunkLevels:j,toggle:N}=M("TreeItemLabel"),{guides:g}=F("TreeItemLabel"),P=g!=="none"&&p>1&&C,m=g!=="none"&&(P||j.length>0),v=n.useRef(null),[h,T]=n.useState(!1),w=i=>{const a=v.current;T(i&&!!a&&a.scrollWidth>a.clientWidth)};return o.jsxs("div",{...x,id:u,"data-slot":"tree-item-label",style:{paddingInlineStart:`calc(var(--tree-indent) * ${p-1} + 0.25rem)`,...s},className:k.cn(U({size:t}),"relative border border-transparent",E?"bg-accent text-accent-foreground font-medium":"hover:bg-muted",S&&"pointer-events-none opacity-50",e),children:[m?o.jsxs("span",{"data-slot":"tree-item-guides","aria-hidden":"true",className:k.cn("pointer-events-none absolute inset-0",g==="hover"&&"opacity-0 transition-opacity group-hover/tree:opacity-100 motion-reduce:transition-none"),children:[j.map(i=>o.jsx("span",{"data-slot":"tree-item-guide-trunk",style:{left:`calc(var(--tree-indent) * ${i-1} + 0.6875rem)`},className:"absolute top-[-0.4375rem] bottom-0 w-0 border-l border-[var(--tree-guide-color)]"},i)),P?o.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,C?o.jsx("span",{"data-slot":"tree-item-indicator","aria-hidden":"true",onClick:i=>{i.stopPropagation(),N()},className:"flex size-3.5 shrink-0 items-center justify-center text-muted-foreground",children:o.jsx(J.ChevronRightIcon,{className:k.cn("size-3.5 transition-transform",b&&"rotate-90")})}):o.jsx("span",{"data-slot":"tree-item-indicator-spacer","aria-hidden":"true",className:"size-3.5 shrink-0"}),l?o.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",E?"text-accent-foreground":"text-muted-foreground"),children:l}):null,o.jsxs(D.Tooltip,{open:h,onOpenChange:w,children:[o.jsx(D.TooltipTrigger,{asChild:!0,children:o.jsx("span",{ref:v,className:"min-w-0 flex-1 truncate",children:r})}),o.jsx(D.TooltipContent,{children:r})]}),d?o.jsx("span",{"data-slot":"tree-item-trailing",className:"ml-auto flex shrink-0 items-center gap-1 [&_svg]:size-3.5",children:d}):null]})}function le({className:e,children:r,...t}){const{expanded:s,level:l}=M("TreeItemGroup");return s?o.jsx(A.Provider,{value:l+1,children:o.jsx("div",{...t,"data-slot":"tree-item-group",role:"group",className:k.cn("flex flex-col",e),children:o.jsx(H,{children:r})})}):null}exports.Tree=se;exports.TreeItem=oe;exports.TreeItemGroup=le;exports.TreeItemLabel=ae;exports.treeItemLabelVariants=U;exports.useTreeItem=ee;
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;
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 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 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\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\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\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 setFocusedId: (id: string) => void;\n activate: (id: string, hasChildren: boolean, expanded: boolean) => 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};\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 ...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\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 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\n const handler = TREE_KEY_HANDLERS[event.key];\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 setFocusedId,\n activate: activateItem,\n });\n },\n [setExpanded, activateItem],\n );\n\n const context = React.useMemo<TreeContextValue>(\n () => ({\n expandedIds: expandedIds ?? new Set<string>(),\n setExpanded,\n selectedId: selectedId ?? null,\n activateItem,\n focusedId,\n setFocusedId,\n expandOnSelect,\n guides,\n onItemKeyDown: handleItemKeyDown,\n }),\n [expandedIds, setExpanded, selectedId, activateItem, focusedId, expandOnSelect, guides, handleItemKeyDown],\n );\n\n return (\n <TreeContext.Provider value={context}>\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 // `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 </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, 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, minimal form: the focused node is the single tab stop, falling back to the\n // first root node before the tree has been entered. SW-2541 extends this (selection-aware entry\n // point, focus retention across collapse and lazy load).\n const tabbable = focusedId ? focusedId === id : level === 1 && posinset === 1;\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\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 ref={textRef} className=\"min-w-0 flex-1 truncate\">\n {children}\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\n data-slot=\"tree-item-trailing\"\n className=\"ml-auto flex shrink-0 items-center gap-1 [&_svg]:size-3.5\"\n >\n {trailing}\n </span>\n ) : null}\n </div>\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","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","moveFocus","element","setFocusedId","id","navigateTo","event","stepBy","offset","items","TREE_KEY_HANDLERS","current","hasChildren","expanded","setExpanded","Tree","className","expandedIdsProp","defaultExpandedIds","onExpandedChange","selectedIdProp","defaultSelectedId","onSelectedChange","onActivate","expandOnSelect","guides","props","treeRef","expandedIds","setExpandedIds","useControllableState","selectedId","setSelectedId","focusedId","next","activateItem","activatedId","handleItemKeyDown","handler","cn","TooltipProvider","TreeItemsContainer","TreeItem","disabled","onClick","onFocus","onKeyDown","style","onItemKeyDown","level","labelId","selected","toggle","select","tabbable","inheritedTrunkLevels","trunkLevels","itemContext","treeItemLabelVariants","cva","TreeItemLabel","size","icon","trailing","showElbow","showGuides","textRef","tooltipOpen","setTooltipOpen","handleTooltipOpenChange","text","jsxs","trunkLevel","ChevronRightIcon","Tooltip","TooltipTrigger","TooltipContent","TreeItemGroup"],"mappings":"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"}
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":"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"}