spoko-design-system 0.8.3 → 0.8.4
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/.github/dependabot.yml +11 -11
- package/.github/todo.yml +3 -3
- package/.github/workflows/deploy.yml +39 -39
- package/.stackblitzrc +5 -5
- package/.vscode/extensions.json +5 -5
- package/.vscode/launch.json +11 -11
- package/.vscode/settings.json +5 -5
- package/LICENSE +21 -21
- package/README.md +114 -114
- package/astro-i18next.config.mjs +17 -17
- package/astro-i18next.config.ts +10 -10
- package/astro.config.mjs +86 -86
- package/dev-dist/sw.js +91 -91
- package/dev-dist/workbox-c676b6d3.js +3391 -3391
- package/icon.config.ts +309 -309
- package/index.ts +66 -66
- package/package.json +123 -123
- package/public/fonts/lg.svg +53 -53
- package/public/fonts/vwhead-bold-demo.html +549 -549
- package/public/fonts/vwhead-regular-demo.html +549 -549
- package/public/fonts/vwtext-bold-demo.html +549 -549
- package/public/fonts/vwtext-regular-demo.html +549 -549
- package/public/github.svg +3 -3
- package/public/grid_dot.svg +4 -4
- package/public/linkedin.svg +44 -44
- package/public/locales/en/translation.json +8 -8
- package/public/locales/pl/translation.json +8 -8
- package/public/make-scrollable-code-focusable.js +3 -3
- package/public/pagefind.yml +3 -3
- package/public/polo.blue.svg +29 -29
- package/public/spoko.space.svg +71 -71
- package/public/twitter.svg +46 -46
- package/renovate.json +6 -6
- package/sandbox.config.json +11 -11
- package/src/MyComponent.astro +8 -8
- package/src/components/Badge.vue +19 -19
- package/src/components/Badges.vue +21 -21
- package/src/components/Breadcrumbs.vue +91 -91
- package/src/components/Button.vue +101 -101
- package/src/components/ButtonCopy.astro +183 -183
- package/src/components/ButtonCopy.vue +36 -36
- package/src/components/Card.astro +27 -27
- package/src/components/Carousel.astro +26 -26
- package/src/components/Category/CategoriesCarousel.astro +101 -101
- package/src/components/Category/CategoryDetails.astro +169 -169
- package/src/components/Category/CategoryLink.vue +28 -28
- package/src/components/Category/CategorySidebarToggler.vue +9 -9
- package/src/components/Category/CategoryTile.astro +37 -37
- package/src/components/Category/CategoryViewToggler.astro +89 -89
- package/src/components/Category/SubCategoryLink.vue +19 -19
- package/src/components/Copyright.astro +12 -12
- package/src/components/Date.astro +7 -7
- package/src/components/Faq.astro +33 -33
- package/src/components/FaqItem.astro +80 -80
- package/src/components/FeaturesList.vue +37 -37
- package/src/components/FuckRussia.vue +62 -62
- package/src/components/HandDrive.astro +29 -29
- package/src/components/Header/Header.astro +210 -210
- package/src/components/Header/SkipToContent.astro +1 -1
- package/src/components/Headline.vue +48 -48
- package/src/components/Image.astro +30 -30
- package/src/components/LeftSidebar.astro +53 -53
- package/src/components/MainColors.vue +22 -22
- package/src/components/MainInput.vue +15 -15
- package/src/components/Modal.astro +27 -27
- package/src/components/PageContent.astro +5 -5
- package/src/components/PartNumber.vue +27 -27
- package/src/components/Post/PostCategories.astro +41 -41
- package/src/components/Post/PostCategories.vue +30 -30
- package/src/components/PostHeader.astro +103 -103
- package/src/components/PrCode.vue +141 -141
- package/src/components/Product/ProductButton.vue +18 -18
- package/src/components/Product/ProductCarousel.astro +35 -35
- package/src/components/Product/ProductEngineType.vue +42 -42
- package/src/components/Product/ProductImage.astro +40 -40
- package/src/components/Product/ProductLink.astro +101 -101
- package/src/components/Product/ProductLink.vue +59 -59
- package/src/components/Product/ProductLinkInfo.astro +37 -37
- package/src/components/Product/ProductNumber.astro +60 -60
- package/src/components/ProductCarousel.astro +38 -38
- package/src/components/ProductCodes.vue +39 -39
- package/src/components/ProductDetailName.vue +52 -52
- package/src/components/ProductDetailsList.vue +216 -197
- package/src/components/ProductTile.astro +48 -48
- package/src/components/Quote.vue +23 -23
- package/src/components/ReloadPrompt.astro +50 -50
- package/src/components/SlimBanner.vue +72 -72
- package/src/components/Table.vue +32 -32
- package/src/components/TableOfContents.astro +15 -15
- package/src/components/Translations.vue +23 -23
- package/src/components/flags/FlagPL.vue +3 -3
- package/src/components/flags/FlagUA.vue +2 -2
- package/src/components/layout/Container.astro +7 -7
- package/src/components/layout/Header.astro +80 -80
- package/src/config.ts +56 -56
- package/src/design.config.ts +98 -98
- package/src/env.d.ts +6 -6
- package/src/layouts/Layout.astro +61 -61
- package/src/layouts/MainLayout.astro +81 -81
- package/src/layouts/partials/FooterCommon.astro +4 -4
- package/src/layouts/partials/HeadCommon.astro +44 -44
- package/src/layouts/partials/HeadSEO.astro +41 -41
- package/src/pages/components/badges.mdx +57 -57
- package/src/pages/components/breadcrumbs.mdx +139 -139
- package/src/pages/components/buttons.mdx +360 -360
- package/src/pages/components/card.mdx +294 -294
- package/src/pages/components/carousel.mdx +62 -62
- package/src/pages/components/copyright.mdx +42 -42
- package/src/pages/components/details-list.mdx +115 -115
- package/src/pages/components/features-list.mdx +37 -37
- package/src/pages/components/flags.mdx +49 -49
- package/src/pages/components/fuck-russia.mdx +39 -39
- package/src/pages/components/hand-drive.mdx +38 -38
- package/src/pages/components/headline.mdx +152 -152
- package/src/pages/components/icons.astro +135 -135
- package/src/pages/components/image.mdx +513 -513
- package/src/pages/components/input.mdx +367 -367
- package/src/pages/components/jumbotron.mdx +359 -359
- package/src/pages/components/modal.mdx +64 -64
- package/src/pages/components/post-header.mdx +64 -64
- package/src/pages/components/pr-code.mdx +65 -65
- package/src/pages/components/product-number.mdx +58 -58
- package/src/pages/components/product-tile.mdx +51 -51
- package/src/pages/components/quote.mdx +33 -33
- package/src/pages/components/slimbanner.mdx +35 -35
- package/src/pages/components/table.mdx +108 -108
- package/src/pages/core/colors.mdx +10 -10
- package/src/pages/core/grid.mdx +89 -89
- package/src/pages/core/introduction.mdx +77 -77
- package/src/pages/core/shadows.astro +20 -20
- package/src/pages/core/typography.astro +49 -49
- package/src/pages/index.astro +133 -133
- package/src/pages/patterns/introduction.mdx +60 -60
- package/src/pwa.ts +12 -12
- package/src/styles/_variables.scss +70 -70
- package/src/styles/base/base.css +184 -184
- package/src/styles/base/grid.css +92 -92
- package/src/styles/base/typography.css +70 -70
- package/src/styles/content.css +73 -73
- package/src/styles/main.css +7 -7
- package/src/types/Product.ts +31 -31
- package/src/types/astro.d.ts +3 -3
- package/src/utils/product/getPriceFormatted.ts +15 -15
- package/src/utils/product/getProductChecklist.ts +17 -17
- package/src/utils/product/useFormatProductNumber.ts +41 -41
- package/src/utils/seo/getShorterDescription.ts +14 -14
- package/src/utils/text/formatDate.ts +5 -5
- package/src/utils/text/formatLocaleNumber.ts +6 -6
- package/src/utils/text/formatPad.ts +12 -12
- package/src/utils/text/getNumberFormatted.ts +33 -33
- package/src/utils/text/getTranslatedLink.ts +5 -5
- package/src/utils/text.ts +19 -19
- package/tailwind.config.cjs +8 -8
- package/tsconfig.json +28 -28
- package/uno-config/index.ts +259 -259
- package/uno-config/theme/breakpoints.ts +9 -9
- package/uno-config/theme/colors.ts +64 -64
- package/uno-config/theme/dimensions.ts +17 -17
- package/uno-config/theme/effects.ts +14 -14
- package/uno-config/theme/grid.ts +10 -10
- package/uno-config/theme/index.ts +28 -28
- package/uno-config/theme/shortcuts/buttons.ts +53 -53
- package/uno-config/theme/shortcuts/components.ts +123 -123
- package/uno-config/theme/shortcuts/index.ts +20 -20
- package/uno-config/theme/shortcuts/layout.ts +64 -64
- package/uno-config/theme/typography.ts +29 -29
- package/uno.config.ts +2 -2
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
---
|
|
2
|
-
import { Image } from 'astro:assets'
|
|
3
|
-
interface ImageObject {
|
|
4
|
-
src: string;
|
|
5
|
-
alt?: string;
|
|
6
|
-
height?: string | number;
|
|
7
|
-
width?: string | number;
|
|
8
|
-
loading?: 'lazy' | 'eager';
|
|
9
|
-
srcset?: string[];
|
|
10
|
-
class?: string;
|
|
11
|
-
index?: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const { imageObject } = Astro.props as { imageObject: ImageObject; };
|
|
15
|
-
|
|
16
|
-
let inputProps = {};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (imageObject.index && imageObject.index === 1) {
|
|
20
|
-
inputProps['data-pagefind-meta'] = 'image[src], image_alt[alt]';
|
|
21
|
-
imageObject.loading = 'eager'
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (imageObject.srcset && imageObject.srcset.length) {
|
|
25
|
-
inputProps['widths'] = imageObject.srcset
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
<Image
|
|
30
|
-
src={imageObject.src}
|
|
31
|
-
alt={imageObject.alt}
|
|
32
|
-
height={Number(imageObject.height)}
|
|
33
|
-
width={Number(imageObject.width)}
|
|
34
|
-
loading={imageObject.loading ? imageObject.loading : 'lazy'}
|
|
35
|
-
itemprop="image"
|
|
36
|
-
format="avif"
|
|
37
|
-
data-pagefind-index-attrs={imageObject.alt}
|
|
38
|
-
onerror="this.style.display='none';"
|
|
39
|
-
class={`product-image ${imageObject.class || ''}`}
|
|
40
|
-
{ ...inputProps}
|
|
1
|
+
---
|
|
2
|
+
import { Image } from 'astro:assets'
|
|
3
|
+
interface ImageObject {
|
|
4
|
+
src: string;
|
|
5
|
+
alt?: string;
|
|
6
|
+
height?: string | number;
|
|
7
|
+
width?: string | number;
|
|
8
|
+
loading?: 'lazy' | 'eager';
|
|
9
|
+
srcset?: string[];
|
|
10
|
+
class?: string;
|
|
11
|
+
index?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { imageObject } = Astro.props as { imageObject: ImageObject; };
|
|
15
|
+
|
|
16
|
+
let inputProps = {};
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if (imageObject.index && imageObject.index === 1) {
|
|
20
|
+
inputProps['data-pagefind-meta'] = 'image[src], image_alt[alt]';
|
|
21
|
+
imageObject.loading = 'eager'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (imageObject.srcset && imageObject.srcset.length) {
|
|
25
|
+
inputProps['widths'] = imageObject.srcset
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
<Image
|
|
30
|
+
src={imageObject.src}
|
|
31
|
+
alt={imageObject.alt}
|
|
32
|
+
height={Number(imageObject.height)}
|
|
33
|
+
width={Number(imageObject.width)}
|
|
34
|
+
loading={imageObject.loading ? imageObject.loading : 'lazy'}
|
|
35
|
+
itemprop="image"
|
|
36
|
+
format="avif"
|
|
37
|
+
data-pagefind-index-attrs={imageObject.alt}
|
|
38
|
+
onerror="this.style.display='none';"
|
|
39
|
+
class={`product-image ${imageObject.class || ''}`}
|
|
40
|
+
{ ...inputProps}
|
|
41
41
|
/>
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
---
|
|
2
|
-
import type { Product } from 'types/index';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
productId?: number;
|
|
6
|
-
productObject?: Product;
|
|
7
|
-
locale: string;
|
|
8
|
-
index: number;
|
|
9
|
-
bigTile?: boolean;
|
|
10
|
-
loading?: "eager" | "lazy";
|
|
11
|
-
isShopProduct?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const {
|
|
15
|
-
productId,
|
|
16
|
-
productObject,
|
|
17
|
-
bigTile,
|
|
18
|
-
locale,
|
|
19
|
-
index,
|
|
20
|
-
loading = "lazy",
|
|
21
|
-
isShopProduct = false,
|
|
22
|
-
} = Astro.props;
|
|
23
|
-
|
|
24
|
-
import { getProductById } from '@utils/product/getProductById';
|
|
25
|
-
import { getShopProductById } from '@utils/product/getShopProductById';
|
|
26
|
-
import { getProductUrl } from "@utils/product/getProductUrl";
|
|
27
|
-
import { getShopProductUrl } from "@utils/product/getShopProductUrl";
|
|
28
|
-
import { getProductTranslation } from "@utils/product/getProductTranslation";
|
|
29
|
-
import { getImageUrl } from '@utils/getImageUrl';
|
|
30
|
-
import i18next, { t } from "i18next";
|
|
31
|
-
import { ProductImage, ProductNumber, removeSemicolon, getPriceFormatted } from "spoko-design-system";
|
|
32
|
-
|
|
33
|
-
// Użycie productObject jeśli przekazane, inaczej pobranie produktu na podstawie productId
|
|
34
|
-
const product = productObject || (productId ? (isShopProduct ? await getShopProductById(productId) : await getProductById(productId)) : null);
|
|
35
|
-
|
|
36
|
-
// Określenie URL miniatury produktu
|
|
37
|
-
const thumb = product ? (
|
|
38
|
-
isShopProduct
|
|
39
|
-
? await getImageUrl(product.images?.[0]?.path || "", "SHOP")
|
|
40
|
-
: await getImageUrl(product.photo || "", `'ProductLink' ${product.number}`)
|
|
41
|
-
) : "";
|
|
42
|
-
|
|
43
|
-
// Tłumaczenie nazwy produktu jeśli dostępne
|
|
44
|
-
const productTranslation = i18next.exists(`parts.${product?.number}.name`)
|
|
45
|
-
? null
|
|
46
|
-
: productId ? await getProductTranslation(productId, product?.number || "") : null;
|
|
47
|
-
|
|
48
|
-
// const productName = product ? (
|
|
49
|
-
// isShopProduct
|
|
50
|
-
// ? (locale === "pl" ? product.name_pl : product.name_en)
|
|
51
|
-
// : productTranslation?.name || t(`parts.${product.number}.name`)
|
|
52
|
-
// ) : "";
|
|
53
|
-
|
|
54
|
-
const productName = product.name || 'NO NAME';
|
|
55
|
-
|
|
56
|
-
const nameFormatted = removeSemicolon(productName.toString());
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
{product && (
|
|
60
|
-
<div class={bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel'}>
|
|
61
|
-
{product.photo !== null && thumb ? (
|
|
62
|
-
<ProductImage
|
|
63
|
-
imagesApiUrl="https://api.polo.blue"
|
|
64
|
-
imageObject={{
|
|
65
|
-
src: thumb,
|
|
66
|
-
alt: productName,
|
|
67
|
-
height: '180',
|
|
68
|
-
width: '240',
|
|
69
|
-
loading
|
|
70
|
-
}}
|
|
71
|
-
/>
|
|
72
|
-
) : (
|
|
73
|
-
<img src="/1x1.png" class="bg-neutral-lightest/70" alt={productName} />
|
|
74
|
-
)}
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<div class={bigTile ? '' : 'sm:pl-4'}>
|
|
78
|
-
{product.price_pln && (
|
|
79
|
-
<p class="block mb-2 font-600 font-headbold text-5">
|
|
80
|
-
{getPriceFormatted(product)}
|
|
81
|
-
</p>
|
|
82
|
-
)}
|
|
83
|
-
|
|
84
|
-
<a
|
|
85
|
-
class="product-link--url"
|
|
86
|
-
href={isShopProduct ? getShopProductUrl(product.slug, locale) : getProductUrl(product.number, locale)}
|
|
87
|
-
itemprop="url"
|
|
88
|
-
title={product.number}
|
|
89
|
-
set:html={nameFormatted}
|
|
90
|
-
/>
|
|
91
|
-
|
|
92
|
-
<ProductNumber productNumber={product.number} copyDisabled={true} />
|
|
93
|
-
|
|
94
|
-
{index !== null && (
|
|
95
|
-
<>
|
|
96
|
-
<meta itemprop="position" content={index.toString()} />
|
|
97
|
-
<meta itemprop="name" content={nameFormatted} />
|
|
98
|
-
</>
|
|
99
|
-
)}
|
|
100
|
-
</div>
|
|
101
|
-
)}
|
|
1
|
+
---
|
|
2
|
+
import type { Product } from 'types/index';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
productId?: number;
|
|
6
|
+
productObject?: Product;
|
|
7
|
+
locale: string;
|
|
8
|
+
index: number;
|
|
9
|
+
bigTile?: boolean;
|
|
10
|
+
loading?: "eager" | "lazy";
|
|
11
|
+
isShopProduct?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
productId,
|
|
16
|
+
productObject,
|
|
17
|
+
bigTile,
|
|
18
|
+
locale,
|
|
19
|
+
index,
|
|
20
|
+
loading = "lazy",
|
|
21
|
+
isShopProduct = false,
|
|
22
|
+
} = Astro.props;
|
|
23
|
+
|
|
24
|
+
import { getProductById } from '@utils/product/getProductById';
|
|
25
|
+
import { getShopProductById } from '@utils/product/getShopProductById';
|
|
26
|
+
import { getProductUrl } from "@utils/product/getProductUrl";
|
|
27
|
+
import { getShopProductUrl } from "@utils/product/getShopProductUrl";
|
|
28
|
+
import { getProductTranslation } from "@utils/product/getProductTranslation";
|
|
29
|
+
import { getImageUrl } from '@utils/getImageUrl';
|
|
30
|
+
import i18next, { t } from "i18next";
|
|
31
|
+
import { ProductImage, ProductNumber, removeSemicolon, getPriceFormatted } from "spoko-design-system";
|
|
32
|
+
|
|
33
|
+
// Użycie productObject jeśli przekazane, inaczej pobranie produktu na podstawie productId
|
|
34
|
+
const product = productObject || (productId ? (isShopProduct ? await getShopProductById(productId) : await getProductById(productId)) : null);
|
|
35
|
+
|
|
36
|
+
// Określenie URL miniatury produktu
|
|
37
|
+
const thumb = product ? (
|
|
38
|
+
isShopProduct
|
|
39
|
+
? await getImageUrl(product.images?.[0]?.path || "", "SHOP")
|
|
40
|
+
: await getImageUrl(product.photo || "", `'ProductLink' ${product.number}`)
|
|
41
|
+
) : "";
|
|
42
|
+
|
|
43
|
+
// Tłumaczenie nazwy produktu jeśli dostępne
|
|
44
|
+
const productTranslation = i18next.exists(`parts.${product?.number}.name`)
|
|
45
|
+
? null
|
|
46
|
+
: productId ? await getProductTranslation(productId, product?.number || "") : null;
|
|
47
|
+
|
|
48
|
+
// const productName = product ? (
|
|
49
|
+
// isShopProduct
|
|
50
|
+
// ? (locale === "pl" ? product.name_pl : product.name_en)
|
|
51
|
+
// : productTranslation?.name || t(`parts.${product.number}.name`)
|
|
52
|
+
// ) : "";
|
|
53
|
+
|
|
54
|
+
const productName = product.name || 'NO NAME';
|
|
55
|
+
|
|
56
|
+
const nameFormatted = removeSemicolon(productName.toString());
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
{product && (
|
|
60
|
+
<div class={bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel'}>
|
|
61
|
+
{product.photo !== null && thumb ? (
|
|
62
|
+
<ProductImage
|
|
63
|
+
imagesApiUrl="https://api.polo.blue"
|
|
64
|
+
imageObject={{
|
|
65
|
+
src: thumb,
|
|
66
|
+
alt: productName,
|
|
67
|
+
height: '180',
|
|
68
|
+
width: '240',
|
|
69
|
+
loading
|
|
70
|
+
}}
|
|
71
|
+
/>
|
|
72
|
+
) : (
|
|
73
|
+
<img src="/1x1.png" class="bg-neutral-lightest/70" alt={productName} />
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div class={bigTile ? '' : 'sm:pl-4'}>
|
|
78
|
+
{product.price_pln && (
|
|
79
|
+
<p class="block mb-2 font-600 font-headbold text-5">
|
|
80
|
+
{getPriceFormatted(product)}
|
|
81
|
+
</p>
|
|
82
|
+
)}
|
|
83
|
+
|
|
84
|
+
<a
|
|
85
|
+
class="product-link--url"
|
|
86
|
+
href={isShopProduct ? getShopProductUrl(product.slug, locale) : getProductUrl(product.number, locale)}
|
|
87
|
+
itemprop="url"
|
|
88
|
+
title={product.number}
|
|
89
|
+
set:html={nameFormatted}
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
<ProductNumber productNumber={product.number} copyDisabled={true} />
|
|
93
|
+
|
|
94
|
+
{index !== null && (
|
|
95
|
+
<>
|
|
96
|
+
<meta itemprop="position" content={index.toString()} />
|
|
97
|
+
<meta itemprop="name" content={nameFormatted} />
|
|
98
|
+
</>
|
|
99
|
+
)}
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="product-link" itemscope itemtype="https://schema.org/Product">
|
|
3
|
-
<div :class="[
|
|
4
|
-
bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel'
|
|
5
|
-
]">
|
|
6
|
-
<!-- Slot na ProductImage z Astro -->
|
|
7
|
-
<slot name="image">
|
|
8
|
-
<img src="/1x1.png" class="bg-neutral-lightest/70" :alt="productName" />
|
|
9
|
-
</slot>
|
|
10
|
-
</div>
|
|
11
|
-
|
|
12
|
-
<div :class="[bigTile ? '' : 'sm:pl-4']">
|
|
13
|
-
<p v-if="price" class="block mb-2 font-600 font-headbold text-5">
|
|
14
|
-
{{ price }}
|
|
15
|
-
</p>
|
|
16
|
-
|
|
17
|
-
<a
|
|
18
|
-
class="product-link--url"
|
|
19
|
-
:href="url"
|
|
20
|
-
itemprop="url"
|
|
21
|
-
:title="productNumber"
|
|
22
|
-
v-html="nameFormatted"
|
|
23
|
-
/>
|
|
24
|
-
|
|
25
|
-
<ProductNumber
|
|
26
|
-
:productNumber="productNumber"
|
|
27
|
-
:copyDisabled="true"
|
|
28
|
-
/>
|
|
29
|
-
|
|
30
|
-
<template v-if="index !== null">
|
|
31
|
-
<meta itemprop="position" :content="index.toString()" />
|
|
32
|
-
<meta itemprop="name" :content="nameFormatted" />
|
|
33
|
-
</template>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
</template>
|
|
37
|
-
|
|
38
|
-
<script setup lang="ts">
|
|
39
|
-
import { computed } from 'vue'
|
|
40
|
-
import { ProductNumber } from 'spoko-design-system'
|
|
41
|
-
import { removeSemicolon } from 'spoko-design-system'
|
|
42
|
-
|
|
43
|
-
interface Props {
|
|
44
|
-
productName: string
|
|
45
|
-
productNumber: string
|
|
46
|
-
url: string
|
|
47
|
-
price?: string
|
|
48
|
-
bigTile?: boolean
|
|
49
|
-
index?: number
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
53
|
-
bigTile: false,
|
|
54
|
-
index: null,
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
const nameFormatted = computed(() => {
|
|
58
|
-
return removeSemicolon(props.productName.toString())
|
|
59
|
-
})
|
|
1
|
+
<template>
|
|
2
|
+
<div class="product-link" itemscope itemtype="https://schema.org/Product">
|
|
3
|
+
<div :class="[
|
|
4
|
+
bigTile ? 'product-link--big-tile' : 'product-thumb--plp product-thumb--carousel'
|
|
5
|
+
]">
|
|
6
|
+
<!-- Slot na ProductImage z Astro -->
|
|
7
|
+
<slot name="image">
|
|
8
|
+
<img src="/1x1.png" class="bg-neutral-lightest/70" :alt="productName" />
|
|
9
|
+
</slot>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div :class="[bigTile ? '' : 'sm:pl-4']">
|
|
13
|
+
<p v-if="price" class="block mb-2 font-600 font-headbold text-5">
|
|
14
|
+
{{ price }}
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<a
|
|
18
|
+
class="product-link--url"
|
|
19
|
+
:href="url"
|
|
20
|
+
itemprop="url"
|
|
21
|
+
:title="productNumber"
|
|
22
|
+
v-html="nameFormatted"
|
|
23
|
+
/>
|
|
24
|
+
|
|
25
|
+
<ProductNumber
|
|
26
|
+
:productNumber="productNumber"
|
|
27
|
+
:copyDisabled="true"
|
|
28
|
+
/>
|
|
29
|
+
|
|
30
|
+
<template v-if="index !== null">
|
|
31
|
+
<meta itemprop="position" :content="index.toString()" />
|
|
32
|
+
<meta itemprop="name" :content="nameFormatted" />
|
|
33
|
+
</template>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<script setup lang="ts">
|
|
39
|
+
import { computed } from 'vue'
|
|
40
|
+
import { ProductNumber } from 'spoko-design-system'
|
|
41
|
+
import { removeSemicolon } from 'spoko-design-system'
|
|
42
|
+
|
|
43
|
+
interface Props {
|
|
44
|
+
productName: string
|
|
45
|
+
productNumber: string
|
|
46
|
+
url: string
|
|
47
|
+
price?: string
|
|
48
|
+
bigTile?: boolean
|
|
49
|
+
index?: number
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
53
|
+
bigTile: false,
|
|
54
|
+
index: null,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const nameFormatted = computed(() => {
|
|
58
|
+
return removeSemicolon(props.productName.toString())
|
|
59
|
+
})
|
|
60
60
|
</script>
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
---
|
|
2
|
-
import type { Product } from '../../types/Product';
|
|
3
|
-
import ProductNumber from "./ProductNumber.astro"
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
product: Product;
|
|
7
|
-
nameFormatted: string;
|
|
8
|
-
price?: string;
|
|
9
|
-
url: string;
|
|
10
|
-
index?: number | null;
|
|
11
|
-
bigTile?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const { product, nameFormatted, price, url, index, bigTile } = Astro.props;
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
<div class={`flex flex-col ${bigTile ? '' : 'sm:pl-4'}`}>
|
|
19
|
-
{price && (
|
|
20
|
-
<p class="block mb-2 font-600 font-headbold text-5">
|
|
21
|
-
{price}
|
|
22
|
-
</p>
|
|
23
|
-
)}
|
|
24
|
-
<a
|
|
25
|
-
class="product-link--url"
|
|
26
|
-
href={url}
|
|
27
|
-
itemprop="url"
|
|
28
|
-
title={product.number}
|
|
29
|
-
set:html={nameFormatted}
|
|
30
|
-
/>
|
|
31
|
-
<ProductNumber productNumber={product.number} copyDisabled={true} />
|
|
32
|
-
{index !== null && (
|
|
33
|
-
<>
|
|
34
|
-
<meta itemprop="position" content={index} />
|
|
35
|
-
<meta itemprop="name" content={nameFormatted} />
|
|
36
|
-
</>
|
|
37
|
-
)}
|
|
1
|
+
---
|
|
2
|
+
import type { Product } from '../../types/Product';
|
|
3
|
+
import ProductNumber from "./ProductNumber.astro"
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
product: Product;
|
|
7
|
+
nameFormatted: string;
|
|
8
|
+
price?: string;
|
|
9
|
+
url: string;
|
|
10
|
+
index?: number | null;
|
|
11
|
+
bigTile?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { product, nameFormatted, price, url, index, bigTile } = Astro.props;
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<div class={`flex flex-col ${bigTile ? '' : 'sm:pl-4'}`}>
|
|
19
|
+
{price && (
|
|
20
|
+
<p class="block mb-2 font-600 font-headbold text-5">
|
|
21
|
+
{price}
|
|
22
|
+
</p>
|
|
23
|
+
)}
|
|
24
|
+
<a
|
|
25
|
+
class="product-link--url"
|
|
26
|
+
href={url}
|
|
27
|
+
itemprop="url"
|
|
28
|
+
title={product.number}
|
|
29
|
+
set:html={nameFormatted}
|
|
30
|
+
/>
|
|
31
|
+
<ProductNumber productNumber={product.number} copyDisabled={true} />
|
|
32
|
+
{index !== null && (
|
|
33
|
+
<>
|
|
34
|
+
<meta itemprop="position" content={index} />
|
|
35
|
+
<meta itemprop="name" content={nameFormatted} />
|
|
36
|
+
</>
|
|
37
|
+
)}
|
|
38
38
|
</div>
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
---
|
|
2
|
-
import ButtonCopy from '../ButtonCopy.astro';
|
|
3
|
-
import useFormatProductNumber from '../../utils/product/useFormatProductNumber';
|
|
4
|
-
|
|
5
|
-
const {
|
|
6
|
-
productNumber,
|
|
7
|
-
copyDisabled = false,
|
|
8
|
-
isPdp = false,
|
|
9
|
-
small = false,
|
|
10
|
-
big = false,
|
|
11
|
-
class: customClass = '',
|
|
12
|
-
buttonTexts = { copy: "Copy", copied: "Copied" },
|
|
13
|
-
} = Astro.props;
|
|
14
|
-
|
|
15
|
-
// Use formatted product number using a helper function
|
|
16
|
-
const { formattedNumbers: formatted } = useFormatProductNumber(productNumber);
|
|
17
|
-
|
|
18
|
-
// Define classes dynamically
|
|
19
|
-
const classNames = [
|
|
20
|
-
'product-number',
|
|
21
|
-
big ? 'text-4.5' : 'number-big',
|
|
22
|
-
customClass,
|
|
23
|
-
].filter(Boolean).join(' ');
|
|
24
|
-
|
|
25
|
-
const trackingClass = small ? 'tracking-wide' : 'tracking-tight';
|
|
26
|
-
|
|
27
|
-
// Determine wrapper tags based on `isPdp`
|
|
28
|
-
const ProductWrapper = isPdp ? 'h2' : 'div';
|
|
29
|
-
const FormattedWrapper = isPdp ? 'h3' : 'div';
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
{productNumber && formatted && (
|
|
33
|
-
<div class={classNames}>
|
|
34
|
-
<div class={['p-number', small ? 'w-full' : ''].join(' ')} itemprop="identifier">
|
|
35
|
-
<ProductWrapper id={productNumber} class="product-code">
|
|
36
|
-
{productNumber}
|
|
37
|
-
</ProductWrapper>
|
|
38
|
-
|
|
39
|
-
{big && (
|
|
40
|
-
<ButtonCopy
|
|
41
|
-
productNumber={productNumber}
|
|
42
|
-
texts={buttonTexts}
|
|
43
|
-
tooltipClasses=""
|
|
44
|
-
/>
|
|
45
|
-
)}
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<div class={['code-formatted', trackingClass].join(' ')}>
|
|
49
|
-
<div class="relative inset-0" data-pagefind-ignore>
|
|
50
|
-
{formatted.dot}
|
|
51
|
-
</div>
|
|
52
|
-
<div class="absolute inset-0" data-pagefind-ignore>
|
|
53
|
-
{formatted.dash}
|
|
54
|
-
</div>
|
|
55
|
-
<FormattedWrapper class="number-secondary">
|
|
56
|
-
{formatted.standard}
|
|
57
|
-
</FormattedWrapper>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
)}
|
|
1
|
+
---
|
|
2
|
+
import ButtonCopy from '../ButtonCopy.astro';
|
|
3
|
+
import useFormatProductNumber from '../../utils/product/useFormatProductNumber';
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
productNumber,
|
|
7
|
+
copyDisabled = false,
|
|
8
|
+
isPdp = false,
|
|
9
|
+
small = false,
|
|
10
|
+
big = false,
|
|
11
|
+
class: customClass = '',
|
|
12
|
+
buttonTexts = { copy: "Copy", copied: "Copied" },
|
|
13
|
+
} = Astro.props;
|
|
14
|
+
|
|
15
|
+
// Use formatted product number using a helper function
|
|
16
|
+
const { formattedNumbers: formatted } = useFormatProductNumber(productNumber);
|
|
17
|
+
|
|
18
|
+
// Define classes dynamically
|
|
19
|
+
const classNames = [
|
|
20
|
+
'product-number',
|
|
21
|
+
big ? 'text-4.5' : 'number-big',
|
|
22
|
+
customClass,
|
|
23
|
+
].filter(Boolean).join(' ');
|
|
24
|
+
|
|
25
|
+
const trackingClass = small ? 'tracking-wide' : 'tracking-tight';
|
|
26
|
+
|
|
27
|
+
// Determine wrapper tags based on `isPdp`
|
|
28
|
+
const ProductWrapper = isPdp ? 'h2' : 'div';
|
|
29
|
+
const FormattedWrapper = isPdp ? 'h3' : 'div';
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
{productNumber && formatted && (
|
|
33
|
+
<div class={classNames}>
|
|
34
|
+
<div class={['p-number', small ? 'w-full' : ''].join(' ')} itemprop="identifier">
|
|
35
|
+
<ProductWrapper id={productNumber} class="product-code">
|
|
36
|
+
{productNumber}
|
|
37
|
+
</ProductWrapper>
|
|
38
|
+
|
|
39
|
+
{big && (
|
|
40
|
+
<ButtonCopy
|
|
41
|
+
productNumber={productNumber}
|
|
42
|
+
texts={buttonTexts}
|
|
43
|
+
tooltipClasses=""
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class={['code-formatted', trackingClass].join(' ')}>
|
|
49
|
+
<div class="relative inset-0" data-pagefind-ignore>
|
|
50
|
+
{formatted.dot}
|
|
51
|
+
</div>
|
|
52
|
+
<div class="absolute inset-0" data-pagefind-ignore>
|
|
53
|
+
{formatted.dash}
|
|
54
|
+
</div>
|
|
55
|
+
<FormattedWrapper class="number-secondary">
|
|
56
|
+
{formatted.standard}
|
|
57
|
+
</FormattedWrapper>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
)}
|