{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "accordion-unfold",
  "title": "Accordion Unfold",
  "description": "A tight paper zigzag unfolds sideways into a flat card with the logo printed across it.",
  "dependencies": ["remotion"],
  "files": [
    {
      "path": "registry/remocn/accordion-unfold/index.tsx",
      "content": "\"use client\";\n\nimport type React from \"react\";\nimport {\n  AbsoluteFill,\n  interpolate,\n  spring,\n  useCurrentFrame,\n  useVideoConfig,\n} from \"remotion\";\n\nexport type AccordionUnfoldProps = {\n  /** Lockup printed across the card. Use a color that reads on `color`. Falls back to a placeholder \"remocn\" lockup. */\n  children?: React.ReactNode;\n  /** Number of vertical pleats. */\n  panels?: number;\n  /** Paper color of the card. */\n  color?: string;\n  /** Darkness of the panels facing away from the light, 0 to 1. */\n  shade?: number;\n  backgroundColor?: string;\n  /** Fold angle of each pleat at the start, in degrees. */\n  foldAngle?: number;\n  speed?: number;\n};\n\nexport const accordionUnfoldDefaults = {\n  panels: 6,\n  color: \"#FFFFFF\",\n  shade: 0.55,\n  backgroundColor: \"#111111\",\n  foldAngle: 82,\n  speed: 1,\n};\n\nconst START = 4;\nconst clamp = {\n  extrapolateLeft: \"clamp\" as const,\n  extrapolateRight: \"clamp\" as const,\n};\n\nconst PLACEHOLDER_FONT =\n  \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, Helvetica, Arial, sans-serif\";\n\n// Neutral lockup shown when no children are passed.\nfunction PlaceholderLockup({\n  mark,\n  dot,\n  text,\n  scale = 1,\n}: {\n  mark: string;\n  dot: string;\n  text: string;\n  scale?: number;\n}) {\n  return (\n    <div style={{ display: \"flex\", alignItems: \"center\", gap: 28 * scale }}>\n      <div\n        style={{\n          width: 120 * scale,\n          height: 120 * scale,\n          borderRadius: 32 * scale,\n          backgroundColor: mark,\n          display: \"flex\",\n          alignItems: \"center\",\n          justifyContent: \"center\",\n        }}\n      >\n        <div\n          style={{\n            width: 36 * scale,\n            height: 36 * scale,\n            borderRadius: \"50%\",\n            backgroundColor: dot,\n          }}\n        />\n      </div>\n      <span\n        style={{\n          fontFamily: PLACEHOLDER_FONT,\n          fontSize: 104 * scale,\n          fontWeight: 800,\n          letterSpacing: \"-0.04em\",\n          color: text,\n        }}\n      >\n        remocn\n      </span>\n    </div>\n  );\n}\n\nexport function AccordionUnfold(props: AccordionUnfoldProps) {\n  const { children, panels, color, shade, backgroundColor, foldAngle, speed } =\n    { ...accordionUnfoldDefaults, ...props };\n  const frame = useCurrentFrame();\n  const { width, height, fps } = useVideoConfig();\n  const t = frame * Math.max(0, speed);\n  const n = Math.max(2, Math.round(panels));\n  const cardW = Math.round(Math.min(width * 0.66, height * 1.3));\n  const cardH = Math.round(Math.min(height * 0.4, cardW * 0.4));\n  const pw = cardW / n;\n\n  const open = spring({\n    frame: t - START,\n    fps,\n    config: { damping: 15, stiffness: 70, mass: 0.9 },\n  });\n  const theta = foldAngle * (1 - open);\n  const rad = (theta * Math.PI) / 180;\n  // Keep the pleated stack centered while its projected width grows.\n  const shift = (cardW - cardW * Math.cos(rad)) / 2;\n  const lift = interpolate(t, [0, START + 2], [0.92, 1], clamp);\n  const appear = interpolate(t, [0, 3], [0, 1], clamp);\n  const flat = Math.abs(theta) < 0.3;\n\n  const print = (offset: number) => (\n    <div\n      style={{\n        position: \"absolute\",\n        top: 0,\n        left: -offset,\n        width: cardW,\n        height: cardH,\n        display: \"flex\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n      }}\n    >\n      {children ?? (\n        <PlaceholderLockup\n          mark={backgroundColor}\n          dot={color}\n          text={backgroundColor}\n          scale={0.8}\n        />\n      )}\n    </div>\n  );\n\n  const panel = (i: number): React.ReactNode => {\n    if (i >= n) return null;\n    const angle = i === 0 ? theta : (i % 2 === 1 ? -2 : 2) * theta;\n    const facing = i % 2 === 0 ? 1 : -1;\n    const tilt = Math.abs(Math.sin(rad));\n    const darkness = facing > 0 ? shade * tilt : shade * 0.25 * tilt;\n    return (\n      <div\n        style={{\n          position: \"absolute\",\n          top: 0,\n          left: i === 0 ? 0 : pw,\n          width: pw,\n          height: cardH,\n          transformOrigin: \"0% 50%\",\n          transform: `rotateY(${angle}deg)`,\n          transformStyle: \"preserve-3d\",\n        }}\n      >\n        <div\n          style={{\n            position: \"absolute\",\n            inset: 0,\n            // A hair of bleed hides antialiased seams between pleats.\n            width: pw + 1,\n            overflow: \"hidden\",\n            backgroundColor: color,\n            backfaceVisibility: \"hidden\",\n          }}\n        >\n          {print(i * pw)}\n          <div\n            style={{\n              position: \"absolute\",\n              inset: 0,\n              background:\n                facing > 0\n                  ? `linear-gradient(90deg, rgba(0,0,0,${darkness * 0.6}), rgba(0,0,0,${darkness}))`\n                  : `linear-gradient(90deg, rgba(255,255,255,${0.12 * tilt}), rgba(0,0,0,${darkness}))`,\n            }}\n          />\n        </div>\n        {panel(i + 1)}\n      </div>\n    );\n  };\n\n  return (\n    <AbsoluteFill\n      style={{\n        backgroundColor,\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        perspective: cardW * 1.8,\n      }}\n    >\n      <div\n        style={{\n          position: \"relative\",\n          width: cardW,\n          height: cardH,\n          opacity: appear,\n          transform: `translateX(${shift}px) scale(${lift})`,\n          transformStyle: \"preserve-3d\",\n        }}\n      >\n        {flat ? (\n          <div\n            style={{\n              position: \"absolute\",\n              inset: 0,\n              backgroundColor: color,\n              overflow: \"hidden\",\n            }}\n          >\n            {print(0)}\n          </div>\n        ) : (\n          panel(0)\n        )}\n      </div>\n    </AbsoluteFill>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/accordion-unfold.tsx"
    }
  ],
  "type": "registry:component"
}
