@bearmenu/ui 0.8.8 → 0.8.9
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-62ES6N32.js +27 -0
- package/dist/chunk-AXV5O2IZ.js +58 -0
- package/dist/chunk-Q6QH52LJ.js +38 -0
- package/dist/chunk-TH6W2PWG.js +213 -0
- package/dist/chunk-THOVPZNN.js +37 -0
- package/dist/chunk-YS6BHKZO.js +92 -0
- package/dist/components/alert.d.ts +2 -2
- 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.d.ts +73 -0
- package/dist/components/concept-compare.js +162 -0
- package/dist/components/event-card.js +1 -1
- package/dist/components/event-compact-row.d.ts +1 -1
- package/dist/components/event-compact-row.js +1 -1
- package/dist/components/event-detail-panel.d.ts +171 -25
- package/dist/components/event-detail-panel.js +471 -174
- package/dist/components/event-list-row-wide.js +1 -1
- package/dist/components/event-list-row.js +1 -1
- package/dist/components/hub-surface.d.ts +27 -0
- package/dist/components/hub-surface.js +20 -0
- package/dist/components/menu-family-card.d.ts +59 -0
- package/dist/components/menu-family-card.js +121 -0
- package/dist/components/menu-field.d.ts +57 -0
- package/dist/components/menu-field.js +3 -0
- package/dist/components/menu-hub-hero.d.ts +65 -0
- package/dist/components/menu-hub-hero.js +103 -0
- package/dist/components/menu-intent-tiles.d.ts +31 -0
- package/dist/components/menu-intent-tiles.js +50 -0
- package/dist/components/menu-item.d.ts +127 -0
- package/dist/components/menu-item.js +5 -0
- package/dist/components/menu-mocks.d.ts +55 -0
- package/dist/components/menu-mocks.js +379 -0
- package/dist/components/menu-types.d.ts +245 -0
- package/dist/components/menu-types.js +1 -0
- package/dist/components/motion-icon-set.js +15 -3
- package/dist/components/open-now-list.d.ts +40 -0
- package/dist/components/open-now-list.js +69 -0
- package/dist/components/place-types.d.ts +112 -1
- package/dist/components/ranked-venue-list.d.ts +49 -0
- package/dist/components/ranked-venue-list.js +87 -0
- package/dist/components/signature-chip.d.ts +37 -0
- package/dist/components/signature-chip.js +4 -0
- package/dist/components/signature-line-list.d.ts +45 -0
- package/dist/components/signature-line-list.js +99 -0
- package/dist/components/snap-rail.d.ts +24 -4
- package/dist/components/snap-rail.js +66 -8
- package/dist/components/spinner.d.ts +2 -2
- package/dist/components/stat-banner.d.ts +47 -0
- package/dist/components/stat-banner.js +61 -0
- package/dist/components/tag.d.ts +2 -2
- package/dist/components/text.d.ts +3 -3
- package/dist/components/venue-busyness-strip.d.ts +35 -0
- package/dist/components/venue-busyness-strip.js +37 -0
- package/dist/components/venue-grade-dimensions.d.ts +36 -0
- package/dist/components/venue-grade-dimensions.js +3 -0
- package/dist/components/venue-quotes.d.ts +32 -0
- package/dist/components/venue-quotes.js +3 -0
- package/dist/components/venue-signature-block.d.ts +39 -0
- package/dist/components/venue-signature-block.js +6 -0
- package/dist/components/venue-spotlight.d.ts +74 -0
- package/dist/components/venue-spotlight.js +138 -0
- package/dist/components/venue-wall.d.ts +41 -0
- package/dist/components/venue-wall.js +118 -0
- package/dist/components/weekday-theme-banner.d.ts +70 -0
- package/dist/components/weekday-theme-banner.js +127 -0
- package/package.json +1 -1
- package/src/components/colour-dictionary.stories.tsx +227 -0
- package/src/components/concept-compare.stories.tsx +104 -0
- package/src/components/concept-compare.tsx +276 -0
- package/src/components/event-compact-row.tsx +1 -1
- package/src/components/event-detail-panel.stories.tsx +205 -97
- package/src/components/event-detail-panel.test.tsx +181 -0
- package/src/components/event-detail-panel.tsx +703 -185
- package/src/components/hub-surface.stories.tsx +68 -0
- package/src/components/hub-surface.tsx +40 -0
- package/src/components/menu-family-card.stories.tsx +112 -0
- package/src/components/menu-family-card.tsx +211 -0
- package/src/components/menu-field.stories.tsx +74 -0
- package/src/components/menu-field.tsx +199 -0
- package/src/components/menu-hub-hero.stories.tsx +92 -0
- package/src/components/menu-hub-hero.tsx +187 -0
- package/src/components/menu-intent-tiles.stories.tsx +54 -0
- package/src/components/menu-intent-tiles.tsx +76 -0
- package/src/components/menu-item.tsx +416 -0
- package/src/components/menu-mocks.ts +417 -0
- package/src/components/menu-types.ts +259 -0
- package/src/components/motion-icon-set.tsx +30 -3
- package/src/components/open-now-list.stories.tsx +76 -0
- package/src/components/open-now-list.tsx +127 -0
- package/src/components/place-types.ts +112 -0
- package/src/components/ranked-venue-list.stories.tsx +80 -0
- package/src/components/ranked-venue-list.tsx +177 -0
- package/src/components/signature-chip.tsx +77 -0
- package/src/components/signature-line-list.stories.tsx +85 -0
- package/src/components/signature-line-list.tsx +136 -0
- package/src/components/snap-rail.tsx +90 -9
- package/src/components/stat-banner.stories.tsx +100 -0
- package/src/components/stat-banner.tsx +117 -0
- package/src/components/venue-busyness-strip.stories.tsx +66 -0
- package/src/components/venue-busyness-strip.tsx +64 -0
- package/src/components/venue-grade-dimensions.stories.tsx +83 -0
- package/src/components/venue-grade-dimensions.tsx +91 -0
- package/src/components/venue-quotes.stories.tsx +59 -0
- package/src/components/venue-quotes.tsx +64 -0
- package/src/components/venue-signature-block.stories.tsx +68 -0
- package/src/components/venue-signature-block.tsx +71 -0
- package/src/components/venue-spotlight.stories.tsx +141 -0
- package/src/components/venue-spotlight.tsx +236 -0
- package/src/components/venue-wall.stories.tsx +78 -0
- package/src/components/venue-wall.tsx +185 -0
- package/src/components/weekday-theme-banner.stories.tsx +113 -0
- package/src/components/weekday-theme-banner.tsx +231 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { MenuItem } from '../chunk-TH6W2PWG.js';
|
|
2
|
+
import '../chunk-Q6QH52LJ.js';
|
|
3
|
+
import { MenuField } from '../chunk-YS6BHKZO.js';
|
|
4
|
+
import '../chunk-UKBNQO6Q.js';
|
|
5
|
+
import { cn } from '../chunk-FEK5XGZW.js';
|
|
6
|
+
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|
|
7
|
+
import { Star, MessageSquare } from 'lucide-react';
|
|
8
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
function DefaultLink(_a) {
|
|
11
|
+
var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
|
|
12
|
+
return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
|
|
13
|
+
}
|
|
14
|
+
function ConceptCompare({
|
|
15
|
+
concept,
|
|
16
|
+
labels,
|
|
17
|
+
itemLabels,
|
|
18
|
+
formatPrice,
|
|
19
|
+
formatCount,
|
|
20
|
+
gradient,
|
|
21
|
+
imageUrl,
|
|
22
|
+
figures,
|
|
23
|
+
hrefs,
|
|
24
|
+
footnote,
|
|
25
|
+
actions,
|
|
26
|
+
linkComponent: LinkComponent = DefaultLink,
|
|
27
|
+
className
|
|
28
|
+
}) {
|
|
29
|
+
var _a;
|
|
30
|
+
const rows = (_a = concept.rows) != null ? _a : [];
|
|
31
|
+
const cheapest = rows.reduce(
|
|
32
|
+
(lowest, row) => lowest === void 0 || row.price < lowest ? row.price : lowest,
|
|
33
|
+
void 0
|
|
34
|
+
);
|
|
35
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("overflow-hidden rounded-[18px] border border-border bg-card", className), children: [
|
|
36
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 p-4 lg:flex-row lg:items-center lg:gap-6 lg:p-5", children: [
|
|
37
|
+
imageUrl ? (
|
|
38
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
"img",
|
|
41
|
+
{
|
|
42
|
+
src: imageUrl,
|
|
43
|
+
alt: "",
|
|
44
|
+
className: "aspect-[16/9] w-full shrink-0 rounded-xl object-cover lg:aspect-auto lg:h-[88px] lg:w-[88px]"
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
) : /* @__PURE__ */ jsx(
|
|
48
|
+
MenuField,
|
|
49
|
+
{
|
|
50
|
+
name: concept.title,
|
|
51
|
+
gradient,
|
|
52
|
+
seedKey: concept.slug,
|
|
53
|
+
className: "aspect-[16/9] w-full shrink-0 rounded-xl lg:aspect-auto lg:h-[88px] lg:w-[88px]"
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
57
|
+
/* @__PURE__ */ jsx("span", { className: "text-[9.5px] font-bold uppercase tracking-[0.12em] text-muted-foreground", children: labels.kind }),
|
|
58
|
+
/* @__PURE__ */ jsx("h3", { className: "mt-1 font-serif text-2xl font-semibold tracking-[-0.02em] lg:text-[30px]", children: concept.title })
|
|
59
|
+
] }),
|
|
60
|
+
figures && figures.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 gap-6 lg:gap-8", children: figures.map((figure) => /* @__PURE__ */ jsxs("div", { className: "text-left lg:text-right", children: [
|
|
61
|
+
/* @__PURE__ */ jsx("div", { className: "text-xl font-extrabold leading-none tracking-[-0.03em] tabular-nums lg:text-2xl", children: figure.value }),
|
|
62
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-[10.5px] text-muted-foreground", children: figure.label })
|
|
63
|
+
] }, figure.label)) })
|
|
64
|
+
] }),
|
|
65
|
+
/* @__PURE__ */ jsx("ul", { className: "border-t border-border lg:hidden", children: rows.map((row) => /* @__PURE__ */ jsx("li", { className: "border-b border-border last:border-b-0", children: /* @__PURE__ */ jsx(
|
|
66
|
+
MenuItem,
|
|
67
|
+
{
|
|
68
|
+
item: {
|
|
69
|
+
id: row.place_slug,
|
|
70
|
+
slug: row.place_slug,
|
|
71
|
+
// The kitchen's OWN wording leads the row — that IS the point
|
|
72
|
+
// of the module.
|
|
73
|
+
name: row.alias,
|
|
74
|
+
kind: concept.kind,
|
|
75
|
+
mentions: row.mentions,
|
|
76
|
+
sizes_and_prices: [{ size: 0, price: row.price }]
|
|
77
|
+
},
|
|
78
|
+
labels: itemLabels,
|
|
79
|
+
formatPrice,
|
|
80
|
+
formatCount,
|
|
81
|
+
venueName: row.place_name,
|
|
82
|
+
href: hrefs == null ? void 0 : hrefs[row.place_slug],
|
|
83
|
+
linkComponent: LinkComponent,
|
|
84
|
+
className: cn(row.price === cheapest && "bg-accent-subtle/40")
|
|
85
|
+
}
|
|
86
|
+
) }, row.place_slug)) }),
|
|
87
|
+
/* @__PURE__ */ jsx("ol", { className: "hidden border-t border-border lg:block", children: rows.map((row, index) => {
|
|
88
|
+
const isCheapest = row.price === cheapest;
|
|
89
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
90
|
+
/* @__PURE__ */ jsx("span", { className: "w-5 shrink-0 text-center text-xs font-bold tabular-nums text-muted-foreground", children: index + 1 }),
|
|
91
|
+
/* @__PURE__ */ jsxs("span", { className: "relative h-10 w-10 shrink-0 overflow-hidden rounded-lg bg-[repeating-linear-gradient(135deg,oklch(0.78_0.018_55)_0_8px,oklch(0.84_0.012_58)_8px_16px)]", children: [
|
|
92
|
+
row.place_thumbnail_url && // eslint-disable-next-line @next/next/no-img-element
|
|
93
|
+
/* @__PURE__ */ jsx(
|
|
94
|
+
"img",
|
|
95
|
+
{
|
|
96
|
+
src: row.place_thumbnail_url,
|
|
97
|
+
alt: "",
|
|
98
|
+
loading: "lazy",
|
|
99
|
+
className: "h-full w-full object-cover"
|
|
100
|
+
}
|
|
101
|
+
),
|
|
102
|
+
row.open_now && /* @__PURE__ */ jsx(
|
|
103
|
+
"i",
|
|
104
|
+
{
|
|
105
|
+
"aria-hidden": true,
|
|
106
|
+
className: "absolute right-0.5 top-0.5 h-[6px] w-[6px] rounded-full bg-[var(--free,currentColor)] ring-2 ring-white/80"
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
] }),
|
|
110
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 w-[200px] shrink-0", children: [
|
|
111
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-bold tracking-[-0.01em]", children: row.place_name }),
|
|
112
|
+
/* @__PURE__ */ jsxs("span", { className: "mt-px flex items-center gap-1.5 text-[11px] text-muted-foreground", children: [
|
|
113
|
+
row.rating != null && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
114
|
+
/* @__PURE__ */ jsx(Star, { className: "h-2.5 w-2.5", "aria-hidden": true }),
|
|
115
|
+
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: row.rating })
|
|
116
|
+
] }),
|
|
117
|
+
row.place_area && /* @__PURE__ */ jsx("span", { className: "truncate", children: row.place_area })
|
|
118
|
+
] })
|
|
119
|
+
] }),
|
|
120
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
121
|
+
/* @__PURE__ */ jsx("span", { className: "block text-[9.5px] font-bold uppercase tracking-[0.1em] text-muted-foreground", children: labels.alias }),
|
|
122
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate font-serif text-[13px] italic", children: row.alias })
|
|
123
|
+
] }),
|
|
124
|
+
row.mentions != null && row.mentions > 0 && /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-[11px] tabular-nums text-muted-foreground", children: [
|
|
125
|
+
/* @__PURE__ */ jsx(MessageSquare, { className: "h-[11px] w-[11px]", "aria-hidden": true }),
|
|
126
|
+
row.mentions
|
|
127
|
+
] }),
|
|
128
|
+
/* @__PURE__ */ jsxs("span", { className: "w-[92px] shrink-0 text-right", children: [
|
|
129
|
+
/* @__PURE__ */ jsx(
|
|
130
|
+
"b",
|
|
131
|
+
{
|
|
132
|
+
className: cn(
|
|
133
|
+
"block text-sm font-extrabold tabular-nums",
|
|
134
|
+
isCheapest && "text-[var(--free,currentColor)]"
|
|
135
|
+
),
|
|
136
|
+
children: formatPrice(row.price)
|
|
137
|
+
}
|
|
138
|
+
),
|
|
139
|
+
/* @__PURE__ */ jsx("span", { className: "block text-[10px] text-muted-foreground", children: isCheapest && labels.cheapest ? labels.cheapest : labels.perPortion })
|
|
140
|
+
] })
|
|
141
|
+
] });
|
|
142
|
+
const rowClasses = "flex items-center gap-4 px-5 py-3";
|
|
143
|
+
return /* @__PURE__ */ jsx("li", { className: "border-b border-border last:border-b-0", children: (hrefs == null ? void 0 : hrefs[row.place_slug]) ? /* @__PURE__ */ jsx(
|
|
144
|
+
LinkComponent,
|
|
145
|
+
{
|
|
146
|
+
href: hrefs[row.place_slug],
|
|
147
|
+
className: cn(
|
|
148
|
+
rowClasses,
|
|
149
|
+
"transition-colors hover:bg-muted/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
|
|
150
|
+
),
|
|
151
|
+
children: content
|
|
152
|
+
}
|
|
153
|
+
) : /* @__PURE__ */ jsx("div", { className: rowClasses, children: content }) }, row.place_slug);
|
|
154
|
+
}) }),
|
|
155
|
+
(footnote || actions) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 p-4", children: [
|
|
156
|
+
footnote && /* @__PURE__ */ jsx("span", { className: "text-[11.5px] text-muted-foreground", children: footnote }),
|
|
157
|
+
actions && /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center gap-2", children: actions })
|
|
158
|
+
] })
|
|
159
|
+
] });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export { ConceptCompare };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TagGroup } from '../chunk-6XMYEZVR.js';
|
|
2
|
-
import { Tag } from '../chunk-ZDAHKI3A.js';
|
|
3
2
|
import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
|
|
3
|
+
import { Tag } from '../chunk-ZDAHKI3A.js';
|
|
4
4
|
import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
|
|
5
5
|
import { Skeleton } from '../chunk-QXHMPJ35.js';
|
|
6
6
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
@@ -56,7 +56,7 @@ type EventCompactRowProps = {
|
|
|
56
56
|
* repeating it on each one is noise — the caller has something more
|
|
57
57
|
* differentiating to say instead (the event's own description). The
|
|
58
58
|
* timeline keeps the default: there the venue IS what tells rows apart
|
|
59
|
-
* across the night. Mirrors `menu-item
|
|
59
|
+
* across the night. Mirrors `menu-item.tsx`'s prop of the same name and
|
|
60
60
|
* intent.
|
|
61
61
|
*/
|
|
62
62
|
subtitle?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TagGroup } from '../chunk-6XMYEZVR.js';
|
|
2
|
-
import { Tag } from '../chunk-ZDAHKI3A.js';
|
|
3
2
|
import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
|
|
3
|
+
import { Tag } from '../chunk-ZDAHKI3A.js';
|
|
4
4
|
import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
|
|
5
5
|
import { Skeleton } from '../chunk-QXHMPJ35.js';
|
|
6
6
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
@@ -3,41 +3,85 @@ import * as React from 'react';
|
|
|
3
3
|
import { EventPreview, EventFormatters } from './event-types.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* EventDetailPanel — the BODY of the event detail sheet
|
|
6
|
+
* EventDetailPanel — the BODY of the event detail sheet, and the body the
|
|
7
|
+
* event PAGE is a superset of.
|
|
7
8
|
*
|
|
8
9
|
* Deliberately not a sheet. The design opens this as a side sheet over a dimmed
|
|
9
|
-
* page on desktop and a bottom
|
|
10
|
-
* and `Drawer`; owning sheet mechanics a third time here would fork
|
|
11
|
-
* consuming app mounts this inside whichever container the
|
|
10
|
+
* page on desktop and a bottom drawer on mobile, and the DS already ships
|
|
11
|
+
* `Sheet` and `Drawer`; owning sheet mechanics a third time here would fork
|
|
12
|
+
* them. The consuming app mounts this inside whichever container the
|
|
13
|
+
* breakpoint calls for, and passes the container's own controls (close, back,
|
|
14
|
+
* share) as `headerActions`, positioned over the poster by this component.
|
|
12
15
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
+
* ONE BODY, TWO HOSTS. The same regions in the same order everywhere: poster,
|
|
17
|
+
* title, when-line, one chip row, venue, line-up, about, external link, then a
|
|
18
|
+
* footer of one primary action over a row of ghost actions. The page renders
|
|
19
|
+
* these regions itself with more room; nothing here is invented twice.
|
|
16
20
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
21
|
+
* THE HERO IS CAPPED, NOT A RATIO. 91% of posters are 4:5 flyers, and at 4:5 a
|
|
22
|
+
* hero took 68% of a side sheet and cut the venue card mid-row before any
|
|
23
|
+
* scrolling — the one thing this surface exists to answer. So `heroHeight`
|
|
24
|
+
* caps it: 300px on the 480px side sheet, 318px on the phone drawer, chosen so
|
|
25
|
+
* the venue card clears the fold even when status, fee, hype and two tags wrap
|
|
26
|
+
* the chip row onto a second line. It crops more than a 4:3 would, and that is
|
|
27
|
+
* the trade; the full flyer is one tap away on the page.
|
|
28
|
+
*
|
|
29
|
+
* STATUS IS A CHIP, IN THE INFO BLOCK. Cards put pills on the poster because a
|
|
30
|
+
* card has nowhere else; a detail surface does, and a portrait flyer is busy
|
|
31
|
+
* artwork already. `live` and the free fee are `--success`; `soon` is the
|
|
32
|
+
* accent — success is reserved for live and free, and a third meaning on the
|
|
33
|
+
* same colour would flatten both. `ended` desaturates and dims the POSTER
|
|
34
|
+
* (never the whole surface, which drops text below AA), mutes the title and
|
|
35
|
+
* adds an explicit chip; the host replaces the primary action rather than
|
|
36
|
+
* disabling it.
|
|
37
|
+
*
|
|
38
|
+
* Everything is injected: strings via `labels`, times via `formatters`, the
|
|
39
|
+
* date line and the soon label composed by the caller (clause order is
|
|
40
|
+
* locale-dependent and "is this live" depends on the app's clock, not the
|
|
41
|
+
* DS's).
|
|
20
42
|
*/
|
|
21
43
|
type EventDetailPanelLinkProps = {
|
|
22
44
|
href: string;
|
|
23
45
|
className?: string;
|
|
24
46
|
children: React.ReactNode;
|
|
47
|
+
onClick?: (mouseEvent: React.MouseEvent) => void;
|
|
25
48
|
};
|
|
49
|
+
type EventDetailStatus = "upcoming" | "soon" | "live" | "ended";
|
|
26
50
|
type EventDetailVenue = {
|
|
27
51
|
name: string;
|
|
28
|
-
/** Address
|
|
29
|
-
|
|
52
|
+
/** Address line, e.g. "Str. Iuliu Maniu 5". */
|
|
53
|
+
address?: string;
|
|
54
|
+
/** e.g. "4.7" — rendered with a star. */
|
|
30
55
|
ratingLabel?: string;
|
|
56
|
+
/** e.g. "open until 20:00" — appended to the meta row when given. */
|
|
57
|
+
openLabel?: string;
|
|
58
|
+
/** Lights the green dot on the thumbnail. */
|
|
59
|
+
isOpenNow?: boolean;
|
|
31
60
|
thumbnailUrl?: string;
|
|
61
|
+
/**
|
|
62
|
+
* The venue's own page. Without it the card is not a link and shows
|
|
63
|
+
* `labels.venueNoPage` beneath the name — a venue the ingest knows by name
|
|
64
|
+
* only, which is common and must not read as a broken link.
|
|
65
|
+
*/
|
|
32
66
|
href?: string;
|
|
33
67
|
};
|
|
34
68
|
type EventDetailPanelLabels = {
|
|
35
69
|
free: string;
|
|
36
70
|
liveNow: string;
|
|
71
|
+
/** The ended chip, e.g. "Ended". */
|
|
72
|
+
ended: string;
|
|
37
73
|
/** Section heading above the venue card. */
|
|
38
74
|
venueHeading: string;
|
|
75
|
+
/** Under the venue name when the venue has no page, e.g. "name only — no venue page yet". */
|
|
76
|
+
venueNoPage: string;
|
|
77
|
+
/** Section heading above the performers. */
|
|
78
|
+
lineupHeading: string;
|
|
39
79
|
/** Section heading above the description. */
|
|
40
80
|
aboutHeading: string;
|
|
81
|
+
/** Italic placeholder when there is no description, e.g. "Event details coming soon." */
|
|
82
|
+
noDescription: string;
|
|
83
|
+
readMore: string;
|
|
84
|
+
readLess: string;
|
|
41
85
|
};
|
|
42
86
|
type EventDetailPanelProps = {
|
|
43
87
|
event: EventPreview;
|
|
@@ -45,36 +89,138 @@ type EventDetailPanelProps = {
|
|
|
45
89
|
formatters: EventFormatters;
|
|
46
90
|
/**
|
|
47
91
|
* The date line, composed by the caller — the design reads
|
|
48
|
-
* "
|
|
49
|
-
* preposition are locale-dependent.
|
|
92
|
+
* "Tuesday, September 8 · Starts at 17:30", or "· time to be announced" when
|
|
93
|
+
* the hour is unknown. Clause order and preposition are locale-dependent.
|
|
50
94
|
*/
|
|
51
95
|
dateLine: string;
|
|
96
|
+
/** The start as an ISO string; when given the date line is a `<time dateTime>`. */
|
|
97
|
+
dateTime?: string;
|
|
98
|
+
status?: EventDetailStatus;
|
|
99
|
+
/** The soon chip's text, composed by the caller — "Starts in 2h 10m". Required to render it. */
|
|
100
|
+
soonLabel?: string;
|
|
101
|
+
/** The hype tier, rendered as given (the app's own badge) in the chip row. */
|
|
102
|
+
hype?: React.ReactNode;
|
|
52
103
|
venue?: EventDetailVenue;
|
|
53
|
-
/**
|
|
104
|
+
/** Activity tags, after status, fee and hype. */
|
|
54
105
|
tags?: string[];
|
|
55
|
-
|
|
56
|
-
|
|
106
|
+
/** Performer names, in the order the API gave them. */
|
|
107
|
+
performers?: string[];
|
|
108
|
+
/** How many performers to show before the "show all" chip. Default 5. */
|
|
109
|
+
performersPreview?: number;
|
|
110
|
+
/** The "show all" chip's text, e.g. "Show all 8 performers". Required to render it. */
|
|
111
|
+
showAllPerformersLabel?: string;
|
|
112
|
+
/** Close, back and share controls, positioned over the poster by this component. */
|
|
57
113
|
headerActions?: React.ReactNode;
|
|
58
|
-
/**
|
|
114
|
+
/** The footer — usually an `EventDetailFooter`. Rendered below the scroll region. */
|
|
59
115
|
footer?: React.ReactNode;
|
|
60
116
|
/** An external link row, e.g. "View on Instagram". */
|
|
61
117
|
externalLink?: React.ReactNode;
|
|
62
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* Poster height cap in px, or `"aspect"` for the poster's own 4:5. Defaults
|
|
120
|
+
* to 318 for `compact` (the phone drawer) and 300 otherwise (the side sheet).
|
|
121
|
+
*/
|
|
122
|
+
heroHeight?: number | "aspect";
|
|
123
|
+
/** `compact` is the phone drawer: the shorter default hero cap. */
|
|
63
124
|
size?: "compact" | "default";
|
|
64
125
|
linkComponent?: React.ComponentType<EventDetailPanelLinkProps>;
|
|
65
126
|
className?: string;
|
|
66
127
|
/** Rendered instead of the poster when it's absent. Defaults to `<EventPosterFallback />`. */
|
|
67
128
|
fallback?: React.ReactNode;
|
|
68
129
|
};
|
|
69
|
-
declare function EventDetailPanel({ event, labels, formatters, dateLine, venue, tags,
|
|
130
|
+
declare function EventDetailPanel({ event, labels, formatters, dateLine, dateTime, status, soonLabel, hype, venue, tags, performers, performersPreview, showAllPerformersLabel, headerActions, footer, externalLink, heroHeight, size, linkComponent: LinkComponent, className, fallback, }: EventDetailPanelProps): react_jsx_runtime.JSX.Element;
|
|
131
|
+
type EventDetailFooterProps = {
|
|
132
|
+
/**
|
|
133
|
+
* The one primary action — a `Button` (reserve, tickets, directions when
|
|
134
|
+
* there is no booking, or "see what's on tonight" for an ended event). The
|
|
135
|
+
* host decides which; this only lays it out.
|
|
136
|
+
*/
|
|
137
|
+
primary: React.ReactNode;
|
|
138
|
+
/**
|
|
139
|
+
* Zero to two ghost actions — `EventDetailGhostAction`s — drawn as one row
|
|
140
|
+
* above the primary with a hairline between them. Ghosts, not bordered
|
|
141
|
+
* boxes: three bordered buttons stacked read as three equal choices, and
|
|
142
|
+
* the reserve action is not one of three.
|
|
143
|
+
*/
|
|
144
|
+
ghosts?: React.ReactNode[];
|
|
145
|
+
className?: string;
|
|
146
|
+
};
|
|
147
|
+
/** The sticky footer under the panel's scroll region: one primary over a ghost row. */
|
|
148
|
+
declare function EventDetailFooter({ primary, ghosts, className, }: EventDetailFooterProps): react_jsx_runtime.JSX.Element;
|
|
149
|
+
type EventDetailGhostActionProps = {
|
|
150
|
+
icon?: React.ReactNode;
|
|
151
|
+
children: React.ReactNode;
|
|
152
|
+
href?: string;
|
|
153
|
+
linkComponent?: React.ComponentType<EventDetailPanelLinkProps>;
|
|
154
|
+
onClick?: (mouseEvent: React.MouseEvent) => void;
|
|
155
|
+
/** `_blank` for an outward link (a maps app). */
|
|
156
|
+
target?: string;
|
|
157
|
+
rel?: string;
|
|
158
|
+
className?: string;
|
|
159
|
+
};
|
|
160
|
+
/** A quiet action in the footer's ghost row. A link when `href` is given, a button otherwise. */
|
|
161
|
+
declare function EventDetailGhostAction({ icon, children, href, linkComponent: LinkComponent, onClick, target, rel, className, }: EventDetailGhostActionProps): react_jsx_runtime.JSX.Element;
|
|
162
|
+
type EventDetailPanelErrorProps = {
|
|
163
|
+
title: string;
|
|
164
|
+
description: string;
|
|
165
|
+
retryLabel: string;
|
|
166
|
+
onRetry: () => void;
|
|
167
|
+
/** The way onward, e.g. "See what's on tonight". */
|
|
168
|
+
secondaryLabel?: string;
|
|
169
|
+
secondaryHref?: string;
|
|
170
|
+
onSecondary?: () => void;
|
|
171
|
+
linkComponent?: React.ComponentType<EventDetailPanelLinkProps>;
|
|
172
|
+
/** Close/share controls over the (empty) hero — same slot as the panel. */
|
|
173
|
+
headerActions?: React.ReactNode;
|
|
174
|
+
className?: string;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* The panel when the event could not be loaded: an empty gradient hero so the
|
|
178
|
+
* sheet keeps its shape and its controls, then the message and a way onward —
|
|
179
|
+
* not only an apology.
|
|
180
|
+
*/
|
|
181
|
+
declare function EventDetailPanelError({ title, description, retryLabel, onRetry, secondaryLabel, secondaryHref, onSecondary, linkComponent: LinkComponent, headerActions, className, }: EventDetailPanelErrorProps): react_jsx_runtime.JSX.Element;
|
|
70
182
|
type EventDetailPanelSkeletonProps = {
|
|
71
|
-
/** `compact` is the
|
|
183
|
+
/** `compact` is the phone drawer: the shorter default hero cap. */
|
|
72
184
|
size?: "compact" | "default";
|
|
73
|
-
|
|
185
|
+
heroHeight?: number | "aspect";
|
|
186
|
+
/** Close and share controls over the poster — same slot as the real component. */
|
|
74
187
|
headerActions?: React.ReactNode;
|
|
188
|
+
/**
|
|
189
|
+
* Announces the skeleton as a busy status region with this text, e.g.
|
|
190
|
+
* "Loading the event". Without it the skeleton is `aria-hidden` and the host
|
|
191
|
+
* is expected to announce loading itself.
|
|
192
|
+
*/
|
|
193
|
+
label?: string;
|
|
75
194
|
className?: string;
|
|
76
195
|
};
|
|
77
|
-
/** Mirrors `<EventDetailPanel>`'s geometry
|
|
78
|
-
declare function EventDetailPanelSkeleton({ size, headerActions, className, }: EventDetailPanelSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
196
|
+
/** Mirrors `<EventDetailPanel>`'s geometry: capped hero, two title lines, when-line, chips, venue card, line-up, about, ghost row and primary. */
|
|
197
|
+
declare function EventDetailPanelSkeleton({ size, heroHeight, headerActions, label, className, }: EventDetailPanelSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
198
|
+
type EventDetailChipRowProps = Pick<EventDetailPanelProps, "event" | "formatters" | "status" | "soonLabel" | "hype" | "tags"> & {
|
|
199
|
+
/** Only the chip strings — a page rendering the row alone need not name the section headings. */
|
|
200
|
+
labels: Pick<EventDetailPanelLabels, "free" | "liveNow" | "ended">;
|
|
201
|
+
className?: string;
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* One wrapping row, all 24px: status, fee, hype, then activity tags. Exported
|
|
205
|
+
* so the page renders the same row above its title — it is the panel's row,
|
|
206
|
+
* not a second one.
|
|
207
|
+
*/
|
|
208
|
+
declare function EventDetailChipRow({ event, labels, formatters, status, soonLabel, hype, tags, className, }: EventDetailChipRowProps): react_jsx_runtime.JSX.Element;
|
|
209
|
+
type EventDetailVenueCardProps = {
|
|
210
|
+
venue: EventDetailVenue;
|
|
211
|
+
labels: Pick<EventDetailPanelLabels, "venueNoPage">;
|
|
212
|
+
linkComponent?: React.ComponentType<EventDetailPanelLinkProps>;
|
|
213
|
+
/** Thumbnail size in px: 52 in the sheet, 64 on the page. */
|
|
214
|
+
thumbnailSize?: 52 | 64;
|
|
215
|
+
/** An inline action beside the chevron — the page's "Open in Maps". */
|
|
216
|
+
action?: React.ReactNode;
|
|
217
|
+
className?: string;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* The venue row: cover with an open-now dot, name, address · rating · open
|
|
221
|
+
* label, a chevron when it links. Without `venue.href` it is not a link and
|
|
222
|
+
* says so — a venue the ingest knows by name only must not read as broken.
|
|
223
|
+
*/
|
|
224
|
+
declare function EventDetailVenueCard({ venue, labels, linkComponent: LinkComponent, thumbnailSize, action, className, }: EventDetailVenueCardProps): react_jsx_runtime.JSX.Element;
|
|
79
225
|
|
|
80
|
-
export { EventDetailPanel, type EventDetailPanelLabels, type EventDetailPanelLinkProps, type EventDetailPanelProps, EventDetailPanelSkeleton, type EventDetailPanelSkeletonProps, type EventDetailVenue };
|
|
226
|
+
export { EventDetailChipRow, type EventDetailChipRowProps, EventDetailFooter, type EventDetailFooterProps, EventDetailGhostAction, type EventDetailGhostActionProps, EventDetailPanel, EventDetailPanelError, type EventDetailPanelErrorProps, type EventDetailPanelLabels, type EventDetailPanelLinkProps, type EventDetailPanelProps, EventDetailPanelSkeleton, type EventDetailPanelSkeletonProps, type EventDetailStatus, type EventDetailVenue, EventDetailVenueCard, type EventDetailVenueCardProps };
|