{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "calculator",
  "type": "registry:component",
  "title": "calculator",
  "description": "Animated calculator icon for Vue",
  "author": "Aniket Pawar <pawaraniket508@gmail.com>",
  "registryDependencies": [],
  "dependencies": [
    "motion-v"
  ],
  "files": [
    {
      "path": "src/icons/calculator.vue",
      "type": "registry:component",
      "target": "~/src/components/heroicons-animated/calculator.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        d=\"M12 2.25C10.108 2.25 8.24156 2.35947 6.40668 2.57241C5.30608 2.70014 4.5 3.649 4.5 4.75699V19.5C4.5 20.7426 5.50736 21.75 6.75 21.75H17.25C18.4926 21.75 19.5 20.7426 19.5 19.5V4.75699C19.5 3.649 18.6939 2.70014 17.5933 2.57241C15.7584 2.35947 13.892 2.25 12 2.25Z\"\n      />\n      <path ref=\"screenRef\" d=\"M8.25 6H15.75V8.25H8.25V6Z\" />\n      <path ref=\"button0Ref\" d=\"M8.25 11.25H8.2575V11.2575H8.25V11.25Z\" />\n      <path\n        ref=\"button2Ref\"\n        d=\"M10.7476 11.25H10.7551V11.2575H10.7476V11.25Z\"\n      />\n      <path ref=\"button1Ref\" d=\"M13.2524 13.5H13.2599V13.5075H13.2524V13.5Z\" />\n      <path ref=\"button4Ref\" d=\"M8.25 15.75H8.2575V15.7575H8.25V15.75Z\" />\n      <path ref=\"button3Ref\" d=\"M15.75 11.25H15.7575V11.2575H15.75V11.25Z\" />\n      <path ref=\"button5Ref\" d=\"M10.7476 18H10.7551V18.0075H10.7476V18Z\" />\n      <path d=\"M8.25 13.5H8.2575V13.5075H8.25V13.5Z\" />\n      <path d=\"M8.25 18H8.2575V18.0075H8.25V18Z\" />\n      <path d=\"M10.7476 13.5H10.7551V13.5075H10.7476V13.5Z\" />\n      <path d=\"M10.7476 15.75H10.7551V15.7575H10.7476V15.75Z\" />\n      <path d=\"M13.2524 11.25H13.2599V11.2575H13.2524V11.25Z\" />\n      <path d=\"M13.2524 15.75H13.2599V15.7575H13.2524V15.75Z\" />\n      <path d=\"M13.2524 18H13.2599V18.0075H13.2524V18Z\" />\n      <path d=\"M15.75 13.5H15.7575V13.5075H15.75V13.5Z\" />\n      <path ref=\"enterRef\" d=\"M15.75 15.75V18\" />\n    </svg>\n  </div>\n</template>\n\n<script lang=\"ts\">\n  export default {\n    name: \"CalculatorIcon\",\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 createButtonVariants = (delay: number) => ({\n    normal: {\n      scale: 1,\n      opacity: 1,\n    },\n    animate: {\n      scale: [1, 1.5, 1],\n      opacity: [1, 0.5, 1],\n      transition: {\n        duration: 0.15,\n        delay: delay * 0.08,\n        ease: \"easeOut\",\n      },\n    },\n  });\n\n  const enterVariants = {\n    normal: {\n      scale: 1,\n      opacity: 1,\n    },\n    animate: {\n      scale: [1, 1.3, 1],\n      opacity: [1, 0.6, 1],\n      transition: {\n        duration: 0.2,\n        delay: 0.5,\n        ease: \"easeOut\",\n      },\n    },\n  };\n\n  const screenVariants = {\n    normal: {\n      opacity: 1,\n    },\n    animate: {\n      opacity: [1, 0.4, 1],\n      transition: {\n        duration: 0.2,\n        delay: 0.65,\n        ease: \"easeOut\",\n      },\n    },\n  };\n\n  const screenRef = ref<SVGPathElement | null>(null);\n  const button0Ref = ref<SVGPathElement | null>(null);\n  const button1Ref = ref<SVGPathElement | null>(null);\n  const button2Ref = ref<SVGPathElement | null>(null);\n  const button3Ref = ref<SVGPathElement | null>(null);\n  const button4Ref = ref<SVGPathElement | null>(null);\n  const button5Ref = ref<SVGPathElement | null>(null);\n  const enterRef = ref<SVGPathElement | null>(null);\n\n  const screenMotion = useMotion(screenRef, {\n    initial: screenVariants.normal,\n    enter: screenVariants.normal,\n  });\n\n  const buttonRefs = [\n    button0Ref,\n    button1Ref,\n    button2Ref,\n    button3Ref,\n    button4Ref,\n    button5Ref,\n  ] as const;\n  const buttonVariants = [\n    createButtonVariants(0),\n    createButtonVariants(1),\n    createButtonVariants(2),\n    createButtonVariants(3),\n    createButtonVariants(4),\n    createButtonVariants(5),\n  ] as const;\n  const buttonMotions = buttonRefs.map((buttonRef, index) =>\n    useMotion(buttonRef, {\n      initial: buttonVariants[index].normal,\n      enter: buttonVariants[index].normal,\n    })\n  );\n\n  const enterMotion = useMotion(enterRef, {\n    initial: enterVariants.normal,\n    enter: enterVariants.normal,\n  });\n\n  let isControlled = false;\n\n  const startAnimation = () => {\n    screenMotion.apply(screenVariants.animate);\n    let index = 0;\n    for (const buttonMotion of buttonMotions) {\n      buttonMotion.apply(buttonVariants[index].animate);\n      index += 1;\n    }\n    enterMotion.apply(enterVariants.animate);\n  };\n\n  const stopAnimation = () => {\n    screenMotion.apply(screenVariants.normal);\n    let index = 0;\n    for (const buttonMotion of buttonMotions) {\n      buttonMotion.apply(buttonVariants[index].normal);\n      index += 1;\n    }\n    enterMotion.apply(enterVariants.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"
    }
  ]
}