@zalify/storefront-kit 0.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.
- package/LICENSE.md +49 -0
- package/README.md +63 -0
- package/dist/commerce/countdown.d.ts +18 -0
- package/dist/commerce/countdown.js +28 -0
- package/dist/commerce/events.d.ts +29 -0
- package/dist/commerce/events.js +14 -0
- package/dist/commerce/facets.d.ts +27 -0
- package/dist/commerce/facets.js +71 -0
- package/dist/commerce/index.d.ts +11 -0
- package/dist/commerce/index.js +11 -0
- package/dist/commerce/money.d.ts +51 -0
- package/dist/commerce/money.js +83 -0
- package/dist/commerce/product.d.ts +102 -0
- package/dist/commerce/product.js +93 -0
- package/dist/editor/frame.d.ts +57 -0
- package/dist/editor/frame.js +241 -0
- package/dist/editor/host.d.ts +31 -0
- package/dist/editor/host.js +67 -0
- package/dist/editor/index.d.ts +9 -0
- package/dist/editor/index.js +9 -0
- package/dist/react/adapter.d.ts +49 -0
- package/dist/react/adapter.js +23 -0
- package/dist/react/blocks/_box.d.ts +10 -0
- package/dist/react/blocks/_box.js +17 -0
- package/dist/react/blocks/_slide.d.ts +24 -0
- package/dist/react/blocks/_slide.js +21 -0
- package/dist/react/blocks/_video-card.d.ts +11 -0
- package/dist/react/blocks/_video-card.js +39 -0
- package/dist/react/blocks/accordion.d.ts +12 -0
- package/dist/react/blocks/accordion.js +5 -0
- package/dist/react/blocks/button.d.ts +10 -0
- package/dist/react/blocks/button.js +15 -0
- package/dist/react/blocks/countdown.d.ts +9 -0
- package/dist/react/blocks/countdown.js +64 -0
- package/dist/react/blocks/custom-liquid.d.ts +11 -0
- package/dist/react/blocks/custom-liquid.js +4 -0
- package/dist/react/blocks/group.d.ts +9 -0
- package/dist/react/blocks/group.js +8 -0
- package/dist/react/blocks/image.d.ts +8 -0
- package/dist/react/blocks/image.js +7 -0
- package/dist/react/blocks/message.d.ts +14 -0
- package/dist/react/blocks/message.js +5 -0
- package/dist/react/blocks/quote.d.ts +9 -0
- package/dist/react/blocks/quote.js +5 -0
- package/dist/react/blocks/spacer.d.ts +8 -0
- package/dist/react/blocks/spacer.js +5 -0
- package/dist/react/blocks/story.d.ts +17 -0
- package/dist/react/blocks/story.js +7 -0
- package/dist/react/blocks/text.d.ts +9 -0
- package/dist/react/blocks/text.js +5 -0
- package/dist/react/blocks/video.d.ts +17 -0
- package/dist/react/blocks/video.js +56 -0
- package/dist/react/components/Facets.d.ts +21 -0
- package/dist/react/components/Facets.js +220 -0
- package/dist/react/components/Icon.d.ts +12 -0
- package/dist/react/components/Icon.js +66 -0
- package/dist/react/components/PaymentIcons.d.ts +5 -0
- package/dist/react/components/PaymentIcons.generated.d.ts +22 -0
- package/dist/react/components/PaymentIcons.generated.js +21 -0
- package/dist/react/components/PaymentIcons.js +18 -0
- package/dist/react/components/Price.d.ts +24 -0
- package/dist/react/components/Price.js +9 -0
- package/dist/react/components/ProductBadges.d.ts +24 -0
- package/dist/react/components/ProductBadges.js +57 -0
- package/dist/react/components/ProductCard.d.ts +17 -0
- package/dist/react/components/ProductCard.js +202 -0
- package/dist/react/components/Rating.d.ts +11 -0
- package/dist/react/components/Rating.js +35 -0
- package/dist/react/components/SwatchStyle.d.ts +23 -0
- package/dist/react/components/SwatchStyle.js +22 -0
- package/dist/react/components/VideoModal.d.ts +55 -0
- package/dist/react/components/VideoModal.js +102 -0
- package/dist/react/engine/CssVariables.d.ts +1 -0
- package/dist/react/engine/CssVariables.js +105 -0
- package/dist/react/engine/context.d.ts +43 -0
- package/dist/react/engine/context.js +45 -0
- package/dist/react/engine/fonts.d.ts +15 -0
- package/dist/react/engine/fonts.js +33 -0
- package/dist/react/engine/images.d.ts +24 -0
- package/dist/react/engine/images.js +40 -0
- package/dist/react/engine/render.d.ts +29 -0
- package/dist/react/engine/render.js +87 -0
- package/dist/react/engine/settings.d.ts +8 -0
- package/dist/react/engine/settings.js +68 -0
- package/dist/react/engine/store.d.ts +64 -0
- package/dist/react/engine/store.js +42 -0
- package/dist/react/engine/translate.d.ts +7 -0
- package/dist/react/engine/translate.js +33 -0
- package/dist/react/engine/types.d.ts +128 -0
- package/dist/react/engine/types.js +1 -0
- package/dist/react/index.d.ts +38 -0
- package/dist/react/index.js +39 -0
- package/dist/react/registries.d.ts +10 -0
- package/dist/react/registries.js +68 -0
- package/dist/react/registries.server.d.ts +2 -0
- package/dist/react/registries.server.js +98 -0
- package/dist/react/sections/404.d.ts +10 -0
- package/dist/react/sections/404.js +10 -0
- package/dist/react/sections/announcement-bar.d.ts +14 -0
- package/dist/react/sections/announcement-bar.js +84 -0
- package/dist/react/sections/article.d.ts +17 -0
- package/dist/react/sections/article.js +31 -0
- package/dist/react/sections/contact-form.d.ts +16 -0
- package/dist/react/sections/contact-form.js +8 -0
- package/dist/react/sections/custom-liquid.d.ts +14 -0
- package/dist/react/sections/custom-liquid.js +7 -0
- package/dist/react/sections/custom-section.d.ts +14 -0
- package/dist/react/sections/custom-section.js +9 -0
- package/dist/react/sections/featured-collection.d.ts +10 -0
- package/dist/react/sections/featured-collection.js +23 -0
- package/dist/react/sections/hero.d.ts +6 -0
- package/dist/react/sections/hero.js +35 -0
- package/dist/react/sections/image-with-text.d.ts +13 -0
- package/dist/react/sections/image-with-text.js +9 -0
- package/dist/react/sections/multicolumn.d.ts +15 -0
- package/dist/react/sections/multicolumn.js +8 -0
- package/dist/react/sections/page.d.ts +13 -0
- package/dist/react/sections/page.js +11 -0
- package/dist/react/sections/password.d.ts +15 -0
- package/dist/react/sections/password.js +9 -0
- package/dist/react/sections/rich-text.d.ts +12 -0
- package/dist/react/sections/rich-text.js +7 -0
- package/dist/react/sections/stories.d.ts +18 -0
- package/dist/react/sections/stories.js +10 -0
- package/dist/react/sections/video-bubble.d.ts +13 -0
- package/dist/react/sections/video-bubble.js +54 -0
- package/dist/react/sections/video-carousel.d.ts +19 -0
- package/dist/react/sections/video-carousel.js +9 -0
- package/dist/react/server.d.ts +7 -0
- package/dist/react/server.js +42 -0
- package/dist/schemas/bridge.d.ts +98 -0
- package/dist/schemas/bridge.js +50 -0
- package/dist/schemas/data.d.ts +54 -0
- package/dist/schemas/data.js +22 -0
- package/dist/schemas/index.d.ts +14 -0
- package/dist/schemas/index.js +14 -0
- package/dist/schemas/manifest.d.ts +63 -0
- package/dist/schemas/manifest.js +32 -0
- package/dist/schemas/schema.d.ts +159 -0
- package/dist/schemas/schema.js +129 -0
- package/dist/schemas/validate.d.ts +22 -0
- package/dist/schemas/validate.js +199 -0
- package/package.json +84 -0
- package/src/commerce/countdown.ts +38 -0
- package/src/commerce/events.ts +43 -0
- package/src/commerce/facets.ts +88 -0
- package/src/commerce/index.ts +11 -0
- package/src/commerce/money.ts +120 -0
- package/src/commerce/product.ts +177 -0
- package/src/editor/frame.ts +305 -0
- package/src/editor/host.ts +101 -0
- package/src/editor/index.ts +9 -0
- package/src/react/adapter.tsx +83 -0
- package/src/react/blocks/_box.tsx +37 -0
- package/src/react/blocks/_slide.tsx +96 -0
- package/src/react/blocks/_video-card.tsx +131 -0
- package/src/react/blocks/accordion.tsx +33 -0
- package/src/react/blocks/button.tsx +36 -0
- package/src/react/blocks/countdown.tsx +105 -0
- package/src/react/blocks/custom-liquid.tsx +21 -0
- package/src/react/blocks/group.tsx +32 -0
- package/src/react/blocks/image.tsx +29 -0
- package/src/react/blocks/message.tsx +28 -0
- package/src/react/blocks/quote.tsx +24 -0
- package/src/react/blocks/spacer.tsx +17 -0
- package/src/react/blocks/story.tsx +40 -0
- package/src/react/blocks/text.tsx +24 -0
- package/src/react/blocks/video.tsx +132 -0
- package/src/react/components/Facets.tsx +424 -0
- package/src/react/components/Icon.tsx +96 -0
- package/src/react/components/PaymentIcons.generated.ts +24 -0
- package/src/react/components/PaymentIcons.tsx +27 -0
- package/src/react/components/Price.tsx +72 -0
- package/src/react/components/ProductBadges.tsx +95 -0
- package/src/react/components/ProductCard.tsx +417 -0
- package/src/react/components/Rating.tsx +59 -0
- package/src/react/components/SwatchStyle.tsx +50 -0
- package/src/react/components/VideoModal.tsx +236 -0
- package/src/react/engine/CssVariables.tsx +142 -0
- package/src/react/engine/context.tsx +108 -0
- package/src/react/engine/fonts.ts +42 -0
- package/src/react/engine/images.tsx +58 -0
- package/src/react/engine/render.tsx +190 -0
- package/src/react/engine/settings.ts +89 -0
- package/src/react/engine/store.ts +103 -0
- package/src/react/engine/translate.ts +40 -0
- package/src/react/engine/types.ts +142 -0
- package/src/react/index.ts +78 -0
- package/src/react/registries.server.ts +110 -0
- package/src/react/registries.ts +80 -0
- package/src/react/sections/404.tsx +37 -0
- package/src/react/sections/announcement-bar.tsx +170 -0
- package/src/react/sections/article.tsx +97 -0
- package/src/react/sections/contact-form.tsx +104 -0
- package/src/react/sections/custom-liquid.tsx +39 -0
- package/src/react/sections/custom-section.tsx +44 -0
- package/src/react/sections/featured-collection.tsx +89 -0
- package/src/react/sections/hero.tsx +84 -0
- package/src/react/sections/image-with-text.tsx +61 -0
- package/src/react/sections/multicolumn.tsx +46 -0
- package/src/react/sections/page.tsx +43 -0
- package/src/react/sections/password.tsx +60 -0
- package/src/react/sections/rich-text.tsx +37 -0
- package/src/react/sections/stories.tsx +51 -0
- package/src/react/sections/video-bubble.tsx +145 -0
- package/src/react/sections/video-carousel.tsx +57 -0
- package/src/react/server.ts +60 -0
- package/src/schemas/bridge.ts +143 -0
- package/src/schemas/data.ts +72 -0
- package/src/schemas/index.ts +14 -0
- package/src/schemas/manifest.ts +85 -0
- package/src/schemas/schema.ts +287 -0
- package/src/schemas/validate.ts +302 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
const ICONS = {
|
|
3
|
+
'icon-account': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none" slot="signed-out-avatar">
|
|
4
|
+
<circle cx="10" cy="6.5" r="2.75" stroke="currentColor" stroke-width="var(--icon-stroke-width)" />
|
|
5
|
+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
|
6
|
+
stroke-width="var(--icon-stroke-width)"
|
|
7
|
+
d="m5.172 14.591-.437.786a.588.588 0 0 0 .514.873h9.502a.588.588 0 0 0 .514-.873l-.437-.786a5.523 5.523 0 0 0-9.656 0" />
|
|
8
|
+
</svg>`,
|
|
9
|
+
'icon-cart': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none">
|
|
10
|
+
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
|
11
|
+
stroke-width="var(--icon-stroke-width)"
|
|
12
|
+
d="M3.392 6.875h13.216v8.016c0 .567-.224 1.112-.624 1.513-.4.402-.941.627-1.506.627H5.522a2.13 2.13 0 0 1-1.506-.627 2.15 2.15 0 0 1-.624-1.513zM8.818 2.969h2.333c.618 0 1.211.247 1.649.686a2.35 2.35 0 0 1 .683 1.658v1.562H6.486V5.313c0-.622.246-1.218.683-1.658a2.33 2.33 0 0 1 1.65-.686" />
|
|
13
|
+
</svg>`,
|
|
14
|
+
'icon-chevron-left': `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
|
15
|
+
<path d="M14.5 5.5L8 12l6.5 6.5"/>
|
|
16
|
+
</svg>`,
|
|
17
|
+
'icon-chevron-right': `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
|
18
|
+
<path d="M9.5 5.5L16 12l-6.5 6.5"/>
|
|
19
|
+
</svg>`,
|
|
20
|
+
'icon-close': `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
|
21
|
+
<path d="M6 6l12 12M18 6L6 18"/>
|
|
22
|
+
</svg>`,
|
|
23
|
+
'icon-facebook': `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true">
|
|
24
|
+
<path stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"/>
|
|
25
|
+
</svg>`,
|
|
26
|
+
'icon-instagram': `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true">
|
|
27
|
+
<rect x="2.5" y="2.5" width="19" height="19" rx="5" stroke="currentColor" stroke-width="1.5"/>
|
|
28
|
+
<circle cx="12" cy="12" r="4.25" stroke="currentColor" stroke-width="1.5"/>
|
|
29
|
+
<circle cx="17.3" cy="6.7" r="1.1" fill="currentColor"/>
|
|
30
|
+
</svg>`,
|
|
31
|
+
'icon-pause': `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
|
32
|
+
<path d="M5.5 3.5v9M10.5 3.5v9"/>
|
|
33
|
+
</svg>`,
|
|
34
|
+
'icon-pinterest': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
|
35
|
+
<path fill="currentColor" d="M12.017 0C5.396 0 .029 5.367.029 11.987c0 5.079 3.158 9.417 7.618 11.162-.105-.949-.199-2.403.041-3.439.219-.937 1.406-5.957 1.406-5.957s-.359-.72-.359-1.781c0-1.663.967-2.911 2.168-2.911 1.024 0 1.518.769 1.518 1.688 0 1.029-.653 2.567-.992 3.992-.285 1.193.6 2.165 1.775 2.165 2.128 0 3.768-2.245 3.768-5.487 0-2.861-2.063-4.869-5.008-4.869-3.41 0-5.409 2.562-5.409 5.199 0 1.033.394 2.143.889 2.741.099.12.112.225.085.345-.09.375-.293 1.199-.334 1.363-.053.225-.172.271-.401.165-1.495-.69-2.433-2.878-2.433-4.646 0-3.776 2.748-7.252 7.92-7.252 4.158 0 7.392 2.967 7.392 6.923 0 4.135-2.607 7.462-6.233 7.462-1.214 0-2.354-.629-2.758-1.379l-.749 2.848c-.269 1.045-1.004 2.352-1.498 3.146 1.123.345 2.306.535 3.55.535 6.607 0 11.985-5.365 11.985-11.987C23.97 5.39 18.592.026 11.985.026z"/>
|
|
36
|
+
</svg>`,
|
|
37
|
+
'icon-play': `<svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
|
38
|
+
<path d="M5 3.2v9.6c0 .4.45.65.8.43l7-4.8a.5.5 0 0 0 0-.86l-7-4.8A.5.5 0 0 0 5 3.2Z"/>
|
|
39
|
+
</svg>`,
|
|
40
|
+
'icon-search': `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16" aria-hidden="true">
|
|
41
|
+
<path stroke-linejoin="round" stroke-linecap="round" stroke="currentColor" d="M3.12939 3.15747C4.90196 1.47122 7.63947 1.37352 9.36572 2.98853L9.52979 3.15063C11.2696 4.96073 11.2614 7.81258 9.54443 9.53247C7.78203 11.2161 5.03421 11.2591 3.29541 9.69653L3.13037 9.54028C1.40138 7.73421 1.40065 4.96368 3.12939 3.15747Z"/>
|
|
42
|
+
<path stroke-linejoin="round" stroke-linecap="round" stroke="currentColor" d="M9.66699 9.66675L13.3337 13.3334"/>
|
|
43
|
+
</svg>`,
|
|
44
|
+
'icon-star': `<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
|
|
45
|
+
<path d="M12 2.5l2.95 6.32 6.93.84-5.11 4.75 1.34 6.84L12 17.85l-6.11 3.4 1.34-6.84-5.11-4.75 6.93-.84z"/>
|
|
46
|
+
</svg>`,
|
|
47
|
+
'icon-tiktok': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
|
48
|
+
<path fill="currentColor" d="M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z"/>
|
|
49
|
+
</svg>`,
|
|
50
|
+
'icon-x': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
|
51
|
+
<path fill="currentColor" d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"/>
|
|
52
|
+
</svg>`,
|
|
53
|
+
'icon-youtube': `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true">
|
|
54
|
+
<path stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" d="M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 0 0-1.94 2A29 29 0 0 0 1 11.75a29 29 0 0 0 .46 5.33A2.78 2.78 0 0 0 3.4 19c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 0 0 1.94-2 29 29 0 0 0 .46-5.25 29 29 0 0 0-.46-5.33z"/>
|
|
55
|
+
<path fill="currentColor" d="M9.75 15.02 15.5 11.75 9.75 8.48z"/>
|
|
56
|
+
</svg>`,
|
|
57
|
+
};
|
|
58
|
+
export function Icon({ name, className }) {
|
|
59
|
+
const svg = ICONS[name];
|
|
60
|
+
if (!svg)
|
|
61
|
+
return null;
|
|
62
|
+
if (!className) {
|
|
63
|
+
return _jsx("span", { dangerouslySetInnerHTML: { __html: svg }, style: { display: 'contents' } });
|
|
64
|
+
}
|
|
65
|
+
return (_jsx("span", { className: className, style: { display: 'contents' }, dangerouslySetInnerHTML: { __html: svg } }));
|
|
66
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED by scripts/payment-icons.mjs — do not edit.
|
|
3
|
+
* Official marks vendored from activemerchant/payment_icons (the
|
|
4
|
+
* source Shopify's `payment_type_svg_tag` serves), verbatim except
|
|
5
|
+
* for the injected payment-icons__icon class.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PAYMENT_ICONS: {
|
|
8
|
+
american_express: string;
|
|
9
|
+
apple_pay: string;
|
|
10
|
+
diners_club: string;
|
|
11
|
+
discover: string;
|
|
12
|
+
google_pay: string;
|
|
13
|
+
jcb: string;
|
|
14
|
+
klarna: string;
|
|
15
|
+
maestro: string;
|
|
16
|
+
master: string;
|
|
17
|
+
paypal: string;
|
|
18
|
+
shopify_pay: string;
|
|
19
|
+
unionpay: string;
|
|
20
|
+
visa: string;
|
|
21
|
+
};
|
|
22
|
+
export type PaymentType = keyof typeof PAYMENT_ICONS;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED by scripts/payment-icons.mjs — do not edit.
|
|
3
|
+
* Official marks vendored from activemerchant/payment_icons (the
|
|
4
|
+
* source Shopify's `payment_type_svg_tag` serves), verbatim except
|
|
5
|
+
* for the injected payment-icons__icon class.
|
|
6
|
+
*/
|
|
7
|
+
export const PAYMENT_ICONS = {
|
|
8
|
+
american_express: `<svg class="payment-icons__icon" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 38 24" width="38" height="24" fill="none" aria-labelledby="pi-american_express"><title id="pi-american_express">American Express</title><rect x=".5" y=".5" width="37" height="23" rx="2.5" stroke="#000" stroke-opacity=".07" fill="none"/><path d="M35 0H3C1.3 0 0 1.3 0 3V21C0 22.7 1.4 24 3 24H35C36.7 24 38 22.7 38 21V3C38 1.3 36.6 0 35 0Z" fill="#0071CE" style="fill:#0071CE;fill:color(display-p3 0.0000 0.4431 0.8078);fill-opacity:1;"/><path d="M3 0.5H35C36.3348 0.5 37.5 1.58692 37.5 3V21C37.5 22.4239 36.4239 23.5 35 23.5H3C1.66524 23.5 0.5 22.4131 0.5 21V3C0.5 1.57614 1.57614 0.5 3 0.5Z" stroke="black" stroke-opacity="0.07" style="stroke:black;stroke-opacity:0.07;"/><path d="M25.8662 6.33203V3H31L31.8662 5.5332L32.7334 3H37V14.2002H36.7998L34.8672 16.2656L36.7998 18.3594H37V21.2666H33.5996L31.9336 19.3994L30.2002 21.2666H19.4668V12.666H16L20.2666 3H24.4004L25.8662 6.33203ZM20.5996 20.2656H27V18.5322H22.666V17.3994H26.8662V15.666H22.666V14.5322H27V12.7988H20.5996V20.2656ZM30.5332 16.5322L27 20.2656H29.5996L31.8662 17.8662L34.0664 20.2656H36.7324L33.1992 16.4658L36.7324 12.7988H34.1328L31.8662 15.1992L29.7324 12.7988H27L30.5332 16.5322ZM17.666 11.7324H19.9326L20.5332 10.1992H23.999L24.666 11.7324H26.999L23.666 4.19922H20.999L17.666 11.7324ZM33.5996 4.19922L31.9326 8.86621L30.1992 4.19922H27V11.666H29.0664V6.39941L31 11.666H32.7998L34.7324 6.39941V11.666H36.7324V4.13281L33.5996 4.19922ZM23.2656 8.46582H21.2656L22.2656 5.99902L23.2656 8.46582Z" fill="white" style="fill:white;fill-opacity:1;"/></svg>`,
|
|
9
|
+
apple_pay: `<svg class="payment-icons__icon" version="1.1" xmlns="http://www.w3.org/2000/svg" role="img" x="0" y="0" width="38" height="24" viewBox="0 0 165.521 105.965" xml:space="preserve" aria-labelledby="pi-apple_pay"><title id="pi-apple_pay">Apple Pay</title><path fill="#000" d="M150.698 0H14.823c-.566 0-1.133 0-1.698.003-.477.004-.953.009-1.43.022-1.039.028-2.087.09-3.113.274a10.51 10.51 0 0 0-2.958.975 9.932 9.932 0 0 0-4.35 4.35 10.463 10.463 0 0 0-.975 2.96C.113 9.611.052 10.658.024 11.696a70.22 70.22 0 0 0-.022 1.43C0 13.69 0 14.256 0 14.823v76.318c0 .567 0 1.132.002 1.699.003.476.009.953.022 1.43.028 1.036.09 2.084.275 3.11a10.46 10.46 0 0 0 .974 2.96 9.897 9.897 0 0 0 1.83 2.52 9.874 9.874 0 0 0 2.52 1.83c.947.483 1.917.79 2.96.977 1.025.183 2.073.245 3.112.273.477.011.953.017 1.43.02.565.004 1.132.004 1.698.004h135.875c.565 0 1.132 0 1.697-.004.476-.002.952-.009 1.431-.02 1.037-.028 2.085-.09 3.113-.273a10.478 10.478 0 0 0 2.958-.977 9.955 9.955 0 0 0 4.35-4.35c.483-.947.789-1.917.974-2.96.186-1.026.246-2.074.274-3.11.013-.477.02-.954.022-1.43.004-.567.004-1.132.004-1.699V14.824c0-.567 0-1.133-.004-1.699a63.067 63.067 0 0 0-.022-1.429c-.028-1.038-.088-2.085-.274-3.112a10.4 10.4 0 0 0-.974-2.96 9.94 9.94 0 0 0-4.35-4.35A10.52 10.52 0 0 0 156.939.3c-1.028-.185-2.076-.246-3.113-.274a71.417 71.417 0 0 0-1.431-.022C151.83 0 151.263 0 150.698 0z" /><path fill="#FFF" d="M150.698 3.532l1.672.003c.452.003.905.008 1.36.02.793.022 1.719.065 2.583.22.75.135 1.38.34 1.984.648a6.392 6.392 0 0 1 2.804 2.807c.306.6.51 1.226.645 1.983.154.854.197 1.783.218 2.58.013.45.019.9.02 1.36.005.557.005 1.113.005 1.671v76.318c0 .558 0 1.114-.004 1.682-.002.45-.008.9-.02 1.35-.022.796-.065 1.725-.221 2.589a6.855 6.855 0 0 1-.645 1.975 6.397 6.397 0 0 1-2.808 2.807c-.6.306-1.228.511-1.971.645-.881.157-1.847.2-2.574.22-.457.01-.912.017-1.379.019-.555.004-1.113.004-1.669.004H14.801c-.55 0-1.1 0-1.66-.004a74.993 74.993 0 0 1-1.35-.018c-.744-.02-1.71-.064-2.584-.22a6.938 6.938 0 0 1-1.986-.65 6.337 6.337 0 0 1-1.622-1.18 6.355 6.355 0 0 1-1.178-1.623 6.935 6.935 0 0 1-.646-1.985c-.156-.863-.2-1.788-.22-2.578a66.088 66.088 0 0 1-.02-1.355l-.003-1.327V14.474l.002-1.325a66.7 66.7 0 0 1 .02-1.357c.022-.792.065-1.717.222-2.587a6.924 6.924 0 0 1 .646-1.981c.304-.598.7-1.144 1.18-1.623a6.386 6.386 0 0 1 1.624-1.18 6.96 6.96 0 0 1 1.98-.646c.865-.155 1.792-.198 2.586-.22.452-.012.905-.017 1.354-.02l1.677-.003h135.875" /><g><g><path fill="#000" d="M43.508 35.77c1.404-1.755 2.356-4.112 2.105-6.52-2.054.102-4.56 1.355-6.012 3.112-1.303 1.504-2.456 3.959-2.156 6.266 2.306.2 4.61-1.152 6.063-2.858" /><path fill="#000" d="M45.587 39.079c-3.35-.2-6.196 1.9-7.795 1.9-1.6 0-4.049-1.8-6.698-1.751-3.447.05-6.645 2-8.395 5.1-3.598 6.2-.95 15.4 2.55 20.45 1.699 2.5 3.747 5.25 6.445 5.151 2.55-.1 3.549-1.65 6.647-1.65 3.097 0 3.997 1.65 6.696 1.6 2.798-.05 4.548-2.5 6.247-5 1.95-2.85 2.747-5.6 2.797-5.75-.05-.05-5.396-2.101-5.446-8.251-.05-5.15 4.198-7.6 4.398-7.751-2.399-3.548-6.147-3.948-7.447-4.048" /></g><g><path fill="#000" d="M78.973 32.11c7.278 0 12.347 5.017 12.347 12.321 0 7.33-5.173 12.373-12.529 12.373h-8.058V69.62h-5.822V32.11h14.062zm-8.24 19.807h6.68c5.07 0 7.954-2.729 7.954-7.46 0-4.73-2.885-7.434-7.928-7.434h-6.706v14.894z" /><path fill="#000" d="M92.764 61.847c0-4.809 3.665-7.564 10.423-7.98l7.252-.442v-2.08c0-3.04-2.001-4.704-5.562-4.704-2.938 0-5.07 1.507-5.51 3.82h-5.252c.157-4.86 4.731-8.395 10.918-8.395 6.654 0 10.995 3.483 10.995 8.89v18.663h-5.38v-4.497h-.13c-1.534 2.937-4.914 4.782-8.579 4.782-5.406 0-9.175-3.222-9.175-8.057zm17.675-2.417v-2.106l-6.472.416c-3.64.234-5.536 1.585-5.536 3.95 0 2.288 1.975 3.77 5.068 3.77 3.95 0 6.94-2.522 6.94-6.03z" /><path fill="#000" d="M120.975 79.652v-4.496c.364.051 1.247.103 1.715.103 2.573 0 4.029-1.09 4.913-3.899l.52-1.663-9.852-27.293h6.082l6.863 22.146h.13l6.862-22.146h5.927l-10.216 28.67c-2.34 6.577-5.017 8.735-10.683 8.735-.442 0-1.872-.052-2.261-.157z" /></g></g></svg>`,
|
|
10
|
+
diners_club: `<svg class="payment-icons__icon" viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" role="img" width="38" height="24" aria-labelledby="pi-diners_club"><title id="pi-diners_club">Diners Club</title><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"/><path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32"/><path d="M12 12v3.7c0 .3-.2.3-.5.2-1.9-.8-3-3.3-2.3-5.4.4-1.1 1.2-2 2.3-2.4.4-.2.5-.1.5.2V12zm2 0V8.3c0-.3 0-.3.3-.2 2.1.8 3.2 3.3 2.4 5.4-.4 1.1-1.2 2-2.3 2.4-.4.2-.4.1-.4-.2V12zm7.2-7H13c3.8 0 6.8 3.1 6.8 7s-3 7-6.8 7h8.2c3.8 0 6.8-3.1 6.8-7s-3-7-6.8-7z" fill="#3086C8"/></svg>`,
|
|
11
|
+
discover: `<svg class="payment-icons__icon" viewBox="0 0 38 24" width="38" height="24" role="img" aria-labelledby="pi-discover" fill="none" xmlns="http://www.w3.org/2000/svg"><title id="pi-discover">Discover</title><path fill="#000" opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"/><path d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32z" fill="#fff"/><path d="M3.57 7.16H2v5.5h1.57c.83 0 1.43-.2 1.96-.63.63-.52 1-1.3 1-2.11-.01-1.63-1.22-2.76-2.96-2.76zm1.26 4.14c-.34.3-.77.44-1.47.44h-.29V8.1h.29c.69 0 1.11.12 1.47.44.37.33.59.84.59 1.37 0 .53-.22 1.06-.59 1.39zm2.19-4.14h1.07v5.5H7.02v-5.5zm3.69 2.11c-.64-.24-.83-.4-.83-.69 0-.35.34-.61.8-.61.32 0 .59.13.86.45l.56-.73c-.46-.4-1.01-.61-1.62-.61-.97 0-1.72.68-1.72 1.58 0 .76.35 1.15 1.35 1.51.42.15.63.25.74.31.21.14.32.34.32.57 0 .45-.35.78-.83.78-.51 0-.92-.26-1.17-.73l-.69.67c.49.73 1.09 1.05 1.9 1.05 1.11 0 1.9-.74 1.9-1.81.02-.89-.35-1.29-1.57-1.74zm1.92.65c0 1.62 1.27 2.87 2.9 2.87.46 0 .86-.09 1.34-.32v-1.26c-.43.43-.81.6-1.29.6-1.08 0-1.85-.78-1.85-1.9 0-1.06.79-1.89 1.8-1.89.51 0 .9.18 1.34.62V7.38c-.47-.24-.86-.34-1.32-.34-1.61 0-2.92 1.28-2.92 2.88zm12.76.94l-1.47-3.7h-1.17l2.33 5.64h.58l2.37-5.64h-1.16l-1.48 3.7zm3.13 1.8h3.04v-.93h-1.97v-1.48h1.9v-.93h-1.9V8.1h1.97v-.94h-3.04v5.5zm7.29-3.87c0-1.03-.71-1.62-1.95-1.62h-1.59v5.5h1.07v-2.21h.14l1.48 2.21h1.32l-1.73-2.32c.81-.17 1.26-.72 1.26-1.56zm-2.16.91h-.31V8.03h.33c.67 0 1.03.28 1.03.82 0 .55-.36.85-1.05.85z" fill="#231F20"/><path d="M20.16 12.86a2.931 2.931 0 100-5.862 2.931 2.931 0 000 5.862z" fill="url(#pi-paint0_linear)"/><path opacity=".65" d="M20.16 12.86a2.931 2.931 0 100-5.862 2.931 2.931 0 000 5.862z" fill="url(#pi-paint1_linear)"/><path d="M36.57 7.506c0-.1-.07-.15-.18-.15h-.16v.48h.12v-.19l.14.19h.14l-.16-.2c.06-.01.1-.06.1-.13zm-.2.07h-.02v-.13h.02c.06 0 .09.02.09.06 0 .05-.03.07-.09.07z" fill="#231F20"/><path d="M36.41 7.176c-.23 0-.42.19-.42.42 0 .23.19.42.42.42.23 0 .42-.19.42-.42 0-.23-.19-.42-.42-.42zm0 .77c-.18 0-.34-.15-.34-.35 0-.19.15-.35.34-.35.18 0 .33.16.33.35 0 .19-.15.35-.33.35z" fill="#231F20"/><path d="M37 12.984S27.09 19.873 8.976 23h26.023a2 2 0 002-1.984l.024-3.02L37 12.985z" fill="#F48120"/><defs><linearGradient id="pi-paint0_linear" x1="21.657" y1="12.275" x2="19.632" y2="9.104" gradientUnits="userSpaceOnUse"><stop stop-color="#F89F20"/><stop offset=".25" stop-color="#F79A20"/><stop offset=".533" stop-color="#F68D20"/><stop offset=".62" stop-color="#F58720"/><stop offset=".723" stop-color="#F48120"/><stop offset="1" stop-color="#F37521"/></linearGradient><linearGradient id="pi-paint1_linear" x1="21.338" y1="12.232" x2="18.378" y2="6.446" gradientUnits="userSpaceOnUse"><stop stop-color="#F58720"/><stop offset=".359" stop-color="#E16F27"/><stop offset=".703" stop-color="#D4602C"/><stop offset=".982" stop-color="#D05B2E"/></linearGradient></defs></svg>`,
|
|
12
|
+
google_pay: `<svg class="payment-icons__icon" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 38 24" width="38" height="24" aria-labelledby="pi-google_pay"><title id="pi-google_pay">Google Pay</title><path d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z" fill="#000" opacity=".07"/><path d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32" fill="#FFF"/><path d="M18.093 11.976v3.2h-1.018v-7.9h2.691a2.447 2.447 0 0 1 1.747.692 2.28 2.28 0 0 1 .11 3.224l-.11.116c-.47.447-1.098.69-1.747.674l-1.673-.006zm0-3.732v2.788h1.698c.377.012.741-.135 1.005-.404a1.391 1.391 0 0 0-1.005-2.354l-1.698-.03zm6.484 1.348c.65-.03 1.286.188 1.778.613.445.43.682 1.03.65 1.649v3.334h-.969v-.766h-.049a1.93 1.93 0 0 1-1.673.931 2.17 2.17 0 0 1-1.496-.533 1.667 1.667 0 0 1-.613-1.324 1.606 1.606 0 0 1 .613-1.336 2.746 2.746 0 0 1 1.698-.515c.517-.02 1.03.093 1.49.331v-.208a1.134 1.134 0 0 0-.417-.901 1.416 1.416 0 0 0-.98-.368 1.545 1.545 0 0 0-1.319.717l-.895-.564a2.488 2.488 0 0 1 2.182-1.06zM23.29 13.52a.79.79 0 0 0 .337.662c.223.176.5.269.785.263.429-.001.84-.17 1.146-.472.305-.286.478-.685.478-1.103a2.047 2.047 0 0 0-1.324-.374 1.716 1.716 0 0 0-1.03.294.883.883 0 0 0-.392.73zm9.286-3.75l-3.39 7.79h-1.048l1.281-2.728-2.224-5.062h1.103l1.612 3.885 1.569-3.885h1.097z" fill="#5F6368"/><path d="M13.986 11.284c0-.308-.024-.616-.073-.92h-4.29v1.747h2.451a2.096 2.096 0 0 1-.9 1.373v1.134h1.464a4.433 4.433 0 0 0 1.348-3.334z" fill="#4285F4"/><path d="M9.629 15.721a4.352 4.352 0 0 0 3.01-1.097l-1.466-1.14a2.752 2.752 0 0 1-4.094-1.44H5.577v1.17a4.53 4.53 0 0 0 4.052 2.507z" fill="#34A853"/><path d="M7.079 12.05a2.709 2.709 0 0 1 0-1.735v-1.17H5.577a4.505 4.505 0 0 0 0 4.075l1.502-1.17z" fill="#FBBC04"/><path d="M9.629 8.44a2.452 2.452 0 0 1 1.74.68l1.3-1.293a4.37 4.37 0 0 0-3.065-1.183 4.53 4.53 0 0 0-4.027 2.5l1.502 1.171a2.715 2.715 0 0 1 2.55-1.875z" fill="#EA4335"/></svg>`,
|
|
13
|
+
jcb: `<svg class="payment-icons__icon" width="38" height="24" role="img" aria-labelledby="pi-jcb" viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg"><title id="pi-jcb">JCB</title><g fill="none" fill-rule="evenodd"><g fill-rule="nonzero"><path d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z" fill="#000" opacity=".07"/><path d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32" fill="#FFF"/></g><path d="M11.5 5H15v11.5a2.5 2.5 0 0 1-2.5 2.5H9V7.5A2.5 2.5 0 0 1 11.5 5z" fill="#006EBC"/><path d="M18.5 5H22v11.5a2.5 2.5 0 0 1-2.5 2.5H16V7.5A2.5 2.5 0 0 1 18.5 5z" fill="#F00036"/><path d="M25.5 5H29v11.5a2.5 2.5 0 0 1-2.5 2.5H23V7.5A2.5 2.5 0 0 1 25.5 5z" fill="#2AB419"/><path d="M10.755 14.5c-1.06 0-2.122-.304-2.656-.987l.78-.676c.068 1.133 3.545 1.24 3.545-.19V9.5h1.802v3.147c0 .728-.574 1.322-1.573 1.632-.466.144-1.365.221-1.898.221zm8.116 0c-.674 0-1.388-.107-1.965-.366-.948-.425-1.312-1.206-1.3-2.199.012-1.014.436-1.782 1.468-2.165 1.319-.49 3.343-.261 3.926.27v.972c-.572-.521-1.958-.898-2.919-.46-.494.226-.737.917-.744 1.448-.006.56.245 1.252.744 1.497.953.467 2.39.04 2.919-.441v1.01c-.358.255-1.253.434-2.129.434zm8.679-2.587c.37-.235.582-.567.582-1.005 0-.438-.116-.687-.348-.939-.206-.207-.58-.469-1.238-.469H23v5h3.546c.696 0 1.097-.23 1.315-.415.283-.25.426-.53.426-.96 0-.431-.155-.908-.737-1.212zm-1.906-.281h-1.428v-1.444h1.495c.956 0 .944 1.444-.067 1.444zm.288 2.157h-1.716v-1.513h1.716c.986 0 1.083 1.513 0 1.513z" fill="#FFF" fill-rule="nonzero"/></g></svg>`,
|
|
14
|
+
klarna: `<svg class="payment-icons__icon" xmlns="http://www.w3.org/2000/svg" role="img" width="38" height="24" viewBox="0 0 38 24" aria-labelledby="pi-klarna" fill="none"><title id="pi-klarna">Klarna</title><rect width="38" height="24" rx="2" fill="#FFA8CD"/><rect x=".5" y=".5" width="37" height="23" rx="1.5" stroke="#000" stroke-opacity=".07"/><path d="M30.62 14.755c-.662 0-1.179-.554-1.179-1.226 0-.673.517-1.226 1.18-1.226.663 0 1.18.553 1.18 1.226 0 .672-.517 1.226-1.18 1.226zm-.33 1.295c.565 0 1.286-.217 1.686-1.068l.04.02c-.176.465-.176.742-.176.81v.11h1.423v-4.786H31.84v.109c0 .069 0 .346.175.81l-.039.02c-.4-.85-1.121-1.068-1.687-1.068-1.355 0-2.31 1.088-2.31 2.522 0 1.433.955 2.521 2.31 2.521zm-4.788-5.043c-.643 0-1.15.228-1.56 1.068l-.039-.02c.175-.464.175-.741.175-.81v-.11h-1.423v4.787h1.462V13.4c0-.662.38-1.078.995-1.078.614 0 .917.356.917 1.068v2.532h1.462v-3.046c0-1.088-.838-1.869-1.989-1.869zm-4.963 1.068l-.039-.02c.176-.464.176-.741.176-.81v-.11h-1.424v4.787h1.463l.01-2.304c0-.673.35-1.078.926-1.078.156 0 .282.02.429.06v-1.464c-.644-.139-1.22.109-1.54.94zm-4.65 2.68c-.664 0-1.18-.554-1.18-1.226 0-.673.516-1.226 1.18-1.226.662 0 1.179.553 1.179 1.226 0 .672-.517 1.226-1.18 1.226zm-.332 1.295c.565 0 1.287-.217 1.687-1.068l.038.02c-.175.465-.175.742-.175.81v.11h1.424v-4.786h-1.424v.109c0 .069 0 .346.175.81l-.038.02c-.4-.85-1.122-1.068-1.687-1.068-1.356 0-2.311 1.088-2.311 2.522 0 1.433.955 2.521 2.31 2.521zm-4.349-.128h1.463V9h-1.463v6.922zM10.136 9H8.644c0 1.236-.751 2.343-1.892 3.134l-.448.317V9h-1.55v6.922h1.55V12.49l2.564 3.43h1.892L8.293 12.64c1.121-.82 1.852-2.096 1.843-3.639z" fill="#0B051D"/></svg>`,
|
|
15
|
+
maestro: `<svg class="payment-icons__icon" viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" width="38" height="24" role="img" aria-labelledby="pi-maestro"><title id="pi-maestro">Maestro</title><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"/><path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32"/><circle fill="#EB001B" cx="15" cy="12" r="7"/><circle fill="#00A2E5" cx="23" cy="12" r="7"/><path fill="#7375CF" d="M22 12c0-2.4-1.2-4.5-3-5.7-1.8 1.3-3 3.4-3 5.7s1.2 4.5 3 5.7c1.8-1.2 3-3.3 3-5.7z"/></svg>`,
|
|
16
|
+
master: `<svg class="payment-icons__icon" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 38 24" width="38" height="24" fill="none" aria-labelledby="pi-master"><title id="pi-master">Mastercard</title><rect x=".5" y=".5" width="37" height="23" rx="2.5" stroke="#000" stroke-opacity=".07" fill="none"/><path d="M35 0H3C1.3 0 0 1.3 0 3V21C0 22.7 1.4 24 3 24H35C36.7 24 38 22.7 38 21V3C38 1.3 36.6 0 35 0Z" fill="#1C1C1C" style="fill:#1C1C1C;fill:color(display-p3 0.1098 0.1098 0.1098);fill-opacity:1;"/><path d="M35 1C36.1 1 37 1.9 37 3V21C37 22.1 36.1 23 35 23H3C1.9 23 1 22.1 1 21V3C1 1.9 1.9 1 3 1H35Z" fill="#232323" style="fill:#232323;fill:color(display-p3 0.1373 0.1373 0.1373);fill-opacity:1;"/><path d="M14.6364 19.2727C18.8538 19.2727 22.2727 15.8538 22.2727 11.6364C22.2727 7.41892 18.8538 4 14.6364 4C10.4189 4 7 7.41892 7 11.6364C7 15.8538 10.4189 19.2727 14.6364 19.2727Z" fill="#EB001B" style="fill:#EB001B;fill:color(display-p3 0.9216 0.0000 0.1059);fill-opacity:1;"/><path d="M23.3637 19.2727C27.5811 19.2727 31 15.8538 31 11.6364C31 7.41892 27.5811 4 23.3637 4C19.1462 4 15.7273 7.41892 15.7273 11.6364C15.7273 15.8538 19.1462 19.2727 23.3637 19.2727Z" fill="#F79E1B" style="fill:#F79E1B;fill:color(display-p3 0.9686 0.6196 0.1059);fill-opacity:1;"/><path d="M22.2727 11.6362C22.2727 9.01797 20.9637 6.72706 19 5.41797C17.0364 6.83615 15.7273 9.12706 15.7273 11.6362C15.7273 14.1452 17.0364 16.5452 19 17.8543C20.9637 16.5452 22.2727 14.2543 22.2727 11.6362Z" fill="#FF5F00" style="fill:#FF5F00;fill:color(display-p3 1.0000 0.3725 0.0000);fill-opacity:1;"/></svg>`,
|
|
17
|
+
paypal: `<svg class="payment-icons__icon" viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" width="38" height="24" role="img" aria-labelledby="pi-paypal"><title id="pi-paypal">PayPal</title><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"/><path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32"/><path fill="#003087" d="M23.9 8.3c.2-1 0-1.7-.6-2.3-.6-.7-1.7-1-3.1-1h-4.1c-.3 0-.5.2-.6.5L14 15.6c0 .2.1.4.3.4H17l.4-3.4 1.8-2.2 4.7-2.1z"/><path fill="#3086C8" d="M23.9 8.3l-.2.2c-.5 2.8-2.2 3.8-4.6 3.8H18c-.3 0-.5.2-.6.5l-.6 3.9-.2 1c0 .2.1.4.3.4H19c.3 0 .5-.2.5-.4v-.1l.4-2.4v-.1c0-.2.3-.4.5-.4h.3c2.1 0 3.7-.8 4.1-3.2.2-1 .1-1.8-.4-2.4-.1-.5-.3-.7-.5-.8z"/><path fill="#012169" d="M23.3 8.1c-.1-.1-.2-.1-.3-.1-.1 0-.2 0-.3-.1-.3-.1-.7-.1-1.1-.1h-3c-.1 0-.2 0-.2.1-.2.1-.3.2-.3.4l-.7 4.4v.1c0-.3.3-.5.6-.5h1.3c2.5 0 4.1-1 4.6-3.8v-.2c-.1-.1-.3-.2-.5-.2h-.1z"/></svg>`,
|
|
18
|
+
shopify_pay: `<svg class="payment-icons__icon" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 38 24" width="38" height="24" aria-labelledby="pi-shopify_pay"><title id="pi-shopify_pay">Shop Pay</title><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z" fill="#000"/><path d="M35.889 0C37.05 0 38 .982 38 2.182v19.636c0 1.2-.95 2.182-2.111 2.182H2.11C.95 24 0 23.018 0 21.818V2.182C0 .982.95 0 2.111 0H35.89z" fill="#5A31F4"/><path d="M9.35 11.368c-1.017-.223-1.47-.31-1.47-.705 0-.372.306-.558.92-.558.54 0 .934.238 1.225.704a.079.079 0 00.104.03l1.146-.584a.082.082 0 00.032-.114c-.475-.831-1.353-1.286-2.51-1.286-1.52 0-2.464.755-2.464 1.956 0 1.275 1.15 1.597 2.17 1.82 1.02.222 1.474.31 1.474.705 0 .396-.332.582-.993.582-.612 0-1.065-.282-1.34-.83a.08.08 0 00-.107-.035l-1.143.57a.083.083 0 00-.036.111c.454.92 1.384 1.437 2.627 1.437 1.583 0 2.539-.742 2.539-1.98s-1.155-1.598-2.173-1.82v-.003zM15.49 8.855c-.65 0-1.224.232-1.636.646a.04.04 0 01-.069-.03v-2.64a.08.08 0 00-.08-.081H12.27a.08.08 0 00-.08.082v8.194a.08.08 0 00.08.082h1.433a.08.08 0 00.081-.082v-3.594c0-.695.528-1.227 1.239-1.227.71 0 1.226.521 1.226 1.227v3.594a.08.08 0 00.081.082h1.433a.08.08 0 00.081-.082v-3.594c0-1.51-.981-2.577-2.355-2.577zM20.753 8.62c-.778 0-1.507.24-2.03.588a.082.082 0 00-.027.109l.632 1.088a.08.08 0 00.11.03 2.5 2.5 0 011.318-.366c1.25 0 2.17.891 2.17 2.068 0 1.003-.736 1.745-1.669 1.745-.76 0-1.288-.446-1.288-1.077 0-.361.152-.657.548-.866a.08.08 0 00.032-.113l-.596-1.018a.08.08 0 00-.098-.035c-.799.299-1.359 1.018-1.359 1.984 0 1.46 1.152 2.55 2.76 2.55 1.877 0 3.227-1.313 3.227-3.195 0-2.018-1.57-3.492-3.73-3.492zM28.675 8.843c-.724 0-1.373.27-1.845.746-.026.027-.069.007-.069-.029v-.572a.08.08 0 00-.08-.082h-1.397a.08.08 0 00-.08.082v8.182a.08.08 0 00.08.081h1.433a.08.08 0 00.081-.081v-2.683c0-.036.043-.054.069-.03a2.6 2.6 0 001.808.7c1.682 0 2.993-1.373 2.993-3.157s-1.313-3.157-2.993-3.157zm-.271 4.929c-.956 0-1.681-.768-1.681-1.783s.723-1.783 1.681-1.783c.958 0 1.68.755 1.68 1.783 0 1.027-.713 1.783-1.681 1.783h.001z" fill="#fff"/></svg>`,
|
|
19
|
+
unionpay: `<svg class="payment-icons__icon" viewBox="-36 25 38 24" xmlns="http://www.w3.org/2000/svg" width="38" height="24" role="img" aria-labelledby="pi-unionpay"><title id="pi-unionpay">Union Pay</title><path fill="#005B9A" d="M-36 46.8v.7-.7zM-18.3 25v24h-7.2c-1.3 0-2.1-1-1.8-2.3l4.4-19.4c.3-1.3 1.9-2.3 3.2-2.3h1.4zm12.6 0c-1.3 0-2.9 1-3.2 2.3l-4.5 19.4c-.3 1.3.5 2.3 1.8 2.3h-4.9V25h10.8z"/><path fill="#E9292D" d="M-19.7 25c-1.3 0-2.9 1.1-3.2 2.3l-4.4 19.4c-.3 1.3.5 2.3 1.8 2.3h-8.9c-.8 0-1.5-.6-1.5-1.4v-21c0-.8.7-1.6 1.5-1.6h14.7z"/><path fill="#0E73B9" d="M-5.7 25c-1.3 0-2.9 1.1-3.2 2.3l-4.4 19.4c-.3 1.3.5 2.3 1.8 2.3H-26h.5c-1.3 0-2.1-1-1.8-2.3l4.4-19.4c.3-1.3 1.9-2.3 3.2-2.3h14z"/><path fill="#059DA4" d="M2 26.6v21c0 .8-.6 1.4-1.5 1.4h-12.1c-1.3 0-2.1-1.1-1.8-2.3l4.5-19.4C-8.6 26-7 25-5.7 25H.5c.9 0 1.5.7 1.5 1.6z"/><path fill="#fff" d="M-21.122 38.645h.14c.14 0 .28-.07.28-.14l.42-.63h1.19l-.21.35h1.4l-.21.63h-1.68c-.21.28-.42.42-.7.42h-.84l.21-.63m-.21.91h3.01l-.21.7h-1.19l-.21.7h1.19l-.21.7h-1.19l-.28 1.05c-.07.14 0 .28.28.21h.98l-.21.7h-1.89c-.35 0-.49-.21-.35-.63l.35-1.33h-.77l.21-.7h.77l.21-.7h-.7l.21-.7zm4.83-1.75v.42s.56-.42 1.12-.42h1.96l-.77 2.66c-.07.28-.35.49-.77.49h-2.24l-.49 1.89c0 .07 0 .14.14.14h.42l-.14.56h-1.12c-.42 0-.56-.14-.49-.35l1.47-5.39h.91zm1.68.77h-1.75l-.21.7s.28-.21.77-.21h1.05l.14-.49zm-.63 1.68c.14 0 .21 0 .21-.14l.14-.35h-1.75l-.14.56 1.54-.07zm-1.19.84h.98v.42h.28c.14 0 .21-.07.21-.14l.07-.28h.84l-.14.49c-.07.35-.35.49-.77.56h-.56v.77c0 .14.07.21.35.21h.49l-.14.56h-1.19c-.35 0-.49-.14-.49-.49l.07-2.1zm4.2-2.45l.21-.84h1.19l-.07.28s.56-.28 1.05-.28h1.47l-.21.84h-.21l-1.12 3.85h.21l-.21.77h-.21l-.07.35h-1.19l.07-.35h-2.17l.21-.77h.21l1.12-3.85h-.28m1.26 0l-.28 1.05s.49-.21.91-.28c.07-.35.21-.77.21-.77h-.84zm-.49 1.54l-.28 1.12s.56-.28.98-.28c.14-.42.21-.77.21-.77l-.91-.07zm.21 2.31l.21-.77h-.84l-.21.77h.84zm2.87-4.69h1.12l.07.42c0 .07.07.14.21.14h.21l-.21.7h-.77c-.28 0-.49-.07-.49-.35l-.14-.91zm-.35 1.47h3.57l-.21.77h-1.19l-.21.7h1.12l-.21.77h-1.26l-.28.42h.63l.14.84c0 .07.07.14.21.14h.21l-.21.7h-.7c-.35 0-.56-.07-.56-.35l-.14-.77-.56.84c-.14.21-.35.35-.63.35h-1.05l.21-.7h.35c.14 0 .21-.07.35-.21l.84-1.26h-1.05l.21-.77h1.19l.21-.7h-1.19l.21-.77zm-19.74-5.04c-.14.7-.42 1.19-.91 1.54-.49.35-1.12.56-1.89.56-.7 0-1.26-.21-1.54-.56-.21-.28-.35-.56-.35-.98 0-.14 0-.35.07-.56l.84-3.92h1.19l-.77 3.92v.28c0 .21.07.35.14.49.14.21.35.28.7.28s.7-.07.91-.28c.21-.21.42-.42.49-.77l.77-3.92h1.19l-.84 3.92m1.12-1.54h.84l-.07.49.14-.14c.28-.28.63-.42 1.05-.42.35 0 .63.14.77.35.14.21.21.49.14.91l-.49 2.38h-.91l.42-2.17c.07-.28.07-.49 0-.56-.07-.14-.21-.14-.35-.14-.21 0-.42.07-.56.21-.14.14-.28.35-.28.63l-.42 2.03h-.91l.63-3.57m9.8 0h.84l-.07.49.14-.14c.28-.28.63-.42 1.05-.42.35 0 .63.14.77.35s.21.49.14.91l-.49 2.38h-.91l.42-2.24c.07-.21 0-.42-.07-.49-.07-.14-.21-.14-.35-.14-.21 0-.42.07-.56.21-.14.14-.28.35-.28.63l-.42 2.03h-.91l.7-3.57m-5.81 0h.98l-.77 3.5h-.98l.77-3.5m.35-1.33h.98l-.21.84h-.98l.21-.84zm1.4 4.55c-.21-.21-.35-.56-.35-.98v-.21c0-.07 0-.21.07-.28.14-.56.35-1.05.7-1.33.35-.35.84-.49 1.33-.49.42 0 .77.14 1.05.35.21.21.35.56.35.98v.21c0 .07 0 .21-.07.28-.14.56-.35.98-.7 1.33-.35.35-.84.49-1.33.49-.35 0-.7-.14-1.05-.35m1.89-.7c.14-.21.28-.49.35-.84v-.35c0-.21-.07-.35-.14-.49a.635.635 0 0 0-.49-.21c-.28 0-.49.07-.63.28-.14.21-.28.49-.35.84v.28c0 .21.07.35.14.49.14.14.28.21.49.21.28.07.42 0 .63-.21m6.51-4.69h2.52c.49 0 .84.14 1.12.35.28.21.35.56.35.91v.28c0 .07 0 .21-.07.28-.07.49-.35.98-.7 1.26-.42.35-.84.49-1.4.49h-1.4l-.42 2.03h-1.19l1.19-5.6m.56 2.59h1.12c.28 0 .49-.07.7-.21.14-.14.28-.35.35-.63v-.28c0-.21-.07-.35-.21-.42-.14-.07-.35-.14-.7-.14h-.91l-.35 1.68zm8.68 3.71c-.35.77-.7 1.26-.91 1.47-.21.21-.63.7-1.61.7l.07-.63c.84-.28 1.26-1.4 1.54-1.96l-.28-3.78h1.19l.07 2.38.91-2.31h1.05l-2.03 4.13m-2.94-3.85l-.42.28c-.42-.35-.84-.56-1.54-.21-.98.49-1.89 4.13.91 2.94l.14.21h1.12l.7-3.29-.91.07m-.56 1.82c-.21.56-.56.84-.91.77-.28-.14-.35-.63-.21-1.19.21-.56.56-.84.91-.77.28.14.35.63.21 1.19"/></svg>`,
|
|
20
|
+
visa: `<svg class="payment-icons__icon" xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 38 24" width="38" height="24" fill="none" aria-labelledby="pi-visa"><title id="pi-visa">Visa</title><rect x=".5" y=".5" width="37" height="23" rx="2.5" stroke="#000" stroke-opacity=".07" fill="none"/><path d="M35 0H3C1.3 0 0 1.3 0 3V21C0 22.7 1.4 24 3 24H35C36.7 24 38 22.7 38 21V3C38 1.3 36.6 0 35 0Z" fill="#142FBD" style="fill:#142FBD;fill:color(display-p3 0.0784 0.1843 0.7412);fill-opacity:1;"/><path d="M35 1C36.1 1 37 1.9 37 3V21C37 22.1 36.1 23 35 23H3C1.9 23 1 22.1 1 21V3C1 1.9 1.9 1 3 1H35Z" fill="#1532CB" style="fill:#1532CB;fill:color(display-p3 0.0824 0.1961 0.7961);fill-opacity:1;"/><path d="M29.5944 10.2167H29.2778C28.8556 11.2722 28.5389 11.8 28.2222 13.3833H30.2278C29.9111 11.8 29.9111 11.0611 29.5944 10.2167V10.2167ZM32.6556 16.4444H30.8611C30.7556 16.4444 30.7556 16.4444 30.65 16.3389L30.4389 15.3889L30.3333 15.1778H27.8C27.6944 15.1778 27.5889 15.1778 27.5889 15.3889L27.2722 16.3389C27.2722 16.4444 27.1667 16.4444 27.1667 16.4444H24.95L25.1611 15.9167L28.2222 8.73889C28.2222 8.21111 28.5389 8 29.0667 8H30.65C30.7556 8 30.8611 8 30.8611 8.21111L32.3389 15.0722C32.4444 15.4944 32.55 15.8111 32.55 16.2333C32.6556 16.3389 32.6556 16.3389 32.6556 16.4444V16.4444ZM18.5111 16.1278L18.9333 14.2278C19.0389 14.2278 19.1444 14.3333 19.1444 14.3333C19.8833 14.65 20.6222 14.8611 21.3611 14.7556C21.5722 14.7556 21.8889 14.65 22.1 14.5444C22.6278 14.3333 22.6278 13.8056 22.2056 13.3833C21.9944 13.1722 21.6778 13.0667 21.3611 12.8556C20.9389 12.6444 20.5167 12.4333 20.2 12.1167C18.9333 11.0611 19.3556 9.58333 20.0944 8.84444C20.7278 8.42222 21.0444 8 21.8889 8C23.1556 8 24.5278 8 25.1611 8.21111H25.2667C25.1611 8.84444 25.0556 9.37222 24.8444 10.0056C24.3167 9.79444 23.7889 9.58333 23.2611 9.58333C22.9444 9.58333 22.6278 9.58333 22.3111 9.68889C22.1 9.68889 21.9944 9.79444 21.8889 9.9C21.6778 10.1111 21.6778 10.4278 21.8889 10.6389L22.4167 11.0611C22.8389 11.2722 23.2611 11.4833 23.5778 11.6944C24.1056 12.0111 24.6333 12.5389 24.7389 13.1722C24.95 14.1222 24.6333 14.9667 23.7889 15.6C23.2611 16.0222 23.05 16.2333 22.3111 16.2333C20.8333 16.2333 19.6722 16.3389 18.7222 16.0222C18.6167 16.2333 18.6167 16.2333 18.5111 16.1278V16.1278ZM14.8167 16.4444C14.9222 15.7056 14.9222 15.7056 15.0278 15.3889C15.5556 13.0667 16.0833 10.6389 16.5056 8.31667C16.6111 8.10556 16.6111 8 16.8222 8H18.7222C18.5111 9.26667 18.3 10.2167 17.9833 11.3778C17.6667 12.9611 17.35 14.5444 16.9278 16.1278C16.9278 16.3389 16.8222 16.3389 16.6111 16.3389L14.8167 16.4444ZM5 8.21111C5 8.10556 5.21111 8 5.31667 8H8.90556C9.43333 8 9.85556 8.31667 9.96111 8.84444L10.9111 13.4889C10.9111 13.5944 10.9111 13.5944 11.0167 13.7C11.0167 13.5944 11.1222 13.5944 11.1222 13.5944L13.3389 8.21111C13.2333 8.10556 13.3389 8 13.4444 8H15.6611C15.6611 8.10556 15.6611 8.10556 15.5556 8.21111L12.2833 15.9167C12.1778 16.1278 12.1778 16.2333 12.0722 16.3389C11.9667 16.4444 11.7556 16.3389 11.5444 16.3389H9.96111C9.85556 16.3389 9.75 16.3389 9.75 16.1278L8.06111 9.58333C7.85 9.37222 7.53333 9.05556 7.11111 8.95C6.47778 8.63333 5.31667 8.42222 5.10556 8.42222L5 8.21111Z" fill="white" style="fill:white;fill-opacity:1;"/></svg>`,
|
|
21
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Mirror of snippets/payment-icons.liquid — the store's payment method
|
|
4
|
+
* icons as a wrapping row.
|
|
5
|
+
*
|
|
6
|
+
* Liquid iterates `shop.enabled_payment_types` and renders Shopify's
|
|
7
|
+
* hosted marks via `payment_type_svg_tag`; neither is available
|
|
8
|
+
* through the Storefront API, so this renders a fixed default set of
|
|
9
|
+
* the official marks, vendored from activemerchant/payment_icons into
|
|
10
|
+
* PaymentIcons.generated.ts by scripts/payment-icons.mjs.
|
|
11
|
+
*/
|
|
12
|
+
import { PAYMENT_ICONS } from './PaymentIcons.generated';
|
|
13
|
+
const ALL_PAYMENT_TYPES = Object.keys(PAYMENT_ICONS);
|
|
14
|
+
export function PaymentIcons({ types = ALL_PAYMENT_TYPES }) {
|
|
15
|
+
if (types.length === 0)
|
|
16
|
+
return null;
|
|
17
|
+
return (_jsx("ul", { className: "payment-icons", role: "list", children: types.map((type) => (_jsx("li", { dangerouslySetInnerHTML: { __html: PAYMENT_ICONS[type] } }, type))) }));
|
|
18
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port of snippets/price.liquid. CSS: app/styles/components/snippets-price.css
|
|
3
|
+
* Renders a price, with optional compare-at (sale) price and unit price.
|
|
4
|
+
* The keep*Placeholder flags mirror the Liquid params of the same name
|
|
5
|
+
* (empty-but-present elements the PDP island toggles on variant change;
|
|
6
|
+
* in React they simply keep the DOM shape identical).
|
|
7
|
+
*/
|
|
8
|
+
import type { Money, UnitPriceMeasurement } from '../../commerce/index.ts';
|
|
9
|
+
import { formatUnitPrice } from '../../commerce/index.ts';
|
|
10
|
+
export { formatUnitPrice };
|
|
11
|
+
export interface PriceProps {
|
|
12
|
+
price: Money | null | undefined;
|
|
13
|
+
compareAt?: Money | null;
|
|
14
|
+
/** Prefix with "From" when a range's min ≠ max. */
|
|
15
|
+
showFrom?: boolean;
|
|
16
|
+
className?: string;
|
|
17
|
+
unitPrice?: Money | null;
|
|
18
|
+
unitPriceMeasurement?: UnitPriceMeasurement | null;
|
|
19
|
+
/** Always render the compare element (hidden when not on sale). */
|
|
20
|
+
keepComparePlaceholder?: boolean;
|
|
21
|
+
/** Always render the unit price element (hidden when absent). */
|
|
22
|
+
keepUnitPlaceholder?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare function Price({ price, compareAt, showFrom, className, unitPrice, unitPriceMeasurement, keepComparePlaceholder, keepUnitPlaceholder, }: PriceProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { formatMoney, formatUnitPrice, isOnSale } from "../../commerce/index.js";
|
|
3
|
+
import { t } from '../engine/translate';
|
|
4
|
+
// Re-exported for existing imports; implementation is commerce-core's.
|
|
5
|
+
export { formatUnitPrice };
|
|
6
|
+
export function Price({ price, compareAt, showFrom, className, unitPrice, unitPriceMeasurement, keepComparePlaceholder, keepUnitPlaceholder, }) {
|
|
7
|
+
const onSale = isOnSale(price, compareAt);
|
|
8
|
+
return (_jsxs("span", { className: `price${onSale ? ' price--sale' : ''}${className ? ` ${className}` : ''}`, children: [showFrom ? _jsx("span", { className: "price__from", children: "From " }) : null, _jsx("span", { className: "price__current", children: formatMoney(price) }), onSale ? (_jsx("s", { className: "price__compare", children: formatMoney(compareAt) })) : keepComparePlaceholder ? (_jsx("s", { className: "price__compare", hidden: true })) : null, unitPrice ? (_jsxs("span", { className: "price__unit", "data-unit-price": "", children: [_jsx("span", { className: "visually-hidden", children: t('products.unit_price_label') }), _jsx("span", { "data-unit-price-value": "", children: formatUnitPrice(unitPrice, unitPriceMeasurement) })] })) : keepUnitPlaceholder ? (_jsxs("span", { className: "price__unit", "data-unit-price": "", hidden: true, children: [_jsx("span", { className: "visually-hidden", children: t('products.unit_price_label') }), _jsx("span", { "data-unit-price-value": "" })] })) : null] }));
|
|
9
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port of snippets/product-badges.liquid — a product's badge chips: the
|
|
3
|
+
* automatic status badge (sold out > sale > best seller, one at most)
|
|
4
|
+
* followed by merchant chips from badge:<Label> product tags. Chip
|
|
5
|
+
* colors come from the theme's badge settings; badge: labels are
|
|
6
|
+
* matched (case-insensitive) against the two badge styles' label
|
|
7
|
+
* lists, falling back to the standard badge colors.
|
|
8
|
+
*
|
|
9
|
+
* Outputs bare chips — the caller provides the positioning wrapper
|
|
10
|
+
* (and uses hasProductBadges() to skip the wrapper entirely, the
|
|
11
|
+
* mirror of Liquid's captured-output blank check).
|
|
12
|
+
*
|
|
13
|
+
* The Liquid snippet also consults a "badge_style" metaobject for
|
|
14
|
+
* unlimited styles; metaobjects aren't in the card fragment, so the
|
|
15
|
+
* mirror supports the two settings slots only.
|
|
16
|
+
*
|
|
17
|
+
* CSS: app/styles/components/snippets-product-badges.css
|
|
18
|
+
*/
|
|
19
|
+
import type { CardProduct } from '../../commerce/index.ts';
|
|
20
|
+
/** Mirror of the card's `badge_check != blank` capture probe. */
|
|
21
|
+
export declare function hasProductBadges(product: CardProduct): boolean;
|
|
22
|
+
export declare function ProductBadges({ product }: {
|
|
23
|
+
product: CardProduct;
|
|
24
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { isOnSale } from "../../commerce/index.js";
|
|
3
|
+
import { t } from '../engine/translate';
|
|
4
|
+
import { themeSettings } from '../engine/settings';
|
|
5
|
+
function splitLabels(value) {
|
|
6
|
+
if (typeof value !== 'string')
|
|
7
|
+
return [];
|
|
8
|
+
return value
|
|
9
|
+
.toLowerCase()
|
|
10
|
+
.split(',')
|
|
11
|
+
.map((label) => label.trim())
|
|
12
|
+
.filter(Boolean);
|
|
13
|
+
}
|
|
14
|
+
function statusBadge(product) {
|
|
15
|
+
if (product.availableForSale === false) {
|
|
16
|
+
return { label: t('products.sold_out'), className: 'badge' };
|
|
17
|
+
}
|
|
18
|
+
if (isOnSale(product.priceRange?.minVariantPrice, product.compareAtPriceRange?.minVariantPrice)) {
|
|
19
|
+
return { label: t('products.sale'), className: 'badge badge--sale' };
|
|
20
|
+
}
|
|
21
|
+
// "Best seller" chip: driven by a product tag (bestseller,
|
|
22
|
+
// best-seller, or best seller — case-insensitive)
|
|
23
|
+
const tagsFlat = (product.tags ?? [])
|
|
24
|
+
.join(',')
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
.replace(/-/g, '')
|
|
27
|
+
.replace(/ /g, '');
|
|
28
|
+
if (tagsFlat.includes('bestseller')) {
|
|
29
|
+
return { label: t('products.best_seller'), className: 'badge' };
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function tagBadges(product) {
|
|
34
|
+
return (product.tags ?? [])
|
|
35
|
+
.filter((tag) => tag.slice(0, 6).toLowerCase() === 'badge:')
|
|
36
|
+
.map((tag) => tag.slice(6, 46).trim());
|
|
37
|
+
}
|
|
38
|
+
/** Mirror of the card's `badge_check != blank` capture probe. */
|
|
39
|
+
export function hasProductBadges(product) {
|
|
40
|
+
return statusBadge(product) !== null || tagBadges(product).length > 0;
|
|
41
|
+
}
|
|
42
|
+
export function ProductBadges({ product }) {
|
|
43
|
+
const status = statusBadge(product);
|
|
44
|
+
const style1Labels = splitLabels(themeSettings.badge_style_1_labels);
|
|
45
|
+
const style2Labels = splitLabels(themeSettings.badge_style_2_labels);
|
|
46
|
+
return (_jsxs(_Fragment, { children: [status ? _jsx("span", { className: status.className, children: status.label }) : null, tagBadges(product).map((label, index) => {
|
|
47
|
+
const labelDown = label.toLowerCase();
|
|
48
|
+
let badgeStyle = '';
|
|
49
|
+
if (style1Labels.includes(labelDown)) {
|
|
50
|
+
badgeStyle = ' badge--style-1';
|
|
51
|
+
}
|
|
52
|
+
else if (style2Labels.includes(labelDown)) {
|
|
53
|
+
badgeStyle = ' badge--style-2';
|
|
54
|
+
}
|
|
55
|
+
return (_jsx("span", { className: `badge${badgeStyle}`, children: label }, `${label}-${index}`));
|
|
56
|
+
})] }));
|
|
57
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CardProduct } from '../../commerce/index.ts';
|
|
2
|
+
export interface ProductCardProps {
|
|
3
|
+
product: CardProduct;
|
|
4
|
+
loading?: 'eager' | 'lazy';
|
|
5
|
+
}
|
|
6
|
+
export declare function ProductCard({ product, loading }: ProductCardProps): import("react").JSX.Element;
|
|
7
|
+
/**
|
|
8
|
+
* Storefront API fragment every section loader uses for product cards.
|
|
9
|
+
* Spread into queries as `...ProductCard` and interpolate the constant
|
|
10
|
+
* (it carries its own nested ProductCardVariant fragment).
|
|
11
|
+
*
|
|
12
|
+
* Mirrors what snippets/product-card.liquid + sections/quick-add.liquid
|
|
13
|
+
* read from the Liquid product drop: images, price/compare/unit price,
|
|
14
|
+
* the full variant list (option probing + quick-add variant
|
|
15
|
+
* resolution), option swatches, and the standardized review metafields.
|
|
16
|
+
*/
|
|
17
|
+
export declare const PRODUCT_CARD_FRAGMENT: "#graphql\n fragment ProductCardVariant on ProductVariant {\n id\n availableForSale\n image {\n id\n url\n altText\n width\n height\n }\n price { amount currencyCode }\n compareAtPrice { amount currencyCode }\n unitPrice { amount currencyCode }\n unitPriceMeasurement { referenceValue referenceUnit }\n selectedOptions { name value }\n }\n fragment ProductCard on Product {\n id\n handle\n title\n vendor\n tags\n availableForSale\n featuredImage {\n id\n url\n altText\n width\n height\n }\n images(first: 2) {\n nodes {\n id\n url\n altText\n width\n height\n }\n }\n priceRange {\n minVariantPrice { amount currencyCode }\n maxVariantPrice { amount currencyCode }\n }\n compareAtPriceRange {\n minVariantPrice { amount currencyCode }\n maxVariantPrice { amount currencyCode }\n }\n options {\n name\n optionValues {\n name\n swatch {\n color\n image {\n previewImage { url }\n }\n }\n firstSelectableVariant {\n ...ProductCardVariant\n }\n }\n }\n selectedOrFirstAvailableVariant {\n ...ProductCardVariant\n }\n variants(first: 50) {\n nodes {\n ...ProductCardVariant\n }\n }\n rating: metafield(namespace: \"reviews\", key: \"rating\") {\n value\n }\n ratingCount: metafield(namespace: \"reviews\", key: \"rating_count\") {\n value\n }\n }\n";
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Port of snippets/product-card.liquid — a product card for grids:
|
|
4
|
+
* square media (second image on hover), title, price, and badges
|
|
5
|
+
* (sold-out/sale/best-seller, plus merchant chips from "badge:<Label>"
|
|
6
|
+
* product tags), variant swatches / image thumbs, and quick add.
|
|
7
|
+
*
|
|
8
|
+
* The Liquid theme's <product-card> island (src/entries/cards.ts)
|
|
9
|
+
* drives swatch-hover previews and the quick-add dialog; here the same
|
|
10
|
+
* behavior lives in React state. CSS: app/styles/components/snippets-product-card.css
|
|
11
|
+
*/
|
|
12
|
+
import { useState } from 'react';
|
|
13
|
+
import { emit, hasOnlyDefaultVariant, numericId, productUrl, resolvePickerOption, targetVariantFor, } from "../../commerce/index.js";
|
|
14
|
+
import { useAdapter } from '../adapter';
|
|
15
|
+
import { Price } from './Price';
|
|
16
|
+
import { Rating } from './Rating';
|
|
17
|
+
import { ProductBadges, hasProductBadges } from './ProductBadges';
|
|
18
|
+
import { swatchStyle } from './SwatchStyle';
|
|
19
|
+
import { imageUrl, PlaceholderSvg } from '../engine/images';
|
|
20
|
+
import { themeSettings } from '../engine/settings';
|
|
21
|
+
import { t } from '../engine/translate';
|
|
22
|
+
const CARD_SIZES = '(min-width: 64rem) 25vw, (min-width: 48rem) 33vw, 50vw';
|
|
23
|
+
const CARD_WIDTHS = [360, 540, 720, 800];
|
|
24
|
+
function cardSrcSet(url) {
|
|
25
|
+
return CARD_WIDTHS.map((w) => `${imageUrl(url, w)} ${w}w`).join(', ');
|
|
26
|
+
}
|
|
27
|
+
/** Localized option names that mark an option as a color, for the
|
|
28
|
+
* picker resolution shared via commerce-core. */
|
|
29
|
+
function colorOptionNames() {
|
|
30
|
+
return t('products.color_option_match')
|
|
31
|
+
.toLowerCase()
|
|
32
|
+
.split(',')
|
|
33
|
+
.map((name) => name.trim())
|
|
34
|
+
.filter(Boolean);
|
|
35
|
+
}
|
|
36
|
+
export function ProductCard({ product, loading = 'lazy' }) {
|
|
37
|
+
const { Link, CartAddForm } = useAdapter();
|
|
38
|
+
const url = productUrl(product);
|
|
39
|
+
const badgePosition = themeSettings.card_badge_position ?? 'corner';
|
|
40
|
+
const showBadges = hasProductBadges(product);
|
|
41
|
+
const available = product.availableForSale !== false;
|
|
42
|
+
const showQuickAdd = available && (themeSettings.card_show_quick_add ?? true);
|
|
43
|
+
const featuredImage = product.featuredImage ?? null;
|
|
44
|
+
// Mirror of `product.images[1]` — the second product image.
|
|
45
|
+
const secondaryImage = (themeSettings.card_show_secondary_image ?? true)
|
|
46
|
+
? (product.images?.nodes?.[1] ?? null)
|
|
47
|
+
: null;
|
|
48
|
+
// Swatch-hover preview, crossfading over the base image. The Liquid
|
|
49
|
+
// island creates the <img> on first hover; React renders it once a
|
|
50
|
+
// swatch has actually been hovered.
|
|
51
|
+
const [preview, setPreview] = useState(null);
|
|
52
|
+
const onSwatchEnter = (mediaUrl) => () => {
|
|
53
|
+
// Touch devices simulate mouseover on tap; mutating the media then
|
|
54
|
+
// makes iOS treat the tap as hover and swallow the navigation
|
|
55
|
+
if (!mediaUrl)
|
|
56
|
+
return;
|
|
57
|
+
if (typeof window !== 'undefined' &&
|
|
58
|
+
window.matchMedia('(hover: none)').matches) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
setPreview((previous) => previous?.src === mediaUrl
|
|
62
|
+
? { src: mediaUrl, visible: true }
|
|
63
|
+
: { src: mediaUrl, visible: false });
|
|
64
|
+
};
|
|
65
|
+
const onSwatchLeave = (event) => {
|
|
66
|
+
if (event.relatedTarget instanceof Node &&
|
|
67
|
+
event.currentTarget.contains(event.relatedTarget)) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
setPreview((previous) => previous ? { ...previous, visible: false } : previous);
|
|
71
|
+
};
|
|
72
|
+
const onQuickAdd = (event) => {
|
|
73
|
+
// Shell missing (customized layout): let the link navigate to the PDP
|
|
74
|
+
if (typeof document === 'undefined' ||
|
|
75
|
+
!document.getElementById('QuickAddDialog')) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
emit('quick-add:open', { product });
|
|
80
|
+
};
|
|
81
|
+
// Rendered twice: hover overlay on the media (desktop) and inline
|
|
82
|
+
// under the variant picker (mobile, Glossier-style)
|
|
83
|
+
const quickAdd = hasOnlyDefaultVariant(product) ? (_jsx(CartAddForm, { lines: [
|
|
84
|
+
{
|
|
85
|
+
merchandiseId: product.selectedOrFirstAvailableVariant?.id ?? '',
|
|
86
|
+
quantity: 1,
|
|
87
|
+
},
|
|
88
|
+
], children: ({ submitting }) => (_jsx("button", { type: "submit", className: "button button--secondary product-card__quick-button", disabled: submitting, children: t('products.add_to_bag') })) })) : (_jsx(Link, { to: url, className: "button button--secondary product-card__quick-button", onClick: onQuickAdd, children: t('products.add_to_bag') }));
|
|
89
|
+
// Variant display per theme settings: color swatches, variant image
|
|
90
|
+
// thumbs, or nothing.
|
|
91
|
+
const swatchStyleSetting = themeSettings.card_swatch_style ?? 'variant_image';
|
|
92
|
+
const pickerOption = resolvePickerOption(product, swatchStyleSetting, colorOptionNames());
|
|
93
|
+
// Image thumbs: 3 + the +N tile fit a narrow mobile column
|
|
94
|
+
const valueLimit = swatchStyleSetting === 'variant_image' ? 3 : 4;
|
|
95
|
+
const extraCount = pickerOption
|
|
96
|
+
? pickerOption.optionValues.length - valueLimit
|
|
97
|
+
: 0;
|
|
98
|
+
return (_jsxs("div", { className: "product-card", children: [_jsxs("div", { className: "product-card__frame", children: [_jsxs(Link, { to: url, className: "product-card__media", "aria-label": product.title, children: [featuredImage ? (_jsxs(_Fragment, { children: [_jsx("img", { className: "product-card__image", src: imageUrl(featuredImage.url, 800), srcSet: cardSrcSet(featuredImage.url), sizes: CARD_SIZES, loading: loading, alt: featuredImage.altText ?? '', width: featuredImage.width ?? undefined, height: featuredImage.height ?? undefined }), secondaryImage ? (_jsx("img", { className: "product-card__image product-card__image--hover", src: imageUrl(secondaryImage.url, 800), srcSet: cardSrcSet(secondaryImage.url), sizes: CARD_SIZES, loading: "lazy", alt: "", "aria-hidden": "true", width: secondaryImage.width ?? undefined, height: secondaryImage.height ?? undefined })) : null] })) : (_jsx(PlaceholderSvg, { className: "product-card__placeholder" })), preview ? (_jsx("img", { className: `product-card__image product-card__image--preview${preview.visible ? ' is-visible' : ''}`, src: preview.src, alt: "", "aria-hidden": "true", onLoad: () => setPreview((previous) => previous ? { ...previous, visible: true } : previous) })) : null, badgePosition === 'corner' && showBadges ? (_jsx("div", { className: "product-card__badges", children: _jsx(ProductBadges, { product: product }) })) : null] }), showQuickAdd ? (_jsx("div", { className: "product-card__quick product-card__quick--overlay", children: quickAdd })) : null] }), _jsxs("div", { className: "product-card__info stack", style: { '--stack-gap': 'var(--space-2xs)' }, children: [badgePosition === 'below' && showBadges ? (_jsx("div", { className: "product-card__badges", children: _jsx(ProductBadges, { product: product }) })) : null, _jsx("h3", { className: "product-card__title", children: _jsx(Link, { to: url, children: product.title }) }), _jsx(Price, { price: product.priceRange?.minVariantPrice, compareAt: product.compareAtPriceRange?.minVariantPrice, unitPrice: product.selectedOrFirstAvailableVariant?.unitPrice, unitPriceMeasurement: product.selectedOrFirstAvailableVariant?.unitPriceMeasurement }), themeSettings.card_show_rating ? _jsx(Rating, { product: product }) : null, pickerOption ? (_jsxs("div", { className: "product-card__swatches", onMouseOut: onSwatchLeave, children: [pickerOption.optionValues.slice(0, valueLimit).map((value) => {
|
|
99
|
+
const targetVariant = targetVariantFor(product, pickerOption, value.name);
|
|
100
|
+
const valueUrl = targetVariant
|
|
101
|
+
? `${url}?variant=${numericId(targetVariant.id)}`
|
|
102
|
+
: url;
|
|
103
|
+
const cardMediaUrl = targetVariant?.image
|
|
104
|
+
? imageUrl(targetVariant.image.url, 800)
|
|
105
|
+
: undefined;
|
|
106
|
+
if (swatchStyleSetting === 'variant_image') {
|
|
107
|
+
if (!targetVariant?.image)
|
|
108
|
+
return null;
|
|
109
|
+
return (_jsx(Link, { className: "product-card__variant-thumb", to: valueUrl, "data-card-media": cardMediaUrl, onMouseOver: onSwatchEnter(cardMediaUrl), "aria-label": `${product.title} – ${value.name}`, children: _jsx("img", { src: imageUrl(targetVariant.image.url, 80), loading: "lazy", alt: targetVariant.image.altText ?? '' }) }, value.name));
|
|
110
|
+
}
|
|
111
|
+
return (_jsx(Link, { className: "swatch swatch--sm", to: valueUrl, "data-card-media": cardMediaUrl, onMouseOver: cardMediaUrl ? onSwatchEnter(cardMediaUrl) : undefined, style: swatchStyle(value.name, value.swatch), "aria-label": `${product.title} – ${value.name}` }, value.name));
|
|
112
|
+
}), extraCount > 0 ? (swatchStyleSetting === 'variant_image' ? (_jsxs(Link, { className: "product-card__swatch-count product-card__swatch-count--tile", to: url, "aria-label": t('products.choose_options'), children: ["+", extraCount] })) : (_jsxs("span", { className: "product-card__swatch-count", "aria-hidden": "true", children: ["+", extraCount] }))) : null] })) : null, showQuickAdd ? (_jsx("div", { className: "product-card__quick product-card__quick--inline", children: quickAdd })) : null] })] }));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Storefront API fragment every section loader uses for product cards.
|
|
116
|
+
* Spread into queries as `...ProductCard` and interpolate the constant
|
|
117
|
+
* (it carries its own nested ProductCardVariant fragment).
|
|
118
|
+
*
|
|
119
|
+
* Mirrors what snippets/product-card.liquid + sections/quick-add.liquid
|
|
120
|
+
* read from the Liquid product drop: images, price/compare/unit price,
|
|
121
|
+
* the full variant list (option probing + quick-add variant
|
|
122
|
+
* resolution), option swatches, and the standardized review metafields.
|
|
123
|
+
*/
|
|
124
|
+
export const PRODUCT_CARD_FRAGMENT = `#graphql
|
|
125
|
+
fragment ProductCardVariant on ProductVariant {
|
|
126
|
+
id
|
|
127
|
+
availableForSale
|
|
128
|
+
image {
|
|
129
|
+
id
|
|
130
|
+
url
|
|
131
|
+
altText
|
|
132
|
+
width
|
|
133
|
+
height
|
|
134
|
+
}
|
|
135
|
+
price { amount currencyCode }
|
|
136
|
+
compareAtPrice { amount currencyCode }
|
|
137
|
+
unitPrice { amount currencyCode }
|
|
138
|
+
unitPriceMeasurement { referenceValue referenceUnit }
|
|
139
|
+
selectedOptions { name value }
|
|
140
|
+
}
|
|
141
|
+
fragment ProductCard on Product {
|
|
142
|
+
id
|
|
143
|
+
handle
|
|
144
|
+
title
|
|
145
|
+
vendor
|
|
146
|
+
tags
|
|
147
|
+
availableForSale
|
|
148
|
+
featuredImage {
|
|
149
|
+
id
|
|
150
|
+
url
|
|
151
|
+
altText
|
|
152
|
+
width
|
|
153
|
+
height
|
|
154
|
+
}
|
|
155
|
+
images(first: 2) {
|
|
156
|
+
nodes {
|
|
157
|
+
id
|
|
158
|
+
url
|
|
159
|
+
altText
|
|
160
|
+
width
|
|
161
|
+
height
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
priceRange {
|
|
165
|
+
minVariantPrice { amount currencyCode }
|
|
166
|
+
maxVariantPrice { amount currencyCode }
|
|
167
|
+
}
|
|
168
|
+
compareAtPriceRange {
|
|
169
|
+
minVariantPrice { amount currencyCode }
|
|
170
|
+
maxVariantPrice { amount currencyCode }
|
|
171
|
+
}
|
|
172
|
+
options {
|
|
173
|
+
name
|
|
174
|
+
optionValues {
|
|
175
|
+
name
|
|
176
|
+
swatch {
|
|
177
|
+
color
|
|
178
|
+
image {
|
|
179
|
+
previewImage { url }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
firstSelectableVariant {
|
|
183
|
+
...ProductCardVariant
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
selectedOrFirstAvailableVariant {
|
|
188
|
+
...ProductCardVariant
|
|
189
|
+
}
|
|
190
|
+
variants(first: 50) {
|
|
191
|
+
nodes {
|
|
192
|
+
...ProductCardVariant
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
rating: metafield(namespace: "reviews", key: "rating") {
|
|
196
|
+
value
|
|
197
|
+
}
|
|
198
|
+
ratingCount: metafield(namespace: "reviews", key: "rating_count") {
|
|
199
|
+
value
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
`;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port of snippets/rating.liquid — compact review score (star, average,
|
|
3
|
+
* review count) from the standardized review metafields reviews.rating
|
|
4
|
+
* and reviews.rating_count (aliased `rating` / `ratingCount` in
|
|
5
|
+
* PRODUCT_CARD_FRAGMENT). Renders nothing for products without reviews.
|
|
6
|
+
* CSS: app/styles/components/snippets-rating.css
|
|
7
|
+
*/
|
|
8
|
+
import type { CardProduct } from '../../commerce/index.ts';
|
|
9
|
+
export declare function Rating({ product }: {
|
|
10
|
+
product: CardProduct;
|
|
11
|
+
}): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from './Icon';
|
|
3
|
+
import { t } from '../engine/translate';
|
|
4
|
+
/**
|
|
5
|
+
* `reviews.rating` is a `rating` type metafield; the Storefront API
|
|
6
|
+
* returns its value as JSON: {"value":"4.5","scale_min":"1.0","scale_max":"5.0"}.
|
|
7
|
+
*/
|
|
8
|
+
function parseRating(raw) {
|
|
9
|
+
if (!raw)
|
|
10
|
+
return null;
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(raw);
|
|
13
|
+
const rating = Number(parsed.value ?? parsed.rating);
|
|
14
|
+
if (!Number.isFinite(rating))
|
|
15
|
+
return null;
|
|
16
|
+
const scaleMax = Number(parsed.scale_max);
|
|
17
|
+
return { rating, scaleMax: Number.isFinite(scaleMax) ? scaleMax : 5 };
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// Plain number value (some apps write a number_decimal metafield)
|
|
21
|
+
const rating = Number(raw);
|
|
22
|
+
return Number.isFinite(rating) ? { rating, scaleMax: 5 } : null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function Rating({ product }) {
|
|
26
|
+
const rating = parseRating(product.rating?.value);
|
|
27
|
+
const ratingCount = Number(product.ratingCount?.value ?? 0);
|
|
28
|
+
if (!rating || !(ratingCount > 0))
|
|
29
|
+
return null;
|
|
30
|
+
return (_jsxs("div", { className: "rating", "aria-label": t('products.rating_label', {
|
|
31
|
+
rating: rating.rating,
|
|
32
|
+
max: rating.scaleMax,
|
|
33
|
+
count: ratingCount,
|
|
34
|
+
}), children: [_jsx("span", { className: "rating__star", "aria-hidden": "true", children: _jsx(Icon, { name: "icon-star" }) }), _jsx("span", { "aria-hidden": "true", children: Math.round(rating.rating * 10) / 10 }), _jsxs("span", { className: "rating__count", "aria-hidden": "true", children: ["(", ratingCount, ")"] })] }));
|
|
35
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port of snippets/swatch-style.liquid — resolves the fill for a color
|
|
3
|
+
* swatch. The Liquid snippet emits a `--swatch: …` inline style
|
|
4
|
+
* declaration (not a stylesheet), so the mirror is a helper returning
|
|
5
|
+
* a React style object — or undefined when the value can't be
|
|
6
|
+
* resolved, in which case the .swatch CSS paints a neutral chip.
|
|
7
|
+
*
|
|
8
|
+
* Resolution order:
|
|
9
|
+
* 1. The value's native swatch (admin-managed taxonomy colors)
|
|
10
|
+
* 2. The value's own name read as a CSS color keyword
|
|
11
|
+
* ("Light Blue" -> lightblue)
|
|
12
|
+
*
|
|
13
|
+
* The Liquid snippet's step 2 (the "swatch_color" metaobject matched
|
|
14
|
+
* by label) needs shop.metaobjects, which isn't part of the card
|
|
15
|
+
* data — intentionally skipped in the mirror.
|
|
16
|
+
*/
|
|
17
|
+
import type { CSSProperties } from 'react';
|
|
18
|
+
import type { CardSwatch } from '../../commerce/index.ts';
|
|
19
|
+
/**
|
|
20
|
+
* `style={swatchStyle(value.name, value.swatch)}` ≙
|
|
21
|
+
* `style='{% render 'swatch-style', swatch: value.swatch, name: value.name %}'`
|
|
22
|
+
*/
|
|
23
|
+
export declare function swatchStyle(name: string, swatch?: CardSwatch | null): CSSProperties | undefined;
|