@dcodegroup-au/page-builder 0.5.9 → 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.
@@ -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>
@@ -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': section.components[0]?.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': section.components[0]?.text_center}">
7
- <h3 class="text-[48px] font-semibold text-gray-900 w-full max-w-[800px] leading-[60px] tracking-[-1px]">{{ section.components[0].title }}</h3>
8
- <h3 class="text-xl font-normal text-gray-600 mt-3 w-full max-w-[800px]" :class="{'pb-[100px]': !hasFeaturedImage}">{{ section.components[0].supporting_text }}</h3>
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
- return section.value.components.find((component) => component.type === "feature_items");
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(() => {
@@ -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
  },