cinqcinqdev-seo 0.1.71 → 0.1.73

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 (123) hide show
  1. package/README.md +39 -2
  2. package/dist/module.json +1 -1
  3. package/dist/runtime/assets/admin-tw.css +1 -1
  4. package/dist/runtime/components/admin-cms/DynamicRenderer.vue +16 -2
  5. package/dist/runtime/components/sections/{BlogHero.vue → cinqcinq/BlogHero.vue} +35 -3
  6. package/dist/runtime/components/sections/{CallToAction.vue → cinqcinq/CallToAction.vue} +35 -3
  7. package/dist/runtime/components/sections/{ContactForm.vue → cinqcinq/ContactForm.vue} +34 -2
  8. package/dist/runtime/components/sections/{FAQ.vue → cinqcinq/FAQ.vue} +35 -3
  9. package/dist/runtime/components/sections/{Features.vue → cinqcinq/Features.vue} +35 -3
  10. package/dist/runtime/components/sections/{HeroSection.vue → cinqcinq/HeroSection.vue} +11 -0
  11. package/dist/runtime/components/sections/{Newsletter.vue → cinqcinq/Newsletter.vue} +35 -3
  12. package/dist/runtime/components/sections/{Pricing.vue → cinqcinq/Pricing.vue} +35 -3
  13. package/dist/runtime/components/sections/{Process.vue → cinqcinq/Process.vue} +35 -3
  14. package/dist/runtime/components/sections/{Quote.vue → cinqcinq/Quote.vue} +35 -3
  15. package/dist/runtime/components/sections/{RichText.vue → cinqcinq/RichText.vue} +32 -4
  16. package/dist/runtime/components/sections/{ServiceGrid.vue → cinqcinq/ServiceGrid.vue} +35 -3
  17. package/dist/runtime/components/sections/{Testimonials.vue → cinqcinq/Testimonials.vue} +35 -3
  18. package/dist/runtime/components/sections/{TextVisual.vue → cinqcinq/TextVisual.vue} +39 -3
  19. package/dist/runtime/components/sections/swiss-style/BlogHero.d.vue.ts +3 -0
  20. package/dist/runtime/components/sections/swiss-style/BlogHero.vue +146 -0
  21. package/dist/runtime/components/sections/swiss-style/BlogHero.vue.d.ts +3 -0
  22. package/dist/runtime/components/sections/swiss-style/CallToAction.d.vue.ts +3 -0
  23. package/dist/runtime/components/sections/swiss-style/CallToAction.vue +138 -0
  24. package/dist/runtime/components/sections/swiss-style/CallToAction.vue.d.ts +3 -0
  25. package/dist/runtime/components/sections/swiss-style/Comparison.d.vue.ts +3 -0
  26. package/dist/runtime/components/sections/swiss-style/Comparison.vue +280 -0
  27. package/dist/runtime/components/sections/swiss-style/Comparison.vue.d.ts +3 -0
  28. package/dist/runtime/components/sections/swiss-style/ContactForm.d.vue.ts +3 -0
  29. package/dist/runtime/components/sections/swiss-style/ContactForm.vue +173 -0
  30. package/dist/runtime/components/sections/swiss-style/ContactForm.vue.d.ts +3 -0
  31. package/dist/runtime/components/sections/swiss-style/DataTable.d.vue.ts +3 -0
  32. package/dist/runtime/components/sections/swiss-style/DataTable.vue +245 -0
  33. package/dist/runtime/components/sections/swiss-style/DataTable.vue.d.ts +3 -0
  34. package/dist/runtime/components/sections/swiss-style/FAQ.d.vue.ts +3 -0
  35. package/dist/runtime/components/sections/swiss-style/FAQ.vue +107 -0
  36. package/dist/runtime/components/sections/swiss-style/FAQ.vue.d.ts +3 -0
  37. package/dist/runtime/components/sections/swiss-style/Features.d.vue.ts +3 -0
  38. package/dist/runtime/components/sections/swiss-style/Features.vue +103 -0
  39. package/dist/runtime/components/sections/swiss-style/Features.vue.d.ts +3 -0
  40. package/dist/runtime/components/sections/swiss-style/HeroFan.d.vue.ts +3 -0
  41. package/dist/runtime/components/sections/swiss-style/HeroFan.vue +108 -0
  42. package/dist/runtime/components/sections/swiss-style/HeroFan.vue.d.ts +3 -0
  43. package/dist/runtime/components/sections/swiss-style/HeroSection.d.vue.ts +3 -0
  44. package/dist/runtime/components/sections/swiss-style/HeroSection.vue +190 -0
  45. package/dist/runtime/components/sections/swiss-style/HeroSection.vue.d.ts +3 -0
  46. package/dist/runtime/components/sections/swiss-style/HeroSlider.d.vue.ts +3 -0
  47. package/dist/runtime/components/sections/swiss-style/HeroSlider.vue +138 -0
  48. package/dist/runtime/components/sections/swiss-style/HeroSlider.vue.d.ts +3 -0
  49. package/dist/runtime/components/sections/swiss-style/Newsletter.d.vue.ts +3 -0
  50. package/dist/runtime/components/sections/swiss-style/Newsletter.vue +125 -0
  51. package/dist/runtime/components/sections/swiss-style/Newsletter.vue.d.ts +3 -0
  52. package/dist/runtime/components/sections/swiss-style/Pricing.d.vue.ts +3 -0
  53. package/dist/runtime/components/sections/swiss-style/Pricing.vue +148 -0
  54. package/dist/runtime/components/sections/swiss-style/Pricing.vue.d.ts +3 -0
  55. package/dist/runtime/components/sections/swiss-style/Process.d.vue.ts +3 -0
  56. package/dist/runtime/components/sections/swiss-style/Process.vue +124 -0
  57. package/dist/runtime/components/sections/swiss-style/Process.vue.d.ts +3 -0
  58. package/dist/runtime/components/sections/swiss-style/Quote.d.vue.ts +3 -0
  59. package/dist/runtime/components/sections/swiss-style/Quote.vue +130 -0
  60. package/dist/runtime/components/sections/swiss-style/Quote.vue.d.ts +3 -0
  61. package/dist/runtime/components/sections/swiss-style/RelatedPages.d.vue.ts +3 -0
  62. package/dist/runtime/components/sections/swiss-style/RelatedPages.vue +212 -0
  63. package/dist/runtime/components/sections/swiss-style/RelatedPages.vue.d.ts +3 -0
  64. package/dist/runtime/components/sections/swiss-style/RichText.d.vue.ts +3 -0
  65. package/dist/runtime/components/sections/swiss-style/RichText.vue +100 -0
  66. package/dist/runtime/components/sections/swiss-style/RichText.vue.d.ts +3 -0
  67. package/dist/runtime/components/sections/swiss-style/ServiceGrid.d.vue.ts +3 -0
  68. package/dist/runtime/components/sections/swiss-style/ServiceGrid.vue +121 -0
  69. package/dist/runtime/components/sections/swiss-style/ServiceGrid.vue.d.ts +3 -0
  70. package/dist/runtime/components/sections/swiss-style/Testimonials.d.vue.ts +3 -0
  71. package/dist/runtime/components/sections/swiss-style/Testimonials.vue +126 -0
  72. package/dist/runtime/components/sections/swiss-style/Testimonials.vue.d.ts +3 -0
  73. package/dist/runtime/components/sections/swiss-style/TextVisual.d.vue.ts +3 -0
  74. package/dist/runtime/components/sections/swiss-style/TextVisual.vue +146 -0
  75. package/dist/runtime/components/sections/swiss-style/TextVisual.vue.d.ts +3 -0
  76. package/dist/runtime/composables/useAdminSections.js +75 -37
  77. package/dist/runtime/composables/useAdminSettings.d.ts +1 -0
  78. package/dist/runtime/pages/admin/editor/[id].vue +15 -1
  79. package/dist/runtime/pages/admin/setup.vue +77 -2
  80. package/package.json +1 -1
  81. /package/dist/runtime/components/sections/{BlogHero.d.vue.ts → cinqcinq/BlogHero.d.vue.ts} +0 -0
  82. /package/dist/runtime/components/sections/{BlogHero.vue.d.ts → cinqcinq/BlogHero.vue.d.ts} +0 -0
  83. /package/dist/runtime/components/sections/{CallToAction.d.vue.ts → cinqcinq/CallToAction.d.vue.ts} +0 -0
  84. /package/dist/runtime/components/sections/{CallToAction.vue.d.ts → cinqcinq/CallToAction.vue.d.ts} +0 -0
  85. /package/dist/runtime/components/sections/{Comparison.d.vue.ts → cinqcinq/Comparison.d.vue.ts} +0 -0
  86. /package/dist/runtime/components/sections/{Comparison.vue → cinqcinq/Comparison.vue} +0 -0
  87. /package/dist/runtime/components/sections/{Comparison.vue.d.ts → cinqcinq/Comparison.vue.d.ts} +0 -0
  88. /package/dist/runtime/components/sections/{ContactForm.d.vue.ts → cinqcinq/ContactForm.d.vue.ts} +0 -0
  89. /package/dist/runtime/components/sections/{ContactForm.vue.d.ts → cinqcinq/ContactForm.vue.d.ts} +0 -0
  90. /package/dist/runtime/components/sections/{DataTable.d.vue.ts → cinqcinq/DataTable.d.vue.ts} +0 -0
  91. /package/dist/runtime/components/sections/{DataTable.vue → cinqcinq/DataTable.vue} +0 -0
  92. /package/dist/runtime/components/sections/{DataTable.vue.d.ts → cinqcinq/DataTable.vue.d.ts} +0 -0
  93. /package/dist/runtime/components/sections/{FAQ.d.vue.ts → cinqcinq/FAQ.d.vue.ts} +0 -0
  94. /package/dist/runtime/components/sections/{FAQ.vue.d.ts → cinqcinq/FAQ.vue.d.ts} +0 -0
  95. /package/dist/runtime/components/sections/{Features.d.vue.ts → cinqcinq/Features.d.vue.ts} +0 -0
  96. /package/dist/runtime/components/sections/{Features.vue.d.ts → cinqcinq/Features.vue.d.ts} +0 -0
  97. /package/dist/runtime/components/sections/{HeroFan.d.vue.ts → cinqcinq/HeroFan.d.vue.ts} +0 -0
  98. /package/dist/runtime/components/sections/{HeroFan.vue → cinqcinq/HeroFan.vue} +0 -0
  99. /package/dist/runtime/components/sections/{HeroFan.vue.d.ts → cinqcinq/HeroFan.vue.d.ts} +0 -0
  100. /package/dist/runtime/components/sections/{HeroSection.d.vue.ts → cinqcinq/HeroSection.d.vue.ts} +0 -0
  101. /package/dist/runtime/components/sections/{HeroSection.vue.d.ts → cinqcinq/HeroSection.vue.d.ts} +0 -0
  102. /package/dist/runtime/components/sections/{HeroSlider.d.vue.ts → cinqcinq/HeroSlider.d.vue.ts} +0 -0
  103. /package/dist/runtime/components/sections/{HeroSlider.vue → cinqcinq/HeroSlider.vue} +0 -0
  104. /package/dist/runtime/components/sections/{HeroSlider.vue.d.ts → cinqcinq/HeroSlider.vue.d.ts} +0 -0
  105. /package/dist/runtime/components/sections/{Newsletter.d.vue.ts → cinqcinq/Newsletter.d.vue.ts} +0 -0
  106. /package/dist/runtime/components/sections/{Newsletter.vue.d.ts → cinqcinq/Newsletter.vue.d.ts} +0 -0
  107. /package/dist/runtime/components/sections/{Pricing.d.vue.ts → cinqcinq/Pricing.d.vue.ts} +0 -0
  108. /package/dist/runtime/components/sections/{Pricing.vue.d.ts → cinqcinq/Pricing.vue.d.ts} +0 -0
  109. /package/dist/runtime/components/sections/{Process.d.vue.ts → cinqcinq/Process.d.vue.ts} +0 -0
  110. /package/dist/runtime/components/sections/{Process.vue.d.ts → cinqcinq/Process.vue.d.ts} +0 -0
  111. /package/dist/runtime/components/sections/{Quote.d.vue.ts → cinqcinq/Quote.d.vue.ts} +0 -0
  112. /package/dist/runtime/components/sections/{Quote.vue.d.ts → cinqcinq/Quote.vue.d.ts} +0 -0
  113. /package/dist/runtime/components/sections/{RelatedPages.d.vue.ts → cinqcinq/RelatedPages.d.vue.ts} +0 -0
  114. /package/dist/runtime/components/sections/{RelatedPages.vue → cinqcinq/RelatedPages.vue} +0 -0
  115. /package/dist/runtime/components/sections/{RelatedPages.vue.d.ts → cinqcinq/RelatedPages.vue.d.ts} +0 -0
  116. /package/dist/runtime/components/sections/{RichText.d.vue.ts → cinqcinq/RichText.d.vue.ts} +0 -0
  117. /package/dist/runtime/components/sections/{RichText.vue.d.ts → cinqcinq/RichText.vue.d.ts} +0 -0
  118. /package/dist/runtime/components/sections/{ServiceGrid.d.vue.ts → cinqcinq/ServiceGrid.d.vue.ts} +0 -0
  119. /package/dist/runtime/components/sections/{ServiceGrid.vue.d.ts → cinqcinq/ServiceGrid.vue.d.ts} +0 -0
  120. /package/dist/runtime/components/sections/{Testimonials.d.vue.ts → cinqcinq/Testimonials.d.vue.ts} +0 -0
  121. /package/dist/runtime/components/sections/{Testimonials.vue.d.ts → cinqcinq/Testimonials.vue.d.ts} +0 -0
  122. /package/dist/runtime/components/sections/{TextVisual.d.vue.ts → cinqcinq/TextVisual.d.vue.ts} +0 -0
  123. /package/dist/runtime/components/sections/{TextVisual.vue.d.ts → cinqcinq/TextVisual.vue.d.ts} +0 -0
@@ -0,0 +1,103 @@
1
+ <template>
2
+ <section ref="sectionEl" :class="[sectionPad, isVisible ? 'sv-in' : 'sv-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
+ <div :class="[containerClass]">
4
+
5
+ <!-- Header -->
6
+ <div class="border-b mb-0 pb-6 flex items-end justify-between gap-8" :style="{ borderColor: ca(textColor,'15') }">
7
+ <component :is="titleTag" class="font-black uppercase leading-[0.88]" :style="{ fontSize: titleFontSize, letterSpacing: '-0.03em' }">{{ title }}</component>
8
+ <span class="text-[9px] font-black uppercase tracking-[0.4em] shrink-0 pb-1" :style="{ opacity: 0.3 }">{{ items.length || 3 }} items</span>
9
+ </div>
10
+
11
+ <!-- Grid -->
12
+ <div v-if="items.length" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 border-b" :style="{ borderColor: ca(textColor,'10') }">
13
+ <div v-for="(item, index) in items" :key="index"
14
+ class="p-8 border-b border-r last:border-r-0 md:[&:nth-child(2n)]:border-r-0 lg:[&:nth-child(2n)]:border-r lg:[&:nth-child(3n)]:border-r-0 transition-colors hover:bg-black/[0.02]"
15
+ :style="{ borderColor: ca(textColor,'10') }">
16
+ <div class="flex items-start justify-between mb-6">
17
+ <span class="font-black tabular-nums" :style="{ fontSize: 'clamp(1.8rem,3vw,2.5rem)', opacity: 0.12, letterSpacing: '-0.04em' }">{{ String(index + 1).padStart(2, '0') }}</span>
18
+ <div class="w-px self-stretch" :style="{ backgroundColor: ca(textColor,'10') }"></div>
19
+ </div>
20
+ <component :is="itemTag" class="font-black uppercase tracking-tight mb-3 leading-tight">{{ item.title }}</component>
21
+ <p :class="[bodyClass, 'leading-relaxed']" :style="{ opacity: 0.55 }">{{ item.description || item.text }}</p>
22
+ </div>
23
+ </div>
24
+
25
+ <!-- Placeholder -->
26
+ <div v-else class="grid grid-cols-1 md:grid-cols-3 border-b" :style="{ borderColor: ca(textColor,'10') }">
27
+ <div v-for="n in 3" :key="n" class="p-8 border-r last:border-r-0" :style="{ borderColor: ca(textColor,'10') }">
28
+ <span class="block font-black tabular-nums mb-6" :style="{ fontSize: '2rem', opacity: 0.08 }">0{{ n }}</span>
29
+ <div class="h-4 mb-3" :style="{ backgroundColor: ca(textColor,'12'), width: '60%' }"></div>
30
+ <div class="h-3" :style="{ backgroundColor: ca(textColor,'08'), width: '80%' }"></div>
31
+ </div>
32
+ </div>
33
+
34
+ </div>
35
+ </section>
36
+ </template>
37
+
38
+ <script setup>
39
+ const ca = (c, h) => {
40
+ const m = c?.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
41
+ return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : (c || "") + h;
42
+ };
43
+ import { ref, computed, onMounted } from "vue";
44
+ const props = defineProps({
45
+ title: { type: String, default: "Why choose us?" },
46
+ titleTag: { type: String, default: "h2" },
47
+ itemTag: { type: String, default: "h3" },
48
+ items: { type: Array, default: () => [] },
49
+ bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
50
+ textColor: { type: String, default: "rgba(var(--text-color), 1)" },
51
+ spacing: { type: String, default: "normal" },
52
+ radius: { type: String, default: "sharp" },
53
+ textDirection: { type: String, default: "ltr" },
54
+ contentWidth: { type: String, default: "normal" },
55
+ textSize: { type: String, default: "md" },
56
+ paddingTop: { type: String, default: "" },
57
+ paddingBottom: { type: String, default: "" },
58
+ marginTop: { type: String, default: "" },
59
+ marginBottom: { type: String, default: "" },
60
+ paddingX: { type: String, default: "" }
61
+ });
62
+ const sectionEl = ref(null);
63
+ const isVisible = ref(false);
64
+ onMounted(() => {
65
+ const obs = new IntersectionObserver(([e]) => {
66
+ if (e.isIntersecting) {
67
+ isVisible.value = true;
68
+ obs.disconnect();
69
+ }
70
+ }, { threshold: 0.06 });
71
+ if (sectionEl.value) obs.observe(sectionEl.value);
72
+ setTimeout(() => {
73
+ if (!isVisible.value) isVisible.value = true;
74
+ }, 300);
75
+ });
76
+ const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-8 md:px-16", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-8 md:px-16");
77
+ const containerClass = computed(() => ({ narrow: "max-w-3xl mx-auto", normal: "max-w-6xl mx-auto", wide: "max-w-7xl mx-auto", full: "max-w-full" })[props.contentWidth] || "max-w-6xl mx-auto");
78
+ const titleFontSize = computed(() => ({ sm: "clamp(1.2rem,2vw,1.8rem)", md: "clamp(1.8rem,3vw,2.8rem)", lg: "clamp(2.5rem,6vw,5rem)" })[props.textSize] || "clamp(1.8rem,3vw,2.8rem)");
79
+ const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
80
+ const SM = { none: "0", xs: "8px", sm: "24px", md: "48px", lg: "80px", xl: "128px", "-xs": "-8px", "-sm": "-24px", "-md": "-48px", "-lg": "-80px", "-xl": "-128px" };
81
+ const spacingStyle = computed(() => {
82
+ const s = {};
83
+ if (props.paddingTop && SM[props.paddingTop]) s.paddingTop = SM[props.paddingTop];
84
+ if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
85
+ if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
86
+ if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
87
+ if (props.paddingX && SM[props.paddingX]) {
88
+ const v = SM[props.paddingX];
89
+ if (v.startsWith("-")) {
90
+ s.marginLeft = v;
91
+ s.marginRight = v;
92
+ } else {
93
+ s.paddingLeft = v;
94
+ s.paddingRight = v;
95
+ }
96
+ }
97
+ return s;
98
+ });
99
+ </script>
100
+
101
+ <style scoped>
102
+ .sv-out{opacity:0;transform:translateY(16px)}.sv-in{opacity:1;transform:none;transition:opacity .6s ease,transform .6s ease}
103
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: any;
@@ -0,0 +1,3 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: any;
@@ -0,0 +1,108 @@
1
+ <template>
2
+ <section
3
+ ref="rootEl"
4
+ class="relative overflow-hidden"
5
+ :dir="textDirection"
6
+ :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]"
7
+ >
8
+ <div :class="['relative mx-auto px-8 md:px-16', containerClass, variant === 'compact' ? 'py-14 md:py-20' : 'py-20 md:py-28']">
9
+
10
+ <!-- Grid layout: text left, images right -->
11
+ <div class="grid md:grid-cols-2 gap-12 md:gap-16 items-center">
12
+
13
+ <!-- Left: text block -->
14
+ <div>
15
+ <div class="border-l-4 pl-8 mb-10" :style="{ borderColor: textColor }">
16
+ <component :is="titleTag" class="font-black uppercase leading-[0.88]" :style="{ fontSize: titleFontSize, letterSpacing: '-0.04em' }">
17
+ {{ title }}
18
+ <template v-if="titleLine2Prefix || titleHighlight">
19
+ <br />
20
+ <span v-if="titleLine2Prefix">{{ titleLine2Prefix }} </span>
21
+ <span v-if="titleHighlight" :style="{ color: highlightColor }">{{ titleHighlight }}</span>
22
+ </template>
23
+ </component>
24
+ </div>
25
+
26
+ <p v-if="description" class="text-sm leading-relaxed mb-8 max-w-sm" :style="{ opacity: 0.6 }">{{ description }}</p>
27
+
28
+ <div v-if="primaryCtaText || secondaryCtaText" class="flex flex-wrap gap-3">
29
+ <NuxtLink v-if="primaryCtaText" :to="primaryCtaLink || '#'"
30
+ class="inline-flex items-center gap-3 px-7 py-3.5 text-[11px] font-black uppercase tracking-widest border transition-all hover:gap-6"
31
+ :style="{ backgroundColor: textColor, color: bgColor, borderColor: textColor }">
32
+ {{ primaryCtaText }}<span>→</span>
33
+ </NuxtLink>
34
+ <NuxtLink v-if="secondaryCtaText" :to="secondaryCtaLink || '#'"
35
+ class="inline-flex items-center gap-3 px-7 py-3.5 border text-[11px] font-black uppercase tracking-widest transition-all hover:gap-6"
36
+ :style="{ borderColor: ca(textColor,'30'), color: textColor }">
37
+ {{ secondaryCtaText }}
38
+ </NuxtLink>
39
+ </div>
40
+
41
+ <p v-if="socialProof" class="text-xs font-medium mt-4 border-t pt-4" :style="{ opacity: 0.4, borderColor: ca(textColor,'12') }">{{ socialProof }}</p>
42
+ </div>
43
+
44
+ <!-- Right: images grid -->
45
+ <div v-if="images?.length" class="grid grid-cols-2 gap-2">
46
+ <div
47
+ v-for="(img, i) in images.slice(0, 4)" :key="i"
48
+ :class="['overflow-hidden border', i === 0 ? 'col-span-2 aspect-[16/7]' : 'aspect-square']"
49
+ :style="{ borderColor: ca(textColor,'12') }"
50
+ >
51
+ <img :src="typeof img === 'object' ? img.url : img" :alt="typeof img === 'object' ? (img.alt || '') : ''" class="w-full h-full object-cover" />
52
+ </div>
53
+ <div v-if="!images.length" v-for="n in 3" :key="n" :class="['border', n === 1 ? 'col-span-2 aspect-[16/7]' : 'aspect-square']" :style="{ borderColor: ca(textColor,'10'), backgroundColor: ca(textColor,'04') }"></div>
54
+ </div>
55
+ <div v-else class="grid grid-cols-2 gap-2">
56
+ <div v-for="n in 3" :key="n" :class="['border', n === 1 ? 'col-span-2 aspect-[16/7]' : 'aspect-square']" :style="{ borderColor: ca(textColor,'10'), backgroundColor: ca(textColor,'04') }"></div>
57
+ </div>
58
+
59
+ </div>
60
+ </div>
61
+ </section>
62
+ </template>
63
+
64
+ <script setup>
65
+ import { ref, computed } from "vue";
66
+ const ca = (c, h) => {
67
+ if (!c) return "#000" + h;
68
+ const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
69
+ return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
70
+ };
71
+ const props = defineProps({
72
+ titleTag: { type: String, default: "h1" },
73
+ title: { type: String, default: "The Headline" },
74
+ titleLine2Prefix: { type: String, default: "" },
75
+ titleHighlight: { type: String, default: "Highlighted" },
76
+ highlightColor: { type: String, default: "rgba(var(--primary-color), 1)" },
77
+ description: { type: String, default: "A compelling subtitle that explains your value proposition clearly." },
78
+ socialProof: { type: String, default: "" },
79
+ primaryCtaText: { type: String, default: "Get Started" },
80
+ primaryCtaLink: { type: String, default: "#" },
81
+ secondaryCtaText: { type: String, default: "" },
82
+ secondaryCtaLink: { type: String, default: "#" },
83
+ images: { type: Array, default: () => [] },
84
+ variant: { type: String, default: "standard" },
85
+ animation: { type: String, default: "subtle" },
86
+ bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
87
+ textColor: { type: String, default: "rgba(var(--text-color), 1)" },
88
+ contentWidth: { type: String, default: "normal" },
89
+ textSize: { type: String, default: "md" },
90
+ textDirection: { type: String, default: "ltr" },
91
+ paddingTop: { type: String, default: "" },
92
+ paddingBottom: { type: String, default: "" },
93
+ marginTop: { type: String, default: "" },
94
+ marginBottom: { type: String, default: "" }
95
+ });
96
+ const rootEl = ref(null);
97
+ const containerClass = computed(() => ({ narrow: "max-w-4xl mx-auto", normal: "max-w-6xl mx-auto", wide: "max-w-7xl mx-auto", full: "max-w-full" })[props.contentWidth] || "max-w-6xl mx-auto");
98
+ const titleFontSize = computed(() => ({ sm: "clamp(2rem,4vw,3.5rem)", md: "clamp(2.5rem,5vw,4.5rem)", lg: "clamp(3rem,7vw,6rem)" })[props.textSize] || "clamp(2.5rem,5vw,4.5rem)");
99
+ const SM = { none: "0", xs: "8px", sm: "24px", md: "48px", lg: "80px", xl: "128px", "-xs": "-8px", "-sm": "-24px", "-md": "-48px", "-lg": "-80px", "-xl": "-128px" };
100
+ const spacingStyle = computed(() => {
101
+ const s = {};
102
+ if (props.paddingTop && SM[props.paddingTop]) s.paddingTop = SM[props.paddingTop];
103
+ if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
104
+ if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
105
+ if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
106
+ return s;
107
+ });
108
+ </script>
@@ -0,0 +1,3 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: any;
@@ -0,0 +1,3 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: any;
@@ -0,0 +1,190 @@
1
+ <template>
2
+ <section ref="sectionEl" class="relative" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
+
4
+ <!-- CENTERED -->
5
+ <div v-if="layout === 'centered'" class="px-8 md:px-16 pt-20 pb-16" :class="[containerClass]">
6
+ <div class="border-l-4 pl-8 mb-12" :style="{ borderColor: textColor }">
7
+ <span v-if="badge" class="block text-[9px] font-black uppercase tracking-[0.5em] mb-4" :style="{ opacity: 0.4 }">{{ badge }}</span>
8
+ <component :is="titleTag" :class="['font-black uppercase leading-[0.85] mb-0', isVisible ? 'sv-in' : 'sv-out']" :style="{ fontSize: titleSize === 'sm' ? 'clamp(2.5rem,5vw,4rem)' : titleSize === 'lg' ? 'clamp(3.5rem,9vw,8rem)' : 'clamp(3rem,7vw,6rem)', letterSpacing: '-0.03em' }">{{ title }}</component>
9
+ </div>
10
+ <div class="grid md:grid-cols-2 gap-12 items-end border-t pt-8" :style="{ borderColor: ca(textColor,'15') }">
11
+ <p class="text-sm leading-relaxed" :style="{ opacity: 0.55 }">{{ subtitle }}</p>
12
+ <div class="flex items-center gap-6">
13
+ <div class="h-px flex-1" :style="{ backgroundColor: ca(textColor,'20') }"></div>
14
+ <NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-3 px-6 py-3 border text-[11px] font-black uppercase tracking-widest transition-all hover:gap-6" :style="{ borderColor: textColor, color: textColor }">{{ ctaText }}<span>→</span></NuxtLink>
15
+ </div>
16
+ </div>
17
+ <div v-if="image" class="mt-12 aspect-video overflow-hidden border" :style="{ borderColor: ca(textColor,'15') }">
18
+ <img :src="image" class="w-full h-full object-cover" />
19
+ </div>
20
+ </div>
21
+
22
+ <!-- SPLIT -->
23
+ <div v-else-if="layout === 'split'" class="px-8 md:px-16 py-16">
24
+ <div :class="[containerClass, 'grid md:grid-cols-2 gap-0 border', isVisible ? 'sv-in' : 'sv-out']" :style="{ borderColor: ca(textColor,'20') }">
25
+ <div class="p-10 md:p-14 border-b md:border-b-0 md:border-r flex flex-col justify-between" :style="{ borderColor: ca(textColor,'15') }">
26
+ <span v-if="badge" class="text-[9px] font-black uppercase tracking-[0.5em] mb-8 block" :style="{ opacity: 0.35 }">{{ badge }}</span>
27
+ <component :is="titleTag" class="font-black uppercase leading-[0.85] mb-0" :style="{ fontSize: 'clamp(2.2rem,5vw,4.5rem)', letterSpacing: '-0.03em' }">{{ title }}</component>
28
+ </div>
29
+ <div class="p-10 md:p-14 flex flex-col justify-between">
30
+ <p class="text-sm leading-relaxed mb-10" :style="{ opacity: 0.55 }">{{ subtitle }}</p>
31
+ <div>
32
+ <div class="h-px mb-8" :style="{ backgroundColor: ca(textColor,'15') }"></div>
33
+ <NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-3 px-6 py-3 border text-[11px] font-black uppercase tracking-widest transition-all hover:gap-6" :style="{ borderColor: textColor, color: textColor }">{{ ctaText }}<span>→</span></NuxtLink>
34
+ </div>
35
+ </div>
36
+ <div v-if="image" class="md:col-span-2 border-t overflow-hidden" :style="{ borderColor: ca(textColor,'15'), height: '320px' }">
37
+ <img :src="image" class="w-full h-full object-cover" />
38
+ </div>
39
+ </div>
40
+ </div>
41
+
42
+ <!-- FULLSCREEN -->
43
+ <div v-else-if="layout === 'fullscreen'" class="relative flex flex-col justify-end" style="min-height: 88vh">
44
+ <div class="absolute inset-0">
45
+ <img v-if="image" :src="image" class="w-full h-full object-cover" />
46
+ <div v-else class="w-full h-full" :style="{ backgroundColor: ca(textColor,'08') }"></div>
47
+ <div v-if="showOverlay" class="absolute inset-0" :style="overlayStyle"></div>
48
+ </div>
49
+ <div :class="[containerClass, 'relative z-10 w-full px-8 md:px-16 pb-12 border-t', isVisible ? 'sv-in' : 'sv-out']" :style="{ borderColor: ca(textColor,'30') }">
50
+ <div class="grid md:grid-cols-3 gap-8 pt-8">
51
+ <div class="md:col-span-2">
52
+ <span v-if="badge" class="block text-[9px] font-black uppercase tracking-[0.5em] mb-4" :style="{ opacity: 0.5 }">{{ badge }}</span>
53
+ <component :is="titleTag" class="font-black uppercase leading-[0.85]" :style="{ fontSize: 'clamp(2.5rem,7vw,6rem)', letterSpacing: '-0.03em' }">{{ title }}</component>
54
+ </div>
55
+ <div class="flex flex-col justify-end">
56
+ <p class="text-sm leading-relaxed mb-6" :style="{ opacity: 0.65 }">{{ subtitle }}</p>
57
+ <NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-3 px-6 py-3 border text-[11px] font-black uppercase tracking-widest transition-all hover:gap-6 self-start" :style="{ borderColor: textColor, color: textColor }">{{ ctaText }}<span>→</span></NuxtLink>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+ <!-- MINIMAL -->
64
+ <div v-else-if="layout === 'minimal'" class="px-8 md:px-16 py-14" :class="[containerClass]">
65
+ <div class="flex items-center gap-6 mb-10 border-b pb-6" :style="{ borderColor: ca(textColor,'15') }">
66
+ <span class="text-[9px] font-black uppercase tracking-[0.5em]" :style="{ opacity: 0.3 }">{{ badge || '—' }}</span>
67
+ <div class="h-px flex-1" :style="{ backgroundColor: ca(textColor,'10') }"></div>
68
+ <span class="text-[9px] font-black uppercase tracking-[0.5em]" :style="{ opacity: 0.2 }">{{ ctaText }}</span>
69
+ </div>
70
+ <component :is="titleTag" :class="['font-black uppercase leading-[0.85] mb-10', isVisible ? 'sv-in' : 'sv-out']" :style="{ fontSize: 'clamp(3.5rem,10vw,9rem)', letterSpacing: '-0.04em' }">{{ title }}</component>
71
+ <div v-if="image" class="mb-10 overflow-hidden border aspect-video" :style="{ borderColor: ca(textColor,'15') }">
72
+ <img :src="image" class="w-full h-full object-cover" />
73
+ </div>
74
+ <div class="flex flex-col md:flex-row items-start md:items-end justify-between gap-6 border-t pt-8" :style="{ borderColor: ca(textColor,'15') }">
75
+ <p class="text-sm leading-relaxed max-w-xs" :style="{ opacity: 0.5 }">{{ subtitle }}</p>
76
+ <NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-3 text-[11px] font-black uppercase tracking-widest transition-all hover:gap-6">{{ ctaText }}<span>→</span></NuxtLink>
77
+ </div>
78
+ </div>
79
+
80
+ <!-- EDITORIAL (default) -->
81
+ <div v-else class="px-8 md:px-16 py-14">
82
+ <div :class="[containerClass]">
83
+ <div class="mb-8 border-b pb-6" :style="{ borderColor: ca(textColor,'12') }">
84
+ <span v-if="badge" class="text-[9px] font-black uppercase tracking-[0.5em]" :style="{ opacity: 0.3 }">{{ badge }}</span>
85
+ </div>
86
+ <component :is="titleTag" :class="['font-black uppercase leading-[0.85] mb-8', isVisible ? 'sv-in' : 'sv-out']" :style="{ fontSize: 'clamp(3rem,9vw,9rem)', letterSpacing: '-0.04em' }">{{ title }}</component>
87
+ <div class="grid md:grid-cols-2 gap-10 border-t pt-8" :style="{ borderColor: ca(textColor,'12') }">
88
+ <p class="text-sm leading-relaxed" :style="{ opacity: 0.5 }">{{ subtitle }}</p>
89
+ <div class="flex items-start justify-end">
90
+ <NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-3 px-6 py-3 border text-[11px] font-black uppercase tracking-widest transition-all hover:gap-6" :style="{ borderColor: textColor, color: textColor }">{{ ctaText }}<span>→</span></NuxtLink>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+
96
+ </section>
97
+ </template>
98
+
99
+ <script setup>
100
+ const ca = (c, h) => {
101
+ const m = c?.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
102
+ return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : (c || "") + h;
103
+ };
104
+ import { ref, computed, onMounted } from "vue";
105
+ const props = defineProps({
106
+ layout: { type: String, default: "centered" },
107
+ animation: { type: String, default: "fadeUp" },
108
+ titleSize: { type: String, default: "md" },
109
+ title: { type: String, default: "Impactful Title" },
110
+ titleTag: { type: String, default: "h1" },
111
+ subtitle: { type: String, default: "" },
112
+ badge: { type: String, default: "" },
113
+ ctaText: { type: String, default: "Get Started" },
114
+ ctaLink: { type: String, default: "#" },
115
+ image: { type: String, default: "" },
116
+ videoUrl: { type: String, default: "" },
117
+ imageStyle: { type: String, default: "cover" },
118
+ imagePosition: { type: String, default: "center" },
119
+ bgColor: { type: String, default: "rgba(var(--primary-color), 1)" },
120
+ textColor: { type: String, default: "rgba(var(--body-bg), 1)" },
121
+ spacing: { type: String, default: "normal" },
122
+ radius: { type: String, default: "sharp" },
123
+ textDirection: { type: String, default: "ltr" },
124
+ contentWidth: { type: String, default: "normal" },
125
+ textSize: { type: String, default: "md" },
126
+ paddingTop: { type: String, default: "" },
127
+ paddingBottom: { type: String, default: "" },
128
+ marginTop: { type: String, default: "" },
129
+ marginBottom: { type: String, default: "" },
130
+ paddingX: { type: String, default: "" },
131
+ overlay: { type: String, default: "auto" },
132
+ overlayDirection: { type: String, default: "to top" },
133
+ overlayStrength: { type: String, default: "medium" },
134
+ overlayColor: { type: String, default: "" }
135
+ });
136
+ const sectionEl = ref(null);
137
+ const isVisible = ref(false);
138
+ onMounted(() => {
139
+ if (!sectionEl.value) return;
140
+ const obs = new IntersectionObserver(([e]) => {
141
+ if (e.isIntersecting) {
142
+ isVisible.value = true;
143
+ obs.disconnect();
144
+ }
145
+ }, { threshold: 0.05 });
146
+ obs.observe(sectionEl.value);
147
+ setTimeout(() => {
148
+ if (!isVisible.value) isVisible.value = true;
149
+ }, 400);
150
+ });
151
+ const showOverlay = computed(() => {
152
+ if (props.overlay === "off") return false;
153
+ if (props.overlay === "on") return true;
154
+ return ["fullscreen", "parallax", "video"].includes(props.layout);
155
+ });
156
+ const overlayStyle = computed(() => {
157
+ const dir = props.overlayDirection || "to top";
158
+ const c = props.overlayColor || props.bgColor;
159
+ const stops = {
160
+ light: `linear-gradient(${dir}, ${ca(c, "99")} 0%, ${ca(c, "44")} 40%, transparent 70%)`,
161
+ medium: `linear-gradient(${dir}, ${c} 15%, ${ca(c, "cc")} 40%, ${ca(c, "44")} 65%, transparent 100%)`,
162
+ strong: `linear-gradient(${dir}, ${c} 35%, ${ca(c, "ee")} 55%, ${ca(c, "88")} 75%, transparent 100%)`
163
+ };
164
+ return { background: stops[props.overlayStrength] || stops.medium };
165
+ });
166
+ const containerClass = computed(() => ({ narrow: "max-w-3xl mx-auto", normal: "max-w-6xl mx-auto", wide: "max-w-7xl mx-auto", full: "max-w-full" })[props.contentWidth] || "max-w-6xl mx-auto");
167
+ const SM = { none: "0", xs: "8px", sm: "24px", md: "48px", lg: "80px", xl: "128px", "-xs": "-8px", "-sm": "-24px", "-md": "-48px", "-lg": "-80px", "-xl": "-128px" };
168
+ const spacingStyle = computed(() => {
169
+ const s = {};
170
+ if (props.paddingTop && SM[props.paddingTop]) s.paddingTop = SM[props.paddingTop];
171
+ if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
172
+ if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
173
+ if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
174
+ if (props.paddingX && SM[props.paddingX]) {
175
+ const v = SM[props.paddingX];
176
+ if (v.startsWith("-")) {
177
+ s.marginLeft = v;
178
+ s.marginRight = v;
179
+ } else {
180
+ s.paddingLeft = v;
181
+ s.paddingRight = v;
182
+ }
183
+ }
184
+ return s;
185
+ });
186
+ </script>
187
+
188
+ <style scoped>
189
+ .sv-out{opacity:0;transform:translateY(16px)}.sv-in{opacity:1;transform:none;transition:opacity .6s ease,transform .6s ease}
190
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: any;
@@ -0,0 +1,3 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: any;
@@ -0,0 +1,138 @@
1
+ <template>
2
+ <section
3
+ class="relative overflow-hidden select-none"
4
+ :dir="textDirection"
5
+ :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]"
6
+ @mouseenter="pauseAutoplay"
7
+ @mouseleave="resumeAutoplay"
8
+ >
9
+ <!-- Slides -->
10
+ <div class="relative overflow-hidden" :style="{ height: heightValue }">
11
+ <div
12
+ v-for="(slide, i) in slides" :key="i"
13
+ class="absolute inset-0 w-full h-full transition-opacity duration-500"
14
+ :style="{ opacity: i === current ? 1 : 0, pointerEvents: i === current ? 'auto' : 'none' }"
15
+ >
16
+ <img v-if="slide.image" :src="slide.image" class="absolute inset-0 w-full h-full object-cover" />
17
+ <div v-if="slide.image && overlay" class="absolute inset-0" :style="{ background: `linear-gradient(to top, ${bgColor} 20%, ${ca(bgColor,'aa')} 50%, transparent 100%)` }"></div>
18
+ <div v-if="!slide.image" class="absolute inset-0" :style="{ backgroundColor: ca(textColor,'08') }"></div>
19
+
20
+ <!-- Content -->
21
+ <div class="relative z-10 h-full flex flex-col justify-end px-8 md:px-16 pb-12 border-t" :style="{ borderColor: ca(textColor,'25') }">
22
+ <div class="max-w-6xl mx-auto w-full grid md:grid-cols-2 gap-8 pt-8">
23
+ <div>
24
+ <span v-if="slide.badge" class="block text-[9px] font-black uppercase tracking-[0.5em] mb-4 border-l-4 pl-3" :style="{ borderColor: textColor, opacity: 0.5 }">{{ slide.badge }}</span>
25
+ <div class="font-black uppercase leading-[0.88]" :style="{ fontSize: titleFontSize, letterSpacing: '-0.04em' }">{{ slide.title || 'Slide Title' }}</div>
26
+ </div>
27
+ <div class="flex flex-col justify-end">
28
+ <p v-if="slide.subtitle" :class="[bodyClass, 'leading-relaxed mb-6']" :style="{ opacity: 0.65 }">{{ slide.subtitle }}</p>
29
+ <div class="flex flex-wrap gap-3">
30
+ <NuxtLink v-if="slide.ctaText" :to="slide.ctaLink || '#'"
31
+ class="inline-flex items-center gap-3 px-6 py-3 text-[11px] font-black uppercase tracking-widest transition-all hover:gap-6 border"
32
+ :style="{ backgroundColor: textColor, color: bgColor, borderColor: textColor }">
33
+ {{ slide.ctaText }}<span>→</span>
34
+ </NuxtLink>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+
42
+ <!-- Slide counter + controls -->
43
+ <div v-if="slides.length > 1" class="absolute bottom-4 right-8 md:right-16 z-20 flex items-center gap-4">
44
+ <button v-if="showArrows" @click="prev" class="w-8 h-8 border flex items-center justify-center text-xs font-black transition-all hover:opacity-70" :style="{ borderColor: ca(textColor,'30'), color: textColor }">←</button>
45
+ <span class="text-[10px] font-black tabular-nums" :style="{ opacity: 0.5 }">{{ String(current + 1).padStart(2,'0') }} / {{ String(slides.length).padStart(2,'0') }}</span>
46
+ <button v-if="showArrows" @click="next" class="w-8 h-8 border flex items-center justify-center text-xs font-black transition-all hover:opacity-70" :style="{ borderColor: ca(textColor,'30'), color: textColor }">→</button>
47
+ </div>
48
+
49
+ <!-- Progress bar -->
50
+ <div v-if="autoplay && slides.length > 1" class="absolute bottom-0 left-0 h-[2px] z-30"
51
+ :style="{ width: `${progress}%`, backgroundColor: textColor, opacity: 0.3, transition: 'width 0.05s linear' }"></div>
52
+ </section>
53
+ </template>
54
+
55
+ <script setup>
56
+ import { ref, computed, onMounted, onUnmounted } from "vue";
57
+ const ca = (c, h) => {
58
+ if (!c) return "#000" + h;
59
+ const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
60
+ return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
61
+ };
62
+ const props = defineProps({
63
+ slides: { type: Array, default: () => [
64
+ { badge: "New", title: "First Slide Title", subtitle: "Describe your offer here.", ctaText: "Discover", ctaLink: "#", image: "" },
65
+ { badge: "", title: "Second Slide Title", subtitle: "Another compelling message.", ctaText: "Learn More", ctaLink: "#", image: "" }
66
+ ] },
67
+ transition: { type: String, default: "fade" },
68
+ autoplay: { type: Boolean, default: true },
69
+ interval: { type: Number, default: 5e3 },
70
+ height: { type: String, default: "large" },
71
+ overlay: { type: Boolean, default: true },
72
+ showDots: { type: Boolean, default: false },
73
+ showArrows: { type: Boolean, default: true },
74
+ contentAlign: { type: String, default: "bottom" },
75
+ titleSize: { type: String, default: "md" },
76
+ bgColor: { type: String, default: "rgba(var(--primary-color), 1)" },
77
+ textColor: { type: String, default: "rgba(var(--body-bg), 1)" },
78
+ radius: { type: String, default: "sharp" },
79
+ contentWidth: { type: String, default: "normal" },
80
+ textSize: { type: String, default: "md" },
81
+ textDirection: { type: String, default: "ltr" },
82
+ paddingTop: { type: String, default: "" },
83
+ paddingBottom: { type: String, default: "" },
84
+ marginTop: { type: String, default: "" },
85
+ marginBottom: { type: String, default: "" }
86
+ });
87
+ const current = ref(0);
88
+ const paused = ref(false);
89
+ const progress = ref(0);
90
+ const heightValue = computed(() => ({ small: "50vh", medium: "65vh", large: "80vh", full: "100vh" })[props.height] || "80vh");
91
+ const titleFontSize = computed(() => ({ sm: "clamp(2rem,4vw,3.5rem)", md: "clamp(2.5rem,5vw,4.5rem)", lg: "clamp(3rem,7vw,6rem)" })[props.titleSize] || "clamp(2.5rem,5vw,4.5rem)");
92
+ const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
93
+ function next() {
94
+ current.value = (current.value + 1) % props.slides.length;
95
+ }
96
+ function prev() {
97
+ current.value = (current.value - 1 + props.slides.length) % props.slides.length;
98
+ }
99
+ let timer = null;
100
+ let progressTimer = null;
101
+ function startAutoplay() {
102
+ if (!props.autoplay || props.slides.length <= 1 || paused.value) return;
103
+ progress.value = 0;
104
+ const step = 100 / (props.interval / 50);
105
+ progressTimer = setInterval(() => {
106
+ progress.value = Math.min(progress.value + step, 100);
107
+ }, 50);
108
+ timer = setTimeout(() => {
109
+ next();
110
+ progress.value = 0;
111
+ clearInterval(progressTimer);
112
+ startAutoplay();
113
+ }, props.interval);
114
+ }
115
+ function pauseAutoplay() {
116
+ paused.value = true;
117
+ clearTimeout(timer);
118
+ clearInterval(progressTimer);
119
+ }
120
+ function resumeAutoplay() {
121
+ paused.value = false;
122
+ startAutoplay();
123
+ }
124
+ onMounted(startAutoplay);
125
+ onUnmounted(() => {
126
+ clearTimeout(timer);
127
+ clearInterval(progressTimer);
128
+ });
129
+ const SM = { none: "0", xs: "8px", sm: "24px", md: "48px", lg: "80px", xl: "128px", "-xs": "-8px", "-sm": "-24px", "-md": "-48px", "-lg": "-80px", "-xl": "-128px" };
130
+ const spacingStyle = computed(() => {
131
+ const s = {};
132
+ if (props.paddingTop && SM[props.paddingTop]) s.paddingTop = SM[props.paddingTop];
133
+ if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
134
+ if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
135
+ if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
136
+ return s;
137
+ });
138
+ </script>
@@ -0,0 +1,3 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: any;
@@ -0,0 +1,3 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: any;