@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
@@ -36,6 +36,7 @@ interface PageBuilderState {
36
36
  parentElement: HTMLElement | null
37
37
  restoredElement: string | null
38
38
  currentClasses: string[]
39
+ currentStyles: Record<string, string>
39
40
  fontVerticalPadding: string | null
40
41
  fontHorizontalPadding: string | null
41
42
  fontVerticalMargin: string | null
@@ -97,6 +98,7 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
97
98
  parentElement: null,
98
99
  restoredElement: null,
99
100
  currentClasses: [],
101
+ currentStyles: {},
100
102
  fontVerticalPadding: null,
101
103
  fontHorizontalPadding: null,
102
104
  fontVerticalMargin: null,
@@ -208,6 +210,9 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
208
210
  getCurrentClasses(state: PageBuilderState): string[] {
209
211
  return state.currentClasses
210
212
  },
213
+ getCurrentStyles(state: PageBuilderState): Record<string, string> {
214
+ return state.currentStyles
215
+ },
211
216
  getFontStyle(state: PageBuilderState): string | null {
212
217
  return state.fontStyle
213
218
  },
@@ -365,6 +370,9 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
365
370
  setCurrentClasses(payload: string[] | ArrayLike<string>): void {
366
371
  this.currentClasses = Array.from(payload)
367
372
  },
373
+ setCurrentStyles(payload: Record<string, string>): void {
374
+ this.currentStyles = payload
375
+ },
368
376
  setFontVerticalPadding(payload: string | null): void {
369
377
  this.fontVerticalPadding = payload
370
378
  },
@@ -5,53 +5,33 @@ import DemoMediaLibraryComponentTest from '../tests/TestComponents/DemoMediaLibr
5
5
  import DemoBuilderComponentsTest from '../tests/TestComponents/DemoBuilderComponentsTest.vue'
6
6
  import { onMounted } from 'vue'
7
7
  import componentsArray from '../tests/componentsArray.test.json'
8
-
9
8
  import { getPageBuilder } from '../composables/builderInstance'
9
+ import { useI18n } from 'vue-i18n'
10
10
  const pageBuilderService = getPageBuilder()
11
+ const { t } = useI18n()
11
12
 
12
13
  const features = [
13
- {
14
- name: 'Live Drag & Drop Builder',
15
- description:
16
- 'Click & Drop content on a page and watch your pages come to life. Bring your vision to life and create impressive pages using a click & drop Page Builder',
17
- },
18
- {
19
- name: 'True Visual Editing',
20
- description:
21
- 'See your changes in real-time as you make them. Elevate your creative vision and create pages using an intuitive click & drop page builder. Break free from design limitations and turn your visions into reality.',
22
- },
23
- {
24
- name: 'Features',
25
- description:
26
- 'Click & Drop, Reordering, True Visual Editing, Responsive Editing, Font Customization, Undo & Redo, Text Editing, Media Library, Unsplash Integration, YouTube Videos.',
27
- },
28
- {
29
- name: 'Technologies',
30
- description:
31
- 'Developed with TypeScript, Vue 3, Composition API, Pinia, CSS, Tailwind CSS and HTML.',
32
- },
33
- {
34
- name: 'Set Brand and Link Colors one place',
35
- description:
36
- 'Global Styles for fonts, designs, & colors. Set Brand and Link Colors once and apply them across the entire Platform with ease.',
37
- },
38
- {
39
- name: 'Mobile-First Approach',
40
- description:
41
- 'Developed with Mobile-First approach. The Page Builder even works on mobile phones.',
42
- },
43
- {
44
- name: 'Media Library',
45
- description:
46
- 'A beautiful and user-friendly media library that allows you to change and update images. Unsplash Integration is included.',
47
- },
48
- {
49
- name: 'Minimal and Intuitive Design',
50
- description:
51
- 'Beautiful, elegant and intuitive design. Enhance user engagement with amazing visual experience.',
52
- },
14
+ { key: 'liveDragDropBuilder' },
15
+ { key: 'trueVisualEditing' },
16
+ { key: 'features' },
17
+ { key: 'technologies' },
18
+ { key: 'setBrandAndLinkColors' },
19
+ { key: 'mobileFirstApproach' },
20
+ { key: 'mediaLibrary' },
21
+ { key: 'minimalIntuitiveDesign' },
53
22
  ]
54
23
 
24
+ const publishPageBuilder = function () {}
25
+
26
+ // Convert componentsArray to HTML string
27
+ const htmlString =
28
+ '<div id="pagebuilder" class="" style="">' +
29
+ componentsArray.map((c) => c.html_code).join('\n') +
30
+ '</div>'
31
+
32
+ // Parse as HTML (not JSON)
33
+ const { /* components, */ pageSettings } = pageBuilderService.parsePageBuilderHTML(htmlString)
34
+
55
35
  const configPageBuilder = {
56
36
  userForPageBuilder: {
57
37
  name: 'Jane Doe',
@@ -62,7 +42,7 @@ const configPageBuilder = {
62
42
  formName: 'collection',
63
43
  },
64
44
  pageBuilderLogo: {
65
- src: '/logo/logo.svg',
45
+ src: '/logo/mybuilder_new_lowercase.svg',
66
46
  },
67
47
  resourceData: {
68
48
  title: 'Demo Article',
@@ -70,31 +50,22 @@ const configPageBuilder = {
70
50
  },
71
51
  userSettings: {
72
52
  theme: 'light',
73
- language: 'en',
53
+ language: {
54
+ default: 'en',
55
+ enable: ['en', 'zh-Hans', 'fr', 'ja', 'ru', 'es', 'pt', 'de', 'ar', 'hi'],
56
+ disableLanguageDropDown: false,
57
+ },
74
58
  autoSave: true,
75
59
  },
76
60
  settings: {
77
61
  brandColor: '#DB93B0',
78
62
  },
79
- // pageSettings: {
80
- // classes:
81
- // 'pbx-font-didot pbx-italic pbx-px-20 pbx-rounded-full pbx-rounded-tr-full pbx-border-8 pbx-border-green-800 pbx-border-solid pbx-text-neutral-300 pbx-bg-stone-700',
82
- // style: {
83
- // backgroundColor: 'red',
84
- // border: '6px solid yellow',
85
- // },
86
- // },
63
+ pageSettings,
87
64
  } as const
88
65
 
89
66
  onMounted(async () => {
90
- const result = await pageBuilderService.startBuilder(configPageBuilder, componentsArray)
91
- console.log('Page Builder Result:', result)
92
- //
93
- //
94
- //
95
- // await pageBuilderService.mountComponentsToDOM(JSON.stringify(html))
96
- // await pageBuilderService.mountComponentsToDOM(JSON.stringify(oldhtmlfromdb))
97
- // await pageBuilderService.mountComponentsToDOM(rawHTML)
67
+ const result = await pageBuilderService.startBuilder(configPageBuilder)
68
+ console.log('Page Builder inspect the result for message, status, or error::', result)
98
69
  })
99
70
  </script>
100
71
 
@@ -103,19 +74,15 @@ onMounted(async () => {
103
74
  <div class="pbx-myPrimaryWidthScreenModule pbx-bg-red-50 lg:pbx-block">
104
75
  <div class="pbx-myPrimaryContentSection">
105
76
  <h2 class="pbx-mySecondaryHeader">
106
- Bring your vision to life and create impressive pages using a click & drop Page Builder
77
+ {{ $t('branding.mainHeader') }}
107
78
  </h2>
108
79
  <p class="pbx-myPrimaryParagraph pbx-font-normal">
109
- The web builder for stunning pages. Enable users to design and publish modern pages at any
110
- scale. Build responsive pages like listings, jobs or blog posts and manage content easily
111
- using the free click & drop Page Builder. Developed with TypeScript, Vue 3, Composition
112
- API, Pinia, CSS, Tailwind CSS and HTML.
113
-
80
+ {{ $t('branding.description') }}
114
81
  <br />
115
82
  </p>
116
83
  <div class="pbx-mt-4">
117
84
  <p class="pbx-myPrimaryParagraph pbx-font-normal">
118
- Download or install our powerful, flexible, and easy-to-use free Vue 3 Page Builder via
85
+ {{ $t('branding.downloadDescription') }}
119
86
  <br />
120
87
  <strong> npm:</strong>
121
88
  <a
@@ -130,7 +97,11 @@ onMounted(async () => {
130
97
  </div>
131
98
  <div class="pbx-m-4">
132
99
  <!-- :CustomBuilderComponents="DemoBuilderComponentsTest" -->
133
- <PageBuilder :CustomMediaLibraryComponent="DemoMediaLibraryComponentTest"></PageBuilder>
100
+ <PageBuilder
101
+ :CustomMediaLibraryComponent="DemoMediaLibraryComponentTest"
102
+ :showPublishButton="true"
103
+ @handlePublishPageBuilder="publishPageBuilder"
104
+ ></PageBuilder>
134
105
  </div>
135
106
  </div>
136
107
 
@@ -149,16 +120,16 @@ onMounted(async () => {
149
120
  >
150
121
  <div
151
122
  v-for="feature in features"
152
- :key="feature.name"
123
+ :key="feature.key"
153
124
  class="pbx-bg-red-200 pbx-bg-opacity-20 hover:pbx-bg-opacity-10 pbx-w-full lg:pbx-min-h-[20rem] pbx-min-h-[12rem] pbx-relative pbx-col-span-1 pbx-flex pbx-flex-col pbx-text-center pbx-rounded-lg pbx-shadow-sm pbx-outline pbx-outline-2 pbx-outline-offset-8 pbx-outline-yellow-400"
154
125
  >
155
126
  <div
156
127
  class="pbx-bg-black/0 pbx-absolute pbx-top-0 pbx-left-0 pbx-w-full pbx-h-full pbx-rounded-lg"
157
128
  ></div>
158
129
  <div class="pbx-px-2 pbx-pt-8 pbx-absolute pbx-top-0 pbx-w-full">
159
- <p class="pbx-myTertiaryHeader">{{ feature.name }}</p>
130
+ <p class="pbx-myTertiaryHeader">{{ t(`features.${feature.key}.name`) }}</p>
160
131
  <p class="pbx-myPrimaryParagraph pbx-font-medium pbx-drop-shadow-sm">
161
- {{ feature.description }}
132
+ {{ t(`features.${feature.key}.description`) }}
162
133
  </p>
163
134
  </div>
164
135
  </div>
@@ -10,7 +10,7 @@
10
10
  "title": "Text"
11
11
  },
12
12
  {
13
- "html_code": "<section data-componentid=\"0bb012a0-631a-497f-9b7f-832313b64a2b\" data-component-title=\"3 Vertical Images\">\n<div class=\"pbx-w-full md:pbx-pt-12 md:pbx-pb-12 pbx-pt-4 pbx-pb-4 lg:pbx-px-4 pbx-px-2 pbx-bg-black\"><div class=\"pbx-mx-auto pbx-max-w-7xl pbx-m\"><div class=\"pbx-myPrimaryGap pbx-grid pbx-grid-cols-1 sm:pbx-grid-cols-3 lg:pbx-grid-cols-3\"> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] pbx-smooth-transition pbx-rounded-tl-full\" src=\"https://images.unsplash.com/photo-1632765866070-3fadf25d3d5b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwxMjh8fG1vZGVsfGVufDB8fHx8MTc0OTgzMDgzMXww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"b2fb2e61-c916-4195-9cd2-c1d25747b4f7\"> </div> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] pbx-smooth-transition pbx-rounded-full\" src=\"https://images.unsplash.com/photo-1542513217-0b0eedf7005d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwxMDR8fG1vZGVsfGVufDB8fHx8MTc0OTgzMDc5MXww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"fdf36a14-f7ef-4025-942f-c87b20b18005\"> </div> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] pbx-smooth-transition pbx-rounded-br-full\" src=\"https://images.unsplash.com/photo-1574015974293-817f0ebebb74?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwyNnx8bW9kZWx8ZW58MHx8fHwxNzQ5ODMwNzM1fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"618a74a7-5d41-4dce-937c-130dd7490569\"></div></div> </div></div>\n</section>",
13
+ "html_code": "<section data-componentid=\"0bb012a0-631a-497f-9b7f-832313b64a2b\" data-component-title=\"3 Vertical Images\">\n<div class=\"pbx-w-full md:pbx-pt-12 md:pbx-pb-12 pbx-pt-4 pbx-pb-4 lg:pbx-px-4 pbx-px-2 pbx-bg-black\"><div class=\"pbx-mx-auto pbx-max-w-7xl pbx-m\"><div class=\"pbx-myPrimaryGap pbx-grid pbx-grid-cols-1 sm:pbx-grid-cols-3 lg:pbx-grid-cols-3\"> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] pbx-rounded-tl-full\" src=\"https://images.unsplash.com/photo-1632765866070-3fadf25d3d5b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwxMjh8fG1vZGVsfGVufDB8fHx8MTc0OTgzMDgzMXww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"b2fb2e61-c916-4195-9cd2-c1d25747b4f7\"> </div> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] pbx-rounded-full\" src=\"https://images.unsplash.com/photo-1542513217-0b0eedf7005d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwxMDR8fG1vZGVsfGVufDB8fHx8MTc0OTgzMDc5MXww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"fdf36a14-f7ef-4025-942f-c87b20b18005\"> </div> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] pbx-rounded-br-full\" src=\"https://images.unsplash.com/photo-1574015974293-817f0ebebb74?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwyNnx8bW9kZWx8ZW58MHx8fHwxNzQ5ODMwNzM1fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"618a74a7-5d41-4dce-937c-130dd7490569\"></div></div> </div></div>\n</section>",
14
14
  "id": "0bb012a0-631a-497f-9b7f-832313b64a2b",
15
15
  "title": "3 Vertical Images"
16
16
  },
@@ -25,7 +25,7 @@
25
25
  "title": "Text"
26
26
  },
27
27
  {
28
- "html_code": "<section data-componentid=\"d3b5a3e4-29a3-4b03-88b6-1f77d319af74\" data-component-title=\"2 Vertical Images\">\n<div class=\"pbx-w-full md:pbx-pt-12 md:pbx-pb-12 pbx-pt-4 pbx-pb-4 lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-mx-auto pbx-max-w-7xl\"><div class=\"pbx-myPrimaryGap pbx-grid pbx-grid-cols-2 sm:pbx-grid-cols-2 lg:pbx-grid-cols-2\"> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] pbx-smooth-transition\" src=\"https://images.unsplash.com/photo-1592966719124-2ca2978ba325?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwzfHxraW5mb2xrfGVufDB8fHx8MTc0OTgzMTAzM3ww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"536340a5-c7e1-479d-a2ae-a85e6dacc2df\"> </div> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] pbx-smooth-transition\" src=\"https://images.unsplash.com/photo-1549298222-1c31e8915347?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwzfHxtYWdhemluZSUyMGZhc2hpb258ZW58MHx8fHwxNzQ5ODMxNTEwfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"41655496-4742-4cc6-bc3c-abe7c2b241fb\"> </div> </div> </div> </div>\n</section>",
28
+ "html_code": "<section data-componentid=\"d3b5a3e4-29a3-4b03-88b6-1f77d319af74\" data-component-title=\"2 Vertical Images\">\n<div class=\"pbx-w-full md:pbx-pt-12 md:pbx-pb-12 pbx-pt-4 pbx-pb-4 lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-mx-auto pbx-max-w-7xl\"><div class=\"pbx-myPrimaryGap pbx-grid pbx-grid-cols-2 sm:pbx-grid-cols-2 lg:pbx-grid-cols-2\"> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] \" src=\"https://images.unsplash.com/photo-1592966719124-2ca2978ba325?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwzfHxraW5mb2xrfGVufDB8fHx8MTc0OTgzMTAzM3ww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"536340a5-c7e1-479d-a2ae-a85e6dacc2df\"> </div> <div class=\"pbx-flex-1 pbx-py-2\"> <img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-[9/16] \" src=\"https://images.unsplash.com/photo-1549298222-1c31e8915347?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwzfHxtYWdhemluZSUyMGZhc2hpb258ZW58MHx8fHwxNzQ5ODMxNTEwfDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"provider\" data-image=\"41655496-4742-4cc6-bc3c-abe7c2b241fb\"> </div> </div> </div> </div>\n</section>",
29
29
  "id": "d3b5a3e4-29a3-4b03-88b6-1f77d319af74",
30
30
  "title": "2 Vertical Images"
31
31
  },
@@ -55,7 +55,7 @@
55
55
  "title": "Text"
56
56
  },
57
57
  {
58
- "html_code": "<section data-componentid=\"7bcda060-8ed5-482f-bcf4-aa6bd7fdb193\" title=\"6 Square Images Grid\" data-component-title=\"6 Square Images Grid\">\n<div class=\"pbx-w-full md:pbx-pt-12 md:pbx-pb-12 pbx-pt-4 pbx-pb-4 lg:pbx-px-4 pbx-px-2 pbx-rounded-tr-full pbx-bg-yellow-100 pbx-rounded-bl-full\">\n<div class=\"pbx-mx-auto pbx-max-w-7xl\">\n<div class=\"pbx-grid pbx-grid-cols-2 md:pbx-grid-cols-3 pbx-myPrimaryGap\">\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-square pbx-smooth-transition\" src=\"https://images.unsplash.com/photo-1616837874254-8d5aaa63e273?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwxOXx8amV3ZXJseXxlbnwwfHx8fDE3NTEwMjE1MDR8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-square pbx-smooth-transition\" src=\"https://images.unsplash.com/photo-1608042314453-ae338d80c427?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwyfHxqZXdlcmx5fGVufDB8fHx8MTc1MTAyMTUwNHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-square pbx-smooth-transition\" src=\"https://images.unsplash.com/photo-1621939745912-aad97fd3a34d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHw1MXx8amV3ZXJseXxlbnwwfHx8fDE3NTEwMjE1NDN8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-aspect-square pbx-smooth-transition pbx-object-bottom\" src=\"https://images.unsplash.com/photo-1617038220319-276d3cfab638?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHw1fHxqZXdlcmx5fGVufDB8fHx8MTc1MTAyMTUwNHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-aspect-square pbx-smooth-transition pbx-object-bottom\" src=\"https://images.unsplash.com/photo-1594924571793-f6517415f594?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHw0Nnx8amV3ZXJseXxlbnwwfHx8fDE3NTEwMjE1Mjd8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-aspect-square pbx-smooth-transition pbx-object-top\" src=\"https://images.unsplash.com/photo-1683099869102-bcf8791eb0e5?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwxMjV8fGpld2VybHl8ZW58MHx8fHwxNzUxMDIxNTc4fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n</div>\n</div>\n</div>\n</section>",
58
+ "html_code": "<section data-componentid=\"7bcda060-8ed5-482f-bcf4-aa6bd7fdb193\" title=\"6 Square Images Grid\" data-component-title=\"6 Square Images Grid\">\n<div class=\"pbx-w-full md:pbx-pt-12 md:pbx-pb-12 pbx-pt-4 pbx-pb-4 lg:pbx-px-4 pbx-px-2 pbx-rounded-tr-full pbx-bg-yellow-100 pbx-rounded-bl-full\">\n<div class=\"pbx-mx-auto pbx-max-w-7xl\">\n<div class=\"pbx-grid pbx-grid-cols-2 md:pbx-grid-cols-3 pbx-myPrimaryGap\">\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-square \" src=\"https://images.unsplash.com/photo-1616837874254-8d5aaa63e273?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwxOXx8amV3ZXJseXxlbnwwfHx8fDE3NTEwMjE1MDR8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-square \" src=\"https://images.unsplash.com/photo-1608042314453-ae338d80c427?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwyfHxqZXdlcmx5fGVufDB8fHx8MTc1MTAyMTUwNHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-object-top pbx-aspect-square \" src=\"https://images.unsplash.com/photo-1621939745912-aad97fd3a34d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHw1MXx8amV3ZXJseXxlbnwwfHx8fDE3NTEwMjE1NDN8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-aspect-square pbx-object-bottom\" src=\"https://images.unsplash.com/photo-1617038220319-276d3cfab638?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHw1fHxqZXdlcmx5fGVufDB8fHx8MTc1MTAyMTUwNHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-aspect-square pbx-object-bottom\" src=\"https://images.unsplash.com/photo-1594924571793-f6517415f594?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHw0Nnx8amV3ZXJseXxlbnwwfHx8fDE3NTEwMjE1Mjd8MA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n<div>\n<img class=\"pbx-object-cover pbx-w-full pbx-aspect-square pbx-object-top\" src=\"https://images.unsplash.com/photo-1683099869102-bcf8791eb0e5?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wzMTI0Mzl8MHwxfHNlYXJjaHwxMjV8fGpld2VybHl8ZW58MHx8fHwxNzUxMDIxNTc4fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1080\" alt=\"image\">\n</div>\n\n</div>\n</div>\n</div>\n</section>",
59
59
  "id": "7bcda060-8ed5-482f-bcf4-aa6bd7fdb193",
60
60
  "title": "6 Square Images Grid"
61
61
  }
@@ -47,7 +47,13 @@ describe('PageBuilderService', () => {
47
47
  typeof (fn as { mockClear?: () => void }).mockClear === 'function' &&
48
48
  (fn as { mockClear: () => void }).mockClear(),
49
49
  )
50
- service = new PageBuilderService(mockStore)
50
+ // Provide a minimal i18n mock for tests
51
+ const mockI18n = {
52
+ global: {
53
+ locale: 'en',
54
+ },
55
+ } as any
56
+ service = new PageBuilderService(mockStore, mockI18n)
51
57
  })
52
58
 
53
59
  it('should start builder and return a success message', async () => {
@@ -29,7 +29,16 @@ export interface BuilderResourceComponent {
29
29
  // For the full resource object passed to your package
30
30
  export type BuilderResourceData = BuilderResourceComponent[]
31
31
 
32
- export type StartBuilderResult = { error: true; reason: string } | { message: string }
32
+ export type StartBuilderResult =
33
+ | { error: true; reason: string }
34
+ | {
35
+ message: string
36
+ validation?:
37
+ | { error: true; warning: string; status: string }
38
+ | { error: true; reason: string }
39
+ passedComponentsArray?: BuilderResourceData
40
+ }
41
+
33
42
  // Store interfaces for better type safety
34
43
  export interface PageBuilderStateStore {
35
44
  getTextAreaVueModel: string | null
@@ -204,7 +213,6 @@ export interface PageBuilderUser {
204
213
  export interface PageSettings {
205
214
  classes: string
206
215
  style?: Record<string, string>
207
- imageUrlPrefix?: string
208
216
  }
209
217
 
210
218
  // Page Builder Configuration interface
@@ -219,7 +227,13 @@ export interface PageBuilderConfig {
219
227
  [key: string]: unknown
220
228
  userSettings?: {
221
229
  theme?: 'light' | 'dark' | 'auto'
222
- language?: string
230
+ language?: {
231
+ default: 'en' | 'zh-Hans' | 'fr' | 'ja' | 'ru' | 'es' | 'pt' | 'de' | 'ar' | 'hi'
232
+ enable?: ReadonlyArray<
233
+ 'en' | 'zh-Hans' | 'fr' | 'ja' | 'ru' | 'es' | 'pt' | 'de' | 'ar' | 'hi'
234
+ >
235
+ }
236
+
223
237
  autoSave?: boolean
224
238
  [key: string]: unknown
225
239
  } | null
@@ -21,52 +21,52 @@ const component: Components[] = [
21
21
  data: [
22
22
  {
23
23
  title: 'Single Image',
24
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-1"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"></div></div></div></div>\n</section>`,
24
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-1"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"></div></div></div></div>\n</section>`,
25
25
  cover_image: null,
26
26
  },
27
27
  {
28
28
  title: '2 Vertical Images',
29
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-2"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] smooth-transition" src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] smooth-transition" src="${placeholderImage}" alt="provider"> </div> </div> </div> </div>\n</section>`,
29
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-2"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] " src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] " src="${placeholderImage}" alt="provider"> </div> </div> </div> </div>\n</section>`,
30
30
  cover_image: null,
31
31
  },
32
32
  {
33
33
  title: '2 Square Images',
34
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"></div></div> </div></div>\n</section>`,
34
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"></div></div> </div></div>\n</section>`,
35
35
  cover_image: null,
36
36
  },
37
37
  {
38
38
  title: '3 Square Images',
39
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"></div></div> </div></div>\n</section>`,
39
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"></div></div> </div></div>\n</section>`,
40
40
  cover_image: null,
41
41
  },
42
42
  {
43
43
  title: '6 Square Images Grid',
44
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2">\n<div class="mx-auto max-w-7xl">\n<div class="grid grid-cols-2 md:grid-cols-3 myPrimaryGap">\n\n<div>\n<img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="image">\n</div>\n\n</div>\n</div>\n</div>\n</section>`,
44
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2">\n<div class="mx-auto max-w-7xl">\n<div class="grid grid-cols-2 md:grid-cols-3 myPrimaryGap">\n\n<div>\n<img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="image">\n</div>\n\n<div>\n<img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="image">\n</div>\n\n</div>\n</div>\n</div>\n</section>`,
45
45
  cover_image: null,
46
46
  },
47
47
  {
48
48
  title: 'Two Square Images With Text',
49
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl">\n<div class="myPrimaryGap lg:flex lg:justify-center"><div class="flex-1 py-2">\n<div class="grid myPrimaryGap grid-cols-1 lg:grid-cols-2"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> </div> </div> </div>\n\n<div class="flex-1 py-2"> <div class="break-words py-2"><p><strong>Title</strong></p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></div></div> \n</div></div></div>\n</section>`,
49
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl">\n<div class="myPrimaryGap lg:flex lg:justify-center"><div class="flex-1 py-2">\n<div class="grid myPrimaryGap grid-cols-1 lg:grid-cols-2"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> </div> </div> </div>\n\n<div class="flex-1 py-2"> <div class="break-words py-2"><p><strong>Title</strong></p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></div></div> \n</div></div></div>\n</section>`,
50
50
  cover_image: null,
51
51
  },
52
52
  {
53
53
  title: '3 Vertical Images',
54
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] smooth-transition" src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] smooth-transition" src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] smooth-transition" src="${placeholderImage}" alt="provider"></div></div> </div></div>\n</section>`,
54
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] " src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] " src="${placeholderImage}" alt="provider"> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-[9/16] " src="${placeholderImage}" alt="provider"></div></div> </div></div>\n</section>`,
55
55
  cover_image: null,
56
56
  },
57
57
  {
58
58
  title: '4 Square Images With Text',
59
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-4"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"><div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> </div> </div> </div>\n</section>`,
59
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-4"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"><div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> </div> </div> </div>\n</section>`,
60
60
  cover_image: null,
61
61
  },
62
62
  {
63
63
  title: '3 Square Images With Text',
64
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> </div> </div> </div>\n</section>`,
64
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> </div> </div> </div>\n</section>`,
65
65
  cover_image: null,
66
66
  },
67
67
  {
68
68
  title: '2 Square Images With Text',
69
- html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-2"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square smooth-transition" src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> </div> </div> </div>\n</section>`,
69
+ html_code: `<section>\n<div class="w-full md:pt-12 md:pb-12 pt-4 pb-4 lg:px-4 px-2"><div class="mx-auto max-w-7xl"><div class="myPrimaryGap grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-2"> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> <div class="flex-1 py-2"> <img class="object-cover w-full object-top aspect-square " src="${placeholderImage}" alt="provider"> <div class="break-words py-2"><p>Layouts and visual.</p><p>Ullamcorper dignissim cras tincidunt.</p></div> </div> </div> </div> </div>\n</section>`,
70
70
  cover_image: null,
71
71
  },
72
72
  ],