@bearmenu/ui 0.8.23 → 0.8.25

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 (83) hide show
  1. package/dist/{chunk-5LTILG3L.js → chunk-5HHRVJOT.js} +14 -1
  2. package/dist/{chunk-SDWN6L4O.js → chunk-AHHDC7ML.js} +1 -1
  3. package/dist/{chunk-5XREWOBB.js → chunk-IEIJP73R.js} +14 -1
  4. package/dist/{chunk-BKKQ7GCZ.js → chunk-QG6I2ILT.js} +1 -1
  5. package/dist/{chunk-TIQNM4XD.js → chunk-VEGFQSZA.js} +17 -1
  6. package/dist/components/alert-dialog.js +1 -1
  7. package/dist/components/alert.d.ts +2 -2
  8. package/dist/components/badge.d.ts +1 -1
  9. package/dist/components/badge.js +1 -1
  10. package/dist/components/booking-row.d.ts +60 -0
  11. package/dist/components/booking-row.js +103 -0
  12. package/dist/components/booking-summary-card.d.ts +38 -0
  13. package/dist/components/booking-summary-card.js +67 -0
  14. package/dist/components/button.d.ts +2 -2
  15. package/dist/components/button.js +1 -1
  16. package/dist/components/calendar.d.ts +17 -3
  17. package/dist/components/calendar.js +100 -12
  18. package/dist/components/carousel.js +1 -1
  19. package/dist/components/coach-marks.js +1 -1
  20. package/dist/components/combobox.js +1 -1
  21. package/dist/components/command.d.ts +7 -7
  22. package/dist/components/concept-convergence.js +2 -2
  23. package/dist/components/empty-state.js +1 -1
  24. package/dist/components/event-card.js +1 -1
  25. package/dist/components/event-compact-row.js +1 -1
  26. package/dist/components/event-detail-panel.js +1 -1
  27. package/dist/components/event-list-row-wide.js +2 -2
  28. package/dist/components/event-list-row.js +1 -1
  29. package/dist/components/filter-category-row.js +1 -1
  30. package/dist/components/hold-countdown.d.ts +43 -0
  31. package/dist/components/hold-countdown.js +90 -0
  32. package/dist/components/kitchen-dossier.js +1 -1
  33. package/dist/components/link-button.js +1 -1
  34. package/dist/components/menu-family-block.js +1 -1
  35. package/dist/components/menu-index-list.js +1 -1
  36. package/dist/components/menu-item.js +3 -3
  37. package/dist/components/motion-icon-set.d.ts +2 -1
  38. package/dist/components/motion-icon-set.js +27 -1
  39. package/dist/components/multi-select-combobox.js +2 -2
  40. package/dist/components/pagination.js +1 -1
  41. package/dist/components/party-counter.d.ts +36 -0
  42. package/dist/components/party-counter.js +61 -0
  43. package/dist/components/place-card.js +2 -2
  44. package/dist/components/place-details-mobile.js +1 -1
  45. package/dist/components/searchable-select.js +1 -1
  46. package/dist/components/signature-chip.js +2 -2
  47. package/dist/components/sliding-panels.js +1 -1
  48. package/dist/components/spinner.d.ts +2 -2
  49. package/dist/components/tag.d.ts +2 -2
  50. package/dist/components/text.d.ts +3 -3
  51. package/dist/components/time-slot.d.ts +73 -0
  52. package/dist/components/time-slot.js +106 -0
  53. package/dist/components/toggle-group.js +15 -2
  54. package/dist/components/toggle.d.ts +1 -1
  55. package/dist/components/toggle.js +1 -1
  56. package/dist/components/top-ranking-entry.js +3 -3
  57. package/dist/components/weekday-chip.d.ts +33 -0
  58. package/dist/components/weekday-chip.js +48 -0
  59. package/package.json +1 -1
  60. package/src/components/badge.stories.tsx +17 -0
  61. package/src/components/badge.tsx +15 -0
  62. package/src/components/booking-primitives.test.tsx +180 -0
  63. package/src/components/booking-row.stories.tsx +66 -0
  64. package/src/components/booking-row.tsx +168 -0
  65. package/src/components/booking-summary-card.stories.tsx +41 -0
  66. package/src/components/booking-summary-card.tsx +109 -0
  67. package/src/components/button.stories.tsx +23 -0
  68. package/src/components/button.tsx +13 -0
  69. package/src/components/calendar.stories.tsx +27 -0
  70. package/src/components/calendar.tsx +110 -3
  71. package/src/components/hold-countdown.stories.tsx +68 -0
  72. package/src/components/hold-countdown.tsx +140 -0
  73. package/src/components/motion-icon-set.stories.tsx +2 -0
  74. package/src/components/motion-icon-set.tsx +42 -0
  75. package/src/components/party-counter.stories.tsx +57 -0
  76. package/src/components/party-counter.tsx +93 -0
  77. package/src/components/time-slot.stories.tsx +85 -0
  78. package/src/components/time-slot.tsx +186 -0
  79. package/src/components/toggle-group.stories.tsx +27 -0
  80. package/src/components/toggle-group.tsx +14 -1
  81. package/src/components/toggle.tsx +16 -0
  82. package/src/components/weekday-chip.stories.tsx +54 -0
  83. package/src/components/weekday-chip.tsx +75 -0
@@ -8,7 +8,7 @@ declare const Command: React.ForwardRefExoticComponent<Omit<{
8
8
  ref?: React.Ref<HTMLDivElement>;
9
9
  } & {
10
10
  asChild?: boolean;
11
- }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & {
11
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
12
12
  label?: string;
13
13
  shouldFilter?: boolean;
14
14
  filter?: (value: string, search: string, keywords?: string[]) => number;
@@ -38,7 +38,7 @@ declare const CommandList: React.ForwardRefExoticComponent<Omit<{
38
38
  ref?: React.Ref<HTMLDivElement>;
39
39
  } & {
40
40
  asChild?: boolean;
41
- }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & {
41
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
42
42
  label?: string;
43
43
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
44
44
  declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
@@ -47,14 +47,14 @@ declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
47
47
  ref?: React.Ref<HTMLDivElement>;
48
48
  } & {
49
49
  asChild?: boolean;
50
- }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
50
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
51
51
  declare const CommandLoading: React.ForwardRefExoticComponent<Omit<{
52
52
  children?: React.ReactNode;
53
53
  } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
54
54
  ref?: React.Ref<HTMLDivElement>;
55
55
  } & {
56
56
  asChild?: boolean;
57
- }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & {
57
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
58
58
  progress?: number;
59
59
  label?: string;
60
60
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
@@ -64,7 +64,7 @@ declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
64
64
  ref?: React.Ref<HTMLDivElement>;
65
65
  } & {
66
66
  asChild?: boolean;
67
- }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>>, "heading" | "value"> & {
67
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "heading" | "value"> & {
68
68
  heading?: React.ReactNode;
69
69
  value?: string;
70
70
  forceMount?: boolean;
@@ -73,7 +73,7 @@ declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<R
73
73
  ref?: React.Ref<HTMLDivElement>;
74
74
  } & {
75
75
  asChild?: boolean;
76
- }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & {
76
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
77
77
  alwaysRender?: boolean;
78
78
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
79
79
  declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
@@ -82,7 +82,7 @@ declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
82
82
  ref?: React.Ref<HTMLDivElement>;
83
83
  } & {
84
84
  asChild?: boolean;
85
- }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>>, "onSelect" | "disabled" | "value"> & {
85
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "disabled" | "value"> & {
86
86
  disabled?: boolean;
87
87
  onSelect?: (value: string) => void;
88
88
  value?: string;
@@ -1,7 +1,7 @@
1
- import { PhotoGround } from '../chunk-SWD6CJ35.js';
2
1
  import { Convergence } from '../chunk-4XDJXMLF.js';
3
2
  import '../chunk-OIV7B44M.js';
4
- import { Badge } from '../chunk-5XREWOBB.js';
3
+ import { PhotoGround } from '../chunk-SWD6CJ35.js';
4
+ import { Badge } from '../chunk-IEIJP73R.js';
5
5
  import { cn } from '../chunk-FEK5XGZW.js';
6
6
  import '../chunk-MMUBH76A.js';
7
7
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,4 +1,4 @@
1
- import { Button } from '../chunk-5LTILG3L.js';
1
+ import { Button } from '../chunk-5HHRVJOT.js';
2
2
  import '../chunk-RIH2IS7X.js';
3
3
  import '../chunk-5YNIQ2BL.js';
4
4
  import { Text } from '../chunk-ZLMRVBD7.js';
@@ -1,6 +1,6 @@
1
1
  import { TagGroup } from '../chunk-PX6RICS5.js';
2
- import { Tag } from '../chunk-MWB7S54O.js';
3
2
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
3
+ import { Tag } from '../chunk-MWB7S54O.js';
4
4
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
5
5
  import { Skeleton } from '../chunk-XBBEX4SF.js';
6
6
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -1,6 +1,6 @@
1
1
  import { TagGroup } from '../chunk-PX6RICS5.js';
2
- import { Tag } from '../chunk-MWB7S54O.js';
3
2
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
3
+ import { Tag } from '../chunk-MWB7S54O.js';
4
4
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
5
5
  import { Skeleton } from '../chunk-XBBEX4SF.js';
6
6
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -2,7 +2,7 @@ import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
2
2
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
3
3
  import { Separator } from '../chunk-NWZGSLPU.js';
4
4
  import { Skeleton } from '../chunk-XBBEX4SF.js';
5
- import { Button } from '../chunk-5LTILG3L.js';
5
+ import { Button } from '../chunk-5HHRVJOT.js';
6
6
  import '../chunk-RIH2IS7X.js';
7
7
  import '../chunk-5YNIQ2BL.js';
8
8
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -1,9 +1,9 @@
1
- import { Tag } from '../chunk-MWB7S54O.js';
2
1
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
2
+ import { Tag } from '../chunk-MWB7S54O.js';
3
3
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
4
4
  import { Separator } from '../chunk-NWZGSLPU.js';
5
5
  import { Skeleton } from '../chunk-XBBEX4SF.js';
6
- import { buttonVariants } from '../chunk-5LTILG3L.js';
6
+ import { buttonVariants } from '../chunk-5HHRVJOT.js';
7
7
  import '../chunk-RIH2IS7X.js';
8
8
  import '../chunk-5YNIQ2BL.js';
9
9
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -1,6 +1,6 @@
1
1
  import { TagGroup } from '../chunk-PX6RICS5.js';
2
- import { Tag } from '../chunk-MWB7S54O.js';
3
2
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
3
+ import { Tag } from '../chunk-MWB7S54O.js';
4
4
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
5
5
  import { Separator } from '../chunk-NWZGSLPU.js';
6
6
  import { Skeleton } from '../chunk-XBBEX4SF.js';
@@ -1,5 +1,5 @@
1
1
  import { Text } from '../chunk-ZLMRVBD7.js';
2
- import { Badge } from '../chunk-5XREWOBB.js';
2
+ import { Badge } from '../chunk-IEIJP73R.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
4
  import '../chunk-MMUBH76A.js';
5
5
  import { ChevronRight } from 'lucide-react';
@@ -0,0 +1,43 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ /**
5
+ * HoldCountdown — "HELD FOR YOU 09:41": how long a table offered from the
6
+ * waitlist stays reserved for this guest (the booking flow's "A table opened
7
+ * up").
8
+ *
9
+ * Measured from the booking design: a card with a warning-colour hairline,
10
+ * 14px radius, 15px inset.
11
+ * - `stacked` (mobile): centred. The label at 10.5px uppercase with 0.06em
12
+ * tracking, muted; the remaining time in mono at 34px bold; a muted
13
+ * 11.5px line under it ("then it goes to the next person").
14
+ * - `inline` (desktop): one row, 18px gaps. The label over the time at
15
+ * 30px, then the explanation at 12.5px muted taking the free width, then
16
+ * the action.
17
+ *
18
+ * Counts down from `expiresAt` once a second and calls `onExpire` once, at
19
+ * zero. It never shows a negative time.
20
+ */
21
+ type HoldCountdownLabels = {
22
+ /** "Held for you" */
23
+ held: string;
24
+ /** Stacked: "then it goes to the next person". Inline: "After the countdown the table goes to the next person on the list." */
25
+ explanation: string;
26
+ /** Spoken form for assistive tech — "9 minutes 41 seconds left". */
27
+ remaining: (minutes: number, seconds: number) => string;
28
+ };
29
+ type HoldCountdownProps = {
30
+ /** When the hold ends — ISO string or epoch milliseconds. */
31
+ expiresAt: string | number;
32
+ labels: HoldCountdownLabels;
33
+ layout?: "stacked" | "inline";
34
+ /** The inline layout's action, typically a `Button variant="cta" size="cta-sm"`. */
35
+ action?: React.ReactNode;
36
+ onExpire?: () => void;
37
+ /** Clock override for stories and tests. */
38
+ now?: () => number;
39
+ className?: string;
40
+ };
41
+ declare function HoldCountdown({ expiresAt, labels, layout, action, onExpire, now, className, }: HoldCountdownProps): react_jsx_runtime.JSX.Element;
42
+
43
+ export { HoldCountdown, type HoldCountdownLabels, type HoldCountdownProps };
@@ -0,0 +1,90 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import '../chunk-MMUBH76A.js';
3
+ import * as React from 'react';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ var HOLD_BORDER = "border-[oklch(0.62_0.15_70)] dark:border-warning";
7
+ function remainingSeconds(expiresAt, now) {
8
+ const end = typeof expiresAt === "number" ? expiresAt : Date.parse(expiresAt);
9
+ return Math.max(0, Math.ceil((end - now) / 1e3));
10
+ }
11
+ function HoldCountdown({
12
+ expiresAt,
13
+ labels,
14
+ layout = "stacked",
15
+ action,
16
+ onExpire,
17
+ now = Date.now,
18
+ className
19
+ }) {
20
+ const [left, setLeft] = React.useState(() => remainingSeconds(expiresAt, now()));
21
+ const expired = React.useRef(false);
22
+ const onExpireRef = React.useRef(onExpire);
23
+ onExpireRef.current = onExpire;
24
+ React.useEffect(() => {
25
+ expired.current = false;
26
+ const tick = () => {
27
+ var _a;
28
+ const next = remainingSeconds(expiresAt, now());
29
+ setLeft(next);
30
+ if (next === 0 && !expired.current) {
31
+ expired.current = true;
32
+ (_a = onExpireRef.current) == null ? void 0 : _a.call(onExpireRef);
33
+ }
34
+ };
35
+ tick();
36
+ const id = window.setInterval(tick, 1e3);
37
+ return () => window.clearInterval(id);
38
+ }, [expiresAt, now]);
39
+ const minutes = Math.floor(left / 60);
40
+ const seconds = left % 60;
41
+ const display = `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
42
+ const label = /* @__PURE__ */ jsx("div", { className: "text-[10.5px] leading-[13px] tracking-[0.06em] text-muted-foreground uppercase", children: labels.held });
43
+ const time = /* @__PURE__ */ jsx(
44
+ "div",
45
+ {
46
+ role: "timer",
47
+ "aria-label": labels.remaining(minutes, seconds),
48
+ className: cn(
49
+ "font-mono font-bold tabular-nums text-foreground",
50
+ layout === "stacked" ? "mt-[5px] text-[34px] leading-[40px]" : "text-[30px] leading-[35px]"
51
+ ),
52
+ children: display
53
+ }
54
+ );
55
+ if (layout === "inline") {
56
+ return /* @__PURE__ */ jsxs(
57
+ "div",
58
+ {
59
+ "data-slot": "hold-countdown",
60
+ className: cn(
61
+ "flex items-center gap-[18px] rounded-[14px] border bg-card p-[15px] text-left",
62
+ HOLD_BORDER,
63
+ className
64
+ ),
65
+ children: [
66
+ /* @__PURE__ */ jsxs("div", { className: "shrink-0", children: [
67
+ label,
68
+ time
69
+ ] }),
70
+ /* @__PURE__ */ jsx("p", { className: "flex-1 text-[12.5px] leading-[15px] text-muted-foreground", children: labels.explanation }),
71
+ action
72
+ ]
73
+ }
74
+ );
75
+ }
76
+ return /* @__PURE__ */ jsxs(
77
+ "div",
78
+ {
79
+ "data-slot": "hold-countdown",
80
+ className: cn("rounded-[14px] border bg-card p-[15px] text-center", HOLD_BORDER, className),
81
+ children: [
82
+ label,
83
+ time,
84
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-[11.5px] leading-[14px] text-muted-foreground", children: labels.explanation })
85
+ ]
86
+ }
87
+ );
88
+ }
89
+
90
+ export { HoldCountdown };
@@ -1,5 +1,5 @@
1
- import { DIMENSION_ORDER, VenueGradeDimensions } from '../chunk-ZQ53AGML.js';
2
1
  import { VenueQuotes } from '../chunk-43RC7MHY.js';
2
+ import { DIMENSION_ORDER, VenueGradeDimensions } from '../chunk-ZQ53AGML.js';
3
3
  import { StoryProvider, StorySegments, StoryPanel } from '../chunk-F6FMZJDG.js';
4
4
  import { GlassGround } from '../chunk-ICOU5QHT.js';
5
5
  import { Separator } from '../chunk-NWZGSLPU.js';
@@ -1,4 +1,4 @@
1
- import { Button } from '../chunk-5LTILG3L.js';
1
+ import { Button } from '../chunk-5HHRVJOT.js';
2
2
  import '../chunk-RIH2IS7X.js';
3
3
  import '../chunk-5YNIQ2BL.js';
4
4
  import '../chunk-FEK5XGZW.js';
@@ -3,7 +3,7 @@ import { HueChip } from '../chunk-6VOWT4YR.js';
3
3
  import { Separator } from '../chunk-NWZGSLPU.js';
4
4
  import { PhotoGround, PHOTO_GROUND } from '../chunk-SWD6CJ35.js';
5
5
  import { Skeleton } from '../chunk-XBBEX4SF.js';
6
- import { buttonVariants } from '../chunk-5LTILG3L.js';
6
+ import { buttonVariants } from '../chunk-5HHRVJOT.js';
7
7
  import '../chunk-RIH2IS7X.js';
8
8
  import '../chunk-5YNIQ2BL.js';
9
9
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -1,6 +1,6 @@
1
1
  import { Separator } from '../chunk-NWZGSLPU.js';
2
2
  import { Skeleton } from '../chunk-XBBEX4SF.js';
3
- import { Button } from '../chunk-5LTILG3L.js';
3
+ import { Button } from '../chunk-5HHRVJOT.js';
4
4
  import '../chunk-RIH2IS7X.js';
5
5
  import '../chunk-5YNIQ2BL.js';
6
6
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -1,5 +1,5 @@
1
- export { MentionSignal, MenuItem } from '../chunk-SDWN6L4O.js';
2
- import '../chunk-BKKQ7GCZ.js';
3
- import '../chunk-5XREWOBB.js';
1
+ export { MentionSignal, MenuItem } from '../chunk-AHHDC7ML.js';
2
+ import '../chunk-QG6I2ILT.js';
3
+ import '../chunk-IEIJP73R.js';
4
4
  import '../chunk-FEK5XGZW.js';
5
5
  import '../chunk-MMUBH76A.js';
@@ -15,6 +15,7 @@ declare function MotionHouse(props: MotionIconProps): react_jsx_runtime.JSX.Elem
15
15
  * the silhouette alone.
16
16
  */
17
17
  declare function MotionUtensils(props: MotionIconProps): react_jsx_runtime.JSX.Element;
18
+ declare function MotionCompass(props: MotionIconProps): react_jsx_runtime.JSX.Element;
18
19
  declare function MotionMapPin(props: MotionIconProps): react_jsx_runtime.JSX.Element;
19
20
  /**
20
21
  * Lucide's calendar has no pages — it is a box, a rule and six dots, and
@@ -36,4 +37,4 @@ declare function MotionFlame(props: MotionIconProps): react_jsx_runtime.JSX.Elem
36
37
  declare function MotionCalendarClock(props: MotionIconProps): react_jsx_runtime.JSX.Element;
37
38
  declare function MotionList(props: MotionIconProps): react_jsx_runtime.JSX.Element;
38
39
 
39
- export { MotionCalendar, MotionCalendarClock, MotionFlame, MotionHouse, MotionLayoutGrid, MotionList, MotionMap, MotionMapPin, MotionUtensils, MotionWine };
40
+ export { MotionCalendar, MotionCalendarClock, MotionCompass, MotionFlame, MotionHouse, MotionLayoutGrid, MotionList, MotionMap, MotionMapPin, MotionUtensils, MotionWine };
@@ -87,6 +87,32 @@ function MotionUtensils(props) {
87
87
  ] })
88
88
  ] }));
89
89
  }
90
+ var COMPASS_TIMES = [0, 0.14, 0.58, 0.76, 0.9, 1];
91
+ var compassNeedle = {
92
+ rest: { rotate: 360, fillOpacity: 0, transition: returnTransition },
93
+ active: { rotate: 360, fillOpacity: 1, transition: returnTransition },
94
+ play: {
95
+ rotate: [0, -24, 380, 352, 364, 360],
96
+ // The fill lands with the needle: it takes as the swing dies.
97
+ fillOpacity: [0, 0, 0, 0.6, 1, 1],
98
+ transition: beats(COMPASS_TIMES, 0.7)
99
+ }
100
+ };
101
+ function MotionCompass(props) {
102
+ return /* @__PURE__ */ jsxs(MotionIcon, __spreadProps(__spreadValues({}, props), { children: [
103
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
104
+ /* @__PURE__ */ jsx(
105
+ motion.path,
106
+ {
107
+ variants: compassNeedle,
108
+ style: pivot(12, 12),
109
+ fill: "currentColor",
110
+ fillOpacity: 0,
111
+ d: "m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z"
112
+ }
113
+ )
114
+ ] }));
115
+ }
90
116
  var PIN_TIMES = [0, 0.16, 0.44, 0.72, 1];
91
117
  var pinBody = {
92
118
  rest: { y: 0, scaleY: 1, transition: returnTransition },
@@ -339,4 +365,4 @@ function MotionList(props) {
339
365
  ] }));
340
366
  }
341
367
 
342
- export { MotionCalendar, MotionCalendarClock, MotionFlame, MotionHouse, MotionLayoutGrid, MotionList, MotionMap, MotionMapPin, MotionUtensils, MotionWine };
368
+ export { MotionCalendar, MotionCalendarClock, MotionCompass, MotionFlame, MotionHouse, MotionLayoutGrid, MotionList, MotionMap, MotionMapPin, MotionUtensils, MotionWine };
@@ -2,10 +2,10 @@ import { Popover, PopoverTrigger, PopoverContent } from '../chunk-2ADCZXZJ.js';
2
2
  import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-MCOHLWRS.js';
3
3
  import '../chunk-PDTPO6NG.js';
4
4
  import { Checkbox } from '../chunk-NMEVJT5Q.js';
5
- import { Button } from '../chunk-5LTILG3L.js';
5
+ import { Button } from '../chunk-5HHRVJOT.js';
6
6
  import '../chunk-RIH2IS7X.js';
7
7
  import '../chunk-5YNIQ2BL.js';
8
- import { Badge } from '../chunk-5XREWOBB.js';
8
+ import { Badge } from '../chunk-IEIJP73R.js';
9
9
  import { cn } from '../chunk-FEK5XGZW.js';
10
10
  import '../chunk-MMUBH76A.js';
11
11
  import * as React from 'react';
@@ -1,4 +1,4 @@
1
- import { buttonVariants } from '../chunk-5LTILG3L.js';
1
+ import { buttonVariants } from '../chunk-5HHRVJOT.js';
2
2
  import '../chunk-RIH2IS7X.js';
3
3
  import '../chunk-5YNIQ2BL.js';
4
4
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -0,0 +1,36 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * PartyCounter — how many people, in the booking flow's "When are you
5
+ * coming?" and "Change party size" screens.
6
+ *
7
+ * Measured from the booking design (`.stepper`): a 52px bordered field on the
8
+ * card ground, 12px radius, 8px side inset. A round 36px minus on the muted
9
+ * surface at the left, a round 36px plus filled with `--gradient-primary` at
10
+ * the right — the plus is the direction the screen is asking about — and the
11
+ * count between them at 19px bold with its unit at 12px muted.
12
+ *
13
+ * At an end the button is disabled, not hidden, so the value never shifts.
14
+ * The value is announced politely on change; the buttons carry their own
15
+ * localised names, because a lone "−" reads as nothing to a screen reader.
16
+ */
17
+ type PartyCounterLabels = {
18
+ /** "Fewer people" */
19
+ decrease: string;
20
+ /** "More people" */
21
+ increase: string;
22
+ /** The unit after the number: "people" / "person" — already pluralised by the caller. */
23
+ unit: (count: number) => string;
24
+ };
25
+ type PartyCounterProps = {
26
+ value: number;
27
+ onValueChange: (value: number) => void;
28
+ min?: number;
29
+ max?: number;
30
+ labels: PartyCounterLabels;
31
+ disabled?: boolean;
32
+ className?: string;
33
+ };
34
+ declare function PartyCounter({ value, onValueChange, min, max, labels, disabled, className, }: PartyCounterProps): react_jsx_runtime.JSX.Element;
35
+
36
+ export { PartyCounter, type PartyCounterLabels, type PartyCounterProps };
@@ -0,0 +1,61 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import '../chunk-MMUBH76A.js';
3
+ import { Minus, Plus } from 'lucide-react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ function PartyCounter({
7
+ value,
8
+ onValueChange,
9
+ min = 1,
10
+ max = 20,
11
+ labels,
12
+ disabled,
13
+ className
14
+ }) {
15
+ const atMin = value <= min;
16
+ const atMax = value >= max;
17
+ const roundButton = "grid size-9 shrink-0 cursor-pointer place-items-center rounded-full transition-[filter,background-color,opacity] duration-150 motion-reduce:transition-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card disabled:cursor-not-allowed disabled:opacity-40 [&_svg]:size-4";
18
+ return /* @__PURE__ */ jsxs(
19
+ "div",
20
+ {
21
+ "data-slot": "party-counter",
22
+ className: cn(
23
+ "flex h-[52px] items-center justify-between gap-2.5 rounded-xl border border-border bg-card px-2",
24
+ className
25
+ ),
26
+ children: [
27
+ /* @__PURE__ */ jsx(
28
+ "button",
29
+ {
30
+ type: "button",
31
+ "aria-label": labels.decrease,
32
+ disabled: disabled || atMin,
33
+ onClick: () => onValueChange(Math.max(min, value - 1)),
34
+ className: cn(roundButton, "bg-surface-2 text-foreground hover:bg-muted"),
35
+ children: /* @__PURE__ */ jsx(Minus, { "aria-hidden": true })
36
+ }
37
+ ),
38
+ /* @__PURE__ */ jsxs("output", { "aria-live": "polite", className: "flex-1 text-center", children: [
39
+ /* @__PURE__ */ jsx("b", { className: "text-[19px] font-bold tabular-nums text-foreground", children: value }),
40
+ /* @__PURE__ */ jsx("span", { className: "ml-1 text-xs text-muted-foreground", children: labels.unit(value) })
41
+ ] }),
42
+ /* @__PURE__ */ jsx(
43
+ "button",
44
+ {
45
+ type: "button",
46
+ "aria-label": labels.increase,
47
+ disabled: disabled || atMax,
48
+ onClick: () => onValueChange(Math.min(max, value + 1)),
49
+ className: cn(
50
+ roundButton,
51
+ "bg-[image:var(--gradient-primary)] text-white hover:brightness-[0.94]"
52
+ ),
53
+ children: /* @__PURE__ */ jsx(Plus, { "aria-hidden": true })
54
+ }
55
+ )
56
+ ]
57
+ }
58
+ );
59
+ }
60
+
61
+ export { PartyCounter };
@@ -3,10 +3,10 @@ import { HOVER_IMAGE_MOTION, HOVER_IMAGE_WRAPPER, HOVER_MOTION, HOVER_LIFT_GRID_
3
3
  import { NEUTRAL_ICON_FILTER } from '../chunk-LQWGZIYA.js';
4
4
  import { GradeAtom } from '../chunk-YE4ZQUTI.js';
5
5
  import { showsGradeAtom } from '../chunk-I5V446BX.js';
6
- import { Separator } from '../chunk-NWZGSLPU.js';
7
6
  import { springSnappy } from '../chunk-OIV7B44M.js';
7
+ import { Separator } from '../chunk-NWZGSLPU.js';
8
8
  import { Skeleton } from '../chunk-XBBEX4SF.js';
9
- import { Badge } from '../chunk-5XREWOBB.js';
9
+ import { Badge } from '../chunk-IEIJP73R.js';
10
10
  import { cn } from '../chunk-FEK5XGZW.js';
11
11
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
12
12
  import { forwardRef, memo, useState, useMemo } from 'react';
@@ -3,7 +3,7 @@ import '../chunk-FMTJGO76.js';
3
3
  import '../chunk-MWB7S54O.js';
4
4
  import '../chunk-NWZGSLPU.js';
5
5
  import { Text } from '../chunk-ZLMRVBD7.js';
6
- import { Badge } from '../chunk-5XREWOBB.js';
6
+ import { Badge } from '../chunk-IEIJP73R.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
8
8
  import '../chunk-MMUBH76A.js';
9
9
  import { useState } from 'react';
@@ -1,7 +1,7 @@
1
1
  import { Popover, PopoverTrigger, PopoverContent } from '../chunk-2ADCZXZJ.js';
2
2
  import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-MCOHLWRS.js';
3
3
  import '../chunk-PDTPO6NG.js';
4
- import { Button } from '../chunk-5LTILG3L.js';
4
+ import { Button } from '../chunk-5HHRVJOT.js';
5
5
  import '../chunk-RIH2IS7X.js';
6
6
  import '../chunk-5YNIQ2BL.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -1,4 +1,4 @@
1
- export { SignatureChip } from '../chunk-BKKQ7GCZ.js';
2
- import '../chunk-5XREWOBB.js';
1
+ export { SignatureChip } from '../chunk-QG6I2ILT.js';
2
+ import '../chunk-IEIJP73R.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
4
  import '../chunk-MMUBH76A.js';
@@ -1,4 +1,4 @@
1
- import { Button } from '../chunk-5LTILG3L.js';
1
+ import { Button } from '../chunk-5HHRVJOT.js';
2
2
  import '../chunk-RIH2IS7X.js';
3
3
  import '../chunk-5YNIQ2BL.js';
4
4
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -4,11 +4,11 @@ import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const spinnerVariants: (props?: ({
6
6
  size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
7
- tone?: "default" | "destructive" | "inherit" | "primary" | null | undefined;
7
+ tone?: "inherit" | "default" | "destructive" | "primary" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  declare const Spinner: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
10
10
  size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
11
- tone?: "default" | "destructive" | "inherit" | "primary" | null | undefined;
11
+ tone?: "inherit" | "default" | "destructive" | "primary" | null | undefined;
12
12
  } & class_variance_authority_types.ClassProp) | undefined) => string> & {
13
13
  /** Visually-hidden label for screen readers. Defaults to "Loading". */
14
14
  label?: string;
@@ -3,11 +3,11 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const tagVariants: (props?: ({
6
- variant?: "default" | "destructive" | "outline" | "success" | "warning" | "primary" | "quiet" | null | undefined;
6
+ variant?: "default" | "destructive" | "outline" | "warning" | "success" | "primary" | "quiet" | null | undefined;
7
7
  size?: "default" | "sm" | "lg" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  declare const Tag: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
10
- variant?: "default" | "destructive" | "outline" | "success" | "warning" | "primary" | "quiet" | null | undefined;
10
+ variant?: "default" | "destructive" | "outline" | "warning" | "success" | "primary" | "quiet" | null | undefined;
11
11
  size?: "default" | "sm" | "lg" | null | undefined;
12
12
  } & class_variance_authority_types.ClassProp) | undefined) => string> & {
13
13
  onRemove?: () => void;
@@ -22,9 +22,9 @@ import { VariantProps } from 'class-variance-authority';
22
22
  * Weights are 400 / 600 / 700. 500 is not in the system.
23
23
  */
24
24
  declare const textVariants: (props?: ({
25
- variant?: "small" | "display" | "h2" | "h3" | "label" | "body" | "caption" | "h1" | "h4" | "body-lg" | "body-sm" | "overline" | null | undefined;
26
- color?: "default" | "destructive" | "inherit" | "muted" | "primary" | "primary-foreground" | null | undefined;
27
- weight?: "medium" | "bold" | "normal" | "semibold" | null | undefined;
25
+ variant?: "h2" | "h3" | "label" | "body" | "caption" | "h1" | "h4" | "small" | "display" | "body-lg" | "body-sm" | "overline" | null | undefined;
26
+ color?: "inherit" | "default" | "destructive" | "muted" | "primary" | "primary-foreground" | null | undefined;
27
+ weight?: "bold" | "medium" | "normal" | "semibold" | null | undefined;
28
28
  leading?: "none" | "normal" | "tight" | "snug" | "relaxed" | "loose" | null | undefined;
29
29
  tracking?: "normal" | "tight" | "wide" | "wider" | null | undefined;
30
30
  wrap?: "balance" | "pretty" | "nowrap" | null | undefined;