@shopware/cms-base-layer 3.1.0 → 4.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 +64 -23
- package/app/app.config.ts +3 -3
- package/app/assets/css/rich-text.css +80 -0
- package/app/components/SwContactForm.vue +2 -1
- package/app/components/SwFilterChips.vue +29 -7
- package/app/components/SwNewsletterForm.vue +2 -1
- package/app/components/SwProductCardImage.vue +5 -1
- package/app/components/SwProductListingFilter.vue +5 -0
- package/app/components/SwProductListingFilters.vue +40 -4
- package/app/components/SwProductListingFiltersHorizontal.vue +37 -2
- package/app/components/SwStockInfo.vue +5 -2
- package/app/components/SwVariantConfigurator.vue +8 -3
- package/app/components/listing-filters/SwFilterCategories.vue +158 -0
- package/app/components/public/cms/FrontendAccountCustomerGroupRegistrationPage.vue +1 -1
- package/app/components/public/cms/element/CmsElementBuyBox.vue +4 -1
- package/app/components/public/cms/element/CmsElementCrossSelling.vue +2 -1
- package/app/components/public/cms/element/CmsElementHtml.vue +1 -1
- package/app/components/public/cms/element/CmsElementImage.vue +41 -1
- package/app/components/public/cms/element/CmsElementImageGallery.vue +2 -1
- package/app/components/public/cms/element/CmsElementProductDescriptionReviews.vue +2 -2
- package/app/components/public/cms/element/CmsElementText.md +77 -0
- package/app/components/public/cms/element/CmsElementText.vue +5 -32
- package/app/helpers/html-to-vue/renderToHtml.test.ts +55 -0
- package/app/helpers/html-to-vue/renderToHtml.ts +5 -1
- package/app/helpers/html-to-vue/renderer.ts +10 -1
- package/app/utils/listingFilters.test.ts +39 -0
- package/app/utils/listingFilters.ts +19 -0
- package/app/utils/useSelectedListingFilters.test.ts +13 -3
- package/app/utils/useSelectedListingFilters.ts +7 -1
- package/component-dirs.json +20 -0
- package/index.d.ts +2 -2
- package/nuxt.config.ts +11 -28
- package/package.json +20 -23
- package/dist/index.d.mts +0 -5
- package/dist/index.d.ts +0 -5
- package/dist/index.mjs +0 -31
- package/index.cjs +0 -7
|
@@ -8,17 +8,27 @@ import {
|
|
|
8
8
|
describe("applyQueryToFilters", () => {
|
|
9
9
|
it("populates sets from pipe-joined values", () => {
|
|
10
10
|
const state = createEmptyFilterState();
|
|
11
|
-
applyQueryToFilters(state, {
|
|
11
|
+
applyQueryToFilters(state, {
|
|
12
|
+
manufacturer: "a|b",
|
|
13
|
+
properties: "x",
|
|
14
|
+
categories: "c1|c2",
|
|
15
|
+
});
|
|
12
16
|
expect([...state.manufacturer]).toEqual(["a", "b"]);
|
|
13
17
|
expect([...state.properties]).toEqual(["x"]);
|
|
18
|
+
expect([...state.categories]).toEqual(["c1", "c2"]);
|
|
14
19
|
});
|
|
15
20
|
|
|
16
21
|
it("clears removed filters when the query no longer has them (Back/Forward)", () => {
|
|
17
22
|
const state = createEmptyFilterState();
|
|
18
|
-
applyQueryToFilters(state, {
|
|
19
|
-
|
|
23
|
+
applyQueryToFilters(state, {
|
|
24
|
+
manufacturer: "a|b",
|
|
25
|
+
categories: "c1",
|
|
26
|
+
search: "shirt",
|
|
27
|
+
});
|
|
28
|
+
applyQueryToFilters(state, { search: "shirt" }); // manufacturer + categories removed
|
|
20
29
|
expect(state.manufacturer.size).toBe(0);
|
|
21
30
|
expect(state.properties.size).toBe(0);
|
|
31
|
+
expect(state.categories.size).toBe(0);
|
|
22
32
|
});
|
|
23
33
|
|
|
24
34
|
it("clears removed scalar filters on resync", () => {
|
|
@@ -8,6 +8,7 @@ import { firstQueryValue, toNumber } from "./routeQuery";
|
|
|
8
8
|
export type FilterState = {
|
|
9
9
|
manufacturer: Set<string>;
|
|
10
10
|
properties: Set<string>;
|
|
11
|
+
categories: Set<string>;
|
|
11
12
|
"min-price": number | undefined;
|
|
12
13
|
"max-price": number | undefined;
|
|
13
14
|
rating: number | undefined;
|
|
@@ -18,6 +19,7 @@ export type FilterState = {
|
|
|
18
19
|
export const createEmptyFilterState = (): FilterState => ({
|
|
19
20
|
manufacturer: new Set<string>(),
|
|
20
21
|
properties: new Set<string>(),
|
|
22
|
+
categories: new Set<string>(),
|
|
21
23
|
"min-price": undefined,
|
|
22
24
|
"max-price": undefined,
|
|
23
25
|
rating: undefined,
|
|
@@ -46,13 +48,14 @@ export const applyQueryToFilters = (
|
|
|
46
48
|
// (props bound to them stay reactive); replace scalars with undefined.
|
|
47
49
|
state.manufacturer.clear();
|
|
48
50
|
state.properties.clear();
|
|
51
|
+
state.categories.clear();
|
|
49
52
|
state["min-price"] = undefined;
|
|
50
53
|
state["max-price"] = undefined;
|
|
51
54
|
state.rating = undefined;
|
|
52
55
|
state["shipping-free"] = undefined;
|
|
53
56
|
|
|
54
57
|
// 2) Repopulate from the current query.
|
|
55
|
-
for (const code of ["manufacturer", "properties"] as const) {
|
|
58
|
+
for (const code of ["manufacturer", "properties", "categories"] as const) {
|
|
56
59
|
const value = firstQueryValue(query[code]);
|
|
57
60
|
if (!value) continue;
|
|
58
61
|
for (const element of value.split("|")) {
|
|
@@ -88,6 +91,9 @@ export const applyQueryToFilters = (
|
|
|
88
91
|
*/
|
|
89
92
|
export const useSelectedListingFilters = (): UnwrapNestedRefs<FilterState> => {
|
|
90
93
|
const route = useRoute();
|
|
94
|
+
// Fresh state per call, deliberately: the sidebar and the horizontal filter
|
|
95
|
+
// bar each hold their own selection object, so a mutation in one is invisible
|
|
96
|
+
// to the other until it reaches the route. The URL is what synchronises them.
|
|
91
97
|
const state = reactive<FilterState>(createEmptyFilterState());
|
|
92
98
|
|
|
93
99
|
// Initial parse (SSR + first client render).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dirs": [
|
|
3
|
+
{
|
|
4
|
+
"path": "./app/components",
|
|
5
|
+
"pattern": "Sw*",
|
|
6
|
+
"global": true
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"path": "./app/components/public",
|
|
10
|
+
"pathPrefix": false,
|
|
11
|
+
"global": true
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"path": "./app/components/ui",
|
|
15
|
+
"prefix": "Sw",
|
|
16
|
+
"global": true
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"excluded": ["SwMedia3D"]
|
|
20
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/// <reference types="@nuxt/schema" />
|
|
2
2
|
|
|
3
|
-
export * from "@shopware/composables";
|
|
4
|
-
export * from "./.nuxt/imports";
|
|
5
3
|
|
|
6
4
|
type CmsBaseLayerAppConfig = {
|
|
7
5
|
/** Placeholder shown while CMS images are loading */
|
|
@@ -42,3 +40,5 @@ declare module "@nuxt/schema" {
|
|
|
42
40
|
interface AppConfig extends CmsBaseLayerAppConfig {}
|
|
43
41
|
interface AppConfigInput extends CmsBaseLayerAppConfig {}
|
|
44
42
|
}
|
|
43
|
+
|
|
44
|
+
export {};
|
package/nuxt.config.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { NuxtConfig } from "@nuxt/schema";
|
|
|
3
3
|
import { defineNuxtConfig } from "nuxt/config";
|
|
4
4
|
import type { LoggingFunction, RollupLog } from "rollup";
|
|
5
5
|
|
|
6
|
+
import componentDirs from "./component-dirs.json";
|
|
7
|
+
|
|
6
8
|
const { resolve: resolveLayer } = createResolver(import.meta.url);
|
|
7
9
|
|
|
8
10
|
export default defineNuxtConfig({
|
|
@@ -15,19 +17,15 @@ export default defineNuxtConfig({
|
|
|
15
17
|
// the UnoCSS setup lives in @shopware/unocss-design-tokens-layer (or your own config),
|
|
16
18
|
// so apps that don't use UnoCSS can still extend this layer.
|
|
17
19
|
modules: ["@nuxt/image"],
|
|
20
|
+
css: [resolveLayer("./app/assets/css/rich-text.css")],
|
|
18
21
|
|
|
19
22
|
hooks: {
|
|
20
23
|
"components:extend"(components) {
|
|
21
24
|
// Exclude SwMedia3D from auto-import to prevent bundling heavy 3D libraries
|
|
22
25
|
// It should be dynamically imported when needed using defineAsyncComponent.
|
|
23
|
-
const
|
|
24
|
-
(c) =>
|
|
25
|
-
|
|
26
|
-
c.kebabName === "sw-media3-d" ||
|
|
27
|
-
c.filePath?.includes("SwMedia3D.vue"),
|
|
28
|
-
);
|
|
29
|
-
if (index > -1) {
|
|
30
|
-
components.splice(index, 1);
|
|
26
|
+
for (const name of componentDirs.excluded) {
|
|
27
|
+
const index = components.findIndex((c) => c.pascalName === name);
|
|
28
|
+
if (index > -1) components.splice(index, 1);
|
|
31
29
|
}
|
|
32
30
|
},
|
|
33
31
|
},
|
|
@@ -90,26 +88,11 @@ export default defineNuxtConfig({
|
|
|
90
88
|
},
|
|
91
89
|
},
|
|
92
90
|
|
|
93
|
-
components:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
global: true,
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
path: resolveLayer("./app/components/ui"),
|
|
102
|
-
extensions: [".vue"],
|
|
103
|
-
prefix: "Sw",
|
|
104
|
-
global: true,
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
path: resolveLayer("./app/components/public"),
|
|
108
|
-
pathPrefix: false,
|
|
109
|
-
global: true,
|
|
110
|
-
extensions: [".vue"],
|
|
111
|
-
},
|
|
112
|
-
],
|
|
91
|
+
components: componentDirs.dirs.map(({ path, ...dir }) => ({
|
|
92
|
+
...dir,
|
|
93
|
+
path: resolveLayer(path),
|
|
94
|
+
extensions: [".vue"],
|
|
95
|
+
})),
|
|
113
96
|
alias: {
|
|
114
97
|
"@cms-assets": resolveLayer("./app/assets"),
|
|
115
98
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopware/cms-base-layer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Vue CMS Nuxt Layer for Shopware",
|
|
5
5
|
"author": "Shopware",
|
|
6
6
|
"repository": {
|
|
@@ -21,20 +21,21 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"type": "module",
|
|
23
23
|
"main": "./nuxt.config.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": "./nuxt.config.ts",
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
24
28
|
"files": [
|
|
25
|
-
"dist",
|
|
26
29
|
"app",
|
|
27
|
-
"
|
|
28
|
-
"index.cjs",
|
|
30
|
+
"component-dirs.json",
|
|
29
31
|
"index.d.ts",
|
|
30
|
-
"app.config.ts",
|
|
31
32
|
"nuxt.config.ts"
|
|
32
33
|
],
|
|
33
34
|
"dependencies": {
|
|
34
|
-
"@iconify-json/carbon": "1.2.
|
|
35
|
-
"@nuxt/image": "2.
|
|
36
|
-
"@nuxt/kit": "4.
|
|
37
|
-
"@tresjs/cientos": "5.
|
|
35
|
+
"@iconify-json/carbon": "1.2.26",
|
|
36
|
+
"@nuxt/image": "2.1.0",
|
|
37
|
+
"@nuxt/kit": "4.5.2",
|
|
38
|
+
"@tresjs/cientos": "5.8.1",
|
|
38
39
|
"@tresjs/nuxt": "^5.6.3",
|
|
39
40
|
"@vuelidate/core": "2.0.3",
|
|
40
41
|
"@vuelidate/validators": "2.0.4",
|
|
@@ -42,34 +43,30 @@
|
|
|
42
43
|
"entities": "8.0.0",
|
|
43
44
|
"scule": "1.3.0",
|
|
44
45
|
"html-to-ast": "0.0.6",
|
|
45
|
-
"three": "0.
|
|
46
|
-
"vue": "3.5.
|
|
46
|
+
"three": "0.185.1",
|
|
47
|
+
"vue": "3.5.42",
|
|
47
48
|
"xss": "1.0.15",
|
|
48
|
-
"@shopware/
|
|
49
|
-
"@shopware/
|
|
50
|
-
"@shopware/helpers": "1.
|
|
49
|
+
"@shopware/composables": "1.13.0",
|
|
50
|
+
"@shopware/api-client": "1.6.0",
|
|
51
|
+
"@shopware/helpers": "1.8.0"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
|
-
"@nuxt/schema": "4.
|
|
54
|
+
"@nuxt/schema": "4.5.2",
|
|
54
55
|
"@types/three": "0.182.0",
|
|
55
56
|
"@typescript/native-preview": "7.0.0-dev.20260205.1",
|
|
56
57
|
"@vitest/coverage-v8": "4.1.10",
|
|
57
|
-
"nuxt": "4.
|
|
58
|
+
"nuxt": "4.5.2",
|
|
58
59
|
"typescript": "5.9.3",
|
|
59
|
-
"unbuild": "3.6.1",
|
|
60
60
|
"vitest": "4.1.10",
|
|
61
|
-
"vue-router": "5.
|
|
62
|
-
"vue-tsc": "3.3.
|
|
61
|
+
"vue-router": "5.2.0",
|
|
62
|
+
"vue-tsc": "3.3.9",
|
|
63
63
|
"tsconfig": "0.0.0"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
|
-
"build": "nuxt prepare && unbuild",
|
|
67
|
-
"dev": "unbuild --stub",
|
|
68
66
|
"lint": "oxlint . && oxfmt --check .",
|
|
69
67
|
"lint:fix": "oxlint --fix . && oxfmt --write . && pnpm run typecheck",
|
|
70
68
|
"typecheck": "pnpm nuxt prepare && tsgo --noEmit",
|
|
71
69
|
"test": "vitest run",
|
|
72
|
-
"test:watch": "vitest"
|
|
73
|
-
"check-colors": "tsx scripts/check-unused-colors.ts"
|
|
70
|
+
"test:watch": "vitest"
|
|
74
71
|
}
|
|
75
72
|
}
|
package/dist/index.d.mts
DELETED
package/dist/index.d.ts
DELETED
package/dist/index.mjs
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { defineNuxtModule } from '@nuxt/kit';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// -- Unbuild CommonJS Shims --
|
|
7
|
-
import __cjs_url__ from 'url';
|
|
8
|
-
import __cjs_path__ from 'path';
|
|
9
|
-
import __cjs_mod__ from 'module';
|
|
10
|
-
const __filename = __cjs_url__.fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = __cjs_path__.dirname(__filename);
|
|
12
|
-
const require = __cjs_mod__.createRequire(import.meta.url);
|
|
13
|
-
const index = defineNuxtModule({
|
|
14
|
-
meta: {
|
|
15
|
-
name: "@shopware/cms-base",
|
|
16
|
-
configKey: "shopware-cms"
|
|
17
|
-
},
|
|
18
|
-
setup(_, nuxt) {
|
|
19
|
-
nuxt.hook("components:dirs", (c) => {
|
|
20
|
-
c.push({
|
|
21
|
-
path: resolve(__dirname, "../components/public"),
|
|
22
|
-
global: true
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
nuxt.options.imports.transform = nuxt.options.imports.transform || {};
|
|
26
|
-
nuxt.options.imports.transform.include = nuxt.options.imports.transform?.include || [];
|
|
27
|
-
nuxt.options.imports.transform?.include.push(/.+cms-base.+/);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
export { index as default };
|
package/index.cjs
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// CommonJS proxy to bypass jiti transforms from nuxt 2 and using native ESM
|
|
2
|
-
module.exports = function (...args) {
|
|
3
|
-
return import("./dist/index.mjs").then((m) => m.default.call(this, ...args));
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
// eslint-disable-next-line
|
|
7
|
-
module.exports.meta = require("./package.json");
|