{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "eye",
  "type": "registry:component",
  "title": "eye",
  "description": "Animated eye icon for Vue",
  "author": "Aniket Pawar <pawaraniket508@gmail.com>",
  "registryDependencies": [],
  "dependencies": [
    "motion-v"
  ],
  "files": [
    {
      "path": "src/icons/eye.vue",
      "type": "registry:component",
      "target": "~/src/components/heroicons-animated/eye.vue",
      "content": "<template>\n  <div\n    :class=\"props.class\"\n    @mouseenter=\"handleMouseEnter\"\n    @mouseleave=\"handleMouseLeave\"\n    v-bind=\"$attrs\"\n  >\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      :width=\"props.size\"\n      :height=\"props.size\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      :stroke=\"props.color\"\n      :stroke-width=\"props.strokeWidth\"\n      stroke-linecap=\"round\"\n      stroke-linejoin=\"round\"\n    >\n      <path\n        ref=\"irisRef\"\n        d=\"M2.03555 12.3224C1.96647 12.1151 1.9664 11.8907 2.03536 11.6834C3.42372 7.50972 7.36079 4.5 12.0008 4.5C16.6387 4.5 20.5742 7.50692 21.9643 11.6776C22.0334 11.8849 22.0335 12.1093 21.9645 12.3166C20.5761 16.4903 16.6391 19.5 11.9991 19.5C7.36119 19.5 3.42564 16.4931 2.03555 12.3224Z\"\n        style=\"transform-origin: 50% 50%\"\n      />\n      <path\n        ref=\"pupilRef\"\n        d=\"M15 12C15 13.6569 13.6569 15 12 15C10.3431 15 9 13.6569 9 12C9 10.3431 10.3431 9 12 9C13.6569 9 15 10.3431 15 12Z\"\n        style=\"transform-origin: 50% 50%\"\n      />\n    </svg>\n  </div>\n</template>\n\n<script lang=\"ts\">\n  export default {\n    name: \"EyeIcon\",\n  };\n</script>\n\n<script setup lang=\"ts\">\n  import { useMotion } from \"../motion\";\n  import { ref } from \"vue\";\n\n  export interface Props {\n    size?: number;\n    class?: string;\n    color?: string;\n    strokeWidth?: number | string;\n  }\n\n  const props = withDefaults(defineProps<Props>(), {\n    size: 28,\n    color: \"currentColor\",\n    strokeWidth: 1.5,\n  });\n\n  // Match React: iris scaleY [1, 0.1, 1], opacity [1, 0.3, 1]; pupil scale [1, 0.3, 1], opacity [1, 0.3, 1]; 0.4s easeInOut\n  const irisVariants = {\n    normal: { scaleY: 1, opacity: 1 },\n    animate: {\n      scaleY: [1, 0.1, 1],\n      opacity: [1, 0.3, 1],\n      transition: { duration: 0.4, ease: \"easeInOut\" },\n    },\n  };\n  const pupilVariants = {\n    normal: { scale: 1, opacity: 1 },\n    animate: {\n      scale: [1, 0.3, 1],\n      opacity: [1, 0.3, 1],\n      transition: { duration: 0.4, ease: \"easeInOut\" },\n    },\n  };\n\n  const irisRef = ref<SVGPathElement | null>(null);\n  const pupilRef = ref<SVGPathElement | null>(null);\n  const irisMotion = useMotion(irisRef, {\n    initial: irisVariants.normal,\n    enter: irisVariants.normal,\n  });\n  const pupilMotion = useMotion(pupilRef, {\n    initial: pupilVariants.normal,\n    enter: pupilVariants.normal,\n  });\n\n  let isControlled = false;\n\n  const startAnimation = () => {\n    irisMotion.apply(irisVariants.animate);\n    pupilMotion.apply(pupilVariants.animate);\n  };\n\n  const stopAnimation = () => {\n    irisMotion.apply(irisVariants.normal);\n    pupilMotion.apply(pupilVariants.normal);\n  };\n\n  const handleMouseEnter = () => {\n    if (!isControlled) {\n      startAnimation();\n    }\n  };\n\n  const handleMouseLeave = () => {\n    if (!isControlled) {\n      stopAnimation();\n    }\n  };\n\n  const setControlled = (value: boolean) => {\n    isControlled = value;\n  };\n\n  defineExpose({\n    startAnimation,\n    stopAnimation,\n    setControlled,\n  });\n</script>\n"
    },
    {
      "path": "src/motion.ts",
      "type": "registry:component",
      "target": "~/src/components/motion.ts",
      "content": "import { animate } from \"motion-v\";\nimport { isRef, watch, type Ref } from \"vue\";\n\ntype MotionElement = Element | SVGElement;\ntype MotionTarget =\n  | MotionElement\n  | Ref<MotionElement | null | undefined>\n  | null\n  | undefined;\n\ntype MotionTransition = Record<string, unknown>;\ntype MotionValues = Record<string, unknown>;\n\nexport interface MotionVariant extends MotionValues {\n  transition?: MotionTransition;\n}\n\nexport interface UseMotionOptions {\n  initial?: MotionVariant;\n  enter?: MotionVariant;\n}\n\ninterface MotionControls {\n  stop?: () => void;\n}\n\nexport interface MotionInstance {\n  apply: (variant: MotionVariant) => void;\n  stop: () => void;\n}\n\nconst isDomElement = (value: unknown): value is MotionElement => {\n  if (typeof window === \"undefined\") {\n    return false;\n  }\n  return value instanceof Element;\n};\n\nconst resolveElement = (target: MotionTarget): MotionElement | null => {\n  const element = isRef(target) ? target.value : target;\n  if (!element) {\n    return null;\n  }\n  return isDomElement(element) ? element : null;\n};\n\nconst takeTransformOrigin = (value: unknown): string | null => {\n  if (typeof value === \"string\") {\n    return value;\n  }\n  if (Array.isArray(value) && value.length > 0) {\n    // biome-ignore lint/style/useAtIndex: ES2020 lib target for package type-check does not include Array.prototype.at.\n    const lastValue = value[value.length - 1];\n    if (typeof lastValue === \"string\") {\n      return lastValue;\n    }\n  }\n  return null;\n};\n\nconst extractAnimatableValues = (\n  element: MotionElement,\n  values: MotionValues\n): MotionValues => {\n  const animatableValues: MotionValues = { ...values };\n  const transformOrigin = takeTransformOrigin(values.transformOrigin);\n\n  if (transformOrigin && \"style\" in element) {\n    element.style.transformOrigin = transformOrigin;\n    animatableValues.transformOrigin = undefined;\n  }\n\n  return animatableValues;\n};\n\nconst runAnimation = (\n  element: MotionElement,\n  controlsRef: { current: MotionControls | null },\n  variant: MotionVariant,\n  instant = false\n): void => {\n  if (typeof window === \"undefined\") {\n    return;\n  }\n\n  const { transition, ...values } = variant;\n  const animatableValues = extractAnimatableValues(element, values);\n\n  if (Object.keys(animatableValues).length === 0) {\n    return;\n  }\n\n  controlsRef.current?.stop?.();\n\n  const animationOptions = instant\n    ? ({ duration: 0 } as MotionTransition)\n    : (transition ?? {});\n\n  controlsRef.current = animate(\n    element,\n    animatableValues as Record<string, unknown>,\n    animationOptions\n  ) as MotionControls;\n};\n\nexport const useMotion = (\n  target: MotionTarget,\n  options: UseMotionOptions = {}\n): MotionInstance => {\n  const controlsRef: { current: MotionControls | null } = { current: null };\n\n  const initialize = (element: MotionElement): void => {\n    if (options.initial) {\n      runAnimation(element, controlsRef, options.initial, true);\n      return;\n    }\n    if (options.enter) {\n      runAnimation(element, controlsRef, options.enter, true);\n    }\n  };\n\n  const resolvedAtSetup = resolveElement(target);\n  if (resolvedAtSetup) {\n    initialize(resolvedAtSetup);\n  }\n\n  if (isRef(target)) {\n    watch(\n      () => target.value,\n      (element) => {\n        if (isDomElement(element)) {\n          initialize(element);\n        }\n      },\n      { immediate: true }\n    );\n  }\n\n  const apply = (variant: MotionVariant): void => {\n    if (typeof window === \"undefined\") {\n      return;\n    }\n    const element = resolveElement(target);\n    if (!element) {\n      return;\n    }\n    runAnimation(element, controlsRef, variant);\n  };\n\n  return {\n    apply,\n    stop: () => {\n      controlsRef.current?.stop?.();\n    },\n  };\n};\n"
    }
  ]
}