{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "clipboard",
  "type": "registry:component",
  "title": "clipboard",
  "description": "Animated clipboard icon for Vue",
  "author": "Aniket Pawar <pawaraniket508@gmail.com>",
  "registryDependencies": [],
  "dependencies": [
    "motion-v"
  ],
  "files": [
    {
      "path": "src/icons/clipboard.vue",
      "type": "registry:component",
      "target": "~/src/components/heroicons-animated/clipboard.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=\"clipRef\"\n        d=\"M15.6657 3.88789C15.3991 2.94272 14.5305 2.25 13.5 2.25H10.5C9.46954 2.25 8.60087 2.94272 8.33426 3.88789M15.6657 3.88789C15.7206 4.0825 15.75 4.28782 15.75 4.5V4.5C15.75 4.91421 15.4142 5.25 15 5.25H9C8.58579 5.25 8.25 4.91421 8.25 4.5V4.5C8.25 4.28782 8.27937 4.0825 8.33426 3.88789\"\n        style=\"transform-origin: 50% 0%\"\n      />\n      <path\n        ref=\"boardRef\"\n        d=\"M15.6657 3.88789C16.3119 3.93668 16.9545 3.99828 17.5933 4.07241C18.6939 4.20014 19.5 5.149 19.5 6.25699V19.5C19.5 20.7426 18.4926 21.75 17.25 21.75H6.75C5.50736 21.75 4.5 20.7426 4.5 19.5V6.25699C4.5 5.149 5.30608 4.20014 6.40668 4.07241C7.04547 3.99828 7.68808 3.93668 8.33426 3.88789\"\n      />\n    </svg>\n  </div>\n</template>\n\n<script lang=\"ts\">\n  export default {\n    name: \"ClipboardIcon\",\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  const clipVariants = {\n    normal: { scaleY: 1, translateY: 0 },\n    animate: {\n      scaleY: [1, 0.8, 1],\n      translateY: [0, 0.5, 0],\n      transition: { duration: 0.3, ease: \"easeInOut\" },\n    },\n  };\n\n  const boardVariants = {\n    normal: { translateY: 0 },\n    animate: {\n      translateY: [0, -0.5, 0],\n      transition: { duration: 0.3, ease: \"easeInOut\" },\n    },\n  };\n\n  const clipRef = ref<SVGPathElement | null>();\n  const boardRef = ref<SVGPathElement | null>();\n  const motionClip = useMotion(clipRef, {\n    initial: clipVariants.normal,\n    enter: clipVariants.normal,\n  });\n  const motionBoard = useMotion(boardRef, {\n    initial: boardVariants.normal,\n    enter: boardVariants.normal,\n  });\n\n  let isControlled = false;\n\n  const startAnimation = () => {\n    motionClip.apply(clipVariants.animate);\n    motionBoard.apply(boardVariants.animate);\n  };\n\n  const stopAnimation = () => {\n    motionClip.apply(clipVariants.normal);\n    motionBoard.apply(boardVariants.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({ startAnimation, stopAnimation, setControlled });\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"
    }
  ]
}