@shopware/cms-base-layer 2.0.0 → 2.1.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 (64) hide show
  1. package/README.md +168 -100
  2. package/app/app.config.ts +11 -0
  3. package/app/components/SwCategoryNavigation.vue +25 -18
  4. package/app/components/SwFilterDropdown.vue +54 -0
  5. package/app/components/SwListingProductPrice.vue +2 -2
  6. package/app/components/SwMedia3D.vue +4 -2
  7. package/app/components/SwProductCard.vue +20 -21
  8. package/app/components/SwProductCardDetails.vue +29 -12
  9. package/app/components/SwProductCardImage.vue +4 -1
  10. package/app/components/SwProductGallery.vue +18 -14
  11. package/app/components/SwProductListingFilter.vue +20 -9
  12. package/app/components/SwProductListingFilters.vue +1 -5
  13. package/app/components/SwProductListingFiltersHorizontal.vue +306 -0
  14. package/app/components/SwProductPrice.vue +3 -3
  15. package/app/components/SwProductRating.vue +40 -0
  16. package/app/components/SwProductReviews.vue +6 -19
  17. package/app/components/SwProductUnits.vue +10 -15
  18. package/app/components/SwQuantitySelect.vue +4 -7
  19. package/app/components/SwSlider.vue +150 -51
  20. package/app/components/SwSortDropdown.vue +10 -6
  21. package/app/components/SwVariantConfigurator.vue +12 -11
  22. package/app/components/listing-filters/SwFilterPrice.vue +45 -40
  23. package/app/components/listing-filters/SwFilterProperties.vue +40 -33
  24. package/app/components/listing-filters/SwFilterRating.vue +36 -27
  25. package/app/components/listing-filters/SwFilterShippingFree.vue +39 -32
  26. package/app/components/public/cms/CmsBlockSpatialViewer.vue +94 -0
  27. package/app/components/public/cms/CmsGenericBlock.md +17 -2
  28. package/app/components/public/cms/CmsGenericBlock.vue +15 -1
  29. package/app/components/public/cms/CmsPage.md +19 -2
  30. package/app/components/public/cms/CmsPage.vue +11 -1
  31. package/app/components/public/cms/block/CmsBlockCenterText.vue +1 -1
  32. package/app/components/public/cms/block/CmsBlockImageText.vue +5 -5
  33. package/app/components/public/cms/block/CmsBlockTextOnImage.vue +5 -12
  34. package/app/components/public/cms/element/CmsElementBuyBox.vue +3 -3
  35. package/app/components/public/cms/element/CmsElementCrossSelling.vue +19 -3
  36. package/app/components/public/cms/element/CmsElementImage.vue +34 -36
  37. package/app/components/public/cms/element/CmsElementImageGallery.vue +117 -50
  38. package/app/components/public/cms/element/CmsElementProductBox.vue +7 -1
  39. package/app/components/public/cms/element/CmsElementProductListing.vue +10 -3
  40. package/app/components/public/cms/element/CmsElementProductName.vue +6 -1
  41. package/app/components/public/cms/element/CmsElementProductSlider.vue +56 -35
  42. package/app/components/public/cms/element/CmsElementSidebarFilter.vue +10 -2
  43. package/app/components/public/cms/element/CmsElementText.vue +10 -11
  44. package/app/components/public/cms/element/SwProductListingPagination.vue +2 -2
  45. package/app/components/public/cms/section/CmsSectionDefault.vue +2 -2
  46. package/app/components/public/cms/section/CmsSectionSidebar.vue +6 -3
  47. package/app/components/ui/BaseButton.vue +18 -15
  48. package/app/components/ui/ChevronIcon.vue +10 -13
  49. package/app/components/ui/WishlistIcon.vue +3 -8
  50. package/app/composables/useImagePlaceholder.ts +1 -1
  51. package/app/composables/useLcpImagePreload.test.ts +229 -0
  52. package/app/composables/useLcpImagePreload.ts +39 -0
  53. package/app/helpers/cms/findFirstCmsImageUrl.ts +86 -0
  54. package/app/helpers/cms/getImageSizes.test.ts +50 -0
  55. package/app/helpers/cms/getImageSizes.ts +36 -0
  56. package/app/helpers/html-to-vue/ast.ts +53 -19
  57. package/app/helpers/html-to-vue/getOptionsFromNode.ts +1 -1
  58. package/app/helpers/html-to-vue/renderToHtml.ts +7 -11
  59. package/app/helpers/html-to-vue/renderer.ts +86 -26
  60. package/app/plugins/unocss-runtime.client.ts +23 -0
  61. package/index.d.ts +24 -0
  62. package/nuxt.config.ts +20 -0
  63. package/package.json +23 -21
  64. package/uno.config.ts +11 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Default mapping of CMS block slot count to responsive `sizes` attribute values.
3
+ * Used by CmsGenericBlock to provide sizing hints to child image elements.
4
+ *
5
+ * Can be overridden via `app.config.ts`:
6
+ * ```ts
7
+ * export default defineAppConfig({
8
+ * imageSizes: {
9
+ * 1: "(max-width: 768px) 100vw, 1200px",
10
+ * 2: "(max-width: 768px) 100vw, 600px",
11
+ * },
12
+ * });
13
+ * ```
14
+ */
15
+ const DEFAULT_IMAGE_SIZES: Record<string, string> = {
16
+ 1: "(max-width: 768px) 100vw, 100vw",
17
+ 2: "(max-width: 768px) 100vw, 50vw",
18
+ 3: "(max-width: 768px) 100vw, 33vw",
19
+ default: "(max-width: 768px) 50vw, 25vw",
20
+ };
21
+
22
+ /**
23
+ * Returns the responsive `sizes` attribute value for an image
24
+ * based on the number of slots in its parent CMS block.
25
+ *
26
+ * @param slotCount - Number of slots in the block
27
+ * @param config - Optional override map from app.config.ts (imageSizes)
28
+ * @returns A valid HTML `sizes` attribute string
29
+ */
30
+ export function getImageSizes(
31
+ slotCount: number,
32
+ config?: Record<string, string>,
33
+ ): string {
34
+ const sizes = { ...DEFAULT_IMAGE_SIZES, ...config };
35
+ return sizes[slotCount] || sizes.default || "100vw";
36
+ }
@@ -1,51 +1,80 @@
1
- //@ts-nocheck
2
1
  /**
3
2
  * Based on the https://github.com/HCESrl/html-to-vue
4
3
  */
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
  import type { NodeObject } from "./getOptionsFromNode";
7
7
 
8
+ type ASTNode = NodeObject | NodeObject[];
9
+
10
+ type VisitCallback = (
11
+ node: unknown,
12
+ parent: NodeObject | null,
13
+ key: string | null,
14
+ index: number | undefined,
15
+ ) => void;
16
+
17
+ type ExtraComponentConfig = {
18
+ conditions: (node: NodeObject) => boolean;
19
+ renderer?: unknown;
20
+ };
21
+
22
+ export type RectifyConfig = {
23
+ extraComponentsMap?: Record<string, ExtraComponentConfig>;
24
+ };
25
+
8
26
  /**
9
27
  * Visit each node in the AST - with callback (adapted from https://lihautan.com/manipulating-ast-with-javascript/)
10
- * @param {*} ast html-parse-stringify AST
11
- * @param {*} callback
28
+ * @param ast html-parse-stringify AST
29
+ * @param callback
12
30
  */
13
- function _visitAST(ast, callback) {
14
- function _visit(node, parent, key, index) {
31
+ function _visitAST(ast: ASTNode, callback: VisitCallback): void {
32
+ function _visit(
33
+ node: unknown,
34
+ parent: NodeObject | null,
35
+ key: string | null,
36
+ index: number | undefined,
37
+ ): void {
15
38
  callback(node, parent, key, index);
16
39
  if (Array.isArray(node)) {
17
40
  // node is an array
18
- node.forEach((value, index) => {
19
- _visit.call(this, value, node, null, index);
41
+ node.forEach((value, idx) => {
42
+ _visit(value, node as unknown as NodeObject, null, idx);
20
43
  });
21
44
  } else if (isNode(node)) {
22
45
  const keys = Object.keys(node);
23
46
  for (let i = 0; i < keys.length; i++) {
24
- const child = node[keys[i]];
47
+ const childKey = keys[i];
48
+ if (childKey === undefined) continue;
49
+ const child = (node as Record<string, unknown>)[childKey];
25
50
  if (Array.isArray(child)) {
26
51
  for (let j = 0; j < child.length; j++) {
27
- _visit.call(this, child[j], node, key, j);
52
+ _visit(child[j], node, key, j);
28
53
  }
29
54
  } else if (isNode(child)) {
30
- _visit.call(this, child, node, key, undefined);
55
+ _visit(child, node, key, undefined);
31
56
  }
32
57
  }
33
58
  }
34
59
  }
35
- _visit.call(this, ast, null, undefined, undefined);
60
+ _visit(ast, null, null, undefined);
36
61
  }
37
62
 
38
63
  /**
39
64
  *
40
65
  * @param node html-parse-stringify AST node
41
- * @returns {boolean|boolean}
66
+ * @returns {boolean}
42
67
  */
43
- export function isNode(node: NodeObject) {
44
- return typeof node === "object" && typeof node.type !== "undefined";
68
+ export function isNode(node: unknown): node is NodeObject {
69
+ return (
70
+ typeof node === "object" &&
71
+ node !== null &&
72
+ typeof (node as NodeObject).type !== "undefined"
73
+ );
45
74
  }
46
75
 
47
- export function generateAST(html) {
48
- return parse(html);
76
+ export function generateAST(html: string): ASTNode {
77
+ return parse(html) as ASTNode;
49
78
  }
50
79
 
51
80
  /**
@@ -54,16 +83,21 @@ export function generateAST(html) {
54
83
  * @param config
55
84
  * @returns {*}
56
85
  */
57
- export function rectifyAST(ast, config) {
58
- const _ast = JSON.parse(JSON.stringify(ast));
86
+ export function rectifyAST(ast: ASTNode, config: RectifyConfig): ASTNode {
87
+ const _ast = JSON.parse(JSON.stringify(ast)) as ASTNode;
59
88
  const keys = config.extraComponentsMap
60
89
  ? Object.keys(config.extraComponentsMap)
61
90
  : [];
62
91
  _visitAST(_ast, (node) => {
92
+ if (!isNode(node)) {
93
+ return;
94
+ }
63
95
  // checking whether the AST has some components that has to become Vue Components
64
96
  for (let i = 0; i < keys.length; i++) {
65
97
  const currentKey = keys[i];
66
- if (config.extraComponentsMap[currentKey].conditions(node)) {
98
+ if (currentKey === undefined) continue;
99
+ const componentConfig = config.extraComponentsMap?.[currentKey];
100
+ if (componentConfig?.conditions(node)) {
67
101
  node.name = currentKey;
68
102
  }
69
103
  }
@@ -7,7 +7,7 @@ export type NodeObject = {
7
7
  content: string;
8
8
  };
9
9
 
10
- type Options = {
10
+ export type Options = {
11
11
  align?: string;
12
12
  attrs: Record<string, string>;
13
13
  class?: string;
@@ -3,17 +3,10 @@
3
3
  */
4
4
 
5
5
  import type { ComponentInternalInstance, h } from "vue";
6
- import { generateAST, rectifyAST } from "./ast";
7
- import { renderer } from "./renderer";
6
+ import { type RectifyConfig, generateAST, rectifyAST } from "./ast";
7
+ import { type RendererConfig, renderer } from "./renderer";
8
8
 
9
- type DefaultConfig = {
10
- container: {
11
- type: string;
12
- };
13
- extraComponentsMap: Record<string, unknown>;
14
- renderAnyway: boolean;
15
- textTransformer: (text: string) => string;
16
- };
9
+ type DefaultConfig = RendererConfig;
17
10
 
18
11
  const defaultConfig: DefaultConfig = {
19
12
  container: {
@@ -33,7 +26,10 @@ export function renderHtml(
33
26
  ) {
34
27
  const mergedConfig = Object.assign(defaultConfig, config);
35
28
  const _ast = generateAST(html);
36
- const _rectifiedAst = rectifyAST(_ast, config);
29
+ const rectifyConfig: RectifyConfig = {
30
+ extraComponentsMap: config.extraComponentsMap,
31
+ };
32
+ const _rectifiedAst = rectifyAST(_ast, rectifyConfig);
37
33
 
38
34
  return renderer(
39
35
  _rectifiedAst,
@@ -1,26 +1,86 @@
1
- //@ts-nocheck
2
1
  /**
3
2
  * Based on the https://github.com/HCESrl/html-to-vue
4
3
  */
5
4
 
5
+ import type { ComponentInternalInstance, VNode } from "vue";
6
6
  import { isNode } from "./ast";
7
+ import type { NodeObject } from "./getOptionsFromNode";
7
8
  import { getOptionsFromNode } from "./getOptionsFromNode";
8
9
 
10
+ type ASTNode = NodeObject | NodeObject[];
11
+
12
+ type RawChildren = string | number | boolean | VNode;
13
+
14
+ type ExtraComponentRenderer = (
15
+ node: NodeObject,
16
+ children: RawChildren[],
17
+ createElement: typeof import("vue").h,
18
+ context: ComponentInternalInstance | null,
19
+ ) => VNode;
20
+
21
+ export type ExtraComponentConfig = {
22
+ conditions: (node: NodeObject) => boolean;
23
+ renderer: ExtraComponentRenderer;
24
+ };
25
+
26
+ export type RendererConfig = {
27
+ container: {
28
+ type: string;
29
+ };
30
+ extraComponentsMap: Record<string, ExtraComponentConfig>;
31
+ renderAnyway: boolean;
32
+ textTransformer: (text: string) => string;
33
+ };
34
+
35
+ function flattenChildren(
36
+ children: RawChildren | RawChildren[] | undefined,
37
+ ): RawChildren[] {
38
+ if (children === undefined) {
39
+ return [];
40
+ }
41
+ if (Array.isArray(children)) {
42
+ const result: RawChildren[] = [];
43
+ for (const child of children) {
44
+ if (child !== null && child !== undefined) {
45
+ if (Array.isArray(child)) {
46
+ result.push(...flattenChildren(child));
47
+ } else {
48
+ result.push(child);
49
+ }
50
+ }
51
+ }
52
+ return result;
53
+ }
54
+ return [children];
55
+ }
56
+
9
57
  /**
10
58
  * rendering the ast into vue render functions
11
- * @param {*} ast AST generated by html-parse-stringify
12
- * @param {*} config our configuration
13
- * @param {*} createElement vue's createElement
14
- * @param {*} context vue functional component context
59
+ * @param ast AST generated by html-parse-stringify
60
+ * @param config our configuration
61
+ * @param createElement vue's createElement
62
+ * @param context vue functional component context
63
+ * @param resolveUrl function to resolve URLs
15
64
  */
16
- export function renderer(ast, config, createElement, context, resolveUrl) {
17
- function _render(h, node) {
65
+ export function renderer(
66
+ ast: ASTNode,
67
+ config: RendererConfig,
68
+ createElement: typeof import("vue").h,
69
+ context: ComponentInternalInstance | null,
70
+ resolveUrl: (url: string) => string,
71
+ ): VNode {
72
+ function _render(
73
+ h: typeof createElement,
74
+ node: unknown,
75
+ ): RawChildren | RawChildren[] | undefined {
18
76
  if (Array.isArray(node)) {
19
- const nodes = [];
77
+ const nodes: RawChildren[] = [];
20
78
  // node is an array
21
- node.forEach((subnode, index) => {
22
- nodes.push(_render.call(this, h, subnode, node, null, index, h));
23
- });
79
+ for (const subnode of node) {
80
+ const rendered = _render(h, subnode);
81
+ const flattened = flattenChildren(rendered);
82
+ nodes.push(...flattened);
83
+ }
24
84
  return nodes;
25
85
  }
26
86
 
@@ -31,26 +91,26 @@ export function renderer(ast, config, createElement, context, resolveUrl) {
31
91
  }
32
92
  if (node.type === "tag") {
33
93
  const transformedNode = getOptionsFromNode(node, resolveUrl);
34
- const children = [];
35
- node.children.forEach((child, index) => {
36
- children.push(_render.call(this, h, child, transformedNode, index));
37
- });
94
+ const children: RawChildren[] = [];
95
+ for (const child of node.children) {
96
+ const rendered = _render(h, child);
97
+ const flattened = flattenChildren(rendered);
98
+ children.push(...flattened);
99
+ }
38
100
  // if it's an extra component use custom renderer
39
- if (typeof config.extraComponentsMap[node.name] !== "undefined") {
40
- return config.extraComponentsMap[node.name].renderer.call(
41
- this,
42
- transformedNode,
43
- children,
44
- h,
45
- context,
46
- );
101
+ const componentConfig = config.extraComponentsMap[node.name];
102
+ if (componentConfig !== undefined) {
103
+ return componentConfig.renderer(node, children, h, context);
47
104
  }
48
105
  // else, create normal html element
49
106
  return h(node.name, transformedNode, [...children]);
50
107
  }
51
108
  }
109
+ return undefined;
52
110
  }
53
- return createElement(config.container.type, context.data, [
54
- ..._render.call(this, createElement, ast),
55
- ]);
111
+
112
+ const rendered = _render(createElement, ast);
113
+ const children = flattenChildren(rendered);
114
+
115
+ return createElement(config.container.type, context?.data || {}, children);
56
116
  }
@@ -0,0 +1,23 @@
1
+ import initUnocssRuntime from "@unocss/runtime";
2
+ import { presetWind3 } from "unocss";
3
+ import { defineNuxtPlugin, useAppConfig } from "#imports";
4
+ import unoConfig from "../../uno.config";
5
+
6
+ // Resolves UnoCSS utility classes at runtime via DOM MutationObserver.
7
+ // Needed when CMS content contains dynamic classes not known at build time,
8
+ // since extracting all CMS-used classes from the backend during build is impractical.
9
+ // Trade-off: may cause layout shift as styles are applied after hydration.
10
+ // Can be disabled via app.config.ts: { unocssRuntime: false }
11
+ // When disabled, CMS classes unknown at build time won't be resolved —
12
+ // add them to the UnoCSS safelist in uno.config.ts to ensure they are generated.
13
+ export default defineNuxtPlugin(() => {
14
+ const appConfig = useAppConfig();
15
+ if (!appConfig.unocssRuntime) return;
16
+
17
+ initUnocssRuntime({
18
+ defaults: {
19
+ theme: unoConfig.theme,
20
+ presets: [presetWind3()],
21
+ },
22
+ });
23
+ });
package/index.d.ts CHANGED
@@ -5,8 +5,32 @@ export * from "./.nuxt/imports";
5
5
 
6
6
  declare module "nuxt/schema" {
7
7
  interface AppConfig {
8
+ /** Placeholder shown while CMS images are loading */
8
9
  imagePlaceholder?: {
10
+ /** CSS color value for the placeholder background */
9
11
  color?: string;
10
12
  };
13
+ /** CDN optimization options applied to CMS background images and synthetic srcsets */
14
+ backgroundImage?: {
15
+ /** Output format passed to the CDN (e.g. "webp", "avif") */
16
+ format?: string;
17
+ /** Image quality 1-100 passed to the CDN */
18
+ quality?: number;
19
+ };
20
+ /**
21
+ * Maps CMS block slot count to a responsive `sizes` attribute value.
22
+ * Used by CmsGenericBlock to provide sizing hints to child image elements.
23
+ * @example
24
+ * ```ts
25
+ * imageSizes: {
26
+ * 1: "(max-width: 768px) 100vw, 100vw",
27
+ * 2: "(max-width: 768px) 100vw, 50vw",
28
+ * default: "(max-width: 768px) 50vw, 25vw",
29
+ * }
30
+ * ```
31
+ */
32
+ imageSizes?: Record<string | number, string>;
33
+ /** Enable UnoCSS runtime for dynamic class generation */
34
+ unocssRuntime?: boolean;
11
35
  }
12
36
  }
package/nuxt.config.ts CHANGED
@@ -5,8 +5,28 @@ import { defineNuxtConfig } from "nuxt/config";
5
5
  const { resolve: resolveLayer } = createResolver(import.meta.url);
6
6
 
7
7
  export default defineNuxtConfig({
8
+ // @tresjs/nuxt is not included here because SwMedia3D is excluded from auto-import
9
+ // to prevent bundling heavy 3D libraries in the initial bundle.
10
+ // If you need 3D support, add "@tresjs/nuxt" to your app's nuxt.config.ts modules array
11
+ // and dynamically import SwMedia3D using defineAsyncComponent.
8
12
  modules: ["@unocss/nuxt", "@nuxt/image"],
9
13
 
14
+ hooks: {
15
+ "components:extend"(components) {
16
+ // Exclude SwMedia3D from auto-import to prevent bundling heavy 3D libraries
17
+ // It should be dynamically imported when needed using defineAsyncComponent.
18
+ const index = components.findIndex(
19
+ (c) =>
20
+ c.pascalName === "SwMedia3D" ||
21
+ c.kebabName === "sw-media3-d" ||
22
+ c.filePath?.includes("SwMedia3D.vue"),
23
+ );
24
+ if (index > -1) {
25
+ components.splice(index, 1);
26
+ }
27
+ },
28
+ },
29
+
10
30
  // @ts-ignore - @nuxt/image config may not be typed in some layer contexts
11
31
  image: {
12
32
  quality: 90,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopware/cms-base-layer",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Vue CMS Nuxt Layer for Shopware",
5
5
  "author": "Shopware",
6
6
  "repository": {
@@ -32,36 +32,38 @@
32
32
  "uno.config.ts"
33
33
  ],
34
34
  "dependencies": {
35
- "@iconify-json/carbon": "1.2.14",
35
+ "@iconify-json/carbon": "1.2.18",
36
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",
37
+ "@nuxt/kit": "4.2.2",
38
+ "@tresjs/cientos": "5.2.4",
39
+ "@tresjs/nuxt": "^5.1.6",
40
+ "@unocss/nuxt": "66.6.0",
41
+ "@unocss/runtime": "66.6.0",
41
42
  "@vuelidate/core": "2.0.3",
42
43
  "@vuelidate/validators": "2.0.4",
43
- "@vueuse/core": "14.0.0",
44
+ "@vueuse/core": "14.1.0",
44
45
  "entities": "6.0.0",
45
46
  "html-to-ast": "0.0.6",
46
- "three": "0.173.0",
47
- "unocss": "66.5.4",
48
- "vue": "3.5.24",
47
+ "three": "0.182.0",
48
+ "unocss": "66.6.0",
49
+ "vue": "3.5.27",
49
50
  "xss": "1.0.15",
50
- "@shopware/composables": "1.10.0",
51
- "@shopware/api-client": "1.4.0",
52
- "@shopware/helpers": "1.6.0"
51
+ "@shopware/api-client": "1.5.0",
52
+ "@shopware/composables": "1.11.0",
53
+ "@shopware/helpers": "1.7.0"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@biomejs/biome": "1.8.3",
56
- "@nuxt/schema": "4.2.1",
57
- "@types/three": "0.173.0",
58
- "@vitest/coverage-v8": "3.2.4",
59
- "nuxt": "4.2.1",
57
+ "@nuxt/schema": "4.2.2",
58
+ "@types/three": "0.182.0",
59
+ "@typescript/native-preview": "7.0.0-dev.20260111.1",
60
+ "@vitest/coverage-v8": "4.0.18",
61
+ "nuxt": "4.2.2",
60
62
  "typescript": "5.9.3",
61
63
  "unbuild": "2.0.0",
62
- "vitest": "3.2.4",
63
- "vue-router": "4.6.3",
64
- "vue-tsc": "3.1.4",
64
+ "vitest": "4.0.18",
65
+ "vue-router": "4.6.4",
66
+ "vue-tsc": "3.2.2",
65
67
  "tsconfig": "0.0.0"
66
68
  },
67
69
  "scripts": {
@@ -69,7 +71,7 @@
69
71
  "dev": "unbuild --stub",
70
72
  "lint": "biome check .",
71
73
  "lint:fix": "biome check . --write && pnpm run typecheck",
72
- "typecheck": "pnpm nuxt prepare && tsc --noEmit",
74
+ "typecheck": "pnpm nuxt prepare && tsgo --noEmit",
73
75
  "test": "vitest run",
74
76
  "test:watch": "vitest",
75
77
  "check-colors": "tsx scripts/check-unused-colors.ts"
package/uno.config.ts CHANGED
@@ -60,6 +60,17 @@ export default defineConfig({
60
60
  "brand-tertiary-hover": "#E3E3E3",
61
61
  "brand-on-tertiary": "#1D1B20",
62
62
  "other-sale": "#D12D24",
63
+ "overlay-dark-highest": "rgba(0, 0, 0, 0.75)",
64
+ "overlay-dark-high": "rgba(0, 0, 0, 0.5)",
65
+ "overlay-dark": "rgba(0, 0, 0, 0.3)",
66
+ "overlay-dark-low": "rgba(0, 0, 0, 0.12)",
67
+ "overlay-dark-lowest": "rgba(0, 0, 0, 0.08)",
68
+ "overlay-light-highest": "rgba(255, 255, 255, 0.75)",
69
+ "overlay-light-high": "rgba(255, 255, 255, 0.5)",
70
+ "overlay-light": "rgba(255, 255, 255, 0.25)",
71
+ "overlay-light-low": "rgba(255, 255, 255, 0.12)",
72
+ "overlay-light-lowest": "rgba(255, 255, 255, 0.08)",
73
+ "fixed-fixed-on-image": "#FFFFFF",
63
74
  },
64
75
  fontFamily: {
65
76
  inter: "Inter",