@bearmenu/ui 0.8.24 → 0.8.26

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 (113) 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-I4RUOAU7.js → chunk-AHL45DD2.js} +11 -38
  4. package/dist/{chunk-TIQNM4XD.js → chunk-F3XK34DV.js} +25 -1
  5. package/dist/{chunk-5XREWOBB.js → chunk-IEIJP73R.js} +14 -1
  6. package/dist/chunk-L3CDXVEP.js +56 -0
  7. package/dist/{chunk-BKKQ7GCZ.js → chunk-QG6I2ILT.js} +1 -1
  8. package/dist/{chunk-CZK2MRS2.js → chunk-VEFKZIK6.js} +13 -3
  9. package/dist/components/alert-dialog.js +1 -1
  10. package/dist/components/badge.d.ts +1 -1
  11. package/dist/components/badge.js +1 -1
  12. package/dist/components/banner.d.ts +36 -0
  13. package/dist/components/banner.js +29 -0
  14. package/dist/components/booking-row.d.ts +60 -0
  15. package/dist/components/booking-row.js +103 -0
  16. package/dist/components/booking-summary-card.d.ts +38 -0
  17. package/dist/components/booking-summary-card.js +67 -0
  18. package/dist/components/button.d.ts +2 -2
  19. package/dist/components/button.js +1 -1
  20. package/dist/components/calendar.d.ts +17 -3
  21. package/dist/components/calendar.js +100 -12
  22. package/dist/components/carousel.js +1 -1
  23. package/dist/components/checkbox.d.ts +9 -2
  24. package/dist/components/checkbox.js +1 -1
  25. package/dist/components/coach-marks.js +1 -1
  26. package/dist/components/combobox.js +1 -1
  27. package/dist/components/concept-convergence.js +2 -2
  28. package/dist/components/currency-input.js +1 -1
  29. package/dist/components/date-input.js +1 -1
  30. package/dist/components/drift-rail.d.ts +2 -29
  31. package/dist/components/drift-rail.js +1 -3
  32. package/dist/components/empty-state.js +1 -1
  33. package/dist/components/event-card.js +1 -1
  34. package/dist/components/event-compact-row.js +1 -1
  35. package/dist/components/event-detail-panel.js +2 -2
  36. package/dist/components/event-index-row.js +1 -1
  37. package/dist/components/event-list-row-wide.js +3 -3
  38. package/dist/components/event-list-row.js +2 -2
  39. package/dist/components/field.d.ts +15 -1
  40. package/dist/components/field.js +62 -21
  41. package/dist/components/filter-category-row.js +1 -1
  42. package/dist/components/hold-countdown.d.ts +43 -0
  43. package/dist/components/hold-countdown.js +90 -0
  44. package/dist/components/input.d.ts +1 -0
  45. package/dist/components/input.js +1 -1
  46. package/dist/components/link-button.js +1 -1
  47. package/dist/components/menu-family-block.js +1 -1
  48. package/dist/components/menu-index-list.js +1 -1
  49. package/dist/components/menu-item.js +3 -3
  50. package/dist/components/motion-icon-set.d.ts +2 -1
  51. package/dist/components/motion-icon-set.js +27 -1
  52. package/dist/components/multi-select-combobox.js +3 -3
  53. package/dist/components/multi-select-menu.js +1 -1
  54. package/dist/components/pagination.js +1 -1
  55. package/dist/components/party-counter.d.ts +36 -0
  56. package/dist/components/party-counter.js +61 -0
  57. package/dist/components/place-card.js +1 -1
  58. package/dist/components/place-details-mobile.js +1 -1
  59. package/dist/components/poster-tape.d.ts +2 -15
  60. package/dist/components/poster-tape.js +3 -12
  61. package/dist/components/searchable-select.js +1 -1
  62. package/dist/components/signature-chip.js +2 -2
  63. package/dist/components/sliding-panels.js +1 -1
  64. package/dist/components/textarea.d.ts +10 -3
  65. package/dist/components/textarea.js +21 -6
  66. package/dist/components/time-slot.d.ts +73 -0
  67. package/dist/components/time-slot.js +106 -0
  68. package/dist/components/toggle-group.js +15 -2
  69. package/dist/components/toggle.d.ts +1 -1
  70. package/dist/components/toggle.js +1 -1
  71. package/dist/components/top-ranking-entry.js +3 -3
  72. package/dist/components/weekday-chip.d.ts +33 -0
  73. package/dist/components/weekday-chip.js +48 -0
  74. package/package.json +207 -23
  75. package/src/components/badge.stories.tsx +17 -0
  76. package/src/components/badge.tsx +15 -0
  77. package/src/components/banner.stories.tsx +36 -0
  78. package/src/components/banner.tsx +58 -0
  79. package/src/components/booking-details-primitives.test.tsx +75 -0
  80. package/src/components/booking-primitives.test.tsx +180 -0
  81. package/src/components/booking-row.stories.tsx +66 -0
  82. package/src/components/booking-row.tsx +168 -0
  83. package/src/components/booking-summary-card.stories.tsx +41 -0
  84. package/src/components/booking-summary-card.tsx +109 -0
  85. package/src/components/button.stories.tsx +23 -0
  86. package/src/components/button.tsx +13 -0
  87. package/src/components/calendar.stories.tsx +27 -0
  88. package/src/components/calendar.tsx +110 -3
  89. package/src/components/checkbox.tsx +49 -23
  90. package/src/components/drift-rail.stories.tsx +1 -29
  91. package/src/components/drift-rail.tsx +4 -71
  92. package/src/components/field.stories.tsx +51 -1
  93. package/src/components/field.tsx +68 -9
  94. package/src/components/hold-countdown.stories.tsx +68 -0
  95. package/src/components/hold-countdown.tsx +140 -0
  96. package/src/components/input.tsx +13 -2
  97. package/src/components/motion-icon-set.stories.tsx +2 -0
  98. package/src/components/motion-icon-set.tsx +42 -0
  99. package/src/components/party-counter.stories.tsx +57 -0
  100. package/src/components/party-counter.tsx +93 -0
  101. package/src/components/poster-tape.stories.tsx +0 -29
  102. package/src/components/poster-tape.tsx +5 -21
  103. package/src/components/textarea.tsx +25 -7
  104. package/src/components/time-slot.stories.tsx +85 -0
  105. package/src/components/time-slot.tsx +186 -0
  106. package/src/components/toggle-group.stories.tsx +27 -0
  107. package/src/components/toggle-group.tsx +14 -1
  108. package/src/components/toggle.tsx +24 -0
  109. package/src/components/weekday-chip.stories.tsx +54 -0
  110. package/src/components/weekday-chip.tsx +75 -0
  111. package/dist/chunk-NMEVJT5Q.js +0 -26
  112. package/src/components/drift-rail.test.tsx +0 -125
  113. package/src/components/poster-tape.test.tsx +0 -42
@@ -56,7 +56,16 @@ var buttonVariants = cva(
56
56
  ink: "border border-white/20 bg-white/[0.16] text-white hover:bg-white/25 focus-visible:ring-white/70 focus-visible:ring-offset-0",
57
57
  brown: "bg-brown text-brown-foreground shadow-sm hover:bg-brown/85 hover:shadow",
58
58
  /** An ON state that is not the primary — a toggled mode, a guide running. */
59
- warning: "bg-warning text-warning-foreground shadow-sm hover:bg-warning/90 hover:shadow"
59
+ warning: "bg-warning text-warning-foreground shadow-sm hover:bg-warning/90 hover:shadow",
60
+ /**
61
+ * The committing action of a flow: "Continue · 19:30", "Confirm
62
+ * booking", "Reserve", "See booking". The booking design draws every
63
+ * one of them on `--gradient-primary` with white type, in both themes —
64
+ * the gradient is warm in dark too, so the ink never inverts.
65
+ * `bg-[image:…]`, not `bg-[…]`: the token is a gradient, and only
66
+ * `background-image` accepts it. Pair with `size="cta"` / `"cta-sm"`.
67
+ */
68
+ cta: "bg-[image:var(--gradient-primary)] text-white hover:brightness-[0.94] active:brightness-90"
60
69
  },
61
70
  size: {
62
71
  xs: "h-8 rounded-lg px-3 text-xs [&_svg]:size-3.5",
@@ -65,6 +74,10 @@ var buttonVariants = cva(
65
74
  lg: "h-12 rounded-2xl px-8",
66
75
  /** The `ink` action's shape. Owns the radius so no variant fights it. */
67
76
  pill: "h-11 rounded-full px-5 text-[13.5px] font-bold",
77
+ /** The booking design's action: 46px, 12px radius, 15px semibold. */
78
+ cta: "h-[46px] rounded-xl px-5 text-[15px] font-semibold",
79
+ /** Its compact form, in dense footers and inline rows: 38px, 10px radius. */
80
+ "cta-sm": "h-[38px] rounded-[10px] px-4 text-[13.5px] font-semibold",
68
81
  icon: "h-11 w-11 rounded-full",
69
82
  "icon-xs": "h-8 w-8 rounded-full [&_svg]:size-3.5",
70
83
  "icon-sm": "h-9 w-9 rounded-full",
@@ -1,4 +1,4 @@
1
- import { SignatureChip } from './chunk-BKKQ7GCZ.js';
1
+ import { SignatureChip } from './chunk-QG6I2ILT.js';
2
2
  import { cn } from './chunk-FEK5XGZW.js';
3
3
  import { __objRest, __spreadValues } from './chunk-MMUBH76A.js';
4
4
  import { memo } from 'react';
@@ -1,7 +1,6 @@
1
- import { MotionPlayPause } from './chunk-4OF4T4AI.js';
2
1
  import { cn } from './chunk-FEK5XGZW.js';
3
2
  import { useRef, useState, useEffect } from 'react';
4
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
4
 
6
5
  var DRIFT_RAIL_DEFAULT_DURATION_SECONDS = 42;
7
6
  var DRIFT_RAIL_RESUME_DELAY_MS = 3e3;
@@ -10,7 +9,6 @@ function DriftRail({
10
9
  reverse = false,
11
10
  durationSeconds = DRIFT_RAIL_DEFAULT_DURATION_SECONDS,
12
11
  pauseOnHover = true,
13
- labels,
14
12
  className
15
13
  }) {
16
14
  const scrollerRef = useRef(null);
@@ -18,8 +16,6 @@ function DriftRail({
18
16
  const [isHovered, setIsHovered] = useState(false);
19
17
  const [inView, setInView] = useState(true);
20
18
  const [reducedMotion, setReducedMotion] = useState(false);
21
- const [isManuallyPaused, setIsManuallyPaused] = useState(false);
22
- const [playPauseReplayToken, setPlayPauseReplayToken] = useState(0);
23
19
  const heldUntil = useRef(0);
24
20
  const mouseDrag = useRef(null);
25
21
  const position = useRef(0);
@@ -41,14 +37,14 @@ function DriftRail({
41
37
  return () => observer.disconnect();
42
38
  }, []);
43
39
  useEffect(() => {
44
- const scroller2 = scrollerRef.current;
40
+ const scroller = scrollerRef.current;
45
41
  const track = trackRef.current;
46
- if (!scroller2 || !track) return void 0;
42
+ if (!scroller || !track) return void 0;
47
43
  let frame = 0;
48
44
  let last = performance.now();
49
- const drifting = !reducedMotion && !isManuallyPaused && inView && !(pauseOnHover && isHovered);
50
- if (reverse && scroller2.scrollLeft === 0) scroller2.scrollLeft = track.scrollWidth / 2;
51
- position.current = scroller2.scrollLeft;
45
+ const drifting = !reducedMotion && inView && !(pauseOnHover && isHovered);
46
+ if (reverse && scroller.scrollLeft === 0) scroller.scrollLeft = track.scrollWidth / 2;
47
+ position.current = scroller.scrollLeft;
52
48
  const tick = (now) => {
53
49
  const half = track.scrollWidth / 2;
54
50
  if (half > 0) {
@@ -58,7 +54,7 @@ function DriftRail({
58
54
  const delta = perSecond * (now - last) / 1e3;
59
55
  position.current += reverse ? -delta : delta;
60
56
  } else {
61
- position.current = scroller2.scrollLeft;
57
+ position.current = scroller.scrollLeft;
62
58
  }
63
59
  let wrapped = false;
64
60
  if (position.current >= half) {
@@ -68,14 +64,14 @@ function DriftRail({
68
64
  position.current += half;
69
65
  wrapped = true;
70
66
  }
71
- if (driftingNow || wrapped) scroller2.scrollLeft = position.current;
67
+ if (driftingNow || wrapped) scroller.scrollLeft = position.current;
72
68
  }
73
69
  last = now;
74
70
  frame = requestAnimationFrame(tick);
75
71
  };
76
72
  frame = requestAnimationFrame(tick);
77
73
  return () => cancelAnimationFrame(frame);
78
- }, [durationSeconds, inView, isHovered, isManuallyPaused, pauseOnHover, reducedMotion, reverse]);
74
+ }, [durationSeconds, inView, isHovered, pauseOnHover, reducedMotion, reverse]);
79
75
  const hold = () => {
80
76
  heldUntil.current = Number.POSITIVE_INFINITY;
81
77
  };
@@ -118,7 +114,7 @@ function DriftRail({
118
114
  event.stopPropagation();
119
115
  }
120
116
  };
121
- const scroller = /* @__PURE__ */ jsx(
117
+ return /* @__PURE__ */ jsx(
122
118
  "div",
123
119
  {
124
120
  ref: scrollerRef,
@@ -140,33 +136,10 @@ function DriftRail({
140
136
  ),
141
137
  children: /* @__PURE__ */ jsxs("div", { ref: trackRef, className: "flex w-max items-stretch gap-3.5", children: [
142
138
  children,
143
- /* @__PURE__ */ jsx("div", { className: "contents", "aria-hidden": "true", inert: true, children })
139
+ /* @__PURE__ */ jsx("div", { className: "contents", "aria-hidden": "true", children })
144
140
  ] })
145
141
  }
146
142
  );
147
- if (!labels || reducedMotion) return scroller;
148
- return /* @__PURE__ */ jsxs(Fragment, { children: [
149
- scroller,
150
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
151
- "button",
152
- {
153
- type: "button",
154
- onClick: () => setIsManuallyPaused((current) => !current),
155
- onPointerDown: () => setPlayPauseReplayToken((n) => n + 1),
156
- "aria-label": isManuallyPaused ? labels.play : labels.pause,
157
- "aria-pressed": isManuallyPaused,
158
- className: "flex h-11 w-11 shrink-0 cursor-pointer items-center justify-center rounded-full text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 motion-reduce:transition-none",
159
- children: /* @__PURE__ */ jsx(
160
- MotionPlayPause,
161
- {
162
- active: !isManuallyPaused,
163
- replayToken: playPauseReplayToken,
164
- className: "size-4"
165
- }
166
- )
167
- }
168
- ) })
169
- ] });
170
143
  }
171
144
 
172
145
  export { DriftRail };
@@ -17,7 +17,23 @@ var toggleVariants = cva(
17
17
  * (`ToggleGroup variant="segmented"`) supplies the capsule; the cell
18
18
  * never fills with the accent, which would read as a primary button.
19
19
  */
20
- segmented: "h-10 w-11 rounded-full text-muted-foreground hover:bg-transparent hover:text-foreground data-[state=on]:bg-card data-[state=on]:text-foreground data-[state=on]:shadow-[var(--shadow-card)]"
20
+ segmented: "h-10 w-11 rounded-full text-muted-foreground hover:bg-transparent hover:text-foreground data-[state=on]:bg-card data-[state=on]:text-foreground data-[state=on]:shadow-[var(--shadow-card)]",
21
+ /**
22
+ * A choice among a few named options that sit in a wrapping row —
23
+ * the booking flow's seating preference ("No preference", "Terrace",
24
+ * "By the window"). Off: a card pill with a hairline. On: the accent
25
+ * hairline over an 8% accent wash and accent type — a selection, not
26
+ * a button, so it never fills.
27
+ */
28
+ chip: "h-auto min-w-0 rounded-full border border-border bg-card px-[13px] py-[7px] text-[12.5px] leading-[1.2] font-normal text-foreground hover:border-accent/40 hover:bg-card hover:text-foreground data-[state=on]:border-accent data-[state=on]:bg-accent/[0.08] data-[state=on]:font-semibold data-[state=on]:text-accent",
29
+ /**
30
+ * One tab of a two-or-three-way switch that shares the width — My
31
+ * bookings' Upcoming / Past. The group (`ToggleGroup variant="tab"`)
32
+ * supplies the muted capsule; the ON tab is a raised card. The type
33
+ * does not change colour between on and off — as drawn, the raised
34
+ * card alone says which tab is current.
35
+ */
36
+ tab: "h-auto min-w-0 flex-1 rounded-full px-3 py-[7px] text-[12.5px] leading-[1.2] font-semibold text-ink-secondary hover:bg-transparent hover:text-foreground data-[state=on]:bg-card data-[state=on]:text-ink-secondary data-[state=on]:shadow-[0_1px_2px_oklch(0.5_0_0/0.12)] dark:data-[state=on]:bg-surface-2 dark:data-[state=on]:text-foreground"
21
37
  },
22
38
  size: {
23
39
  default: "h-9 px-2 min-w-9",
@@ -25,6 +41,14 @@ var toggleVariants = cva(
25
41
  lg: "h-10 px-2.5 min-w-10"
26
42
  }
27
43
  },
44
+ // Chips and tabs size to their type. Restated here, after the size
45
+ // variants, so the default size's `h-9 px-2 min-w-9` never wins the
46
+ // merge — for a `Toggle`, a `ToggleGroupItem` or a bare `toggleVariants`
47
+ // call on another element alike.
48
+ compoundVariants: [
49
+ { variant: "chip", class: "h-auto min-w-0 px-[13px]" },
50
+ { variant: "tab", class: "h-auto min-w-0 px-3" }
51
+ ],
28
52
  defaultVariants: {
29
53
  variant: "default",
30
54
  size: "default"
@@ -18,7 +18,20 @@ var badgeVariants = cva(
18
18
  warning: "border-transparent bg-warning text-warning-foreground",
19
19
  brown: "border-transparent bg-brown text-brown-foreground",
20
20
  /** A count sitting INSIDE a primary-filled control: its own ink, lifted a notch. */
21
- onPrimary: "border-transparent bg-primary-foreground/20 text-primary-foreground"
21
+ onPrimary: "border-transparent bg-primary-foreground/20 text-primary-foreground",
22
+ /**
23
+ * Status pills of a booking — "Confirmed", "Pending" — and its code
24
+ * chip ("BM-8421"). A full pill at 10.5px bold, as the booking design
25
+ * draws them. The status type is darker than the solid tokens: `success`
26
+ * and `warning` sit at 0.48 / 0.72 lightness, which on their own 15–20%
27
+ * wash fall short of AA at this size, so light mode uses the design's
28
+ * 0.38 / 0.42 inks and dark mode the lifted tokens.
29
+ */
30
+ // `border-0`: the base's transparent hairline would add 2px to each
31
+ // side the design does not have.
32
+ confirmed: "rounded-full border-0 bg-success/15 px-[9px] py-[3px] text-[10.5px] leading-[1.2] font-bold text-[oklch(0.38_0.1_155)] dark:text-success",
33
+ pending: "rounded-full border-0 bg-warning/20 px-[9px] py-[3px] text-[10.5px] leading-[1.2] font-bold text-[oklch(0.42_0.1_70)] dark:text-warning",
34
+ code: "rounded-full border-0 bg-surface-2 px-[9px] py-[3px] font-mono text-[10.5px] leading-[1.2] font-bold tabular-nums text-ink-secondary"
22
35
  },
23
36
  // v1.0 motion: "live" surface signal — applies `live-pulse` archetype.
24
37
  // Pair with a colored variant (e.g. variant="destructive" live).
@@ -0,0 +1,56 @@
1
+ import { cn } from './chunk-FEK5XGZW.js';
2
+ import { __objRest, __spreadProps, __spreadValues } from './chunk-MMUBH76A.js';
3
+ import * as React from 'react';
4
+ import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
5
+ import { cva } from 'class-variance-authority';
6
+ import { Minus, Check } from 'lucide-react';
7
+ import { jsx } from 'react/jsx-runtime';
8
+
9
+ var checkboxVariants = cva(
10
+ "peer size-5 shrink-0 rounded-md border border-border bg-background transition-all duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground data-[state=indeterminate]:border-primary hover:border-primary/50 aria-invalid:border-destructive aria-invalid:focus-visible:ring-destructive/40",
11
+ {
12
+ variants: {
13
+ /**
14
+ * The booking flow's opt-in ("Save these details for next time",
15
+ * booking flow.html): a 17px box with a 5px radius, a hairline on the
16
+ * soft ground when off, the brand gradient with an 11px white check
17
+ * when on.
18
+ */
19
+ appearance: {
20
+ default: "",
21
+ booking: "size-[17px] rounded-[5px] bg-surface-2 data-[state=checked]:border-transparent data-[state=checked]:bg-[image:var(--gradient-primary)] data-[state=checked]:text-white [&_svg]:size-[11px]"
22
+ }
23
+ },
24
+ defaultVariants: { appearance: "default" }
25
+ }
26
+ );
27
+ var Checkbox = React.forwardRef(
28
+ (_a, ref) => {
29
+ var _b = _a, { className, appearance } = _b, props = __objRest(_b, ["className", "appearance"]);
30
+ return /* @__PURE__ */ jsx(
31
+ CheckboxPrimitive.Root,
32
+ __spreadProps(__spreadValues({
33
+ ref,
34
+ "data-slot": "checkbox",
35
+ className: cn(checkboxVariants({ appearance }), className)
36
+ }, props), {
37
+ children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, { className: cn("flex items-center justify-center text-current"), children: props.checked === "indeterminate" ? /* @__PURE__ */ jsx(
38
+ Minus,
39
+ {
40
+ className: "size-3.5 animate-in fade-in-0 zoom-in-50 duration-200 ease-out",
41
+ strokeWidth: 3
42
+ }
43
+ ) : /* @__PURE__ */ jsx(
44
+ Check,
45
+ {
46
+ className: "size-3.5 animate-in fade-in-0 zoom-in-50 duration-200 ease-out",
47
+ strokeWidth: 3
48
+ }
49
+ ) })
50
+ })
51
+ );
52
+ }
53
+ );
54
+ Checkbox.displayName = CheckboxPrimitive.Root.displayName;
55
+
56
+ export { Checkbox, checkboxVariants };
@@ -1,4 +1,4 @@
1
- import { Badge } from './chunk-5XREWOBB.js';
1
+ import { Badge } from './chunk-IEIJP73R.js';
2
2
  import { cn } from './chunk-FEK5XGZW.js';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
@@ -16,23 +16,33 @@ var inputVariants = cva(
16
16
  shape: {
17
17
  rounded: "rounded-xl focus-visible:ring-ring",
18
18
  pill: "rounded-full bg-background shadow-[var(--shadow-card)] focus-visible:ring-accent/30"
19
+ },
20
+ /**
21
+ * The booking flow's field (booking flow.html, `.in`): 46px on the card
22
+ * ground rather than the input wash, an 11px radius, 13px inset, 14px
23
+ * type. Last, so it wins over the size and shape it restates.
24
+ */
25
+ appearance: {
26
+ default: "",
27
+ booking: "h-[46px] rounded-[11px] bg-card px-[13px] py-0 text-[14px] leading-[1.2] focus-visible:bg-card focus-visible:ring-ring aria-invalid:border-[oklch(0.52_0.16_25)] dark:aria-invalid:border-destructive"
19
28
  }
20
29
  },
21
30
  defaultVariants: {
22
31
  size: "default",
23
- shape: "rounded"
32
+ shape: "rounded",
33
+ appearance: "default"
24
34
  }
25
35
  }
26
36
  );
27
37
  var Input = React.forwardRef(
28
38
  (_a, ref) => {
29
- var _b = _a, { className, type, size, shape } = _b, props = __objRest(_b, ["className", "type", "size", "shape"]);
39
+ var _b = _a, { className, type, size, shape, appearance } = _b, props = __objRest(_b, ["className", "type", "size", "shape", "appearance"]);
30
40
  return /* @__PURE__ */ jsx(
31
41
  "input",
32
42
  __spreadValues({
33
43
  type,
34
44
  "data-slot": "input",
35
- className: cn(inputVariants({ size, shape }), className),
45
+ className: cn(inputVariants({ size, shape, appearance }), className),
36
46
  ref
37
47
  }, props)
38
48
  );
@@ -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';
@@ -4,7 +4,7 @@ import * as React from 'react';
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const badgeVariants: (props?: ({
7
- variant?: "default" | "destructive" | "outline" | "secondary" | "glass" | "overlay" | "brown" | "warning" | "success" | "onPrimary" | null | undefined;
7
+ variant?: "code" | "default" | "destructive" | "outline" | "secondary" | "glass" | "overlay" | "brown" | "warning" | "success" | "onPrimary" | "confirmed" | "pending" | null | undefined;
8
8
  live?: boolean | null | undefined;
9
9
  } & class_variance_authority_types.ClassProp) | undefined) => string;
10
10
  interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
@@ -1,3 +1,3 @@
1
- export { Badge, badgeVariants } from '../chunk-5XREWOBB.js';
1
+ export { Badge, badgeVariants } from '../chunk-IEIJP73R.js';
2
2
  import '../chunk-FEK5XGZW.js';
3
3
  import '../chunk-MMUBH76A.js';
@@ -0,0 +1,36 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as class_variance_authority_types from 'class-variance-authority/types';
3
+ import * as React from 'react';
4
+ import { VariantProps } from 'class-variance-authority';
5
+
6
+ /**
7
+ * Banner — a short inline note inside a flow, not a page-level alert: the
8
+ * booking flow's "19:30 just went" when a time is taken mid-form, "No table
9
+ * was booked" when a confirm fails, "This venue does not take bookings"
10
+ * (booking flow.html, `.bnr`).
11
+ *
12
+ * Not `Alert`: that one is a bordered card for page-level status with a
13
+ * pinned icon column. This is borderless, sits in the flow of a form, and
14
+ * reads as part of the screen — a soft ground, an optional 16px icon, an
15
+ * optional bold title over the body.
16
+ *
17
+ * Measured from the design: 12px radius, 12px × 14px inset, 10px between
18
+ * icon and text; the title at 13px bold, the body at 12.5px (90% in the
19
+ * warning tone), both at 1.5 leading.
20
+ * - `info`: the soft surface and the secondary ink.
21
+ * - `warning`: a 16% amber wash with the design's amber ink — darker than
22
+ * the solid `--warning`, which falls short of AA on its own wash at this
23
+ * size; dark mode uses the lifted token.
24
+ */
25
+ declare const bannerVariants: (props?: ({
26
+ tone?: "warning" | "info" | null | undefined;
27
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
28
+ type BannerProps = Omit<React.HTMLAttributes<HTMLDivElement>, "title"> & VariantProps<typeof bannerVariants> & {
29
+ /** A lucide icon, drawn at 16px beside the text. */
30
+ icon?: React.ReactNode;
31
+ /** The bold first line — "19:30 just went". */
32
+ title?: React.ReactNode;
33
+ };
34
+ declare function Banner({ tone, icon, title, className, children, ...props }: BannerProps): react_jsx_runtime.JSX.Element;
35
+
36
+ export { Banner, type BannerProps, bannerVariants };
@@ -0,0 +1,29 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
3
+ import { cva } from 'class-variance-authority';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var bannerVariants = cva(
7
+ "flex gap-2.5 rounded-xl px-3.5 py-3 text-[12.5px] leading-normal [&>svg]:mt-0.5 [&>svg]:size-4 [&>svg]:shrink-0",
8
+ {
9
+ variants: {
10
+ tone: {
11
+ info: "bg-surface-2 text-ink-secondary",
12
+ warning: "bg-[oklch(0.62_0.15_70/0.16)] text-[oklch(0.42_0.1_70)] dark:bg-warning/15 dark:text-warning"
13
+ }
14
+ },
15
+ defaultVariants: { tone: "info" }
16
+ }
17
+ );
18
+ function Banner(_a) {
19
+ var _b = _a, { tone, icon, title, className, children } = _b, props = __objRest(_b, ["tone", "icon", "title", "className", "children"]);
20
+ return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({ "data-slot": "banner", className: cn(bannerVariants({ tone }), className) }, props), { children: [
21
+ icon,
22
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
23
+ title ? /* @__PURE__ */ jsx("b", { className: "block text-[13px] font-bold", children: title }) : null,
24
+ /* @__PURE__ */ jsx("div", { className: cn(tone === "warning" && title ? "opacity-90" : void 0), children })
25
+ ] })
26
+ ] }));
27
+ }
28
+
29
+ export { Banner, bannerVariants };
@@ -0,0 +1,60 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ /**
5
+ * BookingRow and BookingRowList — the guest's bookings in "My bookings".
6
+ *
7
+ * Measured from the booking design (`.bkrow`, and the desktop list):
8
+ *
9
+ * Mobile (below `md`): rows 14px tall-padded, 12px gap, divided by a
10
+ * `line-soft` hairline. A 50px thumb with an 11px radius. Line one: the venue
11
+ * at 14px bold, the code chip pushed right. Line two: the venue type at 11.5px
12
+ * muted. Line three, 7px gaps: when at 12.5px medium, the party at 12px muted,
13
+ * then the status pill.
14
+ *
15
+ * Desktop (`md` and up): one card (14px radius, no inset), rows 14px × 18px
16
+ * with 14px gaps, divided by the same hairline. A 46px thumb, then the venue
17
+ * (bold) with its type inline and muted over "when · party" in the secondary
18
+ * ink, then the status pill, the code chip and a muted chevron. The row that
19
+ * is next up gets a 5% accent wash.
20
+ *
21
+ * The whole row is one link. Strings arrive formatted and localised; the thumb
22
+ * arrives rendered, so the app picks its own image component.
23
+ */
24
+ type BookingRowStatus = "confirmed" | "pending";
25
+ type BookingRowLinkProps = {
26
+ href: string;
27
+ className?: string;
28
+ children: React.ReactNode;
29
+ };
30
+ type BookingRowProps = {
31
+ venueName: string;
32
+ /** "Bistro", "Cocktail bar" */
33
+ venueType?: string;
34
+ /** "Fri 14 Aug · 19:30" */
35
+ when: string;
36
+ /** "2 people" */
37
+ party: string;
38
+ status: BookingRowStatus;
39
+ /** "Confirmed", "Pending" — already localised. */
40
+ statusLabel: string;
41
+ code: string;
42
+ href: string;
43
+ /** The venue photo, rendered by the app; a quiet placeholder when absent. */
44
+ thumbnail?: React.ReactNode;
45
+ /** The next booking up — tinted on desktop. */
46
+ highlighted?: boolean;
47
+ linkComponent?: React.ComponentType<BookingRowLinkProps>;
48
+ className?: string;
49
+ };
50
+ declare function BookingRow({ venueName, venueType, when, party, status, statusLabel, code, href, thumbnail, highlighted, linkComponent: LinkComponent, className, }: BookingRowProps): react_jsx_runtime.JSX.Element;
51
+ type BookingRowListProps = {
52
+ children: React.ReactNode;
53
+ /** "Upcoming bookings" — names the list for assistive tech. */
54
+ "aria-label"?: string;
55
+ className?: string;
56
+ };
57
+ /** The list around the rows: hairlines between them on mobile, one card on desktop. */
58
+ declare function BookingRowList({ children, "aria-label": ariaLabel, className }: BookingRowListProps): react_jsx_runtime.JSX.Element;
59
+
60
+ export { BookingRow, type BookingRowLinkProps, BookingRowList, type BookingRowListProps, type BookingRowProps, type BookingRowStatus };
@@ -0,0 +1,103 @@
1
+ import { Badge } from '../chunk-IEIJP73R.js';
2
+ import { cn } from '../chunk-FEK5XGZW.js';
3
+ import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
4
+ import * as React from 'react';
5
+ import { ChevronRight } from 'lucide-react';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ function DefaultLink(_a) {
9
+ var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
10
+ return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
11
+ }
12
+ function Thumb({ children, className }) {
13
+ return /* @__PURE__ */ jsx(
14
+ "span",
15
+ {
16
+ "aria-hidden": true,
17
+ className: cn(
18
+ // Dark: `surface-2` sits a notch from the card and vanishes; the
19
+ // accent-tinted step reads as a photo slot.
20
+ "block shrink-0 overflow-hidden rounded-[11px] bg-surface-2 dark:bg-accent-subtle [&_img]:size-full [&_img]:object-cover",
21
+ className
22
+ ),
23
+ children
24
+ }
25
+ );
26
+ }
27
+ function BookingRow({
28
+ venueName,
29
+ venueType,
30
+ when,
31
+ party,
32
+ status,
33
+ statusLabel,
34
+ code,
35
+ href,
36
+ thumbnail,
37
+ highlighted,
38
+ linkComponent: LinkComponent = DefaultLink,
39
+ className
40
+ }) {
41
+ const statusPill = /* @__PURE__ */ jsx(Badge, { as: "span", variant: status, children: statusLabel });
42
+ const codeChip = /* @__PURE__ */ jsx(Badge, { as: "span", variant: "code", children: code });
43
+ return /* @__PURE__ */ jsxs(
44
+ LinkComponent,
45
+ {
46
+ href,
47
+ className: cn(
48
+ "flex gap-3 py-3.5 leading-[1.2] text-foreground",
49
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",
50
+ "md:items-center md:gap-3.5 md:px-[18px] md:hover:bg-accent/[0.03]",
51
+ highlighted && "md:bg-accent/5 md:hover:bg-accent/5",
52
+ className
53
+ ),
54
+ children: [
55
+ /* @__PURE__ */ jsx(Thumb, { className: "size-[50px] md:size-[46px]", children: thumbnail }),
56
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 md:hidden", children: [
57
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
58
+ /* @__PURE__ */ jsx("b", { className: "truncate text-sm font-bold", children: venueName }),
59
+ codeChip
60
+ ] }),
61
+ venueType && /* @__PURE__ */ jsx("div", { className: "text-[11.5px] text-muted-foreground", children: venueType }),
62
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-[7px]", children: [
63
+ /* @__PURE__ */ jsx("span", { className: "text-[12.5px] font-medium", children: when }),
64
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: party }),
65
+ statusPill
66
+ ] })
67
+ ] }),
68
+ /* @__PURE__ */ jsxs("div", { className: "hidden min-w-0 flex-1 md:block", children: [
69
+ /* @__PURE__ */ jsxs("div", { className: "truncate", children: [
70
+ /* @__PURE__ */ jsx("b", { className: "text-sm font-bold", children: venueName }),
71
+ venueType && /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs text-muted-foreground", children: venueType })
72
+ ] }),
73
+ /* @__PURE__ */ jsxs("div", { className: "mt-0.5 truncate text-[12.5px] text-ink-secondary", children: [
74
+ when,
75
+ " \xB7 ",
76
+ party
77
+ ] })
78
+ ] }),
79
+ /* @__PURE__ */ jsxs("span", { className: "hidden md:contents", children: [
80
+ statusPill,
81
+ codeChip,
82
+ /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-[15px] shrink-0 text-muted-foreground" })
83
+ ] })
84
+ ]
85
+ }
86
+ );
87
+ }
88
+ function BookingRowList({ children, "aria-label": ariaLabel, className }) {
89
+ return /* @__PURE__ */ jsx(
90
+ "ul",
91
+ {
92
+ "aria-label": ariaLabel,
93
+ className: cn(
94
+ "divide-y divide-line-soft",
95
+ "md:overflow-hidden md:rounded-[14px] md:border md:border-border md:bg-card",
96
+ className
97
+ ),
98
+ children: React.Children.map(children, (child) => child ? /* @__PURE__ */ jsx("li", { children: child }) : null)
99
+ }
100
+ );
101
+ }
102
+
103
+ export { BookingRow, BookingRowList };
@@ -0,0 +1,38 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * BookingSummaryCard — the booking at a glance on the confirmation screen
5
+ * ("Your table is booked"): the venue, then when, how many, where you asked
6
+ * to sit and the address, then the booking code.
7
+ *
8
+ * Measured from the booking design (`.cardx` + `.rowi`): a card with a 1px
9
+ * hairline, 14px radius, 15px inset and a 1px/3px shadow. The venue at 16px
10
+ * bold. Rows 11px below it, 7px apart: a 14px icon (1.8 stroke, muted) in a
11
+ * 16px column, 10px gap, text at 13px in the secondary ink. Then a
12
+ * `line-soft` divider 13px below with 13px above the code row: "BOOKING CODE"
13
+ * at 10.5px uppercase, muted, and the code in mono at 15px bold, pushed right.
14
+ *
15
+ * Every string arrives formatted and localised; the card only lays them out.
16
+ */
17
+ type BookingSummaryCardLabels = {
18
+ /** "Booking code" */
19
+ code: string;
20
+ };
21
+ type BookingSummaryCardProps = {
22
+ venueName: string;
23
+ /** "Fri 14 August" */
24
+ date: string;
25
+ /** "19:30 · 2 people" */
26
+ timeAndParty: string;
27
+ /** "Terrace (requested)" — omitted when there is no preference. */
28
+ seating?: string;
29
+ /** "Strada Iuliu Maniu 12" */
30
+ address?: string;
31
+ /** "BM-8421" */
32
+ code: string;
33
+ labels: BookingSummaryCardLabels;
34
+ className?: string;
35
+ };
36
+ declare function BookingSummaryCard({ venueName, date, timeAndParty, seating, address, code, labels, className, }: BookingSummaryCardProps): react_jsx_runtime.JSX.Element;
37
+
38
+ export { BookingSummaryCard, type BookingSummaryCardLabels, type BookingSummaryCardProps };