@bearmenu/ui 0.8.15 → 0.8.17

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 (102) hide show
  1. package/README.md +1 -0
  2. package/dist/{chunk-ZLPWEHZO.js → chunk-54FQQZZJ.js} +1 -1
  3. package/dist/{chunk-5FCC5L5F.js → chunk-5LTILG3L.js} +29 -6
  4. package/dist/{chunk-P43B3ONY.js → chunk-5XREWOBB.js} +3 -1
  5. package/dist/{chunk-V4E333QS.js → chunk-5YNIQ2BL.js} +7 -29
  6. package/dist/{chunk-CLLY6XB3.js → chunk-6VOWT4YR.js} +6 -3
  7. package/dist/{chunk-S33K4RC5.js → chunk-BKKQ7GCZ.js} +1 -1
  8. package/dist/chunk-QY66ME5B.js +207 -0
  9. package/dist/chunk-RIH2IS7X.js +29 -0
  10. package/dist/{chunk-T6S2ZBV6.js → chunk-SDWN6L4O.js} +1 -1
  11. package/dist/{chunk-CNJQUHCU.js → chunk-SWD6CJ35.js} +2 -1
  12. package/dist/{chunk-HDR7V6IZ.js → chunk-TIQNM4XD.js} +8 -1
  13. package/dist/components/alert-dialog.js +3 -2
  14. package/dist/components/badge.d.ts +1 -1
  15. package/dist/components/badge.js +1 -1
  16. package/dist/components/button.d.ts +5 -1
  17. package/dist/components/button.js +3 -2
  18. package/dist/components/calendar.js +3 -2
  19. package/dist/components/carousel.js +3 -2
  20. package/dist/components/coach-marks.d.ts +63 -0
  21. package/dist/components/coach-marks.js +162 -0
  22. package/dist/components/combobox.js +3 -2
  23. package/dist/components/concept-compare-rail.js +2 -2
  24. package/dist/components/concept-compare.js +2 -2
  25. package/dist/components/concept-convergence.js +2 -2
  26. package/dist/components/date-input.d.ts +1 -1
  27. package/dist/components/doorway-tiles.d.ts +11 -0
  28. package/dist/components/doorway-tiles.js +5 -3
  29. package/dist/components/empty-state.js +3 -2
  30. package/dist/components/event-detail-panel.js +4 -3
  31. package/dist/components/event-index-row.js +1 -1
  32. package/dist/components/event-list-row-wide.js +4 -3
  33. package/dist/components/event-list-row.js +1 -1
  34. package/dist/components/facet-group.d.ts +8 -1
  35. package/dist/components/facet-group.js +3 -0
  36. package/dist/components/filter-category-row.js +1 -1
  37. package/dist/components/haptic-switch.d.ts +35 -0
  38. package/dist/components/haptic-switch.js +3 -0
  39. package/dist/components/hue-chip.js +1 -1
  40. package/dist/components/item.js +4 -1
  41. package/dist/components/kitchen-dossier.js +2 -2
  42. package/dist/components/link-button.js +3 -2
  43. package/dist/components/menu-family-block.d.ts +8 -1
  44. package/dist/components/menu-family-block.js +103 -69
  45. package/dist/components/menu-family-card.js +2 -2
  46. package/dist/components/menu-filter-chips.d.ts +12 -3
  47. package/dist/components/menu-filter-chips.js +22 -4
  48. package/dist/components/menu-index-list.js +3 -2
  49. package/dist/components/menu-item.js +3 -3
  50. package/dist/components/menu-kitchen-list.d.ts +14 -2
  51. package/dist/components/menu-kitchen-list.js +1 -1
  52. package/dist/components/multi-select-combobox.js +4 -3
  53. package/dist/components/pagination.js +3 -2
  54. package/dist/components/photo-ground.d.ts +7 -1
  55. package/dist/components/photo-ground.js +1 -1
  56. package/dist/components/place-card.js +2 -2
  57. package/dist/components/place-details-mobile.js +1 -1
  58. package/dist/components/searchable-select.js +3 -2
  59. package/dist/components/section-header.d.ts +7 -1
  60. package/dist/components/section-header.js +11 -7
  61. package/dist/components/signature-chip.js +2 -2
  62. package/dist/components/sliding-panels.js +3 -2
  63. package/dist/components/switch.d.ts +7 -1
  64. package/dist/components/switch.js +33 -24
  65. package/dist/components/toggle-group.js +9 -4
  66. package/dist/components/toggle.d.ts +1 -1
  67. package/dist/components/toggle.js +1 -1
  68. package/dist/components/top-ranking-entry.js +3 -3
  69. package/dist/hooks/use-haptic.d.ts +9 -1
  70. package/dist/hooks/use-haptic.js +1 -1
  71. package/package.json +1 -1
  72. package/src/components/badge.stories.tsx +31 -1
  73. package/src/components/badge.tsx +2 -0
  74. package/src/components/button.stories.tsx +5 -4
  75. package/src/components/button.test.tsx +11 -1
  76. package/src/components/button.tsx +41 -6
  77. package/src/components/coach-marks.stories.tsx +79 -0
  78. package/src/components/coach-marks.test.tsx +140 -0
  79. package/src/components/coach-marks.tsx +252 -0
  80. package/src/components/doorway-tiles.stories.tsx +34 -0
  81. package/src/components/doorway-tiles.test.tsx +27 -0
  82. package/src/components/doorway-tiles.tsx +30 -2
  83. package/src/components/facet-group.tsx +9 -0
  84. package/src/components/haptic-switch.test.tsx +134 -0
  85. package/src/components/haptic-switch.tsx +62 -0
  86. package/src/components/hue-chip.test.tsx +6 -3
  87. package/src/components/hue-chip.tsx +5 -2
  88. package/src/components/item.tsx +4 -1
  89. package/src/components/menu-family-block.stories.tsx +12 -0
  90. package/src/components/menu-family-block.tsx +53 -20
  91. package/src/components/menu-filter-chips.tsx +32 -4
  92. package/src/components/menu-kitchen-list.tsx +45 -6
  93. package/src/components/photo-ground.tsx +7 -0
  94. package/src/components/section-header.test.tsx +15 -0
  95. package/src/components/section-header.tsx +26 -12
  96. package/src/components/switch.tsx +29 -18
  97. package/src/components/toggle-group.stories.tsx +37 -1
  98. package/src/components/toggle-group.tsx +11 -6
  99. package/src/components/toggle.tsx +8 -0
  100. package/src/hooks/use-haptic.test.tsx +54 -59
  101. package/src/hooks/use-haptic.ts +18 -44
  102. package/dist/chunk-SXQZ7DLH.js +0 -167
@@ -0,0 +1,162 @@
1
+ import { Button } from '../chunk-5LTILG3L.js';
2
+ import '../chunk-RIH2IS7X.js';
3
+ import '../chunk-5YNIQ2BL.js';
4
+ import { cn } from '../chunk-FEK5XGZW.js';
5
+ import '../chunk-MMUBH76A.js';
6
+ import { useState, useLayoutEffect, useCallback, useEffect } from 'react';
7
+ import { createPortal } from 'react-dom';
8
+ import { Lightbulb, ArrowRight } from 'lucide-react';
9
+ import { jsxs, jsx } from 'react/jsx-runtime';
10
+
11
+ var PAD = 8;
12
+ var CALLOUT_WIDTH = 320;
13
+ var CALLOUT_GAP = 14;
14
+ var CALLOUT_ROOM = 280;
15
+ var EDGE = 12;
16
+ var PIN = "pointer-events-none absolute z-[1] flex h-8 w-8 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-[oklch(0.26_0.03_60)] text-[13px] font-extrabold text-[oklch(0.82_0.15_85)] ring-2 ring-[oklch(0.82_0.15_85)] shadow-[0_2px_8px_oklch(0.16_0.012_55_/_0.45)] transition-[top,left] duration-300 motion-reduce:transition-none";
17
+ function findTarget(id) {
18
+ if (typeof document === "undefined") return null;
19
+ const candidates = document.querySelectorAll(`[data-coach-mark="${id}"]`);
20
+ for (const candidate of candidates) {
21
+ if (candidate.getClientRects().length > 0) return candidate;
22
+ }
23
+ return null;
24
+ }
25
+ function measure(element) {
26
+ const box = element.getBoundingClientRect();
27
+ return { top: box.top, left: box.left, width: box.width, height: box.height };
28
+ }
29
+ function CoachMarks({ open, stops, onClose, onProgress, labels, className }) {
30
+ const [available, setAvailable] = useState([]);
31
+ const [index, setIndex] = useState(0);
32
+ const [rect, setRect] = useState(null);
33
+ const [viewport, setViewport] = useState({ width: 0, height: 0 });
34
+ const itinerary = stops.map((stop) => stop.id).join("|");
35
+ useLayoutEffect(() => {
36
+ if (!open) return;
37
+ const present = stops.filter((stop) => findTarget(stop.id));
38
+ setAvailable(present);
39
+ setIndex(0);
40
+ if (present.length === 0) onClose();
41
+ }, [open, itinerary]);
42
+ const current = available[index];
43
+ const currentId = current == null ? void 0 : current.id;
44
+ const remeasure = useCallback(() => {
45
+ const element = currentId ? findTarget(currentId) : null;
46
+ setRect(element ? measure(element) : null);
47
+ setViewport({ width: window.innerWidth, height: window.innerHeight });
48
+ }, [currentId]);
49
+ useLayoutEffect(() => {
50
+ if (!open || !current) return;
51
+ const element = findTarget(current.id);
52
+ if (!element) {
53
+ const forward = available.findIndex((stop, at) => at > index && findTarget(stop.id));
54
+ if (forward !== -1) setIndex(forward);
55
+ else onClose();
56
+ return;
57
+ }
58
+ element.scrollIntoView({ block: "center", behavior: "smooth", inline: "nearest" });
59
+ remeasure();
60
+ const settle = setTimeout(remeasure, 400);
61
+ return () => clearTimeout(settle);
62
+ }, [open, current, index, available, remeasure, onClose]);
63
+ useEffect(() => {
64
+ if (!open || !current) return;
65
+ onProgress == null ? void 0 : onProgress(index + 1, available.length, current);
66
+ }, [open, current, index, available.length, onProgress]);
67
+ useEffect(() => {
68
+ if (!open) return;
69
+ window.addEventListener("resize", remeasure);
70
+ window.addEventListener("scroll", remeasure, true);
71
+ const onKey = (event) => {
72
+ if (event.key === "Escape") onClose();
73
+ if (event.key === "ArrowRight") setIndex((at) => Math.min(at + 1, available.length - 1));
74
+ if (event.key === "ArrowLeft") setIndex((at) => Math.max(at - 1, 0));
75
+ };
76
+ window.addEventListener("keydown", onKey);
77
+ return () => {
78
+ window.removeEventListener("resize", remeasure);
79
+ window.removeEventListener("scroll", remeasure, true);
80
+ window.removeEventListener("keydown", onKey);
81
+ };
82
+ }, [open, remeasure, onClose, available.length]);
83
+ if (!open || !current || !rect) return null;
84
+ const last = index === available.length - 1;
85
+ const spot = {
86
+ top: rect.top - PAD,
87
+ left: rect.left - PAD,
88
+ width: rect.width + PAD * 2,
89
+ height: rect.height + PAD * 2
90
+ };
91
+ const roomBelow = viewport.height - (spot.top + spot.height);
92
+ const calloutLeft = Math.min(
93
+ Math.max(spot.left, EDGE),
94
+ Math.max(EDGE, viewport.width - CALLOUT_WIDTH - EDGE)
95
+ );
96
+ const calloutPlace = roomBelow > CALLOUT_ROOM ? { top: spot.top + spot.height + CALLOUT_GAP, left: calloutLeft } : spot.top > CALLOUT_ROOM ? { bottom: viewport.height - spot.top + CALLOUT_GAP, left: calloutLeft } : { bottom: EDGE, left: calloutLeft };
97
+ return createPortal(
98
+ /* @__PURE__ */ jsxs(
99
+ "div",
100
+ {
101
+ className: cn("fixed inset-0 z-[80]", className),
102
+ role: "dialog",
103
+ "aria-modal": true,
104
+ "aria-label": current.title,
105
+ children: [
106
+ /* @__PURE__ */ jsx(
107
+ "button",
108
+ {
109
+ type: "button",
110
+ "aria-label": labels.skip,
111
+ onClick: onClose,
112
+ className: "absolute inset-0 cursor-default"
113
+ }
114
+ ),
115
+ /* @__PURE__ */ jsx(
116
+ "div",
117
+ {
118
+ "aria-hidden": true,
119
+ className: "pointer-events-none absolute rounded-[18px] shadow-[0_0_0_9999px_oklch(0.16_0.012_55_/_0.55)] ring-2 ring-[oklch(0.82_0.15_85)] transition-[top,left,width,height] duration-300 motion-reduce:transition-none",
120
+ style: spot
121
+ }
122
+ ),
123
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: PIN, style: { top: rect.top - 2, left: rect.left - 2 }, children: index + 1 }),
124
+ /* @__PURE__ */ jsxs(
125
+ "div",
126
+ {
127
+ className: "absolute z-[2] w-[min(320px,calc(100vw-24px))] rounded-2xl border border-border bg-card p-4 text-card-foreground shadow-xl",
128
+ style: calloutPlace,
129
+ children: [
130
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-full bg-[oklch(0.82_0.15_85)] px-2.5 py-1 text-[10.5px] font-extrabold uppercase tracking-[0.08em] text-[oklch(0.26_0.03_60)]", children: [
131
+ /* @__PURE__ */ jsx(Lightbulb, { className: "h-3 w-3", "aria-hidden": true }),
132
+ labels.progress(index + 1, available.length)
133
+ ] }),
134
+ /* @__PURE__ */ jsx("p", { className: "mt-3 text-[15px] font-bold leading-snug", children: current.title }),
135
+ /* @__PURE__ */ jsx("p", { className: "mt-1.5 text-sm leading-relaxed text-muted-foreground", children: current.body }),
136
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center gap-2", children: [
137
+ index > 0 && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setIndex(index - 1), children: labels.back }),
138
+ /* @__PURE__ */ jsxs(
139
+ Button,
140
+ {
141
+ type: "button",
142
+ size: "sm",
143
+ onClick: () => last ? onClose() : setIndex(index + 1),
144
+ children: [
145
+ last ? labels.done : labels.next,
146
+ !last && /* @__PURE__ */ jsx(ArrowRight, { "aria-hidden": true })
147
+ ]
148
+ }
149
+ ),
150
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "link", size: "sm", className: "ml-auto", onClick: onClose, children: labels.skip })
151
+ ] })
152
+ ]
153
+ }
154
+ )
155
+ ]
156
+ }
157
+ ),
158
+ document.body
159
+ );
160
+ }
161
+
162
+ export { CoachMarks };
@@ -1,8 +1,9 @@
1
1
  import { Popover, PopoverTrigger, PopoverContent } from '../chunk-2ADCZXZJ.js';
2
2
  import { Command, CommandInput, CommandList, CommandLoading, CommandEmpty, CommandGroup, CommandItem } from '../chunk-MCOHLWRS.js';
3
3
  import '../chunk-PDTPO6NG.js';
4
- import { Button } from '../chunk-5FCC5L5F.js';
5
- import '../chunk-V4E333QS.js';
4
+ import { Button } from '../chunk-5LTILG3L.js';
5
+ import '../chunk-RIH2IS7X.js';
6
+ import '../chunk-5YNIQ2BL.js';
6
7
  import { cn } from '../chunk-FEK5XGZW.js';
7
8
  import '../chunk-MMUBH76A.js';
8
9
  import * as React from 'react';
@@ -1,5 +1,5 @@
1
- export { ConceptCompareRail } from '../chunk-ZLPWEHZO.js';
1
+ export { ConceptCompareRail } from '../chunk-54FQQZZJ.js';
2
2
  import '../chunk-WYTJR2YU.js';
3
- import '../chunk-CNJQUHCU.js';
3
+ import '../chunk-SWD6CJ35.js';
4
4
  import '../chunk-FEK5XGZW.js';
5
5
  import '../chunk-MMUBH76A.js';
@@ -1,7 +1,7 @@
1
1
  import { Separator } from '../chunk-NWZGSLPU.js';
2
- import { ConceptCompareRail } from '../chunk-ZLPWEHZO.js';
2
+ import { ConceptCompareRail } from '../chunk-54FQQZZJ.js';
3
3
  import '../chunk-WYTJR2YU.js';
4
- import { PhotoGround, PHOTO_GROUND } from '../chunk-CNJQUHCU.js';
4
+ import { PhotoGround, PHOTO_GROUND } from '../chunk-SWD6CJ35.js';
5
5
  import { Skeleton } from '../chunk-XBBEX4SF.js';
6
6
  import { cn } from '../chunk-FEK5XGZW.js';
7
7
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
@@ -1,7 +1,7 @@
1
- import { PhotoGround } from '../chunk-CNJQUHCU.js';
1
+ import { PhotoGround } from '../chunk-SWD6CJ35.js';
2
2
  import { Convergence } from '../chunk-4XDJXMLF.js';
3
3
  import '../chunk-OIV7B44M.js';
4
- import { Badge } from '../chunk-P43B3ONY.js';
4
+ import { Badge } from '../chunk-5XREWOBB.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,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
 
3
- declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "type"> & {
3
+ declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> & {
4
4
  /** Native input type. Defaults to "date". */
5
5
  type?: "date" | "datetime-local" | "time" | "month" | "week";
6
6
  size?: "sm" | "default" | "lg";
@@ -33,6 +33,17 @@ type DoorwayTile = {
33
33
  gradient?: string;
34
34
  /** Pre-resolved photograph of the CLASS, from the consumer's own origin. */
35
35
  photoUrl?: string;
36
+ /**
37
+ * A glyph in the photograph's place — for a tile about an ACTION, not a
38
+ * thing. A search door has no class to photograph, and any subject put on
39
+ * it (a table, a lens, a book) reads as one more family; the initial the
40
+ * fallback draws is a family's initial too. So the print holds the glyph
41
+ * instead, on the photo ground with the photo fallback's drop shadow, and
42
+ * the tile keeps its siblings' silhouette. Wins over `photoUrl`.
43
+ *
44
+ * A node rather than a name: the app owns its iconography.
45
+ */
46
+ icon?: React.ReactNode;
36
47
  };
37
48
  type DoorwayTilesTreatment = "polaroid" | "ground";
38
49
  type DoorwayTilesProps = {
@@ -1,4 +1,4 @@
1
- import { PhotoGround } from '../chunk-CNJQUHCU.js';
1
+ import { PHOTO_GROUND, PHOTO_GLYPH_SHADOW, PhotoGround } from '../chunk-SWD6CJ35.js';
2
2
  import { cn } from '../chunk-FEK5XGZW.js';
3
3
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -13,6 +13,8 @@ var SCRIM = "after:pointer-events-none after:absolute after:inset-x-0 after:bott
13
13
  var GROUND_PHOTO = "absolute inset-0 z-0 h-full w-full object-cover mix-blend-multiply transition-transform duration-500 ease-out group-hover:scale-[1.04] motion-reduce:transition-none motion-reduce:group-hover:scale-100";
14
14
  var GROUND_LIFT = "absolute inset-0 z-0 opacity-[0.22]";
15
15
  var GROUND_GLYPH = "absolute inset-0 z-0 flex items-center justify-center font-serif text-[64px] font-semibold leading-none text-white/15";
16
+ var PRINT_ICON = `absolute inset-0 flex items-center justify-center ${PHOTO_GROUND} text-white/90 [&_svg]:h-[44%] [&_svg]:w-[44%] [&_svg]:${PHOTO_GLYPH_SHADOW}`;
17
+ var GROUND_ICON = "absolute inset-0 z-0 flex items-center justify-center text-white/15 [&_svg]:h-[40%] [&_svg]:w-[40%]";
16
18
  function DoorwayTiles({
17
19
  tiles,
18
20
  all,
@@ -31,7 +33,7 @@ function DoorwayTiles({
31
33
  className: cn(TILE, SCRIM),
32
34
  style: ground,
33
35
  children: [
34
- isPolaroid ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: POLAROID, children: tile.photoUrl ? (
36
+ isPolaroid ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: POLAROID, children: tile.icon ? /* @__PURE__ */ jsx("span", { className: PRINT_ICON, children: tile.icon }) : tile.photoUrl ? (
35
37
  /* Not lazy: the grid sits directly under the hero, and these
36
38
  photographs are the first thing the reader looks at. */
37
39
  // eslint-disable-next-line @next/next/no-img-element
@@ -52,7 +54,7 @@ function DoorwayTiles({
52
54
  mode: "stack",
53
55
  glyphClassName: "text-[44px]"
54
56
  }
55
- ) }) : tile.photoUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
57
+ ) }) : tile.icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: GROUND_ICON, children: tile.icon }) : tile.photoUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
56
58
  /* @__PURE__ */ jsx("img", { src: tile.photoUrl, alt: "", decoding: "async", className: GROUND_PHOTO }),
57
59
  /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: GROUND_LIFT, style: ground })
58
60
  ] }) : /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: GROUND_GLYPH, children: tile.label.charAt(0) }),
@@ -1,5 +1,6 @@
1
- import { Button } from '../chunk-5FCC5L5F.js';
2
- import '../chunk-V4E333QS.js';
1
+ import { Button } from '../chunk-5LTILG3L.js';
2
+ import '../chunk-RIH2IS7X.js';
3
+ import '../chunk-5YNIQ2BL.js';
3
4
  import { Text } from '../chunk-ZLMRVBD7.js';
4
5
  import { cn } from '../chunk-FEK5XGZW.js';
5
6
  import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
@@ -1,9 +1,10 @@
1
1
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
2
- import { Separator } from '../chunk-NWZGSLPU.js';
3
2
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
3
+ import { Separator } from '../chunk-NWZGSLPU.js';
4
4
  import { Skeleton } from '../chunk-XBBEX4SF.js';
5
- import { Button } from '../chunk-5FCC5L5F.js';
6
- import '../chunk-V4E333QS.js';
5
+ import { Button } from '../chunk-5LTILG3L.js';
6
+ import '../chunk-RIH2IS7X.js';
7
+ import '../chunk-5YNIQ2BL.js';
7
8
  import { cn } from '../chunk-FEK5XGZW.js';
8
9
  import { __spreadProps, __spreadValues, __objRest } from '../chunk-MMUBH76A.js';
9
10
  import * as React from 'react';
@@ -1,7 +1,7 @@
1
1
  import { TagGroup } from '../chunk-PX6RICS5.js';
2
2
  import { Tag } from '../chunk-MWB7S54O.js';
3
- import { Separator } from '../chunk-NWZGSLPU.js';
4
3
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
4
+ import { Separator } from '../chunk-NWZGSLPU.js';
5
5
  import { cn } from '../chunk-FEK5XGZW.js';
6
6
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
7
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -1,10 +1,11 @@
1
1
  import { Tag } from '../chunk-MWB7S54O.js';
2
2
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
3
- import { Separator } from '../chunk-NWZGSLPU.js';
4
3
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
4
+ import { Separator } from '../chunk-NWZGSLPU.js';
5
5
  import { Skeleton } from '../chunk-XBBEX4SF.js';
6
- import { buttonVariants } from '../chunk-5FCC5L5F.js';
7
- import '../chunk-V4E333QS.js';
6
+ import { buttonVariants } from '../chunk-5LTILG3L.js';
7
+ import '../chunk-RIH2IS7X.js';
8
+ import '../chunk-5YNIQ2BL.js';
8
9
  import { cn } from '../chunk-FEK5XGZW.js';
9
10
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
10
11
  import { memo, useState } from 'react';
@@ -1,8 +1,8 @@
1
1
  import { TagGroup } from '../chunk-PX6RICS5.js';
2
2
  import { Tag } from '../chunk-MWB7S54O.js';
3
3
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
4
- import { Separator } from '../chunk-NWZGSLPU.js';
5
4
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
5
+ import { Separator } from '../chunk-NWZGSLPU.js';
6
6
  import { Skeleton } from '../chunk-XBBEX4SF.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
8
8
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
@@ -75,9 +75,16 @@ type FacetGroupProps = Omit<ComponentPropsWithoutRef<"fieldset">, "title" | "chi
75
75
  /** e.g. "Show all". Omit to hide the trailing action. */
76
76
  moreLabel?: string;
77
77
  onMore?: () => void;
78
+ /**
79
+ * Whether the trailing action has already expanded the options it controls
80
+ * — set it when `onMore` reveals more rows in place (and `moreLabel` reads
81
+ * "Show fewer"), so the button carries `aria-expanded`. Leave it unset when
82
+ * the action opens another surface.
83
+ */
84
+ moreExpanded?: boolean;
78
85
  className?: string;
79
86
  };
80
- declare function FacetGroup({ title, icon: Icon, options, selection, name, size, collapsible, defaultOpen, onToggle, moreLabel, onMore, className, ...rest }: FacetGroupProps): react_jsx_runtime.JSX.Element;
87
+ declare function FacetGroup({ title, icon: Icon, options, selection, name, size, collapsible, defaultOpen, onToggle, moreLabel, onMore, moreExpanded, className, ...rest }: FacetGroupProps): react_jsx_runtime.JSX.Element;
81
88
  type FacetGroupSkeletonProps = {
82
89
  /** How many option rows to draw — match the expected/last-known option count. */
83
90
  optionCount?: number;
@@ -26,6 +26,7 @@ function FacetGroup(_a) {
26
26
  onToggle,
27
27
  moreLabel,
28
28
  onMore,
29
+ moreExpanded,
29
30
  className
30
31
  } = _b, rest = __objRest(_b, [
31
32
  "title",
@@ -39,6 +40,7 @@ function FacetGroup(_a) {
39
40
  "onToggle",
40
41
  "moreLabel",
41
42
  "onMore",
43
+ "moreExpanded",
42
44
  "className"
43
45
  ]);
44
46
  const isSingle = selection === "single";
@@ -191,6 +193,7 @@ function FacetGroup(_a) {
191
193
  {
192
194
  type: "button",
193
195
  onClick: onMore,
196
+ "aria-expanded": moreExpanded,
194
197
  className: "cursor-pointer pt-[11px] text-[12.5px] font-bold text-primary transition-colors duration-150 hover:text-primary/80 motion-reduce:transition-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-sm",
195
198
  children: moreLabel
196
199
  }
@@ -1,5 +1,5 @@
1
1
  import { Text } from '../chunk-ZLMRVBD7.js';
2
- import { Badge } from '../chunk-P43B3ONY.js';
2
+ import { Badge } from '../chunk-5XREWOBB.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
4
  import '../chunk-MMUBH76A.js';
5
5
  import { ChevronRight } from 'lucide-react';
@@ -0,0 +1,35 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ declare const HAPTIC_SWITCH_SLOT = "haptic-switch";
4
+ /** True when a click's target is the overlay switch rather than the host. */
5
+ declare function isHapticSwitchTarget(target: EventTarget | null): boolean;
6
+ type HapticSwitchProps = {
7
+ /** Mirror the host's disabled state; a disabled switch neither flips nor ticks. */
8
+ disabled?: boolean;
9
+ };
10
+ /**
11
+ * The only haptic iOS Safari has left.
12
+ *
13
+ * WebKit plays the system toggle haptic when an `<input type="checkbox" switch>`
14
+ * flips under the user's finger, and since iOS 26.5 under the finger is the
15
+ * only way — a programmatic click on the input or its label no longer counts
16
+ * (WebKit #65327). So the switch goes INSIDE the control, stretched over it and
17
+ * invisible, and the tap that lands on the control lands on the switch first.
18
+ * The click then bubbles to the host's own handler as usual.
19
+ *
20
+ * What the host must do:
21
+ * - be positioned (`relative` at least) so `inset-0` fills it;
22
+ * - not call `preventDefault()` on the click — that cancels the toggle, and
23
+ * the toggle is the haptic;
24
+ * - if it is `type="submit"`, submit explicitly: the click target is the
25
+ * switch, so the button's implicit submission never runs. `Button` does
26
+ * this through `form.requestSubmit()`.
27
+ *
28
+ * Renders nothing on the server and on non-iOS clients (so the first client
29
+ * render matches SSR). Keyboard and assistive-tech activation land on the host,
30
+ * not the switch, and stay silent. `opacity: 0`, never `display: none` — a
31
+ * switch that is not rendered does not tick.
32
+ */
33
+ declare function HapticSwitch({ disabled }: HapticSwitchProps): react_jsx_runtime.JSX.Element | null;
34
+
35
+ export { HAPTIC_SWITCH_SLOT, HapticSwitch, isHapticSwitchTarget };
@@ -0,0 +1,3 @@
1
+ export { HAPTIC_SWITCH_SLOT, HapticSwitch, isHapticSwitchTarget } from '../chunk-RIH2IS7X.js';
2
+ import '../chunk-5YNIQ2BL.js';
3
+ import '../chunk-MMUBH76A.js';
@@ -1,3 +1,3 @@
1
- export { HueChip, hueTint } from '../chunk-CLLY6XB3.js';
1
+ export { HueChip, hueTint } from '../chunk-6VOWT4YR.js';
2
2
  import '../chunk-FEK5XGZW.js';
3
3
  import '../chunk-MMUBH76A.js';
@@ -20,7 +20,10 @@ var itemVariants = cva(
20
20
  lg: "px-5 py-4"
21
21
  },
22
22
  interactive: {
23
- true: "cursor-pointer hover:bg-accent hover:text-accent-foreground active:scale-[0.99]",
23
+ // The surface tint a hover is, not the brand fill: `bg-accent` here is
24
+ // the brown, and a row that inverts under the cursor loses its muted
25
+ // description. Same step the buttons take (`--accent-subtle`).
26
+ true: "cursor-pointer hover:bg-accent-subtle hover:border-accent/40 active:bg-muted active:scale-[0.99]",
24
27
  false: ""
25
28
  }
26
29
  },
@@ -1,9 +1,9 @@
1
- import { VenueQuotes } from '../chunk-43RC7MHY.js';
2
1
  import { DIMENSION_ORDER, VenueGradeDimensions } from '../chunk-ZQ53AGML.js';
2
+ import { VenueQuotes } from '../chunk-43RC7MHY.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';
6
- import { PhotoGround, PHOTO_GROUND } from '../chunk-CNJQUHCU.js';
6
+ import { PhotoGround, PHOTO_GROUND } from '../chunk-SWD6CJ35.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
8
8
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
9
9
  import { MessageSquareQuote, Star } from 'lucide-react';
@@ -1,5 +1,6 @@
1
- import { Button } from '../chunk-5FCC5L5F.js';
2
- import '../chunk-V4E333QS.js';
1
+ import { Button } from '../chunk-5LTILG3L.js';
2
+ import '../chunk-RIH2IS7X.js';
3
+ import '../chunk-5YNIQ2BL.js';
3
4
  import '../chunk-FEK5XGZW.js';
4
5
  import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
5
6
  import * as React from 'react';
@@ -85,10 +85,17 @@ type MenuFamilyBlockProps = {
85
85
  hue?: string;
86
86
  /** Finished CSS gradient — the family's colour over the mosaic. */
87
87
  gradient?: string;
88
+ /**
89
+ * `wide` (default): the phone card below `lg`, the two-column card — photo
90
+ * third, rows beside it — from `lg`. `compact`: the phone card at every
91
+ * width, for a rail on a desktop page where the two-column card is too much
92
+ * to scan across (the browse page's concept rail).
93
+ */
94
+ variant?: "wide" | "compact";
88
95
  linkComponent?: MenuLinkComponent;
89
96
  className?: string;
90
97
  };
91
- declare function MenuFamilyBlock({ family, labels, formatCount, hue, gradient, linkComponent: LinkComponent, className, }: MenuFamilyBlockProps): react_jsx_runtime.JSX.Element;
98
+ declare function MenuFamilyBlock({ family, labels, formatCount, hue, gradient, variant, linkComponent: LinkComponent, className, }: MenuFamilyBlockProps): react_jsx_runtime.JSX.Element;
92
99
  /**
93
100
  * The block's own loading state, at the block's footprint.
94
101
  *