@myissue/vue-website-page-builder 3.0.18 → 3.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +79 -76
  2. package/dist/page-builder/2-images-text.png +0 -0
  3. package/dist/page-builder/3-images-text.png +0 -0
  4. package/dist/page-builder/3-vertical-images.png +0 -0
  5. package/dist/page-builder/4-images-text.png +0 -0
  6. package/dist/vue-website-page-builder.css +1 -1
  7. package/dist/vue-website-page-builder.js +7168 -7261
  8. package/dist/vue-website-page-builder.umd.cjs +146 -81
  9. package/package.json +4 -3
  10. package/src/App.vue +4 -115
  11. package/src/Components/Homepage/HomeSection.vue +70 -162
  12. package/src/Components/MediaLibrary/SidebarUnsplash.vue +9 -16
  13. package/src/Components/MediaLibrary/Unsplash.vue +51 -91
  14. package/src/Components/Modals/MediaLibraryModal.vue +56 -318
  15. package/src/Components/Modals/PageBuilderPreviewModal.vue +22 -40
  16. package/src/Components/PageBuilder/AdvancedPageBuilderSettings.vue +7 -0
  17. package/src/Components/PageBuilder/DropdownsPlusToggles/OptionsDropdown.vue +165 -110
  18. package/src/Components/PageBuilder/EditorMenu/Editables/BackgroundColorEditor.vue +9 -16
  19. package/src/Components/PageBuilder/EditorMenu/Editables/BorderRadius.vue +18 -18
  20. package/src/Components/PageBuilder/EditorMenu/Editables/Borders.vue +16 -21
  21. package/src/Components/PageBuilder/EditorMenu/Editables/ClassEditor.vue +12 -12
  22. package/src/Components/PageBuilder/EditorMenu/Editables/ComponentTopMenu.vue +10 -9
  23. package/src/Components/PageBuilder/EditorMenu/Editables/DeleteElement.vue +9 -9
  24. package/src/Components/PageBuilder/EditorMenu/Editables/EditGetElement.vue +144 -136
  25. package/src/Components/PageBuilder/EditorMenu/Editables/ElementEditor.vue +9 -10
  26. package/src/Components/PageBuilder/EditorMenu/Editables/ImageEditor.vue +31 -27
  27. package/src/Components/PageBuilder/EditorMenu/Editables/LinkEditor.vue +20 -14
  28. package/src/Components/PageBuilder/EditorMenu/Editables/ManageBackgroundOpacity.vue +9 -10
  29. package/src/Components/PageBuilder/EditorMenu/Editables/ManageOpacity.vue +9 -10
  30. package/src/Components/PageBuilder/EditorMenu/Editables/PaddingPlusMargin.vue +16 -16
  31. package/src/Components/PageBuilder/EditorMenu/Editables/TextColorEditor.vue +9 -16
  32. package/src/Components/PageBuilder/EditorMenu/Editables/Typography.vue +22 -20
  33. package/src/Components/PageBuilder/EditorMenu/RightSidebarEditor.vue +25 -27
  34. package/src/Components/PageBuilder/NoneCustomMediaLibraryComponent.vue +3 -0
  35. package/src/Components/PageBuilder/NoneCustomSearchComponent.vue +91 -0
  36. package/src/Components/PageBuilder/PageBuilderSettings.vue +8 -0
  37. package/src/Components/PageBuilder/Settings/AdvancedPageBuilderSettings.vue +31 -72
  38. package/src/Components/PageBuilder/Settings/PageBuilderSettings.vue +32 -36
  39. package/src/Components/Search/SearchComponents.vue +11 -199
  40. package/src/Components/TipTap/TipTap.vue +8 -7
  41. package/src/Components/TipTap/TipTapInput.vue +136 -134
  42. package/src/PageBuilder/PageBuilder.vue +220 -32
  43. package/src/composables/{PageBuilder.ts → PageBuilderClass.ts} +223 -142
  44. package/src/composables/usePageBuilderModal.ts +25 -0
  45. package/src/index.ts +8 -2
  46. package/src/stores/media-library.ts +1 -5
  47. package/src/stores/page-builder-state.ts +52 -36
  48. package/src/stores/user.ts +8 -6
  49. package/src/types/global.d.ts +6 -44
  50. package/src/types/index.ts +169 -0
  51. package/src/utils/html-elements/component.ts +88 -0
  52. package/src/utils/html-elements/componentHelpers.ts +101 -0
  53. package/src/Components/Modals/PageBuilderModal.vue +0 -233
  54. package/src/utils/builder/html-elements/componentHelpers.ts +0 -101
@@ -1,15 +1,15 @@
1
1
  <script setup>
2
2
  import { Editor, useEditor, EditorContent } from '@tiptap/vue-3'
3
3
  import StarterKit from '@tiptap/starter-kit'
4
- import { computed, onBeforeMount, onMounted, ref, watch } from 'vue'
5
- import PageBuilder from '@/composables/PageBuilder.ts'
4
+ import { computed, onBeforeMount, onMounted, ref, watch, inject } from 'vue'
5
+ import PageBuilderClass from '@/composables/PageBuilderClass.ts'
6
6
  import Link from '@tiptap/extension-link'
7
7
  import DynamicModal from '@/Components/Modals/DynamicModal.vue'
8
- import { usePageBuilderStateStore } from '@/stores/page-builder-state'
9
- import { useMediaLibraryStore } from '@/stores/media-library'
10
8
 
11
- const mediaLibraryStore = useMediaLibraryStore()
12
- const pageBuilderStateStore = usePageBuilderStateStore()
9
+ // Get stores from parent PageBuilder component
10
+ const pageBuilderStateStore = inject('pageBuilderStateStore')
11
+ const mediaLibraryStore = inject('mediaLibraryStore')
12
+
13
13
  const showModalUrl = ref(false)
14
14
 
15
15
  // use dynamic model
@@ -25,7 +25,7 @@ const firstModalButtonFunction = ref(null)
25
25
  const secondModalButtonFunction = ref(null)
26
26
  const thirdModalButtonFunction = ref(null)
27
27
 
28
- const pageBuilder = new PageBuilder(pageBuilderStateStore, mediaLibraryStore)
28
+ const pageBuilderClass = new PageBuilderClass(pageBuilderStateStore, mediaLibraryStore)
29
29
 
30
30
  const getElement = computed(() => {
31
31
  return pageBuilderStateStore.getElement
@@ -69,21 +69,21 @@ const editor = useEditor({
69
69
 
70
70
  // watch for changes in textContent and update store and textContentVueModel
71
71
  watch(textContent, (newValue) => {
72
- if (!pageBuilder.selectedElementIsValidText()) return
72
+ if (!pageBuilderClass.selectedElementIsValidText()) return
73
73
 
74
74
  if (getElement.value) {
75
75
  pageBuilderStateStore.setTextAreaVueModel(newValue)
76
76
 
77
77
  if (typeof newValue === 'string' && newValue !== textContentVueModel.value) {
78
- pageBuilder.handleTextInput(newValue)
78
+ pageBuilderClass.handleTextInput(newValue)
79
79
  }
80
80
  }
81
81
  })
82
82
 
83
- // pageBuilder.selectedElementIsValidText(newValue);
83
+ // pageBuilderClass.selectedElementIsValidText(newValue);
84
84
 
85
85
  const TipTapSetContent = function () {
86
- if (!pageBuilder.selectedElementIsValidText()) return
86
+ if (!pageBuilderClass.selectedElementIsValidText()) return
87
87
 
88
88
  if (editor.value) {
89
89
  editor.value.commands.setContent(getElement.value.innerHTML)
@@ -179,146 +179,148 @@ onMounted(() => {
179
179
  })
180
180
  </script>
181
181
  <template>
182
- <DynamicModal
183
- :show="showModalUrl"
184
- :type="typeModal"
185
- :gridColumnAmount="gridColumnModal"
186
- :title="titleModal"
187
- :description="descriptionModal"
188
- :firstButtonText="firstButtonModal"
189
- :secondButtonText="secondButtonModal"
190
- :thirdButtonText="thirdButtonModal"
191
- @firstModalButtonFunction="firstModalButtonFunction"
192
- @secondModalButtonFunction="secondModalButtonFunction"
193
- @thirdModalButtonFunction="thirdModalButtonFunction"
194
- >
195
- <header></header>
196
- <main>
197
- <div class="myInputGroup">
198
- <label class="myPrimaryInputLabel" for="roles"><span>Enter URL</span></label
199
- ><input v-model="urlEnteret" class="myPrimaryInput mt-1" type="url" placeholder="url" />
200
- <div v-if="urlError" class="min-h-[2.5rem] flex items-center justify-start">
201
- <p class="myPrimaryInputError mt-2 mb-0 py-0 self-start">
202
- {{ urlError }}
203
- </p>
182
+ <div>
183
+ <DynamicModal
184
+ :show="showModalUrl"
185
+ :type="typeModal"
186
+ :gridColumnAmount="gridColumnModal"
187
+ :title="titleModal"
188
+ :description="descriptionModal"
189
+ :firstButtonText="firstButtonModal"
190
+ :secondButtonText="secondButtonModal"
191
+ :thirdButtonText="thirdButtonModal"
192
+ @firstModalButtonFunction="firstModalButtonFunction"
193
+ @secondModalButtonFunction="secondModalButtonFunction"
194
+ @thirdModalButtonFunction="thirdModalButtonFunction"
195
+ >
196
+ <header></header>
197
+ <main>
198
+ <div class="myInputGroup">
199
+ <label class="myPrimaryInputLabel" for="roles"><span>Enter URL</span></label
200
+ ><input v-model="urlEnteret" class="myPrimaryInput mt-1" type="url" placeholder="url" />
201
+ <div v-if="urlError" class="min-h-[2.5rem] flex items-center justify-start">
202
+ <p class="myPrimaryInputError mt-2 mb-0 py-0 self-start">
203
+ {{ urlError }}
204
+ </p>
205
+ </div>
204
206
  </div>
205
- </div>
206
- </main>
207
- </DynamicModal>
208
-
209
- <div class="blockease-linear duration-200 block ease-linear">
210
- <div v-if="pageBuilder.selectedElementIsValidText() && editor">
211
- <div class="relative rounded-lg">
212
- <div
213
- class="flex justify-between myPrimaryGap items-center divide-x divide-gray-200 py-4 px-4 overflow-x-auto border-b border-gray-20"
214
- >
215
- <div class="flex items-center 0 divide-x divide-gray-200">
216
- <div class="px-2 flex items-center justify-start gap-2">
217
- <button
218
- @click="editor.chain().focus().setHardBreak().run()"
219
- type="button"
220
- class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
221
- >
222
- <span class="material-symbols-outlined"> keyboard_return </span>
223
- <span>Line break</span>
224
- </button>
207
+ </main>
208
+ </DynamicModal>
209
+
210
+ <div class="blockease-linear duration-200 block ease-linear">
211
+ <div v-if="pageBuilderClass.selectedElementIsValidText() && editor">
212
+ <div class="relative rounded-lg">
213
+ <div
214
+ class="flex justify-between myPrimaryGap items-center divide-x divide-gray-200 py-4 px-4 overflow-x-auto border-b border-gray-20"
215
+ >
216
+ <div>
217
+ <div>
218
+ <div class="px-2 flex items-center justify-start gap-2">
219
+ <button
220
+ @click="pageBuilderStateStore.setShowModalTipTap(false)"
221
+ type="button"
222
+ class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
223
+ >
224
+ <span class="material-symbols-outlined"> Save </span>
225
+ <span>Save</span>
226
+ </button>
227
+ </div>
228
+ </div>
225
229
  </div>
230
+ <div class="flex items-center 0 divide-x divide-gray-200">
231
+ <div class="px-2 flex items-center justify-start gap-2">
232
+ <button
233
+ @click="editor.chain().focus().setHardBreak().run()"
234
+ type="button"
235
+ class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
236
+ >
237
+ <span class="material-symbols-outlined"> keyboard_return </span>
238
+ <span>Line break</span>
239
+ </button>
240
+ </div>
226
241
 
227
- <div class="px-2 flex items-center justify-start gap-2">
228
- <button
229
- @click="editor.chain().focus().toggleBold().run()"
230
- type="button"
231
- class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
232
- :class="{
233
- 'bg-myPrimaryLinkColor text-white': editor.isActive('bold'),
234
- }"
235
- >
236
- <span class="material-symbols-outlined"> format_bold </span>
237
- <span>Bold</span>
238
- </button>
239
- </div>
242
+ <div class="px-2 flex items-center justify-start gap-2">
243
+ <button
244
+ @click="editor.chain().focus().toggleBold().run()"
245
+ type="button"
246
+ class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
247
+ :class="{
248
+ 'bg-myPrimaryLinkColor text-white': editor.isActive('bold'),
249
+ }"
250
+ >
251
+ <span class="material-symbols-outlined"> format_bold </span>
252
+ <span>Bold</span>
253
+ </button>
254
+ </div>
240
255
 
241
- <div class="px-2 flex items-center justify-start gap-2">
242
- <button
243
- @click="handleURL"
244
- type="button"
245
- class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
246
- :class="{
247
- 'bg-myPrimaryLinkColor text-white': editor.isActive('link'),
248
- }"
249
- >
250
- <span class="material-symbols-outlined"> link </span>
251
- <span>Link</span>
252
- </button>
253
- </div>
256
+ <div class="px-2 flex items-center justify-start gap-2">
257
+ <button
258
+ @click="handleURL"
259
+ type="button"
260
+ class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
261
+ :class="{
262
+ 'bg-myPrimaryLinkColor text-white': editor.isActive('link'),
263
+ }"
264
+ >
265
+ <span class="material-symbols-outlined"> link </span>
266
+ <span>Link</span>
267
+ </button>
268
+ </div>
254
269
 
255
- <div class="px-2 flex items-center justify-start gap-2">
256
- <button
257
- @click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
258
- type="button"
259
- class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
260
- :class="{
261
- 'bg-myPrimaryLinkColor text-white': editor.isActive('heading', {
262
- level: 2,
263
- }),
264
- }"
265
- >
266
- <span class="material-symbols-outlined"> titlecase </span>
267
- <span>Header 2</span>
268
- </button>
269
- </div>
270
+ <div class="px-2 flex items-center justify-start gap-2">
271
+ <button
272
+ @click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
273
+ type="button"
274
+ class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
275
+ :class="{
276
+ 'bg-myPrimaryLinkColor text-white': editor.isActive('heading', {
277
+ level: 2,
278
+ }),
279
+ }"
280
+ >
281
+ <span class="material-symbols-outlined"> titlecase </span>
282
+ <span>Header 2</span>
283
+ </button>
284
+ </div>
270
285
 
271
- <div class="px-2 flex items-center justify-start gap-2">
272
- <button
273
- @click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
274
- type="button"
275
- class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
276
- :class="{
277
- 'bg-myPrimaryLinkColor text-white': editor.isActive('heading', {
278
- level: 3,
279
- }),
280
- }"
281
- >
282
- <span class="material-symbols-outlined"> titlecase </span>
283
- <span>Header 3</span>
284
- </button>
285
- </div>
286
+ <div class="px-2 flex items-center justify-start gap-2">
287
+ <button
288
+ @click="editor.chain().focus().toggleHeading({ level: 3 }).run()"
289
+ type="button"
290
+ class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
291
+ :class="{
292
+ 'bg-myPrimaryLinkColor text-white': editor.isActive('heading', {
293
+ level: 3,
294
+ }),
295
+ }"
296
+ >
297
+ <span class="material-symbols-outlined"> titlecase </span>
298
+ <span>Header 3</span>
299
+ </button>
300
+ </div>
286
301
 
287
- <div class="px-2 flex items-center justify-start gap-2">
288
- <button
289
- @click="editor.chain().focus().toggleBulletList().run()"
290
- type="button"
291
- class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
292
- :class="{
293
- 'bg-myPrimaryLinkColor text-white': editor.isActive('bulletList'),
294
- }"
295
- >
296
- <span class="material-symbols-outlined"> list </span>
297
- <span>List</span>
298
- </button>
299
- </div>
300
- </div>
301
- <div>
302
- <div>
303
302
  <div class="px-2 flex items-center justify-start gap-2">
304
303
  <button
305
- @click="pageBuilderStateStore.setShowModalTipTap(false)"
304
+ @click="editor.chain().focus().toggleBulletList().run()"
306
305
  type="button"
307
306
  class="text-[12.5px] gap-2 text-nowrap pl-2 pr-3 w-full h-10 cursor-pointer rounded-full flex items-center border-none justify-center bg-gray-50 hover:bg-myPrimaryLinkColor hover:text-white focus-visible:ring-0"
307
+ :class="{
308
+ 'bg-myPrimaryLinkColor text-white': editor.isActive('bulletList'),
309
+ }"
308
310
  >
309
- <span class="material-symbols-outlined"> Save </span>
310
- <span>Save</span>
311
+ <span class="material-symbols-outlined"> list </span>
312
+ <span>List</span>
311
313
  </button>
312
314
  </div>
313
315
  </div>
314
316
  </div>
315
- </div>
316
317
 
317
- <editor-content
318
- id="page-builder-editor"
319
- :editor="editor"
320
- class="px-4 pt-6 pb-12 bg-white rounded-lg lg:min-h-[20rem] lg:max-h-[30rem] md:min-h-[20rem] md:max-h-[20rem] min-h-[20rem] max-h-[20rem] overflow-y-auto"
321
- />
318
+ <editor-content
319
+ id="page-builder-editor"
320
+ :editor="editor"
321
+ class="px-4 pt-6 pb-12 bg-white rounded-lg lg:min-h-[20rem] lg:max-h-[30rem] md:min-h-[20rem] md:max-h-[20rem] min-h-[20rem] max-h-[20rem] overflow-y-auto"
322
+ />
323
+ </div>
322
324
  </div>
323
325
  </div>
324
326
  </div>
@@ -2,7 +2,7 @@
2
2
  const version = __APP_VERSION__
3
3
  import { onMounted, computed, ref, watch, provide } from 'vue'
4
4
  import { createPinia } from 'pinia'
5
- import PageBuilder from '@/composables/PageBuilder.ts'
5
+ import PageBuilderClass from '@/composables/PageBuilderClass.ts'
6
6
  import PageBuilderPreviewModal from '@/Components/Modals/PageBuilderPreviewModal.vue'
7
7
  import Preview from '@/PageBuilder/Preview.vue'
8
8
  import ComponentTopMenu from '@/Components/PageBuilder/EditorMenu/Editables/ComponentTopMenu.vue'
@@ -12,38 +12,111 @@ import OptionsDropdown from '@/Components/PageBuilder/DropdownsPlusToggles/Optio
12
12
  import RightSidebarEditor from '@/Components/PageBuilder/EditorMenu/RightSidebarEditor.vue'
13
13
  import { usePageBuilderStateStore } from '@/stores/page-builder-state'
14
14
  import { useMediaLibraryStore } from '@/stores/media-library'
15
+ import { useUserStore } from '@/stores/user'
16
+
17
+ /**
18
+ * Props for PageBuilder component
19
+ * @typedef {Object} Props
20
+ * @property {Object|null} CustomMediaLibraryComponent - Custom media component
21
+ * @property {Object|null} CustomSearchComponent - Custom search component
22
+ * @property {string} updateOrCreate - Mode: create or update
23
+ * @property {Object|null} user - User object with name property: { name: string }
24
+ */
25
+ const props = defineProps({
26
+ PageBuilderLogo: {
27
+ type: String,
28
+ default: null,
29
+ },
30
+ CustomMediaLibraryComponent: {
31
+ type: Object,
32
+ default: null,
33
+ },
34
+ CustomSearchComponent: {
35
+ type: Object,
36
+ default: null,
37
+ },
38
+ updateOrCreate: {
39
+ type: String,
40
+ default: 'create',
41
+ required: false,
42
+ },
43
+ userForPageBuilder: {
44
+ type: Object,
45
+ default: null,
46
+ validator: (value) => {
47
+ // Allow null or object with name property
48
+ return value === null || (typeof value === 'object' && typeof value.name === 'string')
49
+ },
50
+ },
51
+ resourceData: {
52
+ type: Object,
53
+ default: null,
54
+ required: false,
55
+ validator: (value) => {
56
+ // Allow null or object with title (string) and id (number) properties
57
+ return (
58
+ value === null ||
59
+ (typeof value === 'object' &&
60
+ typeof value.title === 'string' &&
61
+ typeof value.id === 'number')
62
+ )
63
+ },
64
+ },
65
+ })
66
+
67
+ // Create internal Pinia instance for PageBuilder package
68
+ const internalPinia = createPinia()
69
+ const mediaLibraryStore = useMediaLibraryStore(internalPinia)
70
+ const pageBuilderStateStore = usePageBuilderStateStore(internalPinia)
71
+ const userStore = useUserStore(internalPinia)
15
72
 
16
- // Create internal Pinia instance for this component if none exists
17
- let internalPinia = null
18
- let mediaLibraryStore = null
19
- let pageBuilderStateStore = null
20
- let pageBuilder = null
21
-
22
- try {
23
- // Try to use existing Pinia first
24
- mediaLibraryStore = useMediaLibraryStore()
25
- pageBuilderStateStore = usePageBuilderStateStore()
26
- } catch (error) {
27
- // If no Pinia exists, create our own internal instance
28
- internalPinia = createPinia()
29
- mediaLibraryStore = useMediaLibraryStore(internalPinia)
30
- pageBuilderStateStore = usePageBuilderStateStore(internalPinia)
73
+ // Set logo
74
+ if (props.PageBuilderLogo) {
75
+ pageBuilderStateStore.setPageBuilderLogo(props.PageBuilderLogo)
31
76
  }
32
77
 
78
+ const getPageBuilderLogo = computed(() => {
79
+ return pageBuilderStateStore.getPageBuilderLogo
80
+ })
81
+
82
+ // Set current resource data if provided
83
+ if (props.resourceData) {
84
+ pageBuilderStateStore.setCurrentResourceData(props.resourceData)
85
+ }
86
+ // Set current user if provided
87
+ if (props.userForPageBuilder) {
88
+ userStore.setCurrentUser(props.userForPageBuilder)
89
+ }
90
+
91
+ // Set updateOrCreate in store
92
+ pageBuilderStateStore.setUpdateOrCreate(props.updateOrCreate)
93
+
33
94
  // Initialize PageBuilder with stores
34
- pageBuilder = new PageBuilder(pageBuilderStateStore, mediaLibraryStore)
95
+ const pageBuilderClass = new PageBuilderClass(pageBuilderStateStore, mediaLibraryStore)
96
+
97
+ // Provide stores for child components
98
+ provide('pageBuilderStateStore', pageBuilderStateStore)
99
+ provide('mediaLibraryStore', mediaLibraryStore)
100
+ provide('userStore', userStore)
35
101
 
36
- // Provide the stores for child components if using internal Pinia
37
- if (internalPinia) {
38
- provide('pageBuilderStateStore', pageBuilderStateStore)
39
- provide('mediaLibraryStore', mediaLibraryStore)
102
+ // Provide the internal Pinia instance for components that need to create stores
103
+ provide('internalPinia', internalPinia)
104
+
105
+ // Provide custom components for child components
106
+ provide('CustomMediaComponent', props.CustomMediaLibraryComponent)
107
+ provide('CustomSearchComponent', props.CustomSearchComponent)
108
+
109
+ // Provide modal close function for custom components
110
+ const closeAddComponentModal = () => {
111
+ showModalAddComponent.value = false
40
112
  }
113
+ provide('closeAddComponentModal', closeAddComponentModal)
41
114
 
42
115
  const getMenuRight = computed(() => {
43
116
  return pageBuilderStateStore.getMenuRight
44
117
  })
45
118
  const previewCurrentDesign = function () {
46
- pageBuilder.previewCurrentDesign()
119
+ pageBuilderClass.previewCurrentDesign()
47
120
  }
48
121
  const openPageBuilderPreviewModal = ref(false)
49
122
  const firstPageBuilderPreviewModalButton = ref(null)
@@ -83,8 +156,16 @@ const handleAddComponent = function () {
83
156
  const getComponents = computed(() => {
84
157
  return pageBuilderStateStore.getComponents
85
158
  })
86
- const getComponent = computed(() => {
87
- return pageBuilderStateStore.getComponent
159
+
160
+ const getCurrentUser = computed(() => {
161
+ return userStore.getCurrentUser
162
+ })
163
+
164
+ const getCurrentResourceData = computed(() => {
165
+ return pageBuilderStateStore.getCurrentResourceData
166
+ })
167
+ const getUpdateOrCreate = computed(() => {
168
+ return pageBuilderStateStore.getUpdateOrCreate
88
169
  })
89
170
 
90
171
  const getElement = computed(() => {
@@ -118,8 +199,8 @@ watch(getElementAttributes, (newAttributes, oldAttributes) => {
118
199
  newAttributes?.dataImage !== oldAttributes?.dataImage
119
200
  ) {
120
201
  // Trigger your method when any of the specified attributes change
121
- pageBuilder.handlePageBuilderMethods()
122
- pageBuilder.setEventListenersForElements()
202
+ pageBuilderClass.handlePageBuilderMethods()
203
+ pageBuilderClass.setEventListenersForElements()
123
204
  }
124
205
  })
125
206
 
@@ -130,7 +211,16 @@ const handleSelectComponent = function (componentObject) {
130
211
  const draggableZone = ref(null)
131
212
 
132
213
  onMounted(async () => {
133
- pageBuilder.setEventListenersForElements()
214
+ pageBuilderClass.updateLocalStorageItemName()
215
+ // Set up event listeners
216
+ pageBuilderClass.setEventListenersForElements()
217
+
218
+ //
219
+ //
220
+ //
221
+ //
222
+
223
+ pageBuilderClass.loadExistingContent()
134
224
  })
135
225
  </script>
136
226
 
@@ -141,6 +231,7 @@ onMounted(async () => {
141
231
  :show="showModalAddComponent"
142
232
  :firstButtonText="firstButtonTextSearchComponents"
143
233
  :title="titleModalAddComponent"
234
+ :CustomSearchComponent="props.CustomSearchComponent"
144
235
  @firstModalButtonSearchComponentsFunction="firstModalButtonSearchComponentsFunction"
145
236
  ></SearchComponents>
146
237
  <PageBuilderPreviewModal
@@ -151,6 +242,107 @@ onMounted(async () => {
151
242
  </PageBuilderPreviewModal>
152
243
 
153
244
  <div class="w-full inset-x-0 h-[90vh] z-10 bg-white overflow-x-scroll lg:pt-2 pt-2">
245
+ <!-- Save laylout # start -->
246
+ <div class="p-4 m-8 bg-stone-200 rounded-lg">
247
+ <div
248
+ @click="pageBuilderStateStore.setComponent(null)"
249
+ class="px-4 lg:h-[10vh] h-[16vh] flex items-center justify-between border-b border-gray-200 bg-white"
250
+ >
251
+ <div class="flex items-center justify-start divide-x divide-gray-200">
252
+ <template v-if="getPageBuilderLogo">
253
+ <div class="border-r border-gray-200 pr-6">
254
+ <img class="h-6" :src="getPageBuilderLogo" alt="Logo" />
255
+ </div>
256
+ </template>
257
+ <button
258
+ class="myPrimaryButton lg:text-sm text-[10px] lg:py-2 py-2 min-h-2 ml-4"
259
+ @click="pageBuilderClass.saveComponentsLocalStorage"
260
+ type="button"
261
+ >
262
+ <span class="material-symbols-outlined text-[18px]"> save </span>
263
+ Save layout - saveComponents LocalStorage
264
+ </button>
265
+ <button
266
+ class="myPrimaryButton lg:text-sm text-[10px] lg:py-2 py-2 min-h-2 ml-4 bg-red-500"
267
+ @click="pageBuilderClass.removeItemComponentsLocalStorageCreate"
268
+ type="button"
269
+ >
270
+ <span class="material-symbols-outlined text-[18px]"> delete </span>
271
+ Remove Create Local Storage Item
272
+ </button>
273
+ <button
274
+ class="myPrimaryButton lg:text-sm text-[10px] lg:py-2 py-2 min-h-2 ml-4 bg-red-800"
275
+ @click="pageBuilderClass.removeItemComponentsLocalStorageUpdate"
276
+ type="button"
277
+ >
278
+ <span class="material-symbols-outlined text-[18px]"> delete </span>
279
+ Remove Update Local Storage Item
280
+ </button>
281
+ </div>
282
+ </div>
283
+ </div>
284
+ <!-- Save laylout # end -->
285
+
286
+ <div class="py-4 p-4 bg-red-100 text-sm test-data m-4 rounded-lg">
287
+ <h3 class="font-semibold mb-3 text-gray-800">PageBuilder Debug Info</h3>
288
+ <div class="bg-white rounded border overflow-hidden">
289
+ <table class="min-w-full text-xs">
290
+ <thead class="bg-gray-50">
291
+ <tr>
292
+ <th class="px-3 py-2 text-left font-medium text-gray-700 border-b">Property</th>
293
+ <th class="px-3 py-2 text-left font-medium text-gray-700 border-b">Value</th>
294
+ <th class="px-3 py-2 text-left font-medium text-gray-700 border-b">Type</th>
295
+ <th class="px-3 py-2 text-left font-medium text-gray-700 border-b">Present</th>
296
+ </tr>
297
+ </thead>
298
+ <tbody class="divide-y divide-gray-200">
299
+ <tr>
300
+ <td class="px-3 py-2 font-medium text-gray-600">User (store)</td>
301
+ <td class="px-3 py-2">
302
+ {{ getCurrentUser ? JSON.stringify(getCurrentUser) : 'null' }}
303
+ </td>
304
+ <td class="px-3 py-2 text-gray-500">{{ typeof getCurrentUser }}</td>
305
+ <td class="px-3 py-2 text-gray-500">{{ !!getCurrentUser }}</td>
306
+ </tr>
307
+ <tr>
308
+ <td class="px-3 py-2 font-medium text-gray-600">Update or Create (store)</td>
309
+ <td class="px-3 py-2">{{ getUpdateOrCreate }}</td>
310
+ <td class="px-3 py-2 text-gray-500">{{ typeof getUpdateOrCreate }}</td>
311
+ <td class="px-3 py-2 text-gray-500">{{ !!getUpdateOrCreate }}</td>
312
+ </tr>
313
+ <tr>
314
+ <td class="px-3 py-2 font-medium text-gray-600">Resource Data (store)</td>
315
+ <td class="px-3 py-2">
316
+ {{ getCurrentResourceData ? JSON.stringify(getCurrentResourceData) : 'null' }}
317
+ </td>
318
+ <td class="px-3 py-2 text-gray-500">{{ typeof getCurrentResourceData }}</td>
319
+ <td class="px-3 py-2 text-gray-500">{{ !!getCurrentResourceData }}</td>
320
+ </tr>
321
+ <tr>
322
+ <td class="px-3 py-2 font-medium text-gray-600">Custom Media Component</td>
323
+ <td class="px-3 py-2">
324
+ {{ props.CustomMediaLibraryComponent ? 'Provided' : 'Not provided' }}
325
+ </td>
326
+ <td class="px-3 py-2 text-gray-500">
327
+ {{ props.CustomMediaLibraryComponent ? 'true' : 'false' }}
328
+ </td>
329
+ <td class="px-3 py-2 text-gray-500">{{ !!props.CustomMediaLibraryComponent }}</td>
330
+ </tr>
331
+ <tr>
332
+ <td class="px-3 py-2 font-medium text-gray-600">Custom Search Component</td>
333
+ <td class="px-3 py-2">
334
+ {{ props.CustomSearchComponent ? 'Provided' : 'Not provided' }}
335
+ </td>
336
+ <td class="px-3 py-2 text-gray-500">
337
+ {{ props.CustomSearchComponent ? 'true' : 'false' }}
338
+ </td>
339
+ <td class="px-3 py-2 text-gray-500">{{ !!props.CustomSearchComponent }}</td>
340
+ </tr>
341
+ </tbody>
342
+ </table>
343
+ </div>
344
+ </div>
345
+
154
346
  <div class="relative h-full flex">
155
347
  <div
156
348
  @click.self="pageBuilderStateStore.setComponent(null)"
@@ -250,11 +442,7 @@ onMounted(async () => {
250
442
  </div>
251
443
 
252
444
  <EditGetElement></EditGetElement>
253
- <div
254
- @click="pageBuilderStateStore.setComponent(null)"
255
- id="contains-pagebuilder"
256
- class="pl-4 pr-4 pb-4 overflow-y-auto h-screen pt-1"
257
- >
445
+ <div id="contains-pagebuilder" class="pl-4 pr-4 pb-4 overflow-y-auto h-screen pt-1">
258
446
  <div id="pagebuilder">
259
447
  <div ref="draggableZone">
260
448
  <!-- Added Components to DOM # start -->