@arbidocs/blocks 0.4.112 → 0.4.113
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/agents/index.cjs +208 -208
- package/dist/agents/index.js +3 -3
- package/dist/chat/index.cjs +131 -131
- package/dist/chat/index.js +4 -4
- package/dist/{chunk-HBBJYRGI.cjs → chunk-5U4WY2VW.cjs} +9 -9
- package/dist/{chunk-HBBJYRGI.cjs.map → chunk-5U4WY2VW.cjs.map} +1 -1
- package/dist/{chunk-XKSFJYOD.cjs → chunk-5UHAWSEX.cjs} +4 -4
- package/dist/{chunk-XKSFJYOD.cjs.map → chunk-5UHAWSEX.cjs.map} +1 -1
- package/dist/{chunk-ZP4IFW2E.js → chunk-6Z7DLJU2.js} +4 -4
- package/dist/{chunk-ZP4IFW2E.js.map → chunk-6Z7DLJU2.js.map} +1 -1
- package/dist/{chunk-KZJAG7T3.js → chunk-7XF5SFJ2.js} +3 -3
- package/dist/{chunk-KZJAG7T3.js.map → chunk-7XF5SFJ2.js.map} +1 -1
- package/dist/{chunk-VGOFFCMT.cjs → chunk-B6MVQCXW.cjs} +3 -3
- package/dist/{chunk-VGOFFCMT.cjs.map → chunk-B6MVQCXW.cjs.map} +1 -1
- package/dist/{chunk-VLOPZHFH.js → chunk-D3N67Q4D.js} +3 -3
- package/dist/{chunk-VLOPZHFH.js.map → chunk-D3N67Q4D.js.map} +1 -1
- package/dist/{chunk-Z2NSU7D5.cjs → chunk-FXUQZFAN.cjs} +4 -4
- package/dist/{chunk-Z2NSU7D5.cjs.map → chunk-FXUQZFAN.cjs.map} +1 -1
- package/dist/{chunk-BV7FEMSI.js → chunk-OKERRHLH.js} +3 -3
- package/dist/{chunk-BV7FEMSI.js.map → chunk-OKERRHLH.js.map} +1 -1
- package/dist/{chunk-CXZ7FPTQ.js → chunk-PKZYL2KU.js} +3 -3
- package/dist/{chunk-CXZ7FPTQ.js.map → chunk-PKZYL2KU.js.map} +1 -1
- package/dist/{chunk-NRUPUDWB.js → chunk-PXE5BNK6.js} +3 -3
- package/dist/{chunk-NRUPUDWB.js.map → chunk-PXE5BNK6.js.map} +1 -1
- package/dist/{chunk-HBF4BDRU.cjs → chunk-S6BOINC4.cjs} +7 -7
- package/dist/{chunk-HBF4BDRU.cjs.map → chunk-S6BOINC4.cjs.map} +1 -1
- package/dist/{chunk-6RHHMBZ5.js → chunk-TAXKPPNC.js} +5 -5
- package/dist/{chunk-6RHHMBZ5.js.map → chunk-TAXKPPNC.js.map} +1 -1
- package/dist/{chunk-2UAJVK3C.cjs → chunk-UAMZXRYJ.cjs} +4 -4
- package/dist/{chunk-2UAJVK3C.cjs.map → chunk-UAMZXRYJ.cjs.map} +1 -1
- package/dist/{chunk-VP4KJ4LK.cjs → chunk-XZB2QP76.cjs} +7 -7
- package/dist/{chunk-VP4KJ4LK.cjs.map → chunk-XZB2QP76.cjs.map} +1 -1
- package/dist/collaboration/index.cjs +1 -1
- package/dist/collaboration/index.js +1 -1
- package/dist/connect/index.cjs +17 -17
- package/dist/connect/index.js +6 -6
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/index.cjs +1 -1
- package/dist/files/index.js +1 -1
- package/dist/index.cjs +428 -428
- package/dist/index.js +9 -9
- package/dist/shell/Shell.d.ts +5 -0
- package/dist/shell/index.cjs +69 -69
- package/dist/shell/index.js +4 -4
- package/dist/studio/index.cjs +4 -4
- package/dist/studio/index.js +3 -3
- package/dist/workflow-canvas/index.cjs +10 -10
- package/dist/workflow-canvas/index.js +3 -3
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +4 -4
|
@@ -252,7 +252,7 @@ function PageContainer({
|
|
|
252
252
|
{
|
|
253
253
|
"data-slot": "page-container",
|
|
254
254
|
className: cn(
|
|
255
|
-
"
|
|
255
|
+
"bg-background pb-safe",
|
|
256
256
|
minScreen ? "min-h-screen" : "h-full min-h-0",
|
|
257
257
|
className
|
|
258
258
|
),
|
|
@@ -322,5 +322,5 @@ function ToolButton({
|
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
export { BlocksTooltipProvider, DEFAULT_OVERLAY_ZONE_ID, DEFAULT_PAGE_CONTAINER_PADDING, DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, PageContainer, SHELL_BOTTOM_INSET_VAR, Shell, SidebarToggleButton, ToolButton, useDrawerBehavior, useOverlayZoneId, useShellBottomInset };
|
|
325
|
-
//# sourceMappingURL=chunk-
|
|
326
|
-
//# sourceMappingURL=chunk-
|
|
325
|
+
//# sourceMappingURL=chunk-7XF5SFJ2.js.map
|
|
326
|
+
//# sourceMappingURL=chunk-7XF5SFJ2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/bottom-inset.ts","../src/provider/TooltipScope.tsx","../src/lib/use-drawer.ts","../src/shell/Shell.tsx","../src/shell/ToolButton.tsx"],"names":["useEffect","createContext","useContext","jsx","useRef","cn"],"mappings":"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","file":"chunk-KZJAG7T3.js","sourcesContent":["import { useEffect, type RefObject } from 'react'\nimport { observeResize } from './observe-resize'\n\n/**\n * The CSS custom property that carries how much of the screen's bottom edge is taken by pinned\n * bars (the phone tab bar, a chat composer), set on `<html>`. A floating element (the install\n * prompt, a toast, a back-to-top button) positions itself `calc(var(--shell-bottom-inset, 0px) +\n * 0.75rem)` so it never covers those bars.\n */\nexport const SHELL_BOTTOM_INSET_VAR = '--shell-bottom-inset'\n\nconst measurers = new Map<symbol, () => number>()\n\n/** Re-measure every registered bar and publish the largest: bars stack, so the tallest reach wins. */\nfunction apply(): void {\n if (typeof document === 'undefined') return\n let inset = 0\n for (const measure of measurers.values()) inset = Math.max(inset, measure())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_BOTTOM_INSET_VAR, `${Math.round(inset)}px`)\n else style.removeProperty(SHELL_BOTTOM_INSET_VAR)\n}\n\n/**\n * Report a bottom-pinned element to {@link SHELL_BOTTOM_INSET_VAR}: its distance from the top of\n * the element to the bottom of the viewport, so a composer above the tab bar counts the tab bar\n * too (contributions are combined with `max`, not summed). An element that is not rendered\n * (`display: none`, e.g. the phone-only tab bar on a desktop width) contributes 0. Used by\n * `MobileTabBar` and the chat composer; call it from your own bottom bar.\n */\nexport function useShellBottomInset(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean = true\n): void {\n useEffect(() => {\n const el = ref.current\n if (!enabled || !el) return\n const key = Symbol('shell-bottom-inset')\n measurers.set(key, () => {\n const rect = el.getBoundingClientRect()\n return rect.height > 0 ? Math.max(0, window.innerHeight - rect.top) : 0\n })\n apply()\n // Any bar resizing moves the others (a composer sits on top of the tab bar): re-measure all.\n const stop = observeResize(el, apply)\n window.addEventListener('resize', apply)\n return () => {\n stop()\n window.removeEventListener('resize', apply)\n measurers.delete(key)\n apply()\n }\n }, [ref, enabled])\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport { TooltipProvider } from '@arbidocs/react/ui'\n\nconst TooltipScopeContext = createContext(false)\n\n/**\n * A TooltipProvider that mounts once: inside another `BlocksTooltipProvider` (e.g. a Sidebar under\n * Shell.Root) it renders its children as-is, so tooltips share one delay group. Blocks that show\n * tooltips use this instead of the kit's provider.\n */\nexport function BlocksTooltipProvider({ children }: { children: ReactNode }) {\n const isNested = useContext(TooltipScopeContext)\n if (isNested) return <>{children}</>\n return (\n <TooltipScopeContext.Provider value>\n <TooltipProvider>{children}</TooltipProvider>\n </TooltipScopeContext.Provider>\n )\n}\n","import { useEffect, useRef, type RefObject } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nfunction focusableIn(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => !el.closest('[inert]') && el.getAttribute('aria-hidden') !== 'true'\n )\n}\n\n/**\n * Behaviour of a modal surface (off-canvas drawer, full-screen dock) while it is open: the page\n * behind does not scroll, Escape closes it, focus moves inside and Tab/Shift+Tab cycle within it\n * (portalled popovers opened from inside stay reachable: only the wrap-around is intercepted),\n * and focus returns to the opener on close. Restores the previous body overflow on close/unmount.\n *\n * Pass `containerRef` (the element carrying `role=\"dialog\"`) to get the focus handling; without it\n * only scroll lock and Escape apply.\n */\nexport function useDrawerBehavior(\n isOpen: boolean,\n onClose: () => void,\n containerRef?: RefObject<HTMLElement | null>\n): void {\n // A fresh `onClose` identity per render must not re-run the effect (it would steal focus).\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isOpen) return\n const previousOverflow = document.body.style.overflow\n const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null\n document.body.style.overflow = 'hidden'\n\n const container = containerRef?.current ?? null\n if (container) {\n const first = focusableIn(container)[0]\n if (first) first.focus()\n else {\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1')\n container.focus()\n }\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCloseRef.current()\n return\n }\n if (e.key !== 'Tab' || !container) return\n const items = focusableIn(container)\n if (items.length === 0) {\n e.preventDefault()\n return\n }\n const firstItem = items[0]\n const lastItem = items[items.length - 1]\n const active = document.activeElement\n if (!container.contains(active)) {\n e.preventDefault()\n firstItem.focus()\n } else if (e.shiftKey && active === firstItem) {\n e.preventDefault()\n lastItem.focus()\n } else if (!e.shiftKey && active === lastItem) {\n e.preventDefault()\n firstItem.focus()\n }\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = previousOverflow\n window.removeEventListener('keydown', onKey)\n if (opener?.isConnected) opener.focus()\n }\n }, [isOpen, containerRef])\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useRef,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { PanelLeft, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\n\n/** Default id of the element overlay-mode panels portal into (see `Shell.Content`). */\nexport const DEFAULT_OVERLAY_ZONE_ID = 'app-overlay-zone'\n\nconst OverlayZoneContext = createContext(DEFAULT_OVERLAY_ZONE_ID)\n\n/** The id of the enclosing `Shell.Content` overlay zone, for panels that portal into it. */\nexport function useOverlayZoneId(): string {\n return useContext(OverlayZoneContext)\n}\n\nexport interface ShellRootProps {\n /** Full-width strip above everything (e.g. a deletion-pending banner). */\n banner?: ReactNode\n /** Top chrome: a Shell.Topbar on list pages, a MobileAppBar on phones; omit for none. */\n topbar?: ReactNode\n /** The Sidebar.Root (and its drawer backdrop). */\n sidebar?: ReactNode\n /** Phone bottom navigation. */\n tabBar?: ReactNode\n /** Right-hand column beside the content: a `Shell.Dock` (chat, inspector...). */\n aside?: ReactNode\n /** Extra layers inside the body row (connection monitor, …). */\n overlays?: ReactNode\n /** The Shell.Content region. */\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * The application frame: banner, top chrome, then a body row holding the sidebar beside the\n * content, then the phone tab bar. Every region is a slot, so a custom UI composes its own.\n */\nfunction ShellRoot({\n banner,\n topbar,\n sidebar,\n tabBar,\n aside,\n overlays,\n children,\n className,\n 'data-testid': testId,\n}: ShellRootProps) {\n return (\n <BlocksTooltipProvider>\n <div\n data-slot=\"shell\"\n data-testid={testId}\n className={cn('flex h-screen h-dvh flex-col', className)}\n >\n {banner}\n {topbar}\n {/* `relative` anchors the sidebar's slide-out overlays to this row. */}\n <div className=\"relative flex flex-1 overflow-hidden\">\n {sidebar}\n {children}\n {aside}\n {overlays}\n </div>\n {tabBar}\n </div>\n </BlocksTooltipProvider>\n )\n}\n\nexport interface ShellContentProps {\n children: ReactNode\n /** Scrolling element, for scroll restoration. */\n scrollRef?: Ref<HTMLDivElement>\n onClick?: MouseEventHandler<HTMLDivElement>\n /**\n * Overlay-mode panels portal into this id and cover the content column only. Defaults to\n * `DEFAULT_OVERLAY_ZONE_ID`; descendants read it with `useOverlayZoneId()`.\n */\n overlayZoneId?: string\n className?: string\n}\n\n/**\n * The content column beside the sidebar. It is `relative` so overlay-mode panels (portalled into\n * the overlay zone) cover this region only, leaving the sidebar and its actions interactive.\n */\nfunction ShellContent({\n children,\n scrollRef,\n onClick,\n overlayZoneId = DEFAULT_OVERLAY_ZONE_ID,\n className,\n}: ShellContentProps) {\n return (\n <div\n data-slot=\"shell-content\"\n className={cn('flex min-w-0 flex-1 flex-col', className)}\n onClick={onClick}\n >\n <div className=\"relative min-h-0 flex-1\">\n <OverlayZoneContext.Provider value={overlayZoneId}>\n {/* The content column is a CSS container: pages and parts size by its width with\n container variants (`@3xl:`...), so an open dock or a narrow window is honoured,\n which viewport breakpoints cannot do. */}\n <div ref={scrollRef} className=\"@container h-full overflow-auto\">\n {children}\n </div>\n </OverlayZoneContext.Provider>\n <div id={overlayZoneId} data-slot=\"overlay-zone\" />\n </div>\n </div>\n )\n}\n\nexport interface ShellTopbarProps {\n /** Left side: guidance / breadcrumbs, centred in the page column. */\n children?: ReactNode\n /** Right side: the action cluster. */\n actions?: ReactNode\n className?: string\n}\n\n/** A minimal white header for pages with no sidebar (the workspaces list). */\nfunction ShellTopbar({ children, actions, className }: ShellTopbarProps) {\n return (\n // `relative z-30` keeps dropdowns the header opens above the page region (a later sibling).\n <div\n data-slot=\"shell-topbar\"\n className={cn('relative z-30 flex h-14 shrink-0 items-center bg-background px-2', className)}\n >\n <div className=\"mx-auto flex w-full max-w-6xl items-center\">\n <div className=\"hidden min-w-0 flex-1 px-6 sm:block\">{children}</div>\n </div>\n <div className=\"absolute right-4 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n {actions}\n </div>\n </div>\n )\n}\n\nexport interface ShellDockProps {\n isOpen: boolean\n /** Called with `false` by the mobile close button. */\n onOpenChange?: (isOpen: boolean) => void\n /** Desktop width (CSS length or px). Default 24rem. */\n width?: number | string\n /** Phone layout: the dock covers the screen instead of sitting beside the content. */\n isMobile?: boolean\n /** Accessible name of the dock. */\n label: string\n /** Mobile close button label. */\n closeLabel?: string\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A right-hand dock for a companion surface (chat, inspector). Controlled: the host owns\n * `isOpen`, the width and the mobile breakpoint. Pass it to `Shell.Root` as `aside`.\n */\nfunction ShellDock({\n isOpen,\n onOpenChange,\n width = '24rem',\n isMobile = false,\n label,\n closeLabel = 'Close',\n children,\n className,\n 'data-testid': testId,\n}: ShellDockProps) {\n // The phone dock covers the screen, so it is a modal: Escape closes, focus is trapped and\n // returns to the opener.\n const mobileRef = useRef<HTMLDivElement>(null)\n const closeMobile = useCallback(() => onOpenChange?.(false), [onOpenChange])\n useDrawerBehavior(isOpen && isMobile, closeMobile, mobileRef)\n if (!isOpen) return null\n if (isMobile) {\n return (\n <div\n ref={mobileRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-mobile=\"true\"\n data-testid={testId}\n className={cn('fixed inset-0 z-40 flex flex-col bg-background', className)}\n >\n {onOpenChange && (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n aria-label={closeLabel}\n className=\"absolute right-2 top-2 z-10 rounded-md p-2 text-muted-foreground hover:bg-muted\"\n >\n <X className=\"size-5\" />\n </button>\n )}\n {children}\n </div>\n )\n }\n return (\n <aside\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-testid={testId}\n style={{ width }}\n className={cn(\n 'flex shrink-0 flex-col overflow-hidden border-l border-border bg-background',\n className\n )}\n >\n {children}\n </aside>\n )\n}\n\nexport const Shell = {\n Root: ShellRoot,\n Content: ShellContent,\n Topbar: ShellTopbar,\n Dock: ShellDock,\n}\n\nexport interface PageContainerProps {\n children: ReactNode\n /** Full width instead of the centred 72rem column. */\n wide?: boolean\n /** Stand-alone use: at least a screen tall, instead of filling the parent. */\n minScreen?: boolean\n /** Max width of the centred column (any Tailwind `max-w-*` class). Default `max-w-6xl`. */\n maxWidth?: string\n /**\n * Horizontal padding of the inner column (any Tailwind `px-*` classes, responsive variants\n * welcome). Default `px-4 sm:px-6 lg:px-8`; pass `px-0` for a full-bleed page, or the class\n * string of your own gutter. Use this prop, not `innerClassName`, to change the gutter: the\n * classes are concatenated without a merge step, so a second `px-*` would not reliably win.\n */\n padding?: string\n /** Extra classes for the inner column. */\n innerClassName?: string\n className?: string\n}\n\n/** Default gutter of {@link PageContainer}: tight on a phone, roomier from tablet up. */\nexport const DEFAULT_PAGE_CONTAINER_PADDING = 'px-4 sm:px-6 lg:px-8'\n\n/**\n * Page body wrapper: a white canvas with the standard 72rem column (or full width) and a responsive side gutter. Fills its\n * parent by default so sticky headers and h-full pages keep a definite height chain.\n */\nexport function PageContainer({\n children,\n wide = false,\n minScreen = false,\n maxWidth = 'max-w-6xl',\n padding = DEFAULT_PAGE_CONTAINER_PADDING,\n innerClassName,\n className,\n}: PageContainerProps) {\n return (\n <div\n data-slot=\"page-container\"\n className={cn(\n '@container bg-background pb-safe',\n minScreen ? 'min-h-screen' : 'h-full min-h-0',\n className\n )}\n >\n <div\n className={cn(\n 'flex h-full w-full min-w-0 flex-col pb-safe',\n padding,\n !wide && cn('mx-auto', maxWidth),\n innerClassName\n )}\n >\n {children}\n </div>\n </div>\n )\n}\n\n/** Fixed strings of the sidebar toggle. */\nexport interface SidebarToggleButtonLabels {\n closeSidebar: string\n openSidebar: string\n}\n\nexport const DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS: SidebarToggleButtonLabels = {\n closeSidebar: 'Close sidebar',\n openSidebar: 'Open sidebar',\n}\n\nexport interface SidebarToggleButtonProps {\n /** The sidebar is open (pinned). */\n isOpen: boolean\n onToggle: () => void\n labels?: Partial<SidebarToggleButtonLabels>\n 'data-testid'?: string\n}\n\n/** Opens/closes the sidebar from a page header, so the control sits in the same spot everywhere. */\nexport function SidebarToggleButton({\n isOpen,\n onToggle,\n labels,\n 'data-testid': testId = 'tabheader-sidebar-toggle',\n}: SidebarToggleButtonProps) {\n const l = { ...DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, ...labels }\n const label = isOpen ? l.closeSidebar : l.openSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:p-2.5\"\n aria-label={label}\n title={label}\n data-testid={testId}\n >\n <PanelLeft className=\"size-5\" />\n </button>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface ToolButtonProps {\n onClick: () => void\n /** Accessible name and native tooltip. */\n label: string\n /** The panel/page this opens is showing. */\n active?: boolean\n 'data-testid'?: string\n children: ReactNode\n}\n\n/** An icon button for a topbar or toolbar: 36px (44px coarse), selection tint while active. */\nexport function ToolButton({\n onClick,\n label,\n active = false,\n 'data-testid': testId,\n children,\n}: ToolButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n data-slot=\"tool-button\"\n data-testid={testId}\n className={cn(\n 'relative flex size-9 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-accent-foreground pointer-coarse:size-11',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {children}\n </button>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/bottom-inset.ts","../src/provider/TooltipScope.tsx","../src/lib/use-drawer.ts","../src/shell/Shell.tsx","../src/shell/ToolButton.tsx"],"names":["useEffect","createContext","useContext","jsx","useRef","cn"],"mappings":"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","file":"chunk-7XF5SFJ2.js","sourcesContent":["import { useEffect, type RefObject } from 'react'\nimport { observeResize } from './observe-resize'\n\n/**\n * The CSS custom property that carries how much of the screen's bottom edge is taken by pinned\n * bars (the phone tab bar, a chat composer), set on `<html>`. A floating element (the install\n * prompt, a toast, a back-to-top button) positions itself `calc(var(--shell-bottom-inset, 0px) +\n * 0.75rem)` so it never covers those bars.\n */\nexport const SHELL_BOTTOM_INSET_VAR = '--shell-bottom-inset'\n\nconst measurers = new Map<symbol, () => number>()\n\n/** Re-measure every registered bar and publish the largest: bars stack, so the tallest reach wins. */\nfunction apply(): void {\n if (typeof document === 'undefined') return\n let inset = 0\n for (const measure of measurers.values()) inset = Math.max(inset, measure())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_BOTTOM_INSET_VAR, `${Math.round(inset)}px`)\n else style.removeProperty(SHELL_BOTTOM_INSET_VAR)\n}\n\n/**\n * Report a bottom-pinned element to {@link SHELL_BOTTOM_INSET_VAR}: its distance from the top of\n * the element to the bottom of the viewport, so a composer above the tab bar counts the tab bar\n * too (contributions are combined with `max`, not summed). An element that is not rendered\n * (`display: none`, e.g. the phone-only tab bar on a desktop width) contributes 0. Used by\n * `MobileTabBar` and the chat composer; call it from your own bottom bar.\n */\nexport function useShellBottomInset(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean = true\n): void {\n useEffect(() => {\n const el = ref.current\n if (!enabled || !el) return\n const key = Symbol('shell-bottom-inset')\n measurers.set(key, () => {\n const rect = el.getBoundingClientRect()\n return rect.height > 0 ? Math.max(0, window.innerHeight - rect.top) : 0\n })\n apply()\n // Any bar resizing moves the others (a composer sits on top of the tab bar): re-measure all.\n const stop = observeResize(el, apply)\n window.addEventListener('resize', apply)\n return () => {\n stop()\n window.removeEventListener('resize', apply)\n measurers.delete(key)\n apply()\n }\n }, [ref, enabled])\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport { TooltipProvider } from '@arbidocs/react/ui'\n\nconst TooltipScopeContext = createContext(false)\n\n/**\n * A TooltipProvider that mounts once: inside another `BlocksTooltipProvider` (e.g. a Sidebar under\n * Shell.Root) it renders its children as-is, so tooltips share one delay group. Blocks that show\n * tooltips use this instead of the kit's provider.\n */\nexport function BlocksTooltipProvider({ children }: { children: ReactNode }) {\n const isNested = useContext(TooltipScopeContext)\n if (isNested) return <>{children}</>\n return (\n <TooltipScopeContext.Provider value>\n <TooltipProvider>{children}</TooltipProvider>\n </TooltipScopeContext.Provider>\n )\n}\n","import { useEffect, useRef, type RefObject } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nfunction focusableIn(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => !el.closest('[inert]') && el.getAttribute('aria-hidden') !== 'true'\n )\n}\n\n/**\n * Behaviour of a modal surface (off-canvas drawer, full-screen dock) while it is open: the page\n * behind does not scroll, Escape closes it, focus moves inside and Tab/Shift+Tab cycle within it\n * (portalled popovers opened from inside stay reachable: only the wrap-around is intercepted),\n * and focus returns to the opener on close. Restores the previous body overflow on close/unmount.\n *\n * Pass `containerRef` (the element carrying `role=\"dialog\"`) to get the focus handling; without it\n * only scroll lock and Escape apply.\n */\nexport function useDrawerBehavior(\n isOpen: boolean,\n onClose: () => void,\n containerRef?: RefObject<HTMLElement | null>\n): void {\n // A fresh `onClose` identity per render must not re-run the effect (it would steal focus).\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isOpen) return\n const previousOverflow = document.body.style.overflow\n const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null\n document.body.style.overflow = 'hidden'\n\n const container = containerRef?.current ?? null\n if (container) {\n const first = focusableIn(container)[0]\n if (first) first.focus()\n else {\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1')\n container.focus()\n }\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCloseRef.current()\n return\n }\n if (e.key !== 'Tab' || !container) return\n const items = focusableIn(container)\n if (items.length === 0) {\n e.preventDefault()\n return\n }\n const firstItem = items[0]\n const lastItem = items[items.length - 1]\n const active = document.activeElement\n if (!container.contains(active)) {\n e.preventDefault()\n firstItem.focus()\n } else if (e.shiftKey && active === firstItem) {\n e.preventDefault()\n lastItem.focus()\n } else if (!e.shiftKey && active === lastItem) {\n e.preventDefault()\n firstItem.focus()\n }\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = previousOverflow\n window.removeEventListener('keydown', onKey)\n if (opener?.isConnected) opener.focus()\n }\n }, [isOpen, containerRef])\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useRef,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { PanelLeft, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\n\n/** Default id of the element overlay-mode panels portal into (see `Shell.Content`). */\nexport const DEFAULT_OVERLAY_ZONE_ID = 'app-overlay-zone'\n\nconst OverlayZoneContext = createContext(DEFAULT_OVERLAY_ZONE_ID)\n\n/** The id of the enclosing `Shell.Content` overlay zone, for panels that portal into it. */\nexport function useOverlayZoneId(): string {\n return useContext(OverlayZoneContext)\n}\n\nexport interface ShellRootProps {\n /** Full-width strip above everything (e.g. a deletion-pending banner). */\n banner?: ReactNode\n /** Top chrome: a Shell.Topbar on list pages, a MobileAppBar on phones; omit for none. */\n topbar?: ReactNode\n /** The Sidebar.Root (and its drawer backdrop). */\n sidebar?: ReactNode\n /** Phone bottom navigation. */\n tabBar?: ReactNode\n /** Right-hand column beside the content: a `Shell.Dock` (chat, inspector...). */\n aside?: ReactNode\n /** Extra layers inside the body row (connection monitor, …). */\n overlays?: ReactNode\n /** The Shell.Content region. */\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * The application frame: banner, top chrome, then a body row holding the sidebar beside the\n * content, then the phone tab bar. Every region is a slot, so a custom UI composes its own.\n */\nfunction ShellRoot({\n banner,\n topbar,\n sidebar,\n tabBar,\n aside,\n overlays,\n children,\n className,\n 'data-testid': testId,\n}: ShellRootProps) {\n return (\n <BlocksTooltipProvider>\n <div\n data-slot=\"shell\"\n data-testid={testId}\n className={cn('flex h-screen h-dvh flex-col', className)}\n >\n {banner}\n {topbar}\n {/* `relative` anchors the sidebar's slide-out overlays to this row. */}\n <div className=\"relative flex flex-1 overflow-hidden\">\n {sidebar}\n {children}\n {aside}\n {overlays}\n </div>\n {tabBar}\n </div>\n </BlocksTooltipProvider>\n )\n}\n\nexport interface ShellContentProps {\n children: ReactNode\n /** Scrolling element, for scroll restoration. */\n scrollRef?: Ref<HTMLDivElement>\n onClick?: MouseEventHandler<HTMLDivElement>\n /**\n * Overlay-mode panels portal into this id and cover the content column only. Defaults to\n * `DEFAULT_OVERLAY_ZONE_ID`; descendants read it with `useOverlayZoneId()`.\n */\n overlayZoneId?: string\n className?: string\n}\n\n/**\n * The content column beside the sidebar. It is `relative` so overlay-mode panels (portalled into\n * the overlay zone) cover this region only, leaving the sidebar and its actions interactive.\n */\nfunction ShellContent({\n children,\n scrollRef,\n onClick,\n overlayZoneId = DEFAULT_OVERLAY_ZONE_ID,\n className,\n}: ShellContentProps) {\n return (\n <div\n data-slot=\"shell-content\"\n className={cn('flex min-w-0 flex-1 flex-col', className)}\n onClick={onClick}\n >\n <div className=\"relative min-h-0 flex-1\">\n <OverlayZoneContext.Provider value={overlayZoneId}>\n {/* The content column is a CSS container: pages and parts size by its width with\n container variants (`@3xl:`...), so an open dock or a narrow window is honoured,\n which viewport breakpoints cannot do. */}\n <div ref={scrollRef} className=\"@container h-full overflow-auto\">\n {children}\n </div>\n </OverlayZoneContext.Provider>\n <div id={overlayZoneId} data-slot=\"overlay-zone\" />\n </div>\n </div>\n )\n}\n\nexport interface ShellTopbarProps {\n /** Left side: guidance / breadcrumbs, centred in the page column. */\n children?: ReactNode\n /** Right side: the action cluster. */\n actions?: ReactNode\n className?: string\n}\n\n/** A minimal white header for pages with no sidebar (the workspaces list). */\nfunction ShellTopbar({ children, actions, className }: ShellTopbarProps) {\n return (\n // `relative z-30` keeps dropdowns the header opens above the page region (a later sibling).\n <div\n data-slot=\"shell-topbar\"\n className={cn('relative z-30 flex h-14 shrink-0 items-center bg-background px-2', className)}\n >\n <div className=\"mx-auto flex w-full max-w-6xl items-center\">\n <div className=\"hidden min-w-0 flex-1 px-6 sm:block\">{children}</div>\n </div>\n <div className=\"absolute right-4 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n {actions}\n </div>\n </div>\n )\n}\n\nexport interface ShellDockProps {\n isOpen: boolean\n /** Called with `false` by the mobile close button. */\n onOpenChange?: (isOpen: boolean) => void\n /** Desktop width (CSS length or px). Default 24rem. */\n width?: number | string\n /** Phone layout: the dock covers the screen instead of sitting beside the content. */\n isMobile?: boolean\n /** Accessible name of the dock. */\n label: string\n /** Mobile close button label. */\n closeLabel?: string\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A right-hand dock for a companion surface (chat, inspector). Controlled: the host owns\n * `isOpen`, the width and the mobile breakpoint. Pass it to `Shell.Root` as `aside`.\n */\nfunction ShellDock({\n isOpen,\n onOpenChange,\n width = '24rem',\n isMobile = false,\n label,\n closeLabel = 'Close',\n children,\n className,\n 'data-testid': testId,\n}: ShellDockProps) {\n // The phone dock covers the screen, so it is a modal: Escape closes, focus is trapped and\n // returns to the opener.\n const mobileRef = useRef<HTMLDivElement>(null)\n const closeMobile = useCallback(() => onOpenChange?.(false), [onOpenChange])\n useDrawerBehavior(isOpen && isMobile, closeMobile, mobileRef)\n if (!isOpen) return null\n if (isMobile) {\n return (\n <div\n ref={mobileRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-mobile=\"true\"\n data-testid={testId}\n className={cn('fixed inset-0 z-40 flex flex-col bg-background', className)}\n >\n {onOpenChange && (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n aria-label={closeLabel}\n className=\"absolute right-2 top-2 z-10 rounded-md p-2 text-muted-foreground hover:bg-muted\"\n >\n <X className=\"size-5\" />\n </button>\n )}\n {children}\n </div>\n )\n }\n return (\n <aside\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-testid={testId}\n style={{ width }}\n className={cn(\n 'flex shrink-0 flex-col overflow-hidden border-l border-border bg-background',\n className\n )}\n >\n {children}\n </aside>\n )\n}\n\nexport const Shell = {\n Root: ShellRoot,\n Content: ShellContent,\n Topbar: ShellTopbar,\n Dock: ShellDock,\n}\n\nexport interface PageContainerProps {\n children: ReactNode\n /** Full width instead of the centred 72rem column. */\n wide?: boolean\n /** Stand-alone use: at least a screen tall, instead of filling the parent. */\n minScreen?: boolean\n /** Max width of the centred column (any Tailwind `max-w-*` class). Default `max-w-6xl`. */\n maxWidth?: string\n /**\n * Horizontal padding of the inner column (any Tailwind `px-*` classes, responsive variants\n * welcome). Default `px-4 sm:px-6 lg:px-8`; pass `px-0` for a full-bleed page, or the class\n * string of your own gutter. Use this prop, not `innerClassName`, to change the gutter: the\n * classes are concatenated without a merge step, so a second `px-*` would not reliably win.\n */\n padding?: string\n /** Extra classes for the inner column. */\n innerClassName?: string\n className?: string\n}\n\n/** Default gutter of {@link PageContainer}: tight on a phone, roomier from tablet up. */\nexport const DEFAULT_PAGE_CONTAINER_PADDING = 'px-4 sm:px-6 lg:px-8'\n\n/**\n * Page body wrapper: a white canvas with the standard 72rem column (or full width) and a responsive side gutter. Fills its\n * parent by default so sticky headers and h-full pages keep a definite height chain.\n *\n * NOT a CSS container: its content (a long thread) overflows it into the host's scroller, and\n * Chrome before ~v130 gives `container-type` layout containment, which turns that overflow into\n * ink overflow — the scroller sees no scroll height, so no scrollbar and a dead wheel. Container\n * queries resolve against the scroll surface instead (Shell.Content, the app's DockZone).\n */\nexport function PageContainer({\n children,\n wide = false,\n minScreen = false,\n maxWidth = 'max-w-6xl',\n padding = DEFAULT_PAGE_CONTAINER_PADDING,\n innerClassName,\n className,\n}: PageContainerProps) {\n return (\n <div\n data-slot=\"page-container\"\n className={cn(\n 'bg-background pb-safe',\n minScreen ? 'min-h-screen' : 'h-full min-h-0',\n className\n )}\n >\n <div\n className={cn(\n 'flex h-full w-full min-w-0 flex-col pb-safe',\n padding,\n !wide && cn('mx-auto', maxWidth),\n innerClassName\n )}\n >\n {children}\n </div>\n </div>\n )\n}\n\n/** Fixed strings of the sidebar toggle. */\nexport interface SidebarToggleButtonLabels {\n closeSidebar: string\n openSidebar: string\n}\n\nexport const DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS: SidebarToggleButtonLabels = {\n closeSidebar: 'Close sidebar',\n openSidebar: 'Open sidebar',\n}\n\nexport interface SidebarToggleButtonProps {\n /** The sidebar is open (pinned). */\n isOpen: boolean\n onToggle: () => void\n labels?: Partial<SidebarToggleButtonLabels>\n 'data-testid'?: string\n}\n\n/** Opens/closes the sidebar from a page header, so the control sits in the same spot everywhere. */\nexport function SidebarToggleButton({\n isOpen,\n onToggle,\n labels,\n 'data-testid': testId = 'tabheader-sidebar-toggle',\n}: SidebarToggleButtonProps) {\n const l = { ...DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, ...labels }\n const label = isOpen ? l.closeSidebar : l.openSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:p-2.5\"\n aria-label={label}\n title={label}\n data-testid={testId}\n >\n <PanelLeft className=\"size-5\" />\n </button>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface ToolButtonProps {\n onClick: () => void\n /** Accessible name and native tooltip. */\n label: string\n /** The panel/page this opens is showing. */\n active?: boolean\n 'data-testid'?: string\n children: ReactNode\n}\n\n/** An icon button for a topbar or toolbar: 36px (44px coarse), selection tint while active. */\nexport function ToolButton({\n onClick,\n label,\n active = false,\n 'data-testid': testId,\n children,\n}: ToolButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n data-slot=\"tool-button\"\n data-testid={testId}\n className={cn(\n 'relative flex size-9 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-accent-foreground pointer-coarse:size-11',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {children}\n </button>\n )\n}\n"]}
|
|
@@ -254,7 +254,7 @@ function PageContainer({
|
|
|
254
254
|
{
|
|
255
255
|
"data-slot": "page-container",
|
|
256
256
|
className: ui.cn(
|
|
257
|
-
"
|
|
257
|
+
"bg-background pb-safe",
|
|
258
258
|
minScreen ? "min-h-screen" : "h-full min-h-0",
|
|
259
259
|
className
|
|
260
260
|
),
|
|
@@ -335,5 +335,5 @@ exports.ToolButton = ToolButton;
|
|
|
335
335
|
exports.useDrawerBehavior = useDrawerBehavior;
|
|
336
336
|
exports.useOverlayZoneId = useOverlayZoneId;
|
|
337
337
|
exports.useShellBottomInset = useShellBottomInset;
|
|
338
|
-
//# sourceMappingURL=chunk-
|
|
339
|
-
//# sourceMappingURL=chunk-
|
|
338
|
+
//# sourceMappingURL=chunk-B6MVQCXW.cjs.map
|
|
339
|
+
//# sourceMappingURL=chunk-B6MVQCXW.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/bottom-inset.ts","../src/provider/TooltipScope.tsx","../src/lib/use-drawer.ts","../src/shell/Shell.tsx","../src/shell/ToolButton.tsx"],"names":["useEffect","observeResize","createContext","useContext","jsx","Fragment","TooltipProvider","useRef","jsxs","cn","useCallback","X","PanelLeft"],"mappings":"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","file":"chunk-VGOFFCMT.cjs","sourcesContent":["import { useEffect, type RefObject } from 'react'\nimport { observeResize } from './observe-resize'\n\n/**\n * The CSS custom property that carries how much of the screen's bottom edge is taken by pinned\n * bars (the phone tab bar, a chat composer), set on `<html>`. A floating element (the install\n * prompt, a toast, a back-to-top button) positions itself `calc(var(--shell-bottom-inset, 0px) +\n * 0.75rem)` so it never covers those bars.\n */\nexport const SHELL_BOTTOM_INSET_VAR = '--shell-bottom-inset'\n\nconst measurers = new Map<symbol, () => number>()\n\n/** Re-measure every registered bar and publish the largest: bars stack, so the tallest reach wins. */\nfunction apply(): void {\n if (typeof document === 'undefined') return\n let inset = 0\n for (const measure of measurers.values()) inset = Math.max(inset, measure())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_BOTTOM_INSET_VAR, `${Math.round(inset)}px`)\n else style.removeProperty(SHELL_BOTTOM_INSET_VAR)\n}\n\n/**\n * Report a bottom-pinned element to {@link SHELL_BOTTOM_INSET_VAR}: its distance from the top of\n * the element to the bottom of the viewport, so a composer above the tab bar counts the tab bar\n * too (contributions are combined with `max`, not summed). An element that is not rendered\n * (`display: none`, e.g. the phone-only tab bar on a desktop width) contributes 0. Used by\n * `MobileTabBar` and the chat composer; call it from your own bottom bar.\n */\nexport function useShellBottomInset(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean = true\n): void {\n useEffect(() => {\n const el = ref.current\n if (!enabled || !el) return\n const key = Symbol('shell-bottom-inset')\n measurers.set(key, () => {\n const rect = el.getBoundingClientRect()\n return rect.height > 0 ? Math.max(0, window.innerHeight - rect.top) : 0\n })\n apply()\n // Any bar resizing moves the others (a composer sits on top of the tab bar): re-measure all.\n const stop = observeResize(el, apply)\n window.addEventListener('resize', apply)\n return () => {\n stop()\n window.removeEventListener('resize', apply)\n measurers.delete(key)\n apply()\n }\n }, [ref, enabled])\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport { TooltipProvider } from '@arbidocs/react/ui'\n\nconst TooltipScopeContext = createContext(false)\n\n/**\n * A TooltipProvider that mounts once: inside another `BlocksTooltipProvider` (e.g. a Sidebar under\n * Shell.Root) it renders its children as-is, so tooltips share one delay group. Blocks that show\n * tooltips use this instead of the kit's provider.\n */\nexport function BlocksTooltipProvider({ children }: { children: ReactNode }) {\n const isNested = useContext(TooltipScopeContext)\n if (isNested) return <>{children}</>\n return (\n <TooltipScopeContext.Provider value>\n <TooltipProvider>{children}</TooltipProvider>\n </TooltipScopeContext.Provider>\n )\n}\n","import { useEffect, useRef, type RefObject } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nfunction focusableIn(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => !el.closest('[inert]') && el.getAttribute('aria-hidden') !== 'true'\n )\n}\n\n/**\n * Behaviour of a modal surface (off-canvas drawer, full-screen dock) while it is open: the page\n * behind does not scroll, Escape closes it, focus moves inside and Tab/Shift+Tab cycle within it\n * (portalled popovers opened from inside stay reachable: only the wrap-around is intercepted),\n * and focus returns to the opener on close. Restores the previous body overflow on close/unmount.\n *\n * Pass `containerRef` (the element carrying `role=\"dialog\"`) to get the focus handling; without it\n * only scroll lock and Escape apply.\n */\nexport function useDrawerBehavior(\n isOpen: boolean,\n onClose: () => void,\n containerRef?: RefObject<HTMLElement | null>\n): void {\n // A fresh `onClose` identity per render must not re-run the effect (it would steal focus).\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isOpen) return\n const previousOverflow = document.body.style.overflow\n const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null\n document.body.style.overflow = 'hidden'\n\n const container = containerRef?.current ?? null\n if (container) {\n const first = focusableIn(container)[0]\n if (first) first.focus()\n else {\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1')\n container.focus()\n }\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCloseRef.current()\n return\n }\n if (e.key !== 'Tab' || !container) return\n const items = focusableIn(container)\n if (items.length === 0) {\n e.preventDefault()\n return\n }\n const firstItem = items[0]\n const lastItem = items[items.length - 1]\n const active = document.activeElement\n if (!container.contains(active)) {\n e.preventDefault()\n firstItem.focus()\n } else if (e.shiftKey && active === firstItem) {\n e.preventDefault()\n lastItem.focus()\n } else if (!e.shiftKey && active === lastItem) {\n e.preventDefault()\n firstItem.focus()\n }\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = previousOverflow\n window.removeEventListener('keydown', onKey)\n if (opener?.isConnected) opener.focus()\n }\n }, [isOpen, containerRef])\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useRef,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { PanelLeft, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\n\n/** Default id of the element overlay-mode panels portal into (see `Shell.Content`). */\nexport const DEFAULT_OVERLAY_ZONE_ID = 'app-overlay-zone'\n\nconst OverlayZoneContext = createContext(DEFAULT_OVERLAY_ZONE_ID)\n\n/** The id of the enclosing `Shell.Content` overlay zone, for panels that portal into it. */\nexport function useOverlayZoneId(): string {\n return useContext(OverlayZoneContext)\n}\n\nexport interface ShellRootProps {\n /** Full-width strip above everything (e.g. a deletion-pending banner). */\n banner?: ReactNode\n /** Top chrome: a Shell.Topbar on list pages, a MobileAppBar on phones; omit for none. */\n topbar?: ReactNode\n /** The Sidebar.Root (and its drawer backdrop). */\n sidebar?: ReactNode\n /** Phone bottom navigation. */\n tabBar?: ReactNode\n /** Right-hand column beside the content: a `Shell.Dock` (chat, inspector...). */\n aside?: ReactNode\n /** Extra layers inside the body row (connection monitor, …). */\n overlays?: ReactNode\n /** The Shell.Content region. */\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * The application frame: banner, top chrome, then a body row holding the sidebar beside the\n * content, then the phone tab bar. Every region is a slot, so a custom UI composes its own.\n */\nfunction ShellRoot({\n banner,\n topbar,\n sidebar,\n tabBar,\n aside,\n overlays,\n children,\n className,\n 'data-testid': testId,\n}: ShellRootProps) {\n return (\n <BlocksTooltipProvider>\n <div\n data-slot=\"shell\"\n data-testid={testId}\n className={cn('flex h-screen h-dvh flex-col', className)}\n >\n {banner}\n {topbar}\n {/* `relative` anchors the sidebar's slide-out overlays to this row. */}\n <div className=\"relative flex flex-1 overflow-hidden\">\n {sidebar}\n {children}\n {aside}\n {overlays}\n </div>\n {tabBar}\n </div>\n </BlocksTooltipProvider>\n )\n}\n\nexport interface ShellContentProps {\n children: ReactNode\n /** Scrolling element, for scroll restoration. */\n scrollRef?: Ref<HTMLDivElement>\n onClick?: MouseEventHandler<HTMLDivElement>\n /**\n * Overlay-mode panels portal into this id and cover the content column only. Defaults to\n * `DEFAULT_OVERLAY_ZONE_ID`; descendants read it with `useOverlayZoneId()`.\n */\n overlayZoneId?: string\n className?: string\n}\n\n/**\n * The content column beside the sidebar. It is `relative` so overlay-mode panels (portalled into\n * the overlay zone) cover this region only, leaving the sidebar and its actions interactive.\n */\nfunction ShellContent({\n children,\n scrollRef,\n onClick,\n overlayZoneId = DEFAULT_OVERLAY_ZONE_ID,\n className,\n}: ShellContentProps) {\n return (\n <div\n data-slot=\"shell-content\"\n className={cn('flex min-w-0 flex-1 flex-col', className)}\n onClick={onClick}\n >\n <div className=\"relative min-h-0 flex-1\">\n <OverlayZoneContext.Provider value={overlayZoneId}>\n {/* The content column is a CSS container: pages and parts size by its width with\n container variants (`@3xl:`...), so an open dock or a narrow window is honoured,\n which viewport breakpoints cannot do. */}\n <div ref={scrollRef} className=\"@container h-full overflow-auto\">\n {children}\n </div>\n </OverlayZoneContext.Provider>\n <div id={overlayZoneId} data-slot=\"overlay-zone\" />\n </div>\n </div>\n )\n}\n\nexport interface ShellTopbarProps {\n /** Left side: guidance / breadcrumbs, centred in the page column. */\n children?: ReactNode\n /** Right side: the action cluster. */\n actions?: ReactNode\n className?: string\n}\n\n/** A minimal white header for pages with no sidebar (the workspaces list). */\nfunction ShellTopbar({ children, actions, className }: ShellTopbarProps) {\n return (\n // `relative z-30` keeps dropdowns the header opens above the page region (a later sibling).\n <div\n data-slot=\"shell-topbar\"\n className={cn('relative z-30 flex h-14 shrink-0 items-center bg-background px-2', className)}\n >\n <div className=\"mx-auto flex w-full max-w-6xl items-center\">\n <div className=\"hidden min-w-0 flex-1 px-6 sm:block\">{children}</div>\n </div>\n <div className=\"absolute right-4 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n {actions}\n </div>\n </div>\n )\n}\n\nexport interface ShellDockProps {\n isOpen: boolean\n /** Called with `false` by the mobile close button. */\n onOpenChange?: (isOpen: boolean) => void\n /** Desktop width (CSS length or px). Default 24rem. */\n width?: number | string\n /** Phone layout: the dock covers the screen instead of sitting beside the content. */\n isMobile?: boolean\n /** Accessible name of the dock. */\n label: string\n /** Mobile close button label. */\n closeLabel?: string\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A right-hand dock for a companion surface (chat, inspector). Controlled: the host owns\n * `isOpen`, the width and the mobile breakpoint. Pass it to `Shell.Root` as `aside`.\n */\nfunction ShellDock({\n isOpen,\n onOpenChange,\n width = '24rem',\n isMobile = false,\n label,\n closeLabel = 'Close',\n children,\n className,\n 'data-testid': testId,\n}: ShellDockProps) {\n // The phone dock covers the screen, so it is a modal: Escape closes, focus is trapped and\n // returns to the opener.\n const mobileRef = useRef<HTMLDivElement>(null)\n const closeMobile = useCallback(() => onOpenChange?.(false), [onOpenChange])\n useDrawerBehavior(isOpen && isMobile, closeMobile, mobileRef)\n if (!isOpen) return null\n if (isMobile) {\n return (\n <div\n ref={mobileRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-mobile=\"true\"\n data-testid={testId}\n className={cn('fixed inset-0 z-40 flex flex-col bg-background', className)}\n >\n {onOpenChange && (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n aria-label={closeLabel}\n className=\"absolute right-2 top-2 z-10 rounded-md p-2 text-muted-foreground hover:bg-muted\"\n >\n <X className=\"size-5\" />\n </button>\n )}\n {children}\n </div>\n )\n }\n return (\n <aside\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-testid={testId}\n style={{ width }}\n className={cn(\n 'flex shrink-0 flex-col overflow-hidden border-l border-border bg-background',\n className\n )}\n >\n {children}\n </aside>\n )\n}\n\nexport const Shell = {\n Root: ShellRoot,\n Content: ShellContent,\n Topbar: ShellTopbar,\n Dock: ShellDock,\n}\n\nexport interface PageContainerProps {\n children: ReactNode\n /** Full width instead of the centred 72rem column. */\n wide?: boolean\n /** Stand-alone use: at least a screen tall, instead of filling the parent. */\n minScreen?: boolean\n /** Max width of the centred column (any Tailwind `max-w-*` class). Default `max-w-6xl`. */\n maxWidth?: string\n /**\n * Horizontal padding of the inner column (any Tailwind `px-*` classes, responsive variants\n * welcome). Default `px-4 sm:px-6 lg:px-8`; pass `px-0` for a full-bleed page, or the class\n * string of your own gutter. Use this prop, not `innerClassName`, to change the gutter: the\n * classes are concatenated without a merge step, so a second `px-*` would not reliably win.\n */\n padding?: string\n /** Extra classes for the inner column. */\n innerClassName?: string\n className?: string\n}\n\n/** Default gutter of {@link PageContainer}: tight on a phone, roomier from tablet up. */\nexport const DEFAULT_PAGE_CONTAINER_PADDING = 'px-4 sm:px-6 lg:px-8'\n\n/**\n * Page body wrapper: a white canvas with the standard 72rem column (or full width) and a responsive side gutter. Fills its\n * parent by default so sticky headers and h-full pages keep a definite height chain.\n */\nexport function PageContainer({\n children,\n wide = false,\n minScreen = false,\n maxWidth = 'max-w-6xl',\n padding = DEFAULT_PAGE_CONTAINER_PADDING,\n innerClassName,\n className,\n}: PageContainerProps) {\n return (\n <div\n data-slot=\"page-container\"\n className={cn(\n '@container bg-background pb-safe',\n minScreen ? 'min-h-screen' : 'h-full min-h-0',\n className\n )}\n >\n <div\n className={cn(\n 'flex h-full w-full min-w-0 flex-col pb-safe',\n padding,\n !wide && cn('mx-auto', maxWidth),\n innerClassName\n )}\n >\n {children}\n </div>\n </div>\n )\n}\n\n/** Fixed strings of the sidebar toggle. */\nexport interface SidebarToggleButtonLabels {\n closeSidebar: string\n openSidebar: string\n}\n\nexport const DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS: SidebarToggleButtonLabels = {\n closeSidebar: 'Close sidebar',\n openSidebar: 'Open sidebar',\n}\n\nexport interface SidebarToggleButtonProps {\n /** The sidebar is open (pinned). */\n isOpen: boolean\n onToggle: () => void\n labels?: Partial<SidebarToggleButtonLabels>\n 'data-testid'?: string\n}\n\n/** Opens/closes the sidebar from a page header, so the control sits in the same spot everywhere. */\nexport function SidebarToggleButton({\n isOpen,\n onToggle,\n labels,\n 'data-testid': testId = 'tabheader-sidebar-toggle',\n}: SidebarToggleButtonProps) {\n const l = { ...DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, ...labels }\n const label = isOpen ? l.closeSidebar : l.openSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:p-2.5\"\n aria-label={label}\n title={label}\n data-testid={testId}\n >\n <PanelLeft className=\"size-5\" />\n </button>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface ToolButtonProps {\n onClick: () => void\n /** Accessible name and native tooltip. */\n label: string\n /** The panel/page this opens is showing. */\n active?: boolean\n 'data-testid'?: string\n children: ReactNode\n}\n\n/** An icon button for a topbar or toolbar: 36px (44px coarse), selection tint while active. */\nexport function ToolButton({\n onClick,\n label,\n active = false,\n 'data-testid': testId,\n children,\n}: ToolButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n data-slot=\"tool-button\"\n data-testid={testId}\n className={cn(\n 'relative flex size-9 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-accent-foreground pointer-coarse:size-11',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {children}\n </button>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/bottom-inset.ts","../src/provider/TooltipScope.tsx","../src/lib/use-drawer.ts","../src/shell/Shell.tsx","../src/shell/ToolButton.tsx"],"names":["useEffect","observeResize","createContext","useContext","jsx","Fragment","TooltipProvider","useRef","jsxs","cn","useCallback","X","PanelLeft"],"mappings":"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","file":"chunk-B6MVQCXW.cjs","sourcesContent":["import { useEffect, type RefObject } from 'react'\nimport { observeResize } from './observe-resize'\n\n/**\n * The CSS custom property that carries how much of the screen's bottom edge is taken by pinned\n * bars (the phone tab bar, a chat composer), set on `<html>`. A floating element (the install\n * prompt, a toast, a back-to-top button) positions itself `calc(var(--shell-bottom-inset, 0px) +\n * 0.75rem)` so it never covers those bars.\n */\nexport const SHELL_BOTTOM_INSET_VAR = '--shell-bottom-inset'\n\nconst measurers = new Map<symbol, () => number>()\n\n/** Re-measure every registered bar and publish the largest: bars stack, so the tallest reach wins. */\nfunction apply(): void {\n if (typeof document === 'undefined') return\n let inset = 0\n for (const measure of measurers.values()) inset = Math.max(inset, measure())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_BOTTOM_INSET_VAR, `${Math.round(inset)}px`)\n else style.removeProperty(SHELL_BOTTOM_INSET_VAR)\n}\n\n/**\n * Report a bottom-pinned element to {@link SHELL_BOTTOM_INSET_VAR}: its distance from the top of\n * the element to the bottom of the viewport, so a composer above the tab bar counts the tab bar\n * too (contributions are combined with `max`, not summed). An element that is not rendered\n * (`display: none`, e.g. the phone-only tab bar on a desktop width) contributes 0. Used by\n * `MobileTabBar` and the chat composer; call it from your own bottom bar.\n */\nexport function useShellBottomInset(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean = true\n): void {\n useEffect(() => {\n const el = ref.current\n if (!enabled || !el) return\n const key = Symbol('shell-bottom-inset')\n measurers.set(key, () => {\n const rect = el.getBoundingClientRect()\n return rect.height > 0 ? Math.max(0, window.innerHeight - rect.top) : 0\n })\n apply()\n // Any bar resizing moves the others (a composer sits on top of the tab bar): re-measure all.\n const stop = observeResize(el, apply)\n window.addEventListener('resize', apply)\n return () => {\n stop()\n window.removeEventListener('resize', apply)\n measurers.delete(key)\n apply()\n }\n }, [ref, enabled])\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport { TooltipProvider } from '@arbidocs/react/ui'\n\nconst TooltipScopeContext = createContext(false)\n\n/**\n * A TooltipProvider that mounts once: inside another `BlocksTooltipProvider` (e.g. a Sidebar under\n * Shell.Root) it renders its children as-is, so tooltips share one delay group. Blocks that show\n * tooltips use this instead of the kit's provider.\n */\nexport function BlocksTooltipProvider({ children }: { children: ReactNode }) {\n const isNested = useContext(TooltipScopeContext)\n if (isNested) return <>{children}</>\n return (\n <TooltipScopeContext.Provider value>\n <TooltipProvider>{children}</TooltipProvider>\n </TooltipScopeContext.Provider>\n )\n}\n","import { useEffect, useRef, type RefObject } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nfunction focusableIn(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => !el.closest('[inert]') && el.getAttribute('aria-hidden') !== 'true'\n )\n}\n\n/**\n * Behaviour of a modal surface (off-canvas drawer, full-screen dock) while it is open: the page\n * behind does not scroll, Escape closes it, focus moves inside and Tab/Shift+Tab cycle within it\n * (portalled popovers opened from inside stay reachable: only the wrap-around is intercepted),\n * and focus returns to the opener on close. Restores the previous body overflow on close/unmount.\n *\n * Pass `containerRef` (the element carrying `role=\"dialog\"`) to get the focus handling; without it\n * only scroll lock and Escape apply.\n */\nexport function useDrawerBehavior(\n isOpen: boolean,\n onClose: () => void,\n containerRef?: RefObject<HTMLElement | null>\n): void {\n // A fresh `onClose` identity per render must not re-run the effect (it would steal focus).\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isOpen) return\n const previousOverflow = document.body.style.overflow\n const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null\n document.body.style.overflow = 'hidden'\n\n const container = containerRef?.current ?? null\n if (container) {\n const first = focusableIn(container)[0]\n if (first) first.focus()\n else {\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1')\n container.focus()\n }\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCloseRef.current()\n return\n }\n if (e.key !== 'Tab' || !container) return\n const items = focusableIn(container)\n if (items.length === 0) {\n e.preventDefault()\n return\n }\n const firstItem = items[0]\n const lastItem = items[items.length - 1]\n const active = document.activeElement\n if (!container.contains(active)) {\n e.preventDefault()\n firstItem.focus()\n } else if (e.shiftKey && active === firstItem) {\n e.preventDefault()\n lastItem.focus()\n } else if (!e.shiftKey && active === lastItem) {\n e.preventDefault()\n firstItem.focus()\n }\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = previousOverflow\n window.removeEventListener('keydown', onKey)\n if (opener?.isConnected) opener.focus()\n }\n }, [isOpen, containerRef])\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useRef,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { PanelLeft, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\n\n/** Default id of the element overlay-mode panels portal into (see `Shell.Content`). */\nexport const DEFAULT_OVERLAY_ZONE_ID = 'app-overlay-zone'\n\nconst OverlayZoneContext = createContext(DEFAULT_OVERLAY_ZONE_ID)\n\n/** The id of the enclosing `Shell.Content` overlay zone, for panels that portal into it. */\nexport function useOverlayZoneId(): string {\n return useContext(OverlayZoneContext)\n}\n\nexport interface ShellRootProps {\n /** Full-width strip above everything (e.g. a deletion-pending banner). */\n banner?: ReactNode\n /** Top chrome: a Shell.Topbar on list pages, a MobileAppBar on phones; omit for none. */\n topbar?: ReactNode\n /** The Sidebar.Root (and its drawer backdrop). */\n sidebar?: ReactNode\n /** Phone bottom navigation. */\n tabBar?: ReactNode\n /** Right-hand column beside the content: a `Shell.Dock` (chat, inspector...). */\n aside?: ReactNode\n /** Extra layers inside the body row (connection monitor, …). */\n overlays?: ReactNode\n /** The Shell.Content region. */\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * The application frame: banner, top chrome, then a body row holding the sidebar beside the\n * content, then the phone tab bar. Every region is a slot, so a custom UI composes its own.\n */\nfunction ShellRoot({\n banner,\n topbar,\n sidebar,\n tabBar,\n aside,\n overlays,\n children,\n className,\n 'data-testid': testId,\n}: ShellRootProps) {\n return (\n <BlocksTooltipProvider>\n <div\n data-slot=\"shell\"\n data-testid={testId}\n className={cn('flex h-screen h-dvh flex-col', className)}\n >\n {banner}\n {topbar}\n {/* `relative` anchors the sidebar's slide-out overlays to this row. */}\n <div className=\"relative flex flex-1 overflow-hidden\">\n {sidebar}\n {children}\n {aside}\n {overlays}\n </div>\n {tabBar}\n </div>\n </BlocksTooltipProvider>\n )\n}\n\nexport interface ShellContentProps {\n children: ReactNode\n /** Scrolling element, for scroll restoration. */\n scrollRef?: Ref<HTMLDivElement>\n onClick?: MouseEventHandler<HTMLDivElement>\n /**\n * Overlay-mode panels portal into this id and cover the content column only. Defaults to\n * `DEFAULT_OVERLAY_ZONE_ID`; descendants read it with `useOverlayZoneId()`.\n */\n overlayZoneId?: string\n className?: string\n}\n\n/**\n * The content column beside the sidebar. It is `relative` so overlay-mode panels (portalled into\n * the overlay zone) cover this region only, leaving the sidebar and its actions interactive.\n */\nfunction ShellContent({\n children,\n scrollRef,\n onClick,\n overlayZoneId = DEFAULT_OVERLAY_ZONE_ID,\n className,\n}: ShellContentProps) {\n return (\n <div\n data-slot=\"shell-content\"\n className={cn('flex min-w-0 flex-1 flex-col', className)}\n onClick={onClick}\n >\n <div className=\"relative min-h-0 flex-1\">\n <OverlayZoneContext.Provider value={overlayZoneId}>\n {/* The content column is a CSS container: pages and parts size by its width with\n container variants (`@3xl:`...), so an open dock or a narrow window is honoured,\n which viewport breakpoints cannot do. */}\n <div ref={scrollRef} className=\"@container h-full overflow-auto\">\n {children}\n </div>\n </OverlayZoneContext.Provider>\n <div id={overlayZoneId} data-slot=\"overlay-zone\" />\n </div>\n </div>\n )\n}\n\nexport interface ShellTopbarProps {\n /** Left side: guidance / breadcrumbs, centred in the page column. */\n children?: ReactNode\n /** Right side: the action cluster. */\n actions?: ReactNode\n className?: string\n}\n\n/** A minimal white header for pages with no sidebar (the workspaces list). */\nfunction ShellTopbar({ children, actions, className }: ShellTopbarProps) {\n return (\n // `relative z-30` keeps dropdowns the header opens above the page region (a later sibling).\n <div\n data-slot=\"shell-topbar\"\n className={cn('relative z-30 flex h-14 shrink-0 items-center bg-background px-2', className)}\n >\n <div className=\"mx-auto flex w-full max-w-6xl items-center\">\n <div className=\"hidden min-w-0 flex-1 px-6 sm:block\">{children}</div>\n </div>\n <div className=\"absolute right-4 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n {actions}\n </div>\n </div>\n )\n}\n\nexport interface ShellDockProps {\n isOpen: boolean\n /** Called with `false` by the mobile close button. */\n onOpenChange?: (isOpen: boolean) => void\n /** Desktop width (CSS length or px). Default 24rem. */\n width?: number | string\n /** Phone layout: the dock covers the screen instead of sitting beside the content. */\n isMobile?: boolean\n /** Accessible name of the dock. */\n label: string\n /** Mobile close button label. */\n closeLabel?: string\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A right-hand dock for a companion surface (chat, inspector). Controlled: the host owns\n * `isOpen`, the width and the mobile breakpoint. Pass it to `Shell.Root` as `aside`.\n */\nfunction ShellDock({\n isOpen,\n onOpenChange,\n width = '24rem',\n isMobile = false,\n label,\n closeLabel = 'Close',\n children,\n className,\n 'data-testid': testId,\n}: ShellDockProps) {\n // The phone dock covers the screen, so it is a modal: Escape closes, focus is trapped and\n // returns to the opener.\n const mobileRef = useRef<HTMLDivElement>(null)\n const closeMobile = useCallback(() => onOpenChange?.(false), [onOpenChange])\n useDrawerBehavior(isOpen && isMobile, closeMobile, mobileRef)\n if (!isOpen) return null\n if (isMobile) {\n return (\n <div\n ref={mobileRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-mobile=\"true\"\n data-testid={testId}\n className={cn('fixed inset-0 z-40 flex flex-col bg-background', className)}\n >\n {onOpenChange && (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n aria-label={closeLabel}\n className=\"absolute right-2 top-2 z-10 rounded-md p-2 text-muted-foreground hover:bg-muted\"\n >\n <X className=\"size-5\" />\n </button>\n )}\n {children}\n </div>\n )\n }\n return (\n <aside\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-testid={testId}\n style={{ width }}\n className={cn(\n 'flex shrink-0 flex-col overflow-hidden border-l border-border bg-background',\n className\n )}\n >\n {children}\n </aside>\n )\n}\n\nexport const Shell = {\n Root: ShellRoot,\n Content: ShellContent,\n Topbar: ShellTopbar,\n Dock: ShellDock,\n}\n\nexport interface PageContainerProps {\n children: ReactNode\n /** Full width instead of the centred 72rem column. */\n wide?: boolean\n /** Stand-alone use: at least a screen tall, instead of filling the parent. */\n minScreen?: boolean\n /** Max width of the centred column (any Tailwind `max-w-*` class). Default `max-w-6xl`. */\n maxWidth?: string\n /**\n * Horizontal padding of the inner column (any Tailwind `px-*` classes, responsive variants\n * welcome). Default `px-4 sm:px-6 lg:px-8`; pass `px-0` for a full-bleed page, or the class\n * string of your own gutter. Use this prop, not `innerClassName`, to change the gutter: the\n * classes are concatenated without a merge step, so a second `px-*` would not reliably win.\n */\n padding?: string\n /** Extra classes for the inner column. */\n innerClassName?: string\n className?: string\n}\n\n/** Default gutter of {@link PageContainer}: tight on a phone, roomier from tablet up. */\nexport const DEFAULT_PAGE_CONTAINER_PADDING = 'px-4 sm:px-6 lg:px-8'\n\n/**\n * Page body wrapper: a white canvas with the standard 72rem column (or full width) and a responsive side gutter. Fills its\n * parent by default so sticky headers and h-full pages keep a definite height chain.\n *\n * NOT a CSS container: its content (a long thread) overflows it into the host's scroller, and\n * Chrome before ~v130 gives `container-type` layout containment, which turns that overflow into\n * ink overflow — the scroller sees no scroll height, so no scrollbar and a dead wheel. Container\n * queries resolve against the scroll surface instead (Shell.Content, the app's DockZone).\n */\nexport function PageContainer({\n children,\n wide = false,\n minScreen = false,\n maxWidth = 'max-w-6xl',\n padding = DEFAULT_PAGE_CONTAINER_PADDING,\n innerClassName,\n className,\n}: PageContainerProps) {\n return (\n <div\n data-slot=\"page-container\"\n className={cn(\n 'bg-background pb-safe',\n minScreen ? 'min-h-screen' : 'h-full min-h-0',\n className\n )}\n >\n <div\n className={cn(\n 'flex h-full w-full min-w-0 flex-col pb-safe',\n padding,\n !wide && cn('mx-auto', maxWidth),\n innerClassName\n )}\n >\n {children}\n </div>\n </div>\n )\n}\n\n/** Fixed strings of the sidebar toggle. */\nexport interface SidebarToggleButtonLabels {\n closeSidebar: string\n openSidebar: string\n}\n\nexport const DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS: SidebarToggleButtonLabels = {\n closeSidebar: 'Close sidebar',\n openSidebar: 'Open sidebar',\n}\n\nexport interface SidebarToggleButtonProps {\n /** The sidebar is open (pinned). */\n isOpen: boolean\n onToggle: () => void\n labels?: Partial<SidebarToggleButtonLabels>\n 'data-testid'?: string\n}\n\n/** Opens/closes the sidebar from a page header, so the control sits in the same spot everywhere. */\nexport function SidebarToggleButton({\n isOpen,\n onToggle,\n labels,\n 'data-testid': testId = 'tabheader-sidebar-toggle',\n}: SidebarToggleButtonProps) {\n const l = { ...DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, ...labels }\n const label = isOpen ? l.closeSidebar : l.openSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:p-2.5\"\n aria-label={label}\n title={label}\n data-testid={testId}\n >\n <PanelLeft className=\"size-5\" />\n </button>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface ToolButtonProps {\n onClick: () => void\n /** Accessible name and native tooltip. */\n label: string\n /** The panel/page this opens is showing. */\n active?: boolean\n 'data-testid'?: string\n children: ReactNode\n}\n\n/** An icon button for a topbar or toolbar: 36px (44px coarse), selection tint while active. */\nexport function ToolButton({\n onClick,\n label,\n active = false,\n 'data-testid': testId,\n children,\n}: ToolButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n data-slot=\"tool-button\"\n data-testid={testId}\n className={cn(\n 'relative flex size-9 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-accent-foreground pointer-coarse:size-11',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {children}\n </button>\n )\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { ActionLink } from './chunk-S7PSMMRG.js';
|
|
3
|
-
import { useDrawerBehavior, BlocksTooltipProvider, useShellBottomInset } from './chunk-
|
|
3
|
+
import { useDrawerBehavior, BlocksTooltipProvider, useShellBottomInset } from './chunk-7XF5SFJ2.js';
|
|
4
4
|
import { testIdOr, prefixedTestId } from './chunk-7F6CBP3Z.js';
|
|
5
5
|
import { createContext, forwardRef, useContext, useMemo, useRef, useState, useEffect, useCallback, useId } from 'react';
|
|
6
6
|
import { TriangleAlert, CheckCircle2, Loader2, PanelLeftClose, PanelLeftOpen, X, Globe, Users, Lock, ChevronDown, LayoutGrid, Plus, Sparkles, Search, ArrowUp, Menu, Download, RefreshCw, WifiOff, MousePointerClick, Lightbulb, Pencil, ChevronLeft, ChevronRight, Info } from 'lucide-react';
|
|
@@ -1897,5 +1897,5 @@ function SplitLayout({
|
|
|
1897
1897
|
}
|
|
1898
1898
|
|
|
1899
1899
|
export { ActionCluster, AskField, AskRow, AskTrigger, DEFAULT_ASK_FIELD_LABELS, DEFAULT_INSTALL_PROMPT_LABELS, DEFAULT_MOBILE_BARS_LABELS, DEFAULT_OFFLINE_PILL_LABELS, DEFAULT_REMOTE_CONTROL_PILL_LABELS, DEFAULT_SIDEBAR_LABELS, DEFAULT_TIP_CARD_LABELS, DEFAULT_WORKSPACE_KIND_LABELS, DEFAULT_WORKSPACE_SWITCHER_LABELS, INSTALL_PROMPT_DISMISSED_KEY, InfoBar, InstallPrompt, MobileAppBar, MobileTabBar, OfflinePill, RemoteControlPill, STATUS_ROW_BASE_CLASS, STATUS_ROW_TONES, Sidebar, SidebarBadgeRow, SidebarRowAction, SidebarRowHoverContext, SplitLayout, StatusBadge, StatusRow, TipCard, WorkspaceIdentity, WorkspaceSwitcher, getInstallInstructions, initInstallPrompt, isIosDevice, promptAppInstall, resolveSidebarLayout, useInstallPrompt, useSidebarContext, useSidebarSettle, workspaceKindColor, workspaceKindMeta };
|
|
1900
|
-
//# sourceMappingURL=chunk-
|
|
1901
|
-
//# sourceMappingURL=chunk-
|
|
1900
|
+
//# sourceMappingURL=chunk-D3N67Q4D.js.map
|
|
1901
|
+
//# sourceMappingURL=chunk-D3N67Q4D.js.map
|