@shopware/cms-base-layer 3.0.0 → 3.0.1

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 (102) hide show
  1. package/README.md +47 -63
  2. package/app/components/SwCategoryNavigation.vue +1 -0
  3. package/app/components/SwCategoryNavigationLink.vue +16 -8
  4. package/app/components/SwContactForm.vue +1 -0
  5. package/app/components/SwFilterChips.vue +1 -0
  6. package/app/components/SwListingProductPrice.vue +16 -4
  7. package/app/components/SwMedia3D.vue +1 -4
  8. package/app/components/SwNewsletterForm.vue +4 -3
  9. package/app/components/SwProductAddToCart.vue +24 -7
  10. package/app/components/SwProductCard.vue +1 -0
  11. package/app/components/SwProductCardDetails.vue +27 -9
  12. package/app/components/SwProductCardImage.vue +31 -12
  13. package/app/components/SwProductCardSkeleton.vue +37 -14
  14. package/app/components/SwProductGallery.vue +1 -0
  15. package/app/components/SwProductListingFilter.vue +5 -1
  16. package/app/components/SwProductListingFilters.vue +21 -6
  17. package/app/components/SwProductListingFiltersHorizontal.vue +4 -1
  18. package/app/components/SwProductPrice.vue +1 -0
  19. package/app/components/SwProductReviews.vue +14 -6
  20. package/app/components/SwProductReviewsForm.vue +15 -3
  21. package/app/components/SwProductUnits.vue +1 -0
  22. package/app/components/SwQuantitySelect.vue +10 -3
  23. package/app/components/SwSharedPrice.vue +1 -0
  24. package/app/components/SwSlider.vue +1 -0
  25. package/app/components/SwStockInfo.vue +12 -6
  26. package/app/components/SwVariantConfigurator.vue +4 -1
  27. package/app/components/listing-filters/SwFilterPrice.vue +79 -30
  28. package/app/components/listing-filters/SwFilterProperties.vue +40 -25
  29. package/app/components/listing-filters/SwFilterRating.vue +21 -9
  30. package/app/components/listing-filters/SwFilterShippingFree.vue +16 -8
  31. package/app/components/public/cms/CmsBlockSpatialViewer.vue +1 -0
  32. package/app/components/public/cms/CmsGenericBlock.vue +2 -0
  33. package/app/components/public/cms/CmsGenericElement.vue +1 -0
  34. package/app/components/public/cms/CmsNoComponent.vue +1 -0
  35. package/app/components/public/cms/CmsPage.md +1 -1
  36. package/app/components/public/cms/CmsPage.vue +2 -0
  37. package/app/components/public/cms/block/CmsBlockCategoryNavigation.vue +1 -0
  38. package/app/components/public/cms/block/CmsBlockCenterText.vue +1 -0
  39. package/app/components/public/cms/block/CmsBlockCrossSelling.vue +1 -0
  40. package/app/components/public/cms/block/CmsBlockCustomForm.vue +1 -0
  41. package/app/components/public/cms/block/CmsBlockForm.vue +1 -0
  42. package/app/components/public/cms/block/CmsBlockGalleryBuybox.vue +4 -1
  43. package/app/components/public/cms/block/CmsBlockImage.vue +1 -0
  44. package/app/components/public/cms/block/CmsBlockImageBubbleRow.vue +4 -1
  45. package/app/components/public/cms/block/CmsBlockImageCover.vue +1 -0
  46. package/app/components/public/cms/block/CmsBlockImageFourColumn.vue +4 -1
  47. package/app/components/public/cms/block/CmsBlockImageGallery.vue +1 -0
  48. package/app/components/public/cms/block/CmsBlockImageGalleryBig.vue +1 -0
  49. package/app/components/public/cms/block/CmsBlockImageHighlightRow.vue +4 -1
  50. package/app/components/public/cms/block/CmsBlockImageSimpleGrid.vue +1 -0
  51. package/app/components/public/cms/block/CmsBlockImageSlider.vue +1 -0
  52. package/app/components/public/cms/block/CmsBlockImageText.vue +4 -1
  53. package/app/components/public/cms/block/CmsBlockImageTextBubble.vue +4 -1
  54. package/app/components/public/cms/block/CmsBlockImageTextCover.vue +4 -1
  55. package/app/components/public/cms/block/CmsBlockImageTextGallery.vue +4 -12
  56. package/app/components/public/cms/block/CmsBlockImageTextRow.vue +4 -1
  57. package/app/components/public/cms/block/CmsBlockImageThreeColumn.vue +1 -0
  58. package/app/components/public/cms/block/CmsBlockImageThreeCover.vue +4 -1
  59. package/app/components/public/cms/block/CmsBlockImageTwoColumn.vue +4 -1
  60. package/app/components/public/cms/block/CmsBlockProductDescriptionReviews.vue +1 -0
  61. package/app/components/public/cms/block/CmsBlockProductHeading.vue +1 -0
  62. package/app/components/public/cms/block/CmsBlockProductListing.vue +1 -0
  63. package/app/components/public/cms/block/CmsBlockProductThreeColumn.vue +1 -0
  64. package/app/components/public/cms/block/CmsBlockSidebarFilter.vue +1 -0
  65. package/app/components/public/cms/block/CmsBlockText.vue +1 -0
  66. package/app/components/public/cms/block/CmsBlockTextHero.vue +1 -0
  67. package/app/components/public/cms/block/CmsBlockTextOnImage.vue +2 -4
  68. package/app/components/public/cms/block/CmsBlockTextThreeColumn.vue +1 -0
  69. package/app/components/public/cms/block/CmsBlockTextTwoColumn.vue +4 -1
  70. package/app/components/public/cms/block/CmsBlockVimeoVideo.vue +1 -0
  71. package/app/components/public/cms/block/CmsBlockYoutubeVideo.vue +1 -0
  72. package/app/components/public/cms/element/CmsElementBuyBox.vue +90 -72
  73. package/app/components/public/cms/element/CmsElementCategoryNavigation.vue +14 -3
  74. package/app/components/public/cms/element/CmsElementCrossSelling.vue +3 -1
  75. package/app/components/public/cms/element/CmsElementCustomForm.vue +1 -0
  76. package/app/components/public/cms/element/CmsElementForm.vue +1 -0
  77. package/app/components/public/cms/element/CmsElementHtml.vue +0 -1
  78. package/app/components/public/cms/element/CmsElementImage.vue +2 -0
  79. package/app/components/public/cms/element/CmsElementImageGallery.vue +6 -2
  80. package/app/components/public/cms/element/CmsElementManufacturerLogo.vue +1 -0
  81. package/app/components/public/cms/element/CmsElementProductBox.vue +1 -0
  82. package/app/components/public/cms/element/CmsElementProductDescriptionReviews.vue +77 -29
  83. package/app/components/public/cms/element/CmsElementProductListing.vue +16 -5
  84. package/app/components/public/cms/element/CmsElementProductSlider.vue +6 -4
  85. package/app/components/public/cms/element/CmsElementText.vue +2 -0
  86. package/app/components/public/cms/element/CmsElementVimeoVideo.vue +1 -0
  87. package/app/components/public/cms/element/CmsElementYoutubeVideo.vue +1 -0
  88. package/app/components/public/cms/element/SwProductListingPagination.vue +8 -2
  89. package/app/components/public/cms/section/CmsSectionSidebar.vue +13 -8
  90. package/app/components/public/cms/skeleton/ProductCardSkeleton.vue +16 -5
  91. package/app/components/ui/SwitchButton.vue +53 -14
  92. package/app/components/ui/WishlistIcon.vue +8 -2
  93. package/app/composables/useLcpImagePreload.test.ts +1 -0
  94. package/app/composables/useLcpImagePreload.ts +2 -0
  95. package/app/composables/useTypedAppConfig.ts +1 -0
  96. package/app/helpers/cms/getImageSizes.test.ts +1 -0
  97. package/app/helpers/html-to-vue/ast.ts +1 -0
  98. package/app/helpers/html-to-vue/getOptionsFromNode.test.ts +1 -0
  99. package/app/helpers/html-to-vue/renderToHtml.ts +1 -0
  100. package/app/helpers/html-to-vue/renderer.ts +1 -0
  101. package/app/providers/shopware.test.ts +1 -0
  102. package/package.json +19 -20
@@ -18,14 +18,19 @@ provide("cms-section-layout", "sidebar");
18
18
  </script>
19
19
 
20
20
  <template>
21
- <div class="self-stretch flex flex-col lg:flex-row items-stretch gap-16" :class="{
22
- 'px-6': fullWidth,
23
- }">
24
- <aside :class="{
25
- 'w-full lg:w-72 xl:w-80 flex-shrink-0 bg-surface-surface flex flex-col justify-start items-stretch gap-4 lg:sticky lg:top-20 px-4 lg:px-0':
26
- mobileBehavior !== 'hidden',
27
- 'hidden lg:block': mobileBehavior === 'hidden',
28
- }">
21
+ <div
22
+ class="self-stretch flex flex-col lg:flex-row items-stretch gap-16"
23
+ :class="{
24
+ 'px-6': fullWidth,
25
+ }"
26
+ >
27
+ <aside
28
+ :class="{
29
+ 'w-full lg:w-72 xl:w-80 flex-shrink-0 bg-surface-surface flex flex-col justify-start items-stretch gap-4 lg:sticky lg:top-20 px-4 lg:px-0':
30
+ mobileBehavior !== 'hidden',
31
+ 'hidden lg:block': mobileBehavior === 'hidden',
32
+ }"
33
+ >
29
34
  <div v-for="cmsBlock in sidebarBlocks" :key="cmsBlock.id" class="w-full">
30
35
  <CmsGenericBlock :content="cmsBlock" />
31
36
  </div>
@@ -5,9 +5,14 @@ const placeholderSvg = useImagePlaceholder();
5
5
  </script>
6
6
 
7
7
  <template>
8
- <div role="status" class="p-px flex flex-col justify-start items-start overflow-hidden">
8
+ <div
9
+ role="status"
10
+ class="p-px flex flex-col justify-start items-start overflow-hidden"
11
+ >
9
12
  <!-- Image skeleton -->
10
- <div class="self-stretch min-h-[350px] relative flex items-center justify-center overflow-hidden aspect-square animate-pulse">
13
+ <div
14
+ class="self-stretch min-h-[350px] relative flex items-center justify-center overflow-hidden aspect-square animate-pulse"
15
+ >
11
16
  <img
12
17
  :src="placeholderSvg"
13
18
  alt=""
@@ -18,9 +23,15 @@ const placeholderSvg = useImagePlaceholder();
18
23
 
19
24
  <!-- Details skeleton -->
20
25
  <div class="w-full pt-4 animate-pulse">
21
- <div class="h-4 bg-gray-200 rounded-full dark:bg-gray-700 w-3/4 mb-3"></div>
22
- <div class="h-3 bg-gray-200 rounded-full dark:bg-gray-700 w-1/2 mb-4"></div>
23
- <div class="h-5 bg-gray-200 rounded-full dark:bg-gray-700 w-20 mb-3"></div>
26
+ <div
27
+ class="h-4 bg-gray-200 rounded-full dark:bg-gray-700 w-3/4 mb-3"
28
+ ></div>
29
+ <div
30
+ class="h-3 bg-gray-200 rounded-full dark:bg-gray-700 w-1/2 mb-4"
31
+ ></div>
32
+ <div
33
+ class="h-5 bg-gray-200 rounded-full dark:bg-gray-700 w-20 mb-3"
34
+ ></div>
24
35
  <div class="h-10 bg-gray-200 rounded dark:bg-gray-700 w-full"></div>
25
36
  </div>
26
37
  <span class="sr-only">Loading...</span>
@@ -47,9 +47,11 @@ const activateByClick = (ev?: Event) => {
47
47
  <div class="w-full inline-flex flex-col justify-start items-start gap-2">
48
48
  <div class="self-stretch inline-flex justify-start items-center gap-3">
49
49
  <!-- left label that toggles the input via for="#inputId" -->
50
- <label :for="inputId"
50
+ <label
51
+ :for="inputId"
51
52
  class="flex-1 flex justify-start items-center gap-1 text-surface-on-surface text-base font-normal leading-normal cursor-pointer"
52
- :class="{ 'cursor-not-allowed': disabled }">
53
+ :class="{ 'cursor-not-allowed': disabled }"
54
+ >
53
55
  <span v-if="$slots.default">
54
56
  <slot />
55
57
  </span>
@@ -57,23 +59,55 @@ const activateByClick = (ev?: Event) => {
57
59
  </label>
58
60
 
59
61
  <div class="w-10 h-6 relative">
60
- <label class="inline-block cursor-pointer" :class="{ 'cursor-not-allowed': disabled }">
61
- <input ref="inputRef" :id="inputId" type="checkbox" :name="inputName" class="sr-only" :checked="localChecked"
62
+ <label
63
+ class="inline-block cursor-pointer"
64
+ :class="{ 'cursor-not-allowed': disabled }"
65
+ >
66
+ <input
67
+ ref="inputRef"
68
+ :id="inputId"
69
+ type="checkbox"
70
+ :name="inputName"
71
+ class="sr-only"
72
+ :checked="localChecked"
62
73
  @change="toggleState()"
63
- :disabled="disabled" :aria-label="ariaLabel || undefined" v-bind="$attrs" />
64
- <span role="switch" :aria-checked="localChecked" :tabindex="disabled ? -1 : 0"
74
+ :disabled="disabled"
75
+ :aria-label="ariaLabel || undefined"
76
+ v-bind="$attrs"
77
+ />
78
+ <span
79
+ role="switch"
80
+ :aria-checked="localChecked"
81
+ :tabindex="disabled ? -1 : 0"
65
82
  class="w-10 h-6 relative rounded-full flex-shrink-0 inline-block switch-track cursor-pointer"
66
- :class="localChecked ? 'bg-brand-secondary switch-track--on' : 'bg-surface-surface-container-highest'"
67
- @keydown.space.prevent="activateByKeyboard" @click.prevent="activateByClick">
68
- <span class="w-4 h-4 rounded-full absolute switch-knob"
83
+ :class="
84
+ localChecked
85
+ ? 'bg-brand-secondary switch-track--on'
86
+ : 'bg-surface-surface-container-highest'
87
+ "
88
+ @keydown.space.prevent="activateByKeyboard"
89
+ @click.prevent="activateByClick"
90
+ >
91
+ <span
92
+ class="w-4 h-4 rounded-full absolute switch-knob"
69
93
  :style="{ left: localChecked ? '19px' : '4px', top: '4px' }"
70
- :class="localChecked ? 'bg-brand-on-secondary' : 'bg-surface-on-surface-variant'"></span>
94
+ :class="
95
+ localChecked
96
+ ? 'bg-brand-on-secondary'
97
+ : 'bg-surface-on-surface-variant'
98
+ "
99
+ ></span>
71
100
  </span>
72
101
  </label>
73
102
  </div>
74
103
  </div>
75
- <div v-if="description || $slots.description" class="self-stretch inline-flex justify-start items-center gap-2.5">
76
- <div class="flex-1 justify-start text-surface-on-surface-variant text-sm font-normal leading-tight">
104
+ <div
105
+ v-if="description || $slots.description"
106
+ class="self-stretch inline-flex justify-start items-center gap-2.5"
107
+ >
108
+ <div
109
+ class="flex-1 justify-start text-surface-on-surface-variant text-sm font-normal leading-tight"
110
+ >
77
111
  <slot name="description">{{ description }}</slot>
78
112
  </div>
79
113
  </div>
@@ -82,7 +116,9 @@ const activateByClick = (ev?: Event) => {
82
116
 
83
117
  <style scoped>
84
118
  .switch-track {
85
- transition: background-color 180ms ease-in-out, box-shadow 180ms ease-in-out;
119
+ transition:
120
+ background-color 180ms ease-in-out,
121
+ box-shadow 180ms ease-in-out;
86
122
  }
87
123
 
88
124
  .switch-track--on {
@@ -91,7 +127,10 @@ const activateByClick = (ev?: Event) => {
91
127
  }
92
128
 
93
129
  .switch-knob {
94
- transition: left 180ms cubic-bezier(.2, .9, .2, 1), top 180ms cubic-bezier(.2, .9, .2, 1), background-color 120ms linear;
130
+ transition:
131
+ left 180ms cubic-bezier(0.2, 0.9, 0.2, 1),
132
+ top 180ms cubic-bezier(0.2, 0.9, 0.2, 1),
133
+ background-color 120ms linear;
95
134
  }
96
135
 
97
136
  .switch-track:focus {
@@ -9,7 +9,13 @@ const { filled = false } = defineProps<{
9
9
  <!-- <Icon size="1rem" name="shopware:heart" v-if="type !== 'filled'" class="w-6 h-5 block hover:cursor-pointer" :class="[
10
10
  styles[type]
11
11
  ]" /> -->
12
- <div class="i-carbon-favorite w-6 h-5 hover:cursor-pointer" v-if="!filled"></div>
13
- <div class="i-carbon-favorite-filled w-6 h-5 hover:cursor-pointer" v-else></div>
12
+ <div
13
+ class="i-carbon-favorite w-6 h-5 hover:cursor-pointer"
14
+ v-if="!filled"
15
+ ></div>
16
+ <div
17
+ class="i-carbon-favorite-filled w-6 h-5 hover:cursor-pointer"
18
+ v-else
19
+ ></div>
14
20
  </div>
15
21
  </template>
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
+
2
3
  import { findFirstCmsImageUrl } from "../helpers/cms/findFirstCmsImageUrl";
3
4
 
4
5
  type Sections = Parameters<typeof findFirstCmsImageUrl>[0];
@@ -1,6 +1,8 @@
1
1
  import { computed } from "vue";
2
+
2
3
  import { useHead } from "#imports";
3
4
  import type { Schemas } from "#shopware";
5
+
4
6
  import { findFirstCmsImageUrl } from "../helpers/cms/findFirstCmsImageUrl";
5
7
  import { useTypedAppConfig } from "./useTypedAppConfig";
6
8
 
@@ -1,4 +1,5 @@
1
1
  import type { BackgroundImageOptions } from "@shopware/helpers";
2
+
2
3
  import { useAppConfig } from "#imports";
3
4
 
4
5
  type CmsBaseLayerAppConfig = ReturnType<typeof useAppConfig> & {
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
+
2
3
  import { getImageSizes } from "./getImageSizes";
3
4
 
4
5
  describe("getImageSizes", () => {
@@ -3,6 +3,7 @@
3
3
  */
4
4
  // @ts-expect-error - html-to-ast has type definition issues with package.json exports
5
5
  import { parse } from "html-to-ast";
6
+
6
7
  import type { NodeObject } from "./getOptionsFromNode";
7
8
 
8
9
  type ASTNode = NodeObject | NodeObject[];
@@ -1,4 +1,5 @@
1
1
  import { beforeEach, describe, expect, it, vi } from "vitest";
2
+
2
3
  import { getOptionsFromNode } from "./getOptionsFromNode";
3
4
  import type { NodeObject } from "./getOptionsFromNode";
4
5
 
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { ComponentInternalInstance, h } from "vue";
6
+
6
7
  import { type RectifyConfig, generateAST, rectifyAST } from "./ast";
7
8
  import { type RendererConfig, renderer } from "./renderer";
8
9
 
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { ComponentInternalInstance, VNode } from "vue";
6
+
6
7
  import { isNode } from "./ast";
7
8
  import type { NodeObject } from "./getOptionsFromNode";
8
9
  import { getOptionsFromNode } from "./getOptionsFromNode";
@@ -1,5 +1,6 @@
1
1
  import type { ImageCTX } from "@nuxt/image";
2
2
  import { describe, expect, it } from "vitest";
3
+
3
4
  import shopwareProvider from "./shopware";
4
5
 
5
6
  describe("Shopware Image Provider", () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopware/cms-base-layer",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "Vue CMS Nuxt Layer for Shopware",
5
5
  "author": "Shopware",
6
6
  "repository": {
@@ -32,43 +32,42 @@
32
32
  "uno.config.ts"
33
33
  ],
34
34
  "dependencies": {
35
- "@iconify-json/carbon": "1.2.18",
35
+ "@iconify-json/carbon": "1.2.23",
36
36
  "@nuxt/image": "2.0.0",
37
- "@nuxt/kit": "4.4.6",
38
- "@tresjs/cientos": "5.7.0",
39
- "@tresjs/nuxt": "^5.6.0",
37
+ "@nuxt/kit": "4.4.8",
38
+ "@tresjs/cientos": "5.7.2",
39
+ "@tresjs/nuxt": "^5.6.1",
40
40
  "@vuelidate/core": "2.0.3",
41
41
  "@vuelidate/validators": "2.0.4",
42
- "@vueuse/core": "14.1.0",
42
+ "@vueuse/core": "14.3.0",
43
43
  "entities": "6.0.0",
44
44
  "scule": "1.3.0",
45
45
  "html-to-ast": "0.0.6",
46
46
  "three": "0.183.2",
47
- "vue": "3.5.34",
47
+ "vue": "3.5.38",
48
48
  "xss": "1.0.15",
49
- "@shopware/api-client": "1.5.0",
50
- "@shopware/composables": "1.11.1",
51
- "@shopware/helpers": "1.7.1"
49
+ "@shopware/helpers": "1.7.1",
50
+ "@shopware/composables": "1.12.0",
51
+ "@shopware/api-client": "1.5.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@biomejs/biome": "1.8.3",
55
- "@nuxt/schema": "4.4.6",
54
+ "@nuxt/schema": "4.4.8",
56
55
  "@types/three": "0.182.0",
57
56
  "@typescript/native-preview": "7.0.0-dev.20260205.1",
58
- "@vitest/coverage-v8": "4.1.5",
59
- "nuxt": "4.4.6",
57
+ "@vitest/coverage-v8": "4.1.9",
58
+ "nuxt": "4.4.8",
60
59
  "typescript": "5.9.3",
61
- "unbuild": "2.0.0",
62
- "vitest": "4.1.6",
63
- "vue-router": "5.0.7",
64
- "vue-tsc": "3.2.9",
60
+ "unbuild": "3.6.1",
61
+ "vitest": "4.1.9",
62
+ "vue-router": "5.1.0",
63
+ "vue-tsc": "3.3.5",
65
64
  "tsconfig": "0.0.0"
66
65
  },
67
66
  "scripts": {
68
67
  "build": "nuxt prepare && unbuild",
69
68
  "dev": "unbuild --stub",
70
- "lint": "biome check .",
71
- "lint:fix": "biome check . --write && pnpm run typecheck",
69
+ "lint": "oxlint . && oxfmt --check .",
70
+ "lint:fix": "oxlint --fix . && oxfmt --write . && pnpm run typecheck",
72
71
  "typecheck": "pnpm nuxt prepare && tsgo --noEmit",
73
72
  "test": "vitest run",
74
73
  "test:watch": "vitest",