@bearmenu/ui 0.8.9 → 0.8.10

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 (178) hide show
  1. package/dist/chunk-24RFI4RQ.js +167 -0
  2. package/dist/chunk-2XCZJWTV.js +121 -0
  3. package/dist/chunk-5RWTOT5Y.js +72 -0
  4. package/dist/{chunk-AXV5O2IZ.js → chunk-AKQ57NXY.js} +3 -3
  5. package/dist/chunk-CLLY6XB3.js +41 -0
  6. package/dist/chunk-DTXNDLSE.js +125 -0
  7. package/dist/chunk-F6FMZJDG.js +113 -0
  8. package/dist/{chunk-2WDJR6K7.js → chunk-G7IFL4Z4.js} +4 -1
  9. package/dist/chunk-MZL7CGCL.js +109 -0
  10. package/dist/chunk-SY6RV476.js +48 -0
  11. package/dist/chunk-UDN7UHJW.js +60 -0
  12. package/dist/{chunk-TT3WFS6S.js → chunk-YOKHBAIH.js} +11 -11
  13. package/dist/components/badge.d.ts +1 -1
  14. package/dist/components/button.d.ts +1 -1
  15. package/dist/components/command.d.ts +7 -7
  16. package/dist/components/concept-compare-rail.d.ts +50 -0
  17. package/dist/components/concept-compare-rail.js +5 -0
  18. package/dist/components/concept-compare.d.ts +75 -38
  19. package/dist/components/concept-compare.js +209 -133
  20. package/dist/components/concept-convergence.d.ts +41 -0
  21. package/dist/components/concept-convergence.js +53 -0
  22. package/dist/components/convergence.d.ts +25 -0
  23. package/dist/components/convergence.js +4 -0
  24. package/dist/components/date-input.d.ts +1 -1
  25. package/dist/components/event-card.js +1 -1
  26. package/dist/components/event-compact-row.js +1 -1
  27. package/dist/components/event-detail-panel.js +1 -1
  28. package/dist/components/event-index-row.js +1 -1
  29. package/dist/components/event-list-row-wide.js +1 -1
  30. package/dist/components/event-list-row.js +2 -2
  31. package/dist/components/explainer-steps.d.ts +34 -0
  32. package/dist/components/explainer-steps.js +36 -0
  33. package/dist/components/glass-ground.d.ts +66 -0
  34. package/dist/components/glass-ground.js +3 -0
  35. package/dist/components/hub-surface.js +11 -1
  36. package/dist/components/hue-chip.d.ts +70 -0
  37. package/dist/components/hue-chip.js +3 -0
  38. package/dist/components/kitchen-dossier.d.ts +88 -0
  39. package/dist/components/kitchen-dossier.js +187 -0
  40. package/dist/components/menu-dead-end.d.ts +56 -0
  41. package/dist/components/menu-dead-end.js +49 -0
  42. package/dist/components/menu-family-block.d.ts +99 -0
  43. package/dist/components/menu-family-block.js +155 -0
  44. package/dist/components/menu-family-card.d.ts +33 -27
  45. package/dist/components/menu-family-card.js +43 -85
  46. package/dist/components/menu-field.js +92 -2
  47. package/dist/components/menu-filter-chips.d.ts +86 -0
  48. package/dist/components/menu-filter-chips.js +122 -0
  49. package/dist/components/menu-group-rows.d.ts +53 -0
  50. package/dist/components/menu-group-rows.js +67 -0
  51. package/dist/components/menu-index-header.d.ts +37 -0
  52. package/dist/components/menu-index-header.js +68 -0
  53. package/dist/components/menu-index-list.d.ts +48 -0
  54. package/dist/components/menu-index-list.js +96 -0
  55. package/dist/components/menu-intent-hero.d.ts +69 -0
  56. package/dist/components/menu-intent-hero.js +87 -0
  57. package/dist/components/menu-kitchen-list.d.ts +82 -0
  58. package/dist/components/menu-kitchen-list.js +5 -0
  59. package/dist/components/menu-mocks.d.ts +37 -2
  60. package/dist/components/menu-mocks.js +152 -27
  61. package/dist/components/menu-types.d.ts +182 -6
  62. package/dist/components/motion-icon-controls.js +2 -2
  63. package/dist/components/motion-icon-set.js +6 -6
  64. package/dist/components/motion-icon.d.ts +22 -1
  65. package/dist/components/motion-icon.js +1 -1
  66. package/dist/components/photo-ground.d.ts +64 -0
  67. package/dist/components/photo-ground.js +3 -0
  68. package/dist/components/place-about-tab.js +2 -2
  69. package/dist/components/place-details-mobile.js +2 -2
  70. package/dist/components/place-types.d.ts +2 -2
  71. package/dist/components/qa-block.d.ts +36 -0
  72. package/dist/components/qa-block.js +24 -0
  73. package/dist/components/scroll-fade.js +3 -121
  74. package/dist/components/snap-rail.d.ts +24 -1
  75. package/dist/components/snap-rail.js +3 -109
  76. package/dist/components/spinner.d.ts +2 -2
  77. package/dist/components/story.d.ts +34 -0
  78. package/dist/components/story.js +3 -0
  79. package/dist/components/text.d.ts +3 -3
  80. package/dist/components/top-comparison.d.ts +28 -0
  81. package/dist/components/top-comparison.js +76 -0
  82. package/dist/components/top-cross-link.d.ts +34 -0
  83. package/dist/components/top-cross-link.js +101 -0
  84. package/dist/components/top-ranking-entry.d.ts +53 -0
  85. package/dist/components/top-ranking-entry.js +217 -0
  86. package/dist/components/top-ranking-hero.d.ts +61 -0
  87. package/dist/components/top-ranking-hero.js +99 -0
  88. package/dist/components/top-ranking-legend.d.ts +69 -0
  89. package/dist/components/top-ranking-legend.js +124 -0
  90. package/dist/components/top-types.d.ts +109 -0
  91. package/dist/components/top-types.js +1 -0
  92. package/dist/components/venue-grade-dimensions.d.ts +3 -1
  93. package/dist/components/venue-grade-dimensions.js +1 -1
  94. package/dist/components/weekend-panel.js +2 -2
  95. package/package.json +1 -1
  96. package/src/components/concept-compare-rail.tsx +131 -0
  97. package/src/components/concept-compare.stories.tsx +122 -54
  98. package/src/components/concept-compare.tsx +363 -196
  99. package/src/components/concept-convergence.stories.tsx +53 -0
  100. package/src/components/concept-convergence.tsx +90 -0
  101. package/src/components/convergence.stories.tsx +54 -0
  102. package/src/components/convergence.tsx +177 -0
  103. package/src/components/explainer-steps.stories.tsx +46 -0
  104. package/src/components/explainer-steps.tsx +74 -0
  105. package/src/components/glass-ground.tsx +129 -0
  106. package/src/components/hub-surface.tsx +11 -1
  107. package/src/components/hue-chip.stories.tsx +76 -0
  108. package/src/components/hue-chip.test.tsx +62 -0
  109. package/src/components/hue-chip.tsx +99 -0
  110. package/src/components/kitchen-dossier.stories.tsx +108 -0
  111. package/src/components/kitchen-dossier.tsx +322 -0
  112. package/src/components/menu-dead-end.stories.tsx +67 -0
  113. package/src/components/menu-dead-end.tsx +127 -0
  114. package/src/components/menu-family-block.stories.tsx +91 -0
  115. package/src/components/menu-family-block.tsx +314 -0
  116. package/src/components/menu-family-card.stories.tsx +43 -35
  117. package/src/components/menu-family-card.tsx +122 -142
  118. package/src/components/menu-filter-chips.stories.tsx +107 -0
  119. package/src/components/menu-filter-chips.tsx +238 -0
  120. package/src/components/menu-group-rows.stories.tsx +54 -0
  121. package/src/components/menu-group-rows.tsx +133 -0
  122. package/src/components/menu-index-header.stories.tsx +72 -0
  123. package/src/components/menu-index-header.tsx +125 -0
  124. package/src/components/menu-index-list.stories.tsx +50 -0
  125. package/src/components/menu-index-list.tsx +149 -0
  126. package/src/components/menu-intent-hero.stories.tsx +67 -0
  127. package/src/components/menu-intent-hero.tsx +189 -0
  128. package/src/components/menu-kitchen-list.stories.tsx +67 -0
  129. package/src/components/menu-kitchen-list.test.tsx +78 -0
  130. package/src/components/menu-kitchen-list.tsx +284 -0
  131. package/src/components/menu-mocks.ts +198 -23
  132. package/src/components/menu-types.ts +189 -6
  133. package/src/components/motion-icon-controls.tsx +11 -11
  134. package/src/components/motion-icon-set.tsx +6 -5
  135. package/src/components/motion-icon.test.tsx +23 -1
  136. package/src/components/motion-icon.tsx +20 -0
  137. package/src/components/photo-ground.tsx +147 -0
  138. package/src/components/place-types.ts +2 -2
  139. package/src/components/qa-block.stories.tsx +43 -0
  140. package/src/components/qa-block.tsx +60 -0
  141. package/src/components/snap-rail.tsx +58 -15
  142. package/src/components/story.tsx +225 -0
  143. package/src/components/top-comparison.stories.tsx +78 -0
  144. package/src/components/top-comparison.tsx +151 -0
  145. package/src/components/top-cross-link.stories.tsx +84 -0
  146. package/src/components/top-cross-link.tsx +171 -0
  147. package/src/components/top-ranking-entry.stories.tsx +171 -0
  148. package/src/components/top-ranking-entry.test.tsx +105 -0
  149. package/src/components/top-ranking-entry.tsx +425 -0
  150. package/src/components/top-ranking-hero.stories.tsx +76 -0
  151. package/src/components/top-ranking-hero.tsx +218 -0
  152. package/src/components/top-ranking-legend.stories.tsx +78 -0
  153. package/src/components/top-ranking-legend.tsx +239 -0
  154. package/src/components/top-types.ts +110 -0
  155. package/src/components/venue-grade-dimensions.tsx +2 -2
  156. package/dist/chunk-THOVPZNN.js +0 -37
  157. package/dist/chunk-YS6BHKZO.js +0 -92
  158. package/dist/components/ranked-venue-list.d.ts +0 -49
  159. package/dist/components/ranked-venue-list.js +0 -87
  160. package/dist/components/signature-line-list.d.ts +0 -45
  161. package/dist/components/signature-line-list.js +0 -99
  162. package/dist/components/venue-busyness-strip.d.ts +0 -35
  163. package/dist/components/venue-busyness-strip.js +0 -37
  164. package/dist/components/venue-signature-block.d.ts +0 -39
  165. package/dist/components/venue-signature-block.js +0 -6
  166. package/dist/components/venue-spotlight.d.ts +0 -74
  167. package/dist/components/venue-spotlight.js +0 -138
  168. package/src/components/ranked-venue-list.stories.tsx +0 -80
  169. package/src/components/ranked-venue-list.tsx +0 -177
  170. package/src/components/signature-line-list.stories.tsx +0 -85
  171. package/src/components/signature-line-list.tsx +0 -136
  172. package/src/components/venue-busyness-strip.stories.tsx +0 -66
  173. package/src/components/venue-busyness-strip.tsx +0 -64
  174. package/src/components/venue-signature-block.stories.tsx +0 -68
  175. package/src/components/venue-signature-block.tsx +0 -71
  176. package/src/components/venue-spotlight.stories.tsx +0 -141
  177. package/src/components/venue-spotlight.tsx +0 -236
  178. package/dist/{chunk-XWMRABZW.js → chunk-HSIYYA2E.js} +1 -1
@@ -1,24 +1,38 @@
1
- import { MenuItem } from '../chunk-TH6W2PWG.js';
2
- import '../chunk-Q6QH52LJ.js';
3
- import { MenuField } from '../chunk-YS6BHKZO.js';
4
- import '../chunk-UKBNQO6Q.js';
1
+ import { Separator } from '../chunk-WSRWFA6K.js';
2
+ import { ConceptCompareRail } from '../chunk-UDN7UHJW.js';
3
+ import '../chunk-DTXNDLSE.js';
4
+ import { PhotoGround, PHOTO_GROUND } from '../chunk-5RWTOT5Y.js';
5
+ import { Skeleton } from '../chunk-QXHMPJ35.js';
5
6
  import { cn } from '../chunk-FEK5XGZW.js';
6
7
  import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
7
- import { Star, MessageSquare } from 'lucide-react';
8
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
+ import { ArrowDown, MapPin, Star } from 'lucide-react';
9
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
10
 
10
11
  function DefaultLink(_a) {
11
12
  var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
12
13
  return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
13
14
  }
15
+ var MAX_ROOMS = 4;
16
+ var initialOf = (name) => {
17
+ var _a, _b;
18
+ return ((_b = (_a = name.match(new RegExp("\\p{L}", "u"))) == null ? void 0 : _a[0]) != null ? _b : "").toLocaleUpperCase();
19
+ };
20
+ var GROUND = PHOTO_GROUND;
21
+ var PHOTO_OVERLAY_HOVER = "transition-opacity duration-300 group-hover/room:opacity-0 motion-reduce:transition-none";
22
+ var ROOM_SCRIM = "absolute inset-0 bg-[linear-gradient(to_bottom,oklch(0.16_0.012_55_/_0)_0%,oklch(0.16_0.012_55_/_0)_30%,oklch(0.16_0.012_55_/_0.55)_58%,oklch(0.16_0.012_55_/_0.9)_100%)]";
23
+ var HEAD_GLASS = "before:pointer-events-none before:absolute before:inset-0 before:-z-10 before:content-[''] before:backdrop-blur-lg before:[mask-image:linear-gradient(to_bottom,black_35%,transparent_100%)] before:bg-[linear-gradient(to_bottom,oklch(0.16_0.012_55_/_0.8)_0%,oklch(0.16_0.012_55_/_0.6)_35%,oklch(0.16_0.012_55_/_0.22)_75%,oklch(0.16_0.012_55_/_0)_100%)]";
24
+ var COLUMNS = {
25
+ 1: "lg:grid-cols-1",
26
+ 2: "lg:grid-cols-2",
27
+ 3: "lg:grid-cols-3",
28
+ 4: "lg:grid-cols-4"
29
+ };
30
+ var DESKTOP_FOOT_CLEARANCE = "lg:pb-[104px]";
14
31
  function ConceptCompare({
15
32
  concept,
16
33
  labels,
17
- itemLabels,
34
+ lede,
18
35
  formatPrice,
19
- formatCount,
20
- gradient,
21
- imageUrl,
22
36
  figures,
23
37
  hrefs,
24
38
  footnote,
@@ -26,137 +40,199 @@ function ConceptCompare({
26
40
  linkComponent: LinkComponent = DefaultLink,
27
41
  className
28
42
  }) {
29
- var _a;
30
- const rows = (_a = concept.rows) != null ? _a : [];
31
- const cheapest = rows.reduce(
32
- (lowest, row) => lowest === void 0 || row.price < lowest ? row.price : lowest,
43
+ var _a, _b, _c;
44
+ const rooms = ((_a = concept.rows) != null ? _a : []).slice(0, MAX_ROOMS);
45
+ const count = rooms.length;
46
+ if (count === 0) return null;
47
+ const cheapest = rooms.reduce(
48
+ (lowest, room) => lowest === void 0 || room.price < lowest ? room.price : lowest,
33
49
  void 0
34
50
  );
35
- return /* @__PURE__ */ jsxs("div", { className: cn("overflow-hidden rounded-[18px] border border-border bg-card", className), children: [
36
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 p-4 lg:flex-row lg:items-center lg:gap-6 lg:p-5", children: [
37
- imageUrl ? (
38
- // eslint-disable-next-line @next/next/no-img-element
51
+ const rankOf = (_b = labels.rank) != null ? _b : ((rank) => `#${rank}`);
52
+ const hasFoot = Boolean(footnote || actions);
53
+ return /* @__PURE__ */ jsx(
54
+ "div",
55
+ {
56
+ className: cn(
57
+ /* The edge, OUTSIDE the dark scope — the one thing about this card
58
+ that belongs to the page it sits on. */
59
+ "overflow-hidden rounded-[18px] border border-border shadow-[var(--shadow-card)]",
60
+ className
61
+ ),
62
+ children: /* @__PURE__ */ jsxs("div", { className: cn("dark relative isolate flex flex-col text-foreground", GROUND), children: [
63
+ /* @__PURE__ */ jsxs(
64
+ "div",
65
+ {
66
+ className: cn(
67
+ "relative isolate flex flex-col gap-3 px-4 pb-5 pt-4",
68
+ "lg:absolute lg:inset-x-0 lg:top-0 lg:z-10 lg:flex-row lg:items-start lg:justify-between lg:gap-6 lg:px-5 lg:pb-12 lg:pt-5",
69
+ HEAD_GLASS
70
+ ),
71
+ children: [
72
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
73
+ /* @__PURE__ */ jsx("span", { className: "block text-[10.5px] font-extrabold uppercase tracking-[0.13em] text-white/70", children: labels.kind }),
74
+ /* @__PURE__ */ jsx("h3", { className: "mt-1 font-serif text-[28px] font-semibold leading-tight tracking-[-0.02em] text-white lg:text-[32px]", children: concept.title }),
75
+ lede && /* @__PURE__ */ jsx("p", { className: "mt-1 text-[13px] leading-snug text-white/75", children: lede })
76
+ ] }),
77
+ figures && figures.length > 0 && /* @__PURE__ */ jsx("dl", { className: "flex shrink-0 flex-wrap gap-x-5 gap-y-2 lg:gap-x-6", children: figures.map((figure) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start lg:items-center", children: [
78
+ /* @__PURE__ */ jsx(
79
+ "dd",
80
+ {
81
+ className: cn(
82
+ "text-[22px] font-bold leading-none tabular-nums tracking-[-0.02em]",
83
+ figure.accent ? "text-[oklch(0.82_0.15_85)]" : "text-white"
84
+ ),
85
+ children: figure.value
86
+ }
87
+ ),
88
+ /* @__PURE__ */ jsx("dt", { className: "mt-1 text-[11px] text-white/65", children: figure.label })
89
+ ] }, figure.label)) })
90
+ ]
91
+ }
92
+ ),
39
93
  /* @__PURE__ */ jsx(
40
- "img",
94
+ ConceptCompareRail,
41
95
  {
42
- src: imageUrl,
43
- alt: "",
44
- className: "aspect-[16/9] w-full shrink-0 rounded-xl object-cover lg:aspect-auto lg:h-[88px] lg:w-[88px]"
96
+ backdrops: rooms.map((room) => ({
97
+ src: room.place_thumbnail_url,
98
+ initial: initialOf(room.place_name)
99
+ })),
100
+ railClassName: cn(
101
+ "lg:grid lg:gap-px lg:overflow-visible lg:[&>*]:w-auto",
102
+ (_c = COLUMNS[count]) != null ? _c : COLUMNS[4]
103
+ ),
104
+ foot: hasFoot ? /* @__PURE__ */ jsxs(Fragment, { children: [
105
+ footnote && /* @__PURE__ */ jsx("p", { className: "min-w-0 flex-1 text-[12px] leading-relaxed text-white/70", children: footnote }),
106
+ actions && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 [&>*]:w-full lg:[&>*]:w-auto", children: actions })
107
+ ] }) : void 0,
108
+ children: rooms.map((room, index) => {
109
+ const href = hrefs == null ? void 0 : hrefs[room.place_slug];
110
+ const isCheapest = room.price === cheapest;
111
+ const roomClass = cn(
112
+ /* Transparent on the phone — the card behind it is the room's
113
+ photograph — with only its scrim and its line. A photograph of
114
+ its own from `lg`, where four stand side by side. */
115
+ "group/room relative isolate flex aspect-[4/3] flex-col justify-end overflow-hidden p-4",
116
+ "lg:aspect-auto lg:min-h-[440px] lg:p-4",
117
+ DESKTOP_FOOT_CLEARANCE
118
+ );
119
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
120
+ /* @__PURE__ */ jsxs("span", { "aria-hidden": true, className: "absolute inset-0 -z-10", children: [
121
+ /* @__PURE__ */ jsx(
122
+ PhotoGround,
123
+ {
124
+ className: "hidden lg:block",
125
+ photos: [room.place_thumbnail_url],
126
+ initials: initialOf(room.place_name),
127
+ mosaicClassName: "grid-cols-1",
128
+ overlay: true,
129
+ overlayClassName: PHOTO_OVERLAY_HOVER
130
+ }
131
+ ),
132
+ /* @__PURE__ */ jsx("span", { className: ROOM_SCRIM })
133
+ ] }),
134
+ /* @__PURE__ */ jsxs(
135
+ "span",
136
+ {
137
+ className: cn(
138
+ "inline-flex h-[22px] w-max items-center gap-1 rounded-full px-2 text-[10px] font-extrabold uppercase tracking-[0.08em]",
139
+ isCheapest ? "bg-success text-white" : "bg-white/15 text-white/85 backdrop-blur-[2px]"
140
+ ),
141
+ children: [
142
+ isCheapest && /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
143
+ isCheapest ? labels.cheapest : rankOf(index + 1)
144
+ ]
145
+ }
146
+ ),
147
+ /* @__PURE__ */ jsxs("span", { className: "mt-2.5 flex items-center gap-1.5 text-white", children: [
148
+ /* @__PURE__ */ jsx(MapPin, { className: "h-3.5 w-3.5 shrink-0 text-white/70", "aria-hidden": true }),
149
+ /* @__PURE__ */ jsx("b", { className: "min-w-0 flex-1 truncate text-[15px] font-bold leading-tight", children: room.place_name }),
150
+ room.rating !== void 0 && /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-[12px] text-white/70", children: [
151
+ /* @__PURE__ */ jsx(Star, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
152
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: room.rating })
153
+ ] })
154
+ ] }),
155
+ room.place_area && /* @__PURE__ */ jsx("span", { className: "mt-0.5 block text-[12px] text-white/70", children: room.place_area }),
156
+ /* @__PURE__ */ jsx("span", { className: "mt-2 block truncate font-serif text-[14px] italic text-white/90", children: room.alias }),
157
+ /* @__PURE__ */ jsx(Separator, { className: "my-2.5 via-white/20" }),
158
+ /* @__PURE__ */ jsxs("span", { className: "flex items-baseline gap-2", children: [
159
+ /* @__PURE__ */ jsx(
160
+ "b",
161
+ {
162
+ className: cn(
163
+ "text-[19px] font-bold leading-none tabular-nums tracking-[-0.02em]",
164
+ isCheapest ? "text-success" : "text-white"
165
+ ),
166
+ children: formatPrice(room.price)
167
+ }
168
+ ),
169
+ room.mentions !== void 0 && room.mentions > 0 && /* @__PURE__ */ jsx("span", { className: "text-[11.5px] text-white/65", children: labels.mentions(room.mentions) })
170
+ ] })
171
+ ] });
172
+ return href ? /* @__PURE__ */ jsx(
173
+ LinkComponent,
174
+ {
175
+ href,
176
+ "aria-label": labels.openRoom(room.alias, room.place_name),
177
+ className: cn(
178
+ roomClass,
179
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-white"
180
+ ),
181
+ children: body
182
+ },
183
+ room.place_slug
184
+ ) : /* @__PURE__ */ jsx("div", { className: roomClass, children: body }, room.place_slug);
185
+ })
45
186
  }
46
187
  )
47
- ) : /* @__PURE__ */ jsx(
48
- MenuField,
49
- {
50
- name: concept.title,
51
- gradient,
52
- seedKey: concept.slug,
53
- className: "aspect-[16/9] w-full shrink-0 rounded-xl lg:aspect-auto lg:h-[88px] lg:w-[88px]"
54
- }
188
+ ] })
189
+ }
190
+ );
191
+ }
192
+ function ConceptCompareSkeleton({ className }) {
193
+ return /* @__PURE__ */ jsx(
194
+ "div",
195
+ {
196
+ className: cn(
197
+ "overflow-hidden rounded-[18px] border border-border shadow-[var(--shadow-card)]",
198
+ className
55
199
  ),
56
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
57
- /* @__PURE__ */ jsx("span", { className: "text-[9.5px] font-bold uppercase tracking-[0.12em] text-muted-foreground", children: labels.kind }),
58
- /* @__PURE__ */ jsx("h3", { className: "mt-1 font-serif text-2xl font-semibold tracking-[-0.02em] lg:text-[30px]", children: concept.title })
59
- ] }),
60
- figures && figures.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 gap-6 lg:gap-8", children: figures.map((figure) => /* @__PURE__ */ jsxs("div", { className: "text-left lg:text-right", children: [
61
- /* @__PURE__ */ jsx("div", { className: "text-xl font-extrabold leading-none tracking-[-0.03em] tabular-nums lg:text-2xl", children: figure.value }),
62
- /* @__PURE__ */ jsx("div", { className: "mt-1 text-[10.5px] text-muted-foreground", children: figure.label })
63
- ] }, figure.label)) })
64
- ] }),
65
- /* @__PURE__ */ jsx("ul", { className: "border-t border-border lg:hidden", children: rows.map((row) => /* @__PURE__ */ jsx("li", { className: "border-b border-border last:border-b-0", children: /* @__PURE__ */ jsx(
66
- MenuItem,
67
- {
68
- item: {
69
- id: row.place_slug,
70
- slug: row.place_slug,
71
- // The kitchen's OWN wording leads the row — that IS the point
72
- // of the module.
73
- name: row.alias,
74
- kind: concept.kind,
75
- mentions: row.mentions,
76
- sizes_and_prices: [{ size: 0, price: row.price }]
77
- },
78
- labels: itemLabels,
79
- formatPrice,
80
- formatCount,
81
- venueName: row.place_name,
82
- href: hrefs == null ? void 0 : hrefs[row.place_slug],
83
- linkComponent: LinkComponent,
84
- className: cn(row.price === cheapest && "bg-accent-subtle/40")
85
- }
86
- ) }, row.place_slug)) }),
87
- /* @__PURE__ */ jsx("ol", { className: "hidden border-t border-border lg:block", children: rows.map((row, index) => {
88
- const isCheapest = row.price === cheapest;
89
- const content = /* @__PURE__ */ jsxs(Fragment, { children: [
90
- /* @__PURE__ */ jsx("span", { className: "w-5 shrink-0 text-center text-xs font-bold tabular-nums text-muted-foreground", children: index + 1 }),
91
- /* @__PURE__ */ jsxs("span", { className: "relative h-10 w-10 shrink-0 overflow-hidden rounded-lg bg-[repeating-linear-gradient(135deg,oklch(0.78_0.018_55)_0_8px,oklch(0.84_0.012_58)_8px_16px)]", children: [
92
- row.place_thumbnail_url && // eslint-disable-next-line @next/next/no-img-element
93
- /* @__PURE__ */ jsx(
94
- "img",
95
- {
96
- src: row.place_thumbnail_url,
97
- alt: "",
98
- loading: "lazy",
99
- className: "h-full w-full object-cover"
100
- }
101
- ),
102
- row.open_now && /* @__PURE__ */ jsx(
103
- "i",
104
- {
105
- "aria-hidden": true,
106
- className: "absolute right-0.5 top-0.5 h-[6px] w-[6px] rounded-full bg-[var(--free,currentColor)] ring-2 ring-white/80"
107
- }
108
- )
200
+ "aria-hidden": true,
201
+ children: /* @__PURE__ */ jsxs("div", { className: cn("dark relative flex flex-col text-foreground", GROUND), children: [
202
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 px-4 pb-5 pt-4 lg:absolute lg:inset-x-0 lg:top-0 lg:z-10 lg:flex-row lg:justify-between lg:px-5 lg:pt-5", children: [
203
+ /* @__PURE__ */ jsxs("div", { children: [
204
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-[90px] bg-white/15" }),
205
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-2 h-8 w-[160px] bg-white/15" }),
206
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-2 h-3.5 w-[240px] bg-white/15" })
207
+ ] }),
208
+ /* @__PURE__ */ jsx("div", { className: "flex gap-5", children: Array.from({ length: 4 }, (_, index) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-1.5 lg:items-center", children: [
209
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-8 bg-white/15" }),
210
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-12 bg-white/15" })
211
+ ] }, index)) })
109
212
  ] }),
110
- /* @__PURE__ */ jsxs("span", { className: "min-w-0 w-[200px] shrink-0", children: [
111
- /* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-bold tracking-[-0.01em]", children: row.place_name }),
112
- /* @__PURE__ */ jsxs("span", { className: "mt-px flex items-center gap-1.5 text-[11px] text-muted-foreground", children: [
113
- row.rating != null && /* @__PURE__ */ jsxs(Fragment, { children: [
114
- /* @__PURE__ */ jsx(Star, { className: "h-2.5 w-2.5", "aria-hidden": true }),
115
- /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: row.rating })
116
- ] }),
117
- row.place_area && /* @__PURE__ */ jsx("span", { className: "truncate", children: row.place_area })
118
- ] })
119
- ] }),
120
- /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
121
- /* @__PURE__ */ jsx("span", { className: "block text-[9.5px] font-bold uppercase tracking-[0.1em] text-muted-foreground", children: labels.alias }),
122
- /* @__PURE__ */ jsx("span", { className: "block truncate font-serif text-[13px] italic", children: row.alias })
123
- ] }),
124
- row.mentions != null && row.mentions > 0 && /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-[11px] tabular-nums text-muted-foreground", children: [
125
- /* @__PURE__ */ jsx(MessageSquare, { className: "h-[11px] w-[11px]", "aria-hidden": true }),
126
- row.mentions
127
- ] }),
128
- /* @__PURE__ */ jsxs("span", { className: "w-[92px] shrink-0 text-right", children: [
129
- /* @__PURE__ */ jsx(
130
- "b",
131
- {
132
- className: cn(
133
- "block text-sm font-extrabold tabular-nums",
134
- isCheapest && "text-[var(--free,currentColor)]"
135
- ),
136
- children: formatPrice(row.price)
137
- }
138
- ),
139
- /* @__PURE__ */ jsx("span", { className: "block text-[10px] text-muted-foreground", children: isCheapest && labels.cheapest ? labels.cheapest : labels.perPortion })
213
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 lg:grid-cols-4 lg:gap-px", children: Array.from({ length: 4 }, (_, index) => /* @__PURE__ */ jsxs(
214
+ "div",
215
+ {
216
+ className: cn(
217
+ "flex aspect-[4/3] flex-col justify-end p-4 lg:aspect-auto lg:min-h-[440px] lg:pb-[104px]",
218
+ index > 0 && "hidden lg:flex"
219
+ ),
220
+ children: [
221
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-[22px] w-[72px] rounded-full bg-white/15" }),
222
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-2.5 h-4 w-[60%] bg-white/15" }),
223
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-2 h-3.5 w-[50%] bg-white/15" }),
224
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-4 h-5 w-[80px] bg-white/15" })
225
+ ]
226
+ },
227
+ index
228
+ )) }),
229
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 px-4 pb-4 pt-3 lg:absolute lg:inset-x-0 lg:bottom-0 lg:flex-row lg:items-center lg:gap-5 lg:px-5 lg:pb-4 lg:pt-6", children: [
230
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-full bg-white/15 lg:flex-1" }),
231
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full rounded-full bg-white/15 lg:w-[120px]" })
140
232
  ] })
141
- ] });
142
- const rowClasses = "flex items-center gap-4 px-5 py-3";
143
- return /* @__PURE__ */ jsx("li", { className: "border-b border-border last:border-b-0", children: (hrefs == null ? void 0 : hrefs[row.place_slug]) ? /* @__PURE__ */ jsx(
144
- LinkComponent,
145
- {
146
- href: hrefs[row.place_slug],
147
- className: cn(
148
- rowClasses,
149
- "transition-colors hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
150
- ),
151
- children: content
152
- }
153
- ) : /* @__PURE__ */ jsx("div", { className: rowClasses, children: content }) }, row.place_slug);
154
- }) }),
155
- (footnote || actions) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 p-4", children: [
156
- footnote && /* @__PURE__ */ jsx("span", { className: "text-[11.5px] text-muted-foreground", children: footnote }),
157
- actions && /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center gap-2", children: actions })
158
- ] })
159
- ] });
233
+ ] })
234
+ }
235
+ );
160
236
  }
161
237
 
162
- export { ConceptCompare };
238
+ export { ConceptCompare, ConceptCompareSkeleton };
@@ -0,0 +1,41 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * ConceptConvergence — many names, one dish, drawn on a dark stage.
5
+ *
6
+ * The explainer's proof: the kitchens' OWN spellings of a dish, each with its
7
+ * price, converging on the one concept they were matched into. Five visibly
8
+ * different strings under one photograph with one price column say what a
9
+ * paragraph about "matching" cannot.
10
+ *
11
+ * Drawn for the explainer's dark stage, and only there: the chips are white
12
+ * on ink, not a family's hue — the tint was doing no work once the stage
13
+ * went dark, and the spellings are the point, not the kitchens' cuisines.
14
+ * The concept card is the venue's real photograph, never the item's (which
15
+ * is generated), on the same ground as every photographed card.
16
+ */
17
+ type ConceptConvergenceAlias = {
18
+ /** The kitchen's spelling, verbatim. */
19
+ label: string;
20
+ /** Pre-formatted, e.g. "32 lei". */
21
+ price: string;
22
+ };
23
+ type ConceptConvergenceProps = {
24
+ aliases: ConceptConvergenceAlias[];
25
+ concept: {
26
+ title: string;
27
+ /** A room's photograph — venue photography only. */
28
+ photoUrl?: string;
29
+ /** "32 names" — the badge on the card. */
30
+ badge: string;
31
+ };
32
+ /**
33
+ * Low, middle and high of the ruler under the diagram, e.g.
34
+ * `["8 lei", "45 kitchens", "44 lei"]`. All three, or none.
35
+ */
36
+ scale?: [string, string, string];
37
+ className?: string;
38
+ };
39
+ declare function ConceptConvergence({ aliases, concept, scale, className }: ConceptConvergenceProps): react_jsx_runtime.JSX.Element;
40
+
41
+ export { ConceptConvergence, type ConceptConvergenceAlias, type ConceptConvergenceProps };
@@ -0,0 +1,53 @@
1
+ import { PhotoGround } from '../chunk-5RWTOT5Y.js';
2
+ import { Convergence } from '../chunk-MZL7CGCL.js';
3
+ import '../chunk-LEAYBICI.js';
4
+ import { Badge } from '../chunk-UKBNQO6Q.js';
5
+ import { cn } from '../chunk-FEK5XGZW.js';
6
+ import '../chunk-3GWWZKX7.js';
7
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
+
9
+ function ConceptConvergence({ aliases, concept, scale, className }) {
10
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3 text-white", className), children: [
11
+ /* @__PURE__ */ jsx(
12
+ Convergence,
13
+ {
14
+ linesClassName: "text-white/30",
15
+ sources: aliases.map((alias, index) => /* @__PURE__ */ jsxs(
16
+ "span",
17
+ {
18
+ className: "inline-flex h-7 max-w-full items-center gap-1.5 rounded-full bg-white/10 px-2.5 text-[11.5px] text-white",
19
+ children: [
20
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: alias.label }),
21
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 tabular-nums text-white/60", children: alias.price })
22
+ ]
23
+ },
24
+ index
25
+ )),
26
+ target: /* @__PURE__ */ jsxs("span", { className: "relative isolate block aspect-[4/5] w-[112px] overflow-hidden rounded-[16px] shadow-[0_8px_24px_oklch(0_0_0/0.35)]", children: [
27
+ /* @__PURE__ */ jsx(
28
+ PhotoGround,
29
+ {
30
+ className: "-z-10",
31
+ mode: "stack",
32
+ photos: [concept.photoUrl],
33
+ initials: concept.title.charAt(0).toLocaleUpperCase(),
34
+ overlay: true,
35
+ loading: "eager"
36
+ }
37
+ ),
38
+ /* @__PURE__ */ jsx(Badge, { variant: "overlay", className: "absolute left-2 top-2", children: concept.badge }),
39
+ /* @__PURE__ */ jsx("span", { className: "absolute inset-x-2 bottom-2 block text-balance font-serif text-[17px] font-semibold leading-tight tracking-[-0.02em] [text-shadow:0_1px_8px_oklch(0_0_0/0.5)]", children: concept.title })
40
+ ] })
41
+ }
42
+ ),
43
+ scale && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[11px] tabular-nums text-white/60", children: [
44
+ /* @__PURE__ */ jsx("span", { children: scale[0] }),
45
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-px flex-1 bg-white/20" }),
46
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-white", children: scale[1] }),
47
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-px flex-1 bg-white/20" }),
48
+ /* @__PURE__ */ jsx("span", { children: scale[2] })
49
+ ] })
50
+ ] });
51
+ }
52
+
53
+ export { ConceptConvergence };
@@ -0,0 +1,25 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ type ConvergeLinesProps = {
5
+ /** How many sources the lines leave from. */
6
+ count: number;
7
+ /** Draw the curves in, source by source. Off: drawn already. */
8
+ animate?: boolean;
9
+ className?: string;
10
+ };
11
+ declare function ConvergeLines({ count, animate, className }: ConvergeLinesProps): react_jsx_runtime.JSX.Element;
12
+ type ConvergenceProps = {
13
+ /** The many. One node each; the stack fans slightly so it reads as a spread, not a list. */
14
+ sources: ReactNode[];
15
+ /** The one. */
16
+ target: ReactNode;
17
+ /** The entrance choreography. Off for static reuse; the reader's reduced-motion setting is honoured either way. */
18
+ animate?: boolean;
19
+ /** The curves' colour, e.g. `"text-white/30"` on a dark stage. Defaults to the border. */
20
+ linesClassName?: string;
21
+ className?: string;
22
+ };
23
+ declare function Convergence({ sources, target, animate, linesClassName, className, }: ConvergenceProps): react_jsx_runtime.JSX.Element;
24
+
25
+ export { ConvergeLines, type ConvergeLinesProps, Convergence, type ConvergenceProps };
@@ -0,0 +1,4 @@
1
+ export { ConvergeLines, Convergence } from '../chunk-MZL7CGCL.js';
2
+ import '../chunk-LEAYBICI.js';
3
+ import '../chunk-FEK5XGZW.js';
4
+ import '../chunk-3GWWZKX7.js';
@@ -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";
@@ -1,5 +1,5 @@
1
- import { TagGroup } from '../chunk-6XMYEZVR.js';
2
1
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
2
+ import { TagGroup } from '../chunk-6XMYEZVR.js';
3
3
  import { Tag } from '../chunk-ZDAHKI3A.js';
4
4
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
5
5
  import { Skeleton } from '../chunk-QXHMPJ35.js';
@@ -1,5 +1,5 @@
1
- import { TagGroup } from '../chunk-6XMYEZVR.js';
2
1
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
2
+ import { TagGroup } from '../chunk-6XMYEZVR.js';
3
3
  import { Tag } from '../chunk-ZDAHKI3A.js';
4
4
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
5
5
  import { Skeleton } from '../chunk-QXHMPJ35.js';
@@ -1,5 +1,5 @@
1
- import { Separator } from '../chunk-WSRWFA6K.js';
2
1
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
2
+ import { Separator } from '../chunk-WSRWFA6K.js';
3
3
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
4
4
  import { Skeleton } from '../chunk-QXHMPJ35.js';
5
5
  import { Button } from '../chunk-H3BV4VAG.js';
@@ -1,6 +1,6 @@
1
- import { Separator } from '../chunk-WSRWFA6K.js';
2
1
  import { TagGroup } from '../chunk-6XMYEZVR.js';
3
2
  import { Tag } from '../chunk-ZDAHKI3A.js';
3
+ import { Separator } from '../chunk-WSRWFA6K.js';
4
4
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
5
5
  import { cn } from '../chunk-FEK5XGZW.js';
6
6
  import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
@@ -1,6 +1,6 @@
1
- import { Separator } from '../chunk-WSRWFA6K.js';
2
1
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
3
2
  import { Tag } from '../chunk-ZDAHKI3A.js';
3
+ import { Separator } from '../chunk-WSRWFA6K.js';
4
4
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
5
5
  import { Skeleton } from '../chunk-QXHMPJ35.js';
6
6
  import { buttonVariants } from '../chunk-H3BV4VAG.js';
@@ -1,7 +1,7 @@
1
- import { Separator } from '../chunk-WSRWFA6K.js';
2
- import { TagGroup } from '../chunk-6XMYEZVR.js';
3
1
  import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
2
+ import { TagGroup } from '../chunk-6XMYEZVR.js';
4
3
  import { Tag } from '../chunk-ZDAHKI3A.js';
4
+ import { Separator } from '../chunk-WSRWFA6K.js';
5
5
  import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
6
6
  import { Skeleton } from '../chunk-QXHMPJ35.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -0,0 +1,34 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * ExplainerSteps — how something works, as numbered rules a reader can scan.
6
+ *
7
+ * Each step is a numeral in a ring, one line of prose, and the live figure
8
+ * that proves the line, right-aligned with its unit. A thread runs from one
9
+ * numeral to the next so the three read as a sequence, and the last numeral
10
+ * is filled: the rules end where the reader is asked to do something.
11
+ *
12
+ * A step without a figure shows none — an invented number in the column is
13
+ * worse than an empty one. But a list where no step has a figure should be
14
+ * prose, not steps.
15
+ *
16
+ * Server-safe. Data in, not children: a server component composes these from
17
+ * translated strings and numbers, and an array is easier to number than a
18
+ * child list is to clone.
19
+ */
20
+ type ExplainerStepItem = {
21
+ /** One line. Two at most on a phone; a third is a paragraph and belongs elsewhere. */
22
+ text: ReactNode;
23
+ /** The live figure, pre-formatted. */
24
+ figure?: string;
25
+ /** A unit or caption beside the figure, e.g. "names". */
26
+ unit?: string;
27
+ };
28
+ type ExplainerStepsProps = {
29
+ steps: ExplainerStepItem[];
30
+ className?: string;
31
+ };
32
+ declare function ExplainerSteps({ steps, className }: ExplainerStepsProps): react_jsx_runtime.JSX.Element;
33
+
34
+ export { type ExplainerStepItem, ExplainerSteps, type ExplainerStepsProps };
@@ -0,0 +1,36 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import '../chunk-3GWWZKX7.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ function ExplainerSteps({ steps, className }) {
6
+ return /* @__PURE__ */ jsx("ol", { className: cn("flex flex-col", className), children: steps.map((step, index) => {
7
+ const isLast = index === steps.length - 1;
8
+ return /* @__PURE__ */ jsxs("li", { className: "relative flex gap-3.5 pb-5 last:pb-0", children: [
9
+ !isLast && /* @__PURE__ */ jsx(
10
+ "span",
11
+ {
12
+ "aria-hidden": true,
13
+ className: "absolute bottom-0 left-[11px] top-7 w-px bg-border"
14
+ }
15
+ ),
16
+ /* @__PURE__ */ jsx(
17
+ "span",
18
+ {
19
+ "aria-hidden": true,
20
+ className: cn(
21
+ "relative flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-[11px] font-bold tabular-nums",
22
+ isLast ? "bg-primary text-primary-foreground" : "border border-border bg-background text-muted-foreground"
23
+ ),
24
+ children: index + 1
25
+ }
26
+ ),
27
+ /* @__PURE__ */ jsx("p", { className: "min-w-0 flex-1 pt-0.5 text-[14px] leading-[1.45] text-foreground", children: step.text }),
28
+ step.figure && /* @__PURE__ */ jsxs("span", { className: "shrink-0 pt-0.5 text-right text-[15px] font-bold leading-[1.45] tabular-nums text-foreground", children: [
29
+ step.figure,
30
+ step.unit && /* @__PURE__ */ jsx("span", { className: "ml-1 text-[11px] font-normal text-muted-foreground", children: step.unit })
31
+ ] })
32
+ ] }, index);
33
+ }) });
34
+ }
35
+
36
+ export { ExplainerSteps };