{"$schema":"https://ui.shadcn.com/schema/registry-item.json","author":"Eduardo Calvo <educlopez93@gmail.com>","css":{},"dependencies":["motion"],"description":"A MorphIcon component for SmoothUI.","devDependencies":[],"files":[{"content":"\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { motion, useReducedMotion } from \"motion/react\";\n\nexport const MORPH_ICON_VARIANTS = [\n  \"sidebar\",\n  \"list\",\n  \"grid\",\n  \"compact\",\n  \"menu\",\n  \"search\",\n  \"play\",\n  \"check\",\n] as const;\n\nexport type MorphIconVariant = (typeof MORPH_ICON_VARIANTS)[number];\n\nexport type MorphIconProps = {\n  active?: boolean;\n  className?: string;\n  color?: string;\n  duration?: number;\n  label?: string;\n  size?: number;\n  strokeWidth?: number;\n  variant: MorphIconVariant;\n};\n\nconst DEFAULT_SIZE = 24;\nconst DEFAULT_STROKE_WIDTH = 2;\nconst DEFAULT_DURATION = 0.3;\nconst MOVEMENT_EASE: [number, number, number, number] = [\n  0.645, 0.045, 0.355, 1,\n];\nconst INSTANT = { duration: 0 };\n\ntype Transition = { duration: number; ease?: [number, number, number, number] };\n\nconst SidebarGlyph = ({\n  active,\n  transition,\n}: {\n  active: boolean;\n  transition: Transition;\n}) => (\n  <>\n    <rect height=\"18\" rx=\"2\" width=\"18\" x=\"3\" y=\"3\" />\n    <motion.line\n      animate={{\n        x1: active ? 15 : 9,\n        x2: active ? 15 : 9,\n        y1: 3,\n        y2: 21,\n      }}\n      transition={transition}\n    />\n  </>\n);\n\nconst ListGlyph = ({\n  active,\n  transition,\n}: {\n  active: boolean;\n  transition: Transition;\n}) => (\n  <>\n    <motion.rect\n      animate={\n        active ? { height: 14, rx: 1, y: 5 } : { height: 2, rx: 1, y: 11 }\n      }\n      transition={transition}\n      width=\"2\"\n      x=\"2\"\n    />\n    {[7, 12, 17].map((y) => (\n      <motion.line\n        animate={{ x1: active ? 8 : 4, x2: 20, y1: y, y2: y }}\n        key={y}\n        transition={transition}\n      />\n    ))}\n  </>\n);\n\nconst GRID_CELLS = [\n  { x: 4, y: 4 },\n  { x: 13, y: 4 },\n  { x: 4, y: 13 },\n  { x: 13, y: 13 },\n];\n\nconst GridGlyph = ({\n  active,\n  transition,\n}: {\n  active: boolean;\n  transition: Transition;\n}) => (\n  <>\n    {GRID_CELLS.map((cell) => (\n      <motion.rect\n        animate={\n          active\n            ? { height: 6, rx: 3, width: 6, x: cell.x + 0.5, y: cell.y + 0.5 }\n            : { height: 7, rx: 1, width: 7, x: cell.x, y: cell.y }\n        }\n        key={`${cell.x}-${cell.y}`}\n        transition={transition}\n      />\n    ))}\n  </>\n);\n\nconst COMPACT_SPREAD = [6, 12, 18];\nconst COMPACT_TIGHT = [9, 12, 15];\n\nconst CompactGlyph = ({\n  active,\n  transition,\n}: {\n  active: boolean;\n  transition: Transition;\n}) => (\n  <>\n    {COMPACT_SPREAD.map((y, index) => (\n      <motion.line\n        animate={{\n          x1: 4,\n          x2: 20,\n          y1: active ? COMPACT_TIGHT[index] : y,\n          y2: active ? COMPACT_TIGHT[index] : y,\n        }}\n        key={y}\n        transition={transition}\n      />\n    ))}\n  </>\n);\n\nconst MenuGlyph = ({\n  active,\n  transition,\n}: {\n  active: boolean;\n  transition: Transition;\n}) => (\n  <>\n    <motion.line\n      animate={\n        active\n          ? { x1: 6, x2: 18, y1: 6, y2: 18 }\n          : { x1: 4, x2: 20, y1: 6, y2: 6 }\n      }\n      transition={transition}\n    />\n    <motion.line\n      animate={{ opacity: active ? 0 : 1, x1: 4, x2: 20, y1: 12, y2: 12 }}\n      transition={transition}\n    />\n    <motion.line\n      animate={\n        active\n          ? { x1: 6, x2: 18, y1: 18, y2: 6 }\n          : { x1: 4, x2: 20, y1: 18, y2: 18 }\n      }\n      transition={transition}\n    />\n  </>\n);\n\nconst SearchGlyph = ({\n  active,\n  transition,\n}: {\n  active: boolean;\n  transition: Transition;\n}) => (\n  <>\n    <motion.circle\n      animate={{ cx: 10, cy: 10, r: active ? 7 : 6 }}\n      transition={transition}\n    />\n    <motion.line\n      animate={\n        active\n          ? { x1: 15, x2: 20.5, y1: 15, y2: 20.5 }\n          : { x1: 14.5, x2: 19, y1: 14.5, y2: 19 }\n      }\n      transition={transition}\n    />\n  </>\n);\n\nconst PLAY_PATH = \"M8,5 L8,19 L17,12 L17,12 Z\";\nconst STOP_PATH = \"M7,7 L7,17 L17,17 L17,7 Z\";\n\nconst PlayGlyph = ({\n  active,\n  color,\n  transition,\n}: {\n  active: boolean;\n  color: string;\n  transition: Transition;\n}) => (\n  <motion.path\n    animate={{ d: active ? STOP_PATH : PLAY_PATH }}\n    fill={color}\n    stroke=\"none\"\n    transition={transition}\n  />\n);\n\nconst CheckGlyph = ({\n  active,\n  color,\n  transition,\n}: {\n  active: boolean;\n  color: string;\n  transition: Transition;\n}) => (\n  <>\n    <rect height=\"16\" rx=\"4\" width=\"16\" x=\"4\" y=\"4\" />\n    <motion.rect\n      animate={{ opacity: active ? 1 : 0 }}\n      fill={color}\n      height=\"16\"\n      rx=\"4\"\n      stroke=\"none\"\n      transition={transition}\n      width=\"16\"\n      x=\"4\"\n      y=\"4\"\n    />\n    <motion.path\n      animate={{\n        opacity: active ? 1 : 0,\n        pathLength: active ? 1 : 0,\n      }}\n      d=\"M7 12.5 L10.5 16 L17 8\"\n      stroke=\"var(--color-background)\"\n      transition={transition}\n    />\n  </>\n);\n\nexport default function MorphIcon({\n  variant,\n  active = false,\n  size = DEFAULT_SIZE,\n  strokeWidth = DEFAULT_STROKE_WIDTH,\n  color = \"currentColor\",\n  duration = DEFAULT_DURATION,\n  label,\n  className,\n}: MorphIconProps) {\n  const shouldReduceMotion = useReducedMotion();\n  const transition: Transition = shouldReduceMotion\n    ? INSTANT\n    : { duration, ease: MOVEMENT_EASE };\n\n  return (\n    <svg\n      aria-hidden={label ? undefined : \"true\"}\n      className={cn(\"shrink-0\", className)}\n      fill=\"none\"\n      height={size}\n      role={label ? \"img\" : undefined}\n      stroke={color}\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      strokeWidth={strokeWidth}\n      viewBox=\"0 0 24 24\"\n      width={size}\n    >\n      {label ? <title>{label}</title> : null}\n      {variant === \"sidebar\" && (\n        <SidebarGlyph active={active} transition={transition} />\n      )}\n      {variant === \"list\" && (\n        <ListGlyph active={active} transition={transition} />\n      )}\n      {variant === \"grid\" && (\n        <GridGlyph active={active} transition={transition} />\n      )}\n      {variant === \"compact\" && (\n        <CompactGlyph active={active} transition={transition} />\n      )}\n      {variant === \"menu\" && (\n        <MenuGlyph active={active} transition={transition} />\n      )}\n      {variant === \"search\" && (\n        <SearchGlyph active={active} transition={transition} />\n      )}\n      {variant === \"play\" && (\n        <PlayGlyph active={active} color={color} transition={transition} />\n      )}\n      {variant === \"check\" && (\n        <CheckGlyph active={active} color={color} transition={transition} />\n      )}\n    </svg>\n  );\n}\n","path":"index.tsx","target":"components/smoothui/morph-icon/index.tsx","type":"registry:ui"}],"name":"morph-icon","registryDependencies":[],"title":"Morph Icon","type":"registry:ui"}