{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "clipboard-document",
  "type": "registry:component",
  "title": "clipboard-document",
  "description": "Animated clipboard-document icon for Vue",
  "author": "Aniket Pawar <pawaraniket508@gmail.com>",
  "registryDependencies": [],
  "dependencies": [
    "motion-v"
  ],
  "files": [
    {
      "path": "src/icons/clipboard-document.vue",
      "type": "registry:component",
      "target": "~/src/components/heroicons-animated/clipboard-document.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=\"clipboardRef\"\n        d=\"M8.25 7.5V6.10822C8.25 4.97324 9.09499 4.01015 10.2261 3.91627C10.5994 3.88529 10.9739 3.85858 11.3495 3.83619M15.75 18H18C19.2426 18 20.25 16.9926 20.25 15.75V6.10822C20.25 4.97324 19.405 4.01015 18.2739 3.91627C17.9006 3.88529 17.5261 3.85858 17.1505 3.83619M17.1505 3.83619C16.8672 2.91757 16.0116 2.25 15 2.25H13.5C12.4884 2.25 11.6328 2.91757 11.3495 3.83619M17.1505 3.83619C17.2152 4.04602 17.25 4.26894 17.25 4.5V5.25H11.25V4.5C11.25 4.26894 11.2848 4.04602 11.3495 3.83619\"\n      />\n      <g ref=\"documentRef\">\n        <path\n          d=\"M6.75 7.5H4.875C4.25368 7.5 3.75 8.00368 3.75 8.625V20.625C3.75 21.2463 4.25368 21.75 4.875 21.75H14.625C15.2463 21.75 15.75 21.2463 15.75 20.625V16.5C15.75 11.5294 11.7206 7.5 6.75 7.5Z\"\n        />\n        <path\n          d=\"M15.75 18.75V16.875C15.75 15.011 14.239 13.5 12.375 13.5H10.875C10.2537 13.5 9.75 12.9963 9.75 12.375V10.875C9.75 9.01104 8.23896 7.5 6.375 7.5H5.25\"\n        />\n      </g>\n    </svg>\n  </div>\n</template>\n\n<script lang=\"ts\">\n  export default {\n    name: \"ClipboardDocumentIcon\",\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 clipboardVariants = {\n    normal: {\n      y: 0,\n    },\n    animate: {\n      y: [0, -1, 0],\n      transition: {\n        duration: 0.3,\n        ease: \"easeInOut\",\n      },\n    },\n  };\n\n  const documentVariants = {\n    normal: {\n      x: 0,\n      y: 0,\n      opacity: 1,\n    },\n    animate: {\n      x: [-4, 0],\n      y: [4, 0],\n      opacity: [0, 1],\n      transition: {\n        duration: 0.3,\n        ease: \"easeOut\",\n      },\n    },\n  };\n\n  const clipboardRef = ref<SVGPathElement | null>();\n  const documentRef = ref<SVGGElement | null>();\n\n  const clipboardMotion = useMotion(clipboardRef, {\n    initial: clipboardVariants.normal,\n    enter: clipboardVariants.normal,\n  });\n  const documentMotion = useMotion(documentRef, {\n    initial: documentVariants.normal,\n    enter: documentVariants.normal,\n  });\n\n  let isControlled = false;\n\n  const startAnimation = () => {\n    clipboardMotion.apply(clipboardVariants.animate);\n    documentMotion.apply(documentVariants.animate);\n  };\n\n  const stopAnimation = () => {\n    clipboardMotion.apply(clipboardVariants.normal);\n    documentMotion.apply(documentVariants.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"
    }
  ]
}