@snacky/ui 0.12.0 → 0.13.1

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/index.d.cts CHANGED
@@ -396,6 +396,32 @@ interface SectionProps {
396
396
  */
397
397
  declare function Section({ title, onAction, children, className }: SectionProps): react.JSX.Element;
398
398
 
399
+ type ProductGroupLayout = 'horizontal' | 'banner' | 'grid';
400
+ interface ProductGroupSectionProps {
401
+ title: string;
402
+ /**
403
+ * `horizontal`: one scrolling row of cards (Figma Section `Group-Products-Horizontal`).
404
+ * `banner`: the row laid over a full-bleed banner from x160, scrolling over it (`Group-Products-Banner`).
405
+ * `grid`: two columns (`Group-Products-vertical`).
406
+ */
407
+ layout: ProductGroupLayout;
408
+ /** The products, normally `ProductCard`s with `variant="list"`. */
409
+ children: ReactNode;
410
+ /** Shows the header chevron and, in the scrolling layouts, the trailing "See other products" card. */
411
+ onSeeMore?: () => void;
412
+ seeMoreLabel?: string;
413
+ /** Required for `layout="banner"`, normally a `SquareBanner`. It sits still behind the scrolling row. */
414
+ banner?: ReactNode;
415
+ className?: string;
416
+ }
417
+ /**
418
+ * Snacky Product Group Section: a titled group of product cards, the pattern
419
+ * behind three of Figma's Section variants (8 instances across Home and product
420
+ * detail). Section itself stays a generic shell; this packages the product
421
+ * layouts so they can be used by name instead of rebuilt by hand.
422
+ */
423
+ declare function ProductGroupSection({ title, layout, children, onSeeMore, seeMoreLabel, banner, className, }: ProductGroupSectionProps): react.JSX.Element;
424
+
399
425
  type StepState = 'done' | 'pending' | 'cancelled';
400
426
  interface Step {
401
427
  label: string;
@@ -700,4 +726,4 @@ declare const SnackyIcons: {
700
726
  solid: typeof solid;
701
727
  };
702
728
 
703
- export { Accordion, type AccordionProps, AddressResult, type AddressResultProps, AlertBanner, type AlertBannerProps, Avatar, type AvatarProps, type AvatarSize, BottomSheet, type BottomSheetProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Calendar, type CalendarProps, Callout, type CalloutProps, type CalloutVariant, ChatInput, type ChatInputProps, Checkbox, type CheckboxProps, CopyField, type CopyFieldProps, DiscountTag, type DiscountTagProps, FilterChip, type FilterChipProps, FullWidthBanner, Header, type HeaderLeadingIcon, type HeaderProps, HeroBanner, IconButton, type IconButtonProps, type IconButtonVariant, type IconProps, Illustration, type IllustrationProps, type IllustrationVariant, type ImageBannerProps, ImagePlaceholder, type ImagePlaceholderProps, InfoBadge, type InfoBadgeProps, NavBar, type NavBarProps, type NavItem, NotificationBadge, type NotificationBadgeProps, NotificationListItem, type NotificationListItemProps, OrderListItem, type OrderListItemProps, type OrderStatus, OtpField, type OtpFieldProps, PageIndicator, type PageIndicatorProps, PointBalanceBanner, type PointBalanceBannerProps, ProductCard, type ProductCardDetailsProps, type ProductCardListProps, type ProductCardProps, ProductChip, type ProductChipProps, ProductImage, type ProductImageProps, type ProductImageUsage, RadioOption, type RadioOptionProps, SearchField, type SearchFieldProps, Section, type SectionProps, SnackyIcons, SoldOutBadge, type SoldOutBadgeProps, SquareBanner, type Step, type StepState, Stepper, type StepperProps, TabRow, type TabRowProps, TextField, type TextFieldProps, Toggle, type ToggleProps, UploadButton, type UploadButtonProps, VariantBadge, type VariantBadgeProps, typography };
729
+ export { Accordion, type AccordionProps, AddressResult, type AddressResultProps, AlertBanner, type AlertBannerProps, Avatar, type AvatarProps, type AvatarSize, BottomSheet, type BottomSheetProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Calendar, type CalendarProps, Callout, type CalloutProps, type CalloutVariant, ChatInput, type ChatInputProps, Checkbox, type CheckboxProps, CopyField, type CopyFieldProps, DiscountTag, type DiscountTagProps, FilterChip, type FilterChipProps, FullWidthBanner, Header, type HeaderLeadingIcon, type HeaderProps, HeroBanner, IconButton, type IconButtonProps, type IconButtonVariant, type IconProps, Illustration, type IllustrationProps, type IllustrationVariant, type ImageBannerProps, ImagePlaceholder, type ImagePlaceholderProps, InfoBadge, type InfoBadgeProps, NavBar, type NavBarProps, type NavItem, NotificationBadge, type NotificationBadgeProps, NotificationListItem, type NotificationListItemProps, OrderListItem, type OrderListItemProps, type OrderStatus, OtpField, type OtpFieldProps, PageIndicator, type PageIndicatorProps, PointBalanceBanner, type PointBalanceBannerProps, ProductCard, type ProductCardDetailsProps, type ProductCardListProps, type ProductCardProps, ProductChip, type ProductChipProps, type ProductGroupLayout, ProductGroupSection, type ProductGroupSectionProps, ProductImage, type ProductImageProps, type ProductImageUsage, RadioOption, type RadioOptionProps, SearchField, type SearchFieldProps, Section, type SectionProps, SnackyIcons, SoldOutBadge, type SoldOutBadgeProps, SquareBanner, type Step, type StepState, Stepper, type StepperProps, TabRow, type TabRowProps, TextField, type TextFieldProps, Toggle, type ToggleProps, UploadButton, type UploadButtonProps, VariantBadge, type VariantBadgeProps, typography };
package/dist/index.d.ts CHANGED
@@ -396,6 +396,32 @@ interface SectionProps {
396
396
  */
397
397
  declare function Section({ title, onAction, children, className }: SectionProps): react.JSX.Element;
398
398
 
399
+ type ProductGroupLayout = 'horizontal' | 'banner' | 'grid';
400
+ interface ProductGroupSectionProps {
401
+ title: string;
402
+ /**
403
+ * `horizontal`: one scrolling row of cards (Figma Section `Group-Products-Horizontal`).
404
+ * `banner`: the row laid over a full-bleed banner from x160, scrolling over it (`Group-Products-Banner`).
405
+ * `grid`: two columns (`Group-Products-vertical`).
406
+ */
407
+ layout: ProductGroupLayout;
408
+ /** The products, normally `ProductCard`s with `variant="list"`. */
409
+ children: ReactNode;
410
+ /** Shows the header chevron and, in the scrolling layouts, the trailing "See other products" card. */
411
+ onSeeMore?: () => void;
412
+ seeMoreLabel?: string;
413
+ /** Required for `layout="banner"`, normally a `SquareBanner`. It sits still behind the scrolling row. */
414
+ banner?: ReactNode;
415
+ className?: string;
416
+ }
417
+ /**
418
+ * Snacky Product Group Section: a titled group of product cards, the pattern
419
+ * behind three of Figma's Section variants (8 instances across Home and product
420
+ * detail). Section itself stays a generic shell; this packages the product
421
+ * layouts so they can be used by name instead of rebuilt by hand.
422
+ */
423
+ declare function ProductGroupSection({ title, layout, children, onSeeMore, seeMoreLabel, banner, className, }: ProductGroupSectionProps): react.JSX.Element;
424
+
399
425
  type StepState = 'done' | 'pending' | 'cancelled';
400
426
  interface Step {
401
427
  label: string;
@@ -700,4 +726,4 @@ declare const SnackyIcons: {
700
726
  solid: typeof solid;
701
727
  };
702
728
 
703
- export { Accordion, type AccordionProps, AddressResult, type AddressResultProps, AlertBanner, type AlertBannerProps, Avatar, type AvatarProps, type AvatarSize, BottomSheet, type BottomSheetProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Calendar, type CalendarProps, Callout, type CalloutProps, type CalloutVariant, ChatInput, type ChatInputProps, Checkbox, type CheckboxProps, CopyField, type CopyFieldProps, DiscountTag, type DiscountTagProps, FilterChip, type FilterChipProps, FullWidthBanner, Header, type HeaderLeadingIcon, type HeaderProps, HeroBanner, IconButton, type IconButtonProps, type IconButtonVariant, type IconProps, Illustration, type IllustrationProps, type IllustrationVariant, type ImageBannerProps, ImagePlaceholder, type ImagePlaceholderProps, InfoBadge, type InfoBadgeProps, NavBar, type NavBarProps, type NavItem, NotificationBadge, type NotificationBadgeProps, NotificationListItem, type NotificationListItemProps, OrderListItem, type OrderListItemProps, type OrderStatus, OtpField, type OtpFieldProps, PageIndicator, type PageIndicatorProps, PointBalanceBanner, type PointBalanceBannerProps, ProductCard, type ProductCardDetailsProps, type ProductCardListProps, type ProductCardProps, ProductChip, type ProductChipProps, ProductImage, type ProductImageProps, type ProductImageUsage, RadioOption, type RadioOptionProps, SearchField, type SearchFieldProps, Section, type SectionProps, SnackyIcons, SoldOutBadge, type SoldOutBadgeProps, SquareBanner, type Step, type StepState, Stepper, type StepperProps, TabRow, type TabRowProps, TextField, type TextFieldProps, Toggle, type ToggleProps, UploadButton, type UploadButtonProps, VariantBadge, type VariantBadgeProps, typography };
729
+ export { Accordion, type AccordionProps, AddressResult, type AddressResultProps, AlertBanner, type AlertBannerProps, Avatar, type AvatarProps, type AvatarSize, BottomSheet, type BottomSheetProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Calendar, type CalendarProps, Callout, type CalloutProps, type CalloutVariant, ChatInput, type ChatInputProps, Checkbox, type CheckboxProps, CopyField, type CopyFieldProps, DiscountTag, type DiscountTagProps, FilterChip, type FilterChipProps, FullWidthBanner, Header, type HeaderLeadingIcon, type HeaderProps, HeroBanner, IconButton, type IconButtonProps, type IconButtonVariant, type IconProps, Illustration, type IllustrationProps, type IllustrationVariant, type ImageBannerProps, ImagePlaceholder, type ImagePlaceholderProps, InfoBadge, type InfoBadgeProps, NavBar, type NavBarProps, type NavItem, NotificationBadge, type NotificationBadgeProps, NotificationListItem, type NotificationListItemProps, OrderListItem, type OrderListItemProps, type OrderStatus, OtpField, type OtpFieldProps, PageIndicator, type PageIndicatorProps, PointBalanceBanner, type PointBalanceBannerProps, ProductCard, type ProductCardDetailsProps, type ProductCardListProps, type ProductCardProps, ProductChip, type ProductChipProps, type ProductGroupLayout, ProductGroupSection, type ProductGroupSectionProps, ProductImage, type ProductImageProps, type ProductImageUsage, RadioOption, type RadioOptionProps, SearchField, type SearchFieldProps, Section, type SectionProps, SnackyIcons, SoldOutBadge, type SoldOutBadgeProps, SquareBanner, type Step, type StepState, Stepper, type StepperProps, TabRow, type TabRowProps, TextField, type TextFieldProps, Toggle, type ToggleProps, UploadButton, type UploadButtonProps, VariantBadge, type VariantBadgeProps, typography };
package/dist/index.js CHANGED
@@ -1005,18 +1005,102 @@ function Section({ title, onAction, children, className }) {
1005
1005
  ] });
1006
1006
  }
1007
1007
 
1008
- // src/components/Stepper/Stepper.tsx
1008
+ // src/components/ProductGroupSection/ProductGroupSection.tsx
1009
+ import { useRef as useRef2 } from "react";
1009
1010
  import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
1011
+ function ProductGroupSection({
1012
+ title,
1013
+ layout,
1014
+ children,
1015
+ onSeeMore,
1016
+ seeMoreLabel = "See other products",
1017
+ banner,
1018
+ className
1019
+ }) {
1020
+ const drag = useDragScroll();
1021
+ const seeMore = onSeeMore && layout !== "grid" && /* @__PURE__ */ jsxs20("div", { className: "snacky-product-group__see-more", children: [
1022
+ /* @__PURE__ */ jsx28(IconButton, { size: "small", icon: /* @__PURE__ */ jsx28(angleSmallRight, {}), onClick: onSeeMore, ariaLabel: seeMoreLabel }),
1023
+ /* @__PURE__ */ jsx28("span", { className: "snacky-product-group__see-more-label", children: seeMoreLabel })
1024
+ ] });
1025
+ return /* @__PURE__ */ jsxs20(
1026
+ Section,
1027
+ {
1028
+ title,
1029
+ onAction: onSeeMore,
1030
+ className: cx("snacky-product-group", `snacky-product-group--${layout}`, className),
1031
+ children: [
1032
+ layout === "grid" && /* @__PURE__ */ jsx28("div", { className: "snacky-product-group__grid", children }),
1033
+ layout === "horizontal" && /* @__PURE__ */ jsxs20("div", { className: "snacky-product-group__row", ...drag, children: [
1034
+ children,
1035
+ seeMore
1036
+ ] }),
1037
+ layout === "banner" && /* @__PURE__ */ jsxs20("div", { className: "snacky-product-group__stage", children: [
1038
+ /* @__PURE__ */ jsx28("div", { className: "snacky-product-group__banner", children: banner }),
1039
+ /* @__PURE__ */ jsxs20("div", { className: "snacky-product-group__row", ...drag, children: [
1040
+ children,
1041
+ seeMore
1042
+ ] })
1043
+ ] })
1044
+ ]
1045
+ }
1046
+ );
1047
+ }
1048
+ function useDragScroll() {
1049
+ const state = useRef2(null);
1050
+ const justDragged = useRef2(false);
1051
+ return {
1052
+ onPointerDown(e) {
1053
+ if (e.pointerType !== "mouse") return;
1054
+ state.current = { x: e.clientX, left: e.currentTarget.scrollLeft, moved: false, id: e.pointerId };
1055
+ },
1056
+ onPointerMove(e) {
1057
+ const d = state.current;
1058
+ if (!d) return;
1059
+ const dx = e.clientX - d.x;
1060
+ if (!d.moved && Math.abs(dx) > 4) {
1061
+ d.moved = true;
1062
+ e.currentTarget.setPointerCapture(d.id);
1063
+ e.currentTarget.classList.add("snacky-product-group__row--dragging");
1064
+ }
1065
+ if (d.moved) e.currentTarget.scrollLeft = d.left - dx;
1066
+ },
1067
+ onPointerUp(e) {
1068
+ if (state.current?.moved) {
1069
+ e.currentTarget.classList.remove("snacky-product-group__row--dragging");
1070
+ justDragged.current = true;
1071
+ setTimeout(() => {
1072
+ justDragged.current = false;
1073
+ }, 0);
1074
+ }
1075
+ state.current = null;
1076
+ },
1077
+ onPointerCancel() {
1078
+ state.current = null;
1079
+ },
1080
+ onClickCapture(e) {
1081
+ if (justDragged.current) {
1082
+ e.stopPropagation();
1083
+ e.preventDefault();
1084
+ }
1085
+ },
1086
+ onDragStart(e) {
1087
+ e.preventDefault();
1088
+ }
1089
+ };
1090
+ }
1091
+
1092
+ // src/components/Stepper/Stepper.tsx
1093
+ import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
1010
1094
  function Stepper({ steps, className }) {
1011
- return /* @__PURE__ */ jsx28("ol", { className: cx("snacky-stepper", className), children: steps.map((step, i) => /* @__PURE__ */ jsxs20(
1095
+ return /* @__PURE__ */ jsx29("ol", { className: cx("snacky-stepper", className), children: steps.map((step, i) => /* @__PURE__ */ jsxs21(
1012
1096
  "li",
1013
1097
  {
1014
1098
  className: cx("snacky-stepper__step", i === steps.length - 1 && "snacky-stepper__step--last"),
1015
1099
  children: [
1016
- /* @__PURE__ */ jsx28("span", { className: cx("snacky-stepper__dot", `snacky-stepper__dot--${step.state}`), children: step.state === "cancelled" && /* @__PURE__ */ jsx28(close, { width: 12, height: 12 }) }),
1017
- /* @__PURE__ */ jsxs20("span", { className: "snacky-stepper__body", children: [
1018
- /* @__PURE__ */ jsx28("span", { className: cx("snacky-stepper__label", `snacky-stepper__label--${step.state}`), children: step.label }),
1019
- step.timestamp && /* @__PURE__ */ jsx28("span", { className: "snacky-stepper__time", children: step.timestamp })
1100
+ /* @__PURE__ */ jsx29("span", { className: cx("snacky-stepper__dot", `snacky-stepper__dot--${step.state}`), children: step.state === "cancelled" && /* @__PURE__ */ jsx29(close, { width: 12, height: 12 }) }),
1101
+ /* @__PURE__ */ jsxs21("span", { className: "snacky-stepper__body", children: [
1102
+ /* @__PURE__ */ jsx29("span", { className: cx("snacky-stepper__label", `snacky-stepper__label--${step.state}`), children: step.label }),
1103
+ step.timestamp && /* @__PURE__ */ jsx29("span", { className: "snacky-stepper__time", children: step.timestamp })
1020
1104
  ] })
1021
1105
  ]
1022
1106
  },
@@ -1025,7 +1109,7 @@ function Stepper({ steps, className }) {
1025
1109
  }
1026
1110
 
1027
1111
  // src/components/Calendar/Calendar.tsx
1028
- import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
1112
+ import { jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
1029
1113
  var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
1030
1114
  var MONTHS = [
1031
1115
  "January",
@@ -1072,39 +1156,39 @@ function Calendar({
1072
1156
  const [lo, hi] = range ? [range[0], range[1]].sort((a, b) => a.getTime() - b.getTime()) : [null, null];
1073
1157
  const isEnd = (d) => single && sameDay(d, single) || lo && hi && (sameDay(d, lo) || sameDay(d, hi));
1074
1158
  const isInRange = (d) => lo && hi && d > lo && d < hi;
1075
- return /* @__PURE__ */ jsxs21("div", { className: cx("snacky-calendar", className), children: [
1076
- /* @__PURE__ */ jsxs21("div", { className: "snacky-calendar__header", children: [
1077
- /* @__PURE__ */ jsx29(
1159
+ return /* @__PURE__ */ jsxs22("div", { className: cx("snacky-calendar", className), children: [
1160
+ /* @__PURE__ */ jsxs22("div", { className: "snacky-calendar__header", children: [
1161
+ /* @__PURE__ */ jsx30(
1078
1162
  "button",
1079
1163
  {
1080
1164
  type: "button",
1081
1165
  className: "snacky-calendar__nav",
1082
1166
  onClick: onPrevMonth,
1083
1167
  "aria-label": "Previous month",
1084
- children: /* @__PURE__ */ jsx29(back, { width: 24, height: 24 })
1168
+ children: /* @__PURE__ */ jsx30(back, { width: 24, height: 24 })
1085
1169
  }
1086
1170
  ),
1087
- /* @__PURE__ */ jsxs21("span", { className: "snacky-calendar__label", children: [
1171
+ /* @__PURE__ */ jsxs22("span", { className: "snacky-calendar__label", children: [
1088
1172
  MONTHS[month.getMonth()],
1089
1173
  " ",
1090
1174
  month.getFullYear()
1091
1175
  ] }),
1092
- /* @__PURE__ */ jsx29(
1176
+ /* @__PURE__ */ jsx30(
1093
1177
  "button",
1094
1178
  {
1095
1179
  type: "button",
1096
1180
  className: "snacky-calendar__nav snacky-calendar__nav--next",
1097
1181
  onClick: onNextMonth,
1098
1182
  "aria-label": "Next month",
1099
- children: /* @__PURE__ */ jsx29(back, { width: 24, height: 24 })
1183
+ children: /* @__PURE__ */ jsx30(back, { width: 24, height: 24 })
1100
1184
  }
1101
1185
  )
1102
1186
  ] }),
1103
- /* @__PURE__ */ jsxs21("div", { className: "snacky-calendar__grid", children: [
1104
- WEEKDAYS.map((d) => /* @__PURE__ */ jsx29("span", { className: "snacky-calendar__weekday", children: d }, d)),
1187
+ /* @__PURE__ */ jsxs22("div", { className: "snacky-calendar__grid", children: [
1188
+ WEEKDAYS.map((d) => /* @__PURE__ */ jsx30("span", { className: "snacky-calendar__weekday", children: d }, d)),
1105
1189
  days.map((d, i) => {
1106
1190
  const outside = d.getMonth() !== month.getMonth();
1107
- return /* @__PURE__ */ jsxs21(
1191
+ return /* @__PURE__ */ jsxs22(
1108
1192
  "button",
1109
1193
  {
1110
1194
  type: "button",
@@ -1118,26 +1202,26 @@ function Calendar({
1118
1202
  disabled: outside,
1119
1203
  "aria-current": isEnd(d) ? "date" : void 0,
1120
1204
  children: [
1121
- /* @__PURE__ */ jsx29("span", { className: "snacky-calendar__day-number", children: d.getDate() }),
1122
- marked.some((m) => sameDay(m, d)) && /* @__PURE__ */ jsx29("span", { className: "snacky-calendar__marker" })
1205
+ /* @__PURE__ */ jsx30("span", { className: "snacky-calendar__day-number", children: d.getDate() }),
1206
+ marked.some((m) => sameDay(m, d)) && /* @__PURE__ */ jsx30("span", { className: "snacky-calendar__marker" })
1123
1207
  ]
1124
1208
  },
1125
1209
  i
1126
1210
  );
1127
1211
  })
1128
1212
  ] }),
1129
- onAction && /* @__PURE__ */ jsx29(Button, { onClick: onAction, style: { width: "100%" }, children: actionLabel })
1213
+ onAction && /* @__PURE__ */ jsx30(Button, { onClick: onAction, style: { width: "100%" }, children: actionLabel })
1130
1214
  ] });
1131
1215
  }
1132
1216
 
1133
1217
  // src/components/Avatar/Avatar.tsx
1134
- import { jsx as jsx30 } from "react/jsx-runtime";
1218
+ import { jsx as jsx31 } from "react/jsx-runtime";
1135
1219
  function Avatar({ src, alt, size = "md", className }) {
1136
- return /* @__PURE__ */ jsx30("img", { src, alt, className: cx("snacky-avatar", `snacky-avatar--${size}`, className) });
1220
+ return /* @__PURE__ */ jsx31("img", { src, alt, className: cx("snacky-avatar", `snacky-avatar--${size}`, className) });
1137
1221
  }
1138
1222
 
1139
1223
  // src/components/Illustration/Illustration.tsx
1140
- import { jsx as jsx31 } from "react/jsx-runtime";
1224
+ import { jsx as jsx32 } from "react/jsx-runtime";
1141
1225
  var SIZE = {
1142
1226
  empty: { width: 268, height: 200 },
1143
1227
  createAccount: { width: 360, height: 240 },
@@ -1147,54 +1231,54 @@ var SIZE = {
1147
1231
  };
1148
1232
  function Illustration({ variant, src, alt, className }) {
1149
1233
  const { width, height } = SIZE[variant];
1150
- return /* @__PURE__ */ jsx31("img", { src, alt, width, height, className: cx("snacky-illustration", className) });
1234
+ return /* @__PURE__ */ jsx32("img", { src, alt, width, height, className: cx("snacky-illustration", className) });
1151
1235
  }
1152
1236
 
1153
1237
  // src/components/ProductImage/ProductImage.tsx
1154
- import { jsx as jsx32, jsxs as jsxs22 } from "react/jsx-runtime";
1238
+ import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
1155
1239
  function ProductImage({ src, alt, usage, sold = false, className }) {
1156
- return /* @__PURE__ */ jsxs22("span", { className: cx("snacky-product-image-wrap", `snacky-product-image-wrap--${usage}`, className), children: [
1157
- /* @__PURE__ */ jsx32("img", { src, alt, className: cx("snacky-product-image", `snacky-product-image--${usage}`) }),
1158
- sold && /* @__PURE__ */ jsx32("span", { className: "snacky-product-image-sold-overlay", children: /* @__PURE__ */ jsx32("span", { className: "snacky-product-image-sold-label", children: "Sold Out" }) })
1240
+ return /* @__PURE__ */ jsxs23("span", { className: cx("snacky-product-image-wrap", `snacky-product-image-wrap--${usage}`, className), children: [
1241
+ /* @__PURE__ */ jsx33("img", { src, alt, className: cx("snacky-product-image", `snacky-product-image--${usage}`) }),
1242
+ sold && /* @__PURE__ */ jsx33("span", { className: "snacky-product-image-sold-overlay", children: /* @__PURE__ */ jsx33("span", { className: "snacky-product-image-sold-label", children: "Sold Out" }) })
1159
1243
  ] });
1160
1244
  }
1161
1245
 
1162
1246
  // src/components/ProductCard/ProductCard.tsx
1163
- import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
1247
+ import { jsx as jsx34, jsxs as jsxs24 } from "react/jsx-runtime";
1164
1248
  function ProductCard(props) {
1165
1249
  if (props.variant === "details") {
1166
1250
  const { productName: productName2, imageUrl: imageUrl2, price: price2, rating: rating2, originalPrice: originalPrice2, discountLabel: discountLabel2, ratingCount, favorited, onFavoriteClick, onShareClick, onChatClick, sold, ratingIcon: ratingIcon2, favoriteIcon, shareIcon, chatIcon, onClick: onClick2, className: className2 } = props;
1167
- return /* @__PURE__ */ jsxs23("div", { className: cx("snacky-product-card", "snacky-product-card--details", className2), children: [
1168
- /* @__PURE__ */ jsx33("div", { className: "snacky-product-card__image-block", children: /* @__PURE__ */ jsxs23("div", { className: "snacky-product-card__image-wrap", onClick: onClick2, children: [
1169
- /* @__PURE__ */ jsx33("img", { className: "snacky-product-card__image", src: imageUrl2, alt: productName2 }),
1170
- sold && /* @__PURE__ */ jsx33("span", { className: "snacky-product-card__sold-overlay", children: /* @__PURE__ */ jsx33(SoldOutBadge, {}) })
1251
+ return /* @__PURE__ */ jsxs24("div", { className: cx("snacky-product-card", "snacky-product-card--details", className2), children: [
1252
+ /* @__PURE__ */ jsx34("div", { className: "snacky-product-card__image-block", children: /* @__PURE__ */ jsxs24("div", { className: "snacky-product-card__image-wrap", onClick: onClick2, children: [
1253
+ /* @__PURE__ */ jsx34("img", { className: "snacky-product-card__image", src: imageUrl2, alt: productName2 }),
1254
+ sold && /* @__PURE__ */ jsx34("span", { className: "snacky-product-card__sold-overlay", children: /* @__PURE__ */ jsx34(SoldOutBadge, {}) })
1171
1255
  ] }) }),
1172
- /* @__PURE__ */ jsxs23("div", { className: "snacky-product-card__details-body", children: [
1173
- /* @__PURE__ */ jsx33("p", { className: "snacky-product-card__name", children: productName2 }),
1174
- /* @__PURE__ */ jsxs23("div", { className: "snacky-product-card__price-row", children: [
1175
- /* @__PURE__ */ jsx33("span", { className: "snacky-product-card__price", children: price2 }),
1176
- originalPrice2 && /* @__PURE__ */ jsx33("span", { className: "snacky-product-card__original-price", children: originalPrice2 }),
1177
- discountLabel2 && /* @__PURE__ */ jsx33(DiscountTag, { label: discountLabel2 })
1256
+ /* @__PURE__ */ jsxs24("div", { className: "snacky-product-card__details-body", children: [
1257
+ /* @__PURE__ */ jsx34("p", { className: "snacky-product-card__name", children: productName2 }),
1258
+ /* @__PURE__ */ jsxs24("div", { className: "snacky-product-card__price-row", children: [
1259
+ /* @__PURE__ */ jsx34("span", { className: "snacky-product-card__price", children: price2 }),
1260
+ originalPrice2 && /* @__PURE__ */ jsx34("span", { className: "snacky-product-card__original-price", children: originalPrice2 }),
1261
+ discountLabel2 && /* @__PURE__ */ jsx34(DiscountTag, { label: discountLabel2 })
1178
1262
  ] }),
1179
- /* @__PURE__ */ jsxs23("div", { className: "snacky-product-card__footer-row", children: [
1180
- /* @__PURE__ */ jsxs23("span", { className: "snacky-product-card__rating", children: [
1181
- /* @__PURE__ */ jsx33("span", { className: "snacky-product-card__rating-icon", children: ratingIcon2 ?? /* @__PURE__ */ jsx33(star, { width: 16, height: 16 }) }),
1263
+ /* @__PURE__ */ jsxs24("div", { className: "snacky-product-card__footer-row", children: [
1264
+ /* @__PURE__ */ jsxs24("span", { className: "snacky-product-card__rating", children: [
1265
+ /* @__PURE__ */ jsx34("span", { className: "snacky-product-card__rating-icon", children: ratingIcon2 ?? /* @__PURE__ */ jsx34(star, { width: 16, height: 16 }) }),
1182
1266
  rating2,
1183
1267
  " (",
1184
1268
  ratingCount,
1185
1269
  ")"
1186
1270
  ] }),
1187
- /* @__PURE__ */ jsxs23("div", { className: "snacky-product-card__actions snacky-product-card__actions--details", children: [
1188
- /* @__PURE__ */ jsx33(IconButton, { variant: "secondary", icon: favoriteIcon ?? (favorited ? /* @__PURE__ */ jsx33(heart2, { width: 20, height: 20 }) : /* @__PURE__ */ jsx33(heart, { width: 20, height: 20 })), selected: favorited, onClick: onFavoriteClick, ariaLabel: "Favorite" }),
1189
- /* @__PURE__ */ jsx33(IconButton, { variant: "secondary", icon: shareIcon ?? /* @__PURE__ */ jsx33(share, { width: 20, height: 20 }), onClick: onShareClick, ariaLabel: "Share" }),
1190
- /* @__PURE__ */ jsx33(IconButton, { variant: "secondary", icon: chatIcon ?? /* @__PURE__ */ jsx33(chat, { width: 20, height: 20 }), onClick: onChatClick, ariaLabel: "Chat with seller" })
1271
+ /* @__PURE__ */ jsxs24("div", { className: "snacky-product-card__actions snacky-product-card__actions--details", children: [
1272
+ /* @__PURE__ */ jsx34(IconButton, { variant: "secondary", icon: favoriteIcon ?? (favorited ? /* @__PURE__ */ jsx34(heart2, { width: 20, height: 20 }) : /* @__PURE__ */ jsx34(heart, { width: 20, height: 20 })), selected: favorited, onClick: onFavoriteClick, ariaLabel: "Favorite" }),
1273
+ /* @__PURE__ */ jsx34(IconButton, { variant: "secondary", icon: shareIcon ?? /* @__PURE__ */ jsx34(share, { width: 20, height: 20 }), onClick: onShareClick, ariaLabel: "Share" }),
1274
+ /* @__PURE__ */ jsx34(IconButton, { variant: "secondary", icon: chatIcon ?? /* @__PURE__ */ jsx34(chat, { width: 20, height: 20 }), onClick: onChatClick, ariaLabel: "Chat with seller" })
1191
1275
  ] })
1192
1276
  ] })
1193
1277
  ] })
1194
1278
  ] });
1195
1279
  }
1196
1280
  const { productName, imageUrl, price, rating, originalPrice, discountLabel, onAddToCart, cartIcon, ratingIcon, onClick, className } = props;
1197
- return /* @__PURE__ */ jsxs23(
1281
+ return /* @__PURE__ */ jsxs24(
1198
1282
  "div",
1199
1283
  {
1200
1284
  className: cx("snacky-product-card", "snacky-product-card--list", className),
@@ -1203,25 +1287,25 @@ function ProductCard(props) {
1203
1287
  onClick,
1204
1288
  onKeyDown: (e) => (e.key === "Enter" || e.key === " ") && onClick?.(),
1205
1289
  children: [
1206
- /* @__PURE__ */ jsxs23("div", { className: "snacky-product-card__image-wrap", children: [
1207
- /* @__PURE__ */ jsx33("img", { className: "snacky-product-card__image", src: imageUrl, alt: productName }),
1208
- discountLabel && /* @__PURE__ */ jsx33("span", { className: "snacky-product-card__discount", children: /* @__PURE__ */ jsx33(DiscountTag, { label: discountLabel }) })
1290
+ /* @__PURE__ */ jsxs24("div", { className: "snacky-product-card__image-wrap", children: [
1291
+ /* @__PURE__ */ jsx34("img", { className: "snacky-product-card__image", src: imageUrl, alt: productName }),
1292
+ discountLabel && /* @__PURE__ */ jsx34("span", { className: "snacky-product-card__discount", children: /* @__PURE__ */ jsx34(DiscountTag, { label: discountLabel }) })
1209
1293
  ] }),
1210
- /* @__PURE__ */ jsx33("p", { className: "snacky-product-card__name", children: productName }),
1211
- /* @__PURE__ */ jsxs23("div", { className: "snacky-product-card__price-row", children: [
1212
- /* @__PURE__ */ jsx33("span", { className: "snacky-product-card__price", children: price }),
1213
- originalPrice && /* @__PURE__ */ jsx33("span", { className: "snacky-product-card__original-price", children: originalPrice })
1294
+ /* @__PURE__ */ jsx34("p", { className: "snacky-product-card__name", children: productName }),
1295
+ /* @__PURE__ */ jsxs24("div", { className: "snacky-product-card__price-row", children: [
1296
+ /* @__PURE__ */ jsx34("span", { className: "snacky-product-card__price", children: price }),
1297
+ originalPrice && /* @__PURE__ */ jsx34("span", { className: "snacky-product-card__original-price", children: originalPrice })
1214
1298
  ] }),
1215
- /* @__PURE__ */ jsxs23("div", { className: "snacky-product-card__footer-row", children: [
1216
- /* @__PURE__ */ jsxs23("span", { className: "snacky-product-card__rating", children: [
1217
- /* @__PURE__ */ jsx33("span", { className: "snacky-product-card__rating-icon", children: ratingIcon ?? /* @__PURE__ */ jsx33(star, { width: 16, height: 16 }) }),
1299
+ /* @__PURE__ */ jsxs24("div", { className: "snacky-product-card__footer-row", children: [
1300
+ /* @__PURE__ */ jsxs24("span", { className: "snacky-product-card__rating", children: [
1301
+ /* @__PURE__ */ jsx34("span", { className: "snacky-product-card__rating-icon", children: ratingIcon ?? /* @__PURE__ */ jsx34(star, { width: 16, height: 16 }) }),
1218
1302
  rating
1219
1303
  ] }),
1220
- /* @__PURE__ */ jsx33(
1304
+ /* @__PURE__ */ jsx34(
1221
1305
  IconButton,
1222
1306
  {
1223
1307
  variant: "primary",
1224
- icon: cartIcon ?? /* @__PURE__ */ jsx33(cartAdd, { width: 16, height: 16 }),
1308
+ icon: cartIcon ?? /* @__PURE__ */ jsx34(cartAdd, { width: 16, height: 16 }),
1225
1309
  onClick: (e) => {
1226
1310
  e.stopPropagation();
1227
1311
  onAddToCart();
@@ -1236,17 +1320,17 @@ function ProductCard(props) {
1236
1320
  }
1237
1321
 
1238
1322
  // src/components/ImagePlaceholder/ImagePlaceholder.tsx
1239
- import { jsx as jsx34, jsxs as jsxs24 } from "react/jsx-runtime";
1323
+ import { jsx as jsx35, jsxs as jsxs25 } from "react/jsx-runtime";
1240
1324
  function ImagePlaceholder({ width, height, className }) {
1241
1325
  const iconSize = Math.round(Math.min(width, height) * 0.32);
1242
- return /* @__PURE__ */ jsx34(
1326
+ return /* @__PURE__ */ jsx35(
1243
1327
  "div",
1244
1328
  {
1245
1329
  className: cx("snacky-image-placeholder", className),
1246
1330
  style: { width, height },
1247
1331
  role: "img",
1248
1332
  "aria-label": "No image",
1249
- children: /* @__PURE__ */ jsxs24(
1333
+ children: /* @__PURE__ */ jsxs25(
1250
1334
  "svg",
1251
1335
  {
1252
1336
  width: iconSize,
@@ -1258,9 +1342,9 @@ function ImagePlaceholder({ width, height, className }) {
1258
1342
  strokeLinecap: "round",
1259
1343
  strokeLinejoin: "round",
1260
1344
  children: [
1261
- /* @__PURE__ */ jsx34("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
1262
- /* @__PURE__ */ jsx34("circle", { cx: "8.5", cy: "8.5", r: "1.5", fill: "currentColor", stroke: "none" }),
1263
- /* @__PURE__ */ jsx34("polyline", { points: "21 15 16 10 5 21" })
1345
+ /* @__PURE__ */ jsx35("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
1346
+ /* @__PURE__ */ jsx35("circle", { cx: "8.5", cy: "8.5", r: "1.5", fill: "currentColor", stroke: "none" }),
1347
+ /* @__PURE__ */ jsx35("polyline", { points: "21 15 16 10 5 21" })
1264
1348
  ]
1265
1349
  }
1266
1350
  )
@@ -1297,6 +1381,7 @@ export {
1297
1381
  PointBalanceBanner,
1298
1382
  ProductCard,
1299
1383
  ProductChip,
1384
+ ProductGroupSection,
1300
1385
  ProductImage,
1301
1386
  RadioOption,
1302
1387
  SearchField,