@contractspec/lib.design-system 4.4.1 → 4.4.2

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/README.md CHANGED
@@ -232,11 +232,13 @@ import { AppShell } from "@contractspec/lib.design-system/shell";
232
232
  ```
233
233
 
234
234
  On desktop web, `AppShell` renders a collapsible sidebar, sticky topbar, content
235
- region, and optional `PageOutline` rail. The desktop topbar is inset beside the
236
- sidebar and includes a sidebar toggle. On small web screens, navigation and page
237
- outline move behind accessible menu triggers. On native, the shell maps primary
238
- navigation to bottom tabs and keeps overflow navigation, actions, user content,
239
- and page outline inside the menu sheet.
235
+ region, and optional floating `PageOutline`. The outline does not reserve a
236
+ right-side content column: it reduces to a slim rail while inactive and expands
237
+ on hover or keyboard focus, keeping wide page content centered. The desktop
238
+ topbar is inset beside the sidebar and includes a sidebar toggle. On small web
239
+ screens, navigation and page outline move behind accessible menu triggers. On
240
+ native, the shell maps primary navigation to bottom tabs and keeps overflow
241
+ navigation, actions, user content, and page outline inside the menu sheet.
240
242
 
241
243
  `AppShell` also accepts a prop-driven `notifications` center for in-app
242
244
  notifications. Hosts provide structural `items`, `unreadCount`, loading/empty
@@ -1 +1 @@
1
- import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"lg:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"grid min-h-0 flex-1 grid-cols-1 lg:grid-cols-[minmax(0,1fr)_240px]",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden px-4 py-5 lg:block",children:k(M,{items:V,activeId:E})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
1
+ import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"xl:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"min-h-0 flex-1",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden xl:block",children:k(M,{items:V,activeId:E,variant:"floating"})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
@@ -1 +1 @@
1
- import{jsx as H}from"react/jsx-runtime";import{cn as S}from"@contractspec/lib.ui-kit-web/ui/utils";import*as M from"react";import{resolvePageOutlineItems as U}from"./outline";export function PageOutline({items:z,activeId:E,onNavigate:J,ariaLabel:K="On this page",variant:F="rail",maxLevel:C=3,className:B,...D}){const G=M.useMemo(()=>U(z,C),[z,C]);if(!G.length)return null;return H("nav",{"aria-label":K,className:S("text-muted-foreground text-sm",F==="rail"?"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4":"rounded-md border p-3",B),...D,children:H("ol",{className:"m-0 list-none space-y-1 p-0",children:G.map((q)=>{const Q=E===q.id,T=q.href??`#${q.id}`;return H("li",{children:H("a",{href:T,"aria-current":Q?"location":void 0,onClick:()=>J?.(q),className:S("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",q.resolvedLevel===2&&"pl-5",q.resolvedLevel===3&&"pl-8 text-xs",Q&&"bg-accent font-medium text-accent-foreground"),children:q.label})},`${q.id}-${q.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(z,E){const[J,K]=M.useState(z[0]);M.useEffect(()=>{if(!z.length||typeof IntersectionObserver>"u")return;const F=new IntersectionObserver((C)=>{const B=C.filter((D)=>D.isIntersecting).sort((D,G)=>G.intersectionRatio-D.intersectionRatio)[0];if(B?.target.id)K(B.target.id)},E??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const C of z){const B=document.getElementById(C);if(B)F.observe(B)}return()=>F.disconnect()},[z,E]);return J}
1
+ import{jsx as G,jsxs as Y,Fragment as X}from"react/jsx-runtime";import{cn as M}from"@contractspec/lib.ui-kit-web/ui/utils";import*as U from"react";import{resolvePageOutlineItems as W}from"./outline";export function PageOutline({items:C,activeId:J,onNavigate:Q,ariaLabel:S="On this page",variant:B="rail",maxLevel:E=3,className:D,...H}){const K=U.useMemo(()=>W(C,E),[C,E]);if(!K.length)return null;return G("nav",{"aria-label":S,className:M("text-muted-foreground text-sm",B==="rail"&&"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4",B==="compact"&&"rounded-md border p-3",B==="floating"&&"group fixed top-24 right-4 z-20 hidden max-h-[calc(100svh-7rem)] w-10 overflow-hidden rounded-md border border-transparent bg-background/70 py-2 backdrop-blur-xs transition-[width,background-color,border-color,box-shadow] duration-200 focus-within:w-64 focus-within:border-border focus-within:bg-background/95 focus-within:shadow-md hover:w-64 hover:border-border hover:bg-background/95 hover:shadow-md xl:block",D),...H,children:G("ol",{className:M("m-0 list-none space-y-1 p-0",B==="floating"&&"w-64 pr-2"),children:K.map((z)=>{const T=J===z.id,V=z.href??`#${z.id}`;return G("li",{children:G("a",{href:V,"aria-current":T?"location":void 0,onClick:()=>Q?.(z),className:M("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",B==="floating"&&"grid grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 overflow-hidden",B!=="floating"&&z.resolvedLevel===2&&"pl-5",B!=="floating"&&z.resolvedLevel===3&&"pl-8 text-xs",B==="floating"&&z.resolvedLevel===3&&"text-xs",T&&"bg-accent font-medium text-accent-foreground"),children:B==="floating"?Y(X,{children:[G("span",{"aria-hidden":"true",className:M("h-1.5 w-1.5 rounded-full bg-border transition-colors",z.resolvedLevel===2&&"ml-1",z.resolvedLevel===3&&"ml-2 h-1 w-1",T&&"bg-accent-foreground")}),G("span",{className:"truncate opacity-0 transition-opacity duration-150 group-focus-within:opacity-100 group-hover:opacity-100",children:z.label})]}):z.label})},`${z.id}-${z.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(C,J){const[Q,S]=U.useState(C[0]);U.useEffect(()=>{if(!C.length||typeof IntersectionObserver>"u")return;const B=new IntersectionObserver((E)=>{const D=E.filter((H)=>H.isIntersecting).sort((H,K)=>K.intersectionRatio-H.intersectionRatio)[0];if(D?.target.id)S(D.target.id)},J??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const E of C){const D=document.getElementById(E);if(D)B.observe(D)}return()=>B.disconnect()},[C,J]);return Q}
@@ -1 +1 @@
1
- import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"lg:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"grid min-h-0 flex-1 grid-cols-1 lg:grid-cols-[minmax(0,1fr)_240px]",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden px-4 py-5 lg:block",children:k(M,{items:V,activeId:E})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
1
+ import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"xl:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"min-h-0 flex-1",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden xl:block",children:k(M,{items:V,activeId:E,variant:"floating"})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
@@ -5,7 +5,7 @@ export interface PageOutlineProps extends React.HTMLAttributes<HTMLElement> {
5
5
  activeId?: string;
6
6
  onNavigate?: (item: PageOutlineItem) => void;
7
7
  ariaLabel?: string;
8
- variant?: 'rail' | 'compact';
8
+ variant?: 'rail' | 'compact' | 'floating';
9
9
  maxLevel?: PageOutlineLevel;
10
10
  }
11
11
  export declare function PageOutline({ items, activeId, onNavigate, ariaLabel, variant, maxLevel, className, ...props }: PageOutlineProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1 +1 @@
1
- import{jsx as H}from"react/jsx-runtime";import{cn as S}from"@contractspec/lib.ui-kit-web/ui/utils";import*as M from"react";import{resolvePageOutlineItems as U}from"./outline";export function PageOutline({items:z,activeId:E,onNavigate:J,ariaLabel:K="On this page",variant:F="rail",maxLevel:C=3,className:B,...D}){const G=M.useMemo(()=>U(z,C),[z,C]);if(!G.length)return null;return H("nav",{"aria-label":K,className:S("text-muted-foreground text-sm",F==="rail"?"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4":"rounded-md border p-3",B),...D,children:H("ol",{className:"m-0 list-none space-y-1 p-0",children:G.map((q)=>{const Q=E===q.id,T=q.href??`#${q.id}`;return H("li",{children:H("a",{href:T,"aria-current":Q?"location":void 0,onClick:()=>J?.(q),className:S("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",q.resolvedLevel===2&&"pl-5",q.resolvedLevel===3&&"pl-8 text-xs",Q&&"bg-accent font-medium text-accent-foreground"),children:q.label})},`${q.id}-${q.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(z,E){const[J,K]=M.useState(z[0]);M.useEffect(()=>{if(!z.length||typeof IntersectionObserver>"u")return;const F=new IntersectionObserver((C)=>{const B=C.filter((D)=>D.isIntersecting).sort((D,G)=>G.intersectionRatio-D.intersectionRatio)[0];if(B?.target.id)K(B.target.id)},E??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const C of z){const B=document.getElementById(C);if(B)F.observe(B)}return()=>F.disconnect()},[z,E]);return J}
1
+ import{jsx as G,jsxs as Y,Fragment as X}from"react/jsx-runtime";import{cn as M}from"@contractspec/lib.ui-kit-web/ui/utils";import*as U from"react";import{resolvePageOutlineItems as W}from"./outline";export function PageOutline({items:C,activeId:J,onNavigate:Q,ariaLabel:S="On this page",variant:B="rail",maxLevel:E=3,className:D,...H}){const K=U.useMemo(()=>W(C,E),[C,E]);if(!K.length)return null;return G("nav",{"aria-label":S,className:M("text-muted-foreground text-sm",B==="rail"&&"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4",B==="compact"&&"rounded-md border p-3",B==="floating"&&"group fixed top-24 right-4 z-20 hidden max-h-[calc(100svh-7rem)] w-10 overflow-hidden rounded-md border border-transparent bg-background/70 py-2 backdrop-blur-xs transition-[width,background-color,border-color,box-shadow] duration-200 focus-within:w-64 focus-within:border-border focus-within:bg-background/95 focus-within:shadow-md hover:w-64 hover:border-border hover:bg-background/95 hover:shadow-md xl:block",D),...H,children:G("ol",{className:M("m-0 list-none space-y-1 p-0",B==="floating"&&"w-64 pr-2"),children:K.map((z)=>{const T=J===z.id,V=z.href??`#${z.id}`;return G("li",{children:G("a",{href:V,"aria-current":T?"location":void 0,onClick:()=>Q?.(z),className:M("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",B==="floating"&&"grid grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 overflow-hidden",B!=="floating"&&z.resolvedLevel===2&&"pl-5",B!=="floating"&&z.resolvedLevel===3&&"pl-8 text-xs",B==="floating"&&z.resolvedLevel===3&&"text-xs",T&&"bg-accent font-medium text-accent-foreground"),children:B==="floating"?Y(X,{children:[G("span",{"aria-hidden":"true",className:M("h-1.5 w-1.5 rounded-full bg-border transition-colors",z.resolvedLevel===2&&"ml-1",z.resolvedLevel===3&&"ml-2 h-1 w-1",T&&"bg-accent-foreground")}),G("span",{className:"truncate opacity-0 transition-opacity duration-150 group-focus-within:opacity-100 group-hover:opacity-100",children:z.label})]}):z.label})},`${z.id}-${z.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(C,J){const[Q,S]=U.useState(C[0]);U.useEffect(()=>{if(!C.length||typeof IntersectionObserver>"u")return;const B=new IntersectionObserver((E)=>{const D=E.filter((H)=>H.isIntersecting).sort((H,K)=>K.intersectionRatio-H.intersectionRatio)[0];if(D?.target.id)S(D.target.id)},J??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const E of C){const D=document.getElementById(E);if(D)B.observe(D)}return()=>B.disconnect()},[C,J]);return Q}
@@ -4,6 +4,7 @@ export interface PageOutlineProps {
4
4
  activeId?: string;
5
5
  onNavigate?: (item: PageOutlineItem) => void;
6
6
  ariaLabel?: string;
7
+ variant?: 'rail' | 'compact' | 'floating';
7
8
  maxLevel?: PageOutlineLevel;
8
9
  className?: string;
9
10
  }
@@ -1 +1 @@
1
- import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"lg:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"grid min-h-0 flex-1 grid-cols-1 lg:grid-cols-[minmax(0,1fr)_240px]",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden px-4 py-5 lg:block",children:k(M,{items:V,activeId:E})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
1
+ import{jsx as k,jsxs as z}from"react/jsx-runtime";import{Dialog as P,DialogContent as B,DialogHeader as D,DialogTitle as T}from"@contractspec/lib.ui-kit-web/ui/dialog";import{SidebarInset as g,SidebarProvider as h,SidebarTrigger as u}from"@contractspec/lib.ui-kit-web/ui/sidebar";import{cn as U}from"@contractspec/lib.ui-kit-web/ui/utils";import{MenuIcon as _,PanelRightIcon as x}from"lucide-react";import*as C from"react";import{Button as I}from"../atoms/Button";import{NavBrand as f}from"../atoms/NavBrand";import{Breadcrumbs as d}from"../molecules/Breadcrumbs";import{CommandSearchTrigger as j}from"../molecules/CommandSearchTrigger";import{PageOutline as M}from"./PageOutline";import{ShellNotifications as l}from"./ShellNotifications";import{ShellSidebar as o}from"./ShellSidebar";function r({sections:q,activeHref:G}){return k("nav",{className:"flex flex-col gap-5","aria-label":"Application navigation",children:q.map((F,J)=>z("div",{className:"flex flex-col gap-2",children:[F.title&&k("div",{className:"font-medium text-muted-foreground text-xs uppercase tracking-wide",children:F.title}),k("div",{className:"flex flex-col gap-1",children:F.items.map((A)=>k(N,{item:A,activeHref:G},A.key??A.href??String(A.label)))})]},F.key??J))})}function N({item:q,activeHref:G,depth:F=0}){const J=q.active||Boolean(q.href)&&Boolean(G)&&(q.match==="startsWith"?G?.startsWith(q.href??""):G===q.href),A=z("span",{className:U("inline-flex min-w-0 items-center gap-2",F>0&&"pl-4"),children:[q.icon,k("span",{className:"truncate",children:q.label}),q.badge?k("span",{className:"ml-auto text-muted-foreground text-xs",children:q.badge}):null]}),Q=q.disabled||q.policyDecision?.effect==="deny";return z("div",{className:"flex flex-col gap-1",children:[q.href&&!Q?k("a",{href:q.href,target:q.target,"aria-current":J?"page":void 0,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-sm hover:bg-accent hover:text-accent-foreground",J&&"bg-accent font-medium text-accent-foreground"),children:A}):k("button",{type:"button","aria-disabled":Q||void 0,disabled:Q,"aria-label":q.ariaLabel,onClick:()=>q.onSelect?.(),className:U("rounded-xs px-2 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50",J&&"bg-accent font-medium text-accent-foreground"),children:A}),q.children?.length?k("div",{className:"flex flex-col gap-1",children:q.children.map((K)=>k(N,{item:K,activeHref:G,depth:F+1},K.key??K.href??String(K.label)))}):null]})}export function AppShell({brand:q,logo:G,title:F,homeHref:J,navigation:A=[],commands:Q=[],notifications:K,breadcrumbs:Z=[],pageOutline:V=[],activeHref:$,activeOutlineId:E,userMenu:W,topbarStart:S,topbarEnd:H,children:b,className:p,contentClassName:O,onNavigate:m}){const[v,L]=C.useState(!1),[w,X]=C.useState(!1),R=q??k(f,{href:J,logo:G,title:F}),Y=(y=!1)=>Q.length?k(j,{groups:Q,placeholder:"Search or run action...",compact:y}):null;return z("div",{className:U("min-h-svh bg-background",p),children:[z(h,{children:[k(o,{sections:A,brand:R,commandTrigger:Y(),footer:W,activeHref:$,withProvider:!1}),z(g,{className:"min-h-svh min-w-0",children:[k("header",{className:"sticky top-0 z-30 border-b bg-background/95 backdrop-blur-xs supports-backdrop-filter:bg-background/60",children:z("div",{className:"flex h-14 min-w-0 items-center gap-3 px-3 md:px-4",children:[k(I,{variant:"ghost",size:"icon",className:"md:hidden",ariaLabelI18n:"Open navigation",onPress:()=>L(!0),children:k(_,{className:"h-4 w-4"})}),k(u,{"aria-label":"Toggle sidebar",className:"hidden md:inline-flex"}),k("div",{className:"min-w-0 md:hidden",children:R}),k("div",{className:"hidden min-w-0 md:block",children:S}),k("div",{className:"min-w-0 flex-1 overflow-hidden",children:Z.length?k(d,{items:Z}):null}),k("div",{className:"hidden shrink-0 md:block",children:Y()}),V.length?k(I,{variant:"ghost",size:"icon",className:"xl:hidden",ariaLabelI18n:"Open page outline",onPress:()=>X(!0),children:k(x,{className:"h-4 w-4"})}):null,z("div",{className:"flex shrink-0 items-center gap-2",children:[K?k(l,{notifications:K}):null,H,W]})]})}),z("div",{className:"min-h-0 flex-1",children:[k("div",{className:U("min-w-0 px-4 py-5 md:px-6",O),children:b}),V.length?k("aside",{className:"hidden xl:block",children:k(M,{items:V,activeId:E,variant:"floating"})}):null]})]})]}),k(P,{open:v,onOpenChange:L,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"Menu"})}),z("div",{className:"flex flex-col gap-4",children:[Y(),k(r,{sections:A,activeHref:$}),W]})]})}),k(P,{open:w,onOpenChange:X,children:z(B,{className:"max-h-[85svh] overflow-auto sm:max-w-sm",children:[k(D,{children:k(T,{children:"On this page"})}),k(M,{items:V,activeId:E,variant:"compact",onNavigate:()=>X(!1)})]})})]})}
@@ -1 +1 @@
1
- import{jsx as H}from"react/jsx-runtime";import{cn as S}from"@contractspec/lib.ui-kit-web/ui/utils";import*as M from"react";import{resolvePageOutlineItems as U}from"./outline";export function PageOutline({items:z,activeId:E,onNavigate:J,ariaLabel:K="On this page",variant:F="rail",maxLevel:C=3,className:B,...D}){const G=M.useMemo(()=>U(z,C),[z,C]);if(!G.length)return null;return H("nav",{"aria-label":K,className:S("text-muted-foreground text-sm",F==="rail"?"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4":"rounded-md border p-3",B),...D,children:H("ol",{className:"m-0 list-none space-y-1 p-0",children:G.map((q)=>{const Q=E===q.id,T=q.href??`#${q.id}`;return H("li",{children:H("a",{href:T,"aria-current":Q?"location":void 0,onClick:()=>J?.(q),className:S("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",q.resolvedLevel===2&&"pl-5",q.resolvedLevel===3&&"pl-8 text-xs",Q&&"bg-accent font-medium text-accent-foreground"),children:q.label})},`${q.id}-${q.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(z,E){const[J,K]=M.useState(z[0]);M.useEffect(()=>{if(!z.length||typeof IntersectionObserver>"u")return;const F=new IntersectionObserver((C)=>{const B=C.filter((D)=>D.isIntersecting).sort((D,G)=>G.intersectionRatio-D.intersectionRatio)[0];if(B?.target.id)K(B.target.id)},E??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const C of z){const B=document.getElementById(C);if(B)F.observe(B)}return()=>F.disconnect()},[z,E]);return J}
1
+ import{jsx as G,jsxs as Y,Fragment as X}from"react/jsx-runtime";import{cn as M}from"@contractspec/lib.ui-kit-web/ui/utils";import*as U from"react";import{resolvePageOutlineItems as W}from"./outline";export function PageOutline({items:C,activeId:J,onNavigate:Q,ariaLabel:S="On this page",variant:B="rail",maxLevel:E=3,className:D,...H}){const K=U.useMemo(()=>W(C,E),[C,E]);if(!K.length)return null;return G("nav",{"aria-label":S,className:M("text-muted-foreground text-sm",B==="rail"&&"sticky top-20 max-h-[calc(100svh-6rem)] overflow-auto border-l pl-4",B==="compact"&&"rounded-md border p-3",B==="floating"&&"group fixed top-24 right-4 z-20 hidden max-h-[calc(100svh-7rem)] w-10 overflow-hidden rounded-md border border-transparent bg-background/70 py-2 backdrop-blur-xs transition-[width,background-color,border-color,box-shadow] duration-200 focus-within:w-64 focus-within:border-border focus-within:bg-background/95 focus-within:shadow-md hover:w-64 hover:border-border hover:bg-background/95 hover:shadow-md xl:block",D),...H,children:G("ol",{className:M("m-0 list-none space-y-1 p-0",B==="floating"&&"w-64 pr-2"),children:K.map((z)=>{const T=J===z.id,V=z.href??`#${z.id}`;return G("li",{children:G("a",{href:V,"aria-current":T?"location":void 0,onClick:()=>Q?.(z),className:M("block rounded-xs px-2 py-1 transition-colors hover:bg-accent hover:text-accent-foreground",B==="floating"&&"grid grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 overflow-hidden",B!=="floating"&&z.resolvedLevel===2&&"pl-5",B!=="floating"&&z.resolvedLevel===3&&"pl-8 text-xs",B==="floating"&&z.resolvedLevel===3&&"text-xs",T&&"bg-accent font-medium text-accent-foreground"),children:B==="floating"?Y(X,{children:[G("span",{"aria-hidden":"true",className:M("h-1.5 w-1.5 rounded-full bg-border transition-colors",z.resolvedLevel===2&&"ml-1",z.resolvedLevel===3&&"ml-2 h-1 w-1",T&&"bg-accent-foreground")}),G("span",{className:"truncate opacity-0 transition-opacity duration-150 group-focus-within:opacity-100 group-hover:opacity-100",children:z.label})]}):z.label})},`${z.id}-${z.resolvedLevel}`)})})})}export function usePageOutlineActiveItem(C,J){const[Q,S]=U.useState(C[0]);U.useEffect(()=>{if(!C.length||typeof IntersectionObserver>"u")return;const B=new IntersectionObserver((E)=>{const D=E.filter((H)=>H.isIntersecting).sort((H,K)=>K.intersectionRatio-H.intersectionRatio)[0];if(D?.target.id)S(D.target.id)},J??{rootMargin:"-20% 0px -65% 0px",threshold:[0,0.25,0.5,1]});for(const E of C){const D=document.getElementById(E);if(D)B.observe(D)}return()=>B.disconnect()},[C,J]);return Q}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/lib.design-system",
3
- "version": "4.4.1",
3
+ "version": "4.4.2",
4
4
  "description": "Design tokens and theming primitives",
5
5
  "keywords": [
6
6
  "contractspec",
@@ -31,16 +31,16 @@
31
31
  "sideEffects": false,
32
32
  "tree-shake": true,
33
33
  "dependencies": {
34
- "@contractspec/lib.ai-agent": "8.0.15",
35
- "@contractspec/lib.contracts-runtime-client-react": "3.14.0",
36
- "@contractspec/lib.contracts-spec": "6.2.0",
37
- "@contractspec/lib.presentation-runtime-core": "5.2.1",
38
- "@contractspec/lib.presentation-runtime-react": "40.0.1",
34
+ "@contractspec/lib.ai-agent": "8.0.16",
35
+ "@contractspec/lib.contracts-runtime-client-react": "3.14.1",
36
+ "@contractspec/lib.contracts-spec": "6.3.0",
37
+ "@contractspec/lib.presentation-runtime-core": "5.2.2",
38
+ "@contractspec/lib.presentation-runtime-react": "40.0.2",
39
39
  "@contractspec/lib.schema": "3.7.14",
40
- "@contractspec/lib.translation-runtime": "0.2.0",
41
- "@contractspec/lib.ui-kit": "4.1.4",
42
- "@contractspec/lib.ui-kit-core": "3.8.7",
43
- "@contractspec/lib.ui-kit-web": "3.13.2",
40
+ "@contractspec/lib.translation-runtime": "0.2.1",
41
+ "@contractspec/lib.ui-kit": "4.1.5",
42
+ "@contractspec/lib.ui-kit-core": "3.8.8",
43
+ "@contractspec/lib.ui-kit-web": "3.13.3",
44
44
  "@hookform/resolvers": "5.2.2",
45
45
  "class-variance-authority": "^0.7.1",
46
46
  "clsx": "^2.1.1",