@dcodegroup-au/page-builder 0.2.8 → 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.
Files changed (69) hide show
  1. package/dist/page-builder.css +2 -2
  2. package/dist/page-builder.es.js +33372 -11858
  3. package/dist/page-builder.umd.js +59 -59
  4. package/example/src/App.vue +40 -679
  5. package/example/src/main.js +2 -1
  6. package/example/src/pages/BestLife.js +351 -0
  7. package/example/src/pages/Home.js +677 -0
  8. package/package.json +1 -1
  9. package/src/assets/icons.json +3569 -0
  10. package/src/components/ItemEdit.vue +147 -71
  11. package/src/components/LinkCardEdit.vue +139 -0
  12. package/src/components/PageBuilder.vue +43 -10
  13. package/src/components/PageRender.vue +12 -0
  14. package/src/components/builders/CollectionCarousel.vue +62 -0
  15. package/src/components/builders/Header.vue +82 -0
  16. package/src/components/builders/ImageBlock.vue +56 -0
  17. package/src/components/builders/Items.vue +112 -0
  18. package/src/components/builders/Links.vue +123 -0
  19. package/src/components/builders/Logos.vue +122 -0
  20. package/src/components/builders/NewsGrid.vue +59 -0
  21. package/src/components/builders/Paragraph.vue +93 -0
  22. package/src/components/builders/VideoGrid.vue +101 -0
  23. package/src/components/common/Button.vue +53 -0
  24. package/src/components/common/Card.vue +5 -1
  25. package/src/components/common/FileUpload.vue +1 -1
  26. package/src/components/common/Icon.vue +41 -0
  27. package/src/components/common/IconSelector.vue +106 -0
  28. package/src/components/common/LinkedTo.vue +9 -3
  29. package/src/components/helpers/bundleIcons.js +1189 -0
  30. package/src/components/index.js +2 -1
  31. package/src/components/presenters/components/{VCollectionGridPresenter.vue → CollectionGridPresenter.vue} +0 -5
  32. package/src/components/presenters/modules/CollectionCarousel.vue +2 -2
  33. package/src/components/presenters/modules/CollectionGrid.vue +2 -2
  34. package/src/components/presenters/modules/HeroHeader.vue +2 -2
  35. package/src/components/presenters/modules/LinkCard.vue +55 -0
  36. package/src/components/presenters/modules/LinkList.vue +51 -0
  37. package/src/components/presenters/modules/Paragraph.vue +26 -0
  38. package/src/components/presenters/modules/QuickLinks.vue +2 -2
  39. package/src/components/presenters/modules/StandardHeader.vue +32 -0
  40. package/src/components/presenters/modules/Timeline.vue +55 -0
  41. package/src/components/presenters/modules/TwoColumnsImageContent.vue +36 -0
  42. package/src/components/presenters/modules/VTabs.vue +2 -2
  43. package/src/utils/generateIconBundle.js +33 -0
  44. package/src/utils/generateIconJson.js +30 -0
  45. package/tailwind.config.js +5 -0
  46. package/src/components/builders/BaseModuleForm.vue +0 -86
  47. package/src/components/builders/LogoBuilder.vue +0 -167
  48. package/src/components/builders/PageBuilderCarousel.vue +0 -18
  49. package/src/components/builders/PageBuilderGrid.vue +0 -18
  50. package/src/components/builders/PageBuilderSectionHeader.vue +0 -30
  51. package/src/components/builders/PageModal.vue +0 -92
  52. package/src/components/builders/VCollectionCarousel.vue +0 -58
  53. package/src/components/builders/VHeader.vue +0 -55
  54. package/src/components/builders/VItems.vue +0 -110
  55. package/src/components/builders/VLinks.vue +0 -121
  56. package/src/components/builders/VLogos.vue +0 -120
  57. package/src/components/builders/VNewsGrid.vue +0 -55
  58. package/src/components/builders/VVideoGrid.vue +0 -99
  59. package/src/components/common/forms/LogosForm.vue +0 -39
  60. package/src/components/common/forms/PageBuilderLinksForm.vue +0 -39
  61. package/src/components/common/forms/SectionHeaderForm.vue +0 -45
  62. package/src/components/common/forms/TabForm.vue +0 -90
  63. /package/src/components/common/{VModal.vue → Modal.vue} +0 -0
  64. /package/src/components/common/{VToggle.vue → Toggle.vue} +0 -0
  65. /package/src/components/presenters/components/{VCarouselPresenter.vue → CarouselPresenter.vue} +0 -0
  66. /package/src/components/presenters/components/{VHeaderPresenter.vue → HeaderPresenter.vue} +0 -0
  67. /package/src/components/presenters/components/{VLinkPresenter.vue → LinkPresenter.vue} +0 -0
  68. /package/src/components/presenters/components/{VSliderPresenter.vue → SliderPresenter.vue} +0 -0
  69. /package/src/components/presenters/components/{VVerticalTabPresenter.vue → VerticalTabPresenter.vue} +0 -0
@@ -1,19 +1,76 @@
1
1
  <template>
2
2
  <div class="item-edit">
3
3
  <div class="flex items-start gap-4 px-6 pt-4 h-full min-h-[90vh]">
4
- <div class="flex flex-1 flex-col gap-4">
5
- <card title="Description">
4
+ <div class="flex flex-1 flex-col gap-4 mb-4">
5
+ <div v-if="hasLines">
6
+ <div class="flex justify-between mb-4">
7
+ <div class="flex flex-col gap-1">
8
+ <p class="text-base font-semibold text-gray-900">Events</p>
9
+ <p class="text-sm">
10
+ This timeline item can contain up to {{ item?.max_items }} events.
11
+ </p>
12
+ </div>
13
+ <button
14
+ :disabled="advancedForm.lines.length >= item?.max_items"
15
+ @click="addLine"
16
+ class="text-sm cursor-pointer flex items-center justify-center gap-1 rounded-[99px] border border-brand-600 bg-brand-500 px-3.5 h-[40px] font-semibold text-white hover:bg-brand-600"
17
+ :class="{ 'border-gray-100 bg-gray-100 !text-gray-400 hover:bg-gray-100': advancedForm.lines.length >= item?.max_items }"
18
+ >
19
+ <PlusIcon class="h-5 w-5"></PlusIcon>
20
+ <span>Event</span>
21
+ </button>
22
+ </div>
23
+ <div class="flex flex-col gap-4">
24
+ <div
25
+ v-for="(line, index) in advancedForm.lines"
26
+ :key="index"
27
+ class="flex flex-col gap-2 rounded-lg px-6 pt-4 pb-[40px] bg-gray-50"
28
+ >
29
+ <div class="flex justify-between items-center border-b border-gray-200 pb-3 mb-4">
30
+ <p class="text-lg font-semibold text-gray-900"> Event #{{ index + 1 }}</p>
31
+ <ActionMenu @removeItem="handleDeleteItem(index)"/>
32
+ </div>
33
+ <input-wrapper
34
+ is-vertical
35
+ field="line.title"
36
+ label-text="Heading *"
37
+ class="w-full"
38
+ :value="line.title"
39
+ >
40
+ <input
41
+ v-model="line.title"
42
+ name="line.title"
43
+ type="text"
44
+ placeholder="Heading"
45
+ class="border-1 border-solid border-gray-300 rounded-lg bg-white w-full"
46
+ />
47
+ </input-wrapper>
48
+ <input-wrapper
49
+ is-vertical
50
+ field="line.description"
51
+ label-text="Description *"
52
+ class="w-full"
53
+ :value="descriptionWordCount(line.description)"
54
+ :show-count="true"
55
+ >
56
+ <QuillEditor v-model="line.description"/>
57
+ </input-wrapper>
58
+ </div>
59
+ </div>
60
+ </div>
61
+
62
+ <card title="Description" v-else>
6
63
  <div class="flex flex-col gap-8">
7
64
  <input-wrapper
8
65
  is-vertical
9
66
  field="title"
10
67
  label-text="Title *"
11
68
  class="w-full"
12
- :value="form.title"
69
+ :value="basicForm.title"
13
70
  :limit="51"
14
71
  >
15
72
  <input
16
- v-model="form.title"
73
+ v-model="basicForm.title"
17
74
  name="title"
18
75
  type="text"
19
76
  placeholder="Title"
@@ -26,83 +83,69 @@
26
83
  field="description"
27
84
  label-text="Description *"
28
85
  class="w-full mb-4"
29
- :value="descriptionWordCount"
86
+ :value="descriptionWordCount(basicForm.description)"
30
87
  :show-count="true"
31
88
  >
32
- <QuillEditor v-model="form.description"/>
89
+ <QuillEditor v-model="basicForm.description"/>
33
90
  </input-wrapper>
34
91
  </div>
35
92
  </card>
36
- <card v-if="form.hasOwnProperty('primary_button')" :title="form?.primary_button?.name ?? 'Primary button'">
37
- <div class="flex flex-col gap-8">
38
- <VToggle name="show" v-model="form.primary_button.show" title="Show Button" />
93
+ <VButton v-if="basicForm.hasOwnProperty('primary_button')" :button="basicForm.primary_button" :sites="sites"/>
94
+ <VButton v-if="basicForm.hasOwnProperty('secondary_button')" :button="basicForm.secondary_button" :sites="sites"/>
95
+ </div>
96
+ <div class="flex w-full max-w-[356px] flex-col gap-4">
97
+ <template v-if="!hasLines">
98
+ <card title="Visibility" supporting_text="Toggle off if you'd like to hide this item">
99
+ <VToggle v-model="basicForm.public" name="public" label="Public"/>
100
+ </card>
101
+ <card title="Featured Image" supporting_text="Recommended dimension: 1200*1060px">
102
+ <VFileUpload
103
+ name="image"
104
+ height="h-[200px]"
105
+ v-model="basicForm.featured_image"
106
+ />
107
+ </card>
108
+ </template>
109
+ <template v-else>
110
+ <card title="Timeline item title" supporting_text="To indicate the time period of the events">
39
111
  <input-wrapper
40
112
  is-vertical
41
- field="primary_button.label"
42
- label-text="Button Label *"
43
- class="w-full mb-4"
44
- :value="form.primary_button.label"
113
+ field="title"
114
+ label-text="Timeline item title *"
115
+ class="w-full"
116
+ :value="advancedForm.title"
45
117
  :limit="20"
46
118
  >
47
119
  <input
48
- v-model="form.primary_button.label"
49
- name="primary_button.label"
120
+ v-model="advancedForm.title"
121
+ name="title"
50
122
  type="text"
51
- placeholder="Label"
123
+ placeholder="Title"
52
124
  :maxlength="20"
53
125
  class="border-1 border-solid border-gray-300 rounded-lg bg-white w-full"
54
126
  />
55
127
  </input-wrapper>
56
- <linked-to
57
- name="primary"
58
- v-model:type="form.primary_button.type"
59
- v-model:url="form.primary_button.url"
60
- v-model:openInNewTab="form.primary_button.open_in_new_tab"
61
- :sites="sites"
62
- />
63
- </div>
64
- </card>
65
- <card v-if="form.hasOwnProperty('secondary_button')" :title="form?.secondary_button?.name ?? 'Secondary button'">
66
- <div class="flex flex-col gap-4">
67
- <VToggle name="show" v-model="form.secondary_button.show" title="Show Button" />
128
+ </card>
129
+ <card title="Event group title" supporting_text="The title for the group of events under this time period">
68
130
  <input-wrapper
69
131
  is-vertical
70
- field="secondary_button.label"
71
- label-text="Button Label *"
72
- class="w-full mb-4"
73
- :value="form.secondary_button.label"
74
- :limit="20"
132
+ field="title"
133
+ label-text="Event group title *"
134
+ class="w-full"
135
+ :value="advancedForm.group_title"
136
+ :limit="51"
75
137
  >
76
138
  <input
77
- v-model="form.secondary_button.label"
78
- name="secondary_button.label"
139
+ v-model="advancedForm.group_title"
140
+ name="title"
79
141
  type="text"
80
- placeholder="Label"
81
- :maxlength="20"
142
+ placeholder="Title"
143
+ :maxlength="51"
82
144
  class="border-1 border-solid border-gray-300 rounded-lg bg-white w-full"
83
145
  />
84
146
  </input-wrapper>
85
- <linked-to
86
- name="secondary"
87
- v-model:type="form.secondary_button.type"
88
- v-model:url="form.secondary_button.url"
89
- v-model:openInNewTab="form.secondary_button.open_in_new_tab"
90
- :sites="sites"
91
- />
92
- </div>
93
- </card>
94
- </div>
95
- <div class="flex w-full max-w-[356px] flex-col gap-4">
96
- <card title="Visibility" supporting_text="Toggle off if you'd like to hide this item">
97
- <VToggle v-model="form.public" name="public" label="Public" />
98
- </card>
99
- <card title="Featured Image" supporting_text="Recommended dimension: 1200*1060px">
100
- <VFileUpload
101
- name="image"
102
- height="h-[200px]"
103
- v-model="form.featured_image"
104
- />
105
- </card>
147
+ </card>
148
+ </template>
106
149
  </div>
107
150
  </div>
108
151
  <slot>
@@ -116,20 +159,25 @@
116
159
  >Save changes</a>
117
160
  </div>
118
161
  </slot>
162
+ <VModal ref="modalRef" :entity="'event'" :callback="removeLine"></VModal>
119
163
  </div>
120
164
  </template>
165
+
121
166
  <script setup>
122
- import { ref, computed, inject } from "vue";
167
+ import {ref, computed, inject} from "vue";
123
168
  import QuillEditor from "@/components/common/QuillEditor.vue";
124
169
  import Card from "@/components/common/Card.vue";
125
- import LinkedTo from "@/components/common/LinkedTo.vue";
126
170
  import InputWrapper from "@/components/common/InputWrapper.vue";
127
- import VToggle from "@/components/common/VToggle.vue";
171
+ import VToggle from "@/components/common/Toggle.vue";
128
172
  import DefaultFileUpload from "@/components/common/FileUpload.vue";
129
173
 
130
174
  // Inject the FileUpload component or fallback to the default one
131
175
  const VFileUpload = inject("VFileUpload", DefaultFileUpload);
132
176
  import axios from "axios";
177
+ import VButton from "@/components/common/Button.vue";
178
+ import PlusIcon from "@/assets/img/icons/plus.svg";
179
+ import ActionMenu from "@/components/common/ActionMenu.vue";
180
+ import VModal from "@/components/common/Modal.vue";
133
181
 
134
182
  const emit = defineEmits(["update"]);
135
183
 
@@ -147,39 +195,64 @@ const props = defineProps({
147
195
  required: false,
148
196
  },
149
197
  sites: {
150
- type: Object,
198
+ type: Array,
151
199
  required: true,
152
200
  },
153
201
  });
154
202
 
155
- const form = ref({
203
+ const hasLines = computed(() => {
204
+ return props.item.hasOwnProperty('lines');
205
+ });
206
+
207
+ const modalRef = ref(null);
208
+
209
+ const basicForm = ref({
156
210
  public: props.item.public,
157
211
  title: props.item.title,
158
212
  description: props.item.description,
159
213
  featured_image: props.item.featured_image,
214
+ lines: props.item.lines || [],
215
+ });
216
+
217
+ const advancedForm = ref({
218
+ title: props.item.title,
219
+ title_group: props.item?.title_group,
220
+ max_items: props.item?.max_items,
221
+ lines: props.item.lines || [],
160
222
  });
161
223
 
162
224
  if (props.item.hasOwnProperty('primary_button')) {
163
- form.value.primary_button = props.item.primary_button;
225
+ basicForm.value.primary_button = props.item.primary_button;
164
226
  }
165
227
 
166
228
  if (props.item.hasOwnProperty('secondary_button')) {
167
- form.value.secondary_button = props.item.secondary_button;
229
+ basicForm.value.secondary_button = props.item.secondary_button;
168
230
  }
169
231
 
232
+ const addLine = () => {
233
+ advancedForm.value.lines.push({title: "", description: ""});
234
+ };
235
+
236
+ const removeLine = (index) => {
237
+ advancedForm.value.lines.splice(index, 1);
238
+ emit("update", false);
239
+ };
240
+
170
241
  const save = () => {
242
+ let form = hasLines.value ? advancedForm : basicForm;
171
243
  emit("update", form.value);
172
244
 
173
245
  if (props.saveEndpoint) {
174
- axios.post(props.saveEndpoint, form.value).then (() => {
246
+ axios.post(props.saveEndpoint, form.value).then(() => {
175
247
  if (props.cancelEndpoint) {
176
248
  window.location.href = props.cancelEndpoint;
177
249
  }
178
- })
250
+ });
179
251
  }
180
252
  };
181
253
 
182
254
  const close = () => {
255
+ let form = hasLines.value ? advancedForm : basicForm;
183
256
  emit("close", form.value);
184
257
 
185
258
  if (props.cancelEndpoint) {
@@ -187,10 +260,13 @@ const close = () => {
187
260
  }
188
261
  };
189
262
 
190
- const descriptionWordCount = computed(() => {
191
- const plainText = form.value.description?.replace(/<[^>]*>/g, ' ').trim();
263
+ const descriptionWordCount = (description) => {
264
+ const plainText = description?.replace(/<[^>]*>/g, ' ').trim();
192
265
  const words = plainText.split(/\s+/).filter(word => word.length > 0);
193
266
  return words.length;
194
- });
267
+ };
195
268
 
196
- </script>
269
+ const handleDeleteItem = (index) => {
270
+ modalRef?.value?.open(index);
271
+ };
272
+ </script>
@@ -0,0 +1,139 @@
1
+ <template>
2
+ <div class="item-edit">
3
+ <div class="flex items-start gap-4 px-6 pt-4 h-full min-h-[90vh]">
4
+ <div class="flex flex-1 flex-col gap-4">
5
+ <card title="Description">
6
+ <div class="flex flex-col gap-8">
7
+ <div class="flex gap-4">
8
+ <input-wrapper
9
+ is-vertical
10
+ field="icon"
11
+ label-text="Icon *"
12
+ :value="form.icon"
13
+ >
14
+ <IconSelector id="icon" v-model="form.icon" />
15
+ </input-wrapper>
16
+ <input-wrapper
17
+ is-vertical
18
+ field="title"
19
+ label-text="Title *"
20
+ class="w-full"
21
+ :value="form.title"
22
+ :limit="51"
23
+ >
24
+ <input
25
+ v-model="form.title"
26
+ name="title"
27
+ type="text"
28
+ placeholder="Title"
29
+ :maxlength="51"
30
+ class="border-1 border-solid border-gray-300 rounded-lg bg-white w-full"
31
+ />
32
+ </input-wrapper>
33
+ </div>
34
+ <input-wrapper
35
+ is-vertical
36
+ field="description"
37
+ label-text="Supporting Text *"
38
+ class="w-full mb-4"
39
+ :value="descriptionWordCount"
40
+ :show-count="true"
41
+ >
42
+ <QuillEditor v-model="form.description"/>
43
+ </input-wrapper>
44
+ </div>
45
+ </card>
46
+ <VButton v-if="form.hasOwnProperty('primary_button')" :button="form.primary_button" :sites="sites"/>
47
+ </div>
48
+ <div class="flex w-full max-w-[356px] flex-col gap-4">
49
+ <card title="Visibility" supporting_text="Toggle off if you'd like to hide this item">
50
+ <VToggle v-model="form.public" name="public" label="Public" />
51
+ </card>
52
+ </div>
53
+ </div>
54
+ <slot>
55
+ <div class="flex justify-between space-x-xsSpace pt-xsSpace gap-4 sticky bottom-0 w-full bg-gray-200 py-2 px-6">
56
+ <a @click="close"
57
+ class="w-[200px] py-[9px] bg-white rounded-full border border-gray-300 shadow-xs text-md font-semibold hover:bg-gray-100 text-gray-700 text-center cursor-pointer">
58
+ Cancel
59
+ </a>
60
+ <a @click.prevent="save"
61
+ class="w-full py-[9px] 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"
62
+ >Save changes</a>
63
+ </div>
64
+ </slot>
65
+ </div>
66
+ </template>
67
+ <script setup>
68
+ import { ref, computed } from "vue";
69
+ import QuillEditor from "@/components/common/QuillEditor.vue";
70
+ import IconSelector from "@/components/common/IconSelector.vue";
71
+ import Card from "@/components/common/Card.vue";
72
+ import InputWrapper from "@/components/common/InputWrapper.vue";
73
+ import VToggle from "@/components/common/Toggle.vue";
74
+ import axios from "axios";
75
+ import VButton from "@/components/common/Button.vue";
76
+
77
+ const emit = defineEmits(["update"]);
78
+
79
+ const props = defineProps({
80
+ item: {
81
+ type: Object,
82
+ required: true,
83
+ },
84
+ saveEndpoint: {
85
+ type: String,
86
+ required: false,
87
+ },
88
+ cancelEndpoint: {
89
+ type: String,
90
+ required: false,
91
+ },
92
+ sites: {
93
+ type: Array,
94
+ required: true,
95
+ },
96
+ });
97
+
98
+ const form = ref({
99
+ icon: props.item.icon,
100
+ public: props.item.public,
101
+ title: props.item.title,
102
+ description: props.item.description,
103
+ });
104
+
105
+ if (props.item.hasOwnProperty('primary_button')) {
106
+ form.value.primary_button = props.item.primary_button;
107
+ }
108
+
109
+ if (props.item.hasOwnProperty('secondary_button')) {
110
+ form.value.secondary_button = props.item.secondary_button;
111
+ }
112
+
113
+ const save = () => {
114
+ emit("update", form.value);
115
+
116
+ if (props.saveEndpoint) {
117
+ axios.post(props.saveEndpoint, form.value).then (() => {
118
+ if (props.cancelEndpoint) {
119
+ window.location.href = props.cancelEndpoint;
120
+ }
121
+ })
122
+ }
123
+ };
124
+
125
+ const close = () => {
126
+ emit("close", form.value);
127
+
128
+ if (props.cancelEndpoint) {
129
+ window.location.href = props.cancelEndpoint;
130
+ }
131
+ };
132
+
133
+ const descriptionWordCount = computed(() => {
134
+ const plainText = form.value.description?.replace(/<[^>]*>/g, ' ').trim();
135
+ const words = plainText.split(/\s+/).filter(word => word.length > 0);
136
+ return words.length;
137
+ });
138
+
139
+ </script>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="page-builder overflow-auto">
3
3
  <div class="flex gap-4 px-6 overflow-auto">
4
- <div class="flex w-[356px] flex-col gap-2 pb-10">
4
+ <div class="flex w-[356px] flex-col gap-2 pb-10 overflow-y-auto h-[100vh]">
5
5
  <div v-for="(parent, sectionIndex) in modelValue.sections" class="border-b border-gray-200 pb-2">
6
6
  <div
7
7
  @click="openStates[sectionIndex] = !openStates[sectionIndex]"
@@ -38,8 +38,28 @@
38
38
  </div>
39
39
  </div>
40
40
  </div>
41
- <div class="flex h-full flex-1 flex-col rounded-xl bg-gray-50 px-6 py-5 mb-20">
42
- <Instructions v-if="!selected" />
41
+ <div class="flex h-full flex-1 flex-col mb-20">
42
+ <div class="mb-4 px-6 py-5 rounded-xl bg-gray-50" v-if="!selected">
43
+ <div class="text-lg pb-6 font-semibold text-gray-900 border-b border-gray-200">Settings</div>
44
+ <div class="flex flex-col gap-1 pt-6 text-gray-600">
45
+ <input-wrapper
46
+ field="breadcrumb"
47
+ label-text="Breadcrumb section"
48
+ class="w-full">
49
+ <select id="breadcrumb" v-model="modelValue.breadcrumb" name="url">
50
+ <option
51
+ :value="b"
52
+ v-for="(b) in breadcrumbs">
53
+ {{ b }}
54
+ </option>
55
+ </select>
56
+ </input-wrapper>
57
+ <p>This sets the section name shown in the breadcrumb (e.g. Home / Who We Are / Page). Leave blank to skip the section.</p>
58
+ </div>
59
+ </div>
60
+ <div class="rounded-xl bg-gray-50 px-6 py-5" v-if="!selected">
61
+ <Instructions />
62
+ </div>
43
63
  <component
44
64
  class="min-h-[90vh]"
45
65
  :is="currentComponent"
@@ -68,13 +88,16 @@ import { ref, markRaw, computed } from "vue";
68
88
  import ChevronRight from "@/assets/img/icons/chevron-right.svg";
69
89
  import ChevronDown from "@/assets/img/icons/chevron-down.svg";
70
90
  import Instructions from "@/components/builders/Instructions.vue";
71
- import VItems from "@/components/builders/VItems.vue";
72
- import VLinks from "@/components/builders/VLinks.vue";
73
- import VHeader from "@/components/builders/VHeader.vue";
74
- import VLogos from "@/components/builders/VLogos.vue";
75
- import VCollectionCarousel from "@/components/builders/VCollectionCarousel.vue";
76
- import VNewsGrid from "@/components/builders/VNewsGrid.vue";
77
- import VVideoGrid from "@/components/builders/VVideoGrid.vue";
91
+ import VItems from "@/components/builders/Items.vue";
92
+ import VLinks from "@/components/builders/Links.vue";
93
+ import VHeader from "@/components/builders/Header.vue";
94
+ import VLogos from "@/components/builders/Logos.vue";
95
+ import VCollectionCarousel from "@/components/builders/CollectionCarousel.vue";
96
+ import VNewsGrid from "@/components/builders/NewsGrid.vue";
97
+ import VVideoGrid from "@/components/builders/VideoGrid.vue";
98
+ import VParagraph from "@/components/builders/Paragraph.vue";
99
+ import VImageBlock from "@/components/builders/ImageBlock.vue";
100
+ import InputWrapper from "@/components/common/InputWrapper.vue";
78
101
 
79
102
  const emit = defineEmits(["save", "close"]);
80
103
  const props = defineProps({
@@ -88,6 +111,12 @@ const props = defineProps({
88
111
  return []
89
112
  }
90
113
  },
114
+ breadcrumbs: {
115
+ type: Array,
116
+ default: () => {
117
+ return []
118
+ }
119
+ },
91
120
  });
92
121
 
93
122
  const openStates = ref(JSON.parse(window.localStorage.getItem("pageBuilderOpenStates")));
@@ -103,6 +132,10 @@ const componentMaps = ref({
103
132
  carousel: markRaw(VCollectionCarousel),
104
133
  news_grid: markRaw(VNewsGrid),
105
134
  video_grid: markRaw(VVideoGrid),
135
+ paragraph: markRaw(VParagraph),
136
+ image_block: markRaw(VImageBlock),
137
+ timeline_items: markRaw(VItems),
138
+ link_cards: markRaw(VItems),
106
139
  });
107
140
 
108
141
  if (!openStates.value) {
@@ -17,6 +17,12 @@ import VTabs from "@/components/presenters/modules/VTabs.vue";
17
17
  import LogoCloud from "@/components/presenters/modules/LogoCloud.vue";
18
18
  import CollectionCarousel from "@/components/presenters/modules/CollectionCarousel.vue";
19
19
  import CollectionGrid from "@/components/presenters/modules/CollectionGrid.vue";
20
+ import StandardHeader from "@/components/presenters/modules/StandardHeader.vue";
21
+ import Paragraph from "@/components/presenters/modules/Paragraph.vue";
22
+ import TwoColumnsImageContent from "@/components/presenters/modules/TwoColumnsImageContent.vue";
23
+ import Timeline from "@/components/presenters/modules/Timeline.vue";
24
+ import LinkCard from "@/components/presenters/modules/LinkCard.vue";
25
+ import LinkList from "@/components/presenters/modules/LinkList.vue";
20
26
 
21
27
  const props = defineProps({
22
28
  page: {
@@ -26,12 +32,18 @@ const props = defineProps({
26
32
  });
27
33
 
28
34
  const componentMaps = ref({
35
+ paragraph: markRaw(Paragraph),
36
+ standard_header: markRaw(StandardHeader),
29
37
  header: markRaw(HeroHeader),
30
38
  quick_links: markRaw(QuickLinks),
31
39
  tabs: markRaw(VTabs),
32
40
  logo: markRaw(LogoCloud),
33
41
  collection_carousel: markRaw(CollectionCarousel),
34
42
  collection_grid: markRaw(CollectionGrid),
43
+ two_column_image_content: markRaw(TwoColumnsImageContent),
44
+ timeline: markRaw(Timeline),
45
+ link_card: markRaw(LinkCard),
46
+ link_list: markRaw(LinkList),
35
47
  });
36
48
 
37
49
  const currentComponent = (section) => {
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <div class="rounded-xl bg-gray-50 px-6 py-5">
3
+ <div class="flex flex-col">
4
+ <div class="flex flex-col gap-4 mb-4 border-b border-gray-200 pb-4">
5
+ <p class="text-lg font-semibold text-gray-900 border-b border-gray-200 pb-4">
6
+ Carousel
7
+ </p>
8
+ <div class="flex flex-col gap-6">
9
+ <div class="flex flex-col gap-1.5">
10
+ <input-wrapper
11
+ v-if="componentData.button"
12
+ is-vertical
13
+ field="title"
14
+ label-text="Button label *"
15
+ class="w-full mb-4"
16
+ :value="componentData.button.title"
17
+ :limit="51"
18
+ >
19
+ <input
20
+ v-model="componentData.button.title"
21
+ name="title"
22
+ type="text"
23
+ placeholder="Title"
24
+ :maxlength="51"
25
+ class="border-1 border-solid border-gray-300 rounded-lg bg-white w-full"
26
+ />
27
+ </input-wrapper>
28
+ <linked-to
29
+ v-if="componentData?.button"
30
+ label="Link to"
31
+ name="button"
32
+ v-model:type="componentData.button.type"
33
+ v-model:url="componentData.button.url"
34
+ v-model:openInNewTab="componentData.button.open_in_new_tab"
35
+ :sites="sites"
36
+ />
37
+ </div>
38
+ </div>
39
+ </div>
40
+ <div>
41
+ <h3 v-if="componentData.content?.label" class="text-base text-gray-900 font-semibold">
42
+ {{ componentData.content.label }}</h3>
43
+ <p v-if="componentData.content?.supportive_text" class="text-gray-600 text-base font-normal mt-2">
44
+ {{ componentData.content.supportive_text }}</p>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </template>
49
+ <script setup>
50
+ import {ref} from "vue";
51
+ import {defaultProps} from "@/components/helpers/defaultProps";
52
+ import LinkedTo from "@/components/common/LinkedTo.vue";
53
+ import InputWrapper from "@/components/common/InputWrapper.vue";
54
+
55
+ const emit = defineEmits(["update"]);
56
+
57
+ const props = defineProps({
58
+ ...defaultProps,
59
+ });
60
+
61
+ const componentData = ref(props.data.component);
62
+ </script>