jsrepo v3

This commit is contained in:
David Haz
2025-12-15 23:50:24 +02:00
parent 9214481555
commit e621971723
119 changed files with 401 additions and 2197 deletions

1
public/r/TiltedCard.json Normal file
View File

@@ -0,0 +1 @@
{"name":"TiltedCard","title":"TiltedCard","description":"3D perspective tilt card reacting to pointer.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<template>\n <figure\n ref=\"cardRef\"\n class=\"relative w-full h-full [perspective:800px] flex flex-col items-center justify-center\"\n :style=\"{\n height: containerHeight,\n width: containerWidth\n }\"\n @mousemove=\"handleMouse\"\n @mouseenter=\"handleMouseEnter\"\n @mouseleave=\"handleMouseLeave\"\n >\n <div v-if=\"showMobileWarning\" class=\"absolute top-4 text-center text-sm block sm:hidden\">\n This effect is not optimized for mobile. Check on desktop.\n </div>\n\n <Motion\n tag=\"div\"\n class=\"relative [transform-style:preserve-3d]\"\n :style=\"{\n width: imageWidth,\n height: imageHeight\n }\"\n :animate=\"{\n rotateX: rotateXValue,\n rotateY: rotateYValue,\n scale: scaleValue\n }\"\n :transition=\"springTransition\"\n >\n <img\n :src=\"imageSrc\"\n :alt=\"altText\"\n class=\"absolute top-0 left-0 object-cover rounded-[15px] will-change-transform [transform:translateZ(0)]\"\n :style=\"{\n width: imageWidth,\n height: imageHeight\n }\"\n />\n\n <Motion\n v-if=\"displayOverlayContent && overlayContent\"\n tag=\"div\"\n class=\"absolute top-0 left-0 z-[2] will-change-transform [transform:translateZ(30px)]\"\n >\n <slot name=\"overlay\" />\n </Motion>\n </Motion>\n\n <Motion\n v-if=\"showTooltip && captionText\"\n tag=\"figcaption\"\n class=\"pointer-events-none absolute left-0 top-0 rounded-[4px] bg-white px-[10px] py-[4px] text-[10px] text-[#2d2d2d] opacity-0 z-[3] hidden sm:block\"\n :animate=\"{\n x: xValue,\n y: yValue,\n opacity: opacityValue,\n rotate: rotateFigcaptionValue\n }\"\n :transition=\"tooltipTransition\"\n >\n {{ captionText }}\n </Motion>\n </figure>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, useTemplateRef } from 'vue';\nimport { Motion } from 'motion-v';\n\ninterface TiltedCardProps {\n imageSrc: string;\n altText?: string;\n captionText?: string;\n containerHeight?: string;\n containerWidth?: string;\n imageHeight?: string;\n imageWidth?: string;\n scaleOnHover?: number;\n rotateAmplitude?: number;\n showMobileWarning?: boolean;\n showTooltip?: boolean;\n overlayContent?: boolean;\n displayOverlayContent?: boolean;\n}\n\nconst props = withDefaults(defineProps<TiltedCardProps>(), {\n altText: 'Tilted card image',\n captionText: '',\n containerHeight: '300px',\n containerWidth: '100%',\n imageHeight: '300px',\n imageWidth: '300px',\n scaleOnHover: 1.1,\n rotateAmplitude: 14,\n showMobileWarning: true,\n showTooltip: true,\n overlayContent: false,\n displayOverlayContent: false\n});\n\nconst cardRef = useTemplateRef<HTMLElement>('cardRef');\nconst xValue = ref(0);\nconst yValue = ref(0);\nconst rotateXValue = ref(0);\nconst rotateYValue = ref(0);\nconst scaleValue = ref(1);\nconst opacityValue = ref(0);\nconst rotateFigcaptionValue = ref(0);\nconst lastY = ref(0);\n\nconst springTransition = computed(() => ({\n type: 'spring' as const,\n damping: 30,\n stiffness: 100,\n mass: 2\n}));\n\nconst tooltipTransition = computed(() => ({\n type: 'spring' as const,\n damping: 30,\n stiffness: 350,\n mass: 1\n}));\n\nfunction handleMouse(e: MouseEvent) {\n if (!cardRef.value) return;\n\n const rect = cardRef.value.getBoundingClientRect();\n const offsetX = e.clientX - rect.left - rect.width / 2;\n const offsetY = e.clientY - rect.top - rect.height / 2;\n\n const rotationX = (offsetY / (rect.height / 2)) * -props.rotateAmplitude;\n const rotationY = (offsetX / (rect.width / 2)) * props.rotateAmplitude;\n\n rotateXValue.value = rotationX;\n rotateYValue.value = rotationY;\n\n xValue.value = e.clientX - rect.left;\n yValue.value = e.clientY - rect.top;\n\n const velocityY = offsetY - lastY.value;\n rotateFigcaptionValue.value = -velocityY * 0.6;\n lastY.value = offsetY;\n}\n\nfunction handleMouseEnter() {\n scaleValue.value = props.scaleOnHover;\n opacityValue.value = 1;\n}\n\nfunction handleMouseLeave() {\n opacityValue.value = 0;\n scaleValue.value = 1;\n rotateXValue.value = 0;\n rotateYValue.value = 0;\n rotateFigcaptionValue.value = 0;\n}\n</script>\n","path":"TiltedCard/TiltedCard.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[{"ecosystem":"js","name":"motion-v","version":"^1.5.0"}],"devDependencies":[],"categories":["Components"]}