@myissue/vue-website-page-builder 3.1.53 → 3.2.13

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.
@@ -9,7 +9,15 @@ import SearchComponents from '../Components/Search/SearchComponents.vue'
9
9
  import OptionsDropdown from '../Components/PageBuilder/DropdownsPlusToggles/OptionsDropdown.vue'
10
10
  import RightSidebarEditor from '../Components/PageBuilder/EditorMenu/RightSidebarEditor.vue'
11
11
  import { sharedPageBuilderPinia, sharedPageBuilderStore } from '../stores/shared-store'
12
-
12
+ import {
13
+ isChildrenEmpty,
14
+ onlyUserIsValid,
15
+ onlyUpdateOrCreateIsValid,
16
+ onlyPageBuilderLogoIsValid,
17
+ onlyResourceDataIsValid,
18
+ onlyUserSettingsIsValid,
19
+ updateOrCreateIsFalsy,
20
+ } from '../helpers/passedPageBuilderConfig'
13
21
  /**
14
22
  * Props for PageBuilder component
15
23
  * @typedef {Object} Props
@@ -28,8 +36,9 @@ const props = defineProps({
28
36
  },
29
37
  })
30
38
 
31
- // Use shared Pinia instance for PageBuilder package (THIS IS THE KEY CHANGE!)
39
+ // Use shared Pinia instance for PageBuilder package
32
40
  const internalPinia = sharedPageBuilderPinia
41
+
33
42
  const pageBuilderStateStore = sharedPageBuilderStore
34
43
 
35
44
  // Initialize PageBuilder with store
@@ -81,7 +90,7 @@ const firstButtonTextSearchComponents = ref('')
81
90
  const firstModalButtonSearchComponentsFunction = ref(null)
82
91
 
83
92
  const handleAddComponent = function () {
84
- pageBuilderStateStore.setComponent(null)
93
+ pageBuilderClass.clearHtmlSelection()
85
94
 
86
95
  //
87
96
  titleModalAddComponent.value = 'Add Components to Page'
@@ -143,11 +152,6 @@ const handleSelectComponent = function (componentObject) {
143
152
 
144
153
  const draggableZone = ref(null)
145
154
 
146
- const defaultUpdateOrCreate = {
147
- formType: 'create',
148
- createNewResourceFormName: 'post',
149
- }
150
-
151
155
  const defaultConfigValues = {
152
156
  updateOrCreate: {
153
157
  formType: 'create',
@@ -161,30 +165,89 @@ const defaultConfigValues = {
161
165
  },
162
166
  }
163
167
 
164
- onMounted(async () => {
165
- pageBuilderClass.updateLocalStorageItemName()
166
- await pageBuilderClass.setEventListenersForElements()
167
-
168
+ const handleConfig = function (config) {
169
+ // Set config for page builder if not set by user
168
170
  if (
169
- getConfigPageBuilder.value &&
170
- getConfigPageBuilder.value.updateOrCreate &&
171
- getConfigPageBuilder.value.updateOrCreate.formType === 'create'
171
+ config === null ||
172
+ config === undefined ||
173
+ (config && Object.keys(config).length === 0 && config.constructor === Object)
172
174
  ) {
173
- pageBuilderClass.loadExistingContent()
175
+ console.log('1')
176
+ pageBuilderClass.setConfigPageBuilder(defaultConfigValues)
177
+ return
174
178
  }
175
179
 
180
+ if (config && Object.keys(config).length !== 0 && config.constructor === Object) {
181
+ //
182
+ // Check alone
183
+ // Returns true if all config fields are missing or empty
184
+ if (isChildrenEmpty(config)) {
185
+ console.log('1:')
186
+ return
187
+ }
188
+
189
+ if (onlyUserIsValid(config)) {
190
+ console.log('2:')
191
+ return
192
+ }
193
+
194
+ if (onlyUpdateOrCreateIsValid(config)) {
195
+ console.log('3:')
196
+ return
197
+ }
198
+
199
+ if (onlyPageBuilderLogoIsValid(config)) {
200
+ console.log('4:')
201
+ return
202
+ }
203
+
204
+ if (onlyResourceDataIsValid(config)) {
205
+ console.log('5:')
206
+ return
207
+ }
208
+
209
+ if (onlyUserSettingsIsValid(config)) {
210
+ console.log('6:')
211
+ return
212
+ }
213
+
214
+ if (onlyUserSettingsIsValid(config)) {
215
+ console.log('7:')
216
+ return
217
+ }
218
+
219
+ if (updateOrCreateIsFalsy(config)) {
220
+ console.log('8:')
221
+ return
222
+ }
223
+
224
+ // Check against eachoter in all combinations
225
+ }
226
+
227
+ // In the end make check if form type for update or create is set:
228
+ }
229
+
230
+ watch(
231
+ () => getConfigPageBuilder.value,
232
+ (config) => {
233
+ pageBuilderClass.updateLocalStorageItemName()
234
+
235
+ if (config && config.updateOrCreate && config.updateOrCreate.formType === 'create') {
236
+ pageBuilderClass.loadExistingContent()
237
+ }
238
+ },
239
+ { immediate: true },
240
+ )
241
+
242
+ onMounted(async () => {
243
+ const config = getConfigPageBuilder.value
244
+ handleConfig(config)
245
+
246
+ pageBuilderClass.updateLocalStorageItemName()
247
+
176
248
  pageBuilderClass.removeHoveredAndSelected()
177
249
 
178
- // Set config if it's an empty object
179
- if (
180
- getConfigPageBuilder.value === null ||
181
- getConfigPageBuilder.value === undefined ||
182
- (getConfigPageBuilder.value &&
183
- Object.keys(getConfigPageBuilder.value).length === 0 &&
184
- getConfigPageBuilder.value.constructor === Object)
185
- ) {
186
- pageBuilderClass.setConfigPageBuilder(defaultConfigValues)
187
- }
250
+ await pageBuilderClass.setEventListenersForElements()
188
251
  })
189
252
  </script>
190
253
 
@@ -193,6 +256,39 @@ onMounted(async () => {
193
256
  id="builder-container"
194
257
  class="font-sans max-w-full m-8 border-2 border-myPrimaryLinkColor inset-x-0 z-10 bg-white overflow-x-scroll pt-2 rounded-lg p-2"
195
258
  >
259
+ <div
260
+ @click="pageBuilderClass.clearHtmlSelection()"
261
+ id="pagebuilder-top-area"
262
+ class="px-4 pb-4 mx-4 my-4 rounded-xl"
263
+ >
264
+ <div class="flex justify-start items-center py-2 pl-2 mr-2 mb-6 h-full">
265
+ <div class="flex gap-2">
266
+ <span class="w-2 h-2 rounded-full bg-red-400"></span>
267
+ <span class="w-2 h-2 rounded-full bg-yellow-400"></span>
268
+ <span class="w-2 h-2 rounded-full bg-green-400"></span>
269
+ </div>
270
+ </div>
271
+ <!-- Logo # start -->
272
+ <div
273
+ v-if="
274
+ getConfigPageBuilder &&
275
+ getConfigPageBuilder.pageBuilderLogo &&
276
+ getConfigPageBuilder.pageBuilderLogo.src
277
+ "
278
+ class="flex items-center divide-x divide-gray-200"
279
+ >
280
+ <div class="pr-4">
281
+ <img class="h-6" :src="getConfigPageBuilder.pageBuilderLogo.src" alt="Logo" />
282
+ </div>
283
+ <span class="myPrimaryParagraph font-medium pl-4">Editing Page </span>
284
+ </div>
285
+ <div v-else>
286
+ <div class="pr-6">
287
+ <span class="myPrimaryParagraph font-medium">Editing Page </span>
288
+ </div>
289
+ </div>
290
+ </div>
291
+ <!-- Logo # end -->
196
292
  <SearchComponents
197
293
  v-if="showModalAddComponent"
198
294
  :show="showModalAddComponent"
@@ -211,7 +307,8 @@ onMounted(async () => {
211
307
  <div>
212
308
  <div class="relative h-full flex">
213
309
  <div
214
- @click.self="pageBuilderStateStore.setComponent(null)"
310
+ @click.self="pageBuilderClass.clearHtmlSelection()"
311
+ id="pagebuilder-left-area"
215
312
  class="min-w-[3.5rem] pt-6 pb-2 my-2 mx-2 bg-myPrimaryLightGrayColor rounded-full shadow"
216
313
  >
217
314
  <div class="mx-2 flex flex-col myPrimaryGap">
@@ -229,49 +326,45 @@ onMounted(async () => {
229
326
  <span class="myMediumIcon material-symbols-outlined"> interests </span>
230
327
  </button>
231
328
  </div>
232
- <div @click.self="pageBuilderStateStore.setComponent(null)">
329
+ <div @click.self="pageBuilderClass.clearHtmlSelection()">
233
330
  <ComponentTopMenu v-if="getElement"></ComponentTopMenu>
234
331
  </div>
235
332
  </div>
236
333
  </div>
237
334
  <main class="flex flex-col h-full grow rounded-2xl duration-300 shadow-2xl">
238
335
  <div
239
- class="flex items-center justify-between primary-gap rounded-t-2xl py-2 bg-myPrimaryLightGrayColor"
336
+ id="pagebuilder-toolbar-area"
337
+ class="flex items-center justify-between rounded-t-2xl bg-myPrimaryLightGrayColor"
240
338
  >
241
- <div class="flex myPrimaryGap items-center mr-8 overflow-x-scroll w-96 pt-4">
242
- <div
243
- @click.self="pageBuilderStateStore.setComponent(null)"
244
- class="w-4/12 flex justify-start items-center py-2 pl-2 h-full"
245
- >
246
- <div class="flex gap-2">
247
- <span class="w-2 h-2 rounded-full bg-red-400"></span>
248
- <span class="w-2 h-2 rounded-full bg-yellow-400"></span>
249
- <span class="w-2 h-2 rounded-full bg-green-400"></span>
250
- </div>
251
- </div>
252
-
339
+ <div
340
+ @click="pageBuilderClass.clearHtmlSelection()"
341
+ class="flex myPrimaryGap items-center overflow-x-scroll pt-4 pb-2 pl-2 h-24 w-full"
342
+ >
253
343
  <button
254
344
  class="myPrimaryButton"
255
345
  @click="pageBuilderClass.saveComponentsLocalStorage"
256
346
  type="button"
257
347
  >
258
348
  <span class="material-symbols-outlined text-[18px]"> save </span>
259
- Save layout
349
+ Save
260
350
  </button>
261
351
  </div>
262
352
 
263
353
  <div
264
- @click.self="pageBuilderStateStore.setComponent(null)"
265
- class="w-4/12 flex justify-center py-2"
354
+ @click.self="pageBuilderClass.clearHtmlSelection()"
355
+ class="flex justify-center items-center h-24 w-full"
266
356
  >
267
357
  <OptionsDropdown @previewCurrentDesign="previewCurrentDesign"></OptionsDropdown>
268
358
  </div>
269
359
 
270
360
  <div
271
- @click.self="pageBuilderStateStore.setComponent(null)"
272
- class="w-4/12 flex justify-end py-2 pr-2"
361
+ @click.self="pageBuilderClass.clearHtmlSelection()"
362
+ class="flex justify-end py-2 pr-2 h-24 w-full"
273
363
  >
274
- <div class="flex items-center justify-center gap-4">
364
+ <div
365
+ @click.self="pageBuilderClass.clearHtmlSelection()"
366
+ class="flex items-center justify-center gap-4"
367
+ >
275
368
  <button
276
369
  type="button"
277
370
  @click="
@@ -299,7 +392,7 @@ onMounted(async () => {
299
392
  () => {
300
393
  pageBuilderStateStore.setMenuRight(false)
301
394
  pageBuilderStateStore.setElement(null)
302
- pageBuilderStateStore.setComponent(null)
395
+ pageBuilderClass.clearHtmlSelection()
303
396
  handlePageBuilderPreview()
304
397
  }
305
398
  "
@@ -314,23 +407,33 @@ onMounted(async () => {
314
407
  </span>
315
408
  </div>
316
409
  </button>
410
+ </div>
411
+ </div>
412
+ </div>
317
413
 
318
- <button
319
- type="button"
320
- v-if="getMenuRight === false"
321
- @click="pageBuilderStateStore.setMenuRight(true)"
322
- >
323
- <div class="flex items-center justify-center gap-2">
324
- <span class="lg:block hidden"> Styling </span>
414
+ <div
415
+ @click.self="pageBuilderClass.clearHtmlSelection()"
416
+ class="flex justify-end py-2 pr-2 w-full h-24"
417
+ >
418
+ <div
419
+ @click.self="pageBuilderClass.clearHtmlSelection()"
420
+ class="flex items-center justify-center gap-4"
421
+ >
422
+ <button
423
+ type="button"
424
+ v-if="getMenuRight === false"
425
+ @click="pageBuilderStateStore.setMenuRight(true)"
426
+ >
427
+ <div class="flex items-center justify-center gap-2">
428
+ <span class="lg:block hidden"> Styling </span>
325
429
 
326
- <span
327
- class="h-10 w-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 aspect-square hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
328
- >
329
- <span class="myMediumIcon material-symbols-outlined"> apps </span>
330
- </span>
331
- </div>
332
- </button>
333
- </div>
430
+ <span
431
+ class="h-10 w-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 aspect-square hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
432
+ >
433
+ <span class="myMediumIcon material-symbols-outlined"> more_vert </span>
434
+ </span>
435
+ </div>
436
+ </button>
334
437
  </div>
335
438
  </div>
336
439
  </div>
@@ -361,6 +464,7 @@ onMounted(async () => {
361
464
  handleAddComponent()
362
465
  }
363
466
  "
467
+ id="pagebuilder-bottom-components-area"
364
468
  class="hover:bg-gray-100 rounded-full border-2 border-myPrimaryLinkColor pt-10 pb-14 text-center focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 my-12 mx-8 cursor-pointer"
365
469
  >
366
470
  <div class="flex items-center justify-center gap-2 font-medium cursor-pointer">
@@ -387,6 +491,7 @@ onMounted(async () => {
387
491
 
388
492
  <aside
389
493
  aria-label="Menu"
494
+ id="pagebuilder-right-area"
390
495
  :class="{ 'w-0': !getMenuRight, 'w-80 ml-4': getMenuRight }"
391
496
  class="h-full duration-300 z-20 flex-shrink-0 overflow-hidden shadow-2xl rounded-l-2xl bg-white"
392
497
  >
@@ -127,6 +127,12 @@ class PageBuilderClass {
127
127
  this.delay = delay()
128
128
  }
129
129
 
130
+ // Load existing content from HTML when in update mode
131
+ clearHtmlSelection(): void {
132
+ this.pageBuilderStateStore.setComponent(null)
133
+ this.pageBuilderStateStore.setElement(null)
134
+ this.removeHoveredAndSelected()
135
+ }
130
136
  // Load existing content from HTML when in update mode
131
137
  setConfigPageBuilder(data: PageBuilderConfig): void {
132
138
  this.pageBuilderStateStore.setConfigPageBuilder(data)
@@ -146,7 +152,6 @@ class PageBuilderClass {
146
152
  const currentHTMLElement = this.getElement.value
147
153
  if (!currentHTMLElement) return
148
154
 
149
- // currentCSS array example: ["none","py-0", "py-2", ...] or ['none', 'rounded-sm', 'rounded', 'rounded-md', ...]
150
155
  const currentCSS = CSSArray.find((CSS) => {
151
156
  return currentHTMLElement.classList.contains(CSS)
152
157
  })
@@ -330,36 +335,40 @@ class PageBuilderClass {
330
335
  this.pageBuilderStateStore.setComponents([])
331
336
  }
332
337
 
333
- const hoveredElement = document.querySelector('[hovered]')
334
- if (hoveredElement) {
335
- hoveredElement.removeAttribute('hovered')
336
- }
337
-
338
- this.getComponents.value?.forEach((component) => {
339
- const section = document.querySelector(`section[data-componentid="${component.id}"]`)
338
+ const pagebuilder = document.querySelector('#pagebuilder')
340
339
 
341
- if (section) {
342
- component.html_code = section.outerHTML
340
+ if (pagebuilder) {
341
+ const hoveredElement = pagebuilder.querySelector('[hovered]')
342
+ if (hoveredElement) {
343
+ hoveredElement.removeAttribute('hovered')
343
344
  }
344
- })
345
345
 
346
- // Initialize the MutationObserver
347
- this.observer = new MutationObserver((mutationsList, observer) => {
348
- // Once we have seen a mutation, stop observing and resolve the promise
349
- observer.disconnect()
350
- })
346
+ this.getComponents.value?.forEach((component) => {
347
+ const section = pagebuilder.querySelector(`section[data-componentid="${component.id}"]`)
351
348
 
352
- // Start observing the document with the configured parameters
353
- this.observer.observe(document, {
354
- attributes: true,
355
- childList: true,
356
- subtree: true,
357
- })
349
+ if (section) {
350
+ component.html_code = section.outerHTML
351
+ }
352
+ })
358
353
 
359
- // Use the MutationObserver to wait for the next DOM change
360
- await new Promise<void>((resolve) => {
361
- resolve()
362
- })
354
+ // Initialize the MutationObserver
355
+ this.observer = new MutationObserver((mutationsList, observer) => {
356
+ // Once we have seen a mutation, stop observing and resolve the promise
357
+ observer.disconnect()
358
+ })
359
+
360
+ // Start observing the pagebuilder with the configured parameters
361
+ this.observer.observe(pagebuilder, {
362
+ attributes: true,
363
+ childList: true,
364
+ subtree: true,
365
+ })
366
+
367
+ // Use the MutationObserver to wait for the next DOM change
368
+ await new Promise<void>((resolve) => {
369
+ resolve()
370
+ })
371
+ }
363
372
  }
364
373
 
365
374
  cloneCompObjForDOMInsertion(componentObject: ComponentObject): ComponentObject {
@@ -1104,8 +1113,10 @@ class PageBuilderClass {
1104
1113
  }
1105
1114
 
1106
1115
  updateLocalStorageItemName(): void {
1107
- const updateOrCreate =
1108
- this.pageBuilderStateStore.getConfigPageBuilder?.updateOrCreate?.formType || 'create'
1116
+ // const updateOrCreate =
1117
+ // this.pageBuilderStateStore.getConfigPageBuilder?.updateOrCreate?.formType || 'create'
1118
+
1119
+ const updateOrCreate = this.pageBuilderStateStore.getConfigPageBuilder?.updateOrCreate?.formType
1109
1120
 
1110
1121
  const resourceData = this.pageBuilderStateStore.getConfigPageBuilder?.resourceData
1111
1122
 
@@ -1137,7 +1148,9 @@ class PageBuilderClass {
1137
1148
  if (resourceData && resourceData != null && !resourceData.title) {
1138
1149
  // Check if id is missing, null, undefined, or an empty string (after trimming)
1139
1150
  if (!resourceData.id || typeof resourceData.id === 'string') {
1140
- this.pageBuilderStateStore.setLocalStorageItemName(`page-builder-update-resource`)
1151
+ this.pageBuilderStateStore.setLocalStorageItemName(
1152
+ `page-builder-update-resource-${this.sanitizeForLocalStorage(resourceFormName)}`,
1153
+ )
1141
1154
  return
1142
1155
  }
1143
1156
  }
package/src/css/app.css CHANGED
@@ -509,14 +509,37 @@ h3 {
509
509
  }
510
510
 
511
511
  #page-builder-editor-editable-area #youtube-video::before {
512
- content: 'Select video element';
513
- font-family: 'Jost', sans-serif;
514
- display: inline-block;
512
+ content: 'Select Video Element';
513
+ font-family: 'Jost';
514
+ background: #16a34a !important;
515
+ color: white;
516
+ text-decoration: none;
515
517
  margin-right: 8px;
516
518
  vertical-align: middle;
519
+ min-height: 3rem;
520
+ padding: 0.75rem 0.75rem;
521
+ white-space: nowrap;
522
+ word-break: keep-all;
523
+ font-weight: 500;
524
+ display: inline-flex;
525
+ gap: 0.25rem;
526
+ align-items: center;
527
+ justify-content: center;
528
+ border-radius: 9999px;
529
+ border: 1px solid transparent;
530
+ margin-bottom: 20px;
531
+ font-size: 0.8rem !important;
532
+ }
533
+
534
+ @media (min-width: 640px) {
535
+ #page-builder-editor-editable-area #youtube-video::before {
536
+ font-size: 0.9rem !important;
537
+ width: auto;
538
+ }
517
539
  }
540
+
518
541
  #page-builder-editor-editable-area #youtube-video:hover::before {
519
- text-decoration: underline;
542
+ text-decoration: none;
520
543
  cursor: pointer;
521
544
  }
522
545
 
@@ -0,0 +1,5 @@
1
+ export const isEmptyObject = function (obj: Object) {
2
+ return (
3
+ !obj || (typeof obj === 'object' && obj.constructor === Object && Object.keys(obj).length === 0)
4
+ )
5
+ }