@bearmenu/ui 0.8.9 → 0.8.11

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 (225) hide show
  1. package/dist/chunk-24RFI4RQ.js +167 -0
  2. package/dist/{chunk-UKBNQO6Q.js → chunk-2CXU5WZO.js} +1 -1
  3. package/dist/chunk-2XCZJWTV.js +121 -0
  4. package/dist/{chunk-62ES6N32.js → chunk-43RC7MHY.js} +1 -1
  5. package/dist/chunk-5RWTOT5Y.js +72 -0
  6. package/dist/{chunk-Q6QH52LJ.js → chunk-6TEEY5YA.js} +2 -2
  7. package/dist/{chunk-AXV5O2IZ.js → chunk-AKQ57NXY.js} +3 -3
  8. package/dist/chunk-CLLY6XB3.js +41 -0
  9. package/dist/chunk-DTXNDLSE.js +125 -0
  10. package/dist/chunk-F6FMZJDG.js +113 -0
  11. package/dist/{chunk-2WDJR6K7.js → chunk-G7IFL4Z4.js} +4 -1
  12. package/dist/chunk-H3ZZDX5L.js +61 -0
  13. package/dist/{chunk-H3BV4VAG.js → chunk-JS3EINZD.js} +2 -2
  14. package/dist/chunk-MZL7CGCL.js +109 -0
  15. package/dist/{chunk-TH6W2PWG.js → chunk-UDTG3RSE.js} +1 -1
  16. package/dist/chunk-WCTHZKU7.js +37 -0
  17. package/dist/{chunk-TT3WFS6S.js → chunk-YOKHBAIH.js} +11 -11
  18. package/dist/components/alert-dialog.js +1 -1
  19. package/dist/components/alert.d.ts +2 -2
  20. package/dist/components/avatar.d.ts +3 -3
  21. package/dist/components/badge.d.ts +1 -1
  22. package/dist/components/badge.js +1 -1
  23. package/dist/components/button.d.ts +2 -2
  24. package/dist/components/button.js +1 -1
  25. package/dist/components/calendar.js +1 -1
  26. package/dist/components/card.d.ts +4 -4
  27. package/dist/components/carousel.js +1 -1
  28. package/dist/components/combobox.js +1 -1
  29. package/dist/components/command.d.ts +2 -2
  30. package/dist/components/concept-compare-rail.d.ts +50 -0
  31. package/dist/components/concept-compare-rail.js +5 -0
  32. package/dist/components/concept-compare.d.ts +75 -38
  33. package/dist/components/concept-compare.js +209 -133
  34. package/dist/components/concept-convergence.d.ts +41 -0
  35. package/dist/components/concept-convergence.js +53 -0
  36. package/dist/components/convergence.d.ts +25 -0
  37. package/dist/components/convergence.js +4 -0
  38. package/dist/components/dialog.d.ts +2 -2
  39. package/dist/components/empty-state.js +1 -1
  40. package/dist/components/event-card.js +1 -1
  41. package/dist/components/event-compact-row.js +1 -1
  42. package/dist/components/event-detail-panel.js +2 -2
  43. package/dist/components/event-index-row.js +1 -1
  44. package/dist/components/event-list-row-wide.js +2 -2
  45. package/dist/components/event-list-row.js +2 -2
  46. package/dist/components/explainer-steps.d.ts +34 -0
  47. package/dist/components/explainer-steps.js +36 -0
  48. package/dist/components/filter-category-row.js +1 -1
  49. package/dist/components/glass-ground.d.ts +61 -0
  50. package/dist/components/glass-ground.js +3 -0
  51. package/dist/components/haptic-button.js +1 -1
  52. package/dist/components/hub-surface.js +11 -1
  53. package/dist/components/hue-chip.d.ts +70 -0
  54. package/dist/components/hue-chip.js +3 -0
  55. package/dist/components/input-group.d.ts +2 -2
  56. package/dist/components/input.d.ts +1 -1
  57. package/dist/components/item.d.ts +4 -4
  58. package/dist/components/kbd.d.ts +2 -2
  59. package/dist/components/kitchen-dossier.d.ts +88 -0
  60. package/dist/components/kitchen-dossier.js +186 -0
  61. package/dist/components/link-button.js +1 -1
  62. package/dist/components/menu-dead-end.d.ts +56 -0
  63. package/dist/components/menu-dead-end.js +49 -0
  64. package/dist/components/menu-family-block.d.ts +98 -0
  65. package/dist/components/menu-family-block.js +153 -0
  66. package/dist/components/menu-family-card.d.ts +33 -27
  67. package/dist/components/menu-family-card.js +41 -85
  68. package/dist/components/menu-field.js +92 -2
  69. package/dist/components/menu-filter-chips.d.ts +86 -0
  70. package/dist/components/menu-filter-chips.js +122 -0
  71. package/dist/components/menu-group-rows.d.ts +53 -0
  72. package/dist/components/menu-group-rows.js +67 -0
  73. package/dist/components/menu-hub-hero.js +10 -5
  74. package/dist/components/menu-index-header.d.ts +37 -0
  75. package/dist/components/menu-index-header.js +68 -0
  76. package/dist/components/menu-index-list.d.ts +48 -0
  77. package/dist/components/menu-index-list.js +96 -0
  78. package/dist/components/menu-intent-hero.d.ts +69 -0
  79. package/dist/components/menu-intent-hero.js +87 -0
  80. package/dist/components/menu-item.js +3 -3
  81. package/dist/components/menu-kitchen-list.d.ts +82 -0
  82. package/dist/components/menu-kitchen-list.js +5 -0
  83. package/dist/components/menu-mocks.d.ts +37 -2
  84. package/dist/components/menu-mocks.js +152 -27
  85. package/dist/components/menu-types.d.ts +182 -6
  86. package/dist/components/motion-icon-controls.js +2 -2
  87. package/dist/components/motion-icon-set.js +6 -6
  88. package/dist/components/motion-icon.d.ts +22 -1
  89. package/dist/components/motion-icon.js +1 -1
  90. package/dist/components/multi-select-combobox.js +2 -2
  91. package/dist/components/native-select.d.ts +2 -2
  92. package/dist/components/pagination.js +1 -1
  93. package/dist/components/photo-ground.d.ts +64 -0
  94. package/dist/components/photo-ground.js +3 -0
  95. package/dist/components/place-about-tab.js +2 -2
  96. package/dist/components/place-details-mobile.js +3 -3
  97. package/dist/components/place-types.d.ts +2 -2
  98. package/dist/components/qa-block.d.ts +36 -0
  99. package/dist/components/qa-block.js +24 -0
  100. package/dist/components/scroll-fade.js +3 -121
  101. package/dist/components/searchable-select.js +1 -1
  102. package/dist/components/select.d.ts +1 -1
  103. package/dist/components/signature-chip.d.ts +2 -2
  104. package/dist/components/signature-chip.js +2 -2
  105. package/dist/components/sliding-panels.js +1 -1
  106. package/dist/components/snap-rail.d.ts +26 -3
  107. package/dist/components/snap-rail.js +3 -109
  108. package/dist/components/spinner.d.ts +4 -4
  109. package/dist/components/story.d.ts +34 -0
  110. package/dist/components/story.js +3 -0
  111. package/dist/components/tag.d.ts +4 -4
  112. package/dist/components/text.d.ts +5 -5
  113. package/dist/components/toggle.d.ts +1 -1
  114. package/dist/components/top-comparison.d.ts +28 -0
  115. package/dist/components/top-comparison.js +76 -0
  116. package/dist/components/top-cross-link.d.ts +34 -0
  117. package/dist/components/top-cross-link.js +101 -0
  118. package/dist/components/top-ranking-entry.d.ts +53 -0
  119. package/dist/components/top-ranking-entry.js +217 -0
  120. package/dist/components/top-ranking-hero.d.ts +61 -0
  121. package/dist/components/top-ranking-hero.js +99 -0
  122. package/dist/components/top-ranking-legend.d.ts +69 -0
  123. package/dist/components/top-ranking-legend.js +124 -0
  124. package/dist/components/top-types.d.ts +109 -0
  125. package/dist/components/top-types.js +1 -0
  126. package/dist/components/venue-grade-dimensions.d.ts +3 -1
  127. package/dist/components/venue-grade-dimensions.js +1 -1
  128. package/dist/components/venue-quotes.d.ts +1 -1
  129. package/dist/components/venue-quotes.js +1 -1
  130. package/dist/components/venue-wall.js +5 -3
  131. package/dist/components/weekday-theme-banner.js +1 -1
  132. package/dist/components/weekend-panel.js +2 -2
  133. package/package.json +1 -1
  134. package/src/components/badge.tsx +1 -1
  135. package/src/components/button.tsx +2 -2
  136. package/src/components/concept-compare-rail.tsx +132 -0
  137. package/src/components/concept-compare.stories.tsx +122 -54
  138. package/src/components/concept-compare.tsx +368 -196
  139. package/src/components/concept-convergence.stories.tsx +53 -0
  140. package/src/components/concept-convergence.tsx +90 -0
  141. package/src/components/convergence.stories.tsx +54 -0
  142. package/src/components/convergence.tsx +177 -0
  143. package/src/components/explainer-steps.stories.tsx +46 -0
  144. package/src/components/explainer-steps.tsx +74 -0
  145. package/src/components/glass-ground.tsx +104 -0
  146. package/src/components/hub-surface.tsx +11 -1
  147. package/src/components/hue-chip.stories.tsx +76 -0
  148. package/src/components/hue-chip.test.tsx +62 -0
  149. package/src/components/hue-chip.tsx +99 -0
  150. package/src/components/kitchen-dossier.stories.tsx +108 -0
  151. package/src/components/kitchen-dossier.tsx +321 -0
  152. package/src/components/menu-dead-end.stories.tsx +67 -0
  153. package/src/components/menu-dead-end.tsx +127 -0
  154. package/src/components/menu-family-block.stories.tsx +91 -0
  155. package/src/components/menu-family-block.tsx +303 -0
  156. package/src/components/menu-family-card.stories.tsx +43 -35
  157. package/src/components/menu-family-card.tsx +115 -142
  158. package/src/components/menu-filter-chips.stories.tsx +107 -0
  159. package/src/components/menu-filter-chips.tsx +238 -0
  160. package/src/components/menu-group-rows.stories.tsx +54 -0
  161. package/src/components/menu-group-rows.tsx +133 -0
  162. package/src/components/menu-hub-hero.test.tsx +39 -0
  163. package/src/components/menu-hub-hero.tsx +17 -5
  164. package/src/components/menu-index-header.stories.tsx +72 -0
  165. package/src/components/menu-index-header.tsx +125 -0
  166. package/src/components/menu-index-list.stories.tsx +50 -0
  167. package/src/components/menu-index-list.tsx +149 -0
  168. package/src/components/menu-intent-hero.stories.tsx +67 -0
  169. package/src/components/menu-intent-hero.tsx +189 -0
  170. package/src/components/menu-kitchen-list.stories.tsx +67 -0
  171. package/src/components/menu-kitchen-list.test.tsx +78 -0
  172. package/src/components/menu-kitchen-list.tsx +284 -0
  173. package/src/components/menu-mocks.ts +198 -23
  174. package/src/components/menu-types.ts +189 -6
  175. package/src/components/motion-icon-controls.tsx +11 -11
  176. package/src/components/motion-icon-set.tsx +6 -5
  177. package/src/components/motion-icon.test.tsx +23 -1
  178. package/src/components/motion-icon.tsx +20 -0
  179. package/src/components/photo-ground.tsx +147 -0
  180. package/src/components/place-types.ts +2 -2
  181. package/src/components/qa-block.stories.tsx +43 -0
  182. package/src/components/qa-block.tsx +60 -0
  183. package/src/components/signature-chip.tsx +3 -3
  184. package/src/components/snap-rail.tsx +58 -15
  185. package/src/components/story.tsx +225 -0
  186. package/src/components/top-comparison.stories.tsx +78 -0
  187. package/src/components/top-comparison.tsx +151 -0
  188. package/src/components/top-cross-link.stories.tsx +84 -0
  189. package/src/components/top-cross-link.tsx +171 -0
  190. package/src/components/top-ranking-entry.stories.tsx +171 -0
  191. package/src/components/top-ranking-entry.test.tsx +105 -0
  192. package/src/components/top-ranking-entry.tsx +425 -0
  193. package/src/components/top-ranking-hero.stories.tsx +76 -0
  194. package/src/components/top-ranking-hero.tsx +218 -0
  195. package/src/components/top-ranking-legend.stories.tsx +78 -0
  196. package/src/components/top-ranking-legend.tsx +239 -0
  197. package/src/components/top-types.ts +110 -0
  198. package/src/components/venue-grade-dimensions.tsx +2 -2
  199. package/src/components/venue-quotes.stories.tsx +1 -1
  200. package/src/components/venue-quotes.tsx +4 -2
  201. package/src/components/venue-wall.tsx +9 -4
  202. package/src/components/weekday-theme-banner.tsx +1 -1
  203. package/dist/chunk-THOVPZNN.js +0 -37
  204. package/dist/chunk-YS6BHKZO.js +0 -92
  205. package/dist/components/ranked-venue-list.d.ts +0 -49
  206. package/dist/components/ranked-venue-list.js +0 -87
  207. package/dist/components/signature-line-list.d.ts +0 -45
  208. package/dist/components/signature-line-list.js +0 -99
  209. package/dist/components/venue-busyness-strip.d.ts +0 -35
  210. package/dist/components/venue-busyness-strip.js +0 -37
  211. package/dist/components/venue-signature-block.d.ts +0 -39
  212. package/dist/components/venue-signature-block.js +0 -6
  213. package/dist/components/venue-spotlight.d.ts +0 -74
  214. package/dist/components/venue-spotlight.js +0 -138
  215. package/src/components/ranked-venue-list.stories.tsx +0 -80
  216. package/src/components/ranked-venue-list.tsx +0 -177
  217. package/src/components/signature-line-list.stories.tsx +0 -85
  218. package/src/components/signature-line-list.tsx +0 -136
  219. package/src/components/venue-busyness-strip.stories.tsx +0 -66
  220. package/src/components/venue-busyness-strip.tsx +0 -64
  221. package/src/components/venue-signature-block.stories.tsx +0 -68
  222. package/src/components/venue-signature-block.tsx +0 -71
  223. package/src/components/venue-spotlight.stories.tsx +0 -141
  224. package/src/components/venue-spotlight.tsx +0 -236
  225. package/dist/{chunk-XWMRABZW.js → chunk-HSIYYA2E.js} +1 -1
@@ -0,0 +1,186 @@
1
+ import { DIMENSION_ORDER, VenueGradeDimensions } from '../chunk-AKQ57NXY.js';
2
+ import { VenueQuotes } from '../chunk-43RC7MHY.js';
3
+ import { StoryProvider, StorySegments, StoryPanel } from '../chunk-F6FMZJDG.js';
4
+ import { GlassGround } from '../chunk-WCTHZKU7.js';
5
+ import { Separator } from '../chunk-WSRWFA6K.js';
6
+ import { PhotoGround, PHOTO_GROUND } from '../chunk-5RWTOT5Y.js';
7
+ import { cn } from '../chunk-FEK5XGZW.js';
8
+ import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
9
+ import { MessageSquareQuote, Star } from 'lucide-react';
10
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
11
+
12
+ function DefaultLink(_a) {
13
+ var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
14
+ return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
15
+ }
16
+ var GLASS_LEAD = "128px";
17
+ var DIMENSION_LIMIT = 3;
18
+ var QUOTE_LIMIT = 2;
19
+ var initialOf = (name) => {
20
+ var _a, _b;
21
+ return ((_b = (_a = name.match(new RegExp("\\p{L}", "u"))) == null ? void 0 : _a[0]) != null ? _b : "").toLocaleUpperCase();
22
+ };
23
+ function KitchenDossier({
24
+ place,
25
+ href,
26
+ meta,
27
+ signature,
28
+ quotes,
29
+ grade,
30
+ labels,
31
+ formatPrice,
32
+ formatScore,
33
+ partDurationMs,
34
+ action,
35
+ linkComponent: LinkComponent = DefaultLink,
36
+ className
37
+ }) {
38
+ var _a, _b, _c, _d;
39
+ const rating = (_a = place.rating) == null ? void 0 : _a.rating;
40
+ const parts = [];
41
+ if (signature) {
42
+ const item = signature.item;
43
+ const firstEntry = (_b = item.sizes_and_prices) == null ? void 0 : _b[0];
44
+ const mentions = (_d = (_c = item.mentions) != null ? _c : item.review_count) != null ? _d : 0;
45
+ parts.push(
46
+ /* @__PURE__ */ jsxs(Part, { kicker: labels.knownFor, children: [
47
+ signature.href ? /* @__PURE__ */ jsx(
48
+ LinkComponent,
49
+ {
50
+ href: signature.href,
51
+ className: "w-max max-w-full text-[16px] font-bold leading-tight tracking-[-0.01em] text-white hover:underline focus-visible:outline-none focus-visible:underline",
52
+ children: item.name
53
+ }
54
+ ) : /* @__PURE__ */ jsx("span", { className: "text-[16px] font-bold leading-tight tracking-[-0.01em] text-white", children: item.name }),
55
+ signature.why && /* @__PURE__ */ jsx("p", { className: "mt-1 line-clamp-2 font-serif text-[13px] leading-snug text-white/75", children: signature.why }),
56
+ (firstEntry || mentions > 0) && /* @__PURE__ */ jsxs(Fragment, { children: [
57
+ /* @__PURE__ */ jsx(Separator, { className: "my-2.5 via-white/20" }),
58
+ /* @__PURE__ */ jsxs("div", { className: "flex items-end justify-between gap-3", children: [
59
+ /* @__PURE__ */ jsx("span", { className: "flex items-baseline gap-1.5", children: firstEntry && /* @__PURE__ */ jsxs(Fragment, { children: [
60
+ /* @__PURE__ */ jsxs("span", { className: "text-[18px] font-extrabold leading-none tabular-nums text-white", children: [
61
+ formatPrice(firstEntry.price),
62
+ /* @__PURE__ */ jsx("span", { className: "ml-1 text-[12px] font-bold", children: labels.currency })
63
+ ] }),
64
+ firstEntry.size > 0 && /* @__PURE__ */ jsxs("span", { className: "text-[11.5px] tabular-nums text-white/60", children: [
65
+ firstEntry.size,
66
+ item.kind === "dish" ? "g" : "ml"
67
+ ] })
68
+ ] }) }),
69
+ mentions > 0 && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-[12px] font-semibold tabular-nums text-white/85", children: [
70
+ /* @__PURE__ */ jsx(MessageSquareQuote, { className: "h-3.5 w-3.5", "aria-hidden": true }),
71
+ labels.mentions(mentions)
72
+ ] })
73
+ ] })
74
+ ] })
75
+ ] }, "signature")
76
+ );
77
+ }
78
+ if (quotes && quotes.length > 0) {
79
+ parts.push(
80
+ /* @__PURE__ */ jsx(Part, { kicker: labels.whatPeopleSay, children: /* @__PURE__ */ jsx(VenueQuotes, { quotes, limit: QUOTE_LIMIT, className: "lg:grid-cols-1" }) }, "quotes")
81
+ );
82
+ }
83
+ const dimensions = grade == null ? void 0 : grade.dimensions;
84
+ const strongest = dimensions ? DIMENSION_ORDER.filter((key) => typeof dimensions[key] === "number").sort((a, b) => {
85
+ var _a2, _b2;
86
+ return ((_a2 = dimensions[b]) != null ? _a2 : 0) - ((_b2 = dimensions[a]) != null ? _b2 : 0);
87
+ }).slice(0, DIMENSION_LIMIT) : [];
88
+ if (grade && (grade.overall || strongest.length > 0)) {
89
+ parts.push(
90
+ /* @__PURE__ */ jsx(Part, { kicker: labels.theGrade, children: /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-4", children: [
91
+ grade.overall && /* @__PURE__ */ jsx("span", { className: "text-[34px] font-extrabold leading-none tracking-[-0.03em] tabular-nums text-[oklch(0.82_0.15_85)]", children: grade.overall }),
92
+ dimensions && strongest.length > 0 && /* @__PURE__ */ jsx(
93
+ VenueGradeDimensions,
94
+ {
95
+ className: "min-w-0 flex-1",
96
+ dimensions,
97
+ labels: labels.dimensions,
98
+ order: strongest,
99
+ formatScore
100
+ }
101
+ )
102
+ ] }) }, "grade")
103
+ );
104
+ }
105
+ return /* @__PURE__ */ jsxs(
106
+ "article",
107
+ {
108
+ className: cn(
109
+ /* `flex flex-col` so the story fills the card's height: in a rail
110
+ the cards are stretched to the tallest, and a story that stopped
111
+ at its own min-height left a band of bare photograph under the
112
+ action on every shorter card. */
113
+ "dark relative isolate flex flex-col overflow-hidden rounded-[18px] border border-border text-foreground shadow-[var(--shadow-card)]",
114
+ PHOTO_GROUND,
115
+ className
116
+ ),
117
+ children: [
118
+ /* @__PURE__ */ jsx(PhotoGround, { className: "-z-20", photos: [place.thumbnail_url], initials: initialOf(place.name), loading: "eager" }),
119
+ /* @__PURE__ */ jsxs(
120
+ StoryProvider,
121
+ {
122
+ count: parts.length,
123
+ durationMs: partDurationMs,
124
+ nextLabel: labels.next,
125
+ className: "relative flex min-h-[560px] flex-1 flex-col p-4 lg:min-h-[440px] lg:p-5",
126
+ children: [
127
+ /* @__PURE__ */ jsx(
128
+ StorySegments,
129
+ {
130
+ labels: parts.map((_, index) => labels.part(index, parts.length)),
131
+ className: "-mt-1"
132
+ }
133
+ ),
134
+ /* @__PURE__ */ jsx("div", { className: "relative min-h-[184px] flex-1", children: labels.openUntil && /* @__PURE__ */ jsxs("span", { className: "absolute left-0 top-3 inline-flex h-[30px] items-center gap-[7px] rounded-full bg-[oklch(0.16_0.012_55_/_0.78)] px-3 text-[11.5px] font-bold text-white", children: [
135
+ /* @__PURE__ */ jsx("i", { className: "h-[7px] w-[7px] rounded-full bg-success", "aria-hidden": true }),
136
+ labels.openUntil
137
+ ] }) }),
138
+ /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col gap-3.5", children: [
139
+ /* @__PURE__ */ jsx(
140
+ "div",
141
+ {
142
+ "aria-hidden": true,
143
+ className: "pointer-events-none absolute -inset-x-4 -bottom-4 -top-32 -z-10 lg:-inset-x-5 lg:-bottom-5",
144
+ children: /* @__PURE__ */ jsx(
145
+ GlassGround,
146
+ {
147
+ stops: { direction: "to bottom", clear: "0px", full: GLASS_LEAD },
148
+ peak: 0.6
149
+ }
150
+ )
151
+ }
152
+ ),
153
+ /* @__PURE__ */ jsxs("div", { className: "[text-shadow:0_1px_12px_oklch(0_0_0/0.55)]", children: [
154
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-4", children: [
155
+ /* @__PURE__ */ jsx("h3", { className: "min-w-0 font-serif text-[26px] font-semibold leading-tight tracking-[-0.02em] text-white lg:text-[32px]", children: /* @__PURE__ */ jsx(LinkComponent, { href, className: "focus-visible:outline-none focus-visible:underline", children: place.name }) }),
156
+ rating !== void 0 && /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-[18px] font-extrabold leading-none tabular-nums text-white lg:text-[22px]", children: [
157
+ rating.toFixed(1),
158
+ /* @__PURE__ */ jsx(Star, { className: "h-3.5 w-3.5 lg:h-4 lg:w-4", "aria-hidden": true })
159
+ ] })
160
+ ] }),
161
+ (meta || labels.reviewCount) && /* @__PURE__ */ jsx("p", { className: "mt-1 truncate text-[12.5px] text-white/70", children: [meta, labels.reviewCount].filter(Boolean).join(" \xB7 ") })
162
+ ] }),
163
+ parts.length > 0 && /* @__PURE__ */ jsx(
164
+ StoryPanel,
165
+ {
166
+ parts,
167
+ className: "rounded-[14px] border border-white/10 bg-[oklch(0.16_0.012_55_/_0.62)] p-4"
168
+ }
169
+ ),
170
+ action && /* @__PURE__ */ jsx("div", { className: "flex [&>*]:w-full lg:[&>*]:w-auto", children: action })
171
+ ] })
172
+ ]
173
+ }
174
+ )
175
+ ]
176
+ }
177
+ );
178
+ }
179
+ function Part({ kicker, children }) {
180
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
181
+ /* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-[9.5px] font-bold uppercase tracking-[0.12em] text-white/60", children: kicker }),
182
+ children
183
+ ] });
184
+ }
185
+
186
+ export { KitchenDossier };
@@ -1,4 +1,4 @@
1
- import { Button } from '../chunk-H3BV4VAG.js';
1
+ import { Button } from '../chunk-JS3EINZD.js';
2
2
  import '../chunk-R47NEOSI.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
4
  import { __objRest, __spreadProps, __spreadValues } from '../chunk-3GWWZKX7.js';
@@ -0,0 +1,56 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { MenuLinkComponent, MenuLoosenOption } from './menu-types.js';
3
+ import 'react';
4
+ import './place-types.js';
5
+
6
+ /**
7
+ * MenuDeadEnd — what dropped out, and the one press that brings it back.
8
+ *
9
+ * A filter combination that returns nothing is the intent page's worst state,
10
+ * and an empty-state illustration is the worst answer to it: the reader knows
11
+ * the list is empty, what they do not know is WHICH of their four filters did
12
+ * it. So this says what dropped out, why, and what widening one specific filter
13
+ * would restore — with the count, because "+5 kitchens, including the
14
+ * highest-rated Italian room in the city" is an answer and "try removing a
15
+ * filter" is a shrug.
16
+ *
17
+ * It is also drawn on a NON-empty list, whenever a filter has cost the reader
18
+ * something notable. The board's case is 34 kitchens still standing and Casa
19
+ * Boema — the one they came for — missing.
20
+ *
21
+ * Interactive: the consumer marks its own module `"use client"`.
22
+ */
23
+ type MenuDeadEndProps = {
24
+ /**
25
+ * The explanation, composed by the caller.
26
+ *
27
+ * A node rather than a string because it emphasises real names ("**Casa
28
+ * Boema** and six others dropped out"), and assembling that from fragments
29
+ * here would produce translated word-salad in one of the two locales.
30
+ */
31
+ children: React.ReactNode;
32
+ /** The widening this offers, e.g. "Raise to 60 lei · 16 kitchens". */
33
+ actionLabel?: string;
34
+ /** Where the widening leads. Preferred over `onAction` — see `MenuLoosenOption.href`. */
35
+ actionHref?: string;
36
+ onAction?: () => void;
37
+ linkComponent?: MenuLinkComponent;
38
+ className?: string;
39
+ };
40
+ declare function MenuDeadEnd({ children, actionLabel, actionHref, onAction, linkComponent: LinkComponent, className, }: MenuDeadEndProps): react_jsx_runtime.JSX.Element;
41
+ /**
42
+ * MenuLoosenList — one row per active filter, each priced in kitchens.
43
+ *
44
+ * The companion to the panel above: the panel names the single best widening,
45
+ * this lists every one of them so the reader can choose which constraint they
46
+ * care least about. Every row states what it would return, because a filter the
47
+ * reader cannot price is a filter they will not drop.
48
+ */
49
+ type MenuLoosenListProps = {
50
+ options: MenuLoosenOption[];
51
+ linkComponent?: MenuLinkComponent;
52
+ className?: string;
53
+ };
54
+ declare function MenuLoosenList({ options, linkComponent: LinkComponent, className, }: MenuLoosenListProps): react_jsx_runtime.JSX.Element;
55
+
56
+ export { MenuDeadEnd, type MenuDeadEndProps, MenuLoosenList, type MenuLoosenListProps };
@@ -0,0 +1,49 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
3
+ import { Info } from 'lucide-react';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ function DefaultLink(_a) {
7
+ var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
8
+ return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
9
+ }
10
+ function MenuDeadEnd({
11
+ children,
12
+ actionLabel,
13
+ actionHref,
14
+ onAction,
15
+ linkComponent: LinkComponent = DefaultLink,
16
+ className
17
+ }) {
18
+ const actionClass = "inline-flex h-7 shrink-0 items-center rounded-full bg-foreground px-3 text-[12.5px] font-bold text-background transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 motion-reduce:transition-none lg:ml-auto";
19
+ return /* @__PURE__ */ jsxs(
20
+ "div",
21
+ {
22
+ className: cn(
23
+ "mt-4 flex flex-wrap items-center gap-3 rounded-[14px] bg-muted p-3.5 lg:flex-nowrap lg:gap-4 lg:px-[18px] lg:py-4",
24
+ className
25
+ ),
26
+ children: [
27
+ /* @__PURE__ */ jsx(Info, { className: "h-[18px] w-[18px] shrink-0 text-muted-foreground", "aria-hidden": true }),
28
+ /* @__PURE__ */ jsx("p", { className: "max-w-[560px] text-[13px] leading-[1.55] text-muted-foreground [&_b]:font-bold [&_b]:text-foreground", children }),
29
+ actionLabel && (actionHref ? /* @__PURE__ */ jsx(LinkComponent, { href: actionHref, className: actionClass, children: actionLabel }) : onAction && /* @__PURE__ */ jsx("button", { type: "button", onClick: onAction, className: actionClass, children: actionLabel }))
30
+ ]
31
+ }
32
+ );
33
+ }
34
+ function MenuLoosenList({
35
+ options,
36
+ linkComponent: LinkComponent = DefaultLink,
37
+ className
38
+ }) {
39
+ const rowClass = "inline-flex h-9 items-center justify-between gap-3 rounded-full border border-border bg-card px-4 text-sm font-semibold transition-colors hover:border-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none";
40
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-2.5", className), children: options.map((option) => {
41
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
42
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label }),
43
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 font-bold tabular-nums text-accent", children: option.gainLabel })
44
+ ] });
45
+ return option.href ? /* @__PURE__ */ jsx(LinkComponent, { href: option.href, className: rowClass, children: body }, option.key) : /* @__PURE__ */ jsx("button", { type: "button", onClick: option.onSelect, className: rowClass, children: body }, option.key);
46
+ }) });
47
+ }
48
+
49
+ export { MenuDeadEnd, MenuLoosenList };
@@ -0,0 +1,98 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { MenuKitchenListLabels } from './menu-kitchen-list.js';
3
+ import { MenuFamilyBlockPreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
4
+ import 'react';
5
+ import './place-types.js';
6
+
7
+ /**
8
+ * MenuFamilyBlock — the cuisines index's family card. The mosaic is the ground.
9
+ *
10
+ * ## Three layers, and everything floats on them
11
+ *
12
+ * The grid of venue photographs is the background for the ENTIRE card, edge to
13
+ * edge, and the facts sit on it. Three layers do the work:
14
+ *
15
+ * 1. **The mosaic**, full-bleed, wearing the family's hue through a
16
+ * `mix-blend-color` layer.
17
+ * 2. **An ink gradient** — absent where the photography is the subject, full
18
+ * where the rows begin. This is what buys the contrast. There used to be a
19
+ * masked backdrop-filter under it; it was removed for the measurement
20
+ * recorded in `GlassGround` (73 blur layers cost `/menu` 9 ms per scrolled
21
+ * frame on a phone).
22
+ *
23
+ * On the phone the ink runs top to bottom: the name and the action sit on
24
+ * clear photography, the chips and the rows on the inked foot. On desktop the
25
+ * same layers turn ninety degrees — the photo column on the left stays clear,
26
+ * the row column on the right is the inked one. The mosaic
27
+ * runs 3×2 there rather than 2×2, because at 1110px a four-tile grid makes each
28
+ * photograph too big to read as texture.
29
+ *
30
+ * ## The dark scope
31
+ *
32
+ * The card's content region carries the `dark` class, so every token inside —
33
+ * `text-foreground`, `bg-muted`, `border-border` — resolves to its dark-theme
34
+ * value. That is how `MenuKitchenList` and `HueChip` render correctly on the
35
+ * ink without a fork or a "tone" prop: the mechanism the app already uses to
36
+ * mark a region as dark. It also means the card looks the same in both themes,
37
+ * which is right — it is built on photography, and photography is not themed.
38
+ *
39
+ * ## The two costs, stated
40
+ *
41
+ * A `backdrop-filter` over a mask is expensive to composite, and this card is
42
+ * repeated ten times down a scroll. And the thumbnails now sit on a
43
+ * photograph; they survive only because the ink is heavy under them, and on a
44
+ * busy interior shot they will fight. Both were accepted with the design.
45
+ *
46
+ * ## No "most named" item, no venue count badge
47
+ *
48
+ * The family-level "most named" was the first venue's signature relabelled —
49
+ * Italian, Pizza and Mediterranean all claimed "Turkish Poached Eggs" — and
50
+ * the count used to print three times with two values. One count, under the
51
+ * name; the overflow tile says only how many photographs it stands for.
52
+ */
53
+ /** @deprecated Alias of `MenuLinkProps`; kept for symmetry with the other menu surfaces. */
54
+ type MenuFamilyBlockLinkProps = MenuLinkProps;
55
+ type MenuFamilyBlockLabels = {
56
+ /** Unit under the family name, e.g. "247 kitchens". Pluralised by the caller. */
57
+ venueUnit: (count: number) => string;
58
+ /** The overflow pill over the mosaic, e.g. "+311 more". */
59
+ more: (count: number) => string;
60
+ /**
61
+ * Price-band caption, e.g. "kitchen price band".
62
+ *
63
+ * Never drawn: the band reads as a wallet and a range, and a caption on a
64
+ * pill that short is longer than the fact. It names the pill for a screen
65
+ * reader, which would otherwise be read two numbers and a currency.
66
+ */
67
+ priceBand: string;
68
+ /** Main action, e.g. "Browse Italian". Sits on the photography — keep it short. */
69
+ browse: string;
70
+ /** Passed through to the venue rows. */
71
+ kitchens: MenuKitchenListLabels;
72
+ };
73
+ type MenuFamilyBlockProps = {
74
+ family: MenuFamilyBlockPreview;
75
+ labels: MenuFamilyBlockLabels;
76
+ formatCount?: (value: number) => string;
77
+ /** Finished CSS colour for the chips. */
78
+ hue?: string;
79
+ /** Finished CSS gradient — the family's colour over the mosaic. */
80
+ gradient?: string;
81
+ linkComponent?: MenuLinkComponent;
82
+ className?: string;
83
+ };
84
+ declare function MenuFamilyBlock({ family, labels, formatCount, hue, gradient, linkComponent: LinkComponent, className, }: MenuFamilyBlockProps): react_jsx_runtime.JSX.Element;
85
+ /**
86
+ * The block's own loading state, at the block's footprint.
87
+ *
88
+ * The ground is the card's own, so the placeholder is already the dark
89
+ * surface the photographs will land on — nothing flashes from paper to ink.
90
+ * `venues` matches the rows the caller will render, so a block showing three
91
+ * does not settle from a placeholder showing one.
92
+ */
93
+ declare function MenuFamilyBlockSkeleton({ venues, className, }: {
94
+ venues?: number;
95
+ className?: string;
96
+ }): react_jsx_runtime.JSX.Element;
97
+
98
+ export { MenuFamilyBlock, type MenuFamilyBlockLabels, type MenuFamilyBlockLinkProps, type MenuFamilyBlockProps, MenuFamilyBlockSkeleton };
@@ -0,0 +1,153 @@
1
+ import { MenuKitchenList } from '../chunk-24RFI4RQ.js';
2
+ import { HueChip } from '../chunk-CLLY6XB3.js';
3
+ import { Separator } from '../chunk-WSRWFA6K.js';
4
+ import { PhotoGround, PHOTO_GROUND } from '../chunk-5RWTOT5Y.js';
5
+ import { Skeleton } from '../chunk-QXHMPJ35.js';
6
+ import { cn } from '../chunk-FEK5XGZW.js';
7
+ import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
8
+ import { Wallet } from 'lucide-react';
9
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
+
11
+ function DefaultLink(_a) {
12
+ var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
13
+ return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
14
+ }
15
+ var MOSAIC_TILES = 6;
16
+ var PHONE_TILES = 4;
17
+ var GROUND = PHOTO_GROUND;
18
+ var INK = "bg-[linear-gradient(to_bottom,oklch(0.16_0.012_55_/_0.42)_0%,oklch(0.16_0.012_55_/_0.6)_30%,oklch(0.16_0.012_55_/_0.9)_48%,oklch(0.16_0.012_55_/_0.96)_100%)] lg:bg-[linear-gradient(to_right,oklch(0.16_0.012_55_/_0.38)_0%,oklch(0.16_0.012_55_/_0.6)_30%,oklch(0.16_0.012_55_/_0.92)_46%,oklch(0.16_0.012_55_/_0.96)_100%)]";
19
+ var TEXT_SCRIM = (
20
+ /* `isolate` + `before:-z-10`: a positioned pseudo-element paints ABOVE the
21
+ column's in-flow text unless the column is its own stacking context and
22
+ the layer is ordered beneath. Without `isolate`, `-z-10` would instead
23
+ drop it behind the card's mosaic — inside the article's context. */
24
+ "isolate before:pointer-events-none before:absolute before:inset-x-0 before:bottom-0 before:top-[30%] before:-z-10 before:bg-[linear-gradient(to_bottom,oklch(0.16_0.012_55_/_0)_0%,oklch(0.16_0.012_55_/_0.55)_45%,oklch(0.16_0.012_55_/_0.8)_100%)] before:content-['']"
25
+ );
26
+ function MenuFamilyBlock({
27
+ family,
28
+ labels,
29
+ formatCount = String,
30
+ hue,
31
+ gradient,
32
+ linkComponent: LinkComponent = DefaultLink,
33
+ className
34
+ }) {
35
+ var _a, _b, _c, _d, _e;
36
+ const photos = ((_a = family.photoUrls) != null ? _a : []).slice(0, MOSAIC_TILES);
37
+ const overflow = Math.max(family.venueCount - photos.length, 0);
38
+ const initial = ((_c = (_b = family.name.match(new RegExp("\\p{L}", "u"))) == null ? void 0 : _b[0]) != null ? _c : "").toLocaleUpperCase();
39
+ const venues = (_d = family.venues) != null ? _d : [];
40
+ return /* @__PURE__ */ jsxs(
41
+ "article",
42
+ {
43
+ className: cn(
44
+ /* `isolate` confines the blend and the backdrop-filter to this card.
45
+ `dark` scopes every token inside to its dark-theme value. */
46
+ "dark relative isolate overflow-hidden rounded-[14px] text-foreground",
47
+ GROUND,
48
+ className
49
+ ),
50
+ children: [
51
+ /* @__PURE__ */ jsx(
52
+ PhotoGround,
53
+ {
54
+ photos: photos.length > 0 ? photos : [void 0],
55
+ initials: initial,
56
+ mosaicClassName: photos.length > 0 ? "grid-cols-2 grid-rows-2 lg:grid-cols-3" : "grid-cols-1",
57
+ phoneTiles: PHONE_TILES,
58
+ gradient
59
+ }
60
+ ),
61
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("absolute inset-0", INK) }),
62
+ /* @__PURE__ */ jsxs("div", { className: "relative grid grid-cols-1 lg:grid-cols-[38%_1fr]", children: [
63
+ /* @__PURE__ */ jsxs("div", { className: cn("relative flex flex-col p-3.5 lg:min-h-[320px] lg:justify-end lg:p-5", TEXT_SCRIM), children: [
64
+ overflow > 0 && /* @__PURE__ */ jsx("span", { className: "mb-16 self-end rounded-full bg-[oklch(0.16_0.012_55_/_0.78)] px-2.5 py-1 text-[11px] font-semibold text-white lg:mb-3 lg:self-start", children: labels.more(overflow) }),
65
+ /* @__PURE__ */ jsx("h3", { className: "text-balance font-serif text-[26px] font-semibold leading-tight tracking-[-0.02em] text-white lg:text-[30px]", children: family.name }),
66
+ /* @__PURE__ */ jsx("span", { className: "mt-0.5 block text-[13px] font-medium tabular-nums text-white/70", children: labels.venueUnit(family.venueCount) }),
67
+ /* @__PURE__ */ jsx(
68
+ LinkComponent,
69
+ {
70
+ href: family.href,
71
+ className: "mt-3.5 inline-flex h-10 w-max items-center rounded-full border border-white/20 bg-white/[0.16] px-4 text-[13.5px] font-bold text-white transition-colors hover:bg-white/25 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white motion-reduce:transition-none",
72
+ children: labels.browse
73
+ }
74
+ )
75
+ ] }),
76
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col px-3.5 pb-3.5 lg:p-5", children: [
77
+ /* @__PURE__ */ jsxs("ul", { className: "flex flex-wrap items-center gap-1.5", children: [
78
+ family.priceBandLabel && /* No hue: a fact about money, not about the family. In the dark
79
+ scope `HueChip`'s `--muted` fallback is the dark pill the design
80
+ draws. */
81
+ /* @__PURE__ */ jsx(
82
+ HueChip,
83
+ {
84
+ as: "li",
85
+ className: "font-bold tabular-nums",
86
+ "aria-label": `${labels.priceBand}: ${family.priceBandLabel}`,
87
+ icon: /* @__PURE__ */ jsx(Wallet, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true }),
88
+ children: family.priceBandLabel
89
+ }
90
+ ),
91
+ (_e = family.chips) == null ? void 0 : _e.map((chip) => (
92
+ /* Label only. The counts are VENUES beside a dish group's name,
93
+ which every reader takes for dishes. */
94
+ /* @__PURE__ */ jsx(HueChip, { as: "li", hue, children: chip.label }, chip.slug)
95
+ ))
96
+ ] }),
97
+ venues.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
98
+ /* @__PURE__ */ jsx(Separator, { className: "my-3" }),
99
+ /* @__PURE__ */ jsx(
100
+ MenuKitchenList,
101
+ {
102
+ kitchens: venues,
103
+ labels: labels.kitchens,
104
+ linkComponent: LinkComponent
105
+ }
106
+ )
107
+ ] })
108
+ ] })
109
+ ] })
110
+ ]
111
+ }
112
+ );
113
+ }
114
+ function MenuFamilyBlockSkeleton({
115
+ venues = 3,
116
+ className
117
+ }) {
118
+ return /* @__PURE__ */ jsx(
119
+ "div",
120
+ {
121
+ className: cn("dark relative overflow-hidden rounded-[14px]", GROUND, className),
122
+ "aria-hidden": true,
123
+ children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-[38%_1fr]", children: [
124
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col p-3.5 lg:min-h-[320px] lg:justify-end lg:p-5", children: [
125
+ /* @__PURE__ */ jsx(Skeleton, { className: "mb-16 h-6 w-[72px] self-end rounded-full lg:mb-3 lg:self-start" }),
126
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-[60%]" }),
127
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-2 h-3.5 w-[90px]" }),
128
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-3.5 h-10 w-[160px] rounded-full" })
129
+ ] }),
130
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col px-3.5 pb-3.5 lg:p-5", children: [
131
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5", children: [
132
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-[86px] rounded-full" }),
133
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-[74px] rounded-full" }),
134
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-[66px] rounded-full" })
135
+ ] }),
136
+ /* @__PURE__ */ jsx(Separator, { className: "my-3" }),
137
+ Array.from({ length: venues }, (_, index) => /* @__PURE__ */ jsxs("div", { children: [
138
+ index > 0 && /* @__PURE__ */ jsx(Separator, {}),
139
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 py-2.5", children: [
140
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-[46px] w-[46px] rounded-[11px]" }),
141
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
142
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-[46%]" }),
143
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-[58%]" })
144
+ ] })
145
+ ] })
146
+ ] }, index))
147
+ ] })
148
+ ] })
149
+ }
150
+ );
151
+ }
152
+
153
+ export { MenuFamilyBlock, MenuFamilyBlockSkeleton };
@@ -1,59 +1,65 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { MenuItemLabels } from './menu-item.js';
3
2
  import { MenuFamilyPreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
4
3
  import 'react';
5
4
  import './place-types.js';
6
5
 
7
6
  /**
8
7
  * MenuFamilyCard — a browsable grouping of venues: a cuisine on the dishes tab,
9
- * a drink family on the drinks tab.
8
+ * a drink family on the drinks tab. The hub's doorway to a family.
10
9
  *
11
- * ## The count does the scanning, the item answers the question
10
+ * ## A doorway, not a summary
12
11
  *
13
- * The card is two halves with two jobs. The dark panel is for scanning a row of
14
- * four: one number, one name, and the groups the family consists of, over a
15
- * mosaic of its venues. The white half underneath answers what you would
16
- * actually orderthe production `<MenuItem>`, with its price, portion and
17
- * mention count, so the recommendation is the review census rather than an
18
- * editorial pick.
12
+ * The cuisines index's `MenuFamilyBlock` is the family's SUMMARY: photography,
13
+ * chips, a price band and three venues. This card is the same family drawn
14
+ * one step earlier, in a row of three on the hub, where the reader is choosing
15
+ * a family and not yet a venue so it carries the same photography, the same
16
+ * chips and the same "Browse" action, and lists no venue. A venue on the hub
17
+ * card was tried and it was the first venue's signature relabelled as the
18
+ * family's most named, which was a lie at three-card width.
19
19
  *
20
- * ## Both halves count VENUES
20
+ * ## The count does the scanning
21
21
  *
22
- * Cuisine exists on places and nowhere else no listing endpoint will tell you
23
- * how many dishes are Italian so a card counting dishes cannot be built and
24
- * this one does not try. The groups line is a plain list without counts: at
25
- * four cards across, four chips each carrying a number turned the panel into a
26
- * table, and the numbers were kitchens, which nobody reads a chip as.
22
+ * The card is one number, one name and the groups the family consists of,
23
+ * over a mosaic of its venues. The count is VENUES: cuisine exists on places
24
+ * and nowhere else no listing endpoint will tell you how many dishes are
25
+ * Italian so a card counting dishes cannot be built and this one does not
26
+ * try. The chips are plain labels: at three cards across, chips carrying
27
+ * numbers turned the panel into a table, and the numbers were kitchens, which
28
+ * nobody reads a chip as.
27
29
  *
28
- * The mosaic holds VENUE photographs, which are real. It dims them hard — this
29
- * is a ground for a number, not a gallery, and at this size a legible photo
30
- * competes with the count for the same glance.
30
+ * ## One link
31
+ *
32
+ * The whole card is the link and the "Browse" pill is its visible affordance,
33
+ * not a second link — a pill inside a link is a nested anchor, and a pill that
34
+ * is the only link leaves the photography, the number and the name inert.
31
35
  */
32
36
  /** @deprecated Alias of `MenuLinkProps`; kept so existing imports keep working. */
33
37
  type MenuFamilyCardLinkProps = MenuLinkProps;
34
38
  type MenuFamilyCardLabels = {
35
39
  /** Unit under the count, e.g. "KITCHENS". */
36
40
  venueUnit: string;
37
- /** Kicker over the featured item, e.g. "MOST NAMED". */
38
- mostNamed: string;
39
- /** Footer caption, e.g. "kitchen price band". */
41
+ /**
42
+ * Price-band caption, e.g. "kitchen price band". Never drawn — it names the
43
+ * pill for a screen reader, which would otherwise be read two numbers and a
44
+ * currency.
45
+ */
40
46
  priceBand: string;
47
+ /** The action pill, e.g. "Browse Italian". Sits on the photography — keep it short. */
48
+ browse: string;
41
49
  };
42
50
  type MenuFamilyCardProps = {
43
51
  family: MenuFamilyPreview;
44
52
  labels: MenuFamilyCardLabels;
45
- /** Passed through to the featured `<MenuItem>`. */
46
- itemLabels: MenuItemLabels;
47
- formatPrice: (amount: number) => string;
48
- formatCount?: (value: number) => string;
49
53
  href: string;
50
- /** Finished CSS colour for the featured item's category mark. */
54
+ /** Finished CSS colour for the chips. */
51
55
  hue?: string;
56
+ /** Finished CSS gradient — the family's colour over the mosaic. */
57
+ gradient?: string;
52
58
  /** Composed price band, e.g. "32–84 lei". */
53
59
  priceBandLabel?: string;
54
60
  linkComponent?: MenuLinkComponent;
55
61
  className?: string;
56
62
  };
57
- declare function MenuFamilyCard({ family, labels, itemLabels, formatPrice, formatCount, href, hue, priceBandLabel, linkComponent: LinkComponent, className, }: MenuFamilyCardProps): react_jsx_runtime.JSX.Element;
63
+ declare function MenuFamilyCard({ family, labels, href, hue, gradient, priceBandLabel, linkComponent: LinkComponent, className, }: MenuFamilyCardProps): react_jsx_runtime.JSX.Element;
58
64
 
59
65
  export { MenuFamilyCard, type MenuFamilyCardLabels, type MenuFamilyCardLinkProps, type MenuFamilyCardProps };