@snacky/ui 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/README.md +4 -3
- package/dist/index.cjs +155 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +75 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +32 -5
- package/dist/index.d.ts +32 -5
- package/dist/index.js +154 -65
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,67 @@ How `@snacky/ui` got to its current state. The README documents what the
|
|
|
4
4
|
package *is*; this documents how it got there, including the mistakes, so the
|
|
5
5
|
verification claims in the README can be taken at face value.
|
|
6
6
|
|
|
7
|
+
## ProductGroupSection, and a mouse-draggable product row (0.13.0)
|
|
8
|
+
|
|
9
|
+
`ProductGroupSection` is a titled group of list `ProductCard`s with
|
|
10
|
+
`layout="horizontal" | "banner" | "grid"`. It packages three variants of Figma's
|
|
11
|
+
Section set (`Group-Products-Horizontal`, `-Banner`, `-vertical`), which between
|
|
12
|
+
them have 8 instances across the Home and product detail screens.
|
|
13
|
+
|
|
14
|
+
The reason it exists is that `Section` is a shell: a title, an optional see-more
|
|
15
|
+
chevron, and `children`. Those three variants were never props on it, so every
|
|
16
|
+
use meant rebuilding the same things by hand, and a design agent working from the
|
|
17
|
+
package had to improvise them: the trailing "See other products" card (which
|
|
18
|
+
Figma also draws by hand, twice), a row that runs out to the screen's right edge,
|
|
19
|
+
and for the banner variant, zero side padding plus a full-bleed banner with the
|
|
20
|
+
row laid over it from x160. The component carries all of that:
|
|
21
|
+
|
|
22
|
+
- `onSeeMore` shows the header chevron and, in the two scrolling layouts, the
|
|
23
|
+
trailing card (`seeMoreLabel` defaults to "See other products").
|
|
24
|
+
- `banner` is required for `layout="banner"`, normally a `SquareBanner`. The row
|
|
25
|
+
spans the full width with its first card at x160, so scrolling carries the cards
|
|
26
|
+
over the banner while the banner stays put.
|
|
27
|
+
- Rows scroll by touch and trackpad natively, and by mouse drag. The pointer is
|
|
28
|
+
captured only after a 4px move, so a tap on a card's cart button still lands.
|
|
29
|
+
|
|
30
|
+
Heights match the Figma nodes: 372 horizontal, 396 banner, 1278 for a grid of
|
|
31
|
+
eight cards. `Section` itself is unchanged; the order-screen Section variants have
|
|
32
|
+
no instances in Figma and stay compositions inside it.
|
|
33
|
+
|
|
34
|
+
compose-ui ships the same as `SnackyProductGroupSection` with
|
|
35
|
+
`ProductGroupLayout.Horizontal | Banner | Grid` in `compose-v2.3.0`, where the
|
|
36
|
+
banner is an image slot like the rest of the Banner family. `SnackySection`'s
|
|
37
|
+
header is now a shared internal `SnackySectionHeader`; its public API is
|
|
38
|
+
unchanged. Additive on both sides.
|
|
39
|
+
|
|
40
|
+
## The solid address icon (0.12.0)
|
|
41
|
+
|
|
42
|
+
`SnackyIcons.solid.address` is new: the filled map marker, added to Figma's
|
|
43
|
+
`Icon-solid` set as `general/pin` (UIcons `fi-sr-marker`), 16x16, with its fill
|
|
44
|
+
bound to `icon/icon-brand`. The solid set is 13 icons now.
|
|
45
|
+
|
|
46
|
+
It ships as `address` rather than `pin` because a solid icon here takes the name
|
|
47
|
+
of its outline twin, and this is the same marker shape as the existing
|
|
48
|
+
`SnackyIcons.outline.address`. That is the rule the rest of the set already
|
|
49
|
+
follows (Figma's `riwayat` is `history`, `Fav` is `heart`), and it means an
|
|
50
|
+
active/inactive pair is always `outline.x` and `solid.x` with no lookup table.
|
|
51
|
+
It is 16px where its outline twin is 24; `heart` has the same kind of mismatch
|
|
52
|
+
(20 solid, 24 outline), and each icon still defaults to its own authored size.
|
|
53
|
+
|
|
54
|
+
compose-ui ships the same icon as `SnackyIcons.Solid.Address` in
|
|
55
|
+
`compose-v2.2.0`, plus one helper it was missing:
|
|
56
|
+
`SnackyTypographyToken.toTextStyle(color, fontFamily)`. compose-ui's type tokens
|
|
57
|
+
are raw values rather than `TextStyle`s (the package ships no font), and nothing
|
|
58
|
+
turned one into the other, so every component built the style by hand and 58 of
|
|
59
|
+
the docs site's Kotlin samples were broken or incomplete: 24 called a
|
|
60
|
+
`toTextStyle()` that only existed as a helper the Foundations page told you to
|
|
61
|
+
paste in yourself, and the rest used flat names like
|
|
62
|
+
`SnackyTypography.smallRegular` that never existed at all. Those samples now use
|
|
63
|
+
`SnackyTypography.Small.regular.toTextStyle()`. The React samples had the same
|
|
64
|
+
flat-name problem (`typography.smallRegular`, 43 places) against an export that
|
|
65
|
+
is nested (`typography.small.regular`), and are fixed the same way. Additive on
|
|
66
|
+
both sides.
|
|
67
|
+
|
|
7
68
|
## PageIndicator, and a semantic role for indicator dots (0.11.0)
|
|
8
69
|
|
|
9
70
|
`PageIndicator` is the dot row under a carousel: 8x8 dots, a 28x8 pill for the
|
package/README.md
CHANGED
|
@@ -121,7 +121,7 @@ placeholder artwork rather than a real icon prop. Apply your own
|
|
|
121
121
|
|
|
122
122
|
## What's here
|
|
123
123
|
|
|
124
|
-
All
|
|
124
|
+
All 26 documented components, matching the real Figma-sourced spec values
|
|
125
125
|
(padding, colors, radius, states - all sourced directly from the design
|
|
126
126
|
tokens, not eyeballed):
|
|
127
127
|
|
|
@@ -130,11 +130,12 @@ OtpField, CopyField, ChatInput, AddressResult), Chips (ProductChip/FilterChip),
|
|
|
130
130
|
RadioOption, Checkbox, Toggle, NavBar, TabRow, Header, PageIndicator, Banner
|
|
131
131
|
family, Badge family,
|
|
132
132
|
Callout, List (OrderListItem/NotificationListItem), Accordion, BottomSheet
|
|
133
|
-
(the shared Modal shell), Section (the shared content-block shell),
|
|
133
|
+
(the shared Modal shell), Section (the shared content-block shell),
|
|
134
|
+
ProductGroupSection (titled product rows and grids), Avatar,
|
|
134
135
|
Illustration, ProductImage, ProductCard.
|
|
135
136
|
|
|
136
137
|
Plus the icon set, as `SnackyIcons.outline.*` and `SnackyIcons.solid.*` (42
|
|
137
|
-
Outline,
|
|
138
|
+
Outline, 13 Solid). Two things to know: they are **filled** shapes rather than
|
|
138
139
|
stroked paths, so there is no `strokeWidth` to set, and the set is **not
|
|
139
140
|
uniform** - each icon is authored at 16, 20 or 24px and defaults to its own
|
|
140
141
|
natural size, so pass `width`/`height` if you need them to match.
|
package/dist/index.cjs
CHANGED
|
@@ -49,6 +49,7 @@ __export(index_exports, {
|
|
|
49
49
|
PointBalanceBanner: () => PointBalanceBanner,
|
|
50
50
|
ProductCard: () => ProductCard,
|
|
51
51
|
ProductChip: () => ProductChip,
|
|
52
|
+
ProductGroupSection: () => ProductGroupSection,
|
|
52
53
|
ProductImage: () => ProductImage,
|
|
53
54
|
RadioOption: () => RadioOption,
|
|
54
55
|
SearchField: () => SearchField,
|
|
@@ -705,6 +706,7 @@ function TabRow({ tabs, selected, onSelect, className }) {
|
|
|
705
706
|
var solid_exports = {};
|
|
706
707
|
__export(solid_exports, {
|
|
707
708
|
account: () => account2,
|
|
709
|
+
address: () => address2,
|
|
708
710
|
angleSmallRight: () => angleSmallRight,
|
|
709
711
|
balance: () => balance2,
|
|
710
712
|
bell: () => bell2,
|
|
@@ -736,6 +738,9 @@ var account2 = icon2(20, [
|
|
|
736
738
|
["M10 10C12.7614 10 15 7.76142 15 5C15 2.23858 12.7614 0 10 0C7.23858 0 5 2.23858 5 5C5 7.76142 7.23858 10 10 10Z", "nonzero"],
|
|
737
739
|
["M10 11.6659C5.85977 11.6705 2.50461 15.0257 2.5 19.1659C2.5 19.6261 2.87309 19.9992 3.33332 19.9992H16.6666C17.1269 19.9992 17.5 19.6261 17.5 19.1659C17.4954 15.0257 14.1402 11.6705 10 11.6659Z", "nonzero"]
|
|
738
740
|
]);
|
|
741
|
+
var address2 = icon2(16, [
|
|
742
|
+
["M8.00001 0.0283203C6.23597 0.030261 4.54473 0.731837 3.2973 1.97914C2.04987 3.22644 1.34813 4.91762 1.34601 6.68165C1.34601 8.39499 2.67268 11.0763 5.28934 14.651C5.60085 15.0777 6.00871 15.4249 6.47974 15.6643C6.95077 15.9036 7.47166 16.0283 8.00001 16.0283C8.52836 16.0283 9.04924 15.9036 9.52027 15.6643C9.9913 15.4249 10.3992 15.0777 10.7107 14.651C13.3273 11.0763 14.654 8.39499 14.654 6.68165C14.6519 4.91762 13.9501 3.22644 12.7027 1.97914C11.4553 0.731837 9.76405 0.030261 8.00001 0.0283203V0.0283203ZM8.00001 9.33365C7.47259 9.33365 6.95702 9.17726 6.51849 8.88424C6.07996 8.59122 5.73816 8.17475 5.53633 7.68748C5.3345 7.20021 5.28169 6.66403 5.38458 6.14675C5.48747 5.62946 5.74145 5.15431 6.11439 4.78137C6.48733 4.40843 6.96248 4.15445 7.47977 4.05156C7.99705 3.94867 8.53323 4.00148 9.0205 4.20331C9.50777 4.40514 9.92424 4.74694 10.2173 5.18547C10.5103 5.624 10.6667 6.13957 10.6667 6.66699C10.6667 7.37423 10.3857 8.05251 9.88563 8.55261C9.38553 9.0527 8.70725 9.33365 8.00001 9.33365Z", "nonzero"]
|
|
743
|
+
]);
|
|
739
744
|
var angleSmallRight = icon2(24, [
|
|
740
745
|
["M15.75 9.525L11.164 4.939C10.8827 4.65774 10.5011 4.49978 10.1032 4.49988C9.70534 4.49997 9.32381 4.65811 9.04255 4.9395C8.76129 5.2209 8.60333 5.6025 8.60342 6.00036C8.60352 6.39822 8.76166 6.77974 9.04305 7.061L13.629 11.646C13.6756 11.6925 13.7125 11.7476 13.7378 11.8084C13.763 11.8691 13.7759 11.9342 13.7759 12C13.7759 12.0658 13.763 12.1309 13.7378 12.1916C13.7125 12.2524 13.6756 12.3076 13.629 12.354L9.04305 16.939C8.76166 17.2203 8.60352 17.6018 8.60342 17.9997C8.60333 18.3975 8.76129 18.7791 9.04255 19.0605C9.32381 19.3419 9.70534 19.5 10.1032 19.5001C10.5011 19.5002 10.8827 19.3423 11.164 19.061L15.75 14.475C16.4053 13.818 16.7732 12.9279 16.7732 12C16.7732 11.0721 16.4053 10.182 15.75 9.525Z", "nonzero"]
|
|
741
746
|
]);
|
|
@@ -1063,18 +1068,102 @@ function Section({ title, onAction, children, className }) {
|
|
|
1063
1068
|
] });
|
|
1064
1069
|
}
|
|
1065
1070
|
|
|
1066
|
-
// src/components/
|
|
1071
|
+
// src/components/ProductGroupSection/ProductGroupSection.tsx
|
|
1072
|
+
var import_react12 = require("react");
|
|
1067
1073
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1074
|
+
function ProductGroupSection({
|
|
1075
|
+
title,
|
|
1076
|
+
layout,
|
|
1077
|
+
children,
|
|
1078
|
+
onSeeMore,
|
|
1079
|
+
seeMoreLabel = "See other products",
|
|
1080
|
+
banner,
|
|
1081
|
+
className
|
|
1082
|
+
}) {
|
|
1083
|
+
const drag = useDragScroll();
|
|
1084
|
+
const seeMore = onSeeMore && layout !== "grid" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "snacky-product-group__see-more", children: [
|
|
1085
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(IconButton, { size: "small", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(angleSmallRight, {}), onClick: onSeeMore, ariaLabel: seeMoreLabel }),
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "snacky-product-group__see-more-label", children: seeMoreLabel })
|
|
1087
|
+
] });
|
|
1088
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1089
|
+
Section,
|
|
1090
|
+
{
|
|
1091
|
+
title,
|
|
1092
|
+
onAction: onSeeMore,
|
|
1093
|
+
className: cx("snacky-product-group", `snacky-product-group--${layout}`, className),
|
|
1094
|
+
children: [
|
|
1095
|
+
layout === "grid" && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "snacky-product-group__grid", children }),
|
|
1096
|
+
layout === "horizontal" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "snacky-product-group__row", ...drag, children: [
|
|
1097
|
+
children,
|
|
1098
|
+
seeMore
|
|
1099
|
+
] }),
|
|
1100
|
+
layout === "banner" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "snacky-product-group__stage", children: [
|
|
1101
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "snacky-product-group__banner", children: banner }),
|
|
1102
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "snacky-product-group__row", ...drag, children: [
|
|
1103
|
+
children,
|
|
1104
|
+
seeMore
|
|
1105
|
+
] })
|
|
1106
|
+
] })
|
|
1107
|
+
]
|
|
1108
|
+
}
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
1111
|
+
function useDragScroll() {
|
|
1112
|
+
const state = (0, import_react12.useRef)(null);
|
|
1113
|
+
const justDragged = (0, import_react12.useRef)(false);
|
|
1114
|
+
return {
|
|
1115
|
+
onPointerDown(e) {
|
|
1116
|
+
if (e.pointerType !== "mouse") return;
|
|
1117
|
+
state.current = { x: e.clientX, left: e.currentTarget.scrollLeft, moved: false, id: e.pointerId };
|
|
1118
|
+
},
|
|
1119
|
+
onPointerMove(e) {
|
|
1120
|
+
const d = state.current;
|
|
1121
|
+
if (!d) return;
|
|
1122
|
+
const dx = e.clientX - d.x;
|
|
1123
|
+
if (!d.moved && Math.abs(dx) > 4) {
|
|
1124
|
+
d.moved = true;
|
|
1125
|
+
e.currentTarget.setPointerCapture(d.id);
|
|
1126
|
+
e.currentTarget.classList.add("snacky-product-group__row--dragging");
|
|
1127
|
+
}
|
|
1128
|
+
if (d.moved) e.currentTarget.scrollLeft = d.left - dx;
|
|
1129
|
+
},
|
|
1130
|
+
onPointerUp(e) {
|
|
1131
|
+
if (state.current?.moved) {
|
|
1132
|
+
e.currentTarget.classList.remove("snacky-product-group__row--dragging");
|
|
1133
|
+
justDragged.current = true;
|
|
1134
|
+
setTimeout(() => {
|
|
1135
|
+
justDragged.current = false;
|
|
1136
|
+
}, 0);
|
|
1137
|
+
}
|
|
1138
|
+
state.current = null;
|
|
1139
|
+
},
|
|
1140
|
+
onPointerCancel() {
|
|
1141
|
+
state.current = null;
|
|
1142
|
+
},
|
|
1143
|
+
onClickCapture(e) {
|
|
1144
|
+
if (justDragged.current) {
|
|
1145
|
+
e.stopPropagation();
|
|
1146
|
+
e.preventDefault();
|
|
1147
|
+
}
|
|
1148
|
+
},
|
|
1149
|
+
onDragStart(e) {
|
|
1150
|
+
e.preventDefault();
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
// src/components/Stepper/Stepper.tsx
|
|
1156
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1068
1157
|
function Stepper({ steps, className }) {
|
|
1069
|
-
return /* @__PURE__ */ (0,
|
|
1158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("ol", { className: cx("snacky-stepper", className), children: steps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
1070
1159
|
"li",
|
|
1071
1160
|
{
|
|
1072
1161
|
className: cx("snacky-stepper__step", i === steps.length - 1 && "snacky-stepper__step--last"),
|
|
1073
1162
|
children: [
|
|
1074
|
-
/* @__PURE__ */ (0,
|
|
1075
|
-
/* @__PURE__ */ (0,
|
|
1076
|
-
/* @__PURE__ */ (0,
|
|
1077
|
-
step.timestamp && /* @__PURE__ */ (0,
|
|
1163
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cx("snacky-stepper__dot", `snacky-stepper__dot--${step.state}`), children: step.state === "cancelled" && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(close, { width: 12, height: 12 }) }),
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "snacky-stepper__body", children: [
|
|
1165
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: cx("snacky-stepper__label", `snacky-stepper__label--${step.state}`), children: step.label }),
|
|
1166
|
+
step.timestamp && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "snacky-stepper__time", children: step.timestamp })
|
|
1078
1167
|
] })
|
|
1079
1168
|
]
|
|
1080
1169
|
},
|
|
@@ -1083,7 +1172,7 @@ function Stepper({ steps, className }) {
|
|
|
1083
1172
|
}
|
|
1084
1173
|
|
|
1085
1174
|
// src/components/Calendar/Calendar.tsx
|
|
1086
|
-
var
|
|
1175
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1087
1176
|
var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1088
1177
|
var MONTHS = [
|
|
1089
1178
|
"January",
|
|
@@ -1130,39 +1219,39 @@ function Calendar({
|
|
|
1130
1219
|
const [lo, hi] = range ? [range[0], range[1]].sort((a, b) => a.getTime() - b.getTime()) : [null, null];
|
|
1131
1220
|
const isEnd = (d) => single && sameDay(d, single) || lo && hi && (sameDay(d, lo) || sameDay(d, hi));
|
|
1132
1221
|
const isInRange = (d) => lo && hi && d > lo && d < hi;
|
|
1133
|
-
return /* @__PURE__ */ (0,
|
|
1134
|
-
/* @__PURE__ */ (0,
|
|
1135
|
-
/* @__PURE__ */ (0,
|
|
1222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: cx("snacky-calendar", className), children: [
|
|
1223
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "snacky-calendar__header", children: [
|
|
1224
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1136
1225
|
"button",
|
|
1137
1226
|
{
|
|
1138
1227
|
type: "button",
|
|
1139
1228
|
className: "snacky-calendar__nav",
|
|
1140
1229
|
onClick: onPrevMonth,
|
|
1141
1230
|
"aria-label": "Previous month",
|
|
1142
|
-
children: /* @__PURE__ */ (0,
|
|
1231
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(back, { width: 24, height: 24 })
|
|
1143
1232
|
}
|
|
1144
1233
|
),
|
|
1145
|
-
/* @__PURE__ */ (0,
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "snacky-calendar__label", children: [
|
|
1146
1235
|
MONTHS[month.getMonth()],
|
|
1147
1236
|
" ",
|
|
1148
1237
|
month.getFullYear()
|
|
1149
1238
|
] }),
|
|
1150
|
-
/* @__PURE__ */ (0,
|
|
1239
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1151
1240
|
"button",
|
|
1152
1241
|
{
|
|
1153
1242
|
type: "button",
|
|
1154
1243
|
className: "snacky-calendar__nav snacky-calendar__nav--next",
|
|
1155
1244
|
onClick: onNextMonth,
|
|
1156
1245
|
"aria-label": "Next month",
|
|
1157
|
-
children: /* @__PURE__ */ (0,
|
|
1246
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(back, { width: 24, height: 24 })
|
|
1158
1247
|
}
|
|
1159
1248
|
)
|
|
1160
1249
|
] }),
|
|
1161
|
-
/* @__PURE__ */ (0,
|
|
1162
|
-
WEEKDAYS.map((d) => /* @__PURE__ */ (0,
|
|
1250
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "snacky-calendar__grid", children: [
|
|
1251
|
+
WEEKDAYS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "snacky-calendar__weekday", children: d }, d)),
|
|
1163
1252
|
days.map((d, i) => {
|
|
1164
1253
|
const outside = d.getMonth() !== month.getMonth();
|
|
1165
|
-
return /* @__PURE__ */ (0,
|
|
1254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
1166
1255
|
"button",
|
|
1167
1256
|
{
|
|
1168
1257
|
type: "button",
|
|
@@ -1176,26 +1265,26 @@ function Calendar({
|
|
|
1176
1265
|
disabled: outside,
|
|
1177
1266
|
"aria-current": isEnd(d) ? "date" : void 0,
|
|
1178
1267
|
children: [
|
|
1179
|
-
/* @__PURE__ */ (0,
|
|
1180
|
-
marked.some((m) => sameDay(m, d)) && /* @__PURE__ */ (0,
|
|
1268
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "snacky-calendar__day-number", children: d.getDate() }),
|
|
1269
|
+
marked.some((m) => sameDay(m, d)) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "snacky-calendar__marker" })
|
|
1181
1270
|
]
|
|
1182
1271
|
},
|
|
1183
1272
|
i
|
|
1184
1273
|
);
|
|
1185
1274
|
})
|
|
1186
1275
|
] }),
|
|
1187
|
-
onAction && /* @__PURE__ */ (0,
|
|
1276
|
+
onAction && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Button, { onClick: onAction, style: { width: "100%" }, children: actionLabel })
|
|
1188
1277
|
] });
|
|
1189
1278
|
}
|
|
1190
1279
|
|
|
1191
1280
|
// src/components/Avatar/Avatar.tsx
|
|
1192
|
-
var
|
|
1281
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1193
1282
|
function Avatar({ src, alt, size = "md", className }) {
|
|
1194
|
-
return /* @__PURE__ */ (0,
|
|
1283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("img", { src, alt, className: cx("snacky-avatar", `snacky-avatar--${size}`, className) });
|
|
1195
1284
|
}
|
|
1196
1285
|
|
|
1197
1286
|
// src/components/Illustration/Illustration.tsx
|
|
1198
|
-
var
|
|
1287
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1199
1288
|
var SIZE = {
|
|
1200
1289
|
empty: { width: 268, height: 200 },
|
|
1201
1290
|
createAccount: { width: 360, height: 240 },
|
|
@@ -1205,54 +1294,54 @@ var SIZE = {
|
|
|
1205
1294
|
};
|
|
1206
1295
|
function Illustration({ variant, src, alt, className }) {
|
|
1207
1296
|
const { width, height } = SIZE[variant];
|
|
1208
|
-
return /* @__PURE__ */ (0,
|
|
1297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("img", { src, alt, width, height, className: cx("snacky-illustration", className) });
|
|
1209
1298
|
}
|
|
1210
1299
|
|
|
1211
1300
|
// src/components/ProductImage/ProductImage.tsx
|
|
1212
|
-
var
|
|
1301
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1213
1302
|
function ProductImage({ src, alt, usage, sold = false, className }) {
|
|
1214
|
-
return /* @__PURE__ */ (0,
|
|
1215
|
-
/* @__PURE__ */ (0,
|
|
1216
|
-
sold && /* @__PURE__ */ (0,
|
|
1303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: cx("snacky-product-image-wrap", `snacky-product-image-wrap--${usage}`, className), children: [
|
|
1304
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("img", { src, alt, className: cx("snacky-product-image", `snacky-product-image--${usage}`) }),
|
|
1305
|
+
sold && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "snacky-product-image-sold-overlay", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "snacky-product-image-sold-label", children: "Sold Out" }) })
|
|
1217
1306
|
] });
|
|
1218
1307
|
}
|
|
1219
1308
|
|
|
1220
1309
|
// src/components/ProductCard/ProductCard.tsx
|
|
1221
|
-
var
|
|
1310
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1222
1311
|
function ProductCard(props) {
|
|
1223
1312
|
if (props.variant === "details") {
|
|
1224
1313
|
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;
|
|
1225
|
-
return /* @__PURE__ */ (0,
|
|
1226
|
-
/* @__PURE__ */ (0,
|
|
1227
|
-
/* @__PURE__ */ (0,
|
|
1228
|
-
sold && /* @__PURE__ */ (0,
|
|
1314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cx("snacky-product-card", "snacky-product-card--details", className2), children: [
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "snacky-product-card__image-block", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "snacky-product-card__image-wrap", onClick: onClick2, children: [
|
|
1316
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("img", { className: "snacky-product-card__image", src: imageUrl2, alt: productName2 }),
|
|
1317
|
+
sold && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "snacky-product-card__sold-overlay", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(SoldOutBadge, {}) })
|
|
1229
1318
|
] }) }),
|
|
1230
|
-
/* @__PURE__ */ (0,
|
|
1231
|
-
/* @__PURE__ */ (0,
|
|
1232
|
-
/* @__PURE__ */ (0,
|
|
1233
|
-
/* @__PURE__ */ (0,
|
|
1234
|
-
originalPrice2 && /* @__PURE__ */ (0,
|
|
1235
|
-
discountLabel2 && /* @__PURE__ */ (0,
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "snacky-product-card__details-body", children: [
|
|
1320
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "snacky-product-card__name", children: productName2 }),
|
|
1321
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "snacky-product-card__price-row", children: [
|
|
1322
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "snacky-product-card__price", children: price2 }),
|
|
1323
|
+
originalPrice2 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "snacky-product-card__original-price", children: originalPrice2 }),
|
|
1324
|
+
discountLabel2 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DiscountTag, { label: discountLabel2 })
|
|
1236
1325
|
] }),
|
|
1237
|
-
/* @__PURE__ */ (0,
|
|
1238
|
-
/* @__PURE__ */ (0,
|
|
1239
|
-
/* @__PURE__ */ (0,
|
|
1326
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "snacky-product-card__footer-row", children: [
|
|
1327
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "snacky-product-card__rating", children: [
|
|
1328
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "snacky-product-card__rating-icon", children: ratingIcon2 ?? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(star, { width: 16, height: 16 }) }),
|
|
1240
1329
|
rating2,
|
|
1241
1330
|
" (",
|
|
1242
1331
|
ratingCount,
|
|
1243
1332
|
")"
|
|
1244
1333
|
] }),
|
|
1245
|
-
/* @__PURE__ */ (0,
|
|
1246
|
-
/* @__PURE__ */ (0,
|
|
1247
|
-
/* @__PURE__ */ (0,
|
|
1248
|
-
/* @__PURE__ */ (0,
|
|
1334
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "snacky-product-card__actions snacky-product-card__actions--details", children: [
|
|
1335
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(IconButton, { variant: "secondary", icon: favoriteIcon ?? (favorited ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(heart2, { width: 20, height: 20 }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(heart, { width: 20, height: 20 })), selected: favorited, onClick: onFavoriteClick, ariaLabel: "Favorite" }),
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(IconButton, { variant: "secondary", icon: shareIcon ?? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(share, { width: 20, height: 20 }), onClick: onShareClick, ariaLabel: "Share" }),
|
|
1337
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(IconButton, { variant: "secondary", icon: chatIcon ?? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(chat, { width: 20, height: 20 }), onClick: onChatClick, ariaLabel: "Chat with seller" })
|
|
1249
1338
|
] })
|
|
1250
1339
|
] })
|
|
1251
1340
|
] })
|
|
1252
1341
|
] });
|
|
1253
1342
|
}
|
|
1254
1343
|
const { productName, imageUrl, price, rating, originalPrice, discountLabel, onAddToCart, cartIcon, ratingIcon, onClick, className } = props;
|
|
1255
|
-
return /* @__PURE__ */ (0,
|
|
1344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
1256
1345
|
"div",
|
|
1257
1346
|
{
|
|
1258
1347
|
className: cx("snacky-product-card", "snacky-product-card--list", className),
|
|
@@ -1261,25 +1350,25 @@ function ProductCard(props) {
|
|
|
1261
1350
|
onClick,
|
|
1262
1351
|
onKeyDown: (e) => (e.key === "Enter" || e.key === " ") && onClick?.(),
|
|
1263
1352
|
children: [
|
|
1264
|
-
/* @__PURE__ */ (0,
|
|
1265
|
-
/* @__PURE__ */ (0,
|
|
1266
|
-
discountLabel && /* @__PURE__ */ (0,
|
|
1353
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "snacky-product-card__image-wrap", children: [
|
|
1354
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("img", { className: "snacky-product-card__image", src: imageUrl, alt: productName }),
|
|
1355
|
+
discountLabel && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "snacky-product-card__discount", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(DiscountTag, { label: discountLabel }) })
|
|
1267
1356
|
] }),
|
|
1268
|
-
/* @__PURE__ */ (0,
|
|
1269
|
-
/* @__PURE__ */ (0,
|
|
1270
|
-
/* @__PURE__ */ (0,
|
|
1271
|
-
originalPrice && /* @__PURE__ */ (0,
|
|
1357
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "snacky-product-card__name", children: productName }),
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "snacky-product-card__price-row", children: [
|
|
1359
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "snacky-product-card__price", children: price }),
|
|
1360
|
+
originalPrice && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "snacky-product-card__original-price", children: originalPrice })
|
|
1272
1361
|
] }),
|
|
1273
|
-
/* @__PURE__ */ (0,
|
|
1274
|
-
/* @__PURE__ */ (0,
|
|
1275
|
-
/* @__PURE__ */ (0,
|
|
1362
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "snacky-product-card__footer-row", children: [
|
|
1363
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "snacky-product-card__rating", children: [
|
|
1364
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "snacky-product-card__rating-icon", children: ratingIcon ?? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(star, { width: 16, height: 16 }) }),
|
|
1276
1365
|
rating
|
|
1277
1366
|
] }),
|
|
1278
|
-
/* @__PURE__ */ (0,
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1279
1368
|
IconButton,
|
|
1280
1369
|
{
|
|
1281
1370
|
variant: "primary",
|
|
1282
|
-
icon: cartIcon ?? /* @__PURE__ */ (0,
|
|
1371
|
+
icon: cartIcon ?? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(cartAdd, { width: 16, height: 16 }),
|
|
1283
1372
|
onClick: (e) => {
|
|
1284
1373
|
e.stopPropagation();
|
|
1285
1374
|
onAddToCart();
|
|
@@ -1294,17 +1383,17 @@ function ProductCard(props) {
|
|
|
1294
1383
|
}
|
|
1295
1384
|
|
|
1296
1385
|
// src/components/ImagePlaceholder/ImagePlaceholder.tsx
|
|
1297
|
-
var
|
|
1386
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1298
1387
|
function ImagePlaceholder({ width, height, className }) {
|
|
1299
1388
|
const iconSize = Math.round(Math.min(width, height) * 0.32);
|
|
1300
|
-
return /* @__PURE__ */ (0,
|
|
1389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
1301
1390
|
"div",
|
|
1302
1391
|
{
|
|
1303
1392
|
className: cx("snacky-image-placeholder", className),
|
|
1304
1393
|
style: { width, height },
|
|
1305
1394
|
role: "img",
|
|
1306
1395
|
"aria-label": "No image",
|
|
1307
|
-
children: /* @__PURE__ */ (0,
|
|
1396
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
1308
1397
|
"svg",
|
|
1309
1398
|
{
|
|
1310
1399
|
width: iconSize,
|
|
@@ -1316,9 +1405,9 @@ function ImagePlaceholder({ width, height, className }) {
|
|
|
1316
1405
|
strokeLinecap: "round",
|
|
1317
1406
|
strokeLinejoin: "round",
|
|
1318
1407
|
children: [
|
|
1319
|
-
/* @__PURE__ */ (0,
|
|
1320
|
-
/* @__PURE__ */ (0,
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1408
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
|
|
1409
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5", fill: "currentColor", stroke: "none" }),
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("polyline", { points: "21 15 16 10 5 21" })
|
|
1322
1411
|
]
|
|
1323
1412
|
}
|
|
1324
1413
|
)
|
|
@@ -1356,6 +1445,7 @@ function ImagePlaceholder({ width, height, className }) {
|
|
|
1356
1445
|
PointBalanceBanner,
|
|
1357
1446
|
ProductCard,
|
|
1358
1447
|
ProductChip,
|
|
1448
|
+
ProductGroupSection,
|
|
1359
1449
|
ProductImage,
|
|
1360
1450
|
RadioOption,
|
|
1361
1451
|
SearchField,
|