@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.
Files changed (232) hide show
  1. package/dist/client/cart/components/cart-drawer.mjs +3 -3
  2. package/dist/client/cart/components/cart-drawer.mjs.map +1 -1
  3. package/dist/client/cart/components/cart-trigger.mjs +1 -1
  4. package/dist/client/cart/components/cart-trigger.mjs.map +1 -1
  5. package/dist/client/storefront/blocks/card-video.mjs +1 -1
  6. package/dist/client/storefront/blocks/card-video.mjs.map +1 -1
  7. package/dist/client/storefront/blocks/gallery-with-link-blocks.d.ts.map +1 -1
  8. package/dist/client/storefront/blocks/gallery-with-link-blocks.mjs +13 -5
  9. package/dist/client/storefront/blocks/gallery-with-link-blocks.mjs.map +1 -1
  10. package/dist/client/storefront/blocks/gallery.d.ts +10 -1
  11. package/dist/client/storefront/blocks/gallery.d.ts.map +1 -1
  12. package/dist/client/storefront/blocks/gallery.mjs +51 -27
  13. package/dist/client/storefront/blocks/gallery.mjs.map +1 -1
  14. package/dist/client/storefront/blocks/hero.d.ts +12 -1
  15. package/dist/client/storefront/blocks/hero.d.ts.map +1 -1
  16. package/dist/client/storefront/blocks/hero.mjs +143 -145
  17. package/dist/client/storefront/blocks/hero.mjs.map +1 -1
  18. package/dist/client/storefront/blocks/link-block-small.d.ts.map +1 -1
  19. package/dist/client/storefront/blocks/link-block-small.mjs +1 -1
  20. package/dist/client/storefront/blocks/link-block-small.mjs.map +1 -1
  21. package/dist/client/storefront/blocks/link-block.d.ts.map +1 -1
  22. package/dist/client/storefront/blocks/link-block.mjs +4 -4
  23. package/dist/client/storefront/blocks/link-block.mjs.map +1 -1
  24. package/dist/client/storefront/blocks/product-card-parts.d.ts +1 -1
  25. package/dist/client/storefront/blocks/product-card-parts.d.ts.map +1 -1
  26. package/dist/client/storefront/blocks/product-card-parts.mjs +2 -2
  27. package/dist/client/storefront/blocks/product-card-parts.mjs.map +1 -1
  28. package/dist/client/storefront/blocks/product-card.d.ts +10 -1
  29. package/dist/client/storefront/blocks/product-card.d.ts.map +1 -1
  30. package/dist/client/storefront/blocks/product-card.mjs +122 -116
  31. package/dist/client/storefront/blocks/product-card.mjs.map +1 -1
  32. package/dist/client/storefront/blocks/product-image.mjs +2 -2
  33. package/dist/client/storefront/blocks/product-image.mjs.map +1 -1
  34. package/dist/client/storefront/blocks/text-content-with-image.d.ts +14 -1
  35. package/dist/client/storefront/blocks/text-content-with-image.d.ts.map +1 -1
  36. package/dist/client/storefront/blocks/text-content-with-image.mjs +141 -164
  37. package/dist/client/storefront/blocks/text-content-with-image.mjs.map +1 -1
  38. package/dist/client/storefront/carousel/swipeable-carousel.d.ts +5 -1
  39. package/dist/client/storefront/carousel/swipeable-carousel.d.ts.map +1 -1
  40. package/dist/client/storefront/carousel/swipeable-carousel.mjs +2 -1
  41. package/dist/client/storefront/carousel/swipeable-carousel.mjs.map +1 -1
  42. package/dist/client/storefront/checkout/cart-summary.mjs +1 -1
  43. package/dist/client/storefront/checkout/cart-summary.mjs.map +1 -1
  44. package/dist/client/storefront/components/language-selector.d.ts.map +1 -1
  45. package/dist/client/storefront/components/language-selector.mjs +1 -1
  46. package/dist/client/storefront/components/language-selector.mjs.map +1 -1
  47. package/dist/client/storefront/components/product-recommendations.d.ts.map +1 -1
  48. package/dist/client/storefront/components/product-recommendations.mjs +29 -37
  49. package/dist/client/storefront/components/product-recommendations.mjs.map +1 -1
  50. package/dist/client/storefront/filters/filter-chip.d.ts +5 -2
  51. package/dist/client/storefront/filters/filter-chip.d.ts.map +1 -1
  52. package/dist/client/storefront/filters/filter-chip.mjs +6 -4
  53. package/dist/client/storefront/filters/filter-chip.mjs.map +1 -1
  54. package/dist/client/storefront/filters/filter-panel.mjs +2 -2
  55. package/dist/client/storefront/filters/filter-panel.mjs.map +1 -1
  56. package/dist/client/storefront/filters/toggle-list-view.mjs +1 -1
  57. package/dist/client/storefront/filters/toggle-list-view.mjs.map +1 -1
  58. package/dist/client/storefront/index.d.ts +12 -1
  59. package/dist/client/storefront/index.mjs +12 -1
  60. package/dist/client/storefront/layout/header.d.ts.map +1 -1
  61. package/dist/client/storefront/layout/header.mjs +1 -1
  62. package/dist/client/storefront/layout/header.mjs.map +1 -1
  63. package/dist/client/storefront/layout/mobile-menu-drawer.mjs +1 -1
  64. package/dist/client/storefront/layout/promotion-bar.d.ts.map +1 -1
  65. package/dist/client/storefront/layout/promotion-bar.mjs +3 -3
  66. package/dist/client/storefront/layout/promotion-bar.mjs.map +1 -1
  67. package/dist/client/storefront/primitives/block-heading.d.ts +40 -0
  68. package/dist/client/storefront/primitives/block-heading.d.ts.map +1 -0
  69. package/dist/client/storefront/primitives/block-heading.mjs +43 -0
  70. package/dist/client/storefront/primitives/block-heading.mjs.map +1 -0
  71. package/dist/client/storefront/primitives/button.d.ts +2 -2
  72. package/dist/client/storefront/primitives/button.d.ts.map +1 -1
  73. package/dist/client/storefront/primitives/button.mjs +4 -4
  74. package/dist/client/storefront/primitives/button.mjs.map +1 -1
  75. package/dist/client/storefront/primitives/cta-group.d.ts +25 -0
  76. package/dist/client/storefront/primitives/cta-group.d.ts.map +1 -0
  77. package/dist/client/storefront/primitives/cta-group.mjs +27 -0
  78. package/dist/client/storefront/primitives/cta-group.mjs.map +1 -0
  79. package/dist/client/storefront/primitives/image-with-hover.d.ts +18 -0
  80. package/dist/client/storefront/primitives/image-with-hover.d.ts.map +1 -0
  81. package/dist/client/storefront/primitives/image-with-hover.mjs +16 -0
  82. package/dist/client/storefront/primitives/image-with-hover.mjs.map +1 -0
  83. package/dist/client/storefront/primitives/index.d.ts +4 -1
  84. package/dist/client/storefront/primitives/index.mjs +4 -1
  85. package/dist/client/storefront/primitives/input.d.ts +1 -1
  86. package/dist/client/storefront/primitives/input.mjs.map +1 -1
  87. package/dist/client/storefront/primitives/pagination.mjs +2 -2
  88. package/dist/client/storefront/primitives/pagination.mjs.map +1 -1
  89. package/dist/client/storefront/product/quantity-picker.mjs +2 -2
  90. package/dist/client/storefront/product/quantity-picker.mjs.map +1 -1
  91. package/dist/client/storefront/types.d.ts +1 -1
  92. package/dist/client/storefront/types.d.ts.map +1 -1
  93. package/dist/client/storefront/types.mjs.map +1 -1
  94. package/dist/client/theme/apply.d.ts +1 -1
  95. package/dist/client/theme/apply.d.ts.map +1 -1
  96. package/dist/client/theme/apply.mjs +0 -12
  97. package/dist/client/theme/apply.mjs.map +1 -1
  98. package/dist/client/theme/cli.mjs +0 -16
  99. package/dist/client/theme/cli.mjs.map +1 -1
  100. package/dist/client/theme/codec.d.ts.map +1 -1
  101. package/dist/client/theme/codec.mjs +0 -2
  102. package/dist/client/theme/codec.mjs.map +1 -1
  103. package/dist/client/theme/defaults.d.ts +0 -2
  104. package/dist/client/theme/defaults.mjs +0 -2
  105. package/dist/client/theme/defaults.mjs.map +1 -1
  106. package/dist/client/ui/accordion.d.ts +12 -1
  107. package/dist/client/ui/accordion.d.ts.map +1 -1
  108. package/dist/client/ui/accordion.mjs +23 -5
  109. package/dist/client/ui/accordion.mjs.map +1 -1
  110. package/dist/client/ui/alert.d.ts +16 -7
  111. package/dist/client/ui/alert.d.ts.map +1 -1
  112. package/dist/client/ui/alert.mjs +21 -8
  113. package/dist/client/ui/alert.mjs.map +1 -1
  114. package/dist/client/ui/avatar.d.ts +10 -1
  115. package/dist/client/ui/avatar.d.ts.map +1 -1
  116. package/dist/client/ui/avatar.mjs +18 -4
  117. package/dist/client/ui/avatar.mjs.map +1 -1
  118. package/dist/client/ui/breadcrumb.d.ts +13 -1
  119. package/dist/client/ui/breadcrumb.d.ts.map +1 -1
  120. package/dist/client/ui/breadcrumb.mjs +27 -7
  121. package/dist/client/ui/breadcrumb.mjs.map +1 -1
  122. package/dist/client/ui/button.d.ts +28 -10
  123. package/dist/client/ui/button.d.ts.map +1 -1
  124. package/dist/client/ui/button.mjs +45 -20
  125. package/dist/client/ui/button.mjs.map +1 -1
  126. package/dist/client/ui/card.d.ts +20 -1
  127. package/dist/client/ui/card.d.ts.map +1 -1
  128. package/dist/client/ui/card.mjs +36 -8
  129. package/dist/client/ui/card.mjs.map +1 -1
  130. package/dist/client/ui/carousel.d.ts +9 -1
  131. package/dist/client/ui/carousel.d.ts.map +1 -1
  132. package/dist/client/ui/carousel.mjs +20 -4
  133. package/dist/client/ui/carousel.mjs.map +1 -1
  134. package/dist/client/ui/checkbox.d.ts +9 -1
  135. package/dist/client/ui/checkbox.d.ts.map +1 -1
  136. package/dist/client/ui/checkbox.mjs +12 -3
  137. package/dist/client/ui/checkbox.mjs.map +1 -1
  138. package/dist/client/ui/dialog.d.ts +13 -1
  139. package/dist/client/ui/dialog.d.ts.map +1 -1
  140. package/dist/client/ui/dialog.mjs +27 -7
  141. package/dist/client/ui/dialog.mjs.map +1 -1
  142. package/dist/client/ui/hover-card.d.ts +6 -1
  143. package/dist/client/ui/hover-card.d.ts.map +1 -1
  144. package/dist/client/ui/hover-card.mjs +4 -2
  145. package/dist/client/ui/hover-card.mjs.map +1 -1
  146. package/dist/client/ui/input.d.ts +20 -7
  147. package/dist/client/ui/input.d.ts.map +1 -1
  148. package/dist/client/ui/input.mjs +33 -9
  149. package/dist/client/ui/input.mjs.map +1 -1
  150. package/dist/client/ui/label.d.ts +6 -1
  151. package/dist/client/ui/label.d.ts.map +1 -1
  152. package/dist/client/ui/label.mjs +4 -2
  153. package/dist/client/ui/label.mjs.map +1 -1
  154. package/dist/client/ui/navigation-menu.d.ts +20 -3
  155. package/dist/client/ui/navigation-menu.d.ts.map +1 -1
  156. package/dist/client/ui/navigation-menu.mjs +34 -12
  157. package/dist/client/ui/navigation-menu.mjs.map +1 -1
  158. package/dist/client/ui/pagination.d.ts.map +1 -1
  159. package/dist/client/ui/pagination.mjs +3 -3
  160. package/dist/client/ui/pagination.mjs.map +1 -1
  161. package/dist/client/ui/popover.d.ts +11 -1
  162. package/dist/client/ui/popover.d.ts.map +1 -1
  163. package/dist/client/ui/popover.mjs +21 -5
  164. package/dist/client/ui/popover.mjs.map +1 -1
  165. package/dist/client/ui/progress.d.ts +9 -1
  166. package/dist/client/ui/progress.d.ts.map +1 -1
  167. package/dist/client/ui/progress.mjs +12 -3
  168. package/dist/client/ui/progress.mjs.map +1 -1
  169. package/dist/client/ui/select.d.ts +14 -2
  170. package/dist/client/ui/select.d.ts.map +1 -1
  171. package/dist/client/ui/select.mjs +35 -9
  172. package/dist/client/ui/select.mjs.map +1 -1
  173. package/dist/client/ui/separator.d.ts +6 -1
  174. package/dist/client/ui/separator.d.ts.map +1 -1
  175. package/dist/client/ui/separator.mjs +4 -2
  176. package/dist/client/ui/separator.mjs.map +1 -1
  177. package/dist/client/ui/sheet.d.ts +13 -1
  178. package/dist/client/ui/sheet.d.ts.map +1 -1
  179. package/dist/client/ui/sheet.mjs +35 -7
  180. package/dist/client/ui/sheet.mjs.map +1 -1
  181. package/dist/client/ui/slot-wrapper.d.ts +28 -0
  182. package/dist/client/ui/slot-wrapper.d.ts.map +1 -0
  183. package/dist/client/ui/slot-wrapper.mjs +38 -0
  184. package/dist/client/ui/slot-wrapper.mjs.map +1 -0
  185. package/dist/client/ui/tabs.d.ts +11 -1
  186. package/dist/client/ui/tabs.d.ts.map +1 -1
  187. package/dist/client/ui/tabs.mjs +21 -5
  188. package/dist/client/ui/tabs.mjs.map +1 -1
  189. package/dist/client/ui/toggle-group.d.ts +7 -4
  190. package/dist/client/ui/toggle-group.d.ts.map +1 -1
  191. package/dist/client/ui/toggle-group.mjs +4 -4
  192. package/dist/client/ui/toggle-group.mjs.map +1 -1
  193. package/dist/client/ui/toggle.d.ts +17 -8
  194. package/dist/client/ui/toggle.d.ts.map +1 -1
  195. package/dist/client/ui/toggle.mjs +11 -9
  196. package/dist/client/ui/toggle.mjs.map +1 -1
  197. package/dist/client/ui/tooltip.d.ts +6 -1
  198. package/dist/client/ui/tooltip.d.ts.map +1 -1
  199. package/dist/client/ui/tooltip.mjs +4 -2
  200. package/dist/client/ui/tooltip.mjs.map +1 -1
  201. package/dist/client/ui-resolver/button.d.ts +3 -4
  202. package/dist/client/ui-resolver/button.d.ts.map +1 -1
  203. package/dist/client/ui-resolver/button.mjs +2 -2
  204. package/dist/client/ui-resolver/button.mjs.map +1 -1
  205. package/dist/client/ui-resolver/card.d.ts +14 -1
  206. package/dist/client/ui-resolver/card.d.ts.map +1 -1
  207. package/dist/client/ui-resolver/card.mjs +3 -2
  208. package/dist/client/ui-resolver/card.mjs.map +1 -1
  209. package/dist/client/ui-resolver/context.mjs +1 -1
  210. package/dist/client/ui-resolver/context.mjs.map +1 -1
  211. package/dist/client/ui-resolver/index.d.ts +7 -4
  212. package/dist/client/ui-resolver/index.mjs +8 -6
  213. package/dist/client/ui-resolver/input.d.ts +3 -4
  214. package/dist/client/ui-resolver/input.d.ts.map +1 -1
  215. package/dist/client/ui-resolver/input.mjs +2 -2
  216. package/dist/client/ui-resolver/input.mjs.map +1 -1
  217. package/dist/client/ui-resolver/navigation-menu.d.ts +1 -2
  218. package/dist/client/ui-resolver/navigation-menu.d.ts.map +1 -1
  219. package/dist/client/ui-resolver/recipe.d.ts +95 -0
  220. package/dist/client/ui-resolver/recipe.d.ts.map +1 -0
  221. package/dist/client/ui-resolver/recipe.mjs +134 -0
  222. package/dist/client/ui-resolver/recipe.mjs.map +1 -0
  223. package/dist/client/ui-resolver/toggle.d.ts +2 -2
  224. package/dist/client/ui-resolver/toggle.mjs +2 -2
  225. package/dist/client/ui-resolver/toggle.mjs.map +1 -1
  226. package/dist/client/ui-resolver/types.d.ts +14 -0
  227. package/dist/client/ui-resolver/types.d.ts.map +1 -0
  228. package/dist/client/ui-resolver/types.mjs +1 -0
  229. package/dist/client/wishlist/wishlist-drawer.mjs +4 -4
  230. package/dist/client/wishlist/wishlist-drawer.mjs.map +1 -1
  231. package/dist/styles.css +1 -1
  232. 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 group context for hover effects and overflow handling.\n */\nfunction ProductCardRoot({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"product-card\"\n className={cn(\n \"enad-interactive group overflow-hidden rounded-[var(--enad-card-radius)]\",\n className,\n )}\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,GACT,4EACA,UACD;EACD,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"}
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":";;;;iBAoSS,WAAA,CAAY,KAAA,EAAO,gBAAA,GAAgB,kBAAA,CAAA,GAAA,CAAA,OAAA"}
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 HorizontalCard({ images = [], title, subtitle, price, tag, href, showFavorites = false, onFavoriteClick, className, HeartIcon }) {
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("flex shadow-[var(--enad-card-shadow)] transition-shadow duration-[var(--enad-motion-duration)] hover:shadow-[var(--enad-card-hover-shadow)]", className),
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: "relative w-1/3 shrink-0",
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: "flex-1 justify-center gap-0 p-4 md:p-6",
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("relative", className),
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 translate-y-full p-4 transition-transform duration-[var(--enad-motion-duration)] group-hover:translate-y-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": return /* @__PURE__ */ jsx(HorizontalCard, { ...layoutProps });
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 "list": return /* @__PURE__ */ jsx(ListCard, { ...layoutProps });
221
- case "stripped": return /* @__PURE__ */ jsx(StrippedCard, { ...layoutProps });
222
- default: return /* @__PURE__ */ jsx(GalleryCard, { ...layoutProps });
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 = "outset", showDots = true, showThumbnails = false, className }) {
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 transition-transform duration-[var(--enad-image-hover-duration)]", zoomed && "scale-150")
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\"\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 = \"outset\",\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) => { if (e.key === \"Enter\" || e.key === \" \") { e.preventDefault(); toggleZoom() } }\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(\n \"size-full object-cover transition-transform duration-[var(--enad-image-hover-duration)]\",\n zoomed && \"scale-150\",\n )}\n />\n </div>\n ))\n\n if (images.length === 0) {\n return (\n <div className={cn(\"bg-muted\", aspectClasses[aspectRatio], className)} />\n )\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\n src={img.src}\n alt={img.alt ?? \"\"}\n className=\"size-full object-cover\"\n />\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,UACT,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;AAAE,MAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AAAE,KAAE,gBAAgB;AAAE,eAAY;;;CAElI,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,GACT,2FACA,UAAU,YACX;GACD,CAAA;EACE,EAtBC,EAsBD,CACN;AAEF,KAAI,OAAO,WAAW,EACpB,QACE,oBAAC,OAAD,EAAK,WAAW,GAAG,YAAY,cAAc,cAAc,UAAU,EAAI,CAAA;AAI7E,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;KACE,KAAK,IAAI;KACT,KAAK,IAAI,OAAO;KAChB,WAAU;KACV,CAAA;IACK,EAhBF,EAgBE,CACT;GACE,CAAA,EACN,oBAAC,OAAD;GAAK,WAAU;aAAkB;GAAe,CAAA,CAC5C;;AAIV,QAAO,oBAAC,OAAD;EAAgB;YAAY;EAAe,CAAA"}
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":";;;;iBA6VS,oBAAA,CAAqB,KAAA,EAAO,yBAAA,GAAyB,kBAAA,CAAA,GAAA,CAAA,OAAA"}
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"}