@myissue/vue-website-page-builder 3.0.18 → 3.0.19

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 (54) hide show
  1. package/README.md +79 -76
  2. package/dist/page-builder/2-images-text.png +0 -0
  3. package/dist/page-builder/3-images-text.png +0 -0
  4. package/dist/page-builder/3-vertical-images.png +0 -0
  5. package/dist/page-builder/4-images-text.png +0 -0
  6. package/dist/vue-website-page-builder.css +1 -1
  7. package/dist/vue-website-page-builder.js +7168 -7261
  8. package/dist/vue-website-page-builder.umd.cjs +146 -81
  9. package/package.json +4 -3
  10. package/src/App.vue +4 -115
  11. package/src/Components/Homepage/HomeSection.vue +70 -162
  12. package/src/Components/MediaLibrary/SidebarUnsplash.vue +9 -16
  13. package/src/Components/MediaLibrary/Unsplash.vue +51 -91
  14. package/src/Components/Modals/MediaLibraryModal.vue +56 -318
  15. package/src/Components/Modals/PageBuilderPreviewModal.vue +22 -40
  16. package/src/Components/PageBuilder/AdvancedPageBuilderSettings.vue +7 -0
  17. package/src/Components/PageBuilder/DropdownsPlusToggles/OptionsDropdown.vue +165 -110
  18. package/src/Components/PageBuilder/EditorMenu/Editables/BackgroundColorEditor.vue +9 -16
  19. package/src/Components/PageBuilder/EditorMenu/Editables/BorderRadius.vue +18 -18
  20. package/src/Components/PageBuilder/EditorMenu/Editables/Borders.vue +16 -21
  21. package/src/Components/PageBuilder/EditorMenu/Editables/ClassEditor.vue +12 -12
  22. package/src/Components/PageBuilder/EditorMenu/Editables/ComponentTopMenu.vue +10 -9
  23. package/src/Components/PageBuilder/EditorMenu/Editables/DeleteElement.vue +9 -9
  24. package/src/Components/PageBuilder/EditorMenu/Editables/EditGetElement.vue +144 -136
  25. package/src/Components/PageBuilder/EditorMenu/Editables/ElementEditor.vue +9 -10
  26. package/src/Components/PageBuilder/EditorMenu/Editables/ImageEditor.vue +31 -27
  27. package/src/Components/PageBuilder/EditorMenu/Editables/LinkEditor.vue +20 -14
  28. package/src/Components/PageBuilder/EditorMenu/Editables/ManageBackgroundOpacity.vue +9 -10
  29. package/src/Components/PageBuilder/EditorMenu/Editables/ManageOpacity.vue +9 -10
  30. package/src/Components/PageBuilder/EditorMenu/Editables/PaddingPlusMargin.vue +16 -16
  31. package/src/Components/PageBuilder/EditorMenu/Editables/TextColorEditor.vue +9 -16
  32. package/src/Components/PageBuilder/EditorMenu/Editables/Typography.vue +22 -20
  33. package/src/Components/PageBuilder/EditorMenu/RightSidebarEditor.vue +25 -27
  34. package/src/Components/PageBuilder/NoneCustomMediaLibraryComponent.vue +3 -0
  35. package/src/Components/PageBuilder/NoneCustomSearchComponent.vue +91 -0
  36. package/src/Components/PageBuilder/PageBuilderSettings.vue +8 -0
  37. package/src/Components/PageBuilder/Settings/AdvancedPageBuilderSettings.vue +31 -72
  38. package/src/Components/PageBuilder/Settings/PageBuilderSettings.vue +32 -36
  39. package/src/Components/Search/SearchComponents.vue +11 -199
  40. package/src/Components/TipTap/TipTap.vue +8 -7
  41. package/src/Components/TipTap/TipTapInput.vue +136 -134
  42. package/src/PageBuilder/PageBuilder.vue +220 -32
  43. package/src/composables/{PageBuilder.ts → PageBuilderClass.ts} +223 -142
  44. package/src/composables/usePageBuilderModal.ts +25 -0
  45. package/src/index.ts +8 -2
  46. package/src/stores/media-library.ts +1 -5
  47. package/src/stores/page-builder-state.ts +52 -36
  48. package/src/stores/user.ts +8 -6
  49. package/src/types/global.d.ts +6 -44
  50. package/src/types/index.ts +169 -0
  51. package/src/utils/html-elements/component.ts +88 -0
  52. package/src/utils/html-elements/componentHelpers.ts +101 -0
  53. package/src/Components/Modals/PageBuilderModal.vue +0 -233
  54. package/src/utils/builder/html-elements/componentHelpers.ts +0 -101
@@ -1,61 +1,33 @@
1
1
  // Type definitions
2
- interface ComponentObject {
3
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
- [key: string]: any
5
- }
6
-
7
- interface ImageObject {
8
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
- [key: string]: any
10
- }
11
-
12
- interface PageBuilderStateStore {
13
- getTextAreaVueModel: string | null
14
- getLocalStorageItemName: string | null
15
- getLocalStorageItemNameUpdate: string | null
16
- getHyberlinkEnable: boolean
17
- getComponents: ComponentObject[] | null
18
- getComponent: ComponentObject | null
19
- getElement: HTMLElement | null
20
- getNextSibling: HTMLElement | null
21
- getParentElement: HTMLElement | null
22
- getRestoredElement: string | null
23
- getComponentArrayAddMethod: string | null
24
- setElement: (element: HTMLElement | null) => void
25
- setMenuRight: (value: boolean) => void
26
- setComponent: (component: ComponentObject | null) => void
27
- setComponents: (components: ComponentObject[] | null) => void
28
- setComponentArrayAddMethod: (method: string) => void
29
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
- [key: string]: any // For dynamic mutation methods
31
- }
32
-
33
- interface MediaLibraryStore {
34
- getCurrentImage: ImageObject | null
35
- }
2
+ import type {
3
+ ComponentObject,
4
+ ImageObject,
5
+ PageBuilderStateStore,
6
+ MediaLibraryStore,
7
+ TimerHandle,
8
+ MutationObserver as MutationObserverType,
9
+ TailwindColors,
10
+ TailwindOpacities,
11
+ TailwindFontSizes,
12
+ TailwindFontStyles,
13
+ TailwindPaddingAndMargin,
14
+ TailwindBorderRadius,
15
+ TailwindBorderStyleWidthColor,
16
+ } from '@/types'
36
17
 
37
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
18
  import tailwindColors from '@/utils/builder/tailwaind-colors'
39
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
19
  import tailwindOpacities from '@/utils/builder/tailwind-opacities'
41
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
20
  import tailwindFontSizes from '@/utils/builder/tailwind-font-sizes'
43
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
21
  import tailwindFontStyles from '@/utils/builder/tailwind-font-styles'
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
22
  import tailwindPaddingAndMargin from '@/utils/builder/tailwind-padding-margin'
47
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
23
  import tailwindBorderRadius from '@/utils/builder/tailwind-border-radius'
49
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
24
  import tailwindBorderStyleWidthPlusColor from '@/utils/builder/tailwind-border-style-width-color'
51
- import { computed, ref, nextTick } from 'vue'
25
+ import { computed, ref, nextTick, inject } from 'vue'
52
26
  import type { ComputedRef } from 'vue'
53
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
27
  import { v4 as uuidv4 } from 'uuid'
55
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
28
  import { delay } from '@/composables/delay'
57
29
 
58
- class PageBuilder {
30
+ class PageBuilderClass {
59
31
  // Class properties with types
60
32
  private elementsWithListeners: WeakSet<Element>
61
33
  private nextTick: Promise<void>
@@ -65,7 +37,6 @@ class PageBuilder {
65
37
  private mediaLibraryStore: MediaLibraryStore
66
38
  private getTextAreaVueModel: ComputedRef<string | null>
67
39
  private getLocalStorageItemName: ComputedRef<string | null>
68
- private getLocalStorageItemNameUpdate: ComputedRef<string | null>
69
40
  private getCurrentImage: ComputedRef<ImageObject | null>
70
41
  private getHyberlinkEnable: ComputedRef<boolean>
71
42
  private getComponents: ComputedRef<ComponentObject[] | null>
@@ -79,10 +50,8 @@ class PageBuilder {
79
50
  private additionalTagsNoneListernes: string[]
80
51
  private structuringTags: string[]
81
52
  private showRunningMethodLogs: boolean
82
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
- private delay: any
84
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
- private observer?: any // Add missing observer property
53
+ private delay: ReturnType<typeof delay>
54
+ private observer?: MutationObserverType
86
55
 
87
56
  constructor(pageBuilderStateStore: PageBuilderStateStore, mediaLibraryStore: MediaLibraryStore) {
88
57
  /**
@@ -104,6 +73,8 @@ class PageBuilder {
104
73
  this.containsPagebuilder = document.querySelector('#contains-pagebuilder')
105
74
 
106
75
  this.timer = null
76
+
77
+ // Stores are now required parameters - no fallback to inject
107
78
  this.pageBuilderStateStore = pageBuilderStateStore
108
79
  this.mediaLibraryStore = mediaLibraryStore
109
80
 
@@ -111,9 +82,6 @@ class PageBuilder {
111
82
  this.getLocalStorageItemName = computed(
112
83
  () => this.pageBuilderStateStore.getLocalStorageItemName,
113
84
  )
114
- this.getLocalStorageItemNameUpdate = computed(
115
- () => this.pageBuilderStateStore.getLocalStorageItemNameUpdate,
116
- )
117
85
 
118
86
  this.getCurrentImage = computed(() => this.mediaLibraryStore.getCurrentImage)
119
87
  this.getHyberlinkEnable = computed(() => this.pageBuilderStateStore.getHyberlinkEnable)
@@ -162,22 +130,6 @@ class PageBuilder {
162
130
  this.delay = delay()
163
131
  }
164
132
 
165
- shouldRunMethods(): boolean {
166
- if (!this.getComponents.value) {
167
- return false
168
- }
169
-
170
- if (!this.getComponent.value) {
171
- return false
172
- }
173
-
174
- if (!this.getElement.value) {
175
- return false
176
- }
177
-
178
- return true
179
- }
180
-
181
133
  #applyElementClassChanges(
182
134
  selectedCSS: string,
183
135
  CSSArray: string[],
@@ -186,7 +138,6 @@ class PageBuilder {
186
138
  if (this.showRunningMethodLogs) {
187
139
  console.log('#applyElementClassChanges')
188
140
  }
189
- if (!this.shouldRunMethods()) return
190
141
 
191
142
  const currentCSS = CSSArray.find((CSS) => {
192
143
  return this.getElement.value?.classList.contains(CSS)
@@ -195,7 +146,7 @@ class PageBuilder {
195
146
  // set to 'none' if undefined
196
147
  let elementClass = currentCSS || 'none'
197
148
 
198
- this.pageBuilderStateStore[mutationName](elementClass)
149
+ this.pageBuilderStateStore[mutationName as keyof PageBuilderStateStore](elementClass)
199
150
 
200
151
  if (typeof selectedCSS === 'string' && selectedCSS !== 'none') {
201
152
  if (elementClass && this.getElement.value?.classList.contains(elementClass)) {
@@ -209,7 +160,7 @@ class PageBuilder {
209
160
  elementClass = selectedCSS
210
161
  }
211
162
 
212
- this.pageBuilderStateStore[mutationName](elementClass)
163
+ this.pageBuilderStateStore[mutationName as keyof PageBuilderStateStore](elementClass)
213
164
  this.pageBuilderStateStore.setElement(this.getElement.value)
214
165
 
215
166
  return currentCSS
@@ -251,6 +202,7 @@ class PageBuilder {
251
202
  }
252
203
 
253
204
  #handleElementClick = (e: Event, element: HTMLElement): void => {
205
+ e.preventDefault()
254
206
  e.stopPropagation()
255
207
 
256
208
  const pagebuilder = document.querySelector('#pagebuilder')
@@ -275,7 +227,6 @@ class PageBuilder {
275
227
  if (this.showRunningMethodLogs) {
276
228
  console.log('#handleMouseOver')
277
229
  }
278
- // console.log("YOU MOUSE OVER ME!");
279
230
 
280
231
  e.preventDefault()
281
232
  e.stopPropagation()
@@ -315,7 +266,9 @@ class PageBuilder {
315
266
  * The function is used to
316
267
  * attach event listeners to each element within a 'section'
317
268
  */
318
- setEventListenersForElements = () => {
269
+ setEventListenersForElements = async () => {
270
+ console.log('setEventListenersForElements called')
271
+
319
272
  if (this.showRunningMethodLogs) {
320
273
  console.log('setEventListenersForElements')
321
274
  }
@@ -324,6 +277,10 @@ class PageBuilder {
324
277
 
325
278
  if (!pagebuilder) return
326
279
 
280
+ // Wait for any pending DOM updates
281
+ await nextTick()
282
+ await new Promise((resolve) => requestAnimationFrame(resolve))
283
+
327
284
  pagebuilder.querySelectorAll('section *').forEach(async (element) => {
328
285
  // exclude headerTags && additional Tags for not listening
329
286
  if (
@@ -426,7 +383,7 @@ class PageBuilder {
426
383
  const parser = new DOMParser()
427
384
 
428
385
  // Parse the HTML content of the clonedComponent using the DOMParser
429
- const doc = parser.parseFromString(clonedComponent.html_code, 'text/html')
386
+ const doc = parser.parseFromString(clonedComponent.html_code || '', 'text/html')
430
387
 
431
388
  // Selects all elements within the HTML document, including elements like:
432
389
  const elements = doc.querySelectorAll('*')
@@ -481,8 +438,6 @@ class PageBuilder {
481
438
  console.log('handleAddClasses')
482
439
  }
483
440
 
484
- if (!this.shouldRunMethods()) return
485
-
486
441
  // convert classList to array
487
442
  const classListArray = Array.from(this.getElement.value?.classList || [])
488
443
 
@@ -495,8 +450,6 @@ class PageBuilder {
495
450
  console.log('handleAddClasses')
496
451
  }
497
452
 
498
- if (!this.shouldRunMethods()) return
499
-
500
453
  if (
501
454
  typeof userSelectedClass === 'string' &&
502
455
  userSelectedClass !== '' &&
@@ -514,13 +467,12 @@ class PageBuilder {
514
467
  this.pageBuilderStateStore.setClass(userSelectedClass)
515
468
  }
516
469
  }
470
+
517
471
  handleRemoveClasses(userSelectedClass: string): void {
518
472
  if (this.showRunningMethodLogs) {
519
473
  console.log('handleRemoveClasses')
520
474
  }
521
475
 
522
- if (!this.shouldRunMethods()) return
523
-
524
476
  // remove selected class from element
525
477
  if (this.getElement.value?.classList.contains(userSelectedClass)) {
526
478
  this.getElement.value?.classList.remove(userSelectedClass)
@@ -583,15 +535,16 @@ class PageBuilder {
583
535
 
584
536
  // Append the restored element to its parent
585
537
  // Insert the restored element before its next sibling in its parent
586
- if (newElement.firstChild) {
538
+ if (newElement.firstChild && this.getParentElement.value) {
539
+ // insertBefore can accept null as second parameter (will append to end)
587
540
  this.getParentElement.value.insertBefore(newElement.firstChild, this.getNextSibling.value)
588
541
  }
589
542
  }
590
543
 
591
544
  // Clear
592
-
593
545
  this.pageBuilderStateStore.setParentElement(null)
594
546
  this.pageBuilderStateStore.setRestoredElement(null)
547
+ this.pageBuilderStateStore.setNextSibling(null)
595
548
  this.pageBuilderStateStore.setComponent(null)
596
549
  this.pageBuilderStateStore.setElement(null)
597
550
 
@@ -805,7 +758,6 @@ class PageBuilder {
805
758
  console.log('handleFontSize')
806
759
  }
807
760
 
808
- if (!this.shouldRunMethods()) return
809
761
  if (!userSelectedFontSize) return
810
762
  if (!this.getElement.value) return
811
763
 
@@ -862,7 +814,9 @@ class PageBuilder {
862
814
  !userSelectedFontSize.includes('md:') &&
863
815
  !userSelectedFontSize.includes('lg:')
864
816
  ) {
865
- this.getElement.value.classList.remove(getFontBase.value)
817
+ if (getFontBase.value) {
818
+ this.getElement.value.classList.remove(getFontBase.value)
819
+ }
866
820
  if (!userSelectedFontSize.includes('base:none')) {
867
821
  this.getElement.value.classList.add(userSelectedFontSize)
868
822
  }
@@ -870,7 +824,9 @@ class PageBuilder {
870
824
  this.pageBuilderStateStore.setFontBase(userSelectedFontSize)
871
825
  }
872
826
  if (userSelectedFontSize.includes('lg:')) {
873
- this.getElement.value.classList.remove(getFontDesktop.value)
827
+ if (getFontDesktop.value) {
828
+ this.getElement.value.classList.remove(getFontDesktop.value)
829
+ }
874
830
  if (!userSelectedFontSize.includes('lg:none')) {
875
831
  this.getElement.value.classList.add(userSelectedFontSize)
876
832
  }
@@ -878,7 +834,9 @@ class PageBuilder {
878
834
  this.pageBuilderStateStore.setFontDesktop(userSelectedFontSize)
879
835
  }
880
836
  if (userSelectedFontSize.includes('md:')) {
881
- this.getElement.value.classList.remove(getFontTablet.value)
837
+ if (getFontTablet.value) {
838
+ this.getElement.value.classList.remove(getFontTablet.value)
839
+ }
882
840
  if (!userSelectedFontSize.includes('md:none')) {
883
841
  this.getElement.value.classList.add(userSelectedFontSize)
884
842
  }
@@ -886,7 +844,9 @@ class PageBuilder {
886
844
  this.pageBuilderStateStore.setFontTablet(userSelectedFontSize)
887
845
  }
888
846
  if (userSelectedFontSize.includes('sm:')) {
889
- this.getElement.value.classList.remove(getFontMobile.value)
847
+ if (getFontMobile.value) {
848
+ this.getElement.value.classList.remove(getFontMobile.value)
849
+ }
890
850
  if (!userSelectedFontSize.includes('sm:none')) {
891
851
  this.getElement.value.classList.add(userSelectedFontSize)
892
852
  }
@@ -931,7 +891,6 @@ class PageBuilder {
931
891
  console.log('deleteComponent')
932
892
  }
933
893
 
934
- if (!this.shouldRunMethods()) return
935
894
  if (!this.getComponents.value || !this.getComponent.value) return
936
895
 
937
896
  // Find the index of the component to delete
@@ -959,7 +918,6 @@ class PageBuilder {
959
918
  console.log('moveComponent')
960
919
  }
961
920
 
962
- if (!this.shouldRunMethods()) return
963
921
  if (!this.getComponents.value || !this.getComponent.value) return
964
922
 
965
923
  if (this.getComponents.value.length <= 1) return
@@ -994,7 +952,6 @@ class PageBuilder {
994
952
  console.log('ensureTextAreaHasContent')
995
953
  }
996
954
 
997
- if (!this.shouldRunMethods()) return
998
955
  if (!this.getElement.value) return
999
956
 
1000
957
  // text content
@@ -1024,8 +981,6 @@ class PageBuilder {
1024
981
  console.log('handleTextInput')
1025
982
  }
1026
983
 
1027
- if (!this.shouldRunMethods()) return
1028
-
1029
984
  // // text content
1030
985
  if (typeof this.getElement.value?.innerHTML !== 'string') {
1031
986
  return
@@ -1127,6 +1082,75 @@ class PageBuilder {
1127
1082
  //
1128
1083
  }
1129
1084
 
1085
+ // Helper function to sanitize title for localStorage key
1086
+ private sanitizeForLocalStorage(input: string): string {
1087
+ return input
1088
+ .trim() // Remove leading/trailing spaces
1089
+ .toLowerCase() // Convert to lowercase
1090
+ .replace(/\s+/g, '-') // Replace one or more spaces with single hyphen
1091
+ .replace(/[^a-z0-9-]/g, '') // Remove all non-alphanumeric characters except hyphens
1092
+ .replace(/-+/g, '-') // Replace multiple consecutive hyphens with single hyphen
1093
+ .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens
1094
+ }
1095
+
1096
+ updateLocalStorageItemName(): void {
1097
+ const updateOrCreate = this.pageBuilderStateStore.getUpdateOrCreate
1098
+
1099
+ const resourceData = this.pageBuilderStateStore.getCurrentResourceData
1100
+
1101
+ // Logic for update
1102
+ if (updateOrCreate === 'create') {
1103
+ this.pageBuilderStateStore.setLocalStorageItemName(`page-builder-create-resource`)
1104
+ return
1105
+ }
1106
+
1107
+ // Logic for update
1108
+ if (updateOrCreate === 'update') {
1109
+ // if resource data is null
1110
+ if (resourceData === null) {
1111
+ this.pageBuilderStateStore.setLocalStorageItemName(`page-builder-update-resource`)
1112
+ return
1113
+ }
1114
+
1115
+ // If resource is present
1116
+
1117
+ // Runs when resourceData has id but no title
1118
+ if (typeof resourceData === 'object' && 'id' in resourceData && !('title' in resourceData)) {
1119
+ const sanitizedId = this.sanitizeForLocalStorage(String(resourceData['id']))
1120
+ console.log('ID BUT NOT TITLE:', `page-builder-update-resource-${sanitizedId}`)
1121
+
1122
+ this.pageBuilderStateStore.setLocalStorageItemName(
1123
+ `page-builder-update-resource-${sanitizedId}`,
1124
+ )
1125
+ return
1126
+ }
1127
+
1128
+ // Runs when resourceData has title but no id
1129
+ if (typeof resourceData === 'object' && 'title' in resourceData && !('id' in resourceData)) {
1130
+ const sanitizedTitle = this.sanitizeForLocalStorage(String(resourceData['title']))
1131
+ console.log('TITLE BUT NOT ID:', `page-builder-update-resource-${sanitizedTitle}`)
1132
+
1133
+ this.pageBuilderStateStore.setLocalStorageItemName(
1134
+ `page-builder-update-resource-${sanitizedTitle}`,
1135
+ )
1136
+ return
1137
+ }
1138
+
1139
+ // Runs when resourceData has both title and id
1140
+ if (typeof resourceData === 'object' && 'title' in resourceData && 'id' in resourceData) {
1141
+ const sanitizedId = this.sanitizeForLocalStorage(String(resourceData['id']))
1142
+ const sanitizedTitle = this.sanitizeForLocalStorage(String(resourceData['title']))
1143
+
1144
+ this.pageBuilderStateStore.setLocalStorageItemName(
1145
+ `page-builder-update-resource-${sanitizedTitle}-${sanitizedId}`,
1146
+ )
1147
+ return
1148
+ }
1149
+
1150
+ console.log('both are there...')
1151
+ }
1152
+ }
1153
+
1130
1154
  async saveComponentsLocalStorage() {
1131
1155
  await this.nextTick
1132
1156
  this.synchronizeDOMAndComponents()
@@ -1144,27 +1168,27 @@ class PageBuilder {
1144
1168
  }
1145
1169
  }
1146
1170
 
1147
- async saveComponentsLocalStorageUpdate() {
1171
+ async removeItemComponentsLocalStorageCreate() {
1172
+ console.log('removeItemComponentsLocalStorageCreate')
1148
1173
  if (this.showRunningMethodLogs) {
1149
- console.log('saveComponentsLocalStorageUpdate')
1174
+ console.log('removeItemComponentsLocalStorageCreate')
1150
1175
  }
1151
1176
 
1152
1177
  await this.nextTick
1153
- if (this.getLocalStorageItemNameUpdate.value) {
1154
- localStorage.setItem(
1155
- this.getLocalStorageItemNameUpdate.value,
1156
- JSON.stringify(this.getComponents.value),
1157
- )
1178
+
1179
+ if (this.getLocalStorageItemName.value) {
1180
+ localStorage.removeItem(this.getLocalStorageItemName.value)
1158
1181
  }
1159
1182
  }
1183
+
1160
1184
  async removeItemComponentsLocalStorageUpdate() {
1185
+ console.log('removeItemComponentsLocalStorageUpdate')
1161
1186
  if (this.showRunningMethodLogs) {
1162
1187
  console.log('saveComponentsLocalStorageUpdate')
1163
1188
  }
1164
1189
 
1165
- await this.nextTick
1166
- if (this.getLocalStorageItemNameUpdate.value) {
1167
- localStorage.removeItem(this.getLocalStorageItemNameUpdate.value)
1190
+ if (this.getLocalStorageItemName.value) {
1191
+ localStorage.removeItem(this.getLocalStorageItemName.value)
1168
1192
  }
1169
1193
  }
1170
1194
 
@@ -1175,57 +1199,54 @@ class PageBuilder {
1175
1199
 
1176
1200
  if (!this.getLocalStorageItemName.value) return false
1177
1201
 
1178
- const savedCurrentDesign = localStorage.getItem(this.getLocalStorageItemName.value)
1179
- if (savedCurrentDesign) {
1180
- let components = JSON.parse(savedCurrentDesign)
1181
- if (!components) {
1182
- components = []
1183
- }
1202
+ if (
1203
+ this.getLocalStorageItemName.value &&
1204
+ localStorage.getItem(this.getLocalStorageItemName.value)
1205
+ ) {
1206
+ const savedCurrentDesign = localStorage.getItem(this.getLocalStorageItemName.value)
1184
1207
 
1185
- this.pageBuilderStateStore.setComponents(components)
1208
+ if (savedCurrentDesign) {
1209
+ let components = JSON.parse(savedCurrentDesign)
1186
1210
 
1187
- return true
1188
- }
1211
+ // Ensure components is always an array
1212
+ components = Array.isArray(components) ? components : []
1189
1213
 
1190
- return false
1191
- }
1192
- //
1193
- areComponentsStoredInLocalStorageUpdate() {
1194
- if (this.showRunningMethodLogs) {
1195
- console.log('areComponentsStoredInLocalStorageUpdate')
1196
- }
1214
+ // Transform HTML strings to component objects if needed
1215
+ if (components.length > 0 && typeof components[0] === 'string') {
1216
+ components = components.map((htmlString: string) => ({
1217
+ html_code: htmlString,
1218
+ }))
1219
+ }
1197
1220
 
1198
- if (!this.getLocalStorageItemNameUpdate.value) return false
1221
+ this.pageBuilderStateStore.setComponents(components)
1199
1222
 
1200
- const savedCurrentDesign = localStorage.getItem(this.getLocalStorageItemNameUpdate.value)
1201
- if (savedCurrentDesign) {
1202
- let components = JSON.parse(savedCurrentDesign)
1203
- if (!components) {
1204
- components = []
1223
+ return true
1205
1224
  }
1206
-
1207
- this.pageBuilderStateStore.setComponents(components)
1208
-
1209
- return true
1210
1225
  }
1211
1226
 
1212
1227
  return false
1213
1228
  }
1214
1229
  //
1215
- async updateBasePrimaryImage(data: { type: string }): Promise<void> {
1230
+ //
1231
+ async updateBasePrimaryImage(data?: { type: string }): Promise<void> {
1216
1232
  if (this.showRunningMethodLogs) {
1217
1233
  console.log('updateBasePrimaryImage')
1218
1234
  }
1219
1235
 
1220
1236
  if (!this.getElement.value) return
1221
1237
 
1222
- if (data.type === 'unsplash' && this.getCurrentImage.value) {
1223
- if (this.getCurrentImage.value.file) {
1238
+ // If data is provided, check for specific type (backward compatibility)
1239
+ if (data && data.type === 'unsplash' && this.getCurrentImage.value) {
1240
+ if (this.getCurrentImage.value.src) {
1224
1241
  await this.nextTick
1225
-
1226
- this.pageBuilderStateStore.setBasePrimaryImage(`${this.getCurrentImage.value.file}`)
1242
+ this.pageBuilderStateStore.setBasePrimaryImage(`${this.getCurrentImage.value.src}`)
1227
1243
  }
1228
1244
  }
1245
+ // If no data provided, apply current image if available (new simplified usage)
1246
+ if (this.getCurrentImage.value && this.getCurrentImage.value.src) {
1247
+ await this.nextTick
1248
+ this.pageBuilderStateStore.setBasePrimaryImage(`${this.getCurrentImage.value.src}`)
1249
+ }
1229
1250
  }
1230
1251
 
1231
1252
  showBasePrimaryImage() {
@@ -1264,9 +1285,15 @@ class PageBuilder {
1264
1285
  console.log('#addHyperlinkToElement')
1265
1286
  }
1266
1287
 
1267
- if (!this.shouldRunMethods()) return
1268
1288
  if (!this.getElement.value) return
1269
1289
 
1290
+ // Check if element is a proper DOM element and has closest method
1291
+ if (
1292
+ !(this.getElement.value instanceof HTMLElement) ||
1293
+ typeof this.getElement.value.closest !== 'function'
1294
+ )
1295
+ return
1296
+
1270
1297
  const parentHyperlink = this.getElement.value.closest('a')
1271
1298
  const hyperlink = this.getElement.value.querySelector('a')
1272
1299
 
@@ -1354,7 +1381,6 @@ class PageBuilder {
1354
1381
  console.log('#checkForHyperlink')
1355
1382
  }
1356
1383
 
1357
- if (!this.shouldRunMethods()) return
1358
1384
  if (!this.getElement.value) return
1359
1385
 
1360
1386
  const hyperlink = this.getElement.value.querySelector('a')
@@ -1391,11 +1417,18 @@ class PageBuilder {
1391
1417
  console.log('handleHyperlink')
1392
1418
  }
1393
1419
 
1394
- if (!this.shouldRunMethods()) return
1395
-
1396
1420
  this.pageBuilderStateStore.setHyperlinkAbility(true)
1397
1421
 
1398
- const parentHyperlink = this.getElement.value?.closest('a')
1422
+ if (!this.getElement.value) return
1423
+
1424
+ // Check if element is a proper DOM element and has closest method
1425
+ if (
1426
+ !(this.getElement.value instanceof HTMLElement) ||
1427
+ typeof this.getElement.value.closest !== 'function'
1428
+ )
1429
+ return
1430
+
1431
+ const parentHyperlink = this.getElement.value.closest('a')
1399
1432
 
1400
1433
  // handle case where parent element already has an a href tag
1401
1434
  // when clicking directly on a hyperlink
@@ -1426,8 +1459,6 @@ class PageBuilder {
1426
1459
  }
1427
1460
 
1428
1461
  handlePageBuilderMethods(): void {
1429
- if (!this.shouldRunMethods()) return
1430
-
1431
1462
  this.pageBuilderStateStore.setParentElement(null)
1432
1463
  this.pageBuilderStateStore.setRestoredElement(null)
1433
1464
 
@@ -1478,6 +1509,56 @@ class PageBuilder {
1478
1509
  // handle classes
1479
1510
  this.currentClasses()
1480
1511
  }
1512
+
1513
+ // Helper method for custom components to easily add components
1514
+ async addComponent(componentObject: ComponentObject): Promise<void> {
1515
+ if (this.showRunningMethodLogs) {
1516
+ console.log('addComponent')
1517
+ }
1518
+
1519
+ try {
1520
+ const clonedComponent = this.cloneCompObjForDOMInsertion({
1521
+ html_code: componentObject.html_code,
1522
+ id: componentObject.id,
1523
+ title: componentObject.title,
1524
+ })
1525
+
1526
+ this.pageBuilderStateStore.setPushComponents({
1527
+ component: clonedComponent,
1528
+ componentArrayAddMethod: this.getComponentArrayAddMethod.value || 'push',
1529
+ })
1530
+
1531
+ // Wait for the DOM to update before setting event listeners
1532
+ await nextTick()
1533
+ this.setEventListenersForElements()
1534
+ } catch (error) {
1535
+ console.error('Error adding component:', error)
1536
+ }
1537
+ }
1538
+
1539
+ // Load existing content from HTML when in update mode
1540
+ loadExistingContent(): void {
1541
+ if (this.showRunningMethodLogs) {
1542
+ console.log('loadExistingContent')
1543
+ }
1544
+
1545
+ if (this.pageBuilderStateStore.getUpdateOrCreate === 'update') {
1546
+ if (this.areComponentsStoredInLocalStorage()) {
1547
+ try {
1548
+ // set components
1549
+ const htmlOutput =
1550
+ Array.isArray(this.getComponents.value) &&
1551
+ this.getComponents.value
1552
+ .map((component) => {
1553
+ return component.html_code
1554
+ })
1555
+ .join('')
1556
+ } catch (error) {
1557
+ console.error('Error loading existing content:', error)
1558
+ }
1559
+ }
1560
+ }
1561
+ }
1481
1562
  }
1482
1563
 
1483
- export default PageBuilder
1564
+ export default PageBuilderClass
@@ -0,0 +1,25 @@
1
+ import { inject } from 'vue'
2
+
3
+ // Composable for managing PageBuilder modals
4
+ export function usePageBuilderModal() {
5
+ // Get the close function provided by the PageBuilder component
6
+ const closeAddComponentModal = inject<(() => void) | null>('closeAddComponentModal', null)
7
+ const closeMediaLibraryModal = inject<(() => void) | null>('closeMediaLibraryModal', null)
8
+
9
+ return {
10
+ closeAddComponentModal:
11
+ closeAddComponentModal ||
12
+ (() => {
13
+ console.warn(
14
+ 'closeAddComponentModal function not available. Make sure you are using this within a PageBuilder context.',
15
+ )
16
+ }),
17
+ closeMediaLibraryModal:
18
+ closeMediaLibraryModal ||
19
+ (() => {
20
+ console.warn(
21
+ 'closeMediaLibraryModal function not available. Make sure you are using this within a MediaLibraryModal context.',
22
+ )
23
+ }),
24
+ }
25
+ }