{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "panel",
  "title": "Panel",
  "description": "Ink-framed panel with SVG mitered polygon border, optional slanted gutter edge, and automatic or explicit cut number in reading order.",
  "registryDependencies": [
    "https://frame12.dev/r/frame12-styles.json",
    "https://frame12.dev/r/use-on-twos.json",
    "https://frame12.dev/r/scene.json"
  ],
  "files": [
    {
      "path": "ui/panel.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { useSize } from '@/hooks/use-on-twos';\nimport { resolveAreaProps } from './scene';\n\n// Bundlers (Next.js, webpack, Vite) statically replace `process.env.NODE_ENV`. Declared locally so\n// consumers without @types/node (e.g. Vite's react-ts template) still type-check this file.\ndeclare const process: { env: { NODE_ENV?: string } };\n\nexport type PanelShape = 'rect' | 'slant-bottom' | 'slant-top';\nexport type PanelVariant = 'expressive' | 'quiet';\n\nexport interface PanelProps extends React.HTMLAttributes<HTMLElement> {\n  cut?: string | false;\n  shape?: PanelShape;\n  variant?: PanelVariant;\n  label?: string;\n  area?: string;\n  children?: React.ReactNode;\n}\n\nconst INACTIVE_SIZE_REF: { readonly current: HTMLElement | null } = { current: null };\n\nconst PANEL_VARIANT_CTX_KEY = Symbol.for('frame12.PanelVariantContext');\nconst globalRegistry = globalThis as unknown as Record<\n  symbol,\n  React.Context<PanelVariant | undefined> | undefined\n>;\nconst PanelVariantContext = (globalRegistry[PANEL_VARIANT_CTX_KEY] ??= React.createContext<\n  PanelVariant | undefined\n>(undefined));\n\nexport function usePanelVariantContext(): PanelVariant | undefined {\n  return React.useContext(PanelVariantContext);\n}\n\nexport const Panel = React.forwardRef<HTMLElement, PanelProps>(function Panel(\n  { cut, shape = 'rect', variant, className = '', label, area, style, children, ...rest },\n  forwardedRef,\n) {\n  const inheritedVariant = React.useContext(PanelVariantContext);\n  const resolvedVariant: PanelVariant = variant ?? inheritedVariant ?? 'expressive';\n  const innerRef = React.useRef<HTMLElement | null>(null);\n  const warnedCutRef = React.useRef<string | null>(null);\n  const isQuiet = resolvedVariant === 'quiet';\n  const showSvgFrame = !isQuiet || shape !== 'rect';\n  const setRefs = React.useCallback(\n    (node: HTMLElement | null) => {\n      innerRef.current = node;\n      if (typeof forwardedRef === 'function') {\n        forwardedRef(node);\n      } else if (forwardedRef) {\n        (forwardedRef as React.MutableRefObject<HTMLElement | null>).current = node;\n      }\n    },\n    [forwardedRef],\n  );\n\n  React.useEffect(() => {\n    if (process.env.NODE_ENV !== 'production') {\n      if (typeof cut === 'string' && cut.length > 0 && warnedCutRef.current !== cut) {\n        const sheet = innerRef.current?.closest('.f12-sheet');\n        if (sheet && sheet.hasAttribute('data-autocut')) {\n          warnedCutRef.current = cut;\n          console.warn(\n            `[FRAME/12 Panel] Explicit cut \"${cut}\" used inside <Sheet autoCut>. Cut numbers are automatic inside <Sheet autoCut>; remove the cut prop or use cut={false}.`,\n          );\n        }\n      }\n    }\n  }, [cut]);\n\n  const { w, h } = useSize(showSvgFrame ? innerRef : INACTIVE_SIZE_REF);\n  const s = 1.25; // half of 2.5px stroke\n  const d = 16; // slant rise in px\n  let pts: string;\n  if (shape === 'slant-bottom') {\n    pts = `${s},${s} ${w - s},${s} ${w - s},${h - s - d} ${s},${h - s}`;\n  } else if (shape === 'slant-top') {\n    pts = `${s},${s + d} ${w - s},${s} ${w - s},${h - s} ${s},${h - s}`;\n  } else {\n    pts = `${s},${s} ${w - s},${s} ${w - s},${h - s} ${s},${h - s}`;\n  }\n\n  const ssrPts =\n    shape === 'slant-bottom'\n      ? '0.35,0.35 99.65,0.35 99.65,93.2 0.35,99.65'\n      : shape === 'slant-top'\n        ? '0.35,6.8 99.65,0.35 99.65,99.65 0.35,99.65'\n        : '0.35,0.35 99.65,0.35 99.65,99.65 0.35,99.65';\n\n  const variantClass = isQuiet ? ' f12-panel-quiet' : '';\n  const areaProps = resolveAreaProps(area, style);\n\n  return (\n    <section\n      ref={setRefs}\n      className={`f12-panel f12-${shape}${variantClass}${className ? ` ${className}` : ''}`}\n      data-variant={isQuiet ? 'quiet' : undefined}\n      data-area={areaProps['data-area']}\n      aria-label={label}\n      style={areaProps.style}\n      {...rest}\n    >\n      {showSvgFrame &&\n        (w > 0 ? (\n          <svg className=\"f12-panel-frame\" width={w} height={h} aria-hidden=\"true\">\n            <polygon points={pts} />\n          </svg>\n        ) : (\n          <svg\n            className=\"f12-panel-frame\"\n            viewBox=\"0 0 100 100\"\n            preserveAspectRatio=\"none\"\n            aria-hidden=\"true\"\n          >\n            <polygon vectorEffect=\"non-scaling-stroke\" points={ssrPts} />\n          </svg>\n        ))}\n      {typeof cut === 'string' && cut.length > 0 ? (\n        <span className=\"f12-cut\" aria-hidden=\"true\">\n          {cut}\n        </span>\n      ) : cut === undefined && !isQuiet ? (\n        <span className=\"f12-cut\" data-autocut=\"\" aria-hidden=\"true\" />\n      ) : null}\n      <div className=\"f12-panel-body\">{children}</div>\n    </section>\n  );\n});\n",
      "type": "registry:ui",
      "target": "components/frame12/panel.tsx"
    }
  ],
  "type": "registry:ui"
}