@loczer/storefront-sdk 0.197.0 → 0.198.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 (31) hide show
  1. package/dist/chunks/pkg/ui/dist/{MorphingModalWizard-j1CgFGLe.js → MorphingModalWizard-DOH1GYVR.js} +1 -0
  2. package/dist/components/BikeProductCard/index.d.ts +2 -1
  3. package/dist/components/BikeProductCard/index.d.ts.map +1 -1
  4. package/dist/components/BikeProductCard/index.js +23 -23
  5. package/dist/components/BookingBikeQuickAddCard/index.d.ts +19 -0
  6. package/dist/components/BookingBikeQuickAddCard/index.d.ts.map +1 -0
  7. package/dist/components/BookingBikeQuickAddCard/index.js +174 -0
  8. package/dist/components/BookingBikeVariantDialog/index.d.ts +5 -2
  9. package/dist/components/BookingBikeVariantDialog/index.d.ts.map +1 -1
  10. package/dist/components/BookingBikeVariantDialog/index.js +76 -90
  11. package/dist/components/BookingPeriodSelector/components/BookingEndDateField.js +1 -1
  12. package/dist/components/BookingPeriodSelector/components/BookingEndTimeField.js +1 -1
  13. package/dist/components/BookingPeriodSelector/components/BookingStartDateField.js +1 -1
  14. package/dist/components/BookingPeriodSelector/components/BookingStartTimeField.js +1 -1
  15. package/dist/components/PlatformFooter/index.js +1 -1
  16. package/dist/i18n/en.d.ts +2 -0
  17. package/dist/i18n/en.d.ts.map +1 -1
  18. package/dist/i18n/en.js +2 -0
  19. package/dist/i18n/fr.d.ts +2 -0
  20. package/dist/i18n/fr.d.ts.map +1 -1
  21. package/dist/i18n/fr.js +2 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/pages/BookingPage.d.ts.map +1 -1
  24. package/dist/pages/BookingPage.js +310 -388
  25. package/dist/pages/ErrorPage.d.ts.map +1 -1
  26. package/dist/pages/ErrorPage.js +13 -13
  27. package/dist/pages/NotFoundPage.js +1 -1
  28. package/dist/pages/checkout/components/CheckoutPaymentSummaryCard.js +1 -1
  29. package/dist/storefront.css +1 -1
  30. package/dist/ui/button.js +3 -3
  31. package/package.json +2 -1
@@ -5,6 +5,7 @@ import "./Button-Cr_u8vnh.js";
5
5
  import { createContext as e, useContext as t } from "react";
6
6
  import "react/jsx-runtime";
7
7
  import "lucide-react";
8
+ import "framer-motion";
8
9
  //#region ../ui/dist/MorphingModalWizard.js
9
10
  var n = e(null), r = () => t(n);
10
11
  //#endregion
@@ -1,6 +1,7 @@
1
1
  import { BikeProduct } from '../../lib/products';
2
2
  type BikeProductCardProps = {
3
3
  bike: BikeProduct;
4
+ className?: string;
4
5
  detailsPath: string;
5
6
  productDetailsLinkState: {
6
7
  backTo: string;
@@ -13,6 +14,6 @@ type BikeProductCardProps = {
13
14
  variant?: "default" | "booking";
14
15
  testId?: string;
15
16
  };
16
- export declare function BikeProductCard({ bike, detailsPath, productDetailsLinkState, actionLabelKey, onAction, actionDisabled, availabilityLabel, fallbackLanguage, variant, testId, }: BikeProductCardProps): import("react/jsx-runtime").JSX.Element;
17
+ export declare function BikeProductCard({ bike, className, detailsPath, productDetailsLinkState, actionLabelKey, onAction, actionDisabled, availabilityLabel, fallbackLanguage, variant, testId, }: BikeProductCardProps): import("react/jsx-runtime").JSX.Element;
17
18
  export {};
18
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/BikeProductCard/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AASrD,KAAK,oBAAoB,GAAG;IAC1B,IAAI,EAAE,WAAW,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,uBAAuB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,WAAW,EACX,uBAAuB,EACvB,cAA8B,EAC9B,QAAQ,EACR,cAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,OAAmB,EACnB,MAAM,GACP,EAAE,oBAAoB,2CAgFtB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/BikeProductCard/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AASrD,KAAK,oBAAoB,GAAG;IAC1B,IAAI,EAAE,WAAW,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,uBAAuB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,SAAS,EACT,WAAW,EACX,uBAAuB,EACvB,cAA8B,EAC9B,QAAQ,EACR,cAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,OAAmB,EACnB,MAAM,GACP,EAAE,oBAAoB,2CAgFtB"}
@@ -10,21 +10,21 @@ import { useTranslation as u } from "react-i18next";
10
10
  import { cn as d } from "@rpcbase/ui";
11
11
  import { ArrowRight as f, Bike as p } from "lucide-react";
12
12
  //#region src/components/BikeProductCard/index.tsx
13
- function m({ bike: m, detailsPath: h, productDetailsLinkState: g, actionLabelKey: _ = "product_cta", onAction: v, actionDisabled: y = !1, availabilityLabel: b, fallbackLanguage: x, variant: S = "default", testId: C }) {
14
- let { t: w, i18n: T } = u(), E = t(m.name, T.language, x), D = t(m.description, T.language, x), O = typeof m.images?.[0] == "string" ? m.images[0].trim() : "", k = a(m.primaryImageStyle), A = e(m.availabilityStatus), j = S === "booking", M = m.availabilityStatus === "OUT_OF_STOCK";
13
+ function m({ bike: m, className: h, detailsPath: g, productDetailsLinkState: _, actionLabelKey: v = "product_cta", onAction: y, actionDisabled: b = !1, availabilityLabel: x, fallbackLanguage: S, variant: C = "default", testId: w }) {
14
+ let { t: T, i18n: E } = u(), D = t(m.name, E.language, S), O = t(m.description, E.language, S), k = typeof m.images?.[0] == "string" ? m.images[0].trim() : "", A = a(m.primaryImageStyle), j = e(m.availabilityStatus), M = C === "booking", N = m.availabilityStatus === "OUT_OF_STOCK";
15
15
  return /* @__PURE__ */ c("div", {
16
- className: "flex h-full flex-col gap-2 rounded-xl border border-slate-200 bg-white p-3 shadow-sm",
17
- "data-testid": C,
16
+ className: d("flex h-full flex-col gap-2 rounded-xl border border-slate-200 bg-white p-3 shadow-sm", h),
17
+ "data-testid": w,
18
18
  children: [/* @__PURE__ */ c("div", {
19
19
  className: "flex flex-1 items-stretch gap-4",
20
20
  children: [/* @__PURE__ */ s("div", {
21
21
  className: "w-24 shrink-0 sm:w-28",
22
22
  children: /* @__PURE__ */ c("div", {
23
- className: d("relative h-full min-h-20 overflow-hidden rounded-xl", k.className),
24
- style: k.style,
25
- children: [O ? /* @__PURE__ */ s("img", {
26
- src: O,
27
- alt: E,
23
+ className: d("relative h-full min-h-20 overflow-hidden rounded-xl", A.className),
24
+ style: A.style,
25
+ children: [k ? /* @__PURE__ */ s("img", {
26
+ src: k,
27
+ alt: D,
28
28
  className: "absolute inset-0 h-full w-full object-contain p-1",
29
29
  loading: "lazy"
30
30
  }) : /* @__PURE__ */ s("div", {
@@ -33,10 +33,10 @@ function m({ bike: m, detailsPath: h, productDetailsLinkState: g, actionLabelKey
33
33
  className: "h-7 w-7",
34
34
  "aria-hidden": "true"
35
35
  })
36
- }), j && M ? /* @__PURE__ */ s(n, {
36
+ }), M && N ? /* @__PURE__ */ s(n, {
37
37
  variant: "destructive",
38
38
  className: "pointer-events-none absolute right-2 top-2 shadow-sm",
39
- children: /* @__PURE__ */ s("span", { children: w("availability_out_of_stock") })
39
+ children: /* @__PURE__ */ s("span", { children: T("availability_out_of_stock") })
40
40
  }) : null]
41
41
  })
42
42
  }), /* @__PURE__ */ c("div", {
@@ -44,7 +44,7 @@ function m({ bike: m, detailsPath: h, productDetailsLinkState: g, actionLabelKey
44
44
  children: [
45
45
  /* @__PURE__ */ s("p", {
46
46
  className: "min-w-0 text-sm font-semibold text-slate-950",
47
- children: /* @__PURE__ */ s("span", { children: E })
47
+ children: /* @__PURE__ */ s("span", { children: D })
48
48
  }),
49
49
  /* @__PURE__ */ s(i, {
50
50
  prices: m.prices,
@@ -52,33 +52,33 @@ function m({ bike: m, detailsPath: h, productDetailsLinkState: g, actionLabelKey
52
52
  }),
53
53
  /* @__PURE__ */ s("p", {
54
54
  className: "line-clamp-2 text-xs text-slate-600",
55
- children: /* @__PURE__ */ s("span", { children: D })
55
+ children: /* @__PURE__ */ s("span", { children: O })
56
56
  })
57
57
  ]
58
58
  })]
59
59
  }), /* @__PURE__ */ c("div", {
60
60
  className: "flex flex-wrap items-center gap-x-2 gap-y-1",
61
61
  children: [
62
- j ? null : /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s(n, {
63
- variant: A.variant,
64
- children: /* @__PURE__ */ s("span", { children: b ?? w(A.labelKey) })
62
+ M ? null : /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s(n, {
63
+ variant: j.variant,
64
+ children: /* @__PURE__ */ s("span", { children: x ?? T(j.labelKey) })
65
65
  }), /* @__PURE__ */ s("span", {
66
66
  className: "text-slate-400",
67
67
  children: "·"
68
68
  })] }),
69
69
  /* @__PURE__ */ s(l, {
70
- to: h,
71
- state: g,
70
+ to: g,
71
+ state: _,
72
72
  className: "text-xs font-medium text-slate-700 hover:text-slate-950",
73
- children: /* @__PURE__ */ s("span", { children: w("product_details_link") })
73
+ children: /* @__PURE__ */ s("span", { children: T("product_details_link") })
74
74
  }),
75
75
  /* @__PURE__ */ c(r, {
76
76
  type: "button",
77
77
  size: "sm",
78
- className: "ml-auto rounded-full gap-2 text-xs",
79
- onClick: v,
80
- disabled: y,
81
- children: [/* @__PURE__ */ s("span", { children: w(_) }), /* @__PURE__ */ s(f, {
78
+ className: "ml-auto gap-2 text-xs",
79
+ onClick: y,
80
+ disabled: b,
81
+ children: [/* @__PURE__ */ s("span", { children: T(v) }), /* @__PURE__ */ s(f, {
82
82
  className: "h-4 w-4",
83
83
  "aria-hidden": "true"
84
84
  })]
@@ -0,0 +1,19 @@
1
+ import { BikeProduct } from '../../lib/products';
2
+ type BookingBikeQuickAddCardProps = {
3
+ bike: BikeProduct;
4
+ detailsPath: string;
5
+ productDetailsLinkState: {
6
+ backTo: string;
7
+ };
8
+ actionDisabled?: boolean;
9
+ fallbackLanguage?: string;
10
+ dimOnColumnCount: 1 | 2 | null;
11
+ onAction: () => void;
12
+ onQuickAdd: (variantId: string, quantity: number) => void;
13
+ onHoverStart: () => void;
14
+ onHoverEnd: () => void;
15
+ testId: string;
16
+ };
17
+ export declare function BookingBikeQuickAddCard({ bike, detailsPath, productDetailsLinkState, actionDisabled, fallbackLanguage, dimOnColumnCount, onAction, onQuickAdd, onHoverStart, onHoverEnd, testId, }: BookingBikeQuickAddCardProps): import("react/jsx-runtime").JSX.Element;
18
+ export {};
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/BookingBikeQuickAddCard/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AA0ErD,KAAK,4BAA4B,GAAG;IAClC,IAAI,EAAE,WAAW,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,uBAAuB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3C,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;IAC9B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACzD,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAgB,uBAAuB,CAAC,EACtC,IAAI,EACJ,WAAW,EACX,uBAAuB,EACvB,cAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,UAAU,EACV,MAAM,GACP,EAAE,4BAA4B,2CAwN9B"}
@@ -0,0 +1,174 @@
1
+ import { getStorefrontProductVariantDisplay as e } from "../../lib/productVariants.js";
2
+ import { Button as t } from "../../ui/button.js";
3
+ import { Input as n } from "../../ui/input.js";
4
+ import { BikeProductCard as r } from "../BikeProductCard/index.js";
5
+ import { useEffect as i, useRef as a, useState as o } from "react";
6
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
7
+ import { useTranslation as l } from "react-i18next";
8
+ import { cn as u } from "@rpcbase/ui";
9
+ import { Plus as d } from "lucide-react";
10
+ import { AnimatePresence as f, motion as p } from "framer-motion";
11
+ //#region src/components/BookingBikeQuickAddCard/index.tsx
12
+ var m = () => typeof window < "u" && window.matchMedia("(hover: hover) and (pointer: fine)").matches, h = (e) => {
13
+ let t = Number.parseInt(e, 10);
14
+ return !Number.isFinite(t) || t < 1 ? 1 : t;
15
+ }, g = (e) => {
16
+ let t = e.replace(/\D/g, "");
17
+ return t ? String(h(t)) : "";
18
+ }, _ = (e) => {
19
+ if (!e) return;
20
+ let t = Number(e.trim().replace(",", "."));
21
+ if (!(!Number.isFinite(t) || t <= 0)) return Math.round(t);
22
+ }, v = (e) => (e / 100).toFixed(2), y = (e, t) => e.attributes.find((e) => e.key.trim().toLowerCase() === t)?.value, b = (e) => {
23
+ let t = _(y(e, "min_height_cm")), n = _(y(e, "max_height_cm")), r = t ? v(t) : null, i = n ? v(n) : null;
24
+ return r && i ? `${r} - ${i} m` : r ? `min ${r} m` : i ? `max ${i} m` : null;
25
+ };
26
+ function x({ bike: _, detailsPath: v, productDetailsLinkState: y, actionDisabled: x = !1, fallbackLanguage: S, dimOnColumnCount: C, onAction: w, onQuickAdd: T, onHoverStart: E, onHoverEnd: D, testId: O }) {
27
+ let { t: k } = l(), A = a(null), [j, M] = o(!1), [N, P] = o({}), F = _.productVariants ?? [], I = !x && F.length > 0, L = () => !I || !m() ? !1 : (M(!0), !0), R = () => {
28
+ M(!1), P({});
29
+ };
30
+ i(() => {
31
+ if (!j) return;
32
+ let e = (e) => {
33
+ if (e.pointerType !== "mouse") return;
34
+ let t = e.target;
35
+ t instanceof Node && A.current?.contains(t) || R();
36
+ }, t = (e) => {
37
+ let t = e.target;
38
+ t instanceof Node && A.current?.contains(t) || R();
39
+ };
40
+ return document.addEventListener("pointermove", e), document.addEventListener("pointerdown", t), () => {
41
+ document.removeEventListener("pointermove", e), document.removeEventListener("pointerdown", t);
42
+ };
43
+ }, [j]);
44
+ let z = (e) => {
45
+ e.pointerType === "mouse" && L() && E();
46
+ }, B = (e) => {
47
+ if (e.pointerType !== "mouse") return;
48
+ let t = e.relatedTarget;
49
+ t instanceof Node && e.currentTarget.contains(t) || (R(), D());
50
+ }, V = (e) => {
51
+ let t = e.relatedTarget;
52
+ (!(t instanceof Node) || !e.currentTarget.contains(t)) && R();
53
+ }, H = (e) => N[e] ?? "1", U = (e, t) => {
54
+ P((n) => ({
55
+ ...n,
56
+ [e]: t
57
+ }));
58
+ }, W = (e, t) => {
59
+ let n = t.target.value;
60
+ if (n === "") {
61
+ U(e, "");
62
+ return;
63
+ }
64
+ U(e, g(n));
65
+ }, G = (e) => {
66
+ U(e, String(h(H(e))));
67
+ }, K = (e) => {
68
+ let t = h(H(e));
69
+ U(e, String(t)), T(e, t);
70
+ };
71
+ return /* @__PURE__ */ c("div", {
72
+ ref: A,
73
+ "data-testid": O,
74
+ onPointerEnter: z,
75
+ onPointerLeave: B,
76
+ onFocusCapture: L,
77
+ onBlurCapture: V,
78
+ className: u("relative h-full overflow-visible transition-opacity duration-200", C === 1 && "opacity-20 md:opacity-100", C === 2 && "md:opacity-20", j && I && "z-30"),
79
+ children: [/* @__PURE__ */ s(r, {
80
+ bike: _,
81
+ detailsPath: v,
82
+ productDetailsLinkState: y,
83
+ actionLabelKey: "add_to_cart",
84
+ onAction: w,
85
+ actionDisabled: x,
86
+ fallbackLanguage: S,
87
+ variant: "booking",
88
+ className: u("transition-[border-color,box-shadow,border-radius] duration-200 hover:border-primary/20 hover:shadow-md", j && I && "!rounded-b-none border-primary/20 !border-b-white shadow-lg")
89
+ }), /* @__PURE__ */ s(f, {
90
+ initial: !1,
91
+ children: j && I ? /* @__PURE__ */ s(p.div, {
92
+ initial: {
93
+ opacity: 0,
94
+ y: -8,
95
+ scaleY: .96
96
+ },
97
+ animate: {
98
+ opacity: 1,
99
+ y: 0,
100
+ scaleY: 1
101
+ },
102
+ exit: {
103
+ opacity: 0,
104
+ y: -8,
105
+ scaleY: .96
106
+ },
107
+ transition: {
108
+ duration: .16,
109
+ ease: [
110
+ .22,
111
+ 1,
112
+ .36,
113
+ 1
114
+ ]
115
+ },
116
+ className: "absolute left-0 right-0 top-full z-30 origin-top rounded-b-lg border border-t-0 border-primary/20 bg-white px-3 py-2 shadow-xl",
117
+ "data-testid": `storefront-booking-bike-quick-selector-${_.id}`.toLowerCase(),
118
+ onClick: (e) => e.stopPropagation(),
119
+ onKeyDown: (e) => e.stopPropagation(),
120
+ children: /* @__PURE__ */ s("div", { children: F.map((r) => {
121
+ let { label: i } = e(r), a = b(r), o = `storefront-booking-bike-quick-quantity-${_.id}-${r.id}`.toLowerCase();
122
+ return /* @__PURE__ */ c("div", {
123
+ className: "flex items-center justify-between gap-3 border-b border-slate-100 py-1.5 last:border-b-0",
124
+ children: [
125
+ /* @__PURE__ */ c("div", {
126
+ className: "flex min-w-0 flex-1 items-baseline gap-2",
127
+ children: [/* @__PURE__ */ s("span", {
128
+ className: "min-w-0 truncate text-sm font-semibold text-slate-950",
129
+ title: i,
130
+ children: i
131
+ }), a ? /* @__PURE__ */ s("span", {
132
+ className: "truncate text-xs text-slate-500",
133
+ children: a
134
+ }) : null]
135
+ }),
136
+ /* @__PURE__ */ s("label", {
137
+ className: "sr-only",
138
+ htmlFor: o,
139
+ children: /* @__PURE__ */ s("span", { children: k("quantity_label") })
140
+ }),
141
+ /* @__PURE__ */ c("div", {
142
+ className: "flex shrink-0 items-center",
143
+ children: [/* @__PURE__ */ s(n, {
144
+ id: o,
145
+ type: "text",
146
+ inputMode: "numeric",
147
+ pattern: "[0-9]*",
148
+ value: H(r.id),
149
+ onChange: (e) => W(r.id, e),
150
+ onBlur: () => G(r.id),
151
+ className: "h-8 w-9 rounded-r-none border-r-0 px-1 text-center text-sm focus-visible:z-10",
152
+ "aria-label": k("quantity_label"),
153
+ "data-testid": o
154
+ }), /* @__PURE__ */ c(t, {
155
+ type: "button",
156
+ size: "sm",
157
+ className: "h-8 gap-1 rounded-l-none px-2 text-xs",
158
+ onClick: () => K(r.id),
159
+ "data-testid": `storefront-booking-bike-quick-add-${_.id}-${r.id}`.toLowerCase(),
160
+ children: [/* @__PURE__ */ s("span", { children: k("add_short") }), /* @__PURE__ */ s(d, {
161
+ className: "h-3.5 w-3.5",
162
+ "aria-hidden": "true"
163
+ })]
164
+ })]
165
+ })
166
+ ]
167
+ }, r.id);
168
+ }) })
169
+ }, "quick-selector") : null
170
+ })]
171
+ });
172
+ }
173
+ //#endregion
174
+ export { x as BookingBikeQuickAddCard };
@@ -1,7 +1,10 @@
1
- import { BikeProduct } from '../../lib/products';
1
+ import { StorefrontProduct } from '../../lib/products';
2
+ type StorefrontProductWithAvailability = StorefrontProduct & {
3
+ availabilityStatus?: "AVAILABLE" | "LOW_STOCK" | "OUT_OF_STOCK";
4
+ };
2
5
  type BookingBikeVariantDialogProps = {
3
6
  open: boolean;
4
- product: BikeProduct | null;
7
+ product: StorefrontProductWithAvailability | null;
5
8
  onOpenChange: (open: boolean) => void;
6
9
  getVariantAvailabilityLabel?: (variantId: string) => string | null;
7
10
  isVariantOutOfCapacity?: (variantId: string) => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/BookingBikeVariantDialog/index.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAarD,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,2BAA2B,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IAClE,sBAAsB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAA;IACvD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5D,CAAA;AAED,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,2BAA2B,EAC3B,sBAAsB,EACtB,WAAmB,EACnB,YAAY,GACb,EAAE,6BAA6B,kDAsN/B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/BookingBikeVariantDialog/index.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAa3D,KAAK,iCAAiC,GAAG,iBAAiB,GAAG;IAC3D,kBAAkB,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,cAAc,CAAA;CAChE,CAAA;AAWD,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,iCAAiC,GAAG,IAAI,CAAA;IACjD,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,2BAA2B,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IAClE,sBAAsB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAA;IACvD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5D,CAAA;AAED,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,2BAA2B,EAC3B,sBAAsB,EACtB,WAAmB,EACnB,YAAY,GACb,EAAE,6BAA6B,kDAyN/B"}
@@ -14,22 +14,26 @@ import { jsx as b, jsxs as x } from "react/jsx-runtime";
14
14
  import { useMediaQuery as S } from "@rpcbase/client";
15
15
  import { useTranslation as C } from "react-i18next";
16
16
  import { cn as w } from "@rpcbase/ui";
17
- import { Bike as T, CheckCircle2 as E, Plus as D } from "lucide-react";
17
+ import { Bike as T, CheckCircle2 as E, Package as D, Plus as O } from "lucide-react";
18
18
  //#region src/components/BookingBikeVariantDialog/index.tsx
19
- function O({ open: p, product: O, onOpenChange: A, getVariantAvailabilityLabel: j, isVariantOutOfCapacity: M, addDisabled: N = !1, onAddVariant: P }) {
20
- let { t: F, i18n: I } = C(), L = S(o), R = m(), [z, B] = y({});
19
+ var k = (e) => {
20
+ let t = Number.parseInt(e, 10);
21
+ return !Number.isFinite(t) || t < 1 ? 1 : t;
22
+ };
23
+ function A({ open: p, product: A, onOpenChange: M, getVariantAvailabilityLabel: N, isVariantOutOfCapacity: P, addDisabled: F = !1, onAddVariant: I }) {
24
+ let { t: L, i18n: R } = C(), z = S(o), B = m(), [V, H] = y({});
21
25
  if (v(() => {
22
- !O || !p || B((O.productVariants ?? []).reduce((e, t) => (e[t.id] = 1, e), {}));
23
- }, [p, O]), !O) return null;
24
- let V = (e, t) => {
25
- B((n) => ({
26
+ !A || !p || H((A.productVariants ?? []).reduce((e, t) => (e[t.id] = "1", e), {}));
27
+ }, [p, A]), !A) return null;
28
+ let U = (e, t) => {
29
+ H((n) => ({
26
30
  ...n,
27
- [e]: Math.max(1, Math.floor(t))
31
+ [e]: t
28
32
  }));
29
- }, H = r(O.name, I.language, R), U = r(O.description, I.language, R), W = r(O.warning, I.language, R), G = typeof O.images?.[0] == "string" ? O.images[0].trim() : "", K = _(O.primaryImageStyle), q = n(O.availabilityStatus), J = O.features?.slice(0, 4) ?? [], Y = O.productVariants ?? [], X = Y.some((t) => !!e(t, "size")) ? F("product_size_label") : F("product_variant_label");
33
+ }, W = r(A.name, R.language, B), G = r(A.description, R.language, B), K = r(A.warning, R.language, B), q = typeof A.images?.[0] == "string" ? A.images[0].trim() : "", J = _(A.primaryImageStyle), Y = n(A.availabilityStatus), X = A.features?.slice(0, 4) ?? [], Z = A.productVariants ?? [], Q = Z.some((t) => !!e(t, "size")) ? L("product_size_label") : L("product_variant_label");
30
34
  return /* @__PURE__ */ b(s, {
31
35
  open: p,
32
- onOpenChange: A,
36
+ onOpenChange: M,
33
37
  children: /* @__PURE__ */ b(c, {
34
38
  "data-testid": "storefront-booking-bike-dialog-content",
35
39
  className: "overflow-hidden border-slate-200 bg-white p-0",
@@ -43,10 +47,10 @@ function O({ open: p, product: O, onOpenChange: A, getVariantAvailabilityLabel:
43
47
  className: "border-b border-slate-200 px-5 py-4 text-left sm:px-6",
44
48
  children: [/* @__PURE__ */ b(f, {
45
49
  className: "text-left text-lg font-semibold text-slate-950",
46
- children: /* @__PURE__ */ b("span", { children: H })
50
+ children: /* @__PURE__ */ b("span", { children: W })
47
51
  }), /* @__PURE__ */ b(l, {
48
52
  className: "line-clamp-2 text-left text-sm text-slate-600",
49
- children: /* @__PURE__ */ b("span", { children: U })
53
+ children: /* @__PURE__ */ b("span", { children: G })
50
54
  })]
51
55
  }),
52
56
  /* @__PURE__ */ b("div", {
@@ -57,61 +61,64 @@ function O({ open: p, product: O, onOpenChange: A, getVariantAvailabilityLabel:
57
61
  className: "grid gap-4",
58
62
  children: [
59
63
  /* @__PURE__ */ b("div", {
60
- className: w("relative aspect-[1618/1000] overflow-hidden rounded-2xl", K.className),
61
- style: K.style,
62
- children: G ? /* @__PURE__ */ b("img", {
63
- src: G,
64
- alt: H,
64
+ className: w("relative aspect-[1618/1000] overflow-hidden rounded-2xl", J.className),
65
+ style: J.style,
66
+ children: q ? /* @__PURE__ */ b("img", {
67
+ src: q,
68
+ alt: W,
65
69
  className: "absolute inset-0 h-full w-full object-contain p-2",
66
70
  loading: "lazy"
67
71
  }) : /* @__PURE__ */ b("div", {
68
72
  className: "absolute inset-0 flex items-center justify-center text-slate-400",
69
- children: /* @__PURE__ */ b(T, {
73
+ children: A.kind === "accessory" ? /* @__PURE__ */ b(D, {
74
+ className: "h-12 w-12",
75
+ "aria-hidden": "true"
76
+ }) : /* @__PURE__ */ b(T, {
70
77
  className: "h-12 w-12",
71
78
  "aria-hidden": "true"
72
79
  })
73
80
  })
74
81
  }),
75
- L ? null : /* @__PURE__ */ x("div", {
82
+ z ? null : /* @__PURE__ */ x("div", {
76
83
  className: "flex flex-wrap items-center gap-2",
77
84
  children: [/* @__PURE__ */ b(i, {
78
- variant: q.variant,
79
- children: /* @__PURE__ */ b("span", { children: F(q.labelKey) })
80
- }), /* @__PURE__ */ b(g, { prices: O.prices })]
85
+ variant: Y.variant,
86
+ children: /* @__PURE__ */ b("span", { children: L(Y.labelKey) })
87
+ }), /* @__PURE__ */ b(g, { prices: A.prices })]
81
88
  }),
82
- !L && J.length > 0 ? /* @__PURE__ */ x("div", {
89
+ !z && X.length > 0 ? /* @__PURE__ */ x("div", {
83
90
  className: "grid gap-2",
84
91
  children: [/* @__PURE__ */ b("p", {
85
92
  className: "text-sm font-semibold text-slate-950",
86
- children: /* @__PURE__ */ b("span", { children: F("product_features_title") })
93
+ children: /* @__PURE__ */ b("span", { children: L("product_features_title") })
87
94
  }), /* @__PURE__ */ b("ul", {
88
95
  className: "grid gap-1.5 text-sm text-slate-700",
89
- children: J.map((e, t) => /* @__PURE__ */ x("li", {
96
+ children: X.map((e, t) => /* @__PURE__ */ x("li", {
90
97
  className: "inline-flex items-start gap-2",
91
98
  children: [/* @__PURE__ */ b(E, {
92
99
  className: "mt-0.5 h-4 w-4 text-success",
93
100
  "aria-hidden": "true"
94
- }), /* @__PURE__ */ b("span", { children: r(e, I.language, R) })]
95
- }, `${O.id}-${t}`))
101
+ }), /* @__PURE__ */ b("span", { children: r(e, R.language, B) })]
102
+ }, `${A.id}-${t}`))
96
103
  })]
97
104
  }) : null,
98
- L ? null : /* @__PURE__ */ b(h, { warning: W })
105
+ z ? null : /* @__PURE__ */ b(h, { warning: K })
99
106
  ]
100
107
  }), /* @__PURE__ */ x("div", {
101
108
  className: "grid content-start gap-3",
102
109
  children: [
103
- L ? /* @__PURE__ */ x("div", {
110
+ z ? /* @__PURE__ */ x("div", {
104
111
  className: "flex flex-wrap items-center gap-2",
105
112
  children: [/* @__PURE__ */ b(i, {
106
- variant: q.variant,
107
- children: /* @__PURE__ */ b("span", { children: F(q.labelKey) })
108
- }), /* @__PURE__ */ b(g, { prices: O.prices })]
113
+ variant: Y.variant,
114
+ children: /* @__PURE__ */ b("span", { children: L(Y.labelKey) })
115
+ }), /* @__PURE__ */ b(g, { prices: A.prices })]
109
116
  }) : null,
110
- L && J.length > 0 ? /* @__PURE__ */ x("details", {
117
+ z && X.length > 0 ? /* @__PURE__ */ x("details", {
111
118
  className: "group rounded-2xl border border-slate-200 bg-slate-50",
112
119
  children: [/* @__PURE__ */ x("summary", {
113
120
  className: "flex cursor-pointer list-none items-center justify-between gap-3 px-3 py-2.5 text-sm font-semibold text-slate-950 [&::-webkit-details-marker]:hidden",
114
- children: [/* @__PURE__ */ b("span", { children: F("product_features_title") }), /* @__PURE__ */ b(D, {
121
+ children: [/* @__PURE__ */ b("span", { children: L("product_features_title") }), /* @__PURE__ */ b(O, {
115
122
  className: "h-4 w-4 shrink-0 transition-transform group-open:rotate-45",
116
123
  "aria-hidden": "true"
117
124
  })]
@@ -119,25 +126,25 @@ function O({ open: p, product: O, onOpenChange: A, getVariantAvailabilityLabel:
119
126
  className: "border-t border-slate-200 px-3 py-3",
120
127
  children: /* @__PURE__ */ b("ul", {
121
128
  className: "grid gap-1.5 text-sm text-slate-700",
122
- children: J.map((e, t) => /* @__PURE__ */ x("li", {
129
+ children: X.map((e, t) => /* @__PURE__ */ x("li", {
123
130
  className: "inline-flex items-start gap-2",
124
131
  children: [/* @__PURE__ */ b(E, {
125
132
  className: "mt-0.5 h-4 w-4 text-success",
126
133
  "aria-hidden": "true"
127
- }), /* @__PURE__ */ b("span", { children: r(e, I.language, R) })]
128
- }, `${O.id}-mobile-${t}`))
134
+ }), /* @__PURE__ */ b("span", { children: r(e, R.language, B) })]
135
+ }, `${A.id}-mobile-${t}`))
129
136
  })
130
137
  })]
131
138
  }) : null,
132
- L ? /* @__PURE__ */ b(h, { warning: W }) : null,
139
+ z ? /* @__PURE__ */ b(h, { warning: K }) : null,
133
140
  /* @__PURE__ */ b("p", {
134
141
  className: "text-2xs font-medium uppercase tracking-[0.18em] text-slate-500",
135
- children: /* @__PURE__ */ b("span", { children: X })
142
+ children: /* @__PURE__ */ b("span", { children: Q })
136
143
  }),
137
144
  /* @__PURE__ */ b("div", {
138
145
  className: "grid gap-2",
139
- children: Y.map((e) => {
140
- let n = `storefront-booking-bike-dialog-variant-option-${O.id}-${e.id}`.toLowerCase(), { label: r, description: o } = t(e), s = z[e.id] ?? 1, c = M?.(e.id) === !0, l = j?.(e.id) ?? null;
146
+ children: Z.map((e) => {
147
+ let n = `storefront-booking-bike-dialog-variant-option-${A.id}-${e.id}`.toLowerCase(), { label: r, description: o } = t(e), s = V[e.id] ?? "1", c = P?.(e.id) === !0, l = N?.(e.id) ?? null;
141
148
  return /* @__PURE__ */ x("div", {
142
149
  "data-testid": n,
143
150
  className: w("flex flex-col gap-3 rounded-2xl border p-3 sm:flex-row sm:items-center sm:justify-between", "border-slate-200 bg-slate-50"),
@@ -162,21 +169,20 @@ function O({ open: p, product: O, onOpenChange: A, getVariantAvailabilityLabel:
162
169
  ]
163
170
  }), /* @__PURE__ */ x("div", {
164
171
  className: "flex flex-wrap items-center gap-2 sm:justify-end",
165
- children: [/* @__PURE__ */ b(k, {
172
+ children: [/* @__PURE__ */ b(j, {
166
173
  quantity: s,
167
- decreaseAriaLabel: F("decrease_quantity"),
168
- increaseAriaLabel: F("increase_quantity"),
169
- onQuantityChange: (t) => V(e.id, t),
170
- testIdPrefix: `storefront-booking-bike-dialog-variant-quantity-${O.id}-${e.id}`.toLowerCase()
174
+ ariaLabel: L("quantity_label"),
175
+ onQuantityChange: (t) => U(e.id, t),
176
+ testIdPrefix: `storefront-booking-bike-dialog-variant-quantity-${A.id}-${e.id}`.toLowerCase()
171
177
  }), /* @__PURE__ */ x(a, {
172
178
  type: "button",
173
179
  className: "gap-1.5 rounded-xl",
174
- "data-testid": `storefront-booking-bike-dialog-variant-add-${O.id}-${e.id}`.toLowerCase(),
175
- disabled: N,
180
+ "data-testid": `storefront-booking-bike-dialog-variant-add-${A.id}-${e.id}`.toLowerCase(),
181
+ disabled: F,
176
182
  onClick: () => {
177
- P(e.id, s);
183
+ I(e.id, k(s));
178
184
  },
179
- children: [/* @__PURE__ */ b("span", { children: F("add_short") }), /* @__PURE__ */ b(D, {
185
+ children: [/* @__PURE__ */ b("span", { children: L("add_short") }), /* @__PURE__ */ b(O, {
180
186
  className: "h-4 w-4",
181
187
  "aria-hidden": "true"
182
188
  })]
@@ -195,8 +201,8 @@ function O({ open: p, product: O, onOpenChange: A, getVariantAvailabilityLabel:
195
201
  type: "button",
196
202
  variant: "outline",
197
203
  className: "h-11 w-full rounded-xl sm:w-auto",
198
- onClick: () => A(!1),
199
- children: /* @__PURE__ */ b("span", { children: F("close_modal") })
204
+ onClick: () => M(!1),
205
+ children: /* @__PURE__ */ b("span", { children: L("close_modal") })
200
206
  })
201
207
  })
202
208
  ]
@@ -204,44 +210,24 @@ function O({ open: p, product: O, onOpenChange: A, getVariantAvailabilityLabel:
204
210
  })
205
211
  });
206
212
  }
207
- function k({ decreaseAriaLabel: e, increaseAriaLabel: t, onQuantityChange: n, quantity: r, testIdPrefix: i }) {
208
- let o = (e, t) => {
209
- let i = t?.metaKey || t?.ctrlKey ? 10 : 1;
210
- n(Math.max(1, r + e * i));
211
- };
212
- return /* @__PURE__ */ x("div", {
213
- className: "flex items-center gap-1",
214
- children: [
215
- /* @__PURE__ */ b(a, {
216
- type: "button",
217
- variant: "outline",
218
- size: "icon",
219
- className: "h-9 w-9 font-semibold",
220
- "aria-label": e,
221
- "data-testid": `${i}-decrement`,
222
- onClick: (e) => o(-1, e),
223
- children: /* @__PURE__ */ b("span", { children: "-" })
224
- }),
225
- /* @__PURE__ */ b(p, {
226
- type: "text",
227
- readOnly: !0,
228
- value: r,
229
- className: "h-9 w-12 text-center",
230
- "aria-live": "polite",
231
- "data-testid": `${i}-value`
232
- }),
233
- /* @__PURE__ */ b(a, {
234
- type: "button",
235
- variant: "outline",
236
- size: "icon",
237
- className: "h-9 w-9 font-semibold",
238
- "aria-label": t,
239
- "data-testid": `${i}-increment`,
240
- onClick: (e) => o(1, e),
241
- children: /* @__PURE__ */ b("span", { children: "+" })
242
- })
243
- ]
213
+ function j({ ariaLabel: e, onQuantityChange: t, quantity: n, testIdPrefix: r }) {
214
+ return /* @__PURE__ */ b("div", {
215
+ className: "flex items-center",
216
+ children: /* @__PURE__ */ b(p, {
217
+ type: "text",
218
+ inputMode: "numeric",
219
+ pattern: "[0-9]*",
220
+ value: n,
221
+ onChange: (e) => {
222
+ let n = e.target.value.replace(/\D/g, "");
223
+ t(n ? String(k(n)) : "");
224
+ },
225
+ onBlur: () => t(String(k(n))),
226
+ className: "h-9 w-16 text-center",
227
+ "aria-label": e,
228
+ "data-testid": `${r}-value`
229
+ })
244
230
  });
245
231
  }
246
232
  //#endregion
247
- export { O as BookingBikeVariantDialog };
233
+ export { A as BookingBikeVariantDialog };
@@ -1,6 +1,6 @@
1
1
  import { Content as e, Provider as t, Root as n, TooltipTrigger as r } from "../../../ui/tooltip.js";
2
2
  import { useBookingPeriod as i } from "../BookingPeriodContext.js";
3
- import { useMorphingModalWizardOverlayLayer as a } from "../../../chunks/pkg/ui/dist/MorphingModalWizard-j1CgFGLe.js";
3
+ import { useMorphingModalWizardOverlayLayer as a } from "../../../chunks/pkg/ui/dist/MorphingModalWizard-DOH1GYVR.js";
4
4
  import { DayPicker as o } from "../../../ui/day-picker.js";
5
5
  import { Label as s } from "../../../ui/label.js";
6
6
  import { BookingPeriodFieldErrorMessage as c } from "./BookingPeriodFieldErrorMessage.js";