@instruments/materia-ui 0.4.2 → 0.4.3
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/dist/compositions/product-card/product-card-caption.js +4 -2
- package/dist/compositions/product-card/product-card-content-types.d.ts +8 -0
- package/dist/compositions/product-card/product-card-meta.js +2 -2
- package/dist/compositions/product-card/product-card-provider-types.d.ts +3 -0
- package/dist/compositions/product-card/product-card-provider.js +4 -1
- package/dist/compositions/product-card/product-card-root.d.ts +1 -1
- package/dist/compositions/product-card/product-card-root.js +2 -1
- package/dist/compositions/product-card/product-card-skeleton.d.ts +14 -5
- package/dist/compositions/product-card/product-card-skeleton.js +6 -5
- package/dist/data/docs-manifest.js +24 -0
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import { cn } from "@instruments/materia-ui/utils/cn";
|
|
|
5
5
|
import { createElement, useCallback } from "react";
|
|
6
6
|
import { useProductCard } from "./product-card-context.js";
|
|
7
7
|
export const ProductCardCaption = ({ scale = "default", }) => {
|
|
8
|
-
const { availability, currentVariant, linkComponent, linkPrefetch, onCardClick, product, productNameLines, productUrl, showProductBrand, showProductName, } = useProductCard();
|
|
8
|
+
const { availability, currentVariant, linkComponent, linkPrefetch, onCardClick, product, productBrandLines, productNameLines, productUrl, showProductBrand, showProductName, } = useProductCard();
|
|
9
9
|
const handleLinkClick = useCallback((event) => {
|
|
10
10
|
if (onCardClick) {
|
|
11
11
|
event.preventDefault();
|
|
@@ -33,7 +33,9 @@ export const ProductCardCaption = ({ scale = "default", }) => {
|
|
|
33
33
|
prefetch: isExternalUrl ? undefined : linkPrefetch,
|
|
34
34
|
};
|
|
35
35
|
return (_jsxs(_Fragment, { children: [showProductBrand && hasBrandName
|
|
36
|
-
? createElement(LinkComp, linkProps, _jsx(Text, { className: cn(
|
|
36
|
+
? createElement(LinkComp, linkProps, _jsx(Text, { className: cn(productBrandLines === 2
|
|
37
|
+
? "line-clamp-2 text-pretty"
|
|
38
|
+
: "line-clamp-1 truncate", brandSize), weight: "semibold", children: brandName }))
|
|
37
39
|
: null, showProductName
|
|
38
40
|
? createElement(LinkComp, linkProps, _jsx(Text, { className: cn("text-foreground",
|
|
39
41
|
// `truncate` and `line-clamp-2` cannot both apply: truncate
|
|
@@ -16,6 +16,14 @@ interface ProductCardProcessingProps {
|
|
|
16
16
|
interface ProductCardDisplayOptions {
|
|
17
17
|
addToCart?: boolean | undefined;
|
|
18
18
|
brand?: boolean | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* How many lines the brand may occupy before it clamps. One by default.
|
|
21
|
+
* Raise it to two where brands run long - *Scuffmaster Wolf-Gordon* clamps
|
|
22
|
+
* to *Scuffmaster Wolf-...* on one line of a 208px card - and the brand is
|
|
23
|
+
* how people tell the cards apart. Like `nameLines`, the clamp is a maximum,
|
|
24
|
+
* not a reserved height.
|
|
25
|
+
*/
|
|
26
|
+
brandLines?: 1 | 2 | undefined;
|
|
19
27
|
name?: boolean | undefined;
|
|
20
28
|
/**
|
|
21
29
|
* How many lines the product name may occupy before it clamps. One by
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Box } from "@instruments/materia-ui/components/box";
|
|
4
|
+
import { MarqueeText } from "@instruments/materia-ui/components/marquee-text";
|
|
4
5
|
import { HStack } from "@instruments/materia-ui/components/stack";
|
|
5
|
-
import { Text } from "@instruments/materia-ui/components/text";
|
|
6
6
|
import { ProductCardCategory } from "./product-card-category.js";
|
|
7
7
|
import { useProductCard } from "./product-card-context.js";
|
|
8
8
|
import { ProductCardCost, hasProductCardPrice } from "./product-card-cost.js";
|
|
@@ -22,5 +22,5 @@ export const ProductCardMeta = () => {
|
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
const showCostSeparator = showCategory || showProductType;
|
|
25
|
-
return (_jsxs(HStack, { className: "text-muted-foreground text-caption w-full items-center", gap: "none", children: [showCategory ? _jsx(ProductCardCategory, {}) : null, showProductType ? (_jsx(
|
|
25
|
+
return (_jsxs(HStack, { className: "text-muted-foreground text-caption w-full items-center", gap: "none", children: [showCategory ? _jsx(ProductCardCategory, {}) : null, showProductType ? (_jsx(MarqueeText, { children: product.productType ?? "" })) : null, showCost ? (_jsxs(_Fragment, { children: [_jsx(Dot, { show: showCostSeparator }), _jsx(Box, { as: "span", className: "shrink-0", children: _jsx(ProductCardCost, {}) })] })) : null] }));
|
|
26
26
|
};
|
|
@@ -72,6 +72,7 @@ interface ProductCardContextValue {
|
|
|
72
72
|
showingInstallShot: boolean;
|
|
73
73
|
toggleInstallShot: () => void;
|
|
74
74
|
showAddToCart: boolean;
|
|
75
|
+
productBrandLines: 1 | 2;
|
|
75
76
|
productNameLines: 1 | 2;
|
|
76
77
|
showProductBrand: boolean;
|
|
77
78
|
showProductName: boolean;
|
|
@@ -254,6 +255,8 @@ type ProductCardProps = ComponentProps<"div"> & Pick<ProductCardProviderProps, "
|
|
|
254
255
|
overrideImageUrl?: string | undefined;
|
|
255
256
|
/** Prioritise loading images (sets loading="eager" and adds preload link) */
|
|
256
257
|
priority?: boolean | undefined;
|
|
258
|
+
/** How many lines the brand may take before it clamps; see `ProductCardDisplayOptions.brandLines`. */
|
|
259
|
+
productBrandLines?: 1 | 2 | undefined;
|
|
257
260
|
productNameLines?: 1 | 2 | undefined;
|
|
258
261
|
showAddToCart?: boolean | undefined;
|
|
259
262
|
showProductBrand?: boolean | undefined;
|
|
@@ -62,6 +62,7 @@ const useVariantSelection = ({ mode, onVariantChange, product, variantId, }) =>
|
|
|
62
62
|
* renderer exists: no renderAddToCart slot means no cart UI at all.
|
|
63
63
|
*/
|
|
64
64
|
const resolveDisplay = (display, hasRenderAddToCart) => ({
|
|
65
|
+
productBrandLines: display?.brandLines ?? 1,
|
|
65
66
|
productNameLines: display?.nameLines ?? 1,
|
|
66
67
|
showAddToCart: (display?.addToCart ?? true) && hasRenderAddToCart,
|
|
67
68
|
showProductBrand: display?.brand ?? true,
|
|
@@ -94,12 +95,13 @@ const useResolvedCard = ({ availability: availabilityProp, display, mode, onVari
|
|
|
94
95
|
const availability = availabilityProp ??
|
|
95
96
|
(currentVariant.available === false ? "out-of-stock" : "available");
|
|
96
97
|
const productUrl = buildProductUrl(currentVariant);
|
|
97
|
-
const { productNameLines, showAddToCart, showProductBrand, showProductName, showSwatches, } = resolveDisplay(display, renderAddToCart !== undefined);
|
|
98
|
+
const { productBrandLines, productNameLines, showAddToCart, showProductBrand, showProductName, showSwatches, } = resolveDisplay(display, renderAddToCart !== undefined);
|
|
98
99
|
return useMemo(() => ({
|
|
99
100
|
availability,
|
|
100
101
|
currentVariant,
|
|
101
102
|
hasInstallShot,
|
|
102
103
|
onVariantChange: handleVariantChange,
|
|
104
|
+
productBrandLines,
|
|
103
105
|
productNameLines,
|
|
104
106
|
productUrl,
|
|
105
107
|
selectedVariantId,
|
|
@@ -114,6 +116,7 @@ const useResolvedCard = ({ availability: availabilityProp, display, mode, onVari
|
|
|
114
116
|
currentVariant,
|
|
115
117
|
handleVariantChange,
|
|
116
118
|
hasInstallShot,
|
|
119
|
+
productBrandLines,
|
|
117
120
|
productNameLines,
|
|
118
121
|
productUrl,
|
|
119
122
|
selectedVariantId,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ProductCardProps } from "./product-card-types.js";
|
|
2
|
-
declare const ProductCardBase: ({ className, product, variantId, mode, width, active, dragging, availability, labels, showActivePointer, similarityScore, overrideImageUrl, priority, showSwatches, showAddToCart, productNameLines, showProductBrand, showProductName, maxSwatches, menuOpen, onAdd, addGlyph, onFindSimilar, price, processing, onCardClick, onVariantChange, linkAs, productUrl, linkPrefetch, renderTools, renderImage, renderAddToCart, dragAdapter, action, primaryAction, statusBadge, onQuickView, onAddToCartSuccess, ...props }: ProductCardProps & {
|
|
2
|
+
declare const ProductCardBase: ({ className, product, variantId, mode, width, active, dragging, availability, labels, showActivePointer, similarityScore, overrideImageUrl, priority, showSwatches, showAddToCart, productBrandLines, productNameLines, showProductBrand, showProductName, maxSwatches, menuOpen, onAdd, addGlyph, onFindSimilar, price, processing, onCardClick, onVariantChange, linkAs, productUrl, linkPrefetch, renderTools, renderImage, renderAddToCart, dragAdapter, action, primaryAction, statusBadge, onQuickView, onAddToCartSuccess, ...props }: ProductCardProps & {
|
|
3
3
|
onAddToCartSuccess?: (() => void) | undefined;
|
|
4
4
|
}) => import("react").JSX.Element;
|
|
5
5
|
/**
|
|
@@ -3,9 +3,10 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { memo } from "react";
|
|
4
4
|
import { ProductCardContent } from "./product-card-content.js";
|
|
5
5
|
import { ProductCardProvider } from "./product-card-provider.js";
|
|
6
|
-
const ProductCardBase = ({ className, product, variantId, mode = "group", width, active = false, dragging, availability, labels, showActivePointer, similarityScore, overrideImageUrl, priority, showSwatches, showAddToCart, productNameLines, showProductBrand, showProductName, maxSwatches, menuOpen, onAdd, addGlyph, onFindSimilar, price, processing, onCardClick, onVariantChange, linkAs, productUrl, linkPrefetch, renderTools, renderImage, renderAddToCart, dragAdapter, action, primaryAction, statusBadge, onQuickView, onAddToCartSuccess, ...props }) => (_jsx(ProductCardProvider, { action: action, display: {
|
|
6
|
+
const ProductCardBase = ({ className, product, variantId, mode = "group", width, active = false, dragging, availability, labels, showActivePointer, similarityScore, overrideImageUrl, priority, showSwatches, showAddToCart, productBrandLines, productNameLines, showProductBrand, showProductName, maxSwatches, menuOpen, onAdd, addGlyph, onFindSimilar, price, processing, onCardClick, onVariantChange, linkAs, productUrl, linkPrefetch, renderTools, renderImage, renderAddToCart, dragAdapter, action, primaryAction, statusBadge, onQuickView, onAddToCartSuccess, ...props }) => (_jsx(ProductCardProvider, { action: action, display: {
|
|
7
7
|
addToCart: showAddToCart,
|
|
8
8
|
brand: showProductBrand,
|
|
9
|
+
brandLines: productBrandLines,
|
|
9
10
|
name: showProductName,
|
|
10
11
|
nameLines: productNameLines,
|
|
11
12
|
swatches: showSwatches,
|
|
@@ -2,6 +2,14 @@ import type { CSSProperties } from "react";
|
|
|
2
2
|
interface ProductCardSkeletonProps {
|
|
3
3
|
className?: string;
|
|
4
4
|
style?: CSSProperties;
|
|
5
|
+
/**
|
|
6
|
+
* Draw the add-to-cart control. True by default; pass the same value as the
|
|
7
|
+
* card's `showAddToCart` so a grid without a cart keeps its height when the
|
|
8
|
+
* products arrive.
|
|
9
|
+
*/
|
|
10
|
+
showAddToCart?: boolean;
|
|
11
|
+
/** Draw the row of colourway dots. True by default; pass the card's `showSwatches`. */
|
|
12
|
+
showSwatches?: boolean;
|
|
5
13
|
}
|
|
6
14
|
/**
|
|
7
15
|
* Loading placeholder for `ProductCard`, at whatever size it is given.
|
|
@@ -19,10 +27,11 @@ interface ProductCardSkeletonProps {
|
|
|
19
27
|
* frame's bottom above it), the same padding, gaps and radius steps. Copying
|
|
20
28
|
* the classes keeps it in step as the card changes.
|
|
21
29
|
*
|
|
22
|
-
* It draws the control
|
|
23
|
-
* renders
|
|
24
|
-
* placeholder shorter than every card that does have one,
|
|
25
|
-
* case instead.
|
|
30
|
+
* It draws the control and the swatch row by default. A card whose product has
|
|
31
|
+
* no capability renders no control, so the placeholder overshoots that case -
|
|
32
|
+
* the reverse error, a placeholder shorter than every card that does have one,
|
|
33
|
+
* misjudged the common case instead. A grid that turns either off on every
|
|
34
|
+
* card passes the same flags here.
|
|
26
35
|
*/
|
|
27
|
-
export declare const ProductCardSkeleton: ({ className, style, }: ProductCardSkeletonProps) => import("react").JSX.Element;
|
|
36
|
+
export declare const ProductCardSkeleton: ({ className, showAddToCart, showSwatches, style, }: ProductCardSkeletonProps) => import("react").JSX.Element;
|
|
28
37
|
export {};
|
|
@@ -23,9 +23,10 @@ const SwatchRow = () => (_jsx(HStack, { className: "min-h-5 gap-2.5", children:
|
|
|
23
23
|
* frame's bottom above it), the same padding, gaps and radius steps. Copying
|
|
24
24
|
* the classes keeps it in step as the card changes.
|
|
25
25
|
*
|
|
26
|
-
* It draws the control
|
|
27
|
-
* renders
|
|
28
|
-
* placeholder shorter than every card that does have one,
|
|
29
|
-
* case instead.
|
|
26
|
+
* It draws the control and the swatch row by default. A card whose product has
|
|
27
|
+
* no capability renders no control, so the placeholder overshoots that case -
|
|
28
|
+
* the reverse error, a placeholder shorter than every card that does have one,
|
|
29
|
+
* misjudged the common case instead. A grid that turns either off on every
|
|
30
|
+
* card passes the same flags here.
|
|
30
31
|
*/
|
|
31
|
-
export const ProductCardSkeleton = ({ className, style, }) => (_jsxs(Box, { className: cn("@container/product-card w-full", className), style: style, children: [_jsxs(VStack, { className: "flex @[180px]/product-card:hidden", gap: "none", children: [_jsx(Skeleton, { className: "aspect-square w-full rounded-3xl" }), _jsxs(VStack, { className: "gap-2.5 px-1.5 py-2", gap: "none", children: [_jsxs(VStack, { className: "gap-1 px-0.5", gap: "none", children: [_jsxs(VStack, { className: "gap-0.5", gap: "none", children: [_jsx(Skeleton, { className: "h-5 w-3/5" }), _jsx(Skeleton, { className: "h-4 w-4/5" })] }), _jsx(Skeleton, { className: "h-4 w-2/3" }), _jsx(SwatchRow, {})] }), _jsx(Skeleton, { className: "h-9 w-full rounded-full" })] })] }), _jsxs(VStack, { className: "bg-card hidden overflow-hidden rounded-3xl shadow-xs @[180px]/product-card:flex @[240px]/product-card:rounded-4xl", gap: "none", children: [_jsx(Box, { className: "w-full px-4 pt-4", children: _jsx(Skeleton, { className: "aspect-square w-full rounded-2xl", variant: "light" }) }), _jsx(VStack, { className: "pt-2 pb-4", gap: "none", children: _jsxs(VStack, { className: "gap-2.5 px-4 @[240px]/product-card:gap-4", gap: "none", children: [_jsxs(VStack, { className: "gap-1 px-0.5", gap: "none", children: [_jsxs(VStack, { gap: "none", children: [_jsx(Skeleton, { className: "h-5.5 w-3/5 rounded", variant: "light" }), _jsx(Skeleton, { className: "h-5 w-4/5 rounded", variant: "light" })] }), _jsx(Skeleton, { className: "h-4 w-2/3 rounded", variant: "light" }), _jsx(Box, { className: "pt-1", children: _jsx(SwatchRow, {}) })] }), _jsx(HStack, { children: _jsx(Skeleton, { className: "h-9 w-full rounded-full @[240px]/product-card:w-32", variant: "light" }) })] }) })] })] }));
|
|
32
|
+
export const ProductCardSkeleton = ({ className, showAddToCart = true, showSwatches = true, style, }) => (_jsxs(Box, { className: cn("@container/product-card w-full", className), style: style, children: [_jsxs(VStack, { className: "flex @[180px]/product-card:hidden", gap: "none", children: [_jsx(Skeleton, { className: "aspect-square w-full rounded-3xl" }), _jsxs(VStack, { className: "gap-2.5 px-1.5 py-2", gap: "none", children: [_jsxs(VStack, { className: "gap-1 px-0.5", gap: "none", children: [_jsxs(VStack, { className: "gap-0.5", gap: "none", children: [_jsx(Skeleton, { className: "h-5 w-3/5" }), _jsx(Skeleton, { className: "h-4 w-4/5" })] }), _jsx(Skeleton, { className: "h-4 w-2/3" }), showSwatches ? _jsx(SwatchRow, {}) : null] }), showAddToCart ? (_jsx(Skeleton, { className: "h-9 w-full rounded-full" })) : null] })] }), _jsxs(VStack, { className: "bg-card hidden overflow-hidden rounded-3xl shadow-xs @[180px]/product-card:flex @[240px]/product-card:rounded-4xl", gap: "none", children: [_jsx(Box, { className: "w-full px-4 pt-4", children: _jsx(Skeleton, { className: "aspect-square w-full rounded-2xl", variant: "light" }) }), _jsx(VStack, { className: "pt-2 pb-4", gap: "none", children: _jsxs(VStack, { className: "gap-2.5 px-4 @[240px]/product-card:gap-4", gap: "none", children: [_jsxs(VStack, { className: "gap-1 px-0.5", gap: "none", children: [_jsxs(VStack, { gap: "none", children: [_jsx(Skeleton, { className: "h-5.5 w-3/5 rounded", variant: "light" }), _jsx(Skeleton, { className: "h-5 w-4/5 rounded", variant: "light" })] }), _jsx(Skeleton, { className: "h-4 w-2/3 rounded", variant: "light" }), showSwatches ? (_jsx(Box, { className: "pt-1", children: _jsx(SwatchRow, {}) })) : null] }), showAddToCart ? (_jsx(HStack, { children: _jsx(Skeleton, { className: "h-9 w-full rounded-full @[240px]/product-card:w-32", variant: "light" }) })) : null] }) })] })] }));
|
|
@@ -18761,6 +18761,12 @@ export const docsManifest = {
|
|
|
18761
18761
|
required: false,
|
|
18762
18762
|
description: 'Prioritise loading images (sets loading="eager" and adds preload link)',
|
|
18763
18763
|
},
|
|
18764
|
+
{
|
|
18765
|
+
name: "productBrandLines",
|
|
18766
|
+
type: "1 | 2 | undefined",
|
|
18767
|
+
required: false,
|
|
18768
|
+
description: "How many lines the brand may take before it clamps; see `ProductCardDisplayOptions.brandLines`.",
|
|
18769
|
+
},
|
|
18764
18770
|
{
|
|
18765
18771
|
name: "productNameLines",
|
|
18766
18772
|
type: "1 | 2 | undefined",
|
|
@@ -18981,6 +18987,12 @@ export const docsManifest = {
|
|
|
18981
18987
|
required: false,
|
|
18982
18988
|
description: 'Prioritise loading images (sets loading="eager" and adds preload link)',
|
|
18983
18989
|
},
|
|
18990
|
+
{
|
|
18991
|
+
name: "productBrandLines",
|
|
18992
|
+
type: "1 | 2 | undefined",
|
|
18993
|
+
required: false,
|
|
18994
|
+
description: "How many lines the brand may take before it clamps; see `ProductCardDisplayOptions.brandLines`.",
|
|
18995
|
+
},
|
|
18984
18996
|
{
|
|
18985
18997
|
name: "productNameLines",
|
|
18986
18998
|
type: "1 | 2 | undefined",
|
|
@@ -19470,6 +19482,18 @@ export const docsManifest = {
|
|
|
19470
19482
|
type: "CSSProperties",
|
|
19471
19483
|
required: false,
|
|
19472
19484
|
},
|
|
19485
|
+
{
|
|
19486
|
+
name: "showAddToCart",
|
|
19487
|
+
type: "boolean",
|
|
19488
|
+
required: false,
|
|
19489
|
+
description: "Draw the add-to-cart control. True by default; pass the same value as the\ncard's `showAddToCart` so a grid without a cart keeps its height when the\nproducts arrive.",
|
|
19490
|
+
},
|
|
19491
|
+
{
|
|
19492
|
+
name: "showSwatches",
|
|
19493
|
+
type: "boolean",
|
|
19494
|
+
required: false,
|
|
19495
|
+
description: "Draw the row of colourway dots. True by default; pass the card's `showSwatches`.",
|
|
19496
|
+
},
|
|
19473
19497
|
],
|
|
19474
19498
|
},
|
|
19475
19499
|
{
|