@myissue/vue-website-page-builder 3.3.64 → 3.3.67

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 (48) hide show
  1. package/README.md +216 -129
  2. package/dist/logo/mybuilder_new_lowercase.svg +17558 -0
  3. package/dist/vue-website-page-builder.css +1 -1
  4. package/dist/vue-website-page-builder.js +16345 -13089
  5. package/dist/vue-website-page-builder.umd.cjs +78 -54
  6. package/package.json +3 -2
  7. package/src/Components/DemoUnsplash.vue +1 -4
  8. package/src/Components/PageBuilder/EditorMenu/Editables/BackgroundColorEditor.vue +4 -3
  9. package/src/Components/PageBuilder/EditorMenu/Editables/BorderRadius.vue +32 -13
  10. package/src/Components/PageBuilder/EditorMenu/Editables/Borders.vue +12 -8
  11. package/src/Components/PageBuilder/EditorMenu/Editables/ClassEditor.vue +10 -8
  12. package/src/Components/PageBuilder/EditorMenu/Editables/EditGetElement.vue +5 -5
  13. package/src/Components/PageBuilder/EditorMenu/Editables/ManageBackgroundOpacity.vue +12 -9
  14. package/src/Components/PageBuilder/EditorMenu/Editables/ManageOpacity.vue +6 -4
  15. package/src/Components/PageBuilder/EditorMenu/Editables/Margin.vue +11 -5
  16. package/src/Components/PageBuilder/EditorMenu/Editables/OpacityEditor.vue +1 -1
  17. package/src/Components/PageBuilder/EditorMenu/Editables/Padding.vue +11 -5
  18. package/src/Components/PageBuilder/EditorMenu/Editables/StyleEditor.vue +116 -0
  19. package/src/Components/PageBuilder/EditorMenu/Editables/TextColorEditor.vue +2 -1
  20. package/src/Components/PageBuilder/EditorMenu/Editables/Typography.vue +32 -9
  21. package/src/Components/PageBuilder/EditorMenu/RightSidebarEditor.vue +63 -74
  22. package/src/Components/PageBuilder/Settings/PageBuilderSettings.vue +3 -3
  23. package/src/Components/PageBuilder/ToolbarOption/ToolbarOption.vue +14 -11
  24. package/src/PageBuilder/PageBuilder.vue +169 -65
  25. package/src/PageBuilder/Preview.vue +25 -9
  26. package/src/composables/builderInstance.ts +3 -2
  27. package/src/composables/extractCleanHTMLFromPageBuilder.ts +4 -3
  28. package/src/css/app.css +10 -70
  29. package/src/i18n.ts +28 -0
  30. package/src/locales/ar.json +136 -0
  31. package/src/locales/de.json +136 -0
  32. package/src/locales/en.json +136 -0
  33. package/src/locales/es.json +136 -0
  34. package/src/locales/fr.json +136 -0
  35. package/src/locales/hi.json +136 -0
  36. package/src/locales/ja.json +136 -0
  37. package/src/locales/pt.json +136 -0
  38. package/src/locales/ru.json +136 -0
  39. package/src/locales/zh-Hans.json +136 -0
  40. package/src/main.ts +10 -5
  41. package/src/services/LocalStorageManager.ts +1 -162
  42. package/src/services/PageBuilderService.ts +730 -290
  43. package/src/stores/page-builder-state.ts +8 -0
  44. package/src/tests/PageBuilderTest.vue +41 -70
  45. package/src/tests/componentsArray.test.json +3 -3
  46. package/src/tests/pageBuilderService.test.ts +7 -1
  47. package/src/types/index.ts +17 -3
  48. package/src/utils/html-elements/component.ts +10 -10
@@ -13,6 +13,8 @@ import { useDebounce } from '../composables/useDebounce.ts'
13
13
  import DynamicModalBuilder from '../Components/Modals/DynamicModalBuilder.vue'
14
14
  import GlobalLoader from '../Components/Loaders/GlobalLoader.vue'
15
15
  import { getPageBuilder } from '../composables/builderInstance'
16
+ import { useI18n } from 'vue-i18n'
17
+
16
18
  const pageBuilderService = getPageBuilder()
17
19
  /**
18
20
  * Props for PageBuilder component
@@ -34,6 +36,10 @@ const props = defineProps({
34
36
  type: Boolean,
35
37
  default: false,
36
38
  },
39
+ showPublishButton: {
40
+ type: Boolean,
41
+ default: false,
42
+ },
37
43
  })
38
44
 
39
45
  // Use shared Pinia instance for PageBuilder package
@@ -49,11 +55,15 @@ provide('internalPinia', internalPinia)
49
55
  provide('CustomMediaComponent', props.CustomMediaLibraryComponent)
50
56
  provide('CustomBuilderComponents', props.CustomBuilderComponents)
51
57
 
52
- const emit = defineEmits(['handleClosePageBuilder'])
58
+ const emit = defineEmits(['handleClosePageBuilder', 'handlePublishPageBuilder'])
53
59
 
54
60
  const closePageBuilder = function () {
55
61
  emit('handleClosePageBuilder')
56
62
  }
63
+ const closePublish = function () {
64
+ pageBuilderService.handleManualSave()
65
+ emit('handlePublishPageBuilder')
66
+ }
57
67
 
58
68
  // Provide modal close function for custom components
59
69
  const closeAddComponentModal = () => {
@@ -141,6 +151,28 @@ const getHasLocalDraftForUpdate = computed(() => {
141
151
  return pageBuilderStateStore.getHasLocalDraftForUpdate
142
152
  })
143
153
 
154
+ const { locale } = useI18n()
155
+
156
+ watch(locale, (newLocale) => {
157
+ const config = pageBuilderStateStore.getPageBuilderConfig
158
+ if (config && config.userSettings && config.userSettings.language) {
159
+ // Update the store with a full config (if you want to update the store)
160
+ const updatedConfig = {
161
+ ...config,
162
+ userSettings: {
163
+ ...config.userSettings,
164
+ language: {
165
+ ...config.userSettings.language,
166
+ default: newLocale,
167
+ },
168
+ },
169
+ }
170
+
171
+ pageBuilderStateStore.setPageBuilderConfig(updatedConfig)
172
+ pageBuilderService.saveBuilderConfigToLocalStorage(updatedConfig)
173
+ }
174
+ })
175
+
144
176
  watch(getHasLocalDraftForUpdate, (newVal) => {
145
177
  if (newVal) {
146
178
  handlerRumeEditingForUpdate()
@@ -185,8 +217,6 @@ const handleSelectComponent = function (componentObject) {
185
217
  pageBuilderStateStore.setComponent(componentObject)
186
218
  }
187
219
 
188
- const draggableZone = ref(null)
189
-
190
220
  const getIsLoadingGlobal = computed(() => {
191
221
  return pageBuilderStateStore.getIsLoadingGlobal
192
222
  })
@@ -292,10 +322,10 @@ let lastToolbarTop = null
292
322
 
293
323
  function updatePanelPosition() {
294
324
  const container = pbxToolBar.value
295
- const editToolbar = container && container.querySelector('#editToolbar')
325
+ const editToolbarElement = container && container.querySelector('#pbxEditToolbar')
296
326
  const restored = getRestoredElement.value
297
327
 
298
- if (!container || !editToolbar) return
328
+ if (!container || !editToolbarElement) return
299
329
 
300
330
  const selected = container.querySelector('[selected]')
301
331
 
@@ -304,33 +334,41 @@ function updatePanelPosition() {
304
334
  const containerRect = container.getBoundingClientRect()
305
335
 
306
336
  const left =
307
- selectedRect.left - containerRect.left + selectedRect.width / 2 - editToolbar.offsetWidth / 2
337
+ selectedRect.left -
338
+ containerRect.left +
339
+ selectedRect.width / 2 -
340
+ editToolbarElement.offsetWidth / 2
308
341
 
309
342
  const GAP = 20 // px
310
343
  const proposedTop =
311
- selectedRect.top - containerRect.top + container.scrollTop - editToolbar.offsetHeight - GAP
344
+ selectedRect.top -
345
+ containerRect.top +
346
+ container.scrollTop -
347
+ editToolbarElement.offsetHeight -
348
+ GAP
312
349
 
313
350
  const top = Math.max(0, proposedTop)
314
351
 
315
- editToolbar.style.position = 'absolute'
316
- editToolbar.style.left = `${left}px`
317
- editToolbar.style.top = `${top}px`
318
- editToolbar.classList.add('is-visible')
352
+ editToolbarElement.style.position = 'absolute'
353
+ editToolbarElement.style.left = `${left}px`
354
+ editToolbarElement.style.top = `${top}px`
355
+ editToolbarElement.classList.add('is-visible')
319
356
 
320
357
  lastToolbarLeft = left
321
358
  lastToolbarTop = top
322
359
  } else if (restored && lastToolbarLeft !== null && lastToolbarTop !== null) {
323
- editToolbar.style.position = 'absolute'
324
- editToolbar.style.left = `${lastToolbarLeft}px`
325
- editToolbar.style.top = `${lastToolbarTop}px`
326
- editToolbar.classList.add('is-visible')
360
+ editToolbarElement.style.position = 'absolute'
361
+ editToolbarElement.style.left = `${lastToolbarLeft}px`
362
+ editToolbarElement.style.top = `${lastToolbarTop}px`
363
+ editToolbarElement.classList.add('is-visible')
327
364
  } else {
328
- editToolbar.classList.remove('is-visible')
365
+ editToolbarElement.classList.remove('is-visible')
329
366
  }
330
367
  }
331
368
 
332
369
  onMounted(async () => {
333
- await pageBuilderService.completeBuilderInitialization()
370
+ // await delay(2000)
371
+ await pageBuilderService.completeBuilderInitialization(undefined, true)
334
372
 
335
373
  updatePanelPosition()
336
374
 
@@ -525,7 +563,7 @@ onMounted(async () => {
525
563
  ></span>
526
564
  </span>
527
565
  </div>
528
- <div>Save</div>
566
+ <div>{{ $t('button.save') }}</div>
529
567
  </button>
530
568
  <!-- Save End -->
531
569
 
@@ -568,7 +606,7 @@ onMounted(async () => {
568
606
  </span>
569
607
  </div>
570
608
  <div class="lg:pbx-block pbx-hidden">
571
- <span> Reset Page </span>
609
+ <span>{{ $t('button.resetPage') }}</span>
572
610
  </div>
573
611
  </button>
574
612
  </template>
@@ -602,10 +640,12 @@ onMounted(async () => {
602
640
  "
603
641
  >
604
642
  <div
605
- class="pbx-flex pbx-items-center pbx-justify-center pbx-gap-2 pbx-border-0 pbx-border-solid pbx-border-r pbx-border-gray-200 lg:pbx-pr-6"
643
+ class="pbx-flex pbx-items-center pbx-justify-center pbx-gap-2 pbx-border-gray-200"
606
644
  >
607
645
  <span class="lg:pbx-block pbx-hidden">
608
- <div class="pbx-whitespace-nowrap pbx-cursor-pointer">Add new Components</div>
646
+ <div class="pbx-whitespace-nowrap pbx-cursor-pointer">
647
+ {{ $t('button.addComponents') }}
648
+ </div>
609
649
  </span>
610
650
  <span
611
651
  class="pbx-h-10 pbx-w-10 pbx-cursor-pointer pbx-rounded-full pbx-flex pbx-items-center pbx-border-none pbx-justify-center pbx-bg-gray-50 pbx-aspect-square hover:pbx-bg-myPrimaryLinkColor hover:pbx-text-white focus-visible:pbx-ring-0"
@@ -656,18 +696,92 @@ onMounted(async () => {
656
696
  </div>
657
697
  </div>
658
698
  </div>
659
- <!-- Options # Start -->
660
- <div
661
- @click.self="
662
- async () => {
663
- await pageBuilderService.clearHtmlSelection()
664
- }
699
+
700
+ <div class="pbx-flex gap-2 pbx-items-center">
701
+ <!-- Options # Start -->
702
+ <div
703
+ @click.self="
704
+ async () => {
705
+ await pageBuilderService.clearHtmlSelection()
706
+ }
707
+ "
708
+ class="pbx-flex pbx-items-center pbx-py-2 pbx-min-h-20 pbx-max-h-20 pbx-w-full"
709
+ :class="[showCloseButton ? 'pbx-justify-between' : 'pbx-justify-end']"
710
+ >
711
+ <ToolbarOption></ToolbarOption>
712
+ </div>
713
+ <!-- Options # Start -->
714
+ </div>
715
+ <!-- Close & Publish buttons start -->
716
+ <template v-if="showPublishButton">
717
+ <div class="pbx-ml-2">
718
+ <button
719
+ class="pbx-myPrimaryButton"
720
+ @click="
721
+ async () => {
722
+ closePublish()
723
+ await pageBuilderService.clearHtmlSelection()
724
+ }
725
+ "
726
+ >
727
+ {{ $t('button.publish') }}
728
+ </button>
729
+ </div>
730
+ </template>
731
+ <!-- Select language -->
732
+ <template
733
+ v-if="
734
+ getPageBuilderConfig &&
735
+ getPageBuilderConfig.userSettings &&
736
+ getPageBuilderConfig.userSettings.language &&
737
+ !getPageBuilderConfig.userSettings.language.disableLanguageDropDown
665
738
  "
666
- class="pbx-flex pbx-items-center pbx-py-2 pbx-min-h-20 pbx-max-h-20 pbx-w-full"
667
- :class="[showCloseButton ? 'pbx-justify-between' : 'pbx-justify-end']"
668
739
  >
669
- <ToolbarOption></ToolbarOption>
670
- <template v-if="showCloseButton">
740
+ <template
741
+ v-if="
742
+ getPageBuilderConfig &&
743
+ getPageBuilderConfig.userSettings &&
744
+ getPageBuilderConfig.userSettings.language
745
+ "
746
+ >
747
+ <div class="pbx-flex pbx-justify-center pbx-items-center pbx-ml-2">
748
+ <select
749
+ class="pbx-myPrimarySelect pbx-min-w-20 pbx-max-w-2pbx-min-w-20 pbx-w-max"
750
+ v-model="$i18n.locale"
751
+ >
752
+ <template
753
+ v-if="
754
+ Array.isArray(getPageBuilderConfig.userSettings.language.enable) &&
755
+ getPageBuilderConfig.userSettings.language.enable.length >= 1
756
+ "
757
+ >
758
+ <template
759
+ v-for="lang in pageBuilderService
760
+ .availableLanguage()
761
+ .filter((l) => getPageBuilderConfig.userSettings.language.enable.includes(l))"
762
+ :key="lang"
763
+ >
764
+ <option :value="lang">{{ lang }}</option>
765
+ </template>
766
+ </template>
767
+ <template
768
+ v-if="
769
+ !getPageBuilderConfig.userSettings.language.enable ||
770
+ (Array.isArray(getPageBuilderConfig.userSettings.language.enable) &&
771
+ getPageBuilderConfig.userSettings.language.enable.length === 0)
772
+ "
773
+ >
774
+ <template v-for="lang in pageBuilderService.availableLanguage()" :key="lang">
775
+ <option :value="lang">{{ lang }}</option>
776
+ </template>
777
+ </template>
778
+ </select>
779
+ </div>
780
+ </template>
781
+ </template>
782
+
783
+ <template v-if="showCloseButton">
784
+ <div class="pbx-ml-2">
671
785
  <button
672
786
  class="pbx-h-10 pbx-w-10 pbx-flex-end pbx-cursor-pointer pbx-rounded-full pbx-flex pbx-items-center pbx-border-none pbx-justify-center pbx-bg-gray-50 pbx-aspect-square hover:pbx-bg-myPrimaryLinkColor hover:pbx-text-white hover:pbx-fill-white focus-visible:pbx-ring-0"
673
787
  @click="
@@ -679,9 +793,10 @@ onMounted(async () => {
679
793
  >
680
794
  <span class="material-symbols-outlined"> close </span>
681
795
  </button>
682
- </template>
683
- </div>
684
- <!-- Options # Start -->
796
+ </div>
797
+ </template>
798
+
799
+ <!-- Close & Publish buttons end -->
685
800
  </div>
686
801
 
687
802
  <!-- Top Layout Save And Reset Area - End -->
@@ -728,12 +843,11 @@ onMounted(async () => {
728
843
  :class="{ 'pbx-mr-2': !getMenuRight, '': getMenuRight }"
729
844
  >
730
845
  <div
731
- id="editToolbar"
732
- class="pbx-z-30 lg:pbx-mx-20 pbx-flex pbx-gap-2 pbx-justify-center pbx-min-w-72 pbx-items-center pbx-rounded-full pbx-px-4 pbx-bg-red-200 pbx-h-0"
846
+ id="pbxEditToolbar"
847
+ class="pbx-z-30 lg:pbx-mx-20 pbx-flex pbx-gap-2 pbx-justify-center pbx-items-center pbx-rounded pbx-px-4 pbx-bg-red-200 pbx-h-0"
733
848
  style="
734
849
  box-shadow: 0 0 0 10px oklch(86.9% 0.005 56.366);
735
850
  background: oklch(86.9% 0.005 56.366);
736
- border-radius: 9999px;
737
851
  "
738
852
  >
739
853
  <template v-if="getElement">
@@ -751,26 +865,14 @@ onMounted(async () => {
751
865
  </div>
752
866
  <!-- Element Popover toolbar end -->
753
867
 
754
- <div
755
- id="contains-pagebuilder"
756
- class="pbx-pl-4 pbx-pr-4 pbx-pb-4 pbx-pt-1 pbx-h-full pbx-overflow-y-auto"
757
- >
758
- <div id="pagebuilder" class="pbx-text-black pbx-font-sans">
759
- <div ref="draggableZone">
760
- <!-- Added Components to DOM # start -->
761
- <div
762
- v-for="component in getComponents"
763
- :key="component.id"
764
- id="page-builder-editor-editable-area"
765
- class="pbx-bg-white pbx-grow"
766
- >
767
- <div @mouseup="handleSelectComponent(component)" class="pbx-relative group">
768
- <div v-html="component.html_code"></div>
769
- </div>
770
- </div>
771
- <!-- Added Components to DOM # end -->
772
- </div>
773
- </div>
868
+ <div id="pagebuilder" class="pbx-text-black pbx-font-sans">
869
+ <template v-for="component in getComponents" :key="component.id">
870
+ <section
871
+ v-if="component.html_code"
872
+ v-html="component.html_code"
873
+ @mouseup="handleSelectComponent(component)"
874
+ ></section>
875
+ </template>
774
876
  </div>
775
877
  </main>
776
878
 
@@ -781,7 +883,7 @@ onMounted(async () => {
781
883
  await pageBuilderService.clearHtmlSelection()
782
884
  }
783
885
  "
784
- class="pbx-min-w-[3.5rem] pbx-pt-7 pbx-pb-2 pbx-ml-2 pbx-border-l-solid pbx-border-gray-200"
886
+ class="pbx-min-w-[3rem] pbx-pt-6 pbx-pb-2"
785
887
  >
786
888
  <div
787
889
  @click.self="
@@ -789,15 +891,16 @@ onMounted(async () => {
789
891
  await pageBuilderService.clearHtmlSelection()
790
892
  }
791
893
  "
792
- class="pbx-flex pbx-items-center pbx-justify-center pbx-gap-4"
894
+ class="pbx-flex pbx-flex-col pbx-items-center pbx-justify-center pbx-gap-2"
793
895
  >
794
896
  <button
795
- type="button"
796
897
  v-if="!getMenuRight"
797
898
  @click="pageBuilderStateStore.setMenuRight(true)"
798
- class="pbx-h-10 pbx-w-10 pbx-cursor-pointer pbx-rounded-full pbx-flex pbx-items-center pbx-border-none pbx-justify-center pbx-bg-gray-50 pbx-aspect-square hover:pbx-bg-myPrimaryLinkColor hover:pbx-text-white focus-visible:pbx-ring-0"
899
+ type="button"
900
+ class="pbx-mySecondaryButton"
799
901
  >
800
- <span class="material-symbols-outlined"> palette </span>
902
+ <span class="material-symbols-outlined"> view_sidebar </span>
903
+ <span> Tools </span>
801
904
  </button>
802
905
  </div>
803
906
  </div>
@@ -806,15 +909,16 @@ onMounted(async () => {
806
909
  aria-label="Menu"
807
910
  id="pagebuilder-right-area"
808
911
  :class="{
809
- 'pbx-w-0': !getMenuRight,
912
+ 'pbx-w-0 pbx-mr-0': !getMenuRight,
810
913
  'pbx-w-80 pbx-mr-2 pbx-bg-myPrimaryLightGrayColor pbx-items-stretch': getMenuRight,
811
914
  }"
812
- class="pbx-duration-300 pbx-z-20 pbx-flex-shrink-0 pbx-overflow-hidden pbx-shadow-sm pbx-rounded-l-2xl pbx-h-[100vh]"
915
+ class="pbx-duration-100 pbx-z-20 pbx-flex-shrink-0 pbx-overflow-hidden pbx-shadow-sm pbx-rounded-l-2xl pbx-h-[100vh]"
813
916
  >
814
917
  <RightSidebarEditor @closeEditor="pageBuilderStateStore.setMenuRight(false)">
815
918
  </RightSidebarEditor>
816
919
  </aside>
817
920
  </div>
921
+
818
922
  <div
819
923
  class="pbx-flex pbx-items-center pbx-justify-center pbx-p-4 pbx-border-0 pbx-border-t pbx-border-t-gray-200 pbx-border-solid lg:pbx-mx-10"
820
924
  >
@@ -828,7 +932,7 @@ onMounted(async () => {
828
932
  class="pbx-flex pbx-items-center pbx-justify-center pbx-gap-2 pbx-cursor-pointer"
829
933
  >
830
934
  <span class="lg:pbx-block pbx-hidden">
831
- <div class="pbx-whitespace-nowrap">Add to the bottom</div>
935
+ <div class="pbx-whitespace-nowrap">{{ $t('button.addComponentsToBottom') }}</div>
832
936
  </span>
833
937
  <div class="pbx-flex pbx-gap-2 pbx-items-center pbx-justify-center">
834
938
  <button
@@ -1,13 +1,14 @@
1
1
  <script setup>
2
- import { ref } from 'vue'
2
+ import { ref, watchEffect } from 'vue'
3
3
 
4
- defineProps({
4
+ const props = defineProps({
5
5
  mobile: {
6
6
  type: Boolean,
7
7
  },
8
8
  })
9
9
 
10
10
  const htmlPage = ref('')
11
+ const iframeRef = ref(null)
11
12
 
12
13
  const previewData = localStorage.getItem('preview')
13
14
 
@@ -20,6 +21,23 @@ if (previewData) {
20
21
  htmlPage.value = ''
21
22
  }
22
23
  }
24
+
25
+ watchEffect(() => {
26
+ if (props.mobile && iframeRef.value && htmlPage.value) {
27
+ const iframe = iframeRef.value
28
+ const doc = iframe.contentWindow.document
29
+ doc.open()
30
+ doc.write(
31
+ `<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width, initial-scale=1.0"></head><body>${htmlPage.value}</body></html>`,
32
+ )
33
+ doc.close()
34
+
35
+ // Copy stylesheets
36
+ document.querySelectorAll('link[rel="stylesheet"], style').forEach((node) => {
37
+ doc.head.appendChild(node.cloneNode(true))
38
+ })
39
+ }
40
+ })
23
41
  </script>
24
42
 
25
43
  <template>
@@ -36,13 +54,11 @@ if (previewData) {
36
54
  </template>
37
55
  <template v-if="mobile">
38
56
  <div>
39
- <div
40
- class="pbx-text-black pbx-w-full pbx-inset-x-0 pbx-h-[90vh] pbx-bg-white pbx-overflow-x-scroll lg:pbx-pt-2 pbx-pt-2"
41
- >
42
- <div id="page-builder-editor">
43
- <div class="" v-html="htmlPage"></div>
44
- </div>
45
- </div>
57
+ <iframe
58
+ ref="iframeRef"
59
+ class="pbx-mx-auto pbx-w-full pbx-bg-white pbx-shadow-lg pbx-h-[80vh] pbx-border-0"
60
+ src="about:blank"
61
+ ></iframe>
46
62
  </div>
47
63
  </template>
48
64
  </template>
@@ -1,15 +1,16 @@
1
1
  // builderInstance.ts
2
2
  import { PageBuilderService } from '../services/PageBuilderService'
3
+ import type { I18n } from 'vue-i18n'
3
4
  import { sharedPageBuilderStore } from '../stores/shared-store'
4
5
 
5
6
  // Singleton instance
6
7
  let instance: PageBuilderService | null = null
7
8
 
8
9
  // Used to create and store the single instance
9
- export function initPageBuilder(): PageBuilderService {
10
+ export function initPageBuilder(i18n: I18n): PageBuilderService {
10
11
  if (!instance) {
11
12
  const pageBuilderStateStore = sharedPageBuilderStore
12
- instance = new PageBuilderService(pageBuilderStateStore)
13
+ instance = new PageBuilderService(pageBuilderStateStore, i18n)
13
14
  }
14
15
  return instance
15
16
  }
@@ -25,14 +25,15 @@ export function extractCleanHTMLFromPageBuilder(
25
25
  }
26
26
  })
27
27
 
28
- if (config && config.pageSettings && typeof config.pageSettings.imageUrlPrefix === 'string') {
29
- const imageUrlPrefix = config.pageSettings.imageUrlPrefix
28
+ if (config && config && typeof config.imageUrlPrefix === 'string') {
29
+ const imageUrlPrefix = config.imageUrlPrefix
30
30
  const imgs = clone.querySelectorAll<HTMLImageElement>('img')
31
31
  imgs.forEach((img) => {
32
32
  const src = img.getAttribute('src') || ''
33
33
  if (
34
34
  !src.startsWith('http') &&
35
- imageUrlPrefix && // extra safety
35
+ // extra safety
36
+ imageUrlPrefix &&
36
37
  !src.startsWith(imageUrlPrefix)
37
38
  ) {
38
39
  img.setAttribute('src', imageUrlPrefix + src.replace(/^\/+/, ''))
package/src/css/app.css CHANGED
@@ -384,33 +384,10 @@
384
384
  margin-left: 1em; /* Adjust this value as needed */
385
385
  }
386
386
 
387
- #settingsPanel {
388
- border-radius: 9999px;
389
- position: absolute;
390
- opacity: 0;
391
- pointer-events: none;
392
- transform: translateY(1rem);
393
- transition:
394
- opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
395
- transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
396
- box-shadow:
397
- 0 8px 24px rgba(0, 0, 0, 0.08),
398
- 0 1.5px 4px rgba(0, 0, 0, 0.06);
399
- }
400
-
401
- [selected]:hover #settingsPanel,
402
- [selected]:focus-within #settingsPanel {
403
- opacity: 1;
404
- pointer-events: auto;
405
- transform: translateY(0);
406
- }
407
-
408
- #editToolbar {
387
+ #pbxEditToolbar {
409
388
  opacity: 0;
410
389
  pointer-events: none;
411
390
  transform: translateY(0.1rem) scale(0.1);
412
-
413
- border-radius: 9999px;
414
391
  transition:
415
392
  left 0.3s cubic-bezier(0.4, 0, 0.2, 1),
416
393
  top 0.3s cubic-bezier(0.4, 0, 0.2, 1),
@@ -422,28 +399,23 @@
422
399
  border-radius 0.3s cubic-bezier(0.4, 0, 0.2, 1);
423
400
  }
424
401
 
425
- #editToolbar.is-visible {
402
+ #pbxEditToolbar.is-visible {
426
403
  opacity: 1;
427
404
  pointer-events: auto;
428
405
  transform: translateY(0) scale(1);
429
- min-width: 20rem;
430
- width: 20rem;
431
- height: 2.5rem;
432
- border-radius: 9999px;
433
- }
434
-
435
- #contains-pagebuilder {
436
- position: relative; /* make this the positioning context for absolute children */
437
- overflow-y: auto;
438
- }
439
-
440
- .smooth-transition {
441
- transition: opacity 0.3s ease-in-out;
406
+ min-width: 4rem;
407
+ padding-right: 1rem;
408
+ padding-left: 1rem;
409
+ height: 2.2rem;
442
410
  }
443
411
 
444
412
  /* Manage P, Link, H1, H2 # end */
445
413
 
446
414
  /* CSS for content inside page builder # start */
415
+ #pagebuilder {
416
+ position: relative;
417
+ overflow-y: auto;
418
+ }
447
419
  #pagebuilder a {
448
420
  pointer-events: none;
449
421
  }
@@ -519,38 +491,6 @@
519
491
  padding: 0rem;
520
492
  }
521
493
 
522
- /* Add overflow-x property to enable horizontal scrollbar */
523
- .scrollable {
524
- overflow-x: auto;
525
- overflow-y: auto;
526
- /* Add any other desired styles for the scrollable element */
527
- }
528
- /* Scrollbar Styles - end */
529
-
530
- /* Scrollbar Styles - start */
531
- /* Firefox */
532
- * {
533
- scrollbar-width: thin;
534
- scrollbar-color: black transparent;
535
- }
536
-
537
- *::-webkit-scrollbar-track {
538
- background: transparent;
539
- border-radius: 25px;
540
- }
541
-
542
- /* Chrome, Edge, and Safari */
543
- *::-webkit-scrollbar {
544
- width: 6px;
545
- height: 6px; /* Add height for horizontal scrollbar */
546
- }
547
-
548
- *::-webkit-scrollbar-thumb {
549
- background-color: black;
550
- border-radius: 25px;
551
- border: none;
552
- }
553
-
554
494
  #pagebuilder[data-global-selected] {
555
495
  outline: 4px dashed #b91010 !important;
556
496
  outline-offset: -2px !important;
package/src/i18n.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { createI18n } from 'vue-i18n'
2
+
3
+ // Function to load all locale messages from JSON files
4
+ async function loadLocaleMessages() {
5
+ const locales = import.meta.glob('./locales/*.json')
6
+ const messages: Record<string, object> = {}
7
+ for (const path in locales) {
8
+ const matched = path.match(/([A-Za-z0-9-_]+)\.json$/i)
9
+ if (matched && matched.length > 1) {
10
+ const locale = matched[1]
11
+ const module = (await locales[path]()) as { default: object }
12
+ messages[locale] = module.default
13
+ }
14
+ }
15
+ return messages
16
+ }
17
+
18
+ // Use this in main.ts: const i18n = await setupI18n()
19
+ export async function setupI18n() {
20
+ const messages = await loadLocaleMessages()
21
+ return createI18n({
22
+ legacy: false, // you must set `false`, to use Composition API
23
+ locale: 'en', // set locale
24
+ fallbackLocale: 'en', // set fallback locale
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ messages: messages as any, // typecast to satisfy vue-i18n
27
+ })
28
+ }