{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "icons-core",
  "title": "Icons Core",
  "description": "Shared animation contract, pure frame-to-phase timeline, and SVG path-draw helpers for remocn icons.",
  "dependencies": ["remotion", "@remotion/paths"],
  "files": [
    {
      "path": "registry/remocn-icons/icons-core/index.ts",
      "content": "import { evolvePath } from \"@remotion/paths\";\nimport { spring, useCurrentFrame, useVideoConfig } from \"remotion\";\n\nexport interface IconAnimationProps {\n  animation?: \"draw\" | \"action\" | \"both\";\n  loop?: boolean;\n  speed?: number;\n  size?: number;\n  color?: string;\n  strokeWidth?: number;\n  className?: string;\n}\n\nexport interface IconTimings {\n  drawDurationInFrames?: number;\n  actionDelayInFrames?: number;\n  actionDurationInFrames?: number;\n  loop?: boolean;\n}\n\nexport interface IconTimeline {\n  drawProgress: number;\n  scaleIn: number;\n  actionFrame: number;\n  actionProgress: number;\n  cycleIndex: number;\n}\n\nfunction clamp01(t: number): number {\n  return t < 0 ? 0 : t > 1 ? 1 : t;\n}\n\nfunction easeOut(t: number): number {\n  return 1 - (1 - t) ** 3;\n}\n\nexport function iconTimeline(\n  frame: number,\n  fps: number,\n  props: IconAnimationProps,\n  timings: IconTimings,\n): IconTimeline {\n  const animation = props.animation ?? \"both\";\n  const loop = props.loop ?? timings.loop ?? false;\n  const drawDuration = timings.drawDurationInFrames ?? 14;\n  const actionDelay = timings.actionDelayInFrames ?? 2;\n  const actionDuration = timings.actionDurationInFrames ?? 20;\n\n  const drawProgress =\n    animation === \"action\"\n      ? 1\n      : easeOut(clamp01(drawDuration > 0 ? frame / drawDuration : 1));\n\n  const scaleIn = clamp01(\n    spring({\n      frame,\n      fps,\n      config: { damping: 18, stiffness: 220, mass: 0.7 },\n      durationInFrames: Math.max(1, drawDuration),\n    }),\n  );\n\n  const actionStart = animation === \"action\" ? 0 : drawDuration + actionDelay;\n  const sinceStart = frame - actionStart;\n\n  if (animation === \"draw\" || sinceStart < 0) {\n    return {\n      drawProgress,\n      scaleIn,\n      actionFrame: sinceStart,\n      actionProgress: 0,\n      cycleIndex: 0,\n    };\n  }\n\n  if (actionDuration <= 0) {\n    return {\n      drawProgress,\n      scaleIn,\n      actionFrame: sinceStart,\n      actionProgress: 1,\n      cycleIndex: 0,\n    };\n  }\n\n  if (loop) {\n    const cycleIndex = Math.floor(sinceStart / actionDuration);\n    const local = sinceStart - cycleIndex * actionDuration;\n    return {\n      drawProgress,\n      scaleIn,\n      actionFrame: local,\n      actionProgress: local / actionDuration,\n      cycleIndex,\n    };\n  }\n\n  return {\n    drawProgress,\n    scaleIn,\n    actionFrame: sinceStart,\n    actionProgress: clamp01(sinceStart / actionDuration),\n    cycleIndex: 0,\n  };\n}\n\nexport function useIconAnimation(\n  props: IconAnimationProps,\n  timings: IconTimings,\n): IconTimeline {\n  const frame = useCurrentFrame();\n  const { fps } = useVideoConfig();\n  const speed = props.speed ?? 1;\n  return iconTimeline(frame * speed, fps, props, timings);\n}\n\nexport function staggeredProgress(\n  progress: number,\n  index: number,\n  count: number,\n  overlap = 0.5,\n): number {\n  if (count <= 1) return clamp01(progress);\n  const o = clamp01(overlap);\n  const width = 1 / (count - (count - 1) * o);\n  const start = index * width * (1 - o);\n  return clamp01((progress - start) / width);\n}\n\nexport function drawnPathProps(\n  d: string,\n  progress: number,\n): { strokeDasharray: string; strokeDashoffset: number } {\n  return evolvePath(clamp01(progress), d);\n}\n",
      "type": "registry:lib",
      "target": "lib/remocn-icons/index.ts"
    }
  ],
  "type": "registry:lib"
}
