@myissue/vue-website-page-builder 3.2.90 → 3.2.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +122 -84
  2. package/dist/vue-website-page-builder.css +1 -1
  3. package/dist/vue-website-page-builder.js +5191 -5273
  4. package/dist/vue-website-page-builder.umd.cjs +52 -52
  5. package/package.json +1 -1
  6. package/src/Components/Loaders/GlobalLoader.vue +11 -0
  7. package/src/Components/Modals/DynamicModalBuilder.vue +41 -245
  8. package/src/Components/Modals/ModalBuilder.vue +29 -4
  9. package/src/Components/PageBuilder/DefaultComponents/DefaultBuilderComponents.vue +3 -8
  10. package/src/Components/PageBuilder/EditorMenu/Editables/BackgroundColorEditor.vue +5 -4
  11. package/src/Components/PageBuilder/EditorMenu/Editables/BorderRadius.vue +12 -13
  12. package/src/Components/PageBuilder/EditorMenu/Editables/Borders.vue +8 -8
  13. package/src/Components/PageBuilder/EditorMenu/Editables/ClassEditor.vue +7 -6
  14. package/src/Components/PageBuilder/EditorMenu/Editables/ComponentTopMenu.vue +6 -10
  15. package/src/Components/PageBuilder/EditorMenu/Editables/DeleteElement.vue +4 -4
  16. package/src/Components/PageBuilder/EditorMenu/Editables/EditGetElement.vue +10 -11
  17. package/src/Components/PageBuilder/EditorMenu/Editables/ElementEditor.vue +4 -5
  18. package/src/Components/PageBuilder/EditorMenu/Editables/ImageEditor.vue +0 -9
  19. package/src/Components/PageBuilder/EditorMenu/Editables/LinkEditor.vue +5 -5
  20. package/src/Components/PageBuilder/EditorMenu/Editables/ManageBackgroundOpacity.vue +4 -4
  21. package/src/Components/PageBuilder/EditorMenu/Editables/ManageOpacity.vue +4 -4
  22. package/src/Components/PageBuilder/EditorMenu/Editables/Margin.vue +8 -8
  23. package/src/Components/PageBuilder/EditorMenu/Editables/Padding.vue +8 -8
  24. package/src/Components/PageBuilder/EditorMenu/Editables/TextColorEditor.vue +4 -4
  25. package/src/Components/PageBuilder/EditorMenu/Editables/Typography.vue +16 -16
  26. package/src/Components/PageBuilder/EditorMenu/RightSidebarEditor.vue +3 -7
  27. package/src/Components/PageBuilder/Settings/PageBuilderSettings.vue +55 -58
  28. package/src/Components/PageBuilder/ToolbarOption/ToolbarOption.vue +33 -40
  29. package/src/Components/TipTap/TipTap.vue +4 -9
  30. package/src/Components/TipTap/TipTapInput.vue +8 -8
  31. package/src/DemoComponents/DemoUnsplash.vue +4 -5
  32. package/src/DemoComponents/HomeSection.vue +9 -30
  33. package/src/DemoComponents/html.json +4 -4
  34. package/src/PageBuilder/PageBuilder.vue +194 -96
  35. package/src/composables/{PageBuilderClass.ts → PageBuilderService.ts} +258 -97
  36. package/src/composables/builderInstance.ts +25 -0
  37. package/src/css/app.css +15 -0
  38. package/src/css/dev-global.css +7 -0
  39. package/src/index.ts +4 -2
  40. package/src/main.ts +3 -0
  41. package/src/stores/page-builder-state.ts +32 -2
  42. package/src/types/index.ts +99 -9
  43. package/src/helpers/passedPageBuilderConfig.ts +0 -71
@@ -14,8 +14,9 @@ import { computed, ref, nextTick } from 'vue'
14
14
  import type { ComputedRef } from 'vue'
15
15
  import { v4 as uuidv4 } from 'uuid'
16
16
  import { delay } from './delay'
17
+ import { isEmptyObject } from '../helpers/isEmptyObject'
17
18
 
18
- class PageBuilderClass {
19
+ export class PageBuilderService {
19
20
  // Class properties with types
20
21
  private nextTick: Promise<void>
21
22
  private containsPagebuilder: Element | null
@@ -35,10 +36,10 @@ class PageBuilderClass {
35
36
  private NoneListernesTags: string[]
36
37
  private delay: (ms?: number) => Promise<void>
37
38
  private hasStartedEditing: boolean = false
39
+ private originalComponents: string | null = null
38
40
 
39
41
  constructor(pageBuilderStateStore: ReturnType<typeof usePageBuilderStateStore>) {
40
42
  this.nextTick = nextTick()
41
-
42
43
  this.hasStartedEditing = false
43
44
  this.containsPagebuilder = document.querySelector('#contains-pagebuilder')
44
45
  this.pageBuilderStateStore = pageBuilderStateStore
@@ -93,9 +94,138 @@ class PageBuilderClass {
93
94
  this.pageBuilderStateStore.setElement(null)
94
95
  await this.#removeHoveredAndSelected()
95
96
  }
96
- // Load existing content from HTML when in update mode
97
- applyPageBuilderConfig(data: PageBuilderConfig): void {
98
- this.pageBuilderStateStore.applyPageBuilderConfig(data)
97
+
98
+ #ensureUpdateOrCreateConfig(config: PageBuilderConfig): void {
99
+ // Case A: updateOrCreate is missing or an empty object
100
+ if (!config.updateOrCreate || (config.updateOrCreate && isEmptyObject(config.updateOrCreate))) {
101
+ const updatedConfig = {
102
+ ...config,
103
+ updateOrCreate: {
104
+ formType: 'create',
105
+ formName: 'post',
106
+ },
107
+ } as const
108
+
109
+ this.pageBuilderStateStore.setPageBuilderConfig(updatedConfig)
110
+ return
111
+ }
112
+
113
+ // Case B: formType is valid ('create' or 'update'), but formName is missing or an empty string
114
+ if (
115
+ (config.updateOrCreate &&
116
+ typeof config.updateOrCreate.formType === 'string' &&
117
+ (config.updateOrCreate.formType === 'create' ||
118
+ config.updateOrCreate.formType === 'update') &&
119
+ typeof config.updateOrCreate.formName !== 'string') ||
120
+ (typeof config.updateOrCreate.formName === 'string' &&
121
+ config.updateOrCreate.formName.length === 0)
122
+ ) {
123
+ const updatedConfig = {
124
+ ...config,
125
+ updateOrCreate: {
126
+ formType: config.updateOrCreate.formType,
127
+ formName: 'post',
128
+ },
129
+ } as const
130
+ this.pageBuilderStateStore.setPageBuilderConfig(updatedConfig)
131
+ }
132
+
133
+ // Case C: formType is missing or not a valid string like ('create' or 'update') but formName is valid string
134
+ if (
135
+ (config.updateOrCreate && typeof config.updateOrCreate.formType !== 'string') ||
136
+ (typeof config.updateOrCreate.formType === 'string' &&
137
+ config.updateOrCreate.formType !== 'create' &&
138
+ config.updateOrCreate.formType !== 'update' &&
139
+ typeof config.updateOrCreate.formName === 'string' &&
140
+ config.updateOrCreate.formName.length !== 0)
141
+ ) {
142
+ const updatedConfig = {
143
+ ...config,
144
+ updateOrCreate: {
145
+ formType: 'create',
146
+ formName: config.updateOrCreate.formName,
147
+ },
148
+ } as const
149
+
150
+ this.pageBuilderStateStore.setPageBuilderConfig(updatedConfig)
151
+ return
152
+ }
153
+
154
+ // Case D: formType exists but is not 'create' or 'update', and formName is missing or invalid
155
+ if (
156
+ config.updateOrCreate &&
157
+ typeof config.updateOrCreate.formType === 'string' &&
158
+ config.updateOrCreate.formType !== 'create' &&
159
+ config.updateOrCreate.formType !== 'update' &&
160
+ typeof config.formName !== 'string'
161
+ ) {
162
+ const updatedConfig = {
163
+ ...config,
164
+ updateOrCreate: {
165
+ formType: 'create',
166
+ formName: 'post',
167
+ },
168
+ } as const
169
+
170
+ this.pageBuilderStateStore.setPageBuilderConfig(updatedConfig)
171
+ }
172
+ }
173
+
174
+ #validateConfig(config: PageBuilderConfig): void {
175
+ const defaultConfigValues = {
176
+ updateOrCreate: {
177
+ formType: 'create',
178
+ formName: 'post',
179
+ },
180
+ } as const
181
+
182
+ // Set config for page builder if not set by user
183
+ if (!config || (config && Object.keys(config).length === 0 && config.constructor === Object)) {
184
+ this.pageBuilderStateStore.setPageBuilderConfig(defaultConfigValues)
185
+ }
186
+
187
+ if (config && Object.keys(config).length !== 0 && config.constructor === Object) {
188
+ this.#ensureUpdateOrCreateConfig(config)
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Initializes the Page Builder with the provided configuration.
194
+ * Handles config validation, local storage, and sets up the builder state.
195
+ */
196
+ async startBuilder(config: PageBuilderConfig): Promise<void> {
197
+ // Show a global loading indicator while initializing
198
+ this.pageBuilderStateStore.setIsLoadingGlobal(true)
199
+
200
+ // Wait briefly to ensure UI updates and async processes settle
201
+ await this.delay(300)
202
+
203
+ // Store the provided config in the builder's state store
204
+ this.pageBuilderStateStore.setPageBuilderConfig(config)
205
+
206
+ // Validate and normalize the config (ensure required fields are present)
207
+ this.#validateConfig(config)
208
+
209
+ // Update the localStorage key name based on the config/resource
210
+ this.#updateLocalStorageItemName()
211
+
212
+ // If there is a local draft for this resource, mark it in the state
213
+ if (await this.#hasLocalDraftForUpdate()) {
214
+ this.pageBuilderStateStore.setHasLocalDraftForUpdate(true)
215
+ }
216
+
217
+ // Clean up any old localStorage items related to previous builder sessions
218
+ this.deleteOldPageBuilderLocalStorage()
219
+
220
+ // Clear any selected HTML elements in the builder UI
221
+ await this.clearHtmlSelection()
222
+
223
+ // Attach event listeners to all editable elements in the builder
224
+ await this.addListenersToEditableElements()
225
+
226
+ // Hide the global loading indicator and mark the builder as started
227
+ this.pageBuilderStateStore.setIsLoadingGlobal(false)
228
+ this.pageBuilderStateStore.setBuilderStarted(true)
99
229
  }
100
230
 
101
231
  #applyElementClassChanges(
@@ -265,7 +395,7 @@ class PageBuilderClass {
265
395
 
266
396
  handleAutoSave = async () => {
267
397
  this.startEditing()
268
- const passedConfig = this.pageBuilderStateStore.getConfigPageBuilder
398
+ const passedConfig = this.pageBuilderStateStore.getPageBuilderConfig
269
399
 
270
400
  // Check if config is set
271
401
  if (passedConfig && passedConfig.userSettings) {
@@ -280,7 +410,7 @@ class PageBuilderClass {
280
410
  try {
281
411
  this.pageBuilderStateStore.setIsSaving(true)
282
412
  await this.saveComponentsLocalStorage()
283
- await this.delay(300)
413
+ await this.delay(500)
284
414
  } catch (err) {
285
415
  console.error('Error trying auto save.', err)
286
416
  } finally {
@@ -303,7 +433,7 @@ class PageBuilderClass {
303
433
 
304
434
  handleManualSave = async () => {
305
435
  this.startEditing()
306
- const passedConfig = this.pageBuilderStateStore.getConfigPageBuilder
436
+ const passedConfig = this.pageBuilderStateStore.getPageBuilderConfig
307
437
 
308
438
  // Check if config is set
309
439
  if (passedConfig && passedConfig.userSettings) {
@@ -575,7 +705,6 @@ class PageBuilderClass {
575
705
  )
576
706
  }
577
707
 
578
- // border color, style & width / start
579
708
  handleBorderStyle(borderStyle?: string): void {
580
709
  this.#applyElementClassChanges(
581
710
  borderStyle,
@@ -611,7 +740,6 @@ class PageBuilderClass {
611
740
  this.#applyElementClassChanges(color, tailwindColors.textColorVariables, 'setTextColor')
612
741
  }
613
742
 
614
- // border radius / start
615
743
  handleBorderRadiusGlobal(borderRadiusGlobal?: string): void {
616
744
  this.#applyElementClassChanges(
617
745
  borderRadiusGlobal,
@@ -690,7 +818,7 @@ class PageBuilderClass {
690
818
  this.pageBuilderStateStore.setComponents([])
691
819
  }
692
820
 
693
- deleteSelectedComponent() {
821
+ async deleteSelectedComponent() {
694
822
  if (!this.getComponents.value || !this.getComponent.value) return
695
823
 
696
824
  // Find the index of the component to delete
@@ -706,6 +834,8 @@ class PageBuilderClass {
706
834
  // Remove the component from the array
707
835
  this.getComponents.value.splice(indexToDelete, 1)
708
836
  this.pageBuilderStateStore.setComponents(this.getComponents.value)
837
+ await nextTick()
838
+ await this.addListenersToEditableElements()
709
839
 
710
840
  this.pageBuilderStateStore.setComponent(null)
711
841
  this.pageBuilderStateStore.setElement(null)
@@ -879,16 +1009,16 @@ class PageBuilderClass {
879
1009
  .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens
880
1010
  }
881
1011
 
882
- updateLocalStorageItemName(): void {
1012
+ #updateLocalStorageItemName(): void {
883
1013
  const updateOrCreate =
884
- this.pageBuilderStateStore.getConfigPageBuilder &&
885
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
886
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType
1014
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1015
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1016
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType
887
1017
 
888
- const resourceData = this.pageBuilderStateStore.getConfigPageBuilder?.resourceData
1018
+ const resourceData = this.pageBuilderStateStore.getPageBuilderConfig?.resourceData
889
1019
 
890
1020
  const resourceFormName =
891
- this.pageBuilderStateStore.getConfigPageBuilder?.updateOrCreate?.formName
1021
+ this.pageBuilderStateStore.getPageBuilderConfig?.updateOrCreate?.formName
892
1022
 
893
1023
  // Logic for create resource
894
1024
  if (updateOrCreate === 'create') {
@@ -906,9 +1036,6 @@ class PageBuilderClass {
906
1036
  // Logic for create
907
1037
  // Logic for update and with resource form name
908
1038
  if (updateOrCreate === 'update') {
909
- //
910
- //
911
- //
912
1039
  if (typeof resourceFormName === 'string' && resourceFormName.length > 0) {
913
1040
  //
914
1041
  //
@@ -1053,14 +1180,16 @@ class PageBuilderClass {
1053
1180
  })
1054
1181
  })
1055
1182
 
1056
- if (this.getLocalStorageItemName.value) {
1057
- localStorage.setItem(
1058
- this.getLocalStorageItemName.value,
1059
- JSON.stringify({
1060
- pageBuilderContentSavedAt: new Date().toISOString(),
1061
- components: componentsToSave,
1062
- }),
1063
- )
1183
+ // Save to localStorage with pageBuilderContentSavedAt using the correct key
1184
+ const dataToSave = {
1185
+ components: componentsToSave,
1186
+ pageBuilderContentSavedAt: new Date().toISOString(),
1187
+ }
1188
+
1189
+ const keyForSavingFromDomToLocal = this.getLocalStorageItemName.value
1190
+
1191
+ if (keyForSavingFromDomToLocal && typeof keyForSavingFromDomToLocal === 'string') {
1192
+ localStorage.setItem(keyForSavingFromDomToLocal, JSON.stringify(dataToSave))
1064
1193
  }
1065
1194
 
1066
1195
  // No DOM mutation here!
@@ -1085,10 +1214,10 @@ class PageBuilderClass {
1085
1214
  //
1086
1215
  deleteOldPageBuilderLocalStorage(): void {
1087
1216
  if (
1088
- this.pageBuilderStateStore.getConfigPageBuilder &&
1089
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1090
- typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1091
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'update'
1217
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1218
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1219
+ typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1220
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
1092
1221
  ) {
1093
1222
  let oldCountLocalStorages = 0
1094
1223
  const deletedItemsLog: { Number: number; Key: string; SavedAt: string }[] = []
@@ -1137,14 +1266,14 @@ class PageBuilderClass {
1137
1266
  }
1138
1267
  }
1139
1268
 
1140
- async hasLocalDraftForUpdate(): Promise<boolean> {
1269
+ async #hasLocalDraftForUpdate(): Promise<boolean> {
1141
1270
  if (this.hasStartedEditing) return false
1142
1271
 
1143
1272
  if (
1144
- this.pageBuilderStateStore.getConfigPageBuilder &&
1145
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1146
- typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1147
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'update'
1273
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1274
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1275
+ typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1276
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
1148
1277
  ) {
1149
1278
  const key = this.getLocalStorageItemName.value
1150
1279
  if (typeof key === 'string') {
@@ -1152,10 +1281,13 @@ class PageBuilderClass {
1152
1281
  if (draft) {
1153
1282
  try {
1154
1283
  await this.delay(500)
1155
- const draftParsed = JSON.parse(draft)
1156
- const dbComponents = this.getComponents.value
1157
- return JSON.stringify(draftParsed.components) !== JSON.stringify(dbComponents)
1158
- } catch (e) {
1284
+
1285
+ return true
1286
+ // const dbComponents = this.getComponents.value
1287
+ // const draftParsed = JSON.parse(draft)
1288
+ // return JSON.stringify(draftParsed.components) !== JSON.stringify(dbComponents)
1289
+ } catch (err) {
1290
+ console.error('Unable to mount components to DOM.', err)
1159
1291
  return false
1160
1292
  }
1161
1293
  }
@@ -1169,34 +1301,51 @@ class PageBuilderClass {
1169
1301
  this.hasStartedEditing = true
1170
1302
  }
1171
1303
 
1304
+ //
1172
1305
  async resumeEditingForUpdate() {
1173
1306
  if (
1174
- this.pageBuilderStateStore.getConfigPageBuilder &&
1175
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1176
- typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1177
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'update'
1307
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1308
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1309
+ typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1310
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
1178
1311
  ) {
1179
1312
  const key = this.getLocalStorageItemName.value
1313
+
1180
1314
  if (typeof key === 'string') {
1181
- const savedCurrentDesign = localStorage.getItem(key)
1182
- if (savedCurrentDesign) {
1183
- try {
1184
- const parsed = JSON.parse(savedCurrentDesign)
1185
- if (parsed && Array.isArray(parsed.components)) {
1186
- this.pageBuilderStateStore.setComponents(parsed.components)
1187
- localStorage.removeItem(key)
1188
- await nextTick()
1189
- await this.addListenersToEditableElements()
1190
- await this.handleAutoSave()
1191
- }
1192
- } catch (e) {
1193
- console.error('Failed to parse local draft:', e)
1194
- }
1315
+ const updateDraftFromLocalStorage = localStorage.getItem(key)
1316
+
1317
+ if (typeof updateDraftFromLocalStorage === 'string') {
1318
+ this.pageBuilderStateStore.setIsResumeEditing(true)
1319
+ await delay(500)
1320
+ this.mountComponentsToDOM(updateDraftFromLocalStorage)
1321
+ this.pageBuilderStateStore.setIsResumeEditing(false)
1195
1322
  }
1196
1323
  }
1197
1324
  }
1198
1325
  }
1199
1326
 
1327
+ async restoreOriginalContent() {
1328
+ if (
1329
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1330
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1331
+ typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1332
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
1333
+ ) {
1334
+ this.pageBuilderStateStore.setIsRestoring(true)
1335
+ await this.delay(300)
1336
+
1337
+ // Restore the original content if available
1338
+ if (this.originalComponents) {
1339
+ this.mountComponentsToDOM(this.originalComponents)
1340
+ }
1341
+
1342
+ await nextTick()
1343
+ await this.addListenersToEditableElements()
1344
+
1345
+ this.pageBuilderStateStore.setIsRestoring(false)
1346
+ }
1347
+ }
1348
+
1200
1349
  getStorageItemNameForResource(): string | null {
1201
1350
  return this.getLocalStorageItemName.value
1202
1351
  }
@@ -1476,9 +1625,9 @@ class PageBuilderClass {
1476
1625
  * @param data - JSON string (e.g., '[{"html_code":"...","id":"123","title":"..."}]')
1477
1626
  * OR HTML string (e.g., '<section data-componentid="123">...</section>')
1478
1627
  */
1479
- setComponentsFromData(data: string): void {
1628
+ #setComponentsFromData(htmlString: string): void {
1480
1629
  // Auto-detect if input is JSON or HTML
1481
- const trimmedData = data.trim()
1630
+ const trimmedData = htmlString.trim()
1482
1631
 
1483
1632
  if (trimmedData.startsWith('[') || trimmedData.startsWith('{')) {
1484
1633
  // Looks like JSON - parse as JSON
@@ -1492,7 +1641,7 @@ class PageBuilderClass {
1492
1641
  }
1493
1642
 
1494
1643
  // Private method to parse JSON components and save pageBuilderContentSavedAt to localStorage
1495
- #parseJSONComponents(jsonData: string): void {
1644
+ async #parseJSONComponents(jsonData: string): Promise<void> {
1496
1645
  try {
1497
1646
  const parsedData = JSON.parse(jsonData)
1498
1647
  let componentsArray: ComponentObject[] = []
@@ -1544,18 +1693,8 @@ class PageBuilderClass {
1544
1693
 
1545
1694
  this.pageBuilderStateStore.setComponents(savedCurrentDesign)
1546
1695
 
1547
- // Save to localStorage with pageBuilderContentSavedAt using the correct key
1548
- const dataToSave = {
1549
- pageBuilderContentSavedAt: parsedData.pageBuilderContentSavedAt || new Date().toISOString(),
1550
- components: savedCurrentDesign,
1551
- }
1552
-
1553
- if (
1554
- this.getLocalStorageItemName.value &&
1555
- typeof this.getLocalStorageItemName.value === 'string'
1556
- ) {
1557
- localStorage.setItem(this.getLocalStorageItemName.value, JSON.stringify(dataToSave))
1558
- }
1696
+ await this.clearHtmlSelection()
1697
+ await this.addListenersToEditableElements()
1559
1698
  } catch (error) {
1560
1699
  console.error('Error parsing JSON components:', error)
1561
1700
  this.pageBuilderStateStore.setComponents([])
@@ -1602,37 +1741,60 @@ class PageBuilderClass {
1602
1741
  }
1603
1742
  }
1604
1743
 
1605
- // Load existing content from HTML when in update mode
1606
- mountComponentsToDOM(data?: string, injectCustomHTMLSections?: boolean): void {
1607
- this.pageBuilderStateStore.setComponents([])
1608
-
1609
- if (!this.pageBuilderStateStore.getConfigPageBuilder) return
1610
-
1611
- if (injectCustomHTMLSections && data !== undefined) {
1612
- this.setComponentsFromData(data)
1744
+ /**
1745
+ * Mount Components to DOM
1746
+ * @param passedData - HTML/JSON string to inject (optional)
1747
+ * @param preferLocalStorage - if true, always try localStorage first
1748
+ */
1749
+ mountComponentsToDOM(passedData: string): void {
1750
+ // Save the original content only once, in update mode, and only if passedData is provided
1751
+ // Form type Update
1752
+ if (
1753
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1754
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1755
+ typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1756
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update' &&
1757
+ passedData &&
1758
+ !this.originalComponents
1759
+ ) {
1760
+ this.originalComponents = passedData
1613
1761
  }
1614
1762
 
1615
- const storedData = this.loadStoredComponentsFromStorage()
1763
+ this.pageBuilderStateStore.setComponents([])
1764
+
1765
+ if (!this.pageBuilderStateStore.getPageBuilderConfig) return
1616
1766
 
1767
+ // Form type Update
1617
1768
  if (
1618
- this.pageBuilderStateStore.getConfigPageBuilder &&
1619
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1620
- typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1621
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'create'
1769
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1770
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1771
+ typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1772
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
1622
1773
  ) {
1623
- if (storedData) {
1624
- this.setComponentsFromData(storedData)
1774
+ if (passedData) {
1775
+ this.#setComponentsFromData(passedData)
1776
+ return
1625
1777
  }
1626
1778
  }
1627
1779
 
1780
+ // Form type Create
1781
+ const localStorageData = this.loadStoredComponentsFromStorage()
1782
+
1628
1783
  if (
1629
- this.pageBuilderStateStore.getConfigPageBuilder &&
1630
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1631
- typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1632
- this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'update'
1784
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1785
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1786
+ typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1787
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'create'
1633
1788
  ) {
1634
- if (data) {
1635
- this.setComponentsFromData(data)
1789
+ if (localStorageData) {
1790
+ this.#setComponentsFromData(localStorageData)
1791
+ return
1792
+ }
1793
+
1794
+ // If no localStorage, but passedData exists (for demo), use it
1795
+ if (passedData) {
1796
+ this.#setComponentsFromData(passedData)
1797
+ return
1636
1798
  }
1637
1799
  }
1638
1800
  }
@@ -1646,6 +1808,7 @@ class PageBuilderClass {
1646
1808
  }
1647
1809
 
1648
1810
  async initializeElementStyles(): Promise<void> {
1811
+ if (!this.pageBuilderStateStore.getPageBuilderConfig) return
1649
1812
  await new Promise((resolve) => requestAnimationFrame(resolve))
1650
1813
 
1651
1814
  // handle custom URL
@@ -1699,5 +1862,3 @@ class PageBuilderClass {
1699
1862
  await this.#syncCurrentClasses()
1700
1863
  }
1701
1864
  }
1702
-
1703
- export default PageBuilderClass
@@ -0,0 +1,25 @@
1
+ // builderInstance.ts
2
+ import { PageBuilderService } from '../composables/PageBuilderService'
3
+ import { sharedPageBuilderStore } from '../stores/shared-store'
4
+
5
+ // Singleton instance
6
+ let instance: PageBuilderService | null = null
7
+
8
+ // Used to create and store the single instance
9
+ export function initPageBuilder(): PageBuilderService {
10
+ if (!instance) {
11
+ const pageBuilderStateStore = sharedPageBuilderStore
12
+ instance = new PageBuilderService(pageBuilderStateStore)
13
+ }
14
+ return instance
15
+ }
16
+
17
+ // Used to access the existing instance anywhere else
18
+ export function getPageBuilder(): PageBuilderService {
19
+ if (!instance) {
20
+ throw new Error(
21
+ 'PageBuilderService has not been created. Please call createPageBuilder() first in your App.vue or setup file.',
22
+ )
23
+ }
24
+ return instance
25
+ }
package/src/css/app.css CHANGED
@@ -357,3 +357,18 @@
357
357
  @apply pbx-aspect-square pbx-border pbx-border-gray-200 pbx-cursor-pointer pbx-min-h-[1.5rem] pbx-rounded-sm;
358
358
  }
359
359
  }
360
+
361
+ /* p {
362
+ @apply pbx-font-normal lg:pbx-text-base pbx-text-base;
363
+ } */
364
+
365
+ a {
366
+ @apply pbx-text-myPrimaryLinkColor;
367
+ }
368
+
369
+ h2 {
370
+ @apply pbx-text-3xl pbx-mt-4 pbx-mb-3 pbx-font-medium;
371
+ }
372
+ h3 {
373
+ @apply pbx-text-2xl pbx-mt-4 pbx-mb-3 pbx-font-medium;
374
+ }
@@ -14,8 +14,15 @@ These styles affect all HTML elements (like input, button, h1, etc.) in the cons
14
14
  }
15
15
  /* CSS for content inside page builder # start */
16
16
  #page-builder-editor .tiptap {
17
+ outline: none !important;
18
+ box-shadow: none !important;
17
19
  background: #fff;
18
20
  min-height: 25rem;
21
+ border: 1px solid #aaa;
22
+ border-radius: 10px;
23
+ padding: 6px;
24
+ margin-bottom: 20px;
25
+ padding-bottom: 100px;
19
26
  }
20
27
 
21
28
  #pagebuilder #youtube-video::before {
package/src/index.ts CHANGED
@@ -5,8 +5,6 @@ export { default as Preview } from './PageBuilder/Preview.vue'
5
5
  // Export stores (consolidated into single store)
6
6
  export { usePageBuilderStateStore } from './stores/page-builder-state'
7
7
 
8
- export { default as PageBuilderClass } from './composables/PageBuilderClass.ts'
9
-
10
8
  // Export composables
11
9
  export { usePageBuilderModal } from './composables/usePageBuilderModal'
12
10
 
@@ -21,3 +19,7 @@ import './css/app.css'
21
19
 
22
20
  // Export shared store instances for external access
23
21
  export { sharedPageBuilderPinia, sharedPageBuilderStore } from './stores/shared-store'
22
+
23
+ // export { PageBuilderService } from './composables/PageBuilderService.ts'
24
+
25
+ export { initPageBuilder, getPageBuilder } from './composables/builderInstance'
package/src/main.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import './css/dev-global.css'
2
2
  import './css/app.css'
3
+ import { initPageBuilder } from './composables/builderInstance'
3
4
 
4
5
  import { createApp } from 'vue'
5
6
  import { createPinia } from 'pinia'
6
7
  import App from './App.vue'
7
8
 
9
+ initPageBuilder()
10
+
8
11
  const app = createApp(App)
9
12
 
10
13
  app.use(createPinia())