@myissue/vue-website-page-builder 3.3.97 → 3.3.98

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myissue/vue-website-page-builder",
3
- "version": "3.3.97",
3
+ "version": "3.3.98",
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",
@@ -52,12 +52,12 @@
52
52
  "license": "MIT",
53
53
  "repository": {
54
54
  "type": "git",
55
- "url": "https://github.com/qaiswardag/vue-website-page-builder.git"
55
+ "url": "git+ssh://git@github.com/myissue-org/vue-website-page-builder.git"
56
56
  },
57
57
  "bugs": {
58
- "url": "https://github.com/qaiswardag/vue-website-page-builder/issues"
58
+ "url": "https://github.com/myissue-org/vue-website-page-builder/issues"
59
59
  },
60
- "homepage": "https://mybuilder.dev",
60
+ "homepage": "https://www.mybuilder.dev",
61
61
  "engines": {
62
62
  "node": ">=18.0.0",
63
63
  "npm": ">=8.0.0"
@@ -18,7 +18,7 @@ const version = __APP_VERSION__
18
18
  </p>
19
19
  <p class="pbx-myPrimaryParagraph pbx-mt-3">
20
20
  <a
21
- href="https://github.com/qaiswardag/vue-website-page-builder"
21
+ href="https://github.com/myissue-org/vue-website-page-builder"
22
22
  target="_blank"
23
23
  class="pbx-myPrimaryLink pbx-text-myPrimaryDarkGrayColor"
24
24
  >
package/src/css/style.css CHANGED
@@ -485,22 +485,18 @@
485
485
 
486
486
  @keyframes pbx-reorder-flash {
487
487
  0% {
488
- box-shadow: 0 0 0 0px rgba(66, 153, 225, 0.7);
489
488
  transform: scale(1);
490
489
  opacity: 1;
491
490
  }
492
491
  50% {
493
- box-shadow: 0 0 0 10px rgba(66, 153, 225, 0);
494
- transform: scale(0.2); /* Even more shrink */
495
- opacity: 0.8;
492
+ transform: scale(0.8);
493
+ opacity: 0.6;
496
494
  }
497
495
  100% {
498
- box-shadow: 0 0 0 0px rgba(66, 153, 225, 0);
499
496
  transform: scale(1);
500
497
  opacity: 1;
501
498
  }
502
499
  }
503
500
 
504
501
  .pbx-sibling-highlight {
505
- border: 2px dashed #4299e1; /* Blue dashed border */
506
502
  }
@@ -1043,9 +1043,11 @@ export class PageBuilderService {
1043
1043
  /**
1044
1044
  * Manually saves the current page builder content to local storage.
1045
1045
  */
1046
- public handleManualSave = async () => {
1046
+ public handleManualSave = async (doNoClearHTML?: boolean) => {
1047
1047
  this.pageBuilderStateStore.setIsSaving(true)
1048
- this.clearHtmlSelection()
1048
+ if (!doNoClearHTML) {
1049
+ this.clearHtmlSelection()
1050
+ }
1049
1051
  this.startEditing()
1050
1052
  this.saveDomComponentsToLocalStorage()
1051
1053
  await delay(300)
@@ -1665,10 +1667,12 @@ export class PageBuilderService {
1665
1667
  await nextTick()
1666
1668
 
1667
1669
  // Scroll to the moved component
1668
- const pageBuilderWrapper = document.querySelector('#page-builder-wrapper')
1670
+ const pageBuilderWrapper = document.querySelector(
1671
+ '#page-builder-wrapper',
1672
+ ) as HTMLElement | null
1669
1673
  const movedComponentElement = pageBuilderWrapper?.querySelector(
1670
1674
  `section[data-componentid="${componentToMove.id}"]`,
1671
- )
1675
+ ) as HTMLElement
1672
1676
 
1673
1677
  if (movedComponentElement) {
1674
1678
  // Apply highlight to the moved element
@@ -1685,19 +1689,22 @@ export class PageBuilderService {
1685
1689
  nextSibling.classList.add('pbx-sibling-highlight')
1686
1690
  }
1687
1691
 
1688
- // Scroll to the moved component
1689
- movedComponentElement.scrollIntoView({ behavior: 'smooth', block: 'center' })
1690
-
1691
- // Remove highlights after a delay
1692
- setTimeout(() => {
1693
- movedComponentElement.classList.remove('pbx-reorder-highlight')
1694
- if (prevSibling && prevSibling.tagName === 'SECTION') {
1695
- prevSibling.classList.remove('pbx-sibling-highlight')
1696
- }
1697
- if (nextSibling && nextSibling.tagName === 'SECTION') {
1698
- nextSibling.classList.remove('pbx-sibling-highlight')
1699
- }
1700
- }, 1000) // Adjust delay as needed
1692
+ if (pageBuilderWrapper) {
1693
+ // Scroll to the moved component
1694
+ const topPos = movedComponentElement.offsetTop - pageBuilderWrapper.offsetTop
1695
+ pageBuilderWrapper.scrollTop = topPos - pageBuilderWrapper.clientHeight / 2
1696
+
1697
+ // Remove highlights after a delay
1698
+ setTimeout(() => {
1699
+ movedComponentElement.classList.remove('pbx-reorder-highlight')
1700
+ if (prevSibling && prevSibling.tagName === 'SECTION') {
1701
+ prevSibling.classList.remove('pbx-sibling-highlight')
1702
+ }
1703
+ if (nextSibling && nextSibling.tagName === 'SECTION') {
1704
+ nextSibling.classList.remove('pbx-sibling-highlight')
1705
+ }
1706
+ }, 200)
1707
+ }
1701
1708
  }
1702
1709
  }
1703
1710
 
@@ -1920,6 +1927,9 @@ export class PageBuilderService {
1920
1927
  pagebuilder.querySelectorAll('section[data-componentid]').forEach((section) => {
1921
1928
  const sanitizedSection = this.cloneAndRemoveSelectionAttributes(section as HTMLElement)
1922
1929
 
1930
+ // Remove the data-componentid attribute
1931
+ sanitizedSection.removeAttribute('data-componentid')
1932
+
1923
1933
  componentsToSave.push({
1924
1934
  html_code: sanitizedSection.outerHTML,
1925
1935
  title: sanitizedSection.getAttribute('data-component-title') || 'Untitled Component',
@@ -1938,7 +1948,29 @@ export class PageBuilderService {
1938
1948
  }
1939
1949
 
1940
1950
  const baseKey = this.getHistoryBaseKey()
1951
+
1941
1952
  if (baseKey) {
1953
+ const currentDataRaw = localStorage.getItem(baseKey)
1954
+ if (currentDataRaw) {
1955
+ const currentData = JSON.parse(currentDataRaw)
1956
+
1957
+ // Compare components
1958
+ const currentComponents = currentData.components || []
1959
+ const newComponents = dataToSave.components || []
1960
+
1961
+ const hasChanges = newComponents.some((newComponent, index) => {
1962
+ const currentComponent = currentComponents[index]
1963
+ return (
1964
+ !currentComponent || // New component added
1965
+ currentComponent.html_code !== newComponent.html_code // Component HTML changed
1966
+ )
1967
+ })
1968
+
1969
+ if (!hasChanges) {
1970
+ return
1971
+ }
1972
+ }
1973
+
1942
1974
  localStorage.setItem(baseKey, JSON.stringify(dataToSave))
1943
1975
  let history = LocalStorageManager.getHistory(baseKey)
1944
1976
 
@@ -2588,6 +2620,134 @@ export class PageBuilderService {
2588
2620
  }
2589
2621
  }
2590
2622
 
2623
+ /**
2624
+ * Applies modified components by mounting them to the DOM and attaching listeners.
2625
+ * @param htmlString - The HTML string to apply
2626
+ * @returns {Promise<string | null>} - Returns error message if failed, otherwise null
2627
+ */
2628
+ public async applyModifiedHTML(htmlString: string): Promise<string | null> {
2629
+ if (!htmlString || (typeof htmlString === 'string' && htmlString.length === 0)) {
2630
+ return 'No HTML content was provided. Please ensure a valid HTML string is passed.'
2631
+ }
2632
+
2633
+ // Check if the htmlString contains any <section> tags
2634
+ if (/<section[\s>]/i.test(htmlString)) {
2635
+ return 'Error: The <section> tag cannot be used as it is already included inside this component.'
2636
+ }
2637
+
2638
+ const tempDiv = document.createElement('div')
2639
+ tempDiv.innerHTML = htmlString.trim()
2640
+
2641
+ const parsedElement = tempDiv.firstElementChild as HTMLElement | null
2642
+
2643
+ if (!parsedElement) {
2644
+ return 'Could not parse element from HTML string.'
2645
+ }
2646
+
2647
+ // Replace the actual DOM element
2648
+ const oldElement = this.pageBuilderStateStore.getElement
2649
+
2650
+ if (oldElement && oldElement.parentElement) {
2651
+ oldElement.replaceWith(parsedElement)
2652
+
2653
+ // Update the element in the store (now referencing the new one)
2654
+ this.pageBuilderStateStore.setElement(parsedElement)
2655
+ }
2656
+
2657
+ await this.addListenersToEditableElements()
2658
+ await nextTick()
2659
+ return null
2660
+ }
2661
+
2662
+ private validateMountingHTML(
2663
+ htmlString: string,
2664
+ options?: { logError?: boolean },
2665
+ ): string | null {
2666
+ // Trim HTML string
2667
+ const trimmedData = htmlString.trim()
2668
+ const openingSectionMatches = htmlString.match(/<section\b[^>]*>/gi) || []
2669
+ const closingSectionMatches = htmlString.match(/<\/section>/gi) || []
2670
+
2671
+ if (!htmlString || htmlString.trim().length === 0) {
2672
+ const error = 'No HTML content was provided. Please ensure a valid HTML string is passed.'
2673
+ if (options && options.logError) {
2674
+ console.error(error)
2675
+ // Behavior
2676
+ return error
2677
+ }
2678
+ // default behavior
2679
+ return error
2680
+ }
2681
+
2682
+ if (openingSectionMatches.length !== closingSectionMatches.length) {
2683
+ const error =
2684
+ 'Uneven <section> tags detected in the provided HTML. Each component must be wrapped in its own properly paired <section>...</section>. ' +
2685
+ 'Ensure that all <section> tags have a matching closing </section> tag.'
2686
+
2687
+ if (options && options.logError) {
2688
+ console.error(error)
2689
+ return error
2690
+ }
2691
+
2692
+ return error
2693
+ }
2694
+
2695
+ const tempDiv = document.createElement('div')
2696
+ tempDiv.innerHTML = trimmedData
2697
+ const nestedSection = tempDiv.querySelector('section section')
2698
+ if (nestedSection) {
2699
+ const error =
2700
+ 'Nested <section> tags are not allowed. Please ensure that no <section> is placed inside another <section>.'
2701
+ if (options && options.logError) {
2702
+ console.error(error)
2703
+ return error
2704
+ }
2705
+ return error
2706
+ }
2707
+
2708
+ // Return error since JSON data has been passed to mount HTML to DOM
2709
+ if (trimmedData.startsWith('[') || trimmedData.startsWith('{')) {
2710
+ const error =
2711
+ 'Brackets [] or curly braces {} are not valid HTML. They are used for data formats like JSON.'
2712
+ if (options && options.logError) {
2713
+ console.error(error)
2714
+ return error
2715
+ }
2716
+
2717
+ return error
2718
+ }
2719
+
2720
+ return null
2721
+ }
2722
+
2723
+ /**
2724
+ * Applies modified components by mounting them to the DOM and attaching listeners.
2725
+ * @param htmlString - The HTML string to apply
2726
+ * @returns {Promise<string | null>} - Returns error message if failed, otherwise null
2727
+ */
2728
+ public async applyModifiedComponents(htmlString: string): Promise<string | null> {
2729
+ // Trim HTML string
2730
+ const trimmedData = htmlString.trim()
2731
+
2732
+ const openingSectionMatches = htmlString.match(/<section\b[^>]*>/gi) || []
2733
+
2734
+ if (openingSectionMatches.length === 0) {
2735
+ const error = 'No <section> tags found. Each component must be wrapped in a <section> tag.'
2736
+ if (error) {
2737
+ return error
2738
+ }
2739
+ }
2740
+
2741
+ const validationError = this.validateMountingHTML(trimmedData)
2742
+ if (validationError) return validationError
2743
+
2744
+ // also fixed to use `trimmedData`
2745
+ await this.mountComponentsToDOM(trimmedData)
2746
+ await this.addListenersToEditableElements()
2747
+ await nextTick()
2748
+ return null
2749
+ }
2750
+
2591
2751
  /**
2592
2752
  * Mounts builder components to the DOM from an HTML string.
2593
2753
  *
@@ -2606,13 +2766,11 @@ export class PageBuilderService {
2606
2766
  htmlString: string,
2607
2767
  usePassedPageSettings?: boolean,
2608
2768
  ): Promise<void> {
2769
+ // Trim HTML string
2609
2770
  const trimmedData = htmlString.trim()
2610
2771
 
2611
- // Return error since JSON data has been passed to mount HTML to DOM
2612
- if (trimmedData.startsWith('[') || trimmedData.startsWith('{')) {
2613
- console.error('Error: JSON data passed to mountComponentsToDOM for the Page Builder Package.')
2614
- return
2615
- }
2772
+ const validationError = this.validateMountingHTML(trimmedData, { logError: true })
2773
+ if (validationError) return
2616
2774
 
2617
2775
  // HTML string
2618
2776
  try {
@@ -2851,57 +3009,6 @@ export class PageBuilderService {
2851
3009
  }
2852
3010
  }
2853
3011
 
2854
- /**
2855
- * Applies modified components by mounting them to the DOM and attaching listeners.
2856
- * @param htmlString - The HTML string to apply
2857
- * @returns {Promise<string | null>} - Returns error message if failed, otherwise null
2858
- */
2859
- public async applyModifiedHTML(htmlString: string): Promise<string | null> {
2860
- if (!htmlString || (typeof htmlString === 'string' && htmlString.length === 0)) {
2861
- return 'No HTML content was provided. Please ensure a valid HTML string is passed.'
2862
- }
2863
-
2864
- const tempDiv = document.createElement('div')
2865
- tempDiv.innerHTML = htmlString.trim()
2866
-
2867
- const parsedElement = tempDiv.firstElementChild as HTMLElement | null
2868
-
2869
- if (!parsedElement) {
2870
- return 'Could not parse element from HTML string.'
2871
- }
2872
-
2873
- // Replace the actual DOM element
2874
- const oldElement = this.pageBuilderStateStore.getElement
2875
-
2876
- if (oldElement && oldElement.parentElement) {
2877
- oldElement.replaceWith(parsedElement)
2878
-
2879
- // Update the element in the store (now referencing the new one)
2880
- this.pageBuilderStateStore.setElement(parsedElement)
2881
- }
2882
-
2883
- await this.addListenersToEditableElements()
2884
- await nextTick()
2885
- return null
2886
- }
2887
-
2888
- /**
2889
- * Applies modified components by mounting them to the DOM and attaching listeners.
2890
- * @param htmlString - The HTML string to apply
2891
- * @returns {Promise<string | null>} - Returns error message if failed, otherwise null
2892
- */
2893
- public async applyModifiedComponents(htmlString: string): Promise<string | null> {
2894
- if (!htmlString || (typeof htmlString === 'string' && htmlString.length === 0)) {
2895
- return 'No HTML content was provided. Please ensure a valid HTML string is passed.'
2896
- }
2897
-
2898
- await this.mountComponentsToDOM(htmlString)
2899
-
2900
- await this.addListenersToEditableElements()
2901
- await nextTick()
2902
- return null
2903
- }
2904
-
2905
3012
  /**
2906
3013
  * Initializes the styles for the currently selected element.
2907
3014
  */
@@ -3,7 +3,7 @@ import FullWidthElement from '../Components/Layouts/FullWidthElement.vue'
3
3
  import PageBuilder from '../PageBuilder/PageBuilder.vue'
4
4
  import DemoMediaLibraryComponentTest from '../tests/TestComponents/DemoMediaLibraryComponentTest.vue'
5
5
  import DemoBuilderComponentsTest from '../tests/TestComponents/DemoBuilderComponentsTest.vue'
6
- import { onMounted, computed, watch } from 'vue'
6
+ import { computed, watch } from 'vue'
7
7
  import componentsArray from '../tests/componentsArray.test.json'
8
8
  import { getPageBuilder } from '../composables/builderInstance'
9
9
  import { useTranslations } from '../composables/useTranslations'
@@ -1,61 +1,61 @@
1
1
  [
2
2
  {
3
- "html_code": "<section data-componentid=\"ba0e9774-3779-467c-9c9f-5c95dd47fa6d\" data-component-title=\"Header H2\"><div class=\"pbx-relative pbx-py-4\"><div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-break-words pbx-text-6xl lg:pbx-text-8xl pbx-font-medium\"><h2>{{ translate('Demo Content') }}</h2></div></div></div></section>",
3
+ "html_code": "<section data-component-title=\"Header H2\"><div class=\"pbx-relative pbx-py-4\"><div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-break-words pbx-text-6xl lg:pbx-text-8xl pbx-font-medium\"><h2>{{ translate('Demo Content') }}</h2></div></div></div></section>",
4
4
  "id": "ba0e9774-3779-467c-9c9f-5c95dd47fa6d",
5
5
  "title": "Header H2"
6
6
  },
7
7
  {
8
- "html_code": "<section data-componentid=\"d9fe6bdb-60df-45e4-bed5-1a6f8edf28e5\" data-component-title=\"Text\">\n <div class=\"pbx-relative pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\">\n <div><p>{{ translate('Demo Description') }}</p></div>\n </div>\n </div>\n </section>",
8
+ "html_code": "<section data-component-title=\"Text\">\n <div class=\"pbx-relative pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\">\n <div><p>{{ translate('Demo Description') }}</p></div>\n </div>\n </div>\n </section>",
9
9
  "id": "d9fe6bdb-60df-45e4-bed5-1a6f8edf28e5",
10
10
  "title": "Text"
11
11
  },
12
12
  {
13
- "html_code": "<section data-componentid=\"0bb012a0-631a-497f-9b7f-832313b64a2b\" data-component-title=\"Three 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>",
13
+ "html_code": "<section data-component-title=\"Three 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": "Three Vertical Images"
16
16
  },
17
17
  {
18
- "html_code": "<section data-componentid=\"cd7e27ac-b152-4714-a5f7-5ad660f183bf\" data-component-title=\"Header H3\"><div class=\"pbx-relative pbx-py-4\"><div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-break-words pbx-mt-6 pbx-font-medium pbx-text-2xl lg:pbx-text-4xl\"><h3>{{ translate('Demo Title') }}</h3></div></div></div></section>",
18
+ "html_code": "<section data-component-title=\"Header H3\"><div class=\"pbx-relative pbx-py-4\"><div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-break-words pbx-mt-6 pbx-font-medium pbx-text-2xl lg:pbx-text-4xl\"><h3>{{ translate('Demo Title') }}</h3></div></div></div></section>",
19
19
  "id": "cd7e27ac-b152-4714-a5f7-5ad660f183bf",
20
20
  "title": "Header H3"
21
21
  },
22
22
  {
23
- "html_code": "<section data-componentid=\"b1e75d09-0e72-4c61-a207-a97277cbbfed\" data-component-title=\"Text\">\n <div class=\"pbx-relative pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\">\n <div><p>{{ translate('Demo Description Two') }}</p></div>\n </div>\n </div>\n </section>",
23
+ "html_code": "<section data-component-title=\"Text\">\n <div class=\"pbx-relative pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\">\n <div><p>{{ translate('Demo Description Two') }}</p></div>\n </div>\n </div>\n </section>",
24
24
  "id": "b1e75d09-0e72-4c61-a207-a97277cbbfed",
25
25
  "title": "Text"
26
26
  },
27
27
  {
28
- "html_code": "<section data-componentid=\"d3b5a3e4-29a3-4b03-88b6-1f77d319af74\" data-component-title=\"Two 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>",
28
+ "html_code": "<section data-component-title=\"Two 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": "Two Vertical Images"
31
31
  },
32
32
  {
33
- "html_code": "<section data-componentid=\"f164929b-4460-4b17-9933-119b47e8bbef\" data-component-title=\"Header H3\"><div class=\"pbx-relative pbx-py-4\"><div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-break-words pbx-mt-6 pbx-font-medium pbx-text-2xl lg:pbx-text-4xl\"><h3>{{ translate('Demo Title Two') }}</h3></div></div></div></section>",
33
+ "html_code": "<section data-component-title=\"Header H3\"><div class=\"pbx-relative pbx-py-4\"><div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-break-words pbx-mt-6 pbx-font-medium pbx-text-2xl lg:pbx-text-4xl\"><h3>{{ translate('Demo Title Two') }}</h3></div></div></div></section>",
34
34
  "id": "f164929b-4460-4b17-9933-119b47e8bbef",
35
35
  "title": "Header H3"
36
36
  },
37
37
  {
38
- "html_code": "<section data-componentid=\"fa721207-2444-4892-9de3-5260d576a34b\" data-component-title=\"Text\">\n <div class=\"pbx-relative pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\">\n <div class=\"\"><p>{{ translate('Demo Description Three') }}</p></div>\n </div>\n </div>\n </section>",
38
+ "html_code": "<section data-component-title=\"Text\">\n <div class=\"pbx-relative pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\">\n <div class=\"\"><p>{{ translate('Demo Description Three') }}</p></div>\n </div>\n </div>\n </section>",
39
39
  "id": "fa721207-2444-4892-9de3-5260d576a34b",
40
40
  "title": "Text"
41
41
  },
42
42
  {
43
- "html_code": "<section data-componentid=\"33a26684-eb95-43c9-adb4-d7bce0ca60f7\" data-component-title=\"YouTube Video\">\n <div class=\"pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl pbx-w-full pbx-pt-6 pbx-pb-6\">\n <div id=\"youtube-video\" class=\"pbx-w-full pbx-aspect-video pbx-p-4\">\n\n <iframe frameborder=\"0\" allowfullscreen=\"\" class=\"pbx-w-full pbx-aspect-video\" src=\"https://www.youtube.com/embed/pJvwV1Fm0vU\" allow=\"accelerometer; autoplay; clipboard-write;\">\n </iframe>\n </div>\n </div>\n </div>\n </section>",
43
+ "html_code": "<section data-component-title=\"YouTube Video\">\n <div class=\"pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl pbx-w-full pbx-pt-6 pbx-pb-6\">\n <div id=\"youtube-video\" class=\"pbx-w-full pbx-aspect-video pbx-p-4\">\n\n <iframe frameborder=\"0\" allowfullscreen=\"\" class=\"pbx-w-full pbx-aspect-video\" src=\"https://www.youtube.com/embed/pJvwV1Fm0vU\" allow=\"accelerometer; autoplay; clipboard-write;\">\n </iframe>\n </div>\n </div>\n </div>\n </section>",
44
44
  "id": "33a26684-eb95-43c9-adb4-d7bce0ca60f7",
45
45
  "title": "YouTube Video"
46
46
  },
47
47
  {
48
- "html_code": "<section data-componentid=\"de2208e1-5b65-4302-8ffb-b9beb7d192d7\" title=\"Header H3\" data-component-title=\"Header H3\"><div class=\"pbx-relative pbx-py-4\"><div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-break-words pbx-text-2xl lg:pbx-text-4xl pbx-font-medium\"><h3>{{ translate('Demo Title Three') }}</h3></div></div></div></section>",
48
+ "html_code": "<section data-component-title=\"Header H3\"><div class=\"pbx-relative pbx-py-4\"><div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\"><div class=\"pbx-break-words pbx-text-2xl lg:pbx-text-4xl pbx-font-medium\"><h3>{{ translate('Demo Title Three') }}</h3></div></div></div></section>",
49
49
  "id": "de2208e1-5b65-4302-8ffb-b9beb7d192d7",
50
50
  "title": "Header H3"
51
51
  },
52
52
  {
53
- "html_code": "<section data-componentid=\"e9a5c794-5972-473d-8181-af4345cbaabe\" title=\"Text\" data-component-title=\"Text\">\n <div class=\"pbx-relative pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\">\n <div><p>{{ translate('Demo Description Four') }}</p><p></p></div>\n </div>\n </div>\n </section>",
53
+ "html_code": "<section data-component-title=\"Text\">\n <div class=\"pbx-relative pbx-py-4\">\n <div class=\"pbx-mx-auto pbx-max-w-7xl lg:pbx-px-4 pbx-px-2\">\n <div><p>{{ translate('Demo Description Four') }}</p><p></p></div>\n </div>\n </div>\n </section>",
54
54
  "id": "e9a5c794-5972-473d-8181-af4345cbaabe",
55
55
  "title": "Text"
56
56
  },
57
57
  {
58
- "html_code": "<section data-componentid=\"7bcda060-8ed5-482f-bcf4-aa6bd7fdb193\" title=\"Six Square Images Grid\" data-component-title=\"Six 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>",
58
+ "html_code": "<sectio data-component-title=\"Six 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</sectio>",
59
59
  "id": "7bcda060-8ed5-482f-bcf4-aa6bd7fdb193",
60
60
  "title": "Six Square Images Grid"
61
61
  }