@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.
- package/dist/chunk-24RFI4RQ.js +167 -0
- package/dist/chunk-2XCZJWTV.js +121 -0
- package/dist/chunk-5RWTOT5Y.js +72 -0
- 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-MZL7CGCL.js +109 -0
- package/dist/chunk-SY6RV476.js +48 -0
- package/dist/chunk-UDN7UHJW.js +60 -0
- package/dist/{chunk-TT3WFS6S.js → chunk-YOKHBAIH.js} +11 -11
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/command.d.ts +7 -7
- 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/date-input.d.ts +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 +1 -1
- package/dist/components/event-index-row.js +1 -1
- package/dist/components/event-list-row-wide.js +1 -1
- 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/glass-ground.d.ts +66 -0
- package/dist/components/glass-ground.js +3 -0
- 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/kitchen-dossier.d.ts +88 -0
- package/dist/components/kitchen-dossier.js +187 -0
- 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 +99 -0
- package/dist/components/menu-family-block.js +155 -0
- package/dist/components/menu-family-card.d.ts +33 -27
- package/dist/components/menu-family-card.js +43 -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-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-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/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 +2 -2
- 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/snap-rail.d.ts +24 -1
- package/dist/components/snap-rail.js +3 -109
- package/dist/components/spinner.d.ts +2 -2
- package/dist/components/story.d.ts +34 -0
- package/dist/components/story.js +3 -0
- package/dist/components/text.d.ts +3 -3
- 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/weekend-panel.js +2 -2
- package/package.json +1 -1
- package/src/components/concept-compare-rail.tsx +131 -0
- package/src/components/concept-compare.stories.tsx +122 -54
- package/src/components/concept-compare.tsx +363 -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 +129 -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 +322 -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 +314 -0
- package/src/components/menu-family-card.stories.tsx +43 -35
- package/src/components/menu-family-card.tsx +122 -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-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/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/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
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { stagger, ease, duration, springSnappy } from './chunk-LEAYBICI.js';
|
|
2
|
+
import { cn } from './chunk-FEK5XGZW.js';
|
|
3
|
+
import { __spreadValues, __spreadProps } from './chunk-3GWWZKX7.js';
|
|
4
|
+
import { motion, useReducedMotion } from 'framer-motion';
|
|
5
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var LINE_LEAD = 0.15;
|
|
8
|
+
var TARGET_DELAY = 0.38;
|
|
9
|
+
var sourcesContainer = {
|
|
10
|
+
hidden: {},
|
|
11
|
+
show: { transition: { delayChildren: 0.06, staggerChildren: stagger.tight } }
|
|
12
|
+
};
|
|
13
|
+
var sourceItem = {
|
|
14
|
+
hidden: { opacity: 0, x: -8 },
|
|
15
|
+
show: { opacity: 1, x: 0, transition: { duration: duration.quick, ease: ease.enter } }
|
|
16
|
+
};
|
|
17
|
+
var targetItem = {
|
|
18
|
+
hidden: { opacity: 0, scale: 0.92 },
|
|
19
|
+
show: { opacity: 1, scale: 1, transition: __spreadValues({ delay: TARGET_DELAY }, springSnappy) }
|
|
20
|
+
};
|
|
21
|
+
var LINES_WIDTH = 40;
|
|
22
|
+
var LINES_HEIGHT = 100;
|
|
23
|
+
function ConvergeLines({ count, animate = true, className }) {
|
|
24
|
+
const mid = LINES_HEIGHT / 2;
|
|
25
|
+
return /* @__PURE__ */ jsx(
|
|
26
|
+
"svg",
|
|
27
|
+
{
|
|
28
|
+
"aria-hidden": true,
|
|
29
|
+
viewBox: `0 0 ${LINES_WIDTH} ${LINES_HEIGHT}`,
|
|
30
|
+
preserveAspectRatio: "none",
|
|
31
|
+
className: cn("h-full w-10 text-border", className),
|
|
32
|
+
children: Array.from({ length: count }, (_, index) => {
|
|
33
|
+
const y = (index + 0.5) / count * LINES_HEIGHT;
|
|
34
|
+
const d = `M0 ${y} C ${LINES_WIDTH / 2} ${y}, ${LINES_WIDTH / 2} ${mid}, ${LINES_WIDTH} ${mid}`;
|
|
35
|
+
const stroke = {
|
|
36
|
+
d,
|
|
37
|
+
fill: "none",
|
|
38
|
+
stroke: "currentColor",
|
|
39
|
+
strokeWidth: 1.5,
|
|
40
|
+
strokeLinecap: "round",
|
|
41
|
+
vectorEffect: "non-scaling-stroke"
|
|
42
|
+
};
|
|
43
|
+
return animate ? /* @__PURE__ */ jsx(
|
|
44
|
+
motion.path,
|
|
45
|
+
__spreadProps(__spreadValues({}, stroke), {
|
|
46
|
+
initial: { pathLength: 0, opacity: 0 },
|
|
47
|
+
animate: { pathLength: 1, opacity: 1 },
|
|
48
|
+
transition: {
|
|
49
|
+
delay: LINE_LEAD + index * stagger.tight,
|
|
50
|
+
duration: duration.standard,
|
|
51
|
+
ease: ease.standard
|
|
52
|
+
}
|
|
53
|
+
}),
|
|
54
|
+
index
|
|
55
|
+
) : /* @__PURE__ */ jsx("path", __spreadValues({}, stroke), index);
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
function Convergence({
|
|
61
|
+
sources,
|
|
62
|
+
target,
|
|
63
|
+
animate = true,
|
|
64
|
+
linesClassName,
|
|
65
|
+
className
|
|
66
|
+
}) {
|
|
67
|
+
const reduce = useReducedMotion();
|
|
68
|
+
const run = animate && !reduce;
|
|
69
|
+
const fadeOnly = animate && reduce;
|
|
70
|
+
return /* @__PURE__ */ jsxs(
|
|
71
|
+
motion.div,
|
|
72
|
+
{
|
|
73
|
+
className: cn("grid grid-cols-[minmax(0,1fr)_auto_auto] items-center", className),
|
|
74
|
+
initial: fadeOnly ? { opacity: 0 } : false,
|
|
75
|
+
animate: fadeOnly ? { opacity: 1 } : void 0,
|
|
76
|
+
transition: { duration: duration.quick, ease: ease.standard },
|
|
77
|
+
children: [
|
|
78
|
+
/* @__PURE__ */ jsx(
|
|
79
|
+
motion.div,
|
|
80
|
+
{
|
|
81
|
+
className: cn(
|
|
82
|
+
"flex min-w-0 flex-col items-start justify-center gap-2 py-1",
|
|
83
|
+
/* The fan: the middle sources sit a little further right than the
|
|
84
|
+
ends, so five chips read as one hand of cards, not as a menu. */
|
|
85
|
+
"[&>*:nth-child(2)]:translate-x-1.5 [&>*:nth-child(3)]:translate-x-3 [&>*:nth-child(4)]:translate-x-1.5"
|
|
86
|
+
),
|
|
87
|
+
variants: run ? sourcesContainer : void 0,
|
|
88
|
+
initial: run ? "hidden" : false,
|
|
89
|
+
animate: run ? "show" : void 0,
|
|
90
|
+
children: sources.map((node, index) => /* @__PURE__ */ jsx(motion.div, { className: "flex max-w-full", variants: run ? sourceItem : void 0, children: node }, index))
|
|
91
|
+
}
|
|
92
|
+
),
|
|
93
|
+
/* @__PURE__ */ jsx("div", { className: "self-stretch", children: /* @__PURE__ */ jsx(ConvergeLines, { count: sources.length, animate: run, className: linesClassName }) }),
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
motion.div,
|
|
96
|
+
{
|
|
97
|
+
className: "flex items-center",
|
|
98
|
+
variants: run ? targetItem : void 0,
|
|
99
|
+
initial: run ? "hidden" : false,
|
|
100
|
+
animate: run ? "show" : void 0,
|
|
101
|
+
children: target
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export { ConvergeLines, Convergence };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { cn } from './chunk-FEK5XGZW.js';
|
|
2
|
+
import { __spreadProps, __spreadValues } from './chunk-3GWWZKX7.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var STOPS = [0, 0.25, 0.5, 0.75, 1];
|
|
6
|
+
var EASE = [0, 0.06, 0.25, 0.56, 1];
|
|
7
|
+
var FROST_SOFT = "[mask-image:linear-gradient(var(--glass-dir),transparent_var(--glass-s0),rgba(0,0,0,0.25)_var(--glass-s1),black_var(--glass-s2))] lg:[mask-image:linear-gradient(var(--glass-lg-dir),transparent_var(--glass-lg-s0),rgba(0,0,0,0.25)_var(--glass-lg-s1),black_var(--glass-lg-s2))]";
|
|
8
|
+
var FROST_HEAVY = "[mask-image:linear-gradient(var(--glass-dir),transparent_var(--glass-s1),rgba(0,0,0,0.25)_var(--glass-s2),rgba(0,0,0,0.6)_var(--glass-s3),black_var(--glass-s4))] lg:[mask-image:linear-gradient(var(--glass-lg-dir),transparent_var(--glass-lg-s1),rgba(0,0,0,0.25)_var(--glass-lg-s2),rgba(0,0,0,0.6)_var(--glass-lg-s3),black_var(--glass-lg-s4))]";
|
|
9
|
+
var INK = "bg-[linear-gradient(var(--glass-dir),oklch(0.16_0.012_55_/_0)_var(--glass-s0),oklch(0.16_0.012_55_/_var(--glass-a1))_var(--glass-s1),oklch(0.16_0.012_55_/_var(--glass-a2))_var(--glass-s2),oklch(0.16_0.012_55_/_var(--glass-a3))_var(--glass-s3),oklch(0.16_0.012_55_/_var(--glass-a4))_var(--glass-s4),oklch(0.16_0.012_55_/_var(--glass-a-peak))_100%)] lg:bg-[linear-gradient(var(--glass-lg-dir),oklch(0.16_0.012_55_/_0)_var(--glass-lg-s0),oklch(0.16_0.012_55_/_var(--glass-a1))_var(--glass-lg-s1),oklch(0.16_0.012_55_/_var(--glass-a2))_var(--glass-lg-s2),oklch(0.16_0.012_55_/_var(--glass-a3))_var(--glass-lg-s3),oklch(0.16_0.012_55_/_var(--glass-a4))_var(--glass-lg-s4),oklch(0.16_0.012_55_/_var(--glass-a-peak))_100%)]";
|
|
10
|
+
var BLUR = {
|
|
11
|
+
sm: ["backdrop-blur-[2px]", "backdrop-blur-sm"],
|
|
12
|
+
md: ["backdrop-blur-sm", "backdrop-blur-md"],
|
|
13
|
+
lg: ["backdrop-blur-md", "backdrop-blur-lg"],
|
|
14
|
+
xl: ["backdrop-blur-lg", "backdrop-blur-xl"]
|
|
15
|
+
};
|
|
16
|
+
function measure(value) {
|
|
17
|
+
const match = value.trim().match(/^(-?\d*\.?\d+)\s*([a-z%]*)$/i);
|
|
18
|
+
if (!match) throw new Error(`GlassGround: cannot read stop "${value}"`);
|
|
19
|
+
return [Number(match[1]), match[2] || "px"];
|
|
20
|
+
}
|
|
21
|
+
function positions(clear, full) {
|
|
22
|
+
const [from, unit] = measure(clear);
|
|
23
|
+
const [to] = measure(full);
|
|
24
|
+
return STOPS.map((fraction) => `${from + (to - from) * fraction}${unit}`);
|
|
25
|
+
}
|
|
26
|
+
function GlassGround({
|
|
27
|
+
stops,
|
|
28
|
+
lgStops = stops,
|
|
29
|
+
peak = 0.96,
|
|
30
|
+
blur = "xl",
|
|
31
|
+
className
|
|
32
|
+
}) {
|
|
33
|
+
const base = positions(stops.clear, stops.full);
|
|
34
|
+
const lg = positions(lgStops.clear, lgStops.full);
|
|
35
|
+
const style = __spreadProps(__spreadValues(__spreadValues(__spreadValues({
|
|
36
|
+
"--glass-dir": stops.direction,
|
|
37
|
+
"--glass-lg-dir": lgStops.direction
|
|
38
|
+
}, Object.fromEntries(base.map((position, index) => [`--glass-s${index}`, position]))), Object.fromEntries(lg.map((position, index) => [`--glass-lg-s${index}`, position]))), Object.fromEntries(EASE.slice(1).map((share, index) => [`--glass-a${index + 1}`, String(peak * 0.8 * share)]))), {
|
|
39
|
+
"--glass-a-peak": String(peak)
|
|
40
|
+
});
|
|
41
|
+
return /* @__PURE__ */ jsxs("span", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-0 block", className), style, children: [
|
|
42
|
+
/* @__PURE__ */ jsx("span", { className: cn("absolute inset-0", BLUR[blur][0], FROST_SOFT) }),
|
|
43
|
+
/* @__PURE__ */ jsx("span", { className: cn("absolute inset-0", BLUR[blur][1], FROST_HEAVY) }),
|
|
44
|
+
/* @__PURE__ */ jsx("span", { className: cn("absolute inset-0", INK) })
|
|
45
|
+
] });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { GlassGround };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { SnapRail, SnapRailDots } from './chunk-DTXNDLSE.js';
|
|
2
|
+
import { PhotoGround } from './chunk-5RWTOT5Y.js';
|
|
3
|
+
import { cn } from './chunk-FEK5XGZW.js';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var FOOT_GLASS = cn(
|
|
8
|
+
"before:pointer-events-none before:absolute before:inset-0 before:-z-10 before:content-[''] before:backdrop-blur-lg",
|
|
9
|
+
"before:bg-[oklch(0.16_0.012_55_/_0.9)]",
|
|
10
|
+
"lg:before:[mask-image:linear-gradient(to_top,black_60%,transparent_100%)] lg:before:bg-[linear-gradient(to_top,oklch(0.16_0.012_55_/_0.88)_0%,oklch(0.16_0.012_55_/_0.84)_60%,oklch(0.16_0.012_55_/_0.4)_85%,oklch(0.16_0.012_55_/_0)_100%)]"
|
|
11
|
+
);
|
|
12
|
+
function ConceptCompareRail({
|
|
13
|
+
backdrops,
|
|
14
|
+
railClassName,
|
|
15
|
+
foot,
|
|
16
|
+
children
|
|
17
|
+
}) {
|
|
18
|
+
const [active, setActive] = React.useState(0);
|
|
19
|
+
const count = React.Children.count(children);
|
|
20
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
21
|
+
/* @__PURE__ */ jsx(
|
|
22
|
+
PhotoGround,
|
|
23
|
+
{
|
|
24
|
+
className: "-z-10 lg:hidden",
|
|
25
|
+
mode: "stack",
|
|
26
|
+
active,
|
|
27
|
+
photos: backdrops.map((backdrop) => backdrop.src),
|
|
28
|
+
initials: backdrops.map((backdrop) => backdrop.initial),
|
|
29
|
+
overlay: true,
|
|
30
|
+
loading: "eager"
|
|
31
|
+
}
|
|
32
|
+
),
|
|
33
|
+
/* @__PURE__ */ jsx(
|
|
34
|
+
SnapRail,
|
|
35
|
+
{
|
|
36
|
+
itemWidth: "full",
|
|
37
|
+
gap: "sm",
|
|
38
|
+
onActiveChange: setActive,
|
|
39
|
+
className: cn("pb-0 overscroll-x-contain", railClassName),
|
|
40
|
+
children
|
|
41
|
+
}
|
|
42
|
+
),
|
|
43
|
+
foot && /* @__PURE__ */ jsxs(
|
|
44
|
+
"div",
|
|
45
|
+
{
|
|
46
|
+
className: cn(
|
|
47
|
+
"relative isolate flex flex-col gap-3 px-4 pb-4 pt-3",
|
|
48
|
+
"lg:absolute lg:inset-x-0 lg:bottom-0 lg:z-10 lg:flex-row lg:items-center lg:gap-5 lg:px-5 lg:pb-4 lg:pt-6",
|
|
49
|
+
FOOT_GLASS
|
|
50
|
+
),
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsx(SnapRailDots, { count, active, className: "lg:hidden" }),
|
|
53
|
+
foot
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
] });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { ConceptCompareRail };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { beats, returnTransition, MotionIcon } from './chunk-
|
|
1
|
+
import { beats, returnTransition, MotionIcon, pivot } from './chunk-G7IFL4Z4.js';
|
|
2
2
|
import { __spreadProps, __spreadValues } from './chunk-3GWWZKX7.js';
|
|
3
3
|
import { motion } from 'framer-motion';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
@@ -19,7 +19,7 @@ function MotionHeart(props) {
|
|
|
19
19
|
motion.path,
|
|
20
20
|
{
|
|
21
21
|
variants: heartBody,
|
|
22
|
-
style:
|
|
22
|
+
style: pivot(12, 13),
|
|
23
23
|
fill: "currentColor",
|
|
24
24
|
fillOpacity: 0,
|
|
25
25
|
d: "M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5"
|
|
@@ -43,7 +43,7 @@ function MotionBookmark(props) {
|
|
|
43
43
|
motion.path,
|
|
44
44
|
{
|
|
45
45
|
variants: bookmarkBody,
|
|
46
|
-
style:
|
|
46
|
+
style: pivot(12, 21),
|
|
47
47
|
fill: "currentColor",
|
|
48
48
|
fillOpacity: 0,
|
|
49
49
|
d: "M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"
|
|
@@ -89,7 +89,7 @@ var found = {
|
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
91
|
function MotionSearch(props) {
|
|
92
|
-
return /* @__PURE__ */ jsx(MotionIcon, __spreadProps(__spreadValues({}, props), { children: /* @__PURE__ */ jsxs(motion.g, { variants: lens, style:
|
|
92
|
+
return /* @__PURE__ */ jsx(MotionIcon, __spreadProps(__spreadValues({}, props), { children: /* @__PURE__ */ jsxs(motion.g, { variants: lens, style: pivot(21, 21), children: [
|
|
93
93
|
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
|
|
94
94
|
/* @__PURE__ */ jsx("path", { d: "m21 21-4.34-4.34" }),
|
|
95
95
|
/* @__PURE__ */ jsx(
|
|
@@ -97,7 +97,7 @@ function MotionSearch(props) {
|
|
|
97
97
|
{
|
|
98
98
|
variants: found,
|
|
99
99
|
opacity: 0,
|
|
100
|
-
style:
|
|
100
|
+
style: pivot(11, 11),
|
|
101
101
|
fill: "currentColor",
|
|
102
102
|
cx: "11",
|
|
103
103
|
cy: "11",
|
|
@@ -207,7 +207,7 @@ var crescent = {
|
|
|
207
207
|
}
|
|
208
208
|
};
|
|
209
209
|
function MotionTheme(props) {
|
|
210
|
-
const origin =
|
|
210
|
+
const origin = pivot(12, 12);
|
|
211
211
|
return /* @__PURE__ */ jsxs(MotionIcon, __spreadProps(__spreadValues({}, props), { children: [
|
|
212
212
|
/* @__PURE__ */ jsx(motion.g, { variants: rays, style: origin, children: SUN_RAYS.map((d) => /* @__PURE__ */ jsx("path", { d }, d)) }),
|
|
213
213
|
/* @__PURE__ */ jsx(motion.circle, { variants: disc, style: origin, cx: "12", cy: "12", r: "4" }),
|
|
@@ -232,7 +232,7 @@ var chevron = {
|
|
|
232
232
|
}
|
|
233
233
|
};
|
|
234
234
|
function MotionChevron(props) {
|
|
235
|
-
return /* @__PURE__ */ jsx(MotionIcon, __spreadProps(__spreadValues({}, props), { children: /* @__PURE__ */ jsx(motion.path, { variants: chevron, style:
|
|
235
|
+
return /* @__PURE__ */ jsx(MotionIcon, __spreadProps(__spreadValues({}, props), { children: /* @__PURE__ */ jsx(motion.path, { variants: chevron, style: pivot(12, 12), d: "m6 9 6 6 6-6" }) }));
|
|
236
236
|
}
|
|
237
237
|
var PLAYPAUSE_TIMES = [0, 0.24, 0.72, 1];
|
|
238
238
|
var playHead = {
|
|
@@ -255,7 +255,7 @@ function pauseBar(dx) {
|
|
|
255
255
|
var barLeft = pauseBar(5);
|
|
256
256
|
var barRight = pauseBar(-5);
|
|
257
257
|
function MotionPlayPause(props) {
|
|
258
|
-
const origin =
|
|
258
|
+
const origin = pivot(12, 12);
|
|
259
259
|
return /* @__PURE__ */ jsxs(MotionIcon, __spreadProps(__spreadValues({}, props), { children: [
|
|
260
260
|
/* @__PURE__ */ jsx(
|
|
261
261
|
motion.path,
|
|
@@ -290,7 +290,7 @@ var slash = {
|
|
|
290
290
|
}
|
|
291
291
|
};
|
|
292
292
|
function MotionEye(props) {
|
|
293
|
-
const origin =
|
|
293
|
+
const origin = pivot(12, 12);
|
|
294
294
|
return /* @__PURE__ */ jsxs(MotionIcon, __spreadProps(__spreadValues({}, props), { children: [
|
|
295
295
|
/* @__PURE__ */ jsx(
|
|
296
296
|
motion.path,
|
|
@@ -320,7 +320,7 @@ function MotionStar(props) {
|
|
|
320
320
|
motion.path,
|
|
321
321
|
{
|
|
322
322
|
variants: starBody,
|
|
323
|
-
style:
|
|
323
|
+
style: pivot(12, 12),
|
|
324
324
|
fill: "currentColor",
|
|
325
325
|
fillOpacity: 0,
|
|
326
326
|
d: "M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"
|
|
@@ -368,7 +368,7 @@ var refreshRing = {
|
|
|
368
368
|
}
|
|
369
369
|
};
|
|
370
370
|
function MotionRefresh(props) {
|
|
371
|
-
return /* @__PURE__ */ jsx(MotionIcon, __spreadProps(__spreadValues({}, props), { children: /* @__PURE__ */ jsxs(motion.g, { variants: refreshRing, style:
|
|
371
|
+
return /* @__PURE__ */ jsx(MotionIcon, __spreadProps(__spreadValues({}, props), { children: /* @__PURE__ */ jsxs(motion.g, { variants: refreshRing, style: pivot(12, 12), children: [
|
|
372
372
|
/* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
|
|
373
373
|
/* @__PURE__ */ jsx("path", { d: "M21 3v5h-5" }),
|
|
374
374
|
/* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
|
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const badgeVariants: (props?: ({
|
|
7
|
-
variant?: "default" | "
|
|
7
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "glass" | "overlay" | "brown" | "success" | "warning" | null | undefined;
|
|
8
8
|
live?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "glass" | "overlay" | "brown" | "antagonist" | null | undefined;
|
|
7
7
|
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
8
8
|
fullWidth?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
@@ -8,7 +8,7 @@ declare const Command: React.ForwardRefExoticComponent<Omit<{
|
|
|
8
8
|
ref?: React.Ref<HTMLDivElement>;
|
|
9
9
|
} & {
|
|
10
10
|
asChild?: boolean;
|
|
11
|
-
}, "key" |
|
|
11
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
12
12
|
label?: string;
|
|
13
13
|
shouldFilter?: boolean;
|
|
14
14
|
filter?: (value: string, search: string, keywords?: string[]) => number;
|
|
@@ -38,7 +38,7 @@ declare const CommandList: React.ForwardRefExoticComponent<Omit<{
|
|
|
38
38
|
ref?: React.Ref<HTMLDivElement>;
|
|
39
39
|
} & {
|
|
40
40
|
asChild?: boolean;
|
|
41
|
-
}, "key" |
|
|
41
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
42
42
|
label?: string;
|
|
43
43
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
44
44
|
declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
@@ -47,14 +47,14 @@ declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
|
47
47
|
ref?: React.Ref<HTMLDivElement>;
|
|
48
48
|
} & {
|
|
49
49
|
asChild?: boolean;
|
|
50
|
-
}, "key" |
|
|
50
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
51
51
|
declare const CommandLoading: React.ForwardRefExoticComponent<Omit<{
|
|
52
52
|
children?: React.ReactNode;
|
|
53
53
|
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
54
54
|
ref?: React.Ref<HTMLDivElement>;
|
|
55
55
|
} & {
|
|
56
56
|
asChild?: boolean;
|
|
57
|
-
}, "key" |
|
|
57
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
58
58
|
progress?: number;
|
|
59
59
|
label?: string;
|
|
60
60
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -64,7 +64,7 @@ declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
|
64
64
|
ref?: React.Ref<HTMLDivElement>;
|
|
65
65
|
} & {
|
|
66
66
|
asChild?: boolean;
|
|
67
|
-
}, "key" |
|
|
67
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "heading" | "value"> & {
|
|
68
68
|
heading?: React.ReactNode;
|
|
69
69
|
value?: string;
|
|
70
70
|
forceMount?: boolean;
|
|
@@ -73,7 +73,7 @@ declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<R
|
|
|
73
73
|
ref?: React.Ref<HTMLDivElement>;
|
|
74
74
|
} & {
|
|
75
75
|
asChild?: boolean;
|
|
76
|
-
}, "key" |
|
|
76
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
77
77
|
alwaysRender?: boolean;
|
|
78
78
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
79
79
|
declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
@@ -82,7 +82,7 @@ declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
|
82
82
|
ref?: React.Ref<HTMLDivElement>;
|
|
83
83
|
} & {
|
|
84
84
|
asChild?: boolean;
|
|
85
|
-
}, "key" |
|
|
85
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "disabled" | "value"> & {
|
|
86
86
|
disabled?: boolean;
|
|
87
87
|
onSelect?: (value: string) => void;
|
|
88
88
|
value?: string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ConceptCompareRail — the rooms as a rail, the card's backdrop following the
|
|
6
|
+
* active room, and the foot band that carries the page dots.
|
|
7
|
+
*
|
|
8
|
+
* On the phone the card IS the current room's photograph: the head, the rail
|
|
9
|
+
* and the foot all sit on it, and it cross-fades to the next room as the
|
|
10
|
+
* reader swipes. That needs the rail's active index, which is state — so this
|
|
11
|
+
* is the one client boundary in `ConceptCompare`. It takes only what can cross
|
|
12
|
+
* that boundary: photograph URLs, initials, and the pre-rendered rooms and
|
|
13
|
+
* foot as children. `labels`, `formatPrice` and the rest stay server-side.
|
|
14
|
+
*
|
|
15
|
+
* ## Why the backdrop lives here and not in each slide
|
|
16
|
+
*
|
|
17
|
+
* A slide carrying its own photograph is a boxed card sliding over a dark
|
|
18
|
+
* ground; the backdrop changing under a transparent slide is the reader
|
|
19
|
+
* turning to look at the next room. The second is the smoother thing, and it
|
|
20
|
+
* is also cheaper to look at — one photograph at a time instead of the edge of
|
|
21
|
+
* the next one peeking in.
|
|
22
|
+
*
|
|
23
|
+
* ## Why the foot is here too
|
|
24
|
+
*
|
|
25
|
+
* The dots need the rail's state, and on the phone they belong INSIDE the foot
|
|
26
|
+
* band's glass — under the rail they sat on a strip of bare photograph between
|
|
27
|
+
* the room's scrim and the foot's. So the foot renders here, with the dots as
|
|
28
|
+
* its first row below `lg`, and `ConceptCompare` hands it the foot's content.
|
|
29
|
+
*
|
|
30
|
+
* Desktop ignores the backdrop and the dots (`lg:hidden`); each room carries
|
|
31
|
+
* its own photograph there, side by side, and the foot is an absolute glass
|
|
32
|
+
* band over them.
|
|
33
|
+
*/
|
|
34
|
+
type ConceptCompareBackdrop = {
|
|
35
|
+
/** The room's photograph. Absent: the ground with the venue's initial. */
|
|
36
|
+
src?: string;
|
|
37
|
+
/** The venue's first letter, for the no-photograph fallback. */
|
|
38
|
+
initial: string;
|
|
39
|
+
};
|
|
40
|
+
type ConceptCompareRailProps = {
|
|
41
|
+
backdrops: ConceptCompareBackdrop[];
|
|
42
|
+
/** Classes for the rail itself — the desktop grid lives here. */
|
|
43
|
+
railClassName?: string;
|
|
44
|
+
/** The foot's content: the note and the action. Omit for no foot. */
|
|
45
|
+
foot?: React.ReactNode;
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
};
|
|
48
|
+
declare function ConceptCompareRail({ backdrops, railClassName, foot, children, }: ConceptCompareRailProps): react_jsx_runtime.JSX.Element;
|
|
49
|
+
|
|
50
|
+
export { type ConceptCompareBackdrop, ConceptCompareRail, type ConceptCompareRailProps };
|
|
@@ -1,73 +1,110 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { MenuItemLabels } from './menu-item.js';
|
|
3
2
|
import { MenuConceptPreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
4
3
|
import 'react';
|
|
5
4
|
import './place-types.js';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
|
-
* ConceptCompare — one dish or drink across
|
|
9
|
-
* whatever name each of them uses.
|
|
7
|
+
* ConceptCompare — one dish or drink across the kitchens that make it, under
|
|
8
|
+
* whatever name each of them uses. No surfaces at all.
|
|
10
9
|
*
|
|
11
10
|
* The keystone module: a single menu can list papanași, only a catalogue can
|
|
12
|
-
* say that
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* showing each kitchen's own wording is the evidence for that.
|
|
11
|
+
* say that forty-five kitchens make them under eight names between 29 and 52
|
|
12
|
+
* lei. Each kitchen's own wording is the evidence that these are matched rows
|
|
13
|
+
* rather than one row repeated.
|
|
16
14
|
*
|
|
17
|
-
* ## The
|
|
15
|
+
* ## The card IS the rooms
|
|
18
16
|
*
|
|
19
|
-
* Each
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* length is not.
|
|
17
|
+
* Every panel is gone. Each room is a VENUE photograph — real and licensed
|
|
18
|
+
* where an item's would be generated — with the kitchen's line floating over
|
|
19
|
+
* it, and the three readable things sit on glass: the identity in a band
|
|
20
|
+
* across the top, each kitchen's line over its own photograph, the foot along
|
|
21
|
+
* the bottom.
|
|
25
22
|
*
|
|
26
|
-
* ##
|
|
23
|
+
* ## Read across on desktop, one at a time on the phone
|
|
27
24
|
*
|
|
28
|
-
* From `lg` the
|
|
29
|
-
* the
|
|
30
|
-
*
|
|
31
|
-
* the
|
|
25
|
+
* From `lg` the rooms stand side by side — four kitchens, each with its own
|
|
26
|
+
* name for the dish and its own price, so comparing is a horizontal glance —
|
|
27
|
+
* and the head and foot are ABSOLUTE glass bands over them, so the photographs
|
|
28
|
+
* run the full height of the card beneath both. The head's glass fades out
|
|
29
|
+
* downward on the same curve as its mask; the foot's fades out upward the same
|
|
30
|
+
* way. It was the ink stopping short of the mask that drew a line where a band
|
|
31
|
+
* ended.
|
|
32
|
+
*
|
|
33
|
+
* Below `lg` four rooms in a 2×2 was too much happening in one card, so the
|
|
34
|
+
* rooms become a `SnapRail`: one room per swipe, page dots under it, the head
|
|
35
|
+
* and foot static on the card's ground above and below. The dots are the
|
|
36
|
+
* rail's own — the same object the hub's other rails use.
|
|
37
|
+
*
|
|
38
|
+
* ## The dark overlay, and the hover that lifts it
|
|
39
|
+
*
|
|
40
|
+
* Four busy interiors are four competing subjects, and type over them had
|
|
41
|
+
* nothing to sit on but its own local scrim — the eye could not settle. Every
|
|
42
|
+
* photograph carries a uniform dark overlay so the words lead and the picture
|
|
43
|
+
* supports; hovering a room lifts the overlay off THAT room only, so the reader
|
|
44
|
+
* can look at the place they are about to open.
|
|
45
|
+
*
|
|
46
|
+
* ## Light and dark
|
|
47
|
+
*
|
|
48
|
+
* There is nothing in it to theme. Photographs and their scrims are identical
|
|
49
|
+
* in both, because text over an image needs the same treatment either way —
|
|
50
|
+
* the content is `.dark`-scoped for exactly that. What adapts is the card's
|
|
51
|
+
* EDGE: a soft shadow and hairline on light, a deeper shadow and a light
|
|
52
|
+
* hairline on dark. The edge lives on the outer wrapper, outside the scope.
|
|
53
|
+
*
|
|
54
|
+
* ## No room here is a room that does not serve it
|
|
55
|
+
*
|
|
56
|
+
* The earlier card led with an AI-generated picture of the dish, and a
|
|
57
|
+
* generated image at the head of a block whose whole argument is "we counted
|
|
58
|
+
* real menus" undercut the argument. The rooms are real.
|
|
32
59
|
*/
|
|
33
60
|
/** @deprecated Alias of `MenuLinkProps`; kept so existing imports keep working. */
|
|
34
61
|
type ConceptCompareLinkProps = MenuLinkProps;
|
|
35
62
|
type ConceptCompareFigure = {
|
|
36
|
-
/** Pre-formatted, e.g. "44". */
|
|
63
|
+
/** Pre-formatted, e.g. "44" or "29–52". */
|
|
37
64
|
value: string;
|
|
38
65
|
label: string;
|
|
66
|
+
/** Draws the value in amber — the spread, which is the number the card is about. */
|
|
67
|
+
accent?: boolean;
|
|
39
68
|
};
|
|
40
69
|
type ConceptCompareLabels = {
|
|
41
70
|
/** Small caps kicker, e.g. "DISH CONCEPT". */
|
|
42
71
|
kind: string;
|
|
43
|
-
/**
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
|
|
72
|
+
/** The badge on the lowest-priced room, e.g. "CHEAPEST". */
|
|
73
|
+
cheapest: string;
|
|
74
|
+
/** The badge on every other room, e.g. "#2". Defaults to `#${rank}`. */
|
|
75
|
+
rank?: (rank: number) => string;
|
|
76
|
+
/** Beside each price, e.g. "12 mentions". Pluralised by the caller. */
|
|
77
|
+
mentions: (count: number) => string;
|
|
78
|
+
/** Accessible name for a room's link, e.g. "Papanași at Casa Maramureșeană". */
|
|
79
|
+
openRoom: (alias: string, venue: string) => string;
|
|
49
80
|
};
|
|
50
81
|
type ConceptCompareProps = {
|
|
51
82
|
concept: MenuConceptPreview;
|
|
52
83
|
labels: ConceptCompareLabels;
|
|
53
|
-
/**
|
|
54
|
-
|
|
84
|
+
/** One line under the title, e.g. "45 kitchens make it, and they do not agree on the name". */
|
|
85
|
+
lede?: string;
|
|
55
86
|
formatPrice: (amount: number) => string;
|
|
56
|
-
formatCount?: (value: number) => string;
|
|
57
|
-
/** CSS gradient for the header swatch, when there is no photograph. */
|
|
58
|
-
gradient: string;
|
|
59
|
-
/** A real photograph of the concept, when the matched menu row carries one. */
|
|
60
|
-
imageUrl?: string;
|
|
61
87
|
figures?: ConceptCompareFigure[];
|
|
62
|
-
/** Destination per
|
|
88
|
+
/** Destination per room, keyed by place slug. A room without one is inert. */
|
|
63
89
|
hrefs?: Record<string, string>;
|
|
64
|
-
/** The provenance note in the
|
|
90
|
+
/** The provenance note in the foot. */
|
|
65
91
|
footnote?: string;
|
|
66
|
-
/**
|
|
92
|
+
/** The action in the foot — pass a rendered link or button. */
|
|
67
93
|
actions?: React.ReactNode;
|
|
68
94
|
linkComponent?: MenuLinkComponent;
|
|
69
95
|
className?: string;
|
|
70
96
|
};
|
|
71
|
-
declare function ConceptCompare({ concept, labels,
|
|
97
|
+
declare function ConceptCompare({ concept, labels, lede, formatPrice, figures, hrefs, footnote, actions, linkComponent: LinkComponent, className, }: ConceptCompareProps): react_jsx_runtime.JSX.Element | null;
|
|
98
|
+
/**
|
|
99
|
+
* The card's own loading state, at the card's footprint.
|
|
100
|
+
*
|
|
101
|
+
* The ground is the card's own dark surface, so the placeholder is already
|
|
102
|
+
* what the photographs will land on and nothing flashes from paper to ink.
|
|
103
|
+
* The phone shape is one room tall with the head above and the foot below;
|
|
104
|
+
* from `lg` it is the four-room row with the head and foot laid over it.
|
|
105
|
+
*/
|
|
106
|
+
declare function ConceptCompareSkeleton({ className }: {
|
|
107
|
+
className?: string;
|
|
108
|
+
}): react_jsx_runtime.JSX.Element;
|
|
72
109
|
|
|
73
|
-
export { ConceptCompare, type ConceptCompareFigure, type ConceptCompareLabels, type ConceptCompareLinkProps, type ConceptCompareProps };
|
|
110
|
+
export { ConceptCompare, type ConceptCompareFigure, type ConceptCompareLabels, type ConceptCompareLinkProps, type ConceptCompareProps, ConceptCompareSkeleton };
|