@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.
- package/README.md +79 -76
- package/dist/page-builder/2-images-text.png +0 -0
- package/dist/page-builder/3-images-text.png +0 -0
- package/dist/page-builder/3-vertical-images.png +0 -0
- package/dist/page-builder/4-images-text.png +0 -0
- package/dist/vue-website-page-builder.css +1 -1
- package/dist/vue-website-page-builder.js +7168 -7261
- package/dist/vue-website-page-builder.umd.cjs +146 -81
- package/package.json +4 -3
- package/src/App.vue +4 -115
- package/src/Components/Homepage/HomeSection.vue +70 -162
- package/src/Components/MediaLibrary/SidebarUnsplash.vue +9 -16
- package/src/Components/MediaLibrary/Unsplash.vue +51 -91
- package/src/Components/Modals/MediaLibraryModal.vue +56 -318
- package/src/Components/Modals/PageBuilderPreviewModal.vue +22 -40
- package/src/Components/PageBuilder/AdvancedPageBuilderSettings.vue +7 -0
- package/src/Components/PageBuilder/DropdownsPlusToggles/OptionsDropdown.vue +165 -110
- package/src/Components/PageBuilder/EditorMenu/Editables/BackgroundColorEditor.vue +9 -16
- package/src/Components/PageBuilder/EditorMenu/Editables/BorderRadius.vue +18 -18
- package/src/Components/PageBuilder/EditorMenu/Editables/Borders.vue +16 -21
- package/src/Components/PageBuilder/EditorMenu/Editables/ClassEditor.vue +12 -12
- package/src/Components/PageBuilder/EditorMenu/Editables/ComponentTopMenu.vue +10 -9
- package/src/Components/PageBuilder/EditorMenu/Editables/DeleteElement.vue +9 -9
- package/src/Components/PageBuilder/EditorMenu/Editables/EditGetElement.vue +144 -136
- package/src/Components/PageBuilder/EditorMenu/Editables/ElementEditor.vue +9 -10
- package/src/Components/PageBuilder/EditorMenu/Editables/ImageEditor.vue +31 -27
- package/src/Components/PageBuilder/EditorMenu/Editables/LinkEditor.vue +20 -14
- package/src/Components/PageBuilder/EditorMenu/Editables/ManageBackgroundOpacity.vue +9 -10
- package/src/Components/PageBuilder/EditorMenu/Editables/ManageOpacity.vue +9 -10
- package/src/Components/PageBuilder/EditorMenu/Editables/PaddingPlusMargin.vue +16 -16
- package/src/Components/PageBuilder/EditorMenu/Editables/TextColorEditor.vue +9 -16
- package/src/Components/PageBuilder/EditorMenu/Editables/Typography.vue +22 -20
- package/src/Components/PageBuilder/EditorMenu/RightSidebarEditor.vue +25 -27
- package/src/Components/PageBuilder/NoneCustomMediaLibraryComponent.vue +3 -0
- package/src/Components/PageBuilder/NoneCustomSearchComponent.vue +91 -0
- package/src/Components/PageBuilder/PageBuilderSettings.vue +8 -0
- package/src/Components/PageBuilder/Settings/AdvancedPageBuilderSettings.vue +31 -72
- package/src/Components/PageBuilder/Settings/PageBuilderSettings.vue +32 -36
- package/src/Components/Search/SearchComponents.vue +11 -199
- package/src/Components/TipTap/TipTap.vue +8 -7
- package/src/Components/TipTap/TipTapInput.vue +136 -134
- package/src/PageBuilder/PageBuilder.vue +220 -32
- package/src/composables/{PageBuilder.ts → PageBuilderClass.ts} +223 -142
- package/src/composables/usePageBuilderModal.ts +25 -0
- package/src/index.ts +8 -2
- package/src/stores/media-library.ts +1 -5
- package/src/stores/page-builder-state.ts +52 -36
- package/src/stores/user.ts +8 -6
- package/src/types/global.d.ts +6 -44
- package/src/types/index.ts +169 -0
- package/src/utils/html-elements/component.ts +88 -0
- package/src/utils/html-elements/componentHelpers.ts +101 -0
- package/src/Components/Modals/PageBuilderModal.vue +0 -233
- package/src/utils/builder/html-elements/componentHelpers.ts +0 -101
|
@@ -1,61 +1,33 @@
|
|
|
1
1
|
// Type definitions
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
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
|
-
|
|
83
|
-
private
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1171
|
+
async removeItemComponentsLocalStorageCreate() {
|
|
1172
|
+
console.log('removeItemComponentsLocalStorageCreate')
|
|
1148
1173
|
if (this.showRunningMethodLogs) {
|
|
1149
|
-
console.log('
|
|
1174
|
+
console.log('removeItemComponentsLocalStorageCreate')
|
|
1150
1175
|
}
|
|
1151
1176
|
|
|
1152
1177
|
await this.nextTick
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
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
|
-
|
|
1166
|
-
|
|
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
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
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
|
-
|
|
1208
|
+
if (savedCurrentDesign) {
|
|
1209
|
+
let components = JSON.parse(savedCurrentDesign)
|
|
1186
1210
|
|
|
1187
|
-
|
|
1188
|
-
|
|
1211
|
+
// Ensure components is always an array
|
|
1212
|
+
components = Array.isArray(components) ? components : []
|
|
1189
1213
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
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
|
-
|
|
1221
|
+
this.pageBuilderStateStore.setComponents(components)
|
|
1199
1222
|
|
|
1200
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1223
|
-
|
|
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
|
-
|
|
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
|
|
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
|
+
}
|