@myissue/vue-website-page-builder 3.2.92 → 3.2.94
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 +1 -1
- package/dist/vue-website-page-builder.js +3787 -3766
- package/dist/vue-website-page-builder.umd.cjs +36 -36
- package/package.json +1 -1
- package/src/DemoComponents/DemoUnsplash.vue +8 -8
- package/src/DemoComponents/HomeSection.vue +6 -1
- package/src/PageBuilder/PageBuilder.vue +7 -2
- package/src/composables/PageBuilderService.ts +122 -54
- package/src/composables/builderInstance.ts +1 -1
- package/src/stores/page-builder-state.ts +7 -8
- package/src/types/index.ts +1 -1
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@ const getIsLoadingImage = ref(false)
|
|
|
17
17
|
const getSearchTerm = ref('')
|
|
18
18
|
const getCurrentPageNumber = ref(1)
|
|
19
19
|
const getOrientationValue = ref('')
|
|
20
|
-
const
|
|
20
|
+
const getApplyImageToSelection = ref('')
|
|
21
21
|
const getCurrentUser = ref('')
|
|
22
22
|
|
|
23
23
|
const getUnsplashImages = ref([])
|
|
@@ -72,7 +72,7 @@ const handleImageClick = async function (data) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
await delay(100)
|
|
75
|
-
|
|
75
|
+
getApplyImageToSelection.value = data.url || ''
|
|
76
76
|
|
|
77
77
|
getIsLoadingImage.value = false
|
|
78
78
|
}
|
|
@@ -100,11 +100,11 @@ const nextPage = async function () {
|
|
|
100
100
|
|
|
101
101
|
const applySelectedImage = async function (imageURL) {
|
|
102
102
|
// Ensure the current image is set in the store with proper structure
|
|
103
|
-
|
|
103
|
+
pageBuilderService.stageImageForSelectedElement({
|
|
104
104
|
src: `${imageURL}`,
|
|
105
105
|
})
|
|
106
106
|
|
|
107
|
-
await pageBuilderService.
|
|
107
|
+
await pageBuilderService.applyPendingImageToSelectedElement()
|
|
108
108
|
|
|
109
109
|
closeMediaLibraryModal()
|
|
110
110
|
}
|
|
@@ -341,10 +341,10 @@ onMounted(async () => {
|
|
|
341
341
|
</div>
|
|
342
342
|
</div>
|
|
343
343
|
</template>
|
|
344
|
-
<template v-if="
|
|
344
|
+
<template v-if="getApplyImageToSelection && !getIsLoadingImage">
|
|
345
345
|
<img
|
|
346
346
|
class="pbx-mx-auto pbx-block pbx-w-full pbx-object-cover pbx-object-center pbx-cursor-pointer"
|
|
347
|
-
:src="`${
|
|
347
|
+
:src="`${getApplyImageToSelection}`"
|
|
348
348
|
alt="file"
|
|
349
349
|
/>
|
|
350
350
|
<div class="md:pbx-px-3 pbx-px-2">
|
|
@@ -392,8 +392,8 @@ onMounted(async () => {
|
|
|
392
392
|
Close
|
|
393
393
|
</button>
|
|
394
394
|
<button
|
|
395
|
-
v-if="
|
|
396
|
-
@click="applySelectedImage(
|
|
395
|
+
v-if="getApplyImageToSelection && typeof getApplyImageToSelection === 'string'"
|
|
396
|
+
@click="applySelectedImage(getApplyImageToSelection)"
|
|
397
397
|
class="pbx-myPrimaryButton"
|
|
398
398
|
type="button"
|
|
399
399
|
>
|
|
@@ -83,7 +83,12 @@ const configPageBuilder = {
|
|
|
83
83
|
|
|
84
84
|
onMounted(async () => {
|
|
85
85
|
await pageBuilderService.startBuilder(configPageBuilder)
|
|
86
|
-
|
|
86
|
+
//
|
|
87
|
+
//
|
|
88
|
+
//
|
|
89
|
+
// await pageBuilderService.mountComponentsToDOM(JSON.stringify(html))
|
|
90
|
+
// await pageBuilderService.mountComponentsToDOM(JSON.stringify(oldhtmlfromdb))
|
|
91
|
+
await pageBuilderService.mountComponentsToDOM(rawHTML)
|
|
87
92
|
})
|
|
88
93
|
</script>
|
|
89
94
|
|
|
@@ -263,12 +263,17 @@ const ensureBuilderInitialized = function () {
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
onMounted(async () => {
|
|
266
|
+
// Try to mount any pending data if #pagebuilder is now present
|
|
267
|
+
if (pageBuilderService.statuspendingMountData()) {
|
|
268
|
+
await pageBuilderService.tryMountPendingData()
|
|
269
|
+
}
|
|
270
|
+
|
|
266
271
|
// Check if Builder started
|
|
267
|
-
await delay(
|
|
272
|
+
await delay(6000)
|
|
268
273
|
ensureBuilderInitialized()
|
|
269
274
|
|
|
270
275
|
// Re-check if Builder started
|
|
271
|
-
await delay(
|
|
276
|
+
await delay(6000)
|
|
272
277
|
ensureBuilderInitialized()
|
|
273
278
|
})
|
|
274
279
|
</script>
|
|
@@ -24,7 +24,7 @@ export class PageBuilderService {
|
|
|
24
24
|
private pageBuilderStateStore: ReturnType<typeof usePageBuilderStateStore>
|
|
25
25
|
private getTextAreaVueModel: ComputedRef<string | null>
|
|
26
26
|
private getLocalStorageItemName: ComputedRef<string | null>
|
|
27
|
-
private
|
|
27
|
+
private getApplyImageToSelection: ComputedRef<ImageObject>
|
|
28
28
|
private getHyberlinkEnable: ComputedRef<boolean>
|
|
29
29
|
private getComponents: ComputedRef<ComponentObject[] | null>
|
|
30
30
|
private getComponent: ComputedRef<ComponentObject | null>
|
|
@@ -36,7 +36,10 @@ export class PageBuilderService {
|
|
|
36
36
|
private NoneListernesTags: string[]
|
|
37
37
|
private delay: (ms?: number) => Promise<void>
|
|
38
38
|
private hasStartedEditing: boolean = false
|
|
39
|
+
// Hold data from Database or Backend for updated post
|
|
39
40
|
private originalComponents: string | null = null
|
|
41
|
+
// Holds data to be mounted when #pagebuilder is not yet present in the DOM
|
|
42
|
+
private pendingMountData: string | null = null
|
|
40
43
|
|
|
41
44
|
constructor(pageBuilderStateStore: ReturnType<typeof usePageBuilderStateStore>) {
|
|
42
45
|
this.nextTick = nextTick()
|
|
@@ -49,7 +52,9 @@ export class PageBuilderService {
|
|
|
49
52
|
() => this.pageBuilderStateStore.getLocalStorageItemName,
|
|
50
53
|
)
|
|
51
54
|
|
|
52
|
-
this.
|
|
55
|
+
this.getApplyImageToSelection = computed(
|
|
56
|
+
() => this.pageBuilderStateStore.getApplyImageToSelection,
|
|
57
|
+
)
|
|
53
58
|
this.getHyberlinkEnable = computed(() => this.pageBuilderStateStore.getHyberlinkEnable)
|
|
54
59
|
this.getComponents = computed(() => this.pageBuilderStateStore.getComponents)
|
|
55
60
|
|
|
@@ -88,7 +93,7 @@ export class PageBuilderService {
|
|
|
88
93
|
this.delay = delay
|
|
89
94
|
}
|
|
90
95
|
|
|
91
|
-
//
|
|
96
|
+
// Deselect any selected or hovered elements in the builder UI
|
|
92
97
|
async clearHtmlSelection(): Promise<void> {
|
|
93
98
|
this.pageBuilderStateStore.setComponent(null)
|
|
94
99
|
this.pageBuilderStateStore.setElement(null)
|
|
@@ -217,11 +222,12 @@ export class PageBuilderService {
|
|
|
217
222
|
// Clean up any old localStorage items related to previous builder sessions
|
|
218
223
|
this.deleteOldPageBuilderLocalStorage()
|
|
219
224
|
|
|
220
|
-
//
|
|
225
|
+
// Deselect any selected or hovered elements in the builder UI
|
|
221
226
|
await this.clearHtmlSelection()
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
227
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
228
|
+
await nextTick()
|
|
229
|
+
// Attach event listeners to all editable elements in the Builder
|
|
230
|
+
await this.#addListenersToEditableElements()
|
|
225
231
|
|
|
226
232
|
// Hide the global loading indicator and mark the builder as started
|
|
227
233
|
this.pageBuilderStateStore.setIsLoadingGlobal(false)
|
|
@@ -364,16 +370,14 @@ export class PageBuilderService {
|
|
|
364
370
|
* The function is used to
|
|
365
371
|
* attach event listeners to each element within a 'section'
|
|
366
372
|
*/
|
|
367
|
-
addListenersToEditableElements = async () => {
|
|
373
|
+
#addListenersToEditableElements = async () => {
|
|
368
374
|
const elementsWithListeners = new WeakSet<Element>()
|
|
369
375
|
|
|
370
376
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
371
|
-
|
|
372
377
|
if (!pagebuilder) return
|
|
373
378
|
|
|
374
|
-
// Wait for
|
|
379
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
375
380
|
await nextTick()
|
|
376
|
-
await new Promise((resolve) => requestAnimationFrame(resolve))
|
|
377
381
|
|
|
378
382
|
pagebuilder.querySelectorAll('section *').forEach((element) => {
|
|
379
383
|
// exclude NoneListernesTags && additional Tags for not listening
|
|
@@ -536,10 +540,7 @@ export class PageBuilderService {
|
|
|
536
540
|
}
|
|
537
541
|
|
|
538
542
|
async #removeHoveredAndSelected() {
|
|
539
|
-
await new Promise((resolve) => requestAnimationFrame(resolve))
|
|
540
|
-
|
|
541
543
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
542
|
-
|
|
543
544
|
if (!pagebuilder) return
|
|
544
545
|
|
|
545
546
|
const hoveredElement = pagebuilder.querySelector('[hovered]')
|
|
@@ -555,8 +556,6 @@ export class PageBuilderService {
|
|
|
555
556
|
}
|
|
556
557
|
|
|
557
558
|
async #syncCurrentClasses() {
|
|
558
|
-
await new Promise((resolve) => requestAnimationFrame(resolve))
|
|
559
|
-
|
|
560
559
|
// convert classList to array
|
|
561
560
|
const classListArray = Array.from(this.getElement.value?.classList || [])
|
|
562
561
|
|
|
@@ -651,7 +650,10 @@ export class PageBuilderService {
|
|
|
651
650
|
this.pageBuilderStateStore.setComponent(null)
|
|
652
651
|
this.pageBuilderStateStore.setElement(null)
|
|
653
652
|
|
|
654
|
-
|
|
653
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
654
|
+
await nextTick()
|
|
655
|
+
// Attach event listeners to all editable elements in the Builder
|
|
656
|
+
await this.#addListenersToEditableElements()
|
|
655
657
|
}
|
|
656
658
|
|
|
657
659
|
handleFontWeight(userSelectedFontWeight?: string): void {
|
|
@@ -834,8 +836,11 @@ export class PageBuilderService {
|
|
|
834
836
|
// Remove the component from the array
|
|
835
837
|
this.getComponents.value.splice(indexToDelete, 1)
|
|
836
838
|
this.pageBuilderStateStore.setComponents(this.getComponents.value)
|
|
839
|
+
|
|
840
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
837
841
|
await nextTick()
|
|
838
|
-
|
|
842
|
+
// Attach event listeners to all editable elements in the Builder
|
|
843
|
+
await this.#addListenersToEditableElements()
|
|
839
844
|
|
|
840
845
|
this.pageBuilderStateStore.setComponent(null)
|
|
841
846
|
this.pageBuilderStateStore.setElement(null)
|
|
@@ -961,7 +966,6 @@ export class PageBuilderService {
|
|
|
961
966
|
this.pageBuilderStateStore.setElement(null)
|
|
962
967
|
|
|
963
968
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
964
|
-
|
|
965
969
|
if (!pagebuilder) return
|
|
966
970
|
|
|
967
971
|
const addedHtmlComponents = ref<string[]>([])
|
|
@@ -1339,8 +1343,10 @@ export class PageBuilderService {
|
|
|
1339
1343
|
this.mountComponentsToDOM(this.originalComponents)
|
|
1340
1344
|
}
|
|
1341
1345
|
|
|
1346
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
1342
1347
|
await nextTick()
|
|
1343
|
-
|
|
1348
|
+
// Attach event listeners to all editable elements in the Builder
|
|
1349
|
+
await this.#addListenersToEditableElements()
|
|
1344
1350
|
|
|
1345
1351
|
this.pageBuilderStateStore.setIsRestoring(false)
|
|
1346
1352
|
}
|
|
@@ -1366,39 +1372,56 @@ export class PageBuilderService {
|
|
|
1366
1372
|
|
|
1367
1373
|
return false
|
|
1368
1374
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1375
|
+
|
|
1376
|
+
/**
|
|
1377
|
+
* Sets the image selected from the media library as the "pending" image
|
|
1378
|
+
* to be applied to the currently selected element in the builder.
|
|
1379
|
+
* This does not update the DOM immediately—call `applyPendingImageToSelectedElement` to commit.
|
|
1380
|
+
* @param image - The image object to be staged for application
|
|
1381
|
+
*/
|
|
1382
|
+
stageImageForSelectedElement(image: ImageObject) {
|
|
1383
|
+
this.pageBuilderStateStore.setApplyImageToSelection(image)
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
/**
|
|
1387
|
+
* Applies the staged image (set by `stageImageForSelectedElement`) to the currently selected element.
|
|
1388
|
+
* This updates the builder state and triggers an auto-save.
|
|
1389
|
+
* If no element is selected or no image is staged, nothing happens.
|
|
1390
|
+
*/
|
|
1391
|
+
async applyPendingImageToSelectedElement(): Promise<void> {
|
|
1372
1392
|
if (!this.getElement.value) return
|
|
1373
1393
|
|
|
1374
|
-
//
|
|
1375
|
-
if (this.
|
|
1394
|
+
// Only apply if an image is staged
|
|
1395
|
+
if (this.getApplyImageToSelection.value && this.getApplyImageToSelection.value.src) {
|
|
1376
1396
|
await this.nextTick
|
|
1377
|
-
this.pageBuilderStateStore.setBasePrimaryImage(`${this.
|
|
1397
|
+
this.pageBuilderStateStore.setBasePrimaryImage(`${this.getApplyImageToSelection.value.src}`)
|
|
1398
|
+
|
|
1378
1399
|
await this.handleAutoSave()
|
|
1379
1400
|
}
|
|
1380
1401
|
}
|
|
1381
1402
|
|
|
1382
|
-
|
|
1403
|
+
/**
|
|
1404
|
+
* Inspects the currently selected element and, if it contains exactly one <img> and no <div>,
|
|
1405
|
+
* sets that image's src as the base primary image in the builder state.
|
|
1406
|
+
* If the element does not meet these criteria, clears the base primary image.
|
|
1407
|
+
*/
|
|
1408
|
+
setBasePrimaryImageFromSelectedElement() {
|
|
1383
1409
|
if (!this.getElement.value) return
|
|
1384
1410
|
|
|
1385
1411
|
const currentImageContainer = document.createElement('div')
|
|
1386
|
-
|
|
1387
1412
|
currentImageContainer.innerHTML = this.getElement.value.outerHTML
|
|
1388
1413
|
|
|
1389
1414
|
// Get all img and div within the current image container
|
|
1390
1415
|
const imgElements = currentImageContainer.getElementsByTagName('img')
|
|
1391
1416
|
const divElements = currentImageContainer.getElementsByTagName('div')
|
|
1392
1417
|
|
|
1393
|
-
//
|
|
1418
|
+
// If exactly one img and no div, set as base primary image
|
|
1394
1419
|
if (imgElements.length === 1 && divElements.length === 0) {
|
|
1395
|
-
// Return the source of the only img
|
|
1396
|
-
|
|
1397
1420
|
this.pageBuilderStateStore.setBasePrimaryImage(imgElements[0].src)
|
|
1398
|
-
|
|
1399
1421
|
return
|
|
1400
1422
|
}
|
|
1401
1423
|
|
|
1424
|
+
// Otherwise, clear the base primary image
|
|
1402
1425
|
this.pageBuilderStateStore.setBasePrimaryImage(null)
|
|
1403
1426
|
}
|
|
1404
1427
|
|
|
@@ -1585,9 +1608,11 @@ export class PageBuilderService {
|
|
|
1585
1608
|
componentArrayAddMethod: this.getComponentArrayAddMethod.value || 'push',
|
|
1586
1609
|
})
|
|
1587
1610
|
|
|
1588
|
-
// Wait for
|
|
1611
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
1589
1612
|
await nextTick()
|
|
1590
|
-
|
|
1613
|
+
// Attach event listeners to all editable elements in the Builder
|
|
1614
|
+
await this.#addListenersToEditableElements()
|
|
1615
|
+
|
|
1591
1616
|
await this.handleAutoSave()
|
|
1592
1617
|
} catch (error) {
|
|
1593
1618
|
console.error('Error adding component:', error)
|
|
@@ -1625,18 +1650,18 @@ export class PageBuilderService {
|
|
|
1625
1650
|
* @param data - JSON string (e.g., '[{"html_code":"...","id":"123","title":"..."}]')
|
|
1626
1651
|
* OR HTML string (e.g., '<section data-componentid="123">...</section>')
|
|
1627
1652
|
*/
|
|
1628
|
-
#setComponentsFromData(htmlString: string): void {
|
|
1653
|
+
async #setComponentsFromData(htmlString: string): Promise<void> {
|
|
1629
1654
|
// Auto-detect if input is JSON or HTML
|
|
1630
1655
|
const trimmedData = htmlString.trim()
|
|
1631
1656
|
|
|
1632
1657
|
if (trimmedData.startsWith('[') || trimmedData.startsWith('{')) {
|
|
1633
1658
|
// Looks like JSON - parse as JSON
|
|
1634
|
-
this.#parseJSONComponents(trimmedData)
|
|
1659
|
+
await this.#parseJSONComponents(trimmedData)
|
|
1635
1660
|
} else if (trimmedData.startsWith('<')) {
|
|
1636
1661
|
// Looks like HTML - parse as HTML
|
|
1637
|
-
this.#parseHTMLComponents(trimmedData)
|
|
1662
|
+
await this.#parseHTMLComponents(trimmedData)
|
|
1638
1663
|
} else {
|
|
1639
|
-
this.#parseJSONComponents(trimmedData)
|
|
1664
|
+
await this.#parseJSONComponents(trimmedData)
|
|
1640
1665
|
}
|
|
1641
1666
|
}
|
|
1642
1667
|
|
|
@@ -1693,15 +1718,17 @@ export class PageBuilderService {
|
|
|
1693
1718
|
|
|
1694
1719
|
this.pageBuilderStateStore.setComponents(savedCurrentDesign)
|
|
1695
1720
|
|
|
1696
|
-
|
|
1697
|
-
await
|
|
1721
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
1722
|
+
await nextTick()
|
|
1723
|
+
// Attach event listeners to all editable elements in the Builder
|
|
1724
|
+
await this.#addListenersToEditableElements()
|
|
1698
1725
|
} catch (error) {
|
|
1699
1726
|
console.error('Error parsing JSON components:', error)
|
|
1700
1727
|
this.pageBuilderStateStore.setComponents([])
|
|
1701
1728
|
}
|
|
1702
1729
|
}
|
|
1703
1730
|
// Private method to parse HTML components
|
|
1704
|
-
#parseHTMLComponents(htmlData: string): void {
|
|
1731
|
+
async #parseHTMLComponents(htmlData: string): Promise<void> {
|
|
1705
1732
|
try {
|
|
1706
1733
|
const parser = new DOMParser()
|
|
1707
1734
|
const doc = parser.parseFromString(htmlData, 'text/html')
|
|
@@ -1711,6 +1738,14 @@ export class PageBuilderService {
|
|
|
1711
1738
|
|
|
1712
1739
|
const extractedSections: ComponentObject[] = []
|
|
1713
1740
|
sectionElements.forEach((section) => {
|
|
1741
|
+
// Process all elements inside section to add prefix to classes
|
|
1742
|
+
section.querySelectorAll('[class]').forEach((el) => {
|
|
1743
|
+
el.setAttribute(
|
|
1744
|
+
'class',
|
|
1745
|
+
this.#addTailwindPrefixToClasses(el.getAttribute('class') || '', 'pbx-'),
|
|
1746
|
+
)
|
|
1747
|
+
})
|
|
1748
|
+
|
|
1714
1749
|
const htmlElement = section as HTMLElement
|
|
1715
1750
|
|
|
1716
1751
|
// Ensure data-componentid exists
|
|
@@ -1735,6 +1770,13 @@ export class PageBuilderService {
|
|
|
1735
1770
|
})
|
|
1736
1771
|
|
|
1737
1772
|
this.pageBuilderStateStore.setComponents(extractedSections)
|
|
1773
|
+
|
|
1774
|
+
// Deselect any selected or hovered elements in the builder UI
|
|
1775
|
+
await this.clearHtmlSelection()
|
|
1776
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
1777
|
+
await nextTick()
|
|
1778
|
+
// Attach event listeners to all editable elements in the Builder
|
|
1779
|
+
await this.#addListenersToEditableElements()
|
|
1738
1780
|
} catch (error) {
|
|
1739
1781
|
console.error('Error parsing HTML components:', error)
|
|
1740
1782
|
this.pageBuilderStateStore.setComponents([])
|
|
@@ -1746,9 +1788,21 @@ export class PageBuilderService {
|
|
|
1746
1788
|
* @param passedData - HTML/JSON string to inject (optional)
|
|
1747
1789
|
* @param preferLocalStorage - if true, always try localStorage first
|
|
1748
1790
|
*/
|
|
1749
|
-
mountComponentsToDOM(passedData: string): void {
|
|
1750
|
-
|
|
1751
|
-
|
|
1791
|
+
async mountComponentsToDOM(passedData: string): Promise<void> {
|
|
1792
|
+
const pagebuilder = document.querySelector('#pagebuilder')
|
|
1793
|
+
|
|
1794
|
+
// If #pagebuilder is not present, cache the data and exit
|
|
1795
|
+
if (!pagebuilder) {
|
|
1796
|
+
this.pendingMountData = passedData
|
|
1797
|
+
return
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
// Clear the cache if we are mounting now
|
|
1801
|
+
this.pendingMountData = null
|
|
1802
|
+
|
|
1803
|
+
this.pageBuilderStateStore.setComponents([])
|
|
1804
|
+
|
|
1805
|
+
// On from type update Save Original Post
|
|
1752
1806
|
if (
|
|
1753
1807
|
this.pageBuilderStateStore.getPageBuilderConfig &&
|
|
1754
1808
|
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
|
|
@@ -1760,10 +1814,6 @@ export class PageBuilderService {
|
|
|
1760
1814
|
this.originalComponents = passedData
|
|
1761
1815
|
}
|
|
1762
1816
|
|
|
1763
|
-
this.pageBuilderStateStore.setComponents([])
|
|
1764
|
-
|
|
1765
|
-
if (!this.pageBuilderStateStore.getPageBuilderConfig) return
|
|
1766
|
-
|
|
1767
1817
|
// Form type Update
|
|
1768
1818
|
if (
|
|
1769
1819
|
this.pageBuilderStateStore.getPageBuilderConfig &&
|
|
@@ -1772,7 +1822,7 @@ export class PageBuilderService {
|
|
|
1772
1822
|
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
|
|
1773
1823
|
) {
|
|
1774
1824
|
if (passedData) {
|
|
1775
|
-
this.#setComponentsFromData(passedData)
|
|
1825
|
+
await this.#setComponentsFromData(passedData)
|
|
1776
1826
|
return
|
|
1777
1827
|
}
|
|
1778
1828
|
}
|
|
@@ -1787,29 +1837,47 @@ export class PageBuilderService {
|
|
|
1787
1837
|
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'create'
|
|
1788
1838
|
) {
|
|
1789
1839
|
if (localStorageData) {
|
|
1790
|
-
this.#setComponentsFromData(localStorageData)
|
|
1840
|
+
await this.#setComponentsFromData(localStorageData)
|
|
1791
1841
|
return
|
|
1792
1842
|
}
|
|
1793
1843
|
|
|
1794
1844
|
// If no localStorage, but passedData exists (for demo), use it
|
|
1795
1845
|
if (passedData) {
|
|
1796
|
-
this.#setComponentsFromData(passedData)
|
|
1846
|
+
await this.#setComponentsFromData(passedData)
|
|
1797
1847
|
return
|
|
1798
1848
|
}
|
|
1799
1849
|
}
|
|
1800
1850
|
}
|
|
1801
1851
|
|
|
1852
|
+
statuspendingMountData(): string | null {
|
|
1853
|
+
return this.pendingMountData
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
// Try re-mounting
|
|
1857
|
+
async tryMountPendingData() {
|
|
1858
|
+
if (this.pendingMountData && document.querySelector('#pagebuilder')) {
|
|
1859
|
+
await this.mountComponentsToDOM(this.pendingMountData)
|
|
1860
|
+
this.pendingMountData = null
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1802
1864
|
async toggleTipTapModal(status: boolean): Promise<void> {
|
|
1803
1865
|
this.pageBuilderStateStore.setShowModalTipTap(status)
|
|
1804
1866
|
|
|
1867
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
1868
|
+
await nextTick()
|
|
1869
|
+
// Attach event listeners to all editable elements in the Builder
|
|
1870
|
+
await this.#addListenersToEditableElements()
|
|
1871
|
+
|
|
1805
1872
|
if (!status) {
|
|
1806
1873
|
await this.handleAutoSave()
|
|
1807
1874
|
}
|
|
1808
1875
|
}
|
|
1809
1876
|
|
|
1810
1877
|
async initializeElementStyles(): Promise<void> {
|
|
1811
|
-
|
|
1812
|
-
|
|
1878
|
+
// Wait for Vue to finish DOM updates before attaching event listeners.
|
|
1879
|
+
// This ensure elements exist in the DOM.
|
|
1880
|
+
await nextTick()
|
|
1813
1881
|
|
|
1814
1882
|
// handle custom URL
|
|
1815
1883
|
this.handleHyperlink(undefined, null, false)
|
|
@@ -1818,7 +1886,7 @@ export class PageBuilderService {
|
|
|
1818
1886
|
// handle BG opacity
|
|
1819
1887
|
this.handleBackgroundOpacity(undefined)
|
|
1820
1888
|
// displayed image
|
|
1821
|
-
this.
|
|
1889
|
+
this.setBasePrimaryImageFromSelectedElement()
|
|
1822
1890
|
// border style
|
|
1823
1891
|
this.handleBorderStyle(undefined)
|
|
1824
1892
|
// border width
|
|
@@ -18,7 +18,7 @@ export function initPageBuilder(): PageBuilderService {
|
|
|
18
18
|
export function getPageBuilder(): PageBuilderService {
|
|
19
19
|
if (!instance) {
|
|
20
20
|
throw new Error(
|
|
21
|
-
'PageBuilderService has not been created. Please call
|
|
21
|
+
'PageBuilderService has not been created. Please call initPageBuilder() first in your App.vue or setup file.',
|
|
22
22
|
)
|
|
23
23
|
}
|
|
24
24
|
return instance
|
|
@@ -56,7 +56,7 @@ interface PageBuilderState {
|
|
|
56
56
|
configPageBuilder: PageBuilderConfig | null
|
|
57
57
|
|
|
58
58
|
// Media Library State
|
|
59
|
-
|
|
59
|
+
applyImageToSelection: ImageObject
|
|
60
60
|
currentPreviewImage: string | null
|
|
61
61
|
|
|
62
62
|
// User State
|
|
@@ -117,7 +117,7 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
|
|
|
117
117
|
configPageBuilder: null,
|
|
118
118
|
|
|
119
119
|
// Media Library State
|
|
120
|
-
|
|
120
|
+
applyImageToSelection: { src: '' },
|
|
121
121
|
currentPreviewImage: null,
|
|
122
122
|
|
|
123
123
|
// User State
|
|
@@ -264,10 +264,10 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
|
|
|
264
264
|
return state.configPageBuilder
|
|
265
265
|
},
|
|
266
266
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
return state.currentImage
|
|
267
|
+
getApplyImageToSelection(state: PageBuilderState): ImageObject {
|
|
268
|
+
return state.applyImageToSelection
|
|
270
269
|
},
|
|
270
|
+
|
|
271
271
|
getCurrentPreviewImage(state: PageBuilderState): string | null {
|
|
272
272
|
return state.currentPreviewImage
|
|
273
273
|
},
|
|
@@ -455,9 +455,8 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
|
|
|
455
455
|
this.configPageBuilder = payload
|
|
456
456
|
},
|
|
457
457
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
this.currentImage = payload
|
|
458
|
+
setApplyImageToSelection(payload: ImageObject): void {
|
|
459
|
+
this.applyImageToSelection = payload
|
|
461
460
|
},
|
|
462
461
|
setCurrentPreviewImage(payload: string | null): void {
|
|
463
462
|
this.currentPreviewImage = payload
|
package/src/types/index.ts
CHANGED
|
@@ -83,7 +83,7 @@ export interface PageBuilderStateStore {
|
|
|
83
83
|
setTextColor: (color: string) => void
|
|
84
84
|
setBackgroundOpacity: (opacity: string) => void
|
|
85
85
|
setOpacity: (opacity: string) => void
|
|
86
|
-
|
|
86
|
+
getApplyImageToSelection: ImageObject | null
|
|
87
87
|
setCurrentImage: (image: ImageObject) => void
|
|
88
88
|
getCurrentPreviewImage: string | null
|
|
89
89
|
setCurrentPreviewImage: (url: string | null) => void
|