@myissue/vue-website-page-builder 3.3.89 → 3.3.91
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 +5 -5
- package/dist/style.css +1 -1
- package/dist/vue-website-page-builder.js +932 -608
- package/dist/vue-website-page-builder.umd.cjs +24 -24
- package/package.json +1 -1
- package/src/Components/TipTap/TipTap.vue +1 -1
- package/src/PageBuilder/PageBuilder.vue +9 -15
- package/src/composables/builderInstance.ts +30 -5
- package/src/services/PageBuilderService.ts +399 -77
|
@@ -136,20 +136,36 @@ export class PageBuilderService {
|
|
|
136
136
|
]
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Returns an array of available languages.
|
|
141
|
+
* @returns {AvailableLanguage[]} An array of available language codes.
|
|
142
|
+
*/
|
|
139
143
|
public availableLanguage(): AvailableLanguage[] {
|
|
140
144
|
return AVAILABLE_LANGUAGES
|
|
141
145
|
}
|
|
142
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Sets the current language in the page builder state.
|
|
149
|
+
* @param {string} lang - The language code to set.
|
|
150
|
+
*/
|
|
143
151
|
public changeLanguage(lang: string) {
|
|
144
152
|
this.pageBuilderStateStore.setCurrentLanguage(lang)
|
|
145
153
|
}
|
|
146
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Deselects any selected or hovered elements in the builder UI.
|
|
156
|
+
* @returns {Promise<void>}
|
|
157
|
+
*/
|
|
147
158
|
async clearHtmlSelection(): Promise<void> {
|
|
148
159
|
this.pageBuilderStateStore.setComponent(null)
|
|
149
160
|
this.pageBuilderStateStore.setElement(null)
|
|
150
161
|
await this.removeHoveredAndSelected()
|
|
151
162
|
}
|
|
152
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Ensures that the `updateOrCreate` configuration is valid and sets default values if necessary.
|
|
166
|
+
* @param {PageBuilderConfig} config - The page builder configuration.
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
153
169
|
private ensureUpdateOrCreateConfig(config: PageBuilderConfig): void {
|
|
154
170
|
// Case A: updateOrCreate is missing or an empty object
|
|
155
171
|
if (!config.updateOrCreate || (config.updateOrCreate && isEmptyObject(config.updateOrCreate))) {
|
|
@@ -226,6 +242,12 @@ export class PageBuilderService {
|
|
|
226
242
|
}
|
|
227
243
|
}
|
|
228
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Validates the user-provided components array.
|
|
247
|
+
* @param {unknown} components - The components data to validate.
|
|
248
|
+
* @returns {{error: true, warning: string, status: string} | {error: true, reason: string} | undefined} An error object if validation fails, otherwise undefined.
|
|
249
|
+
* @private
|
|
250
|
+
*/
|
|
229
251
|
private validateUserProvidedComponents(components: unknown) {
|
|
230
252
|
const formType =
|
|
231
253
|
this.pageBuilderStateStore.getPageBuilderConfig &&
|
|
@@ -278,6 +300,11 @@ export class PageBuilderService {
|
|
|
278
300
|
return
|
|
279
301
|
}
|
|
280
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Ensures that the language configuration is valid and sets default values if necessary.
|
|
305
|
+
* @param {PageBuilderConfig} config - The page builder configuration.
|
|
306
|
+
* @private
|
|
307
|
+
*/
|
|
281
308
|
private ensureLanguage(config: PageBuilderConfig): void {
|
|
282
309
|
// Set default language config if missing, empty, or language missing/empty
|
|
283
310
|
const defaultLang = 'en'
|
|
@@ -327,6 +354,11 @@ export class PageBuilderService {
|
|
|
327
354
|
}
|
|
328
355
|
}
|
|
329
356
|
|
|
357
|
+
/**
|
|
358
|
+
* Validates the entire page builder configuration.
|
|
359
|
+
* @param {PageBuilderConfig} config - The page builder configuration.
|
|
360
|
+
* @private
|
|
361
|
+
*/
|
|
330
362
|
private validateConfig(config: PageBuilderConfig): void {
|
|
331
363
|
const defaultConfigValues = {
|
|
332
364
|
updateOrCreate: {
|
|
@@ -347,6 +379,10 @@ export class PageBuilderService {
|
|
|
347
379
|
this.ensureLanguage(config)
|
|
348
380
|
}
|
|
349
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Saves user settings to local storage.
|
|
384
|
+
* @param {string} newLang - The new language to save.
|
|
385
|
+
*/
|
|
350
386
|
public saveUserSettingsStorage(newLang: string) {
|
|
351
387
|
localStorage.setItem(
|
|
352
388
|
'userSettingsPageBuilder',
|
|
@@ -355,14 +391,10 @@ export class PageBuilderService {
|
|
|
355
391
|
}
|
|
356
392
|
|
|
357
393
|
/**
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
* -
|
|
361
|
-
*
|
|
362
|
-
* - Updates the localStorage key name based on the config/resource.
|
|
363
|
-
* - Completes builder initialization if the DOM is ready.
|
|
364
|
-
*
|
|
365
|
-
* @param config - The configuration object for the Page Builder.
|
|
394
|
+
* Initializes the Page Builder.
|
|
395
|
+
* @param {PageBuilderConfig} config - The configuration object for the Page Builder.
|
|
396
|
+
* @param {BuilderResourceData} [passedComponentsArray] - Optional array of components to load.
|
|
397
|
+
* @returns {Promise<StartBuilderResult>} A result object indicating success or failure.
|
|
366
398
|
*/
|
|
367
399
|
async startBuilder(
|
|
368
400
|
config: PageBuilderConfig,
|
|
@@ -425,6 +457,11 @@ export class PageBuilderService {
|
|
|
425
457
|
}
|
|
426
458
|
}
|
|
427
459
|
|
|
460
|
+
/**
|
|
461
|
+
* Completes the builder initialization process once the DOM is ready.
|
|
462
|
+
* @param {BuilderResourceData} [passedComponentsArray] - Optional array of components to load.
|
|
463
|
+
* @returns {Promise<void>}
|
|
464
|
+
*/
|
|
428
465
|
async completeBuilderInitialization(passedComponentsArray?: BuilderResourceData): Promise<void> {
|
|
429
466
|
this.pageBuilderStateStore.setIsLoadingGlobal(true)
|
|
430
467
|
await delay(400)
|
|
@@ -504,6 +541,12 @@ export class PageBuilderService {
|
|
|
504
541
|
//
|
|
505
542
|
}
|
|
506
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Completes the mounting process by loading components into the DOM and setting up listeners.
|
|
546
|
+
* @param {string} html - The HTML string of components to mount.
|
|
547
|
+
* @param {boolean} [usePassedPageSettings] - Whether to use page settings from the passed data.
|
|
548
|
+
* @private
|
|
549
|
+
*/
|
|
507
550
|
private async completeMountProcess(html: string, usePassedPageSettings?: boolean) {
|
|
508
551
|
await this.mountComponentsToDOM(html, usePassedPageSettings)
|
|
509
552
|
|
|
@@ -519,6 +562,14 @@ export class PageBuilderService {
|
|
|
519
562
|
await this.addListenersToEditableElements()
|
|
520
563
|
}
|
|
521
564
|
|
|
565
|
+
/**
|
|
566
|
+
* Applies CSS class changes to the currently selected element.
|
|
567
|
+
* @param {string | undefined} cssUserSelection - The user's CSS class selection.
|
|
568
|
+
* @param {string[]} CSSArray - The array of possible CSS classes for this property.
|
|
569
|
+
* @param {string} mutationName - The name of the store mutation to call.
|
|
570
|
+
* @returns {string | undefined} The previously applied CSS class.
|
|
571
|
+
* @private
|
|
572
|
+
*/
|
|
522
573
|
private applyElementClassChanges(
|
|
523
574
|
cssUserSelection: string | undefined,
|
|
524
575
|
CSSArray: string[],
|
|
@@ -591,6 +642,10 @@ export class PageBuilderService {
|
|
|
591
642
|
return currentCSS
|
|
592
643
|
}
|
|
593
644
|
|
|
645
|
+
/**
|
|
646
|
+
* Removes all CSS classes from the main page builder container.
|
|
647
|
+
* @returns {Promise<void>}
|
|
648
|
+
*/
|
|
594
649
|
public async clearClassesFromPage() {
|
|
595
650
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
596
651
|
if (!pagebuilder) return
|
|
@@ -600,6 +655,10 @@ export class PageBuilderService {
|
|
|
600
655
|
this.initializeElementStyles()
|
|
601
656
|
await nextTick()
|
|
602
657
|
}
|
|
658
|
+
/**
|
|
659
|
+
* Removes all inline styles from the main page builder container.
|
|
660
|
+
* @returns {Promise<void>}
|
|
661
|
+
*/
|
|
603
662
|
public async clearInlineStylesFromPagee() {
|
|
604
663
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
605
664
|
if (!pagebuilder) return
|
|
@@ -610,6 +669,10 @@ export class PageBuilderService {
|
|
|
610
669
|
await nextTick()
|
|
611
670
|
}
|
|
612
671
|
|
|
672
|
+
/**
|
|
673
|
+
* Selects the main page builder container for global styling.
|
|
674
|
+
* @returns {Promise<void>}
|
|
675
|
+
*/
|
|
613
676
|
public async globalPageStyles() {
|
|
614
677
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
615
678
|
if (!pagebuilder) return
|
|
@@ -626,6 +689,10 @@ export class PageBuilderService {
|
|
|
626
689
|
await nextTick()
|
|
627
690
|
}
|
|
628
691
|
|
|
692
|
+
/**
|
|
693
|
+
* Handles changes to the font weight of the selected element.
|
|
694
|
+
* @param {string} [userSelectedFontWeight] - The selected font weight class.
|
|
695
|
+
*/
|
|
629
696
|
public handleFontWeight(userSelectedFontWeight?: string): void {
|
|
630
697
|
this.applyElementClassChanges(
|
|
631
698
|
userSelectedFontWeight,
|
|
@@ -634,10 +701,18 @@ export class PageBuilderService {
|
|
|
634
701
|
)
|
|
635
702
|
}
|
|
636
703
|
|
|
704
|
+
/**
|
|
705
|
+
* Handles changes to the base font size of the selected element.
|
|
706
|
+
* @param {string} [userSelectedFontSize] - The selected font size class.
|
|
707
|
+
*/
|
|
637
708
|
public handleFontSizeBase(userSelectedFontSize?: string): void {
|
|
638
709
|
this.applyElementClassChanges(userSelectedFontSize, tailwindFontSizes.fontBase, 'setFontBase')
|
|
639
710
|
}
|
|
640
711
|
|
|
712
|
+
/**
|
|
713
|
+
* Handles changes to the desktop font size of the selected element.
|
|
714
|
+
* @param {string} [userSelectedFontSize] - The selected font size class for desktop.
|
|
715
|
+
*/
|
|
641
716
|
public handleFontSizeDesktop(userSelectedFontSize?: string): void {
|
|
642
717
|
const currentHTMLElement = this.getElement.value
|
|
643
718
|
if (!currentHTMLElement) return
|
|
@@ -693,6 +768,11 @@ export class PageBuilderService {
|
|
|
693
768
|
}
|
|
694
769
|
}
|
|
695
770
|
|
|
771
|
+
/**
|
|
772
|
+
* Applies helper CSS classes to elements, such as wrapping them or adding responsive text classes.
|
|
773
|
+
* @param {HTMLElement} element - The element to process.
|
|
774
|
+
* @private
|
|
775
|
+
*/
|
|
696
776
|
private applyHelperCSSToElements(element: HTMLElement): void {
|
|
697
777
|
this.wrapElementInDivIfExcluded(element)
|
|
698
778
|
|
|
@@ -720,6 +800,11 @@ export class PageBuilderService {
|
|
|
720
800
|
}
|
|
721
801
|
}
|
|
722
802
|
|
|
803
|
+
/**
|
|
804
|
+
* Toggles the visibility of the TipTap modal for rich text editing.
|
|
805
|
+
* @param {boolean} status - Whether to show or hide the modal.
|
|
806
|
+
* @returns {Promise<void>}
|
|
807
|
+
*/
|
|
723
808
|
public async toggleTipTapModal(status: boolean): Promise<void> {
|
|
724
809
|
this.pageBuilderStateStore.setShowModalTipTap(status)
|
|
725
810
|
|
|
@@ -733,6 +818,11 @@ export class PageBuilderService {
|
|
|
733
818
|
}
|
|
734
819
|
}
|
|
735
820
|
|
|
821
|
+
/**
|
|
822
|
+
* Wraps an element in a div if it's an excluded tag and adjacent to an image.
|
|
823
|
+
* @param {HTMLElement} element - The element to potentially wrap.
|
|
824
|
+
* @private
|
|
825
|
+
*/
|
|
736
826
|
private wrapElementInDivIfExcluded(element: HTMLElement): void {
|
|
737
827
|
if (!element) return
|
|
738
828
|
|
|
@@ -747,6 +837,12 @@ export class PageBuilderService {
|
|
|
747
837
|
}
|
|
748
838
|
}
|
|
749
839
|
|
|
840
|
+
/**
|
|
841
|
+
* Handles the mouseover event for editable elements, showing a hover state.
|
|
842
|
+
* @param {Event} e - The mouse event.
|
|
843
|
+
* @param {HTMLElement} element - The element being hovered over.
|
|
844
|
+
* @private
|
|
845
|
+
*/
|
|
750
846
|
private handleMouseOver = (e: Event, element: HTMLElement): void => {
|
|
751
847
|
e.preventDefault()
|
|
752
848
|
e.stopPropagation()
|
|
@@ -765,6 +861,11 @@ export class PageBuilderService {
|
|
|
765
861
|
}
|
|
766
862
|
}
|
|
767
863
|
|
|
864
|
+
/**
|
|
865
|
+
* Handles the mouseleave event for editable elements, removing the hover state.
|
|
866
|
+
* @param {Event} e - The mouse event.
|
|
867
|
+
* @private
|
|
868
|
+
*/
|
|
768
869
|
private handleMouseLeave = (e: Event): void => {
|
|
769
870
|
e.preventDefault()
|
|
770
871
|
e.stopPropagation()
|
|
@@ -778,27 +879,32 @@ export class PageBuilderService {
|
|
|
778
879
|
}
|
|
779
880
|
}
|
|
780
881
|
|
|
882
|
+
/**
|
|
883
|
+
* Checks if an element is editable based on its tag name.
|
|
884
|
+
* @param {Element | null} el - The element to check.
|
|
885
|
+
* @returns {boolean} True if the element is editable, false otherwise.
|
|
886
|
+
*/
|
|
781
887
|
public isEditableElement(el: Element | null): boolean {
|
|
782
888
|
if (!el) return false
|
|
783
889
|
return !this.NoneListernesTags.includes(el.tagName)
|
|
784
890
|
}
|
|
785
891
|
|
|
786
892
|
/**
|
|
787
|
-
*
|
|
788
|
-
*
|
|
893
|
+
* Attaches click, mouseover, and mouseleave event listeners to all editable elements in the page builder.
|
|
894
|
+
* @private
|
|
789
895
|
*/
|
|
790
896
|
private addListenersToEditableElements = async () => {
|
|
791
897
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
792
898
|
if (!pagebuilder) return
|
|
793
899
|
|
|
794
|
-
// Wait for
|
|
900
|
+
// Wait for the next DOM update cycle to ensure all elements are rendered.
|
|
795
901
|
await nextTick()
|
|
796
902
|
|
|
797
903
|
pagebuilder.querySelectorAll('section *').forEach((element) => {
|
|
798
904
|
if (this.isEditableElement(element)) {
|
|
799
905
|
const htmlElement = element as HTMLElement
|
|
800
906
|
|
|
801
|
-
//
|
|
907
|
+
// If the element already has listeners, remove them to avoid duplicates.
|
|
802
908
|
if (this.elementsWithListeners.has(htmlElement)) {
|
|
803
909
|
const listeners = this.elementsWithListeners.get(htmlElement)
|
|
804
910
|
if (listeners) {
|
|
@@ -808,17 +914,17 @@ export class PageBuilderService {
|
|
|
808
914
|
}
|
|
809
915
|
}
|
|
810
916
|
|
|
811
|
-
// Define new
|
|
917
|
+
// Define new listener functions.
|
|
812
918
|
const clickListener = (e: Event) => this.handleElementClick(e, htmlElement)
|
|
813
919
|
const mouseoverListener = (e: Event) => this.handleMouseOver(e, htmlElement)
|
|
814
920
|
const mouseleaveListener = (e: Event) => this.handleMouseLeave(e)
|
|
815
921
|
|
|
816
|
-
//
|
|
922
|
+
// Add the new event listeners.
|
|
817
923
|
htmlElement.addEventListener('click', clickListener)
|
|
818
924
|
htmlElement.addEventListener('mouseover', mouseoverListener)
|
|
819
925
|
htmlElement.addEventListener('mouseleave', mouseleaveListener)
|
|
820
926
|
|
|
821
|
-
// Store the new listeners in the WeakMap
|
|
927
|
+
// Store the new listeners in the WeakMap to track them.
|
|
822
928
|
this.elementsWithListeners.set(htmlElement, {
|
|
823
929
|
click: clickListener,
|
|
824
930
|
mouseover: mouseoverListener,
|
|
@@ -828,6 +934,12 @@ export class PageBuilderService {
|
|
|
828
934
|
})
|
|
829
935
|
}
|
|
830
936
|
|
|
937
|
+
/**
|
|
938
|
+
* Handles the click event for editable elements, setting the element as selected.
|
|
939
|
+
* @param {Event} e - The click event.
|
|
940
|
+
* @param {HTMLElement} element - The clicked element.
|
|
941
|
+
* @private
|
|
942
|
+
*/
|
|
831
943
|
private handleElementClick = async (e: Event, element: HTMLElement): Promise<void> => {
|
|
832
944
|
e.preventDefault()
|
|
833
945
|
e.stopPropagation()
|
|
@@ -852,6 +964,9 @@ export class PageBuilderService {
|
|
|
852
964
|
await this.handleAutoSave()
|
|
853
965
|
}
|
|
854
966
|
|
|
967
|
+
/**
|
|
968
|
+
* Triggers an auto-save of the current page builder content to local storage if enabled.
|
|
969
|
+
*/
|
|
855
970
|
public handleAutoSave = async () => {
|
|
856
971
|
this.startEditing()
|
|
857
972
|
const passedConfig = this.pageBuilderStateStore.getPageBuilderConfig
|
|
@@ -892,16 +1007,23 @@ export class PageBuilderService {
|
|
|
892
1007
|
}
|
|
893
1008
|
}
|
|
894
1009
|
|
|
1010
|
+
/**
|
|
1011
|
+
* Manually saves the current page builder content to local storage.
|
|
1012
|
+
*/
|
|
895
1013
|
public handleManualSave = async () => {
|
|
896
|
-
this.startEditing()
|
|
897
1014
|
this.pageBuilderStateStore.setIsSaving(true)
|
|
898
|
-
this.
|
|
1015
|
+
this.clearHtmlSelection()
|
|
1016
|
+
this.startEditing()
|
|
899
1017
|
this.saveDomComponentsToLocalStorage()
|
|
900
1018
|
await delay(300)
|
|
901
1019
|
this.pageBuilderStateStore.setIsSaving(false)
|
|
902
|
-
this.pageBuilderStateStore.setIsLoadingGlobal(false)
|
|
903
1020
|
}
|
|
904
1021
|
|
|
1022
|
+
/**
|
|
1023
|
+
* Clones a component object and prepares it for insertion into the DOM by adding unique IDs and prefixes.
|
|
1024
|
+
* @param {ComponentObject} componentObject - The component object to clone.
|
|
1025
|
+
* @returns {ComponentObject} The cloned and prepared component object.
|
|
1026
|
+
*/
|
|
905
1027
|
public cloneCompObjForDOMInsertion(componentObject: ComponentObject): ComponentObject {
|
|
906
1028
|
// Deep clone clone component
|
|
907
1029
|
const clonedComponent = { ...componentObject }
|
|
@@ -962,6 +1084,10 @@ export class PageBuilderService {
|
|
|
962
1084
|
return clonedComponent
|
|
963
1085
|
}
|
|
964
1086
|
|
|
1087
|
+
/**
|
|
1088
|
+
* Removes the 'hovered' and 'selected' attributes from all elements in the page builder.
|
|
1089
|
+
* @private
|
|
1090
|
+
*/
|
|
965
1091
|
private async removeHoveredAndSelected() {
|
|
966
1092
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
967
1093
|
if (!pagebuilder) return
|
|
@@ -978,6 +1104,10 @@ export class PageBuilderService {
|
|
|
978
1104
|
}
|
|
979
1105
|
}
|
|
980
1106
|
|
|
1107
|
+
/**
|
|
1108
|
+
* Syncs the CSS classes of the currently selected element to the state store.
|
|
1109
|
+
* @private
|
|
1110
|
+
*/
|
|
981
1111
|
private async syncCurrentClasses() {
|
|
982
1112
|
// convert classList to array
|
|
983
1113
|
const classListArray = Array.from(this.getElement.value?.classList || [])
|
|
@@ -986,6 +1116,10 @@ export class PageBuilderService {
|
|
|
986
1116
|
this.pageBuilderStateStore.setCurrentClasses(classListArray)
|
|
987
1117
|
}
|
|
988
1118
|
|
|
1119
|
+
/**
|
|
1120
|
+
* Syncs the inline styles of the currently selected element to the state store.
|
|
1121
|
+
* @private
|
|
1122
|
+
*/
|
|
989
1123
|
private async syncCurrentStyles() {
|
|
990
1124
|
const style = this.getElement.value?.getAttribute('style')
|
|
991
1125
|
if (style) {
|
|
@@ -996,6 +1130,10 @@ export class PageBuilderService {
|
|
|
996
1130
|
}
|
|
997
1131
|
}
|
|
998
1132
|
|
|
1133
|
+
/**
|
|
1134
|
+
* Adds a CSS class to the currently selected element.
|
|
1135
|
+
* @param {string} userSelectedClass - The class to add.
|
|
1136
|
+
*/
|
|
999
1137
|
public handleAddClasses(userSelectedClass: string): void {
|
|
1000
1138
|
if (
|
|
1001
1139
|
typeof userSelectedClass === 'string' &&
|
|
@@ -1016,6 +1154,11 @@ export class PageBuilderService {
|
|
|
1016
1154
|
}
|
|
1017
1155
|
}
|
|
1018
1156
|
|
|
1157
|
+
/**
|
|
1158
|
+
* Adds or updates an inline style property on the currently selected element.
|
|
1159
|
+
* @param {string} property - The CSS property to add/update.
|
|
1160
|
+
* @param {string} value - The value of the CSS property.
|
|
1161
|
+
*/
|
|
1019
1162
|
public handleAddStyle(property: string, value: string): void {
|
|
1020
1163
|
const element = this.getElement.value
|
|
1021
1164
|
if (!element || !property || !value) return
|
|
@@ -1024,6 +1167,10 @@ export class PageBuilderService {
|
|
|
1024
1167
|
this.pageBuilderStateStore.setElement(element)
|
|
1025
1168
|
}
|
|
1026
1169
|
|
|
1170
|
+
/**
|
|
1171
|
+
* Removes an inline style property from the currently selected element.
|
|
1172
|
+
* @param {string} property - The CSS property to remove.
|
|
1173
|
+
*/
|
|
1027
1174
|
public handleRemoveStyle(property: string): void {
|
|
1028
1175
|
const element = this.getElement.value
|
|
1029
1176
|
if (!element || !property) return
|
|
@@ -1032,6 +1179,10 @@ export class PageBuilderService {
|
|
|
1032
1179
|
this.pageBuilderStateStore.setElement(element)
|
|
1033
1180
|
}
|
|
1034
1181
|
|
|
1182
|
+
/**
|
|
1183
|
+
* Handles changes to the font family of the selected element.
|
|
1184
|
+
* @param {string} [userSelectedFontFamily] - The selected font family class.
|
|
1185
|
+
*/
|
|
1035
1186
|
public handleFontFamily(userSelectedFontFamily?: string): void {
|
|
1036
1187
|
this.applyElementClassChanges(
|
|
1037
1188
|
userSelectedFontFamily,
|
|
@@ -1039,6 +1190,10 @@ export class PageBuilderService {
|
|
|
1039
1190
|
'setFontFamily',
|
|
1040
1191
|
)
|
|
1041
1192
|
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Handles changes to the font style of the selected element.
|
|
1195
|
+
* @param {string} [userSelectedFontStyle] - The selected font style class.
|
|
1196
|
+
*/
|
|
1042
1197
|
public handleFontStyle(userSelectedFontStyle?: string): void {
|
|
1043
1198
|
this.applyElementClassChanges(
|
|
1044
1199
|
userSelectedFontStyle,
|
|
@@ -1046,6 +1201,10 @@ export class PageBuilderService {
|
|
|
1046
1201
|
'setFontStyle',
|
|
1047
1202
|
)
|
|
1048
1203
|
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Handles changes to the vertical padding of the selected element.
|
|
1206
|
+
* @param {string} [userSelectedVerticalPadding] - The selected vertical padding class.
|
|
1207
|
+
*/
|
|
1049
1208
|
public handleVerticalPadding(userSelectedVerticalPadding?: string): void {
|
|
1050
1209
|
this.applyElementClassChanges(
|
|
1051
1210
|
userSelectedVerticalPadding,
|
|
@@ -1053,6 +1212,10 @@ export class PageBuilderService {
|
|
|
1053
1212
|
'setFontVerticalPadding',
|
|
1054
1213
|
)
|
|
1055
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Handles changes to the horizontal padding of the selected element.
|
|
1217
|
+
* @param {string} [userSelectedHorizontalPadding] - The selected horizontal padding class.
|
|
1218
|
+
*/
|
|
1056
1219
|
public handleHorizontalPadding(userSelectedHorizontalPadding?: string): void {
|
|
1057
1220
|
this.applyElementClassChanges(
|
|
1058
1221
|
userSelectedHorizontalPadding,
|
|
@@ -1061,6 +1224,10 @@ export class PageBuilderService {
|
|
|
1061
1224
|
)
|
|
1062
1225
|
}
|
|
1063
1226
|
|
|
1227
|
+
/**
|
|
1228
|
+
* Handles changes to the vertical margin of the selected element.
|
|
1229
|
+
* @param {string} [userSelectedVerticalMargin] - The selected vertical margin class.
|
|
1230
|
+
*/
|
|
1064
1231
|
public handleVerticalMargin(userSelectedVerticalMargin?: string): void {
|
|
1065
1232
|
this.applyElementClassChanges(
|
|
1066
1233
|
userSelectedVerticalMargin,
|
|
@@ -1068,6 +1235,10 @@ export class PageBuilderService {
|
|
|
1068
1235
|
'setFontVerticalMargin',
|
|
1069
1236
|
)
|
|
1070
1237
|
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Handles changes to the horizontal margin of the selected element.
|
|
1240
|
+
* @param {string} [userSelectedHorizontalMargin] - The selected horizontal margin class.
|
|
1241
|
+
*/
|
|
1071
1242
|
public handleHorizontalMargin(userSelectedHorizontalMargin?: string): void {
|
|
1072
1243
|
this.applyElementClassChanges(
|
|
1073
1244
|
userSelectedHorizontalMargin,
|
|
@@ -1076,6 +1247,10 @@ export class PageBuilderService {
|
|
|
1076
1247
|
)
|
|
1077
1248
|
}
|
|
1078
1249
|
|
|
1250
|
+
/**
|
|
1251
|
+
* Handles changes to the border style of the selected element.
|
|
1252
|
+
* @param {string} [borderStyle] - The selected border style class.
|
|
1253
|
+
*/
|
|
1079
1254
|
public handleBorderStyle(borderStyle?: string): void {
|
|
1080
1255
|
this.applyElementClassChanges(
|
|
1081
1256
|
borderStyle,
|
|
@@ -1083,6 +1258,10 @@ export class PageBuilderService {
|
|
|
1083
1258
|
'setBorderStyle',
|
|
1084
1259
|
)
|
|
1085
1260
|
}
|
|
1261
|
+
/**
|
|
1262
|
+
* Handles changes to the border width of the selected element.
|
|
1263
|
+
* @param {string} [borderWidth] - The selected border width class.
|
|
1264
|
+
*/
|
|
1086
1265
|
public handleBorderWidth(borderWidth?: string): void {
|
|
1087
1266
|
this.applyElementClassChanges(
|
|
1088
1267
|
borderWidth,
|
|
@@ -1090,6 +1269,10 @@ export class PageBuilderService {
|
|
|
1090
1269
|
'setBorderWidth',
|
|
1091
1270
|
)
|
|
1092
1271
|
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Handles changes to the border color of the selected element.
|
|
1274
|
+
* @param {string} [borderColor] - The selected border color class.
|
|
1275
|
+
*/
|
|
1093
1276
|
public handleBorderColor(borderColor?: string): void {
|
|
1094
1277
|
this.applyElementClassChanges(
|
|
1095
1278
|
borderColor,
|
|
@@ -1099,6 +1282,10 @@ export class PageBuilderService {
|
|
|
1099
1282
|
}
|
|
1100
1283
|
// border color, style & width / end
|
|
1101
1284
|
|
|
1285
|
+
/**
|
|
1286
|
+
* Handles changes to the background color of the selected element.
|
|
1287
|
+
* @param {string} [color] - The selected background color class.
|
|
1288
|
+
*/
|
|
1102
1289
|
public handleBackgroundColor(color?: string): void {
|
|
1103
1290
|
this.applyElementClassChanges(
|
|
1104
1291
|
color,
|
|
@@ -1107,10 +1294,18 @@ export class PageBuilderService {
|
|
|
1107
1294
|
)
|
|
1108
1295
|
}
|
|
1109
1296
|
|
|
1297
|
+
/**
|
|
1298
|
+
* Handles changes to the text color of the selected element.
|
|
1299
|
+
* @param {string} [color] - The selected text color class.
|
|
1300
|
+
*/
|
|
1110
1301
|
public handleTextColor(color?: string): void {
|
|
1111
1302
|
this.applyElementClassChanges(color, tailwindColors.textColorVariables, 'setTextColor')
|
|
1112
1303
|
}
|
|
1113
1304
|
|
|
1305
|
+
/**
|
|
1306
|
+
* Handles changes to the global border radius of the selected element.
|
|
1307
|
+
* @param {string} [borderRadiusGlobal] - The selected global border radius class.
|
|
1308
|
+
*/
|
|
1114
1309
|
handleBorderRadiusGlobal(borderRadiusGlobal?: string): void {
|
|
1115
1310
|
this.applyElementClassChanges(
|
|
1116
1311
|
borderRadiusGlobal,
|
|
@@ -1118,6 +1313,10 @@ export class PageBuilderService {
|
|
|
1118
1313
|
'setBorderRadiusGlobal',
|
|
1119
1314
|
)
|
|
1120
1315
|
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Handles changes to the top-left border radius of the selected element.
|
|
1318
|
+
* @param {string} [borderRadiusTopLeft] - The selected top-left border radius class.
|
|
1319
|
+
*/
|
|
1121
1320
|
handleBorderRadiusTopLeft(borderRadiusTopLeft?: string): void {
|
|
1122
1321
|
this.applyElementClassChanges(
|
|
1123
1322
|
borderRadiusTopLeft,
|
|
@@ -1125,6 +1324,10 @@ export class PageBuilderService {
|
|
|
1125
1324
|
'setBorderRadiusTopLeft',
|
|
1126
1325
|
)
|
|
1127
1326
|
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Handles changes to the top-right border radius of the selected element.
|
|
1329
|
+
* @param {string} [borderRadiusTopRight] - The selected top-right border radius class.
|
|
1330
|
+
*/
|
|
1128
1331
|
handleBorderRadiusTopRight(borderRadiusTopRight?: string): void {
|
|
1129
1332
|
this.applyElementClassChanges(
|
|
1130
1333
|
borderRadiusTopRight,
|
|
@@ -1132,6 +1335,10 @@ export class PageBuilderService {
|
|
|
1132
1335
|
'setBorderRadiusTopRight',
|
|
1133
1336
|
)
|
|
1134
1337
|
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Handles changes to the bottom-left border radius of the selected element.
|
|
1340
|
+
* @param {string} [borderRadiusBottomleft] - The selected bottom-left border radius class.
|
|
1341
|
+
*/
|
|
1135
1342
|
handleBorderRadiusBottomleft(borderRadiusBottomleft?: string): void {
|
|
1136
1343
|
this.applyElementClassChanges(
|
|
1137
1344
|
borderRadiusBottomleft,
|
|
@@ -1139,6 +1346,10 @@ export class PageBuilderService {
|
|
|
1139
1346
|
'setBorderRadiusBottomleft',
|
|
1140
1347
|
)
|
|
1141
1348
|
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Handles changes to the bottom-right border radius of the selected element.
|
|
1351
|
+
* @param {string} [borderRadiusBottomRight] - The selected bottom-right border radius class.
|
|
1352
|
+
*/
|
|
1142
1353
|
handleBorderRadiusBottomRight(borderRadiusBottomRight?: string): void {
|
|
1143
1354
|
this.applyElementClassChanges(
|
|
1144
1355
|
borderRadiusBottomRight,
|
|
@@ -1148,6 +1359,10 @@ export class PageBuilderService {
|
|
|
1148
1359
|
}
|
|
1149
1360
|
// border radius / end
|
|
1150
1361
|
|
|
1362
|
+
/**
|
|
1363
|
+
* Handles changes to the tablet font size of the selected element.
|
|
1364
|
+
* @param {string} [userSelectedFontSize] - The selected font size class for tablet.
|
|
1365
|
+
*/
|
|
1151
1366
|
handleFontSizeTablet(userSelectedFontSize?: string): void {
|
|
1152
1367
|
this.applyElementClassChanges(
|
|
1153
1368
|
userSelectedFontSize,
|
|
@@ -1155,6 +1370,10 @@ export class PageBuilderService {
|
|
|
1155
1370
|
'setFontTablet',
|
|
1156
1371
|
)
|
|
1157
1372
|
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Handles changes to the mobile font size of the selected element.
|
|
1375
|
+
* @param {string} [userSelectedFontSize] - The selected font size class for mobile.
|
|
1376
|
+
*/
|
|
1158
1377
|
handleFontSizeMobile(userSelectedFontSize?: string): void {
|
|
1159
1378
|
this.applyElementClassChanges(
|
|
1160
1379
|
userSelectedFontSize,
|
|
@@ -1163,6 +1382,10 @@ export class PageBuilderService {
|
|
|
1163
1382
|
)
|
|
1164
1383
|
}
|
|
1165
1384
|
|
|
1385
|
+
/**
|
|
1386
|
+
* Handles changes to the background opacity of the selected element.
|
|
1387
|
+
* @param {string} [opacity] - The selected background opacity class.
|
|
1388
|
+
*/
|
|
1166
1389
|
handleBackgroundOpacity(opacity?: string): void {
|
|
1167
1390
|
this.applyElementClassChanges(
|
|
1168
1391
|
opacity,
|
|
@@ -1170,20 +1393,18 @@ export class PageBuilderService {
|
|
|
1170
1393
|
'setBackgroundOpacity',
|
|
1171
1394
|
)
|
|
1172
1395
|
}
|
|
1396
|
+
/**
|
|
1397
|
+
* Handles changes to the opacity of the selected element.
|
|
1398
|
+
* @param {string} [opacity] - The selected opacity class.
|
|
1399
|
+
*/
|
|
1173
1400
|
handleOpacity(opacity?: string): void {
|
|
1174
1401
|
this.applyElementClassChanges(opacity, tailwindOpacities.opacities, 'setOpacity')
|
|
1175
1402
|
}
|
|
1176
1403
|
|
|
1177
1404
|
/**
|
|
1178
1405
|
* Removes all components from both the builder state and the DOM.
|
|
1179
|
-
*
|
|
1180
|
-
* - First clears the components array in the store.
|
|
1181
|
-
* - Then, as a defensive measure, also manually removes all sections elements from the DOM.
|
|
1182
|
-
*
|
|
1183
|
-
* This manual DOM clearing is only optional
|
|
1184
|
-
*
|
|
1406
|
+
* @private
|
|
1185
1407
|
*/
|
|
1186
|
-
|
|
1187
1408
|
private deleteAllComponentsFromDOM() {
|
|
1188
1409
|
// Clear the store
|
|
1189
1410
|
this.pageBuilderStateStore.setComponents([])
|
|
@@ -1198,6 +1419,10 @@ export class PageBuilderService {
|
|
|
1198
1419
|
}
|
|
1199
1420
|
}
|
|
1200
1421
|
|
|
1422
|
+
/**
|
|
1423
|
+
* Deletes the currently selected component from the DOM and the state.
|
|
1424
|
+
* @returns {Promise<void>}
|
|
1425
|
+
*/
|
|
1201
1426
|
public async deleteComponentFromDOM() {
|
|
1202
1427
|
this.syncDomToStoreOnly()
|
|
1203
1428
|
await nextTick()
|
|
@@ -1206,17 +1431,17 @@ export class PageBuilderService {
|
|
|
1206
1431
|
|
|
1207
1432
|
if (!components) return
|
|
1208
1433
|
|
|
1209
|
-
// Find the index of the component to
|
|
1434
|
+
// Find the index of the component to be deleted.
|
|
1210
1435
|
const indexToDelete = components.findIndex(
|
|
1211
1436
|
(component) => component.id === this.getComponent.value?.id,
|
|
1212
1437
|
)
|
|
1213
1438
|
|
|
1214
1439
|
if (indexToDelete === -1) {
|
|
1215
|
-
//
|
|
1440
|
+
// If the component is not found, do nothing.
|
|
1216
1441
|
return
|
|
1217
1442
|
}
|
|
1218
1443
|
|
|
1219
|
-
// Create a new array
|
|
1444
|
+
// Create a new array excluding the component to be deleted.
|
|
1220
1445
|
const newComponents = [
|
|
1221
1446
|
...components.slice(0, indexToDelete),
|
|
1222
1447
|
...components.slice(indexToDelete + 1),
|
|
@@ -1224,7 +1449,7 @@ export class PageBuilderService {
|
|
|
1224
1449
|
|
|
1225
1450
|
this.pageBuilderStateStore.setComponents(newComponents)
|
|
1226
1451
|
|
|
1227
|
-
// Remove the section from the DOM
|
|
1452
|
+
// Remove the component's corresponding section from the DOM.
|
|
1228
1453
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
1229
1454
|
if (pagebuilder && this.getComponent.value?.id) {
|
|
1230
1455
|
const section = pagebuilder.querySelector(
|
|
@@ -1233,22 +1458,26 @@ export class PageBuilderService {
|
|
|
1233
1458
|
if (section) section.remove()
|
|
1234
1459
|
}
|
|
1235
1460
|
|
|
1236
|
-
// Wait for
|
|
1461
|
+
// Wait for the DOM to update before re-attaching event listeners.
|
|
1237
1462
|
await nextTick()
|
|
1238
1463
|
await this.addListenersToEditableElements()
|
|
1239
1464
|
|
|
1240
1465
|
this.pageBuilderStateStore.setComponent(null)
|
|
1241
1466
|
this.pageBuilderStateStore.setElement(null)
|
|
1242
1467
|
|
|
1243
|
-
//
|
|
1468
|
+
// Trigger an auto-save after deletion.
|
|
1244
1469
|
await this.handleAutoSave()
|
|
1245
1470
|
}
|
|
1246
1471
|
|
|
1472
|
+
/**
|
|
1473
|
+
* Deletes the currently selected element from the DOM and stores it for potential restoration.
|
|
1474
|
+
* @returns {Promise<void>}
|
|
1475
|
+
*/
|
|
1247
1476
|
public async deleteElementFromDOM() {
|
|
1248
1477
|
const element = this.getElement.value
|
|
1249
1478
|
if (!element) return
|
|
1250
1479
|
|
|
1251
|
-
// Remove 'selected' attribute before deletion
|
|
1480
|
+
// Remove the 'selected' attribute before deletion to avoid visual artifacts.
|
|
1252
1481
|
element.removeAttribute('selected')
|
|
1253
1482
|
|
|
1254
1483
|
if (!element.parentNode) {
|
|
@@ -1257,56 +1486,64 @@ export class PageBuilderService {
|
|
|
1257
1486
|
return
|
|
1258
1487
|
}
|
|
1259
1488
|
|
|
1260
|
-
// If the element is
|
|
1489
|
+
// If the element is not a top-level section, store its information for undo functionality.
|
|
1261
1490
|
if (element.parentElement?.tagName !== 'SECTION') {
|
|
1262
1491
|
this.pageBuilderStateStore.setParentElement(element.parentNode as HTMLElement)
|
|
1263
1492
|
this.pageBuilderStateStore.setRestoredElement(element.outerHTML)
|
|
1264
1493
|
this.pageBuilderStateStore.setNextSibling(element.nextSibling as HTMLElement | null)
|
|
1265
|
-
// Remove
|
|
1494
|
+
// Remove the element from the DOM.
|
|
1266
1495
|
element.remove()
|
|
1267
1496
|
}
|
|
1268
1497
|
|
|
1269
|
-
// Clear selection state
|
|
1498
|
+
// Clear the selection state.
|
|
1270
1499
|
this.pageBuilderStateStore.setComponent(null)
|
|
1271
1500
|
this.pageBuilderStateStore.setElement(null)
|
|
1272
1501
|
|
|
1273
|
-
// Deselect any selected or hovered elements in the builder UI
|
|
1502
|
+
// Deselect any selected or hovered elements in the builder UI.
|
|
1274
1503
|
await this.clearHtmlSelection()
|
|
1275
|
-
// Wait for
|
|
1504
|
+
// Wait for the DOM to update before re-attaching event listeners.
|
|
1276
1505
|
await nextTick()
|
|
1277
|
-
//
|
|
1506
|
+
// Re-attach event listeners to all editable elements.
|
|
1278
1507
|
await this.addListenersToEditableElements()
|
|
1279
1508
|
}
|
|
1280
1509
|
|
|
1510
|
+
/**
|
|
1511
|
+
* Restores the last deleted element to its previous position in the DOM.
|
|
1512
|
+
* @returns {Promise<void>}
|
|
1513
|
+
*/
|
|
1281
1514
|
public async restoreDeletedElementToDOM() {
|
|
1282
|
-
//
|
|
1515
|
+
// Retrieve the details of the element to be restored.
|
|
1283
1516
|
const restoredHTML = this.getRestoredElement.value
|
|
1284
1517
|
const parent = this.getParentElement.value
|
|
1285
1518
|
const nextSibling = this.getNextSibling.value
|
|
1286
1519
|
|
|
1287
1520
|
if (restoredHTML && parent) {
|
|
1288
|
-
// Create a container
|
|
1521
|
+
// Create a temporary container to parse the stored HTML.
|
|
1289
1522
|
const container = document.createElement('div')
|
|
1290
1523
|
container.innerHTML = restoredHTML
|
|
1291
1524
|
|
|
1292
|
-
// Insert the restored element
|
|
1525
|
+
// Insert the restored element back into its original position.
|
|
1293
1526
|
if (container.firstChild) {
|
|
1294
1527
|
parent.insertBefore(container.firstChild, nextSibling)
|
|
1295
1528
|
}
|
|
1296
1529
|
}
|
|
1297
1530
|
|
|
1298
|
-
// Clear
|
|
1531
|
+
// Clear the state related to the restored element.
|
|
1299
1532
|
this.pageBuilderStateStore.setParentElement(null)
|
|
1300
1533
|
this.pageBuilderStateStore.setRestoredElement(null)
|
|
1301
1534
|
this.pageBuilderStateStore.setNextSibling(null)
|
|
1302
1535
|
this.pageBuilderStateStore.setComponent(null)
|
|
1303
1536
|
this.pageBuilderStateStore.setElement(null)
|
|
1304
1537
|
|
|
1305
|
-
// Wait for
|
|
1538
|
+
// Wait for the DOM to update before re-attaching event listeners.
|
|
1306
1539
|
await nextTick()
|
|
1307
1540
|
await this.addListenersToEditableElements()
|
|
1308
1541
|
}
|
|
1309
1542
|
|
|
1543
|
+
/**
|
|
1544
|
+
* Removes a CSS class from the currently selected element.
|
|
1545
|
+
* @param {string} userSelectedClass - The class to remove.
|
|
1546
|
+
*/
|
|
1310
1547
|
public handleRemoveClasses(userSelectedClass: string): void {
|
|
1311
1548
|
// remove selected class from element
|
|
1312
1549
|
if (this.getElement.value?.classList.contains(userSelectedClass)) {
|
|
@@ -1317,38 +1554,43 @@ export class PageBuilderService {
|
|
|
1317
1554
|
}
|
|
1318
1555
|
}
|
|
1319
1556
|
|
|
1320
|
-
|
|
1321
|
-
|
|
1557
|
+
/**
|
|
1558
|
+
* Reorders the currently selected component up or down in the component list.
|
|
1559
|
+
* @param {number} direction - The direction to move the component (-1 for up, 1 for down).
|
|
1560
|
+
*/
|
|
1322
1561
|
public reorderComponent(direction: number): void {
|
|
1323
1562
|
if (!this.getComponents.value || !this.getComponent.value) return
|
|
1324
1563
|
|
|
1325
1564
|
if (this.getComponents.value.length <= 1) return
|
|
1326
1565
|
|
|
1327
|
-
//
|
|
1566
|
+
// Find the component to move.
|
|
1328
1567
|
const componentToMove = this.getComponent.value
|
|
1329
1568
|
|
|
1330
|
-
// Determine the
|
|
1569
|
+
// Determine the current index of the component.
|
|
1331
1570
|
const currentIndex = this.getComponents.value.findIndex(
|
|
1332
1571
|
(component) => component.id === componentToMove.id,
|
|
1333
1572
|
)
|
|
1334
1573
|
|
|
1335
1574
|
if (currentIndex === -1) {
|
|
1336
|
-
// Component not found in the array
|
|
1575
|
+
// Component not found in the array.
|
|
1337
1576
|
return
|
|
1338
1577
|
}
|
|
1339
1578
|
|
|
1340
1579
|
const newIndex = currentIndex + direction
|
|
1341
1580
|
|
|
1342
|
-
// Ensure the
|
|
1581
|
+
// Ensure the new index is within the bounds of the array.
|
|
1343
1582
|
if (newIndex < 0 || newIndex >= this.getComponents.value.length) {
|
|
1344
1583
|
return
|
|
1345
1584
|
}
|
|
1346
1585
|
|
|
1347
|
-
// Move the component to the new position
|
|
1586
|
+
// Move the component to the new position in the array.
|
|
1348
1587
|
this.getComponents.value.splice(currentIndex, 1)
|
|
1349
1588
|
this.getComponents.value.splice(newIndex, 0, componentToMove)
|
|
1350
1589
|
}
|
|
1351
1590
|
|
|
1591
|
+
/**
|
|
1592
|
+
* Ensures that a text area element has content, adding a visual indicator if it's empty.
|
|
1593
|
+
*/
|
|
1352
1594
|
public ensureTextAreaHasContent = () => {
|
|
1353
1595
|
if (!this.getElement.value) return
|
|
1354
1596
|
|
|
@@ -1373,6 +1615,11 @@ export class PageBuilderService {
|
|
|
1373
1615
|
}
|
|
1374
1616
|
}
|
|
1375
1617
|
|
|
1618
|
+
/**
|
|
1619
|
+
* Handles text input for an element, updating its content.
|
|
1620
|
+
* @param {string} textContentVueModel - The new text content from the Vue model.
|
|
1621
|
+
* @returns {Promise<void>}
|
|
1622
|
+
*/
|
|
1376
1623
|
public handleTextInput = async (textContentVueModel: string): Promise<void> => {
|
|
1377
1624
|
if (typeof this.getElement.value?.innerHTML !== 'string') {
|
|
1378
1625
|
return
|
|
@@ -1392,8 +1639,10 @@ export class PageBuilderService {
|
|
|
1392
1639
|
this.ensureTextAreaHasContent()
|
|
1393
1640
|
}
|
|
1394
1641
|
|
|
1395
|
-
|
|
1396
|
-
|
|
1642
|
+
/**
|
|
1643
|
+
* Checks if the selected element or its first child is an iframe.
|
|
1644
|
+
* @returns {boolean} True if it is an iframe, false otherwise.
|
|
1645
|
+
*/
|
|
1397
1646
|
public ElOrFirstChildIsIframe() {
|
|
1398
1647
|
if (
|
|
1399
1648
|
this.getElement.value?.tagName === 'IFRAME' ||
|
|
@@ -1404,9 +1653,10 @@ export class PageBuilderService {
|
|
|
1404
1653
|
return false
|
|
1405
1654
|
}
|
|
1406
1655
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1656
|
+
/**
|
|
1657
|
+
* Checks if the selected element is a valid text container (i.e., does not contain images or divs).
|
|
1658
|
+
* @returns {boolean | undefined} True if it's a valid text element, otherwise undefined.
|
|
1659
|
+
*/
|
|
1410
1660
|
public isSelectedElementValidText() {
|
|
1411
1661
|
let reachedElseStatement = false
|
|
1412
1662
|
|
|
@@ -1433,6 +1683,9 @@ export class PageBuilderService {
|
|
|
1433
1683
|
return reachedElseStatement
|
|
1434
1684
|
}
|
|
1435
1685
|
|
|
1686
|
+
/**
|
|
1687
|
+
* Generates a preview of the current page design.
|
|
1688
|
+
*/
|
|
1436
1689
|
public previewCurrentDesign() {
|
|
1437
1690
|
this.pageBuilderStateStore.setElement(null)
|
|
1438
1691
|
|
|
@@ -1454,7 +1707,11 @@ export class PageBuilderService {
|
|
|
1454
1707
|
this.pageBuilderStateStore.setCurrentLayoutPreview(previewData)
|
|
1455
1708
|
}
|
|
1456
1709
|
}
|
|
1457
|
-
|
|
1710
|
+
/**
|
|
1711
|
+
* Sanitizes a string to be used as a key in local storage.
|
|
1712
|
+
* @param {string} input - The string to sanitize.
|
|
1713
|
+
* @returns {string} The sanitized string.
|
|
1714
|
+
*/
|
|
1458
1715
|
public sanitizeForLocalStorage(input: string): string {
|
|
1459
1716
|
return input
|
|
1460
1717
|
.trim() // Remove leading/trailing spaces
|
|
@@ -1466,9 +1723,10 @@ export class PageBuilderService {
|
|
|
1466
1723
|
}
|
|
1467
1724
|
|
|
1468
1725
|
/**
|
|
1469
|
-
*
|
|
1470
|
-
*
|
|
1471
|
-
* @
|
|
1726
|
+
* Clones an element and removes selection-related attributes from the clone.
|
|
1727
|
+
* @param {HTMLElement} element - The element to clone.
|
|
1728
|
+
* @returns {HTMLElement} The sanitized clone.
|
|
1729
|
+
* @private
|
|
1472
1730
|
*/
|
|
1473
1731
|
private cloneAndRemoveSelectionAttributes(element: HTMLElement): HTMLElement {
|
|
1474
1732
|
// Deep clone the element
|
|
@@ -1485,8 +1743,8 @@ export class PageBuilderService {
|
|
|
1485
1743
|
}
|
|
1486
1744
|
|
|
1487
1745
|
/**
|
|
1488
|
-
* Syncs the current DOM state
|
|
1489
|
-
*
|
|
1746
|
+
* Syncs the current DOM state of components to the in-memory store.
|
|
1747
|
+
* @private
|
|
1490
1748
|
*/
|
|
1491
1749
|
private syncDomToStoreOnly() {
|
|
1492
1750
|
const pagebuilder = document.querySelector('#pagebuilder')
|
|
@@ -1507,7 +1765,8 @@ export class PageBuilderService {
|
|
|
1507
1765
|
}
|
|
1508
1766
|
|
|
1509
1767
|
/**
|
|
1510
|
-
* Saves the current DOM state
|
|
1768
|
+
* Saves the current DOM state of components to local storage.
|
|
1769
|
+
* @private
|
|
1511
1770
|
*/
|
|
1512
1771
|
private saveDomComponentsToLocalStorage() {
|
|
1513
1772
|
this.updateLocalStorageItemName()
|
|
@@ -1547,6 +1806,10 @@ export class PageBuilderService {
|
|
|
1547
1806
|
localStorage.setItem(keyForSavingFromDomToLocal, JSON.stringify(dataToSave))
|
|
1548
1807
|
}
|
|
1549
1808
|
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Removes the current page's components from local storage.
|
|
1811
|
+
* @private
|
|
1812
|
+
*/
|
|
1550
1813
|
private async removeCurrentComponentsFromLocalStorage() {
|
|
1551
1814
|
this.updateLocalStorageItemName()
|
|
1552
1815
|
await nextTick()
|
|
@@ -1557,12 +1820,22 @@ export class PageBuilderService {
|
|
|
1557
1820
|
}
|
|
1558
1821
|
}
|
|
1559
1822
|
|
|
1823
|
+
/**
|
|
1824
|
+
* Handles the form submission process, clearing local storage and the DOM.
|
|
1825
|
+
* @returns {Promise<void>}
|
|
1826
|
+
*/
|
|
1560
1827
|
public async handleFormSubmission() {
|
|
1561
1828
|
await this.removeCurrentComponentsFromLocalStorage()
|
|
1562
1829
|
this.deleteAllComponentsFromDOM()
|
|
1563
1830
|
this.pageBuilderStateStore.setComponents([])
|
|
1564
1831
|
}
|
|
1565
1832
|
|
|
1833
|
+
/**
|
|
1834
|
+
* Parses a CSS style string into a key-value object.
|
|
1835
|
+
* @param {string} style - The style string to parse.
|
|
1836
|
+
* @returns {Record<string, string>} The parsed style object.
|
|
1837
|
+
* @private
|
|
1838
|
+
*/
|
|
1566
1839
|
private parseStyleString(style: string): Record<string, string> {
|
|
1567
1840
|
return style
|
|
1568
1841
|
.split(';')
|
|
@@ -1578,6 +1851,9 @@ export class PageBuilderService {
|
|
|
1578
1851
|
)
|
|
1579
1852
|
}
|
|
1580
1853
|
|
|
1854
|
+
/**
|
|
1855
|
+
* Deletes old page builder data from local storage (older than 2 weeks).
|
|
1856
|
+
*/
|
|
1581
1857
|
deleteOldPageBuilderLocalStorage(): void {
|
|
1582
1858
|
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
1583
1859
|
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
@@ -1630,12 +1906,17 @@ export class PageBuilderService {
|
|
|
1630
1906
|
}
|
|
1631
1907
|
}
|
|
1632
1908
|
|
|
1633
|
-
|
|
1909
|
+
/**
|
|
1910
|
+
* Sets a flag to indicate that the user has started editing.
|
|
1911
|
+
*/
|
|
1634
1912
|
public startEditing() {
|
|
1635
1913
|
this.hasStartedEditing = true
|
|
1636
1914
|
}
|
|
1637
1915
|
|
|
1638
|
-
|
|
1916
|
+
/**
|
|
1917
|
+
* Resumes editing from a draft saved in local storage.
|
|
1918
|
+
* @returns {Promise<void>}
|
|
1919
|
+
*/
|
|
1639
1920
|
public async resumeEditingFromDraft() {
|
|
1640
1921
|
this.updateLocalStorageItemName()
|
|
1641
1922
|
|
|
@@ -1656,6 +1937,10 @@ export class PageBuilderService {
|
|
|
1656
1937
|
this.pageBuilderStateStore.setIsLoadingResumeEditing(false)
|
|
1657
1938
|
}
|
|
1658
1939
|
|
|
1940
|
+
/**
|
|
1941
|
+
* Restores the original content that was loaded when the builder started.
|
|
1942
|
+
* @returns {Promise<void>}
|
|
1943
|
+
*/
|
|
1659
1944
|
public async restoreOriginalContent() {
|
|
1660
1945
|
this.updateLocalStorageItemName()
|
|
1661
1946
|
|
|
@@ -1678,10 +1963,18 @@ export class PageBuilderService {
|
|
|
1678
1963
|
this.pageBuilderStateStore.setIsRestoring(false)
|
|
1679
1964
|
}
|
|
1680
1965
|
|
|
1966
|
+
/**
|
|
1967
|
+
* Gets the local storage key for the current resource.
|
|
1968
|
+
* @returns {string | null} The local storage key.
|
|
1969
|
+
*/
|
|
1681
1970
|
public getStorageItemNameForResource(): string | null {
|
|
1682
1971
|
return this.getLocalStorageItemName.value
|
|
1683
1972
|
}
|
|
1684
1973
|
|
|
1974
|
+
/**
|
|
1975
|
+
* Retrieves the saved page HTML from local storage.
|
|
1976
|
+
* @returns {string | false} The HTML string or false if not found.
|
|
1977
|
+
*/
|
|
1685
1978
|
public getSavedPageHtml() {
|
|
1686
1979
|
if (!this.getLocalStorageItemName.value) return false
|
|
1687
1980
|
|
|
@@ -1705,9 +1998,9 @@ export class PageBuilderService {
|
|
|
1705
1998
|
}
|
|
1706
1999
|
|
|
1707
2000
|
/**
|
|
1708
|
-
* Applies
|
|
1709
|
-
*
|
|
1710
|
-
*
|
|
2001
|
+
* Applies a selected image to the current element.
|
|
2002
|
+
* @param {ImageObject} image - The image object to apply.
|
|
2003
|
+
* @returns {Promise<void>}
|
|
1711
2004
|
*/
|
|
1712
2005
|
public async applySelectedImage(image: ImageObject): Promise<void> {
|
|
1713
2006
|
this.pageBuilderStateStore.setApplyImageToSelection(image)
|
|
@@ -1724,9 +2017,8 @@ export class PageBuilderService {
|
|
|
1724
2017
|
}
|
|
1725
2018
|
|
|
1726
2019
|
/**
|
|
1727
|
-
*
|
|
1728
|
-
*
|
|
1729
|
-
* If the element does not meet these criteria, clears the base primary image.
|
|
2020
|
+
* Sets the base primary image from the currently selected element if it's an image.
|
|
2021
|
+
* @private
|
|
1730
2022
|
*/
|
|
1731
2023
|
private setBasePrimaryImageFromSelectedElement() {
|
|
1732
2024
|
if (!this.getElement.value) return
|
|
@@ -1748,6 +2040,13 @@ export class PageBuilderService {
|
|
|
1748
2040
|
this.pageBuilderStateStore.setBasePrimaryImage(null)
|
|
1749
2041
|
}
|
|
1750
2042
|
|
|
2043
|
+
/**
|
|
2044
|
+
* Adds or removes a hyperlink from the selected element.
|
|
2045
|
+
* @param {boolean} hyperlinkEnable - Whether to enable or disable the hyperlink.
|
|
2046
|
+
* @param {string | null} urlInput - The URL for the hyperlink.
|
|
2047
|
+
* @param {boolean} openHyperlinkInNewTab - Whether the link should open in a new tab.
|
|
2048
|
+
* @private
|
|
2049
|
+
*/
|
|
1751
2050
|
private addHyperlinkToElement(
|
|
1752
2051
|
hyperlinkEnable: boolean,
|
|
1753
2052
|
urlInput: string | null,
|
|
@@ -1844,6 +2143,10 @@ export class PageBuilderService {
|
|
|
1844
2143
|
}
|
|
1845
2144
|
}
|
|
1846
2145
|
|
|
2146
|
+
/**
|
|
2147
|
+
* Checks if the selected element contains a hyperlink and updates the state accordingly.
|
|
2148
|
+
* @private
|
|
2149
|
+
*/
|
|
1847
2150
|
private checkForHyperlink() {
|
|
1848
2151
|
if (!this.getElement.value) return
|
|
1849
2152
|
|
|
@@ -1872,6 +2175,12 @@ export class PageBuilderService {
|
|
|
1872
2175
|
this.pageBuilderStateStore.setHyberlinkEnable(false)
|
|
1873
2176
|
}
|
|
1874
2177
|
|
|
2178
|
+
/**
|
|
2179
|
+
* Handles all hyperlink-related actions for the selected element.
|
|
2180
|
+
* @param {boolean} [hyperlinkEnable] - Whether to enable or disable the hyperlink.
|
|
2181
|
+
* @param {string | null} [urlInput] - The URL for the hyperlink.
|
|
2182
|
+
* @param {boolean} [openHyperlinkInNewTab] - Whether the link should open in a new tab.
|
|
2183
|
+
*/
|
|
1875
2184
|
public handleHyperlink(
|
|
1876
2185
|
hyperlinkEnable?: boolean,
|
|
1877
2186
|
urlInput?: string | null,
|
|
@@ -1917,7 +2226,11 @@ export class PageBuilderService {
|
|
|
1917
2226
|
this.addHyperlinkToElement(hyperlinkEnable, urlInput || null, openHyperlinkInNewTab || false)
|
|
1918
2227
|
}
|
|
1919
2228
|
|
|
1920
|
-
|
|
2229
|
+
/**
|
|
2230
|
+
* Adds a new component to the page builder.
|
|
2231
|
+
* @param {ComponentObject} componentObject - The component to add.
|
|
2232
|
+
* @returns {Promise<void>}
|
|
2233
|
+
*/
|
|
1921
2234
|
public async addComponent(componentObject: ComponentObject): Promise<void> {
|
|
1922
2235
|
try {
|
|
1923
2236
|
const clonedComponent = this.cloneCompObjForDOMInsertion({
|
|
@@ -1957,10 +2270,12 @@ export class PageBuilderService {
|
|
|
1957
2270
|
}
|
|
1958
2271
|
|
|
1959
2272
|
/**
|
|
1960
|
-
*
|
|
1961
|
-
*
|
|
2273
|
+
* Adds a prefix to Tailwind CSS classes in a string.
|
|
2274
|
+
* @param {string} classList - The string of classes.
|
|
2275
|
+
* @param {string} [prefix='pbx-'] - The prefix to add.
|
|
2276
|
+
* @returns {string} The prefixed class string.
|
|
2277
|
+
* @private
|
|
1962
2278
|
*/
|
|
1963
|
-
|
|
1964
2279
|
private addTailwindPrefixToClasses(classList: string, prefix = 'pbx-'): string {
|
|
1965
2280
|
return classList
|
|
1966
2281
|
.split(/\s+/)
|
|
@@ -1975,6 +2290,12 @@ export class PageBuilderService {
|
|
|
1975
2290
|
.join(' ')
|
|
1976
2291
|
}
|
|
1977
2292
|
|
|
2293
|
+
/**
|
|
2294
|
+
* Converts a style object to a CSS string.
|
|
2295
|
+
* @param {string | Record<string, string> | null | undefined} styleObj - The style object.
|
|
2296
|
+
* @returns {string} The CSS style string.
|
|
2297
|
+
* @private
|
|
2298
|
+
*/
|
|
1978
2299
|
private convertStyleObjectToString(
|
|
1979
2300
|
styleObj: string | Record<string, string> | null | undefined,
|
|
1980
2301
|
): string {
|
|
@@ -1991,8 +2312,6 @@ export class PageBuilderService {
|
|
|
1991
2312
|
|
|
1992
2313
|
/**
|
|
1993
2314
|
* Parses a string of HTML and extracts builder components and global page settings.
|
|
1994
|
-
*
|
|
1995
|
-
* ⚠️ **Important:**
|
|
1996
2315
|
* - This method expects an **HTML string** containing one or more `<section>...</section>` elements (such as the output from `getSavedPageHtml()` or a previously saved builder HTML string).
|
|
1997
2316
|
* - **Do NOT pass a JSON string** (such as the result of `JSON.stringify(componentsArray)`) to this method. Passing a JSON string to `DOMParser.parseFromString(..., 'text/html')` will not produce valid DOM nodes. Instead, it will treat the JSON as plain text, resulting in a `<html><head></head><body>{...json...}</body></html>` structure, not real HTML elements.
|
|
1998
2317
|
* - If you pass a JSON string, you will see lots of `\n` and strange HTML, because the parser is just wrapping your JSON in a `<body>` tag as text.
|
|
@@ -2473,6 +2792,9 @@ export class PageBuilderService {
|
|
|
2473
2792
|
}
|
|
2474
2793
|
}
|
|
2475
2794
|
|
|
2795
|
+
/**
|
|
2796
|
+
* Initializes the styles for the currently selected element.
|
|
2797
|
+
*/
|
|
2476
2798
|
public async initializeElementStyles(): Promise<void> {
|
|
2477
2799
|
// Wait for Vue to finish DOM updates before attaching event listeners.
|
|
2478
2800
|
// This ensures elements exist in the DOM.
|