@dcodegroup-au/page-builder 0.5.8 → 0.6.0
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/page-builder.css +185 -0
- package/dist/page-builder.es.js +6111 -5532
- package/dist/page-builder.umd.js +6111 -5532
- package/example/src/App.vue +5 -3
- package/example/src/pages/AssessmentSupportService.js +120 -0
- package/example/src/pages/LandingPage.js +245 -0
- package/package.json +1 -1
- package/src/assets/svg/select-type.svg +4 -0
- package/src/components/PageBuilder.vue +4 -0
- package/src/components/PageRender.vue +6 -0
- package/src/components/builders/Header.vue +18 -0
- package/src/components/builders/HorizontalTabs.vue +21 -0
- package/src/components/builders/Links.vue +1 -1
- package/src/components/helpers/pageBuilderFactory.js +1 -1
- package/src/components/presenters/modules/AccordionPricing.vue +72 -0
- package/src/components/presenters/modules/HorizontalTabs.vue +161 -0
- package/src/components/presenters/modules/Paragraph.vue +1 -1
- package/src/components/presenters/modules/StandardHeader.vue +25 -4
- package/src/components/presenters/modules/TestimonialSlider.vue +88 -0
- package/src/components/presenters/modules/TwoColumnsImageContent.vue +18 -3
- package/tailwind.config.js +5 -0
|
@@ -44,7 +44,7 @@ export function createItem(overrides = {}, withSecondary = true, isTimeline = fa
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export function createLink(overrides = {}, type = null) {
|
|
47
|
-
if (type === 'faqs') {
|
|
47
|
+
if (type === 'faqs' || type === 'pricing') {
|
|
48
48
|
return {
|
|
49
49
|
has_extra: true,
|
|
50
50
|
as_item: true,
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="max-w-[1640px] md:px-[120px] mx-auto w-full py-[40px] flex justify-center gap-[10%] ">
|
|
3
|
+
<div class="bg-pale-100 flex w-full rounded-[20px] p-8 gap-6">
|
|
4
|
+
<div class="w-1/2">
|
|
5
|
+
<p class="text-[36px] font-semibold text-gray-900 mb-[48px]" v-text="pricingComponent.title"></p>
|
|
6
|
+
<div class="flex flex-col divide-y divide-gray-200 px-6 bg-white rounded-[16px] overflow-hidden">
|
|
7
|
+
<div v-for="(price, index) in pricingComponent.data"
|
|
8
|
+
class="relative w-full py-6">
|
|
9
|
+
<a class="text-gray-900 cursor-pointer w-full inline-flex justify-between gap-1.5 items-center leading-[28px] font-semibold text-lg">
|
|
10
|
+
<span class="hover:underline text-lg leading-[28px] text-gray-900" @click="toggle(index)">
|
|
11
|
+
{{ price.title }}
|
|
12
|
+
</span>
|
|
13
|
+
<span class="min-w-[24px]">
|
|
14
|
+
<Plus v-if="!show[index]"
|
|
15
|
+
class="w-6 h-6 cursor-pointer text-gray-400 hover:text-gray-700"
|
|
16
|
+
@click="toggle(index)"></Plus>
|
|
17
|
+
<Minus v-else
|
|
18
|
+
class="w-6 h-6 cursor-pointer text-gray-400 hover:text-gray-700"
|
|
19
|
+
@click="toggle(index)"></Minus>
|
|
20
|
+
</span>
|
|
21
|
+
</a>
|
|
22
|
+
<p v-if="show[index]" class="mt-2 text-gray-600 leading-[24px] all-unset"
|
|
23
|
+
v-html="price?.supporting_text"></p>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="w-1/2 bg-white rounded-[16px] overflow-hidden flex flex-col items-center justify-center px-12">
|
|
28
|
+
<div v-if="paragraphComponent">
|
|
29
|
+
<p class="text-[32px] font-semibold text-gray-900" v-text="paragraphComponent.title"></p>
|
|
30
|
+
<p class="text-[18px]text-gray-600 mt-2" v-html="paragraphComponent.paragraph"></p>
|
|
31
|
+
</div>
|
|
32
|
+
<a v-if="paragraphComponent?.hasOwnProperty('button') && paragraphComponent.button.show" :href="paragraphComponent.button.url"
|
|
33
|
+
class="mt-4 flex justify-center items-center w-full gap-2 px-3 py-2.5 rounded-full shadow-xs text-[16px] font-semibold text-white bg-brand-600 hover:bg-brand-700 border border-brand-600 text-center cursor-pointer"
|
|
34
|
+
>
|
|
35
|
+
{{ paragraphComponent.button.title }} <ArrowUpRight class="w-5 h-5"></ArrowUpRight>
|
|
36
|
+
</a>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
<script setup>
|
|
42
|
+
import {ref, computed} from "vue";
|
|
43
|
+
import Plus from "@/assets/img/icons/plus-circle.svg";
|
|
44
|
+
import Minus from "@/assets/img/icons/minus-circle.svg";
|
|
45
|
+
import ArrowUpRight from "@/assets/img/icons/arrow-up-right.svg";
|
|
46
|
+
|
|
47
|
+
const props = defineProps({
|
|
48
|
+
section: {
|
|
49
|
+
required: true,
|
|
50
|
+
type: Object,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const section = ref(props.section);
|
|
55
|
+
const show = ref([]);
|
|
56
|
+
const paragraphComponent = computed(() => {
|
|
57
|
+
return section.value.components.find((component) => component.type === "paragraph");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const pricingComponent = computed(() => {
|
|
61
|
+
return section.value.components.find((component) => component.type === "pricing");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
pricingComponent.value.data.forEach((value, index) => {
|
|
65
|
+
show.value[index] = false;
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const toggle = (index) => {
|
|
69
|
+
show.value[index] = !show.value[index];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
</script>
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section class="px-6 mt-4 mb-36">
|
|
3
|
+
<div class="bg-navy-800 p-10 rounded-[48px]">
|
|
4
|
+
<div class="max-w-[51.25rem] text-center mx-auto">
|
|
5
|
+
<article class="mb-10">
|
|
6
|
+
<p class="leading-6 font-semibold text-yellow-100 mb-2" v-text="headerComponent.sub_title"></p>
|
|
7
|
+
<h2 class="text-5xl leading-10 mb-4 font-semibold text-white" v-text="headerComponent.title"></h2>
|
|
8
|
+
<p class="text-xl leading-8 text-gray-200" v-text="headerComponent.supporting_text"></p>
|
|
9
|
+
</article>
|
|
10
|
+
|
|
11
|
+
<nav class="h-14 border border-white rounded-[48px] flex items-center justify-stretch px-1.5 space-x-1 mb-8">
|
|
12
|
+
<button
|
|
13
|
+
v-for="membership in horizontalTabComponent.data"
|
|
14
|
+
:key="membership.id"
|
|
15
|
+
@click="active = membership.id"
|
|
16
|
+
class="h-11 rounded-[48px] flex-1 text-white transition-colors text-md font-semibold"
|
|
17
|
+
:class="{ 'bg-white !text-gray-700': active === membership.id }"
|
|
18
|
+
>
|
|
19
|
+
{{ membership.name }}
|
|
20
|
+
</button>
|
|
21
|
+
</nav>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<!-- Show image when none selected with transition -->
|
|
25
|
+
<div v-if="!active" class="flex justify-center pb-32">
|
|
26
|
+
<SelectType></SelectType>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<!-- Membership details with transition -->
|
|
30
|
+
<Transition name="fade" mode="out-in">
|
|
31
|
+
<div
|
|
32
|
+
v-if="activeMembership"
|
|
33
|
+
:key="activeMembership.id"
|
|
34
|
+
class="bg-white py-8 rounded-3xl shadow-sm border border-gray-200 flex max-w-[1400px] mx-auto -mb-[140px]"
|
|
35
|
+
>
|
|
36
|
+
<!-- Left section -->
|
|
37
|
+
<div class="w-2/5 px-8">
|
|
38
|
+
<div
|
|
39
|
+
:class="[
|
|
40
|
+
'p-8 rounded-[20px] text-left min-h-full',
|
|
41
|
+
activeMembership.theme === 'dark' ? 'bg-navy-25' : 'bg-brand-25'
|
|
42
|
+
]"
|
|
43
|
+
>
|
|
44
|
+
<span
|
|
45
|
+
:class="[
|
|
46
|
+
'w-12 h-12 flex items-center justify-center rounded-full mb-4',
|
|
47
|
+
activeMembership.theme === 'dark' ? 'bg-navy-100 text-navy-600' : 'bg-brand-100 text-brand-600'
|
|
48
|
+
]"
|
|
49
|
+
>
|
|
50
|
+
<StarIcon class="w-5 h-5"></StarIcon>
|
|
51
|
+
</span>
|
|
52
|
+
<h3
|
|
53
|
+
:class="[
|
|
54
|
+
'text-4xl leading-10 font-semibold mb-4',
|
|
55
|
+
activeMembership.theme === 'dark' ? 'text-navy-700' : 'text-brand-700'
|
|
56
|
+
]"
|
|
57
|
+
>
|
|
58
|
+
{{ activeMembership.name }}
|
|
59
|
+
</h3>
|
|
60
|
+
<p class="leading-6 text-gray-600">{{ activeMembership.description }}</p>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<!-- Right section -->
|
|
65
|
+
<div class="w-3/5 px-8 flex flex-col justify-between">
|
|
66
|
+
<div class="mb-12">
|
|
67
|
+
<div class="flex space-x-6">
|
|
68
|
+
<div v-if="activeMembership.access" class="flex-1">
|
|
69
|
+
<h4 class="font-bold text-gray-900 leading-6 mb-6">{{ activeMembership.access.title }}</h4>
|
|
70
|
+
<ul>
|
|
71
|
+
<li
|
|
72
|
+
v-for="(item, idx) in activeMembership.access.list"
|
|
73
|
+
:key="`access-${activeMembership.id}-${idx}`"
|
|
74
|
+
class="leading-6 flex items-top text-gray-600 mb-4"
|
|
75
|
+
>
|
|
76
|
+
<span class="flex items-center justify-center min-w-6 h-6 bg-success-100 text-success-500 rounded-full mr-3">
|
|
77
|
+
<Check class="w-5 h-5"></Check>
|
|
78
|
+
</span>
|
|
79
|
+
{{ item }}
|
|
80
|
+
</li>
|
|
81
|
+
</ul>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div v-if="activeMembership.excludes" class="flex-1">
|
|
85
|
+
<h4 class="font-bold text-gray-900 leading-6 mb-6">{{ activeMembership.excludes.title }}</h4>
|
|
86
|
+
<ul>
|
|
87
|
+
<li
|
|
88
|
+
v-for="(item, idx) in activeMembership.excludes.list"
|
|
89
|
+
:key="`excludes-${activeMembership.id}-${idx}`"
|
|
90
|
+
class="leading-6 flex items-top text-gray-600 mb-4"
|
|
91
|
+
>
|
|
92
|
+
<span class="flex items-center justify-center min-w-6 h-6 bg-gray-100 rounded-full mr-3">
|
|
93
|
+
<XIcon class="w-5 h-5"></XIcon>
|
|
94
|
+
</span>
|
|
95
|
+
{{ item }}
|
|
96
|
+
</li>
|
|
97
|
+
</ul>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<!-- CTA Button -->
|
|
103
|
+
<a
|
|
104
|
+
:href="activeMembership.url"
|
|
105
|
+
class="py-3 px-6 rounded-full font-semibold flex items-center justify-center transition-colors"
|
|
106
|
+
:class="activeMembership.theme === 'dark'
|
|
107
|
+
? 'bg-brand-800 text-white hover:bg-brand-700'
|
|
108
|
+
: 'bg-navy-600 text-white hover:bg-navy-500'"
|
|
109
|
+
>
|
|
110
|
+
{{ activeMembership.button.label }}
|
|
111
|
+
<span class="ml-2"><ArrowUpRight class="w-5 h-5"></ArrowUpRight></span>
|
|
112
|
+
</a>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</Transition>
|
|
116
|
+
</div>
|
|
117
|
+
</section>
|
|
118
|
+
</template>
|
|
119
|
+
|
|
120
|
+
<script setup>
|
|
121
|
+
import { ref, computed } from 'vue'
|
|
122
|
+
import SelectType from '@/assets/svg/select-type.svg'
|
|
123
|
+
import ArrowUpRight from '@/assets/img/icons/arrow-up-right.svg'
|
|
124
|
+
import Check from '@/assets/img/icons/check.svg'
|
|
125
|
+
import XIcon from '@/assets/img/icons/x.svg'
|
|
126
|
+
import StarIcon from '@/assets/img/icons/stars-02.svg'
|
|
127
|
+
|
|
128
|
+
const props = defineProps({
|
|
129
|
+
section: {
|
|
130
|
+
required: true,
|
|
131
|
+
type: Object,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const section = ref(props.section);
|
|
136
|
+
|
|
137
|
+
const headerComponent = computed(() => {
|
|
138
|
+
return section.value.components.find((component) => component.type === "header");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const horizontalTabComponent = computed(() => {
|
|
142
|
+
return section.value.components.find((component) => component.type === "horizontal_tabs");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const active = ref('')
|
|
146
|
+
|
|
147
|
+
const activeMembership = computed(() =>
|
|
148
|
+
horizontalTabComponent.value.data.find(m => m.id === active.value) || null
|
|
149
|
+
)
|
|
150
|
+
</script>
|
|
151
|
+
|
|
152
|
+
<style scoped>
|
|
153
|
+
.fade-enter-active,
|
|
154
|
+
.fade-leave-active {
|
|
155
|
+
transition: opacity 0.4s ease;
|
|
156
|
+
}
|
|
157
|
+
.fade-enter-from,
|
|
158
|
+
.fade-leave-to {
|
|
159
|
+
opacity: 0;
|
|
160
|
+
}
|
|
161
|
+
</style>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</h3>
|
|
8
8
|
<div class="all-unset">
|
|
9
9
|
<div v-html="component.paragraph"></div>
|
|
10
|
-
<div v-if="component?.hasOwnProperty('button')">
|
|
10
|
+
<div v-if="component?.hasOwnProperty('button') && button.show">
|
|
11
11
|
<a :href="button.url"
|
|
12
12
|
class="inline-flex items-center gap-2 !no-underline px-3 py-2.5 rounded-full shadow-xs text-md font-semibold !text-white bg-brand-600 hover:bg-brand-700 border border-brand-600 text-center cursor-pointer"
|
|
13
13
|
>{{ button.title }} <ArrowUpRight class="w-5 h-5"></ArrowUpRight></a>
|
|
@@ -2,10 +2,26 @@
|
|
|
2
2
|
<div class="rounded-[48px] 1xl:max-w-[1824px] mx-auto w-full">
|
|
3
3
|
<div v-if="section.hasOwnProperty('components') > 0 && section.components.length > 0"
|
|
4
4
|
class="md:px-[90px]"
|
|
5
|
-
:class="{'flex flex-col items-center text-center':
|
|
6
|
-
<div class="bg-navy-50 rounded-[48px] relative pt-[164px] px-[120px]" :class="{'flex flex-col items-center text-center':
|
|
7
|
-
<h3 class="text-[48px] font-semibold text-gray-900 w-full max-w-[800px] leading-[60px] tracking-[-1px]">{{
|
|
8
|
-
<h3 class="text-xl font-normal text-gray-600 mt-3 w-full max-w-[800px]" :class="{'pb-[100px]': !hasFeaturedImage}">{{
|
|
5
|
+
:class="{'flex flex-col items-center text-center': headerComponent?.center, 'mb-[64px]': hasFeaturedImage}">
|
|
6
|
+
<div class="bg-navy-50 rounded-[48px] relative pt-[164px] px-[120px]" :class="{'flex flex-col items-center text-center': headerComponent?.text_center}">
|
|
7
|
+
<h3 class="text-[48px] font-semibold text-gray-900 w-full max-w-[800px] leading-[60px] tracking-[-1px]">{{ headerComponent.title }}</h3>
|
|
8
|
+
<h3 class="text-xl font-normal text-gray-600 mt-3 w-full max-w-[800px]" :class="{'pb-[100px]': !hasFeaturedImage}">{{ headerComponent.supporting_text }}</h3>
|
|
9
|
+
<div class="flex gap-3 mt-8 flex-col lg:flex-row"
|
|
10
|
+
v-if="headerComponent?.secondary_button?.show || headerComponent?.primary_button?.show">
|
|
11
|
+
<a class="text-gray-700 text-base font-semibold border border-gray-300 px-6 py-2 rounded-full hover:border-gray-400"
|
|
12
|
+
:href="formatUrl(headerComponent.secondary_button.url)"
|
|
13
|
+
v-if="headerComponent.secondary_button.show"
|
|
14
|
+
:target="headerComponent.secondary_button.open_in_new_tab ? '_blank' : ''">
|
|
15
|
+
<span>{{ headerComponent.secondary_button.label }}</span>
|
|
16
|
+
</a>
|
|
17
|
+
<a class="hover:bg-brand-600 bg-brand-500 text-white h-[40px] rounded-full px-[14px] py-[10px] inline-flex gap-1.5 items-center shadow-xs text-base"
|
|
18
|
+
:href="formatUrl(headerComponent.primary_button.url)"
|
|
19
|
+
v-if="headerComponent.primary_button.show"
|
|
20
|
+
:target="headerComponent.primary_button.open_in_new_tab ? '_blank' : ''">
|
|
21
|
+
{{ headerComponent.primary_button.label }}
|
|
22
|
+
<ArrowDownRight class="w-5 h-5" />
|
|
23
|
+
</a>
|
|
24
|
+
</div>
|
|
9
25
|
<img
|
|
10
26
|
v-if="hasFeaturedImage"
|
|
11
27
|
:src="section.components[0]?.featured_image"
|
|
@@ -19,6 +35,8 @@
|
|
|
19
35
|
|
|
20
36
|
<script setup>
|
|
21
37
|
import {ref, computed} from "vue";
|
|
38
|
+
import {formatUrl} from "@/components/helpers/common";
|
|
39
|
+
import ArrowDownRight from "@/assets/img/icons/arrow-down-right.svg";
|
|
22
40
|
|
|
23
41
|
const props = defineProps({
|
|
24
42
|
section: {
|
|
@@ -28,6 +46,9 @@ const props = defineProps({
|
|
|
28
46
|
});
|
|
29
47
|
|
|
30
48
|
const section = ref(props.section);
|
|
49
|
+
const headerComponent = computed(() => {
|
|
50
|
+
return section.value?.components[0];
|
|
51
|
+
});
|
|
31
52
|
const hasFeaturedImage = computed(() => {
|
|
32
53
|
return section.value?.components[0]?.hasOwnProperty('featured_image');
|
|
33
54
|
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section>
|
|
3
|
+
<div class="relative overflow-hidden bg-gray-50">
|
|
4
|
+
<div
|
|
5
|
+
class="flex w-full transition-transform duration-500 ease-in-out"
|
|
6
|
+
:style="{ transform: `translateX(-${currentIndex * 100}%)` }"
|
|
7
|
+
>
|
|
8
|
+
<div
|
|
9
|
+
v-for="(feature, index) in slides.data"
|
|
10
|
+
:key="index"
|
|
11
|
+
class="w-full flex-shrink-0 py-10"
|
|
12
|
+
>
|
|
13
|
+
<div class="flex space-x-16 max-w-[1640px] md:px-[120px] mx-auto w-full">
|
|
14
|
+
<article class="flex-1 flex flex-col justify-center gap-8">
|
|
15
|
+
<span class="flex items-center gap-1">
|
|
16
|
+
<template v-for="star in 5">
|
|
17
|
+
<Star class="w-5 h-5 text-yellow-100"></Star>
|
|
18
|
+
</template>
|
|
19
|
+
</span>
|
|
20
|
+
<h3 class="font-medium text-3xl leading-9">{{ feature.title }}</h3>
|
|
21
|
+
<p class="text-gray-600" v-html="feature.description"></p>
|
|
22
|
+
</article>
|
|
23
|
+
<div class="w-[30rem]">
|
|
24
|
+
<img
|
|
25
|
+
v-if="feature.featured_image"
|
|
26
|
+
:src="feature.featured_image"
|
|
27
|
+
alt="Audience smiling"
|
|
28
|
+
class="rounded-tl-3xl rounded-br-3xl"
|
|
29
|
+
/>
|
|
30
|
+
<img
|
|
31
|
+
v-else
|
|
32
|
+
class="rounded-tl-3xl rounded-br-3xl"
|
|
33
|
+
src="@/assets/img/no_image_available.jpeg"
|
|
34
|
+
alt="No Image Available">
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<!-- Controls -->
|
|
41
|
+
<footer class="flex max-w-[1640px] md:px-[120px] mx-auto w-full gap-4 absolute bottom-10 left-20">
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
@click="prevSlide"
|
|
45
|
+
class="w-12 h-12 border border-gray-200 rounded-full flex items-center justify-center bg-gray-50"
|
|
46
|
+
>
|
|
47
|
+
<ArrowLeft class="w-6 h-6 text-gray-500"></ArrowLeft>
|
|
48
|
+
</button>
|
|
49
|
+
<button
|
|
50
|
+
type="button"
|
|
51
|
+
@click="nextSlide"
|
|
52
|
+
class="w-12 h-12 border border-gray-200 rounded-full flex items-center justify-center bg-gray-50"
|
|
53
|
+
>
|
|
54
|
+
<ArrowRight class="w-6 h-6 text-gray-500"></ArrowRight>
|
|
55
|
+
</button>
|
|
56
|
+
</footer>
|
|
57
|
+
</div>
|
|
58
|
+
</section>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<script setup>
|
|
62
|
+
import {ref, computed} from 'vue'
|
|
63
|
+
import ArrowLeft from '@/assets/img/icons/arrow-left.svg'
|
|
64
|
+
import ArrowRight from '@/assets/img/icons/arrow-right.svg'
|
|
65
|
+
import Star from '@/assets/img/icons/star.svg'
|
|
66
|
+
|
|
67
|
+
const props = defineProps({
|
|
68
|
+
section: {
|
|
69
|
+
required: true,
|
|
70
|
+
type: Object,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const section = ref(props.section);
|
|
75
|
+
const slides = computed(() => {
|
|
76
|
+
return section.value.components.find((component) => component.type === "testimonial_slider");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const currentIndex = ref(0)
|
|
80
|
+
|
|
81
|
+
function nextSlide() {
|
|
82
|
+
currentIndex.value = (currentIndex.value + 1) % slides.value?.data?.length
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function prevSlide() {
|
|
86
|
+
currentIndex.value = (currentIndex.value - 1 + slides.value?.data?.length) % slides.value?.data?.length
|
|
87
|
+
}
|
|
88
|
+
</script>
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<div
|
|
16
16
|
v-if="headerComponent"
|
|
17
17
|
class="w-full flex-col mb-6"
|
|
18
|
-
:class="{'text-center': headerComponent?.text_center}"
|
|
18
|
+
:class="{'text-center items-center flex': headerComponent?.text_center}"
|
|
19
19
|
>
|
|
20
20
|
<h3 class="text-[36px] text-gray-900 font-semibold">{{ headerComponent.title }}</h3>
|
|
21
21
|
<p v-if="headerComponent?.supporting_text"
|
|
22
|
-
class="text-[20px] font-normal mt-4 text-gray-600 leading-[30px]"
|
|
22
|
+
class="text-[20px] font-normal mt-4 text-gray-600 leading-[30px] max-w-[800px]"
|
|
23
23
|
v-html="headerComponent.supporting_text"></p>
|
|
24
24
|
</div>
|
|
25
25
|
<div :class="featureItemsComponent.hasOwnProperty('grid_columns') ? '' : 'flex flex-row gap-8'">
|
|
@@ -39,6 +39,14 @@
|
|
|
39
39
|
<div class="max-w-[324px]" :class="{'max-w-full': featureItemsComponent?.has_background}">
|
|
40
40
|
<h3 class="font-semibold text-[20px] text-gray-900">{{ item.title }}</h3>
|
|
41
41
|
<p class="mt-2 text-md font-normal text-gray-600 leading-[24px]">{{ item.supporting_text }}</p>
|
|
42
|
+
<a
|
|
43
|
+
v-if="item?.primary_button?.show && item?.primary_button?.url"
|
|
44
|
+
class="text-brand-700 inline-flex gap-1.5 items-center font-semibold text-base mt-4"
|
|
45
|
+
:href="formatUrl(item.primary_button.url)"
|
|
46
|
+
:target="item.primary_button.open_in_new_tab ? '_blank' : ''">
|
|
47
|
+
{{ item.primary_button.label }}
|
|
48
|
+
<ArrowUpRight class="w-5 h-5"></ArrowUpRight>
|
|
49
|
+
</a>
|
|
42
50
|
</div>
|
|
43
51
|
</template>
|
|
44
52
|
<img v-else :src="item.image" alt="Feature Image" class="w-full h-full object-cover"/>
|
|
@@ -57,6 +65,8 @@
|
|
|
57
65
|
<script setup>
|
|
58
66
|
import IconComponent from "@/components/common/Icon.vue";
|
|
59
67
|
import {ref, computed, onMounted} from "vue";
|
|
68
|
+
import {formatUrl} from "@/components/helpers/common";
|
|
69
|
+
import ArrowUpRight from "@/assets/img/icons/arrow-up-right.svg";
|
|
60
70
|
|
|
61
71
|
const props = defineProps({
|
|
62
72
|
section: {
|
|
@@ -79,7 +89,12 @@ const imageComponent = computed(() => {
|
|
|
79
89
|
return section.value.components.find((component) => component.type === "image_block");
|
|
80
90
|
});
|
|
81
91
|
const featureItemsComponent = computed(() => {
|
|
82
|
-
|
|
92
|
+
let c = section.value.components.find((component) => component.type === "feature_items");
|
|
93
|
+
if (!c) {
|
|
94
|
+
return section.value.components.find((component) => component.type === "link_cards")
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return c;
|
|
83
98
|
});
|
|
84
99
|
|
|
85
100
|
onMounted(() => {
|
package/tailwind.config.js
CHANGED
|
@@ -50,7 +50,9 @@ module.exports = {
|
|
|
50
50
|
},
|
|
51
51
|
success: {
|
|
52
52
|
50: 'rgba(236, 253, 243, 1)',
|
|
53
|
+
100: '#DCFAE6',
|
|
53
54
|
200: 'rgba(171, 239, 198, 1)',
|
|
55
|
+
500: '#17B26A',
|
|
54
56
|
700: 'rgba(6, 118, 71, 1)',
|
|
55
57
|
},
|
|
56
58
|
error: {
|
|
@@ -74,6 +76,9 @@ module.exports = {
|
|
|
74
76
|
500: 'rgba(247, 144, 9, 1)',
|
|
75
77
|
700: 'rgba(181, 71, 8, 1)',
|
|
76
78
|
},
|
|
79
|
+
yellow: {
|
|
80
|
+
100: '#DAAA00',
|
|
81
|
+
}
|
|
77
82
|
},
|
|
78
83
|
},
|
|
79
84
|
},
|