reborn-ui 0.1.62 → 0.1.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/index.js +54 -6
  2. package/dist/index.js.map +1 -1
  3. package/package.json +2 -2
  4. package/registry/components/animate-grid.json +10 -6
  5. package/registry/components/animated-beam.json +9 -3
  6. package/registry/components/animated-circular-progressbar.json +9 -3
  7. package/registry/components/animated-list.json +16 -4
  8. package/registry/components/animated-testimonials.json +9 -3
  9. package/registry/components/animated-tooltip.json +9 -3
  10. package/registry/components/apple-card-carousel.json +32 -8
  11. package/registry/components/aurora-background.json +9 -3
  12. package/registry/components/balance-slider.json +9 -3
  13. package/registry/components/bending-gallery.json +9 -3
  14. package/registry/components/bento-grid.json +24 -6
  15. package/registry/components/bg-black-hole.json +9 -3
  16. package/registry/components/bg-bubbles.json +9 -3
  17. package/registry/components/bg-falling-stars.json +9 -3
  18. package/registry/components/bg-neural.json +9 -3
  19. package/registry/components/bg-particle-whirlpool.json +9 -3
  20. package/registry/components/bg-silk.json +9 -3
  21. package/registry/components/bg-singularity.json +22 -0
  22. package/registry/components/bg-stars.json +9 -3
  23. package/registry/components/bg-stractium.json +9 -3
  24. package/registry/components/bg-thunderstorm.json +22 -0
  25. package/registry/components/blur-reveal.json +9 -3
  26. package/registry/components/book.json +31 -7
  27. package/registry/components/border-beam.json +9 -3
  28. package/registry/components/box-reveal.json +9 -3
  29. package/registry/components/card-3d.json +28 -6
  30. package/registry/components/card-spotlight.json +9 -3
  31. package/registry/components/carousel-3d.json +13 -3
  32. package/registry/components/color-picker.json +24 -6
  33. package/registry/components/colourful-text.json +9 -3
  34. package/registry/components/compare.json +17 -7
  35. package/registry/components/confetti.json +16 -4
  36. package/registry/components/container-scroll.json +23 -5
  37. package/registry/components/container-text-flip.json +9 -3
  38. package/registry/components/cosmic-portal.json +9 -3
  39. package/registry/components/direction-aware-hover.json +9 -3
  40. package/registry/components/dither-shader.json +22 -0
  41. package/registry/components/dock.json +24 -6
  42. package/registry/components/expandable-gallery.json +9 -3
  43. package/registry/components/file-tree.json +31 -7
  44. package/registry/components/file-upload.json +16 -4
  45. package/registry/components/flickering-grid.json +9 -3
  46. package/registry/components/flip-card.json +9 -3
  47. package/registry/components/flip-words.json +9 -3
  48. package/registry/components/fluid-cursor.json +9 -3
  49. package/registry/components/focus.json +9 -3
  50. package/registry/components/github-globe.json +9 -3
  51. package/registry/components/glare-card.json +9 -3
  52. package/registry/components/globe.json +9 -3
  53. package/registry/components/glow-border.json +9 -3
  54. package/registry/components/glowing-effect.json +9 -3
  55. package/registry/components/gradient-button.json +9 -3
  56. package/registry/components/halo-search.json +9 -3
  57. package/registry/components/hyper-text.json +9 -3
  58. package/registry/components/icon-cloud.json +9 -3
  59. package/registry/components/image-trail-cursor.json +9 -3
  60. package/registry/components/images-slider.json +9 -3
  61. package/registry/components/infinite-grid.json +16 -10
  62. package/registry/components/input.json +9 -3
  63. package/registry/components/interactive-grid-pattern.json +9 -3
  64. package/registry/components/interactive-hover-button.json +9 -3
  65. package/registry/components/iphone-mockup.json +9 -3
  66. package/registry/components/lamp-effect.json +9 -3
  67. package/registry/components/lens.json +9 -3
  68. package/registry/components/letter-pullup.json +9 -3
  69. package/registry/components/light-speed.json +10 -4
  70. package/registry/components/line-shadow-text.json +9 -3
  71. package/registry/components/link-preview.json +9 -3
  72. package/registry/components/liquid-background.json +9 -3
  73. package/registry/components/liquid-glass.json +9 -3
  74. package/registry/components/liquid-logo.json +10 -4
  75. package/registry/components/logo-cloud.json +24 -6
  76. package/registry/components/logo-origami.json +16 -4
  77. package/registry/components/marquee.json +16 -4
  78. package/registry/components/meteors.json +9 -3
  79. package/registry/components/morphing-tabs.json +9 -3
  80. package/registry/components/morphing-text.json +9 -3
  81. package/registry/components/multi-step-loader.json +9 -3
  82. package/registry/components/neon-border.json +9 -3
  83. package/registry/components/number-ticker.json +9 -3
  84. package/registry/components/orbit.json +9 -3
  85. package/registry/components/particle-image.json +11 -5
  86. package/registry/components/particles-bg.json +9 -3
  87. package/registry/components/pattern-background.json +10 -4
  88. package/registry/components/photo-gallery.json +9 -3
  89. package/registry/components/radiant-text.json +9 -3
  90. package/registry/components/rainbow-button.json +9 -3
  91. package/registry/components/ripple-button.json +9 -3
  92. package/registry/components/ripple.json +23 -5
  93. package/registry/components/safari-mockup.json +9 -3
  94. package/registry/components/scratch-to-reveal.json +9 -3
  95. package/registry/components/scroll-island.json +9 -3
  96. package/registry/components/shader-toy.json +11 -5
  97. package/registry/components/shimmer-button.json +9 -3
  98. package/registry/components/sleek-line-cursor.json +9 -3
  99. package/registry/components/smooth-cursor.json +16 -4
  100. package/registry/components/snowfall-bg.json +9 -3
  101. package/registry/components/sparkles-text.json +9 -3
  102. package/registry/components/sparkles.json +9 -3
  103. package/registry/components/spinning-text.json +9 -3
  104. package/registry/components/spline.json +17 -5
  105. package/registry/components/spring-calendar.json +16 -4
  106. package/registry/components/svg-mask.json +9 -3
  107. package/registry/components/tailed-cursor.json +9 -3
  108. package/registry/components/testimonial-slider.json +9 -3
  109. package/registry/components/tetris.json +9 -3
  110. package/registry/components/text-3d.json +9 -3
  111. package/registry/components/text-generate-effect.json +9 -3
  112. package/registry/components/text-glitch.json +9 -3
  113. package/registry/components/text-highlight.json +9 -3
  114. package/registry/components/text-hover-effect.json +9 -3
  115. package/registry/components/text-reveal-card.json +16 -4
  116. package/registry/components/text-reveal.json +9 -3
  117. package/registry/components/text-scroll-reveal.json +16 -4
  118. package/registry/components/timeline.json +9 -3
  119. package/registry/components/tracing-beam.json +9 -3
  120. package/registry/components/vanishing-input.json +10 -6
  121. package/registry/components/video-text.json +9 -3
  122. package/registry/components/vortex.json +9 -4
  123. package/registry/components/warp-background.json +16 -4
  124. package/registry/components/wavy-background.json +9 -4
  125. package/registry/components/world-map.json +9 -3
  126. package/registry/registry.json +1175 -191
@@ -6,7 +6,13 @@
6
6
  "files": [
7
7
  {
8
8
  "path": "AnimatedList.vue",
9
- "content": "<template>\r\n <div :class=\"cn('flex flex-col items-center gap-4', $props.class)\">\r\n <transition-group\r\n name=\"list\"\r\n tag=\"div\"\r\n class=\"flex flex-col-reverse items-center gap-3\"\r\n move-class=\"move\"\r\n >\r\n <!-- Only render the items up to the current index -->\r\n <Motion\r\n v-for=\"data in itemsToShow\"\r\n :key=\"data.id\"\r\n as=\"div\"\r\n :initial=\"{ scale: 0, opacity: 0 }\"\r\n :animate=\"{\r\n scale: 1,\r\n opacity: 1,\r\n y: 0,\r\n }\"\r\n :exit=\"{\r\n scale: 0,\r\n opacity: 0,\r\n y: 0,\r\n }\"\r\n :transition=\"{\r\n type: 'spring',\r\n stiffness: 350,\r\n damping: 40,\r\n }\"\r\n :class=\"cn('mx-auto w-full')\"\r\n >\r\n <component :is=\"data.node\" />\r\n </Motion>\r\n </transition-group>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { Motion } from \"motion-v\";\r\nimport { computed, onMounted, ref, useSlots } from \"vue\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ninterface Props {\r\n class?: string;\r\n delay?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n delay: 1000,\r\n});\r\n\r\nconst slots = useSlots();\r\nconst displayedItems = ref<{ node: unknown; id: string }[]>([]);\r\nconst nextIndex = ref(0);\r\n\r\nonMounted(startLoop);\r\n\r\nasync function startLoop() {\r\n const notifications = slots.default ? (slots.default()[0].children ?? []) : [];\r\n if (!notifications.length) return;\r\n\r\n while (displayedItems.value.length < notifications.length) {\r\n displayedItems.value.push({\r\n node: notifications[nextIndex.value],\r\n id: `${nextIndex.value}-${Date.now()}`,\r\n });\r\n nextIndex.value = (nextIndex.value + 1) % notifications.length;\r\n await wait(props.delay);\r\n }\r\n\r\n while (true) {\r\n displayedItems.value.shift();\r\n displayedItems.value.push({\r\n node: notifications[nextIndex.value],\r\n id: `${nextIndex.value}-${Date.now()}`,\r\n });\r\n nextIndex.value = (nextIndex.value + 1) % notifications.length;\r\n await wait(props.delay);\r\n }\r\n}\r\n\r\nconst itemsToShow = computed(() => displayedItems.value);\r\n\r\nasync function wait(ms: number) {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.move {\r\n transition: transform 0.4s ease-out;\r\n}\r\n</style>\r\n"
9
+ "content": "<script lang=\"ts\" setup>\r\nimport { Motion } from \"motion-v\";\r\nimport { computed, onMounted, ref, useSlots } from \"vue\";\r\n\r\ninterface Props {\r\n class?: string;\r\n delay?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n delay: 1000,\r\n});\r\n\r\nconst slots = useSlots();\r\nconst displayedItems = ref<{ node: unknown; id: string }[]>([]);\r\nconst nextIndex = ref(0);\r\n\r\nonMounted(startLoop);\r\n\r\nasync function startLoop() {\r\n const notifications = slots.default ? (slots.default()[0].children ?? []) : [];\r\n if (!notifications.length) return;\r\n\r\n while (displayedItems.value.length < notifications.length) {\r\n displayedItems.value.push({\r\n node: notifications[nextIndex.value],\r\n id: `${nextIndex.value}-${Date.now()}`,\r\n });\r\n nextIndex.value = (nextIndex.value + 1) % notifications.length;\r\n await wait(props.delay);\r\n }\r\n\r\n while (true) {\r\n displayedItems.value.shift();\r\n displayedItems.value.push({\r\n node: notifications[nextIndex.value],\r\n id: `${nextIndex.value}-${Date.now()}`,\r\n });\r\n nextIndex.value = (nextIndex.value + 1) % notifications.length;\r\n await wait(props.delay);\r\n }\r\n}\r\n\r\nconst itemsToShow = computed(() => displayedItems.value);\r\n\r\nasync function wait(ms: number) {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n class=\"flex flex-col items-center gap-4\"\r\n :class=\"[props.class]\"\r\n >\r\n <transition-group\r\n name=\"list\"\r\n tag=\"div\"\r\n class=\"flex flex-col-reverse items-center gap-3\"\r\n move-class=\"move\"\r\n >\r\n <!-- Only render the items up to the current index -->\r\n <Motion\r\n v-for=\"data in itemsToShow\"\r\n :key=\"data.id\"\r\n as=\"div\"\r\n :initial=\"{ scale: 0, opacity: 0 }\"\r\n :animate=\"{\r\n scale: 1,\r\n opacity: 1,\r\n y: 0,\r\n }\"\r\n :exit=\"{\r\n scale: 0,\r\n opacity: 0,\r\n y: 0,\r\n }\"\r\n :transition=\"{\r\n type: 'spring',\r\n stiffness: 350,\r\n damping: 40,\r\n }\"\r\n class=\"mx-auto w-full\"\r\n >\r\n <component :is=\"data.node\" />\r\n </Motion>\r\n </transition-group>\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.move {\r\n transition: transform 0.4s ease-out;\r\n}\r\n</style>\r\n",
10
+ "target": "web"
11
+ },
12
+ {
13
+ "path": "AnimatedList.vue",
14
+ "content": "<script lang=\"ts\" setup>\r\nimport { Motion } from \"motion-v\";\r\nimport { computed, onMounted, ref, useSlots } from \"vue\";\r\n\r\ninterface Props {\r\n class?: string;\r\n delay?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n delay: 1000,\r\n});\r\n\r\nconst slots = useSlots();\r\nconst displayedItems = ref<{ node: unknown; id: string }[]>([]);\r\nconst nextIndex = ref(0);\r\n\r\nonMounted(startLoop);\r\n\r\nasync function startLoop() {\r\n const notifications = slots.default ? (slots.default()[0].children ?? []) : [];\r\n if (!notifications.length) return;\r\n\r\n while (displayedItems.value.length < notifications.length) {\r\n displayedItems.value.push({\r\n node: notifications[nextIndex.value],\r\n id: `${nextIndex.value}-${Date.now()}`,\r\n });\r\n nextIndex.value = (nextIndex.value + 1) % notifications.length;\r\n await wait(props.delay);\r\n }\r\n\r\n while (true) {\r\n displayedItems.value.shift();\r\n displayedItems.value.push({\r\n node: notifications[nextIndex.value],\r\n id: `${nextIndex.value}-${Date.now()}`,\r\n });\r\n nextIndex.value = (nextIndex.value + 1) % notifications.length;\r\n await wait(props.delay);\r\n }\r\n}\r\n\r\nconst itemsToShow = computed(() => displayedItems.value);\r\n\r\nasync function wait(ms: number) {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n</script>\r\n\r\n<template>\r\n <view\r\n class=\"flex flex-col items-center gap-4\"\r\n :class=\"[props.class]\"\r\n >\r\n <transition-group\r\n name=\"list\"\r\n tag=\"div\"\r\n class=\"flex flex-col-reverse items-center gap-3\"\r\n move-class=\"move\"\r\n >\r\n <!-- Only render the items up to the current index -->\r\n <Motion\r\n v-for=\"data in itemsToShow\"\r\n :key=\"data.id\"\r\n as=\"div\"\r\n :initial=\"{ scale: 0, opacity: 0 }\"\r\n :animate=\"{\r\n scale: 1,\r\n opacity: 1,\r\n y: 0,\r\n }\"\r\n :exit=\"{\r\n scale: 0,\r\n opacity: 0,\r\n y: 0,\r\n }\"\r\n :transition=\"{\r\n type: 'spring',\r\n stiffness: 350,\r\n damping: 40,\r\n }\"\r\n class=\"mx-auto w-full\"\r\n >\r\n <component :is=\"data.node\" />\r\n </Motion>\r\n </transition-group>\r\n </view>\r\n</template>\r\n\r\n<style scoped>\r\n.move {\r\n transition: transform 0.4s ease-out;\r\n}\r\n</style>\r\n",
15
+ "target": "uniapp"
10
16
  },
11
17
  {
12
18
  "path": "index.ts",
@@ -14,9 +20,15 @@
14
20
  },
15
21
  {
16
22
  "path": "Notification.vue",
17
- "content": "<template>\r\n <div\r\n :class=\"\r\n cn(\r\n 'relative mx-auto min-h-fit w-full max-w-[400px] cursor-pointer overflow-hidden rounded-2xl p-4',\r\n // animation styles\r\n 'transition-all duration-200 ease-in-out hover:scale-[103%]',\r\n // light styles\r\n 'bg-white [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]',\r\n // dark styles\r\n 'transform-gpu dark:bg-transparent dark:backdrop-blur-md dark:[border:1px_solid_rgba(255,255,255,.1)] dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset]',\r\n )\r\n \"\r\n >\r\n <div class=\"flex flex-row items-center gap-3\">\r\n <div\r\n class=\"flex size-10 items-center justify-center rounded-2xl\"\r\n :style=\"`background-color: ${color}`\"\r\n >\r\n <span class=\"text-lg\">{{ icon }}</span>\r\n </div>\r\n <div class=\"flex flex-col overflow-hidden\">\r\n <div class=\"flex flex-row items-center whitespace-pre text-lg font-medium dark:text-white\">\r\n <span class=\"text-sm sm:text-lg\">{{ name }}</span>\r\n <span class=\"mx-1\">·</span>\r\n <span class=\"text-xs text-gray-500\">{{ time }}</span>\r\n </div>\r\n <p class=\"text-sm font-normal dark:text-white/60\">{{ description }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ntype NotificationProps = {\r\n name?: string;\r\n description?: string;\r\n time?: string;\r\n icon?: string;\r\n color?: string;\r\n};\r\n\r\nwithDefaults(defineProps<NotificationProps>(), {\r\n name: \"\",\r\n description: \"\",\r\n time: \"\",\r\n icon: \"\",\r\n color: \"\",\r\n});\r\n</script>\r\n"
23
+ "content": "<script lang=\"ts\" setup>\r\ninterface NotificationProps {\r\n name?: string;\r\n description?: string;\r\n time?: string;\r\n icon?: string;\r\n color?: string;\r\n}\r\n\r\nwithDefaults(defineProps<NotificationProps>(), {\r\n name: \"\",\r\n description: \"\",\r\n time: \"\",\r\n icon: \"\",\r\n color: \"\",\r\n});\r\n</script>\r\n\r\n<template>\r\n <div\r\n class=\"relative mx-auto min-h-fit w-full max-w-[400px] transform-gpu cursor-pointer overflow-hidden rounded-2xl bg-white p-4 [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)] transition-all duration-200 ease-in-out hover:scale-[103%] dark:bg-transparent dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset] dark:backdrop-blur-md dark:[border:1px_solid_rgba(255,255,255,.1)]\"\r\n >\r\n <div class=\"flex flex-row items-center gap-3\">\r\n <div\r\n class=\"flex size-10 items-center justify-center rounded-2xl\"\r\n :style=\"`background-color: ${color}`\"\r\n >\r\n <span class=\"text-lg\">{{ icon }}</span>\r\n </div>\r\n <div class=\"flex flex-col overflow-hidden\">\r\n <div class=\"flex flex-row items-center text-lg font-medium whitespace-pre dark:text-white\">\r\n <span class=\"text-sm sm:text-lg\">{{ name }}</span>\r\n <span class=\"mx-1\">·</span>\r\n <span class=\"text-xs text-gray-500\">{{ time }}</span>\r\n </div>\r\n <p class=\"text-sm font-normal dark:text-white/60\">{{ description }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n",
24
+ "target": "web"
25
+ },
26
+ {
27
+ "path": "Notification.vue",
28
+ "content": "<script lang=\"ts\" setup>\r\ninterface NotificationProps {\r\n name?: string;\r\n description?: string;\r\n time?: string;\r\n icon?: string;\r\n color?: string;\r\n}\r\n\r\nwithDefaults(defineProps<NotificationProps>(), {\r\n name: \"\",\r\n description: \"\",\r\n time: \"\",\r\n icon: \"\",\r\n color: \"\",\r\n});\r\n</script>\r\n\r\n<template>\r\n <view\r\n class=\"relative mx-auto min-h-fit w-full max-w-[400px] transform-gpu cursor-pointer overflow-hidden rounded-2xl bg-white p-4 [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)] transition-all duration-200 ease-in-out hover:scale-[103%] dark:bg-transparent dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset] dark:backdrop-blur-md dark:[border:1px_solid_rgba(255,255,255,.1)]\"\r\n >\r\n <view class=\"flex flex-row items-center gap-3\">\r\n <view\r\n class=\"flex size-10 items-center justify-center rounded-2xl\"\r\n :style=\"`background-color: ${color}`\"\r\n >\r\n <text class=\"text-lg\">{{ icon }}</text>\r\n </view>\r\n <view class=\"flex flex-col overflow-hidden\">\r\n <view class=\"flex flex-row items-center text-lg font-medium whitespace-pre dark:text-white\">\r\n <text class=\"text-sm sm:text-lg\">{{ name }}</text>\r\n <text class=\"mx-1\">·</text>\r\n <text class=\"text-xs text-gray-500\">{{ time }}</text>\r\n </view>\r\n <p class=\"text-sm font-normal dark:text-white/60\">{{ description }}</p>\r\n </view>\r\n </view>\r\n </view>\r\n</template>\r\n",
29
+ "target": "uniapp"
18
30
  }
19
31
  ],
20
- "fileCount": 3,
21
- "contentHash": "dd6d4a2257148e8e166fa1b2588dc2c3c0f6d028"
32
+ "fileCount": 5,
33
+ "contentHash": "38c063c3a0be1549f7dee393f14116103310d42a"
22
34
  }
@@ -6,13 +6,19 @@
6
6
  "files": [
7
7
  {
8
8
  "path": "AnimatedTestimonials.vue",
9
- "content": "<template>\r\n <div class=\"mx-auto max-w-sm px-4 py-20 font-sans antialiased lg:px-12 md:max-w-4xl md:px-8\">\r\n <div class=\"relative grid grid-cols-1 gap-20 md:grid-cols-2\">\r\n <div>\r\n <div class=\"relative h-80 w-full\">\r\n <AnimatePresence>\r\n <Motion\r\n v-for=\"(testimonial, index) in props.testimonials\"\r\n :key=\"testimonial.image\"\r\n as=\"div\"\r\n :initial=\"{\r\n opacity: 0,\r\n scale: 0.9,\r\n z: -100,\r\n rotate: randomRotateY(),\r\n }\"\r\n :animate=\"{\r\n opacity: isActive(index) ? 1 : 0.7,\r\n scale: isActive(index) ? 1 : 0.95,\r\n z: isActive(index) ? 0 : -100,\r\n rotate: isActive(index) ? 0 : randomRotateY(),\r\n zIndex: isActive(index) ? 40 : testimonials.length + 2 - index,\r\n y: isActive(index) ? [0, -80, 0] : 0,\r\n }\"\r\n :exit=\"{\r\n opacity: 0,\r\n scale: 0.9,\r\n z: 100,\r\n rotate: randomRotateY(),\r\n }\"\r\n :transition=\"{\r\n duration: 0.4,\r\n ease: 'easeInOut',\r\n }\"\r\n class=\"absolute inset-0 origin-bottom\"\r\n >\r\n <NuxtImg\r\n :src=\"testimonial.image\"\r\n :alt=\"testimonial.name\"\r\n width=\"500\"\r\n height=\"500\"\r\n :draggable=\"false\"\r\n class=\"size-full rounded-3xl object-cover object-center\"\r\n />\r\n </Motion>\r\n </AnimatePresence>\r\n </div>\r\n </div>\r\n <div class=\"flex flex-col justify-between py-4\">\r\n <Motion\r\n :key=\"active\"\r\n as=\"div\"\r\n :initial=\"{\r\n y: 20,\r\n opacity: 0,\r\n }\"\r\n :animate=\"{\r\n y: 0,\r\n opacity: 1,\r\n }\"\r\n :exit=\"{\r\n y: -20,\r\n opacity: 0,\r\n }\"\r\n :transition=\"{\r\n duration: 0.2,\r\n ease: 'easeInOut',\r\n }\"\r\n >\r\n <h3 class=\"text-2xl font-bold text-black dark:text-white\">\r\n {{ props.testimonials[active].name }}\r\n </h3>\r\n <p class=\"text-sm text-gray-500 dark:text-neutral-500\">\r\n {{ props.testimonials[active].designation }}\r\n </p>\r\n <Motion\r\n as=\"p\"\r\n class=\"mt-8 text-lg text-gray-500 dark:text-neutral-300\"\r\n >\r\n <Motion\r\n v-for=\"(word, index) in activeTestimonialQuote\"\r\n :key=\"index\"\r\n as=\"span\"\r\n :initial=\"{\r\n filter: 'blur(10px)',\r\n opacity: 0,\r\n y: 5,\r\n }\"\r\n :animate=\"{\r\n filter: 'blur(0px)',\r\n opacity: 1,\r\n y: 0,\r\n }\"\r\n :transition=\"{\r\n duration: 0.2,\r\n ease: 'easeInOut',\r\n delay: 0.02 * index,\r\n }\"\r\n class=\"inline-block\"\r\n >\r\n {{ word }}&nbsp;\r\n </Motion>\r\n </Motion>\r\n </Motion>\r\n <div class=\"flex gap-4 pt-12 md:pt-0\">\r\n <button\r\n class=\"group/button flex size-7 items-center justify-center rounded-full bg-gray-100 dark:bg-neutral-800\"\r\n @click=\"handlePrev\"\r\n >\r\n <Icon\r\n name=\"lucide:arrow-left\"\r\n class=\"size-5 text-black transition-transform duration-300 group-hover/button:rotate-12 dark:text-neutral-400\"\r\n />\r\n </button>\r\n <button\r\n class=\"group/button flex size-7 items-center justify-center rounded-full bg-gray-100 dark:bg-neutral-800\"\r\n @click=\"handleNext\"\r\n >\r\n <Icon\r\n name=\"lucide:arrow-right\"\r\n class=\"size-5 text-black transition-transform duration-300 group-hover/button:-rotate-12 dark:text-neutral-400\"\r\n />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { Motion } from \"motion-v\";\r\n\r\ninterface Testimonial {\r\n quote: string;\r\n name: string;\r\n designation: string;\r\n image: string;\r\n}\r\ninterface Props {\r\n testimonials?: Testimonial[];\r\n autoplay?: boolean;\r\n duration?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n testimonials: () => [],\r\n autoplay: () => false,\r\n duration: 5000,\r\n});\r\n\r\nconst active = ref(0);\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nconst interval = ref<any>();\r\n\r\nconst activeTestimonialQuote = computed(() => {\r\n return props.testimonials[active.value].quote.split(\" \");\r\n});\r\n\r\nonMounted(() => {\r\n if (props.autoplay) {\r\n interval.value = setInterval(handleNext, props.duration);\r\n }\r\n});\r\n\r\nonUnmounted(() => {\r\n if (!interval.value) {\r\n clearInterval(interval.value);\r\n }\r\n});\r\n\r\nfunction handleNext() {\r\n active.value = (active.value + 1) % props.testimonials.length;\r\n}\r\n\r\nfunction handlePrev() {\r\n active.value = (active.value - 1 + props.testimonials.length) % props.testimonials.length;\r\n}\r\n\r\nfunction isActive(index: number) {\r\n return active.value === index;\r\n}\r\n\r\nfunction randomRotateY() {\r\n return Math.floor(Math.random() * 21) - 10;\r\n}\r\n</script>\r\n"
9
+ "content": "<script lang=\"ts\" setup>\r\nimport { Motion } from \"motion-v\";\r\n\r\ninterface Testimonial {\r\n quote: string;\r\n name: string;\r\n designation: string;\r\n image: string;\r\n}\r\ninterface Props {\r\n testimonials?: Testimonial[];\r\n autoplay?: boolean;\r\n duration?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n testimonials: () => [],\r\n autoplay: () => false,\r\n duration: 5000,\r\n});\r\n\r\nconst active = ref(0);\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nconst interval = ref<any>();\r\n\r\nconst activeTestimonialQuote = computed(() => {\r\n return props.testimonials[active.value].quote.split(\" \");\r\n});\r\n\r\nonMounted(() => {\r\n if (props.autoplay) {\r\n interval.value = setInterval(handleNext, props.duration);\r\n }\r\n});\r\n\r\nonUnmounted(() => {\r\n if (!interval.value) {\r\n clearInterval(interval.value);\r\n }\r\n});\r\n\r\nfunction handleNext() {\r\n active.value = (active.value + 1) % props.testimonials.length;\r\n}\r\n\r\nfunction handlePrev() {\r\n active.value = (active.value - 1 + props.testimonials.length) % props.testimonials.length;\r\n}\r\n\r\nfunction isActive(index: number) {\r\n return active.value === index;\r\n}\r\n\r\nfunction randomRotateY() {\r\n return Math.floor(Math.random() * 21) - 10;\r\n}\r\n</script>\r\n\r\n<template>\r\n <div class=\"mx-auto max-w-sm px-4 py-20 font-sans antialiased md:max-w-4xl md:px-8 lg:px-12\">\r\n <div class=\"relative grid grid-cols-1 gap-20 md:grid-cols-2\">\r\n <div>\r\n <div class=\"relative h-80 w-full\">\r\n <AnimatePresence>\r\n <Motion\r\n v-for=\"(testimonial, index) in props.testimonials\"\r\n :key=\"testimonial.image\"\r\n as=\"div\"\r\n :initial=\"{\r\n opacity: 0,\r\n scale: 0.9,\r\n z: -100,\r\n rotate: randomRotateY(),\r\n }\"\r\n :animate=\"{\r\n opacity: isActive(index) ? 1 : 0.7,\r\n scale: isActive(index) ? 1 : 0.95,\r\n z: isActive(index) ? 0 : -100,\r\n rotate: isActive(index) ? 0 : randomRotateY(),\r\n zIndex: isActive(index) ? 40 : testimonials.length + 2 - index,\r\n y: isActive(index) ? [0, -80, 0] : 0,\r\n }\"\r\n :exit=\"{\r\n opacity: 0,\r\n scale: 0.9,\r\n z: 100,\r\n rotate: randomRotateY(),\r\n }\"\r\n :transition=\"{\r\n duration: 0.4,\r\n ease: 'easeInOut',\r\n }\"\r\n class=\"absolute inset-0 origin-bottom\"\r\n >\r\n <NuxtImg\r\n :src=\"testimonial.image\"\r\n :alt=\"testimonial.name\"\r\n width=\"500\"\r\n height=\"500\"\r\n :draggable=\"false\"\r\n class=\"size-full rounded-3xl object-cover object-center\"\r\n />\r\n </Motion>\r\n </AnimatePresence>\r\n </div>\r\n </div>\r\n <div class=\"flex flex-col justify-between py-4\">\r\n <Motion\r\n :key=\"active\"\r\n as=\"div\"\r\n :initial=\"{\r\n y: 20,\r\n opacity: 0,\r\n }\"\r\n :animate=\"{\r\n y: 0,\r\n opacity: 1,\r\n }\"\r\n :exit=\"{\r\n y: -20,\r\n opacity: 0,\r\n }\"\r\n :transition=\"{\r\n duration: 0.2,\r\n ease: 'easeInOut',\r\n }\"\r\n >\r\n <h3 class=\"text-2xl font-bold text-black dark:text-white\">\r\n {{ props.testimonials[active].name }}\r\n </h3>\r\n <p class=\"text-sm text-gray-500 dark:text-neutral-500\">\r\n {{ props.testimonials[active].designation }}\r\n </p>\r\n <Motion\r\n as=\"p\"\r\n class=\"mt-8 text-lg text-gray-500 dark:text-neutral-300\"\r\n >\r\n <Motion\r\n v-for=\"(word, index) in activeTestimonialQuote\"\r\n :key=\"index\"\r\n as=\"span\"\r\n :initial=\"{\r\n filter: 'blur(10px)',\r\n opacity: 0,\r\n y: 5,\r\n }\"\r\n :animate=\"{\r\n filter: 'blur(0px)',\r\n opacity: 1,\r\n y: 0,\r\n }\"\r\n :transition=\"{\r\n duration: 0.2,\r\n ease: 'easeInOut',\r\n delay: 0.02 * index,\r\n }\"\r\n class=\"inline-block\"\r\n >\r\n {{ word }}&nbsp;\r\n </Motion>\r\n </Motion>\r\n </Motion>\r\n <div class=\"flex gap-4 pt-12 md:pt-0\">\r\n <button\r\n class=\"group/button flex size-7 items-center justify-center rounded-full bg-gray-100 dark:bg-neutral-800\"\r\n @click=\"handlePrev\"\r\n >\r\n <Icon\r\n name=\"lucide:arrow-left\"\r\n class=\"size-5 text-black transition-transform duration-300 group-hover/button:rotate-12 dark:text-neutral-400\"\r\n />\r\n </button>\r\n <button\r\n class=\"group/button flex size-7 items-center justify-center rounded-full bg-gray-100 dark:bg-neutral-800\"\r\n @click=\"handleNext\"\r\n >\r\n <Icon\r\n name=\"lucide:arrow-right\"\r\n class=\"size-5 text-black transition-transform duration-300 group-hover/button:-rotate-12 dark:text-neutral-400\"\r\n />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n",
10
+ "target": "web"
11
+ },
12
+ {
13
+ "path": "AnimatedTestimonials.vue",
14
+ "content": "<script lang=\"ts\" setup>\r\nimport { Motion } from \"motion-v\";\r\n\r\ninterface Testimonial {\r\n quote: string;\r\n name: string;\r\n designation: string;\r\n image: string;\r\n}\r\ninterface Props {\r\n testimonials?: Testimonial[];\r\n autoplay?: boolean;\r\n duration?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n testimonials: () => [],\r\n autoplay: () => false,\r\n duration: 5000,\r\n});\r\n\r\nconst active = ref(0);\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nconst interval = ref<any>();\r\n\r\nconst activeTestimonialQuote = computed(() => {\r\n return props.testimonials[active.value].quote.split(\" \");\r\n});\r\n\r\nonMounted(() => {\r\n if (props.autoplay) {\r\n interval.value = setInterval(handleNext, props.duration);\r\n }\r\n});\r\n\r\nonUnmounted(() => {\r\n if (!interval.value) {\r\n clearInterval(interval.value);\r\n }\r\n});\r\n\r\nfunction handleNext() {\r\n active.value = (active.value + 1) % props.testimonials.length;\r\n}\r\n\r\nfunction handlePrev() {\r\n active.value = (active.value - 1 + props.testimonials.length) % props.testimonials.length;\r\n}\r\n\r\nfunction isActive(index: number) {\r\n return active.value === index;\r\n}\r\n\r\nfunction randomRotateY() {\r\n return Math.floor(Math.random() * 21) - 10;\r\n}\r\n</script>\r\n\r\n<template>\r\n <view class=\"mx-auto max-w-sm px-4 py-20 font-sans antialiased md:max-w-4xl md:px-8 lg:px-12\">\r\n <view class=\"relative grid grid-cols-1 gap-20 md:grid-cols-2\">\r\n <view>\r\n <view class=\"relative h-80 w-full\">\r\n <AnimatePresence>\r\n <Motion\r\n v-for=\"(testimonial, index) in props.testimonials\"\r\n :key=\"testimonial.image\"\r\n as=\"div\"\r\n :initial=\"{\r\n opacity: 0,\r\n scale: 0.9,\r\n z: -100,\r\n rotate: randomRotateY(),\r\n }\"\r\n :animate=\"{\r\n opacity: isActive(index) ? 1 : 0.7,\r\n scale: isActive(index) ? 1 : 0.95,\r\n z: isActive(index) ? 0 : -100,\r\n rotate: isActive(index) ? 0 : randomRotateY(),\r\n zIndex: isActive(index) ? 40 : testimonials.length + 2 - index,\r\n y: isActive(index) ? [0, -80, 0] : 0,\r\n }\"\r\n :exit=\"{\r\n opacity: 0,\r\n scale: 0.9,\r\n z: 100,\r\n rotate: randomRotateY(),\r\n }\"\r\n :transition=\"{\r\n duration: 0.4,\r\n ease: 'easeInOut',\r\n }\"\r\n class=\"absolute inset-0 origin-bottom\"\r\n >\r\n <NuxtImg\r\n :src=\"testimonial.image\"\r\n :alt=\"testimonial.name\"\r\n width=\"500\"\r\n height=\"500\"\r\n :draggable=\"false\"\r\n class=\"size-full rounded-3xl object-cover object-center\"\r\n />\r\n </Motion>\r\n </AnimatePresence>\r\n </view>\r\n </view>\r\n <view class=\"flex flex-col justify-between py-4\">\r\n <Motion\r\n :key=\"active\"\r\n as=\"div\"\r\n :initial=\"{\r\n y: 20,\r\n opacity: 0,\r\n }\"\r\n :animate=\"{\r\n y: 0,\r\n opacity: 1,\r\n }\"\r\n :exit=\"{\r\n y: -20,\r\n opacity: 0,\r\n }\"\r\n :transition=\"{\r\n duration: 0.2,\r\n ease: 'easeInOut',\r\n }\"\r\n >\r\n <h3 class=\"text-2xl font-bold text-black dark:text-white\">\r\n {{ props.testimonials[active].name }}\r\n </h3>\r\n <p class=\"text-sm text-gray-500 dark:text-neutral-500\">\r\n {{ props.testimonials[active].designation }}\r\n </p>\r\n <Motion\r\n as=\"p\"\r\n class=\"mt-8 text-lg text-gray-500 dark:text-neutral-300\"\r\n >\r\n <Motion\r\n v-for=\"(word, index) in activeTestimonialQuote\"\r\n :key=\"index\"\r\n as=\"span\"\r\n :initial=\"{\r\n filter: 'blur(10px)',\r\n opacity: 0,\r\n y: 5,\r\n }\"\r\n :animate=\"{\r\n filter: 'blur(0px)',\r\n opacity: 1,\r\n y: 0,\r\n }\"\r\n :transition=\"{\r\n duration: 0.2,\r\n ease: 'easeInOut',\r\n delay: 0.02 * index,\r\n }\"\r\n class=\"inline-block\"\r\n >\r\n {{ word }}&nbsp;\r\n </Motion>\r\n </Motion>\r\n </Motion>\r\n <view class=\"flex gap-4 pt-12 md:pt-0\">\r\n <button\r\n class=\"group/button flex size-7 items-center justify-center rounded-full bg-gray-100 dark:bg-neutral-800\"\r\n @click=\"handlePrev\"\r\n >\r\n <Icon\r\n name=\"lucide:arrow-left\"\r\n class=\"size-5 text-black transition-transform duration-300 group-hover/button:rotate-12 dark:text-neutral-400\"\r\n />\r\n </button>\r\n <button\r\n class=\"group/button flex size-7 items-center justify-center rounded-full bg-gray-100 dark:bg-neutral-800\"\r\n @click=\"handleNext\"\r\n >\r\n <Icon\r\n name=\"lucide:arrow-right\"\r\n class=\"size-5 text-black transition-transform duration-300 group-hover/button:-rotate-12 dark:text-neutral-400\"\r\n />\r\n </button>\r\n </view>\r\n </view>\r\n </view>\r\n </view>\r\n</template>\r\n",
15
+ "target": "uniapp"
10
16
  },
11
17
  {
12
18
  "path": "index.ts",
13
19
  "content": "export { default as AnimatedTestimonials } from \"./AnimatedTestimonials.vue\";\r\n"
14
20
  }
15
21
  ],
16
- "fileCount": 2,
17
- "contentHash": "f660ab172808ae3ca330384ab1ec91925dd9c0fc"
22
+ "fileCount": 3,
23
+ "contentHash": "a4b2ce3ab02c3a5fcc7db4e02d527c57a13c8112"
18
24
  }
@@ -6,13 +6,19 @@
6
6
  "files": [
7
7
  {
8
8
  "path": "AnimatedTooltip.vue",
9
- "content": "<template>\r\n <div\r\n v-for=\"item in items\"\r\n :key=\"item.id\"\r\n class=\"group relative -mr-4\"\r\n @mouseenter=\"(e) => handleMouseEnter(e, item.id)\"\r\n @mouseleave=\"hoveredIndex = null\"\r\n @mousemove=\"handleMouseMove\"\r\n >\r\n <!-- Tooltip -->\r\n <Motion\r\n v-if=\"hoveredIndex === item.id\"\r\n :initial=\"{\r\n opacity: 0,\r\n y: 20,\r\n scale: 0.6,\r\n }\"\r\n :animate=\"{\r\n opacity: 1,\r\n y: 0,\r\n scale: 1,\r\n }\"\r\n :transition=\"{\r\n type: 'spring',\r\n stiffness: 260,\r\n damping: 10,\r\n }\"\r\n :exit=\"{\r\n opacity: 0,\r\n y: 20,\r\n scale: 0.6,\r\n }\"\r\n :style=\"{\r\n translateX: `${translation}px`,\r\n rotate: `${rotation}deg`,\r\n }\"\r\n class=\"absolute left-1/2 -top-16 z-50 flex -translate-x-1/2 flex-col items-center justify-center whitespace-nowrap rounded-md bg-black px-4 py-2 text-xs shadow-xl\"\r\n >\r\n <div\r\n class=\"absolute right-1/2 translate-x-1/2 -bottom-px z-30 h-px w-2/5 me-1 bg-gradient-to-r from-transparent via-emerald-500 to-transparent\"\r\n />\r\n <div\r\n class=\"absolute left-1/2 -translate-x-1/2 -bottom-px z-30 h-px w-2/5 ms-1 bg-gradient-to-r from-transparent via-sky-500 to-transparent\"\r\n />\r\n <div class=\"relative z-30 text-base font-bold text-white\">\r\n {{ item.name }}\r\n </div>\r\n <div class=\"text-xs text-white\">{{ item.designation }}</div>\r\n </Motion>\r\n\r\n <!-- Avatar Image -->\r\n <img\r\n :src=\"item.image\"\r\n :alt=\"item.name\"\r\n class=\"relative !m-0 size-14 rounded-full border-2 border-white object-cover object-top !p-0 transition duration-500 group-hover:z-30 group-hover:scale-105\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref } from \"vue\";\r\nimport { Motion } from \"motion-v\";\r\n\r\ninterface Item {\r\n id: number;\r\n name: string;\r\n designation: string;\r\n image: string;\r\n}\r\n\r\ndefineProps<{\r\n items: Item[];\r\n}>();\r\n\r\nconst hoveredIndex = ref<number | null>(null);\r\nconst mouseX = ref<number>(0);\r\n\r\n// Calculate rotation and translation based on mouse position\r\nconst rotation = computed<number>(() => {\r\n const x = mouseX.value;\r\n return (x / 100) * 50;\r\n});\r\n\r\nconst translation = computed<number>(() => {\r\n const x = mouseX.value;\r\n return (x / 100) * 50;\r\n});\r\n\r\n// Handle initial mouse position and hover\r\nfunction handleMouseEnter(event: MouseEvent, itemId: number) {\r\n hoveredIndex.value = itemId;\r\n // Calculate initial position immediately\r\n const rect = (event.target as HTMLElement)?.getBoundingClientRect();\r\n const halfWidth = rect.width / 2;\r\n mouseX.value = event.clientX - rect.left - halfWidth;\r\n}\r\n\r\n// Handle mouse movement\r\nfunction handleMouseMove(event: MouseEvent) {\r\n const rect = (event.target as HTMLElement)?.getBoundingClientRect();\r\n const halfWidth = rect.width / 2;\r\n mouseX.value = event.clientX - rect.left - halfWidth;\r\n}\r\n</script>\r\n"
9
+ "content": "<script setup lang=\"ts\">\r\nimport { Motion } from \"motion-v\";\r\nimport { computed, ref } from \"vue\";\r\n\r\ninterface Item {\r\n id: number;\r\n name: string;\r\n designation: string;\r\n image: string;\r\n}\r\n\r\ndefineProps<{\r\n items: Item[];\r\n}>();\r\n\r\nconst hoveredIndex = ref<number | null>(null);\r\nconst mouseX = ref<number>(0);\r\n\r\n// Calculate rotation and translation based on mouse position\r\nconst rotation = computed<number>(() => {\r\n const x = mouseX.value;\r\n return (x / 100) * 50;\r\n});\r\n\r\nconst translation = computed<number>(() => {\r\n const x = mouseX.value;\r\n return (x / 100) * 50;\r\n});\r\n\r\n// Handle initial mouse position and hover\r\nfunction handleMouseEnter(event: MouseEvent, itemId: number) {\r\n hoveredIndex.value = itemId;\r\n // Calculate initial position immediately\r\n const rect = (event.target as HTMLElement)?.getBoundingClientRect();\r\n const halfWidth = rect.width / 2;\r\n mouseX.value = event.clientX - rect.left - halfWidth;\r\n}\r\n\r\n// Handle mouse movement\r\nfunction handleMouseMove(event: MouseEvent) {\r\n const rect = (event.target as HTMLElement)?.getBoundingClientRect();\r\n const halfWidth = rect.width / 2;\r\n mouseX.value = event.clientX - rect.left - halfWidth;\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n v-for=\"item in items\"\r\n :key=\"item.id\"\r\n class=\"group relative -mr-4\"\r\n @mouseenter=\"(e) => handleMouseEnter(e, item.id)\"\r\n @mouseleave=\"hoveredIndex = null\"\r\n @mousemove=\"handleMouseMove\"\r\n >\r\n <!-- Tooltip -->\r\n <Motion\r\n v-if=\"hoveredIndex === item.id\"\r\n :initial=\"{\r\n opacity: 0,\r\n y: 20,\r\n scale: 0.6,\r\n }\"\r\n :animate=\"{\r\n opacity: 1,\r\n y: 0,\r\n scale: 1,\r\n }\"\r\n :transition=\"{\r\n type: 'spring',\r\n stiffness: 260,\r\n damping: 10,\r\n }\"\r\n :exit=\"{\r\n opacity: 0,\r\n y: 20,\r\n scale: 0.6,\r\n }\"\r\n :style=\"{\r\n translateX: `${translation}px`,\r\n rotate: `${rotation}deg`,\r\n }\"\r\n class=\"absolute -top-16 left-1/2 z-50 flex -translate-x-1/2 flex-col items-center justify-center rounded-md bg-black px-4 py-2 text-xs whitespace-nowrap shadow-xl\"\r\n >\r\n <div\r\n class=\"absolute right-1/2 -bottom-px z-30 me-1 h-px w-2/5 translate-x-1/2 bg-gradient-to-r from-transparent via-emerald-500 to-transparent\"\r\n />\r\n <div\r\n class=\"absolute -bottom-px left-1/2 z-30 ms-1 h-px w-2/5 -translate-x-1/2 bg-gradient-to-r from-transparent via-sky-500 to-transparent\"\r\n />\r\n <div class=\"relative z-30 text-base font-bold text-white\">\r\n {{ item.name }}\r\n </div>\r\n <div class=\"text-xs text-white\">{{ item.designation }}</div>\r\n </Motion>\r\n\r\n <!-- Avatar Image -->\r\n <img\r\n :src=\"item.image\"\r\n :alt=\"item.name\"\r\n class=\"relative !m-0 size-14 rounded-full border-2 border-white object-cover object-top !p-0 transition duration-500 group-hover:z-30 group-hover:scale-105\"\r\n />\r\n </div>\r\n</template>\r\n",
10
+ "target": "web"
11
+ },
12
+ {
13
+ "path": "AnimatedTooltip.vue",
14
+ "content": "<script setup lang=\"ts\">\r\nimport { Motion } from \"motion-v\";\r\nimport { computed, ref } from \"vue\";\r\n\r\ninterface Item {\r\n id: number;\r\n name: string;\r\n designation: string;\r\n image: string;\r\n}\r\n\r\ndefineProps<{\r\n items: Item[];\r\n}>();\r\n\r\nconst hoveredIndex = ref<number | null>(null);\r\nconst mouseX = ref<number>(0);\r\n\r\n// Calculate rotation and translation based on mouse position\r\nconst rotation = computed<number>(() => {\r\n const x = mouseX.value;\r\n return (x / 100) * 50;\r\n});\r\n\r\nconst translation = computed<number>(() => {\r\n const x = mouseX.value;\r\n return (x / 100) * 50;\r\n});\r\n\r\n// Handle initial mouse position and hover\r\nfunction handleMouseEnter(event: MouseEvent, itemId: number) {\r\n hoveredIndex.value = itemId;\r\n // Calculate initial position immediately\r\n const rect = (event.target as HTMLElement)?.getBoundingClientRect();\r\n const halfWidth = rect.width / 2;\r\n mouseX.value = event.clientX - rect.left - halfWidth;\r\n}\r\n\r\n// Handle mouse movement\r\nfunction handleMouseMove(event: MouseEvent) {\r\n const rect = (event.target as HTMLElement)?.getBoundingClientRect();\r\n const halfWidth = rect.width / 2;\r\n mouseX.value = event.clientX - rect.left - halfWidth;\r\n}\r\n</script>\r\n\r\n<template>\r\n <view\r\n v-for=\"item in items\"\r\n :key=\"item.id\"\r\n class=\"group relative -mr-4\"\r\n @mouseenter=\"(e) => handleMouseEnter(e, item.id)\"\r\n @mouseleave=\"hoveredIndex = null\"\r\n @mousemove=\"handleMouseMove\"\r\n >\r\n <!-- Tooltip -->\r\n <Motion\r\n v-if=\"hoveredIndex === item.id\"\r\n :initial=\"{\r\n opacity: 0,\r\n y: 20,\r\n scale: 0.6,\r\n }\"\r\n :animate=\"{\r\n opacity: 1,\r\n y: 0,\r\n scale: 1,\r\n }\"\r\n :transition=\"{\r\n type: 'spring',\r\n stiffness: 260,\r\n damping: 10,\r\n }\"\r\n :exit=\"{\r\n opacity: 0,\r\n y: 20,\r\n scale: 0.6,\r\n }\"\r\n :style=\"{\r\n translateX: `${translation}px`,\r\n rotate: `${rotation}deg`,\r\n }\"\r\n class=\"absolute -top-16 left-1/2 z-50 flex -translate-x-1/2 flex-col items-center justify-center rounded-md bg-black px-4 py-2 text-xs whitespace-nowrap shadow-xl\"\r\n >\r\n <view\r\n class=\"absolute right-1/2 -bottom-px z-30 me-1 h-px w-2/5 translate-x-1/2 bg-gradient-to-r from-transparent via-emerald-500 to-transparent\"\r\n />\r\n <view\r\n class=\"absolute -bottom-px left-1/2 z-30 ms-1 h-px w-2/5 -translate-x-1/2 bg-gradient-to-r from-transparent via-sky-500 to-transparent\"\r\n />\r\n <view class=\"relative z-30 text-base font-bold text-white\">\r\n {{ item.name }}\r\n </view>\r\n <view class=\"text-xs text-white\">{{ item.designation }}</view>\r\n </Motion>\r\n\r\n <!-- Avatar Image -->\r\n <image\r\n :src=\"item.image\"\r\n :alt=\"item.name\"\r\n class=\"relative !m-0 size-14 rounded-full border-2 border-white object-cover object-top !p-0 transition duration-500 group-hover:z-30 group-hover:scale-105\"\r\n />\r\n </view>\r\n</template>\r\n",
15
+ "target": "uniapp"
10
16
  },
11
17
  {
12
18
  "path": "index.ts",
13
19
  "content": "export { default as AnimatedTooltip } from \"./AnimatedTooltip.vue\";\r\n"
14
20
  }
15
21
  ],
16
- "fileCount": 2,
17
- "contentHash": "ddacc08a121e54bdc3aea7c291182fe69614b89e"
22
+ "fileCount": 3,
23
+ "contentHash": "28d7e43f4b467262c02ceaa51d5202e6eceb3eb0"
18
24
  }
@@ -7,29 +7,53 @@
7
7
  "files": [
8
8
  {
9
9
  "path": "AppleBlurImage.vue",
10
- "content": "<template>\r\n <img\r\n :class=\"\r\n cn(\r\n 'transition duration-300',\r\n isLoading ? 'blur-sm' : 'blur-0',\r\n props.class,\r\n fill ? 'h-full w-full' : '',\r\n )\r\n \"\r\n :src=\"src\"\r\n :width=\"width\"\r\n :height=\"height\"\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n :alt=\"alt\"\r\n @load=\"handleLoad\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ninterface Props {\r\n height?: number | string;\r\n width?: number | string;\r\n src: string;\r\n class?: string;\r\n alt?: string;\r\n fill?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n height: undefined,\r\n width: undefined,\r\n class: \"\",\r\n alt: \"Background of a beautiful view\",\r\n fill: false,\r\n});\r\n\r\nconst isLoading = ref(true);\r\n\r\nfunction handleLoad() {\r\n isLoading.value = false;\r\n}\r\n</script>\r\n"
10
+ "content": "<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\n\r\ninterface Props {\r\n height?: number | string;\r\n width?: number | string;\r\n src: string;\r\n class?: string;\r\n alt?: string;\r\n fill?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n height: undefined,\r\n width: undefined,\r\n class: \"\",\r\n alt: \"Background of a beautiful view\",\r\n fill: false,\r\n});\r\n\r\nconst isLoading = ref(true);\r\n\r\nfunction handleLoad() {\r\n isLoading.value = false;\r\n}\r\n</script>\r\n\r\n<template>\r\n <img\r\n class=\"transition duration-300\"\r\n :class=\"[isLoading ? 'blur-sm' : 'blur-0', props.class, fill ? 'h-full w-full' : '']\"\r\n :src=\"src\"\r\n :width=\"width\"\r\n :height=\"height\"\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n :alt=\"alt\"\r\n @load=\"handleLoad\"\r\n />\r\n</template>\r\n",
11
+ "target": "web"
12
+ },
13
+ {
14
+ "path": "AppleBlurImage.vue",
15
+ "content": "<script setup lang=\"ts\">\r\nimport { ref } from \"vue\";\r\n\r\ninterface Props {\r\n height?: number | string;\r\n width?: number | string;\r\n src: string;\r\n class?: string;\r\n alt?: string;\r\n fill?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n height: undefined,\r\n width: undefined,\r\n class: \"\",\r\n alt: \"Background of a beautiful view\",\r\n fill: false,\r\n});\r\n\r\nconst isLoading = ref(true);\r\n\r\nfunction handleLoad() {\r\n isLoading.value = false;\r\n}\r\n</script>\r\n\r\n<template>\r\n <image\r\n class=\"transition duration-300\"\r\n :class=\"[isLoading ? 'blur-sm' : 'blur-0', props.class, fill ? 'h-full w-full' : '']\"\r\n :src=\"src\"\r\n :width=\"width\"\r\n :height=\"height\"\r\n loading=\"lazy\"\r\n decoding=\"async\"\r\n :alt=\"alt\"\r\n @load=\"handleLoad\"\r\n />\r\n</template>\r\n",
16
+ "target": "uniapp"
17
+ },
18
+ {
19
+ "path": "AppleCard.vue",
20
+ "content": "<script setup lang=\"ts\">\r\nimport { onClickOutside } from \"@vueuse/core\";\r\nimport { AnimatePresence, Motion } from \"motion-v\";\r\nimport { inject, onMounted, onUnmounted, ref, watch } from \"vue\";\r\nimport { CarouselKey } from \"./AppleCarouselContext\";\r\n\r\ninterface Card {\r\n src: string;\r\n title: string;\r\n category: string;\r\n}\r\n\r\ninterface Props {\r\n card: Card;\r\n index: number;\r\n layout?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n layout: false,\r\n});\r\n\r\nconst open = ref(false);\r\nconst containerRef = ref<HTMLDivElement | null>(null);\r\nconst carouselContext = inject(CarouselKey);\r\n\r\nif (!carouselContext) {\r\n throw new Error(\"Card must be used within a Carousel\");\r\n}\r\n\r\nconst { onCardClose, currentIndex } = carouselContext;\r\n\r\nfunction handleKeyDown(event: KeyboardEvent) {\r\n if (event.key === \"Escape\") {\r\n handleClose();\r\n }\r\n}\r\n\r\nonMounted(() => {\r\n window.addEventListener(\"keydown\", handleKeyDown);\r\n});\r\n\r\nonUnmounted(() => {\r\n window.removeEventListener(\"keydown\", handleKeyDown);\r\n});\r\n\r\nwatch(open, (newVal) => {\r\n if (newVal) {\r\n document.body.style.overflow = \"hidden\";\r\n } else {\r\n document.body.style.overflow = \"auto\";\r\n }\r\n});\r\n\r\nonClickOutside(containerRef, () => handleClose());\r\n\r\nfunction handleOpen() {\r\n open.value = true;\r\n}\r\n\r\nfunction handleClose() {\r\n open.value = false;\r\n onCardClose(props.index);\r\n}\r\n</script>\r\n\r\n<template>\r\n <Teleport to=\"body\">\r\n <AnimatePresence>\r\n <div\r\n v-if=\"open\"\r\n class=\"fixed inset-0 z-50 h-screen overflow-auto\"\r\n >\r\n <Motion\r\n as=\"div\"\r\n :initial=\"{ opacity: 0 }\"\r\n :animate=\"{ opacity: 1 }\"\r\n :exit=\"{ opacity: 0 }\"\r\n class=\"fixed inset-0 size-full bg-black/80 backdrop-blur-lg\"\r\n />\r\n <Motion\r\n ref=\"containerRef\"\r\n as=\"div\"\r\n :initial=\"{ opacity: 0 }\"\r\n :animate=\"{ opacity: 1 }\"\r\n :exit=\"{ opacity: 0 }\"\r\n :layout-id=\"layout ? `card-${card.title}` : undefined\"\r\n class=\"relative z-[60] mx-auto my-10 h-fit max-w-5xl rounded-3xl bg-white p-4 font-sans md:p-10 dark:bg-neutral-900\"\r\n >\r\n <button\r\n class=\"sticky top-4 right-0 ml-auto flex size-8 items-center justify-center rounded-full bg-black dark:bg-white\"\r\n @click=\"handleClose\"\r\n >\r\n <Icon\r\n name=\"tabler:x\"\r\n class=\"size-6 text-neutral-100 dark:text-neutral-900\"\r\n />\r\n </button>\r\n <Motion\r\n as=\"div\"\r\n :layout-id=\"layout ? `category-${card.title}` : undefined\"\r\n class=\"text-base font-medium text-black dark:text-white\"\r\n >\r\n {{ card.category }}\r\n </Motion>\r\n <Motion\r\n as=\"div\"\r\n :layout-id=\"layout ? `title-${card.title}` : undefined\"\r\n class=\"mt-4 text-2xl font-semibold text-neutral-700 md:text-5xl dark:text-white\"\r\n >\r\n {{ card.title }}\r\n </Motion>\r\n <div class=\"py-10\">\r\n <slot />\r\n </div>\r\n </Motion>\r\n </div>\r\n </AnimatePresence>\r\n </Teleport>\r\n\r\n <Motion\r\n :layout-id=\"layout ? `card-${card.title}` : undefined\"\r\n class=\"relative z-10 flex h-80 w-56 flex-col items-start justify-start overflow-hidden rounded-3xl bg-gray-100 md:h-[40rem] md:w-96 dark:bg-neutral-900\"\r\n @click=\"handleOpen\"\r\n >\r\n <div\r\n class=\"pointer-events-none absolute inset-x-0 top-0 z-30 h-full bg-gradient-to-b from-black/50 via-transparent to-transparent\"\r\n />\r\n <div class=\"relative z-40 p-8\">\r\n <Motion\r\n :layout-id=\"layout ? `category-${card.category}` : undefined\"\r\n class=\"text-left font-sans text-sm font-medium text-white md:text-base\"\r\n >\r\n {{ card.category }}\r\n </Motion>\r\n <Motion\r\n :layout-id=\"layout ? `title-${card.title}` : undefined\"\r\n class=\"mt-2 max-w-xs text-left font-sans text-xl font-semibold [text-wrap:balance] text-white md:text-3xl\"\r\n >\r\n {{ card.title }}\r\n </Motion>\r\n </div>\r\n <AppleBlurImage\r\n :src=\"card.src\"\r\n :alt=\"card.title\"\r\n class=\"absolute inset-0 z-10 object-cover\"\r\n :fill=\"true\"\r\n />\r\n </Motion>\r\n</template>\r\n",
21
+ "target": "web"
11
22
  },
12
23
  {
13
24
  "path": "AppleCard.vue",
14
- "content": "<template>\r\n <Teleport to=\"body\">\r\n <AnimatePresence>\r\n <div\r\n v-if=\"open\"\r\n class=\"fixed inset-0 z-50 h-screen overflow-auto\"\r\n >\r\n <Motion\r\n as=\"div\"\r\n :initial=\"{ opacity: 0 }\"\r\n :animate=\"{ opacity: 1 }\"\r\n :exit=\"{ opacity: 0 }\"\r\n class=\"fixed inset-0 size-full bg-black/80 backdrop-blur-lg\"\r\n />\r\n <Motion\r\n ref=\"containerRef\"\r\n as=\"div\"\r\n :initial=\"{ opacity: 0 }\"\r\n :animate=\"{ opacity: 1 }\"\r\n :exit=\"{ opacity: 0 }\"\r\n :layout-id=\"layout ? `card-${card.title}` : undefined\"\r\n class=\"relative z-[60] mx-auto my-10 h-fit max-w-5xl rounded-3xl bg-white p-4 font-sans md:p-10 dark:bg-neutral-900\"\r\n >\r\n <button\r\n class=\"sticky right-0 top-4 ml-auto flex size-8 items-center justify-center rounded-full bg-black dark:bg-white\"\r\n @click=\"handleClose\"\r\n >\r\n <Icon\r\n name=\"tabler:x\"\r\n class=\"size-6 text-neutral-100 dark:text-neutral-900\"\r\n />\r\n </button>\r\n <Motion\r\n as=\"div\"\r\n :layout-id=\"layout ? `category-${card.title}` : undefined\"\r\n class=\"text-base font-medium text-black dark:text-white\"\r\n >\r\n {{ card.category }}\r\n </Motion>\r\n <Motion\r\n as=\"div\"\r\n :layout-id=\"layout ? `title-${card.title}` : undefined\"\r\n class=\"mt-4 text-2xl font-semibold text-neutral-700 md:text-5xl dark:text-white\"\r\n >\r\n {{ card.title }}\r\n </Motion>\r\n <div class=\"py-10\">\r\n <slot></slot>\r\n </div>\r\n </Motion>\r\n </div>\r\n </AnimatePresence>\r\n </Teleport>\r\n\r\n <Motion\r\n :layout-id=\"layout ? `card-${card.title}` : undefined\"\r\n class=\"relative z-10 flex h-80 w-56 flex-col items-start justify-start overflow-hidden rounded-3xl bg-gray-100 md:h-[40rem] md:w-96 dark:bg-neutral-900\"\r\n @click=\"handleOpen\"\r\n >\r\n <div\r\n class=\"pointer-events-none absolute inset-x-0 top-0 z-30 h-full bg-gradient-to-b from-black/50 via-transparent to-transparent\"\r\n />\r\n <div class=\"relative z-40 p-8\">\r\n <Motion\r\n :layout-id=\"layout ? `category-${card.category}` : undefined\"\r\n class=\"text-left font-sans text-sm font-medium text-white md:text-base\"\r\n >\r\n {{ card.category }}\r\n </Motion>\r\n <Motion\r\n :layout-id=\"layout ? `title-${card.title}` : undefined\"\r\n class=\"mt-2 max-w-xs text-left font-sans text-xl font-semibold text-white [text-wrap:balance] md:text-3xl\"\r\n >\r\n {{ card.title }}\r\n </Motion>\r\n </div>\r\n <AppleBlurImage\r\n :src=\"card.src\"\r\n :alt=\"card.title\"\r\n class=\"absolute inset-0 z-10 object-cover\"\r\n :fill=\"true\"\r\n />\r\n </Motion>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, onMounted, inject, onUnmounted, watch } from \"vue\";\r\nimport { Motion, AnimatePresence } from \"motion-v\";\r\nimport { onClickOutside } from \"@vueuse/core\";\r\nimport { CarouselKey } from \"./AppleCarouselContext\";\r\n\r\ninterface Card {\r\n src: string;\r\n title: string;\r\n category: string;\r\n}\r\n\r\ninterface Props {\r\n card: Card;\r\n index: number;\r\n layout?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n layout: false,\r\n});\r\n\r\nconst open = ref(false);\r\nconst containerRef = ref<HTMLDivElement | null>(null);\r\nconst carouselContext = inject(CarouselKey);\r\n\r\nif (!carouselContext) {\r\n throw new Error(\"Card must be used within a Carousel\");\r\n}\r\n\r\nconst { onCardClose, currentIndex } = carouselContext;\r\n\r\nfunction handleKeyDown(event: KeyboardEvent) {\r\n if (event.key === \"Escape\") {\r\n handleClose();\r\n }\r\n}\r\n\r\nonMounted(() => {\r\n window.addEventListener(\"keydown\", handleKeyDown);\r\n});\r\n\r\nonUnmounted(() => {\r\n window.removeEventListener(\"keydown\", handleKeyDown);\r\n});\r\n\r\nwatch(open, (newVal) => {\r\n if (newVal) {\r\n document.body.style.overflow = \"hidden\";\r\n } else {\r\n document.body.style.overflow = \"auto\";\r\n }\r\n});\r\n\r\nonClickOutside(containerRef, () => handleClose());\r\n\r\nfunction handleOpen() {\r\n open.value = true;\r\n}\r\n\r\nfunction handleClose() {\r\n open.value = false;\r\n onCardClose(props.index);\r\n}\r\n</script>\r\n"
25
+ "content": "<script setup lang=\"ts\">\r\nimport { onClickOutside } from \"@vueuse/core\";\r\nimport { AnimatePresence, Motion } from \"motion-v\";\r\nimport { inject, onMounted, onUnmounted, ref, watch } from \"vue\";\r\nimport { CarouselKey } from \"./AppleCarouselContext\";\r\n\r\ninterface Card {\r\n src: string;\r\n title: string;\r\n category: string;\r\n}\r\n\r\ninterface Props {\r\n card: Card;\r\n index: number;\r\n layout?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n layout: false,\r\n});\r\n\r\nconst open = ref(false);\r\nconst containerRef = ref<HTMLDivElement | null>(null);\r\nconst carouselContext = inject(CarouselKey);\r\n\r\nif (!carouselContext) {\r\n throw new Error(\"Card must be used within a Carousel\");\r\n}\r\n\r\nconst { onCardClose, currentIndex } = carouselContext;\r\n\r\nfunction handleKeyDown(event: KeyboardEvent) {\r\n if (event.key === \"Escape\") {\r\n handleClose();\r\n }\r\n}\r\n\r\nonMounted(() => {\r\n window.addEventListener(\"keydown\", handleKeyDown);\r\n});\r\n\r\nonUnmounted(() => {\r\n window.removeEventListener(\"keydown\", handleKeyDown);\r\n});\r\n\r\nwatch(open, (newVal) => {\r\n if (newVal) {\r\n document.body.style.overflow = \"hidden\";\r\n } else {\r\n document.body.style.overflow = \"auto\";\r\n }\r\n});\r\n\r\nonClickOutside(containerRef, () => handleClose());\r\n\r\nfunction handleOpen() {\r\n open.value = true;\r\n}\r\n\r\nfunction handleClose() {\r\n open.value = false;\r\n onCardClose(props.index);\r\n}\r\n</script>\r\n\r\n<template>\r\n <Teleport to=\"body\">\r\n <AnimatePresence>\r\n <view\r\n v-if=\"open\"\r\n class=\"fixed inset-0 z-50 h-screen overflow-auto\"\r\n >\r\n <Motion\r\n as=\"div\"\r\n :initial=\"{ opacity: 0 }\"\r\n :animate=\"{ opacity: 1 }\"\r\n :exit=\"{ opacity: 0 }\"\r\n class=\"fixed inset-0 size-full bg-black/80 backdrop-blur-lg\"\r\n />\r\n <Motion\r\n ref=\"containerRef\"\r\n as=\"div\"\r\n :initial=\"{ opacity: 0 }\"\r\n :animate=\"{ opacity: 1 }\"\r\n :exit=\"{ opacity: 0 }\"\r\n :layout-id=\"layout ? `card-${card.title}` : undefined\"\r\n class=\"relative z-[60] mx-auto my-10 h-fit max-w-5xl rounded-3xl bg-white p-4 font-sans md:p-10 dark:bg-neutral-900\"\r\n >\r\n <button\r\n class=\"sticky top-4 right-0 ml-auto flex size-8 items-center justify-center rounded-full bg-black dark:bg-white\"\r\n @click=\"handleClose\"\r\n >\r\n <Icon\r\n name=\"tabler:x\"\r\n class=\"size-6 text-neutral-100 dark:text-neutral-900\"\r\n />\r\n </button>\r\n <Motion\r\n as=\"div\"\r\n :layout-id=\"layout ? `category-${card.title}` : undefined\"\r\n class=\"text-base font-medium text-black dark:text-white\"\r\n >\r\n {{ card.category }}\r\n </Motion>\r\n <Motion\r\n as=\"div\"\r\n :layout-id=\"layout ? `title-${card.title}` : undefined\"\r\n class=\"mt-4 text-2xl font-semibold text-neutral-700 md:text-5xl dark:text-white\"\r\n >\r\n {{ card.title }}\r\n </Motion>\r\n <view class=\"py-10\">\r\n <slot />\r\n </view>\r\n </Motion>\r\n </view>\r\n </AnimatePresence>\r\n </Teleport>\r\n\r\n <Motion\r\n :layout-id=\"layout ? `card-${card.title}` : undefined\"\r\n class=\"relative z-10 flex h-80 w-56 flex-col items-start justify-start overflow-hidden rounded-3xl bg-gray-100 md:h-[40rem] md:w-96 dark:bg-neutral-900\"\r\n @click=\"handleOpen\"\r\n >\r\n <view\r\n class=\"pointer-events-none absolute inset-x-0 top-0 z-30 h-full bg-gradient-to-b from-black/50 via-transparent to-transparent\"\r\n />\r\n <view class=\"relative z-40 p-8\">\r\n <Motion\r\n :layout-id=\"layout ? `category-${card.category}` : undefined\"\r\n class=\"text-left font-sans text-sm font-medium text-white md:text-base\"\r\n >\r\n {{ card.category }}\r\n </Motion>\r\n <Motion\r\n :layout-id=\"layout ? `title-${card.title}` : undefined\"\r\n class=\"mt-2 max-w-xs text-left font-sans text-xl font-semibold [text-wrap:balance] text-white md:text-3xl\"\r\n >\r\n {{ card.title }}\r\n </Motion>\r\n </view>\r\n <AppleBlurImage\r\n :src=\"card.src\"\r\n :alt=\"card.title\"\r\n class=\"absolute inset-0 z-10 object-cover\"\r\n :fill=\"true\"\r\n />\r\n </Motion>\r\n</template>\r\n",
26
+ "target": "uniapp"
15
27
  },
16
28
  {
17
29
  "path": "AppleCardCarousel.vue",
18
- "content": "<template>\r\n <div class=\"relative w-full\">\r\n <div\r\n ref=\"carouselRef\"\r\n class=\"flex w-full overflow-x-scroll overscroll-x-auto scroll-smooth py-10 [scrollbar-width:none] md:py-20\"\r\n @scroll=\"checkScrollability\"\r\n >\r\n <div\r\n :class=\"cn('absolute right-0 z-[1000] h-auto w-[5%] overflow-hidden bg-gradient-to-l')\"\r\n ></div>\r\n\r\n <div :class=\"cn('flex flex-row justify-start gap-4 pl-4', 'mx-auto max-w-7xl')\">\r\n <slot></slot>\r\n </div>\r\n </div>\r\n <div class=\"mr-10 flex justify-end gap-2\">\r\n <button\r\n class=\"relative z-40 flex size-10 items-center justify-center rounded-full bg-gray-100 disabled:opacity-50\"\r\n :disabled=\"!canScrollLeft\"\r\n @click=\"scrollLeft\"\r\n >\r\n <Icon\r\n name=\"tabler:arrow-narrow-left\"\r\n class=\"size-6 text-gray-500\"\r\n />\r\n </button>\r\n <button\r\n class=\"relative z-40 flex size-10 items-center justify-center rounded-full bg-gray-100 disabled:opacity-50\"\r\n :disabled=\"!canScrollRight\"\r\n @click=\"scrollRight\"\r\n >\r\n <Icon\r\n name=\"tabler:arrow-narrow-right\"\r\n class=\"size-6 text-gray-500\"\r\n />\r\n </button>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, onMounted, watch, provide, computed } from \"vue\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { CarouselKey } from \"./AppleCarouselContext\";\r\n\r\ninterface Props {\r\n initialScroll?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n initialScroll: 0,\r\n});\r\n\r\nconst carouselRef = ref<HTMLDivElement | null>(null);\r\nconst canScrollLeft = ref(false);\r\nconst canScrollRight = ref(true);\r\nconst currentIndex = ref(0);\r\n\r\nonMounted(() => {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollLeft = props.initialScroll;\r\n checkScrollability();\r\n }\r\n});\r\n\r\nwatch(\r\n () => props.initialScroll,\r\n (newVal) => {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollLeft = newVal;\r\n checkScrollability();\r\n }\r\n },\r\n);\r\n\r\nfunction checkScrollability() {\r\n if (carouselRef.value) {\r\n const { scrollLeft, scrollWidth, clientWidth } = carouselRef.value;\r\n canScrollLeft.value = scrollLeft > 0;\r\n canScrollRight.value = scrollLeft < scrollWidth - clientWidth;\r\n }\r\n}\r\n\r\nfunction scrollLeft() {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollBy({ left: -300, behavior: \"smooth\" });\r\n }\r\n}\r\n\r\nfunction scrollRight() {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollBy({ left: 300, behavior: \"smooth\" });\r\n }\r\n}\r\n\r\nfunction handleCardClose(index: number) {\r\n if (carouselRef.value) {\r\n const cardWidth = isMobile.value ? 230 : 384; // (md:w-96)\r\n const gap = isMobile.value ? 4 : 8;\r\n const scrollPosition = (cardWidth + gap) * (index + 1);\r\n carouselRef.value.scrollTo({\r\n left: scrollPosition,\r\n behavior: \"smooth\",\r\n });\r\n currentIndex.value = index;\r\n }\r\n}\r\n\r\nconst isMobile = computed(() => {\r\n return window && window.innerWidth < 768;\r\n});\r\n\r\nprovide(CarouselKey, {\r\n onCardClose: handleCardClose,\r\n currentIndex,\r\n});\r\n</script>\r\n"
30
+ "content": "<script setup lang=\"ts\">\r\nimport { computed, onMounted, provide, ref, watch } from \"vue\";\r\nimport { CarouselKey } from \"./AppleCarouselContext\";\r\n\r\ninterface Props {\r\n initialScroll?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n initialScroll: 0,\r\n});\r\n\r\nconst carouselRef = ref<HTMLDivElement | null>(null);\r\nconst canScrollLeft = ref(false);\r\nconst canScrollRight = ref(true);\r\nconst currentIndex = ref(0);\r\n\r\nonMounted(() => {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollLeft = props.initialScroll;\r\n checkScrollability();\r\n }\r\n});\r\n\r\nwatch(\r\n () => props.initialScroll,\r\n (newVal) => {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollLeft = newVal;\r\n checkScrollability();\r\n }\r\n },\r\n);\r\n\r\nfunction checkScrollability() {\r\n if (carouselRef.value) {\r\n const { scrollLeft, scrollWidth, clientWidth } = carouselRef.value;\r\n canScrollLeft.value = scrollLeft > 0;\r\n canScrollRight.value = scrollLeft < scrollWidth - clientWidth;\r\n }\r\n}\r\n\r\nfunction scrollLeft() {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollBy({ left: -300, behavior: \"smooth\" });\r\n }\r\n}\r\n\r\nfunction scrollRight() {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollBy({ left: 300, behavior: \"smooth\" });\r\n }\r\n}\r\n\r\nfunction handleCardClose(index: number) {\r\n if (carouselRef.value) {\r\n const cardWidth = isMobile.value ? 230 : 384; // (md:w-96)\r\n const gap = isMobile.value ? 4 : 8;\r\n const scrollPosition = (cardWidth + gap) * (index + 1);\r\n carouselRef.value.scrollTo({\r\n left: scrollPosition,\r\n behavior: \"smooth\",\r\n });\r\n currentIndex.value = index;\r\n }\r\n}\r\n\r\nconst isMobile = computed(() => {\r\n return window && window.innerWidth < 768;\r\n});\r\n\r\nprovide(CarouselKey, {\r\n onCardClose: handleCardClose,\r\n currentIndex,\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"relative w-full\">\r\n <div\r\n ref=\"carouselRef\"\r\n class=\"flex w-full overflow-x-scroll overscroll-x-auto scroll-smooth py-10 [scrollbar-width:none] md:py-20\"\r\n @scroll=\"checkScrollability\"\r\n >\r\n <div class=\"absolute right-0 z-[1000] h-auto w-[5%] overflow-hidden bg-gradient-to-l\" />\r\n\r\n <div class=\"mx-auto flex max-w-7xl flex-row justify-start gap-4 pl-4\">\r\n <slot />\r\n </div>\r\n </div>\r\n <div class=\"mr-10 flex justify-end gap-2\">\r\n <button\r\n class=\"relative z-40 flex size-10 items-center justify-center rounded-full bg-gray-100 disabled:opacity-50\"\r\n :disabled=\"!canScrollLeft\"\r\n @click=\"scrollLeft\"\r\n >\r\n <Icon\r\n name=\"tabler:arrow-narrow-left\"\r\n class=\"size-6 text-gray-500\"\r\n />\r\n </button>\r\n <button\r\n class=\"relative z-40 flex size-10 items-center justify-center rounded-full bg-gray-100 disabled:opacity-50\"\r\n :disabled=\"!canScrollRight\"\r\n @click=\"scrollRight\"\r\n >\r\n <Icon\r\n name=\"tabler:arrow-narrow-right\"\r\n class=\"size-6 text-gray-500\"\r\n />\r\n </button>\r\n </div>\r\n </div>\r\n</template>\r\n",
31
+ "target": "web"
32
+ },
33
+ {
34
+ "path": "AppleCardCarousel.vue",
35
+ "content": "<script setup lang=\"ts\">\r\nimport { computed, onMounted, provide, ref, watch } from \"vue\";\r\nimport { CarouselKey } from \"./AppleCarouselContext\";\r\n\r\ninterface Props {\r\n initialScroll?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n initialScroll: 0,\r\n});\r\n\r\nconst carouselRef = ref<HTMLDivElement | null>(null);\r\nconst canScrollLeft = ref(false);\r\nconst canScrollRight = ref(true);\r\nconst currentIndex = ref(0);\r\n\r\nonMounted(() => {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollLeft = props.initialScroll;\r\n checkScrollability();\r\n }\r\n});\r\n\r\nwatch(\r\n () => props.initialScroll,\r\n (newVal) => {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollLeft = newVal;\r\n checkScrollability();\r\n }\r\n },\r\n);\r\n\r\nfunction checkScrollability() {\r\n if (carouselRef.value) {\r\n const { scrollLeft, scrollWidth, clientWidth } = carouselRef.value;\r\n canScrollLeft.value = scrollLeft > 0;\r\n canScrollRight.value = scrollLeft < scrollWidth - clientWidth;\r\n }\r\n}\r\n\r\nfunction scrollLeft() {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollBy({ left: -300, behavior: \"smooth\" });\r\n }\r\n}\r\n\r\nfunction scrollRight() {\r\n if (carouselRef.value) {\r\n carouselRef.value.scrollBy({ left: 300, behavior: \"smooth\" });\r\n }\r\n}\r\n\r\nfunction handleCardClose(index: number) {\r\n if (carouselRef.value) {\r\n const cardWidth = isMobile.value ? 230 : 384; // (md:w-96)\r\n const gap = isMobile.value ? 4 : 8;\r\n const scrollPosition = (cardWidth + gap) * (index + 1);\r\n carouselRef.value.scrollTo({\r\n left: scrollPosition,\r\n behavior: \"smooth\",\r\n });\r\n currentIndex.value = index;\r\n }\r\n}\r\n\r\nconst isMobile = computed(() => {\r\n return window && window.innerWidth < 768;\r\n});\r\n\r\nprovide(CarouselKey, {\r\n onCardClose: handleCardClose,\r\n currentIndex,\r\n});\r\n</script>\r\n\r\n<template>\r\n <view class=\"relative w-full\">\r\n <view\r\n ref=\"carouselRef\"\r\n class=\"flex w-full overflow-x-scroll overscroll-x-auto scroll-smooth py-10 [scrollbar-width:none] md:py-20\"\r\n @scroll=\"checkScrollability\"\r\n >\r\n <view class=\"absolute right-0 z-[1000] h-auto w-[5%] overflow-hidden bg-gradient-to-l\" />\r\n\r\n <view class=\"mx-auto flex max-w-7xl flex-row justify-start gap-4 pl-4\">\r\n <slot />\r\n </view>\r\n </view>\r\n <view class=\"mr-10 flex justify-end gap-2\">\r\n <button\r\n class=\"relative z-40 flex size-10 items-center justify-center rounded-full bg-gray-100 disabled:opacity-50\"\r\n :disabled=\"!canScrollLeft\"\r\n @click=\"scrollLeft\"\r\n >\r\n <Icon\r\n name=\"tabler:arrow-narrow-left\"\r\n class=\"size-6 text-gray-500\"\r\n />\r\n </button>\r\n <button\r\n class=\"relative z-40 flex size-10 items-center justify-center rounded-full bg-gray-100 disabled:opacity-50\"\r\n :disabled=\"!canScrollRight\"\r\n @click=\"scrollRight\"\r\n >\r\n <Icon\r\n name=\"tabler:arrow-narrow-right\"\r\n class=\"size-6 text-gray-500\"\r\n />\r\n </button>\r\n </view>\r\n </view>\r\n</template>\r\n",
36
+ "target": "uniapp"
19
37
  },
20
38
  {
21
39
  "path": "AppleCarouselContext.ts",
22
- "content": "import { type InjectionKey, type Ref } from \"vue\";\r\n\r\nexport interface CarouselContextType {\r\n onCardClose: (index: number) => void;\r\n currentIndex: Ref<number>;\r\n}\r\n\r\nexport const CarouselKey = Symbol() as InjectionKey<CarouselContextType>;\r\n"
40
+ "content": "import type { InjectionKey, Ref } from \"vue\";\r\n\r\nexport interface CarouselContextType {\r\n onCardClose: (index: number) => void;\r\n currentIndex: Ref<number>;\r\n}\r\n\r\nexport const CarouselKey = Symbol() as InjectionKey<CarouselContextType>;\r\n"
41
+ },
42
+ {
43
+ "path": "AppleCarouselItem.vue",
44
+ "content": "<script setup lang=\"ts\">\r\nimport { Motion } from \"motion-v\";\r\n\r\ninterface Props {\r\n index: number;\r\n}\r\n\r\ndefineProps<Props>();\r\n</script>\r\n\r\n<template>\r\n <Motion\r\n as=\"div\"\r\n :initial=\"{\r\n opacity: 0,\r\n y: 20,\r\n }\"\r\n :animate=\"{\r\n opacity: 1,\r\n y: 0,\r\n transition: {\r\n duration: 0.5,\r\n delay: 0.2 * index,\r\n ease: 'easeOut',\r\n once: true,\r\n },\r\n }\"\r\n class=\"rounded-3xl last:pr-[5%] md:last:pr-[33%]\"\r\n >\r\n <slot />\r\n </Motion>\r\n</template>\r\n",
45
+ "target": "web"
23
46
  },
24
47
  {
25
48
  "path": "AppleCarouselItem.vue",
26
- "content": "<template>\r\n <Motion\r\n as=\"div\"\r\n :initial=\"{\r\n opacity: 0,\r\n y: 20,\r\n }\"\r\n :animate=\"{\r\n opacity: 1,\r\n y: 0,\r\n transition: {\r\n duration: 0.5,\r\n delay: 0.2 * index,\r\n ease: 'easeOut',\r\n once: true,\r\n },\r\n }\"\r\n class=\"rounded-3xl last:pr-[5%] md:last:pr-[33%]\"\r\n >\r\n <slot></slot>\r\n </Motion>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { Motion } from \"motion-v\";\r\n\r\ninterface Props {\r\n index: number;\r\n}\r\n\r\ndefineProps<Props>();\r\n</script>\r\n"
49
+ "content": "<script setup lang=\"ts\">\r\nimport { Motion } from \"motion-v\";\r\n\r\ninterface Props {\r\n index: number;\r\n}\r\n\r\ndefineProps<Props>();\r\n</script>\r\n\r\n<template>\r\n <Motion\r\n as=\"div\"\r\n :initial=\"{\r\n opacity: 0,\r\n y: 20,\r\n }\"\r\n :animate=\"{\r\n opacity: 1,\r\n y: 0,\r\n transition: {\r\n duration: 0.5,\r\n delay: 0.2 * index,\r\n ease: 'easeOut',\r\n once: true,\r\n },\r\n }\"\r\n class=\"rounded-3xl last:pr-[5%] md:last:pr-[33%]\"\r\n >\r\n <slot />\r\n </Motion>\r\n</template>\r\n",
50
+ "target": "uniapp"
27
51
  },
28
52
  {
29
53
  "path": "index.ts",
30
- "content": "export { default as AppleCardCarousel } from \"./AppleCardCarousel.vue\";\r\nexport { default as AppleCarouselItem } from \"./AppleCarouselItem.vue\";\r\nexport { default as AppleCard } from \"./AppleCard.vue\";\r\nexport { default as AppleBlurImage } from \"./AppleBlurImage.vue\";\r\nexport * from \"./AppleCarouselContext\";\r\n"
54
+ "content": "export { default as AppleBlurImage } from \"./AppleBlurImage.vue\";\r\nexport { default as AppleCard } from \"./AppleCard.vue\";\r\nexport { default as AppleCardCarousel } from \"./AppleCardCarousel.vue\";\r\nexport * from \"./AppleCarouselContext\";\r\nexport { default as AppleCarouselItem } from \"./AppleCarouselItem.vue\";\r\n"
31
55
  }
32
56
  ],
33
- "fileCount": 6,
34
- "contentHash": "82edd74b20d26c18a1fa5f94a374cb842a0f125c"
57
+ "fileCount": 10,
58
+ "contentHash": "12facd293832c399b5969dfbce6ee484d4f23ca6"
35
59
  }
@@ -4,13 +4,19 @@
4
4
  "files": [
5
5
  {
6
6
  "path": "AuroraBackground.vue",
7
- "content": "<template>\r\n <main>\r\n <div\r\n v-bind=\"props\"\r\n :class=\"\r\n cn(\r\n 'transition-bg relative flex h-[100vh] flex-col items-center justify-center bg-zinc-50 text-slate-950 dark:bg-zinc-900',\r\n props.class,\r\n )\r\n \"\r\n >\r\n <div\r\n :style=\"styles\"\r\n class=\"absolute inset-0 overflow-hidden\"\r\n >\r\n <div\r\n :class=\"\r\n cn(\r\n `after:animate-aurora pointer-events-none absolute -inset-[10px] [background-image:var(--white-gradient),var(--aurora)] [background-size:300%,_200%] [background-position:50%_50%,50%_50%] opacity-50 blur-[10px] invert filter will-change-transform [--aurora:repeating-linear-gradient(100deg,var(--blue-500)_10%,var(--indigo-300)_15%,var(--blue-300)_20%,var(--violet-200)_25%,var(--blue-400)_30%)] [--dark-gradient:repeating-linear-gradient(100deg,var(--black)_0%,var(--black)_7%,var(--transparent)_10%,var(--transparent)_12%,var(--black)_16%)] [--white-gradient:repeating-linear-gradient(100deg,var(--white)_0%,var(--white)_7%,var(--transparent)_10%,var(--transparent)_12%,var(--white)_16%)] after:absolute after:inset-0 after:[background-image:var(--white-gradient),var(--aurora)] after:[background-size:200%,_100%] after:[background-attachment:fixed] after:mix-blend-difference after:content-[''] dark:[background-image:var(--dark-gradient),var(--aurora)] dark:invert-0 after:dark:[background-image:var(--dark-gradient),var(--aurora)]`,\r\n props.radialGradient &&\r\n `[mask-image:radial-gradient(ellipse_at_100%_0%,black_10%,var(--transparent)_70%)]`,\r\n )\r\n \"\r\n />\r\n </div>\r\n <slot />\r\n </div>\r\n </main>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { cn } from \"@/lib/utils\";\r\nimport { computed } from \"vue\";\r\n\r\ninterface AuroraBackgroundProps {\r\n radialGradient?: boolean;\r\n class?: string;\r\n}\r\n\r\nconst props = withDefaults(defineProps<AuroraBackgroundProps>(), {\r\n radialGradient: true,\r\n});\r\n\r\nconst styles = computed(() => {\r\n return {\r\n \"--aurora\":\r\n \"repeating-linear-gradient(100deg,#3b82f6_10%,#a5b4fc_15%,#93c5fd_20%,#ddd6fe_25%,#60a5fa_30%)\",\r\n \"--dark-gradient\":\r\n \"repeating-linear-gradient(100deg,#000_0%,#000_7%,transparent_10%,transparent_12%,#000_16%)\",\r\n \"--white-gradient\":\r\n \"repeating-linear-gradient(100deg,#fff_0%,#fff_7%,transparent_10%,transparent_12%,#fff_16%)\",\r\n\r\n \"--blue-300\": \"#93c5fd\",\r\n \"--blue-400\": \"#60a5fa\",\r\n \"--blue-500\": \"#3b82f6\",\r\n \"--indigo-300\": \"#a5b4fc\",\r\n \"--violet-200\": \"#ddd6fe\",\r\n \"--black\": \"#000\",\r\n \"--white\": \"#fff\",\r\n \"--transparent\": \"transparent\",\r\n \"--animate-aurora\": \"aurora 60s linear infinite\",\r\n };\r\n});\r\n</script>\r\n"
7
+ "content": "<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\n\r\ninterface AuroraBackgroundProps {\r\n radialGradient?: boolean;\r\n class?: string;\r\n}\r\n\r\nconst props = withDefaults(defineProps<AuroraBackgroundProps>(), {\r\n radialGradient: true,\r\n});\r\n\r\nconst styles = computed(() => {\r\n return {\r\n \"--aurora\":\r\n \"repeating-linear-gradient(100deg,#3b82f6_10%,#a5b4fc_15%,#93c5fd_20%,#ddd6fe_25%,#60a5fa_30%)\",\r\n \"--dark-gradient\":\r\n \"repeating-linear-gradient(100deg,#000_0%,#000_7%,transparent_10%,transparent_12%,#000_16%)\",\r\n \"--white-gradient\":\r\n \"repeating-linear-gradient(100deg,#fff_0%,#fff_7%,transparent_10%,transparent_12%,#fff_16%)\",\r\n\r\n \"--blue-300\": \"#93c5fd\",\r\n \"--blue-400\": \"#60a5fa\",\r\n \"--blue-500\": \"#3b82f6\",\r\n \"--indigo-300\": \"#a5b4fc\",\r\n \"--violet-200\": \"#ddd6fe\",\r\n \"--black\": \"#000\",\r\n \"--white\": \"#fff\",\r\n \"--transparent\": \"transparent\",\r\n \"--animate-aurora\": \"aurora 60s linear infinite\",\r\n };\r\n});\r\n</script>\r\n\r\n<template>\r\n <main>\r\n <div\r\n v-bind=\"props\"\r\n class=\"transition-bg relative flex h-[100vh] flex-col items-center justify-center bg-zinc-50 text-slate-950 dark:bg-zinc-900\"\r\n :class=\"[props.class]\"\r\n >\r\n <div\r\n :style=\"styles\"\r\n class=\"absolute inset-0 overflow-hidden\"\r\n >\r\n <div\r\n class=\"after:animate-aurora pointer-events-none absolute -inset-[10px] [background-image:var(--white-gradient),var(--aurora)] [background-size:300%,_200%] [background-position:50%_50%,50%_50%] opacity-50 blur-[10px] invert filter will-change-transform [--aurora:repeating-linear-gradient(100deg,var(--blue-500)_10%,var(--indigo-300)_15%,var(--blue-300)_20%,var(--violet-200)_25%,var(--blue-400)_30%)] [--dark-gradient:repeating-linear-gradient(100deg,var(--black)_0%,var(--black)_7%,var(--transparent)_10%,var(--transparent)_12%,var(--black)_16%)] [--white-gradient:repeating-linear-gradient(100deg,var(--white)_0%,var(--white)_7%,var(--transparent)_10%,var(--transparent)_12%,var(--white)_16%)] after:absolute after:inset-0 after:[background-image:var(--white-gradient),var(--aurora)] after:[background-size:200%,_100%] after:[background-attachment:fixed] after:mix-blend-difference after:content-[''] dark:[background-image:var(--dark-gradient),var(--aurora)] dark:invert-0 after:dark:[background-image:var(--dark-gradient),var(--aurora)]\"\r\n :class=\"[\r\n props.radialGradient &&\r\n `[mask-image:radial-gradient(ellipse_at_100%_0%,black_10%,var(--transparent)_70%)]`,\r\n ]\"\r\n />\r\n </div>\r\n <slot />\r\n </div>\r\n </main>\r\n</template>\r\n",
8
+ "target": "web"
9
+ },
10
+ {
11
+ "path": "AuroraBackground.vue",
12
+ "content": "<script setup lang=\"ts\">\r\nimport { computed } from \"vue\";\r\n\r\ninterface AuroraBackgroundProps {\r\n radialGradient?: boolean;\r\n class?: string;\r\n}\r\n\r\nconst props = withDefaults(defineProps<AuroraBackgroundProps>(), {\r\n radialGradient: true,\r\n});\r\n\r\nconst styles = computed(() => {\r\n return {\r\n \"--aurora\":\r\n \"repeating-linear-gradient(100deg,#3b82f6_10%,#a5b4fc_15%,#93c5fd_20%,#ddd6fe_25%,#60a5fa_30%)\",\r\n \"--dark-gradient\":\r\n \"repeating-linear-gradient(100deg,#000_0%,#000_7%,transparent_10%,transparent_12%,#000_16%)\",\r\n \"--white-gradient\":\r\n \"repeating-linear-gradient(100deg,#fff_0%,#fff_7%,transparent_10%,transparent_12%,#fff_16%)\",\r\n\r\n \"--blue-300\": \"#93c5fd\",\r\n \"--blue-400\": \"#60a5fa\",\r\n \"--blue-500\": \"#3b82f6\",\r\n \"--indigo-300\": \"#a5b4fc\",\r\n \"--violet-200\": \"#ddd6fe\",\r\n \"--black\": \"#000\",\r\n \"--white\": \"#fff\",\r\n \"--transparent\": \"transparent\",\r\n \"--animate-aurora\": \"aurora 60s linear infinite\",\r\n };\r\n});\r\n</script>\r\n\r\n<template>\r\n <main>\r\n <view\r\n v-bind=\"props\"\r\n class=\"transition-bg relative flex h-[100vh] flex-col items-center justify-center bg-zinc-50 text-slate-950 dark:bg-zinc-900\"\r\n :class=\"[props.class]\"\r\n >\r\n <view\r\n :style=\"styles\"\r\n class=\"absolute inset-0 overflow-hidden\"\r\n >\r\n <view\r\n class=\"after:animate-aurora pointer-events-none absolute -inset-[10px] [background-image:var(--white-gradient),var(--aurora)] [background-size:300%,_200%] [background-position:50%_50%,50%_50%] opacity-50 blur-[10px] invert filter will-change-transform [--aurora:repeating-linear-gradient(100deg,var(--blue-500)_10%,var(--indigo-300)_15%,var(--blue-300)_20%,var(--violet-200)_25%,var(--blue-400)_30%)] [--dark-gradient:repeating-linear-gradient(100deg,var(--black)_0%,var(--black)_7%,var(--transparent)_10%,var(--transparent)_12%,var(--black)_16%)] [--white-gradient:repeating-linear-gradient(100deg,var(--white)_0%,var(--white)_7%,var(--transparent)_10%,var(--transparent)_12%,var(--white)_16%)] after:absolute after:inset-0 after:[background-image:var(--white-gradient),var(--aurora)] after:[background-size:200%,_100%] after:[background-attachment:fixed] after:mix-blend-difference after:content-[''] dark:[background-image:var(--dark-gradient),var(--aurora)] dark:invert-0 after:dark:[background-image:var(--dark-gradient),var(--aurora)]\"\r\n :class=\"[\r\n props.radialGradient &&\r\n `[mask-image:radial-gradient(ellipse_at_100%_0%,black_10%,var(--transparent)_70%)]`,\r\n ]\"\r\n />\r\n </view>\r\n <slot />\r\n </view>\r\n </main>\r\n</template>\r\n",
13
+ "target": "uniapp"
8
14
  },
9
15
  {
10
16
  "path": "index.ts",
11
17
  "content": "export { default as AuroraBackground } from \"./AuroraBackground.vue\";\r\n"
12
18
  }
13
19
  ],
14
- "fileCount": 2,
15
- "contentHash": "e5adb4691fb18fe72332491030138d006279efe4"
20
+ "fileCount": 3,
21
+ "contentHash": "691bdfb7edf38af9ba66403200a6ea3d9053aa81"
16
22
  }
@@ -4,13 +4,19 @@
4
4
  "files": [
5
5
  {
6
6
  "path": "BalanceSlider.vue",
7
- "content": "<template>\r\n <div\r\n class=\"slider-container relative mx-auto my-0 grid place-items-center overflow-hidden\"\r\n :style=\"sliderStyles\"\r\n @mouseenter=\"active = 1\"\r\n @mouseleave=\"active = 0\"\r\n @focusin=\"active = 1\"\r\n @focusout=\"active = 0\"\r\n @touchstart=\"active = 1\"\r\n @touchend=\"active = 0\"\r\n >\r\n <input\r\n id=\"track\"\r\n v-model=\"value\"\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"100\"\r\n class=\"size-full touch-none opacity-0 hover:cursor-grab focus-visible:outline-offset-4 focus-visible:outline-transparent active:cursor-grabbing\"\r\n />\r\n <div\r\n aria-hidden=\"true\"\r\n :class=\"\r\n cn('slider-value-labels pointer-events-none absolute inset-x-0 top-0 z-[2] h-1/2 text-base')\r\n \"\r\n :style=\"sliderLabelStyles\"\r\n ></div>\r\n <div\r\n class=\"slider-track pointer-events-none absolute bottom-0 w-full\"\r\n :style=\"sliderTrackStyles\"\r\n >\r\n <div\r\n class=\"slider-indicator absolute top-1/2 z-[2] h-3/4 w-1 -translate-x-1/2 -translate-y-1/2 rounded-sm\"\r\n ></div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref } from \"vue\";\r\nimport { cn } from \"@/lib/utils\";\r\n\r\ninterface Props {\r\n initialValue?: number;\r\n leftColor?: string;\r\n rightColor?: string;\r\n minShiftLimit?: number;\r\n maxShiftLimit?: number;\r\n leftContent?: string;\r\n rightContent?: string;\r\n indicatorColor?: string;\r\n borderRadius?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n initialValue: 50,\r\n minShiftLimit: 40,\r\n maxShiftLimit: 68,\r\n leftContent: \"LEFT\",\r\n rightContent: \"RIGHT\",\r\n leftColor: \"#e68a00\",\r\n rightColor: \"#ffffff\",\r\n indicatorColor: \"#FFFFFF\",\r\n borderRadius: 8,\r\n});\r\n\r\nconst value = ref(props.initialValue);\r\nconst active = ref(0);\r\n\r\nconst shift = computed(() =>\r\n value.value > props.minShiftLimit && value.value < props.maxShiftLimit ? 1 : 0,\r\n);\r\n\r\nconst sliderStyles = computed(() => ({\r\n \"--value\": value.value,\r\n \"--shift\": shift.value,\r\n \"--active\": active.value,\r\n \"--leftContent\": `\"${props.leftContent} \"`,\r\n \"--rightContent\": `\" ${props.rightContent}\"`,\r\n \"--indicatorColor\": indicatorColorHsl.value,\r\n}));\r\n\r\nconst sliderLabelStyles = computed(() => ({\r\n \"--shift\": shift.value,\r\n}));\r\n\r\nconst sliderTrackStyles = computed(() => ({\r\n \"--value\": value.value,\r\n \"--shift\": shift.value,\r\n \"--leftColor\": leftColorHsl.value,\r\n \"--rightColor\": rightColorHsl.value,\r\n}));\r\n\r\nconst leftColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.leftColor);\r\n const alpha = 0.4;\r\n const lightness = 24 + (30 * (100 - value.value)) / 100;\r\n return `hsl(${h} ${s}% ${lightness}% / ${alpha})`;\r\n});\r\n\r\nconst rightColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.rightColor);\r\n const alpha = 0.1 + (0.4 * (100 - value.value)) / 100;\r\n return `hsl(${h} ${s}% ${l}% / ${alpha})`;\r\n});\r\n\r\nconst indicatorColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.indicatorColor); // Base color as hex, here white (#ffffff)\r\n const activeAlpha = active.value * 0.5 + 0.5; // Calculate alpha based on active state\r\n return `hsl(${h} ${s}% ${l}% / ${activeAlpha})`;\r\n});\r\n\r\nconst borderRadiusInPx = computed(() => `${props.borderRadius}px`);\r\n\r\nfunction hexToHsl(hex: string): [number, number, number] {\r\n // Remove \"#\" if present\r\n hex = hex.replace(/^#/, \"\");\r\n\r\n // Parse r, g, b values\r\n let r = parseInt(hex.substring(0, 2), 16) / 255;\r\n let g = parseInt(hex.substring(2, 4), 16) / 255;\r\n let b = parseInt(hex.substring(4, 6), 16) / 255;\r\n\r\n // Find min and max values of r, g, b\r\n let max = Math.max(r, g, b),\r\n min = Math.min(r, g, b);\r\n let h = 0,\r\n s = 0,\r\n l = (max + min) / 2;\r\n\r\n if (max != min) {\r\n let d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n\r\n return [h * 360, s * 100, l * 100];\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.slider-container {\r\n --speed: 0.65s;\r\n --update: 0s;\r\n --timing: linear(\r\n 0,\r\n 0.5007 7.21%,\r\n 0.7803 12.29%,\r\n 0.8883 14.93%,\r\n 0.9724 17.63%,\r\n 1.0343 20.44%,\r\n 1.0754 23.44%,\r\n 1.0898 25.22%,\r\n 1.0984 27.11%,\r\n 1.1014 29.15%,\r\n 1.0989 31.4%,\r\n 1.0854 35.23%,\r\n 1.0196 48.86%,\r\n 1.0043 54.06%,\r\n 0.9956 59.6%,\r\n 0.9925 68.11%,\r\n 1\r\n );\r\n}\r\n\r\n.slider-value-labels {\r\n transform: translateY(calc(var(--shift, 0) * 50%));\r\n transition: transform var(--speed) var(--timing);\r\n counter-reset: low var(--value) high calc(100 - var(--value));\r\n}\r\n\r\n.slider-value-labels::after,\r\n.slider-value-labels::before {\r\n font-variant: tabular-nums;\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n font-weight: bold;\r\n color: white;\r\n font-family: monospace;\r\n}\r\n\r\n.slider-value-labels::before {\r\n --range: calc((70 - (var(--value) / 100 * 10)) * 1%);\r\n color: hsl(24 74% 54%);\r\n content: var(--leftContent) counter(low) \"%\";\r\n mask: linear-gradient(90deg, hsl(0 0% 100% / 0.6) var(--range), hsl(0 0% 100% / 1) var(--range));\r\n left: 0.5rem;\r\n}\r\n\r\n.slider-value-labels::after {\r\n --range: calc((50 - (var(--value) / 100 * 10)) * 1%);\r\n content: counter(high) \"% \" var(--rightContent);\r\n mask: linear-gradient(90deg, hsl(0 0% 100% / 1) var(--range), hsl(0 0% 100% / 0.5) var(--range));\r\n right: 0.5rem;\r\n}\r\n\r\n.slider-track {\r\n height: calc(50% + (var(--shift) * 50%));\r\n transition: height var(--speed) var(--timing);\r\n}\r\n\r\n.slider-track::before {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n width: calc(var(--value, 0) * 1% - 0.5rem);\r\n background: var(--leftColor);\r\n border-radius: v-bind(borderRadiusInPx);\r\n transition: width var(--update);\r\n}\r\n\r\n.slider-track::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n right: 0;\r\n width: calc((100 - var(--value, 0)) * 1% - 0.5rem);\r\n background: var(--rightColor);\r\n border-radius: v-bind(borderRadiusInPx);\r\n transition: width var(--update);\r\n}\r\n\r\n.slider-indicator {\r\n background: var(--indicatorColor);\r\n left: calc(var(--value, 0) * 1%);\r\n transition: left var(--update);\r\n}\r\n\r\n/* Range input styles */\r\n[type=\"range\"]::-webkit-slider-thumb {\r\n appearance: none;\r\n height: 120px;\r\n width: 40px;\r\n margin-top: 0px;\r\n opacity: 1;\r\n}\r\n\r\n[type=\"range\"]::-webkit-slider-runnable-track {\r\n height: 120px;\r\n background: hsl(10 80% 50% / 0.5);\r\n margin-top: -60px;\r\n box-shadow:\r\n 1px 1px 1px #000000,\r\n 0px 0px 1px #0d0d0d;\r\n}\r\n\r\n[type=\"range\"]::-moz-range-track {\r\n height: 120px;\r\n background: hsl(10 80% 50% / 0.5);\r\n margin-top: -60px;\r\n box-shadow:\r\n 1px 1px 1px #000000,\r\n 0px 0px 1px #0d0d0d;\r\n}\r\n</style>\r\n"
7
+ "content": "<script setup lang=\"ts\">\r\nimport { computed, ref } from \"vue\";\r\n\r\ninterface Props {\r\n initialValue?: number;\r\n leftColor?: string;\r\n rightColor?: string;\r\n minShiftLimit?: number;\r\n maxShiftLimit?: number;\r\n leftContent?: string;\r\n rightContent?: string;\r\n indicatorColor?: string;\r\n borderRadius?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n initialValue: 50,\r\n minShiftLimit: 40,\r\n maxShiftLimit: 68,\r\n leftContent: \"LEFT\",\r\n rightContent: \"RIGHT\",\r\n leftColor: \"#e68a00\",\r\n rightColor: \"#ffffff\",\r\n indicatorColor: \"#FFFFFF\",\r\n borderRadius: 8,\r\n});\r\n\r\nconst value = ref(props.initialValue);\r\nconst active = ref(0);\r\n\r\nconst shift = computed(() =>\r\n value.value > props.minShiftLimit && value.value < props.maxShiftLimit ? 1 : 0,\r\n);\r\n\r\nconst sliderStyles = computed(() => ({\r\n \"--value\": value.value,\r\n \"--shift\": shift.value,\r\n \"--active\": active.value,\r\n \"--leftContent\": `\"${props.leftContent} \"`,\r\n \"--rightContent\": `\" ${props.rightContent}\"`,\r\n \"--indicatorColor\": indicatorColorHsl.value,\r\n}));\r\n\r\nconst sliderLabelStyles = computed(() => ({\r\n \"--shift\": shift.value,\r\n}));\r\n\r\nconst sliderTrackStyles = computed(() => ({\r\n \"--value\": value.value,\r\n \"--shift\": shift.value,\r\n \"--leftColor\": leftColorHsl.value,\r\n \"--rightColor\": rightColorHsl.value,\r\n}));\r\n\r\nconst leftColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.leftColor);\r\n const alpha = 0.4;\r\n const lightness = 24 + (30 * (100 - value.value)) / 100;\r\n return `hsl(${h} ${s}% ${lightness}% / ${alpha})`;\r\n});\r\n\r\nconst rightColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.rightColor);\r\n const alpha = 0.1 + (0.4 * (100 - value.value)) / 100;\r\n return `hsl(${h} ${s}% ${l}% / ${alpha})`;\r\n});\r\n\r\nconst indicatorColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.indicatorColor); // Base color as hex, here white (#ffffff)\r\n const activeAlpha = active.value * 0.5 + 0.5; // Calculate alpha based on active state\r\n return `hsl(${h} ${s}% ${l}% / ${activeAlpha})`;\r\n});\r\n\r\nconst borderRadiusInPx = computed(() => `${props.borderRadius}px`);\r\n\r\nfunction hexToHsl(hex: string): [number, number, number] {\r\n // Remove \"#\" if present\r\n hex = hex.replace(/^#/, \"\");\r\n\r\n // Parse r, g, b values\r\n const r = Number.parseInt(hex.substring(0, 2), 16) / 255;\r\n const g = Number.parseInt(hex.substring(2, 4), 16) / 255;\r\n const b = Number.parseInt(hex.substring(4, 6), 16) / 255;\r\n\r\n // Find min and max values of r, g, b\r\n const max = Math.max(r, g, b);\r\n const min = Math.min(r, g, b);\r\n let h = 0;\r\n let s = 0;\r\n const l = (max + min) / 2;\r\n\r\n if (max != min) {\r\n const d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n\r\n return [h * 360, s * 100, l * 100];\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n class=\"slider-container relative mx-auto my-0 grid place-items-center overflow-hidden\"\r\n :style=\"sliderStyles\"\r\n @mouseenter=\"active = 1\"\r\n @mouseleave=\"active = 0\"\r\n @focusin=\"active = 1\"\r\n @focusout=\"active = 0\"\r\n @touchstart=\"active = 1\"\r\n @touchend=\"active = 0\"\r\n >\r\n <input\r\n id=\"track\"\r\n v-model=\"value\"\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"100\"\r\n class=\"size-full touch-none opacity-0 hover:cursor-grab focus-visible:outline-offset-4 focus-visible:outline-transparent active:cursor-grabbing\"\r\n />\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"slider-value-labels pointer-events-none absolute inset-x-0 top-0 z-[2] h-1/2 text-base\"\r\n :style=\"sliderLabelStyles\"\r\n />\r\n <div\r\n class=\"slider-track pointer-events-none absolute bottom-0 w-full\"\r\n :style=\"sliderTrackStyles\"\r\n >\r\n <div\r\n class=\"slider-indicator absolute top-1/2 z-[2] h-3/4 w-1 -translate-x-1/2 -translate-y-1/2 rounded-sm\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<style scoped>\r\n.slider-container {\r\n --speed: 0.65s;\r\n --update: 0s;\r\n --timing: linear(\r\n 0,\r\n 0.5007 7.21%,\r\n 0.7803 12.29%,\r\n 0.8883 14.93%,\r\n 0.9724 17.63%,\r\n 1.0343 20.44%,\r\n 1.0754 23.44%,\r\n 1.0898 25.22%,\r\n 1.0984 27.11%,\r\n 1.1014 29.15%,\r\n 1.0989 31.4%,\r\n 1.0854 35.23%,\r\n 1.0196 48.86%,\r\n 1.0043 54.06%,\r\n 0.9956 59.6%,\r\n 0.9925 68.11%,\r\n 1\r\n );\r\n}\r\n\r\n.slider-value-labels {\r\n transform: translateY(calc(var(--shift, 0) * 50%));\r\n transition: transform var(--speed) var(--timing);\r\n counter-reset: low var(--value) high calc(100 - var(--value));\r\n}\r\n\r\n.slider-value-labels::after,\r\n.slider-value-labels::before {\r\n font-variant: tabular-nums;\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n font-weight: bold;\r\n color: white;\r\n font-family: monospace;\r\n}\r\n\r\n.slider-value-labels::before {\r\n --range: calc((70 - (var(--value) / 100 * 10)) * 1%);\r\n color: hsl(24 74% 54%);\r\n content: var(--leftContent) counter(low) \"%\";\r\n mask: linear-gradient(90deg, hsl(0 0% 100% / 0.6) var(--range), hsl(0 0% 100% / 1) var(--range));\r\n left: 0.5rem;\r\n}\r\n\r\n.slider-value-labels::after {\r\n --range: calc((50 - (var(--value) / 100 * 10)) * 1%);\r\n content: counter(high) \"% \" var(--rightContent);\r\n mask: linear-gradient(90deg, hsl(0 0% 100% / 1) var(--range), hsl(0 0% 100% / 0.5) var(--range));\r\n right: 0.5rem;\r\n}\r\n\r\n.slider-track {\r\n height: calc(50% + (var(--shift) * 50%));\r\n transition: height var(--speed) var(--timing);\r\n}\r\n\r\n.slider-track::before {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n width: calc(var(--value, 0) * 1% - 0.5rem);\r\n background: var(--leftColor);\r\n border-radius: v-bind(borderRadiusInPx);\r\n transition: width var(--update);\r\n}\r\n\r\n.slider-track::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n right: 0;\r\n width: calc((100 - var(--value, 0)) * 1% - 0.5rem);\r\n background: var(--rightColor);\r\n border-radius: v-bind(borderRadiusInPx);\r\n transition: width var(--update);\r\n}\r\n\r\n.slider-indicator {\r\n background: var(--indicatorColor);\r\n left: calc(var(--value, 0) * 1%);\r\n transition: left var(--update);\r\n}\r\n\r\n/* Range input styles */\r\n[type=\"range\"]::-webkit-slider-thumb {\r\n appearance: none;\r\n height: 120px;\r\n width: 40px;\r\n margin-top: 0px;\r\n opacity: 1;\r\n}\r\n\r\n[type=\"range\"]::-webkit-slider-runnable-track {\r\n height: 120px;\r\n background: hsl(10 80% 50% / 0.5);\r\n margin-top: -60px;\r\n box-shadow:\r\n 1px 1px 1px #000000,\r\n 0px 0px 1px #0d0d0d;\r\n}\r\n\r\n[type=\"range\"]::-moz-range-track {\r\n height: 120px;\r\n background: hsl(10 80% 50% / 0.5);\r\n margin-top: -60px;\r\n box-shadow:\r\n 1px 1px 1px #000000,\r\n 0px 0px 1px #0d0d0d;\r\n}\r\n</style>\r\n",
8
+ "target": "web"
9
+ },
10
+ {
11
+ "path": "BalanceSlider.vue",
12
+ "content": "<script setup lang=\"ts\">\r\nimport { computed, ref } from \"vue\";\r\n\r\ninterface Props {\r\n initialValue?: number;\r\n leftColor?: string;\r\n rightColor?: string;\r\n minShiftLimit?: number;\r\n maxShiftLimit?: number;\r\n leftContent?: string;\r\n rightContent?: string;\r\n indicatorColor?: string;\r\n borderRadius?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n initialValue: 50,\r\n minShiftLimit: 40,\r\n maxShiftLimit: 68,\r\n leftContent: \"LEFT\",\r\n rightContent: \"RIGHT\",\r\n leftColor: \"#e68a00\",\r\n rightColor: \"#ffffff\",\r\n indicatorColor: \"#FFFFFF\",\r\n borderRadius: 8,\r\n});\r\n\r\nconst value = ref(props.initialValue);\r\nconst active = ref(0);\r\n\r\nconst shift = computed(() =>\r\n value.value > props.minShiftLimit && value.value < props.maxShiftLimit ? 1 : 0,\r\n);\r\n\r\nconst sliderStyles = computed(() => ({\r\n \"--value\": value.value,\r\n \"--shift\": shift.value,\r\n \"--active\": active.value,\r\n \"--leftContent\": `\"${props.leftContent} \"`,\r\n \"--rightContent\": `\" ${props.rightContent}\"`,\r\n \"--indicatorColor\": indicatorColorHsl.value,\r\n}));\r\n\r\nconst sliderLabelStyles = computed(() => ({\r\n \"--shift\": shift.value,\r\n}));\r\n\r\nconst sliderTrackStyles = computed(() => ({\r\n \"--value\": value.value,\r\n \"--shift\": shift.value,\r\n \"--leftColor\": leftColorHsl.value,\r\n \"--rightColor\": rightColorHsl.value,\r\n}));\r\n\r\nconst leftColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.leftColor);\r\n const alpha = 0.4;\r\n const lightness = 24 + (30 * (100 - value.value)) / 100;\r\n return `hsl(${h} ${s}% ${lightness}% / ${alpha})`;\r\n});\r\n\r\nconst rightColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.rightColor);\r\n const alpha = 0.1 + (0.4 * (100 - value.value)) / 100;\r\n return `hsl(${h} ${s}% ${l}% / ${alpha})`;\r\n});\r\n\r\nconst indicatorColorHsl = computed(() => {\r\n const [h, s, l] = hexToHsl(props.indicatorColor); // Base color as hex, here white (#ffffff)\r\n const activeAlpha = active.value * 0.5 + 0.5; // Calculate alpha based on active state\r\n return `hsl(${h} ${s}% ${l}% / ${activeAlpha})`;\r\n});\r\n\r\nconst borderRadiusInPx = computed(() => `${props.borderRadius}px`);\r\n\r\nfunction hexToHsl(hex: string): [number, number, number] {\r\n // Remove \"#\" if present\r\n hex = hex.replace(/^#/, \"\");\r\n\r\n // Parse r, g, b values\r\n const r = Number.parseInt(hex.substring(0, 2), 16) / 255;\r\n const g = Number.parseInt(hex.substring(2, 4), 16) / 255;\r\n const b = Number.parseInt(hex.substring(4, 6), 16) / 255;\r\n\r\n // Find min and max values of r, g, b\r\n const max = Math.max(r, g, b);\r\n const min = Math.min(r, g, b);\r\n let h = 0;\r\n let s = 0;\r\n const l = (max + min) / 2;\r\n\r\n if (max != min) {\r\n const d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n\r\n return [h * 360, s * 100, l * 100];\r\n}\r\n</script>\r\n\r\n<template>\r\n <view\r\n class=\"slider-container relative mx-auto my-0 grid place-items-center overflow-hidden\"\r\n :style=\"sliderStyles\"\r\n @mouseenter=\"active = 1\"\r\n @mouseleave=\"active = 0\"\r\n @focusin=\"active = 1\"\r\n @focusout=\"active = 0\"\r\n @touchstart=\"active = 1\"\r\n @touchend=\"active = 0\"\r\n >\r\n <input\r\n id=\"track\"\r\n v-model=\"value\"\r\n type=\"range\"\r\n min=\"0\"\r\n max=\"100\"\r\n class=\"size-full touch-none opacity-0 hover:cursor-grab focus-visible:outline-offset-4 focus-visible:outline-transparent active:cursor-grabbing\"\r\n />\r\n <view\r\n aria-hidden=\"true\"\r\n class=\"slider-value-labels pointer-events-none absolute inset-x-0 top-0 z-[2] h-1/2 text-base\"\r\n :style=\"sliderLabelStyles\"\r\n />\r\n <view\r\n class=\"slider-track pointer-events-none absolute bottom-0 w-full\"\r\n :style=\"sliderTrackStyles\"\r\n >\r\n <view\r\n class=\"slider-indicator absolute top-1/2 z-[2] h-3/4 w-1 -translate-x-1/2 -translate-y-1/2 rounded-sm\"\r\n />\r\n </view>\r\n </view>\r\n</template>\r\n\r\n<style scoped>\r\n.slider-container {\r\n --speed: 0.65s;\r\n --update: 0s;\r\n --timing: linear(\r\n 0,\r\n 0.5007 7.21%,\r\n 0.7803 12.29%,\r\n 0.8883 14.93%,\r\n 0.9724 17.63%,\r\n 1.0343 20.44%,\r\n 1.0754 23.44%,\r\n 1.0898 25.22%,\r\n 1.0984 27.11%,\r\n 1.1014 29.15%,\r\n 1.0989 31.4%,\r\n 1.0854 35.23%,\r\n 1.0196 48.86%,\r\n 1.0043 54.06%,\r\n 0.9956 59.6%,\r\n 0.9925 68.11%,\r\n 1\r\n );\r\n}\r\n\r\n.slider-value-labels {\r\n transform: translateY(calc(var(--shift, 0) * 50%));\r\n transition: transform var(--speed) var(--timing);\r\n counter-reset: low var(--value) high calc(100 - var(--value));\r\n}\r\n\r\n.slider-value-labels::after,\r\n.slider-value-labels::before {\r\n font-variant: tabular-nums;\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n font-weight: bold;\r\n color: white;\r\n font-family: monospace;\r\n}\r\n\r\n.slider-value-labels::before {\r\n --range: calc((70 - (var(--value) / 100 * 10)) * 1%);\r\n color: hsl(24 74% 54%);\r\n content: var(--leftContent) counter(low) \"%\";\r\n mask: linear-gradient(90deg, hsl(0 0% 100% / 0.6) var(--range), hsl(0 0% 100% / 1) var(--range));\r\n left: 0.5rem;\r\n}\r\n\r\n.slider-value-labels::after {\r\n --range: calc((50 - (var(--value) / 100 * 10)) * 1%);\r\n content: counter(high) \"% \" var(--rightContent);\r\n mask: linear-gradient(90deg, hsl(0 0% 100% / 1) var(--range), hsl(0 0% 100% / 0.5) var(--range));\r\n right: 0.5rem;\r\n}\r\n\r\n.slider-track {\r\n height: calc(50% + (var(--shift) * 50%));\r\n transition: height var(--speed) var(--timing);\r\n}\r\n\r\n.slider-track::before {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n width: calc(var(--value, 0) * 1% - 0.5rem);\r\n background: var(--leftColor);\r\n border-radius: v-bind(borderRadiusInPx);\r\n transition: width var(--update);\r\n}\r\n\r\n.slider-track::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n bottom: 0;\r\n right: 0;\r\n width: calc((100 - var(--value, 0)) * 1% - 0.5rem);\r\n background: var(--rightColor);\r\n border-radius: v-bind(borderRadiusInPx);\r\n transition: width var(--update);\r\n}\r\n\r\n.slider-indicator {\r\n background: var(--indicatorColor);\r\n left: calc(var(--value, 0) * 1%);\r\n transition: left var(--update);\r\n}\r\n\r\n/* Range input styles */\r\n[type=\"range\"]::-webkit-slider-thumb {\r\n appearance: none;\r\n height: 120px;\r\n width: 40px;\r\n margin-top: 0px;\r\n opacity: 1;\r\n}\r\n\r\n[type=\"range\"]::-webkit-slider-runnable-track {\r\n height: 120px;\r\n background: hsl(10 80% 50% / 0.5);\r\n margin-top: -60px;\r\n box-shadow:\r\n 1px 1px 1px #000000,\r\n 0px 0px 1px #0d0d0d;\r\n}\r\n\r\n[type=\"range\"]::-moz-range-track {\r\n height: 120px;\r\n background: hsl(10 80% 50% / 0.5);\r\n margin-top: -60px;\r\n box-shadow:\r\n 1px 1px 1px #000000,\r\n 0px 0px 1px #0d0d0d;\r\n}\r\n</style>\r\n",
13
+ "target": "uniapp"
8
14
  },
9
15
  {
10
16
  "path": "index.ts",
11
17
  "content": "export { default as BalanceSlider } from \"./BalanceSlider.vue\";\r\n"
12
18
  }
13
19
  ],
14
- "fileCount": 2,
15
- "contentHash": "511269f6a6bdd94fdaa1df002128a40f6376aafe"
20
+ "fileCount": 3,
21
+ "contentHash": "67cb69ce4398d7157212fd05de834ec51327c488"
16
22
  }