Files
vue-bits/public/r/GlareHover.json
David Haz e621971723 jsrepo v3
2025-12-15 23:50:24 +02:00

1 line
3.5 KiB
JSON

{"name":"GlareHover","title":"GlareHover","description":"Adds a realistic moving glare highlight on hover over any element.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<script setup lang=\"ts\">\nimport { computed, useTemplateRef } from 'vue';\n\ninterface GlareHoverProps {\n width?: string;\n height?: string;\n background?: string;\n borderRadius?: string;\n borderColor?: string;\n glareColor?: string;\n glareOpacity?: number;\n glareAngle?: number;\n glareSize?: number;\n transitionDuration?: number;\n playOnce?: boolean;\n className?: string;\n style?: Record<string, string | number>;\n}\n\nconst props = withDefaults(defineProps<GlareHoverProps>(), {\n width: '500px',\n height: '500px',\n background: '#000',\n borderRadius: '10px',\n borderColor: '#333',\n glareColor: '#ffffff',\n glareOpacity: 0.5,\n glareAngle: -45,\n glareSize: 250,\n transitionDuration: 650,\n playOnce: false,\n className: '',\n style: () => ({})\n});\n\nconst overlayRef = useTemplateRef<HTMLDivElement>('overlayRef');\n\nconst rgba = computed(() => {\n const hex = props.glareColor.replace('#', '');\n let result = props.glareColor;\n\n if (/^[\\dA-Fa-f]{6}$/.test(hex)) {\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n result = `rgba(${r}, ${g}, ${b}, ${props.glareOpacity})`;\n } else if (/^[\\dA-Fa-f]{3}$/.test(hex)) {\n const r = parseInt(hex[0] + hex[0], 16);\n const g = parseInt(hex[1] + hex[1], 16);\n const b = parseInt(hex[2] + hex[2], 16);\n result = `rgba(${r}, ${g}, ${b}, ${props.glareOpacity})`;\n }\n\n return result;\n});\n\nconst overlayStyle = computed(() => ({\n position: 'absolute' as const,\n inset: '0',\n background: `linear-gradient(${props.glareAngle}deg,\n hsla(0,0%,0%,0) 60%,\n ${rgba.value} 70%,\n hsla(0,0%,0%,0) 100%)`,\n backgroundSize: `${props.glareSize}% ${props.glareSize}%, 100% 100%`,\n backgroundRepeat: 'no-repeat',\n backgroundPosition: '-100% -100%, 0 0',\n pointerEvents: 'none' as const\n}));\n\nconst animateIn = () => {\n const el = overlayRef.value;\n if (!el) return;\n\n el.style.transition = 'none';\n el.style.backgroundPosition = '-100% -100%, 0 0';\n void el.offsetHeight;\n el.style.transition = `${props.transitionDuration}ms ease`;\n el.style.backgroundPosition = '100% 100%, 0 0';\n};\n\nconst animateOut = () => {\n const el = overlayRef.value;\n if (!el) return;\n\n if (props.playOnce) {\n el.style.transition = 'none';\n el.style.backgroundPosition = '-100% -100%, 0 0';\n } else {\n el.style.transition = `${props.transitionDuration}ms ease`;\n el.style.backgroundPosition = '-100% -100%, 0 0';\n }\n};\n</script>\n\n<template>\n <div\n :class=\"`relative grid place-items-center overflow-hidden border cursor-pointer ${props.className}`\"\n :style=\"{\n width: props.width,\n height: props.height,\n background: props.background,\n borderRadius: props.borderRadius,\n borderColor: props.borderColor,\n ...props.style\n }\"\n @mouseenter=\"animateIn\"\n @mouseleave=\"animateOut\"\n >\n <div ref=\"overlayRef\" :style=\"overlayStyle\" />\n\n <slot />\n </div>\n</template>\n","path":"GlareHover/GlareHover.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[],"devDependencies":[],"categories":["Animations"]}