@bearmenu/ui 0.8.10 → 0.8.12
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-UKBNQO6Q.js → chunk-2CXU5WZO.js} +1 -1
- package/dist/{chunk-62ES6N32.js → chunk-43RC7MHY.js} +1 -1
- package/dist/{chunk-Q6QH52LJ.js → chunk-6TEEY5YA.js} +2 -2
- package/dist/{chunk-UDN7UHJW.js → chunk-7A42J73Q.js} +3 -2
- package/dist/{chunk-5RWTOT5Y.js → chunk-CNJQUHCU.js} +11 -1
- package/dist/{chunk-TH6W2PWG.js → chunk-UDTG3RSE.js} +1 -1
- package/dist/{chunk-H3BV4VAG.js → chunk-VAXOQS7W.js} +14 -2
- package/dist/{chunk-SY6RV476.js → chunk-WCTHZKU7.js} +10 -21
- package/dist/{chunk-AKQ57NXY.js → chunk-ZQ53AGML.js} +2 -2
- package/dist/components/alert-dialog.js +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/carousel.js +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/components/concept-compare-rail.js +2 -2
- package/dist/components/concept-compare.d.ts +1 -1
- package/dist/components/concept-compare.js +31 -10
- package/dist/components/concept-convergence.js +2 -2
- package/dist/components/empty-state.js +1 -1
- package/dist/components/event-detail-panel.js +1 -1
- package/dist/components/event-list-row-wide.js +1 -1
- package/dist/components/filter-category-row.js +1 -1
- package/dist/components/glass-ground.d.ts +26 -31
- package/dist/components/glass-ground.js +1 -1
- package/dist/components/haptic-button.js +1 -1
- package/dist/components/input-group.d.ts +2 -2
- package/dist/components/input.d.ts +1 -1
- package/dist/components/item.d.ts +15 -5
- package/dist/components/item.js +15 -10
- package/dist/components/kitchen-dossier.d.ts +9 -7
- package/dist/components/kitchen-dossier.js +31 -25
- package/dist/components/link-button.js +1 -1
- package/dist/components/menu-family-block.d.ts +22 -17
- package/dist/components/menu-family-block.js +62 -61
- package/dist/components/menu-family-card.js +2 -4
- package/dist/components/menu-family-tiles.d.ts +19 -0
- package/dist/components/menu-family-tiles.js +57 -0
- package/dist/components/menu-hub-hero.js +18 -11
- package/dist/components/menu-index-list.d.ts +31 -12
- package/dist/components/menu-index-list.js +68 -31
- package/dist/components/menu-intent-hero.d.ts +1 -1
- package/dist/components/menu-item.js +3 -3
- package/dist/components/menu-mocks.d.ts +10 -3
- package/dist/components/menu-mocks.js +21 -9
- package/dist/components/menu-types.d.ts +33 -10
- package/dist/components/multi-select-combobox.js +2 -2
- package/dist/components/pagination.js +1 -1
- package/dist/components/photo-ground.d.ts +8 -2
- package/dist/components/photo-ground.js +1 -1
- package/dist/components/place-details-mobile.js +1 -1
- package/dist/components/searchable-select.js +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/top-ranking-entry.js +3 -3
- 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.d.ts +24 -3
- package/dist/components/weekday-theme-banner.js +63 -15
- package/package.json +1 -1
- package/src/components/badge.tsx +1 -1
- package/src/components/button.stories.tsx +25 -2
- package/src/components/button.tsx +14 -2
- package/src/components/colour-dictionary.stories.tsx +1 -1
- package/src/components/concept-compare-rail.tsx +2 -1
- package/src/components/concept-compare.stories.tsx +3 -3
- package/src/components/concept-compare.tsx +50 -14
- package/src/components/glass-ground.tsx +31 -56
- package/src/components/item.tsx +69 -45
- package/src/components/kitchen-dossier.stories.tsx +1 -1
- package/src/components/kitchen-dossier.tsx +60 -40
- package/src/components/menu-family-block.stories.tsx +3 -3
- package/src/components/menu-family-block.tsx +94 -98
- package/src/components/menu-family-card.stories.tsx +2 -2
- package/src/components/menu-family-card.tsx +6 -13
- package/src/components/menu-family-tiles.stories.tsx +54 -0
- package/src/components/menu-family-tiles.test.tsx +30 -0
- package/src/components/menu-family-tiles.tsx +132 -0
- package/src/components/menu-hub-hero.test.tsx +39 -0
- package/src/components/menu-hub-hero.tsx +30 -12
- package/src/components/menu-index-list.stories.tsx +6 -1
- package/src/components/menu-index-list.tsx +101 -54
- package/src/components/menu-intent-hero.tsx +1 -1
- package/src/components/menu-mocks.ts +32 -9
- package/src/components/menu-types.ts +32 -9
- package/src/components/photo-ground.tsx +14 -2
- package/src/components/signature-chip.tsx +3 -3
- package/src/components/venue-grade-dimensions.tsx +9 -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.stories.tsx +43 -4
- package/src/components/weekday-theme-banner.tsx +95 -18
- package/dist/components/menu-intent-tiles.d.ts +0 -31
- package/dist/components/menu-intent-tiles.js +0 -50
- package/src/components/menu-intent-tiles.stories.tsx +0 -54
- package/src/components/menu-intent-tiles.tsx +0 -76
|
@@ -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
|
),
|
|
@@ -80,15 +85,17 @@ function MenuHubHero({
|
|
|
80
85
|
kickerIcon,
|
|
81
86
|
kicker
|
|
82
87
|
] }),
|
|
83
|
-
/* @__PURE__ */ jsx("h1", { className: "max-w-[640px] font-serif text-[
|
|
88
|
+
/* @__PURE__ */ jsx("h1", { className: "max-w-[640px] font-serif text-[28px] font-semibold leading-[1.06] tracking-[-0.025em] lg:text-[50px] lg:leading-[1.04]", children: headline }),
|
|
84
89
|
body && /* @__PURE__ */ jsx("p", { className: "hidden max-w-[540px] text-sm leading-[1.6] opacity-[0.84] lg:block lg:text-[15.5px]", children: body }),
|
|
85
|
-
figures && figures.length > 0 && //
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
figures && figures.length > 0 && // One row of four on the phone. It was two by two, which was the
|
|
91
|
+
// taller half of a 500px hero; at 20px the widest figure ("19,090")
|
|
92
|
+
// is ~68px and four of them share a 358px column with room.
|
|
93
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-between gap-x-3 pt-2 lg:flex-wrap lg:justify-start lg:gap-x-8 lg:gap-y-4 lg:pt-1.5", children: figures.map((figure) => /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
94
|
+
/* @__PURE__ */ jsx("div", { className: "text-xl font-black leading-none tracking-[-0.02em] tabular-nums lg:text-[32px] lg:tracking-[-0.03em]", children: figure.value }),
|
|
95
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-[11px] leading-tight opacity-[0.72] lg:mt-[5px] lg:text-xs", children: figure.label })
|
|
89
96
|
] }, figure.label)) }),
|
|
90
|
-
(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/
|
|
97
|
+
(proof || action) && /* @__PURE__ */ jsxs("div", { className: "mt-auto flex flex-wrap items-center gap-3 pt-4 lg:pt-5", children: [
|
|
98
|
+
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
99
|
proofIcon,
|
|
93
100
|
proof
|
|
94
101
|
] }),
|
|
@@ -4,19 +4,24 @@ import 'react';
|
|
|
4
4
|
import './place-types.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* MenuIndexList — the complete set,
|
|
7
|
+
* MenuIndexList — the complete set: one column on a phone, three from `lg`.
|
|
8
8
|
*
|
|
9
9
|
* ## This block is why the page can afford to be progressive
|
|
10
10
|
*
|
|
11
11
|
* It carries a crawlable link to EVERY destination the city has — all
|
|
12
|
-
* thirty-eight cuisines, not the
|
|
13
|
-
* it the page's entire link-equity job, which in turn means the rich
|
|
14
|
-
*
|
|
15
|
-
* crawler needs is hidden behind that control, because it is all
|
|
12
|
+
* thirty-eight cuisines, not the eight the page draws in full above. That
|
|
13
|
+
* makes it the page's entire link-equity job, which in turn means the rich
|
|
14
|
+
* blocks are free to load eight at a time behind a "show more": nothing a
|
|
15
|
+
* crawler needs is hidden behind that control, because it is all here.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* The phone's own "show all" is CSS, not markup: every row is in the DOM and
|
|
18
|
+
* the ones past `collapsedCount` are hidden below `lg` until the button is
|
|
19
|
+
* pressed. A list that mounted its tail on tap would have taken twenty-six
|
|
20
|
+
* links out of the page for the crawler that never taps.
|
|
21
|
+
*
|
|
22
|
+
* Get this backwards — put the whole set behind the disclosure and only eight
|
|
23
|
+
* links in the markup — and the page silently stops linking to thirty pages
|
|
24
|
+
* it is supposed to be the index for.
|
|
20
25
|
*
|
|
21
26
|
* ## Ordered by count, and the counts overlap
|
|
22
27
|
*
|
|
@@ -24,6 +29,10 @@ import './place-types.js';
|
|
|
24
29
|
* places, because a trattoria is Italian AND pizza AND international. So this
|
|
25
30
|
* is a ranked list of ways in, never a partition, and no copy near it may total
|
|
26
31
|
* the numbers or call them a breakdown.
|
|
32
|
+
*
|
|
33
|
+
* A client component for the one piece of state the expander needs; the
|
|
34
|
+
* `linkComponent` a server caller hands in must therefore be a client
|
|
35
|
+
* reference (`ClientLink`), not `next/link` itself.
|
|
27
36
|
*/
|
|
28
37
|
/** @deprecated Alias of `MenuLinkProps`; kept for symmetry with the other menu surfaces. */
|
|
29
38
|
type MenuIndexListLinkProps = MenuLinkProps;
|
|
@@ -33,13 +42,23 @@ type MenuIndexListProps = {
|
|
|
33
42
|
title: string;
|
|
34
43
|
/** One line under it, e.g. "Ordered by kitchens — every one has its own page". */
|
|
35
44
|
subtitle?: string;
|
|
36
|
-
/**
|
|
37
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Rows shown on a phone before the expander; the rest are hidden below `lg`
|
|
47
|
+
* until it is pressed. Omit to show every row at every width.
|
|
48
|
+
*/
|
|
49
|
+
collapsedCount?: number;
|
|
50
|
+
/** The expander's labels, e.g. "Show all 38 cuisines" / "Show fewer". */
|
|
51
|
+
expandLabels?: {
|
|
52
|
+
showAll: string;
|
|
53
|
+
showFewer: string;
|
|
54
|
+
};
|
|
55
|
+
/** The colour mark beside each name, keyed by slug. Falls back to the border colour. */
|
|
56
|
+
hues?: Record<string, string>;
|
|
38
57
|
linkComponent?: MenuLinkComponent;
|
|
39
58
|
className?: string;
|
|
40
59
|
};
|
|
41
|
-
declare function MenuIndexList({ entries, title, subtitle,
|
|
42
|
-
/**
|
|
60
|
+
declare function MenuIndexList({ entries, title, subtitle, collapsedCount, expandLabels, hues, linkComponent: LinkComponent, className, }: MenuIndexListProps): react_jsx_runtime.JSX.Element;
|
|
61
|
+
/** One column on a phone, three from `lg` — the grid the list itself renders. */
|
|
43
62
|
declare function MenuIndexListSkeleton({ rows, className, }: {
|
|
44
63
|
rows?: number;
|
|
45
64
|
className?: string;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Separator } from '../chunk-WSRWFA6K.js';
|
|
2
2
|
import { Skeleton } from '../chunk-QXHMPJ35.js';
|
|
3
|
+
import { Button } from '../chunk-VAXOQS7W.js';
|
|
4
|
+
import '../chunk-R47NEOSI.js';
|
|
3
5
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
4
6
|
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|
|
5
|
-
import {
|
|
7
|
+
import { useState } from 'react';
|
|
8
|
+
import { ChevronRight, ChevronDown } from 'lucide-react';
|
|
6
9
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
10
|
|
|
8
11
|
function DefaultLink(_a) {
|
|
@@ -13,10 +16,14 @@ function MenuIndexList({
|
|
|
13
16
|
entries,
|
|
14
17
|
title,
|
|
15
18
|
subtitle,
|
|
16
|
-
|
|
19
|
+
collapsedCount,
|
|
20
|
+
expandLabels,
|
|
21
|
+
hues,
|
|
17
22
|
linkComponent: LinkComponent = DefaultLink,
|
|
18
23
|
className
|
|
19
24
|
}) {
|
|
25
|
+
const [expanded, setExpanded] = useState(false);
|
|
26
|
+
const collapsible = collapsedCount !== void 0 && expandLabels !== void 0 && entries.length > collapsedCount;
|
|
20
27
|
return /* @__PURE__ */ jsxs(
|
|
21
28
|
"section",
|
|
22
29
|
{
|
|
@@ -29,44 +36,74 @@ function MenuIndexList({
|
|
|
29
36
|
/* @__PURE__ */ jsx("h2", { className: "text-[15px] font-bold tracking-[-0.01em]", children: title }),
|
|
30
37
|
subtitle && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-[12.5px] text-muted-foreground", children: subtitle })
|
|
31
38
|
] }),
|
|
32
|
-
/* @__PURE__ */ jsx("ul", { className: "grid grid-cols-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
/* @__PURE__ */ jsx("ul", { className: "grid grid-cols-1 lg:grid-cols-3 lg:gap-x-8", children: entries.map((entry, index) => {
|
|
40
|
+
var _a;
|
|
41
|
+
const hue = hues == null ? void 0 : hues[entry.slug];
|
|
42
|
+
return /* @__PURE__ */ jsxs(
|
|
43
|
+
"li",
|
|
36
44
|
{
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
className: cn(
|
|
46
|
+
collapsible && !expanded && index >= collapsedCount && "max-lg:hidden"
|
|
47
|
+
),
|
|
39
48
|
children: [
|
|
40
|
-
/* @__PURE__ */ jsx(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"aria-hidden": true,
|
|
44
|
-
className: cn(
|
|
45
|
-
"h-2.5 w-2.5 shrink-0 rounded-[3px]",
|
|
46
|
-
!entry.gradient && "bg-border"
|
|
47
|
-
),
|
|
48
|
-
style: entry.gradient ? { backgroundImage: entry.gradient } : void 0
|
|
49
|
-
}
|
|
50
|
-
),
|
|
51
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-[13.5px]", children: entry.name }),
|
|
52
|
-
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-[13px] tabular-nums text-muted-foreground", children: formatCount(entry.count) }),
|
|
53
|
-
/* @__PURE__ */ jsx(
|
|
54
|
-
ChevronRight,
|
|
49
|
+
/* @__PURE__ */ jsx(Separator, {}),
|
|
50
|
+
/* @__PURE__ */ jsxs(
|
|
51
|
+
LinkComponent,
|
|
55
52
|
{
|
|
56
|
-
|
|
57
|
-
"
|
|
53
|
+
href: entry.href,
|
|
54
|
+
className: "group flex items-center gap-2.5 py-2.5 transition-colors hover:text-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring motion-reduce:transition-none",
|
|
55
|
+
children: [
|
|
56
|
+
/* @__PURE__ */ jsx(
|
|
57
|
+
"span",
|
|
58
|
+
{
|
|
59
|
+
"aria-hidden": true,
|
|
60
|
+
className: cn("h-2 w-2 shrink-0 rounded-full", !hue && !entry.gradient && "bg-border"),
|
|
61
|
+
style: hue ? { backgroundColor: hue } : entry.gradient ? { backgroundImage: entry.gradient } : void 0
|
|
62
|
+
}
|
|
63
|
+
),
|
|
64
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: entry.name }),
|
|
65
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-[13px] tabular-nums text-muted-foreground", children: (_a = entry.countLabel) != null ? _a : String(entry.count) }),
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
ChevronRight,
|
|
68
|
+
{
|
|
69
|
+
className: "h-3.5 w-3.5 shrink-0 text-muted-foreground transition-colors group-hover:text-accent motion-reduce:transition-none",
|
|
70
|
+
"aria-hidden": true
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
]
|
|
58
74
|
}
|
|
59
75
|
)
|
|
60
76
|
]
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
77
|
+
},
|
|
78
|
+
entry.slug
|
|
79
|
+
);
|
|
80
|
+
}) }),
|
|
81
|
+
collapsible && /* @__PURE__ */ jsxs(
|
|
82
|
+
Button,
|
|
83
|
+
{
|
|
84
|
+
variant: "outline",
|
|
85
|
+
fullWidth: true,
|
|
86
|
+
className: "mt-2 lg:hidden",
|
|
87
|
+
"aria-expanded": expanded,
|
|
88
|
+
onClick: () => setExpanded((open) => !open),
|
|
89
|
+
children: [
|
|
90
|
+
expanded ? expandLabels.showFewer : expandLabels.showAll,
|
|
91
|
+
/* @__PURE__ */ jsx(
|
|
92
|
+
ChevronDown,
|
|
93
|
+
{
|
|
94
|
+
className: cn("transition-transform motion-reduce:transition-none", expanded && "rotate-180"),
|
|
95
|
+
"aria-hidden": true
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
)
|
|
64
101
|
]
|
|
65
102
|
}
|
|
66
103
|
);
|
|
67
104
|
}
|
|
68
105
|
function MenuIndexListSkeleton({
|
|
69
|
-
rows =
|
|
106
|
+
rows = 12,
|
|
70
107
|
className
|
|
71
108
|
}) {
|
|
72
109
|
return /* @__PURE__ */ jsxs(
|
|
@@ -80,10 +117,10 @@ function MenuIndexListSkeleton({
|
|
|
80
117
|
children: [
|
|
81
118
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-[15px] w-[140px]" }),
|
|
82
119
|
/* @__PURE__ */ jsx(Skeleton, { className: "mt-1.5 h-3 w-[240px]" }),
|
|
83
|
-
/* @__PURE__ */ jsx("ul", { className: "mt-2 grid grid-cols-
|
|
120
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-2 grid grid-cols-1 lg:grid-cols-3 lg:gap-x-8", children: Array.from({ length: rows }, (_, index) => /* @__PURE__ */ jsxs("li", { children: [
|
|
84
121
|
/* @__PURE__ */ jsx(Separator, {}),
|
|
85
122
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 py-2.5", children: [
|
|
86
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-2
|
|
123
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-2 w-2 rounded-full" }),
|
|
87
124
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 flex-1" }),
|
|
88
125
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-6" })
|
|
89
126
|
] })
|
|
@@ -52,7 +52,7 @@ type MenuIntentHeroProps = {
|
|
|
52
52
|
* Finished CSS gradient for the ground, e.g. `linear-gradient(140deg, …)`.
|
|
53
53
|
*
|
|
54
54
|
* A gradient rather than a token name, for the same reason `<MenuField>` and
|
|
55
|
-
* `<
|
|
55
|
+
* `<MenuFamilyTiles>` take one: the hue tables are app-owned, and a component
|
|
56
56
|
* referencing `var(--h-pizza)` renders an unstyled panel in any consumer that
|
|
57
57
|
* does not define it. Missing, the panel falls back to the foreground colour
|
|
58
58
|
* — visibly unstyled rather than white text on white.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { MentionSignal, MenuItem } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { MentionSignal, MenuItem } from '../chunk-UDTG3RSE.js';
|
|
2
|
+
import '../chunk-6TEEY5YA.js';
|
|
3
|
+
import '../chunk-2CXU5WZO.js';
|
|
4
4
|
import '../chunk-FEK5XGZW.js';
|
|
5
5
|
import '../chunk-3GWWZKX7.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MenuFamilyBlockPreview, MenuConceptPreview, MenuFamilyPreview, MenuFilterChip, MenuIndexEntry, MenuIntentFigure,
|
|
1
|
+
import { MenuFamilyBlockPreview, MenuConceptPreview, MenuFamilyPreview, MenuFamilyTile, MenuFilterChip, MenuIndexEntry, MenuIntentFigure, MenuItemPreview, MenuKitchenPreview, MenuLoosenOption, QaItem, MenuVenuePreview } from './menu-types.js';
|
|
2
2
|
import { PlacePreview } from './place-types.js';
|
|
3
3
|
import 'react';
|
|
4
4
|
|
|
@@ -36,7 +36,14 @@ declare const mockConcept: MenuConceptPreview;
|
|
|
36
36
|
declare const mockFamily: MenuFamilyPreview;
|
|
37
37
|
/** The drinks counterpart, and the reason `chip.count` is optional. */
|
|
38
38
|
declare const mockDrinkFamily: MenuFamilyPreview;
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* The hub's seven cuisines, in the registry's order. The photograph is a
|
|
41
|
+
* venue's, never a plate's; the last one ships without, so the story shows
|
|
42
|
+
* the initial fallback beside six real tiles.
|
|
43
|
+
*/
|
|
44
|
+
declare const mockFamilyTiles: MenuFamilyTile[];
|
|
45
|
+
/** The closing tile: stone, so it reads as the index and not as an eighth cuisine. */
|
|
46
|
+
declare const mockFamilyTilesAll: MenuFamilyTile;
|
|
40
47
|
/** Formatters the stories pass. Real callers inject locale-aware ones. */
|
|
41
48
|
declare const mockFormatters: {
|
|
42
49
|
price: (value: number) => string;
|
|
@@ -87,4 +94,4 @@ declare const mockFamilyBlock: MenuFamilyBlockPreview;
|
|
|
87
94
|
declare const mockBareFamilyBlock: MenuFamilyBlockPreview;
|
|
88
95
|
declare const mockQa: QaItem[];
|
|
89
96
|
|
|
90
|
-
export { mockBareFamilyBlock, mockConcept, mockDrinkFamily, mockFamily, mockFamilyBlock, mockFilterChips, mockFormatters, mockGradients, mockHubLabels, mockIndexEntries, mockIntentFigures,
|
|
97
|
+
export { mockBareFamilyBlock, mockConcept, mockDrinkFamily, mockFamily, mockFamilyBlock, mockFamilyTiles, mockFamilyTilesAll, mockFilterChips, mockFormatters, mockGradients, mockHubLabels, mockIndexEntries, mockIntentFigures, mockItems, mockKitchens, mockLoosenOptions, mockMatchedKitchens, mockPlaces, mockQa, mockVenues };
|
|
@@ -330,15 +330,27 @@ var mockDrinkFamily = {
|
|
|
330
330
|
price_median: 28,
|
|
331
331
|
venue_photo_urls: []
|
|
332
332
|
};
|
|
333
|
-
var
|
|
334
|
-
var
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
{ slug: "
|
|
339
|
-
{ slug: "
|
|
340
|
-
{ slug: "
|
|
333
|
+
var familyGradient = (hue) => `linear-gradient(150deg, oklch(0.52 0.14 ${hue}), oklch(0.43 0.13 ${hue - 4}))`;
|
|
334
|
+
var familyPhoto = (hue) => "data:image/svg+xml;utf8," + encodeURIComponent(
|
|
335
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="320" height="320"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="hsl(${hue} 28% 60%)"/><stop offset="1" stop-color="hsl(${hue} 22% 26%)"/></linearGradient></defs><rect width="320" height="320" fill="url(#g)"/><circle cx="100" cy="110" r="56" fill="hsl(${hue} 40% 82%)" opacity=".55"/><rect x="170" y="190" width="120" height="90" fill="hsl(${hue} 15% 18%)" opacity=".7"/></svg>`
|
|
336
|
+
);
|
|
337
|
+
var mockFamilyTiles = [
|
|
338
|
+
{ slug: "italian", label: "Italian", countLabel: "66", href: "/menu/cuisines/italian", gradient: familyGradient(38), photoUrl: familyPhoto(30) },
|
|
339
|
+
{ slug: "romanian", label: "Romanian", countLabel: "64", href: "/menu/cuisines/romanian", gradient: familyGradient(25), photoUrl: familyPhoto(10) },
|
|
340
|
+
{ slug: "breakfast-brunch", label: "Breakfast & brunch", countLabel: "64", href: "/menu/cuisines/breakfast-brunch", gradient: familyGradient(82), photoUrl: familyPhoto(45) },
|
|
341
|
+
{ slug: "vegetarian", label: "Vegetarian", countLabel: "64", href: "/menu/cuisines/vegetarian", gradient: familyGradient(148), photoUrl: familyPhoto(120) },
|
|
342
|
+
{ slug: "pizza", label: "Pizza", countLabel: "63", href: "/menu/cuisines/pizza", gradient: familyGradient(58), photoUrl: familyPhoto(20) },
|
|
343
|
+
{ slug: "vegan", label: "Vegan", countLabel: "38", href: "/menu/cuisines/vegan", gradient: familyGradient(135), photoUrl: familyPhoto(100) },
|
|
344
|
+
{ slug: "bakery", label: "Bakeries & patisseries", countLabel: "65", href: "/menu/cuisines/bakery", gradient: familyGradient(72) }
|
|
341
345
|
];
|
|
346
|
+
var mockFamilyTilesAll = {
|
|
347
|
+
slug: "all",
|
|
348
|
+
label: "All 38 cuisines",
|
|
349
|
+
countLabel: "The full index",
|
|
350
|
+
href: "/menu/cuisines",
|
|
351
|
+
gradient: "linear-gradient(150deg, oklch(0.50 0.03 70), oklch(0.40 0.028 64))",
|
|
352
|
+
photoUrl: familyPhoto(60)
|
|
353
|
+
};
|
|
342
354
|
var mockFormatters = {
|
|
343
355
|
price: (value) => `${value} lei`,
|
|
344
356
|
number: (value) => value.toLocaleString("en-US"),
|
|
@@ -501,4 +513,4 @@ var mockQa = [
|
|
|
501
513
|
}
|
|
502
514
|
];
|
|
503
515
|
|
|
504
|
-
export { mockBareFamilyBlock, mockConcept, mockDrinkFamily, mockFamily, mockFamilyBlock, mockFilterChips, mockFormatters, mockGradients, mockHubLabels, mockIndexEntries, mockIntentFigures,
|
|
516
|
+
export { mockBareFamilyBlock, mockConcept, mockDrinkFamily, mockFamily, mockFamilyBlock, mockFamilyTiles, mockFamilyTilesAll, mockFilterChips, mockFormatters, mockGradients, mockHubLabels, mockIndexEntries, mockIntentFigures, mockItems, mockKitchens, mockLoosenOptions, mockMatchedKitchens, mockPlaces, mockQa, mockVenues };
|
|
@@ -126,6 +126,20 @@ type MenuConceptRow = {
|
|
|
126
126
|
featured?: boolean;
|
|
127
127
|
/** Portion, already formatted with its unit, e.g. "260g". */
|
|
128
128
|
portion_label?: string;
|
|
129
|
+
/**
|
|
130
|
+
* What this room WON — "CHEAPEST", "MOST NAMED", "HIGHEST GRADE",
|
|
131
|
+
* "DEAREST" — already localised. A card whose rooms are four winners rather
|
|
132
|
+
* than four ranks sets one per room; without it the card falls back to
|
|
133
|
+
* "cheapest, then #2, #3, #4".
|
|
134
|
+
*/
|
|
135
|
+
badge?: string;
|
|
136
|
+
/** Which figure the badge is about; that figure is emphasised. */
|
|
137
|
+
lead?: 'price' | 'mentions' | 'grade';
|
|
138
|
+
/**
|
|
139
|
+
* The venue's BearMenu grade, pre-formatted ("9.2"). Takes the star's
|
|
140
|
+
* place beside the kitchen's name; `rating` (Google's) shows only without it.
|
|
141
|
+
*/
|
|
142
|
+
grade?: string;
|
|
129
143
|
};
|
|
130
144
|
/**
|
|
131
145
|
* A browsable grouping of venues — a cuisine on the dishes tab, a drink family
|
|
@@ -190,17 +204,21 @@ type MenuVenueSignature = {
|
|
|
190
204
|
isSignature?: boolean;
|
|
191
205
|
};
|
|
192
206
|
/**
|
|
193
|
-
*
|
|
207
|
+
* A family tile — a cuisine on the dishes tab, a going-out family on the
|
|
208
|
+
* drinks tab — as the hub's doorway grid draws it: a hue, a name, a venue
|
|
209
|
+
* count and one venue's photograph.
|
|
194
210
|
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* rather than linking nowhere.
|
|
211
|
+
* `href` is required: a tile that cannot resolve to a real destination is not
|
|
212
|
+
* rendered rather than linking nowhere.
|
|
198
213
|
*/
|
|
199
|
-
type
|
|
214
|
+
type MenuFamilyTile = {
|
|
200
215
|
slug: string;
|
|
201
216
|
label: string;
|
|
202
|
-
/**
|
|
203
|
-
|
|
217
|
+
/**
|
|
218
|
+
* The venue count, already formatted by the caller — "64", "1,204" — because
|
|
219
|
+
* thousands separators are locale-dependent and the DS owns no locale.
|
|
220
|
+
*/
|
|
221
|
+
countLabel?: string;
|
|
204
222
|
href: string;
|
|
205
223
|
/**
|
|
206
224
|
* Finished CSS gradient for the tile's ground, e.g.
|
|
@@ -213,8 +231,8 @@ type MenuIntentTile = {
|
|
|
213
231
|
* — visible and obviously unstyled, rather than white text on white.
|
|
214
232
|
*/
|
|
215
233
|
gradient?: string;
|
|
216
|
-
/**
|
|
217
|
-
|
|
234
|
+
/** Pre-resolved VENUE photograph. Venue photography is real; item photography is not. */
|
|
235
|
+
photoUrl?: string;
|
|
218
236
|
};
|
|
219
237
|
/**
|
|
220
238
|
* One figure in the intent hero — a number the reader can tap to filter by.
|
|
@@ -333,6 +351,11 @@ type MenuIndexEntry = {
|
|
|
333
351
|
slug: string;
|
|
334
352
|
name: string;
|
|
335
353
|
count: number;
|
|
354
|
+
/**
|
|
355
|
+
* `count`, already formatted ("1,204"). The list is a client component and a
|
|
356
|
+
* formatter cannot cross into it from a server caller; a string can.
|
|
357
|
+
*/
|
|
358
|
+
countLabel?: string;
|
|
336
359
|
href: string;
|
|
337
360
|
/** Finished CSS gradient for the mark. Falls back to the border colour. */
|
|
338
361
|
gradient?: string;
|
|
@@ -418,4 +441,4 @@ type MenuHubLabels = {
|
|
|
418
441
|
until: string;
|
|
419
442
|
};
|
|
420
443
|
|
|
421
|
-
export { type MenuConceptPreview, type MenuConceptRow, type MenuFamilyBlockPreview, type MenuFamilyChip, type MenuFamilyPreview, type MenuFilterChip, type MenuFormatters, type MenuHubLabels, type MenuIndexEntry, type MenuIntentFigure, type
|
|
444
|
+
export { type MenuConceptPreview, type MenuConceptRow, type MenuFamilyBlockPreview, type MenuFamilyChip, type MenuFamilyPreview, type MenuFamilyTile, type MenuFilterChip, type MenuFormatters, type MenuHubLabels, type MenuIndexEntry, type MenuIntentFigure, type MenuItemPlaceRef, type MenuItemPreview, type MenuKitchenDish, type MenuKitchenPreview, type MenuLinkComponent, type MenuLinkProps, type MenuLoosenOption, MenuSizeAndPrice, type MenuVenuePreview, type MenuVenueSignature, type QaItem };
|
|
@@ -2,9 +2,9 @@ import { Popover, PopoverTrigger, PopoverContent } from '../chunk-66MAPLXS.js';
|
|
|
2
2
|
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-XNA2INVQ.js';
|
|
3
3
|
import '../chunk-FRPPIXMY.js';
|
|
4
4
|
import { Checkbox } from '../chunk-D5QHEHXJ.js';
|
|
5
|
-
import { Button } from '../chunk-
|
|
5
|
+
import { Button } from '../chunk-VAXOQS7W.js';
|
|
6
6
|
import '../chunk-R47NEOSI.js';
|
|
7
|
-
import { Badge } from '../chunk-
|
|
7
|
+
import { Badge } from '../chunk-2CXU5WZO.js';
|
|
8
8
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
9
9
|
import '../chunk-3GWWZKX7.js';
|
|
10
10
|
import * as React from 'react';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buttonVariants } from '../chunk-
|
|
1
|
+
import { buttonVariants } from '../chunk-VAXOQS7W.js';
|
|
2
2
|
import '../chunk-R47NEOSI.js';
|
|
3
3
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
4
4
|
import { __objRest, __spreadValues, __spreadProps } from '../chunk-3GWWZKX7.js';
|
|
@@ -14,7 +14,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
14
14
|
*
|
|
15
15
|
* It owns the photographs and their colour: the ground, the tiles, the fallback
|
|
16
16
|
* initial, the family's hue and an optional uniform dark overlay. It does NOT
|
|
17
|
-
* own the
|
|
17
|
+
* own the ink — the scrims and bands that carry a card's type run in
|
|
18
18
|
* a different direction on every card (down the family block's phone, across
|
|
19
19
|
* its desktop, in from both ends of the concept card) and are the card's own.
|
|
20
20
|
*
|
|
@@ -57,8 +57,14 @@ type PhotoGroundProps = {
|
|
|
57
57
|
overlayClassName?: string;
|
|
58
58
|
/** How eagerly the first photograph loads. `stack` grounds are above the fold. */
|
|
59
59
|
loading?: "lazy" | "eager";
|
|
60
|
+
/**
|
|
61
|
+
* Classes on the fallback initial — its size, when the ground is smaller
|
|
62
|
+
* than a card. The 64px default fills a card cell; a tile's 88px polaroid
|
|
63
|
+
* passes `text-[44px]`.
|
|
64
|
+
*/
|
|
65
|
+
glyphClassName?: string;
|
|
60
66
|
className?: string;
|
|
61
67
|
};
|
|
62
|
-
declare function PhotoGround({ photos, initials, mode, active, mosaicClassName, phoneTiles, gradient, overlay, overlayClassName, loading, className, }: PhotoGroundProps): react_jsx_runtime.JSX.Element;
|
|
68
|
+
declare function PhotoGround({ photos, initials, mode, active, mosaicClassName, phoneTiles, gradient, overlay, overlayClassName, loading, glyphClassName, className, }: PhotoGroundProps): react_jsx_runtime.JSX.Element;
|
|
63
69
|
|
|
64
70
|
export { PHOTO_GROUND, PhotoGround, type PhotoGroundProps };
|
|
@@ -3,7 +3,7 @@ import '../chunk-VG3PND3D.js';
|
|
|
3
3
|
import '../chunk-ZDAHKI3A.js';
|
|
4
4
|
import '../chunk-WSRWFA6K.js';
|
|
5
5
|
import { Text } from '../chunk-7BWTYWM3.js';
|
|
6
|
-
import { Badge } from '../chunk-
|
|
6
|
+
import { Badge } from '../chunk-2CXU5WZO.js';
|
|
7
7
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
8
8
|
import '../chunk-3GWWZKX7.js';
|
|
9
9
|
import { useState } from 'react';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Popover, PopoverTrigger, PopoverContent } from '../chunk-66MAPLXS.js';
|
|
2
2
|
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-XNA2INVQ.js';
|
|
3
3
|
import '../chunk-FRPPIXMY.js';
|
|
4
|
-
import { Button } from '../chunk-
|
|
4
|
+
import { Button } from '../chunk-VAXOQS7W.js';
|
|
5
5
|
import '../chunk-R47NEOSI.js';
|
|
6
6
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
7
7
|
import '../chunk-3GWWZKX7.js';
|
|
@@ -18,8 +18,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
18
18
|
*
|
|
19
19
|
* `surface="image"` is for card covers, where the chip sits over the photo
|
|
20
20
|
* rather than in the caption block. The accent-on-canvas palette has no
|
|
21
|
-
* contrast guarantee over an arbitrary photo, so it swaps to the same
|
|
22
|
-
* fill the place badge uses there and keeps the dashed edge — which is what
|
|
21
|
+
* contrast guarantee over an arbitrary photo, so it swaps to the same solid
|
|
22
|
+
* ink fill the place badge uses there and keeps the dashed edge — which is what
|
|
23
23
|
* says "there is evidence behind this" — in the inverted colour.
|
|
24
24
|
*
|
|
25
25
|
* The label is passed in: the DS owns no translation keys.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { MenuItem } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
import { MenuItem } from '../chunk-UDTG3RSE.js';
|
|
2
|
+
import '../chunk-6TEEY5YA.js';
|
|
3
3
|
import { Separator } from '../chunk-WSRWFA6K.js';
|
|
4
4
|
import { Skeleton } from '../chunk-QXHMPJ35.js';
|
|
5
|
-
import '../chunk-
|
|
5
|
+
import '../chunk-2CXU5WZO.js';
|
|
6
6
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
7
7
|
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|
|
8
8
|
import { MapPin, Star, MessageSquareQuote } from 'lucide-react';
|
|
@@ -6,7 +6,7 @@ import { CitedText } from './place-types.js';
|
|
|
6
6
|
*
|
|
7
7
|
* These are `reviews_digest.highlights`: one to three short positives already
|
|
8
8
|
* resolved into the request locale. They are the only place on a hub where a
|
|
9
|
-
* reviewer speaks in their own register, so they are set in serif
|
|
9
|
+
* reviewer speaks in their own register, so they are set in quoted serif
|
|
10
10
|
* against the sans everything else uses.
|
|
11
11
|
*
|
|
12
12
|
* `onCite` turns a quote into a button that opens the reviews behind it —
|