@dcodegroup-au/page-builder 0.2.7 → 0.2.9
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 +2 -2
- package/dist/page-builder.es.js +33346 -11815
- package/dist/page-builder.umd.js +59 -59
- package/example/src/App.vue +40 -679
- package/example/src/main.js +2 -1
- package/example/src/pages/BestLife.js +351 -0
- package/example/src/pages/Home.js +677 -0
- package/package.json +1 -1
- package/src/assets/icons.json +3569 -0
- package/src/components/ItemEdit.vue +147 -71
- package/src/components/LinkCardEdit.vue +139 -0
- package/src/components/PageBuilder.vue +43 -10
- package/src/components/PageRender.vue +12 -0
- package/src/components/builders/CollectionCarousel.vue +62 -0
- package/src/components/builders/Header.vue +82 -0
- package/src/components/builders/ImageBlock.vue +56 -0
- package/src/components/builders/Items.vue +112 -0
- package/src/components/builders/Links.vue +123 -0
- package/src/components/builders/Logos.vue +122 -0
- package/src/components/builders/NewsGrid.vue +59 -0
- package/src/components/builders/Paragraph.vue +93 -0
- package/src/components/builders/VideoGrid.vue +101 -0
- package/src/components/common/Button.vue +53 -0
- package/src/components/common/Card.vue +5 -1
- package/src/components/common/FileUpload.vue +1 -1
- package/src/components/common/Icon.vue +41 -0
- package/src/components/common/IconSelector.vue +106 -0
- package/src/components/common/LinkedTo.vue +9 -3
- package/src/components/helpers/bundleIcons.js +1189 -0
- package/src/components/index.js +2 -1
- package/src/components/presenters/components/{VCarouselPresenter.vue → CarouselPresenter.vue} +8 -18
- package/src/components/presenters/components/{VCollectionGridPresenter.vue → CollectionGridPresenter.vue} +0 -5
- package/src/components/presenters/modules/CollectionCarousel.vue +2 -2
- package/src/components/presenters/modules/CollectionGrid.vue +2 -2
- package/src/components/presenters/modules/HeroHeader.vue +3 -3
- package/src/components/presenters/modules/LinkCard.vue +55 -0
- package/src/components/presenters/modules/LinkList.vue +51 -0
- package/src/components/presenters/modules/LogoCloud.vue +1 -1
- package/src/components/presenters/modules/Paragraph.vue +26 -0
- package/src/components/presenters/modules/QuickLinks.vue +2 -2
- package/src/components/presenters/modules/StandardHeader.vue +32 -0
- package/src/components/presenters/modules/Timeline.vue +55 -0
- package/src/components/presenters/modules/TwoColumnsImageContent.vue +36 -0
- package/src/components/presenters/modules/VTabs.vue +2 -2
- package/src/components/presenters/overridables/VCarouselPrimaryButton.vue +28 -0
- package/src/utils/generateIconBundle.js +33 -0
- package/src/utils/generateIconJson.js +30 -0
- package/tailwind.config.js +5 -0
- package/src/components/builders/BaseModuleForm.vue +0 -86
- package/src/components/builders/LogoBuilder.vue +0 -167
- package/src/components/builders/PageBuilderCarousel.vue +0 -18
- package/src/components/builders/PageBuilderGrid.vue +0 -18
- package/src/components/builders/PageBuilderSectionHeader.vue +0 -30
- package/src/components/builders/PageModal.vue +0 -92
- package/src/components/builders/VCollectionCarousel.vue +0 -58
- package/src/components/builders/VHeader.vue +0 -55
- package/src/components/builders/VItems.vue +0 -110
- package/src/components/builders/VLinks.vue +0 -121
- package/src/components/builders/VLogos.vue +0 -121
- package/src/components/builders/VNewsGrid.vue +0 -55
- package/src/components/builders/VVideoGrid.vue +0 -99
- package/src/components/common/forms/LogosForm.vue +0 -39
- package/src/components/common/forms/PageBuilderLinksForm.vue +0 -39
- package/src/components/common/forms/SectionHeaderForm.vue +0 -45
- package/src/components/common/forms/TabForm.vue +0 -90
- /package/src/components/common/{VModal.vue → Modal.vue} +0 -0
- /package/src/components/common/{VToggle.vue → Toggle.vue} +0 -0
- /package/src/components/presenters/components/{VHeaderPresenter.vue → HeaderPresenter.vue} +0 -0
- /package/src/components/presenters/components/{VLinkPresenter.vue → LinkPresenter.vue} +0 -0
- /package/src/components/presenters/components/{VSliderPresenter.vue → SliderPresenter.vue} +0 -0
- /package/src/components/presenters/components/{VVerticalTabPresenter.vue → VerticalTabPresenter.vue} +0 -0
package/src/components/index.js
CHANGED
|
@@ -2,5 +2,6 @@ import '@/assets/css/style.css';
|
|
|
2
2
|
import PageBuilder from './PageBuilder.vue';
|
|
3
3
|
import PageRender from './PageRender.vue';
|
|
4
4
|
import ItemEdit from './ItemEdit.vue';
|
|
5
|
+
import LinkCardEdit from './LinkCardEdit.vue';
|
|
5
6
|
|
|
6
|
-
export { PageBuilder, PageRender, ItemEdit };
|
|
7
|
+
export { PageBuilder, PageRender, ItemEdit, LinkCardEdit };
|
package/src/components/presenters/components/{VCarouselPresenter.vue → CarouselPresenter.vue}
RENAMED
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
{{ tag }}
|
|
31
31
|
</span>
|
|
32
32
|
</div>
|
|
33
|
-
<h3 class="
|
|
34
|
-
{{ slide?.title }}
|
|
33
|
+
<h3 class="my-3">
|
|
34
|
+
<a class="text-[24px] font-semibold text-gray-900 leading-[32px] hover:underline" :href="slide.url" target="_blank">{{ slide?.title }}</a>
|
|
35
35
|
</h3>
|
|
36
36
|
<p
|
|
37
37
|
class="text-base font-normal text-gray-600 leading-[24px] multiline-ellipsis"
|
|
@@ -47,19 +47,7 @@
|
|
|
47
47
|
</div>
|
|
48
48
|
</div>
|
|
49
49
|
<div class="border-t border-gray-200 mt-4 pt-[17px] flex justify-between items-center">
|
|
50
|
-
<
|
|
51
|
-
v-if="slide.primary_button?.url"
|
|
52
|
-
:href="formatUrl(slide.primary_button.url)"
|
|
53
|
-
target="_blank"
|
|
54
|
-
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-sm"
|
|
55
|
-
>
|
|
56
|
-
<Plus v-if="slide.primary_button?.icon === 'plus'" class="w-4 h-4" />
|
|
57
|
-
<ShoppingCart
|
|
58
|
-
v-if="slide.primary_button?.icon === 'shopping-cart-01'"
|
|
59
|
-
class="w-4 h-4"
|
|
60
|
-
/>
|
|
61
|
-
{{ slide.primary_button.title }}
|
|
62
|
-
</a>
|
|
50
|
+
<VCarouselPrimaryButton :button="slide.primary_button" />
|
|
63
51
|
<a
|
|
64
52
|
v-if="slide.secondary_button"
|
|
65
53
|
target="_blank"
|
|
@@ -101,14 +89,16 @@
|
|
|
101
89
|
</template>
|
|
102
90
|
|
|
103
91
|
<script setup>
|
|
104
|
-
import { ref } from "vue";
|
|
92
|
+
import { ref, inject } from "vue";
|
|
105
93
|
import Clock from "@/assets/img/icons/clock.svg";
|
|
106
|
-
import Plus from "@/assets/img/icons/plus.svg";
|
|
107
|
-
import ShoppingCart from "@/assets/img/icons/shopping-cart-01.svg";
|
|
108
94
|
import ChevronRight from "@/assets/img/icons/chevron-right.svg";
|
|
109
95
|
import ChevronLeft from "@/assets/img/icons/chevron-left.svg";
|
|
110
96
|
import ArrowUpRight from "@/assets/img/icons/arrow-up-right.svg";
|
|
111
97
|
import Ticket from "@/assets/img/icons/ticket-02.svg";
|
|
98
|
+
import DefaultPrimaryButton from "@/components/presenters/overridables/VCarouselPrimaryButton.vue";
|
|
99
|
+
|
|
100
|
+
// Inject the FileUpload component or fallback to the default one
|
|
101
|
+
const VCarouselPrimaryButton = inject("VCarouselPrimaryButton", DefaultPrimaryButton);
|
|
112
102
|
|
|
113
103
|
const props = defineProps({
|
|
114
104
|
component: {
|
|
@@ -26,11 +26,6 @@
|
|
|
26
26
|
alt="Card Image"
|
|
27
27
|
class="w-full h-[281px] object-cover rounded-[16px] mb-4"
|
|
28
28
|
/>
|
|
29
|
-
<img
|
|
30
|
-
v-else
|
|
31
|
-
alt="Card Image"
|
|
32
|
-
class="w-full h-[281px] object-cover rounded-[16px] mb-4"
|
|
33
|
-
>
|
|
34
29
|
<img v-else class="w-full h-[281px] object-cover rounded-[16px] mb-4" src="@/assets/img/no_image_available.jpeg">
|
|
35
30
|
<div class="flex flex-col gap-2 items-start text-left w-full">
|
|
36
31
|
<div v-if="card.categories && card.categories.length" class="flex gap-2">
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
<script setup>
|
|
15
15
|
import { ref, computed } from "vue";
|
|
16
|
-
import VHeaderPresenter from "@/components/presenters/components/
|
|
17
|
-
import VCarousel from "@/components/presenters/components/
|
|
16
|
+
import VHeaderPresenter from "@/components/presenters/components/HeaderPresenter.vue";
|
|
17
|
+
import VCarousel from "@/components/presenters/components/CarouselPresenter.vue";
|
|
18
18
|
|
|
19
19
|
const props = defineProps({
|
|
20
20
|
section: {
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
<script setup>
|
|
15
15
|
import { ref, markRaw } from "vue";
|
|
16
|
-
import VHeaderPresenter from "@/components/presenters/components/
|
|
17
|
-
import VCollectionGridPresenter from "@/components/presenters/components/
|
|
16
|
+
import VHeaderPresenter from "@/components/presenters/components/HeaderPresenter.vue";
|
|
17
|
+
import VCollectionGridPresenter from "@/components/presenters/components/CollectionGridPresenter.vue";
|
|
18
18
|
|
|
19
19
|
const props = defineProps({
|
|
20
20
|
section: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="rounded-[48px]
|
|
2
|
+
<div class="rounded-[48px] 1xl:max-w-[1824px] mx-auto w-full">
|
|
3
3
|
<div v-for="(component, index) in section.components" class="md:px-[90px]">
|
|
4
4
|
<component
|
|
5
5
|
:is="currentComponent(component)"
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
<script setup>
|
|
14
14
|
import { ref, markRaw } from "vue";
|
|
15
|
-
import VSliderPresenter from "@/components/presenters/components/
|
|
16
|
-
import VLinkPresenter from "@/components/presenters/components/
|
|
15
|
+
import VSliderPresenter from "@/components/presenters/components/SliderPresenter.vue";
|
|
16
|
+
import VLinkPresenter from "@/components/presenters/components/LinkPresenter.vue";
|
|
17
17
|
|
|
18
18
|
const props = defineProps({
|
|
19
19
|
section: {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="overflow-hidden bg-aqua-100">
|
|
3
|
+
<div class="max-w-[1400px] mx-auto w-full my-[40px]">
|
|
4
|
+
<div class="rounded-xl px-[40px] text-center mb-6 max-w-[1280px] mx-auto" v-if="headerComponent">
|
|
5
|
+
<h3 class="text-[36px] text-gray-900 font-semibold">{{ headerComponent.title }}</h3>
|
|
6
|
+
<p v-if="headerComponent?.supporting_text" class="text-[20px] font-normal mt-2 text-gray-600 leading-[30px] max-w-[768px] mx-auto" v-html="headerComponent.supporting_text"></p>
|
|
7
|
+
</div>
|
|
8
|
+
<div v-if="cardComponent" class="flex w-full" :class="{'gap-8': headerComponent?.featured_image}">
|
|
9
|
+
<img v-if="headerComponent?.featured_image"
|
|
10
|
+
:src="headerComponent?.featured_image"
|
|
11
|
+
class="w-1/2 h-[492px] rounded-br-[24px] rounded-tl-[24px]"
|
|
12
|
+
alt="Feature"/>
|
|
13
|
+
|
|
14
|
+
<div class="flex gap-8 w-full" :class="{'!w-1/2 flex-col': headerComponent?.featured_image}">
|
|
15
|
+
<div v-for="(data, index) in cardComponent.data" class="relative bg-white p-8 rounded-[24px] w-full">
|
|
16
|
+
<div v-if="data.icon" class="w-[48px] h-[48px] flex justify-center items-center rounded-[10px] text-white bg-aqua-900 mb-4">
|
|
17
|
+
<IconComponent :icon="data.icon" icon-classes="w-5 h-5" :key="index"></IconComponent>
|
|
18
|
+
</div>
|
|
19
|
+
<h1 class="text-[20px] font-semibold text-gray-900">{{ data.title }}</h1>
|
|
20
|
+
<p class="text-lg text-gray-600 mt-2 mb-4 leading-[24px]">{{ data.description }}</p>
|
|
21
|
+
<a
|
|
22
|
+
v-if="data?.primary_button.url"
|
|
23
|
+
class="text-brand-700 inline-flex gap-1.5 items-center font-semibold text-base"
|
|
24
|
+
:href="data.primary_button.url"
|
|
25
|
+
:target="data.primary_button.is_new_tab ? '_blank' : ''">
|
|
26
|
+
{{ data.primary_button.label }}
|
|
27
|
+
<ArrowUpRight class="w-5 h-5"></ArrowUpRight>
|
|
28
|
+
</a>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
<script setup>
|
|
36
|
+
import {ref, computed} from "vue";
|
|
37
|
+
import ArrowUpRight from "@/assets/img/icons/arrow-up-right.svg";
|
|
38
|
+
import IconComponent from "@/components/common/Icon.vue";
|
|
39
|
+
|
|
40
|
+
const props = defineProps({
|
|
41
|
+
section: {
|
|
42
|
+
required: true,
|
|
43
|
+
type: Object,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const section = ref(props.section);
|
|
48
|
+
const headerComponent = computed(() => {
|
|
49
|
+
return section.value.components.find((component) => component.type === "header");
|
|
50
|
+
});
|
|
51
|
+
const cardComponent = computed(() => {
|
|
52
|
+
return section.value.components.find((component) => component.type === "link_cards");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
</script>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="overflow-hidden">
|
|
3
|
+
<div class="max-w-[1400px] mx-auto w-full bg-white py-[40px] flex">
|
|
4
|
+
<div v-for="(header, index) in headerComponents" v-if="section.two_columns" class="w-1/2 gap-4 px-[120px]">
|
|
5
|
+
<div class="rounded-xl px-[40px] text-center mb-6 max-w-[1280px] mx-auto" v-if="header">
|
|
6
|
+
<h3 class="text-[36px] text-gray-900 font-semibold">{{ header.title }}</h3>
|
|
7
|
+
<p v-if="header?.supporting_text" class="text-[20px] font-normal mt-2 text-gray-600 leading-[30px] max-w-[768px] mx-auto" v-html="header.supporting_text"></p>
|
|
8
|
+
</div>
|
|
9
|
+
<div v-if="linkComponents[index]" class="flex w-full">
|
|
10
|
+
<div class="flex flex-col gap-4 w-full">
|
|
11
|
+
<div v-for="(link, index) in linkComponents[index].data" class="relative bg-white hover:bg-gray-100 p-2 rounded-lg w-full">
|
|
12
|
+
<a
|
|
13
|
+
v-if="link.url"
|
|
14
|
+
class="text-gray-900 w-full inline-flex justify-between gap-1.5 items-center leading-[28px] font-semibold text-lg hover:underline"
|
|
15
|
+
:href="link.url"
|
|
16
|
+
:target="link.open_in_new_tab ? '_blank' : ''">
|
|
17
|
+
<div class="flex gap-4 items-center max-w-[94%] w-full">
|
|
18
|
+
<LinkExternal class="w-5 h-5"></LinkExternal>
|
|
19
|
+
<span class="w-full">{{ link.title }}</span>
|
|
20
|
+
</div>
|
|
21
|
+
<ArrowUpRight class="w-5 h-5"></ArrowUpRight>
|
|
22
|
+
</a>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
<script setup>
|
|
31
|
+
import {ref, computed} from "vue";
|
|
32
|
+
import ArrowUpRight from "@/assets/img/icons/arrow-up-right.svg";
|
|
33
|
+
import LinkExternal from "@/assets/img/icons/link-external-01.svg";
|
|
34
|
+
|
|
35
|
+
const props = defineProps({
|
|
36
|
+
section: {
|
|
37
|
+
required: true,
|
|
38
|
+
type: Object,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const section = ref(props.section);
|
|
43
|
+
const headerComponents = computed(() => {
|
|
44
|
+
return section.value.components.filter((component) => component.type === "header");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const linkComponents = computed(() => {
|
|
48
|
+
return section.value.components.filter((component) => component.type === "links");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="w-full relative"
|
|
2
|
+
<div class="w-full relative">
|
|
3
3
|
<div class="1xl:max-w-[1824px] mx-auto relative flex justify-center items-center"
|
|
4
4
|
:class="{'py-8': isHorizontal, 'flex-col py-6': !isHorizontal}">
|
|
5
5
|
<div v-for="(component, index) in section.components">
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="overflow-hidden">
|
|
3
|
+
<div class="max-w-[1400px] mx-auto w-full pt-4 mb-4">
|
|
4
|
+
<div class="max-w-[800px]" v-if="section.components[0]?.title">
|
|
5
|
+
<h3 class="text-[36px] text-gray-900 font-semibold">
|
|
6
|
+
{{ section.components[0].title }}
|
|
7
|
+
</h3>
|
|
8
|
+
<p class="text-xl font-normal leading-[30px] mt-4 text-gray-600" v-html="section.components[0].paragraph"></p>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
import {ref} from "vue";
|
|
16
|
+
|
|
17
|
+
const props = defineProps({
|
|
18
|
+
section: {
|
|
19
|
+
required: true,
|
|
20
|
+
type: Object,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const section = ref(props.section);
|
|
25
|
+
|
|
26
|
+
</script>
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
|
|
19
19
|
<script setup>
|
|
20
20
|
import { ref, markRaw } from "vue";
|
|
21
|
-
import VLinkPresenter from "@/components/presenters/components/
|
|
22
|
-
import VHeaderPresenter from "@/components/presenters/components/
|
|
21
|
+
import VLinkPresenter from "@/components/presenters/components/LinkPresenter.vue";
|
|
22
|
+
import VHeaderPresenter from "@/components/presenters/components/HeaderPresenter.vue";
|
|
23
23
|
import HeaderVector from "@/assets/svg/header_right_vector.svg";
|
|
24
24
|
|
|
25
25
|
const props = defineProps({
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="rounded-[48px] 1xl:max-w-[1824px] mx-auto w-full">
|
|
3
|
+
<div v-if="section.hasOwnProperty('components') > 0 && section.components.length > 0"
|
|
4
|
+
class="md:px-[90px] bg-navy-50 rounded-[48px] relative mb-[64px] pt-[164px]"
|
|
5
|
+
:class="{'flex flex-col items-center text-center': section.components[0]?.center}">
|
|
6
|
+
<h3 class="text-[48px] font-semibold text-gray-900 w-1/2">{{ section.components[0].title }}</h3>
|
|
7
|
+
<h3 class="text-xl font-normal text-gray-600 mt-3 w-1/2">{{ section.components[0].supporting_text }}</h3>
|
|
8
|
+
<img
|
|
9
|
+
v-if="section?.components[0]?.featured_image"
|
|
10
|
+
:src="section.components[0]?.featured_image"
|
|
11
|
+
alt="Card Image"
|
|
12
|
+
class="w-full max-w-[1632px] h-[480px] object-cover rounded-[48px] relative top-[64px]"
|
|
13
|
+
/>
|
|
14
|
+
<img v-else class="w-full max-w-[1632px] h-[480px] object-cover rounded-[48px] relative top-[64px]"
|
|
15
|
+
src="@/assets/img/no_image_available.jpeg">
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup>
|
|
21
|
+
import {ref} from "vue";
|
|
22
|
+
|
|
23
|
+
const props = defineProps({
|
|
24
|
+
section: {
|
|
25
|
+
required: true,
|
|
26
|
+
type: Object,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const section = ref(props.section);
|
|
31
|
+
|
|
32
|
+
</script>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="overflow-hidden">
|
|
3
|
+
<div class="max-w-[1400px] mx-auto w-full mt-[40px]">
|
|
4
|
+
<div class="rounded-xl px-[40px] text-center mb-1 max-w-[1280px] mx-auto" v-if="headerComponent">
|
|
5
|
+
<h3 class="text-[36px] text-gray-900 font-semibold">{{ headerComponent.title }}</h3>
|
|
6
|
+
<p v-if="headerComponent?.supporting_text" class="text-[20px] font-normal mt-2 text-gray-600 leading-[30px] max-w-[768px] mx-auto" v-html="headerComponent.supporting_text"></p>
|
|
7
|
+
</div>
|
|
8
|
+
<div v-if="timelineComponent">
|
|
9
|
+
<img :src="timelineComponent.featured_image" :alt="timelineComponent.caption" class="w-full h-auto" />
|
|
10
|
+
<p v-html="timelineComponent.caption" class="mt-2 text-[13px]"></p>
|
|
11
|
+
<div class="mt-4">
|
|
12
|
+
<div v-for="(data, index) in timelineComponent.data" class="flex flex-row">
|
|
13
|
+
<div class="w-1/5 mr-[40px] relative">
|
|
14
|
+
<h1 class=" text-[24px] font-semibold text-navy-800">{{ data.title }}</h1>
|
|
15
|
+
<div class="w-[32px] h-[32px] flex items-center justify-center border-2 border-navy-100 rounded-full absolute right-[-17px] bg-white top-0">
|
|
16
|
+
<p class="w-[16px] h-[16px] rounded-full bg-navy-600"></p>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="h-full absolute right-[-2px]" style="background: repeating-linear-gradient(to bottom, transparent, transparent 10px, #A9B8C6 8px, #A9B8C6 20px); width: 2px;"></div>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="w-4/5">
|
|
21
|
+
<p v-if="data.group_title" class="text-[24px] mb-6 font-semibold text-navy-800">{{ data.group_title }}</p>
|
|
22
|
+
<div
|
|
23
|
+
v-for="(line, index) in data.lines"
|
|
24
|
+
:key="index"
|
|
25
|
+
class="bg-pale-orange-100 p-6 mb-6 rounded-[16px]"
|
|
26
|
+
>
|
|
27
|
+
<h4 class="text-xl font-semibold text-gray-900">{{ line.title }}</h4>
|
|
28
|
+
<p class="text-xl text-gray-600 mt-3 leading-[30px]">{{ line.description }}</p>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
<script setup>
|
|
38
|
+
import {ref, computed} from "vue";
|
|
39
|
+
|
|
40
|
+
const props = defineProps({
|
|
41
|
+
section: {
|
|
42
|
+
required: true,
|
|
43
|
+
type: Object,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const section = ref(props.section);
|
|
48
|
+
const headerComponent = computed(() => {
|
|
49
|
+
return section.value.components.find((component) => component.type === "header");
|
|
50
|
+
});
|
|
51
|
+
const timelineComponent = computed(() => {
|
|
52
|
+
return section.value.components.find((component) => component.type === "timeline_items");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
</script>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="overflow-hidden">
|
|
3
|
+
<div class="max-w-[1400px] mx-auto w-full mt-4">
|
|
4
|
+
<div class="grid grid-cols-12 gap-4">
|
|
5
|
+
<div class="col-span-4 bg-gray-100 rounded-xl p-8" v-if="paragraphComponent">
|
|
6
|
+
<h3 class="text-[20px] text-gray-900 font-semibold">{{ paragraphComponent.title }}</h3>
|
|
7
|
+
<p class="text-md font-normal mt-2 text-gray-600 leading-6" v-html="paragraphComponent.paragraph"></p>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="col-span-8" v-if="imageComponent">
|
|
10
|
+
<img :src="imageComponent.featured_image" :alt="imageComponent.caption" class="w-full h-auto" />
|
|
11
|
+
<p v-html="imageComponent.caption" class="mt-2 text-[13px]"></p>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup>
|
|
19
|
+
import {ref, computed} from "vue";
|
|
20
|
+
|
|
21
|
+
const props = defineProps({
|
|
22
|
+
section: {
|
|
23
|
+
required: true,
|
|
24
|
+
type: Object,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const section = ref(props.section);
|
|
29
|
+
const paragraphComponent = computed(() => {
|
|
30
|
+
return section.value.components.find((component) => component.type === "paragraph");
|
|
31
|
+
});
|
|
32
|
+
const imageComponent = computed(() => {
|
|
33
|
+
return section.value.components.find((component) => component.type === "image_block");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
</script>
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
<script setup>
|
|
16
16
|
import { ref, markRaw } from "vue";
|
|
17
|
-
import VHeaderPresenter from "@/components/presenters/components/
|
|
18
|
-
import VVerticalTabPresenter from "@/components/presenters/components/
|
|
17
|
+
import VHeaderPresenter from "@/components/presenters/components/HeaderPresenter.vue";
|
|
18
|
+
import VVerticalTabPresenter from "@/components/presenters/components/VerticalTabPresenter.vue";
|
|
19
19
|
|
|
20
20
|
const props = defineProps({
|
|
21
21
|
section: {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a
|
|
3
|
+
v-if="button?.url"
|
|
4
|
+
:href="formatUrl(button.url)"
|
|
5
|
+
target="_blank"
|
|
6
|
+
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-sm"
|
|
7
|
+
>
|
|
8
|
+
<Plus v-if="button?.icon === 'plus'" class="w-4 h-4" />
|
|
9
|
+
<ShoppingCart v-if="button?.icon === 'shopping-cart-01'" class="w-4 h-4" />
|
|
10
|
+
{{ button.title }}
|
|
11
|
+
</a>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
import Plus from "@/assets/img/icons/plus.svg";
|
|
16
|
+
import ShoppingCart from "@/assets/img/icons/shopping-cart-01.svg";
|
|
17
|
+
|
|
18
|
+
const props = defineProps({
|
|
19
|
+
button: {
|
|
20
|
+
type: Object,
|
|
21
|
+
required: true,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const formatUrl = (url) => {
|
|
26
|
+
return url.startsWith("http") ? url : `//${url}`;
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const iconsDir = path.resolve(__dirname, '../assets/img/icons');
|
|
5
|
+
const iconFolder = path.resolve(__dirname, '../components/helpers');
|
|
6
|
+
const outputFile = path.resolve(iconFolder, 'bundleIcons.js');
|
|
7
|
+
|
|
8
|
+
const generateIconsBundle = () => {
|
|
9
|
+
try {
|
|
10
|
+
const files = fs.readdirSync(iconsDir);
|
|
11
|
+
const components = files
|
|
12
|
+
.filter((file) => file.endsWith('.svg')) // Only include .svg files
|
|
13
|
+
.map((file) => {
|
|
14
|
+
const name = path.basename(file, '.svg').toLowerCase()
|
|
15
|
+
.split(/[^a-zA-Z0-9]+/) // Split by non-alphanumeric characters
|
|
16
|
+
.map((word, index) =>
|
|
17
|
+
index === 0
|
|
18
|
+
? word.charAt(0).toUpperCase() + word.slice(1) // Uppercase first word
|
|
19
|
+
: word.charAt(0).toUpperCase() + word.slice(1) // Uppercase subsequent words
|
|
20
|
+
)
|
|
21
|
+
.join('');
|
|
22
|
+
return `export { default as ${name} } from '@/assets/img/icons/${file}?component';`;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const bundleContent = components.join('\n');
|
|
26
|
+
fs.writeFileSync(outputFile, bundleContent);
|
|
27
|
+
console.log(`Icons bundle generated successfully at ${outputFile}`);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error('Error generating icons bundle:', error);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
generateIconsBundle();
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const iconsDir = path.resolve(__dirname, '../assets/img/icons');
|
|
5
|
+
const outputFile = path.resolve(__dirname, '../assets/icons.json');
|
|
6
|
+
|
|
7
|
+
const generateIconsJson = () => {
|
|
8
|
+
try {
|
|
9
|
+
const files = fs.readdirSync(iconsDir);
|
|
10
|
+
const icons = files
|
|
11
|
+
.filter((file) => file.endsWith('.svg')) // Only include .svg files
|
|
12
|
+
.map((file) => ({
|
|
13
|
+
name: path.basename(file, '.svg').toLowerCase()
|
|
14
|
+
.split(/[^a-zA-Z0-9]+/) // Split by non-alphanumeric characters
|
|
15
|
+
.map((word, index) =>
|
|
16
|
+
index === 0
|
|
17
|
+
? word.charAt(0).toUpperCase() + word.slice(1) // Uppercase first word
|
|
18
|
+
: word.charAt(0).toUpperCase() + word.slice(1) // Uppercase subsequent words
|
|
19
|
+
)
|
|
20
|
+
.join(''), // Extract the name without extension
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
fs.writeFileSync(outputFile, JSON.stringify(icons, null, 2));
|
|
24
|
+
console.log(`Icons JSON generated successfully at ${outputFile}`);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error('Error generating icons JSON:', error);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
generateIconsJson();
|
package/tailwind.config.js
CHANGED
|
@@ -23,6 +23,7 @@ module.exports = {
|
|
|
23
23
|
600: '#3E5F7E',
|
|
24
24
|
400: '#69829B',
|
|
25
25
|
200: '#94A6B8',
|
|
26
|
+
100: '#A9B8C6',
|
|
26
27
|
50: '#DFE5EC',
|
|
27
28
|
25: '#EFF2F5',
|
|
28
29
|
},
|
|
@@ -42,6 +43,10 @@ module.exports = {
|
|
|
42
43
|
},
|
|
43
44
|
aqua: {
|
|
44
45
|
100: '#EEF2F2',
|
|
46
|
+
900: '#0FAC9A',
|
|
47
|
+
},
|
|
48
|
+
'pale-orange': {
|
|
49
|
+
100: '#FBF5F4',
|
|
45
50
|
},
|
|
46
51
|
success: {
|
|
47
52
|
50: 'rgba(236, 253, 243, 1)',
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="pb-8">
|
|
3
|
-
<component :is="props.form" @update="update" :data="props.data" :errors="errors" :sites="sites"></component>
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
<script setup>
|
|
7
|
-
const props = defineProps({
|
|
8
|
-
form: {
|
|
9
|
-
type: String,
|
|
10
|
-
required: true,
|
|
11
|
-
},
|
|
12
|
-
subType: {
|
|
13
|
-
type: String,
|
|
14
|
-
required: false,
|
|
15
|
-
},
|
|
16
|
-
page: {
|
|
17
|
-
type: Object,
|
|
18
|
-
required: true,
|
|
19
|
-
},
|
|
20
|
-
attribute: {
|
|
21
|
-
type: Object,
|
|
22
|
-
required: true,
|
|
23
|
-
},
|
|
24
|
-
moduleIndex: {
|
|
25
|
-
required: true,
|
|
26
|
-
},
|
|
27
|
-
itemIndex: {
|
|
28
|
-
required: false,
|
|
29
|
-
},
|
|
30
|
-
data: {
|
|
31
|
-
type: Object,
|
|
32
|
-
required: true,
|
|
33
|
-
},
|
|
34
|
-
backUrl: {
|
|
35
|
-
type: String,
|
|
36
|
-
required: true,
|
|
37
|
-
},
|
|
38
|
-
sites: {
|
|
39
|
-
type: Object,
|
|
40
|
-
required: true,
|
|
41
|
-
},
|
|
42
|
-
redirectAfterResponse: {
|
|
43
|
-
type: Boolean,
|
|
44
|
-
default: true,
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const errors = ref({});
|
|
49
|
-
const content = ref(props.page.attributes);
|
|
50
|
-
const route = inject("route");
|
|
51
|
-
const contentUnchanged = ref(true);
|
|
52
|
-
|
|
53
|
-
const update = (data) => {
|
|
54
|
-
const attributeIndex = content.value.findIndex((item) => item.id === props.attribute.id);
|
|
55
|
-
if (props.itemIndex) {
|
|
56
|
-
content.value[attributeIndex]["value"]["submodules"][props.moduleIndex]["items"][props.itemIndex] = data;
|
|
57
|
-
} else {
|
|
58
|
-
content.value[attributeIndex]["value"]["submodules"][props.moduleIndex] = data;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
axios
|
|
62
|
-
.post(route("api.admin.pages.update-content", { page: props.page.id }), {
|
|
63
|
-
attributes: content.value,
|
|
64
|
-
changes: data,
|
|
65
|
-
form: props.form,
|
|
66
|
-
subType: props.subType,
|
|
67
|
-
})
|
|
68
|
-
.then((response) => {
|
|
69
|
-
contentUnchanged.value = true;
|
|
70
|
-
if (props.redirectAfterResponse) {
|
|
71
|
-
window.location.href = props.backUrl;
|
|
72
|
-
} else {
|
|
73
|
-
alert("Success");
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
.catch(({ response }) => {
|
|
77
|
-
errors.value = response.data.errors;
|
|
78
|
-
});
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
watch(
|
|
82
|
-
() => content.value,
|
|
83
|
-
() => (contentUnchanged.value = false),
|
|
84
|
-
{ deep: true },
|
|
85
|
-
);
|
|
86
|
-
</script>
|