@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,64 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PhotoGround — venue photography as the ground of a card.
|
|
5
|
+
*
|
|
6
|
+
* Three cards are built on photographs rather than on panels: the hub's family
|
|
7
|
+
* card, the cuisines index's family block and the concept card. Each had grown
|
|
8
|
+
* its own copy of the same stack — a dark ground, a grid of `<img>`s with an
|
|
9
|
+
* initial for the missing ones, a hue layer, an overlay — and the one rule that
|
|
10
|
+
* matters for all of them (the tint has to be `mix-blend-color`, the ground
|
|
11
|
+
* has to be a fixed literal) was written three times. This is the stack, once.
|
|
12
|
+
*
|
|
13
|
+
* ## What it owns and what it leaves to the card
|
|
14
|
+
*
|
|
15
|
+
* It owns the photographs and their colour: the ground, the tiles, the fallback
|
|
16
|
+
* initial, the family's hue and an optional uniform dark overlay. It does NOT
|
|
17
|
+
* own the glass — the scrims and frosted bands that carry a card's type run in
|
|
18
|
+
* a different direction on every card (down the family block's phone, across
|
|
19
|
+
* its desktop, in from both ends of the concept card) and are the card's own.
|
|
20
|
+
*
|
|
21
|
+
* ## Two layouts
|
|
22
|
+
*
|
|
23
|
+
* `mosaic` tiles every photograph into a grid the caller shapes; `stack` shows
|
|
24
|
+
* ONE of them, `active`, and cross-fades to the next — a card whose ground
|
|
25
|
+
* follows a swipe. Same slots, same fallback, same tint either way.
|
|
26
|
+
*
|
|
27
|
+
* ## Why the ground is a literal, and why the tint is `color`
|
|
28
|
+
*
|
|
29
|
+
* The ground is the backdrop a blend or blur samples before a lazy image lands
|
|
30
|
+
* and the tile an empty slot shows, so it must not change with the theme —
|
|
31
|
+
* photography is not themed, and a card that flashed paper-white behind its
|
|
32
|
+
* photographs in light mode was wrong in exactly the mode most people use.
|
|
33
|
+
* `mix-blend-mode: color` takes hue and chroma from the tint layer and
|
|
34
|
+
* luminance from the photograph, so the room keeps its structure and the
|
|
35
|
+
* family keeps its colour; a plain overlay would have muddied both.
|
|
36
|
+
*/
|
|
37
|
+
/** The ground under the photography. Fixed, and deliberately not a token. */
|
|
38
|
+
declare const PHOTO_GROUND = "bg-[oklch(0.21_0.012_55)]";
|
|
39
|
+
type PhotoGroundProps = {
|
|
40
|
+
/** One per slot. An absent one draws the slot's initial on the ground. */
|
|
41
|
+
photos: (string | undefined)[];
|
|
42
|
+
/** The fallback glyph per slot — a venue's first letter. One is reused for all. */
|
|
43
|
+
initials: string | string[];
|
|
44
|
+
/** `mosaic` tiles every slot; `stack` shows `active` and cross-fades. */
|
|
45
|
+
mode?: "mosaic" | "stack";
|
|
46
|
+
/** `stack` only: which slot is showing. */
|
|
47
|
+
active?: number;
|
|
48
|
+
/** `mosaic` only: the grid template, e.g. `"grid-cols-2 grid-rows-2 lg:grid-cols-3"`. */
|
|
49
|
+
mosaicClassName?: string;
|
|
50
|
+
/** `mosaic` only: slots from this index on are desktop-only tiles. */
|
|
51
|
+
phoneTiles?: number;
|
|
52
|
+
/** Finished CSS gradient — the family's colour, laid over the photographs. */
|
|
53
|
+
gradient?: string;
|
|
54
|
+
/** A uniform dark overlay on every photograph. */
|
|
55
|
+
overlay?: boolean;
|
|
56
|
+
/** Extra classes on the overlay, e.g. a hover that lifts it. */
|
|
57
|
+
overlayClassName?: string;
|
|
58
|
+
/** How eagerly the first photograph loads. `stack` grounds are above the fold. */
|
|
59
|
+
loading?: "lazy" | "eager";
|
|
60
|
+
className?: string;
|
|
61
|
+
};
|
|
62
|
+
declare function PhotoGround({ photos, initials, mode, active, mosaicClassName, phoneTiles, gradient, overlay, overlayClassName, loading, className, }: PhotoGroundProps): react_jsx_runtime.JSX.Element;
|
|
63
|
+
|
|
64
|
+
export { PHOTO_GROUND, PhotoGround, type PhotoGroundProps };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { PlaceAboutTab } from '../chunk-
|
|
1
|
+
export { PlaceAboutTab } from '../chunk-HSIYYA2E.js';
|
|
2
2
|
import '../chunk-VG3PND3D.js';
|
|
3
|
-
import '../chunk-WSRWFA6K.js';
|
|
4
3
|
import '../chunk-ZDAHKI3A.js';
|
|
4
|
+
import '../chunk-WSRWFA6K.js';
|
|
5
5
|
import '../chunk-7BWTYWM3.js';
|
|
6
6
|
import '../chunk-FEK5XGZW.js';
|
|
7
7
|
import '../chunk-3GWWZKX7.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { PlaceAboutTab } from '../chunk-
|
|
1
|
+
import { PlaceAboutTab } from '../chunk-HSIYYA2E.js';
|
|
2
2
|
import '../chunk-VG3PND3D.js';
|
|
3
|
-
import '../chunk-WSRWFA6K.js';
|
|
4
3
|
import '../chunk-ZDAHKI3A.js';
|
|
4
|
+
import '../chunk-WSRWFA6K.js';
|
|
5
5
|
import { Text } from '../chunk-7BWTYWM3.js';
|
|
6
6
|
import { Badge } from '../chunk-UKBNQO6Q.js';
|
|
7
7
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
@@ -49,7 +49,7 @@ type PlacePreview = {
|
|
|
49
49
|
}>;
|
|
50
50
|
/**
|
|
51
51
|
* The review distillation. Drives every menu-hub surface that speaks for a
|
|
52
|
-
* venue — `<
|
|
52
|
+
* venue — `<KitchenDossier>`, `<MenuKitchenList>`, `<OpenNowList>` —
|
|
53
53
|
* because the signature dish, the pull-quotes and the graded dimensions all
|
|
54
54
|
* live here rather than on the menu itself.
|
|
55
55
|
*/
|
|
@@ -168,7 +168,7 @@ type PlaceReviewsDigest = {
|
|
|
168
168
|
tagline?: CitedText;
|
|
169
169
|
verdict?: CitedText;
|
|
170
170
|
caveat?: CitedText;
|
|
171
|
-
/** 1–3 standout positives. The pull-quotes on `<
|
|
171
|
+
/** 1–3 standout positives. The pull-quotes on `<KitchenDossier>`. */
|
|
172
172
|
highlights?: CitedText[];
|
|
173
173
|
must_try?: PlaceMustTry[];
|
|
174
174
|
/** Vibe codes (cozy, quiet, family_friendly, …). Localised by the caller. */
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { QaItem } from './menu-types.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
import './place-types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* QaBlock — questions answered from the numbers, as static prose.
|
|
8
|
+
*
|
|
9
|
+
* ## Never an accordion
|
|
10
|
+
*
|
|
11
|
+
* This block exists to be crawled as much as read: it is the visible half of
|
|
12
|
+
* the page's `FAQPage` markup, and the rule is that structured data must mirror
|
|
13
|
+
* content the reader can actually see. Collapsing it hides every answer from
|
|
14
|
+
* the crawler's first paint and buys nothing — three short answers are cheaper
|
|
15
|
+
* to scroll past than to expand.
|
|
16
|
+
*
|
|
17
|
+
* The caller renders the JSON-LD from the SAME array it passes here, so the
|
|
18
|
+
* markup and the visible answers cannot drift.
|
|
19
|
+
*
|
|
20
|
+
* ## Three across, then one
|
|
21
|
+
*
|
|
22
|
+
* Answers are two or three lines each, so a single column wastes the desktop
|
|
23
|
+
* measure and a two-column grid leaves an orphan. On the phone it is one
|
|
24
|
+
* column, in order.
|
|
25
|
+
*/
|
|
26
|
+
type QaBlockProps = {
|
|
27
|
+
items: QaItem[];
|
|
28
|
+
/** Section heading, e.g. "Questions people ask". Omit where the page supplies one. */
|
|
29
|
+
heading?: string;
|
|
30
|
+
/** Heading level for the questions. Defaults to `h3`, under a page's `h2`. */
|
|
31
|
+
questionAs?: "h3" | "h4";
|
|
32
|
+
className?: string;
|
|
33
|
+
};
|
|
34
|
+
declare function QaBlock({ items, heading, questionAs: Question, className }: QaBlockProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
|
|
36
|
+
export { QaBlock, type QaBlockProps };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { cn } from '../chunk-FEK5XGZW.js';
|
|
2
|
+
import '../chunk-3GWWZKX7.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
function QaBlock({ items, heading, questionAs: Question = "h3", className }) {
|
|
6
|
+
return /* @__PURE__ */ jsxs("section", { className: cn(className), children: [
|
|
7
|
+
heading && /* @__PURE__ */ jsx("h2", { className: "text-[15px] font-bold leading-tight tracking-[-0.01em]", children: heading }),
|
|
8
|
+
/* @__PURE__ */ jsx(
|
|
9
|
+
"div",
|
|
10
|
+
{
|
|
11
|
+
className: cn(
|
|
12
|
+
"grid grid-cols-1 gap-[18px] lg:grid-cols-3 lg:gap-[26px]",
|
|
13
|
+
heading && "mt-3.5"
|
|
14
|
+
),
|
|
15
|
+
children: items.map((item) => /* @__PURE__ */ jsxs("div", { children: [
|
|
16
|
+
/* @__PURE__ */ jsx(Question, { className: "text-sm font-bold leading-[1.35] tracking-[-0.01em] lg:text-[15px]", children: item.question }),
|
|
17
|
+
/* @__PURE__ */ jsx("p", { className: "mt-[7px] text-[13px] leading-[1.65] text-muted-foreground [text-wrap:pretty] lg:text-[13.5px]", children: item.answer })
|
|
18
|
+
] }, item.question))
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
] });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { QaBlock };
|
|
@@ -1,121 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
-
|
|
6
|
-
var fromMap = {
|
|
7
|
-
background: "from-background",
|
|
8
|
-
card: "from-card",
|
|
9
|
-
muted: "from-muted"
|
|
10
|
-
};
|
|
11
|
-
var sizeMap = {
|
|
12
|
-
vertical: { sm: "h-6", md: "h-12", lg: "h-20" },
|
|
13
|
-
horizontal: { sm: "w-8", md: "w-16", lg: "w-28" }
|
|
14
|
-
};
|
|
15
|
-
var ScrollFade = React.forwardRef(
|
|
16
|
-
(_a, ref) => {
|
|
17
|
-
var _b = _a, {
|
|
18
|
-
orientation = "vertical",
|
|
19
|
-
fadeColor = "background",
|
|
20
|
-
size = "md",
|
|
21
|
-
className,
|
|
22
|
-
scrollClassName,
|
|
23
|
-
children
|
|
24
|
-
} = _b, props = __objRest(_b, [
|
|
25
|
-
"orientation",
|
|
26
|
-
"fadeColor",
|
|
27
|
-
"size",
|
|
28
|
-
"className",
|
|
29
|
-
"scrollClassName",
|
|
30
|
-
"children"
|
|
31
|
-
]);
|
|
32
|
-
const innerRef = React.useRef(null);
|
|
33
|
-
React.useImperativeHandle(ref, () => innerRef.current);
|
|
34
|
-
const [atStart, setAtStart] = React.useState(true);
|
|
35
|
-
const [atEnd, setAtEnd] = React.useState(true);
|
|
36
|
-
const update = React.useCallback(() => {
|
|
37
|
-
const el = innerRef.current;
|
|
38
|
-
if (!el) return;
|
|
39
|
-
if (orientation === "vertical") {
|
|
40
|
-
const overflow = el.scrollHeight - el.clientHeight;
|
|
41
|
-
setAtStart(el.scrollTop <= 1);
|
|
42
|
-
setAtEnd(overflow <= 1 || el.scrollTop >= overflow - 1);
|
|
43
|
-
} else {
|
|
44
|
-
const overflow = el.scrollWidth - el.clientWidth;
|
|
45
|
-
setAtStart(el.scrollLeft <= 1);
|
|
46
|
-
setAtEnd(overflow <= 1 || el.scrollLeft >= overflow - 1);
|
|
47
|
-
}
|
|
48
|
-
}, [orientation]);
|
|
49
|
-
React.useEffect(() => {
|
|
50
|
-
const el = innerRef.current;
|
|
51
|
-
if (!el) return;
|
|
52
|
-
update();
|
|
53
|
-
el.addEventListener("scroll", update, { passive: true });
|
|
54
|
-
const ro = new ResizeObserver(update);
|
|
55
|
-
ro.observe(el);
|
|
56
|
-
return () => {
|
|
57
|
-
el.removeEventListener("scroll", update);
|
|
58
|
-
ro.disconnect();
|
|
59
|
-
};
|
|
60
|
-
}, [update]);
|
|
61
|
-
const fromClass = fromMap[fadeColor];
|
|
62
|
-
const fadeSize = sizeMap[orientation][size];
|
|
63
|
-
return /* @__PURE__ */ jsxs(
|
|
64
|
-
"div",
|
|
65
|
-
{
|
|
66
|
-
className: cn(
|
|
67
|
-
"relative isolate flex",
|
|
68
|
-
orientation === "vertical" ? "flex-col" : "flex-row",
|
|
69
|
-
className
|
|
70
|
-
),
|
|
71
|
-
children: [
|
|
72
|
-
/* @__PURE__ */ jsx(
|
|
73
|
-
"div",
|
|
74
|
-
__spreadProps(__spreadValues({
|
|
75
|
-
ref: innerRef,
|
|
76
|
-
className: cn(
|
|
77
|
-
"min-h-0 min-w-0 flex-1",
|
|
78
|
-
orientation === "vertical" ? "overflow-y-auto" : "overflow-x-auto",
|
|
79
|
-
scrollClassName
|
|
80
|
-
)
|
|
81
|
-
}, props), {
|
|
82
|
-
children
|
|
83
|
-
})
|
|
84
|
-
),
|
|
85
|
-
/* @__PURE__ */ jsx(
|
|
86
|
-
"div",
|
|
87
|
-
{
|
|
88
|
-
"aria-hidden": true,
|
|
89
|
-
className: cn(
|
|
90
|
-
"pointer-events-none absolute z-10 transition-opacity duration-300",
|
|
91
|
-
// `from-30%` adds a solid plateau before the gradient starts
|
|
92
|
-
// fading — without it the gradient is a pure linear ramp and only
|
|
93
|
-
// the very top pixel reads as solid, leaving the cut edge visible.
|
|
94
|
-
// -4px inset pulls the fade past the container edge so the very
|
|
95
|
-
// edge of clipped content is covered by the solid plateau.
|
|
96
|
-
orientation === "vertical" ? `inset-x-0 -top-1 ${fadeSize} bg-gradient-to-b from-30%` : `inset-y-0 -left-1 ${fadeSize} bg-gradient-to-r from-30%`,
|
|
97
|
-
fromClass,
|
|
98
|
-
atStart ? "opacity-0" : "opacity-100"
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
),
|
|
102
|
-
/* @__PURE__ */ jsx(
|
|
103
|
-
"div",
|
|
104
|
-
{
|
|
105
|
-
"aria-hidden": true,
|
|
106
|
-
className: cn(
|
|
107
|
-
"pointer-events-none absolute z-10 transition-opacity duration-300",
|
|
108
|
-
orientation === "vertical" ? `inset-x-0 -bottom-1 ${fadeSize} bg-gradient-to-t from-30%` : `inset-y-0 -right-1 ${fadeSize} bg-gradient-to-l from-30%`,
|
|
109
|
-
fromClass,
|
|
110
|
-
atEnd ? "opacity-0" : "opacity-100"
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
)
|
|
114
|
-
]
|
|
115
|
-
}
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
);
|
|
119
|
-
ScrollFade.displayName = "ScrollFade";
|
|
120
|
-
|
|
121
|
-
export { ScrollFade };
|
|
1
|
+
export { ScrollFade } from '../chunk-2XCZJWTV.js';
|
|
2
|
+
import '../chunk-FEK5XGZW.js';
|
|
3
|
+
import '../chunk-3GWWZKX7.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
1
2
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
2
3
|
import * as React from 'react';
|
|
3
4
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -34,6 +35,12 @@ type SnapRailProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof
|
|
|
34
35
|
dots?: boolean;
|
|
35
36
|
/** Classes for the dots row, e.g. `lg:hidden` where the rail becomes a grid. */
|
|
36
37
|
dotsClassName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Reports the current page whenever it changes — for a caller that wants
|
|
40
|
+
* to react to the swipe beyond the dots, e.g. a backdrop that follows the
|
|
41
|
+
* active card. Tracking runs whenever this or `dots` is set.
|
|
42
|
+
*/
|
|
43
|
+
onActiveChange?: (index: number) => void;
|
|
37
44
|
};
|
|
38
45
|
declare const SnapRail: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
39
46
|
itemWidth?: "sm" | "lg" | "full" | "md" | null | undefined;
|
|
@@ -49,6 +56,22 @@ declare const SnapRail: React.ForwardRefExoticComponent<React.HTMLAttributes<HTM
|
|
|
49
56
|
dots?: boolean;
|
|
50
57
|
/** Classes for the dots row, e.g. `lg:hidden` where the rail becomes a grid. */
|
|
51
58
|
dotsClassName?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Reports the current page whenever it changes — for a caller that wants
|
|
61
|
+
* to react to the swipe beyond the dots, e.g. a backdrop that follows the
|
|
62
|
+
* active card. Tracking runs whenever this or `dots` is set.
|
|
63
|
+
*/
|
|
64
|
+
onActiveChange?: (index: number) => void;
|
|
52
65
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
66
|
+
/**
|
|
67
|
+
* The page dots on their own, for a caller that tracks the rail through
|
|
68
|
+
* `onActiveChange` and wants the dots somewhere other than directly under it —
|
|
69
|
+
* inside a foot band, say. Decorative, as on the rail: the rail is the control.
|
|
70
|
+
*/
|
|
71
|
+
declare function SnapRailDots({ count, active, className, }: {
|
|
72
|
+
count: number;
|
|
73
|
+
active: number;
|
|
74
|
+
className?: string;
|
|
75
|
+
}): react_jsx_runtime.JSX.Element;
|
|
53
76
|
|
|
54
|
-
export { SnapRail, type SnapRailProps };
|
|
77
|
+
export { SnapRail, SnapRailDots, type SnapRailProps };
|
|
@@ -1,109 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { cva } from 'class-variance-authority';
|
|
5
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
|
-
|
|
7
|
-
var snapRailVariants = cva(
|
|
8
|
-
cn(
|
|
9
|
-
"flex snap-x snap-mandatory overflow-x-auto pb-0.5 scrollbar-hide",
|
|
10
|
-
"[&>*]:shrink-0 [&>*]:snap-start"
|
|
11
|
-
),
|
|
12
|
-
{
|
|
13
|
-
variants: {
|
|
14
|
-
itemWidth: {
|
|
15
|
-
sm: "[&>*]:w-[46%]",
|
|
16
|
-
md: "[&>*]:w-[60%]",
|
|
17
|
-
lg: "[&>*]:w-[80%]",
|
|
18
|
-
/** One card per view — pair with `dots` so the reader knows there is more. */
|
|
19
|
-
full: "[&>*]:w-full"
|
|
20
|
-
},
|
|
21
|
-
gap: {
|
|
22
|
-
sm: "gap-2",
|
|
23
|
-
default: "gap-3"
|
|
24
|
-
},
|
|
25
|
-
bleed: {
|
|
26
|
-
none: "",
|
|
27
|
-
card: "-mx-3.5 px-3.5 scroll-px-3.5",
|
|
28
|
-
page: "-mx-4 px-4 scroll-px-4"
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
defaultVariants: {
|
|
32
|
-
itemWidth: "sm",
|
|
33
|
-
gap: "default",
|
|
34
|
-
bleed: "none"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
);
|
|
38
|
-
var SnapRail = React.forwardRef(
|
|
39
|
-
(_a, ref) => {
|
|
40
|
-
var _b = _a, { className, itemWidth, gap, bleed, dots, dotsClassName, children } = _b, props = __objRest(_b, ["className", "itemWidth", "gap", "bleed", "dots", "dotsClassName", "children"]);
|
|
41
|
-
const railRef = React.useRef(null);
|
|
42
|
-
const [active, setActive] = React.useState(0);
|
|
43
|
-
const count = React.Children.count(children);
|
|
44
|
-
const setRefs = React.useCallback(
|
|
45
|
-
(node) => {
|
|
46
|
-
railRef.current = node;
|
|
47
|
-
if (typeof ref === "function") ref(node);
|
|
48
|
-
else if (ref) ref.current = node;
|
|
49
|
-
},
|
|
50
|
-
[ref]
|
|
51
|
-
);
|
|
52
|
-
React.useEffect(() => {
|
|
53
|
-
if (!dots) return;
|
|
54
|
-
const rail2 = railRef.current;
|
|
55
|
-
if (!rail2) return;
|
|
56
|
-
let frame = 0;
|
|
57
|
-
const sync = () => {
|
|
58
|
-
frame = 0;
|
|
59
|
-
const origin = rail2.scrollLeft + parseFloat(getComputedStyle(rail2).scrollPaddingLeft || "0");
|
|
60
|
-
let best = 0;
|
|
61
|
-
let bestDistance = Number.POSITIVE_INFINITY;
|
|
62
|
-
Array.from(rail2.children).forEach((child, index) => {
|
|
63
|
-
const distance = Math.abs(child.offsetLeft - origin);
|
|
64
|
-
if (distance < bestDistance) {
|
|
65
|
-
bestDistance = distance;
|
|
66
|
-
best = index;
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
setActive(best);
|
|
70
|
-
};
|
|
71
|
-
const onScroll = () => {
|
|
72
|
-
if (!frame) frame = requestAnimationFrame(sync);
|
|
73
|
-
};
|
|
74
|
-
sync();
|
|
75
|
-
rail2.addEventListener("scroll", onScroll, { passive: true });
|
|
76
|
-
return () => {
|
|
77
|
-
if (frame) cancelAnimationFrame(frame);
|
|
78
|
-
rail2.removeEventListener("scroll", onScroll);
|
|
79
|
-
};
|
|
80
|
-
}, [dots, count]);
|
|
81
|
-
const rail = /* @__PURE__ */ jsx(
|
|
82
|
-
"div",
|
|
83
|
-
__spreadProps(__spreadValues({
|
|
84
|
-
ref: setRefs,
|
|
85
|
-
"data-slot": "snap-rail",
|
|
86
|
-
className: cn(snapRailVariants({ itemWidth, gap, bleed }), className)
|
|
87
|
-
}, props), {
|
|
88
|
-
children
|
|
89
|
-
})
|
|
90
|
-
);
|
|
91
|
-
if (!dots) return rail;
|
|
92
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
93
|
-
rail,
|
|
94
|
-
/* @__PURE__ */ jsx("div", { "aria-hidden": true, className: cn("flex justify-center gap-1.5", dotsClassName), children: Array.from({ length: count }, (_, index) => /* @__PURE__ */ jsx(
|
|
95
|
-
"span",
|
|
96
|
-
{
|
|
97
|
-
className: cn(
|
|
98
|
-
"h-1.5 rounded-full transition-[width,background-color] duration-200 motion-reduce:transition-none",
|
|
99
|
-
index === active ? "w-4 bg-foreground" : "w-1.5 bg-foreground/25"
|
|
100
|
-
)
|
|
101
|
-
},
|
|
102
|
-
index
|
|
103
|
-
)) })
|
|
104
|
-
] });
|
|
105
|
-
}
|
|
106
|
-
);
|
|
107
|
-
SnapRail.displayName = "SnapRail";
|
|
108
|
-
|
|
109
|
-
export { SnapRail };
|
|
1
|
+
export { SnapRail, SnapRailDots } from '../chunk-DTXNDLSE.js';
|
|
2
|
+
import '../chunk-FEK5XGZW.js';
|
|
3
|
+
import '../chunk-3GWWZKX7.js';
|
|
@@ -4,11 +4,11 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
|
|
5
5
|
declare const spinnerVariants: (props?: ({
|
|
6
6
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
7
|
-
tone?: "
|
|
7
|
+
tone?: "inherit" | "default" | "destructive" | "primary" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const Spinner: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
|
|
10
10
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
11
|
-
tone?: "
|
|
11
|
+
tone?: "inherit" | "default" | "destructive" | "primary" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
/** Visually-hidden label for screen readers. Defaults to "Loading". */
|
|
14
14
|
label?: string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
type StoryProviderProps = {
|
|
5
|
+
/** How many parts the story has. */
|
|
6
|
+
count: number;
|
|
7
|
+
/** How long each part shows. */
|
|
8
|
+
durationMs?: number;
|
|
9
|
+
/** Accessible name of the tap-to-advance, e.g. "Next". */
|
|
10
|
+
nextLabel: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
};
|
|
14
|
+
declare function StoryProvider({ count, durationMs, nextLabel, className, children, }: StoryProviderProps): react_jsx_runtime.JSX.Element;
|
|
15
|
+
type StorySegmentsProps = {
|
|
16
|
+
/**
|
|
17
|
+
* Accessible name per segment, one per part, e.g. `["Part 1 of 3", …]`.
|
|
18
|
+
* Strings rather than a function: a server component renders this and a
|
|
19
|
+
* function cannot cross into a client one.
|
|
20
|
+
*/
|
|
21
|
+
labels: string[];
|
|
22
|
+
className?: string;
|
|
23
|
+
};
|
|
24
|
+
/** The segments: one per part, the active one filling on the timer. */
|
|
25
|
+
declare function StorySegments({ labels, className }: StorySegmentsProps): react_jsx_runtime.JSX.Element | null;
|
|
26
|
+
type StoryPanelProps = {
|
|
27
|
+
/** The parts, in order. Rendered by the caller; shown one at a time. */
|
|
28
|
+
parts: React.ReactNode[];
|
|
29
|
+
className?: string;
|
|
30
|
+
};
|
|
31
|
+
/** The panel: every part in one cell, the active one visible. */
|
|
32
|
+
declare function StoryPanel({ parts, className }: StoryPanelProps): react_jsx_runtime.JSX.Element;
|
|
33
|
+
|
|
34
|
+
export { StoryPanel, type StoryPanelProps, StoryProvider, type StoryProviderProps, StorySegments, type StorySegmentsProps };
|
|
@@ -22,9 +22,9 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
22
22
|
* Weights are 400 / 600 / 700. 500 is not in the system.
|
|
23
23
|
*/
|
|
24
24
|
declare const textVariants: (props?: ({
|
|
25
|
-
variant?: "
|
|
26
|
-
color?: "
|
|
27
|
-
weight?: "
|
|
25
|
+
variant?: "h2" | "h3" | "label" | "body" | "caption" | "h1" | "h4" | "small" | "display" | "body-lg" | "body-sm" | "overline" | null | undefined;
|
|
26
|
+
color?: "inherit" | "default" | "destructive" | "muted" | "primary" | "primary-foreground" | null | undefined;
|
|
27
|
+
weight?: "bold" | "medium" | "normal" | "semibold" | null | undefined;
|
|
28
28
|
leading?: "none" | "normal" | "tight" | "snug" | "relaxed" | "loose" | null | undefined;
|
|
29
29
|
tracking?: "normal" | "tight" | "wide" | "wider" | null | undefined;
|
|
30
30
|
wrap?: "balance" | "pretty" | "nowrap" | null | undefined;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { MenuLinkComponent } from './menu-types.js';
|
|
3
|
+
import { TopComparisonRow } from './top-types.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
import './place-types.js';
|
|
6
|
+
|
|
7
|
+
type TopComparisonLabels = {
|
|
8
|
+
venue: string;
|
|
9
|
+
grade: string;
|
|
10
|
+
signature: string;
|
|
11
|
+
price: string;
|
|
12
|
+
late: string;
|
|
13
|
+
terrace: string;
|
|
14
|
+
/** Screen-reader text for a "no" cell — never an empty cell. */
|
|
15
|
+
no: string;
|
|
16
|
+
yes: string;
|
|
17
|
+
};
|
|
18
|
+
type TopComparisonProps = {
|
|
19
|
+
rows: TopComparisonRow[];
|
|
20
|
+
labels: TopComparisonLabels;
|
|
21
|
+
/** Accessible name for the table. */
|
|
22
|
+
caption: string;
|
|
23
|
+
linkComponent?: MenuLinkComponent;
|
|
24
|
+
className?: string;
|
|
25
|
+
};
|
|
26
|
+
declare function TopComparison({ rows, labels, caption, linkComponent: LinkComponent, className, }: TopComparisonProps): react_jsx_runtime.JSX.Element;
|
|
27
|
+
|
|
28
|
+
export { TopComparison, type TopComparisonLabels, type TopComparisonProps };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|
|
2
|
+
import { Moon, Sun } from 'lucide-react';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
function DefaultLink(_a) {
|
|
6
|
+
var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
|
|
7
|
+
return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
|
|
8
|
+
}
|
|
9
|
+
function TopComparison({
|
|
10
|
+
rows,
|
|
11
|
+
labels,
|
|
12
|
+
caption,
|
|
13
|
+
linkComponent: LinkComponent = DefaultLink,
|
|
14
|
+
className
|
|
15
|
+
}) {
|
|
16
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
17
|
+
/* @__PURE__ */ jsx("div", { className: "hidden overflow-x-auto lg:block", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-[13px]", children: [
|
|
18
|
+
/* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }),
|
|
19
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-border text-left text-[11px] font-bold uppercase tracking-[0.07em] text-muted-foreground", children: [
|
|
20
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "w-10 py-2 font-bold", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "#" }) }),
|
|
21
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "py-2 font-bold", children: labels.venue }),
|
|
22
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "py-2 font-bold", children: labels.grade }),
|
|
23
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "py-2 font-bold", children: labels.signature }),
|
|
24
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "py-2 font-bold", children: labels.price }),
|
|
25
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "py-2 font-bold", children: labels.late }),
|
|
26
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "py-2 font-bold", children: labels.terrace })
|
|
27
|
+
] }) }),
|
|
28
|
+
/* @__PURE__ */ jsx("tbody", { children: rows.map((row) => {
|
|
29
|
+
var _a, _b, _c;
|
|
30
|
+
return /* @__PURE__ */ jsxs("tr", { className: "border-b border-border/60", children: [
|
|
31
|
+
/* @__PURE__ */ jsx("td", { className: "py-2.5 tabular-nums text-muted-foreground", children: String(row.rank).padStart(2, "0") }),
|
|
32
|
+
/* @__PURE__ */ jsx("td", { className: "py-2.5 font-semibold", children: /* @__PURE__ */ jsx(
|
|
33
|
+
LinkComponent,
|
|
34
|
+
{
|
|
35
|
+
href: row.href,
|
|
36
|
+
className: "hover:text-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
37
|
+
children: row.name
|
|
38
|
+
}
|
|
39
|
+
) }),
|
|
40
|
+
/* @__PURE__ */ jsx("td", { className: "py-2.5 font-bold tabular-nums text-accent", children: (_a = row.gradeLabel) != null ? _a : "\u2014" }),
|
|
41
|
+
/* @__PURE__ */ jsx("td", { className: "py-2.5 text-muted-foreground", children: (_b = row.signature) != null ? _b : "\u2014" }),
|
|
42
|
+
/* @__PURE__ */ jsx("td", { className: "py-2.5 tabular-nums", children: (_c = row.priceLabel) != null ? _c : "\u2014" }),
|
|
43
|
+
/* @__PURE__ */ jsx("td", { className: "py-2.5", children: /* @__PURE__ */ jsx(Mark, { on: row.late, yes: labels.yes, no: labels.no }) }),
|
|
44
|
+
/* @__PURE__ */ jsx("td", { className: "py-2.5", children: /* @__PURE__ */ jsx(Mark, { on: row.terrace, yes: labels.yes, no: labels.no }) })
|
|
45
|
+
] }, row.name);
|
|
46
|
+
}) })
|
|
47
|
+
] }) }),
|
|
48
|
+
/* @__PURE__ */ jsx("ul", { className: "lg:hidden", children: rows.map((row) => /* @__PURE__ */ jsx("li", { className: "border-t border-border first:border-t-0", children: /* @__PURE__ */ jsxs(
|
|
49
|
+
LinkComponent,
|
|
50
|
+
{
|
|
51
|
+
href: row.href,
|
|
52
|
+
className: "flex items-center gap-3 py-2.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
53
|
+
children: [
|
|
54
|
+
/* @__PURE__ */ jsx("span", { className: "w-6 shrink-0 text-[13px] font-bold tabular-nums text-muted-foreground", children: String(row.rank).padStart(2, "0") }),
|
|
55
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
56
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-[13.5px] font-bold", children: row.name }),
|
|
57
|
+
(row.signature || row.priceLabel) && /* @__PURE__ */ jsx("span", { className: "block truncate text-[11.5px] text-muted-foreground", children: [row.signature, row.priceLabel].filter(Boolean).join(" \xB7 ") })
|
|
58
|
+
] }),
|
|
59
|
+
/* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-muted-foreground", children: [
|
|
60
|
+
row.late && /* @__PURE__ */ jsx(Moon, { className: "h-3.5 w-3.5", "aria-label": labels.late }),
|
|
61
|
+
row.terrace && /* @__PURE__ */ jsx(Sun, { className: "h-3.5 w-3.5", "aria-label": labels.terrace })
|
|
62
|
+
] }),
|
|
63
|
+
row.gradeLabel && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[13px] font-extrabold tabular-nums text-accent", children: row.gradeLabel })
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
) }, row.name)) })
|
|
67
|
+
] });
|
|
68
|
+
}
|
|
69
|
+
function Mark({ on, yes, no }) {
|
|
70
|
+
return on ? /* @__PURE__ */ jsx("span", { className: "font-semibold text-[color:var(--free,oklch(0.45_0.13_155))]", children: yes }) : /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
71
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u2014" }),
|
|
72
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: no })
|
|
73
|
+
] });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { TopComparison };
|