@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myissue/vue-website-page-builder",
3
- "version": "3.3.64",
3
+ "version": "3.3.67",
4
4
  "description": "Vue 3 page builder component with drag & drop functionality.",
5
5
  "type": "module",
6
6
  "main": "./dist/vue-website-page-builder.umd.cjs",
@@ -50,7 +50,7 @@
50
50
  "bugs": {
51
51
  "url": "https://github.com/qaiswardag/vue-website-page-builder/issues"
52
52
  },
53
- "homepage": "https://www.builder-demo.myissue.dk/",
53
+ "homepage": "https://mybuilder.dev",
54
54
  "engines": {
55
55
  "node": ">=18.0.0",
56
56
  "npm": ">=8.0.0"
@@ -79,6 +79,7 @@
79
79
  "pinia": "^2.1.7",
80
80
  "uuid": "^9.0.0",
81
81
  "vue": "^3.5.13",
82
+ "vue-i18n": "^11.1.9",
82
83
  "vue-website-page-builder": "file:"
83
84
  },
84
85
  "devDependencies": {
@@ -96,13 +96,10 @@ const nextPage = async function () {
96
96
  }
97
97
 
98
98
  const applySelectedImage = async function (imageURL) {
99
- // Ensure the current image is set in the store with proper structure
100
- pageBuilderService.stageImageForSelectedElement({
99
+ await pageBuilderService.applySelectedImage({
101
100
  src: `${imageURL}`,
102
101
  })
103
102
 
104
- await pageBuilderService.applyPendingImageToSelectedElement()
105
-
106
103
  closeMediaLibraryModal()
107
104
  }
108
105
 
@@ -49,7 +49,7 @@ watch(
49
49
  class="pbx-aspect-square pbx-w-6 pbx-h-6 pbx-border pbx-border-gray-800 pbx-rounded-sm"
50
50
  :class="`pbx-bg-${backgroundColor?.replace('pbx-bg-', '')}`"
51
51
  ></div>
52
- <div>Background Color</div>
52
+ <div>{{ $t('backgroundColorEditor.label') }}</div>
53
53
  </div>
54
54
 
55
55
  <span v-if="globalPageLayout" class="material-symbols-outlined"> chevron_right </span>
@@ -57,12 +57,13 @@ watch(
57
57
 
58
58
  <ListboxButton
59
59
  v-if="!globalPageLayout"
60
- 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-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
60
+ 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-200 pbx-aspect-square hover:pbx-bg-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
61
61
  >
62
62
  <div class="pbx-flex pbx-flex-col">
63
63
  <div class="pbx-flex pbx-gap-2 pbx-items-center">
64
64
  <span
65
65
  class="material-symbols-outlined"
66
+ style="text-shadow: rgb(0 0 0 / 10%) 1.5px 1.5px 0px"
66
67
  :class="`pbx-text-${backgroundColor?.replace('pbx-bg-', '')}`"
67
68
  >
68
69
  format_color_fill
@@ -98,7 +99,7 @@ watch(
98
99
  >
99
100
  <div v-if="color === 'none'" class="pbx-flex pbx-items-center">
100
101
  <span class="material-symbols-outlined"> ev_shadow </span>
101
- <span class="pbx-ml-3">Transparent</span>
102
+ <span class="pbx-ml-3">{{ $t('backgroundColorEditor.transparent') }}</span>
102
103
  </div>
103
104
  <div v-if="color !== 'none'" class="pbx-flex pbx-items-center">
104
105
  <div
@@ -73,17 +73,22 @@ watch(
73
73
 
74
74
  <template>
75
75
  <EditorAccordion>
76
- <template #title>Border Radius</template>
76
+ <template #title>{{ $t('borderRadius.title') }}</template>
77
77
  <template #content>
78
- <p class="pbx-myPrimaryParagraph pbx-font-medium pbx-py-0 pbx-my-4">Global</p>
78
+ <p class="pbx-myPrimaryParagraph pbx-font-medium pbx-py-0 pbx-my-4">
79
+ {{ $t('borderRadius.global') }}
80
+ </p>
79
81
  <div class="pbx-my-2 pbx-py-2">
80
- <label class="pbx-myPrimaryInputLabel"> Border Radius </label>
82
+ <label for="global-border-radius" class="pbx-myPrimaryInputLabel">{{
83
+ $t('borderRadius.label')
84
+ }}</label>
81
85
  <select
86
+ id="global-border-radius"
82
87
  v-model="borderRadiusGlobal"
83
88
  class="pbx-myPrimarySelect"
84
89
  @change="pageBuilderService.handleBorderRadiusGlobal(borderRadiusGlobal)"
85
90
  >
86
- <option disabled value="">Select</option>
91
+ <option disabled value="">{{ $t('borderRadius.select') }}</option>
87
92
  <option
88
93
  v-for="borderRadiusGlobal in tailwindBorderRadius.roundedGlobal"
89
94
  :key="borderRadiusGlobal"
@@ -92,15 +97,20 @@ watch(
92
97
  </option>
93
98
  </select>
94
99
  </div>
95
- <p class="pbx-myPrimaryParagraph pbx-font-medium pbx-py-0 pbx-my-4">Specific</p>
100
+ <p class="pbx-myPrimaryParagraph pbx-font-medium pbx-py-0 pbx-my-4">
101
+ {{ $t('borderRadius.specific') }}
102
+ </p>
96
103
  <div class="pbx-my-2 pbx-py-2">
97
- <label class="pbx-myPrimaryInputLabel"> Border Radius top left </label>
104
+ <label for="border-radius-top-left" class="pbx-myPrimaryInputLabel">
105
+ {{ $t('borderRadius.topLeft') }}
106
+ </label>
98
107
  <select
108
+ id="border-radius-top-left"
99
109
  v-model="borderRadiusTopLeft"
100
110
  class="pbx-myPrimarySelect"
101
111
  @change="pageBuilderService.handleBorderRadiusTopLeft(borderRadiusTopLeft)"
102
112
  >
103
- <option disabled value="">Select</option>
113
+ <option disabled value="">{{ $t('borderRadius.select') }}</option>
104
114
  <option
105
115
  v-for="borderRadiusTopLeft in tailwindBorderRadius.roundedTopLeft"
106
116
  :key="borderRadiusTopLeft"
@@ -110,13 +120,16 @@ watch(
110
120
  </select>
111
121
  </div>
112
122
  <div class="pbx-my-2 pbx-py-2">
113
- <label class="pbx-myPrimaryInputLabel"> Border Radius top right </label>
123
+ <label for="border-radius-top-right" class="pbx-myPrimaryInputLabel">
124
+ {{ $t('borderRadius.topRight') }}
125
+ </label>
114
126
  <select
127
+ id="border-radius-top-right"
115
128
  v-model="borderRadiusTopRight"
116
129
  class="pbx-myPrimarySelect"
117
130
  @change="pageBuilderService.handleBorderRadiusTopRight(borderRadiusTopRight)"
118
131
  >
119
- <option disabled value="">Select</option>
132
+ <option disabled value="">{{ $t('borderRadius.select') }}</option>
120
133
  <option
121
134
  v-for="borderRadiusTopRight in tailwindBorderRadius.roundedTopRight"
122
135
  :key="borderRadiusTopRight"
@@ -126,13 +139,16 @@ watch(
126
139
  </select>
127
140
  </div>
128
141
  <div class="pbx-my-2 pbx-py-2">
129
- <label class="pbx-myPrimaryInputLabel"> Border Radius bottom left </label>
142
+ <label for="border-radius-bottom-left" class="pbx-myPrimaryInputLabel">
143
+ {{ $t('borderRadius.bottomLeft') }}
144
+ </label>
130
145
  <select
146
+ id="border-radius-bottom-left"
131
147
  v-model="borderRadiusBottomleft"
132
148
  class="pbx-myPrimarySelect"
133
149
  @change="pageBuilderService.handleBorderRadiusBottomleft(borderRadiusBottomleft)"
134
150
  >
135
- <option disabled value="">Select</option>
151
+ <option disabled value="">{{ $t('borderRadius.select') }}</option>
136
152
  <option
137
153
  v-for="borderRadiusBottomleft in tailwindBorderRadius.roundedBottomLeft"
138
154
  :key="borderRadiusBottomleft"
@@ -142,13 +158,16 @@ watch(
142
158
  </select>
143
159
  </div>
144
160
  <div class="pbx-my-2 pbx-py-2">
145
- <label class="pbx-myPrimaryInputLabel"> Border Radius bottom right </label>
161
+ <label for="border-radius-bottom-right" class="pbx-myPrimaryInputLabel">
162
+ {{ $t('borderRadius.bottomRight') }}
163
+ </label>
146
164
  <select
165
+ id="border-radius-bottom-right"
147
166
  v-model="borderRadiusBottomRight"
148
167
  class="pbx-myPrimarySelect"
149
168
  @change="pageBuilderService.handleBorderRadiusBottomRight(borderRadiusBottomRight)"
150
169
  >
151
- <option disabled value="">Select</option>
170
+ <option disabled value="">{{ $t('borderRadius.select') }}</option>
152
171
  <option
153
172
  v-for="borderRadiusBottomRight in tailwindBorderRadius.roundedBottomRight"
154
173
  :key="borderRadiusBottomRight"
@@ -52,18 +52,21 @@ watch(
52
52
 
53
53
  <template>
54
54
  <EditorAccordion>
55
- <template #title>Border Style, Width & Color</template>
55
+ <template #title>{{ $t('borders.title') }}</template>
56
56
  <template #content>
57
- <p class="pbx-myPrimaryParagraph pbx-font-medium pbx-py-0 pbx-my-4">Border</p>
57
+ <p class="pbx-myPrimaryParagraph pbx-font-medium pbx-py-0 pbx-my-4">
58
+ {{ $t('borders.border') }}
59
+ </p>
58
60
 
59
61
  <div class="pbx-my-2 pbx-py-2">
60
- <label class="pbx-myPrimaryInputLabel"> Border Style </label>
62
+ <label for="border-style" class="pbx-myPrimaryInputLabel">{{ $t('borders.style') }}</label>
61
63
  <select
64
+ id="border-style"
62
65
  v-model="borderStyle"
63
66
  class="pbx-myPrimarySelect"
64
67
  @change="pageBuilderService.handleBorderStyle(borderStyle)"
65
68
  >
66
- <option disabled value="">Select</option>
69
+ <option disabled value="">{{ $t('borders.select') }}</option>
67
70
  <option
68
71
  v-for="borderStyle in tailwindBorderStyleWidthPlusColor.borderStyle"
69
72
  :key="borderStyle"
@@ -73,13 +76,14 @@ watch(
73
76
  </select>
74
77
  </div>
75
78
  <div class="pbx-my-2 pbx-py-2">
76
- <label class="pbx-myPrimaryInputLabel"> Border Width </label>
79
+ <label for="border-width" class="pbx-myPrimaryInputLabel">{{ $t('borders.width') }}</label>
77
80
  <select
81
+ id="border-width"
78
82
  v-model="borderWidth"
79
83
  class="pbx-myPrimarySelect"
80
84
  @change="pageBuilderService.handleBorderWidth(borderWidth)"
81
85
  >
82
- <option disabled value="">Select</option>
86
+ <option disabled value="">{{ $t('borders.select') }}</option>
83
87
  <option
84
88
  v-for="borderWidth in tailwindBorderStyleWidthPlusColor.borderWidth"
85
89
  :key="borderWidth"
@@ -89,10 +93,10 @@ watch(
89
93
  </select>
90
94
  </div>
91
95
 
92
- <label class="pbx-myPrimaryInputLabel"> Border Color </label>
96
+ <label for="border-color" class="pbx-myPrimaryInputLabel">{{ $t('borders.color') }}</label>
93
97
  <Listbox as="div" v-model="borderColor">
94
98
  <div class="pbx-relative pbx-mt-2">
95
- <ListboxButton class="pbx-myPrimarySelect">
99
+ <ListboxButton class="pbx-myPrimarySelect" id="border-color">
96
100
  <span class="pbx-flex pbx-items-center pbx-gap-2">
97
101
  <div v-if="getBorderColor === 'none'">
98
102
  <div class="pbx-myPrimaryColorPreview pbx-border-none">
@@ -50,11 +50,10 @@ const handleAddClasses = async () => {
50
50
 
51
51
  <template>
52
52
  <EditorAccordion>
53
- <template #title>Generated CSS</template>
53
+ <template #title>{{ $t('classEditor.title') }}</template>
54
54
  <template #content>
55
55
  <label class="pbx-myPrimaryInputLabel pbx-my-4">
56
- This is the CSS applied by the builder. Add your own CSS and press Enter to apply it to the
57
- selected element.
56
+ {{ $t('classEditor.info') }}
58
57
  </label>
59
58
 
60
59
  <div class="pbx-flex pbx-flex-row pbx-flex-wrap pbx-gap-2 pbx-mt-2 pbx-mb-4">
@@ -78,22 +77,25 @@ const handleAddClasses = async () => {
78
77
  </div>
79
78
 
80
79
  <div>
81
- <label class="pbx-myPrimaryInputLabel">
82
- Add your CSS.
80
+ <label for="custom-css" class="pbx-myPrimaryInputLabel">
81
+ {{ $t('classEditor.add') }}
83
82
  <br />
84
- The pbx- prefix is added automatically.
83
+ {{ $t('classEditor.prefix') }}
85
84
  </label>
86
85
  <div class="pbx-flex pbx-gap-2 pbx-item-center">
87
86
  <input
87
+ id="custom-css"
88
88
  v-model="inputClass"
89
89
  type="text"
90
- placeholder="Type class"
90
+ :placeholder="$t('classEditor.placeholder')"
91
91
  @keydown.enter="handleAddClasses()"
92
92
  autocomplete="off"
93
93
  class="pbx-myPrimaryInput"
94
94
  />
95
95
 
96
- <button @click="handleAddClasses" type="button" class="pbx-myPrimaryButton">Add</button>
96
+ <button @click="handleAddClasses" type="button" class="pbx-myPrimaryButton">
97
+ {{ $t('classEditor.addButton') }}
98
+ </button>
97
99
  </div>
98
100
  </div>
99
101
  <p v-if="errorMessage" class="pbx-myPrimaryInputError">{{ errorMessage }}</p>
@@ -273,7 +273,7 @@ const getRestoredElement = computed(() => {
273
273
  <button
274
274
  @click="handleModalIframeSrc"
275
275
  type="button"
276
- 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-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
276
+ 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-200 pbx-aspect-square hover:pbx-bg-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
277
277
  >
278
278
  <span class="material-symbols-outlined"> play_circle </span>
279
279
  </button>
@@ -290,7 +290,7 @@ const getRestoredElement = computed(() => {
290
290
  <button
291
291
  @click="handleModalPreviewTiptap"
292
292
  type="button"
293
- 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-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
293
+ 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-200 pbx-aspect-square hover:pbx-bg-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
294
294
  >
295
295
  <span class="material-symbols-outlined"> edit </span>
296
296
  </button>
@@ -310,7 +310,7 @@ const getRestoredElement = computed(() => {
310
310
  <button
311
311
  @click="handleAddImage"
312
312
  type="button"
313
- 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-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
313
+ 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-200 pbx-aspect-square hover:pbx-bg-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
314
314
  >
315
315
  <span class="material-symbols-outlined"> add_photo_alternate </span>
316
316
  </button>
@@ -332,7 +332,7 @@ const getRestoredElement = computed(() => {
332
332
  <button
333
333
  @click="pageBuilderService.deleteElementFromDOM"
334
334
  type="button"
335
- 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-red-500 hover:pbx-fill-white focus-visible:pbx-ring-0"
335
+ 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-200 pbx-aspect-square hover:pbx-bg-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
336
336
  >
337
337
  <span class="material-symbols-outlined"> delete </span>
338
338
  </button>
@@ -340,7 +340,7 @@ const getRestoredElement = computed(() => {
340
340
 
341
341
  <div
342
342
  v-if="getElement && getComponent"
343
- 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-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
343
+ 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-200 pbx-aspect-square hover:pbx-bg-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
344
344
  @click="pageBuilderService.clearHtmlSelection()"
345
345
  >
346
346
  <span class="material-symbols-outlined"> close </span>
@@ -32,11 +32,13 @@ watch(
32
32
 
33
33
  <template>
34
34
  <div class="pbx-my-2 pbx-py-2">
35
- <label class="pbx-myPrimaryInputLabel"> Background opacity</label>
35
+ <label for="bg-opacity" class="pbx-myPrimaryInputLabel">{{
36
+ $t('backgroundOpacity.label')
37
+ }}</label>
36
38
 
37
39
  <Listbox as="div" v-model="opacityVueModel">
38
40
  <div class="pbx-relative">
39
- <ListboxButton class="pbx-myPrimarySelect">
41
+ <ListboxButton class="pbx-myPrimarySelect" id="bg-opacity">
40
42
  <span class="pbx-flex pbx-items-center pbx-gap-2">
41
43
  <div v-if="opacityVueModel === 'none'">
42
44
  <div class="pbx-myPrimaryColorPreview pbx-border-none">
@@ -51,7 +53,7 @@ watch(
51
53
  ></div>
52
54
 
53
55
  <span class="pbx-block pbx-truncate" :class="[opacityVueModel !== 'none' ? '' : '']">{{
54
- opacityVueModel === 'none' ? 'Transparent' : opacityVueModel
56
+ opacityVueModel === 'none' ? $t('backgroundOpacity.transparent') : opacityVueModel
55
57
  }}</span>
56
58
  </span>
57
59
  <span
@@ -79,15 +81,14 @@ watch(
79
81
  >
80
82
  <li
81
83
  :class="[
82
- active ? 'bg-myPrimaryLinkColor text-white' : 'pbx-text-myPrimaryDarkGrayColor',
84
+ active
85
+ ? 'pbx-bg-myPrimaryLinkColor text-white'
86
+ : 'pbx-text-myPrimaryDarkGrayColor',
83
87
  'pbx-relative pbx-cursor-default pbx-select-none pbx-py-2 pbx-pl-3 pbx-pr-9',
84
88
  ]"
85
89
  >
86
90
  <div class="pbx-flex pbx-items-center">
87
- <div
88
- v-if="backgroundOpacity === 'none'"
89
- class="pbx-aspect-square pbx-w-6 pbx-h-6"
90
- >
91
+ <div v-if="backgroundOpacity === 'none'">
91
92
  <div class="pbx-myPrimaryColorPreview pbx-border-none">
92
93
  <span class="material-symbols-outlined"> ev_shadow </span>
93
94
  </div>
@@ -98,10 +99,12 @@ watch(
98
99
  class="pbx-aspect-square pbx-w-6 pbx-h-6 pbx-bg-gray-950"
99
100
  :class="`${backgroundOpacity}`"
100
101
  ></div>
102
+ <span v-if="backgroundOpacity === 'none'" class="pbx-ml-3">{{
103
+ $t('backgroundOpacity.transparent')
104
+ }}</span>
101
105
  <span v-if="backgroundOpacity !== 'none'" class="pbx-ml-3">{{
102
106
  backgroundOpacity
103
107
  }}</span>
104
- <span v-if="backgroundOpacity === 'none'" class="pbx-ml-3">Transparent</span>
105
108
  </div>
106
109
  </li>
107
110
  </ListboxOption>
@@ -31,11 +31,11 @@ watch(
31
31
 
32
32
  <template>
33
33
  <div class="pbx-my-2 pbx-py-2">
34
- <label class="pbx-myPrimaryInputLabel"> Opacity</label>
34
+ <label for="default-opacity" class="pbx-myPrimaryInputLabel">{{ $t('opacity.label') }}</label>
35
35
 
36
36
  <Listbox as="div" v-model="opacityVueModel">
37
37
  <div class="pbx-relative">
38
- <ListboxButton class="pbx-myPrimarySelect">
38
+ <ListboxButton class="pbx-myPrimarySelect" id="default-opacity">
39
39
  <span class="pbx-flex pbx-items-center pbx-gap-2">
40
40
  <div v-if="opacityVueModel === 'none'">
41
41
  <div class="pbx-myPrimaryColorPreview pbx-border-none">
@@ -50,7 +50,7 @@ watch(
50
50
  ></div>
51
51
 
52
52
  <span class="pbx-block pbx-truncate" :class="[opacityVueModel !== 'none' ? '' : '']">{{
53
- opacityVueModel === 'none' ? 'Transparent' : opacityVueModel
53
+ opacityVueModel === 'none' ? $t('opacity.transparent') : opacityVueModel
54
54
  }}</span>
55
55
  </span>
56
56
  <span
@@ -96,7 +96,9 @@ watch(
96
96
  class="pbx-aspect-square pbx-w-6 pbx-h-6 pbx-bg-gray-950"
97
97
  :class="`${elementOpacity}`"
98
98
  ></div>
99
- <span v-if="elementOpacity === 'none'" class="pbx-ml-3">Transparent</span>
99
+ <span v-if="elementOpacity === 'none'" class="pbx-ml-3">{{
100
+ $t('opacity.transparent')
101
+ }}</span>
100
102
  <span v-if="elementOpacity !== 'none'" class="pbx-ml-3">{{
101
103
  elementOpacity
102
104
  }}</span>
@@ -61,16 +61,19 @@ watch(
61
61
  </script>
62
62
  <template>
63
63
  <EditorAccordion>
64
- <template #title>Margin</template>
64
+ <template #title>{{ $t('margin.title') }}</template>
65
65
  <template #content>
66
66
  <div class="pbx-my-2 pbx-py-2">
67
- <label class="pbx-myPrimaryInputLabel"> Vertical Margin </label>
67
+ <label for="vertical-margin" class="pbx-myPrimaryInputLabel">{{
68
+ $t('margin.vertical')
69
+ }}</label>
68
70
  <select
71
+ id="vertical-margin"
69
72
  v-model="fontVerticalMargin"
70
73
  class="pbx-myPrimarySelect"
71
74
  @change="pageBuilderService.handleVerticalMargin(fontVerticalMargin)"
72
75
  >
73
- <option disabled value="">Select</option>
76
+ <option disabled value="">{{ $t('margin.select') }}</option>
74
77
  <option
75
78
  v-for="verticalMargin in tailwindPaddingPlusMargin.verticalMargin"
76
79
  :key="verticalMargin"
@@ -81,13 +84,16 @@ watch(
81
84
  </div>
82
85
  <hr />
83
86
  <div class="pbx-my-2 pbx-py-2">
84
- <label class="pbx-myPrimaryInputLabel"> Horizontal Margin </label>
87
+ <label for="horizontal-margin" class="pbx-myPrimaryInputLabel">{{
88
+ $t('margin.horizontal')
89
+ }}</label>
85
90
  <select
91
+ id="horizontal-margin"
86
92
  v-model="fontHorizontalMargin"
87
93
  class="pbx-myPrimarySelect"
88
94
  @change="pageBuilderService.handleHorizontalMargin(fontHorizontalMargin)"
89
95
  >
90
- <option disabled value="">Select</option>
96
+ <option disabled value="">{{ $t('margin.select') }}</option>
91
97
  <option
92
98
  v-for="horizontalMargin in tailwindPaddingPlusMargin.horizontalMargin"
93
99
  :key="horizontalMargin"
@@ -6,7 +6,7 @@ import ManageOpacity from './ManageOpacity.vue'
6
6
 
7
7
  <template>
8
8
  <EditorAccordion>
9
- <template #title>Opacity & Transparency </template>
9
+ <template #title>{{ $t('opacityEditor.title') }}</template>
10
10
  <template #content>
11
11
  <ManageOpacity></ManageOpacity>
12
12
  <hr />
@@ -61,16 +61,19 @@ watch(
61
61
  </script>
62
62
  <template>
63
63
  <EditorAccordion>
64
- <template #title>Padding</template>
64
+ <template #title>{{ $t('padding.title') }}</template>
65
65
  <template #content>
66
66
  <div class="pbx-my-2 pbx-py-2">
67
- <label class="pbx-myPrimaryInputLabel"> Vertical Padding </label>
67
+ <label for="vertical-padding" class="pbx-myPrimaryInputLabel">{{
68
+ $t('padding.vertical')
69
+ }}</label>
68
70
  <select
71
+ id="vertical-padding"
69
72
  v-model="fontVerticalPadding"
70
73
  class="pbx-myPrimarySelect"
71
74
  @change="pageBuilderService.handleVerticalPadding(fontVerticalPadding)"
72
75
  >
73
- <option disabled value="">Select</option>
76
+ <option disabled value="">{{ $t('padding.select') }}</option>
74
77
  <option
75
78
  v-for="verticalPadding in tailwindPaddingPlusMargin.verticalPadding"
76
79
  :key="verticalPadding"
@@ -81,13 +84,16 @@ watch(
81
84
  </div>
82
85
  <hr />
83
86
  <div class="pbx-my-2 pbx-py-2">
84
- <label class="pbx-myPrimaryInputLabel"> Horizontal Padding </label>
87
+ <label for="horizontal-padding" class="pbx-myPrimaryInputLabel">{{
88
+ $t('padding.horizontal')
89
+ }}</label>
85
90
  <select
91
+ id="horizontal-padding"
86
92
  v-model="fontHorizontalPadding"
87
93
  class="pbx-myPrimarySelect"
88
94
  @change="pageBuilderService.handleHorizontalPadding(fontHorizontalPadding)"
89
95
  >
90
- <option disabled value="">Select</option>
96
+ <option disabled value="">{{ $t('padding.select') }}</option>
91
97
  <option
92
98
  v-for="horizontalPadding in tailwindPaddingPlusMargin.horizontalPadding"
93
99
  :key="horizontalPadding"
@@ -0,0 +1,116 @@
1
+ <script setup>
2
+ import { ref, computed, watch, nextTick } from 'vue'
3
+ import { sharedPageBuilderStore } from '../../../../stores/shared-store'
4
+ import EditorAccordion from '../EditorAccordion.vue'
5
+ import { getPageBuilder } from '../../../../composables/builderInstance'
6
+
7
+ const pageBuilderService = getPageBuilder()
8
+
9
+ const pageBuilderStateStore = sharedPageBuilderStore
10
+
11
+ const currentStyles = ref(null)
12
+ const getCurrentStyles = computed(() => pageBuilderStateStore.getCurrentStyles)
13
+
14
+ watch(
15
+ getCurrentStyles,
16
+ (newValue) => {
17
+ currentStyles.value = newValue
18
+ },
19
+ { immediate: true },
20
+ )
21
+
22
+ const inputProperty = ref('')
23
+ const inputValue = ref('')
24
+ const errorMessage = ref('')
25
+ const valueInputRef = ref(null)
26
+
27
+ const handleEnterOnProperty = () => {
28
+ if (valueInputRef.value) {
29
+ valueInputRef.value.focus()
30
+ }
31
+ }
32
+
33
+ const handleAddStyle = async () => {
34
+ const property = inputProperty.value.trim()
35
+ const value = inputValue.value.trim()
36
+
37
+ if (!property || !value) {
38
+ errorMessage.value = 'Please enter a property and a value.'
39
+ return
40
+ }
41
+
42
+ if (currentStyles.value && currentStyles.value[property]) {
43
+ errorMessage.value = `Property "${property}" already exists. Remove it first to add a new one.`
44
+ return
45
+ }
46
+
47
+ errorMessage.value = '' // Clear error
48
+
49
+ pageBuilderService.handleAddStyle(property, value)
50
+ await pageBuilderService.initializeElementStyles()
51
+
52
+ inputProperty.value = ''
53
+ inputValue.value = ''
54
+ }
55
+ </script>
56
+
57
+ <template>
58
+ <EditorAccordion>
59
+ <template #title>{{ $t('styleEditor.title') }}</template>
60
+ <template #content>
61
+ <label class="pbx-myPrimaryInputLabel pbx-my-4">
62
+ {{ $t('styleEditor.info') }}
63
+ </label>
64
+
65
+ <div class="pbx-flex pbx-flex-row pbx-flex-wrap pbx-gap-2 pbx-mt-2 pbx-mb-4">
66
+ <div
67
+ v-for="(value, key) in currentStyles"
68
+ :key="key"
69
+ class="pbx-myPrimaryTag pbx-cursor-pointer hover:pbx-bg-myPrimaryErrorColor hover:pbx-text-white pbx-text-xs pbx-py-2 pbx-font-medium"
70
+ @click="
71
+ async () => {
72
+ pageBuilderService.handleRemoveStyle(key)
73
+ await pageBuilderService.initializeElementStyles()
74
+ }
75
+ "
76
+ >
77
+ <div class="pbx-flex pbx-items-center pbx-gap-1">
78
+ <span class="pbx-mr-1"> {{ key }}: {{ value }}; </span>
79
+ </div>
80
+ </div>
81
+ </div>
82
+
83
+ <div>
84
+ <label for="custom-style-property" class="pbx-myPrimaryInputLabel">
85
+ {{ $t('styleEditor.add') }}
86
+ </label>
87
+ <div class="pbx-flex pbx-gap-2 pbx-flex-col pbx-item-center">
88
+ <input
89
+ id="custom-style-property"
90
+ v-model="inputProperty"
91
+ type="text"
92
+ :placeholder="$t('styleEditor.propertyPlaceholder')"
93
+ @keydown.enter.prevent="handleEnterOnProperty"
94
+ autocomplete="off"
95
+ class="pbx-myPrimaryInput"
96
+ />
97
+ <input
98
+ id="custom-style-value"
99
+ ref="valueInputRef"
100
+ v-model="inputValue"
101
+ type="text"
102
+ :placeholder="$t('styleEditor.valuePlaceholder')"
103
+ @keydown.enter="handleAddStyle"
104
+ autocomplete="off"
105
+ class="pbx-myPrimaryInput"
106
+ />
107
+
108
+ <button @click="handleAddStyle" type="button" class="pbx-myPrimaryButton">
109
+ {{ $t('styleEditor.addButton') }}
110
+ </button>
111
+ </div>
112
+ </div>
113
+ <p v-if="errorMessage" class="pbx-myPrimaryInputError">{{ errorMessage }}</p>
114
+ </template>
115
+ </EditorAccordion>
116
+ </template>
@@ -57,12 +57,13 @@ watch(
57
57
 
58
58
  <ListboxButton
59
59
  v-if="!globalPageLayout"
60
- 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-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
60
+ 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-200 pbx-aspect-square hover:pbx-bg-gray-100 hover:pbx-fill-white focus-visible:pbx-ring-0"
61
61
  >
62
62
  <div class="pbx-flex pbx-flex-col">
63
63
  <div class="pbx-flex pbx-gap-2 pbx-items-center">
64
64
  <span
65
65
  class="material-symbols-outlined"
66
+ style="text-shadow: rgb(0 0 0 / 10%) 1.5px 1.5px 0px"
66
67
  :class="`pbx-text-${textColor?.replace('pbx-text-', '')}`"
67
68
  >
68
69
  format_color_text