{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-xml",
  "type": "registry:ui",
  "title": "code-xml",
  "description": "Animated code xml icon for Vue",
  "dependencies": [
    "motion-v"
  ],
  "files": [
    {
      "path": "components/ui/code-xml.vue",
      "type": "registry:ui",
      "content": "<script setup lang=\"ts\">\nimport { motion, useAnimationControls } from 'motion-v'\nimport type { Variants } from 'motion-v'\nimport { useIconAnimation } from '../composables/useIconAnimation'\nimport type { AnimatedIconHandle } from '../types'\n\ndefineOptions({ inheritAttrs: false, name: 'CodeXmlIcon' })\n\nwithDefaults(\n  defineProps<{\n    size?: number\n  }>(),\n  { size: 28 },\n)\n\nconst CODE_DURATION = 1.12;\nconst CODE_TIMES = [\n  0, 0.05, 0.1, 0.16, 0.24, 0.34, 0.44, 0.56, 0.68, 0.76, 0.82, 0.87,\n  0.92, 0.97, 1,\n];\n\n// The source slash clears toward the bottom left, like the established off icons.\nconst departingSlashVariants: Variants = {\n  normal: {\n    transform: 'translate(0px, 0px)',\n    transition: { duration: 0.18, ease: [0.23, 1, 0.32, 1] },\n  },\n  animate: {\n    transform: [\n      'translate(0px, 0px)',\n      'translate(-0.4px, 0.4px)',\n      'translate(-1.4px, 1.4px)',\n      'translate(-5px, 5px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n      'translate(-24px, 24px)',\n    ],\n    transition: { duration: CODE_DURATION, ease: 'linear', times: CODE_TIMES },\n  },\n};\n\n// A replacement slash returns from the top right while the brackets stay anchored.\nconst arrivingSlashVariants: Variants = {\n  normal: {\n    transform: 'translate(24px, -24px)',\n    transition: { duration: 0.18, ease: [0.23, 1, 0.32, 1] },\n  },\n  animate: {\n    transform: [\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(24px, -24px)',\n      'translate(18px, -18px)',\n      'translate(8px, -8px)',\n      'translate(1.6px, -1.6px)',\n      'translate(-0.65px, 0.65px)',\n      'translate(0px, 0px)',\n    ],\n    transition: { duration: CODE_DURATION, ease: 'linear', times: CODE_TIMES },\n  },\n};\n\nconst generatedGeometryVariants: Variants = {\n  normal: { visibility: 'hidden', transition: { duration: 0 } },\n  animate: { visibility: 'visible', transition: { duration: 0 } },\n};\n\nconst controls = useAnimationControls()\nconst { onMouseEnter, onMouseLeave, startAnimation, stopAnimation } = useIconAnimation({\n  controls,\n  loops: false,\n})\n\ndefineExpose<AnimatedIconHandle>({ startAnimation, stopAnimation })\n</script>\n\n<template>\n  <div class=\"hia-icon\" @mouseenter=\"onMouseEnter\" @mouseleave=\"onMouseLeave\" v-bind=\"$attrs\">\n          <svg xmlns=\"http://www.w3.org/2000/svg\" :width=\"size\" :height=\"size\" viewBox=\"0 0 24 24\" fill=\"none\" overflow=\"hidden\">\n            <motion.path d=\"M15 4L9 20\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" :variants=\"departingSlashVariants\" :animate=\"controls\" initial=\"normal\" />\n            <path d=\"M5.99997 16C5.99997 16 2.00001 13.054 2 12C1.99999 10.9459 6 8 6 8\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" />\n            <path d=\"M18 8C18 8 22 10.946 22 12C22 13.0541 18 16 18 16\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" />\n            <motion.g :variants=\"generatedGeometryVariants\" :animate=\"controls\" initial=\"normal\">\n              <motion.path d=\"M15 4L9 20\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" :variants=\"arrivingSlashVariants\" :animate=\"controls\" initial=\"normal\" />\n            </motion.g>\n          </svg>\n        </div>\n</template>\n"
    },
    {
      "path": "composables/useIconAnimation.ts",
      "type": "registry:lib",
      "content": "import { ref, toValue, type MaybeRefOrGetter } from 'vue'\nimport type { AnimatedIconHandle } from '../types'\n\nexport type IconPose = 'normal' | 'animate'\n\ntype AnimationControls = {\n  set: (variant: IconPose | Record<string, unknown>) => void\n  start: (variant: IconPose | Record<string, unknown>) => Promise<unknown>\n}\n\nexport function useReducedMotionFlag(\n  reduced?: MaybeRefOrGetter<boolean | undefined>,\n) {\n  if (typeof window === 'undefined') return () => false\n  return () => {\n    const override = reduced === undefined ? undefined : toValue(reduced)\n    if (override !== undefined) return override\n    return window.matchMedia('(prefers-reduced-motion: reduce)').matches\n  }\n}\n\nexport function useIconAnimation(options: {\n  controls: AnimationControls\n  loops?: boolean\n}): AnimatedIconHandle & {\n  onMouseEnter: () => void\n  onMouseLeave: () => void\n} {\n  const { controls, loops = false } = options\n  const isPlaying = ref(false)\n  let run = 0\n\n  const prefersReduced = () =>\n    typeof window !== 'undefined' &&\n    window.matchMedia('(prefers-reduced-motion: reduce)').matches\n\n  async function startAnimation() {\n    if (prefersReduced() || isPlaying.value) return\n\n    isPlaying.value = true\n    const current = ++run\n    controls.set('normal')\n    await controls.start('animate')\n    if (run === current) isPlaying.value = false\n  }\n\n  function stopAnimation() {\n    if (!loops) return\n    run += 1\n    isPlaying.value = false\n    void controls.start('normal')\n  }\n\n  return {\n    startAnimation,\n    stopAnimation,\n    onMouseEnter: () => {\n      void startAnimation()\n    },\n    onMouseLeave: () => {\n      stopAnimation()\n    },\n  }\n}\n"
    },
    {
      "path": "types/animated-icon.ts",
      "type": "registry:lib",
      "content": "export interface AnimatedIconHandle {\n  startAnimation: () => void\n  stopAnimation: () => void\n}\n\nexport interface AnimatedIconProps {\n  size?: number\n}\n"
    }
  ]
}
