{
  "name": "infusion",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "name": "Infusion.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, type CSSProperties } from 'vue';\n\ninterface Props {\n  src: string;\n  opacity?: number;\n  opacityDark?: number;\n  zIndex?: number;\n  blur?: number;\n  noiseIntensity?: number;\n  noiseScale?: number;\n  noiseOpacity?: number;\n  blendMode?: CSSProperties['mixBlendMode'];\n  relative?: boolean;\n  type?: 'image' | 'video';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  src: '',\n  opacity: 0.2,\n  opacityDark: 0.3,\n  zIndex: 100,\n  blur: 64,\n  noiseIntensity: 0.5,\n  noiseScale: 1,\n  noiseOpacity: 0.05,\n  blendMode: 'normal',\n  relative: false,\n  type: 'image',\n});\n\nconst imageStyle = computed(() => ({\n  '--infusion-opacity': props.opacity,\n  '--infusion-opacity-dark': props.opacityDark,\n  '--infusion-z-index': props.zIndex,\n  '--infusion-blur': `${props.blur}px`,\n  '--infusion-noise-intensity': props.noiseIntensity,\n  '--infusion-noise-scale': props.noiseScale,\n  '--infusion-noise-opacity': props.noiseOpacity,\n  'mixBlendMode': props.blendMode,\n}));\n\nconst noiseDataUrl = computed(() => {\n  if (props.noiseIntensity === 0) {\n    return '';\n  }\n\n  if (typeof document === 'undefined') {\n    return '';\n  }\n\n  const canvas = document.createElement('canvas');\n  canvas.width = 256;\n  canvas.height = 256;\n  const context = canvas.getContext('2d');\n\n  if (!context) {\n    return '';\n  }\n\n  const imageData = context.createImageData(canvas.width, canvas.height);\n  const data = imageData.data;\n\n  for (let index = 0; index < data.length; index += 4) {\n    const value = Math.random() * 255;\n    data[index] = value;\n    data[index + 1] = value;\n    data[index + 2] = value;\n    data[index + 3] = props.noiseIntensity * 255;\n  }\n\n  context.putImageData(imageData, 0, 0);\n  return canvas.toDataURL();\n});\n\nconst containerClass = computed(() => [\n  'top-0 left-0 overflow-hidden pointer-events-none z-(--infusion-z-index)',\n  props.relative\n    ? 'absolute w-full h-full'\n    : 'fixed w-screen h-screen',\n]);\n\nconst mediaClass = 'w-full h-full object-cover scale-110 opacity-(--infusion-opacity) dark:opacity-(--infusion-opacity-dark)';\nconst noiseClass = 'absolute top-0 left-0 w-full h-full bg-repeat mix-blend-overlay';\n</script>\n\n<template>\n  <div\n    :class=\"containerClass\"\n    :style=\"imageStyle\"\n  >\n    <img\n      v-if=\"props.type === 'image'\"\n      :class=\"mediaClass\"\n      :src=\"props.src\"\n      :style=\"{\n        filter: `blur(var(--infusion-blur))`,\n      }\"\n      alt=\"\"\n    >\n    <video\n      v-if=\"props.type === 'video'\"\n      :class=\"mediaClass\"\n      :src=\"props.src\"\n      :style=\"{\n        filter: `blur(var(--infusion-blur))`,\n      }\"\n      autoplay\n      loop\n      muted\n      playsinline\n      alt=\"\"\n    />\n    <div\n      v-if=\"noiseIntensity > 0\"\n      :class=\"noiseClass\"\n      :style=\"{\n        backgroundImage: `url(${noiseDataUrl})`,\n        backgroundSize: 'calc(256px * var(--infusion-noise-scale))',\n        opacity: 'var(--infusion-noise-opacity)',\n      }\"\n    />\n  </div>\n</template>\n"
    },
    {
      "name": "index.ts",
      "content": "export { default as Infusion } from './Infusion.vue';\n"
    }
  ],
  "type": "components:ui"
}