@enadhq/enad-react-sdk 1.1.0 → 1.3.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/dist/client/cart/components/cart-drawer.mjs +3 -3
- package/dist/client/cart/components/cart-drawer.mjs.map +1 -1
- package/dist/client/cart/components/cart-trigger.mjs +1 -1
- package/dist/client/cart/components/cart-trigger.mjs.map +1 -1
- package/dist/client/storefront/blocks/card-video.mjs +1 -1
- package/dist/client/storefront/blocks/card-video.mjs.map +1 -1
- package/dist/client/storefront/blocks/gallery-with-link-blocks.d.ts.map +1 -1
- package/dist/client/storefront/blocks/gallery-with-link-blocks.mjs +13 -5
- package/dist/client/storefront/blocks/gallery-with-link-blocks.mjs.map +1 -1
- package/dist/client/storefront/blocks/gallery.d.ts +10 -1
- package/dist/client/storefront/blocks/gallery.d.ts.map +1 -1
- package/dist/client/storefront/blocks/gallery.mjs +51 -27
- package/dist/client/storefront/blocks/gallery.mjs.map +1 -1
- package/dist/client/storefront/blocks/hero.d.ts +12 -1
- package/dist/client/storefront/blocks/hero.d.ts.map +1 -1
- package/dist/client/storefront/blocks/hero.mjs +143 -145
- package/dist/client/storefront/blocks/hero.mjs.map +1 -1
- package/dist/client/storefront/blocks/link-block-small.d.ts.map +1 -1
- package/dist/client/storefront/blocks/link-block-small.mjs +1 -1
- package/dist/client/storefront/blocks/link-block-small.mjs.map +1 -1
- package/dist/client/storefront/blocks/link-block.d.ts.map +1 -1
- package/dist/client/storefront/blocks/link-block.mjs +4 -4
- package/dist/client/storefront/blocks/link-block.mjs.map +1 -1
- package/dist/client/storefront/blocks/product-card-parts.d.ts +1 -1
- package/dist/client/storefront/blocks/product-card-parts.d.ts.map +1 -1
- package/dist/client/storefront/blocks/product-card-parts.mjs +2 -2
- package/dist/client/storefront/blocks/product-card-parts.mjs.map +1 -1
- package/dist/client/storefront/blocks/product-card.d.ts +10 -1
- package/dist/client/storefront/blocks/product-card.d.ts.map +1 -1
- package/dist/client/storefront/blocks/product-card.mjs +122 -116
- package/dist/client/storefront/blocks/product-card.mjs.map +1 -1
- package/dist/client/storefront/blocks/product-image.mjs +2 -2
- package/dist/client/storefront/blocks/product-image.mjs.map +1 -1
- package/dist/client/storefront/blocks/text-content-with-image.d.ts +14 -1
- package/dist/client/storefront/blocks/text-content-with-image.d.ts.map +1 -1
- package/dist/client/storefront/blocks/text-content-with-image.mjs +141 -164
- package/dist/client/storefront/blocks/text-content-with-image.mjs.map +1 -1
- package/dist/client/storefront/carousel/swipeable-carousel.d.ts +5 -1
- package/dist/client/storefront/carousel/swipeable-carousel.d.ts.map +1 -1
- package/dist/client/storefront/carousel/swipeable-carousel.mjs +2 -1
- package/dist/client/storefront/carousel/swipeable-carousel.mjs.map +1 -1
- package/dist/client/storefront/checkout/cart-summary.mjs +1 -1
- package/dist/client/storefront/checkout/cart-summary.mjs.map +1 -1
- package/dist/client/storefront/components/language-selector.d.ts.map +1 -1
- package/dist/client/storefront/components/language-selector.mjs +1 -1
- package/dist/client/storefront/components/language-selector.mjs.map +1 -1
- package/dist/client/storefront/components/product-recommendations.d.ts.map +1 -1
- package/dist/client/storefront/components/product-recommendations.mjs +29 -37
- package/dist/client/storefront/components/product-recommendations.mjs.map +1 -1
- package/dist/client/storefront/filters/filter-chip.d.ts +5 -2
- package/dist/client/storefront/filters/filter-chip.d.ts.map +1 -1
- package/dist/client/storefront/filters/filter-chip.mjs +6 -4
- package/dist/client/storefront/filters/filter-chip.mjs.map +1 -1
- package/dist/client/storefront/filters/filter-panel.mjs +2 -2
- package/dist/client/storefront/filters/filter-panel.mjs.map +1 -1
- package/dist/client/storefront/filters/toggle-list-view.mjs +1 -1
- package/dist/client/storefront/filters/toggle-list-view.mjs.map +1 -1
- package/dist/client/storefront/index.d.ts +12 -1
- package/dist/client/storefront/index.mjs +12 -1
- package/dist/client/storefront/layout/header.d.ts.map +1 -1
- package/dist/client/storefront/layout/header.mjs +1 -1
- package/dist/client/storefront/layout/header.mjs.map +1 -1
- package/dist/client/storefront/layout/mobile-menu-drawer.mjs +1 -1
- package/dist/client/storefront/layout/promotion-bar.d.ts.map +1 -1
- package/dist/client/storefront/layout/promotion-bar.mjs +3 -3
- package/dist/client/storefront/layout/promotion-bar.mjs.map +1 -1
- package/dist/client/storefront/primitives/block-heading.d.ts +40 -0
- package/dist/client/storefront/primitives/block-heading.d.ts.map +1 -0
- package/dist/client/storefront/primitives/block-heading.mjs +43 -0
- package/dist/client/storefront/primitives/block-heading.mjs.map +1 -0
- package/dist/client/storefront/primitives/button.d.ts +2 -2
- package/dist/client/storefront/primitives/button.d.ts.map +1 -1
- package/dist/client/storefront/primitives/button.mjs +4 -4
- package/dist/client/storefront/primitives/button.mjs.map +1 -1
- package/dist/client/storefront/primitives/cta-group.d.ts +25 -0
- package/dist/client/storefront/primitives/cta-group.d.ts.map +1 -0
- package/dist/client/storefront/primitives/cta-group.mjs +27 -0
- package/dist/client/storefront/primitives/cta-group.mjs.map +1 -0
- package/dist/client/storefront/primitives/image-with-hover.d.ts +18 -0
- package/dist/client/storefront/primitives/image-with-hover.d.ts.map +1 -0
- package/dist/client/storefront/primitives/image-with-hover.mjs +16 -0
- package/dist/client/storefront/primitives/image-with-hover.mjs.map +1 -0
- package/dist/client/storefront/primitives/index.d.ts +4 -1
- package/dist/client/storefront/primitives/index.mjs +4 -1
- package/dist/client/storefront/primitives/input.d.ts +1 -1
- package/dist/client/storefront/primitives/input.mjs.map +1 -1
- package/dist/client/storefront/primitives/pagination.mjs +2 -2
- package/dist/client/storefront/primitives/pagination.mjs.map +1 -1
- package/dist/client/storefront/product/quantity-picker.mjs +2 -2
- package/dist/client/storefront/product/quantity-picker.mjs.map +1 -1
- package/dist/client/storefront/types.d.ts +1 -1
- package/dist/client/storefront/types.d.ts.map +1 -1
- package/dist/client/storefront/types.mjs.map +1 -1
- package/dist/client/theme/apply.d.ts +1 -1
- package/dist/client/theme/apply.d.ts.map +1 -1
- package/dist/client/theme/apply.mjs +0 -12
- package/dist/client/theme/apply.mjs.map +1 -1
- package/dist/client/theme/cli.mjs +0 -16
- package/dist/client/theme/cli.mjs.map +1 -1
- package/dist/client/theme/codec.d.ts.map +1 -1
- package/dist/client/theme/codec.mjs +0 -2
- package/dist/client/theme/codec.mjs.map +1 -1
- package/dist/client/theme/defaults.d.ts +0 -2
- package/dist/client/theme/defaults.mjs +0 -2
- package/dist/client/theme/defaults.mjs.map +1 -1
- package/dist/client/ui/accordion.d.ts +12 -1
- package/dist/client/ui/accordion.d.ts.map +1 -1
- package/dist/client/ui/accordion.mjs +23 -5
- package/dist/client/ui/accordion.mjs.map +1 -1
- package/dist/client/ui/alert.d.ts +16 -7
- package/dist/client/ui/alert.d.ts.map +1 -1
- package/dist/client/ui/alert.mjs +21 -8
- package/dist/client/ui/alert.mjs.map +1 -1
- package/dist/client/ui/avatar.d.ts +10 -1
- package/dist/client/ui/avatar.d.ts.map +1 -1
- package/dist/client/ui/avatar.mjs +18 -4
- package/dist/client/ui/avatar.mjs.map +1 -1
- package/dist/client/ui/breadcrumb.d.ts +13 -1
- package/dist/client/ui/breadcrumb.d.ts.map +1 -1
- package/dist/client/ui/breadcrumb.mjs +27 -7
- package/dist/client/ui/breadcrumb.mjs.map +1 -1
- package/dist/client/ui/button.d.ts +28 -10
- package/dist/client/ui/button.d.ts.map +1 -1
- package/dist/client/ui/button.mjs +45 -20
- package/dist/client/ui/button.mjs.map +1 -1
- package/dist/client/ui/card.d.ts +20 -1
- package/dist/client/ui/card.d.ts.map +1 -1
- package/dist/client/ui/card.mjs +36 -8
- package/dist/client/ui/card.mjs.map +1 -1
- package/dist/client/ui/carousel.d.ts +9 -1
- package/dist/client/ui/carousel.d.ts.map +1 -1
- package/dist/client/ui/carousel.mjs +20 -4
- package/dist/client/ui/carousel.mjs.map +1 -1
- package/dist/client/ui/checkbox.d.ts +9 -1
- package/dist/client/ui/checkbox.d.ts.map +1 -1
- package/dist/client/ui/checkbox.mjs +12 -3
- package/dist/client/ui/checkbox.mjs.map +1 -1
- package/dist/client/ui/dialog.d.ts +13 -1
- package/dist/client/ui/dialog.d.ts.map +1 -1
- package/dist/client/ui/dialog.mjs +27 -7
- package/dist/client/ui/dialog.mjs.map +1 -1
- package/dist/client/ui/hover-card.d.ts +6 -1
- package/dist/client/ui/hover-card.d.ts.map +1 -1
- package/dist/client/ui/hover-card.mjs +4 -2
- package/dist/client/ui/hover-card.mjs.map +1 -1
- package/dist/client/ui/input.d.ts +20 -7
- package/dist/client/ui/input.d.ts.map +1 -1
- package/dist/client/ui/input.mjs +33 -9
- package/dist/client/ui/input.mjs.map +1 -1
- package/dist/client/ui/label.d.ts +6 -1
- package/dist/client/ui/label.d.ts.map +1 -1
- package/dist/client/ui/label.mjs +4 -2
- package/dist/client/ui/label.mjs.map +1 -1
- package/dist/client/ui/navigation-menu.d.ts +20 -3
- package/dist/client/ui/navigation-menu.d.ts.map +1 -1
- package/dist/client/ui/navigation-menu.mjs +34 -12
- package/dist/client/ui/navigation-menu.mjs.map +1 -1
- package/dist/client/ui/pagination.d.ts.map +1 -1
- package/dist/client/ui/pagination.mjs +3 -3
- package/dist/client/ui/pagination.mjs.map +1 -1
- package/dist/client/ui/popover.d.ts +11 -1
- package/dist/client/ui/popover.d.ts.map +1 -1
- package/dist/client/ui/popover.mjs +21 -5
- package/dist/client/ui/popover.mjs.map +1 -1
- package/dist/client/ui/progress.d.ts +9 -1
- package/dist/client/ui/progress.d.ts.map +1 -1
- package/dist/client/ui/progress.mjs +12 -3
- package/dist/client/ui/progress.mjs.map +1 -1
- package/dist/client/ui/select.d.ts +14 -2
- package/dist/client/ui/select.d.ts.map +1 -1
- package/dist/client/ui/select.mjs +35 -9
- package/dist/client/ui/select.mjs.map +1 -1
- package/dist/client/ui/separator.d.ts +6 -1
- package/dist/client/ui/separator.d.ts.map +1 -1
- package/dist/client/ui/separator.mjs +4 -2
- package/dist/client/ui/separator.mjs.map +1 -1
- package/dist/client/ui/sheet.d.ts +13 -1
- package/dist/client/ui/sheet.d.ts.map +1 -1
- package/dist/client/ui/sheet.mjs +35 -7
- package/dist/client/ui/sheet.mjs.map +1 -1
- package/dist/client/ui/slot-wrapper.d.ts +28 -0
- package/dist/client/ui/slot-wrapper.d.ts.map +1 -0
- package/dist/client/ui/slot-wrapper.mjs +38 -0
- package/dist/client/ui/slot-wrapper.mjs.map +1 -0
- package/dist/client/ui/tabs.d.ts +11 -1
- package/dist/client/ui/tabs.d.ts.map +1 -1
- package/dist/client/ui/tabs.mjs +21 -5
- package/dist/client/ui/tabs.mjs.map +1 -1
- package/dist/client/ui/toggle-group.d.ts +7 -4
- package/dist/client/ui/toggle-group.d.ts.map +1 -1
- package/dist/client/ui/toggle-group.mjs +4 -4
- package/dist/client/ui/toggle-group.mjs.map +1 -1
- package/dist/client/ui/toggle.d.ts +17 -8
- package/dist/client/ui/toggle.d.ts.map +1 -1
- package/dist/client/ui/toggle.mjs +11 -9
- package/dist/client/ui/toggle.mjs.map +1 -1
- package/dist/client/ui/tooltip.d.ts +6 -1
- package/dist/client/ui/tooltip.d.ts.map +1 -1
- package/dist/client/ui/tooltip.mjs +4 -2
- package/dist/client/ui/tooltip.mjs.map +1 -1
- package/dist/client/ui-resolver/button.d.ts +3 -4
- package/dist/client/ui-resolver/button.d.ts.map +1 -1
- package/dist/client/ui-resolver/button.mjs +2 -2
- package/dist/client/ui-resolver/button.mjs.map +1 -1
- package/dist/client/ui-resolver/card.d.ts +14 -1
- package/dist/client/ui-resolver/card.d.ts.map +1 -1
- package/dist/client/ui-resolver/card.mjs +3 -2
- package/dist/client/ui-resolver/card.mjs.map +1 -1
- package/dist/client/ui-resolver/context.mjs +1 -1
- package/dist/client/ui-resolver/context.mjs.map +1 -1
- package/dist/client/ui-resolver/index.d.ts +7 -4
- package/dist/client/ui-resolver/index.mjs +8 -6
- package/dist/client/ui-resolver/input.d.ts +3 -4
- package/dist/client/ui-resolver/input.d.ts.map +1 -1
- package/dist/client/ui-resolver/input.mjs +2 -2
- package/dist/client/ui-resolver/input.mjs.map +1 -1
- package/dist/client/ui-resolver/navigation-menu.d.ts +1 -2
- package/dist/client/ui-resolver/navigation-menu.d.ts.map +1 -1
- package/dist/client/ui-resolver/recipe.d.ts +95 -0
- package/dist/client/ui-resolver/recipe.d.ts.map +1 -0
- package/dist/client/ui-resolver/recipe.mjs +134 -0
- package/dist/client/ui-resolver/recipe.mjs.map +1 -0
- package/dist/client/ui-resolver/toggle.d.ts +2 -2
- package/dist/client/ui-resolver/toggle.mjs +2 -2
- package/dist/client/ui-resolver/toggle.mjs.map +1 -1
- package/dist/client/ui-resolver/types.d.ts +14 -0
- package/dist/client/ui-resolver/types.d.ts.map +1 -0
- package/dist/client/ui-resolver/types.mjs +1 -0
- package/dist/client/wishlist/wishlist-drawer.mjs +4 -4
- package/dist/client/wishlist/wishlist-drawer.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-card-parts.mjs","names":[],"sources":["../../../../src/client/storefront/blocks/product-card-parts.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../ui/utils\";\n\n/* ─── ProductCard compound sub-components ─── */\n\n/**\n * Root container for a composable product card.\n * Provides
|
|
1
|
+
{"version":3,"file":"product-card-parts.mjs","names":[],"sources":["../../../../src/client/storefront/blocks/product-card-parts.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../ui/utils\";\n\n/* ─── ProductCard compound sub-components ─── */\n\n/**\n * Root container for a composable product card.\n * Provides grouping and overflow handling for composed layouts.\n */\nfunction ProductCardRoot({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"product-card\"\n className={cn(\"group overflow-hidden rounded-[var(--enad-card-radius)]\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Container for the product image area.\n * Use as a wrapper for ProductCardImage, ProductCardTag, and ProductCardFavoriteButton.\n */\nfunction ProductCardImageArea({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"product-card-image-area\"\n className={cn(\"relative bg-muted\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Product image with lazy loading.\n */\nfunction ProductCardImage({\n className,\n alt = \"\",\n loading = \"lazy\",\n ...props\n}: React.ComponentProps<\"img\">) {\n return (\n <img\n data-slot=\"product-card-image\"\n alt={alt}\n loading={loading}\n className={cn(\"size-full object-cover\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Badge overlay for product status (Sale, New, etc.).\n * Positioned absolutely within ProductCardImageArea by default.\n */\nfunction ProductCardTag({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"product-card-tag\"\n className={cn(\n \"absolute start-3 top-3 rounded-[var(--enad-card-radius)] bg-background/90 px-2 py-0.5 text-xs font-medium text-foreground\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Favorite/wishlist toggle button.\n * Stops event propagation by default (safe inside links).\n */\nfunction ProductCardFavoriteButton({\n className,\n onClick,\n ...props\n}: React.ComponentProps<\"button\">) {\n return (\n <button\n type=\"button\"\n data-slot=\"product-card-favorite\"\n className={cn(\n \"rounded-full bg-background/80 p-1.5 text-foreground transition-colors hover:bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n className,\n )}\n aria-label=\"Add to favorites\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick?.(e);\n }}\n {...props}\n />\n );\n}\n\n/**\n * Container for product text content (title, subtitle, price).\n */\nfunction ProductCardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"product-card-content\"\n className={cn(\"flex min-w-0 flex-col gap-0.5 p-3\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Product name / title.\n */\nfunction ProductCardTitle({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"product-card-title\"\n className={cn(\"line-clamp-2 text-sm font-medium text-foreground\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Secondary text (category, brand, etc.).\n */\nfunction ProductCardSubtitle({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"product-card-subtitle\"\n className={cn(\"truncate text-sm text-muted-foreground\", className)}\n {...props}\n />\n );\n}\n\n/**\n * Price display.\n */\nfunction ProductCardPrice({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"product-card-price\"\n className={cn(\"text-sm font-medium text-foreground\", className)}\n {...props}\n />\n );\n}\n\nexport {\n ProductCardRoot,\n ProductCardImageArea,\n ProductCardImage,\n ProductCardTag,\n ProductCardFavoriteButton,\n ProductCardContent,\n ProductCardTitle,\n ProductCardSubtitle,\n ProductCardPrice,\n};\n"],"mappings":";;;;;;;;;AAWA,SAAS,gBAAgB,EAAE,WAAW,GAAG,SAAsC;AAC7E,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,2DAA2D,UAAU;EACnF,GAAI;EACJ,CAAA;;;;;;AAQN,SAAS,qBAAqB,EAAE,WAAW,GAAG,SAAsC;AAClF,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,qBAAqB,UAAU;EAC7C,GAAI;EACJ,CAAA;;;;;AAON,SAAS,iBAAiB,EACxB,WACA,MAAM,IACN,UAAU,QACV,GAAG,SAC2B;AAC9B,QACE,oBAAC,OAAD;EACE,aAAU;EACL;EACI;EACT,WAAW,GAAG,0BAA0B,UAAU;EAClD,GAAI;EACJ,CAAA;;;;;;AAQN,SAAS,eAAe,EAAE,WAAW,GAAG,SAAuC;AAC7E,QACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GACT,6HACA,UACD;EACD,GAAI;EACJ,CAAA;;;;;;AAQN,SAAS,0BAA0B,EACjC,WACA,SACA,GAAG,SAC8B;AACjC,QACE,oBAAC,UAAD;EACE,MAAK;EACL,aAAU;EACV,WAAW,GACT,qKACA,UACD;EACD,cAAW;EACX,UAAU,MAAM;AACd,KAAE,gBAAgB;AAClB,KAAE,iBAAiB;AACnB,aAAU,EAAE;;EAEd,GAAI;EACJ,CAAA;;;;;AAON,SAAS,mBAAmB,EAAE,WAAW,GAAG,SAAsC;AAChF,QACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,qCAAqC,UAAU;EAC7D,GAAI;EACJ,CAAA;;;;;AAON,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAoC;AAC5E,QACE,oBAAC,KAAD;EACE,aAAU;EACV,WAAW,GAAG,oDAAoD,UAAU;EAC5E,GAAI;EACJ,CAAA;;;;;AAON,SAAS,oBAAoB,EAAE,WAAW,GAAG,SAAoC;AAC/E,QACE,oBAAC,KAAD;EACE,aAAU;EACV,WAAW,GAAG,0CAA0C,UAAU;EAClE,GAAI;EACJ,CAAA;;;;;AAON,SAAS,iBAAiB,EAAE,WAAW,GAAG,SAAuC;AAC/E,QACE,oBAAC,QAAD;EACE,aAAU;EACV,WAAW,GAAG,uCAAuC,UAAU;EAC/D,GAAI;EACJ,CAAA"}
|
|
@@ -2,7 +2,16 @@ import { ProductCardProps } from "../types.js";
|
|
|
2
2
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/client/storefront/blocks/product-card.d.ts
|
|
5
|
+
declare const productCardRecipe: (props?: ({
|
|
6
|
+
layout?: "gallery" | "list" | "minimal" | "horizontal" | "stripped" | undefined;
|
|
7
|
+
} & {
|
|
8
|
+
className?: Partial<Record<"root" | "content" | "imageWrapper", string>> | undefined;
|
|
9
|
+
}) | undefined) => {
|
|
10
|
+
root: string;
|
|
11
|
+
content: string;
|
|
12
|
+
imageWrapper: string;
|
|
13
|
+
};
|
|
5
14
|
declare function ProductCard(props: ProductCardProps): react_jsx_runtime0.JSX.Element;
|
|
6
15
|
//#endregion
|
|
7
|
-
export { ProductCard, type ProductCardProps };
|
|
16
|
+
export { ProductCard, type ProductCardProps, productCardRecipe };
|
|
8
17
|
//# sourceMappingURL=product-card.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-card.d.ts","names":[],"sources":["../../../../src/client/storefront/blocks/product-card.tsx"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"product-card.d.ts","names":[],"sources":["../../../../src/client/storefront/blocks/product-card.tsx"],"mappings":";;;;cAuBM,iBAAA,GAAiB,KAAA;;;cAmCrB,OAAA,CAAA,MAAA;AAAA;;;;;iBAgQO,WAAA,CAAY,KAAA,EAAO,gBAAA,GAAgB,kBAAA,CAAA,GAAA,CAAA,OAAA"}
|
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useIcon } from "../../icons/icon-context.mjs";
|
|
3
3
|
import { cn } from "../../ui/utils.mjs";
|
|
4
|
+
import { defineSlotRecipe } from "../../ui-resolver/recipe.mjs";
|
|
4
5
|
import { useVariantDefault } from "../../ui-resolver/context.mjs";
|
|
5
6
|
import { SwipeableCarousel } from "../carousel/swipeable-carousel.mjs";
|
|
6
7
|
import { ProductCardContent, ProductCardFavoriteButton, ProductCardImage, ProductCardImageArea, ProductCardPrice, ProductCardRoot, ProductCardSubtitle, ProductCardTag, ProductCardTitle } from "./product-card-parts.mjs";
|
|
7
8
|
import "react";
|
|
8
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
10
|
//#region src/client/storefront/blocks/product-card.tsx
|
|
11
|
+
const productCardRecipe = defineSlotRecipe({
|
|
12
|
+
slots: [
|
|
13
|
+
"root",
|
|
14
|
+
"imageWrapper",
|
|
15
|
+
"content"
|
|
16
|
+
],
|
|
17
|
+
base: {
|
|
18
|
+
root: "",
|
|
19
|
+
imageWrapper: "relative",
|
|
20
|
+
content: ""
|
|
21
|
+
},
|
|
22
|
+
variants: { layout: {
|
|
23
|
+
gallery: {
|
|
24
|
+
root: "shadow-none",
|
|
25
|
+
content: "flex min-w-0 flex-col gap-[var(--enad-product-card-content-gap,0.125rem)] p-[var(--enad-product-card-content-py,0.75rem)]"
|
|
26
|
+
},
|
|
27
|
+
horizontal: {
|
|
28
|
+
root: "flex shadow-[var(--enad-card-shadow)]",
|
|
29
|
+
imageWrapper: "w-1/3 shrink-0",
|
|
30
|
+
content: "flex min-w-0 flex-1 flex-col justify-center gap-0 p-4 md:p-6"
|
|
31
|
+
},
|
|
32
|
+
minimal: {
|
|
33
|
+
root: "relative",
|
|
34
|
+
content: ""
|
|
35
|
+
},
|
|
36
|
+
list: {
|
|
37
|
+
root: "flex shadow-none",
|
|
38
|
+
imageWrapper: "w-32 shrink-0",
|
|
39
|
+
content: "flex min-w-0 flex-1 flex-col justify-center p-4"
|
|
40
|
+
},
|
|
41
|
+
stripped: {
|
|
42
|
+
root: "rounded-none shadow-none",
|
|
43
|
+
content: ""
|
|
44
|
+
}
|
|
45
|
+
} },
|
|
46
|
+
defaultVariants: { layout: "gallery" }
|
|
47
|
+
});
|
|
10
48
|
function OptionalLink({ href, radiusClass, children }) {
|
|
11
49
|
if (!href) return children;
|
|
12
50
|
return /* @__PURE__ */ jsx("a", {
|
|
@@ -29,40 +67,95 @@ function GalleryImageArea({ imageElements, fallback, showPaginationDots }) {
|
|
|
29
67
|
if (imageElements.length === 1) return imageElements[0];
|
|
30
68
|
return fallback;
|
|
31
69
|
}
|
|
32
|
-
function
|
|
70
|
+
function VerticalCard({ images = [], title, subtitle, price, tag, href, layout = "gallery", showFavorites = false, showPaginationDots = true, onFavoriteClick, className, HeartIcon }) {
|
|
71
|
+
const classes = productCardRecipe({ layout });
|
|
72
|
+
const isStripped = layout === "stripped";
|
|
73
|
+
const imageElements = images.map((img, i) => /* @__PURE__ */ jsx(ProductCardImageArea, {
|
|
74
|
+
className: "aspect-[var(--enad-image-product-aspect)]",
|
|
75
|
+
children: /* @__PURE__ */ jsx(ProductCardImage, {
|
|
76
|
+
src: img.src,
|
|
77
|
+
alt: img.alt ?? title ?? ""
|
|
78
|
+
})
|
|
79
|
+
}, i));
|
|
33
80
|
return /* @__PURE__ */ jsx(OptionalLink, {
|
|
34
81
|
href,
|
|
35
82
|
children: /* @__PURE__ */ jsxs(ProductCardRoot, {
|
|
36
|
-
className: cn(
|
|
83
|
+
className: cn(classes.root, className),
|
|
84
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
85
|
+
className: classes.imageWrapper,
|
|
86
|
+
children: isStripped ? /* @__PURE__ */ jsx("div", {
|
|
87
|
+
className: "overflow-hidden",
|
|
88
|
+
children: images[0] ? /* @__PURE__ */ jsx(ProductCardImageArea, {
|
|
89
|
+
className: "aspect-[var(--enad-image-product-aspect)]",
|
|
90
|
+
children: /* @__PURE__ */ jsx(ProductCardImage, {
|
|
91
|
+
src: images[0].src,
|
|
92
|
+
alt: images[0].alt ?? title ?? ""
|
|
93
|
+
})
|
|
94
|
+
}) : /* @__PURE__ */ jsx(FallbackImage, {})
|
|
95
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
96
|
+
/* @__PURE__ */ jsx(GalleryImageArea, {
|
|
97
|
+
imageElements,
|
|
98
|
+
fallback: /* @__PURE__ */ jsx(FallbackImage, {}),
|
|
99
|
+
showPaginationDots
|
|
100
|
+
}),
|
|
101
|
+
tag && /* @__PURE__ */ jsx(ProductCardTag, { children: tag }),
|
|
102
|
+
showFavorites && /* @__PURE__ */ jsx(ProductCardFavoriteButton, {
|
|
103
|
+
className: "absolute end-3 top-3",
|
|
104
|
+
onClick: () => onFavoriteClick?.(),
|
|
105
|
+
children: /* @__PURE__ */ jsx(HeartIcon, { className: "size-4" })
|
|
106
|
+
})
|
|
107
|
+
] })
|
|
108
|
+
}), isStripped ? /* @__PURE__ */ jsxs(Fragment, { children: [title && /* @__PURE__ */ jsx(ProductCardTitle, {
|
|
109
|
+
className: "mt-2",
|
|
110
|
+
children: title
|
|
111
|
+
}), price && /* @__PURE__ */ jsx(ProductCardPrice, {
|
|
112
|
+
className: "text-muted-foreground",
|
|
113
|
+
children: price
|
|
114
|
+
})] }) : /* @__PURE__ */ jsxs(ProductCardContent, {
|
|
115
|
+
className: classes.content,
|
|
116
|
+
children: [
|
|
117
|
+
title && /* @__PURE__ */ jsx(ProductCardTitle, { children: title }),
|
|
118
|
+
subtitle && /* @__PURE__ */ jsx(ProductCardSubtitle, { children: subtitle }),
|
|
119
|
+
price && /* @__PURE__ */ jsx(ProductCardPrice, { children: price })
|
|
120
|
+
]
|
|
121
|
+
})]
|
|
122
|
+
})
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function HorizontalCardLayout({ images = [], title, subtitle, price, tag, href, layout = "horizontal", showFavorites = false, onFavoriteClick, className, HeartIcon }) {
|
|
126
|
+
const classes = productCardRecipe({ layout });
|
|
127
|
+
return /* @__PURE__ */ jsx(OptionalLink, {
|
|
128
|
+
href,
|
|
129
|
+
children: /* @__PURE__ */ jsxs(ProductCardRoot, {
|
|
130
|
+
className: cn(classes.root, className),
|
|
37
131
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
38
|
-
className:
|
|
132
|
+
className: classes.imageWrapper,
|
|
39
133
|
children: [images[0] ? /* @__PURE__ */ jsx(ProductCardImageArea, {
|
|
40
134
|
className: "aspect-[var(--enad-image-product-aspect)]",
|
|
41
135
|
children: /* @__PURE__ */ jsx(ProductCardImage, {
|
|
42
136
|
src: images[0].src,
|
|
43
|
-
alt: images[0].alt ?? title ?? ""
|
|
44
|
-
className: "transition-transform duration-[var(--enad-image-hover-duration)] group-hover:scale-[var(--enad-image-hover-scale)]"
|
|
137
|
+
alt: images[0].alt ?? title ?? ""
|
|
45
138
|
})
|
|
46
|
-
}) : /* @__PURE__ */ jsx(FallbackImage, {}), tag && /* @__PURE__ */ jsx(ProductCardTag, {
|
|
139
|
+
}) : /* @__PURE__ */ jsx(FallbackImage, {}), tag && layout === "horizontal" && /* @__PURE__ */ jsx(ProductCardTag, {
|
|
47
140
|
className: "start-2 top-2",
|
|
48
141
|
children: tag
|
|
49
142
|
})]
|
|
50
143
|
}), /* @__PURE__ */ jsxs(ProductCardContent, {
|
|
51
|
-
className:
|
|
144
|
+
className: classes.content,
|
|
52
145
|
children: [
|
|
53
146
|
title && /* @__PURE__ */ jsx(ProductCardTitle, {
|
|
54
|
-
className: "text-base",
|
|
147
|
+
className: layout === "horizontal" ? "text-base" : void 0,
|
|
55
148
|
children: title
|
|
56
149
|
}),
|
|
57
150
|
subtitle && /* @__PURE__ */ jsx(ProductCardSubtitle, {
|
|
58
|
-
className: "mt-1",
|
|
151
|
+
className: layout === "horizontal" ? "mt-1" : "mt-0.5",
|
|
59
152
|
children: subtitle
|
|
60
153
|
}),
|
|
61
154
|
price && /* @__PURE__ */ jsx(ProductCardPrice, {
|
|
62
|
-
className: "mt-2 text-base",
|
|
155
|
+
className: layout === "horizontal" ? "mt-2 text-base" : "mt-1",
|
|
63
156
|
children: price
|
|
64
157
|
}),
|
|
65
|
-
showFavorites && /* @__PURE__ */ jsx(ProductCardFavoriteButton, {
|
|
158
|
+
showFavorites && layout === "horizontal" && /* @__PURE__ */ jsx(ProductCardFavoriteButton, {
|
|
66
159
|
className: "mt-3 self-start bg-muted hover:bg-accent",
|
|
67
160
|
onClick: () => onFavoriteClick?.(),
|
|
68
161
|
children: /* @__PURE__ */ jsx(HeartIcon, { className: "size-4" })
|
|
@@ -77,14 +170,13 @@ function MinimalCard({ images = [], title, price, tag, href, showFavorites = fal
|
|
|
77
170
|
href,
|
|
78
171
|
radiusClass: "rounded-[var(--enad-card-radius)]",
|
|
79
172
|
children: /* @__PURE__ */ jsxs(ProductCardRoot, {
|
|
80
|
-
className: cn("
|
|
173
|
+
className: cn(productCardRecipe({ layout: "minimal" }).root, className),
|
|
81
174
|
children: [
|
|
82
175
|
images[0] ? /* @__PURE__ */ jsx(ProductCardImageArea, {
|
|
83
176
|
className: "aspect-[var(--enad-image-product-aspect)]",
|
|
84
177
|
children: /* @__PURE__ */ jsx(ProductCardImage, {
|
|
85
178
|
src: images[0].src,
|
|
86
|
-
alt: images[0].alt ?? title ?? ""
|
|
87
|
-
className: "transition-transform duration-[var(--enad-image-hover-duration)] group-hover:scale-[var(--enad-image-hover-scale)]"
|
|
179
|
+
alt: images[0].alt ?? title ?? ""
|
|
88
180
|
})
|
|
89
181
|
}) : /* @__PURE__ */ jsx(FallbackImage, {}),
|
|
90
182
|
tag && /* @__PURE__ */ jsx(ProductCardTag, {
|
|
@@ -97,7 +189,7 @@ function MinimalCard({ images = [], title, price, tag, href, showFavorites = fal
|
|
|
97
189
|
children: /* @__PURE__ */ jsx(HeartIcon, { className: "size-4" })
|
|
98
190
|
}),
|
|
99
191
|
/* @__PURE__ */ jsxs("div", {
|
|
100
|
-
className: "absolute inset-x-0 bottom-0 min-w-0
|
|
192
|
+
className: "absolute inset-x-0 bottom-0 min-w-0 p-4",
|
|
101
193
|
style: { background: "linear-gradient(to top, color-mix(in oklch, var(--enad-overlay-color) calc(var(--enad-overlay-from-opacity) * 100%), transparent), transparent)" },
|
|
102
194
|
children: [title && /* @__PURE__ */ jsx(ProductCardTitle, {
|
|
103
195
|
className: "text-white",
|
|
@@ -111,101 +203,6 @@ function MinimalCard({ images = [], title, price, tag, href, showFavorites = fal
|
|
|
111
203
|
})
|
|
112
204
|
});
|
|
113
205
|
}
|
|
114
|
-
function ListCard({ images = [], title, subtitle, price, href, className }) {
|
|
115
|
-
return /* @__PURE__ */ jsx(OptionalLink, {
|
|
116
|
-
href,
|
|
117
|
-
children: /* @__PURE__ */ jsxs(ProductCardRoot, {
|
|
118
|
-
className: cn("flex shadow-none", className),
|
|
119
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
120
|
-
className: "w-32 shrink-0",
|
|
121
|
-
children: images[0] ? /* @__PURE__ */ jsx(ProductCardImageArea, {
|
|
122
|
-
className: "aspect-[var(--enad-image-product-aspect)]",
|
|
123
|
-
children: /* @__PURE__ */ jsx(ProductCardImage, {
|
|
124
|
-
src: images[0].src,
|
|
125
|
-
alt: images[0].alt ?? title ?? ""
|
|
126
|
-
})
|
|
127
|
-
}) : /* @__PURE__ */ jsx(FallbackImage, {})
|
|
128
|
-
}), /* @__PURE__ */ jsxs(ProductCardContent, {
|
|
129
|
-
className: "flex-1 justify-center p-4",
|
|
130
|
-
children: [
|
|
131
|
-
title && /* @__PURE__ */ jsx(ProductCardTitle, { children: title }),
|
|
132
|
-
subtitle && /* @__PURE__ */ jsx(ProductCardSubtitle, {
|
|
133
|
-
className: "mt-0.5",
|
|
134
|
-
children: subtitle
|
|
135
|
-
}),
|
|
136
|
-
price && /* @__PURE__ */ jsx(ProductCardPrice, {
|
|
137
|
-
className: "mt-1",
|
|
138
|
-
children: price
|
|
139
|
-
})
|
|
140
|
-
]
|
|
141
|
-
})]
|
|
142
|
-
})
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
function StrippedCard({ images = [], title, price, href, className }) {
|
|
146
|
-
return /* @__PURE__ */ jsx(OptionalLink, {
|
|
147
|
-
href,
|
|
148
|
-
children: /* @__PURE__ */ jsxs(ProductCardRoot, {
|
|
149
|
-
className: cn("rounded-none shadow-none", className),
|
|
150
|
-
children: [
|
|
151
|
-
/* @__PURE__ */ jsx("div", {
|
|
152
|
-
className: "relative overflow-hidden",
|
|
153
|
-
children: images[0] ? /* @__PURE__ */ jsx(ProductCardImageArea, {
|
|
154
|
-
className: "aspect-[var(--enad-image-product-aspect)]",
|
|
155
|
-
children: /* @__PURE__ */ jsx(ProductCardImage, {
|
|
156
|
-
src: images[0].src,
|
|
157
|
-
alt: images[0].alt ?? title ?? "",
|
|
158
|
-
className: "transition-transform duration-[var(--enad-image-hover-duration)] group-hover:scale-[var(--enad-image-hover-scale)]"
|
|
159
|
-
})
|
|
160
|
-
}) : /* @__PURE__ */ jsx(FallbackImage, {})
|
|
161
|
-
}),
|
|
162
|
-
title && /* @__PURE__ */ jsx(ProductCardTitle, {
|
|
163
|
-
className: "mt-2",
|
|
164
|
-
children: title
|
|
165
|
-
}),
|
|
166
|
-
price && /* @__PURE__ */ jsx(ProductCardPrice, {
|
|
167
|
-
className: "text-muted-foreground",
|
|
168
|
-
children: price
|
|
169
|
-
})
|
|
170
|
-
]
|
|
171
|
-
})
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
function GalleryCard({ images = [], title, subtitle, price, tag, href, showFavorites = false, showPaginationDots = true, onFavoriteClick, className, HeartIcon }) {
|
|
175
|
-
const imageElements = images.map((img, i) => /* @__PURE__ */ jsx(ProductCardImageArea, {
|
|
176
|
-
className: "aspect-[var(--enad-image-product-aspect)]",
|
|
177
|
-
children: /* @__PURE__ */ jsx(ProductCardImage, {
|
|
178
|
-
src: img.src,
|
|
179
|
-
alt: img.alt ?? title ?? ""
|
|
180
|
-
})
|
|
181
|
-
}, i));
|
|
182
|
-
return /* @__PURE__ */ jsx(OptionalLink, {
|
|
183
|
-
href,
|
|
184
|
-
children: /* @__PURE__ */ jsxs(ProductCardRoot, {
|
|
185
|
-
className: cn("shadow-none", className),
|
|
186
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
187
|
-
className: "relative",
|
|
188
|
-
children: [
|
|
189
|
-
/* @__PURE__ */ jsx(GalleryImageArea, {
|
|
190
|
-
imageElements,
|
|
191
|
-
fallback: /* @__PURE__ */ jsx(FallbackImage, {}),
|
|
192
|
-
showPaginationDots
|
|
193
|
-
}),
|
|
194
|
-
tag && /* @__PURE__ */ jsx(ProductCardTag, { children: tag }),
|
|
195
|
-
showFavorites && /* @__PURE__ */ jsx(ProductCardFavoriteButton, {
|
|
196
|
-
className: "absolute end-3 top-3",
|
|
197
|
-
onClick: () => onFavoriteClick?.(),
|
|
198
|
-
children: /* @__PURE__ */ jsx(HeartIcon, { className: "size-4" })
|
|
199
|
-
})
|
|
200
|
-
]
|
|
201
|
-
}), /* @__PURE__ */ jsxs(ProductCardContent, { children: [
|
|
202
|
-
title && /* @__PURE__ */ jsx(ProductCardTitle, { children: title }),
|
|
203
|
-
subtitle && /* @__PURE__ */ jsx(ProductCardSubtitle, { children: subtitle }),
|
|
204
|
-
price && /* @__PURE__ */ jsx(ProductCardPrice, { children: price })
|
|
205
|
-
] })]
|
|
206
|
-
})
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
206
|
function ProductCard(props) {
|
|
210
207
|
const cardDefault = useVariantDefault("productCard");
|
|
211
208
|
const HeartIcon = useIcon("heart");
|
|
@@ -215,14 +212,23 @@ function ProductCard(props) {
|
|
|
215
212
|
HeartIcon
|
|
216
213
|
};
|
|
217
214
|
switch (layout) {
|
|
218
|
-
case "horizontal":
|
|
215
|
+
case "horizontal":
|
|
216
|
+
case "list": return /* @__PURE__ */ jsx(HorizontalCardLayout, {
|
|
217
|
+
...layoutProps,
|
|
218
|
+
layout
|
|
219
|
+
});
|
|
219
220
|
case "minimal": return /* @__PURE__ */ jsx(MinimalCard, { ...layoutProps });
|
|
220
|
-
case "
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
case "stripped": return /* @__PURE__ */ jsx(VerticalCard, {
|
|
222
|
+
...layoutProps,
|
|
223
|
+
layout: "stripped"
|
|
224
|
+
});
|
|
225
|
+
default: return /* @__PURE__ */ jsx(VerticalCard, {
|
|
226
|
+
...layoutProps,
|
|
227
|
+
layout: "gallery"
|
|
228
|
+
});
|
|
223
229
|
}
|
|
224
230
|
}
|
|
225
231
|
//#endregion
|
|
226
|
-
export { ProductCard };
|
|
232
|
+
export { ProductCard, productCardRecipe };
|
|
227
233
|
|
|
228
234
|
//# sourceMappingURL=product-card.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-card.mjs","names":[],"sources":["../../../../src/client/storefront/blocks/product-card.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { useIcon } from \"../../icons/icon-context\";\nimport { cn } from \"../../ui/utils\";\nimport { useVariantDefault } from \"../../ui-resolver/context\";\nimport { SwipeableCarousel } from \"../carousel/swipeable-carousel\";\nimport type { ProductCardProps } from \"../types\";\nimport {\n ProductCardContent,\n ProductCardFavoriteButton,\n ProductCardImage,\n ProductCardImageArea,\n ProductCardPrice,\n ProductCardRoot,\n ProductCardSubtitle,\n ProductCardTag,\n ProductCardTitle,\n} from \"./product-card-parts\";\n\n/* ─── Shared helpers ─── */\n\ntype CardLayoutProps = ProductCardProps & {\n HeartIcon: React.ComponentType<{ className?: string }>;\n};\n\nfunction OptionalLink({\n href,\n radiusClass,\n children,\n}: {\n href?: string;\n radiusClass?: string;\n children: React.ReactNode;\n}) {\n if (!href) return children;\n return (\n <a\n href={href}\n className={cn(\n \"block focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n radiusClass,\n )}\n >\n {children}\n </a>\n );\n}\n\nfunction FallbackImage() {\n return (\n <ProductCardImageArea\n className=\"aspect-[var(--enad-image-product-aspect)]\"\n aria-hidden=\"true\"\n />\n );\n}\n\n/* ─── Gallery image element helper ─── */\n\nfunction GalleryImageArea({\n imageElements,\n fallback,\n showPaginationDots,\n}: {\n imageElements: React.ReactNode[];\n fallback: React.ReactNode;\n showPaginationDots: boolean;\n}) {\n if (imageElements.length > 1) {\n return <SwipeableCarousel items={imageElements} showDots={showPaginationDots} />;\n }\n if (imageElements.length === 1) {\n return imageElements[0];\n }\n return fallback;\n}\n\n/* ─── Horizontal layout ─── */\n\nfunction HorizontalCard({\n images = [],\n title,\n subtitle,\n price,\n tag,\n href,\n showFavorites = false,\n onFavoriteClick,\n className,\n HeartIcon,\n}: CardLayoutProps) {\n const content = (\n <ProductCardRoot\n className={cn(\n \"flex shadow-[var(--enad-card-shadow)] transition-shadow duration-[var(--enad-motion-duration)] hover:shadow-[var(--enad-card-hover-shadow)]\",\n className,\n )}\n >\n <div className=\"relative w-1/3 shrink-0\">\n {images[0] ? (\n <ProductCardImageArea className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage\n src={images[0].src}\n alt={images[0].alt ?? title ?? \"\"}\n className=\"transition-transform duration-[var(--enad-image-hover-duration)] group-hover:scale-[var(--enad-image-hover-scale)]\"\n />\n </ProductCardImageArea>\n ) : (\n <FallbackImage />\n )}\n {tag && <ProductCardTag className=\"start-2 top-2\">{tag}</ProductCardTag>}\n </div>\n <ProductCardContent className=\"flex-1 justify-center gap-0 p-4 md:p-6\">\n {title && <ProductCardTitle className=\"text-base\">{title}</ProductCardTitle>}\n {subtitle && <ProductCardSubtitle className=\"mt-1\">{subtitle}</ProductCardSubtitle>}\n {price && <ProductCardPrice className=\"mt-2 text-base\">{price}</ProductCardPrice>}\n {showFavorites && (\n <ProductCardFavoriteButton\n className=\"mt-3 self-start bg-muted hover:bg-accent\"\n onClick={() => onFavoriteClick?.()}\n >\n <HeartIcon className=\"size-4\" />\n </ProductCardFavoriteButton>\n )}\n </ProductCardContent>\n </ProductCardRoot>\n );\n return <OptionalLink href={href}>{content}</OptionalLink>;\n}\n\n/* ─── Minimal layout ─── */\n\nfunction MinimalCard({\n images = [],\n title,\n price,\n tag,\n href,\n showFavorites = false,\n onFavoriteClick,\n className,\n HeartIcon,\n}: CardLayoutProps) {\n const content = (\n <ProductCardRoot className={cn(\"relative\", className)}>\n {images[0] ? (\n <ProductCardImageArea className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage\n src={images[0].src}\n alt={images[0].alt ?? title ?? \"\"}\n className=\"transition-transform duration-[var(--enad-image-hover-duration)] group-hover:scale-[var(--enad-image-hover-scale)]\"\n />\n </ProductCardImageArea>\n ) : (\n <FallbackImage />\n )}\n\n {tag && <ProductCardTag className=\"z-10\">{tag}</ProductCardTag>}\n\n {showFavorites && (\n <ProductCardFavoriteButton\n className=\"absolute end-3 top-3 z-10\"\n onClick={() => onFavoriteClick?.()}\n >\n <HeartIcon className=\"size-4\" />\n </ProductCardFavoriteButton>\n )}\n\n {/* Hover overlay with product info */}\n <div\n className=\"absolute inset-x-0 bottom-0 min-w-0 translate-y-full p-4 transition-transform duration-[var(--enad-motion-duration)] group-hover:translate-y-0\"\n style={{\n background:\n \"linear-gradient(to top, color-mix(in oklch, var(--enad-overlay-color) calc(var(--enad-overlay-from-opacity) * 100%), transparent), transparent)\",\n }}\n >\n {title && <ProductCardTitle className=\"text-white\">{title}</ProductCardTitle>}\n {price && <ProductCardPrice className=\"mt-0.5 text-white/80\">{price}</ProductCardPrice>}\n </div>\n </ProductCardRoot>\n );\n return (\n <OptionalLink href={href} radiusClass=\"rounded-[var(--enad-card-radius)]\">\n {content}\n </OptionalLink>\n );\n}\n\n/* ─── List layout ─── */\n\nfunction ListCard({ images = [], title, subtitle, price, href, className }: CardLayoutProps) {\n const content = (\n <ProductCardRoot className={cn(\"flex shadow-none\", className)}>\n <div className=\"w-32 shrink-0\">\n {images[0] ? (\n <ProductCardImageArea className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage src={images[0].src} alt={images[0].alt ?? title ?? \"\"} />\n </ProductCardImageArea>\n ) : (\n <FallbackImage />\n )}\n </div>\n <ProductCardContent className=\"flex-1 justify-center p-4\">\n {title && <ProductCardTitle>{title}</ProductCardTitle>}\n {subtitle && <ProductCardSubtitle className=\"mt-0.5\">{subtitle}</ProductCardSubtitle>}\n {price && <ProductCardPrice className=\"mt-1\">{price}</ProductCardPrice>}\n </ProductCardContent>\n </ProductCardRoot>\n );\n return <OptionalLink href={href}>{content}</OptionalLink>;\n}\n\n/* ─── Stripped layout ─── */\n\nfunction StrippedCard({ images = [], title, price, href, className }: CardLayoutProps) {\n const content = (\n <ProductCardRoot className={cn(\"rounded-none shadow-none\", className)}>\n <div className=\"relative overflow-hidden\">\n {images[0] ? (\n <ProductCardImageArea className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage\n src={images[0].src}\n alt={images[0].alt ?? title ?? \"\"}\n className=\"transition-transform duration-[var(--enad-image-hover-duration)] group-hover:scale-[var(--enad-image-hover-scale)]\"\n />\n </ProductCardImageArea>\n ) : (\n <FallbackImage />\n )}\n </div>\n {title && <ProductCardTitle className=\"mt-2\">{title}</ProductCardTitle>}\n {price && <ProductCardPrice className=\"text-muted-foreground\">{price}</ProductCardPrice>}\n </ProductCardRoot>\n );\n return <OptionalLink href={href}>{content}</OptionalLink>;\n}\n\n/* ─── Gallery layout (default) ─── */\n\nfunction GalleryCard({\n images = [],\n title,\n subtitle,\n price,\n tag,\n href,\n showFavorites = false,\n showPaginationDots = true,\n onFavoriteClick,\n className,\n HeartIcon,\n}: CardLayoutProps) {\n const imageElements = images.map((img, i) => (\n <ProductCardImageArea key={i} className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage src={img.src} alt={img.alt ?? title ?? \"\"} />\n </ProductCardImageArea>\n ));\n\n const content = (\n <ProductCardRoot className={cn(\"shadow-none\", className)}>\n <div className=\"relative\">\n <GalleryImageArea\n imageElements={imageElements}\n fallback={<FallbackImage />}\n showPaginationDots={showPaginationDots}\n />\n\n {tag && <ProductCardTag>{tag}</ProductCardTag>}\n\n {showFavorites && (\n <ProductCardFavoriteButton\n className=\"absolute end-3 top-3\"\n onClick={() => onFavoriteClick?.()}\n >\n <HeartIcon className=\"size-4\" />\n </ProductCardFavoriteButton>\n )}\n </div>\n\n <ProductCardContent>\n {title && <ProductCardTitle>{title}</ProductCardTitle>}\n {subtitle && <ProductCardSubtitle>{subtitle}</ProductCardSubtitle>}\n {price && <ProductCardPrice>{price}</ProductCardPrice>}\n </ProductCardContent>\n </ProductCardRoot>\n );\n return <OptionalLink href={href}>{content}</OptionalLink>;\n}\n\n/* ─── Main component (dispatcher) ─── */\n\nfunction ProductCard(props: ProductCardProps) {\n const cardDefault = useVariantDefault(\"productCard\");\n const HeartIcon = useIcon(\"heart\");\n const layout = props.layout ?? cardDefault ?? \"gallery\";\n const layoutProps: CardLayoutProps = { ...props, HeartIcon };\n\n switch (layout) {\n case \"horizontal\":\n return <HorizontalCard {...layoutProps} />;\n case \"minimal\":\n return <MinimalCard {...layoutProps} />;\n case \"list\":\n return <ListCard {...layoutProps} />;\n case \"stripped\":\n return <StrippedCard {...layoutProps} />;\n default:\n return <GalleryCard {...layoutProps} />;\n }\n}\n\nexport { ProductCard, type ProductCardProps };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"product-card.mjs","names":[],"sources":["../../../../src/client/storefront/blocks/product-card.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { useIcon } from \"../../icons/icon-context\";\nimport { cn } from \"../../ui/utils\";\nimport { defineSlotRecipe } from \"../../ui-resolver/recipe\";\nimport { useVariantDefault } from \"../../ui-resolver/context\";\nimport { SwipeableCarousel } from \"../carousel/swipeable-carousel\";\nimport type { ProductCardProps } from \"../types\";\nimport {\n ProductCardContent,\n ProductCardFavoriteButton,\n ProductCardImage,\n ProductCardImageArea,\n ProductCardPrice,\n ProductCardRoot,\n ProductCardSubtitle,\n ProductCardTag,\n ProductCardTitle,\n} from \"./product-card-parts\";\n\n/* ─── Recipe ─── */\n\nconst productCardRecipe = defineSlotRecipe({\n slots: [\"root\", \"imageWrapper\", \"content\"] as const,\n base: {\n root: \"\",\n imageWrapper: \"relative\",\n content: \"\",\n },\n variants: {\n layout: {\n gallery: {\n root: \"shadow-none\",\n content:\n \"flex min-w-0 flex-col gap-[var(--enad-product-card-content-gap,0.125rem)] p-[var(--enad-product-card-content-py,0.75rem)]\",\n },\n horizontal: {\n root: \"flex shadow-[var(--enad-card-shadow)]\",\n imageWrapper: \"w-1/3 shrink-0\",\n content: \"flex min-w-0 flex-1 flex-col justify-center gap-0 p-4 md:p-6\",\n },\n minimal: {\n root: \"relative\",\n content: \"\",\n },\n list: {\n root: \"flex shadow-none\",\n imageWrapper: \"w-32 shrink-0\",\n content: \"flex min-w-0 flex-1 flex-col justify-center p-4\",\n },\n stripped: {\n root: \"rounded-none shadow-none\",\n content: \"\",\n },\n },\n },\n defaultVariants: { layout: \"gallery\" },\n});\n\n/* ─── Shared helpers ─── */\n\nfunction OptionalLink({\n href,\n radiusClass,\n children,\n}: {\n href?: string;\n radiusClass?: string;\n children: React.ReactNode;\n}) {\n if (!href) return children;\n return (\n <a\n href={href}\n className={cn(\n \"block focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n radiusClass,\n )}\n >\n {children}\n </a>\n );\n}\n\nfunction FallbackImage() {\n return (\n <ProductCardImageArea\n className=\"aspect-[var(--enad-image-product-aspect)]\"\n aria-hidden=\"true\"\n />\n );\n}\n\nfunction GalleryImageArea({\n imageElements,\n fallback,\n showPaginationDots,\n}: {\n imageElements: React.ReactNode[];\n fallback: React.ReactNode;\n showPaginationDots: boolean;\n}) {\n if (imageElements.length > 1) {\n return <SwipeableCarousel items={imageElements} showDots={showPaginationDots} />;\n }\n if (imageElements.length === 1) {\n return imageElements[0];\n }\n return fallback;\n}\n\n/* ─── Internal layout prop type ─── */\n\ntype CardLayoutProps = ProductCardProps & {\n HeartIcon: React.ComponentType<{ className?: string }>;\n};\n\n/* ─── Vertical layout (gallery + stripped) ─── */\n\nfunction VerticalCard({\n images = [],\n title,\n subtitle,\n price,\n tag,\n href,\n layout = \"gallery\",\n showFavorites = false,\n showPaginationDots = true,\n onFavoriteClick,\n className,\n HeartIcon,\n}: CardLayoutProps) {\n const classes = productCardRecipe({ layout });\n const isStripped = layout === \"stripped\";\n\n const imageElements = images.map((img, i) => (\n <ProductCardImageArea key={i} className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage src={img.src} alt={img.alt ?? title ?? \"\"} />\n </ProductCardImageArea>\n ));\n\n const content = (\n <ProductCardRoot className={cn(classes.root, className)}>\n <div className={classes.imageWrapper}>\n {isStripped ? (\n <div className=\"overflow-hidden\">\n {images[0] ? (\n <ProductCardImageArea className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage src={images[0].src} alt={images[0].alt ?? title ?? \"\"} />\n </ProductCardImageArea>\n ) : (\n <FallbackImage />\n )}\n </div>\n ) : (\n <>\n <GalleryImageArea\n imageElements={imageElements}\n fallback={<FallbackImage />}\n showPaginationDots={showPaginationDots}\n />\n {tag && <ProductCardTag>{tag}</ProductCardTag>}\n {showFavorites && (\n <ProductCardFavoriteButton\n className=\"absolute end-3 top-3\"\n onClick={() => onFavoriteClick?.()}\n >\n <HeartIcon className=\"size-4\" />\n </ProductCardFavoriteButton>\n )}\n </>\n )}\n </div>\n\n {isStripped ? (\n <>\n {title && <ProductCardTitle className=\"mt-2\">{title}</ProductCardTitle>}\n {price && <ProductCardPrice className=\"text-muted-foreground\">{price}</ProductCardPrice>}\n </>\n ) : (\n <ProductCardContent className={classes.content}>\n {title && <ProductCardTitle>{title}</ProductCardTitle>}\n {subtitle && <ProductCardSubtitle>{subtitle}</ProductCardSubtitle>}\n {price && <ProductCardPrice>{price}</ProductCardPrice>}\n </ProductCardContent>\n )}\n </ProductCardRoot>\n );\n\n return <OptionalLink href={href}>{content}</OptionalLink>;\n}\n\n/* ─── Horizontal layout (horizontal + list) ─── */\n\nfunction HorizontalCardLayout({\n images = [],\n title,\n subtitle,\n price,\n tag,\n href,\n layout = \"horizontal\",\n showFavorites = false,\n onFavoriteClick,\n className,\n HeartIcon,\n}: CardLayoutProps) {\n const classes = productCardRecipe({ layout });\n\n const content = (\n <ProductCardRoot className={cn(classes.root, className)}>\n <div className={classes.imageWrapper}>\n {images[0] ? (\n <ProductCardImageArea className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage src={images[0].src} alt={images[0].alt ?? title ?? \"\"} />\n </ProductCardImageArea>\n ) : (\n <FallbackImage />\n )}\n {tag && layout === \"horizontal\" && (\n <ProductCardTag className=\"start-2 top-2\">{tag}</ProductCardTag>\n )}\n </div>\n <ProductCardContent className={classes.content}>\n {title && (\n <ProductCardTitle className={layout === \"horizontal\" ? \"text-base\" : undefined}>\n {title}\n </ProductCardTitle>\n )}\n {subtitle && (\n <ProductCardSubtitle className={layout === \"horizontal\" ? \"mt-1\" : \"mt-0.5\"}>\n {subtitle}\n </ProductCardSubtitle>\n )}\n {price && (\n <ProductCardPrice className={layout === \"horizontal\" ? \"mt-2 text-base\" : \"mt-1\"}>\n {price}\n </ProductCardPrice>\n )}\n {showFavorites && layout === \"horizontal\" && (\n <ProductCardFavoriteButton\n className=\"mt-3 self-start bg-muted hover:bg-accent\"\n onClick={() => onFavoriteClick?.()}\n >\n <HeartIcon className=\"size-4\" />\n </ProductCardFavoriteButton>\n )}\n </ProductCardContent>\n </ProductCardRoot>\n );\n\n return <OptionalLink href={href}>{content}</OptionalLink>;\n}\n\n/* ─── Minimal layout (hover overlay) ─── */\n\nfunction MinimalCard({\n images = [],\n title,\n price,\n tag,\n href,\n showFavorites = false,\n onFavoriteClick,\n className,\n HeartIcon,\n}: CardLayoutProps) {\n const classes = productCardRecipe({ layout: \"minimal\" });\n\n const content = (\n <ProductCardRoot className={cn(classes.root, className)}>\n {images[0] ? (\n <ProductCardImageArea className=\"aspect-[var(--enad-image-product-aspect)]\">\n <ProductCardImage src={images[0].src} alt={images[0].alt ?? title ?? \"\"} />\n </ProductCardImageArea>\n ) : (\n <FallbackImage />\n )}\n\n {tag && <ProductCardTag className=\"z-10\">{tag}</ProductCardTag>}\n\n {showFavorites && (\n <ProductCardFavoriteButton\n className=\"absolute end-3 top-3 z-10\"\n onClick={() => onFavoriteClick?.()}\n >\n <HeartIcon className=\"size-4\" />\n </ProductCardFavoriteButton>\n )}\n\n <div\n className=\"absolute inset-x-0 bottom-0 min-w-0 p-4\"\n style={{\n background:\n \"linear-gradient(to top, color-mix(in oklch, var(--enad-overlay-color) calc(var(--enad-overlay-from-opacity) * 100%), transparent), transparent)\",\n }}\n >\n {title && <ProductCardTitle className=\"text-white\">{title}</ProductCardTitle>}\n {price && <ProductCardPrice className=\"mt-0.5 text-white/80\">{price}</ProductCardPrice>}\n </div>\n </ProductCardRoot>\n );\n\n return (\n <OptionalLink href={href} radiusClass=\"rounded-[var(--enad-card-radius)]\">\n {content}\n </OptionalLink>\n );\n}\n\n/* ─── Main component (dispatcher) ─── */\n\nfunction ProductCard(props: ProductCardProps) {\n const cardDefault = useVariantDefault(\"productCard\");\n const HeartIcon = useIcon(\"heart\");\n const layout = props.layout ?? cardDefault ?? \"gallery\";\n const layoutProps: CardLayoutProps = { ...props, HeartIcon };\n\n switch (layout) {\n case \"horizontal\":\n case \"list\":\n return <HorizontalCardLayout {...layoutProps} layout={layout} />;\n case \"minimal\":\n return <MinimalCard {...layoutProps} />;\n case \"stripped\":\n return <VerticalCard {...layoutProps} layout=\"stripped\" />;\n default:\n return <VerticalCard {...layoutProps} layout=\"gallery\" />;\n }\n}\n\nexport { ProductCard, productCardRecipe, type ProductCardProps };\n"],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ const aspectClasses = {
|
|
|
11
11
|
function getZoomLabel(zoomed) {
|
|
12
12
|
return zoomed ? "Zoom out" : "Zoom in";
|
|
13
13
|
}
|
|
14
|
-
function ProductImage({ images, aspectRatio = "4:5", showZoom = false, arrows =
|
|
14
|
+
function ProductImage({ images, aspectRatio = "4:5", showZoom = false, arrows = void 0, showDots = true, showThumbnails = false, className }) {
|
|
15
15
|
const [zoomed, setZoomed] = React$1.useState(false);
|
|
16
16
|
const [activeSlide, setActiveSlide] = React$1.useState(0);
|
|
17
17
|
const toggleZoom = () => {
|
|
@@ -35,7 +35,7 @@ function ProductImage({ images, aspectRatio = "4:5", showZoom = false, arrows =
|
|
|
35
35
|
children: /* @__PURE__ */ jsx("img", {
|
|
36
36
|
src: img.src,
|
|
37
37
|
alt: img.alt ?? "",
|
|
38
|
-
className: cn("size-full object-cover
|
|
38
|
+
className: cn("size-full object-cover", zoomed && "scale-150")
|
|
39
39
|
})
|
|
40
40
|
}, i));
|
|
41
41
|
if (images.length === 0) return /* @__PURE__ */ jsx("div", { className: cn("bg-muted", aspectClasses[aspectRatio], className) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-image.mjs","names":["React"],"sources":["../../../../src/client/storefront/blocks/product-image.tsx"],"sourcesContent":["\"use client\"
|
|
1
|
+
{"version":3,"file":"product-image.mjs","names":["React"],"sources":["../../../../src/client/storefront/blocks/product-image.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../ui/utils\";\nimport { SwipeableCarousel } from \"../carousel/swipeable-carousel\";\nimport type { ProductImageProps } from \"../types\";\n\nconst aspectClasses: Record<string, string> = {\n \"1:1\": \"aspect-square\",\n \"4:5\": \"aspect-[4/5]\",\n};\n\nfunction getZoomLabel(zoomed: boolean): string {\n return zoomed ? \"Zoom out\" : \"Zoom in\";\n}\n\nfunction ProductImage({\n images,\n aspectRatio = \"4:5\",\n showZoom = false,\n arrows = undefined,\n showDots = true,\n showThumbnails = false,\n className,\n}: ProductImageProps) {\n const [zoomed, setZoomed] = React.useState(false);\n const [activeSlide, setActiveSlide] = React.useState(0);\n\n const toggleZoom = () => {\n if (showZoom) setZoomed((z) => !z);\n };\n\n const handleZoomKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n toggleZoom();\n }\n };\n\n const imageElements = images.map((img, i) => (\n <div\n key={i}\n className={cn(\n \"relative overflow-hidden bg-muted\",\n aspectClasses[aspectRatio],\n showZoom && (zoomed ? \"cursor-zoom-out\" : \"cursor-zoom-in\"),\n )}\n {...(showZoom && {\n role: \"button\" as const,\n tabIndex: 0,\n \"aria-label\": getZoomLabel(zoomed),\n onClick: toggleZoom,\n onKeyDown: handleZoomKeyDown,\n })}\n >\n <img\n src={img.src}\n alt={img.alt ?? \"\"}\n className={cn(\"size-full object-cover\", zoomed && \"scale-150\")}\n />\n </div>\n ));\n\n if (images.length === 0) {\n return <div className={cn(\"bg-muted\", aspectClasses[aspectRatio], className)} />;\n }\n\n if (images.length === 1) {\n return <div className={className}>{imageElements[0]}</div>;\n }\n\n const carousel = (\n <SwipeableCarousel\n items={imageElements}\n arrows={arrows}\n showDots={showDots}\n activeSlide={activeSlide}\n onSlideChange={setActiveSlide}\n />\n );\n\n if (showThumbnails && images.length > 1) {\n return (\n <div className={cn(\"flex gap-3\", className)}>\n <div className=\"hidden md:flex flex-col gap-2 w-16 shrink-0\">\n {images.map((img, i) => (\n <button\n key={i}\n type=\"button\"\n aria-label={`View image ${i + 1}`}\n onClick={() => setActiveSlide(i)}\n className={cn(\n \"relative aspect-square overflow-hidden rounded-[var(--enad-card-radius)] border-2 transition\",\n i === activeSlide\n ? \"border-primary ring-1 ring-primary/30\"\n : \"border-transparent opacity-60 hover:opacity-100\",\n )}\n >\n <img src={img.src} alt={img.alt ?? \"\"} className=\"size-full object-cover\" />\n </button>\n ))}\n </div>\n <div className=\"min-w-0 flex-1\">{carousel}</div>\n </div>\n );\n }\n\n return <div className={className}>{carousel}</div>;\n}\n\nexport { ProductImage, type ProductImageProps };\n"],"mappings":";;;;;;AAOA,MAAM,gBAAwC;CAC5C,OAAO;CACP,OAAO;CACR;AAED,SAAS,aAAa,QAAyB;AAC7C,QAAO,SAAS,aAAa;;AAG/B,SAAS,aAAa,EACpB,QACA,cAAc,OACd,WAAW,OACX,SAAS,KAAA,GACT,WAAW,MACX,iBAAiB,OACjB,aACoB;CACpB,MAAM,CAAC,QAAQ,aAAaA,QAAM,SAAS,MAAM;CACjD,MAAM,CAAC,aAAa,kBAAkBA,QAAM,SAAS,EAAE;CAEvD,MAAM,mBAAmB;AACvB,MAAI,SAAU,YAAW,MAAM,CAAC,EAAE;;CAGpC,MAAM,qBAAqB,MAA2B;AACpD,MAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,KAAE,gBAAgB;AAClB,eAAY;;;CAIhB,MAAM,gBAAgB,OAAO,KAAK,KAAK,MACrC,oBAAC,OAAD;EAEE,WAAW,GACT,qCACA,cAAc,cACd,aAAa,SAAS,oBAAoB,kBAC3C;EACD,GAAK,YAAY;GACf,MAAM;GACN,UAAU;GACV,cAAc,aAAa,OAAO;GAClC,SAAS;GACT,WAAW;GACZ;YAED,oBAAC,OAAD;GACE,KAAK,IAAI;GACT,KAAK,IAAI,OAAO;GAChB,WAAW,GAAG,0BAA0B,UAAU,YAAY;GAC9D,CAAA;EACE,EAnBC,EAmBD,CACN;AAEF,KAAI,OAAO,WAAW,EACpB,QAAO,oBAAC,OAAD,EAAK,WAAW,GAAG,YAAY,cAAc,cAAc,UAAU,EAAI,CAAA;AAGlF,KAAI,OAAO,WAAW,EACpB,QAAO,oBAAC,OAAD;EAAgB;YAAY,cAAc;EAAS,CAAA;CAG5D,MAAM,WACJ,oBAAC,mBAAD;EACE,OAAO;EACC;EACE;EACG;EACb,eAAe;EACf,CAAA;AAGJ,KAAI,kBAAkB,OAAO,SAAS,EACpC,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,cAAc,UAAU;YAA3C,CACE,oBAAC,OAAD;GAAK,WAAU;aACZ,OAAO,KAAK,KAAK,MAChB,oBAAC,UAAD;IAEE,MAAK;IACL,cAAY,cAAc,IAAI;IAC9B,eAAe,eAAe,EAAE;IAChC,WAAW,GACT,gGACA,MAAM,cACF,0CACA,kDACL;cAED,oBAAC,OAAD;KAAK,KAAK,IAAI;KAAK,KAAK,IAAI,OAAO;KAAI,WAAU;KAA2B,CAAA;IACrE,EAZF,EAYE,CACT;GACE,CAAA,EACN,oBAAC,OAAD;GAAK,WAAU;aAAkB;GAAe,CAAA,CAC5C;;AAIV,QAAO,oBAAC,OAAD;EAAgB;YAAY;EAAe,CAAA"}
|
|
@@ -2,7 +2,20 @@ import { TextContentWithImageProps } from "../types.js";
|
|
|
2
2
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/client/storefront/blocks/text-content-with-image.d.ts
|
|
5
|
+
declare const textContentWithImageRecipe: (props?: ({
|
|
6
|
+
variant?: "side-by-side" | "stacked" | "overlap" | undefined;
|
|
7
|
+
fullWidth?: "true" | "false" | undefined;
|
|
8
|
+
imagePosition?: "first" | "last" | undefined;
|
|
9
|
+
} & {
|
|
10
|
+
className?: Partial<Record<"root" | "image" | "inner" | "imageArea" | "textArea", string>> | undefined;
|
|
11
|
+
}) | undefined) => {
|
|
12
|
+
root: string;
|
|
13
|
+
image: string;
|
|
14
|
+
inner: string;
|
|
15
|
+
imageArea: string;
|
|
16
|
+
textArea: string;
|
|
17
|
+
};
|
|
5
18
|
declare function TextContentWithImage(props: TextContentWithImageProps): react_jsx_runtime0.JSX.Element;
|
|
6
19
|
//#endregion
|
|
7
|
-
export { TextContentWithImage, type TextContentWithImageProps };
|
|
20
|
+
export { TextContentWithImage, type TextContentWithImageProps, textContentWithImageRecipe };
|
|
8
21
|
//# sourceMappingURL=text-content-with-image.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-content-with-image.d.ts","names":[],"sources":["../../../../src/client/storefront/blocks/text-content-with-image.tsx"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"text-content-with-image.d.ts","names":[],"sources":["../../../../src/client/storefront/blocks/text-content-with-image.tsx"],"mappings":";;;;cAWM,0BAAA,GAA0B,KAAA;;;;;cA6E9B,OAAA,CAAA,MAAA;AAAA;;;;;;;iBA6JO,oBAAA,CAAqB,KAAA,EAAO,yBAAA,GAAyB,kBAAA,CAAA,GAAA,CAAA,OAAA"}
|