@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.
- package/dist/chunk-24RFI4RQ.js +167 -0
- package/dist/{chunk-UKBNQO6Q.js → chunk-2CXU5WZO.js} +1 -1
- package/dist/chunk-2XCZJWTV.js +121 -0
- package/dist/{chunk-62ES6N32.js → chunk-43RC7MHY.js} +1 -1
- package/dist/chunk-5RWTOT5Y.js +72 -0
- package/dist/{chunk-Q6QH52LJ.js → chunk-6TEEY5YA.js} +2 -2
- package/dist/{chunk-AXV5O2IZ.js → chunk-AKQ57NXY.js} +3 -3
- package/dist/chunk-CLLY6XB3.js +41 -0
- package/dist/chunk-DTXNDLSE.js +125 -0
- package/dist/chunk-F6FMZJDG.js +113 -0
- package/dist/{chunk-2WDJR6K7.js → chunk-G7IFL4Z4.js} +4 -1
- package/dist/chunk-H3ZZDX5L.js +61 -0
- package/dist/{chunk-H3BV4VAG.js → chunk-JS3EINZD.js} +2 -2
- package/dist/chunk-MZL7CGCL.js +109 -0
- package/dist/{chunk-TH6W2PWG.js → chunk-UDTG3RSE.js} +1 -1
- package/dist/chunk-WCTHZKU7.js +37 -0
- package/dist/{chunk-TT3WFS6S.js → chunk-YOKHBAIH.js} +11 -11
- package/dist/components/alert-dialog.js +1 -1
- package/dist/components/alert.d.ts +2 -2
- package/dist/components/avatar.d.ts +3 -3
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/button.d.ts +2 -2
- package/dist/components/button.js +1 -1
- package/dist/components/calendar.js +1 -1
- package/dist/components/card.d.ts +4 -4
- package/dist/components/carousel.js +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/components/command.d.ts +2 -2
- package/dist/components/concept-compare-rail.d.ts +50 -0
- package/dist/components/concept-compare-rail.js +5 -0
- package/dist/components/concept-compare.d.ts +75 -38
- package/dist/components/concept-compare.js +209 -133
- package/dist/components/concept-convergence.d.ts +41 -0
- package/dist/components/concept-convergence.js +53 -0
- package/dist/components/convergence.d.ts +25 -0
- package/dist/components/convergence.js +4 -0
- package/dist/components/dialog.d.ts +2 -2
- package/dist/components/empty-state.js +1 -1
- package/dist/components/event-card.js +1 -1
- package/dist/components/event-compact-row.js +1 -1
- package/dist/components/event-detail-panel.js +2 -2
- package/dist/components/event-index-row.js +1 -1
- package/dist/components/event-list-row-wide.js +2 -2
- package/dist/components/event-list-row.js +2 -2
- package/dist/components/explainer-steps.d.ts +34 -0
- package/dist/components/explainer-steps.js +36 -0
- package/dist/components/filter-category-row.js +1 -1
- package/dist/components/glass-ground.d.ts +61 -0
- package/dist/components/glass-ground.js +3 -0
- package/dist/components/haptic-button.js +1 -1
- package/dist/components/hub-surface.js +11 -1
- package/dist/components/hue-chip.d.ts +70 -0
- package/dist/components/hue-chip.js +3 -0
- package/dist/components/input-group.d.ts +2 -2
- package/dist/components/input.d.ts +1 -1
- package/dist/components/item.d.ts +4 -4
- package/dist/components/kbd.d.ts +2 -2
- package/dist/components/kitchen-dossier.d.ts +88 -0
- package/dist/components/kitchen-dossier.js +186 -0
- package/dist/components/link-button.js +1 -1
- package/dist/components/menu-dead-end.d.ts +56 -0
- package/dist/components/menu-dead-end.js +49 -0
- package/dist/components/menu-family-block.d.ts +98 -0
- package/dist/components/menu-family-block.js +153 -0
- package/dist/components/menu-family-card.d.ts +33 -27
- package/dist/components/menu-family-card.js +41 -85
- package/dist/components/menu-field.js +92 -2
- package/dist/components/menu-filter-chips.d.ts +86 -0
- package/dist/components/menu-filter-chips.js +122 -0
- package/dist/components/menu-group-rows.d.ts +53 -0
- package/dist/components/menu-group-rows.js +67 -0
- package/dist/components/menu-hub-hero.js +10 -5
- package/dist/components/menu-index-header.d.ts +37 -0
- package/dist/components/menu-index-header.js +68 -0
- package/dist/components/menu-index-list.d.ts +48 -0
- package/dist/components/menu-index-list.js +96 -0
- package/dist/components/menu-intent-hero.d.ts +69 -0
- package/dist/components/menu-intent-hero.js +87 -0
- package/dist/components/menu-item.js +3 -3
- package/dist/components/menu-kitchen-list.d.ts +82 -0
- package/dist/components/menu-kitchen-list.js +5 -0
- package/dist/components/menu-mocks.d.ts +37 -2
- package/dist/components/menu-mocks.js +152 -27
- package/dist/components/menu-types.d.ts +182 -6
- package/dist/components/motion-icon-controls.js +2 -2
- package/dist/components/motion-icon-set.js +6 -6
- package/dist/components/motion-icon.d.ts +22 -1
- package/dist/components/motion-icon.js +1 -1
- package/dist/components/multi-select-combobox.js +2 -2
- package/dist/components/native-select.d.ts +2 -2
- package/dist/components/pagination.js +1 -1
- package/dist/components/photo-ground.d.ts +64 -0
- package/dist/components/photo-ground.js +3 -0
- package/dist/components/place-about-tab.js +2 -2
- package/dist/components/place-details-mobile.js +3 -3
- package/dist/components/place-types.d.ts +2 -2
- package/dist/components/qa-block.d.ts +36 -0
- package/dist/components/qa-block.js +24 -0
- package/dist/components/scroll-fade.js +3 -121
- package/dist/components/searchable-select.js +1 -1
- package/dist/components/select.d.ts +1 -1
- package/dist/components/signature-chip.d.ts +2 -2
- package/dist/components/signature-chip.js +2 -2
- package/dist/components/sliding-panels.js +1 -1
- package/dist/components/snap-rail.d.ts +26 -3
- package/dist/components/snap-rail.js +3 -109
- package/dist/components/spinner.d.ts +4 -4
- package/dist/components/story.d.ts +34 -0
- package/dist/components/story.js +3 -0
- package/dist/components/tag.d.ts +4 -4
- package/dist/components/text.d.ts +5 -5
- package/dist/components/toggle.d.ts +1 -1
- package/dist/components/top-comparison.d.ts +28 -0
- package/dist/components/top-comparison.js +76 -0
- package/dist/components/top-cross-link.d.ts +34 -0
- package/dist/components/top-cross-link.js +101 -0
- package/dist/components/top-ranking-entry.d.ts +53 -0
- package/dist/components/top-ranking-entry.js +217 -0
- package/dist/components/top-ranking-hero.d.ts +61 -0
- package/dist/components/top-ranking-hero.js +99 -0
- package/dist/components/top-ranking-legend.d.ts +69 -0
- package/dist/components/top-ranking-legend.js +124 -0
- package/dist/components/top-types.d.ts +109 -0
- package/dist/components/top-types.js +1 -0
- package/dist/components/venue-grade-dimensions.d.ts +3 -1
- package/dist/components/venue-grade-dimensions.js +1 -1
- package/dist/components/venue-quotes.d.ts +1 -1
- package/dist/components/venue-quotes.js +1 -1
- package/dist/components/venue-wall.js +5 -3
- package/dist/components/weekday-theme-banner.js +1 -1
- package/dist/components/weekend-panel.js +2 -2
- package/package.json +1 -1
- package/src/components/badge.tsx +1 -1
- package/src/components/button.tsx +2 -2
- package/src/components/concept-compare-rail.tsx +132 -0
- package/src/components/concept-compare.stories.tsx +122 -54
- package/src/components/concept-compare.tsx +368 -196
- package/src/components/concept-convergence.stories.tsx +53 -0
- package/src/components/concept-convergence.tsx +90 -0
- package/src/components/convergence.stories.tsx +54 -0
- package/src/components/convergence.tsx +177 -0
- package/src/components/explainer-steps.stories.tsx +46 -0
- package/src/components/explainer-steps.tsx +74 -0
- package/src/components/glass-ground.tsx +104 -0
- package/src/components/hub-surface.tsx +11 -1
- package/src/components/hue-chip.stories.tsx +76 -0
- package/src/components/hue-chip.test.tsx +62 -0
- package/src/components/hue-chip.tsx +99 -0
- package/src/components/kitchen-dossier.stories.tsx +108 -0
- package/src/components/kitchen-dossier.tsx +321 -0
- package/src/components/menu-dead-end.stories.tsx +67 -0
- package/src/components/menu-dead-end.tsx +127 -0
- package/src/components/menu-family-block.stories.tsx +91 -0
- package/src/components/menu-family-block.tsx +303 -0
- package/src/components/menu-family-card.stories.tsx +43 -35
- package/src/components/menu-family-card.tsx +115 -142
- package/src/components/menu-filter-chips.stories.tsx +107 -0
- package/src/components/menu-filter-chips.tsx +238 -0
- package/src/components/menu-group-rows.stories.tsx +54 -0
- package/src/components/menu-group-rows.tsx +133 -0
- package/src/components/menu-hub-hero.test.tsx +39 -0
- package/src/components/menu-hub-hero.tsx +17 -5
- package/src/components/menu-index-header.stories.tsx +72 -0
- package/src/components/menu-index-header.tsx +125 -0
- package/src/components/menu-index-list.stories.tsx +50 -0
- package/src/components/menu-index-list.tsx +149 -0
- package/src/components/menu-intent-hero.stories.tsx +67 -0
- package/src/components/menu-intent-hero.tsx +189 -0
- package/src/components/menu-kitchen-list.stories.tsx +67 -0
- package/src/components/menu-kitchen-list.test.tsx +78 -0
- package/src/components/menu-kitchen-list.tsx +284 -0
- package/src/components/menu-mocks.ts +198 -23
- package/src/components/menu-types.ts +189 -6
- package/src/components/motion-icon-controls.tsx +11 -11
- package/src/components/motion-icon-set.tsx +6 -5
- package/src/components/motion-icon.test.tsx +23 -1
- package/src/components/motion-icon.tsx +20 -0
- package/src/components/photo-ground.tsx +147 -0
- package/src/components/place-types.ts +2 -2
- package/src/components/qa-block.stories.tsx +43 -0
- package/src/components/qa-block.tsx +60 -0
- package/src/components/signature-chip.tsx +3 -3
- package/src/components/snap-rail.tsx +58 -15
- package/src/components/story.tsx +225 -0
- package/src/components/top-comparison.stories.tsx +78 -0
- package/src/components/top-comparison.tsx +151 -0
- package/src/components/top-cross-link.stories.tsx +84 -0
- package/src/components/top-cross-link.tsx +171 -0
- package/src/components/top-ranking-entry.stories.tsx +171 -0
- package/src/components/top-ranking-entry.test.tsx +105 -0
- package/src/components/top-ranking-entry.tsx +425 -0
- package/src/components/top-ranking-hero.stories.tsx +76 -0
- package/src/components/top-ranking-hero.tsx +218 -0
- package/src/components/top-ranking-legend.stories.tsx +78 -0
- package/src/components/top-ranking-legend.tsx +239 -0
- package/src/components/top-types.ts +110 -0
- package/src/components/venue-grade-dimensions.tsx +2 -2
- package/src/components/venue-quotes.stories.tsx +1 -1
- package/src/components/venue-quotes.tsx +4 -2
- package/src/components/venue-wall.tsx +9 -4
- package/src/components/weekday-theme-banner.tsx +1 -1
- package/dist/chunk-THOVPZNN.js +0 -37
- package/dist/chunk-YS6BHKZO.js +0 -92
- package/dist/components/ranked-venue-list.d.ts +0 -49
- package/dist/components/ranked-venue-list.js +0 -87
- package/dist/components/signature-line-list.d.ts +0 -45
- package/dist/components/signature-line-list.js +0 -99
- package/dist/components/venue-busyness-strip.d.ts +0 -35
- package/dist/components/venue-busyness-strip.js +0 -37
- package/dist/components/venue-signature-block.d.ts +0 -39
- package/dist/components/venue-signature-block.js +0 -6
- package/dist/components/venue-spotlight.d.ts +0 -74
- package/dist/components/venue-spotlight.js +0 -138
- package/src/components/ranked-venue-list.stories.tsx +0 -80
- package/src/components/ranked-venue-list.tsx +0 -177
- package/src/components/signature-line-list.stories.tsx +0 -85
- package/src/components/signature-line-list.tsx +0 -136
- package/src/components/venue-busyness-strip.stories.tsx +0 -66
- package/src/components/venue-busyness-strip.tsx +0 -64
- package/src/components/venue-signature-block.stories.tsx +0 -68
- package/src/components/venue-signature-block.tsx +0 -71
- package/src/components/venue-spotlight.stories.tsx +0 -141
- package/src/components/venue-spotlight.tsx +0 -236
- package/dist/{chunk-XWMRABZW.js → chunk-HSIYYA2E.js} +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-UKBNQO6Q.js';
|
|
1
|
+
import { HueChip } from '../chunk-CLLY6XB3.js';
|
|
2
|
+
import { PhotoGround, PHOTO_GROUND } from '../chunk-5RWTOT5Y.js';
|
|
4
3
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
5
4
|
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|
|
6
5
|
import { Wallet } from 'lucide-react';
|
|
@@ -11,107 +10,64 @@ function DefaultLink(_a) {
|
|
|
11
10
|
return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
|
|
12
11
|
}
|
|
13
12
|
var MOSAIC_CELLS = 4;
|
|
13
|
+
var GROUND = PHOTO_GROUND;
|
|
14
|
+
var INK = "bg-[linear-gradient(to_bottom,oklch(0.16_0.012_55_/_0.78)_0%,oklch(0.16_0.012_55_/_0.5)_34%,oklch(0.16_0.012_55_/_0.86)_62%,oklch(0.16_0.012_55_/_0.96)_100%)]";
|
|
14
15
|
function MenuFamilyCard({
|
|
15
16
|
family,
|
|
16
17
|
labels,
|
|
17
|
-
itemLabels,
|
|
18
|
-
formatPrice,
|
|
19
|
-
formatCount,
|
|
20
18
|
href,
|
|
21
19
|
hue,
|
|
20
|
+
gradient,
|
|
22
21
|
priceBandLabel,
|
|
23
22
|
linkComponent: LinkComponent = DefaultLink,
|
|
24
23
|
className
|
|
25
24
|
}) {
|
|
26
|
-
var _a, _b, _c;
|
|
25
|
+
var _a, _b, _c, _d;
|
|
27
26
|
const photos = (_a = family.venue_photo_urls) != null ? _a : [];
|
|
28
|
-
const
|
|
27
|
+
const tiles = photos.length ? Array.from({ length: MOSAIC_CELLS }, (_, cell) => photos[cell % photos.length]) : [void 0];
|
|
29
28
|
return /* @__PURE__ */ jsxs(
|
|
30
|
-
|
|
29
|
+
LinkComponent,
|
|
31
30
|
{
|
|
31
|
+
href,
|
|
32
32
|
className: cn(
|
|
33
|
-
"flex h-
|
|
33
|
+
"group dark relative isolate flex min-h-[280px] flex-col justify-between overflow-hidden rounded-[14px] border border-border p-3.5",
|
|
34
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-white",
|
|
35
|
+
GROUND,
|
|
34
36
|
className
|
|
35
37
|
),
|
|
36
38
|
children: [
|
|
37
|
-
/* @__PURE__ */
|
|
38
|
-
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
PhotoGround,
|
|
39
41
|
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
(_, cell) => photos.length ? (
|
|
46
|
-
// eslint-disable-next-line @next/next/no-img-element
|
|
47
|
-
/* @__PURE__ */ jsx(
|
|
48
|
-
"img",
|
|
49
|
-
{
|
|
50
|
-
src: photos[cell % photos.length],
|
|
51
|
-
alt: "",
|
|
52
|
-
loading: "lazy",
|
|
53
|
-
decoding: "async",
|
|
54
|
-
className: "h-full w-full object-cover"
|
|
55
|
-
},
|
|
56
|
-
cell
|
|
57
|
-
)
|
|
58
|
-
) : /* @__PURE__ */ jsx(
|
|
59
|
-
"span",
|
|
60
|
-
{
|
|
61
|
-
className: "bg-[repeating-linear-gradient(135deg,oklch(0.6_0.02_55)_0_9px,oklch(0.68_0.016_58)_9px_18px)] opacity-[0.18]"
|
|
62
|
-
},
|
|
63
|
-
cell
|
|
64
|
-
)
|
|
65
|
-
) }),
|
|
66
|
-
hue && /* @__PURE__ */ jsx(
|
|
67
|
-
"span",
|
|
68
|
-
{
|
|
69
|
-
"aria-hidden": true,
|
|
70
|
-
className: "absolute inset-0 opacity-90 mix-blend-color",
|
|
71
|
-
style: { backgroundColor: hue }
|
|
72
|
-
}
|
|
73
|
-
),
|
|
74
|
-
/* @__PURE__ */ jsx(
|
|
75
|
-
"span",
|
|
76
|
-
{
|
|
77
|
-
"aria-hidden": true,
|
|
78
|
-
className: "absolute inset-0 bg-[linear-gradient(180deg,oklch(0.16_0.012_55_/_0.9)_0%,oklch(0.16_0.012_55_/_0.62)_45%,oklch(0.16_0.012_55_/_0.94)_100%)]"
|
|
79
|
-
}
|
|
80
|
-
),
|
|
81
|
-
/* @__PURE__ */ jsxs("span", { className: "relative flex min-h-[260px] flex-col justify-between p-3.5 text-white", children: [
|
|
82
|
-
/* @__PURE__ */ jsxs("span", { className: "block", children: [
|
|
83
|
-
/* @__PURE__ */ jsx("b", { className: "block text-[34px] font-extrabold leading-none tracking-[-0.03em] tabular-nums", children: family.venue_count }),
|
|
84
|
-
/* @__PURE__ */ jsx("span", { className: "mt-1 block text-[9.5px] font-bold tracking-[0.12em] opacity-80", children: labels.venueUnit })
|
|
85
|
-
] }),
|
|
86
|
-
/* @__PURE__ */ jsxs("span", { className: "block", children: [
|
|
87
|
-
/* @__PURE__ */ jsx("span", { className: "block text-[17px] font-bold tracking-[-0.01em]", children: family.name }),
|
|
88
|
-
groups.length > 0 && /* @__PURE__ */ jsx("span", { className: "mt-0.5 block truncate text-[11.5px] opacity-75", children: groups.join(" \xB7 ") }),
|
|
89
|
-
priceBandLabel && /* @__PURE__ */ jsxs("span", { className: "mt-2 inline-flex items-center gap-1.5 rounded-full bg-white/15 px-2.5 py-1 text-[11px] backdrop-blur-[2px]", children: [
|
|
90
|
-
/* @__PURE__ */ jsx(Wallet, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
|
|
91
|
-
/* @__PURE__ */ jsx("span", { className: "opacity-80", children: labels.priceBand }),
|
|
92
|
-
/* @__PURE__ */ jsx("b", { className: "font-semibold tabular-nums", children: priceBandLabel })
|
|
93
|
-
] })
|
|
94
|
-
] })
|
|
95
|
-
] })
|
|
96
|
-
]
|
|
42
|
+
className: "-z-30",
|
|
43
|
+
photos: tiles,
|
|
44
|
+
initials: family.name.charAt(0),
|
|
45
|
+
mosaicClassName: photos.length ? "grid-cols-2 grid-rows-2" : "grid-cols-1",
|
|
46
|
+
gradient
|
|
97
47
|
}
|
|
98
48
|
),
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
/* @__PURE__ */ jsx(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
49
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("absolute inset-0 -z-10", INK) }),
|
|
50
|
+
/* @__PURE__ */ jsxs("span", { className: "block text-white", children: [
|
|
51
|
+
/* @__PURE__ */ jsx("b", { className: "block text-[34px] font-extrabold leading-none tracking-[-0.03em] tabular-nums", children: family.venue_count }),
|
|
52
|
+
/* @__PURE__ */ jsx("span", { className: "mt-1 block text-[9.5px] font-bold uppercase tracking-[0.12em] opacity-80", children: labels.venueUnit })
|
|
53
|
+
] }),
|
|
54
|
+
/* @__PURE__ */ jsxs("span", { className: "block", children: [
|
|
55
|
+
/* @__PURE__ */ jsx("span", { className: "block text-balance font-serif text-[24px] font-semibold leading-tight tracking-[-0.02em] text-white", children: family.name }),
|
|
56
|
+
(priceBandLabel || ((_c = (_b = family.chips) == null ? void 0 : _b.length) != null ? _c : 0) > 0) && /* @__PURE__ */ jsxs("span", { className: "mt-2.5 flex flex-wrap items-center gap-1.5", children: [
|
|
57
|
+
priceBandLabel && /* No hue: a fact about money, not about the family. In the dark
|
|
58
|
+
scope `HueChip`'s `--muted` fallback is the dark pill. */
|
|
59
|
+
/* @__PURE__ */ jsx(
|
|
60
|
+
HueChip,
|
|
61
|
+
{
|
|
62
|
+
className: "font-bold tabular-nums",
|
|
63
|
+
"aria-label": `${labels.priceBand}: ${priceBandLabel}`,
|
|
64
|
+
icon: /* @__PURE__ */ jsx(Wallet, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true }),
|
|
65
|
+
children: priceBandLabel
|
|
66
|
+
}
|
|
67
|
+
),
|
|
68
|
+
(_d = family.chips) == null ? void 0 : _d.map((chip) => /* @__PURE__ */ jsx(HueChip, { hue, children: chip.label }, chip.slug))
|
|
69
|
+
] }),
|
|
70
|
+
/* @__PURE__ */ jsx("span", { className: "mt-3.5 inline-flex h-10 items-center rounded-full border border-white/20 bg-white/[0.16] px-4 text-[13.5px] font-bold text-white transition-colors group-hover:bg-white/25 motion-reduce:transition-none", children: labels.browse })
|
|
115
71
|
] })
|
|
116
72
|
]
|
|
117
73
|
}
|
|
@@ -1,3 +1,93 @@
|
|
|
1
|
-
|
|
2
|
-
import '../chunk-FEK5XGZW.js';
|
|
1
|
+
import { cn } from '../chunk-FEK5XGZW.js';
|
|
3
2
|
import '../chunk-3GWWZKX7.js';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var GHOST_ROWS = 13;
|
|
6
|
+
var GHOST_CENTRE = (GHOST_ROWS - 1) / 2;
|
|
7
|
+
var ALPHA_PEAK = 0.44;
|
|
8
|
+
var ALPHA_EDGE = 0;
|
|
9
|
+
var FALLOFF_EXPONENT = 3.4;
|
|
10
|
+
var GHOST_LINE_CHARS = 56;
|
|
11
|
+
function hashString(input) {
|
|
12
|
+
let hash = 5381;
|
|
13
|
+
for (let i = 0; i < input.length; i++) hash = hash * 33 ^ input.charCodeAt(i);
|
|
14
|
+
return Math.abs(hash);
|
|
15
|
+
}
|
|
16
|
+
function MenuField({
|
|
17
|
+
name,
|
|
18
|
+
gradient,
|
|
19
|
+
seedKey,
|
|
20
|
+
variant = "repeat",
|
|
21
|
+
className
|
|
22
|
+
}) {
|
|
23
|
+
if (variant === "display") {
|
|
24
|
+
const words = name.trim().split(/\s+/).filter(Boolean);
|
|
25
|
+
const longestWord = Math.max(1, ...words.map((word) => word.length));
|
|
26
|
+
const lineCount = Math.max(1, words.length);
|
|
27
|
+
const byWidth = (96 / (longestWord * 0.62)).toFixed(1);
|
|
28
|
+
const byHeight = (90 / (lineCount * 0.9)).toFixed(1);
|
|
29
|
+
const fontSize = `clamp(9cqw, min(19cqw, ${byWidth}cqw, ${byHeight}cqh), 19cqw)`;
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
"div",
|
|
32
|
+
{
|
|
33
|
+
className: cn("relative isolate overflow-hidden", className),
|
|
34
|
+
style: { backgroundImage: gradient, containerType: "size" },
|
|
35
|
+
children: /* @__PURE__ */ jsx(
|
|
36
|
+
"span",
|
|
37
|
+
{
|
|
38
|
+
"aria-hidden": true,
|
|
39
|
+
className: "pointer-events-none absolute inset-0 flex select-none items-center justify-center p-[4cqw] text-center font-black uppercase leading-[0.9] tracking-[-0.03em] text-white/[0.26]",
|
|
40
|
+
style: { fontSize },
|
|
41
|
+
children: name
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
const unit = `${name} \xB7 `;
|
|
48
|
+
const repeats = Math.max(2, Math.ceil(GHOST_LINE_CHARS / Math.max(unit.length, 1)));
|
|
49
|
+
const ghostLine = unit.repeat(repeats);
|
|
50
|
+
const seed = hashString(seedKey != null ? seedKey : name);
|
|
51
|
+
const rows = Array.from({ length: GHOST_ROWS }, (_, row) => {
|
|
52
|
+
const distance = Math.abs(row - GHOST_CENTRE) / GHOST_CENTRE;
|
|
53
|
+
const alpha = ALPHA_EDGE + (ALPHA_PEAK - ALPHA_EDGE) * Math.pow(1 - distance, FALLOFF_EXPONENT);
|
|
54
|
+
return { row, alpha, offset: (seed >> row % 12) % 90 - 45 };
|
|
55
|
+
});
|
|
56
|
+
return /* @__PURE__ */ jsx(
|
|
57
|
+
"div",
|
|
58
|
+
{
|
|
59
|
+
className: cn("relative isolate overflow-hidden", className),
|
|
60
|
+
style: { backgroundImage: gradient },
|
|
61
|
+
children: /* @__PURE__ */ jsx(
|
|
62
|
+
"div",
|
|
63
|
+
{
|
|
64
|
+
"aria-hidden": true,
|
|
65
|
+
className: "pointer-events-none absolute left-1/2 top-1/2 flex h-[180%] w-[180%] -translate-x-1/2 -translate-y-1/2 -rotate-[11deg] select-none flex-col justify-center",
|
|
66
|
+
children: rows.map(({ row, alpha, offset }) => /* @__PURE__ */ jsx(
|
|
67
|
+
"span",
|
|
68
|
+
{
|
|
69
|
+
className: "block whitespace-nowrap text-center text-[15px] font-bold leading-[1.45] tracking-[-0.01em]",
|
|
70
|
+
style: {
|
|
71
|
+
color: `oklch(1 0 0 / ${alpha.toFixed(3)})`,
|
|
72
|
+
// Emboss, both edges scaled by this row's alpha: a dark edge below
|
|
73
|
+
// cuts the letterform into the field, a light edge above lifts its
|
|
74
|
+
// top. The dark edge is kept well under the fill — at parity it
|
|
75
|
+
// ringed every glyph and dragged the type back toward grey, which
|
|
76
|
+
// is the opposite of what the fill is doing.
|
|
77
|
+
textShadow: [
|
|
78
|
+
`0 1px 1px oklch(0 0 0 / ${(alpha * 0.4).toFixed(3)})`,
|
|
79
|
+
`0 -1px 0 oklch(1 0 0 / ${(alpha * 0.4).toFixed(3)})`
|
|
80
|
+
].join(", "),
|
|
81
|
+
transform: `translateX(${offset}px)`
|
|
82
|
+
},
|
|
83
|
+
children: ghostLine
|
|
84
|
+
},
|
|
85
|
+
row
|
|
86
|
+
))
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { MenuField };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { MenuFilterChip } from './menu-types.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
import './place-types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MenuFilterChips — the intent page's filter row.
|
|
8
|
+
*
|
|
9
|
+
* ## One unit, one list that moves
|
|
10
|
+
*
|
|
11
|
+
* Every chip counts KITCHENS, whatever facet is behind it. A dietary chip reads
|
|
12
|
+
* "has a vegetarian dish" and counts venues; a dish-group chip reads "has a
|
|
13
|
+
* pizza" and counts venues. The earlier version mixed venue counts and dish
|
|
14
|
+
* counts in one row and became unreadable — you could not tell what a number
|
|
15
|
+
* was counting without reading the label that produced it. The unit is stated
|
|
16
|
+
* once, at the head of the row (`unitLabel`, e.g. "KITCHENS · 247"), and never
|
|
17
|
+
* again.
|
|
18
|
+
*
|
|
19
|
+
* ## A zero-count chip is dimmed, not disabled
|
|
20
|
+
*
|
|
21
|
+
* `empty` chips stay tappable. Pressing one swaps it in and drops whichever
|
|
22
|
+
* active filter conflicts with it, and the caller says which in a line beneath.
|
|
23
|
+
* Disabling it would refuse the reader the thing they asked for and give no
|
|
24
|
+
* reason; this way the row answers the question by being pressed. Facets the
|
|
25
|
+
* API says are unavailable for this intent are not passed in at all — not
|
|
26
|
+
* drawn, rather than drawn dead.
|
|
27
|
+
*
|
|
28
|
+
* ## The row scrolls; the escape hatch does not
|
|
29
|
+
*
|
|
30
|
+
* One line in every state. Chips scroll horizontally under a `<ScrollFade>`,
|
|
31
|
+
* and "More filters" is pinned opposite the unit label rather than wrapping,
|
|
32
|
+
* so the way out of a full row is always in the same place.
|
|
33
|
+
*
|
|
34
|
+
* Interactive: the consumer marks its own module `"use client"`.
|
|
35
|
+
*/
|
|
36
|
+
type MenuFilterChipsProps = {
|
|
37
|
+
chips: MenuFilterChip[];
|
|
38
|
+
onToggle: (key: string) => void;
|
|
39
|
+
/** The unit and the current total, composed by the caller, e.g. "KITCHENS · 247". */
|
|
40
|
+
unitLabel?: string;
|
|
41
|
+
/** Opens the full filter sheet. Omit for a row where every facet is a chip. */
|
|
42
|
+
onMore?: () => void;
|
|
43
|
+
moreLabel?: string;
|
|
44
|
+
/**
|
|
45
|
+
* A glyph for the phone's icon-only "more filters" button.
|
|
46
|
+
*
|
|
47
|
+
* The label is the widest fixed element in the row — "More filters" is ~80px
|
|
48
|
+
* of a 358px viewport, and it is the one thing that never scrolls, so it eats
|
|
49
|
+
* the chips' runway on every phone. Given an icon, the button collapses to a
|
|
50
|
+
* square below `lg` and keeps `moreLabel` as its accessible name.
|
|
51
|
+
*
|
|
52
|
+
* A node rather than a name because the app owns its iconography, and this
|
|
53
|
+
* one is animated on press — the DS neither knows the glyph nor drives it.
|
|
54
|
+
*/
|
|
55
|
+
moreIcon?: React.ReactNode;
|
|
56
|
+
/** Press handler for the icon button, e.g. to replay the glyph's animation. */
|
|
57
|
+
onMorePointerDown?: () => void;
|
|
58
|
+
/** Locale-aware integer formatter for the counts. Defaults to `String`. */
|
|
59
|
+
formatCount?: (value: number) => string;
|
|
60
|
+
/** Accessible name for the row. */
|
|
61
|
+
ariaLabel?: string;
|
|
62
|
+
className?: string;
|
|
63
|
+
};
|
|
64
|
+
declare function MenuFilterChips({ chips, onToggle, unitLabel, onMore, moreLabel, moreIcon, onMorePointerDown, formatCount, ariaLabel, className, }: MenuFilterChipsProps): react_jsx_runtime.JSX.Element;
|
|
65
|
+
/**
|
|
66
|
+
* MenuFilterSummary — what the active filters did, and the way out.
|
|
67
|
+
*
|
|
68
|
+
* Sits under the row whenever anything is on. The sentence is composed by the
|
|
69
|
+
* caller because it is a real sentence in two languages ("Three filters · 34 of
|
|
70
|
+
* 247 kitchens are mid-range, have a vegetarian Italian dish, and are open
|
|
71
|
+
* now") and assembling it from fragments here would produce translated
|
|
72
|
+
* word-salad in one of them.
|
|
73
|
+
*/
|
|
74
|
+
type MenuFilterSummaryProps = {
|
|
75
|
+
/** The composed sentence. */
|
|
76
|
+
summary: React.ReactNode;
|
|
77
|
+
clearLabel: string;
|
|
78
|
+
onClear: () => void;
|
|
79
|
+
className?: string;
|
|
80
|
+
};
|
|
81
|
+
declare function MenuFilterSummary({ summary, clearLabel, onClear, className, }: MenuFilterSummaryProps): react_jsx_runtime.JSX.Element;
|
|
82
|
+
declare function MenuFilterChipsSkeleton({ className }: {
|
|
83
|
+
className?: string;
|
|
84
|
+
}): react_jsx_runtime.JSX.Element;
|
|
85
|
+
|
|
86
|
+
export { MenuFilterChips, type MenuFilterChipsProps, MenuFilterChipsSkeleton, MenuFilterSummary, type MenuFilterSummaryProps };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ScrollFade } from '../chunk-2XCZJWTV.js';
|
|
2
|
+
import { Skeleton } from '../chunk-QXHMPJ35.js';
|
|
3
|
+
import { cn } from '../chunk-FEK5XGZW.js';
|
|
4
|
+
import '../chunk-3GWWZKX7.js';
|
|
5
|
+
import { X } from 'lucide-react';
|
|
6
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
function MenuFilterChips({
|
|
9
|
+
chips,
|
|
10
|
+
onToggle,
|
|
11
|
+
unitLabel,
|
|
12
|
+
onMore,
|
|
13
|
+
moreLabel,
|
|
14
|
+
moreIcon,
|
|
15
|
+
onMorePointerDown,
|
|
16
|
+
formatCount = String,
|
|
17
|
+
ariaLabel,
|
|
18
|
+
className
|
|
19
|
+
}) {
|
|
20
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative flex items-center gap-2", className), children: [
|
|
21
|
+
unitLabel && /* @__PURE__ */ jsx("span", { className: "hidden shrink-0 pr-0.5 text-[11px] font-extrabold uppercase tracking-[0.1em] text-muted-foreground lg:inline", children: unitLabel }),
|
|
22
|
+
/* @__PURE__ */ jsx(
|
|
23
|
+
ScrollFade,
|
|
24
|
+
{
|
|
25
|
+
orientation: "horizontal",
|
|
26
|
+
size: "sm",
|
|
27
|
+
className: "min-w-0 flex-1",
|
|
28
|
+
scrollClassName: "scrollbar-hide",
|
|
29
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", role: "group", "aria-label": ariaLabel, children: chips.map((chip) => /* @__PURE__ */ jsx(
|
|
30
|
+
Chip,
|
|
31
|
+
{
|
|
32
|
+
chip,
|
|
33
|
+
onToggle: () => onToggle(chip.key),
|
|
34
|
+
formatCount
|
|
35
|
+
},
|
|
36
|
+
chip.key
|
|
37
|
+
)) })
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
onMore && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
41
|
+
moreIcon && /* @__PURE__ */ jsx(
|
|
42
|
+
"button",
|
|
43
|
+
{
|
|
44
|
+
type: "button",
|
|
45
|
+
onClick: onMore,
|
|
46
|
+
onPointerDown: onMorePointerDown,
|
|
47
|
+
"aria-label": moreLabel,
|
|
48
|
+
"aria-haspopup": "dialog",
|
|
49
|
+
className: "inline-flex size-10 shrink-0 items-center justify-center rounded-full border border-border text-accent transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none lg:hidden",
|
|
50
|
+
children: moreIcon
|
|
51
|
+
}
|
|
52
|
+
),
|
|
53
|
+
/* @__PURE__ */ jsx(
|
|
54
|
+
"button",
|
|
55
|
+
{
|
|
56
|
+
type: "button",
|
|
57
|
+
onClick: onMore,
|
|
58
|
+
className: cn(
|
|
59
|
+
"shrink-0 rounded-md pl-2 text-[12.5px] font-bold text-accent transition-colors hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none",
|
|
60
|
+
moreIcon && "hidden lg:inline"
|
|
61
|
+
),
|
|
62
|
+
children: moreLabel
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
] })
|
|
66
|
+
] });
|
|
67
|
+
}
|
|
68
|
+
function Chip({
|
|
69
|
+
chip,
|
|
70
|
+
onToggle,
|
|
71
|
+
formatCount
|
|
72
|
+
}) {
|
|
73
|
+
return /* @__PURE__ */ jsxs(
|
|
74
|
+
"button",
|
|
75
|
+
{
|
|
76
|
+
type: "button",
|
|
77
|
+
onClick: onToggle,
|
|
78
|
+
"aria-pressed": chip.active,
|
|
79
|
+
className: cn(
|
|
80
|
+
"inline-flex h-9 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border px-4 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none",
|
|
81
|
+
chip.active ? "border-accent font-semibold text-accent shadow-[0_1px_2px_oklch(0.51_0.095_45_/_0.08)]" : "border-border bg-card text-foreground hover:border-accent/40",
|
|
82
|
+
// Dimmed, never disabled — pressing it is how the reader finds out
|
|
83
|
+
// which active filter is in the way.
|
|
84
|
+
chip.empty && "opacity-45"
|
|
85
|
+
),
|
|
86
|
+
children: [
|
|
87
|
+
chip.icon,
|
|
88
|
+
chip.label,
|
|
89
|
+
chip.count !== void 0 && /* @__PURE__ */ jsx("span", { className: cn("tabular-nums", chip.active ? "text-accent" : "text-muted-foreground"), children: formatCount(chip.count) }),
|
|
90
|
+
chip.active && /* @__PURE__ */ jsx(X, { className: "h-3 w-3 shrink-0", "aria-hidden": true })
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
function MenuFilterSummary({
|
|
96
|
+
summary,
|
|
97
|
+
clearLabel,
|
|
98
|
+
onClear,
|
|
99
|
+
className
|
|
100
|
+
}) {
|
|
101
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap items-center gap-2.5 pt-3.5", className), children: [
|
|
102
|
+
/* @__PURE__ */ jsx("span", { className: "text-[13px] text-muted-foreground [&_b]:font-bold [&_b]:text-foreground", children: summary }),
|
|
103
|
+
/* @__PURE__ */ jsx(
|
|
104
|
+
"button",
|
|
105
|
+
{
|
|
106
|
+
type: "button",
|
|
107
|
+
onClick: onClear,
|
|
108
|
+
className: "ml-auto shrink-0 rounded-md text-[12.5px] font-bold text-accent transition-colors hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none",
|
|
109
|
+
children: clearLabel
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
] });
|
|
113
|
+
}
|
|
114
|
+
var CHIP_WIDTHS = [128, 104, 96, 148, 112, 88];
|
|
115
|
+
function MenuFilterChipsSkeleton({ className }) {
|
|
116
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2 overflow-hidden", className), "aria-hidden": true, children: [
|
|
117
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-[92px] shrink-0" }),
|
|
118
|
+
CHIP_WIDTHS.map((width, index) => /* @__PURE__ */ jsx(Skeleton, { className: "h-9 shrink-0 rounded-full", style: { width } }, index))
|
|
119
|
+
] });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { MenuFilterChips, MenuFilterChipsSkeleton, MenuFilterSummary };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
import './place-types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MenuGroupRows — what an intent consists of.
|
|
8
|
+
*
|
|
9
|
+
* On a cuisine page this is the `dish_groups` facet narrowed by the cuisine
|
|
10
|
+
* ("Pizza · 120 kitchens · 30–68"); on a going-out page it is the digest tags
|
|
11
|
+
* and graded strengths ("Cocktails · 63 places"). One component for both,
|
|
12
|
+
* because both are the same object: a facet value, its venue count, and a range.
|
|
13
|
+
*
|
|
14
|
+
* ## The counts are VENUES, and the label has to say so
|
|
15
|
+
*
|
|
16
|
+
* There is no endpoint that counts dishes per cuisine — `/dishes` accepts
|
|
17
|
+
* `cuisine_slugs` and ignores it — so "120" here is a hundred and twenty
|
|
18
|
+
* kitchens that make a pizza, not a hundred and twenty pizzas. The `meta` line
|
|
19
|
+
* is composed by the caller precisely so that it can say which, in a language
|
|
20
|
+
* where the two words differ.
|
|
21
|
+
*
|
|
22
|
+
* ## Not `<ConceptCard>`
|
|
23
|
+
*
|
|
24
|
+
* That one is a cover-led card for a thing with a date and a venue. This is a
|
|
25
|
+
* row in a sidebar: a hue bar, a name, a count and a range. Giving it a cover
|
|
26
|
+
* would mean finding a photograph of "pasta", which is the kind of picture that
|
|
27
|
+
* makes a page look generated.
|
|
28
|
+
*/
|
|
29
|
+
/** @deprecated Alias of `MenuLinkProps`; kept for symmetry with the other menu surfaces. */
|
|
30
|
+
type MenuGroupRowsLinkProps = MenuLinkProps;
|
|
31
|
+
type MenuGroupRow = {
|
|
32
|
+
slug: string;
|
|
33
|
+
name: string;
|
|
34
|
+
/** Venue count line, e.g. "120 kitchens". Pluralised by the caller. */
|
|
35
|
+
meta: string;
|
|
36
|
+
/** Price range, already formatted, e.g. "30—68". Omitted where none is known. */
|
|
37
|
+
rangeLabel?: string;
|
|
38
|
+
href?: string;
|
|
39
|
+
/** Finished CSS gradient for the bar. A missing one falls back to the border colour. */
|
|
40
|
+
gradient?: string;
|
|
41
|
+
};
|
|
42
|
+
type MenuGroupRowsProps = {
|
|
43
|
+
rows: MenuGroupRow[];
|
|
44
|
+
linkComponent?: MenuLinkComponent;
|
|
45
|
+
className?: string;
|
|
46
|
+
};
|
|
47
|
+
declare function MenuGroupRows({ rows, linkComponent: LinkComponent, className, }: MenuGroupRowsProps): react_jsx_runtime.JSX.Element;
|
|
48
|
+
declare function MenuGroupRowsSkeleton({ rows, className, }: {
|
|
49
|
+
rows?: number;
|
|
50
|
+
className?: string;
|
|
51
|
+
}): react_jsx_runtime.JSX.Element;
|
|
52
|
+
|
|
53
|
+
export { type MenuGroupRow, MenuGroupRows, type MenuGroupRowsLinkProps, type MenuGroupRowsProps, MenuGroupRowsSkeleton };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Skeleton } from '../chunk-QXHMPJ35.js';
|
|
2
|
+
import { cn } from '../chunk-FEK5XGZW.js';
|
|
3
|
+
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|
|
4
|
+
import { ChevronRight } from 'lucide-react';
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function DefaultLink(_a) {
|
|
8
|
+
var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
|
|
9
|
+
return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
|
|
10
|
+
}
|
|
11
|
+
function MenuGroupRows({
|
|
12
|
+
rows,
|
|
13
|
+
linkComponent: LinkComponent = DefaultLink,
|
|
14
|
+
className
|
|
15
|
+
}) {
|
|
16
|
+
return /* @__PURE__ */ jsx("ul", { className: cn("flex flex-col", className), children: rows.map((row) => {
|
|
17
|
+
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
18
|
+
/* @__PURE__ */ jsx(
|
|
19
|
+
"span",
|
|
20
|
+
{
|
|
21
|
+
"aria-hidden": true,
|
|
22
|
+
className: cn(
|
|
23
|
+
"h-[34px] w-2 shrink-0 rounded-full",
|
|
24
|
+
!row.gradient && "bg-border"
|
|
25
|
+
),
|
|
26
|
+
style: row.gradient ? { backgroundImage: row.gradient } : void 0
|
|
27
|
+
}
|
|
28
|
+
),
|
|
29
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
30
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-bold", children: row.name }),
|
|
31
|
+
/* @__PURE__ */ jsx("span", { className: "mt-px block truncate text-[11.5px] text-muted-foreground", children: row.meta })
|
|
32
|
+
] }),
|
|
33
|
+
row.rangeLabel && /* @__PURE__ */ jsx("span", { className: "shrink-0 font-mono text-xs tabular-nums text-muted-foreground", children: row.rangeLabel }),
|
|
34
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true })
|
|
35
|
+
] });
|
|
36
|
+
return /* @__PURE__ */ jsx("li", { className: "border-t border-border first:border-t-0", children: row.href ? /* @__PURE__ */ jsx(
|
|
37
|
+
LinkComponent,
|
|
38
|
+
{
|
|
39
|
+
href: row.href,
|
|
40
|
+
className: "flex items-center gap-3 py-3 transition-colors hover:bg-muted/30 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring motion-reduce:transition-none",
|
|
41
|
+
children: body
|
|
42
|
+
}
|
|
43
|
+
) : /* @__PURE__ */ jsx("span", { className: "flex items-center gap-3 py-3", children: body }) }, row.slug);
|
|
44
|
+
}) });
|
|
45
|
+
}
|
|
46
|
+
function MenuGroupRowsSkeleton({
|
|
47
|
+
rows = 5,
|
|
48
|
+
className
|
|
49
|
+
}) {
|
|
50
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, index) => /* @__PURE__ */ jsxs(
|
|
51
|
+
"div",
|
|
52
|
+
{
|
|
53
|
+
className: "flex items-center gap-3 border-t border-border py-3 first:border-t-0",
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[34px] w-2 rounded-full" }),
|
|
56
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
|
|
57
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-[50%]" }),
|
|
58
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-[35%]" })
|
|
59
|
+
] }),
|
|
60
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-[52px]" })
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
index
|
|
64
|
+
)) });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { MenuGroupRows, MenuGroupRowsSkeleton };
|
|
@@ -3,6 +3,7 @@ import '../chunk-3GWWZKX7.js';
|
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
5
|
var TEXTURE_CELLS = 28;
|
|
6
|
+
var PHONE_CELLS = 6;
|
|
6
7
|
function MenuHubHero({
|
|
7
8
|
kicker,
|
|
8
9
|
kickerIcon,
|
|
@@ -39,9 +40,10 @@ function MenuHubHero({
|
|
|
39
40
|
"div",
|
|
40
41
|
{
|
|
41
42
|
"aria-hidden": true,
|
|
42
|
-
className: "absolute inset-0 grid auto-rows-fr grid-cols-
|
|
43
|
+
className: "absolute inset-0 grid auto-rows-fr grid-cols-3 gap-0.5 lg:grid-cols-7",
|
|
43
44
|
children: Array.from({ length: TEXTURE_CELLS }, (_, cell) => {
|
|
44
45
|
const url = (tileUrls == null ? void 0 : tileUrls.length) ? tileUrls[cell % tileUrls.length] : void 0;
|
|
46
|
+
const phone = cell < PHONE_CELLS ? void 0 : "hidden lg:block";
|
|
45
47
|
return url ? (
|
|
46
48
|
// eslint-disable-next-line @next/next/no-img-element
|
|
47
49
|
/* @__PURE__ */ jsx(
|
|
@@ -51,14 +53,17 @@ function MenuHubHero({
|
|
|
51
53
|
alt: "",
|
|
52
54
|
loading: "lazy",
|
|
53
55
|
decoding: "async",
|
|
54
|
-
className: "h-full w-full object-cover"
|
|
56
|
+
className: cn("h-full w-full object-cover", phone)
|
|
55
57
|
},
|
|
56
58
|
cell
|
|
57
59
|
)
|
|
58
60
|
) : /* @__PURE__ */ jsx(
|
|
59
61
|
"div",
|
|
60
62
|
{
|
|
61
|
-
className:
|
|
63
|
+
className: cn(
|
|
64
|
+
"bg-[repeating-linear-gradient(135deg,oklch(0.6_0.02_55)_0_9px,oklch(0.68_0.016_58)_9px_18px)] opacity-[0.42]",
|
|
65
|
+
phone
|
|
66
|
+
)
|
|
62
67
|
},
|
|
63
68
|
cell
|
|
64
69
|
);
|
|
@@ -71,7 +76,7 @@ function MenuHubHero({
|
|
|
71
76
|
"aria-hidden": true,
|
|
72
77
|
className: cn(
|
|
73
78
|
"absolute inset-0",
|
|
74
|
-
(tileUrls == null ? void 0 : tileUrls.length) || backgroundUrl ? "bg-[linear-gradient(100deg,oklch(0.16_0.012_55_/_0.96)_0%,oklch(0.16_0.012_55_/_0.
|
|
79
|
+
(tileUrls == null ? void 0 : tileUrls.length) || backgroundUrl ? "bg-[linear-gradient(100deg,oklch(0.16_0.012_55_/_0.96)_0%,oklch(0.16_0.012_55_/_0.86)_52%,oklch(0.16_0.012_55_/_0.6)_100%)]" : "bg-[linear-gradient(100deg,oklch(0.18_0.012_55_/_0.95)_0%,oklch(0.18_0.012_55_/_0.72)_52%,oklch(0.18_0.012_55_/_0.3)_100%)]"
|
|
75
80
|
)
|
|
76
81
|
}
|
|
77
82
|
),
|
|
@@ -88,7 +93,7 @@ function MenuHubHero({
|
|
|
88
93
|
/* @__PURE__ */ jsx("div", { className: "mt-[5px] text-xs opacity-[0.72]", children: figure.label })
|
|
89
94
|
] }, figure.label)) }),
|
|
90
95
|
(proof || action) && /* @__PURE__ */ jsxs("div", { className: "mt-auto flex flex-wrap items-center gap-3 pt-5", children: [
|
|
91
|
-
proof && /* @__PURE__ */ jsxs("span", { className: "inline-flex min-h-11 items-center gap-2.5 rounded-full bg-white/
|
|
96
|
+
proof && /* @__PURE__ */ jsxs("span", { className: "inline-flex min-h-11 items-center gap-2.5 rounded-full bg-white/[0.14] px-4 py-2 text-[13px]", children: [
|
|
92
97
|
proofIcon,
|
|
93
98
|
proof
|
|
94
99
|
] }),
|