@shopware/cms-base-layer 1.5.0 → 2.0.0
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/README.md +328 -13
- package/app/app.config.ts +7 -0
- package/app/assets/icons/check-circle.svg +3 -0
- package/app/assets/icons/checkmark.svg +3 -0
- package/app/assets/icons/chevron.svg +3 -0
- package/app/assets/icons/exclamation-circle.svg +3 -0
- package/app/assets/icons/star-empty.svg +3 -0
- package/app/assets/icons/star-filled.svg +3 -0
- package/app/assets/icons/user.svg +1 -0
- package/app/components/SwCategoryNavigation.vue +76 -0
- package/app/components/SwCategoryNavigationLink.vue +128 -0
- package/{components → app/components}/SwContactForm.vue +27 -27
- package/app/components/SwFilterChips.vue +144 -0
- package/app/components/SwListingProductPrice.vue +89 -0
- package/{components → app/components}/SwNewsletterForm.vue +45 -34
- package/{components → app/components}/SwPagination.vue +3 -5
- package/{components → app/components}/SwProductAddToCart.vue +22 -27
- package/app/components/SwProductCard.vue +170 -0
- package/app/components/SwProductCardDetails.vue +57 -0
- package/app/components/SwProductCardImage.vue +87 -0
- package/app/components/SwProductCardSkeleton.vue +33 -0
- package/app/components/SwProductListingFilter.vue +64 -0
- package/app/components/SwProductListingFilters.vue +308 -0
- package/{components → app/components}/SwProductReviews.vue +28 -13
- package/app/components/SwProductReviewsForm.vue +292 -0
- package/app/components/SwQuantitySelect.vue +106 -0
- package/{components → app/components}/SwSlider.vue +4 -4
- package/app/components/SwSortDropdown.vue +83 -0
- package/app/components/SwStockInfo.vue +44 -0
- package/{components → app/components}/SwVariantConfigurator.vue +1 -1
- package/app/components/listing-filters/SwFilterPrice.vue +214 -0
- package/app/components/listing-filters/SwFilterProperties.vue +113 -0
- package/app/components/listing-filters/SwFilterRating.vue +90 -0
- package/app/components/listing-filters/SwFilterShippingFree.vue +107 -0
- package/{components → app/components}/public/cms/CmsPage.vue +19 -4
- package/{components → app/components}/public/cms/block/CmsBlockGalleryBuybox.vue +5 -5
- package/{components → app/components}/public/cms/block/CmsBlockImageBubbleRow.vue +5 -5
- package/app/components/public/cms/block/CmsBlockImageFourColumn.vue +41 -0
- package/app/components/public/cms/block/CmsBlockImageGalleryBig.vue +42 -0
- package/app/components/public/cms/block/CmsBlockImageHighlightRow.vue +37 -0
- package/{components → app/components}/public/cms/block/CmsBlockImageSimpleGrid.vue +11 -5
- package/{components → app/components}/public/cms/block/CmsBlockImageText.vue +7 -3
- package/{components → app/components}/public/cms/block/CmsBlockImageTextBubble.vue +13 -16
- package/{components → app/components}/public/cms/block/CmsBlockImageTextCover.vue +7 -9
- package/app/components/public/cms/block/CmsBlockImageTextGallery.vue +88 -0
- package/app/components/public/cms/block/CmsBlockImageTextRow.vue +53 -0
- package/{components → app/components}/public/cms/block/CmsBlockImageThreeColumn.vue +10 -4
- package/app/components/public/cms/block/CmsBlockImageThreeCover.vue +37 -0
- package/app/components/public/cms/block/CmsBlockImageTwoColumn.vue +37 -0
- package/{components → app/components}/public/cms/block/CmsBlockProductHeading.vue +1 -1
- package/{components → app/components}/public/cms/block/CmsBlockProductThreeColumn.vue +10 -4
- package/{components → app/components}/public/cms/block/CmsBlockSidebarFilter.vue +3 -1
- package/app/components/public/cms/block/CmsBlockTextOnImage.vue +30 -0
- package/{components → app/components}/public/cms/block/CmsBlockTextTeaserSection.vue +4 -4
- package/{components → app/components}/public/cms/block/CmsBlockTextTwoColumn.vue +3 -5
- package/app/components/public/cms/element/CmsElementBuyBox.vue +145 -0
- package/app/components/public/cms/element/CmsElementCategoryNavigation.vue +53 -0
- package/{components → app/components}/public/cms/element/CmsElementCrossSelling.vue +3 -3
- package/{components → app/components}/public/cms/element/CmsElementImage.vue +52 -13
- package/app/components/public/cms/element/CmsElementImageGallery.vue +158 -0
- package/{components → app/components}/public/cms/element/CmsElementImageSlider.vue +2 -2
- package/{components → app/components}/public/cms/element/CmsElementProductBox.vue +2 -1
- package/app/components/public/cms/element/CmsElementProductDescriptionReviews.vue +217 -0
- package/{components → app/components}/public/cms/element/CmsElementProductListing.vue +23 -94
- package/app/components/public/cms/element/CmsElementProductName.vue +11 -0
- package/{components → app/components}/public/cms/element/CmsElementProductSlider.vue +4 -4
- package/{components → app/components}/public/cms/element/CmsElementText.vue +8 -2
- package/{components → app/components}/public/cms/element/CmsElementYoutubeVideo.vue +8 -2
- package/app/components/public/cms/element/SwProductListingPagination.vue +70 -0
- package/{components → app/components}/public/cms/section/CmsSectionDefault.vue +1 -1
- package/app/components/public/cms/section/CmsSectionSidebar.vue +36 -0
- package/app/components/public/cms/skeleton/ProductCardSkeleton.vue +28 -0
- package/app/components/ui/BaseButton.vue +99 -0
- package/app/components/ui/BaseIcon.vue +15 -0
- package/app/components/ui/Checkbox.vue +49 -0
- package/app/components/ui/CheckmarkIcon.vue +23 -0
- package/app/components/ui/ChevronIcon.vue +37 -0
- package/app/components/ui/ExclamationIcon.vue +11 -0
- package/app/components/ui/IconButton.vue +32 -0
- package/app/components/ui/RadioButton.vue +26 -0
- package/app/components/ui/StarIcon.vue +18 -0
- package/app/components/ui/SwitchButton.vue +100 -0
- package/app/components/ui/UserIcon.vue +11 -0
- package/app/components/ui/WishlistIcon.vue +20 -0
- package/app/composables/useImagePlaceholder.ts +27 -0
- package/{helpers → app/helpers}/clientOnly.ts +5 -0
- package/app/providers/shopware.test.ts +213 -0
- package/app/providers/shopware.ts +107 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +2 -2
- package/index.d.ts +12 -0
- package/nuxt.config.ts +80 -6
- package/package.json +29 -21
- package/uno.config.ts +83 -0
- package/components/SwCategoryNavigation.vue +0 -44
- package/components/SwCategoryNavigationLink.vue +0 -57
- package/components/SwListingProductPrice.vue +0 -89
- package/components/SwProductCard.vue +0 -286
- package/components/SwProductListingFilter.vue +0 -42
- package/components/SwProductListingFilters.vue +0 -292
- package/components/listing-filters/SwFilterPrice.vue +0 -160
- package/components/listing-filters/SwFilterProperties.vue +0 -123
- package/components/listing-filters/SwFilterRating.vue +0 -101
- package/components/listing-filters/SwFilterShippingFree.vue +0 -104
- package/components/public/cms/block/CmsBlockImageFourColumn.vue +0 -29
- package/components/public/cms/block/CmsBlockImageHighlightRow.vue +0 -27
- package/components/public/cms/block/CmsBlockImageTextGallery.vue +0 -85
- package/components/public/cms/block/CmsBlockImageTextRow.vue +0 -43
- package/components/public/cms/block/CmsBlockImageThreeCover.vue +0 -27
- package/components/public/cms/block/CmsBlockImageTwoColumn.vue +0 -25
- package/components/public/cms/block/CmsBlockTextOnImage.vue +0 -20
- package/components/public/cms/element/CmsBlockHtml.md +0 -1
- package/components/public/cms/element/CmsElementBuyBox.vue +0 -190
- package/components/public/cms/element/CmsElementCategoryNavigation.vue +0 -167
- package/components/public/cms/element/CmsElementImageGallery.vue +0 -249
- package/components/public/cms/element/CmsElementProductDescriptionReviews.vue +0 -123
- package/components/public/cms/element/CmsElementProductName.vue +0 -10
- package/components/public/cms/section/CmsSectionSidebar.vue +0 -49
- package/components/public/cms/skeleton/ProductCardSkeleton.vue +0 -44
- /package/{components → app/components}/SwMedia3D.vue +0 -0
- /package/{components → app/components}/SwProductGallery.vue +0 -0
- /package/{components → app/components}/SwProductPrice.vue +0 -0
- /package/{components → app/components}/SwProductUnits.vue +0 -0
- /package/{components → app/components}/SwSharedPrice.vue +0 -0
- /package/{components → app/components}/public/cms/CmsGenericBlock.md +0 -0
- /package/{components → app/components}/public/cms/CmsGenericBlock.vue +0 -0
- /package/{components → app/components}/public/cms/CmsGenericElement.md +0 -0
- /package/{components → app/components}/public/cms/CmsGenericElement.vue +0 -0
- /package/{components → app/components}/public/cms/CmsNoComponent.vue +0 -0
- /package/{components → app/components}/public/cms/CmsPage.md +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockCategoryNavigation.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockCenterText.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockCrossSelling.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockCustomForm.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockDefault.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockForm.vue +0 -0
- /package/{components/public/cms/element → app/components/public/cms/block}/CmsBlockHtml.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockImage.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockImageCover.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockImageGallery.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockImageSlider.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockProductDescriptionReviews.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockProductListing.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockProductSlider.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockText.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockTextHero.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockTextTeaser.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockTextThreeColumn.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockVimeoVideo.vue +0 -0
- /package/{components → app/components}/public/cms/block/CmsBlockYoutubeVideo.vue +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementBuyBox.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementCategoryNavigation.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementCrossSelling.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementCustomForm.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementCustomForm.vue +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementForm.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementForm.vue +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementHtml.vue +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementImage.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementImageGallery.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementImageGallery3dPlaceholder.vue +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementImageSlider.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementManufacturerLogo.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementManufacturerLogo.vue +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementProductBox.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementProductDescriptionReviews.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementProductListing.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementProductName.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementProductSlider.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementSidebarFilter.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementSidebarFilter.vue +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementText.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementVimeoVideo.md +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementVimeoVideo.vue +0 -0
- /package/{components → app/components}/public/cms/element/CmsElementYoutubeVideo.md +0 -0
- /package/{components → app/components}/public/cms/section/CmsSectionDefault.md +0 -0
- /package/{components → app/components}/public/cms/section/CmsSectionSidebar.md +0 -0
- /package/{helpers → app/helpers}/html-to-vue/ast.ts +0 -0
- /package/{helpers → app/helpers}/html-to-vue/getOptionsFromNode.test.ts +0 -0
- /package/{helpers → app/helpers}/html-to-vue/getOptionsFromNode.ts +0 -0
- /package/{helpers → app/helpers}/html-to-vue/renderToHtml.ts +0 -0
- /package/{helpers → app/helpers}/html-to-vue/renderer.ts +0 -0
- /package/{helpers → app/helpers}/media/isSpatial.ts +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script
|
|
2
|
+
setup
|
|
3
|
+
lang="ts"
|
|
4
|
+
generic="
|
|
5
|
+
ListingFilter extends {
|
|
6
|
+
id: string;
|
|
7
|
+
code: keyof Schemas['ProductListingResult']['currentFilters'];
|
|
8
|
+
label: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
"
|
|
12
|
+
>
|
|
13
|
+
import { useCmsTranslations } from "@shopware/composables";
|
|
14
|
+
import { onClickOutside } from "@vueuse/core";
|
|
15
|
+
import { defu } from "defu";
|
|
16
|
+
import { computed, ref } from "vue";
|
|
17
|
+
import type { Schemas } from "#shopware";
|
|
18
|
+
|
|
19
|
+
const props = defineProps<{
|
|
20
|
+
filter: ListingFilter;
|
|
21
|
+
selectedFilters: Schemas["ProductListingResult"]["currentFilters"];
|
|
22
|
+
description?: string; // Optional description for i18n
|
|
23
|
+
}>();
|
|
24
|
+
|
|
25
|
+
type Translations = {
|
|
26
|
+
listing: {
|
|
27
|
+
freeShipping: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
let translations: Translations = {
|
|
31
|
+
listing: {
|
|
32
|
+
freeShipping: "Free shipping",
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
translations = defu(useCmsTranslations(), translations) as Translations;
|
|
36
|
+
|
|
37
|
+
const emits =
|
|
38
|
+
defineEmits<
|
|
39
|
+
(e: "select-value", value: { code: string; value: unknown }) => void
|
|
40
|
+
>();
|
|
41
|
+
const currentFilterData = computed(
|
|
42
|
+
() => !!props.selectedFilters[props.filter?.code],
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const isFilterVisible = ref<boolean>(false);
|
|
46
|
+
const toggle = () => {
|
|
47
|
+
isFilterVisible.value = !isFilterVisible.value;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const dropdownElement = ref(null);
|
|
51
|
+
onClickOutside(dropdownElement, () => {
|
|
52
|
+
isFilterVisible.value = false;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const handleRadioUpdate = (val: string | null | boolean | undefined) => {
|
|
56
|
+
emits("select-value", { code: props.filter.code, value: !!val });
|
|
57
|
+
};
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<template>
|
|
61
|
+
<div class="self-stretch flex flex-col justify-start items-start gap-4">
|
|
62
|
+
<div class="self-stretch flex flex-col justify-center items-center">
|
|
63
|
+
<div
|
|
64
|
+
class="self-stretch py-3 border-b border-outline-outline-variant inline-flex justify-between items-center gap-1 cursor-pointer"
|
|
65
|
+
@click="toggle"
|
|
66
|
+
role="button"
|
|
67
|
+
tabindex="0"
|
|
68
|
+
:aria-expanded="isFilterVisible"
|
|
69
|
+
:aria-controls="`filter-${props.filter.code}`"
|
|
70
|
+
@keydown.enter="toggle"
|
|
71
|
+
@keydown.space.prevent="toggle"
|
|
72
|
+
>
|
|
73
|
+
<div class="flex-1 flex items-center gap-2.5">
|
|
74
|
+
<div class="flex-1 text-surface-on-surface text-base font-bold leading-normal text-left">
|
|
75
|
+
{{ props.filter.label }}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
<SwIconButton
|
|
79
|
+
type="ghost"
|
|
80
|
+
:aria-label="isFilterVisible ? 'Collapse filter' : 'Expand filter'"
|
|
81
|
+
tabindex="-1"
|
|
82
|
+
>
|
|
83
|
+
<SwChevronIcon :direction="isFilterVisible ? 'up' : 'down'" :size="24" />
|
|
84
|
+
</SwIconButton>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<transition name="filter-collapse">
|
|
89
|
+
<div v-if="isFilterVisible" class="self-stretch">
|
|
90
|
+
<div class="pt-6 space-y-4">
|
|
91
|
+
<div class="self-stretch inline-flex justify-start items-start gap-2 w-full">
|
|
92
|
+
<div class="flex-1 pt-[3px]">
|
|
93
|
+
<SwSwitchButton
|
|
94
|
+
:model-value="currentFilterData"
|
|
95
|
+
@update:model-value="handleRadioUpdate"
|
|
96
|
+
:name="props.filter.code"
|
|
97
|
+
:aria-label="props.filter.label"
|
|
98
|
+
:label="props.filter.label"
|
|
99
|
+
:description="props.description || translations.listing.freeShipping"
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</transition>
|
|
106
|
+
</div>
|
|
107
|
+
</template>
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getBackgroundImageUrl,
|
|
4
4
|
getCmsLayoutConfiguration,
|
|
5
|
+
getProductListingFromCmsPage,
|
|
5
6
|
} from "@shopware/helpers";
|
|
6
7
|
import { pascalCase } from "scule";
|
|
7
|
-
import { computed, h, resolveComponent } from "vue";
|
|
8
|
+
import { computed, h, resolveComponent, watchEffect } from "vue";
|
|
8
9
|
import { createCategoryListingContext, useNavigationContext } from "#imports";
|
|
9
10
|
import type { Schemas } from "#shopware";
|
|
10
11
|
|
|
@@ -13,10 +14,24 @@ const props = defineProps<{
|
|
|
13
14
|
}>();
|
|
14
15
|
|
|
15
16
|
const { routeName } = useNavigationContext();
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
// Function to initialize or update listing context
|
|
19
|
+
function updateListingContext(content: Schemas["CmsPage"]) {
|
|
20
|
+
if (routeName.value === "frontend.navigation.page") {
|
|
21
|
+
const initialListing =
|
|
22
|
+
getProductListingFromCmsPage<Schemas["ProductListingResult"]>(content);
|
|
23
|
+
|
|
24
|
+
if (initialListing) {
|
|
25
|
+
createCategoryListingContext(initialListing);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
18
28
|
}
|
|
19
29
|
|
|
30
|
+
// Watch for content changes and update context
|
|
31
|
+
watchEffect(() => {
|
|
32
|
+
updateListingContext(props.content);
|
|
33
|
+
});
|
|
34
|
+
|
|
20
35
|
const cmsSections = computed<Schemas["CmsSection"][]>(() => {
|
|
21
36
|
return props.content?.sections || [];
|
|
22
37
|
});
|
|
@@ -48,7 +63,7 @@ const DynamicRender = () => {
|
|
|
48
63
|
content: componentObject.section,
|
|
49
64
|
class: {
|
|
50
65
|
...cssClasses,
|
|
51
|
-
"max-w-screen-2xl mx-auto": layoutStyles?.sizingMode === "boxed",
|
|
66
|
+
"max-w-screen-2xl w-full mx-auto": layoutStyles?.sizingMode === "boxed",
|
|
52
67
|
},
|
|
53
68
|
style: {
|
|
54
69
|
backgroundColor: layoutStyles?.backgroundColor,
|
|
@@ -12,13 +12,13 @@ const leftContent = getSlotContent("left");
|
|
|
12
12
|
</script>
|
|
13
13
|
|
|
14
14
|
<template>
|
|
15
|
-
<div
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<div class="overflow-hidden basis-4/6">
|
|
15
|
+
<div class="w-full flex flex-col lg:flex-row justify-center items-stretch gap-4 lg:gap-10 lg:px-0 overflow-hidden">
|
|
16
|
+
<!-- Gallery Section -->
|
|
17
|
+
<div class="w-full lg:w-3/5">
|
|
19
18
|
<CmsGenericElement :content="leftContent" />
|
|
20
19
|
</div>
|
|
21
|
-
|
|
20
|
+
<!-- Buybox Section -->
|
|
21
|
+
<div class="w-full lg:w-2/5">
|
|
22
22
|
<CmsGenericElement :content="rightContent" />
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
@@ -13,20 +13,20 @@ const rightContent = getSlotContent("right");
|
|
|
13
13
|
const centerContent = getSlotContent("center");
|
|
14
14
|
</script>
|
|
15
15
|
<template>
|
|
16
|
-
<div class="cms-block-image-bubble-row
|
|
17
|
-
<div class="flex items-center justify-center">
|
|
16
|
+
<div class="cms-block-image-bubble-row flex flex-col sm:flex-row justify-start items-start gap-6 w-full">
|
|
17
|
+
<div class="w-full sm:flex-1 flex items-center justify-center">
|
|
18
18
|
<CmsGenericElement :content="leftContent" class="w-full" />
|
|
19
19
|
</div>
|
|
20
|
-
<div class="flex items-center justify-center">
|
|
20
|
+
<div class="w-full sm:flex-1 flex items-center justify-center">
|
|
21
21
|
<CmsGenericElement :content="centerContent" class="w-full" />
|
|
22
22
|
</div>
|
|
23
|
-
<div class="flex items-center justify-center">
|
|
23
|
+
<div class="w-full sm:flex-1 flex items-center justify-center">
|
|
24
24
|
<CmsGenericElement :content="rightContent" class="w-full" />
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
27
27
|
</template>
|
|
28
28
|
<style scoped>
|
|
29
|
-
.cms-block-image-bubble-row .cms-element-image {
|
|
29
|
+
.cms-block-image-bubble-row :deep(.cms-element-image) {
|
|
30
30
|
@apply object-cover max-w-xs overflow-hidden rounded-full aspect-square;
|
|
31
31
|
}
|
|
32
32
|
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { CmsBlockImageFourColumn } from "@shopware/composables";
|
|
3
|
+
import { useCmsBlock } from "#imports";
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
content: CmsBlockImageFourColumn;
|
|
7
|
+
}>();
|
|
8
|
+
|
|
9
|
+
const { getSlotContent } = useCmsBlock(props.content);
|
|
10
|
+
|
|
11
|
+
const leftContent = getSlotContent("left");
|
|
12
|
+
const rightContent = getSlotContent("right");
|
|
13
|
+
const centerLeftContent = getSlotContent("center-left");
|
|
14
|
+
const centerRightContent = getSlotContent("center-right");
|
|
15
|
+
</script>
|
|
16
|
+
<template>
|
|
17
|
+
<div class="cms-block-image-four-column flex flex-col sm:flex-row sm:flex-wrap lg:flex-nowrap justify-start items-start gap-6 w-full">
|
|
18
|
+
<div class="w-full sm:w-[calc(50%-12px)] lg:flex-1">
|
|
19
|
+
<CmsGenericElement :content="leftContent" />
|
|
20
|
+
</div>
|
|
21
|
+
<div class="w-full sm:w-[calc(50%-12px)] lg:flex-1">
|
|
22
|
+
<CmsGenericElement :content="centerLeftContent" />
|
|
23
|
+
</div>
|
|
24
|
+
<div class="w-full sm:w-[calc(50%-12px)] lg:flex-1">
|
|
25
|
+
<CmsGenericElement :content="centerRightContent" />
|
|
26
|
+
</div>
|
|
27
|
+
<div class="w-full sm:w-[calc(50%-12px)] lg:flex-1">
|
|
28
|
+
<CmsGenericElement :content="rightContent" />
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<style scoped>
|
|
34
|
+
.cms-block-image-four-column :deep(.cms-element-image) {
|
|
35
|
+
@apply relative h-full w-full;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.cms-block-image-four-column :deep(.cms-element-image img) {
|
|
39
|
+
@apply w-full h-full object-cover;
|
|
40
|
+
}
|
|
41
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { CmsBlockImageGalleryBig } from "@shopware/composables";
|
|
3
|
+
import { useCmsBlock } from "#imports";
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
content: CmsBlockImageGalleryBig;
|
|
7
|
+
}>();
|
|
8
|
+
|
|
9
|
+
const { getSlotContent } = useCmsBlock(props.content);
|
|
10
|
+
|
|
11
|
+
const cmsContent = getSlotContent("imageGallery");
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<div class="cms-block-image-gallery-big">
|
|
16
|
+
<CmsGenericElement :content="cmsContent" />
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<style scoped>
|
|
21
|
+
.cms-block-image-gallery-big {
|
|
22
|
+
@apply w-full;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.cms-block-image-gallery-big :deep(.cms-element-image-gallery) {
|
|
26
|
+
@apply max-w-screen-xl mx-auto;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Enhanced styling for the big gallery version */
|
|
30
|
+
.cms-block-image-gallery-big :deep(.gallery-slider) {
|
|
31
|
+
@apply max-h-[800px];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.cms-block-image-gallery-big :deep(img) {
|
|
35
|
+
@apply object-contain mx-auto;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Larger navigation controls */
|
|
39
|
+
.cms-block-image-gallery-big :deep(.gallery-slider-controls) {
|
|
40
|
+
@apply scale-125;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { CmsBlockImageHighlightRow } from "@shopware/composables";
|
|
3
|
+
import { useCmsBlock } from "#imports";
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
content: CmsBlockImageHighlightRow;
|
|
7
|
+
}>();
|
|
8
|
+
|
|
9
|
+
const { getSlotContent } = useCmsBlock(props.content);
|
|
10
|
+
|
|
11
|
+
const leftContent = getSlotContent("left");
|
|
12
|
+
const rightContent = getSlotContent("right");
|
|
13
|
+
const centerContent = getSlotContent("center");
|
|
14
|
+
</script>
|
|
15
|
+
<template>
|
|
16
|
+
<div class="cms-block-image-highlight-row flex flex-col sm:flex-row justify-start items-start gap-6 w-full">
|
|
17
|
+
<div class="w-full sm:flex-1">
|
|
18
|
+
<CmsGenericElement :content="leftContent" />
|
|
19
|
+
</div>
|
|
20
|
+
<div class="w-full sm:flex-1">
|
|
21
|
+
<CmsGenericElement :content="centerContent" />
|
|
22
|
+
</div>
|
|
23
|
+
<div class="w-full sm:flex-1">
|
|
24
|
+
<CmsGenericElement :content="rightContent" />
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<style scoped>
|
|
30
|
+
.cms-block-image-highlight-row :deep(.cms-element-image) {
|
|
31
|
+
@apply relative h-full w-full border-[12px] border-surface-surface;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.cms-block-image-highlight-row :deep(.cms-element-image img) {
|
|
35
|
+
@apply w-full h-full object-cover;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
@@ -14,11 +14,17 @@ const rightContent = getSlotContent("right");
|
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
16
|
<template>
|
|
17
|
-
<div class="
|
|
18
|
-
<div class="
|
|
19
|
-
<
|
|
20
|
-
|
|
17
|
+
<div class="flex flex-col md:flex-row justify-start items-start gap-6 w-full">
|
|
18
|
+
<div class="w-full md:flex-1 flex flex-col justify-start items-start gap-6">
|
|
19
|
+
<div class="w-full">
|
|
20
|
+
<CmsGenericElement :content="leftTopContent" />
|
|
21
|
+
</div>
|
|
22
|
+
<div class="w-full">
|
|
23
|
+
<CmsGenericElement :content="leftBottomContent" />
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="w-full md:flex-1">
|
|
27
|
+
<CmsGenericElement :content="rightContent" />
|
|
21
28
|
</div>
|
|
22
|
-
<CmsGenericElement :content="rightContent" />
|
|
23
29
|
</div>
|
|
24
30
|
</template>
|
|
@@ -12,8 +12,12 @@ const leftContent = getSlotContent("left");
|
|
|
12
12
|
const rightContent = getSlotContent("right");
|
|
13
13
|
</script>
|
|
14
14
|
<template>
|
|
15
|
-
<div class="
|
|
16
|
-
<
|
|
17
|
-
|
|
15
|
+
<div class="flex flex-col md:flex-row justify-start items-start gap-6 w-full">
|
|
16
|
+
<div class="w-full md:flex-1 p-4">
|
|
17
|
+
<CmsGenericElement :content="leftContent" />
|
|
18
|
+
</div>
|
|
19
|
+
<div class="w-full md:flex-1 p-4">
|
|
20
|
+
<CmsGenericElement :content="rightContent" />
|
|
21
|
+
</div>
|
|
18
22
|
</div>
|
|
19
23
|
</template>
|
|
@@ -16,36 +16,33 @@ const rightText = getSlotContent("right-text");
|
|
|
16
16
|
const rightImage = getSlotContent("right-image");
|
|
17
17
|
</script>
|
|
18
18
|
<template>
|
|
19
|
-
<div class="cms-block-image-text-bubble
|
|
20
|
-
<div class="
|
|
21
|
-
<div class="flex justify-center">
|
|
19
|
+
<div class="cms-block-image-text-bubble flex flex-col sm:flex-row justify-start items-start gap-6 w-full">
|
|
20
|
+
<div class="w-full sm:flex-1">
|
|
21
|
+
<div class="self-stretch flex justify-center">
|
|
22
22
|
<CmsGenericElement
|
|
23
23
|
:content="leftImage"
|
|
24
|
-
class="object-center rounded-full"
|
|
25
|
-
style="height: calc(100vw / 3 - 64px); width: calc(100vw / 3 - 64px)"
|
|
24
|
+
class="object-center rounded-full w-48 h-48 sm:w-56 sm:h-56 lg:w-64 lg:h-64"
|
|
26
25
|
/>
|
|
27
26
|
</div>
|
|
28
|
-
<CmsGenericElement :content="leftText" />
|
|
27
|
+
<CmsGenericElement :content="leftText" class="self-stretch" />
|
|
29
28
|
</div>
|
|
30
|
-
<div class="
|
|
31
|
-
<div class="flex justify-center">
|
|
29
|
+
<div class="w-full sm:flex-1">
|
|
30
|
+
<div class="self-stretch flex justify-center">
|
|
32
31
|
<CmsGenericElement
|
|
33
32
|
:content="centerImage"
|
|
34
|
-
class="object-center rounded-full"
|
|
35
|
-
style="height: calc(100vw / 3 - 64px); width: calc(100vw / 3 - 64px)"
|
|
33
|
+
class="object-center rounded-full w-48 h-48 sm:w-56 sm:h-56 lg:w-64 lg:h-64"
|
|
36
34
|
/>
|
|
37
35
|
</div>
|
|
38
|
-
<CmsGenericElement :content="centerText" />
|
|
36
|
+
<CmsGenericElement :content="centerText" class="self-stretch" />
|
|
39
37
|
</div>
|
|
40
|
-
<div class="
|
|
41
|
-
<div class="flex justify-center">
|
|
38
|
+
<div class="w-full sm:flex-1">
|
|
39
|
+
<div class="self-stretch flex justify-center">
|
|
42
40
|
<CmsGenericElement
|
|
43
41
|
:content="rightImage"
|
|
44
|
-
class="object-center rounded-full"
|
|
45
|
-
style="height: calc(100vw / 3 - 64px); width: calc(100vw / 3 - 64px)"
|
|
42
|
+
class="object-center rounded-full w-48 h-48 sm:w-56 sm:h-56 lg:w-64 lg:h-64"
|
|
46
43
|
/>
|
|
47
44
|
</div>
|
|
48
|
-
<CmsGenericElement :content="rightText" />
|
|
45
|
+
<CmsGenericElement :content="rightText" class="self-stretch" />
|
|
49
46
|
</div>
|
|
50
47
|
</div>
|
|
51
48
|
</template>
|
|
@@ -12,14 +12,12 @@ const leftContent = getSlotContent("left");
|
|
|
12
12
|
const rightContent = getSlotContent("right");
|
|
13
13
|
</script>
|
|
14
14
|
<template>
|
|
15
|
-
<article class="
|
|
16
|
-
<
|
|
17
|
-
:content="leftContent"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class="cms-block-image-text-cover__text"
|
|
23
|
-
/>
|
|
15
|
+
<article class="flex flex-col md:flex-row justify-start items-start gap-6 w-full pb-6">
|
|
16
|
+
<div class="w-full md:flex-1 px-6 pt-6 md:px-0 md:pt-6 md:pl-6">
|
|
17
|
+
<CmsGenericElement :content="leftContent" />
|
|
18
|
+
</div>
|
|
19
|
+
<div class="w-full md:flex-1 px-6 pt-0 md:pt-6 pb-6 md:px-0 md:pr-6">
|
|
20
|
+
<CmsGenericElement :content="rightContent" />
|
|
21
|
+
</div>
|
|
24
22
|
</article>
|
|
25
23
|
</template>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type {
|
|
3
|
+
CmsBlockImageTextGallery,
|
|
4
|
+
CmsElementImage,
|
|
5
|
+
CmsElementText,
|
|
6
|
+
} from "@shopware/composables";
|
|
7
|
+
import { useCmsBlock } from "#imports";
|
|
8
|
+
|
|
9
|
+
const props = defineProps<{
|
|
10
|
+
content: CmsBlockImageTextGallery;
|
|
11
|
+
}>();
|
|
12
|
+
|
|
13
|
+
const { getSlotContent } = useCmsBlock(props.content);
|
|
14
|
+
|
|
15
|
+
const leftTextContent = getSlotContent("left-text") as CmsElementText;
|
|
16
|
+
const rightTextContent = getSlotContent("right-text") as CmsElementText;
|
|
17
|
+
const centerTextContent = getSlotContent("center-text") as CmsElementText;
|
|
18
|
+
|
|
19
|
+
const leftImageContent = getSlotContent(
|
|
20
|
+
"left-image",
|
|
21
|
+
) as unknown as CmsElementImage;
|
|
22
|
+
const rightImageContent = getSlotContent(
|
|
23
|
+
"right-image",
|
|
24
|
+
) as unknown as CmsElementImage;
|
|
25
|
+
const centerImageContent = getSlotContent(
|
|
26
|
+
"center-image",
|
|
27
|
+
) as unknown as CmsElementImage;
|
|
28
|
+
|
|
29
|
+
// TODO: useRouter
|
|
30
|
+
function onImageClick(
|
|
31
|
+
slotContent: CmsElementImage & {
|
|
32
|
+
data: {
|
|
33
|
+
url?: string;
|
|
34
|
+
newTab?: boolean;
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
) {
|
|
38
|
+
if (slotContent.data?.url) {
|
|
39
|
+
if (slotContent.data?.newTab) {
|
|
40
|
+
window.open(slotContent.data.url);
|
|
41
|
+
} else {
|
|
42
|
+
window.location.href = slotContent.data.url;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
<template>
|
|
48
|
+
<article
|
|
49
|
+
class="cms-block-image-text-gallery flex flex-col sm:flex-row justify-start items-start gap-6 w-full"
|
|
50
|
+
:style="{ backgroundColor: content.backgroundColor || '' }"
|
|
51
|
+
>
|
|
52
|
+
<div class="w-full sm:flex-1">
|
|
53
|
+
<CmsElementImage
|
|
54
|
+
:content="leftImageContent"
|
|
55
|
+
:style="{ cursor: leftImageContent.data?.url && 'pointer' }"
|
|
56
|
+
@click="onImageClick(leftImageContent)"
|
|
57
|
+
/>
|
|
58
|
+
<CmsElementText
|
|
59
|
+
:content="leftTextContent"
|
|
60
|
+
class="self-stretch"
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="w-full sm:flex-1">
|
|
64
|
+
<CmsElementImage
|
|
65
|
+
:content="centerImageContent"
|
|
66
|
+
:style="{
|
|
67
|
+
cursor: centerImageContent.data?.url && 'pointer',
|
|
68
|
+
}"
|
|
69
|
+
@click="onImageClick(centerImageContent)"
|
|
70
|
+
/>
|
|
71
|
+
<CmsElementText
|
|
72
|
+
:content="centerTextContent"
|
|
73
|
+
class="self-stretch"
|
|
74
|
+
/>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="w-full sm:flex-1">
|
|
77
|
+
<CmsElementImage
|
|
78
|
+
:content="rightImageContent"
|
|
79
|
+
:style="{ cursor: rightImageContent.data?.url && 'pointer' }"
|
|
80
|
+
@click="onImageClick(rightImageContent)"
|
|
81
|
+
/>
|
|
82
|
+
<CmsElementText
|
|
83
|
+
:content="rightTextContent"
|
|
84
|
+
class="self-stretch"
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
</article>
|
|
88
|
+
</template>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { CmsBlockImageTextRow } from "@shopware/composables";
|
|
3
|
+
import { useCmsBlock } from "#imports";
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
content: CmsBlockImageTextRow;
|
|
7
|
+
}>();
|
|
8
|
+
|
|
9
|
+
const { getSlotContent } = useCmsBlock(props.content);
|
|
10
|
+
|
|
11
|
+
const leftImageContent = getSlotContent("left-image");
|
|
12
|
+
const leftTextContent = getSlotContent("left-text");
|
|
13
|
+
const centerImageContent = getSlotContent("center-image");
|
|
14
|
+
const centerTextContent = getSlotContent("center-text");
|
|
15
|
+
const rightImageContent = getSlotContent("right-image");
|
|
16
|
+
const rightTextContent = getSlotContent("right-text");
|
|
17
|
+
</script>
|
|
18
|
+
<template>
|
|
19
|
+
<div class="cms-block-image-text-row flex flex-col md:flex-row justify-center items-stretch gap-6 w-full">
|
|
20
|
+
<div class="w-full md:flex-1 flex flex-col">
|
|
21
|
+
<div class="flex-1 mb-4 overflow-hidden rounded-lg min-h-64">
|
|
22
|
+
<CmsGenericElement :content="leftImageContent" />
|
|
23
|
+
</div>
|
|
24
|
+
<CmsGenericElement :content="leftTextContent" class="text-center" />
|
|
25
|
+
</div>
|
|
26
|
+
<div class="w-full md:flex-1 flex flex-col">
|
|
27
|
+
<div class="flex-1 mb-4 overflow-hidden rounded-lg min-h-64">
|
|
28
|
+
<CmsGenericElement :content="centerImageContent" />
|
|
29
|
+
</div>
|
|
30
|
+
<CmsGenericElement :content="centerTextContent" class="text-center" />
|
|
31
|
+
</div>
|
|
32
|
+
<div class="w-full md:flex-1 flex flex-col">
|
|
33
|
+
<div class="flex-1 mb-4 overflow-hidden rounded-lg min-h-64">
|
|
34
|
+
<CmsGenericElement :content="rightImageContent" />
|
|
35
|
+
</div>
|
|
36
|
+
<CmsGenericElement :content="rightTextContent" class="text-center" />
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<style scoped>
|
|
42
|
+
.cms-block-image-text-row :deep(.cms-element-image) {
|
|
43
|
+
@apply relative h-full w-full;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.cms-block-image-text-row :deep(.cms-element-image img) {
|
|
47
|
+
@apply w-full h-full object-cover rounded-lg;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.cms-block-image-text-row :deep(.cms-element-text) {
|
|
51
|
+
@apply self-stretch min-h-12;
|
|
52
|
+
}
|
|
53
|
+
</style>
|
|
@@ -13,9 +13,15 @@ const rightContent = getSlotContent("right");
|
|
|
13
13
|
const centerContent = getSlotContent("center");
|
|
14
14
|
</script>
|
|
15
15
|
<template>
|
|
16
|
-
<div class="
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
<div class="flex flex-col sm:flex-row justify-start items-start gap-6 w-full">
|
|
17
|
+
<div class="w-full sm:flex-1">
|
|
18
|
+
<CmsGenericElement :content="leftContent" />
|
|
19
|
+
</div>
|
|
20
|
+
<div class="w-full sm:flex-1">
|
|
21
|
+
<CmsGenericElement :content="centerContent" />
|
|
22
|
+
</div>
|
|
23
|
+
<div class="w-full sm:flex-1">
|
|
24
|
+
<CmsGenericElement :content="rightContent" />
|
|
25
|
+
</div>
|
|
20
26
|
</div>
|
|
21
27
|
</template>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { CmsBlockImageThreeCover } from "@shopware/composables";
|
|
3
|
+
import { useCmsBlock } from "#imports";
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
content: CmsBlockImageThreeCover;
|
|
7
|
+
}>();
|
|
8
|
+
|
|
9
|
+
const { getSlotContent } = useCmsBlock(props.content);
|
|
10
|
+
|
|
11
|
+
const leftContent = getSlotContent("left");
|
|
12
|
+
const rightContent = getSlotContent("right");
|
|
13
|
+
const centerContent = getSlotContent("center");
|
|
14
|
+
</script>
|
|
15
|
+
<template>
|
|
16
|
+
<div class="cms-block-image-three-cover flex flex-col sm:flex-row justify-start items-start gap-6 w-full">
|
|
17
|
+
<div class="w-full sm:flex-1">
|
|
18
|
+
<CmsGenericElement :content="leftContent" />
|
|
19
|
+
</div>
|
|
20
|
+
<div class="w-full sm:flex-1">
|
|
21
|
+
<CmsGenericElement :content="centerContent" />
|
|
22
|
+
</div>
|
|
23
|
+
<div class="w-full sm:flex-1">
|
|
24
|
+
<CmsGenericElement :content="rightContent" />
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<style scoped>
|
|
30
|
+
.cms-block-image-three-cover :deep(.cms-element-image) {
|
|
31
|
+
@apply aspect-square relative h-full w-full;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.cms-block-image-three-cover :deep(.cms-element-image img) {
|
|
35
|
+
@apply w-full h-full object-cover;
|
|
36
|
+
}
|
|
37
|
+
</style>
|