@loczer/storefront-sdk 0.194.0 → 0.195.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 (64) hide show
  1. package/dist/chunks/pkg/ui/dist/{Button-CxG2fSpA.js → Button-Cr_u8vnh.js} +1 -1
  2. package/dist/chunks/pkg/ui/dist/{Dialog-4leTWiev.js → Dialog-CczmPDwY.js} +1 -1
  3. package/dist/chunks/pkg/ui/dist/Drawer/{index-DA5V7R_q.js → index-CSvSVP_J.js} +1 -1
  4. package/dist/chunks/pkg/ui/dist/Map/{MapContent-BmKjdWmq.js → MapContent-CDeWtwKa.js} +1 -1
  5. package/dist/chunks/pkg/ui/dist/{Map-CsOTdTtL.js → Map-Cs7wgtH9.js} +2 -2
  6. package/dist/chunks/pkg/ui/dist/{MorphingModalWizard-CfEqkJ0y.js → MorphingModalWizard-j1CgFGLe.js} +4 -3
  7. package/dist/chunks/pkg/ui/dist/{ResponsiveDialog-C6IWYoIg.js → ResponsiveDialog-BVwhTZQo.js} +3 -3
  8. package/dist/chunks/pkg/ui/dist/{ScrollArea-Bjwo84cv.js → ScrollArea-BqLd0xZj.js} +1 -1
  9. package/dist/chunks/pkg/ui/dist/Spinner/{index-DzMEU0iA.js → index-Cgi70z_E.js} +1 -1
  10. package/dist/chunks/pkg/ui/dist/lib/utils-DXB19bzk.js +8 -0
  11. package/dist/components/BikeProductCard/index.js +6 -6
  12. package/dist/components/BookingBikeVariantDialog/index.js +7 -7
  13. package/dist/components/BookingFlowSteps/index.js +11 -11
  14. package/dist/components/BookingPeriodSelector/components/BookingEndDateField.js +1 -1
  15. package/dist/components/BookingPeriodSelector/components/BookingEndTimeField.js +1 -1
  16. package/dist/components/BookingPeriodSelector/components/BookingStartDateField.js +1 -1
  17. package/dist/components/BookingPeriodSelector/components/BookingStartTimeField.js +1 -1
  18. package/dist/components/BookingPeriodSelector/components/internal/BookingHourPickerField.d.ts +1 -1
  19. package/dist/components/BookingPeriodSelector/components/internal/BookingHourPickerField.d.ts.map +1 -1
  20. package/dist/components/BookingPeriodSelector/components/internal/BookingHourPickerField.js +16 -18
  21. package/dist/components/BookingPeriodSelector/components/internal/StorefrontHourPickerField.d.ts +36 -0
  22. package/dist/components/BookingPeriodSelector/components/internal/StorefrontHourPickerField.d.ts.map +1 -0
  23. package/dist/components/BookingPeriodSelector/components/internal/StorefrontHourPickerField.js +830 -0
  24. package/dist/components/BookingPeriodSelector/components/internal/useIsTouchDevice.d.ts +2 -0
  25. package/dist/components/BookingPeriodSelector/components/internal/useIsTouchDevice.d.ts.map +1 -0
  26. package/dist/components/BookingPeriodSelector/components/internal/useIsTouchDevice.js +21 -0
  27. package/dist/components/BookingPeriodSelector/useBookingPeriodController.d.ts +1 -1
  28. package/dist/components/BookingPeriodSelector/useBookingPeriodController.d.ts.map +1 -1
  29. package/dist/components/ContactSection/index.js +35 -35
  30. package/dist/components/ContractSaleDocument/DocumentAcceptanceSection.js +4 -4
  31. package/dist/components/ContractSaleDocument/ThumbnailSidebar.js +1 -1
  32. package/dist/components/DeliveryAddressSelector/index.js +5 -5
  33. package/dist/components/Footer/index.js +11 -11
  34. package/dist/components/FulfillmentSection/index.js +9 -9
  35. package/dist/components/Header/index.js +61 -61
  36. package/dist/components/Map/index.js +1 -1
  37. package/dist/components/PoweredByLoczerBadge/index.js +5 -5
  38. package/dist/components/ProductPriceBadge/index.js +73 -73
  39. package/dist/components/StorefrontCancellationPolicyNotice/index.js +6 -6
  40. package/dist/components/StorefrontCartPanel/index.js +8 -8
  41. package/dist/components/StorefrontInsuranceNotice/index.js +6 -6
  42. package/dist/components/StorefrontPopupMessages/index.js +8 -8
  43. package/dist/components/payment/MollieCardFieldsForm.js +1 -1
  44. package/dist/components/payment/StripeCardFieldsForm.js +1 -1
  45. package/dist/index.d.ts +10 -3
  46. package/dist/lib/utils.d.ts +3 -1
  47. package/dist/lib/utils.d.ts.map +1 -1
  48. package/dist/lib/utils.js +9 -5
  49. package/dist/pages/BookingPage.js +8 -8
  50. package/dist/pages/CheckoutPaymentPage.js +1 -1
  51. package/dist/pages/ContractSaleDocumentPage.js +15 -15
  52. package/dist/pages/HomePage.js +19 -19
  53. package/dist/pages/PaymentLinkPage.js +1 -1
  54. package/dist/pages/PaymentLinkSuccessPage.js +1 -1
  55. package/dist/pages/ProductPage.js +143 -143
  56. package/dist/pages/checkout/components/CheckoutCouponCard.js +5 -5
  57. package/dist/pages/checkout/components/CheckoutPaymentSummaryCard.js +1 -1
  58. package/package.json +5 -1
  59. package/dist/chunks/node_modules/clsx/dist/clsx-CdyIqUTr.js +0 -16
  60. package/dist/chunks/node_modules/tailwind-merge/dist/bundle-mjs-CF4QheV5.js +0 -1608
  61. package/dist/chunks/pkg/ui/dist/lib/utils-BN5KOMSm.js +0 -8
  62. package/dist/components/BookingPeriodSelector/components/internal/ModalHourPickerField.d.ts +0 -22
  63. package/dist/components/BookingPeriodSelector/components/internal/ModalHourPickerField.d.ts.map +0 -1
  64. package/dist/components/BookingPeriodSelector/components/internal/ModalHourPickerField.js +0 -342
@@ -0,0 +1,830 @@
1
+ import { cn as e } from "../../../../lib/utils.js";
2
+ import { useIsTouchDevice as t } from "./useIsTouchDevice.js";
3
+ import * as n from "react";
4
+ import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ import { Check as o, ChevronDown as s, ChevronUp as c } from "lucide-react";
6
+ import { createPortal as l } from "react-dom";
7
+ import { IMaskInput as u } from "react-imask";
8
+ import d, { InputMask as f } from "imask";
9
+ //#region src/components/BookingPeriodSelector/components/internal/StorefrontHourPickerField.tsx
10
+ var p = d;
11
+ typeof p.InputMask != "function" && (p.InputMask = f);
12
+ var m = {
13
+ left: 0,
14
+ top: 0,
15
+ width: 0,
16
+ strategy: "fixed"
17
+ };
18
+ function h(e, t, n) {
19
+ let r = e.getBoundingClientRect(), i = t.offsetHeight, a = window.innerWidth ?? 0, o = window.innerHeight ?? 0, s = r.width, c = r.left;
20
+ c + s > a - 8 && (c = Math.max(8, a - s - 8)), c < 8 && (c = 8);
21
+ let l = r.bottom + 8, u = l + i > o - 8, d = r.top - i - 8;
22
+ if (u && d >= 8 && (l = d), l < 8 && (l = 8), l + i > o - 8 && (l = Math.max(8, o - i - 8)), !n) return {
23
+ left: c,
24
+ top: l,
25
+ width: s,
26
+ strategy: "fixed"
27
+ };
28
+ let f = n.getBoundingClientRect();
29
+ return {
30
+ left: c - f.left,
31
+ top: l - f.top,
32
+ width: s,
33
+ strategy: "absolute"
34
+ };
35
+ }
36
+ function g(e) {
37
+ return String(e).padStart(2, "0");
38
+ }
39
+ function _(e) {
40
+ let t = e.trim();
41
+ if (!t) return null;
42
+ let n = /^(\d{1,2}):(\d{2})$/.exec(t);
43
+ if (!n) return null;
44
+ let r = Number(n[1]), i = Number(n[2]);
45
+ return !Number.isFinite(r) || !Number.isFinite(i) || r < 0 || r > 23 || i < 0 || i > 59 ? null : `${g(r)}:${g(i)}`;
46
+ }
47
+ function v(e) {
48
+ let t = _(e);
49
+ if (t) return `parsed:${t}`;
50
+ let n = e.replace(/\D/g, "");
51
+ if (!n) return "empty";
52
+ if (n.length <= 2) return `hour:${Number(n)}`;
53
+ let r = n.slice(-2), i = n.slice(0, -2);
54
+ return `hour-minute:${Number(i)}:${r}`;
55
+ }
56
+ function y(e, t) {
57
+ let n = _(e);
58
+ return n ? x(t.find((e) => e.value === n)) ? {
59
+ parsed: n,
60
+ selectableValue: n
61
+ } : {
62
+ parsed: n,
63
+ selectableValue: null
64
+ } : null;
65
+ }
66
+ function b(e) {
67
+ let t = /^(\d{2}):(\d{2})$/.exec(e);
68
+ if (!t) return null;
69
+ let n = Number(t[1]), r = Number(t[2]);
70
+ return !Number.isFinite(n) || !Number.isFinite(r) ? null : n * 60 + r;
71
+ }
72
+ function x(e) {
73
+ return e ? !e.disabled : !1;
74
+ }
75
+ function S(e, t, n) {
76
+ let r = e ? n.findIndex((t) => t.value === e) : -1;
77
+ r === -1 && (r = t === 1 ? -1 : n.length);
78
+ for (let e = r + t; e >= 0 && e < n.length; e += t) {
79
+ let t = n[e];
80
+ if (x(t)) return t.value;
81
+ }
82
+ return null;
83
+ }
84
+ function C(e, t, r, i) {
85
+ n.useEffect(() => {
86
+ if (!t || !r) return;
87
+ let n = e.current, a = n?.ownerDocument.defaultView?.IntersectionObserver;
88
+ if (!n || !a) return;
89
+ let o = !0, s = new a((e) => {
90
+ if (!o) return;
91
+ let t = e[0];
92
+ t && !t.isIntersecting && i(!1);
93
+ });
94
+ return s.observe(n), () => {
95
+ o = !1, s.disconnect();
96
+ };
97
+ }, [
98
+ r,
99
+ t,
100
+ i,
101
+ e
102
+ ]);
103
+ }
104
+ function w(e, t) {
105
+ let n = null, r = Infinity, i = -Infinity;
106
+ for (let a of t) {
107
+ if (!x(a)) continue;
108
+ let t = b(a.value);
109
+ if (t == null) continue;
110
+ let o = Math.abs(t - e);
111
+ (o < r || o === r && t > i) && (n = a, r = o, i = t);
112
+ }
113
+ return n;
114
+ }
115
+ function T({ direction: t, viewportRef: r, speed: a = 400, className: o }) {
116
+ let [l, u] = n.useState(!0), d = n.useRef(void 0), f = n.useRef(void 0), p = n.useRef(!1), m = n.useCallback(() => {
117
+ let e = r.current;
118
+ if (!e) {
119
+ u(!0);
120
+ return;
121
+ }
122
+ let { scrollTop: n, scrollHeight: i, clientHeight: a } = e, o = n > 2, s = n < i - a - 2;
123
+ if (!(i > a + 2)) {
124
+ u(!0);
125
+ return;
126
+ }
127
+ u(t === "up" ? !o : !s);
128
+ }, [t, r]);
129
+ n.useEffect(() => {
130
+ let e = r.current;
131
+ if (!e) return;
132
+ m();
133
+ let t = () => m(), n = () => m();
134
+ e.addEventListener("scroll", t, { passive: !0 });
135
+ let i = new ResizeObserver(n);
136
+ i.observe(e);
137
+ let a = new MutationObserver(n);
138
+ return a.observe(e, {
139
+ childList: !0,
140
+ subtree: !0
141
+ }), () => {
142
+ e.removeEventListener("scroll", t), i.disconnect(), a.disconnect();
143
+ };
144
+ }, [r, m]);
145
+ let h = n.useCallback(() => {
146
+ d.current &&= (cancelAnimationFrame(d.current), void 0), p.current = !1, f.current = void 0;
147
+ }, []), g = n.useCallback((e) => {
148
+ let n = r.current;
149
+ if (!n || l || !p.current) {
150
+ h();
151
+ return;
152
+ }
153
+ f.current ||= e;
154
+ let i = a * (e - f.current) / 1e3;
155
+ if (i < .1) {
156
+ d.current = requestAnimationFrame(g);
157
+ return;
158
+ }
159
+ let o = n.scrollTop, s = n.scrollHeight - n.clientHeight, c;
160
+ c = t === "up" ? Math.max(0, o - i) : Math.min(s, o + i), n.scrollTo({ top: c }), f.current = e, (t === "up" ? c > 1 : c < s - 1) && Math.abs(c - o) > .01 ? d.current = requestAnimationFrame(g) : (h(), setTimeout(m, 16));
161
+ }, [
162
+ m,
163
+ t,
164
+ l,
165
+ a,
166
+ h,
167
+ r
168
+ ]), _ = n.useCallback(() => {
169
+ l || !r.current || p.current || (p.current = !0, f.current = void 0, d.current = requestAnimationFrame(g));
170
+ }, [
171
+ l,
172
+ g,
173
+ r
174
+ ]);
175
+ return n.useEffect(() => h, [h]), /* @__PURE__ */ i("div", {
176
+ className: e("flex items-center justify-center py-1 select-none", l ? "cursor-default opacity-40" : "cursor-pointer opacity-100 hover:bg-accent/20", o),
177
+ onPointerEnter: () => {
178
+ l || _();
179
+ },
180
+ onPointerMove: () => {
181
+ !l && !p.current && _();
182
+ },
183
+ onPointerLeave: () => {
184
+ h();
185
+ },
186
+ children: i(t === "up" ? c : s, {
187
+ "aria-hidden": !0,
188
+ className: "h-4 w-4 opacity-50"
189
+ })
190
+ });
191
+ }
192
+ function E({ id: t, value: s, onChange: c, onValueUpdate: u, options: d, placeholder: f = "Select time", className: p, inputClassName: g, disabled: _, readOnly: v, open: y, onOpenChange: b, triggerTestId: S, contentTestId: w, isHydrated: E, portalContainer: D }) {
193
+ let O = n.useId(), A = t ?? `hours-picker-${O}`, j = n.useRef(null), M = n.useRef(null), N = n.useCallback((e) => {
194
+ M.current = e;
195
+ }, []), P = n.useRef(null), F = n.useRef(!1), [I, L] = n.useState(null), R = n.useRef(null), z = n.useRef(null), B = n.useRef(null), [V, H] = n.useState(m), [U, W] = n.useState(!1), G = y ?? U, K = b ?? W, q = n.useRef(!1);
196
+ q.current = G, n.useEffect(() => {
197
+ if (!G || _ || v) return;
198
+ let e = j.current;
199
+ e instanceof HTMLInputElement && (typeof document < "u" && document.activeElement === e || e.focus({ preventScroll: !0 }));
200
+ }, [
201
+ _,
202
+ G,
203
+ v
204
+ ]);
205
+ let J = n.useCallback((e) => {
206
+ P.current = e, L(e);
207
+ }, []), Y = n.useCallback(() => {
208
+ F.current = !0;
209
+ }, []);
210
+ n.useEffect(() => {
211
+ if (!G) return;
212
+ let e = d.find((e) => e.value === s);
213
+ if (e && x(e)) {
214
+ J(e.value);
215
+ return;
216
+ }
217
+ let t = d.find((e) => x(e));
218
+ J(t?.value ?? null);
219
+ }, [
220
+ G,
221
+ d,
222
+ J,
223
+ s
224
+ ]);
225
+ let X = n.useCallback((e) => {
226
+ if (e === null) {
227
+ u && u(null);
228
+ return;
229
+ }
230
+ x(d.find((t) => t.value === e)) && u && u(e);
231
+ }, [u, d]), Z = n.useCallback((e) => {
232
+ if (e === null) {
233
+ u && u(null), c(null);
234
+ return;
235
+ }
236
+ x(d.find((t) => t.value === e)) && (u && u(e), c(e));
237
+ }, [
238
+ c,
239
+ u,
240
+ d
241
+ ]);
242
+ n.useEffect(() => {
243
+ if (!G) return;
244
+ let e = R.current?.ownerDocument ?? document, t = e.defaultView ?? window, n = (e) => {
245
+ let t = e.target;
246
+ if (!(t instanceof Node)) return;
247
+ let n = R.current;
248
+ n && (n.contains(t) || z.current?.contains(t) || K(!1));
249
+ }, r = (e) => {
250
+ if (e.key !== "Escape" || !q.current) return;
251
+ let t = e.target;
252
+ if (!(t instanceof Node)) return;
253
+ let n = R.current, r = z.current;
254
+ !n?.contains(t) && !r?.contains(t) || (e.preventDefault(), e.stopPropagation(), K(!1));
255
+ };
256
+ return e.addEventListener("pointerdown", n, !0), t.addEventListener("keydown", r, !0), () => {
257
+ e.removeEventListener("pointerdown", n, !0), t.removeEventListener("keydown", r, !0);
258
+ };
259
+ }, [G, K]), n.useEffect(() => {
260
+ if (!G) return;
261
+ let e = z.current;
262
+ if (!e) return;
263
+ let t = (e) => {
264
+ let t = B.current;
265
+ if (!t) return;
266
+ let n = e.deltaY;
267
+ if (n === 0) return;
268
+ let r = Math.max(0, t.scrollHeight - t.clientHeight), i = t.scrollTop <= 0, a = t.scrollTop >= r, o = e.target;
269
+ if (o instanceof Node && t.contains(o)) {
270
+ (n < 0 && i || n > 0 && a) && e.preventDefault();
271
+ return;
272
+ }
273
+ e.preventDefault(), t.scrollTop = Math.min(r, Math.max(0, t.scrollTop + n));
274
+ };
275
+ return e.addEventListener("wheel", t, { passive: !1 }), () => {
276
+ e.removeEventListener("wheel", t);
277
+ };
278
+ }, [G]), C(j, G, y === void 0 || b !== void 0, K);
279
+ let Q = n.useCallback(() => {
280
+ if (typeof window > "u") return;
281
+ let e = j.current, t = z.current;
282
+ !(e instanceof HTMLElement) || !t || H(h(e, t, D));
283
+ }, [D]);
284
+ n.useLayoutEffect(() => {
285
+ if (!G || _ || typeof window > "u") return;
286
+ Q();
287
+ let e = window.requestAnimationFrame(Q);
288
+ return window.addEventListener("scroll", Q, !0), window.addEventListener("resize", Q), () => {
289
+ window.cancelAnimationFrame(e), window.removeEventListener("scroll", Q, !0), window.removeEventListener("resize", Q);
290
+ };
291
+ }, [
292
+ _,
293
+ G,
294
+ Q
295
+ ]), n.useEffect(() => {
296
+ if (!G) return;
297
+ let e = B.current;
298
+ if (!e) return;
299
+ let t = requestAnimationFrame(() => {
300
+ let t = e.querySelector("[role=\"option\"][data-state=\"checked\"]");
301
+ if (t instanceof HTMLElement) {
302
+ let n = t.offsetTop - 8, r = t.offsetTop + t.offsetHeight + 8;
303
+ if (n < e.scrollTop) {
304
+ e.scrollTop = Math.max(0, n);
305
+ return;
306
+ }
307
+ r > e.scrollTop + e.clientHeight && (e.scrollTop = Math.max(0, r - e.clientHeight));
308
+ return;
309
+ }
310
+ let n = Array.from(e.querySelectorAll("[role=\"option\"]"));
311
+ if (!n.length) return;
312
+ let r, i;
313
+ for (let e of n) {
314
+ if (!e.hasAttribute("data-disabled")) {
315
+ r = e;
316
+ break;
317
+ }
318
+ i = e;
319
+ }
320
+ if (!r) return;
321
+ let a = Math.max(0, (i || r).offsetTop - 8);
322
+ e.scrollTop = a;
323
+ });
324
+ return () => cancelAnimationFrame(t);
325
+ }, [G, d]), n.useEffect(() => {
326
+ if (!G || !I || !F.current) return;
327
+ let e = B.current;
328
+ if (!e) return;
329
+ let t = e.querySelector(`[role="option"][data-value="${I}"]`);
330
+ if (!(t instanceof HTMLElement)) return;
331
+ let n = t.offsetTop - 8, r = t.offsetTop + t.offsetHeight + 8;
332
+ if (n < e.scrollTop) {
333
+ e.scrollTop = Math.max(0, n);
334
+ return;
335
+ }
336
+ r > e.scrollTop + e.clientHeight && (e.scrollTop = Math.max(0, r - e.clientHeight));
337
+ }, [I, G]);
338
+ let $ = d.find((e) => e.value === s);
339
+ return /* @__PURE__ */ i("div", {
340
+ "data-slot": "hours-picker-input",
341
+ className: e("w-[150px]", p),
342
+ ref: R,
343
+ children: /* @__PURE__ */ a("div", {
344
+ className: "relative",
345
+ children: [/* @__PURE__ */ i(k, {
346
+ id: A,
347
+ placeholder: f,
348
+ value: s,
349
+ onValueUpdate: X,
350
+ onCommit: Z,
351
+ options: d,
352
+ selectedLabel: $?.selectedLabel,
353
+ disabled: _,
354
+ readOnly: v,
355
+ open: G,
356
+ setOpen: K,
357
+ inputClassName: g,
358
+ triggerTestId: S,
359
+ isHydrated: E,
360
+ highlightedValueRef: P,
361
+ setHighlightedValue: J,
362
+ markKeyboardNavigation: Y,
363
+ inputRef: (e) => {
364
+ j.current = e;
365
+ },
366
+ onDraftValueHandlerChange: N
367
+ }), G ? (() => {
368
+ let t = /* @__PURE__ */ i(r, { children: /* @__PURE__ */ a("div", {
369
+ ref: z,
370
+ "data-testid": w,
371
+ "data-state": "open",
372
+ className: e("pointer-events-auto z-[60] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md", "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95"),
373
+ style: {
374
+ position: V.strategy,
375
+ left: V.left,
376
+ top: V.top,
377
+ width: V.width
378
+ },
379
+ children: [
380
+ /* @__PURE__ */ i(T, {
381
+ direction: "up",
382
+ viewportRef: B
383
+ }),
384
+ /* @__PURE__ */ i("div", {
385
+ ref: B,
386
+ role: "listbox",
387
+ className: "max-h-64 overflow-y-auto p-1 [overscroll-behavior:contain] [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden",
388
+ children: d.map((t) => {
389
+ let n = t.value === s;
390
+ return /* @__PURE__ */ a("div", {
391
+ role: "option",
392
+ "aria-selected": n,
393
+ "data-value": t.value,
394
+ "data-state": n ? "checked" : "unchecked",
395
+ "data-disabled": t.disabled ? "" : void 0,
396
+ className: e("relative flex w-full select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none cursor-pointer", t.disabled && "pointer-events-none opacity-50", I === t.value && "bg-accent text-accent-foreground"),
397
+ onMouseDown: (e) => {
398
+ e.preventDefault();
399
+ },
400
+ onClick: () => {
401
+ t.disabled || (M.current?.(t.value), J(t.value), j.current?.focus({ preventScroll: !0 }), Z(t.value), K(!1));
402
+ },
403
+ onPointerEnter: () => {
404
+ F.current || (F.current = !1, J(t.value));
405
+ },
406
+ onPointerMove: (e) => {
407
+ F.current && e.movementX === 0 && e.movementY === 0 || (F.current = !1, J(t.value));
408
+ },
409
+ children: [/* @__PURE__ */ i("span", {
410
+ className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
411
+ children: n ? /* @__PURE__ */ i(o, {
412
+ "aria-hidden": !0,
413
+ className: "h-4 w-4"
414
+ }) : null
415
+ }), /* @__PURE__ */ a("div", {
416
+ className: "flex flex-col",
417
+ children: [/* @__PURE__ */ i("span", { children: t.label }), t.description == null ? null : /* @__PURE__ */ i("span", {
418
+ "data-slot": "description",
419
+ className: "text-xs text-muted-foreground",
420
+ children: t.description
421
+ })]
422
+ })]
423
+ }, t.value);
424
+ })
425
+ }),
426
+ /* @__PURE__ */ i(T, {
427
+ direction: "down",
428
+ viewportRef: B
429
+ })
430
+ ]
431
+ }) });
432
+ return typeof document > "u" ? t : l(t, D ?? document.body);
433
+ })() : null]
434
+ })
435
+ });
436
+ }
437
+ E.displayName = "HourPickerInput";
438
+ function D({ id: t, value: c, onChange: u, onValueUpdate: d, options: f, placeholder: p = "Select time", className: g, inputClassName: _, disabled: v, readOnly: y, open: b, onOpenChange: w, triggerTestId: E, contentTestId: D, isHydrated: O, portalContainer: k }) {
439
+ let A = n.useId(), j = t ?? `hours-picker-${A}`, M = n.useRef(null), N = n.useRef(null), P = n.useRef(null), F = n.useRef(null), [I, L] = n.useState(m), [R, z] = n.useState(null), [B, V] = n.useState(!1), H = b ?? B, U = w ?? V, W = n.useRef(!1);
440
+ W.current = H;
441
+ let G = n.useCallback((e) => {
442
+ x(f.find((t) => t.value === e)) && (d && d(e), u(e));
443
+ }, [
444
+ u,
445
+ d,
446
+ f
447
+ ]);
448
+ n.useEffect(() => {
449
+ if (!H) return;
450
+ let e = f.find((e) => e.value === c);
451
+ if (x(e)) {
452
+ z(e.value);
453
+ return;
454
+ }
455
+ let t = f.find((e) => x(e));
456
+ z(t?.value ?? null);
457
+ }, [
458
+ f,
459
+ H,
460
+ c
461
+ ]), n.useEffect(() => {
462
+ if (!H || !R) return;
463
+ let e = F.current;
464
+ if (!e) return;
465
+ let t = e.querySelector(`[role="option"][data-value="${R}"]`);
466
+ if (!(t instanceof HTMLElement)) return;
467
+ let n = t.offsetTop - 8, r = t.offsetTop + t.offsetHeight + 8;
468
+ if (n < e.scrollTop) {
469
+ e.scrollTop = Math.max(0, n);
470
+ return;
471
+ }
472
+ r > e.scrollTop + e.clientHeight && (e.scrollTop = Math.max(0, r - e.clientHeight));
473
+ }, [R, H]), C(M, H, b === void 0 || w !== void 0, U);
474
+ let K = n.useCallback(() => {
475
+ if (typeof window > "u") return;
476
+ let e = M.current, t = P.current;
477
+ !(e instanceof HTMLElement) || !t || L(h(e, t, k));
478
+ }, [k]);
479
+ n.useLayoutEffect(() => {
480
+ if (!H || v || typeof window > "u") return;
481
+ K();
482
+ let e = window.requestAnimationFrame(K);
483
+ return window.addEventListener("scroll", K, !0), window.addEventListener("resize", K), () => {
484
+ window.cancelAnimationFrame(e), window.removeEventListener("scroll", K, !0), window.removeEventListener("resize", K);
485
+ };
486
+ }, [
487
+ v,
488
+ H,
489
+ K
490
+ ]), n.useEffect(() => {
491
+ if (!H) return;
492
+ let e = N.current?.ownerDocument ?? document, t = e.defaultView ?? window, n = (e) => {
493
+ let t = e.target;
494
+ t instanceof Node && (N.current?.contains(t) || P.current?.contains(t) || U(!1));
495
+ }, r = (e) => {
496
+ if (e.key !== "Escape" || !W.current) return;
497
+ let t = e.target;
498
+ if (!(t instanceof Node)) return;
499
+ let n = N.current, r = P.current;
500
+ !n?.contains(t) && !r?.contains(t) || (e.preventDefault(), e.stopPropagation(), U(!1), M.current?.focus({ preventScroll: !0 }));
501
+ };
502
+ return e.addEventListener("pointerdown", n, !0), t.addEventListener("keydown", r, !0), () => {
503
+ e.removeEventListener("pointerdown", n, !0), t.removeEventListener("keydown", r, !0);
504
+ };
505
+ }, [H, U]);
506
+ let q = f.find((e) => e.value === c), J = q?.selectedLabel ?? q?.label ?? c, Y = f.findIndex((e) => e.value === R), X = Y >= 0 ? `${j}-option-${Y}` : void 0;
507
+ return /* @__PURE__ */ a("div", {
508
+ "data-slot": "hours-picker-field",
509
+ className: e("w-[150px]", g),
510
+ ref: N,
511
+ children: [/* @__PURE__ */ a("button", {
512
+ ref: M,
513
+ id: j,
514
+ type: "button",
515
+ role: "combobox",
516
+ "aria-expanded": H,
517
+ "aria-controls": `${j}-content`,
518
+ "aria-haspopup": "listbox",
519
+ "aria-activedescendant": H ? X : void 0,
520
+ disabled: v,
521
+ "data-testid": E,
522
+ "data-hydrated": O ? "true" : void 0,
523
+ className: e("flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", "hover:bg-accent hover:text-accent-foreground", !c && "text-muted-foreground", H && "ring-2 ring-primary ring-offset-2", _),
524
+ onClick: () => {
525
+ v || y || U(!H);
526
+ },
527
+ onKeyDown: (e) => {
528
+ if (v || y) return;
529
+ if (e.key === "Tab") {
530
+ H && U(!1);
531
+ return;
532
+ }
533
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
534
+ if (e.preventDefault(), !H) {
535
+ U(!0);
536
+ return;
537
+ }
538
+ let t = S(R ?? c, e.key === "ArrowDown" ? 1 : -1, f);
539
+ if (!t) return;
540
+ z(t), d?.(t);
541
+ return;
542
+ }
543
+ if (e.key !== "Enter" && e.key !== " ") return;
544
+ if (e.preventDefault(), !H) {
545
+ U(!0);
546
+ return;
547
+ }
548
+ let t = f.find((e) => e.value === R), n = x(t) ? t.value : f.find((e) => x(e))?.value;
549
+ n && (G(n), U(!1));
550
+ },
551
+ children: [/* @__PURE__ */ i("span", {
552
+ className: "line-clamp-1 text-left",
553
+ children: c ? J : p
554
+ }), /* @__PURE__ */ i(s, {
555
+ "aria-hidden": !0,
556
+ className: "h-4 w-4 shrink-0 opacity-50"
557
+ })]
558
+ }), H ? (() => {
559
+ let t = /* @__PURE__ */ i(r, { children: /* @__PURE__ */ a("div", {
560
+ ref: P,
561
+ id: `${j}-content`,
562
+ "data-testid": D,
563
+ "data-state": "open",
564
+ className: e("pointer-events-auto z-[60] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md", "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95"),
565
+ style: {
566
+ position: I.strategy,
567
+ left: I.left,
568
+ top: I.top,
569
+ width: I.width
570
+ },
571
+ children: [
572
+ /* @__PURE__ */ i(T, {
573
+ direction: "up",
574
+ viewportRef: F
575
+ }),
576
+ /* @__PURE__ */ i("div", {
577
+ ref: F,
578
+ role: "listbox",
579
+ className: "max-h-64 overflow-y-auto p-1 [overscroll-behavior:contain] [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden",
580
+ children: f.map((t, n) => {
581
+ let r = t.value === c, s = t.value === R;
582
+ return /* @__PURE__ */ a("div", {
583
+ id: `${j}-option-${n}`,
584
+ role: "option",
585
+ "aria-selected": r,
586
+ "aria-disabled": t.disabled || void 0,
587
+ "data-value": t.value,
588
+ "data-state": r ? "checked" : "unchecked",
589
+ "data-disabled": t.disabled ? "" : void 0,
590
+ className: e("relative flex w-full select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none cursor-pointer", t.disabled && "pointer-events-none opacity-50", s && "bg-accent text-accent-foreground"),
591
+ onMouseDown: (e) => {
592
+ e.preventDefault();
593
+ },
594
+ onClick: () => {
595
+ t.disabled || y || (z(t.value), G(t.value), U(!1), M.current?.focus({ preventScroll: !0 }));
596
+ },
597
+ children: [/* @__PURE__ */ i("span", {
598
+ className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
599
+ children: r ? /* @__PURE__ */ i(o, {
600
+ "aria-hidden": !0,
601
+ className: "h-4 w-4"
602
+ }) : null
603
+ }), /* @__PURE__ */ a("div", {
604
+ className: "flex flex-col",
605
+ children: [/* @__PURE__ */ i("span", { children: t.label }), t.description == null ? null : /* @__PURE__ */ i("span", {
606
+ "data-slot": "description",
607
+ className: "text-xs text-muted-foreground",
608
+ children: t.description
609
+ })]
610
+ })]
611
+ }, t.value);
612
+ })
613
+ }),
614
+ /* @__PURE__ */ i(T, {
615
+ direction: "down",
616
+ viewportRef: F
617
+ })
618
+ ]
619
+ }) });
620
+ return typeof document > "u" ? t : l(t, k ?? document.body);
621
+ })() : null]
622
+ });
623
+ }
624
+ function O(e) {
625
+ return t() ? /* @__PURE__ */ i(D, { ...e }) : /* @__PURE__ */ i(E, { ...e });
626
+ }
627
+ O.displayName = "HourPickerField";
628
+ function k({ id: t, placeholder: r, value: o, onValueUpdate: c, onCommit: l, options: d, selectedLabel: f, disabled: p, readOnly: m, open: h, setOpen: _, inputClassName: S, triggerTestId: C, isHydrated: T, highlightedValueRef: E, setHighlightedValue: D, markKeyboardNavigation: O, inputRef: k, onDraftValueHandlerChange: A }) {
629
+ let j = n.useRef(!1), M = n.useRef(!1), N = n.useRef(!1), P = n.useRef(null), F = n.useRef(null), I = n.useRef(!1), [L, R] = n.useState(() => o || "");
630
+ n.useEffect(() => (A((e) => {
631
+ R(e);
632
+ }), () => {
633
+ A(null);
634
+ }), [A]);
635
+ let z = n.useCallback((e) => {
636
+ let t = E.current ?? o ?? "", n = d.findIndex((e) => e.value === t);
637
+ n === -1 && (n = e === 1 ? -1 : d.length);
638
+ for (let t = n + e; t >= 0 && t < d.length; t += e) {
639
+ let e = d[t];
640
+ if (x(e)) {
641
+ D(e.value), P.current = e.value, R(e.value), c(e.value);
642
+ return;
643
+ }
644
+ }
645
+ }, [
646
+ E,
647
+ c,
648
+ d,
649
+ D,
650
+ o
651
+ ]);
652
+ n.useEffect(() => {
653
+ j.current || R(o || "");
654
+ }, [o]), n.useEffect(() => {
655
+ F.current = v(L);
656
+ }, [L]), n.useEffect(() => {
657
+ o === null && (I.current = !1);
658
+ }, [o]);
659
+ let B = o != null && f != null, V = e("peer flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "transition-colors group-hover:bg-accent", !B && "group-hover:text-accent-foreground", !L && "text-muted-foreground", h && "ring-2 ring-primary ring-offset-2", "[&_[data-slot='description']]:hidden", S, B && "text-transparent focus:text-foreground");
660
+ return /* @__PURE__ */ a("div", {
661
+ className: "relative group",
662
+ children: [
663
+ /* @__PURE__ */ i(u, {
664
+ id: t,
665
+ "data-testid": C,
666
+ "data-hydrated": T ? "true" : void 0,
667
+ type: "text",
668
+ disabled: p,
669
+ readOnly: m,
670
+ inputRef: k,
671
+ autoComplete: "off",
672
+ mask: [{
673
+ mask: "00:00",
674
+ lazy: !0
675
+ }, {
676
+ mask: "0:00",
677
+ lazy: !0
678
+ }],
679
+ dispatch: (e, t) => {
680
+ let n = (t.value + e).replace(/\D/g, "");
681
+ if (n.length <= 2 || n.length >= 4) return t.compiledMasks[0];
682
+ let r = g(Number(n.slice(0, 2)));
683
+ return d.some((e) => e.value.startsWith(`${r}:`)) ? t.compiledMasks[0] : t.compiledMasks[1];
684
+ },
685
+ placeholder: r,
686
+ value: L,
687
+ className: V,
688
+ onAccept: (e, t, n) => {
689
+ if (!n) return;
690
+ let r = typeof e == "string" ? e : String(e ?? ""), i = r.replace(/\D/g, ""), a = v(r);
691
+ if (F.current !== a) {
692
+ if (F.current = a, R(r), i.length !== 0) {
693
+ I.current = !1;
694
+ return;
695
+ }
696
+ o && !I.current && (I.current = !0, l(null));
697
+ }
698
+ },
699
+ onComplete: (e, t, n) => {
700
+ if (!n) return;
701
+ let r = typeof e == "string" ? e : String(e ?? "");
702
+ if (P.current === r) {
703
+ P.current = null;
704
+ return;
705
+ }
706
+ let i = y(r, d);
707
+ if (!i) return;
708
+ if (i.selectableValue) {
709
+ if (D(i.selectableValue), R(i.selectableValue), o === i.selectableValue) return;
710
+ l(i.selectableValue);
711
+ return;
712
+ }
713
+ let a = b(i.parsed);
714
+ if (a == null) return;
715
+ let s = w(a, d);
716
+ s && D(s.value);
717
+ },
718
+ onPointerDown: () => {
719
+ M.current = !0, !p && (h || _(!0));
720
+ },
721
+ onMouseDown: (e) => {
722
+ M.current = !0, N.current = typeof document < "u" && document.activeElement === e.currentTarget, !p && (h || _(!0));
723
+ },
724
+ onClick: () => {
725
+ p || h || _(!0);
726
+ },
727
+ onKeyDown: (e) => {
728
+ if (!p) {
729
+ if (e.key === "Tab" && h && !e.defaultPrevented) {
730
+ _(!1);
731
+ return;
732
+ }
733
+ if (e.key === "Escape") {
734
+ if (!h) return;
735
+ e.preventDefault(), _(!1);
736
+ return;
737
+ }
738
+ if (!h && !e.defaultPrevented && (e.key.length === 1 || e.key === "Backspace" || e.key === "Delete") && !e.ctrlKey && !e.metaKey && !e.altKey && _(!0), e.key === "ArrowDown" || e.key === "ArrowUp") {
739
+ if (O(), e.preventDefault(), !h) {
740
+ _(!0);
741
+ return;
742
+ }
743
+ z(e.key === "ArrowDown" ? 1 : -1);
744
+ return;
745
+ }
746
+ if (e.key === "Enter") {
747
+ O();
748
+ let t = y(L, d);
749
+ if (!t) {
750
+ if (!h || L.trim() !== "") return;
751
+ let t = d.find((e) => e.value === E.current), n = (x(t) ? t?.value : void 0) ?? d.find((e) => x(e))?.value;
752
+ if (!n) return;
753
+ e.preventDefault(), D(n), R(n), l(n), _(!1);
754
+ return;
755
+ }
756
+ if (t.selectableValue) {
757
+ e.preventDefault(), D(t.selectableValue), R(t.selectableValue), l(t.selectableValue), _(!1);
758
+ return;
759
+ }
760
+ let n = b(t.parsed);
761
+ if (n == null) return;
762
+ let r = w(n, d);
763
+ if (!r) return;
764
+ e.preventDefault(), D(r.value), R(r.value), l(r.value), _(!1);
765
+ return;
766
+ }
767
+ }
768
+ },
769
+ onFocus: (e) => {
770
+ let t = !M.current || !N.current;
771
+ if (M.current = !1, N.current = !1, j.current = !0, t) {
772
+ let t = e.currentTarget;
773
+ requestAnimationFrame(() => t.select());
774
+ }
775
+ p || h || _(!0);
776
+ },
777
+ onBlur: () => {
778
+ j.current = !1;
779
+ let e = L.trim();
780
+ if (!e) {
781
+ R(o || "");
782
+ return;
783
+ }
784
+ let t = y(e, d);
785
+ if (!t) {
786
+ R(o || "");
787
+ return;
788
+ }
789
+ if (!t.selectableValue) {
790
+ R(o || "");
791
+ return;
792
+ }
793
+ R(t.selectableValue), o !== t.selectableValue && l(t.selectableValue);
794
+ }
795
+ }),
796
+ o && f != null ? /* @__PURE__ */ i("span", {
797
+ "aria-hidden": "true",
798
+ "data-slot": "hours-picker-input-selected-label",
799
+ className: e("pointer-events-none absolute inset-y-0 left-3 right-10 flex min-w-0 items-center text-base transition-colors group-hover:text-accent-foreground peer-focus:hidden md:text-sm", p && "opacity-50"),
800
+ children: /* @__PURE__ */ i("span", {
801
+ className: "min-w-0 truncate",
802
+ children: f
803
+ })
804
+ }) : null,
805
+ /* @__PURE__ */ i("button", {
806
+ type: "button",
807
+ tabIndex: -1,
808
+ disabled: p,
809
+ "data-slot": "hours-picker-input-toggle",
810
+ className: e("absolute right-1 top-1/2 inline-flex size-8 -translate-y-1/2 items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"),
811
+ "aria-label": h ? "Close time picker" : "Open time picker",
812
+ onPointerDown: (e) => {
813
+ e.preventDefault();
814
+ },
815
+ onMouseDown: (e) => {
816
+ e.preventDefault();
817
+ },
818
+ onClick: () => {
819
+ p || _(!h);
820
+ },
821
+ children: /* @__PURE__ */ i(s, {
822
+ "aria-hidden": !0,
823
+ className: "size-4"
824
+ })
825
+ })
826
+ ]
827
+ });
828
+ }
829
+ //#endregion
830
+ export { O as HourPickerField, E as HourPickerInput };