cinqcinqdev-seo 0.1.44 → 0.1.46
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.
- package/dist/module.json +1 -1
- package/dist/runtime/assets/admin-tw.css +1 -1
- package/dist/runtime/components/sections/BlogHero.vue +16 -10
- package/dist/runtime/components/sections/CallToAction.vue +17 -11
- package/dist/runtime/components/sections/Comparison.d.vue.ts +3 -0
- package/dist/runtime/components/sections/Comparison.vue +264 -0
- package/dist/runtime/components/sections/Comparison.vue.d.ts +3 -0
- package/dist/runtime/components/sections/ContactForm.vue +11 -5
- package/dist/runtime/components/sections/DataTable.d.vue.ts +3 -0
- package/dist/runtime/components/sections/DataTable.vue +207 -0
- package/dist/runtime/components/sections/DataTable.vue.d.ts +3 -0
- package/dist/runtime/components/sections/FAQ.vue +11 -5
- package/dist/runtime/components/sections/Features.vue +11 -5
- package/dist/runtime/components/sections/HeroSection.vue +19 -14
- package/dist/runtime/components/sections/Newsletter.vue +17 -11
- package/dist/runtime/components/sections/Pricing.vue +11 -5
- package/dist/runtime/components/sections/Process.vue +11 -5
- package/dist/runtime/components/sections/Quote.vue +13 -8
- package/dist/runtime/components/sections/RichText.vue +11 -4
- package/dist/runtime/components/sections/ServiceGrid.vue +11 -5
- package/dist/runtime/components/sections/Testimonials.vue +11 -5
- package/dist/runtime/components/sections/TextVisual.vue +17 -11
- package/dist/runtime/composables/useAdminSections.js +267 -27
- package/package.json +1 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section class="relative overflow-hidden" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
2
|
+
<section class="relative overflow-hidden" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
3
|
|
|
4
4
|
<!-- CENTERED -->
|
|
5
5
|
<div v-if="layout === 'centered'" class="px-6 md:px-12 pt-20 pb-16 text-center">
|
|
6
|
-
<div class="
|
|
6
|
+
<div :class="[containerClass]">
|
|
7
7
|
<span v-if="badge" class="inline-flex items-center gap-1.5 text-[10px] font-bold tracking-[0.4em] uppercase px-4 py-1.5 rounded-full border mb-8" :style="{ borderColor: ca(textColor, '30'), color: ca(textColor, '80') }">
|
|
8
8
|
<span class="w-1.5 h-1.5 rounded-full inline-block" :style="{ backgroundColor: ca(textColor, '60') }"></span>{{ badge }}
|
|
9
9
|
</span>
|
|
10
10
|
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.88] mb-6" :style="{ fontSize: titleSize === 'sm' ? 'clamp(2.5rem,5vw,4rem)' : titleSize === 'lg' ? 'clamp(3.5rem,9vw,8rem)' : 'clamp(3rem,7vw,6rem)' }">{{ title }}</component>
|
|
11
|
-
<p class="
|
|
11
|
+
<p :class="[bodyClass, 'leading-relaxed max-w-lg mx-auto mb-10']" :style="{ opacity: 0.5 }">{{ subtitle }}</p>
|
|
12
12
|
<NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-2.5 px-8 py-3.5 rounded-full text-[11px] font-black uppercase tracking-widest transition-all hover:gap-5 active:scale-95" :style="{ backgroundColor: textColor, color: bgColor }">{{ ctaText }}<span>→</span></NuxtLink>
|
|
13
13
|
<div v-if="image" :class="['mt-14 mx-auto aspect-video overflow-hidden max-w-3xl', cardRound]">
|
|
14
14
|
<img :src="image" class="w-full h-full object-cover" />
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
|
|
19
19
|
<!-- SPLIT -->
|
|
20
20
|
<div v-else-if="layout === 'split'" class="px-6 md:px-12 py-16">
|
|
21
|
-
<div class="
|
|
21
|
+
<div :class="[containerClass, 'grid md:grid-cols-2 gap-12 md:gap-20 items-center']">
|
|
22
22
|
<div>
|
|
23
23
|
<span v-if="badge" class="inline-block text-[9px] font-black tracking-[0.5em] uppercase mb-6 opacity-35">{{ badge }}</span>
|
|
24
24
|
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.88] mb-6" :style="{ fontSize: 'clamp(2.2rem,5vw,4.5rem)' }">{{ title }}</component>
|
|
25
|
-
<p class="
|
|
25
|
+
<p :class="[bodyClass, 'leading-relaxed mb-10 max-w-sm']" :style="{ opacity: 0.5 }">{{ subtitle }}</p>
|
|
26
26
|
<NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-2.5 px-7 py-3 rounded-full text-[11px] font-black uppercase tracking-widest transition-all hover:gap-5 active:scale-95" :style="{ backgroundColor: textColor, color: bgColor }">{{ ctaText }}<span>→</span></NuxtLink>
|
|
27
27
|
</div>
|
|
28
28
|
<div :class="['aspect-[4/3] overflow-hidden', cardRound]">
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
|
|
35
35
|
<!-- BENTO -->
|
|
36
36
|
<div v-else-if="layout === 'bento'" class="p-3 md:p-5">
|
|
37
|
-
<div class="
|
|
37
|
+
<div :class="[containerClass, 'grid grid-cols-12 gap-3']">
|
|
38
38
|
<div :class="['col-span-12 md:col-span-7 p-8 md:p-10 border flex flex-col justify-between min-h-[320px]', cardRound]" :style="{ borderColor: ca(textColor, '10'), backgroundColor: ca(textColor, '04') }">
|
|
39
39
|
<span v-if="badge" class="text-[9px] font-black uppercase tracking-[0.4em] opacity-30">{{ badge }}</span>
|
|
40
40
|
<div>
|
|
41
41
|
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.88] mb-4" :style="{ fontSize: 'clamp(2rem,4.5vw,3.8rem)' }">{{ title }}</component>
|
|
42
|
-
<p class="
|
|
42
|
+
<p :class="[bodyClass, 'leading-relaxed mb-8 max-w-xs']" :style="{ opacity: 0.45 }">{{ subtitle }}</p>
|
|
43
43
|
<NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-2.5 px-6 py-3 rounded-full text-[10px] font-black uppercase tracking-widest transition-all hover:gap-5 active:scale-95" :style="{ backgroundColor: textColor, color: bgColor }">{{ ctaText }}<span>→</span></NuxtLink>
|
|
44
44
|
</div>
|
|
45
45
|
</div>
|
|
@@ -57,11 +57,11 @@
|
|
|
57
57
|
<div v-else class="w-full h-full" :style="{ backgroundColor: ca(textColor, '08') }"></div>
|
|
58
58
|
<div class="absolute inset-0" :style="{ background: `linear-gradient(to top, ${bgColor} 20%, ${ca(bgColor, 'cc')} 40%, ${ca(bgColor, '44')} 65%, transparent 100%)` }"></div>
|
|
59
59
|
</div>
|
|
60
|
-
<div class="relative z-10
|
|
60
|
+
<div :class="[containerClass, 'relative z-10 w-full px-6 md:px-12 pb-14']">
|
|
61
61
|
<span v-if="badge" class="inline-block text-[9px] font-black uppercase tracking-[0.5em] opacity-40 mb-4">{{ badge }}</span>
|
|
62
62
|
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.88] mb-6" :style="{ fontSize: 'clamp(3rem,8vw,7rem)' }">{{ title }}</component>
|
|
63
63
|
<div class="flex flex-col sm:flex-row sm:items-center gap-6 sm:gap-10">
|
|
64
|
-
<p class="
|
|
64
|
+
<p :class="[bodyClass, 'leading-relaxed max-w-xs']" :style="{ opacity: 0.6 }">{{ subtitle }}</p>
|
|
65
65
|
<NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-2.5 px-7 py-3 rounded-full text-[11px] font-black uppercase tracking-widest border transition-all hover:gap-5 shrink-0" :style="{ borderColor: ca(textColor, '50'), color: textColor }">{{ ctaText }}<span>→</span></NuxtLink>
|
|
66
66
|
</div>
|
|
67
67
|
</div>
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
|
|
70
70
|
<!-- MINIMAL -->
|
|
71
71
|
<div v-else-if="layout === 'minimal'" class="px-6 md:px-12 py-14">
|
|
72
|
-
<div class="
|
|
72
|
+
<div :class="[containerClass]">
|
|
73
73
|
<div class="flex items-center gap-4 mb-10 border-b pb-5" :style="{ borderColor: ca(textColor, '10') }">
|
|
74
74
|
<span v-if="badge" class="text-[9px] font-black uppercase tracking-[0.5em] opacity-30">{{ badge }}</span>
|
|
75
75
|
<div class="flex-1 h-px" :style="{ backgroundColor: ca(textColor, '08') }"></div>
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
<img :src="image" class="w-full h-full object-cover" />
|
|
81
81
|
</div>
|
|
82
82
|
<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, '10') }">
|
|
83
|
-
<p class="
|
|
83
|
+
<p :class="[bodyClass, 'leading-relaxed max-w-xs']" :style="{ opacity: 0.5 }">{{ subtitle }}</p>
|
|
84
84
|
<NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-2.5 text-[11px] font-black uppercase tracking-widest transition-all hover:gap-5 shrink-0">{{ ctaText }}<span>→</span></NuxtLink>
|
|
85
85
|
</div>
|
|
86
86
|
</div>
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
|
|
89
89
|
<!-- EDITORIAL -->
|
|
90
90
|
<div v-else class="px-6 md:px-12 py-14">
|
|
91
|
-
<div class="
|
|
91
|
+
<div :class="[containerClass]">
|
|
92
92
|
<div class="flex items-center gap-4 mb-8">
|
|
93
93
|
<div class="w-8 h-px" :style="{ backgroundColor: ca(textColor, '30') }"></div>
|
|
94
94
|
<span class="text-[9px] font-black uppercase tracking-[0.5em] opacity-30">{{ badge || '—' }}</span>
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
</div>
|
|
101
101
|
</div>
|
|
102
102
|
<div class="flex flex-col md:flex-row items-start md:items-center justify-between gap-6 border-t pt-8" :style="{ borderColor: ca(textColor, '10') }">
|
|
103
|
-
<p class="
|
|
103
|
+
<p :class="[bodyClass, 'leading-relaxed max-w-sm']" :style="{ opacity: 0.5 }">{{ subtitle }}</p>
|
|
104
104
|
<NuxtLink :to="ctaLink || '#'" class="inline-flex items-center gap-2.5 px-7 py-3 rounded-full text-[11px] font-black uppercase tracking-widest transition-all hover:gap-5 shrink-0 active:scale-95" :style="{ backgroundColor: textColor, color: bgColor }">{{ ctaText }}<span>→</span></NuxtLink>
|
|
105
105
|
</div>
|
|
106
106
|
</div>
|
|
@@ -131,7 +131,12 @@ const props = defineProps({
|
|
|
131
131
|
bgColor: { type: String, default: "rgba(var(--primary-color), 1)" },
|
|
132
132
|
textColor: { type: String, default: "rgba(var(--body-bg), 1)" },
|
|
133
133
|
spacing: { type: String, default: "normal" },
|
|
134
|
-
radius: { type: String, default: "rounded" }
|
|
134
|
+
radius: { type: String, default: "rounded" },
|
|
135
|
+
textDirection: { type: String, default: "ltr" },
|
|
136
|
+
contentWidth: { type: String, default: "normal" },
|
|
137
|
+
textSize: { type: String, default: "md" }
|
|
135
138
|
});
|
|
136
139
|
const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-3xl", pill: "rounded-[40px]" })[props.radius] || "rounded-3xl");
|
|
140
|
+
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");
|
|
141
|
+
const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
|
|
137
142
|
</script>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section :class="[sectionPad]" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
2
|
+
<section :class="[sectionPad]" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
3
|
|
|
4
4
|
<!-- CENTERED -->
|
|
5
|
-
<div v-if="layout === 'centered'" class="
|
|
5
|
+
<div v-if="layout === 'centered'" :class="[containerClass, 'text-center']">
|
|
6
6
|
<span v-if="badge" class="inline-block text-[10px] font-black uppercase tracking-[0.4em] px-3 py-1 rounded-full border mb-6" :style="{ borderColor: ca(textColor, '25'), color: ca(textColor, 'aa') }">{{ badge }}</span>
|
|
7
|
-
<h2 class="font-black uppercase tracking-tighter leading-[0.9] mb-3" :style="{ fontSize:
|
|
8
|
-
<p v-if="description" class="
|
|
7
|
+
<h2 class="font-black uppercase tracking-tighter leading-[0.9] mb-3" :style="{ fontSize: titleFontSize }">{{ title }}</h2>
|
|
8
|
+
<p v-if="description" :class="[bodyClass, 'leading-relaxed mb-8']" :style="{ opacity: 0.6 }">{{ description }}</p>
|
|
9
9
|
<div class="flex gap-2 max-w-sm mx-auto">
|
|
10
10
|
<input type="email" :placeholder="placeholder || 'your@email.com'" class="flex-1 px-4 py-3 text-sm outline-none rounded-xl border" :style="{ backgroundColor: ca(textColor, '06'), borderColor: ca(textColor, '15'), color: textColor }" />
|
|
11
11
|
<button :class="['px-5 py-3 text-[11px] font-black uppercase tracking-wider shrink-0', cardRound]" :style="{ backgroundColor: textColor, color: bgColor }">{{ buttonText || 'Subscribe' }}</button>
|
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
16
|
<!-- SPLIT -->
|
|
17
|
-
<div v-else-if="layout === 'split'" :class="['grid grid-cols-1 md:grid-cols-2 gap-10 md:gap-16 items-center
|
|
17
|
+
<div v-else-if="layout === 'split'" :class="[containerClass, 'grid grid-cols-1 md:grid-cols-2 gap-10 md:gap-16 items-center']">
|
|
18
18
|
<div>
|
|
19
19
|
<span v-if="badge" class="inline-block text-[10px] font-black uppercase tracking-[0.4em] mb-4" :style="{ opacity: 0.5 }">{{ badge }}</span>
|
|
20
|
-
<h2 class="font-black uppercase tracking-tighter leading-[0.9] mb-3" :style="{ fontSize:
|
|
21
|
-
<p v-if="description" class="
|
|
20
|
+
<h2 class="font-black uppercase tracking-tighter leading-[0.9] mb-3" :style="{ fontSize: titleFontSize }">{{ title }}</h2>
|
|
21
|
+
<p v-if="description" :class="[bodyClass, 'leading-relaxed']" :style="{ opacity: 0.6 }">{{ description }}</p>
|
|
22
22
|
</div>
|
|
23
23
|
<div>
|
|
24
24
|
<div class="flex gap-2">
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
</div>
|
|
31
31
|
|
|
32
32
|
<!-- MINIMAL -->
|
|
33
|
-
<div v-else class="
|
|
33
|
+
<div v-else :class="[containerClass]">
|
|
34
34
|
<div class="flex flex-col md:flex-row items-start md:items-center gap-6 border-t border-b py-10" :style="{ borderColor: ca(textColor, '15') }">
|
|
35
35
|
<div class="flex-1">
|
|
36
|
-
<h2 class="font-black uppercase tracking-tight leading-[0.92] mb-1" :style="{ fontSize:
|
|
37
|
-
<p v-if="description" class="
|
|
36
|
+
<h2 class="font-black uppercase tracking-tight leading-[0.92] mb-1" :style="{ fontSize: titleFontSize }">{{ title }}</h2>
|
|
37
|
+
<p v-if="description" :class="[bodyClass]" :style="{ opacity: 0.55 }">{{ description }}</p>
|
|
38
38
|
</div>
|
|
39
39
|
<div class="flex gap-2 w-full md:w-auto">
|
|
40
40
|
<input type="email" :placeholder="placeholder || 'your@email.com'" class="flex-1 md:w-48 px-4 py-2.5 text-sm outline-none rounded-lg border" :style="{ backgroundColor: ca(textColor, '06'), borderColor: ca(textColor, '15'), color: textColor }" />
|
|
@@ -63,8 +63,14 @@ const props = defineProps({
|
|
|
63
63
|
bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
|
|
64
64
|
textColor: { type: String, default: "rgba(var(--text-color), 1)" },
|
|
65
65
|
spacing: { type: String, default: "normal" },
|
|
66
|
-
radius: { type: String, default: "rounded" }
|
|
66
|
+
radius: { type: String, default: "rounded" },
|
|
67
|
+
textDirection: { type: String, default: "ltr" },
|
|
68
|
+
contentWidth: { type: String, default: "normal" },
|
|
69
|
+
textSize: { type: String, default: "md" }
|
|
67
70
|
});
|
|
68
71
|
const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-6 md:px-12", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-6 md:px-12");
|
|
69
72
|
const cardRound = computed(() => ({ sharp: "rounded-lg", rounded: "rounded-xl", pill: "rounded-full" })[props.radius] || "rounded-xl");
|
|
73
|
+
const containerClass = computed(() => ({ narrow: "max-w-3xl mx-auto", normal: "max-w-5xl mx-auto", wide: "max-w-7xl mx-auto", full: "max-w-full" })[props.contentWidth] || "max-w-5xl mx-auto");
|
|
74
|
+
const titleFontSize = computed(() => ({ sm: "clamp(1rem,2vw,1.5rem)", md: "clamp(1.8rem,5vw,3.5rem)", lg: "clamp(2.2rem,6vw,4.5rem)" })[props.textSize] || "clamp(1.8rem,5vw,3.5rem)");
|
|
75
|
+
const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
|
|
70
76
|
</script>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section :class="[sectionPad]" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
|
-
<div class="
|
|
2
|
+
<section :class="[sectionPad]" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
|
+
<div :class="[containerClass]">
|
|
4
4
|
|
|
5
5
|
<div v-if="title || description" class="mb-12 text-center max-w-2xl mx-auto">
|
|
6
6
|
<span v-if="badge" class="inline-block text-[10px] font-bold tracking-[0.5em] uppercase px-3 py-1 rounded-full border mb-4" :style="{ borderColor: ca(textColor, '25'), color: ca(textColor, 'aa') }">{{ badge }}</span>
|
|
7
|
-
<component :is="titleTag" class="
|
|
8
|
-
<p v-if="description" class="
|
|
7
|
+
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9] mb-4" :style="{ fontSize: titleFontSize }">{{ title }}</component>
|
|
8
|
+
<p v-if="description" :class="[bodyClass, 'leading-relaxed']" :style="{ opacity: 0.55 }">{{ description }}</p>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<!-- CARDS -->
|
|
@@ -99,10 +99,16 @@ const props = defineProps({
|
|
|
99
99
|
bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
|
|
100
100
|
textColor: { type: String, default: "rgba(var(--text-color), 1)" },
|
|
101
101
|
spacing: { type: String, default: "normal" },
|
|
102
|
-
radius: { type: String, default: "rounded" }
|
|
102
|
+
radius: { type: String, default: "rounded" },
|
|
103
|
+
textDirection: { type: String, default: "ltr" },
|
|
104
|
+
contentWidth: { type: String, default: "normal" },
|
|
105
|
+
textSize: { type: String, default: "md" }
|
|
103
106
|
});
|
|
104
107
|
const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-6 md:px-12", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-6 md:px-12");
|
|
105
108
|
const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-3xl", pill: "rounded-[40px]" })[props.radius] || "rounded-3xl");
|
|
109
|
+
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");
|
|
110
|
+
const titleFontSize = computed(() => ({ sm: "clamp(1.5rem,3vw,2.5rem)", md: "clamp(2rem,4vw,3.5rem)", lg: "clamp(2.5rem,6vw,5rem)" })[props.textSize] || "clamp(2rem,4vw,3.5rem)");
|
|
111
|
+
const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
|
|
106
112
|
const allFeatures = computed(() => {
|
|
107
113
|
const set = /* @__PURE__ */ new Set();
|
|
108
114
|
props.items.forEach((p) => (p.features || []).forEach((f) => set.add(typeof f === "object" ? f.fr || JSON.stringify(f) : f)));
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section :class="[sectionPad]" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
|
-
<div class="
|
|
2
|
+
<section :class="[sectionPad]" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
|
+
<div :class="[containerClass]">
|
|
4
4
|
|
|
5
5
|
<div v-if="title || description" class="mb-12" :class="['horizontal','cards'].includes(layout) ? 'text-center max-w-2xl mx-auto' : 'max-w-xl'">
|
|
6
6
|
<span v-if="badge" class="inline-block text-[10px] font-bold tracking-[0.5em] uppercase px-3 py-1 rounded-full border mb-4" :style="{ borderColor: ca(textColor, '25'), color: ca(textColor, 'aa') }">{{ badge }}</span>
|
|
7
|
-
<component :is="titleTag" class="
|
|
8
|
-
<p v-if="description" class="
|
|
7
|
+
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9] mb-4" :style="{ fontSize: titleFontSize }">{{ title }}</component>
|
|
8
|
+
<p v-if="description" :class="[bodyClass, 'leading-relaxed']" :style="{ opacity: 0.55 }">{{ description }}</p>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<!-- STEPS (vertical) -->
|
|
@@ -92,8 +92,14 @@ const props = defineProps({
|
|
|
92
92
|
bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
|
|
93
93
|
textColor: { type: String, default: "rgba(var(--text-color), 1)" },
|
|
94
94
|
spacing: { type: String, default: "normal" },
|
|
95
|
-
radius: { type: String, default: "rounded" }
|
|
95
|
+
radius: { type: String, default: "rounded" },
|
|
96
|
+
textDirection: { type: String, default: "ltr" },
|
|
97
|
+
contentWidth: { type: String, default: "normal" },
|
|
98
|
+
textSize: { type: String, default: "md" }
|
|
96
99
|
});
|
|
97
100
|
const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-6 md:px-12", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-6 md:px-12");
|
|
98
101
|
const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-3xl", pill: "rounded-[40px]" })[props.radius] || "rounded-3xl");
|
|
102
|
+
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");
|
|
103
|
+
const titleFontSize = computed(() => ({ sm: "clamp(1.5rem,3vw,2.5rem)", md: "clamp(2rem,4vw,3.5rem)", lg: "clamp(2.5rem,6vw,5rem)" })[props.textSize] || "clamp(2rem,4vw,3.5rem)");
|
|
104
|
+
const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
|
|
99
105
|
</script>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section :class="[sectionPad]" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
2
|
+
<section :class="[sectionPad]" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
3
|
|
|
4
4
|
<!-- CENTERED -->
|
|
5
|
-
<div v-if="layout === 'centered'" class="
|
|
5
|
+
<div v-if="layout === 'centered'" :class="[containerClass, 'text-center']">
|
|
6
6
|
<div class="text-6xl font-black mb-6 leading-none" :style="{ opacity: 0.15 }">"</div>
|
|
7
|
-
<blockquote class="font-black uppercase tracking-tighter leading-[0.92] mb-8" :style="{ fontSize:
|
|
7
|
+
<blockquote class="font-black uppercase tracking-tighter leading-[0.92] mb-8" :style="{ fontSize: quoteFontSize }">{{ quote }}</blockquote>
|
|
8
8
|
<div class="flex items-center justify-center gap-3">
|
|
9
9
|
<img v-if="avatar" :src="avatar" class="w-10 h-10 rounded-full object-cover" />
|
|
10
10
|
<div v-else-if="author" class="w-10 h-10 rounded-full flex items-center justify-center text-xs font-black" :style="{ backgroundColor: ca(textColor, '15') }">{{ author[0] }}</div>
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
18
|
<!-- LEFT -->
|
|
19
|
-
<div v-else-if="layout === 'left'" class="
|
|
19
|
+
<div v-else-if="layout === 'left'" :class="[containerClass, 'flex gap-8 items-start']">
|
|
20
20
|
<div class="text-8xl font-black leading-none shrink-0 mt-2" :style="{ opacity: 0.12 }">"</div>
|
|
21
21
|
<div>
|
|
22
|
-
<blockquote class="font-black uppercase tracking-tight leading-[0.92] mb-7" :style="{ fontSize:
|
|
22
|
+
<blockquote class="font-black uppercase tracking-tight leading-[0.92] mb-7" :style="{ fontSize: quoteFontSize }">{{ quote }}</blockquote>
|
|
23
23
|
<div class="flex items-center gap-3">
|
|
24
24
|
<img v-if="avatar" :src="avatar" class="w-9 h-9 rounded-full object-cover" />
|
|
25
25
|
<div v-else-if="author" class="w-9 h-9 rounded-full flex items-center justify-center text-xs font-black" :style="{ backgroundColor: ca(textColor, '15') }">{{ author[0] }}</div>
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
</div>
|
|
33
33
|
|
|
34
34
|
<!-- LARGE (full width statement) -->
|
|
35
|
-
<div v-else class="
|
|
35
|
+
<div v-else :class="[containerClass]">
|
|
36
36
|
<div class="border-t border-b py-12 md:py-16" :style="{ borderColor: ca(textColor, '20') }">
|
|
37
|
-
<blockquote class="font-black uppercase tracking-tighter leading-[0.88] mb-10" :style="{ fontSize:
|
|
37
|
+
<blockquote class="font-black uppercase tracking-tighter leading-[0.88] mb-10" :style="{ fontSize: quoteFontSize }">{{ quote }}</blockquote>
|
|
38
38
|
<div class="flex items-center gap-4">
|
|
39
39
|
<div class="w-12 h-px" :style="{ backgroundColor: textColor }"></div>
|
|
40
40
|
<img v-if="avatar" :src="avatar" class="w-8 h-8 rounded-full object-cover" />
|
|
@@ -72,7 +72,12 @@ const props = defineProps({
|
|
|
72
72
|
bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
|
|
73
73
|
textColor: { type: String, default: "rgba(var(--text-color), 1)" },
|
|
74
74
|
spacing: { type: String, default: "normal" },
|
|
75
|
-
radius: { type: String, default: "rounded" }
|
|
75
|
+
radius: { type: String, default: "rounded" },
|
|
76
|
+
textDirection: { type: String, default: "ltr" },
|
|
77
|
+
contentWidth: { type: String, default: "narrow" },
|
|
78
|
+
textSize: { type: String, default: "md" }
|
|
76
79
|
});
|
|
77
80
|
const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-6 md:px-12", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-6 md:px-12");
|
|
81
|
+
const containerClass = computed(() => ({ narrow: "max-w-3xl mx-auto", normal: "max-w-5xl mx-auto", wide: "max-w-7xl mx-auto", full: "max-w-full" })[props.contentWidth] || "max-w-3xl mx-auto");
|
|
82
|
+
const quoteFontSize = computed(() => ({ sm: "clamp(1rem,2.5vw,1.8rem)", md: "clamp(1.6rem,4vw,3rem)", lg: "clamp(2rem,6vw,5rem)" })[props.textSize] || "clamp(1.6rem,4vw,3rem)");
|
|
78
83
|
</script>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section :class="[sectionPad]" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
2
|
+
<section :class="[sectionPad]" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
3
|
<div :class="maxW">
|
|
4
4
|
|
|
5
5
|
<!-- Optional title -->
|
|
6
|
-
<component v-if="title" :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9] mb-10" :style="{ fontSize:
|
|
6
|
+
<component v-if="title" :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9] mb-10" :style="{ fontSize: titleFontSize }">{{ title }}</component>
|
|
7
7
|
|
|
8
8
|
<!-- Divider above content -->
|
|
9
9
|
<div v-if="title" class="mb-10 h-px w-12" :style="{ backgroundColor: textColor }"></div>
|
|
@@ -43,11 +43,18 @@ const props = defineProps({
|
|
|
43
43
|
bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
|
|
44
44
|
textColor: { type: String, default: "rgba(var(--text-color), 1)" },
|
|
45
45
|
spacing: { type: String, default: "normal" },
|
|
46
|
-
radius: { type: String, default: "rounded" }
|
|
46
|
+
radius: { type: String, default: "rounded" },
|
|
47
|
+
textDirection: { type: String, default: "ltr" },
|
|
48
|
+
contentWidth: { type: String, default: "normal" },
|
|
49
|
+
textSize: { type: String, default: "md" }
|
|
47
50
|
});
|
|
48
51
|
const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-6 md:px-12", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-6 md:px-12");
|
|
49
52
|
const cardRound = computed(() => ({ sharp: "rounded-lg", rounded: "rounded-xl", pill: "rounded-full" })[props.radius] || "rounded-xl");
|
|
50
|
-
const
|
|
53
|
+
const titleFontSize = computed(() => ({ sm: "clamp(1rem,2vw,1.5rem)", md: "clamp(1.6rem,4vw,3rem)", lg: "clamp(2rem,5vw,4rem)" })[props.textSize] || "clamp(1.6rem,4vw,3rem)");
|
|
54
|
+
const maxW = computed(() => {
|
|
55
|
+
if (props.contentWidth !== "normal") return { narrow: "max-w-2xl mx-auto", normal: "max-w-4xl mx-auto", wide: "max-w-6xl mx-auto", full: "max-w-full" }[props.contentWidth] || "max-w-4xl mx-auto";
|
|
56
|
+
return { article: "max-w-2xl mx-auto", wide: "max-w-4xl mx-auto", full: "w-full" }[props.layout] || "max-w-2xl mx-auto";
|
|
57
|
+
});
|
|
51
58
|
const rendered = computed(() => {
|
|
52
59
|
if (!props.content) return "";
|
|
53
60
|
if (typeof props.content === "object") return props.content.fr || "";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section :class="[sectionPad]" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
|
-
<div class="
|
|
2
|
+
<section :class="[sectionPad]" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
|
+
<div :class="[containerClass]">
|
|
4
4
|
|
|
5
5
|
<div v-if="title || description" class="mb-12" :class="headerAlign === 'center' ? 'text-center max-w-2xl mx-auto' : 'max-w-xl'">
|
|
6
6
|
<span v-if="badge" class="inline-block text-[10px] font-bold tracking-[0.5em] uppercase px-3 py-1 rounded-full border mb-4" :style="{ borderColor: ca(textColor, '25'), color: ca(textColor, 'aa') }">{{ badge }}</span>
|
|
7
|
-
<component :is="titleTag" class="
|
|
8
|
-
<p v-if="description" class="
|
|
7
|
+
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9] mb-4" :style="{ fontSize: titleFontSize }">{{ title }}</component>
|
|
8
|
+
<p v-if="description" :class="[bodyClass, 'leading-relaxed mb-6']" :style="{ opacity: 0.55 }">{{ description }}</p>
|
|
9
9
|
<div v-if="ctas && ctas.length" class="flex flex-wrap gap-3">
|
|
10
10
|
<NuxtLink v-for="(cta, i) in ctas" :key="i" :to="cta.link || '#'"
|
|
11
11
|
class="inline-flex items-center gap-2.5 px-6 py-3 rounded-full text-[11px] font-black uppercase tracking-widest transition-all hover:gap-5"
|
|
@@ -94,8 +94,14 @@ const props = defineProps({
|
|
|
94
94
|
bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
|
|
95
95
|
textColor: { type: String, default: "rgba(var(--text-color), 1)" },
|
|
96
96
|
spacing: { type: String, default: "normal" },
|
|
97
|
-
radius: { type: String, default: "rounded" }
|
|
97
|
+
radius: { type: String, default: "rounded" },
|
|
98
|
+
textDirection: { type: String, default: "ltr" },
|
|
99
|
+
contentWidth: { type: String, default: "normal" },
|
|
100
|
+
textSize: { type: String, default: "md" }
|
|
98
101
|
});
|
|
99
102
|
const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-6 md:px-12", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-6 md:px-12");
|
|
100
103
|
const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-3xl", pill: "rounded-[40px]" })[props.radius] || "rounded-3xl");
|
|
104
|
+
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");
|
|
105
|
+
const titleFontSize = computed(() => ({ sm: "clamp(1.5rem,3vw,2.5rem)", md: "clamp(2rem,4vw,3.5rem)", lg: "clamp(2.5rem,6vw,5rem)" })[props.textSize] || "clamp(2rem,4vw,3.5rem)");
|
|
106
|
+
const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
|
|
101
107
|
</script>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section :class="[sectionPad]" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
|
-
<div class="
|
|
2
|
+
<section :class="[sectionPad]" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
|
+
<div :class="[containerClass]">
|
|
4
4
|
|
|
5
5
|
<div v-if="title || description" class="mb-12 max-w-xl">
|
|
6
6
|
<span v-if="badge" class="inline-block text-[10px] font-bold tracking-[0.5em] uppercase px-3 py-1 rounded-full border mb-4" :style="{ borderColor: ca(textColor, '25'), color: ca(textColor, 'aa') }">{{ badge }}</span>
|
|
7
|
-
<component :is="titleTag" class="
|
|
8
|
-
<p v-if="description" class="
|
|
7
|
+
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9] mb-3" :style="{ fontSize: titleFontSize }">{{ title }}</component>
|
|
8
|
+
<p v-if="description" :class="[bodyClass, 'leading-relaxed']" :style="{ opacity: 0.55 }">{{ description }}</p>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<!-- GRID -->
|
|
@@ -92,8 +92,14 @@ const props = defineProps({
|
|
|
92
92
|
bgColor: { type: String, default: "rgba(var(--body-bg), 1)" },
|
|
93
93
|
textColor: { type: String, default: "rgba(var(--text-color), 1)" },
|
|
94
94
|
spacing: { type: String, default: "normal" },
|
|
95
|
-
radius: { type: String, default: "rounded" }
|
|
95
|
+
radius: { type: String, default: "rounded" },
|
|
96
|
+
textDirection: { type: String, default: "ltr" },
|
|
97
|
+
contentWidth: { type: String, default: "normal" },
|
|
98
|
+
textSize: { type: String, default: "md" }
|
|
96
99
|
});
|
|
97
100
|
const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-6 md:px-12", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-6 md:px-12");
|
|
98
101
|
const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-3xl", pill: "rounded-[40px]" })[props.radius] || "rounded-3xl");
|
|
102
|
+
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");
|
|
103
|
+
const titleFontSize = computed(() => ({ sm: "clamp(1.5rem,3vw,2.5rem)", md: "clamp(2rem,4vw,3.5rem)", lg: "clamp(2.5rem,6vw,5rem)" })[props.textSize] || "clamp(2rem,4vw,3.5rem)");
|
|
104
|
+
const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
|
|
99
105
|
</script>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section :class="[sectionPad]" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
2
|
+
<section :class="[sectionPad]" :dir="textDirection" :style="{ backgroundColor: bgColor, color: textColor }">
|
|
3
3
|
|
|
4
4
|
<!-- SPLIT -->
|
|
5
|
-
<div v-if="layout === 'split'" :class="['
|
|
5
|
+
<div v-if="layout === 'split'" :class="[containerClass, 'flex flex-col md:flex-row gap-12 items-center', reverse ? 'md:flex-row-reverse' : '']">
|
|
6
6
|
<div class="flex-1 space-y-6">
|
|
7
7
|
<span v-if="badge" class="inline-block text-[10px] font-bold tracking-[0.5em] uppercase px-3 py-1 rounded-full border" :style="{ borderColor: ca(textColor, '25'), color: ca(textColor, 'aa') }">{{ badge }}</span>
|
|
8
|
-
<component :is="titleTag" class="
|
|
9
|
-
<p class="leading-relaxed
|
|
8
|
+
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9]" :style="{ fontSize: titleFontSize }">{{ title }}</component>
|
|
9
|
+
<p :class="[bodyClass, 'leading-relaxed max-w-md']" :style="{ opacity: 0.55 }">{{ content }}</p>
|
|
10
10
|
<div v-if="ctas && ctas.length" class="flex flex-wrap gap-3 pt-1">
|
|
11
11
|
<NuxtLink v-for="(cta, i) in ctas" :key="i" :to="cta.link || '#'"
|
|
12
12
|
class="inline-flex items-center gap-2.5 px-6 py-3 rounded-full text-[11px] font-black uppercase tracking-widest transition-all hover:gap-5"
|
|
@@ -22,15 +22,15 @@
|
|
|
22
22
|
</div>
|
|
23
23
|
|
|
24
24
|
<!-- STACKED -->
|
|
25
|
-
<div v-else-if="layout === 'stacked'" class="
|
|
25
|
+
<div v-else-if="layout === 'stacked'" :class="[containerClass, 'space-y-8']">
|
|
26
26
|
<div :class="['w-full overflow-hidden relative', imageContainerClass]">
|
|
27
27
|
<img v-if="image" :src="image" class="w-full h-full object-cover" />
|
|
28
28
|
<div v-else class="w-full h-full" :style="{ backgroundColor: ca(textColor, '08') }"></div>
|
|
29
29
|
</div>
|
|
30
30
|
<div class="space-y-5">
|
|
31
31
|
<span v-if="badge" class="inline-block text-[10px] font-bold tracking-[0.5em] uppercase px-3 py-1 rounded-full border" :style="{ borderColor: ca(textColor, '25'), color: ca(textColor, 'aa') }">{{ badge }}</span>
|
|
32
|
-
<component :is="titleTag" class="
|
|
33
|
-
<p class="leading-relaxed
|
|
32
|
+
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9]" :style="{ fontSize: titleFontSize }">{{ title }}</component>
|
|
33
|
+
<p :class="[bodyClass, 'leading-relaxed']" :style="{ opacity: 0.55 }">{{ content }}</p>
|
|
34
34
|
<div v-if="ctas && ctas.length" class="flex flex-wrap gap-3 pt-1">
|
|
35
35
|
<NuxtLink v-for="(cta, i) in ctas" :key="i" :to="cta.link || '#'"
|
|
36
36
|
class="inline-flex items-center gap-2.5 px-6 py-3 rounded-full text-[11px] font-black uppercase tracking-widest transition-all hover:gap-5"
|
|
@@ -42,15 +42,15 @@
|
|
|
42
42
|
</div>
|
|
43
43
|
|
|
44
44
|
<!-- WIDE -->
|
|
45
|
-
<div v-else :class="['
|
|
45
|
+
<div v-else :class="[containerClass, 'flex flex-col md:flex-row gap-10 items-center', reverse ? 'md:flex-row-reverse' : '']">
|
|
46
46
|
<div :class="['md:w-2/3 w-full overflow-hidden relative', imageContainerClass]">
|
|
47
47
|
<img v-if="image" :src="image" class="w-full h-full object-cover transition-transform duration-700 hover:scale-105" />
|
|
48
48
|
<div v-else class="w-full h-full" :style="{ backgroundColor: ca(textColor, '08') }"></div>
|
|
49
49
|
</div>
|
|
50
50
|
<div class="md:w-1/3 space-y-5">
|
|
51
51
|
<span v-if="badge" class="inline-block text-[10px] font-bold tracking-[0.5em] uppercase px-3 py-1 rounded-full border" :style="{ borderColor: ca(textColor, '25'), color: ca(textColor, 'aa') }">{{ badge }}</span>
|
|
52
|
-
<component :is="titleTag" class="
|
|
53
|
-
<p class="leading-relaxed
|
|
52
|
+
<component :is="titleTag" class="font-black uppercase tracking-tighter leading-[0.9]" :style="{ fontSize: titleFontSize }">{{ title }}</component>
|
|
53
|
+
<p :class="[bodyClass, 'leading-relaxed']" :style="{ opacity: 0.55 }">{{ content }}</p>
|
|
54
54
|
<div v-if="ctas && ctas.length" class="flex flex-wrap gap-3 pt-1">
|
|
55
55
|
<NuxtLink v-for="(cta, i) in ctas" :key="i" :to="cta.link || '#'"
|
|
56
56
|
class="inline-flex items-center gap-2.5 px-6 py-3 rounded-full text-[11px] font-black uppercase tracking-widest transition-all hover:gap-5"
|
|
@@ -86,10 +86,16 @@ const props = defineProps({
|
|
|
86
86
|
textColor: { type: String, default: "rgba(var(--text-color), 1)" },
|
|
87
87
|
ctas: { type: Array, default: () => [] },
|
|
88
88
|
spacing: { type: String, default: "normal" },
|
|
89
|
-
radius: { type: String, default: "rounded" }
|
|
89
|
+
radius: { type: String, default: "rounded" },
|
|
90
|
+
textDirection: { type: String, default: "ltr" },
|
|
91
|
+
contentWidth: { type: String, default: "normal" },
|
|
92
|
+
textSize: { type: String, default: "md" }
|
|
90
93
|
});
|
|
91
94
|
const sectionPad = computed(() => ({ compact: "py-8 px-4 md:px-8", normal: "py-14 px-6 md:px-12", spacious: "py-24 px-8 md:px-16" })[props.spacing] || "py-14 px-6 md:px-12");
|
|
92
95
|
const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-3xl", pill: "rounded-[40px]" })[props.radius] || "rounded-3xl");
|
|
96
|
+
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");
|
|
97
|
+
const titleFontSize = computed(() => ({ sm: "clamp(1.2rem,2.5vw,2rem)", md: "clamp(1.5rem,3.5vw,2.8rem)", lg: "clamp(2rem,5vw,4rem)" })[props.textSize] || "clamp(1.5rem,3.5vw,2.8rem)");
|
|
98
|
+
const bodyClass = computed(() => ({ sm: "text-xs", md: "text-sm", lg: "text-base" })[props.textSize] || "text-sm");
|
|
93
99
|
const imageContainerClass = computed(() => {
|
|
94
100
|
const r = cardRound.value;
|
|
95
101
|
const styles = { rounded: `aspect-[4/3] ${r}`, square: "aspect-square rounded-xl", circle: "aspect-square rounded-full max-w-[360px] mx-auto", portrait: `aspect-[3/4] ${r} max-w-sm mx-auto` };
|