@shopware/cms-base-layer 2.1.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 (109) hide show
  1. package/README.md +93 -135
  2. package/app/app.config.ts +1 -0
  3. package/app/components/SwCategoryNavigation.vue +1 -0
  4. package/app/components/SwCategoryNavigationLink.vue +16 -8
  5. package/app/components/SwContactForm.vue +1 -0
  6. package/app/components/SwFilterChips.vue +1 -0
  7. package/app/components/SwListingProductPrice.vue +16 -4
  8. package/app/components/SwMedia3D.vue +13 -9
  9. package/app/components/SwNewsletterForm.vue +4 -3
  10. package/app/components/SwProductAddToCart.vue +24 -7
  11. package/app/components/SwProductCard.vue +5 -0
  12. package/app/components/SwProductCardDetails.vue +27 -9
  13. package/app/components/SwProductCardImage.vue +52 -35
  14. package/app/components/SwProductCardSkeleton.vue +37 -14
  15. package/app/components/SwProductGallery.vue +1 -0
  16. package/app/components/SwProductListingFilter.vue +5 -1
  17. package/app/components/SwProductListingFilters.vue +23 -8
  18. package/app/components/SwProductListingFiltersHorizontal.vue +6 -3
  19. package/app/components/SwProductPrice.vue +1 -0
  20. package/app/components/SwProductReviews.vue +14 -6
  21. package/app/components/SwProductReviewsForm.vue +15 -3
  22. package/app/components/SwProductUnits.vue +1 -0
  23. package/app/components/SwQuantitySelect.vue +10 -3
  24. package/app/components/SwSharedPrice.vue +1 -0
  25. package/app/components/SwSlider.vue +1 -0
  26. package/app/components/SwStockInfo.vue +12 -6
  27. package/app/components/SwVariantConfigurator.vue +5 -3
  28. package/app/components/listing-filters/SwFilterPrice.vue +79 -30
  29. package/app/components/listing-filters/SwFilterProperties.vue +40 -25
  30. package/app/components/listing-filters/SwFilterRating.vue +21 -9
  31. package/app/components/listing-filters/SwFilterShippingFree.vue +16 -8
  32. package/app/components/public/cms/CmsBlockSpatialViewer.vue +1 -0
  33. package/app/components/public/cms/CmsGenericBlock.vue +11 -4
  34. package/app/components/public/cms/CmsGenericElement.vue +8 -2
  35. package/app/components/public/cms/CmsNoComponent.vue +88 -8
  36. package/app/components/public/cms/CmsPage.md +1 -1
  37. package/app/components/public/cms/CmsPage.vue +5 -6
  38. package/app/components/public/cms/FrontendAccountCustomerGroupRegistrationPage.vue +52 -0
  39. package/app/components/public/cms/block/CmsBlockCategoryNavigation.vue +1 -0
  40. package/app/components/public/cms/block/CmsBlockCenterText.vue +1 -0
  41. package/app/components/public/cms/block/CmsBlockCrossSelling.vue +1 -0
  42. package/app/components/public/cms/block/CmsBlockCustomForm.vue +1 -0
  43. package/app/components/public/cms/block/CmsBlockForm.vue +1 -0
  44. package/app/components/public/cms/block/CmsBlockGalleryBuybox.vue +4 -1
  45. package/app/components/public/cms/block/CmsBlockImage.vue +1 -0
  46. package/app/components/public/cms/block/CmsBlockImageBubbleRow.vue +4 -1
  47. package/app/components/public/cms/block/CmsBlockImageCover.vue +1 -0
  48. package/app/components/public/cms/block/CmsBlockImageFourColumn.vue +4 -1
  49. package/app/components/public/cms/block/CmsBlockImageGallery.vue +1 -0
  50. package/app/components/public/cms/block/CmsBlockImageGalleryBig.vue +1 -0
  51. package/app/components/public/cms/block/CmsBlockImageHighlightRow.vue +4 -1
  52. package/app/components/public/cms/block/CmsBlockImageSimpleGrid.vue +1 -0
  53. package/app/components/public/cms/block/CmsBlockImageSlider.vue +1 -0
  54. package/app/components/public/cms/block/CmsBlockImageText.vue +4 -1
  55. package/app/components/public/cms/block/CmsBlockImageTextBubble.vue +4 -1
  56. package/app/components/public/cms/block/CmsBlockImageTextCover.vue +4 -1
  57. package/app/components/public/cms/block/CmsBlockImageTextGallery.vue +4 -12
  58. package/app/components/public/cms/block/CmsBlockImageTextRow.vue +4 -1
  59. package/app/components/public/cms/block/CmsBlockImageThreeColumn.vue +1 -0
  60. package/app/components/public/cms/block/CmsBlockImageThreeCover.vue +4 -1
  61. package/app/components/public/cms/block/CmsBlockImageTwoColumn.vue +4 -1
  62. package/app/components/public/cms/block/CmsBlockProductDescriptionReviews.vue +1 -0
  63. package/app/components/public/cms/block/CmsBlockProductHeading.vue +1 -0
  64. package/app/components/public/cms/block/CmsBlockProductListing.vue +1 -0
  65. package/app/components/public/cms/block/CmsBlockProductThreeColumn.vue +1 -0
  66. package/app/components/public/cms/block/CmsBlockSidebarFilter.vue +1 -0
  67. package/app/components/public/cms/block/CmsBlockText.vue +1 -0
  68. package/app/components/public/cms/block/CmsBlockTextHero.vue +1 -0
  69. package/app/components/public/cms/block/CmsBlockTextOnImage.vue +2 -4
  70. package/app/components/public/cms/block/CmsBlockTextThreeColumn.vue +1 -0
  71. package/app/components/public/cms/block/CmsBlockTextTwoColumn.vue +4 -1
  72. package/app/components/public/cms/block/CmsBlockVimeoVideo.vue +1 -0
  73. package/app/components/public/cms/block/CmsBlockYoutubeVideo.vue +1 -0
  74. package/app/components/public/cms/element/CmsElementBuyBox.vue +90 -72
  75. package/app/components/public/cms/element/CmsElementCategoryNavigation.vue +14 -3
  76. package/app/components/public/cms/element/CmsElementCrossSelling.vue +3 -1
  77. package/app/components/public/cms/element/CmsElementCustomForm.vue +1 -0
  78. package/app/components/public/cms/element/CmsElementForm.vue +1 -0
  79. package/app/components/public/cms/element/CmsElementHtml.vue +0 -1
  80. package/app/components/public/cms/element/CmsElementImage.vue +15 -34
  81. package/app/components/public/cms/element/CmsElementImageGallery.vue +6 -2
  82. package/app/components/public/cms/element/CmsElementManufacturerLogo.vue +1 -0
  83. package/app/components/public/cms/element/CmsElementProductBox.vue +1 -0
  84. package/app/components/public/cms/element/CmsElementProductDescriptionReviews.vue +77 -29
  85. package/app/components/public/cms/element/CmsElementProductListing.vue +22 -7
  86. package/app/components/public/cms/element/CmsElementProductSlider.vue +6 -4
  87. package/app/components/public/cms/element/CmsElementText.vue +2 -0
  88. package/app/components/public/cms/element/CmsElementVimeoVideo.vue +1 -0
  89. package/app/components/public/cms/element/CmsElementYoutubeVideo.vue +1 -0
  90. package/app/components/public/cms/element/SwProductListingPagination.vue +8 -2
  91. package/app/components/public/cms/section/CmsSectionSidebar.vue +13 -8
  92. package/app/components/public/cms/skeleton/ProductCardSkeleton.vue +16 -5
  93. package/app/components/ui/SwitchButton.vue +53 -14
  94. package/app/components/ui/WishlistIcon.vue +8 -2
  95. package/app/composables/useImagePlaceholder.ts +2 -2
  96. package/app/composables/useLcpImagePreload.test.ts +1 -0
  97. package/app/composables/useLcpImagePreload.ts +12 -6
  98. package/app/composables/useTypedAppConfig.ts +16 -0
  99. package/app/helpers/cms/getImageSizes.test.ts +1 -0
  100. package/app/helpers/html-to-vue/ast.ts +1 -0
  101. package/app/helpers/html-to-vue/getOptionsFromNode.test.ts +1 -0
  102. package/app/helpers/html-to-vue/renderToHtml.ts +1 -0
  103. package/app/helpers/html-to-vue/renderer.ts +1 -0
  104. package/app/providers/shopware.test.ts +1 -0
  105. package/index.d.ts +37 -29
  106. package/nuxt.config.ts +5 -0
  107. package/package.json +22 -25
  108. package/app/plugins/unocss-runtime.client.ts +0 -23
  109. package/uno.config.ts +0 -94
@@ -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,4 @@
1
- import { useAppConfig } from "nuxt/app";
1
+ import { useTypedAppConfig } from "./useTypedAppConfig";
2
2
 
3
3
  /**
4
4
  * Composable that provides an SVG placeholder image as a data URI
@@ -8,7 +8,7 @@ import { useAppConfig } from "nuxt/app";
8
8
  * @returns Base64-encoded SVG data URI
9
9
  */
10
10
  export function useImagePlaceholder(color?: string) {
11
- const appConfig = useAppConfig();
11
+ const appConfig = useTypedAppConfig();
12
12
  const placeholderColor =
13
13
  color || appConfig.imagePlaceholder?.color || "#543B95";
14
14
 
@@ -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,7 +1,10 @@
1
1
  import { computed } from "vue";
2
- import { useAppConfig, useHead } from "#imports";
2
+
3
+ import { useHead } from "#imports";
3
4
  import type { Schemas } from "#shopware";
5
+
4
6
  import { findFirstCmsImageUrl } from "../helpers/cms/findFirstCmsImageUrl";
7
+ import { useTypedAppConfig } from "./useTypedAppConfig";
5
8
 
6
9
  /**
7
10
  * Preloads the first image found in CMS sections (background or element).
@@ -11,13 +14,16 @@ import { findFirstCmsImageUrl } from "../helpers/cms/findFirstCmsImageUrl";
11
14
  * allowing the browser to fetch the image before parsing CSS.
12
15
  */
13
16
  export function useLcpImagePreload(sections: Schemas["CmsSection"][]) {
14
- const appConfig = useAppConfig();
17
+ const appConfig = useTypedAppConfig();
18
+ const isEnabled = Boolean(appConfig.lcpImagePreload);
15
19
 
16
20
  const lcpImageHref = computed(() =>
17
- findFirstCmsImageUrl(sections, {
18
- format: appConfig.backgroundImage?.format,
19
- quality: appConfig.backgroundImage?.quality,
20
- }),
21
+ isEnabled
22
+ ? findFirstCmsImageUrl(sections, {
23
+ format: appConfig.backgroundImage?.format,
24
+ quality: appConfig.backgroundImage?.quality,
25
+ })
26
+ : undefined,
21
27
  );
22
28
 
23
29
  useHead(
@@ -0,0 +1,16 @@
1
+ import type { BackgroundImageOptions } from "@shopware/helpers";
2
+
3
+ import { useAppConfig } from "#imports";
4
+
5
+ type CmsBaseLayerAppConfig = ReturnType<typeof useAppConfig> & {
6
+ imagePlaceholder?: {
7
+ color?: string;
8
+ };
9
+ backgroundImage?: BackgroundImageOptions;
10
+ imageSizes?: Record<string, string>;
11
+ lcpImagePreload?: boolean;
12
+ };
13
+
14
+ export function useTypedAppConfig() {
15
+ return useAppConfig() as CmsBaseLayerAppConfig;
16
+ }
@@ -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/index.d.ts CHANGED
@@ -3,34 +3,42 @@
3
3
  export * from "@shopware/composables";
4
4
  export * from "./.nuxt/imports";
5
5
 
6
+ type CmsBaseLayerAppConfig = {
7
+ /** Placeholder shown while CMS images are loading */
8
+ imagePlaceholder?: {
9
+ /** CSS color value for the placeholder background */
10
+ color?: string;
11
+ };
12
+ /** CDN optimization options applied to CMS background images and synthetic srcsets */
13
+ backgroundImage?: {
14
+ /** Output format passed to the CDN (e.g. "webp", "avif") */
15
+ format?: string;
16
+ /** Image quality 1-100 passed to the CDN */
17
+ quality?: number;
18
+ };
19
+ /** Preload the first CMS image as a likely LCP candidate */
20
+ lcpImagePreload?: boolean;
21
+ /**
22
+ * Maps CMS block slot count to a responsive `sizes` attribute value.
23
+ * Used by CmsGenericBlock to provide sizing hints to child image elements.
24
+ * @example
25
+ * ```ts
26
+ * imageSizes: {
27
+ * 1: "(max-width: 768px) 100vw, 100vw",
28
+ * 2: "(max-width: 768px) 100vw, 50vw",
29
+ * default: "(max-width: 768px) 50vw, 25vw",
30
+ * }
31
+ * ```
32
+ */
33
+ imageSizes?: Record<string | number, string>;
34
+ };
35
+
6
36
  declare module "nuxt/schema" {
7
- interface AppConfig {
8
- /** Placeholder shown while CMS images are loading */
9
- imagePlaceholder?: {
10
- /** CSS color value for the placeholder background */
11
- color?: string;
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;
35
- }
37
+ interface AppConfig extends CmsBaseLayerAppConfig {}
38
+ interface AppConfigInput extends CmsBaseLayerAppConfig {}
39
+ }
40
+
41
+ declare module "@nuxt/schema" {
42
+ interface AppConfig extends CmsBaseLayerAppConfig {}
43
+ interface AppConfigInput extends CmsBaseLayerAppConfig {}
36
44
  }
package/nuxt.config.ts CHANGED
@@ -111,6 +111,11 @@ export default defineNuxtConfig({
111
111
  build: {
112
112
  transpile: ["@shopware/cms-base-layer"],
113
113
  },
114
+ vite: {
115
+ optimizeDeps: {
116
+ include: ["xss"],
117
+ },
118
+ },
114
119
  telemetry: {
115
120
  enabled: false,
116
121
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopware/cms-base-layer",
3
- "version": "2.1.0",
3
+ "version": "3.0.1",
4
4
  "description": "Vue CMS Nuxt Layer for Shopware",
5
5
  "author": "Shopware",
6
6
  "repository": {
@@ -32,45 +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.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",
37
+ "@nuxt/kit": "4.4.8",
38
+ "@tresjs/cientos": "5.7.2",
39
+ "@tresjs/nuxt": "^5.6.1",
42
40
  "@vuelidate/core": "2.0.3",
43
41
  "@vuelidate/validators": "2.0.4",
44
- "@vueuse/core": "14.1.0",
42
+ "@vueuse/core": "14.3.0",
45
43
  "entities": "6.0.0",
44
+ "scule": "1.3.0",
46
45
  "html-to-ast": "0.0.6",
47
- "three": "0.182.0",
48
- "unocss": "66.6.0",
49
- "vue": "3.5.27",
46
+ "three": "0.183.2",
47
+ "vue": "3.5.38",
50
48
  "xss": "1.0.15",
51
- "@shopware/api-client": "1.5.0",
52
- "@shopware/composables": "1.11.0",
53
- "@shopware/helpers": "1.7.0"
49
+ "@shopware/helpers": "1.7.1",
50
+ "@shopware/composables": "1.12.0",
51
+ "@shopware/api-client": "1.5.0"
54
52
  },
55
53
  "devDependencies": {
56
- "@biomejs/biome": "1.8.3",
57
- "@nuxt/schema": "4.2.2",
54
+ "@nuxt/schema": "4.4.8",
58
55
  "@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",
56
+ "@typescript/native-preview": "7.0.0-dev.20260205.1",
57
+ "@vitest/coverage-v8": "4.1.9",
58
+ "nuxt": "4.4.8",
62
59
  "typescript": "5.9.3",
63
- "unbuild": "2.0.0",
64
- "vitest": "4.0.18",
65
- "vue-router": "4.6.4",
66
- "vue-tsc": "3.2.2",
60
+ "unbuild": "3.6.1",
61
+ "vitest": "4.1.9",
62
+ "vue-router": "5.1.0",
63
+ "vue-tsc": "3.3.5",
67
64
  "tsconfig": "0.0.0"
68
65
  },
69
66
  "scripts": {
70
67
  "build": "nuxt prepare && unbuild",
71
68
  "dev": "unbuild --stub",
72
- "lint": "biome check .",
73
- "lint:fix": "biome check . --write && pnpm run typecheck",
69
+ "lint": "oxlint . && oxfmt --check .",
70
+ "lint:fix": "oxlint --fix . && oxfmt --write . && pnpm run typecheck",
74
71
  "typecheck": "pnpm nuxt prepare && tsgo --noEmit",
75
72
  "test": "vitest run",
76
73
  "test:watch": "vitest",
@@ -1,23 +0,0 @@
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/uno.config.ts DELETED
@@ -1,94 +0,0 @@
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
- "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",
74
- },
75
- fontFamily: {
76
- inter: "Inter",
77
- Noto_Serif: "Noto Serif",
78
- },
79
- },
80
- safelist: ["states-success", "states-error", "states-info", "states-warning"],
81
- presets: [
82
- presetWind3(),
83
- presetIcons({
84
- collections: {
85
- carbon: () =>
86
- import("@iconify-json/carbon/icons.json", {
87
- with: { type: "json" },
88
- }).then((i) => i.default),
89
- },
90
- }),
91
- presetAttributify(),
92
- presetTypography(),
93
- ],
94
- });