@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.
- package/README.md +93 -135
- package/app/app.config.ts +1 -0
- package/app/components/SwCategoryNavigation.vue +1 -0
- package/app/components/SwCategoryNavigationLink.vue +16 -8
- package/app/components/SwContactForm.vue +1 -0
- package/app/components/SwFilterChips.vue +1 -0
- package/app/components/SwListingProductPrice.vue +16 -4
- package/app/components/SwMedia3D.vue +13 -9
- package/app/components/SwNewsletterForm.vue +4 -3
- package/app/components/SwProductAddToCart.vue +24 -7
- package/app/components/SwProductCard.vue +5 -0
- package/app/components/SwProductCardDetails.vue +27 -9
- package/app/components/SwProductCardImage.vue +52 -35
- package/app/components/SwProductCardSkeleton.vue +37 -14
- package/app/components/SwProductGallery.vue +1 -0
- package/app/components/SwProductListingFilter.vue +5 -1
- package/app/components/SwProductListingFilters.vue +23 -8
- package/app/components/SwProductListingFiltersHorizontal.vue +6 -3
- package/app/components/SwProductPrice.vue +1 -0
- package/app/components/SwProductReviews.vue +14 -6
- package/app/components/SwProductReviewsForm.vue +15 -3
- package/app/components/SwProductUnits.vue +1 -0
- package/app/components/SwQuantitySelect.vue +10 -3
- package/app/components/SwSharedPrice.vue +1 -0
- package/app/components/SwSlider.vue +1 -0
- package/app/components/SwStockInfo.vue +12 -6
- package/app/components/SwVariantConfigurator.vue +5 -3
- package/app/components/listing-filters/SwFilterPrice.vue +79 -30
- package/app/components/listing-filters/SwFilterProperties.vue +40 -25
- package/app/components/listing-filters/SwFilterRating.vue +21 -9
- package/app/components/listing-filters/SwFilterShippingFree.vue +16 -8
- package/app/components/public/cms/CmsBlockSpatialViewer.vue +1 -0
- package/app/components/public/cms/CmsGenericBlock.vue +11 -4
- package/app/components/public/cms/CmsGenericElement.vue +8 -2
- package/app/components/public/cms/CmsNoComponent.vue +88 -8
- package/app/components/public/cms/CmsPage.md +1 -1
- package/app/components/public/cms/CmsPage.vue +5 -6
- package/app/components/public/cms/FrontendAccountCustomerGroupRegistrationPage.vue +52 -0
- package/app/components/public/cms/block/CmsBlockCategoryNavigation.vue +1 -0
- package/app/components/public/cms/block/CmsBlockCenterText.vue +1 -0
- package/app/components/public/cms/block/CmsBlockCrossSelling.vue +1 -0
- package/app/components/public/cms/block/CmsBlockCustomForm.vue +1 -0
- package/app/components/public/cms/block/CmsBlockForm.vue +1 -0
- package/app/components/public/cms/block/CmsBlockGalleryBuybox.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImage.vue +1 -0
- package/app/components/public/cms/block/CmsBlockImageBubbleRow.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImageCover.vue +1 -0
- package/app/components/public/cms/block/CmsBlockImageFourColumn.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImageGallery.vue +1 -0
- package/app/components/public/cms/block/CmsBlockImageGalleryBig.vue +1 -0
- package/app/components/public/cms/block/CmsBlockImageHighlightRow.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImageSimpleGrid.vue +1 -0
- package/app/components/public/cms/block/CmsBlockImageSlider.vue +1 -0
- package/app/components/public/cms/block/CmsBlockImageText.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImageTextBubble.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImageTextCover.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImageTextGallery.vue +4 -12
- package/app/components/public/cms/block/CmsBlockImageTextRow.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImageThreeColumn.vue +1 -0
- package/app/components/public/cms/block/CmsBlockImageThreeCover.vue +4 -1
- package/app/components/public/cms/block/CmsBlockImageTwoColumn.vue +4 -1
- package/app/components/public/cms/block/CmsBlockProductDescriptionReviews.vue +1 -0
- package/app/components/public/cms/block/CmsBlockProductHeading.vue +1 -0
- package/app/components/public/cms/block/CmsBlockProductListing.vue +1 -0
- package/app/components/public/cms/block/CmsBlockProductThreeColumn.vue +1 -0
- package/app/components/public/cms/block/CmsBlockSidebarFilter.vue +1 -0
- package/app/components/public/cms/block/CmsBlockText.vue +1 -0
- package/app/components/public/cms/block/CmsBlockTextHero.vue +1 -0
- package/app/components/public/cms/block/CmsBlockTextOnImage.vue +2 -4
- package/app/components/public/cms/block/CmsBlockTextThreeColumn.vue +1 -0
- package/app/components/public/cms/block/CmsBlockTextTwoColumn.vue +4 -1
- package/app/components/public/cms/block/CmsBlockVimeoVideo.vue +1 -0
- package/app/components/public/cms/block/CmsBlockYoutubeVideo.vue +1 -0
- package/app/components/public/cms/element/CmsElementBuyBox.vue +90 -72
- package/app/components/public/cms/element/CmsElementCategoryNavigation.vue +14 -3
- package/app/components/public/cms/element/CmsElementCrossSelling.vue +3 -1
- package/app/components/public/cms/element/CmsElementCustomForm.vue +1 -0
- package/app/components/public/cms/element/CmsElementForm.vue +1 -0
- package/app/components/public/cms/element/CmsElementHtml.vue +0 -1
- package/app/components/public/cms/element/CmsElementImage.vue +15 -34
- package/app/components/public/cms/element/CmsElementImageGallery.vue +6 -2
- package/app/components/public/cms/element/CmsElementManufacturerLogo.vue +1 -0
- package/app/components/public/cms/element/CmsElementProductBox.vue +1 -0
- package/app/components/public/cms/element/CmsElementProductDescriptionReviews.vue +77 -29
- package/app/components/public/cms/element/CmsElementProductListing.vue +22 -7
- package/app/components/public/cms/element/CmsElementProductSlider.vue +6 -4
- package/app/components/public/cms/element/CmsElementText.vue +2 -0
- package/app/components/public/cms/element/CmsElementVimeoVideo.vue +1 -0
- package/app/components/public/cms/element/CmsElementYoutubeVideo.vue +1 -0
- package/app/components/public/cms/element/SwProductListingPagination.vue +8 -2
- package/app/components/public/cms/section/CmsSectionSidebar.vue +13 -8
- package/app/components/public/cms/skeleton/ProductCardSkeleton.vue +16 -5
- package/app/components/ui/SwitchButton.vue +53 -14
- package/app/components/ui/WishlistIcon.vue +8 -2
- package/app/composables/useImagePlaceholder.ts +2 -2
- package/app/composables/useLcpImagePreload.test.ts +1 -0
- package/app/composables/useLcpImagePreload.ts +12 -6
- package/app/composables/useTypedAppConfig.ts +16 -0
- package/app/helpers/cms/getImageSizes.test.ts +1 -0
- package/app/helpers/html-to-vue/ast.ts +1 -0
- package/app/helpers/html-to-vue/getOptionsFromNode.test.ts +1 -0
- package/app/helpers/html-to-vue/renderToHtml.ts +1 -0
- package/app/helpers/html-to-vue/renderer.ts +1 -0
- package/app/providers/shopware.test.ts +1 -0
- package/index.d.ts +37 -29
- package/nuxt.config.ts +5 -0
- package/package.json +22 -25
- package/app/plugins/unocss-runtime.client.ts +0 -23
- 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
|
|
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
|
|
61
|
-
|
|
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"
|
|
64
|
-
|
|
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="
|
|
67
|
-
|
|
68
|
-
|
|
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="
|
|
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
|
|
76
|
-
|
|
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:
|
|
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:
|
|
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
|
|
13
|
-
|
|
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 {
|
|
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 =
|
|
11
|
+
const appConfig = useTypedAppConfig();
|
|
12
12
|
const placeholderColor =
|
|
13
13
|
color || appConfig.imagePlaceholder?.color || "#543B95";
|
|
14
14
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import { useHead } from "#imports";
|
|
3
4
|
import type { Schemas } from "#shopware";
|
|
5
|
+
|
|
4
6
|
import { findFirstCmsImageUrl } from "../helpers/cms/findFirstCmsImageUrl";
|
|
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 =
|
|
17
|
+
const appConfig = useTypedAppConfig();
|
|
18
|
+
const isEnabled = Boolean(appConfig.lcpImagePreload);
|
|
15
19
|
|
|
16
20
|
const lcpImageHref = computed(() =>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
+
}
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopware/cms-base-layer",
|
|
3
|
-
"version": "
|
|
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.
|
|
35
|
+
"@iconify-json/carbon": "1.2.23",
|
|
36
36
|
"@nuxt/image": "2.0.0",
|
|
37
|
-
"@nuxt/kit": "4.
|
|
38
|
-
"@tresjs/cientos": "5.2
|
|
39
|
-
"@tresjs/nuxt": "^5.1
|
|
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.
|
|
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.
|
|
48
|
-
"
|
|
49
|
-
"vue": "3.5.27",
|
|
46
|
+
"three": "0.183.2",
|
|
47
|
+
"vue": "3.5.38",
|
|
50
48
|
"xss": "1.0.15",
|
|
51
|
-
"@shopware/
|
|
52
|
-
"@shopware/composables": "1.
|
|
53
|
-
"@shopware/
|
|
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
|
-
"@
|
|
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.
|
|
60
|
-
"@vitest/coverage-v8": "4.
|
|
61
|
-
"nuxt": "4.
|
|
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": "
|
|
64
|
-
"vitest": "4.
|
|
65
|
-
"vue-router": "
|
|
66
|
-
"vue-tsc": "3.
|
|
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": "
|
|
73
|
-
"lint:fix": "
|
|
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
|
-
});
|