@shopware/cms-base-layer 1.5.1 → 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.
Files changed (183) hide show
  1. package/README.md +330 -12
  2. package/app/app.config.ts +7 -0
  3. package/app/assets/icons/check-circle.svg +3 -0
  4. package/app/assets/icons/checkmark.svg +3 -0
  5. package/app/assets/icons/chevron.svg +3 -0
  6. package/app/assets/icons/exclamation-circle.svg +3 -0
  7. package/app/assets/icons/star-empty.svg +3 -0
  8. package/app/assets/icons/star-filled.svg +3 -0
  9. package/app/assets/icons/user.svg +1 -0
  10. package/app/components/SwCategoryNavigation.vue +76 -0
  11. package/app/components/SwCategoryNavigationLink.vue +128 -0
  12. package/{components → app/components}/SwContactForm.vue +27 -27
  13. package/app/components/SwFilterChips.vue +144 -0
  14. package/app/components/SwListingProductPrice.vue +89 -0
  15. package/{components → app/components}/SwNewsletterForm.vue +45 -34
  16. package/{components → app/components}/SwPagination.vue +3 -5
  17. package/{components → app/components}/SwProductAddToCart.vue +22 -27
  18. package/app/components/SwProductCard.vue +170 -0
  19. package/app/components/SwProductCardDetails.vue +57 -0
  20. package/app/components/SwProductCardImage.vue +87 -0
  21. package/app/components/SwProductCardSkeleton.vue +33 -0
  22. package/app/components/SwProductListingFilter.vue +64 -0
  23. package/app/components/SwProductListingFilters.vue +308 -0
  24. package/{components → app/components}/SwProductReviews.vue +28 -13
  25. package/app/components/SwProductReviewsForm.vue +292 -0
  26. package/app/components/SwQuantitySelect.vue +106 -0
  27. package/{components → app/components}/SwSlider.vue +4 -4
  28. package/app/components/SwSortDropdown.vue +83 -0
  29. package/app/components/SwStockInfo.vue +44 -0
  30. package/{components → app/components}/SwVariantConfigurator.vue +1 -1
  31. package/app/components/listing-filters/SwFilterPrice.vue +214 -0
  32. package/app/components/listing-filters/SwFilterProperties.vue +113 -0
  33. package/app/components/listing-filters/SwFilterRating.vue +90 -0
  34. package/app/components/listing-filters/SwFilterShippingFree.vue +107 -0
  35. package/{components → app/components}/public/cms/CmsPage.vue +19 -4
  36. package/{components → app/components}/public/cms/block/CmsBlockGalleryBuybox.vue +5 -5
  37. package/{components → app/components}/public/cms/block/CmsBlockImageBubbleRow.vue +5 -5
  38. package/app/components/public/cms/block/CmsBlockImageFourColumn.vue +41 -0
  39. package/app/components/public/cms/block/CmsBlockImageGalleryBig.vue +42 -0
  40. package/app/components/public/cms/block/CmsBlockImageHighlightRow.vue +37 -0
  41. package/{components → app/components}/public/cms/block/CmsBlockImageSimpleGrid.vue +11 -5
  42. package/{components → app/components}/public/cms/block/CmsBlockImageText.vue +7 -3
  43. package/{components → app/components}/public/cms/block/CmsBlockImageTextBubble.vue +13 -16
  44. package/{components → app/components}/public/cms/block/CmsBlockImageTextCover.vue +7 -9
  45. package/app/components/public/cms/block/CmsBlockImageTextGallery.vue +88 -0
  46. package/app/components/public/cms/block/CmsBlockImageTextRow.vue +53 -0
  47. package/{components → app/components}/public/cms/block/CmsBlockImageThreeColumn.vue +10 -4
  48. package/app/components/public/cms/block/CmsBlockImageThreeCover.vue +37 -0
  49. package/app/components/public/cms/block/CmsBlockImageTwoColumn.vue +37 -0
  50. package/{components → app/components}/public/cms/block/CmsBlockProductHeading.vue +1 -1
  51. package/{components → app/components}/public/cms/block/CmsBlockProductThreeColumn.vue +10 -4
  52. package/{components → app/components}/public/cms/block/CmsBlockSidebarFilter.vue +3 -1
  53. package/app/components/public/cms/block/CmsBlockTextOnImage.vue +30 -0
  54. package/app/components/public/cms/element/CmsElementBuyBox.vue +145 -0
  55. package/app/components/public/cms/element/CmsElementCategoryNavigation.vue +53 -0
  56. package/{components → app/components}/public/cms/element/CmsElementCrossSelling.vue +3 -3
  57. package/{components → app/components}/public/cms/element/CmsElementImage.vue +52 -13
  58. package/app/components/public/cms/element/CmsElementImageGallery.vue +158 -0
  59. package/{components → app/components}/public/cms/element/CmsElementImageSlider.vue +2 -2
  60. package/{components → app/components}/public/cms/element/CmsElementProductBox.vue +2 -1
  61. package/app/components/public/cms/element/CmsElementProductDescriptionReviews.vue +217 -0
  62. package/{components → app/components}/public/cms/element/CmsElementProductListing.vue +23 -94
  63. package/app/components/public/cms/element/CmsElementProductName.vue +11 -0
  64. package/{components → app/components}/public/cms/element/CmsElementProductSlider.vue +4 -4
  65. package/{components → app/components}/public/cms/element/CmsElementText.vue +8 -2
  66. package/app/components/public/cms/element/SwProductListingPagination.vue +70 -0
  67. package/{components → app/components}/public/cms/section/CmsSectionDefault.vue +1 -1
  68. package/app/components/public/cms/section/CmsSectionSidebar.vue +36 -0
  69. package/app/components/public/cms/skeleton/ProductCardSkeleton.vue +28 -0
  70. package/app/components/ui/BaseButton.vue +99 -0
  71. package/app/components/ui/BaseIcon.vue +15 -0
  72. package/app/components/ui/Checkbox.vue +49 -0
  73. package/app/components/ui/CheckmarkIcon.vue +23 -0
  74. package/app/components/ui/ChevronIcon.vue +37 -0
  75. package/app/components/ui/ExclamationIcon.vue +11 -0
  76. package/app/components/ui/IconButton.vue +32 -0
  77. package/app/components/ui/RadioButton.vue +26 -0
  78. package/app/components/ui/StarIcon.vue +18 -0
  79. package/app/components/ui/SwitchButton.vue +100 -0
  80. package/app/components/ui/UserIcon.vue +11 -0
  81. package/app/components/ui/WishlistIcon.vue +20 -0
  82. package/app/composables/useImagePlaceholder.ts +27 -0
  83. package/{helpers → app/helpers}/clientOnly.ts +5 -0
  84. package/app/providers/shopware.test.ts +213 -0
  85. package/app/providers/shopware.ts +107 -0
  86. package/dist/index.d.mts +3 -3
  87. package/dist/index.d.ts +3 -3
  88. package/dist/index.mjs +2 -2
  89. package/index.d.ts +12 -0
  90. package/nuxt.config.ts +80 -6
  91. package/package.json +29 -21
  92. package/uno.config.ts +83 -0
  93. package/components/SwCategoryNavigation.vue +0 -44
  94. package/components/SwCategoryNavigationLink.vue +0 -57
  95. package/components/SwListingProductPrice.vue +0 -89
  96. package/components/SwProductCard.vue +0 -286
  97. package/components/SwProductListingFilter.vue +0 -42
  98. package/components/SwProductListingFilters.vue +0 -292
  99. package/components/listing-filters/SwFilterPrice.vue +0 -160
  100. package/components/listing-filters/SwFilterProperties.vue +0 -123
  101. package/components/listing-filters/SwFilterRating.vue +0 -101
  102. package/components/listing-filters/SwFilterShippingFree.vue +0 -104
  103. package/components/public/cms/block/CmsBlockImageFourColumn.vue +0 -29
  104. package/components/public/cms/block/CmsBlockImageHighlightRow.vue +0 -27
  105. package/components/public/cms/block/CmsBlockImageTextGallery.vue +0 -85
  106. package/components/public/cms/block/CmsBlockImageTextRow.vue +0 -43
  107. package/components/public/cms/block/CmsBlockImageThreeCover.vue +0 -27
  108. package/components/public/cms/block/CmsBlockImageTwoColumn.vue +0 -25
  109. package/components/public/cms/block/CmsBlockTextOnImage.vue +0 -20
  110. package/components/public/cms/element/CmsElementBuyBox.vue +0 -190
  111. package/components/public/cms/element/CmsElementCategoryNavigation.vue +0 -167
  112. package/components/public/cms/element/CmsElementImageGallery.vue +0 -249
  113. package/components/public/cms/element/CmsElementProductDescriptionReviews.vue +0 -123
  114. package/components/public/cms/element/CmsElementProductName.vue +0 -10
  115. package/components/public/cms/section/CmsSectionSidebar.vue +0 -41
  116. package/components/public/cms/skeleton/ProductCardSkeleton.vue +0 -44
  117. /package/{components → app/components}/SwMedia3D.vue +0 -0
  118. /package/{components → app/components}/SwProductGallery.vue +0 -0
  119. /package/{components → app/components}/SwProductPrice.vue +0 -0
  120. /package/{components → app/components}/SwProductUnits.vue +0 -0
  121. /package/{components → app/components}/SwSharedPrice.vue +0 -0
  122. /package/{components → app/components}/public/cms/CmsGenericBlock.md +0 -0
  123. /package/{components → app/components}/public/cms/CmsGenericBlock.vue +0 -0
  124. /package/{components → app/components}/public/cms/CmsGenericElement.md +0 -0
  125. /package/{components → app/components}/public/cms/CmsGenericElement.vue +0 -0
  126. /package/{components → app/components}/public/cms/CmsNoComponent.vue +0 -0
  127. /package/{components → app/components}/public/cms/CmsPage.md +0 -0
  128. /package/{components → app/components}/public/cms/block/CmsBlockCategoryNavigation.vue +0 -0
  129. /package/{components → app/components}/public/cms/block/CmsBlockCenterText.vue +0 -0
  130. /package/{components → app/components}/public/cms/block/CmsBlockCrossSelling.vue +0 -0
  131. /package/{components → app/components}/public/cms/block/CmsBlockCustomForm.vue +0 -0
  132. /package/{components → app/components}/public/cms/block/CmsBlockDefault.vue +0 -0
  133. /package/{components → app/components}/public/cms/block/CmsBlockForm.vue +0 -0
  134. /package/{components → app/components}/public/cms/block/CmsBlockHtml.vue +0 -0
  135. /package/{components → app/components}/public/cms/block/CmsBlockImage.vue +0 -0
  136. /package/{components → app/components}/public/cms/block/CmsBlockImageCover.vue +0 -0
  137. /package/{components → app/components}/public/cms/block/CmsBlockImageGallery.vue +0 -0
  138. /package/{components → app/components}/public/cms/block/CmsBlockImageSlider.vue +0 -0
  139. /package/{components → app/components}/public/cms/block/CmsBlockProductDescriptionReviews.vue +0 -0
  140. /package/{components → app/components}/public/cms/block/CmsBlockProductListing.vue +0 -0
  141. /package/{components → app/components}/public/cms/block/CmsBlockProductSlider.vue +0 -0
  142. /package/{components → app/components}/public/cms/block/CmsBlockText.vue +0 -0
  143. /package/{components → app/components}/public/cms/block/CmsBlockTextHero.vue +0 -0
  144. /package/{components → app/components}/public/cms/block/CmsBlockTextTeaser.vue +0 -0
  145. /package/{components → app/components}/public/cms/block/CmsBlockTextTeaserSection.vue +0 -0
  146. /package/{components → app/components}/public/cms/block/CmsBlockTextThreeColumn.vue +0 -0
  147. /package/{components → app/components}/public/cms/block/CmsBlockTextTwoColumn.vue +0 -0
  148. /package/{components → app/components}/public/cms/block/CmsBlockVimeoVideo.vue +0 -0
  149. /package/{components → app/components}/public/cms/block/CmsBlockYoutubeVideo.vue +0 -0
  150. /package/{components → app/components}/public/cms/element/CmsElementBuyBox.md +0 -0
  151. /package/{components → app/components}/public/cms/element/CmsElementCategoryNavigation.md +0 -0
  152. /package/{components → app/components}/public/cms/element/CmsElementCrossSelling.md +0 -0
  153. /package/{components → app/components}/public/cms/element/CmsElementCustomForm.md +0 -0
  154. /package/{components → app/components}/public/cms/element/CmsElementCustomForm.vue +0 -0
  155. /package/{components → app/components}/public/cms/element/CmsElementForm.md +0 -0
  156. /package/{components → app/components}/public/cms/element/CmsElementForm.vue +0 -0
  157. /package/{components → app/components}/public/cms/element/CmsElementHtml.vue +0 -0
  158. /package/{components → app/components}/public/cms/element/CmsElementImage.md +0 -0
  159. /package/{components → app/components}/public/cms/element/CmsElementImageGallery.md +0 -0
  160. /package/{components → app/components}/public/cms/element/CmsElementImageGallery3dPlaceholder.vue +0 -0
  161. /package/{components → app/components}/public/cms/element/CmsElementImageSlider.md +0 -0
  162. /package/{components → app/components}/public/cms/element/CmsElementManufacturerLogo.md +0 -0
  163. /package/{components → app/components}/public/cms/element/CmsElementManufacturerLogo.vue +0 -0
  164. /package/{components → app/components}/public/cms/element/CmsElementProductBox.md +0 -0
  165. /package/{components → app/components}/public/cms/element/CmsElementProductDescriptionReviews.md +0 -0
  166. /package/{components → app/components}/public/cms/element/CmsElementProductListing.md +0 -0
  167. /package/{components → app/components}/public/cms/element/CmsElementProductName.md +0 -0
  168. /package/{components → app/components}/public/cms/element/CmsElementProductSlider.md +0 -0
  169. /package/{components → app/components}/public/cms/element/CmsElementSidebarFilter.md +0 -0
  170. /package/{components → app/components}/public/cms/element/CmsElementSidebarFilter.vue +0 -0
  171. /package/{components → app/components}/public/cms/element/CmsElementText.md +0 -0
  172. /package/{components → app/components}/public/cms/element/CmsElementVimeoVideo.md +0 -0
  173. /package/{components → app/components}/public/cms/element/CmsElementVimeoVideo.vue +0 -0
  174. /package/{components → app/components}/public/cms/element/CmsElementYoutubeVideo.md +0 -0
  175. /package/{components → app/components}/public/cms/element/CmsElementYoutubeVideo.vue +0 -0
  176. /package/{components → app/components}/public/cms/section/CmsSectionDefault.md +0 -0
  177. /package/{components → app/components}/public/cms/section/CmsSectionSidebar.md +0 -0
  178. /package/{helpers → app/helpers}/html-to-vue/ast.ts +0 -0
  179. /package/{helpers → app/helpers}/html-to-vue/getOptionsFromNode.test.ts +0 -0
  180. /package/{helpers → app/helpers}/html-to-vue/getOptionsFromNode.ts +0 -0
  181. /package/{helpers → app/helpers}/html-to-vue/renderToHtml.ts +0 -0
  182. /package/{helpers → app/helpers}/html-to-vue/renderer.ts +0 -0
  183. /package/{helpers → app/helpers}/media/isSpatial.ts +0 -0
@@ -0,0 +1,107 @@
1
+ import { defineProvider } from "@nuxt/image/runtime";
2
+ import { encodeUrlPath } from "@shopware/helpers";
3
+
4
+ /**
5
+ * Shopware Image Provider for Nuxt Image
6
+ *
7
+ * Generates optimized image URLs compatible with Shopware's remote thumbnail generation feature.
8
+ * This provider appends transformation parameters as query strings to image URLs, which are then
9
+ * processed by your configured image transformation backend.
10
+ *
11
+ * @remarks
12
+ * Shopware has built-in thumbnail generation (using GD2 or ImageMagick) that creates predefined
13
+ * sizes (400x400, 800x800, 1920x1920) during upload. However, for **on-the-fly transformations**
14
+ * via query parameters (like `?width=800`), you need to configure remote thumbnail generation:
15
+ * - Shopware Cloud: Uses Fastly CDN (configured automatically)
16
+ * - Self-hosted: Requires external middleware (Thumbor, Sharp, imgproxy) or plugins like FroshPlatformThumbnailProcessor
17
+ *
18
+ * Without remote thumbnail generation, query parameters will have no effect and original/predefined thumbnails are served
19
+ *
20
+ * @param src - The source image URL (e.g., "/media/image/product.jpg")
21
+ * @param options - Configuration options
22
+ * @param options.modifiers - Image transformation modifiers
23
+ * @param options.modifiers.width - Target width in pixels
24
+ * @param options.modifiers.height - Target height in pixels
25
+ * @param options.modifiers.quality - Image quality (0-100)
26
+ * @param options.modifiers.format - Output format (jpg, png, webp, avif)
27
+ * @param options.modifiers.fit - Resize mode (cover, contain, crop, bounds, crop_center)
28
+ *
29
+ * @returns Object containing the transformed image URL with query parameters
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * // Basic usage
34
+ * const result = getImage('/media/image/product.jpg', {
35
+ * modifiers: {
36
+ * width: 800,
37
+ * height: 600,
38
+ * quality: 85,
39
+ * format: 'webp',
40
+ * fit: 'cover'
41
+ * }
42
+ * });
43
+ * // Returns: { url: '/media/image/product.jpg?width=800&height=600&quality=85&format=webp&fit=cover' }
44
+ * ```
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * // With existing query parameters
49
+ * const result = getImage('/media/image/product.jpg?v=123', {
50
+ * modifiers: { width: 400 }
51
+ * });
52
+ * // Returns: { url: '/media/image/product.jpg?v=123&width=400' }
53
+ * ```
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * // No modifiers - returns original URL
58
+ * const result = getImage('/media/image/product.jpg');
59
+ * // Returns: { url: '/media/image/product.jpg' }
60
+ * ```
61
+ *
62
+ * @see {@link https://developer.shopware.com/docs/guides/plugins/plugins/content/media/remote-thumbnail-generation.html | Shopware Remote Thumbnail Generation}
63
+ * @see {@link https://image.nuxt.com/providers/custom | Nuxt Image Custom Providers}
64
+ */
65
+
66
+ export default defineProvider(() => ({
67
+ getImage(src, { modifiers }, _ctx) {
68
+ // Encode special characters in the URL pathname (commas, spaces, etc.)
69
+ const encodedSrc = encodeUrlPath(src);
70
+
71
+ const params = new URLSearchParams();
72
+
73
+ // Map Nuxt Image modifiers to Shopware query parameters
74
+ if (modifiers.width) {
75
+ params.set("width", String(modifiers.width));
76
+ }
77
+
78
+ if (modifiers.height) {
79
+ params.set("height", String(modifiers.height));
80
+ }
81
+
82
+ if (modifiers.quality) {
83
+ params.set("quality", String(modifiers.quality));
84
+ }
85
+
86
+ if (modifiers.format) {
87
+ params.set("format", String(modifiers.format));
88
+ }
89
+
90
+ if (modifiers.fit) {
91
+ params.set("fit", String(modifiers.fit));
92
+ }
93
+
94
+ const query = params.toString();
95
+
96
+ if (!query) {
97
+ return { url: encodedSrc };
98
+ }
99
+
100
+ // Check if URL already has query parameters
101
+ const separator = encodedSrc.includes("?") ? "&" : "?";
102
+
103
+ return {
104
+ url: `${encodedSrc}${separator}${query}`,
105
+ };
106
+ },
107
+ }));
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { NuxtModule } from '@nuxt/schema';
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
- declare const nuxtModule: NuxtModule;
3
+ declare const _default: _nuxt_schema.NuxtModule<_nuxt_schema.ModuleOptions, _nuxt_schema.ModuleOptions, false>;
4
4
 
5
- export { nuxtModule as default };
5
+ export { _default as default };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { NuxtModule } from '@nuxt/schema';
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
- declare const nuxtModule: NuxtModule;
3
+ declare const _default: _nuxt_schema.NuxtModule<_nuxt_schema.ModuleOptions, _nuxt_schema.ModuleOptions, false>;
4
4
 
5
- export { nuxtModule as default };
5
+ export { _default as default };
package/dist/index.mjs CHANGED
@@ -10,7 +10,7 @@ import __cjs_mod__ from 'module';
10
10
  const __filename = __cjs_url__.fileURLToPath(import.meta.url);
11
11
  const __dirname = __cjs_path__.dirname(__filename);
12
12
  const require = __cjs_mod__.createRequire(import.meta.url);
13
- const nuxtModule = defineNuxtModule({
13
+ const index = defineNuxtModule({
14
14
  meta: {
15
15
  name: "@shopware/cms-base",
16
16
  configKey: "shopware-cms"
@@ -28,4 +28,4 @@ const nuxtModule = defineNuxtModule({
28
28
  }
29
29
  });
30
30
 
31
- export { nuxtModule as default };
31
+ export { index as default };
package/index.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ /// <reference types="@nuxt/schema" />
2
+
3
+ export * from "@shopware/composables";
4
+ export * from "./.nuxt/imports";
5
+
6
+ declare module "nuxt/schema" {
7
+ interface AppConfig {
8
+ imagePlaceholder?: {
9
+ color?: string;
10
+ };
11
+ }
12
+ }
package/nuxt.config.ts CHANGED
@@ -1,19 +1,93 @@
1
+ import { createResolver } from "@nuxt/kit";
1
2
  import type { NuxtConfig } from "@nuxt/schema";
2
3
  import { defineNuxtConfig } from "nuxt/config";
4
+
5
+ const { resolve: resolveLayer } = createResolver(import.meta.url);
6
+
3
7
  export default defineNuxtConfig({
8
+ modules: ["@unocss/nuxt", "@nuxt/image"],
9
+
10
+ // @ts-ignore - @nuxt/image config may not be typed in some layer contexts
11
+ image: {
12
+ quality: 90,
13
+ format: ["webp", "avif", "jpg"],
14
+ // Custom Shopware provider that maps Nuxt Image modifiers to Shopware query parameters
15
+ provider: "shopware",
16
+ providers: {
17
+ shopware: {
18
+ name: "shopware",
19
+ provider: resolveLayer("./app/providers/shopware.ts"),
20
+ },
21
+ },
22
+
23
+ // Responsive breakpoints matching UnoCSS
24
+ screens: {
25
+ xs: 320,
26
+ sm: 640,
27
+ md: 768,
28
+ lg: 1024,
29
+ xl: 1280,
30
+ xxl: 1536,
31
+ },
32
+
33
+ // Presets for common CMS use cases
34
+ presets: {
35
+ productCard: {
36
+ modifiers: {
37
+ format: "webp",
38
+ quality: 90,
39
+ fit: "cover",
40
+ },
41
+ },
42
+ productDetail: {
43
+ modifiers: {
44
+ format: "webp",
45
+ quality: 90,
46
+ fit: "contain",
47
+ },
48
+ },
49
+ thumbnail: {
50
+ modifiers: {
51
+ format: "webp",
52
+ quality: 90,
53
+ width: 150,
54
+ height: 150,
55
+ fit: "cover",
56
+ },
57
+ },
58
+ hero: {
59
+ modifiers: {
60
+ format: "webp",
61
+ quality: 95,
62
+ fit: "cover",
63
+ },
64
+ },
65
+ },
66
+ },
67
+
4
68
  components: [
5
69
  {
6
- path: "./components/public",
7
- pathPrefix: false,
8
- // global: true,
70
+ path: resolveLayer("./app/components"),
71
+ pattern: "Sw*",
72
+ extensions: [".vue"],
73
+ global: true,
9
74
  },
10
75
  {
11
- path: "./components/",
12
- pattern: "Sw*",
76
+ path: resolveLayer("./app/components/ui"),
77
+ extensions: [".vue"],
78
+ prefix: "Sw",
79
+ global: true,
80
+ },
81
+ {
82
+ path: resolveLayer("./app/components/public"),
83
+ pathPrefix: false,
84
+ global: true,
13
85
  extensions: [".vue"],
14
- global: false,
15
86
  },
16
87
  ],
88
+ alias: {
89
+ "@cms-assets": resolveLayer("./app/assets"),
90
+ },
17
91
  build: {
18
92
  transpile: ["@shopware/cms-base-layer"],
19
93
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopware/cms-base-layer",
3
- "version": "1.5.1",
3
+ "version": "2.0.0",
4
4
  "description": "Vue CMS Nuxt Layer for Shopware",
5
5
  "author": "Shopware",
6
6
  "repository": {
@@ -23,47 +23,55 @@
23
23
  "main": "./nuxt.config.ts",
24
24
  "files": [
25
25
  "dist",
26
- "components",
26
+ "app",
27
27
  "helpers",
28
28
  "index.cjs",
29
- "nuxt.config.ts"
29
+ "index.d.ts",
30
+ "app.config.ts",
31
+ "nuxt.config.ts",
32
+ "uno.config.ts"
30
33
  ],
31
34
  "dependencies": {
32
- "@nuxt/kit": "3.17.5",
33
- "@tresjs/cientos": "4.3.0",
34
- "@tresjs/core": "4.3.3",
35
+ "@iconify-json/carbon": "1.2.14",
36
+ "@nuxt/image": "2.0.0",
37
+ "@nuxt/kit": "4.2.1",
38
+ "@tresjs/cientos": "4.3.1",
39
+ "@tresjs/core": "4.3.6",
40
+ "@unocss/nuxt": "66.5.4",
35
41
  "@vuelidate/core": "2.0.3",
36
42
  "@vuelidate/validators": "2.0.4",
37
- "@vueuse/core": "13.3.0",
43
+ "@vueuse/core": "14.0.0",
38
44
  "entities": "6.0.0",
39
45
  "html-to-ast": "0.0.6",
40
46
  "three": "0.173.0",
41
- "vue": "3.5.16",
47
+ "unocss": "66.5.4",
48
+ "vue": "3.5.24",
42
49
  "xss": "1.0.15",
43
- "@shopware/composables": "1.9.1",
44
- "@shopware/api-client": "1.3.0",
45
- "@shopware/helpers": "1.5.0"
50
+ "@shopware/composables": "1.10.0",
51
+ "@shopware/api-client": "1.4.0",
52
+ "@shopware/helpers": "1.6.0"
46
53
  },
47
54
  "devDependencies": {
48
55
  "@biomejs/biome": "1.8.3",
49
- "@nuxt/schema": "3.17.5",
56
+ "@nuxt/schema": "4.2.1",
50
57
  "@types/three": "0.173.0",
51
- "@vitest/coverage-v8": "3.2.3",
52
- "nuxt": "3.17.5",
53
- "typescript": "5.8.3",
58
+ "@vitest/coverage-v8": "3.2.4",
59
+ "nuxt": "4.2.1",
60
+ "typescript": "5.9.3",
54
61
  "unbuild": "2.0.0",
55
- "vitest": "3.2.3",
56
- "vue-router": "4.5.1",
57
- "vue-tsc": "2.2.10",
62
+ "vitest": "3.2.4",
63
+ "vue-router": "4.6.3",
64
+ "vue-tsc": "3.1.4",
58
65
  "tsconfig": "0.0.0"
59
66
  },
60
67
  "scripts": {
61
- "build": "unbuild",
68
+ "build": "nuxt prepare && unbuild",
62
69
  "dev": "unbuild --stub",
63
70
  "lint": "biome check .",
64
71
  "lint:fix": "biome check . --write && pnpm run typecheck",
65
- "typecheck": "tsc --noEmit",
72
+ "typecheck": "pnpm nuxt prepare && tsc --noEmit",
66
73
  "test": "vitest run",
67
- "test:watch": "vitest"
74
+ "test:watch": "vitest",
75
+ "check-colors": "tsx scripts/check-unused-colors.ts"
68
76
  }
69
77
  }
package/uno.config.ts ADDED
@@ -0,0 +1,83 @@
1
+ import {
2
+ defineConfig,
3
+ presetAttributify,
4
+ presetIcons,
5
+ presetTypography,
6
+ presetWind3,
7
+ } from "unocss";
8
+
9
+ export default defineConfig({
10
+ shortcuts: {},
11
+ preflights: [
12
+ {
13
+ getCSS: () => `
14
+ /* Filter collapse transition */
15
+ .filter-collapse-enter-active,
16
+ .filter-collapse-leave-active {
17
+ transition: all 0.3s ease-in-out;
18
+ overflow: hidden;
19
+ }
20
+
21
+ .filter-collapse-enter-from,
22
+ .filter-collapse-leave-to {
23
+ max-height: 0;
24
+ opacity: 0;
25
+ }
26
+
27
+ .filter-collapse-enter-to,
28
+ .filter-collapse-leave-from {
29
+ max-height: 1000px;
30
+ opacity: 1;
31
+ }
32
+ `,
33
+ },
34
+ ],
35
+ theme: {
36
+ colors: {
37
+ "brand-primary": "#543B95",
38
+ "surface-surface": "#FFFFFF",
39
+ "outline-outline": "#79747E",
40
+ "outline-outline-variant": "#CAC4D0",
41
+ "outline-outline-primary": "#543B95",
42
+ "surface-on-surface": "#1D1B20",
43
+ "surface-surface-variant": "#FBF6FF",
44
+ "states-success": "#15B31C",
45
+ "surface-on-surface-variant": "#696470",
46
+ "surface-surface-disabled": "#E8E8E8",
47
+ "surface-on-surface-disabled": "#9893A6",
48
+ "surface-surface-primary": "#D0BCFF",
49
+ "states-warning": "#F57C00",
50
+ "surface-surface-container": "#F3EDF7",
51
+ "surface-surface-container-highest": "#E6E0E9",
52
+ "states-error": "#D12D24",
53
+ "states-on-error": "#FFFFFF",
54
+ "brand-primary-hover": "#45317A",
55
+ "brand-on-primary": "#FFFFFF",
56
+ "brand-secondary": "#E1D5FF",
57
+ "brand-secondary-hover": "#D0BCFC",
58
+ "brand-on-secondary": "#3A276A",
59
+ "brand-tertiary": "#F1F1F1",
60
+ "brand-tertiary-hover": "#E3E3E3",
61
+ "brand-on-tertiary": "#1D1B20",
62
+ "other-sale": "#D12D24",
63
+ },
64
+ fontFamily: {
65
+ inter: "Inter",
66
+ Noto_Serif: "Noto Serif",
67
+ },
68
+ },
69
+ safelist: ["states-success", "states-error", "states-info", "states-warning"],
70
+ presets: [
71
+ presetWind3(),
72
+ presetIcons({
73
+ collections: {
74
+ carbon: () =>
75
+ import("@iconify-json/carbon/icons.json", {
76
+ with: { type: "json" },
77
+ }).then((i) => i.default),
78
+ },
79
+ }),
80
+ presetAttributify(),
81
+ presetTypography(),
82
+ ],
83
+ });
@@ -1,44 +0,0 @@
1
- <script setup lang="ts">
2
- import type { Schemas } from "#shopware";
3
-
4
- const props = withDefaults(
5
- defineProps<{
6
- activeCategory: Schemas["Category"];
7
- elements: Schemas["Category"][];
8
- level: number;
9
- }>(),
10
- {
11
- level: 0,
12
- },
13
- );
14
-
15
- function getHighlightCategory(navigationElement: Schemas["Category"]) {
16
- return (
17
- (props.activeCategory?.path || "").includes(navigationElement.id) ||
18
- navigationElement.id === props.activeCategory?.id
19
- );
20
- }
21
- </script>
22
- <template>
23
- <ul v-if="props.elements?.length" class="list-none m-0 px-5">
24
- <li
25
- v-for="(navigationElement, index) in props.elements"
26
- :key="index"
27
- :class="{
28
- 'border-b border-gray-200': props.level === 0,
29
- }"
30
- >
31
- <SwCategoryNavigationLink
32
- :navigation-element="navigationElement"
33
- :is-highlighted="getHighlightCategory(navigationElement)"
34
- :is-active="navigationElement.id === props.activeCategory?.id"
35
- />
36
- <SwCategoryNavigation
37
- v-if="navigationElement.children"
38
- :elements="navigationElement.children"
39
- :active-category="props.activeCategory"
40
- :level="props.level + 1"
41
- />
42
- </li>
43
- </ul>
44
- </template>
@@ -1,57 +0,0 @@
1
- <script setup lang="ts">
2
- import {
3
- buildUrlPrefix,
4
- getCategoryRoute,
5
- getTranslatedProperty,
6
- urlIsAbsolute,
7
- } from "@shopware/helpers";
8
- import { computed } from "vue";
9
- import { RouterLink } from "vue-router";
10
- import { useUrlResolver } from "#imports";
11
- import type { Schemas } from "#shopware";
12
-
13
- interface Props {
14
- navigationElement: Schemas["Category"];
15
- isActive?: boolean;
16
- isHighlighted?: boolean;
17
- }
18
-
19
- const props = defineProps<Props>();
20
- const { getUrlPrefix } = useUrlResolver();
21
- const url = computed(() => {
22
- return buildUrlPrefix(
23
- getCategoryRoute(props.navigationElement),
24
- getUrlPrefix(),
25
- );
26
- });
27
- </script>
28
- <template>
29
- <div
30
- class="flex items-center py-2 px-5 text-base rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 my-2"
31
- >
32
- <RouterLink
33
- v-if="!urlIsAbsolute(url.path)"
34
- :to="url"
35
- :class="[
36
- props.isHighlighted ? 'font-bold' : 'font-normal',
37
- props.isActive ? 'text-indigo-600' : 'text-gray-900',
38
- ]"
39
- >
40
- <span>{{ getTranslatedProperty(navigationElement, "name") }}</span>
41
- </RouterLink>
42
- <a
43
- v-else
44
- :href="url.path"
45
- :class="[
46
- props.isHighlighted ? 'font-bold' : 'font-normal',
47
- props.isActive ? 'text-indigo-600' : 'text-gray-900',
48
- ]"
49
- :target="
50
- navigationElement.externalLink || navigationElement.linkNewTab
51
- ? '_blank'
52
- : ''
53
- "
54
- ><span>{{ getTranslatedProperty(navigationElement, "name") }}</span></a
55
- >
56
- </div>
57
- </template>
@@ -1,89 +0,0 @@
1
- <script setup lang="ts">
2
- import { useCmsTranslations, useProductPrice } from "@shopware/composables";
3
- import { defu } from "defu";
4
- import { toRefs } from "vue";
5
- import type { Schemas } from "#shopware";
6
-
7
- const props = defineProps<{
8
- product: Schemas["Product"];
9
- }>();
10
-
11
- type Translations = {
12
- listing: {
13
- variantsFrom: string;
14
- previously: string;
15
- from: string;
16
- to: string;
17
- };
18
- };
19
-
20
- let translations: Translations = {
21
- listing: {
22
- variantsFrom: "variants from",
23
- previously: "previously",
24
- from: "from",
25
- to: "to",
26
- },
27
- };
28
-
29
- translations = defu(useCmsTranslations(), translations) as Translations;
30
-
31
- const { product } = toRefs(props);
32
-
33
- const {
34
- price,
35
- unitPrice,
36
- displayFromVariants,
37
- displayFrom,
38
- isListPrice,
39
- regulationPrice,
40
- } = useProductPrice(product);
41
- </script>
42
-
43
- <template>
44
- <div :id="product.id">
45
- <SwSharedPrice
46
- v-if="isListPrice"
47
- class="text-l text-gray-900 basis-2/6 justify-end line-through"
48
- :value="price?.listPrice?.price"
49
- />
50
- <template v-if="!isListPrice">
51
- <div class="h-6"><!-- placeholder --></div>
52
- </template>
53
- <SwSharedPrice
54
- v-if="displayFromVariants"
55
- class="text-xl text-gray-900 basis-2/6 justify-end"
56
- :value="displayFromVariants"
57
- >
58
- <template #beforePrice
59
- ><span v-if="displayFromVariants" class="text-sm">{{
60
- translations.listing.variantsFrom
61
- }}</span></template
62
- >
63
- </SwSharedPrice>
64
- <SwSharedPrice
65
- class="text-gray-900 basis-2/6"
66
- :class="{
67
- 'text-red-600 font-bold': isListPrice,
68
- 'justify-end text-xl':
69
- regulationPrice || !regulationPrice || !displayFromVariants,
70
- }"
71
- :value="unitPrice"
72
- >
73
- <template #beforePrice
74
- ><span v-if="displayFrom || displayFromVariants" class="text-sm">{{
75
- translations.listing.from
76
- }}</span></template
77
- >
78
- </SwSharedPrice>
79
- <template v-if="regulationPrice">
80
- <div class="flex gap-2 justify-end text-gray-500 text-3.5 mb-2">
81
- {{ translations.listing.previously }}
82
- <SwSharedPrice :value="regulationPrice" />
83
- </div>
84
- </template>
85
- <template v-if="!regulationPrice">
86
- <div class="h-7"><!-- placeholder --></div>
87
- </template>
88
- </div>
89
- </template>