cinqcinqdev-seo 0.1.70 → 0.1.72

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 CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0"
6
6
  },
7
- "version": "0.1.70",
7
+ "version": "0.1.72",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "unknown"
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="isVisible ? 'sec-in' : 'sec-out'" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
3
 
4
4
  <!-- ── CENTERED ─────────────────────────────────────────────── -->
5
5
  <div v-if="layout === 'centered'" :class="[sectionPad]">
@@ -121,7 +121,7 @@ const ca = (c, h) => {
121
121
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
122
122
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
123
123
  };
124
- import { computed } from "vue";
124
+ import { ref, computed, onMounted } from "vue";
125
125
  const props = defineProps({
126
126
  layout: { type: String, default: "centered" },
127
127
  titleTag: { type: String, default: "h1" },
@@ -144,7 +144,25 @@ const props = defineProps({
144
144
  paddingTop: { type: String, default: "" },
145
145
  paddingBottom: { type: String, default: "" },
146
146
  marginTop: { type: String, default: "" },
147
- marginBottom: { type: String, default: "" }
147
+ marginBottom: { type: String, default: "" },
148
+ paddingX: { type: String, default: "" }
149
+ });
150
+ const sectionEl = ref(null);
151
+ const isVisible = ref(false);
152
+ onMounted(() => {
153
+ const obs = new IntersectionObserver(
154
+ ([e]) => {
155
+ if (e.isIntersecting) {
156
+ isVisible.value = true;
157
+ obs.disconnect();
158
+ }
159
+ },
160
+ { threshold: 0.06 }
161
+ );
162
+ if (sectionEl.value) obs.observe(sectionEl.value);
163
+ setTimeout(() => {
164
+ if (!isVisible.value) isVisible.value = true;
165
+ }, 300);
148
166
  });
149
167
  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");
150
168
  const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-[24px]", pill: "rounded-[36px]" })[props.radius] || "rounded-[24px]");
@@ -161,6 +179,20 @@ const spacingStyle = computed(() => {
161
179
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
162
180
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
163
181
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
182
+ if (props.paddingX && SM[props.paddingX]) {
183
+ const v = SM[props.paddingX];
184
+ if (v.startsWith("-")) {
185
+ s.marginLeft = v;
186
+ s.marginRight = v;
187
+ } else {
188
+ s.paddingLeft = v;
189
+ s.paddingRight = v;
190
+ }
191
+ }
164
192
  return s;
165
193
  });
166
194
  </script>
195
+
196
+ <style scoped>
197
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
198
+ </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :class="[sectionPad]" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="[sectionPad, isVisible ? 'sec-in' : 'sec-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
3
 
4
4
  <!-- CENTERED -->
5
5
  <div v-if="layout === 'centered'" :class="[containerClass, 'text-center']">
@@ -65,7 +65,7 @@ const ca = (c, h) => {
65
65
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
66
66
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
67
67
  };
68
- import { computed } from "vue";
68
+ import { ref, computed, onMounted } from "vue";
69
69
  const props = defineProps({
70
70
  layout: { type: String, default: "centered" },
71
71
  badge: { type: String, default: "" },
@@ -85,7 +85,25 @@ const props = defineProps({
85
85
  paddingTop: { type: String, default: "" },
86
86
  paddingBottom: { type: String, default: "" },
87
87
  marginTop: { type: String, default: "" },
88
- marginBottom: { type: String, default: "" }
88
+ marginBottom: { type: String, default: "" },
89
+ paddingX: { type: String, default: "" }
90
+ });
91
+ const sectionEl = ref(null);
92
+ const isVisible = ref(false);
93
+ onMounted(() => {
94
+ const obs = new IntersectionObserver(
95
+ ([e]) => {
96
+ if (e.isIntersecting) {
97
+ isVisible.value = true;
98
+ obs.disconnect();
99
+ }
100
+ },
101
+ { threshold: 0.06 }
102
+ );
103
+ if (sectionEl.value) obs.observe(sectionEl.value);
104
+ setTimeout(() => {
105
+ if (!isVisible.value) isVisible.value = true;
106
+ }, 300);
89
107
  });
90
108
  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");
91
109
  const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-2xl", pill: "rounded-full" })[props.radius] || "rounded-2xl");
@@ -99,6 +117,20 @@ const spacingStyle = computed(() => {
99
117
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
100
118
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
101
119
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
120
+ if (props.paddingX && SM[props.paddingX]) {
121
+ const v = SM[props.paddingX];
122
+ if (v.startsWith("-")) {
123
+ s.marginLeft = v;
124
+ s.marginRight = v;
125
+ } else {
126
+ s.paddingLeft = v;
127
+ s.paddingRight = v;
128
+ }
129
+ }
102
130
  return s;
103
131
  });
104
132
  </script>
133
+
134
+ <style scoped>
135
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
136
+ </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :class="[sectionPad]" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="[sectionPad, isVisible ? 'sec-in' : 'sec-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
3
  <div :class="[containerClass]">
4
4
 
5
5
  <!-- SPLIT layout -->
@@ -100,7 +100,7 @@ const ca = (c, h) => {
100
100
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
101
101
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
102
102
  };
103
- import { ref, reactive, computed } from "vue";
103
+ import { ref, reactive, computed, onMounted } from "vue";
104
104
  const props = defineProps({
105
105
  layout: { type: String, default: "split" },
106
106
  title: { type: String, default: "Contactez-nous" },
@@ -116,6 +116,7 @@ const props = defineProps({
116
116
  paddingBottom: { type: String, default: "" },
117
117
  marginTop: { type: String, default: "" },
118
118
  marginBottom: { type: String, default: "" },
119
+ paddingX: { type: String, default: "" },
119
120
  fields: {
120
121
  type: Array,
121
122
  default: () => [
@@ -130,6 +131,23 @@ const props = defineProps({
130
131
  spacing: { type: String, default: "normal" },
131
132
  radius: { type: String, default: "rounded" }
132
133
  });
134
+ const sectionEl = ref(null);
135
+ const isVisible = ref(false);
136
+ onMounted(() => {
137
+ const obs = new IntersectionObserver(
138
+ ([e]) => {
139
+ if (e.isIntersecting) {
140
+ isVisible.value = true;
141
+ obs.disconnect();
142
+ }
143
+ },
144
+ { threshold: 0.06 }
145
+ );
146
+ if (sectionEl.value) obs.observe(sectionEl.value);
147
+ setTimeout(() => {
148
+ if (!isVisible.value) isVisible.value = true;
149
+ }, 300);
150
+ });
133
151
  const emit = defineEmits(["submit"]);
134
152
  const submitting = ref(false);
135
153
  const sent = ref(false);
@@ -156,6 +174,20 @@ const spacingStyle = computed(() => {
156
174
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
157
175
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
158
176
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
177
+ if (props.paddingX && SM[props.paddingX]) {
178
+ const v = SM[props.paddingX];
179
+ if (v.startsWith("-")) {
180
+ s.marginLeft = v;
181
+ s.marginRight = v;
182
+ } else {
183
+ s.paddingLeft = v;
184
+ s.paddingRight = v;
185
+ }
186
+ }
159
187
  return s;
160
188
  });
161
189
  </script>
190
+
191
+ <style scoped>
192
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
193
+ </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :class="[sectionPad]" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="[sectionPad, isVisible ? 'sec-in' : 'sec-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
3
  <div :class="[containerClass]">
4
4
  <div class="text-center mb-16">
5
5
  <component :is="titleTag" class="font-black uppercase tracking-tighter italic" :style="{ fontSize: titleFontSize }">{{ title }}</component>
@@ -31,7 +31,7 @@ const ca = (c, h) => {
31
31
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
32
32
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
33
33
  };
34
- import { ref, computed } from "vue";
34
+ import { ref, computed, onMounted } from "vue";
35
35
  const props = defineProps({
36
36
  title: { type: String, default: "FAQ" },
37
37
  titleTag: { type: String, default: "h2" },
@@ -46,7 +46,25 @@ const props = defineProps({
46
46
  paddingTop: { type: String, default: "" },
47
47
  paddingBottom: { type: String, default: "" },
48
48
  marginTop: { type: String, default: "" },
49
- marginBottom: { type: String, default: "" }
49
+ marginBottom: { type: String, default: "" },
50
+ paddingX: { type: String, default: "" }
51
+ });
52
+ const sectionEl = ref(null);
53
+ const isVisible = ref(false);
54
+ onMounted(() => {
55
+ const obs = new IntersectionObserver(
56
+ ([e]) => {
57
+ if (e.isIntersecting) {
58
+ isVisible.value = true;
59
+ obs.disconnect();
60
+ }
61
+ },
62
+ { threshold: 0.06 }
63
+ );
64
+ if (sectionEl.value) obs.observe(sectionEl.value);
65
+ setTimeout(() => {
66
+ if (!isVisible.value) isVisible.value = true;
67
+ }, 300);
50
68
  });
51
69
  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");
52
70
  const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-[24px]", pill: "rounded-[36px]" })[props.radius] || "rounded-[24px]");
@@ -64,6 +82,20 @@ const spacingStyle = computed(() => {
64
82
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
65
83
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
66
84
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
85
+ if (props.paddingX && SM[props.paddingX]) {
86
+ const v = SM[props.paddingX];
87
+ if (v.startsWith("-")) {
88
+ s.marginLeft = v;
89
+ s.marginRight = v;
90
+ } else {
91
+ s.paddingLeft = v;
92
+ s.paddingRight = v;
93
+ }
94
+ }
67
95
  return s;
68
96
  });
69
97
  </script>
98
+
99
+ <style scoped>
100
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
101
+ </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :class="[sectionPad, 'overflow-hidden']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="[sectionPad, 'overflow-hidden', isVisible ? 'sec-in' : 'sec-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
3
  <div :class="[containerClass]">
4
4
  <div class="mb-16 md:mb-20">
5
5
  <component :is="titleTag" class="font-black uppercase tracking-tighter leading-none italic" :style="{ fontSize: titleFontSize }">{{ title }}</component>
@@ -29,7 +29,7 @@ const ca = (c, h) => {
29
29
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
30
30
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
31
31
  };
32
- import { computed } from "vue";
32
+ import { ref, computed, onMounted } from "vue";
33
33
  const props = defineProps({
34
34
  title: { type: String, default: "Why choose us?" },
35
35
  titleTag: { type: String, default: "h2" },
@@ -45,7 +45,25 @@ const props = defineProps({
45
45
  paddingTop: { type: String, default: "" },
46
46
  paddingBottom: { type: String, default: "" },
47
47
  marginTop: { type: String, default: "" },
48
- marginBottom: { type: String, default: "" }
48
+ marginBottom: { type: String, default: "" },
49
+ paddingX: { type: String, default: "" }
50
+ });
51
+ const sectionEl = ref(null);
52
+ const isVisible = ref(false);
53
+ onMounted(() => {
54
+ const obs = new IntersectionObserver(
55
+ ([e]) => {
56
+ if (e.isIntersecting) {
57
+ isVisible.value = true;
58
+ obs.disconnect();
59
+ }
60
+ },
61
+ { threshold: 0.06 }
62
+ );
63
+ if (sectionEl.value) obs.observe(sectionEl.value);
64
+ setTimeout(() => {
65
+ if (!isVisible.value) isVisible.value = true;
66
+ }, 300);
49
67
  });
50
68
  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");
51
69
  const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-[32px]", pill: "rounded-[48px]" })[props.radius] || "rounded-[32px]");
@@ -59,6 +77,20 @@ const spacingStyle = computed(() => {
59
77
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
60
78
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
61
79
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
80
+ if (props.paddingX && SM[props.paddingX]) {
81
+ const v = SM[props.paddingX];
82
+ if (v.startsWith("-")) {
83
+ s.marginLeft = v;
84
+ s.marginRight = v;
85
+ } else {
86
+ s.paddingLeft = v;
87
+ s.paddingRight = v;
88
+ }
89
+ }
62
90
  return s;
63
91
  });
64
92
  </script>
93
+
94
+ <style scoped>
95
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
96
+ </style>
@@ -193,9 +193,11 @@ const props = defineProps({
193
193
  paddingBottom: { type: String, default: "" },
194
194
  marginTop: { type: String, default: "" },
195
195
  marginBottom: { type: String, default: "" },
196
- overlay: { default: null },
196
+ paddingX: { type: String, default: "" },
197
+ overlay: { type: String, default: "auto" },
197
198
  overlayDirection: { type: String, default: "to top" },
198
- overlayStrength: { type: String, default: "medium" }
199
+ overlayStrength: { type: String, default: "medium" },
200
+ overlayColor: { type: String, default: "" }
199
201
  });
200
202
  const sectionEl = ref(null);
201
203
  const isVisible = ref(false);
@@ -225,13 +227,13 @@ const as_ = (n) => {
225
227
  return { animationDelay: `${n * 0.1}s`, animationFillMode: "both" };
226
228
  };
227
229
  const showOverlay = computed(() => {
228
- if (props.overlay === false) return false;
229
- if (props.overlay === true) return true;
230
+ if (props.overlay === "off") return false;
231
+ if (props.overlay === "on") return true;
230
232
  return ["fullscreen", "parallax", "video", "magazine"].includes(props.layout);
231
233
  });
232
234
  const overlayStyle = computed(() => {
233
235
  const dir = props.overlayDirection || "to top";
234
- const c = props.bgColor;
236
+ const c = props.overlayColor || props.bgColor;
235
237
  const stops = {
236
238
  light: `linear-gradient(${dir}, ${ca(c, "99")} 0%, ${ca(c, "44")} 40%, transparent 70%)`,
237
239
  medium: `linear-gradient(${dir}, ${c} 15%, ${ca(c, "cc")} 40%, ${ca(c, "44")} 65%, transparent 100%)`,
@@ -249,6 +251,16 @@ const spacingStyle = computed(() => {
249
251
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
250
252
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
251
253
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
254
+ if (props.paddingX && SM[props.paddingX]) {
255
+ const v = SM[props.paddingX];
256
+ if (v.startsWith("-")) {
257
+ s.marginLeft = v;
258
+ s.marginRight = v;
259
+ } else {
260
+ s.paddingLeft = v;
261
+ s.paddingRight = v;
262
+ }
263
+ }
252
264
  return s;
253
265
  });
254
266
  </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :class="[sectionPad]" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="[sectionPad, isVisible ? 'sec-in' : 'sec-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
3
 
4
4
  <!-- CENTERED -->
5
5
  <div v-if="layout === 'centered'" :class="[containerClass, 'text-center']">
@@ -51,7 +51,7 @@ const ca = (c, h) => {
51
51
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
52
52
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
53
53
  };
54
- import { computed } from "vue";
54
+ import { ref, computed, onMounted } from "vue";
55
55
  const props = defineProps({
56
56
  layout: { type: String, default: "centered" },
57
57
  badge: { type: String, default: "" },
@@ -70,7 +70,25 @@ const props = defineProps({
70
70
  paddingTop: { type: String, default: "" },
71
71
  paddingBottom: { type: String, default: "" },
72
72
  marginTop: { type: String, default: "" },
73
- marginBottom: { type: String, default: "" }
73
+ marginBottom: { type: String, default: "" },
74
+ paddingX: { type: String, default: "" }
75
+ });
76
+ const sectionEl = ref(null);
77
+ const isVisible = ref(false);
78
+ onMounted(() => {
79
+ const obs = new IntersectionObserver(
80
+ ([e]) => {
81
+ if (e.isIntersecting) {
82
+ isVisible.value = true;
83
+ obs.disconnect();
84
+ }
85
+ },
86
+ { threshold: 0.06 }
87
+ );
88
+ if (sectionEl.value) obs.observe(sectionEl.value);
89
+ setTimeout(() => {
90
+ if (!isVisible.value) isVisible.value = true;
91
+ }, 300);
74
92
  });
75
93
  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");
76
94
  const cardRound = computed(() => ({ sharp: "rounded-lg", rounded: "rounded-xl", pill: "rounded-full" })[props.radius] || "rounded-xl");
@@ -84,6 +102,20 @@ const spacingStyle = computed(() => {
84
102
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
85
103
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
86
104
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
105
+ if (props.paddingX && SM[props.paddingX]) {
106
+ const v = SM[props.paddingX];
107
+ if (v.startsWith("-")) {
108
+ s.marginLeft = v;
109
+ s.marginRight = v;
110
+ } else {
111
+ s.paddingLeft = v;
112
+ s.paddingRight = v;
113
+ }
114
+ }
87
115
  return s;
88
116
  });
89
117
  </script>
118
+
119
+ <style scoped>
120
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
121
+ </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :class="[sectionPad]" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="[sectionPad, isVisible ? 'sec-in' : 'sec-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
3
  <div :class="[containerClass]">
4
4
 
5
5
  <div v-if="title || description" class="mb-12 text-center max-w-2xl mx-auto">
@@ -88,7 +88,7 @@ const ca = (c, h) => {
88
88
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
89
89
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
90
90
  };
91
- import { computed } from "vue";
91
+ import { ref, computed, onMounted } from "vue";
92
92
  const props = defineProps({
93
93
  layout: { type: String, default: "cards" },
94
94
  title: { type: String, default: "Our Pricing" },
@@ -106,7 +106,25 @@ const props = defineProps({
106
106
  paddingTop: { type: String, default: "" },
107
107
  paddingBottom: { type: String, default: "" },
108
108
  marginTop: { type: String, default: "" },
109
- marginBottom: { type: String, default: "" }
109
+ marginBottom: { type: String, default: "" },
110
+ paddingX: { type: String, default: "" }
111
+ });
112
+ const sectionEl = ref(null);
113
+ const isVisible = ref(false);
114
+ onMounted(() => {
115
+ const obs = new IntersectionObserver(
116
+ ([e]) => {
117
+ if (e.isIntersecting) {
118
+ isVisible.value = true;
119
+ obs.disconnect();
120
+ }
121
+ },
122
+ { threshold: 0.06 }
123
+ );
124
+ if (sectionEl.value) obs.observe(sectionEl.value);
125
+ setTimeout(() => {
126
+ if (!isVisible.value) isVisible.value = true;
127
+ }, 300);
110
128
  });
111
129
  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");
112
130
  const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-3xl", pill: "rounded-[40px]" })[props.radius] || "rounded-3xl");
@@ -126,6 +144,20 @@ const spacingStyle = computed(() => {
126
144
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
127
145
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
128
146
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
147
+ if (props.paddingX && SM[props.paddingX]) {
148
+ const v = SM[props.paddingX];
149
+ if (v.startsWith("-")) {
150
+ s.marginLeft = v;
151
+ s.marginRight = v;
152
+ } else {
153
+ s.paddingLeft = v;
154
+ s.paddingRight = v;
155
+ }
156
+ }
129
157
  return s;
130
158
  });
131
159
  </script>
160
+
161
+ <style scoped>
162
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
163
+ </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :class="[sectionPad]" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="[sectionPad, isVisible ? 'sec-in' : 'sec-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
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'">
@@ -80,7 +80,7 @@ const ca = (c, h) => {
80
80
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
81
81
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
82
82
  };
83
- import { computed } from "vue";
83
+ import { ref, computed, onMounted } from "vue";
84
84
  const props = defineProps({
85
85
  layout: { type: String, default: "steps" },
86
86
  title: { type: String, default: "How it works" },
@@ -99,7 +99,25 @@ const props = defineProps({
99
99
  paddingTop: { type: String, default: "" },
100
100
  paddingBottom: { type: String, default: "" },
101
101
  marginTop: { type: String, default: "" },
102
- marginBottom: { type: String, default: "" }
102
+ marginBottom: { type: String, default: "" },
103
+ paddingX: { type: String, default: "" }
104
+ });
105
+ const sectionEl = ref(null);
106
+ const isVisible = ref(false);
107
+ onMounted(() => {
108
+ const obs = new IntersectionObserver(
109
+ ([e]) => {
110
+ if (e.isIntersecting) {
111
+ isVisible.value = true;
112
+ obs.disconnect();
113
+ }
114
+ },
115
+ { threshold: 0.06 }
116
+ );
117
+ if (sectionEl.value) obs.observe(sectionEl.value);
118
+ setTimeout(() => {
119
+ if (!isVisible.value) isVisible.value = true;
120
+ }, 300);
103
121
  });
104
122
  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
123
  const cardRound = computed(() => ({ sharp: "rounded-xl", rounded: "rounded-3xl", pill: "rounded-[40px]" })[props.radius] || "rounded-3xl");
@@ -113,6 +131,20 @@ const spacingStyle = computed(() => {
113
131
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
114
132
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
115
133
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
134
+ if (props.paddingX && SM[props.paddingX]) {
135
+ const v = SM[props.paddingX];
136
+ if (v.startsWith("-")) {
137
+ s.marginLeft = v;
138
+ s.marginRight = v;
139
+ } else {
140
+ s.paddingLeft = v;
141
+ s.paddingRight = v;
142
+ }
143
+ }
116
144
  return s;
117
145
  });
118
146
  </script>
147
+
148
+ <style scoped>
149
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
150
+ </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <section :class="[sectionPad]" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
2
+ <section ref="sectionEl" :class="[sectionPad, isVisible ? 'sec-in' : 'sec-out']" :dir="textDirection" :style="[{ backgroundColor: bgColor, color: textColor }, spacingStyle]">
3
3
 
4
4
  <!-- CENTERED -->
5
5
  <div v-if="layout === 'centered'" :class="[containerClass, 'text-center']">
@@ -62,7 +62,7 @@ const ca = (c, h) => {
62
62
  const m = c.match(/rgba\((var\([^)]+\)),\s*[\d.]+\)/);
63
63
  return m ? `rgba(${m[1]}, ${Math.round(parseInt(h, 16) / 255 * 1e3) / 1e3})` : c + h;
64
64
  };
65
- import { computed } from "vue";
65
+ import { ref, computed, onMounted } from "vue";
66
66
  const props = defineProps({
67
67
  layout: { type: String, default: "centered" },
68
68
  quote: { type: String, default: "" },
@@ -79,7 +79,25 @@ const props = defineProps({
79
79
  paddingTop: { type: String, default: "" },
80
80
  paddingBottom: { type: String, default: "" },
81
81
  marginTop: { type: String, default: "" },
82
- marginBottom: { type: String, default: "" }
82
+ marginBottom: { type: String, default: "" },
83
+ paddingX: { type: String, default: "" }
84
+ });
85
+ const sectionEl = ref(null);
86
+ const isVisible = ref(false);
87
+ onMounted(() => {
88
+ const obs = new IntersectionObserver(
89
+ ([e]) => {
90
+ if (e.isIntersecting) {
91
+ isVisible.value = true;
92
+ obs.disconnect();
93
+ }
94
+ },
95
+ { threshold: 0.06 }
96
+ );
97
+ if (sectionEl.value) obs.observe(sectionEl.value);
98
+ setTimeout(() => {
99
+ if (!isVisible.value) isVisible.value = true;
100
+ }, 300);
83
101
  });
84
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");
85
103
  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");
@@ -91,6 +109,20 @@ const spacingStyle = computed(() => {
91
109
  if (props.paddingBottom && SM[props.paddingBottom]) s.paddingBottom = SM[props.paddingBottom];
92
110
  if (props.marginTop && SM[props.marginTop]) s.marginTop = SM[props.marginTop];
93
111
  if (props.marginBottom && SM[props.marginBottom]) s.marginBottom = SM[props.marginBottom];
112
+ if (props.paddingX && SM[props.paddingX]) {
113
+ const v = SM[props.paddingX];
114
+ if (v.startsWith("-")) {
115
+ s.marginLeft = v;
116
+ s.marginRight = v;
117
+ } else {
118
+ s.paddingLeft = v;
119
+ s.paddingRight = v;
120
+ }
121
+ }
94
122
  return s;
95
123
  });
96
124
  </script>
125
+
126
+ <style scoped>
127
+ .sec-out{opacity:0;transform:translateY(20px)}.sec-in{opacity:1;transform:none;transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1)}
128
+ </style>