{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sidebar-shell",
  "type": "registry:ui",
  "title": "SidebarShell",
  "description": "Responsive application shell with physical left/right navigation, optional header, independently scrolling content, optional content-width or full-shell bottom bar, plain/workbench chrome, accessible skip link and reduced-motion-aware transitions.",
  "dependencies": [
    "motion@^12.43.0"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://components.dethink.co.uk/r/dethink-base.json",
    "https://components.dethink.co.uk/r/sidebar.json"
  ],
  "files": [
    {
      "path": "packages/components/src/components/sidebar-shell/sidebar-shell.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/components/sidebar-shell/sidebar-shell.tsx",
      "content": "import {\n  Children,\n  Fragment,\n  cloneElement,\n  createContext,\n  forwardRef,\n  isValidElement,\n  useCallback,\n  useContext,\n  useId,\n  useMemo,\n  useState,\n  type AnchorHTMLAttributes,\n  type ForwardedRef,\n  type HTMLAttributes,\n  type ReactNode,\n} from \"react\";\nimport {\n  MotionConfig,\n  motion as motionElement,\n  useReducedMotion,\n  type Transition,\n} from \"motion/react\";\nimport { cn } from \"../../utils/cn\";\nimport {\n  getSidebarShellPart,\n  markSidebarShellPart,\n} from \"../../utils/sidebar-shell-part\";\nimport {\n  Sidebar,\n  SidebarProvider,\n  sidebarSkipLinkClassNames,\n  type SidebarMotion,\n  type SidebarSide,\n  type SidebarVariant,\n} from \"../sidebar\";\n\nexport type SidebarShellChrome = \"workbench\" | \"plain\";\nexport type SidebarShellLayout = \"viewport\";\n\ntype MotionBackedEventProps =\n  | \"onAnimationEnd\"\n  | \"onAnimationEndCapture\"\n  | \"onAnimationIteration\"\n  | \"onAnimationIterationCapture\"\n  | \"onAnimationStart\"\n  | \"onAnimationStartCapture\"\n  | \"onDrag\"\n  | \"onDragCapture\"\n  | \"onDragEnd\"\n  | \"onDragEndCapture\"\n  | \"onDragEnter\"\n  | \"onDragEnterCapture\"\n  | \"onDragExit\"\n  | \"onDragExitCapture\"\n  | \"onDragLeave\"\n  | \"onDragLeaveCapture\"\n  | \"onDragOver\"\n  | \"onDragOverCapture\"\n  | \"onDragStart\"\n  | \"onDragStartCapture\";\n\ntype MotionSafeDivProps = Omit<\n  HTMLAttributes<HTMLDivElement>,\n  MotionBackedEventProps\n>;\n\ntype MotionSafeLandmarkProps = Omit<\n  HTMLAttributes<HTMLElement>,\n  MotionBackedEventProps\n>;\n\nexport interface SidebarShellProps extends MotionSafeDivProps {\n  animate?: boolean;\n  chrome?: SidebarShellChrome;\n  collapsed?: boolean;\n  defaultCollapsed?: boolean;\n  defaultMobileOpen?: boolean;\n  mainId?: string;\n  mobileOpen?: boolean;\n  motion?: SidebarMotion;\n  onCollapsedChange?: (collapsed: boolean) => void;\n  onMobileOpenChange?: (open: boolean) => void;\n  side?: SidebarSide;\n  variant?: SidebarVariant;\n}\n\nexport interface SidebarShellHeaderProps extends MotionSafeLandmarkProps {\n  as?: \"header\" | \"div\";\n}\n\nexport type SidebarShellNavigationProps = MotionSafeDivProps;\n\nexport interface SidebarShellMainProps extends MotionSafeLandmarkProps {\n  as?: \"main\" | \"div\" | \"section\";\n}\n\nexport interface SidebarShellFooterProps extends MotionSafeLandmarkProps {\n  as?: \"footer\" | \"div\";\n  /** Content width by default; shell spans beneath navigation and content. */\n  span?: \"content\" | \"shell\";\n}\n\nexport interface SidebarShellSkipLinkProps extends Omit<\n  AnchorHTMLAttributes<HTMLAnchorElement>,\n  MotionBackedEventProps\n> {\n  targetId?: string;\n}\n\nexport interface SidebarShellMotionConfig {\n  hoverScale: number;\n  motion: SidebarMotion;\n  reducedMotion: boolean;\n  surfaceLift: number;\n  tapScale: number;\n  transition: Transition;\n}\n\ntype SidebarShellContextValue = {\n  chrome: SidebarShellChrome;\n  collapsed: boolean;\n  mainId: string;\n  motionConfig: SidebarShellMotionConfig;\n  side: SidebarSide;\n};\n\nconst SidebarShellContext = createContext<SidebarShellContextValue | null>(\n  null,\n);\n\nconst sidebarShellRootClasses =\n  \"group/sidebar-shell relative isolate grid [container-type:size] [--bottom-bar-shell-limit:50cqh] h-[100dvh] min-h-0 w-full min-w-0 grid-cols-[auto_minmax(0,1fr)] grid-rows-[minmax(0,1fr)] data-[has-shell-footer=true]:grid-rows-[minmax(0,1fr)_auto] overflow-hidden text-foreground data-[side=right]:grid-cols-[minmax(0,1fr)_auto] rtl:data-[side=left]:grid-cols-[minmax(0,1fr)_auto] rtl:data-[side=right]:grid-cols-[auto_minmax(0,1fr)] data-[has-navigation=false]:grid-cols-1 data-[chrome=workbench]:gap-[var(--dt-density-gap)] data-[chrome=workbench]:bg-muted/40 data-[chrome=workbench]:p-[var(--dt-density-gap)] data-[chrome=workbench]:[&>[data-slot=sidebar]]:h-full data-[chrome=workbench]:[&>[data-slot=sidebar]]:rounded-xl data-[chrome=workbench]:[&>[data-slot=sidebar]]:border data-[chrome=workbench]:[&>[data-slot=sidebar]]:shadow-sm data-[chrome=plain]:bg-background\";\n\nconst sidebarShellFrameClasses =\n  \"relative z-0 col-start-2 row-start-1 grid [container-type:size] min-h-0 min-w-0 grid-rows-[auto_minmax(0,1fr)_auto] overflow-hidden bg-background group-data-[side=right]/sidebar-shell:col-start-1 rtl:group-data-[side=left]/sidebar-shell:col-start-1 rtl:group-data-[side=right]/sidebar-shell:col-start-2 group-data-[has-navigation=false]/sidebar-shell:col-span-full data-[chrome=workbench]:rounded-xl data-[chrome=workbench]:border data-[chrome=workbench]:border-border data-[chrome=workbench]:shadow-sm\";\n\nconst sidebarShellNavigationClasses =\n  \"relative z-20 min-h-0 shrink-0 [&>[data-slot=sidebar]]:h-full data-[chrome=workbench]:rounded-xl data-[chrome=workbench]:border data-[chrome=workbench]:border-border data-[chrome=workbench]:shadow-sm data-[chrome=workbench]:[&>[data-slot=sidebar]]:rounded-[inherit] data-[chrome=workbench]:[&>[data-slot=sidebar]]:border-0\";\n\nconst sidebarShellHeaderClasses =\n  \"relative z-10 row-start-1 flex min-h-[calc(var(--dt-density-control)+var(--dt-space-4))] min-w-0 items-center gap-[calc(var(--dt-density-gap)+var(--dt-space-1))] border-b border-border bg-background px-[var(--dt-space-4)] py-[var(--dt-density-gap)] text-foreground outline-none data-[chrome=workbench]:bg-muted/35\";\n\nconst sidebarShellMainClasses =\n  \"row-start-2 min-h-0 min-w-0 overflow-auto overscroll-contain bg-background p-[calc(var(--dt-density-gap)+var(--dt-space-2))] text-foreground outline-none focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\";\n\nconst sidebarShellFooterClasses =\n  \"relative z-10 row-start-3 flex min-h-[calc(var(--dt-density-control)+var(--dt-space-1))] min-w-0 flex-wrap items-center gap-[var(--dt-density-gap)] border-t border-border bg-background px-[var(--dt-space-4)] py-[var(--dt-density-gap)] pb-[max(var(--dt-density-gap),env(safe-area-inset-bottom))] text-sm text-muted-foreground data-[span=shell]:col-span-full data-[span=shell]:row-start-2 data-[span=shell]:max-h-[40dvh] data-[span=shell]:overflow-auto data-[chrome=workbench]:bg-muted/20 data-[span=shell]:data-[chrome=workbench]:rounded-xl data-[span=shell]:data-[chrome=workbench]:border\";\n\nconst sidebarShellMotionSettings: Record<\n  SidebarMotion,\n  {\n    bounce: number;\n    duration: number;\n    hoverScale: number;\n    surfaceLift: number;\n    tapScale: number;\n  }\n> = {\n  none: {\n    bounce: 0,\n    duration: 0,\n    hoverScale: 1,\n    surfaceLift: 0,\n    tapScale: 1,\n  },\n  subtle: {\n    bounce: 0.02,\n    duration: 0.18,\n    hoverScale: 1.002,\n    surfaceLift: 0.5,\n    tapScale: 0.998,\n  },\n  standard: {\n    bounce: 0.06,\n    duration: 0.26,\n    hoverScale: 1.004,\n    surfaceLift: 1,\n    tapScale: 0.996,\n  },\n  expressive: {\n    bounce: 0.14,\n    duration: 0.36,\n    hoverScale: 1.008,\n    surfaceLift: 1.5,\n    tapScale: 0.992,\n  },\n};\n\nexport function getSidebarShellMotionConfig(\n  motion: SidebarMotion,\n  reducedMotion = false,\n): SidebarShellMotionConfig {\n  const resolvedMotion = reducedMotion ? \"none\" : motion;\n  const settings = sidebarShellMotionSettings[resolvedMotion];\n\n  return {\n    hoverScale: settings.hoverScale,\n    motion: resolvedMotion,\n    reducedMotion: resolvedMotion === \"none\",\n    surfaceLift: settings.surfaceLift,\n    tapScale: settings.tapScale,\n    transition:\n      settings.duration === 0\n        ? { duration: 0 }\n        : {\n            type: \"spring\",\n            visualDuration: settings.duration,\n            bounce: settings.bounce,\n          },\n  };\n}\n\nexport function sidebarShellClassNames({\n  className,\n}: Pick<SidebarShellProps, \"className\"> = {}) {\n  return cn(sidebarShellRootClasses, className);\n}\n\nexport function sidebarShellFrameClassNames({\n  className,\n}: { className?: string } = {}) {\n  return cn(sidebarShellFrameClasses, className);\n}\n\nexport function sidebarShellNavigationClassNames({\n  className,\n}: Pick<SidebarShellNavigationProps, \"className\"> = {}) {\n  return cn(sidebarShellNavigationClasses, className);\n}\n\nexport function sidebarShellHeaderClassNames({\n  className,\n}: Pick<SidebarShellHeaderProps, \"className\"> = {}) {\n  return cn(sidebarShellHeaderClasses, className);\n}\n\nexport function sidebarShellMainClassNames({\n  className,\n}: Pick<SidebarShellMainProps, \"className\"> = {}) {\n  return cn(sidebarShellMainClasses, className);\n}\n\nexport function sidebarShellFooterClassNames({\n  className,\n}: Pick<SidebarShellFooterProps, \"className\"> = {}) {\n  return cn(sidebarShellFooterClasses, className);\n}\n\nexport function sidebarShellSkipLinkClassNames({\n  className,\n}: Pick<SidebarShellSkipLinkProps, \"className\"> = {}) {\n  return sidebarSkipLinkClassNames({ className });\n}\n\nfunction useSidebarShellContext(componentName: string) {\n  const context = useContext(SidebarShellContext);\n\n  if (!context) {\n    throw new Error(`${componentName} must be used within SidebarShell.`);\n  }\n\n  return context;\n}\n\nfunction useControllableBoolean({\n  defaultValue = false,\n  onChange,\n  value,\n}: {\n  defaultValue?: boolean;\n  onChange?: (value: boolean) => void;\n  value?: boolean;\n}) {\n  const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n  const controlled = value !== undefined;\n  const currentValue = value ?? uncontrolledValue;\n\n  const setValue = useCallback(\n    (nextValue: boolean) => {\n      if (nextValue === currentValue) {\n        return;\n      }\n\n      if (!controlled) {\n        setUncontrolledValue(nextValue);\n      }\n\n      onChange?.(nextValue);\n    },\n    [controlled, currentValue, onChange],\n  );\n\n  return [currentValue, setValue] as const;\n}\n\n// Fragments are transparent slots. Qualify keys so sibling fragments can reuse keys.\nfunction flattenShellChildren(children: ReactNode, prefix = \"\"): ReactNode[] {\n  return Children.toArray(children).flatMap((child) => {\n    if (!isValidElement<{ children?: ReactNode }>(child)) return [child];\n    const key = `${prefix}${child.key}`;\n    return child.type === Fragment\n      ? flattenShellChildren(child.props.children, `${key}/`)\n      : [cloneElement(child, { key })];\n  });\n}\n\nfunction isSidebarChild(child: ReactNode) {\n  if (!isValidElement(child) || typeof child.type === \"string\") {\n    return false;\n  }\n\n  return (\n    child.type === Sidebar ||\n    (child.type as { displayName?: string }).displayName === \"Sidebar\"\n  );\n}\n\nexport const SidebarShellSkipLink = forwardRef<\n  HTMLAnchorElement,\n  SidebarShellSkipLinkProps\n>(\n  (\n    { children = \"Skip to main content\", className, href, targetId, ...props },\n    ref,\n  ) => {\n    const context = useSidebarShellContext(\"SidebarShellSkipLink\");\n    const resolvedTargetId = targetId ?? context.mainId;\n    const motionConfig = context.motionConfig;\n\n    return (\n      <motionElement.a\n        {...props}\n        ref={ref}\n        href={href ?? `#${resolvedTargetId}`}\n        data-slot=\"sidebar-shell-skip-link\"\n        data-motion={motionConfig.motion}\n        className={sidebarShellSkipLinkClassNames({ className })}\n        initial={false}\n        whileFocus={\n          motionConfig.reducedMotion\n            ? undefined\n            : { y: -motionConfig.surfaceLift }\n        }\n        whileHover={\n          motionConfig.reducedMotion\n            ? undefined\n            : {\n                y: -motionConfig.surfaceLift,\n                scale: motionConfig.hoverScale,\n              }\n        }\n        whileTap={\n          motionConfig.reducedMotion\n            ? undefined\n            : { scale: motionConfig.tapScale }\n        }\n        transition={motionConfig.transition}\n      >\n        {children}\n      </motionElement.a>\n    );\n  },\n);\n\nSidebarShellSkipLink.displayName = \"SidebarShellSkipLink\";\nmarkSidebarShellPart(SidebarShellSkipLink, \"SkipLink\");\n\nexport const SidebarShellNavigation = forwardRef<\n  HTMLDivElement,\n  SidebarShellNavigationProps\n>(({ className, ...props }, ref) => {\n  const context = useSidebarShellContext(\"SidebarShellNavigation\");\n  const motionConfig = context.motionConfig;\n\n  return (\n    <motionElement.div\n      {...props}\n      ref={ref}\n      data-slot=\"sidebar-shell-navigation\"\n      data-chrome={context.chrome}\n      data-collapsed={context.collapsed ? \"true\" : \"false\"}\n      data-motion={motionConfig.motion}\n      data-side={context.side}\n      className={sidebarShellNavigationClassNames({ className })}\n      initial={false}\n      transition={motionConfig.transition}\n    />\n  );\n});\n\nSidebarShellNavigation.displayName = \"SidebarShellNavigation\";\nmarkSidebarShellPart(SidebarShellNavigation, \"Navigation\");\n\nexport const SidebarShellHeader = forwardRef<\n  HTMLElement,\n  SidebarShellHeaderProps\n>(({ as = \"header\", className, ...props }, ref) => {\n  const context = useSidebarShellContext(\"SidebarShellHeader\");\n  const motionConfig = context.motionConfig;\n  const motionProps = {\n    ...props,\n    \"data-slot\": \"sidebar-shell-header\",\n    \"data-chrome\": context.chrome,\n    \"data-collapsed\": context.collapsed ? \"true\" : \"false\",\n    \"data-motion\": motionConfig.motion,\n    \"data-side\": context.side,\n    className: sidebarShellHeaderClassNames({ className }),\n    initial: false as const,\n    layout: \"position\" as const,\n    whileHover: motionConfig.reducedMotion\n      ? undefined\n      : { y: -motionConfig.surfaceLift },\n    transition: motionConfig.transition,\n  };\n\n  if (as === \"div\") {\n    return (\n      <motionElement.div\n        {...motionProps}\n        ref={ref as ForwardedRef<HTMLDivElement>}\n      />\n    );\n  }\n\n  return <motionElement.header {...motionProps} ref={ref} />;\n});\n\nSidebarShellHeader.displayName = \"SidebarShellHeader\";\nmarkSidebarShellPart(SidebarShellHeader, \"Header\");\n\nexport const SidebarShellMain = forwardRef<HTMLElement, SidebarShellMainProps>(\n  ({ as = \"main\", className, id, tabIndex = 0, ...props }, ref) => {\n    const context = useSidebarShellContext(\"SidebarShellMain\");\n    const motionConfig = context.motionConfig;\n    const motionProps = {\n      ...props,\n      id: id ?? context.mainId,\n      tabIndex,\n      \"data-slot\": \"sidebar-shell-main\",\n      \"data-chrome\": context.chrome,\n      \"data-collapsed\": context.collapsed ? \"true\" : \"false\",\n      \"data-motion\": motionConfig.motion,\n      \"data-side\": context.side,\n      className: sidebarShellMainClassNames({ className }),\n      initial: false as const,\n      transition: motionConfig.transition,\n    };\n\n    if (as === \"div\") {\n      return (\n        <motionElement.div\n          {...motionProps}\n          ref={ref as ForwardedRef<HTMLDivElement>}\n        />\n      );\n    }\n\n    if (as === \"section\") {\n      return <motionElement.section {...motionProps} ref={ref} />;\n    }\n\n    return <motionElement.main {...motionProps} ref={ref} />;\n  },\n);\n\nSidebarShellMain.displayName = \"SidebarShellMain\";\nmarkSidebarShellPart(SidebarShellMain, \"Main\");\n\nexport const SidebarShellFooter = forwardRef<\n  HTMLElement,\n  SidebarShellFooterProps\n>(({ as = \"footer\", className, span = \"content\", ...props }, ref) => {\n  const context = useSidebarShellContext(\"SidebarShellFooter\");\n  const motionConfig = context.motionConfig;\n  const motionProps = {\n    ...props,\n    \"data-slot\": \"sidebar-shell-footer\",\n    \"data-span\": span,\n    \"data-chrome\": context.chrome,\n    \"data-collapsed\": context.collapsed ? \"true\" : \"false\",\n    \"data-motion\": motionConfig.motion,\n    \"data-side\": context.side,\n    className: sidebarShellFooterClassNames({ className }),\n    initial: false as const,\n    layout: \"position\" as const,\n    transition: motionConfig.transition,\n  };\n\n  if (as === \"div\") {\n    return (\n      <motionElement.div\n        {...motionProps}\n        ref={ref as ForwardedRef<HTMLDivElement>}\n      />\n    );\n  }\n\n  return <motionElement.footer {...motionProps} ref={ref} />;\n});\n\nSidebarShellFooter.displayName = \"SidebarShellFooter\";\nmarkSidebarShellPart(SidebarShellFooter, \"Footer\");\n\nexport const SidebarShell = forwardRef<HTMLDivElement, SidebarShellProps>(\n  (\n    {\n      animate = true,\n      children,\n      chrome = \"workbench\",\n      className,\n      collapsed,\n      defaultCollapsed = false,\n      defaultMobileOpen = false,\n      mainId,\n      mobileOpen,\n      motion = \"standard\",\n      onCollapsedChange,\n      onMobileOpenChange,\n      side = \"left\",\n      variant = \"default\",\n      ...props\n    },\n    ref,\n  ) => {\n    const generatedMainId = useId();\n    const prefersReducedMotion = useReducedMotion();\n    const reducedMotion =\n      !animate || motion === \"none\" || prefersReducedMotion === true;\n    const motionConfig = useMemo(\n      () => getSidebarShellMotionConfig(motion, reducedMotion),\n      [motion, reducedMotion],\n    );\n    const [resolvedCollapsed, setCollapsed] = useControllableBoolean({\n      defaultValue: defaultCollapsed,\n      onChange: onCollapsedChange,\n      value: collapsed,\n    });\n    const [resolvedMobileOpen, setMobileOpen] = useControllableBoolean({\n      defaultValue: defaultMobileOpen,\n      onChange: onMobileOpenChange,\n      value: mobileOpen,\n    });\n    const resolvedChildren = flattenShellChildren(children);\n    const explicitMainId = resolvedChildren.find(\n      (child) => getSidebarShellPart(child) === \"Main\",\n    );\n    const childMainId = isValidElement(explicitMainId)\n      ? (explicitMainId.props as { id?: string }).id\n      : undefined;\n    const resolvedMainId =\n      childMainId ?? mainId ?? `sidebar-shell-main-${generatedMainId}`;\n    const contextValue: SidebarShellContextValue = {\n      chrome,\n      collapsed: resolvedCollapsed,\n      mainId: resolvedMainId,\n      motionConfig,\n      side,\n    };\n    const skipLinkChildren = resolvedChildren.filter(\n      (child) => getSidebarShellPart(child) === \"SkipLink\",\n    );\n    const navigationChildren = resolvedChildren.filter(isSidebarChild);\n    const navigationRegionChildren = resolvedChildren.filter(\n      (child) => getSidebarShellPart(child) === \"Navigation\",\n    );\n    const shellFooters = resolvedChildren.filter(\n      (child) =>\n        getSidebarShellPart(child) === \"Footer\" &&\n        isValidElement<SidebarShellFooterProps>(child) &&\n        child.props.span === \"shell\",\n    );\n    const frameChildren = resolvedChildren.filter(\n      (child) =>\n        getSidebarShellPart(child) !== \"SkipLink\" &&\n        getSidebarShellPart(child) !== \"Navigation\" &&\n        !shellFooters.includes(child) &&\n        !isSidebarChild(child),\n    );\n    const navigation = [...navigationRegionChildren, ...navigationChildren];\n    const frame = (\n      <motionElement.div\n        key=\"shell-frame\"\n        data-slot=\"sidebar-shell-frame\"\n        data-chrome={chrome}\n        data-collapsed={resolvedCollapsed ? \"true\" : \"false\"}\n        data-motion={motionConfig.motion}\n        className={sidebarShellFrameClassNames()}\n        initial={false}\n      >\n        {frameChildren}\n      </motionElement.div>\n    );\n\n    return (\n      <SidebarProvider\n        animate={animate}\n        className=\"contents\"\n        collapsed={resolvedCollapsed}\n        mobileOpen={resolvedMobileOpen}\n        motion={motionConfig.motion}\n        onCollapsedChange={setCollapsed}\n        onMobileOpenChange={setMobileOpen}\n        side={side}\n        variant={variant}\n      >\n        <SidebarShellContext.Provider value={contextValue}>\n          <MotionConfig\n            reducedMotion={motionConfig.reducedMotion ? \"always\" : \"user\"}\n            transition={motionConfig.transition}\n          >\n            <motionElement.div\n              role={\n                props[\"aria-label\"] || props[\"aria-labelledby\"]\n                  ? \"group\"\n                  : undefined\n              }\n              {...props}\n              ref={ref}\n              data-slot=\"sidebar-shell\"\n              data-animate={animate ? \"true\" : \"false\"}\n              data-chrome={chrome}\n              data-collapsed={resolvedCollapsed ? \"true\" : \"false\"}\n              data-layout=\"viewport\"\n              data-mobile-open={resolvedMobileOpen ? \"true\" : \"false\"}\n              data-motion={motionConfig.motion}\n              data-reduced-motion={\n                motionConfig.reducedMotion ? \"true\" : undefined\n              }\n              data-side={side}\n              data-has-navigation={navigation.length > 0 ? \"true\" : \"false\"}\n              data-has-shell-footer={shellFooters.length > 0 ? \"true\" : \"false\"}\n              className={sidebarShellClassNames({ className })}\n              initial={false}\n            >\n              {skipLinkChildren.length > 0 ? (\n                skipLinkChildren\n              ) : (\n                <SidebarShellSkipLink />\n              )}\n              {side === \"left\"\n                ? [...navigation, frame]\n                : [frame, ...navigation]}\n              {shellFooters}\n            </motionElement.div>\n          </MotionConfig>\n        </SidebarShellContext.Provider>\n      </SidebarProvider>\n    );\n  },\n);\n\nSidebarShell.displayName = \"SidebarShell\";\n"
    },
    {
      "path": "packages/components/src/components/sidebar-shell/index.ts",
      "type": "registry:file",
      "target": "~/components/dethink/components/sidebar-shell/index.ts",
      "content": "export {\n  SidebarShell,\n  SidebarShellFooter,\n  SidebarShellHeader,\n  SidebarShellMain,\n  SidebarShellNavigation,\n  SidebarShellSkipLink,\n  getSidebarShellMotionConfig,\n  sidebarShellClassNames,\n  sidebarShellFooterClassNames,\n  sidebarShellFrameClassNames,\n  sidebarShellHeaderClassNames,\n  sidebarShellMainClassNames,\n  sidebarShellNavigationClassNames,\n  sidebarShellSkipLinkClassNames,\n  type SidebarShellChrome,\n  type SidebarShellFooterProps,\n  type SidebarShellHeaderProps,\n  type SidebarShellLayout,\n  type SidebarShellMainProps,\n  type SidebarShellMotionConfig,\n  type SidebarShellNavigationProps,\n  type SidebarShellProps,\n  type SidebarShellSkipLinkProps,\n} from \"./sidebar-shell\";\n"
    },
    {
      "path": "packages/components/src/utils/cn.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/cn.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"
    },
    {
      "path": "packages/components/src/utils/sidebar-shell-part.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/sidebar-shell-part.ts",
      "content": "import { isValidElement, type ReactNode } from \"react\";\n\ntype SidebarShellPartName =\n  \"Navigation\" | \"Header\" | \"Main\" | \"Footer\" | \"SkipLink\";\nconst SIDEBAR_SHELL_PART = Symbol.for(\"@dethink/sidebar-shell.part\");\n\nexport function markSidebarShellPart(\n  component: unknown,\n  partName: SidebarShellPartName,\n) {\n  Object.defineProperty(component, SIDEBAR_SHELL_PART, {\n    configurable: true,\n    value: partName,\n  });\n}\n\nexport function getSidebarShellPart(child: ReactNode) {\n  if (!isValidElement(child) || typeof child.type === \"string\")\n    return undefined;\n  return (child.type as { [SIDEBAR_SHELL_PART]?: SidebarShellPartName })[\n    SIDEBAR_SHELL_PART\n  ];\n}\n"
    }
  ]
}
