@adea-ai/ui 0.115.0 → 0.115.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/components/layout/contextual-sidebar/contextual-sidebar.d.ts.map +1 -1
- package/dist/components/layout/contextual-sidebar/contextual-sidebar.js +1 -0
- package/dist/components/layout/contextual-sidebar/contextual-sidebar.js.map +1 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.d.ts.map +1 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.js +2 -2
- package/dist/components/layout/sidebar-nav/sidebar-nav.js.map +1 -1
- package/dist/components/layout/top-bar/top-bar.d.ts.map +1 -1
- package/dist/components/layout/top-bar/top-bar.js +1 -1
- package/dist/components/layout/top-bar/top-bar.js.map +1 -1
- package/dist/components/ui/modal-dialog/modal-dialog.d.ts +2 -1
- package/dist/components/ui/modal-dialog/modal-dialog.d.ts.map +1 -1
- package/dist/components/ui/modal-dialog/modal-dialog.js +3 -0
- package/dist/components/ui/modal-dialog/modal-dialog.js.map +1 -1
- package/dist/components/ui/resizable/resizable.d.ts.map +1 -1
- package/dist/components/ui/resizable/resizable.js +1 -1
- package/dist/components/ui/resizable/resizable.js.map +1 -1
- package/dist/r/src/components/layout/contextual-sidebar/contextual-sidebar.tsx +3 -0
- package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +11 -1
- package/dist/r/src/components/layout/top-bar/top-bar.tsx +7 -3
- package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +3 -1
- package/dist/r/src/components/ui/resizable/resizable.tsx +4 -3
- package/package.json +1 -1
- package/src/components/layout/contextual-sidebar/contextual-sidebar.tsx +3 -0
- package/src/components/layout/sidebar-nav/sidebar-nav.tsx +11 -1
- package/src/components/layout/top-bar/top-bar.tsx +7 -3
- package/src/components/ui/modal-dialog/modal-dialog.tsx +3 -1
- package/src/components/ui/resizable/resizable.tsx +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contextual-sidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/contextual-sidebar/contextual-sidebar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAe7C,MAAM,MAAM,8BAA8B,GAAG;IAC3C,wEAAwE;IACxE,MAAM,EAAE,OAAO,CAAA;IACf,qFAAqF;IACrF,WAAW,IAAI,WAAW,GAAG,SAAS,CAAA;CACvC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,qDAAqD;IACrD,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,eAAe,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACrC,8EAA8E;IAC9E,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACjC,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sEAAsE;IACtE,eAAe,CAAC,EAAE,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;IACnD,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9E,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IACnD,iEAAiE;IACjE,MAAM,CAAC,CAAC,OAAO,EAAE,8BAA8B,GAAG,GAAG,CAAC,OAAO,CAAA;IAC7D,0EAA0E;IAC1E,OAAO,CAAC,OAAO,EAAE,8BAA8B,GAAG,GAAG,CAAC,OAAO,CAAA;IAC7D,oEAAoE;IACpE,MAAM,CAAC,CAAC,OAAO,EAAE,8BAA8B,GAAG,GAAG,CAAC,OAAO,CAAA;IAC7D,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,aAAa,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"contextual-sidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/contextual-sidebar/contextual-sidebar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAe7C,MAAM,MAAM,8BAA8B,GAAG;IAC3C,wEAAwE;IACxE,MAAM,EAAE,OAAO,CAAA;IACf,qFAAqF;IACrF,WAAW,IAAI,WAAW,GAAG,SAAS,CAAA;CACvC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,qDAAqD;IACrD,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,eAAe,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACrC,8EAA8E;IAC9E,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACjC,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,sEAAsE;IACtE,eAAe,CAAC,EAAE,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;IACnD,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IAC9E,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IACnD,iEAAiE;IACjE,MAAM,CAAC,CAAC,OAAO,EAAE,8BAA8B,GAAG,GAAG,CAAC,OAAO,CAAA;IAC7D,0EAA0E;IAC1E,OAAO,CAAC,OAAO,EAAE,8BAA8B,GAAG,GAAG,CAAC,OAAO,CAAA;IAC7D,oEAAoE;IACpE,MAAM,CAAC,CAAC,OAAO,EAAE,8BAA8B,GAAG,GAAG,CAAC,OAAO,CAAA;IAC7D,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,aAAa,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACpC,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,eAmJ9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contextual-sidebar.js","names":["Accessor","JSX","Show","createSignal","createUniqueId","onCleanup","onMount","cn","SidebarNav","SidebarNavContent","SidebarNavFooter","SidebarNavHeader","SidebarNavTitle","PixelResizeHandle","MobileModule","MobileLoad","error","ContextualSidebarRenderContext","mobile","portalMount","HTMLElement","ContextualSidebarProps","id","label","title","titleVisibility","open","onOpenChange","width","minimum","maximum","step","wideViewportAtLoad","resizeLabel","restoreFocusRef","onSidebarElement","element","sidebarClass","sheetClass","headerClass","contentClass","footerClass","headingAs","header","context","Element","content","footer","onWidthChange","onWidthCommit","ContextualSidebar","props","isNarrowViewport","setIsNarrowViewport","mobileLoad","setMobileLoad","mobileRequested","loadMobile","then","module","mobileMount","setMobileMount","connected","mount","isConnected","undefined","media","window","matchMedia","updateViewport","wasNarrow","matches","addEventListener","removeEventListener","renderSidebar","navigationId","_$createComponent","as","aria-label","aria-hidden","inert","data-open","String","ref","node","queueMicrotask","class","children","when","side","value","controls","onChange","onCommit","fallback","_$memo","_wide","keyed","loaded","MobileSidebar","_$createComponent","_$memo"],"sources":["../../../../src/components/layout/contextual-sidebar/contextual-sidebar.tsx"],"sourcesContent":["import type { Accessor, JSX } from 'solid-js'\nimport { Show, createSignal, createUniqueId, onCleanup, onMount } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport {\n SidebarNav,\n SidebarNavContent,\n SidebarNavFooter,\n SidebarNavHeader,\n SidebarNavTitle,\n} from '../sidebar-nav/sidebar-nav'\nimport { PixelResizeHandle } from '../pixel-resize-handle/pixel-resize-handle'\n\ntype MobileModule = typeof import('./mobile-contextual-sidebar')\ntype MobileLoad = MobileModule | { error: unknown }\n\nexport type ContextualSidebarRenderContext = {\n /** Whether the slot is being rendered inside the modal mobile sheet. */\n mobile: boolean\n /** Mount nested popovers and menus inside the mobile dialog's accessibility tree. */\n portalMount(): HTMLElement | undefined\n}\n\nexport type ContextualSidebarProps = {\n /** Stable host id prefix; generated when omitted. */\n id?: string\n /** Landmark name shared by the desktop and mobile navigation. */\n label: string\n /** Visible navigation title and mobile dialog title. */\n title: string\n /**\n * Where the title row shows. `always` (default) draws it on desktop and in\n * the mobile sheet; `mobile` keeps the desktop title for assistive\n * technology only and drops the desktop row, for hosts whose top bar\n * already names the context. A `header` slot keeps the row visible.\n */\n titleVisibility?: 'always' | 'mobile'\n /** Host-controlled expanded state for the desktop panel and mobile dialog. */\n open: boolean\n onOpenChange(open: boolean): void\n /** Current host-owned pixel width, reflected by the resize handle. */\n width: number\n minimum: number\n maximum: number\n step?: number\n /** Pass the host's initial viewport seed to distinguish stale desktop state. */\n wideViewportAtLoad?: boolean\n resizeLabel?: string\n /** Stable external opener used when the modal mobile sheet closes. */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n /** Called with the nav node so a host can project width onto its layout root. */\n onSidebarElement?: (element: HTMLElement | undefined, mobile: boolean) => void\n /** Host-owned layout classes applied to both nav instances. */\n sidebarClass?: string\n /** Host-owned responsive constraints for the modal sheet. */\n sheetClass?: string\n headerClass?: string\n contentClass?: string\n footerClass?: string\n headingAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n /** Optional action/content slot alongside the shared heading. */\n header?(context: ContextualSidebarRenderContext): JSX.Element\n /** View-specific navigation rows, projects, rooms, files, or sessions. */\n content(context: ContextualSidebarRenderContext): JSX.Element\n /** Optional view-specific footer, such as an archive affordance. */\n footer?(context: ContextualSidebarRenderContext): JSX.Element\n onWidthChange(width: number): void\n onWidthCommit?(width: number): void\n}\n\n/**\n * ContextualSidebar.\n *\n * Shared navigation geometry and interaction policy for an application's\n * contextual sidebar. The host keeps ownership of the actual grid width,\n * persisted preference, open state, and view-specific navigation content.\n */\nexport function ContextualSidebar(props: ContextualSidebarProps) {\n const [isNarrowViewport, setIsNarrowViewport] = createSignal(false)\n const [mobileLoad, setMobileLoad] = createSignal<MobileLoad>()\n let mobileRequested = false\n // Keep the resolved component mounted across viewport changes for Sheet cleanup.\n const loadMobile = () => {\n if (mobileRequested) return\n mobileRequested = true\n // Native module caching shares successful loads without keeping a rejected promise.\n void import('./mobile-contextual-sidebar').then(\n (module) => {\n if (mobileRequested) setMobileLoad(module)\n },\n (error: unknown) => {\n if (mobileRequested) setMobileLoad({ error })\n }\n )\n }\n const [mobileMount, setMobileMount] = createSignal<\n { element: HTMLElement; connected: boolean } | undefined\n >()\n const id = props.id ?? `contextual-sidebar-${createUniqueId()}`\n const resizeLabel = () => props.resizeLabel ?? `Resize ${props.label}`\n const portalMount = () => {\n const mount = mobileMount()\n return mount?.connected && mount.element.isConnected ? mount.element : undefined\n }\n\n onMount(() => {\n const media = window.matchMedia('(max-width: 48rem)')\n const updateViewport = () => {\n const wasNarrow = isNarrowViewport()\n if (media.matches) loadMobile()\n // Close before mounting a modal. A desktop-expanded host state is not\n // mobile intent, and opening the Sheet for one frame can steal focus.\n if (media.matches && !wasNarrow) props.onOpenChange(false)\n setIsNarrowViewport(media.matches)\n }\n\n // A route can mount after a wide-loaded host crosses into mobile. Clear\n // that stale seed, but preserve a sidebar intentionally opened at a\n // narrow boot viewport.\n if (media.matches) loadMobile()\n if (media.matches && props.wideViewportAtLoad && props.open) props.onOpenChange(false)\n setIsNarrowViewport(media.matches)\n media.addEventListener('change', updateViewport)\n onCleanup(() => {\n mobileRequested = false\n media.removeEventListener('change', updateViewport)\n })\n })\n\n const renderSidebar = (mobile: boolean) => {\n let element: HTMLElement | undefined\n const context: ContextualSidebarRenderContext = {\n mobile,\n portalMount: () => (mobile ? portalMount() : undefined),\n }\n const navigationId = `${id}-${mobile ? 'mobile' : 'desktop'}`\n\n onCleanup(() => {\n if (mobile && mobileMount()?.element === element) setMobileMount(undefined)\n element = undefined\n props.onSidebarElement?.(undefined, mobile)\n })\n\n return (\n <SidebarNav\n as=\"aside\"\n id={navigationId}\n aria-label={props.label}\n aria-hidden={!mobile && !props.open ? 'true' : undefined}\n inert={!mobile && !props.open}\n data-contextual-sidebar={mobile ? 'mobile' : 'desktop'}\n data-open={mobile ? undefined : String(props.open)}\n ref={(node) => {\n element = node\n if (mobile) {\n setMobileMount({ element: node, connected: node.isConnected })\n queueMicrotask(() => {\n if (node.isConnected && mobileMount()?.element === node)\n setMobileMount({ element: node, connected: true })\n })\n }\n props.onSidebarElement?.(node, mobile)\n }}\n class={cn('relative h-full w-full max-w-full', props.sidebarClass)}\n >\n <Show when={!mobile && props.open}>\n <PixelResizeHandle\n side=\"left\"\n value={props.width}\n minimum={props.minimum}\n maximum={props.maximum}\n step={props.step}\n label={resizeLabel()}\n controls={navigationId}\n onChange={props.onWidthChange}\n onCommit={props.onWidthCommit}\n />\n </Show>\n <Show when={!mobile || mobileMount()?.connected}>\n <Show\n when={mobile || props.titleVisibility !== 'mobile' || props.header}\n fallback={\n <SidebarNavTitle as={props.headingAs ?? 'h2'} class=\"sr-only\">\n {props.title}\n </SidebarNavTitle>\n }\n >\n <SidebarNavHeader class={cn(mobile && 'pe-12', props.headerClass)}>\n <SidebarNavTitle as={props.headingAs ?? 'h2'}>{props.title}</SidebarNavTitle>\n {props.header?.(context)}\n </SidebarNavHeader>\n </Show>\n <SidebarNavContent class={props.contentClass}>{props.content(context)}</SidebarNavContent>\n {props.footer ? (\n <SidebarNavFooter class={props.footerClass}>{props.footer(context)}</SidebarNavFooter>\n ) : null}\n </Show>\n </SidebarNav>\n )\n }\n\n return (\n <>\n <Show when={!isNarrowViewport()}>{(_wide) => renderSidebar(false)}</Show>\n <Show when={mobileLoad()} keyed>\n {(loaded) => {\n if ('error' in loaded) throw loaded.error\n return (\n <loaded.MobileSidebar\n open={isNarrowViewport() && props.open}\n onOpenChange={props.onOpenChange}\n label={props.label}\n sheetClass={props.sheetClass}\n restoreFocusRef={props.restoreFocusRef}\n renderSidebar={() => renderSidebar(true)}\n />\n )\n }}\n </Show>\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"contextual-sidebar.js","names":["Accessor","JSX","Show","createSignal","createUniqueId","onCleanup","onMount","cn","SidebarNav","SidebarNavContent","SidebarNavFooter","SidebarNavHeader","SidebarNavTitle","PixelResizeHandle","MobileModule","MobileLoad","error","ContextualSidebarRenderContext","mobile","portalMount","HTMLElement","ContextualSidebarProps","id","label","title","titleVisibility","open","onOpenChange","width","minimum","maximum","step","wideViewportAtLoad","resizeLabel","restoreFocusRef","onSidebarElement","element","sidebarClass","sheetClass","headerClass","contentClass","footerClass","headingAs","header","context","Element","content","footer","onWidthChange","onWidthCommit","ContextualSidebar","props","isNarrowViewport","setIsNarrowViewport","mobileLoad","setMobileLoad","mobileRequested","loadMobile","then","module","mobileMount","setMobileMount","connected","mount","isConnected","undefined","media","window","matchMedia","updateViewport","wasNarrow","matches","addEventListener","removeEventListener","renderSidebar","navigationId","_$createComponent","as","aria-label","aria-hidden","inert","data-open","String","ref","node","queueMicrotask","class","children","when","side","value","controls","onChange","onCommit","fallback","_$memo","_wide","keyed","loaded","MobileSidebar","_$createComponent","_$memo"],"sources":["../../../../src/components/layout/contextual-sidebar/contextual-sidebar.tsx"],"sourcesContent":["import type { Accessor, JSX } from 'solid-js'\nimport { Show, createSignal, createUniqueId, onCleanup, onMount } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport {\n SidebarNav,\n SidebarNavContent,\n SidebarNavFooter,\n SidebarNavHeader,\n SidebarNavTitle,\n} from '../sidebar-nav/sidebar-nav'\nimport { PixelResizeHandle } from '../pixel-resize-handle/pixel-resize-handle'\n\ntype MobileModule = typeof import('./mobile-contextual-sidebar')\ntype MobileLoad = MobileModule | { error: unknown }\n\nexport type ContextualSidebarRenderContext = {\n /** Whether the slot is being rendered inside the modal mobile sheet. */\n mobile: boolean\n /** Mount nested popovers and menus inside the mobile dialog's accessibility tree. */\n portalMount(): HTMLElement | undefined\n}\n\nexport type ContextualSidebarProps = {\n /** Stable host id prefix; generated when omitted. */\n id?: string\n /** Landmark name shared by the desktop and mobile navigation. */\n label: string\n /** Visible navigation title and mobile dialog title. */\n title: string\n /**\n * Where the title row shows. `always` (default) draws it on desktop and in\n * the mobile sheet; `mobile` keeps the desktop title for assistive\n * technology only and drops the desktop row, for hosts whose top bar\n * already names the context. A `header` slot keeps the row visible.\n */\n titleVisibility?: 'always' | 'mobile'\n /** Host-controlled expanded state for the desktop panel and mobile dialog. */\n open: boolean\n onOpenChange(open: boolean): void\n /** Current host-owned pixel width, reflected by the resize handle. */\n width: number\n minimum: number\n maximum: number\n step?: number\n /** Pass the host's initial viewport seed to distinguish stale desktop state. */\n wideViewportAtLoad?: boolean\n resizeLabel?: string\n /** Stable external opener used when the modal mobile sheet closes. */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n /** Called with the nav node so a host can project width onto its layout root. */\n onSidebarElement?: (element: HTMLElement | undefined, mobile: boolean) => void\n /** Host-owned layout classes applied to both nav instances. */\n sidebarClass?: string\n /** Host-owned responsive constraints for the modal sheet. */\n sheetClass?: string\n headerClass?: string\n contentClass?: string\n footerClass?: string\n headingAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n /** Optional action/content slot alongside the shared heading. */\n header?(context: ContextualSidebarRenderContext): JSX.Element\n /** View-specific navigation rows, projects, rooms, files, or sessions. */\n content(context: ContextualSidebarRenderContext): JSX.Element\n /** Optional view-specific footer, such as an archive affordance. */\n footer?(context: ContextualSidebarRenderContext): JSX.Element\n onWidthChange(width: number): void\n onWidthCommit?(width: number): void\n}\n\n/**\n * ContextualSidebar.\n *\n * Shared navigation geometry and interaction policy for an application's\n * contextual sidebar. The host keeps ownership of the actual grid width,\n * persisted preference, open state, and view-specific navigation content.\n */\nexport function ContextualSidebar(props: ContextualSidebarProps) {\n const [isNarrowViewport, setIsNarrowViewport] = createSignal(false)\n const [mobileLoad, setMobileLoad] = createSignal<MobileLoad>()\n let mobileRequested = false\n // Keep the resolved component mounted across viewport changes for Sheet cleanup.\n const loadMobile = () => {\n if (mobileRequested) return\n mobileRequested = true\n // Native module caching shares successful loads without keeping a rejected promise.\n void import('./mobile-contextual-sidebar').then(\n (module) => {\n if (mobileRequested) setMobileLoad(module)\n },\n (error: unknown) => {\n if (mobileRequested) setMobileLoad({ error })\n }\n )\n }\n const [mobileMount, setMobileMount] = createSignal<\n { element: HTMLElement; connected: boolean } | undefined\n >()\n const id = props.id ?? `contextual-sidebar-${createUniqueId()}`\n const resizeLabel = () => props.resizeLabel ?? `Resize ${props.label}`\n const portalMount = () => {\n const mount = mobileMount()\n return mount?.connected && mount.element.isConnected ? mount.element : undefined\n }\n\n onMount(() => {\n const media = window.matchMedia('(max-width: 48rem)')\n const updateViewport = () => {\n const wasNarrow = isNarrowViewport()\n if (media.matches) loadMobile()\n // Close before mounting a modal. A desktop-expanded host state is not\n // mobile intent, and opening the Sheet for one frame can steal focus.\n if (media.matches && !wasNarrow) props.onOpenChange(false)\n setIsNarrowViewport(media.matches)\n }\n\n // A route can mount after a wide-loaded host crosses into mobile. Clear\n // that stale seed, but preserve a sidebar intentionally opened at a\n // narrow boot viewport.\n if (media.matches) loadMobile()\n if (media.matches && props.wideViewportAtLoad && props.open) props.onOpenChange(false)\n setIsNarrowViewport(media.matches)\n media.addEventListener('change', updateViewport)\n onCleanup(() => {\n mobileRequested = false\n media.removeEventListener('change', updateViewport)\n })\n })\n\n const renderSidebar = (mobile: boolean) => {\n let element: HTMLElement | undefined\n const context: ContextualSidebarRenderContext = {\n mobile,\n portalMount: () => (mobile ? portalMount() : undefined),\n }\n const navigationId = `${id}-${mobile ? 'mobile' : 'desktop'}`\n\n onCleanup(() => {\n if (mobile && mobileMount()?.element === element) setMobileMount(undefined)\n element = undefined\n props.onSidebarElement?.(undefined, mobile)\n })\n\n return (\n <SidebarNav\n as=\"aside\"\n id={navigationId}\n aria-label={props.label}\n aria-hidden={!mobile && !props.open ? 'true' : undefined}\n inert={!mobile && !props.open}\n data-contextual-sidebar={mobile ? 'mobile' : 'desktop'}\n data-open={mobile ? undefined : String(props.open)}\n ref={(node) => {\n element = node\n if (mobile) {\n setMobileMount({ element: node, connected: node.isConnected })\n queueMicrotask(() => {\n if (node.isConnected && mobileMount()?.element === node)\n setMobileMount({ element: node, connected: true })\n })\n }\n props.onSidebarElement?.(node, mobile)\n }}\n class={cn('relative h-full w-full max-w-full', props.sidebarClass)}\n >\n <Show when={!mobile && props.open}>\n <PixelResizeHandle\n // The ruler spans the sidebar as a pointer-events-none overlay; lift\n // it above the neighbouring pane so the edge stays grabbable.\n class=\"z-(--z-docked)\"\n side=\"left\"\n value={props.width}\n minimum={props.minimum}\n maximum={props.maximum}\n step={props.step}\n label={resizeLabel()}\n controls={navigationId}\n onChange={props.onWidthChange}\n onCommit={props.onWidthCommit}\n />\n </Show>\n <Show when={!mobile || mobileMount()?.connected}>\n <Show\n when={mobile || props.titleVisibility !== 'mobile' || props.header}\n fallback={\n <SidebarNavTitle as={props.headingAs ?? 'h2'} class=\"sr-only\">\n {props.title}\n </SidebarNavTitle>\n }\n >\n <SidebarNavHeader class={cn(mobile && 'pe-12', props.headerClass)}>\n <SidebarNavTitle as={props.headingAs ?? 'h2'}>{props.title}</SidebarNavTitle>\n {props.header?.(context)}\n </SidebarNavHeader>\n </Show>\n <SidebarNavContent class={props.contentClass}>{props.content(context)}</SidebarNavContent>\n {props.footer ? (\n <SidebarNavFooter class={props.footerClass}>{props.footer(context)}</SidebarNavFooter>\n ) : null}\n </Show>\n </SidebarNav>\n )\n }\n\n return (\n <>\n <Show when={!isNarrowViewport()}>{(_wide) => renderSidebar(false)}</Show>\n <Show when={mobileLoad()} keyed>\n {(loaded) => {\n if ('error' in loaded) throw loaded.error\n return (\n <loaded.MobileSidebar\n open={isNarrowViewport() && props.open}\n onOpenChange={props.onOpenChange}\n label={props.label}\n sheetClass={props.sheetClass}\n restoreFocusRef={props.restoreFocusRef}\n renderSidebar={() => renderSidebar(true)}\n />\n )\n }}\n </Show>\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar-nav.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/sidebar-nav/sidebar-nav.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAGjE,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAanE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,cAAc,GAAG,KAAK,IAAI,gBAAgB,CAC9E,CAAC,EACD;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAC1C,CAAA;AAED,wBAAgB,UAAU,CAAC,CAAC,SAAS,cAAc,GAAG,KAAK,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,eAgBrF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,eAS5D;AAED,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,cAAc,GAAG,KAAK,IAAI,gBAAgB,CACnF,CAAC,EACD;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CACnB,CAAA;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,cAAc,GAAG,KAAK,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,eAU/F;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"sidebar-nav.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/sidebar-nav/sidebar-nav.tsx"],"names":[],"mappings":"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"}
|
|
@@ -68,7 +68,7 @@ function SidebarNavContent(props) {
|
|
|
68
68
|
return (() => {
|
|
69
69
|
var _el$2 = _tmpl$2();
|
|
70
70
|
spread(_el$2, mergeProps({ get ["class"]() {
|
|
71
|
-
return cn("flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-2 py-2", local.class);
|
|
71
|
+
return cn("flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-2 py-2 [scrollbar-gutter:stable]", local.class);
|
|
72
72
|
} }, rest), false, false);
|
|
73
73
|
return _el$2;
|
|
74
74
|
})();
|
|
@@ -185,7 +185,7 @@ function SidebarNavSection(props) {
|
|
|
185
185
|
trigger.onReorder?.(event.key === "ArrowUp" ? "up" : "down");
|
|
186
186
|
},
|
|
187
187
|
get ["class"]() {
|
|
188
|
-
return cn("flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11", local.active ? "text-foreground" : "text-sidebar-muted-foreground");
|
|
188
|
+
return cn("flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11", "-my-1.5 py-1.5 [@media(any-pointer:coarse)]:my-0 [@media(any-pointer:coarse)]:py-0", local.active ? "text-foreground" : "text-sidebar-muted-foreground");
|
|
189
189
|
}
|
|
190
190
|
}), false, true);
|
|
191
191
|
insert(_el$8, heading);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar-nav.js","names":["PolymorphicProps","Polymorphic","ChevronRight","ComponentProps","JSX","ValidComponent","Show","createSignal","splitProps","cn","invokeEventHandler","handler","event","Event","Array","isArray","callback","data","SidebarNavProps","T","class","SidebarNav","props","local","rest","_$createComponent","_$mergeProps","as","aria-label","children","SidebarNavHeader","_el$","_tmpl$","_$spread","SidebarNavTitleProps","SidebarNavTitle","SidebarNavContent","_el$2","_tmpl$2","SidebarNavFooter","_el$3","_tmpl$3","SidebarNavSectionTriggerProps","Omit","onReorder","direction","onClick","onKeyDown","SidebarNavSectionProps","label","collapsible","defaultOpen","active","open","onOpenChange","triggerProps","count","action","Element","actionVisibility","headingAs","SidebarNavSection","uncontrolledOpen","setUncontrolledOpen","setOpen","next","undefined","trigger","triggerRest","heading","when","_el$4","_tmpl$4","_$insert","_el$5","_tmpl$5","_el$6","_tmpl$9","_el$7","firstChild","_$memo","fallback","_el$8","_tmpl$6","aria-expanded","aria-current","defaultPrevented","altKey","key","preventDefault","stopPropagation","_el$9","_tmpl$7","_$effect","_$className","_el$0","_tmpl$8","_p$","_v$","_v$2","e","_$setAttribute","t","SidebarNavRowProps","actions","SidebarNavRow","_el$1","_tmpl$1","_el$10","_tmpl$0","SidebarNavLabel","_el$11","_tmpl$10","SidebarNavItemProps","nested","trailing","sidebarNavItemClass","join","sidebarNavItemStateClass","idle","SidebarNavItem","data-active","_el$12","_tmpl$11","SidebarNavButton","_el$13","_tmpl$12","_$createComponent","_$mergeProps","_$memo","_$className","_$setAttribute"],"sources":["../../../../src/components/layout/sidebar-nav/sidebar-nav.tsx"],"sourcesContent":["import type { PolymorphicProps } from '@kobalte/core/polymorphic'\nimport { Polymorphic } from '@kobalte/core/polymorphic'\nimport { ChevronRight } from 'lucide-solid'\nimport type { ComponentProps, JSX, ValidComponent } from 'solid-js'\nimport { Show, createSignal, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\nfunction invokeEventHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n ;(handler as (event: Event) => void)(event)\n }\n}\n\n/**\n * SidebarNav.\n *\n * The secondary navigation column: the list of things inside the destination\n * the rail selected — projects, sessions, files, threads. It is a different\n * object from the rail, not a wider version of it, which is why it is a separate\n * component rather than the rail with labels on.\n *\n * Rows share one recipe with the rail's, so a row in a sidebar and a row in a\n * rail read as the same kind of thing at the same density. That recipe is\n * exactly KiroCrew's nav row: `text-sm font-medium`, `gap-2.5`, `px-3 py-2`,\n * `rounded-md`, `transition-colors`.\n *\n * The width comes from `--sidebar-width`. Sections collapse by default only when\n * the caller says so, because a section that starts collapsed and holds the\n * user's own work is a hidden default.\n */\nexport type SidebarNavProps<T extends ValidComponent = 'nav'> = PolymorphicProps<\n T,\n { class?: string; 'aria-label'?: string }\n>\n\nexport function SidebarNav<T extends ValidComponent = 'nav'>(props: SidebarNavProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavProps, ['class', 'aria-label', 'children'])\n\n return (\n <Polymorphic\n as=\"nav\"\n aria-label={local['aria-label'] ?? 'Section'}\n class={cn(\n 'bg-sidebar text-sidebar-foreground flex h-full w-sidebar min-w-0 max-w-full shrink-0 flex-col border-e border-sidebar-border',\n local.class\n )}\n {...(rest as ComponentProps<'nav'>)}\n >\n {local.children}\n </Polymorphic>\n )\n}\n\nexport function SidebarNavHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-header\"\n class={cn('flex h-topbar shrink-0 items-center justify-between gap-2 px-3', local.class)}\n {...rest}\n />\n )\n}\n\nexport type SidebarNavTitleProps<T extends ValidComponent = 'div'> = PolymorphicProps<\n T,\n { class?: string }\n>\n\nexport function SidebarNavTitle<T extends ValidComponent = 'div'>(props: SidebarNavTitleProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavTitleProps, ['class'])\n return (\n <Polymorphic\n as=\"div\"\n data-slot=\"sidebar-nav-title\"\n class={cn('truncate text-sm font-semibold tracking-tight', local.class)}\n {...(rest as ComponentProps<'div'>)}\n />\n )\n}\n\n/** The scrolling middle of the sidebar. */\nexport function SidebarNavContent(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-content\"\n class={cn('flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-2 py-2', local.class)}\n {...rest}\n />\n )\n}\n\nexport function SidebarNavFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-footer\"\n class={cn('flex shrink-0 items-center gap-1 border-t border-sidebar-border p-2', local.class)}\n {...rest}\n />\n )\n}\n\n/** Props forwarded to a collapsible section's disclosure button. */\nexport type SidebarNavSectionTriggerProps = Omit<\n ComponentProps<'button'>,\n 'type' | 'aria-expanded' | 'onClick' | 'onKeyDown' | 'children' | 'class' | 'style'\n> & {\n /** Called for Alt+ArrowUp/Down; the host owns ordering and row identity. */\n onReorder?: (direction: 'up' | 'down') => void\n /** Runs before the section toggle and may cancel it with `preventDefault()`. */\n onClick?: ComponentProps<'button'>['onClick']\n /** Runs before shared Alt+Arrow handling and may cancel it with `preventDefault()`. */\n onKeyDown?: ComponentProps<'button'>['onKeyDown']\n}\n\n/**\n * A titled, collapsible group. Collapsible because a list of projects\n * inevitably outgrows the column, and the user needs to put the ones they are\n * not using away *without* them disappearing into a menu.\n */\nexport type SidebarNavSectionProps = ComponentProps<'div'> & {\n label: string\n /** Render a disclosure control instead of a plain heading. */\n collapsible?: boolean\n defaultOpen?: boolean\n /** Mark the current project/group without changing its disclosure state. */\n active?: boolean\n /** Controlled disclosure state. When supplied, the host owns changes. */\n open?: boolean\n /** Called for user-initiated disclosure changes. */\n onOpenChange?: (open: boolean) => void\n /** Native props and reorder callbacks for the disclosure control. */\n triggerProps?: SidebarNavSectionTriggerProps\n /** Count shown beside the label. */\n count?: number\n /** A control at the trailing edge of the heading row. */\n action?: JSX.Element\n /**\n * When the trailing action shows. `hover` (default) reveals it on hover or\n * focus; `always` keeps it visible, for a section whose primary action is\n * creating its first item.\n */\n actionVisibility?: 'hover' | 'always'\n /** Semantic heading element for a host's section hierarchy. */\n headingAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n}\n\nexport function SidebarNavSection(props: SidebarNavSectionProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'collapsible',\n 'defaultOpen',\n 'active',\n 'open',\n 'onOpenChange',\n 'triggerProps',\n 'count',\n 'action',\n 'actionVisibility',\n 'headingAs',\n 'children',\n ])\n const [uncontrolledOpen, setUncontrolledOpen] = createSignal(local.defaultOpen ?? true)\n const open = () => local.open ?? uncontrolledOpen()\n const setOpen = (next: boolean) => {\n if (local.open === undefined) setUncontrolledOpen(next)\n local.onOpenChange?.(next)\n }\n\n const [trigger, triggerRest] = splitProps(local.triggerProps ?? {}, [\n 'onClick',\n 'onKeyDown',\n 'onReorder',\n ])\n\n const heading = (\n <>\n <Show when={local.collapsible}>\n <ChevronRight\n aria-hidden=\"true\"\n class={cn('size-3.5 shrink-0 text-muted-foreground transition-transform ease-out', {\n 'rotate-90': open(),\n })}\n />\n </Show>\n <span class=\"min-w-0 flex-1 truncate text-start\">{local.label}</span>\n <Show when={local.count !== undefined}>\n <span class=\"shrink-0 tabular-nums text-muted-foreground\">{local.count}</span>\n </Show>\n </>\n )\n\n return (\n <div data-slot=\"sidebar-nav-section\" class={cn('flex flex-col gap-0.5', local.class)} {...rest}>\n <div\n data-slot=\"sidebar-nav-section-header\"\n data-active={local.active ? '' : undefined}\n class={cn(\n 'group/section-header flex items-center gap-1 rounded-md px-2 py-1.5',\n { '[@media(any-pointer:coarse)]:py-0': local.collapsible },\n local.active ? 'bg-primary-subtle text-foreground' : 'hover:bg-sidebar-accent/60'\n )}\n >\n <Polymorphic\n as={local.headingAs ?? 'div'}\n aria-label={local.headingAs ? local.label : undefined}\n class={cn(\n 'flex min-w-0 flex-1 items-center gap-1.5 text-2xs font-medium tracking-wide uppercase',\n local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'\n )}\n >\n <Show when={local.collapsible} fallback={heading}>\n <button\n {...(triggerRest as ComponentProps<'button'>)}\n type=\"button\"\n aria-expanded={open()}\n aria-current={local.active ? 'page' : triggerRest['aria-current']}\n onClick={(event) => {\n invokeEventHandler(trigger.onClick, event)\n if (event.defaultPrevented) return\n setOpen(!open())\n }}\n onKeyDown={(event) => {\n invokeEventHandler(trigger.onKeyDown, event)\n if (event.defaultPrevented || !event.altKey) return\n if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') return\n event.preventDefault()\n event.stopPropagation()\n trigger.onReorder?.(event.key === 'ArrowUp' ? 'up' : 'down')\n }}\n class={cn(\n 'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11',\n local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'\n )}\n >\n {heading}\n </button>\n </Show>\n </Polymorphic>\n <Show when={local.action}>\n <span\n data-slot=\"sidebar-nav-section-action\"\n class={cn('shrink-0', {\n 'opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(any-pointer:coarse)]:opacity-100':\n local.actionVisibility !== 'always',\n })}\n >\n {local.action}\n </span>\n </Show>\n </div>\n <Show when={!local.collapsible || open()}>\n <div class=\"flex flex-col gap-0.5\">{local.children}</div>\n </Show>\n </div>\n )\n}\n\nexport type SidebarNavRowProps = ComponentProps<'div'> & {\n /** Adjacent controls, outside the navigation item's interactive element. */\n actions?: JSX.Element\n}\n\n/**\n * A navigation item and its adjacent controls. Actions stay outside the item\n * to avoid nested buttons; touch, keyboard focus, and expanded menus expose\n * them without requiring a pointer hover. A narrow lane or enlarged text\n * may move actions onto a second line rather than clipping the label or controls.\n */\nexport function SidebarNavRow(props: SidebarNavRowProps) {\n const [local, rest] = splitProps(props, ['class', 'children', 'actions'])\n return (\n <div\n data-slot=\"sidebar-nav-row\"\n class={cn(\n 'group/sidebar-nav-row flex min-w-0 flex-wrap items-center gap-0.5 [&>[data-slot=sidebar-nav-item]]:flex-1 [&>[data-slot=sidebar-nav-item]]:basis-36',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <Show when={local.actions}>\n <span\n data-slot=\"sidebar-nav-row-actions\"\n class=\"ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(any-pointer:coarse)]:opacity-100\"\n >\n {local.actions}\n </span>\n </Show>\n </div>\n )\n}\n\n/** Row text may truncate visually; its complete content remains the accessible name. */\nexport function SidebarNavLabel(props: ComponentProps<'span'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <span\n data-slot=\"sidebar-nav-label\"\n class={cn('min-w-0 flex-1 truncate text-start', local.class)}\n {...rest}\n />\n )\n}\n\nexport type SidebarNavItemProps<T extends ValidComponent = 'a'> = PolymorphicProps<\n T,\n {\n class?: string\n active?: boolean\n /** Indent one level, for a child row such as a branch under a project. */\n nested?: boolean\n /** Trailing slot: a count, a status dot, a hover action. */\n trailing?: JSX.Element\n }\n>\n\n/**\n * A sidebar row. Exported classes, so a caller's own element can match it.\n * Any coarse pointer gets a 44px target without changing desktop density.\n */\nexport const sidebarNavItemClass = [\n 'group/nav-item relative flex min-w-0 items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium',\n 'whitespace-nowrap transition-colors ease-out outline-none select-none [@media(any-pointer:coarse)]:min-h-11',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n '[&_svg]:size-4 [&_svg]:shrink-0',\n].join(' ')\n\nexport const sidebarNavItemStateClass = {\n active: 'bg-primary-subtle text-foreground',\n idle: 'text-muted-foreground hover:bg-surface-hover hover:text-foreground',\n}\n\nexport function SidebarNavItem<T extends ValidComponent = 'a'>(props: SidebarNavItemProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavItemProps, [\n 'class',\n 'active',\n 'nested',\n 'trailing',\n 'children',\n ])\n\n return (\n <Polymorphic\n as=\"a\"\n data-slot=\"sidebar-nav-item\"\n aria-current={local.active ? 'page' : undefined}\n data-active={local.active ? '' : undefined}\n class={cn(\n sidebarNavItemClass,\n local.active ? sidebarNavItemStateClass.active : sidebarNavItemStateClass.idle,\n { 'ps-8': local.nested },\n local.class\n )}\n {...(rest as ComponentProps<'a'>)}\n >\n {local.children}\n <Show when={local.trailing}>\n <span class=\"ms-auto flex shrink-0 items-center gap-1\">{local.trailing}</span>\n </Show>\n </Polymorphic>\n )\n}\n\n/** A row that is a button rather than a destination — \"New project\". */\nexport function SidebarNavButton(props: ComponentProps<'button'>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <button\n type=\"button\"\n class={cn(\n sidebarNavItemClass,\n sidebarNavItemStateClass.idle,\n 'w-full disabled:pointer-events-none disabled:opacity-50',\n local.class\n )}\n {...rest}\n >\n {local.children}\n </button>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sidebar-nav.js","names":["PolymorphicProps","Polymorphic","ChevronRight","ComponentProps","JSX","ValidComponent","Show","createSignal","splitProps","cn","invokeEventHandler","handler","event","Event","Array","isArray","callback","data","SidebarNavProps","T","class","SidebarNav","props","local","rest","_$createComponent","_$mergeProps","as","aria-label","children","SidebarNavHeader","_el$","_tmpl$","_$spread","SidebarNavTitleProps","SidebarNavTitle","SidebarNavContent","_el$2","_tmpl$2","SidebarNavFooter","_el$3","_tmpl$3","SidebarNavSectionTriggerProps","Omit","onReorder","direction","onClick","onKeyDown","SidebarNavSectionProps","label","collapsible","defaultOpen","active","open","onOpenChange","triggerProps","count","action","Element","actionVisibility","headingAs","SidebarNavSection","uncontrolledOpen","setUncontrolledOpen","setOpen","next","undefined","trigger","triggerRest","heading","when","_el$4","_tmpl$4","_$insert","_el$5","_tmpl$5","_el$6","_tmpl$9","_el$7","firstChild","_$memo","fallback","_el$8","_tmpl$6","aria-expanded","aria-current","defaultPrevented","altKey","key","preventDefault","stopPropagation","_el$9","_tmpl$7","_$effect","_$className","_el$0","_tmpl$8","_p$","_v$","_v$2","e","_$setAttribute","t","SidebarNavRowProps","actions","SidebarNavRow","_el$1","_tmpl$1","_el$10","_tmpl$0","SidebarNavLabel","_el$11","_tmpl$10","SidebarNavItemProps","nested","trailing","sidebarNavItemClass","join","sidebarNavItemStateClass","idle","SidebarNavItem","data-active","_el$12","_tmpl$11","SidebarNavButton","_el$13","_tmpl$12","_$createComponent","_$mergeProps","_$memo","_$className","_$setAttribute"],"sources":["../../../../src/components/layout/sidebar-nav/sidebar-nav.tsx"],"sourcesContent":["import type { PolymorphicProps } from '@kobalte/core/polymorphic'\nimport { Polymorphic } from '@kobalte/core/polymorphic'\nimport { ChevronRight } from 'lucide-solid'\nimport type { ComponentProps, JSX, ValidComponent } from 'solid-js'\nimport { Show, createSignal, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\nfunction invokeEventHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n ;(handler as (event: Event) => void)(event)\n }\n}\n\n/**\n * SidebarNav.\n *\n * The secondary navigation column: the list of things inside the destination\n * the rail selected — projects, sessions, files, threads. It is a different\n * object from the rail, not a wider version of it, which is why it is a separate\n * component rather than the rail with labels on.\n *\n * Rows share one recipe with the rail's, so a row in a sidebar and a row in a\n * rail read as the same kind of thing at the same density. That recipe is\n * exactly KiroCrew's nav row: `text-sm font-medium`, `gap-2.5`, `px-3 py-2`,\n * `rounded-md`, `transition-colors`.\n *\n * The width comes from `--sidebar-width`. Sections collapse by default only when\n * the caller says so, because a section that starts collapsed and holds the\n * user's own work is a hidden default.\n */\nexport type SidebarNavProps<T extends ValidComponent = 'nav'> = PolymorphicProps<\n T,\n { class?: string; 'aria-label'?: string }\n>\n\nexport function SidebarNav<T extends ValidComponent = 'nav'>(props: SidebarNavProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavProps, ['class', 'aria-label', 'children'])\n\n return (\n <Polymorphic\n as=\"nav\"\n aria-label={local['aria-label'] ?? 'Section'}\n class={cn(\n 'bg-sidebar text-sidebar-foreground flex h-full w-sidebar min-w-0 max-w-full shrink-0 flex-col border-e border-sidebar-border',\n local.class\n )}\n {...(rest as ComponentProps<'nav'>)}\n >\n {local.children}\n </Polymorphic>\n )\n}\n\nexport function SidebarNavHeader(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-header\"\n class={cn('flex h-topbar shrink-0 items-center justify-between gap-2 px-3', local.class)}\n {...rest}\n />\n )\n}\n\nexport type SidebarNavTitleProps<T extends ValidComponent = 'div'> = PolymorphicProps<\n T,\n { class?: string }\n>\n\nexport function SidebarNavTitle<T extends ValidComponent = 'div'>(props: SidebarNavTitleProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavTitleProps, ['class'])\n return (\n <Polymorphic\n as=\"div\"\n data-slot=\"sidebar-nav-title\"\n class={cn('truncate text-sm font-semibold tracking-tight', local.class)}\n {...(rest as ComponentProps<'div'>)}\n />\n )\n}\n\n/** The scrolling middle of the sidebar. */\nexport function SidebarNavContent(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-content\"\n class={cn(\n /* A stable gutter keeps rows from shifting sideways when the list\n grows past the fold and the scrollbar appears. */\n 'flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-2 py-2 [scrollbar-gutter:stable]',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport function SidebarNavFooter(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"sidebar-nav-footer\"\n class={cn('flex shrink-0 items-center gap-1 border-t border-sidebar-border p-2', local.class)}\n {...rest}\n />\n )\n}\n\n/** Props forwarded to a collapsible section's disclosure button. */\nexport type SidebarNavSectionTriggerProps = Omit<\n ComponentProps<'button'>,\n 'type' | 'aria-expanded' | 'onClick' | 'onKeyDown' | 'children' | 'class' | 'style'\n> & {\n /** Called for Alt+ArrowUp/Down; the host owns ordering and row identity. */\n onReorder?: (direction: 'up' | 'down') => void\n /** Runs before the section toggle and may cancel it with `preventDefault()`. */\n onClick?: ComponentProps<'button'>['onClick']\n /** Runs before shared Alt+Arrow handling and may cancel it with `preventDefault()`. */\n onKeyDown?: ComponentProps<'button'>['onKeyDown']\n}\n\n/**\n * A titled, collapsible group. Collapsible because a list of projects\n * inevitably outgrows the column, and the user needs to put the ones they are\n * not using away *without* them disappearing into a menu.\n */\nexport type SidebarNavSectionProps = ComponentProps<'div'> & {\n label: string\n /** Render a disclosure control instead of a plain heading. */\n collapsible?: boolean\n defaultOpen?: boolean\n /** Mark the current project/group without changing its disclosure state. */\n active?: boolean\n /** Controlled disclosure state. When supplied, the host owns changes. */\n open?: boolean\n /** Called for user-initiated disclosure changes. */\n onOpenChange?: (open: boolean) => void\n /** Native props and reorder callbacks for the disclosure control. */\n triggerProps?: SidebarNavSectionTriggerProps\n /** Count shown beside the label. */\n count?: number\n /** A control at the trailing edge of the heading row. */\n action?: JSX.Element\n /**\n * When the trailing action shows. `hover` (default) reveals it on hover or\n * focus; `always` keeps it visible, for a section whose primary action is\n * creating its first item.\n */\n actionVisibility?: 'hover' | 'always'\n /** Semantic heading element for a host's section hierarchy. */\n headingAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n}\n\nexport function SidebarNavSection(props: SidebarNavSectionProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'label',\n 'collapsible',\n 'defaultOpen',\n 'active',\n 'open',\n 'onOpenChange',\n 'triggerProps',\n 'count',\n 'action',\n 'actionVisibility',\n 'headingAs',\n 'children',\n ])\n const [uncontrolledOpen, setUncontrolledOpen] = createSignal(local.defaultOpen ?? true)\n const open = () => local.open ?? uncontrolledOpen()\n const setOpen = (next: boolean) => {\n if (local.open === undefined) setUncontrolledOpen(next)\n local.onOpenChange?.(next)\n }\n\n const [trigger, triggerRest] = splitProps(local.triggerProps ?? {}, [\n 'onClick',\n 'onKeyDown',\n 'onReorder',\n ])\n\n const heading = (\n <>\n <Show when={local.collapsible}>\n <ChevronRight\n aria-hidden=\"true\"\n class={cn('size-3.5 shrink-0 text-muted-foreground transition-transform ease-out', {\n 'rotate-90': open(),\n })}\n />\n </Show>\n <span class=\"min-w-0 flex-1 truncate text-start\">{local.label}</span>\n <Show when={local.count !== undefined}>\n <span class=\"shrink-0 tabular-nums text-muted-foreground\">{local.count}</span>\n </Show>\n </>\n )\n\n return (\n <div data-slot=\"sidebar-nav-section\" class={cn('flex flex-col gap-0.5', local.class)} {...rest}>\n <div\n data-slot=\"sidebar-nav-section-header\"\n data-active={local.active ? '' : undefined}\n class={cn(\n 'group/section-header flex items-center gap-1 rounded-md px-2 py-1.5',\n { '[@media(any-pointer:coarse)]:py-0': local.collapsible },\n local.active ? 'bg-primary-subtle text-foreground' : 'hover:bg-sidebar-accent/60'\n )}\n >\n <Polymorphic\n as={local.headingAs ?? 'div'}\n aria-label={local.headingAs ? local.label : undefined}\n class={cn(\n 'flex min-w-0 flex-1 items-center gap-1.5 text-2xs font-medium tracking-wide uppercase',\n local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'\n )}\n >\n <Show when={local.collapsible} fallback={heading}>\n <button\n {...(triggerRest as ComponentProps<'button'>)}\n type=\"button\"\n aria-expanded={open()}\n aria-current={local.active ? 'page' : triggerRest['aria-current']}\n onClick={(event) => {\n invokeEventHandler(trigger.onClick, event)\n if (event.defaultPrevented) return\n setOpen(!open())\n }}\n onKeyDown={(event) => {\n invokeEventHandler(trigger.onKeyDown, event)\n if (event.defaultPrevented || !event.altKey) return\n if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') return\n event.preventDefault()\n event.stopPropagation()\n trigger.onReorder?.(event.key === 'ArrowUp' ? 'up' : 'down')\n }}\n class={cn(\n 'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11',\n /* WCAG 2.5.8: the row's vertical padding sits on the header, so\n the bare label would be a ~16px target. Stretch the button\n across that padding; the row's height does not change. A\n coarse pointer already gets min-h-11 on an unpadded row. */\n '-my-1.5 py-1.5 [@media(any-pointer:coarse)]:my-0 [@media(any-pointer:coarse)]:py-0',\n local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'\n )}\n >\n {heading}\n </button>\n </Show>\n </Polymorphic>\n <Show when={local.action}>\n <span\n data-slot=\"sidebar-nav-section-action\"\n class={cn('shrink-0', {\n 'opacity-0 transition-opacity ease-out group-hover/section-header:opacity-100 focus-within:opacity-100 [@media(any-pointer:coarse)]:opacity-100':\n local.actionVisibility !== 'always',\n })}\n >\n {local.action}\n </span>\n </Show>\n </div>\n <Show when={!local.collapsible || open()}>\n <div class=\"flex flex-col gap-0.5\">{local.children}</div>\n </Show>\n </div>\n )\n}\n\nexport type SidebarNavRowProps = ComponentProps<'div'> & {\n /** Adjacent controls, outside the navigation item's interactive element. */\n actions?: JSX.Element\n}\n\n/**\n * A navigation item and its adjacent controls. Actions stay outside the item\n * to avoid nested buttons; touch, keyboard focus, and expanded menus expose\n * them without requiring a pointer hover. A narrow lane or enlarged text\n * may move actions onto a second line rather than clipping the label or controls.\n */\nexport function SidebarNavRow(props: SidebarNavRowProps) {\n const [local, rest] = splitProps(props, ['class', 'children', 'actions'])\n return (\n <div\n data-slot=\"sidebar-nav-row\"\n class={cn(\n 'group/sidebar-nav-row flex min-w-0 flex-wrap items-center gap-0.5 [&>[data-slot=sidebar-nav-item]]:flex-1 [&>[data-slot=sidebar-nav-item]]:basis-36',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <Show when={local.actions}>\n <span\n data-slot=\"sidebar-nav-row-actions\"\n class=\"ms-auto flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity ease-out group-hover/sidebar-nav-row:opacity-100 group-focus-within/sidebar-nav-row:opacity-100 has-[[aria-haspopup=menu][aria-expanded=true]]:opacity-100 has-[[aria-haspopup=true][aria-expanded=true]]:opacity-100 [@media(any-pointer:coarse)]:opacity-100\"\n >\n {local.actions}\n </span>\n </Show>\n </div>\n )\n}\n\n/** Row text may truncate visually; its complete content remains the accessible name. */\nexport function SidebarNavLabel(props: ComponentProps<'span'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <span\n data-slot=\"sidebar-nav-label\"\n class={cn('min-w-0 flex-1 truncate text-start', local.class)}\n {...rest}\n />\n )\n}\n\nexport type SidebarNavItemProps<T extends ValidComponent = 'a'> = PolymorphicProps<\n T,\n {\n class?: string\n active?: boolean\n /** Indent one level, for a child row such as a branch under a project. */\n nested?: boolean\n /** Trailing slot: a count, a status dot, a hover action. */\n trailing?: JSX.Element\n }\n>\n\n/**\n * A sidebar row. Exported classes, so a caller's own element can match it.\n * Any coarse pointer gets a 44px target without changing desktop density.\n */\nexport const sidebarNavItemClass = [\n 'group/nav-item relative flex min-w-0 items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium',\n 'whitespace-nowrap transition-colors ease-out outline-none select-none [@media(any-pointer:coarse)]:min-h-11',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n '[&_svg]:size-4 [&_svg]:shrink-0',\n].join(' ')\n\nexport const sidebarNavItemStateClass = {\n active: 'bg-primary-subtle text-foreground',\n idle: 'text-muted-foreground hover:bg-surface-hover hover:text-foreground',\n}\n\nexport function SidebarNavItem<T extends ValidComponent = 'a'>(props: SidebarNavItemProps<T>) {\n const [local, rest] = splitProps(props as SidebarNavItemProps, [\n 'class',\n 'active',\n 'nested',\n 'trailing',\n 'children',\n ])\n\n return (\n <Polymorphic\n as=\"a\"\n data-slot=\"sidebar-nav-item\"\n aria-current={local.active ? 'page' : undefined}\n data-active={local.active ? '' : undefined}\n class={cn(\n sidebarNavItemClass,\n local.active ? sidebarNavItemStateClass.active : sidebarNavItemStateClass.idle,\n { 'ps-8': local.nested },\n local.class\n )}\n {...(rest as ComponentProps<'a'>)}\n >\n {local.children}\n <Show when={local.trailing}>\n <span class=\"ms-auto flex shrink-0 items-center gap-1\">{local.trailing}</span>\n </Show>\n </Polymorphic>\n )\n}\n\n/** A row that is a button rather than a destination — \"New project\". */\nexport function SidebarNavButton(props: ComponentProps<'button'>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <button\n type=\"button\"\n class={cn(\n sidebarNavItemClass,\n sidebarNavItemStateClass.idle,\n 'w-full disabled:pointer-events-none disabled:opacity-50',\n local.class\n )}\n {...rest}\n >\n {local.children}\n </button>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"top-bar.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/top-bar/top-bar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAK9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG;IACnD,sDAAsD;IACtD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,kDAAkD;IAClD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,qDAAqD;IACrD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"top-bar.d.ts","sourceRoot":"","sources":["../../../../src/components/layout/top-bar/top-bar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAK9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG;IACnD,sDAAsD;IACtD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,kDAAkD;IAClD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,qDAAqD;IACrD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,kCA2BxC;AAYD,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAA;CAAE,kCAqBvF;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IAC7B,mEAAmE;IACnE,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;CAC3B,kCAgBF;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,kCAY5D;AAED,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG;IACzD,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,kCA8BpD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,kCAqB7E"}
|
|
@@ -21,7 +21,7 @@ function TopBar(props) {
|
|
|
21
21
|
return (() => {
|
|
22
22
|
var _el$ = _tmpl$();
|
|
23
23
|
spread(_el$, mergeProps({ get ["class"]() {
|
|
24
|
-
return cn("h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card text-card-foreground
|
|
24
|
+
return cn("h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card text-card-foreground md:grid-cols-[minmax(0,1fr)_clamp(240px,22vw,480px)_minmax(0,1fr)]", local.glass && "glass-panel", local.draggable && "window-drag", local.macosInset ? "window-inset-macos" : "ps-3", local.windowsInset ? "window-inset-windows" : "pe-3", local.class);
|
|
25
25
|
} }, rest), false, false);
|
|
26
26
|
return _el$;
|
|
27
27
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"top-bar.js","names":["ComponentProps","Show","splitProps","Search","cn","TopBarProps","draggable","macosInset","windowsInset","glass","TopBar","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","class","invokeFocusHandler","handler","event","Event","Array","isArray","callback","data","TopBarSection","align","_el$2","_tmpl$2","$$focusin","target","HTMLElement","scrollIntoView","block","inline","onFocusIn","TopBarTitle","_el$3","_tmpl$3","TopBarBreadcrumb","_el$4","_tmpl$4","TopBarSearchProps","placeholder","shortcut","keyshortcuts","TopBarSearch","_el$5","_tmpl$6","_el$6","firstChild","aria-keyshortcuts","_$insert","_$createComponent","when","children","_el$7","_tmpl$5","TopBarPill","label","_el$8","_tmpl$7","_el$9","_$delegateEvents","_$mergeProps","_$createComponent","_$delegateEvents"],"sources":["../../../../src/components/layout/top-bar/top-bar.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { Search } from 'lucide-solid'\nimport { cn } from '#lib/utils'\n\n/**\n * TopBar.\n *\n * The window's title row and primary toolbar. Three tracks: a leading group, a\n * centred search, and a trailing group. On wide screens the search is a fixed\n * function of the window width and the side groups are equal remainders. On\n * narrow screens the middle track yields space to the controls, and each side\n * group scrolls when necessary so keyboard focus can reveal every action.\n *\n * On a frameless desktop window this row is also the drag region, so it carries\n * `window-drag` and the controls inside it opt back out. `macos-inset` and\n * `windows-inset` reserve the space the native window controls occupy, which is\n * why the row can look off-centre in a frameless window and be correct: it is\n * centred in the space the user can actually see.\n */\nexport type TopBarProps = ComponentProps<'header'> & {\n /** Make the row draggable, for a frameless window. */\n draggable?: boolean\n /** Reserve space for the macOS traffic lights. */\n macosInset?: boolean\n /** Reserve space for the Windows caption buttons. */\n windowsInset?: boolean\n /** Blur the content scrolling under the bar. */\n glass?: boolean\n}\n\nexport function TopBar(props: TopBarProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'draggable',\n 'macosInset',\n 'windowsInset',\n 'glass',\n ])\n\n return (\n <header\n data-slot=\"top-bar\"\n class={cn(\n 'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card text-card-foreground px-3 md:grid-cols-[minmax(0,1fr)_clamp(240px,22vw,480px)_minmax(0,1fr)]',\n local.glass && 'glass-panel',\n local.draggable && 'window-drag',\n local.macosInset && 'window-inset-macos',\n local.windowsInset && 'window-inset-windows',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nfunction invokeFocusHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n const callback = handler as (event: Event) => void\n callback(event)\n }\n}\n\n/** A scrollable side group; equal wide-screen tracks centre the search. */\nexport function TopBarSection(props: ComponentProps<'div'> & { align?: 'start' | 'end' }) {\n const [local, rest] = splitProps(props, ['class', 'align', 'onFocusIn'])\n\n return (\n <div\n data-slot=\"top-bar-section\"\n class={cn(\n 'window-no-drag flex min-w-0 items-center gap-2 overflow-x-auto overflow-y-hidden',\n local.align === 'end' && 'md:justify-end',\n local.align !== 'end' && 'justify-start',\n local.class\n )}\n onFocusIn={(event) => {\n if (event.target instanceof HTMLElement) {\n event.target.scrollIntoView({ block: 'nearest', inline: 'nearest' })\n }\n invokeFocusHandler(local.onFocusIn, event)\n }}\n {...rest}\n />\n )\n}\n\nexport function TopBarTitle(\n props: ComponentProps<'div'> & {\n /** Aligns text within this slot; it does not position the slot. */\n align?: 'start' | 'center'\n }\n) {\n const [local, rest] = splitProps(props, ['class', 'align'])\n return (\n <div\n data-slot=\"top-bar-title\"\n class={cn(\n /* The title slot sits in the drag region; a link, button or field\n placed in it (a breadcrumb, a view's search) must stay pressable. */\n 'truncate text-sm font-medium [&_:is(a,button,input)]:window-no-drag',\n local.align === 'center' && 'text-center',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/** A breadcrumb or path readout that yields to the actions when space runs out. */\nexport function TopBarBreadcrumb(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"top-bar-breadcrumb\"\n class={cn(\n 'flex min-w-0 items-center gap-1.5 text-sm [&_:is(a,button,input)]:window-no-drag',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type TopBarSearchProps = ComponentProps<'button'> & {\n /** The hint shown inside the field, e.g. \"Search projects and files\". */\n placeholder?: string\n /** The shortcut chip drawn at the trailing edge, e.g. \"⌘K\". */\n shortcut?: string\n /**\n * The parseable chord behind `shortcut`, e.g. `Meta+K`. The chip is\n * `aria-hidden` — reading it out would pollute the button's accessible\n * name — so this is what assistive technology announces instead. Supply it\n * whenever `shortcut` is drawn.\n */\n keyshortcuts?: string\n}\n\n/**\n * The search affordance in the middle track.\n *\n * It is a button, not an input, and that is deliberate: clicking it opens the\n * command palette, which already owns the input, the ranking and the keyboard\n * handling. A second live input here would be a second source of truth for the\n * same query. It is styled to read as a field because that is what it behaves\n * like from the user's side.\n */\nexport function TopBarSearch(props: TopBarSearchProps) {\n const [local, rest] = splitProps(props, ['class', 'placeholder', 'shortcut', 'keyshortcuts'])\n\n return (\n <button\n type=\"button\"\n data-slot=\"top-bar-search\"\n class={cn(\n 'text-muted-foreground flex h-control-md w-full min-w-(--control-height-md) items-center justify-center gap-2 rounded-md border border-input px-3 text-sm sm:justify-start',\n 'transition-colors ease-out outline-none',\n 'hover:bg-surface-hover hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'window-no-drag',\n local.class\n )}\n aria-keyshortcuts={local.keyshortcuts}\n {...rest}\n >\n <Search aria-hidden=\"true\" class=\"size-4 shrink-0 sm:hidden\" />\n <span class=\"sr-only sm:not-sr-only sm:truncate\">{local.placeholder ?? 'Search'}</span>\n <Show when={local.shortcut}>\n <kbd\n aria-hidden=\"true\"\n class=\"bg-muted ms-auto hidden h-5 shrink-0 items-center rounded-sm border border-border px-1.5 font-code text-code sm:flex\"\n >\n {local.shortcut}\n </kbd>\n </Show>\n </button>\n )\n}\n\n/**\n * A labelled top-bar control — the readouts KiroCrew puts in the trailing\n * group. Container queries on the group decide which of these survive a narrow\n * window; a caller marks the cheap-to-drop ones and the group handles the rest.\n */\nexport function TopBarPill(props: ComponentProps<'button'> & { label: string }) {\n const [local, rest] = splitProps(props, ['class', 'label', 'children'])\n\n return (\n <button\n type=\"button\"\n data-slot=\"top-bar-pill\"\n class={cn(\n 'text-muted-foreground inline-flex h-control-sm shrink-0 items-center gap-1.5 rounded-md border border-border px-2.5 text-xs font-medium',\n 'transition-colors ease-out outline-none',\n 'hover:border-input hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'window-no-drag [&_svg]:size-3.5 [&_svg]:shrink-0',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <span>{local.label}</span>\n </button>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"top-bar.js","names":["ComponentProps","Show","splitProps","Search","cn","TopBarProps","draggable","macosInset","windowsInset","glass","TopBar","props","local","rest","_el$","_tmpl$","_$spread","_$mergeProps","class","invokeFocusHandler","handler","event","Event","Array","isArray","callback","data","TopBarSection","align","_el$2","_tmpl$2","$$focusin","target","HTMLElement","scrollIntoView","block","inline","onFocusIn","TopBarTitle","_el$3","_tmpl$3","TopBarBreadcrumb","_el$4","_tmpl$4","TopBarSearchProps","placeholder","shortcut","keyshortcuts","TopBarSearch","_el$5","_tmpl$6","_el$6","firstChild","aria-keyshortcuts","_$insert","_$createComponent","when","children","_el$7","_tmpl$5","TopBarPill","label","_el$8","_tmpl$7","_el$9","_$delegateEvents","_$mergeProps","_$createComponent","_$delegateEvents"],"sources":["../../../../src/components/layout/top-bar/top-bar.tsx"],"sourcesContent":["import type { ComponentProps } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { Search } from 'lucide-solid'\nimport { cn } from '#lib/utils'\n\n/**\n * TopBar.\n *\n * The window's title row and primary toolbar. Three tracks: a leading group, a\n * centred search, and a trailing group. On wide screens the search is a fixed\n * function of the window width and the side groups are equal remainders. On\n * narrow screens the middle track yields space to the controls, and each side\n * group scrolls when necessary so keyboard focus can reveal every action.\n *\n * On a frameless desktop window this row is also the drag region, so it carries\n * `window-drag` and the controls inside it opt back out. `macos-inset` and\n * `windows-inset` reserve the space the native window controls occupy, which is\n * why the row can look off-centre in a frameless window and be correct: it is\n * centred in the space the user can actually see.\n */\nexport type TopBarProps = ComponentProps<'header'> & {\n /** Make the row draggable, for a frameless window. */\n draggable?: boolean\n /** Reserve space for the macOS traffic lights. */\n macosInset?: boolean\n /** Reserve space for the Windows caption buttons. */\n windowsInset?: boolean\n /** Blur the content scrolling under the bar. */\n glass?: boolean\n}\n\nexport function TopBar(props: TopBarProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'draggable',\n 'macosInset',\n 'windowsInset',\n 'glass',\n ])\n\n return (\n <header\n data-slot=\"top-bar\"\n class={cn(\n 'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card text-card-foreground md:grid-cols-[minmax(0,1fr)_clamp(240px,22vw,480px)_minmax(0,1fr)]',\n local.glass && 'glass-panel',\n local.draggable && 'window-drag',\n /* Each edge gets exactly one inline-padding utility. A window inset\n and px-3 would share a layer and tie-break by build order, and a\n build that put px-3 last hid the leading controls under the\n traffic lights. */\n local.macosInset ? 'window-inset-macos' : 'ps-3',\n local.windowsInset ? 'window-inset-windows' : 'pe-3',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nfunction invokeFocusHandler(handler: unknown, event: Event) {\n if (Array.isArray(handler)) {\n const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]\n callback(data, event)\n } else if (typeof handler === 'function') {\n const callback = handler as (event: Event) => void\n callback(event)\n }\n}\n\n/** A scrollable side group; equal wide-screen tracks centre the search. */\nexport function TopBarSection(props: ComponentProps<'div'> & { align?: 'start' | 'end' }) {\n const [local, rest] = splitProps(props, ['class', 'align', 'onFocusIn'])\n\n return (\n <div\n data-slot=\"top-bar-section\"\n class={cn(\n 'window-no-drag flex min-w-0 items-center gap-2 overflow-x-auto overflow-y-hidden',\n local.align === 'end' && 'md:justify-end',\n local.align !== 'end' && 'justify-start',\n local.class\n )}\n onFocusIn={(event) => {\n if (event.target instanceof HTMLElement) {\n event.target.scrollIntoView({ block: 'nearest', inline: 'nearest' })\n }\n invokeFocusHandler(local.onFocusIn, event)\n }}\n {...rest}\n />\n )\n}\n\nexport function TopBarTitle(\n props: ComponentProps<'div'> & {\n /** Aligns text within this slot; it does not position the slot. */\n align?: 'start' | 'center'\n }\n) {\n const [local, rest] = splitProps(props, ['class', 'align'])\n return (\n <div\n data-slot=\"top-bar-title\"\n class={cn(\n /* The title slot sits in the drag region; a link, button or field\n placed in it (a breadcrumb, a view's search) must stay pressable. */\n 'truncate text-sm font-medium [&_:is(a,button,input)]:window-no-drag',\n local.align === 'center' && 'text-center',\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/** A breadcrumb or path readout that yields to the actions when space runs out. */\nexport function TopBarBreadcrumb(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"top-bar-breadcrumb\"\n class={cn(\n 'flex min-w-0 items-center gap-1.5 text-sm [&_:is(a,button,input)]:window-no-drag',\n local.class\n )}\n {...rest}\n />\n )\n}\n\nexport type TopBarSearchProps = ComponentProps<'button'> & {\n /** The hint shown inside the field, e.g. \"Search projects and files\". */\n placeholder?: string\n /** The shortcut chip drawn at the trailing edge, e.g. \"⌘K\". */\n shortcut?: string\n /**\n * The parseable chord behind `shortcut`, e.g. `Meta+K`. The chip is\n * `aria-hidden` — reading it out would pollute the button's accessible\n * name — so this is what assistive technology announces instead. Supply it\n * whenever `shortcut` is drawn.\n */\n keyshortcuts?: string\n}\n\n/**\n * The search affordance in the middle track.\n *\n * It is a button, not an input, and that is deliberate: clicking it opens the\n * command palette, which already owns the input, the ranking and the keyboard\n * handling. A second live input here would be a second source of truth for the\n * same query. It is styled to read as a field because that is what it behaves\n * like from the user's side.\n */\nexport function TopBarSearch(props: TopBarSearchProps) {\n const [local, rest] = splitProps(props, ['class', 'placeholder', 'shortcut', 'keyshortcuts'])\n\n return (\n <button\n type=\"button\"\n data-slot=\"top-bar-search\"\n class={cn(\n 'text-muted-foreground flex h-control-md w-full min-w-(--control-height-md) items-center justify-center gap-2 rounded-md border border-input px-3 text-sm sm:justify-start',\n 'transition-colors ease-out outline-none',\n 'hover:bg-surface-hover hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'window-no-drag',\n local.class\n )}\n aria-keyshortcuts={local.keyshortcuts}\n {...rest}\n >\n <Search aria-hidden=\"true\" class=\"size-4 shrink-0 sm:hidden\" />\n <span class=\"sr-only sm:not-sr-only sm:truncate\">{local.placeholder ?? 'Search'}</span>\n <Show when={local.shortcut}>\n <kbd\n aria-hidden=\"true\"\n class=\"bg-muted ms-auto hidden h-5 shrink-0 items-center rounded-sm border border-border px-1.5 font-code text-code sm:flex\"\n >\n {local.shortcut}\n </kbd>\n </Show>\n </button>\n )\n}\n\n/**\n * A labelled top-bar control — the readouts KiroCrew puts in the trailing\n * group. Container queries on the group decide which of these survive a narrow\n * window; a caller marks the cheap-to-drop ones and the group handles the rest.\n */\nexport function TopBarPill(props: ComponentProps<'button'> & { label: string }) {\n const [local, rest] = splitProps(props, ['class', 'label', 'children'])\n\n return (\n <button\n type=\"button\"\n data-slot=\"top-bar-pill\"\n class={cn(\n 'text-muted-foreground inline-flex h-control-sm shrink-0 items-center gap-1.5 rounded-md border border-border px-2.5 text-xs font-medium',\n 'transition-colors ease-out outline-none',\n 'hover:border-input hover:text-foreground',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'window-no-drag [&_svg]:size-3.5 [&_svg]:shrink-0',\n local.class\n )}\n {...rest}\n >\n {local.children}\n <span>{local.label}</span>\n </button>\n )\n}\n"],"mappings":"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"}
|
|
@@ -32,7 +32,8 @@ import { DialogContent } from '../dialog/dialog';
|
|
|
32
32
|
*
|
|
33
33
|
* Use `Dialog` directly when you need its composition; use this when you want a
|
|
34
34
|
* dialog that is correct by default. `size="settings"` supplies a wide, bounded
|
|
35
|
-
* shell for a shared settings layout
|
|
35
|
+
* shell for a shared settings layout, titled by a banded header like a sheet's;
|
|
36
|
+
* ordinary dialogs keep their compact default.
|
|
36
37
|
*/
|
|
37
38
|
export type ModalDialogProps = Omit<ComponentProps<typeof DialogContent>, 'children' | 'aria-label' | 'aria-labelledby' | 'positioner'> & {
|
|
38
39
|
/** Selects the bounded, scrollable shell used for grouped workspace settings. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/modal-dialog/modal-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG7D,OAAO,EAGL,aAAa,EAId,MAAM,kBAAkB,CAAA;AAEzB
|
|
1
|
+
{"version":3,"file":"modal-dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/modal-dialog/modal-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAG7D,OAAO,EAGL,aAAa,EAId,MAAM,kBAAkB,CAAA;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,CAAC,OAAO,aAAa,CAAC,EACpC,UAAU,GAAG,YAAY,GAAG,iBAAiB,GAAG,YAAY,CAC7D,GAAG;IACF,iFAAiF;IACjF,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;OAGG;IACH,eAAe,CAAC,EAAE,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC,CAAA;IACnD,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;CACvB,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,eAqGlD"}
|
|
@@ -79,6 +79,9 @@ function ModalDialog(props) {
|
|
|
79
79
|
},
|
|
80
80
|
get children() {
|
|
81
81
|
return [createComponent(DialogHeader, {
|
|
82
|
+
get band() {
|
|
83
|
+
return local.size === "settings";
|
|
84
|
+
},
|
|
82
85
|
get ["class"]() {
|
|
83
86
|
return local.size === "settings" ? "shrink-0 gap-1 border-b border-border px-5 pt-4 pb-3 pe-14" : void 0;
|
|
84
87
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-dialog.js","names":["Accessor","ComponentProps","JSX","Show","createEffect","createSignal","onCleanup","splitProps","cn","createDialogFocusRestoration","Dialog","DialogContent","DialogDescription","DialogHeader","DialogTitle","ModalDialogProps","Omit","size","open","onClose","title","modal","description","headerLeading","Element","restoreFocusRef","HTMLElement","children","ModalDialog","props","local","rest","content","setContent","focusRestoration","onOpenAutoFocus","onCloseAutoFocus","element","background","document","body","filter","child","contains","wasInert","map","node","hasAttribute","setAttribute","forEach","index","removeAttribute","portal","parentElement","_$createComponent","when","onOpenChange","next","_$mergeProps","ref","positioner","class","aria-label","aria-labelledby","undefined","_$memo","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/modal-dialog/modal-dialog.tsx"],"sourcesContent":["import type { Accessor, ComponentProps, JSX } from 'solid-js'\nimport { Show, createEffect, createSignal, onCleanup, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport {\n createDialogFocusRestoration,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '../dialog/dialog'\n\n/**\n * ModalDialog.\n *\n * A dialog that owns four things `Dialog` leaves to its caller, each of which is a\n * real defect when it is missed:\n *\n * 1. **It unmounts while closed.** An always-mounted dialog that closes as a side\n * effect of an async action can leave Kobalte's `aria-hidden` bookkeeping behind,\n * which hides the rest of the application from assistive technology. Unmounting\n * the whole owner makes cleanup the only way the layer can end.\n * 2. **It marks the background `inert`.** `inert` keeps the background out of the\n * tab order and the accessibility tree without depending on that bookkeeping, and\n * it restores exactly the elements that did not already have it — so a nested\n * dialog does not un-inert its parent.\n * 3. **It sets an explicit accessible name.** The content receives `aria-label`\n * from `title`, so its name does not depend on the title id registration effect.\n * Pass `aria-label` to use a different name while keeping the visible title;\n * pass `aria-labelledby` when another visible label should take precedence.\n * 4. **It returns focus to the opener.** The opener is captured before the dialog\n * autofocuses and restored after the owner closes, unless a close-autofocus\n * handler takes control or focus has moved to another layer. For controlled\n * dialogs without a composed trigger, pass `restoreFocusRef` when the opener\n * cannot be inferred from the focused element.\n * 5. **It keeps its own portal out of an enclosing layer's `aria-hidden`\n * bookkeeping.** A non-modal dialog opened while a modal `Sheet` is alive would\n * otherwise be aria-hidden one frame after it mounts — the enclosing layer's\n * hide-outside observer walks late-arriving body children as background. The\n * portal carries the marker that observer exempts; a modal layer opened above\n * still hides it, because that path matches a different attribute.\n *\n * Use `Dialog` directly when you need its composition; use this when you want a\n * dialog that is correct by default. `size=\"settings\"` supplies a wide, bounded\n * shell for a shared settings layout; ordinary dialogs keep their compact default.\n */\nexport type ModalDialogProps = Omit<\n ComponentProps<typeof DialogContent>,\n 'children' | 'aria-label' | 'aria-labelledby' | 'positioner'\n> & {\n /** Selects the bounded, scrollable shell used for grouped workspace settings. */\n size?: 'default' | 'settings'\n open: boolean\n onClose: () => void\n title: string\n /**\n * Controls Kobalte's focus, scroll and accessibility modality. Defaults to `true`;\n * background body children remain inert in either mode.\n */\n modal?: boolean\n description?: string\n /** A mark or icon drawn before the title. */\n headerLeading?: JSX.Element\n /** Replaces `title` as the accessible name while keeping the visible title. */\n 'aria-label'?: string\n /** Names the dialog from a visible element; ARIA gives it precedence over `aria-label`. */\n 'aria-labelledby'?: string\n /**\n * Supplies the external control to focus when this controlled dialog closes.\n * Defaults to the element focused immediately before the dialog opens.\n */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n children?: JSX.Element\n}\n\nexport function ModalDialog(props: ModalDialogProps) {\n const [local, rest] = splitProps(props, [\n 'open',\n 'onClose',\n 'title',\n 'modal',\n 'size',\n 'description',\n 'headerLeading',\n 'class',\n 'children',\n 'aria-label',\n 'aria-labelledby',\n 'restoreFocusRef',\n 'onOpenAutoFocus',\n 'onCloseAutoFocus',\n ])\n\n const [content, setContent] = createSignal<HTMLElement>()\n const focusRestoration = createDialogFocusRestoration({\n open: () => local.open,\n restoreFocusRef: local.restoreFocusRef,\n onOpenAutoFocus: local.onOpenAutoFocus,\n onCloseAutoFocus: local.onCloseAutoFocus,\n })\n\n createEffect(() => {\n if (!local.open) return\n const element = content()\n if (!element) return\n\n const background = [...document.body.children].filter(\n (child): child is HTMLElement => child instanceof HTMLElement && !child.contains(element)\n )\n const wasInert = background.map((node) => node.hasAttribute('inert'))\n for (const node of background) node.setAttribute('inert', '')\n\n onCleanup(() => {\n background.forEach((node, index) => {\n // Only the elements that were not already inert are restored, so a nested\n // dialog closing does not undo its parent's containment.\n if (!wasInert[index]) node.removeAttribute('inert')\n })\n })\n\n // Kobalte's hide-outside observer walks body children added after its layer\n // opened and aria-hides them one frame later, so a non-modal dialog portaled\n // in during that window would land outside the accessibility tree — role\n // queries never resolve it again while the enclosing layer stays open. The\n // observer exempts added nodes carrying its top-layer marker (it checks the\n // React Aria spelling it ported; `data-kb-top-layer` is only matched by a\n // newer layer's initial walk, which must still hide this dialog).\n let portal = element\n while (portal.parentElement !== null && portal.parentElement !== document.body) {\n portal = portal.parentElement\n }\n portal.setAttribute('data-react-aria-top-layer', 'true')\n onCleanup(() => portal.removeAttribute('data-react-aria-top-layer'))\n })\n\n return (\n <Show when={local.open}>\n <Dialog open modal={local.modal ?? true} onOpenChange={(next) => !next && local.onClose()}>\n <DialogContent\n ref={setContent}\n positioner={local.size === 'settings' ? 'inset' : 'default'}\n class={cn(\n 'gap-4',\n local.size === 'settings' &&\n 'flex h-208 max-h-full min-h-0 max-w-6xl flex-col gap-0 overflow-hidden p-0',\n local.class\n )}\n aria-label={local['aria-label'] ?? local.title}\n aria-labelledby={\n local['aria-labelledby'] ?? (local['aria-label'] !== undefined ? '' : undefined)\n }\n {...rest}\n onOpenAutoFocus={focusRestoration.onOpenAutoFocus}\n onCloseAutoFocus={focusRestoration.onCloseAutoFocus}\n >\n <DialogHeader\n class={\n local.size === 'settings'\n ? 'shrink-0 gap-1 border-b border-border px-5 pt-4 pb-3 pe-14'\n : undefined\n }\n >\n <DialogTitle class=\"flex items-center gap-2\">\n <Show when={local.headerLeading}>{local.headerLeading}</Show>\n {local.title}\n </DialogTitle>\n <Show when={local.description}>\n <DialogDescription>{local.description}</DialogDescription>\n </Show>\n </DialogHeader>\n {local.children}\n </DialogContent>\n </Dialog>\n </Show>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modal-dialog.js","names":["Accessor","ComponentProps","JSX","Show","createEffect","createSignal","onCleanup","splitProps","cn","createDialogFocusRestoration","Dialog","DialogContent","DialogDescription","DialogHeader","DialogTitle","ModalDialogProps","Omit","size","open","onClose","title","modal","description","headerLeading","Element","restoreFocusRef","HTMLElement","children","ModalDialog","props","local","rest","content","setContent","focusRestoration","onOpenAutoFocus","onCloseAutoFocus","element","background","document","body","filter","child","contains","wasInert","map","node","hasAttribute","setAttribute","forEach","index","removeAttribute","portal","parentElement","_$createComponent","when","onOpenChange","next","_$mergeProps","ref","positioner","class","aria-label","aria-labelledby","undefined","band","_$memo","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/modal-dialog/modal-dialog.tsx"],"sourcesContent":["import type { Accessor, ComponentProps, JSX } from 'solid-js'\nimport { Show, createEffect, createSignal, onCleanup, splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\nimport {\n createDialogFocusRestoration,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '../dialog/dialog'\n\n/**\n * ModalDialog.\n *\n * A dialog that owns four things `Dialog` leaves to its caller, each of which is a\n * real defect when it is missed:\n *\n * 1. **It unmounts while closed.** An always-mounted dialog that closes as a side\n * effect of an async action can leave Kobalte's `aria-hidden` bookkeeping behind,\n * which hides the rest of the application from assistive technology. Unmounting\n * the whole owner makes cleanup the only way the layer can end.\n * 2. **It marks the background `inert`.** `inert` keeps the background out of the\n * tab order and the accessibility tree without depending on that bookkeeping, and\n * it restores exactly the elements that did not already have it — so a nested\n * dialog does not un-inert its parent.\n * 3. **It sets an explicit accessible name.** The content receives `aria-label`\n * from `title`, so its name does not depend on the title id registration effect.\n * Pass `aria-label` to use a different name while keeping the visible title;\n * pass `aria-labelledby` when another visible label should take precedence.\n * 4. **It returns focus to the opener.** The opener is captured before the dialog\n * autofocuses and restored after the owner closes, unless a close-autofocus\n * handler takes control or focus has moved to another layer. For controlled\n * dialogs without a composed trigger, pass `restoreFocusRef` when the opener\n * cannot be inferred from the focused element.\n * 5. **It keeps its own portal out of an enclosing layer's `aria-hidden`\n * bookkeeping.** A non-modal dialog opened while a modal `Sheet` is alive would\n * otherwise be aria-hidden one frame after it mounts — the enclosing layer's\n * hide-outside observer walks late-arriving body children as background. The\n * portal carries the marker that observer exempts; a modal layer opened above\n * still hides it, because that path matches a different attribute.\n *\n * Use `Dialog` directly when you need its composition; use this when you want a\n * dialog that is correct by default. `size=\"settings\"` supplies a wide, bounded\n * shell for a shared settings layout, titled by a banded header like a sheet's;\n * ordinary dialogs keep their compact default.\n */\nexport type ModalDialogProps = Omit<\n ComponentProps<typeof DialogContent>,\n 'children' | 'aria-label' | 'aria-labelledby' | 'positioner'\n> & {\n /** Selects the bounded, scrollable shell used for grouped workspace settings. */\n size?: 'default' | 'settings'\n open: boolean\n onClose: () => void\n title: string\n /**\n * Controls Kobalte's focus, scroll and accessibility modality. Defaults to `true`;\n * background body children remain inert in either mode.\n */\n modal?: boolean\n description?: string\n /** A mark or icon drawn before the title. */\n headerLeading?: JSX.Element\n /** Replaces `title` as the accessible name while keeping the visible title. */\n 'aria-label'?: string\n /** Names the dialog from a visible element; ARIA gives it precedence over `aria-label`. */\n 'aria-labelledby'?: string\n /**\n * Supplies the external control to focus when this controlled dialog closes.\n * Defaults to the element focused immediately before the dialog opens.\n */\n restoreFocusRef?: Accessor<HTMLElement | undefined>\n children?: JSX.Element\n}\n\nexport function ModalDialog(props: ModalDialogProps) {\n const [local, rest] = splitProps(props, [\n 'open',\n 'onClose',\n 'title',\n 'modal',\n 'size',\n 'description',\n 'headerLeading',\n 'class',\n 'children',\n 'aria-label',\n 'aria-labelledby',\n 'restoreFocusRef',\n 'onOpenAutoFocus',\n 'onCloseAutoFocus',\n ])\n\n const [content, setContent] = createSignal<HTMLElement>()\n const focusRestoration = createDialogFocusRestoration({\n open: () => local.open,\n restoreFocusRef: local.restoreFocusRef,\n onOpenAutoFocus: local.onOpenAutoFocus,\n onCloseAutoFocus: local.onCloseAutoFocus,\n })\n\n createEffect(() => {\n if (!local.open) return\n const element = content()\n if (!element) return\n\n const background = [...document.body.children].filter(\n (child): child is HTMLElement => child instanceof HTMLElement && !child.contains(element)\n )\n const wasInert = background.map((node) => node.hasAttribute('inert'))\n for (const node of background) node.setAttribute('inert', '')\n\n onCleanup(() => {\n background.forEach((node, index) => {\n // Only the elements that were not already inert are restored, so a nested\n // dialog closing does not undo its parent's containment.\n if (!wasInert[index]) node.removeAttribute('inert')\n })\n })\n\n // Kobalte's hide-outside observer walks body children added after its layer\n // opened and aria-hides them one frame later, so a non-modal dialog portaled\n // in during that window would land outside the accessibility tree — role\n // queries never resolve it again while the enclosing layer stays open. The\n // observer exempts added nodes carrying its top-layer marker (it checks the\n // React Aria spelling it ported; `data-kb-top-layer` is only matched by a\n // newer layer's initial walk, which must still hide this dialog).\n let portal = element\n while (portal.parentElement !== null && portal.parentElement !== document.body) {\n portal = portal.parentElement\n }\n portal.setAttribute('data-react-aria-top-layer', 'true')\n onCleanup(() => portal.removeAttribute('data-react-aria-top-layer'))\n })\n\n return (\n <Show when={local.open}>\n <Dialog open modal={local.modal ?? true} onOpenChange={(next) => !next && local.onClose()}>\n <DialogContent\n ref={setContent}\n positioner={local.size === 'settings' ? 'inset' : 'default'}\n class={cn(\n 'gap-4',\n local.size === 'settings' &&\n 'flex h-208 max-h-full min-h-0 max-w-6xl flex-col gap-0 overflow-hidden p-0',\n local.class\n )}\n aria-label={local['aria-label'] ?? local.title}\n aria-labelledby={\n local['aria-labelledby'] ?? (local['aria-label'] !== undefined ? '' : undefined)\n }\n {...rest}\n onOpenAutoFocus={focusRestoration.onOpenAutoFocus}\n onCloseAutoFocus={focusRestoration.onCloseAutoFocus}\n >\n <DialogHeader\n band={local.size === 'settings'}\n class={\n local.size === 'settings'\n ? 'shrink-0 gap-1 border-b border-border px-5 pt-4 pb-3 pe-14'\n : undefined\n }\n >\n <DialogTitle class=\"flex items-center gap-2\">\n <Show when={local.headerLeading}>{local.headerLeading}</Show>\n {local.title}\n </DialogTitle>\n <Show when={local.description}>\n <DialogDescription>{local.description}</DialogDescription>\n </Show>\n </DialogHeader>\n {local.children}\n </DialogContent>\n </Dialog>\n </Show>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resizable.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/resizable/resizable.tsx"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,kBAAkB,CAAA;AAExC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAuB9C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAa/F;AAgBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAchG;AAED,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,SAAS,CAAC,MAAM,CAAC,GAAG;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"resizable.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/resizable/resizable.tsx"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,kBAAkB,CAAA;AAExC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAuB9C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAa/F;AAgBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAchG;AAED,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,OAAO,SAAS,CAAC,MAAM,CAAC,GAAG;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,kCAgC1D"}
|
|
@@ -75,7 +75,7 @@ function ResizableHandle(props) {
|
|
|
75
75
|
return group.orientation() === "horizontal" ? "vertical" : "horizontal";
|
|
76
76
|
},
|
|
77
77
|
get ["class"]() {
|
|
78
|
-
return cn("group/resize bg-border relative flex w-px shrink-0 items-center justify-center", "after:absolute after:inset-y-0 after:-inset-x-
|
|
78
|
+
return cn("group/resize bg-border relative flex w-px shrink-0 items-center justify-center", "after:absolute after:inset-y-0 after:-inset-x-3 after:w-6", "transition-colors ease-out hover:bg-primary", "focus-visible:bg-primary focus-visible:outline-none", "data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full", "data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-3 data-[orientation=vertical]:after:h-6 data-[orientation=vertical]:after:w-full", local.class);
|
|
79
79
|
}
|
|
80
80
|
}, rest, { get children() {
|
|
81
81
|
return memo(() => !!local.withHandle)() ? (() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resizable.js","names":["Resizable","GripVertical","ComponentProps","createContext","splitProps","useContext","cn","GroupSizesContext","ResizablePanelGroup","props","class","local","rest","_$createComponent","Provider","value","initialSizes","undefined","sizes","children","_$mergeProps","remainingSize","left","reduce","total","size","length","ResizablePanel","Panel","group","contextId","groupHasSizes","initialSize","ResizableHandleProps","Handle","withHandle","label","ResizableHandle","aria-label","aria-orientation","orientation","_$memo","_el$","_tmpl$","_$insert","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/resizable/resizable.tsx"],"sourcesContent":["import Resizable from '@corvu/resizable'\nimport { GripVertical } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { createContext, splitProps, useContext } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * Resizable.\n *\n * A split layout: panels the user can resize, with a handle between them. This\n * is the shape of every IDE-like surface — rail, file tree, editor, terminal —\n * and the reason it is a primitive rather than something each view improvises.\n *\n * corvu supplies the pointer capture, the min/max constraints and the keyboard\n * resizing, which is what makes a divider operable without a mouse. The handle\n * is a real focusable element with an accessible role, so a split pane can be\n * adjusted from the keyboard; a bare `cursor-col-resize` div cannot.\n */\n/**\n * Whether the group was given `initialSizes` or controlled `sizes`. Those are corvu's to apply, and a\n * panel's own `initialSize` overrides them — so an unsized panel must not invent\n * one when the group already has an answer.\n */\nconst GroupSizesContext = createContext<() => boolean>(() => false)\n\nexport function ResizablePanelGroup(props: ComponentProps<typeof Resizable> & { class?: string }) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <GroupSizesContext.Provider\n value={() => rest.initialSizes !== undefined || rest.sizes !== undefined}\n >\n <Resizable\n class={cn('flex size-full data-[orientation=vertical]:flex-col', local.class)}\n {...rest}\n />\n </GroupSizesContext.Provider>\n )\n}\n\n/**\n * The size an unsized panel registers with: whatever its earlier siblings left.\n *\n * corvu registers a panel without `initialSize` at a flat 50%, so `0.28` beside\n * an unsized panel summed to 78% and left a gap. Panels register in document\n * order, so at registration `sizes` holds exactly the panels before this one.\n * When nothing is left — a second unsized panel — it takes an equal share, and\n * corvu shrinks the earlier panels by that share to keep the total at 100%.\n */\nfunction remainingSize(sizes: readonly number[]): number {\n const left = 1 - sizes.reduce((total, size) => total + size, 0)\n return left > 0.001 ? left : 1 / (sizes.length + 1)\n}\n\nexport function ResizablePanel(props: ComponentProps<typeof Resizable.Panel> & { class?: string }) {\n const [local, rest] = splitProps(props, ['class', 'initialSize'])\n const group = Resizable.useContext(rest.contextId)\n const groupHasSizes = useContext(GroupSizesContext)\n\n return (\n <Resizable.Panel\n initialSize={\n local.initialSize ?? (groupHasSizes() ? undefined : remainingSize(group.sizes()))\n }\n class={cn('min-h-0 min-w-0 overflow-hidden', local.class)}\n {...rest}\n />\n )\n}\n\nexport type ResizableHandleProps = ComponentProps<typeof Resizable.Handle> & {\n class?: string\n /** Draw a visible grip in the middle of the divider. */\n withHandle?: boolean\n /**\n * The divider's accessible name. It is a focusable control — arrow keys move\n * the split — so it needs one; without it a screen reader announces an\n * unlabelled button between the two panels.\n */\n label?: string\n}\n\nexport function ResizableHandle(props: ResizableHandleProps) {\n const [local, rest] = splitProps(props, ['class', 'withHandle', 'label'])\n const group = Resizable.useContext(rest.contextId)\n\n return (\n <Resizable.Handle\n aria-label={local.label ?? 'Resize panels'}\n // A separator's orientation is the line's own, which runs across the\n // group: a row of panels is divided by a vertical line, a column by a\n // horizontal one. corvu reports the group's orientation instead.\n aria-orientation={group.orientation() === 'horizontal' ? 'vertical' : 'horizontal'}\n class={cn(\n 'group/resize bg-border relative flex w-px shrink-0 items-center justify-center',\n /* Widen the hit target without moving the visual line: the divider is\n a hairline, but a hairline is far too small to grab. */\n 'after:absolute after:inset-y-0 after:-inset-x-
|
|
1
|
+
{"version":3,"file":"resizable.js","names":["Resizable","GripVertical","ComponentProps","createContext","splitProps","useContext","cn","GroupSizesContext","ResizablePanelGroup","props","class","local","rest","_$createComponent","Provider","value","initialSizes","undefined","sizes","children","_$mergeProps","remainingSize","left","reduce","total","size","length","ResizablePanel","Panel","group","contextId","groupHasSizes","initialSize","ResizableHandleProps","Handle","withHandle","label","ResizableHandle","aria-label","aria-orientation","orientation","_$memo","_el$","_tmpl$","_$insert","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/resizable/resizable.tsx"],"sourcesContent":["import Resizable from '@corvu/resizable'\nimport { GripVertical } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { createContext, splitProps, useContext } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * Resizable.\n *\n * A split layout: panels the user can resize, with a handle between them. This\n * is the shape of every IDE-like surface — rail, file tree, editor, terminal —\n * and the reason it is a primitive rather than something each view improvises.\n *\n * corvu supplies the pointer capture, the min/max constraints and the keyboard\n * resizing, which is what makes a divider operable without a mouse. The handle\n * is a real focusable element with an accessible role, so a split pane can be\n * adjusted from the keyboard; a bare `cursor-col-resize` div cannot.\n */\n/**\n * Whether the group was given `initialSizes` or controlled `sizes`. Those are corvu's to apply, and a\n * panel's own `initialSize` overrides them — so an unsized panel must not invent\n * one when the group already has an answer.\n */\nconst GroupSizesContext = createContext<() => boolean>(() => false)\n\nexport function ResizablePanelGroup(props: ComponentProps<typeof Resizable> & { class?: string }) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <GroupSizesContext.Provider\n value={() => rest.initialSizes !== undefined || rest.sizes !== undefined}\n >\n <Resizable\n class={cn('flex size-full data-[orientation=vertical]:flex-col', local.class)}\n {...rest}\n />\n </GroupSizesContext.Provider>\n )\n}\n\n/**\n * The size an unsized panel registers with: whatever its earlier siblings left.\n *\n * corvu registers a panel without `initialSize` at a flat 50%, so `0.28` beside\n * an unsized panel summed to 78% and left a gap. Panels register in document\n * order, so at registration `sizes` holds exactly the panels before this one.\n * When nothing is left — a second unsized panel — it takes an equal share, and\n * corvu shrinks the earlier panels by that share to keep the total at 100%.\n */\nfunction remainingSize(sizes: readonly number[]): number {\n const left = 1 - sizes.reduce((total, size) => total + size, 0)\n return left > 0.001 ? left : 1 / (sizes.length + 1)\n}\n\nexport function ResizablePanel(props: ComponentProps<typeof Resizable.Panel> & { class?: string }) {\n const [local, rest] = splitProps(props, ['class', 'initialSize'])\n const group = Resizable.useContext(rest.contextId)\n const groupHasSizes = useContext(GroupSizesContext)\n\n return (\n <Resizable.Panel\n initialSize={\n local.initialSize ?? (groupHasSizes() ? undefined : remainingSize(group.sizes()))\n }\n class={cn('min-h-0 min-w-0 overflow-hidden', local.class)}\n {...rest}\n />\n )\n}\n\nexport type ResizableHandleProps = ComponentProps<typeof Resizable.Handle> & {\n class?: string\n /** Draw a visible grip in the middle of the divider. */\n withHandle?: boolean\n /**\n * The divider's accessible name. It is a focusable control — arrow keys move\n * the split — so it needs one; without it a screen reader announces an\n * unlabelled button between the two panels.\n */\n label?: string\n}\n\nexport function ResizableHandle(props: ResizableHandleProps) {\n const [local, rest] = splitProps(props, ['class', 'withHandle', 'label'])\n const group = Resizable.useContext(rest.contextId)\n\n return (\n <Resizable.Handle\n aria-label={local.label ?? 'Resize panels'}\n // A separator's orientation is the line's own, which runs across the\n // group: a row of panels is divided by a vertical line, a column by a\n // horizontal one. corvu reports the group's orientation instead.\n aria-orientation={group.orientation() === 'horizontal' ? 'vertical' : 'horizontal'}\n class={cn(\n 'group/resize bg-border relative flex w-px shrink-0 items-center justify-center',\n /* Widen the hit target without moving the visual line: the divider is\n a hairline, but a hairline is far too small to grab. 24px on the\n drag axis meets WCAG 2.5.8's minimum target. */\n 'after:absolute after:inset-y-0 after:-inset-x-3 after:w-6',\n 'transition-colors ease-out hover:bg-primary',\n 'focus-visible:bg-primary focus-visible:outline-none',\n 'data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full',\n 'data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-3 data-[orientation=vertical]:after:h-6 data-[orientation=vertical]:after:w-full',\n local.class\n )}\n {...rest}\n >\n {local.withHandle ? (\n <div class=\"bg-border z-(--z-docked) flex h-4 w-2.5 items-center justify-center rounded-sm border border-border\">\n <GripVertical class=\"size-2.5 text-muted-foreground\" />\n </div>\n ) : null}\n </Resizable.Handle>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAuBA,IAAMO,oBAAoBJ,oBAAmC,KAAK;AAElE,SAAgBK,oBAAoBC,OAA8D;CAChG,MAAM,CAACE,OAAOC,QAAQR,WAAWK,OAAO,CAAC,OAAO,CAAC;CAEjD,OAAAI,gBACGN,kBAAkBO,UAAQ;EACzBC,aAAaH,KAAKI,iBAAiBC,KAAAA,KAAaL,KAAKM,UAAUD,KAAAA;EAAS,IAAAE,WAAA;GAAA,OAAAN,gBAEvEb,WAASoB,WAAA,EAAA,KAAA,WAAA;IAAA,OACDd,GAAG,uDAAuDK,MAAMD,KAAK;GAAC,EAAA,GACzEE,IAAI,CAAA;EAAA;CAAA,CAAA;AAIhB;;;;;;;;;;AAWA,SAASS,cAAcH,OAAkC;CACvD,MAAMI,OAAO,IAAIJ,MAAMK,QAAQC,OAAOC,SAASD,QAAQC,MAAM,CAAC;CAC9D,OAAOH,OAAO,OAAQA,OAAO,KAAKJ,MAAMQ,SAAS;AACnD;AAEA,SAAgBC,eAAelB,OAAoE;CACjG,MAAM,CAACE,OAAOC,QAAQR,WAAWK,OAAO,CAAC,SAAS,aAAa,CAAC;CAChE,MAAMoB,QAAQ7B,UAAUK,WAAWO,KAAKkB,SAAS;CACjD,MAAMC,gBAAgB1B,WAAWE,iBAAiB;CAElD,OAAAM,gBACGb,UAAU4B,OAAKR,WAAA;EAAA,IACdY,cAAW;GAAA,OACTrB,MAAMqB,gBAAgBD,cAAc,IAAId,KAAAA,IAAYI,cAAcQ,MAAMX,MAAM,CAAC;EAAE;EAAA,KAAA,WAAA;GAAA,OAE5EZ,GAAG,mCAAmCK,MAAMD,KAAK;EAAC;CAAA,GACrDE,IAAI,CAAA;AAGd;AAcA,SAAgByB,gBAAgB5B,OAA6B;CAC3D,MAAM,CAACE,OAAOC,QAAQR,WAAWK,OAAO;EAAC;EAAS;EAAc;CAAO,CAAC;CACxE,MAAMoB,QAAQ7B,UAAUK,WAAWO,KAAKkB,SAAS;CAEjD,OAAAjB,gBACGb,UAAUkC,QAAMd,WAAA;EAAA,KAAA,gBAAA;GAAA,OACHT,MAAMyB,SAAS;EAAe;EAAA,KAAA,sBAAA;GAAA,OAIxBP,MAAMW,YAAY,MAAM,eAAe,aAAa;EAAY;EAAA,KAAA,WAAA;GAAA,OAC3ElC,GACL,kFAIA,6DACA,+CACA,uDACA,uEACA,2KACAK,MAAMD,KACR;EAAC;CAAA,GACGE,MAAI,EAAA,IAAAO,WAAA;EAAA,OAEPsB,WAAA,CAAA,CAAA9B,MAAMwB,UAAU,CAAA,CAAA,WAAA;GAAA,IAAAO,OAAAC,OAAA;GAAAC,OAAAF,MAAA7B,gBAEZZ,cAAY,EAAA,SAAA,iCAAA,CAAA,CAAA;GAAA,OAAAyC;EAAA,EAAA,CAAA,IAEb;CAAI,EAAA,CAAA,CAAA;AAGd"}
|
|
@@ -164,6 +164,9 @@ export function ContextualSidebar(props: ContextualSidebarProps) {
|
|
|
164
164
|
>
|
|
165
165
|
<Show when={!mobile && props.open}>
|
|
166
166
|
<PixelResizeHandle
|
|
167
|
+
// The ruler spans the sidebar as a pointer-events-none overlay; lift
|
|
168
|
+
// it above the neighbouring pane so the edge stays grabbable.
|
|
169
|
+
class="z-(--z-docked)"
|
|
167
170
|
side="left"
|
|
168
171
|
value={props.width}
|
|
169
172
|
minimum={props.minimum}
|
|
@@ -88,7 +88,12 @@ export function SidebarNavContent(props: ComponentProps<'div'>) {
|
|
|
88
88
|
return (
|
|
89
89
|
<div
|
|
90
90
|
data-slot="sidebar-nav-content"
|
|
91
|
-
class={cn(
|
|
91
|
+
class={cn(
|
|
92
|
+
/* A stable gutter keeps rows from shifting sideways when the list
|
|
93
|
+
grows past the fold and the scrollbar appears. */
|
|
94
|
+
'flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-2 py-2 [scrollbar-gutter:stable]',
|
|
95
|
+
local.class
|
|
96
|
+
)}
|
|
92
97
|
{...rest}
|
|
93
98
|
/>
|
|
94
99
|
)
|
|
@@ -236,6 +241,11 @@ export function SidebarNavSection(props: SidebarNavSectionProps) {
|
|
|
236
241
|
}}
|
|
237
242
|
class={cn(
|
|
238
243
|
'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11',
|
|
244
|
+
/* WCAG 2.5.8: the row's vertical padding sits on the header, so
|
|
245
|
+
the bare label would be a ~16px target. Stretch the button
|
|
246
|
+
across that padding; the row's height does not change. A
|
|
247
|
+
coarse pointer already gets min-h-11 on an unpadded row. */
|
|
248
|
+
'-my-1.5 py-1.5 [@media(any-pointer:coarse)]:my-0 [@media(any-pointer:coarse)]:py-0',
|
|
239
249
|
local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'
|
|
240
250
|
)}
|
|
241
251
|
>
|
|
@@ -42,11 +42,15 @@ export function TopBar(props: TopBarProps) {
|
|
|
42
42
|
<header
|
|
43
43
|
data-slot="top-bar"
|
|
44
44
|
class={cn(
|
|
45
|
-
'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card text-card-foreground
|
|
45
|
+
'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card text-card-foreground md:grid-cols-[minmax(0,1fr)_clamp(240px,22vw,480px)_minmax(0,1fr)]',
|
|
46
46
|
local.glass && 'glass-panel',
|
|
47
47
|
local.draggable && 'window-drag',
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
/* Each edge gets exactly one inline-padding utility. A window inset
|
|
49
|
+
and px-3 would share a layer and tie-break by build order, and a
|
|
50
|
+
build that put px-3 last hid the leading controls under the
|
|
51
|
+
traffic lights. */
|
|
52
|
+
local.macosInset ? 'window-inset-macos' : 'ps-3',
|
|
53
|
+
local.windowsInset ? 'window-inset-windows' : 'pe-3',
|
|
50
54
|
local.class
|
|
51
55
|
)}
|
|
52
56
|
{...rest}
|
|
@@ -42,7 +42,8 @@ import {
|
|
|
42
42
|
*
|
|
43
43
|
* Use `Dialog` directly when you need its composition; use this when you want a
|
|
44
44
|
* dialog that is correct by default. `size="settings"` supplies a wide, bounded
|
|
45
|
-
* shell for a shared settings layout
|
|
45
|
+
* shell for a shared settings layout, titled by a banded header like a sheet's;
|
|
46
|
+
* ordinary dialogs keep their compact default.
|
|
46
47
|
*/
|
|
47
48
|
export type ModalDialogProps = Omit<
|
|
48
49
|
ComponentProps<typeof DialogContent>,
|
|
@@ -154,6 +155,7 @@ export function ModalDialog(props: ModalDialogProps) {
|
|
|
154
155
|
onCloseAutoFocus={focusRestoration.onCloseAutoFocus}
|
|
155
156
|
>
|
|
156
157
|
<DialogHeader
|
|
158
|
+
band={local.size === 'settings'}
|
|
157
159
|
class={
|
|
158
160
|
local.size === 'settings'
|
|
159
161
|
? 'shrink-0 gap-1 border-b border-border px-5 pt-4 pb-3 pe-14'
|
|
@@ -94,12 +94,13 @@ export function ResizableHandle(props: ResizableHandleProps) {
|
|
|
94
94
|
class={cn(
|
|
95
95
|
'group/resize bg-border relative flex w-px shrink-0 items-center justify-center',
|
|
96
96
|
/* Widen the hit target without moving the visual line: the divider is
|
|
97
|
-
a hairline, but a hairline is far too small to grab.
|
|
98
|
-
|
|
97
|
+
a hairline, but a hairline is far too small to grab. 24px on the
|
|
98
|
+
drag axis meets WCAG 2.5.8's minimum target. */
|
|
99
|
+
'after:absolute after:inset-y-0 after:-inset-x-3 after:w-6',
|
|
99
100
|
'transition-colors ease-out hover:bg-primary',
|
|
100
101
|
'focus-visible:bg-primary focus-visible:outline-none',
|
|
101
102
|
'data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full',
|
|
102
|
-
'data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-
|
|
103
|
+
'data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-3 data-[orientation=vertical]:after:h-6 data-[orientation=vertical]:after:w-full',
|
|
103
104
|
local.class
|
|
104
105
|
)}
|
|
105
106
|
{...rest}
|
package/package.json
CHANGED
|
@@ -164,6 +164,9 @@ export function ContextualSidebar(props: ContextualSidebarProps) {
|
|
|
164
164
|
>
|
|
165
165
|
<Show when={!mobile && props.open}>
|
|
166
166
|
<PixelResizeHandle
|
|
167
|
+
// The ruler spans the sidebar as a pointer-events-none overlay; lift
|
|
168
|
+
// it above the neighbouring pane so the edge stays grabbable.
|
|
169
|
+
class="z-(--z-docked)"
|
|
167
170
|
side="left"
|
|
168
171
|
value={props.width}
|
|
169
172
|
minimum={props.minimum}
|
|
@@ -88,7 +88,12 @@ export function SidebarNavContent(props: ComponentProps<'div'>) {
|
|
|
88
88
|
return (
|
|
89
89
|
<div
|
|
90
90
|
data-slot="sidebar-nav-content"
|
|
91
|
-
class={cn(
|
|
91
|
+
class={cn(
|
|
92
|
+
/* A stable gutter keeps rows from shifting sideways when the list
|
|
93
|
+
grows past the fold and the scrollbar appears. */
|
|
94
|
+
'flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-2 py-2 [scrollbar-gutter:stable]',
|
|
95
|
+
local.class
|
|
96
|
+
)}
|
|
92
97
|
{...rest}
|
|
93
98
|
/>
|
|
94
99
|
)
|
|
@@ -236,6 +241,11 @@ export function SidebarNavSection(props: SidebarNavSectionProps) {
|
|
|
236
241
|
}}
|
|
237
242
|
class={cn(
|
|
238
243
|
'flex min-w-0 flex-1 items-center gap-1.5 rounded-sm text-2xs font-medium tracking-wide uppercase outline-none transition-colors ease-out hover:text-sidebar-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle [@media(any-pointer:coarse)]:min-h-11',
|
|
244
|
+
/* WCAG 2.5.8: the row's vertical padding sits on the header, so
|
|
245
|
+
the bare label would be a ~16px target. Stretch the button
|
|
246
|
+
across that padding; the row's height does not change. A
|
|
247
|
+
coarse pointer already gets min-h-11 on an unpadded row. */
|
|
248
|
+
'-my-1.5 py-1.5 [@media(any-pointer:coarse)]:my-0 [@media(any-pointer:coarse)]:py-0',
|
|
239
249
|
local.active ? 'text-foreground' : 'text-sidebar-muted-foreground'
|
|
240
250
|
)}
|
|
241
251
|
>
|
|
@@ -42,11 +42,15 @@ export function TopBar(props: TopBarProps) {
|
|
|
42
42
|
<header
|
|
43
43
|
data-slot="top-bar"
|
|
44
44
|
class={cn(
|
|
45
|
-
'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card text-card-foreground
|
|
45
|
+
'h-topbar relative z-(--z-sticky) grid shrink-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3 border-b border-border bg-card text-card-foreground md:grid-cols-[minmax(0,1fr)_clamp(240px,22vw,480px)_minmax(0,1fr)]',
|
|
46
46
|
local.glass && 'glass-panel',
|
|
47
47
|
local.draggable && 'window-drag',
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
/* Each edge gets exactly one inline-padding utility. A window inset
|
|
49
|
+
and px-3 would share a layer and tie-break by build order, and a
|
|
50
|
+
build that put px-3 last hid the leading controls under the
|
|
51
|
+
traffic lights. */
|
|
52
|
+
local.macosInset ? 'window-inset-macos' : 'ps-3',
|
|
53
|
+
local.windowsInset ? 'window-inset-windows' : 'pe-3',
|
|
50
54
|
local.class
|
|
51
55
|
)}
|
|
52
56
|
{...rest}
|
|
@@ -42,7 +42,8 @@ import {
|
|
|
42
42
|
*
|
|
43
43
|
* Use `Dialog` directly when you need its composition; use this when you want a
|
|
44
44
|
* dialog that is correct by default. `size="settings"` supplies a wide, bounded
|
|
45
|
-
* shell for a shared settings layout
|
|
45
|
+
* shell for a shared settings layout, titled by a banded header like a sheet's;
|
|
46
|
+
* ordinary dialogs keep their compact default.
|
|
46
47
|
*/
|
|
47
48
|
export type ModalDialogProps = Omit<
|
|
48
49
|
ComponentProps<typeof DialogContent>,
|
|
@@ -154,6 +155,7 @@ export function ModalDialog(props: ModalDialogProps) {
|
|
|
154
155
|
onCloseAutoFocus={focusRestoration.onCloseAutoFocus}
|
|
155
156
|
>
|
|
156
157
|
<DialogHeader
|
|
158
|
+
band={local.size === 'settings'}
|
|
157
159
|
class={
|
|
158
160
|
local.size === 'settings'
|
|
159
161
|
? 'shrink-0 gap-1 border-b border-border px-5 pt-4 pb-3 pe-14'
|
|
@@ -94,12 +94,13 @@ export function ResizableHandle(props: ResizableHandleProps) {
|
|
|
94
94
|
class={cn(
|
|
95
95
|
'group/resize bg-border relative flex w-px shrink-0 items-center justify-center',
|
|
96
96
|
/* Widen the hit target without moving the visual line: the divider is
|
|
97
|
-
a hairline, but a hairline is far too small to grab.
|
|
98
|
-
|
|
97
|
+
a hairline, but a hairline is far too small to grab. 24px on the
|
|
98
|
+
drag axis meets WCAG 2.5.8's minimum target. */
|
|
99
|
+
'after:absolute after:inset-y-0 after:-inset-x-3 after:w-6',
|
|
99
100
|
'transition-colors ease-out hover:bg-primary',
|
|
100
101
|
'focus-visible:bg-primary focus-visible:outline-none',
|
|
101
102
|
'data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full',
|
|
102
|
-
'data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-
|
|
103
|
+
'data-[orientation=vertical]:after:inset-x-0 data-[orientation=vertical]:after:-inset-y-3 data-[orientation=vertical]:after:h-6 data-[orientation=vertical]:after:w-full',
|
|
103
104
|
local.class
|
|
104
105
|
)}
|
|
105
106
|
{...rest}
|