@bearmenu/ui 0.8.7 → 0.8.8
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-637L7XQ3.js → chunk-3TNPSN4D.js} +28 -9
- package/dist/chunk-AHL45DD2.js +145 -0
- package/dist/chunk-IYDH5IU6.js +66 -0
- package/dist/chunk-OPVKL4VS.js +18 -0
- package/dist/components/alert.d.ts +2 -2
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/category-deck.js +10 -1
- package/dist/components/coverflow.d.ts +11 -3
- package/dist/components/coverflow.js +34 -51
- package/dist/components/date-input.d.ts +1 -1
- package/dist/components/drift-rail.d.ts +24 -10
- package/dist/components/drift-rail.js +1 -1
- package/dist/components/event-card.d.ts +8 -0
- package/dist/components/event-card.js +63 -33
- package/dist/components/event-compact-row.d.ts +32 -5
- package/dist/components/event-compact-row.js +119 -38
- package/dist/components/event-day-header.js +3 -1
- package/dist/components/event-day-separator.d.ts +7 -1
- package/dist/components/event-day-separator.js +3 -2
- package/dist/components/event-hub-hero.d.ts +25 -4
- package/dist/components/event-hub-hero.js +89 -19
- package/dist/components/event-list-row.d.ts +19 -6
- package/dist/components/event-list-row.js +78 -34
- package/dist/components/hour-band.d.ts +38 -40
- package/dist/components/hour-band.js +55 -27
- package/dist/components/hour-group.js +1 -1
- package/dist/components/poster-tape.js +1 -1
- package/dist/components/poster-wall.d.ts +3 -3
- package/dist/components/poster-wall.js +73 -17
- package/dist/components/section-header.d.ts +16 -1
- package/dist/components/section-header.js +26 -7
- package/dist/components/snap-rail.d.ts +34 -0
- package/dist/components/snap-rail.js +51 -0
- package/dist/components/tag.d.ts +2 -2
- package/dist/components/text.d.ts +1 -1
- package/dist/components/timeline-band.d.ts +20 -2
- package/dist/components/timeline-band.js +1 -1
- package/dist/components/timeline-playhead.d.ts +26 -0
- package/dist/components/timeline-playhead.js +25 -0
- package/dist/components/weekend-panel.d.ts +5 -4
- package/dist/components/weekend-panel.js +85 -71
- package/dist/hooks/use-drag-swipe.d.ts +44 -0
- package/dist/hooks/use-drag-swipe.js +2 -0
- package/dist/hooks/use-media-query.d.ts +17 -0
- package/dist/hooks/use-media-query.js +2 -0
- package/package.json +1 -1
- package/src/components/category-deck.tsx +19 -8
- package/src/components/coverflow.test.tsx +28 -1
- package/src/components/coverflow.tsx +37 -43
- package/src/components/drift-rail.tsx +167 -42
- package/src/components/event-card.tsx +55 -10
- package/src/components/event-compact-row.stories.tsx +30 -0
- package/src/components/event-compact-row.test.tsx +49 -0
- package/src/components/event-compact-row.tsx +161 -37
- package/src/components/event-day-header.tsx +3 -1
- package/src/components/event-day-separator.tsx +8 -1
- package/src/components/event-hub-hero.stories.tsx +30 -0
- package/src/components/event-hub-hero.tsx +102 -30
- package/src/components/event-list-row.stories.tsx +34 -0
- package/src/components/event-list-row.test.tsx +53 -0
- package/src/components/event-list-row.tsx +135 -87
- package/src/components/hour-band.stories.tsx +28 -5
- package/src/components/hour-band.tsx +90 -70
- package/src/components/poster-wall.test.tsx +28 -0
- package/src/components/poster-wall.tsx +96 -23
- package/src/components/section-header.stories.tsx +24 -0
- package/src/components/section-header.test.tsx +28 -0
- package/src/components/section-header.tsx +45 -7
- package/src/components/snap-rail.stories.tsx +79 -0
- package/src/components/snap-rail.test.tsx +18 -0
- package/src/components/snap-rail.tsx +67 -0
- package/src/components/timeline-band.tsx +52 -12
- package/src/components/timeline-playhead.stories.tsx +30 -0
- package/src/components/timeline-playhead.test.tsx +11 -0
- package/src/components/timeline-playhead.tsx +46 -0
- package/src/components/weekend-panel.test.tsx +43 -0
- package/src/components/weekend-panel.tsx +142 -108
- package/src/hooks/use-drag-swipe.test.tsx +66 -0
- package/src/hooks/use-drag-swipe.ts +105 -0
- package/src/hooks/use-media-query.ts +31 -0
- package/dist/chunk-GPH6L4DX.js +0 -55
|
@@ -25,6 +25,8 @@ var EventCard = memo(function EventCard2({
|
|
|
25
25
|
tags,
|
|
26
26
|
liveStatus,
|
|
27
27
|
hideWhen,
|
|
28
|
+
isEnded,
|
|
29
|
+
endedLabel,
|
|
28
30
|
dayLabel,
|
|
29
31
|
showPrice,
|
|
30
32
|
href,
|
|
@@ -36,6 +38,7 @@ var EventCard = memo(function EventCard2({
|
|
|
36
38
|
}) {
|
|
37
39
|
var _a;
|
|
38
40
|
const [imgError, setImgError] = useState(false);
|
|
41
|
+
const showEnded = isEnded && !!endedLabel;
|
|
39
42
|
const time = hideWhen ? "" : formatters.time(event.starts_at);
|
|
40
43
|
const fee = resolveEventEntryFee(event);
|
|
41
44
|
const showPoster = !!event.poster_url && !imgError;
|
|
@@ -46,6 +49,7 @@ var EventCard = memo(function EventCard2({
|
|
|
46
49
|
{
|
|
47
50
|
className: cn(
|
|
48
51
|
"relative overflow-hidden rounded-xl bg-muted",
|
|
52
|
+
isEnded && "opacity-45",
|
|
49
53
|
posterAspect === "3/4" ? "aspect-[3/4]" : posterAspect === "4/5" ? "aspect-[4/5]" : "aspect-[4/3]"
|
|
50
54
|
),
|
|
51
55
|
children: [
|
|
@@ -66,10 +70,19 @@ var EventCard = memo(function EventCard2({
|
|
|
66
70
|
) : fallback,
|
|
67
71
|
/* @__PURE__ */ jsxs("div", { className: "absolute inset-x-2 top-2 flex items-start justify-between gap-2", children: [
|
|
68
72
|
badge ? /* @__PURE__ */ jsx("span", { className: cn(PILL_BASE, "bg-black/55 text-white"), children: badge }) : /* @__PURE__ */ jsx("span", {}),
|
|
69
|
-
fee.kind === "free" && /* @__PURE__ */ jsxs(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
fee.kind === "free" && /* @__PURE__ */ jsxs(
|
|
74
|
+
"span",
|
|
75
|
+
{
|
|
76
|
+
className: cn(
|
|
77
|
+
PILL_BASE,
|
|
78
|
+
"bg-success font-bold text-success-foreground"
|
|
79
|
+
),
|
|
80
|
+
children: [
|
|
81
|
+
/* @__PURE__ */ jsx(Gift, { className: "h-3 w-3", "aria-hidden": true }),
|
|
82
|
+
labels.free
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
)
|
|
73
86
|
] }),
|
|
74
87
|
tagLabel && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-2 bottom-2 flex gap-1", children: /* @__PURE__ */ jsx("span", { className: cn(PILL_BASE, "bg-black/55 text-white"), children: tagLabel }) })
|
|
75
88
|
]
|
|
@@ -80,7 +93,8 @@ var EventCard = memo(function EventCard2({
|
|
|
80
93
|
{
|
|
81
94
|
className: cn(
|
|
82
95
|
"mt-2.5 leading-[1.35]",
|
|
83
|
-
emphasis ? "text-lg font-bold tracking-[-0.02em]" : "text-sm font-semibold"
|
|
96
|
+
emphasis ? "text-lg font-bold tracking-[-0.02em]" : "text-sm font-semibold",
|
|
97
|
+
isEnded && "text-muted-foreground"
|
|
84
98
|
),
|
|
85
99
|
children: event.title
|
|
86
100
|
}
|
|
@@ -104,7 +118,8 @@ var EventCard = memo(function EventCard2({
|
|
|
104
118
|
liveStatus && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5 text-xs font-bold text-success", children: [
|
|
105
119
|
/* @__PURE__ */ jsx(Radio, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
|
|
106
120
|
liveStatus
|
|
107
|
-
] })
|
|
121
|
+
] }),
|
|
122
|
+
showEnded && /* @__PURE__ */ jsx("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx(Tag, { size: "sm", variant: "default", className: "font-extrabold", children: endedLabel }) })
|
|
108
123
|
] });
|
|
109
124
|
const rootClasses = cn(
|
|
110
125
|
"flex min-w-0 flex-col text-left",
|
|
@@ -123,7 +138,15 @@ var EventCard = memo(function EventCard2({
|
|
|
123
138
|
);
|
|
124
139
|
}
|
|
125
140
|
if (onClick) {
|
|
126
|
-
return /* @__PURE__ */ jsx(
|
|
141
|
+
return /* @__PURE__ */ jsx(
|
|
142
|
+
"button",
|
|
143
|
+
{
|
|
144
|
+
type: "button",
|
|
145
|
+
className: rootClasses,
|
|
146
|
+
onClick: (e) => onClick(event, e),
|
|
147
|
+
children: body
|
|
148
|
+
}
|
|
149
|
+
);
|
|
127
150
|
}
|
|
128
151
|
return /* @__PURE__ */ jsx("div", { className: rootClasses, children: body });
|
|
129
152
|
});
|
|
@@ -133,32 +156,39 @@ function EventCardSkeleton({
|
|
|
133
156
|
hideWhen,
|
|
134
157
|
className
|
|
135
158
|
}) {
|
|
136
|
-
return /* @__PURE__ */ jsxs(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
return /* @__PURE__ */ jsxs(
|
|
160
|
+
"div",
|
|
161
|
+
{
|
|
162
|
+
"aria-hidden": "true",
|
|
163
|
+
className: cn("flex min-w-0 flex-col text-left", className),
|
|
164
|
+
children: [
|
|
165
|
+
/* @__PURE__ */ jsx(
|
|
166
|
+
Skeleton,
|
|
167
|
+
{
|
|
168
|
+
className: cn(
|
|
169
|
+
posterAspect === "3/4" ? "aspect-[3/4]" : posterAspect === "4/5" ? "aspect-[4/5]" : "aspect-[4/3]"
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
),
|
|
173
|
+
emphasis ? /* @__PURE__ */ jsxs("div", { className: "mt-2.5 space-y-2", children: [
|
|
174
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-full" }),
|
|
175
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-full" }),
|
|
176
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-5 w-1/2" })
|
|
177
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "mt-2.5 space-y-1.5", children: [
|
|
178
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-full" }),
|
|
179
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-2/3" })
|
|
180
|
+
] }),
|
|
181
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex items-center gap-1", children: [
|
|
182
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-3 shrink-0 rounded-full" }),
|
|
183
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
|
|
184
|
+
] }),
|
|
185
|
+
!hideWhen && /* @__PURE__ */ jsxs("div", { className: "mt-[3px] flex items-center gap-1.5", children: [
|
|
186
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-16" }),
|
|
187
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-10" })
|
|
188
|
+
] })
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
);
|
|
162
192
|
}
|
|
163
193
|
|
|
164
194
|
export { EventCard, EventCardSkeleton };
|
|
@@ -14,10 +14,25 @@ import { EventPreview, EventCardLabels, EventFormatters } from './event-types.js
|
|
|
14
14
|
*
|
|
15
15
|
* THIS ROW DOES NOT DRAW DIVIDERS; ITS CONTAINER DOES. `<HourGroup>` already
|
|
16
16
|
* draws the rule under the hour heading, so a row-level top separator here
|
|
17
|
-
* doubled it directly beneath every hour
|
|
18
|
-
* `<EventListRowWide>` are different:
|
|
19
|
-
* other rule around them, so their own top
|
|
20
|
-
* do not carry this rule over to them.
|
|
17
|
+
* doubled it directly beneath every hour; `<HourBand>` rules between its rows
|
|
18
|
+
* with a wrapper. `<EventListRow>` and `<EventListRowWide>` are different:
|
|
19
|
+
* they stack in a plain list with no other rule around them, so their own top
|
|
20
|
+
* separator is the only one there — do not carry this rule over to them.
|
|
21
|
+
*
|
|
22
|
+
* STATE LIVES ON THE META LINE. `isLive` adds the on-air chip and `isEnded`
|
|
23
|
+
* the ended chip beside the time and venue, so a row's state is read in the
|
|
24
|
+
* same glance as its facts. Ended dims the POSTER and moves the title to
|
|
25
|
+
* `--muted-foreground` — never row-level opacity, which composites the text
|
|
26
|
+
* below AA.
|
|
27
|
+
*
|
|
28
|
+
* THE PRICE IS ON THE LAST ROW, right-aligned beside the tags, not on the
|
|
29
|
+
* title line. Two bold things on one line compete — the title and a price
|
|
30
|
+
* both in 700 read as one shout — and the title is the thing the reader is
|
|
31
|
+
* scanning for. `showPrice` renders it (free in `--success`, paid in
|
|
32
|
+
* `--foreground`); without it the row keeps its trailing free pill for the
|
|
33
|
+
* hub's venue block. This is ONE row for the timeline and the list view:
|
|
34
|
+
* the list used to have its own, and the reader met two anatomies for the
|
|
35
|
+
* same object.
|
|
21
36
|
*
|
|
22
37
|
* Same contract as the rest: DS-owned view model, injected labels/formatters,
|
|
23
38
|
* plain `<img>`, anchor whenever `href` is given.
|
|
@@ -51,6 +66,18 @@ type EventCompactRowProps = {
|
|
|
51
66
|
* rather than truncate, so a chip's own text is never cut mid-word. Cap
|
|
52
67
|
* the count at the call site — this row does not. */
|
|
53
68
|
tags?: string[];
|
|
69
|
+
/** Currently running — adds the `labels.liveNow` chip to the meta line. */
|
|
70
|
+
isLive?: boolean;
|
|
71
|
+
/** Already over — dims the poster, mutes the title, adds the `endedLabel` chip. */
|
|
72
|
+
isEnded?: boolean;
|
|
73
|
+
/** Chip text for an ended event, e.g. "Ended". Required to render the chip. */
|
|
74
|
+
endedLabel?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Prints the fee on the meta line — `labels.free` in `--success`, a paid
|
|
77
|
+
* amount via `formatters.price` — instead of the trailing free pill. An
|
|
78
|
+
* unknown fee prints nothing, same as every sibling row.
|
|
79
|
+
*/
|
|
80
|
+
showPrice?: boolean;
|
|
54
81
|
size?: "sm" | "default";
|
|
55
82
|
href?: string;
|
|
56
83
|
linkComponent?: React.ComponentType<EventCompactRowLinkProps>;
|
|
@@ -68,6 +95,6 @@ type EventCompactRowSkeletonProps = {
|
|
|
68
95
|
className?: string;
|
|
69
96
|
};
|
|
70
97
|
/** Mirrors `<EventCompactRow>`'s geometry exactly so nothing shifts when data lands. */
|
|
71
|
-
declare function EventCompactRowSkeleton({ size, className }: EventCompactRowSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
98
|
+
declare function EventCompactRowSkeleton({ size, className, }: EventCompactRowSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
72
99
|
|
|
73
100
|
export { EventCompactRow, type EventCompactRowLinkProps, type EventCompactRowProps, EventCompactRowSkeleton, type EventCompactRowSkeletonProps };
|
|
@@ -6,6 +6,7 @@ import { Skeleton } from '../chunk-QXHMPJ35.js';
|
|
|
6
6
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
7
7
|
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|
|
8
8
|
import { memo, useState } from 'react';
|
|
9
|
+
import { Radio } from 'lucide-react';
|
|
9
10
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
10
11
|
|
|
11
12
|
function DefaultLink(_a) {
|
|
@@ -19,6 +20,10 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
19
20
|
hideTime,
|
|
20
21
|
subtitle,
|
|
21
22
|
tags,
|
|
23
|
+
isLive,
|
|
24
|
+
isEnded,
|
|
25
|
+
endedLabel,
|
|
26
|
+
showPrice,
|
|
22
27
|
size = "default",
|
|
23
28
|
href,
|
|
24
29
|
linkComponent: LinkComponent = DefaultLink,
|
|
@@ -34,50 +39,107 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
34
39
|
const showPoster = !!event.poster_url && !imgError;
|
|
35
40
|
const venue = (_a = event.place_name) != null ? _a : event.location;
|
|
36
41
|
const time = formatters.time(event.starts_at);
|
|
42
|
+
const priceText = fee.kind === "free" ? labels.free : fee.kind === "paid" ? formatters.price(fee.amountRon) : void 0;
|
|
43
|
+
const showEnded = isEnded && !!endedLabel;
|
|
44
|
+
const separator = /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-border", children: "\xB7" });
|
|
37
45
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38
|
-
/* @__PURE__ */ jsx(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
/* @__PURE__ */ jsx(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
className: cn(
|
|
50
|
+
"relative aspect-[4/5] w-16 shrink-0 overflow-hidden rounded-[10px] bg-muted",
|
|
51
|
+
isEnded && "opacity-45"
|
|
52
|
+
),
|
|
53
|
+
children: showPoster ? (
|
|
54
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
55
|
+
/* @__PURE__ */ jsx(
|
|
56
|
+
"img",
|
|
57
|
+
{
|
|
58
|
+
src: event.poster_url,
|
|
59
|
+
alt: "",
|
|
60
|
+
loading: priority ? "eager" : "lazy",
|
|
61
|
+
decoding: "async",
|
|
62
|
+
className: "h-full w-full object-cover",
|
|
63
|
+
onError: () => setImgError(true)
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
) : (
|
|
67
|
+
// A bare `bg-muted` rectangle was survivable at 34px. At 58x72 beside
|
|
68
|
+
// real posters it reads as a broken image rather than an absent one —
|
|
69
|
+
// so this row finally joins every sibling in the family in having a
|
|
70
|
+
// designed fallback.
|
|
71
|
+
fallback
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
),
|
|
58
75
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
59
76
|
/* @__PURE__ */ jsx(
|
|
60
77
|
"div",
|
|
61
78
|
{
|
|
62
79
|
className: cn(
|
|
63
|
-
"
|
|
80
|
+
"leading-[1.3]",
|
|
64
81
|
"transition-colors duration-150 motion-reduce:transition-none",
|
|
65
|
-
isSm ? "text-[13.5px]" : "text-[13px]",
|
|
82
|
+
isSm ? "text-[14.5px] lg:text-[13.5px]" : "text-[14px] lg:text-[13px]",
|
|
83
|
+
isEnded ? "font-semibold text-muted-foreground" : "font-bold text-foreground lg:font-semibold",
|
|
66
84
|
(href || onClick) && "group-hover:text-primary"
|
|
67
85
|
),
|
|
68
86
|
children: event.title
|
|
69
87
|
}
|
|
70
88
|
),
|
|
71
|
-
/* @__PURE__ */
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
/* @__PURE__ */ jsxs(
|
|
90
|
+
"div",
|
|
91
|
+
{
|
|
92
|
+
className: cn(
|
|
93
|
+
"mt-1 flex items-center gap-1.5 text-[11.5px] text-muted-foreground",
|
|
94
|
+
isLive || showEnded ? "flex-wrap" : "truncate"
|
|
95
|
+
),
|
|
96
|
+
children: [
|
|
97
|
+
subtitle ? subtitle : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
98
|
+
!hideTime && time && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
99
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono tabular-nums", children: time }),
|
|
100
|
+
separator
|
|
101
|
+
] }),
|
|
102
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: venue })
|
|
103
|
+
] }),
|
|
104
|
+
isLive && /* @__PURE__ */ jsxs(
|
|
105
|
+
Tag,
|
|
106
|
+
{
|
|
107
|
+
size: "sm",
|
|
108
|
+
variant: "success",
|
|
109
|
+
className: "shrink-0 whitespace-nowrap font-extrabold",
|
|
110
|
+
children: [
|
|
111
|
+
/* @__PURE__ */ jsx(Radio, { className: "h-2.5 w-2.5", "aria-hidden": true }),
|
|
112
|
+
labels.liveNow
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
),
|
|
116
|
+
showEnded && /* @__PURE__ */ jsx(
|
|
117
|
+
Tag,
|
|
118
|
+
{
|
|
119
|
+
size: "sm",
|
|
120
|
+
variant: "default",
|
|
121
|
+
className: "shrink-0 whitespace-nowrap font-extrabold",
|
|
122
|
+
children: endedLabel
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
(tags && tags.length > 0 || showPrice && priceText) && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 flex items-center gap-2", children: [
|
|
129
|
+
tags && tags.length > 0 ? /* @__PURE__ */ jsx(TagGroup, { className: "min-w-0 flex-1", children: tags.map((tag) => /* @__PURE__ */ jsx(Tag, { size: "sm", variant: "quiet", children: tag }, tag)) }) : /* @__PURE__ */ jsx("span", { className: "flex-1" }),
|
|
130
|
+
showPrice && priceText && /* @__PURE__ */ jsx(
|
|
131
|
+
"span",
|
|
132
|
+
{
|
|
133
|
+
className: cn(
|
|
134
|
+
"shrink-0 text-[13px] tabular-nums",
|
|
135
|
+
fee.kind === "free" ? "font-semibold text-success" : "font-bold text-foreground"
|
|
136
|
+
),
|
|
137
|
+
children: priceText
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
] })
|
|
79
141
|
] }),
|
|
80
|
-
fee.kind === "free" && /* @__PURE__ */ jsx(
|
|
142
|
+
!showPrice && fee.kind === "free" && /* @__PURE__ */ jsx(
|
|
81
143
|
"span",
|
|
82
144
|
{
|
|
83
145
|
className: cn(
|
|
@@ -89,7 +151,7 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
89
151
|
)
|
|
90
152
|
] });
|
|
91
153
|
const rootClasses = cn(
|
|
92
|
-
"group relative -mx-2.5 flex w-full items-start gap-
|
|
154
|
+
"group relative -mx-2.5 flex w-full items-start gap-3 rounded-lg px-2.5 py-[11px] text-left lg:gap-[11px] lg:py-2",
|
|
93
155
|
"transition-colors duration-150 motion-reduce:transition-none",
|
|
94
156
|
(href || onClick) && "cursor-pointer hover:bg-foreground/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
95
157
|
className
|
|
@@ -106,25 +168,44 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
106
168
|
);
|
|
107
169
|
}
|
|
108
170
|
if (onClick) {
|
|
109
|
-
return /* @__PURE__ */ jsx(
|
|
171
|
+
return /* @__PURE__ */ jsx(
|
|
172
|
+
"button",
|
|
173
|
+
{
|
|
174
|
+
type: "button",
|
|
175
|
+
className: rootClasses,
|
|
176
|
+
onClick: (e) => onClick(event, e),
|
|
177
|
+
children: body
|
|
178
|
+
}
|
|
179
|
+
);
|
|
110
180
|
}
|
|
111
181
|
return /* @__PURE__ */ jsx("div", { className: rootClasses, children: body });
|
|
112
182
|
});
|
|
113
|
-
function EventCompactRowSkeleton({
|
|
183
|
+
function EventCompactRowSkeleton({
|
|
184
|
+
size = "default",
|
|
185
|
+
className
|
|
186
|
+
}) {
|
|
114
187
|
const isSm = size === "sm";
|
|
115
188
|
return /* @__PURE__ */ jsxs(
|
|
116
189
|
"div",
|
|
117
190
|
{
|
|
118
191
|
"aria-hidden": "true",
|
|
119
192
|
className: cn(
|
|
120
|
-
"relative -mx-2.5 flex w-full items-start gap-
|
|
193
|
+
"relative -mx-2.5 flex w-full items-start gap-3 rounded-lg px-2.5 py-[11px] text-left lg:gap-[11px] lg:py-2",
|
|
121
194
|
className
|
|
122
195
|
),
|
|
123
196
|
children: [
|
|
124
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "aspect-[4/5] w-16 shrink-0 rounded-[
|
|
197
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "aspect-[4/5] w-16 shrink-0 rounded-[10px]" }),
|
|
125
198
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
126
|
-
/* @__PURE__ */ jsx(
|
|
127
|
-
|
|
199
|
+
/* @__PURE__ */ jsx(
|
|
200
|
+
Skeleton,
|
|
201
|
+
{
|
|
202
|
+
className: cn(
|
|
203
|
+
isSm ? "h-[14.5px] lg:h-[13.5px]" : "h-[14px] lg:h-[13px]",
|
|
204
|
+
"w-3/5"
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
),
|
|
208
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "mt-1 h-[11.5px] w-1/3" })
|
|
128
209
|
] })
|
|
129
210
|
]
|
|
130
211
|
}
|
|
@@ -27,7 +27,9 @@ function EventDayHeader({
|
|
|
27
27
|
{
|
|
28
28
|
className: cn(
|
|
29
29
|
"font-black leading-[0.82] tracking-[-0.05em] tabular-nums",
|
|
30
|
-
|
|
30
|
+
// `sm` is the phone scale: 30px, the design's app day head. 40px
|
|
31
|
+
// was a page-scale number that took a third of a 390px row.
|
|
32
|
+
large ? "text-[58px]" : "text-[30px] leading-[0.86]"
|
|
31
33
|
),
|
|
32
34
|
children: dayNumber
|
|
33
35
|
}
|
|
@@ -25,6 +25,12 @@ import { ElementType } from 'react';
|
|
|
25
25
|
* `<Separator>` above the label), not the weight.
|
|
26
26
|
*/
|
|
27
27
|
type EventDaySeparatorProps = {
|
|
28
|
+
/**
|
|
29
|
+
* `always` (default) draws the trailing rule at every width. `lg` drops it
|
|
30
|
+
* below `lg`, where the list is an app sheet whose day heads are bold
|
|
31
|
+
* labels alone — the rows below rule themselves — and keeps it from `lg`.
|
|
32
|
+
*/
|
|
33
|
+
rule?: "always" | "lg";
|
|
28
34
|
label: string;
|
|
29
35
|
count?: string;
|
|
30
36
|
size?: "sm" | "default";
|
|
@@ -32,7 +38,7 @@ type EventDaySeparatorProps = {
|
|
|
32
38
|
as?: ElementType;
|
|
33
39
|
className?: string;
|
|
34
40
|
};
|
|
35
|
-
declare function EventDaySeparator({ label, count, size, as: Tag, className, }: EventDaySeparatorProps): react_jsx_runtime.JSX.Element;
|
|
41
|
+
declare function EventDaySeparator({ label, count, size, as: Tag, className, rule, }: EventDaySeparatorProps): react_jsx_runtime.JSX.Element;
|
|
36
42
|
type EventDaySeparatorSkeletonProps = {
|
|
37
43
|
/** Matches `EventDaySeparatorProps["size"]`. */
|
|
38
44
|
size?: "sm" | "default";
|
|
@@ -9,7 +9,8 @@ function EventDaySeparator({
|
|
|
9
9
|
count,
|
|
10
10
|
size = "default",
|
|
11
11
|
as: Tag = "h2",
|
|
12
|
-
className
|
|
12
|
+
className,
|
|
13
|
+
rule = "always"
|
|
13
14
|
}) {
|
|
14
15
|
return /* @__PURE__ */ jsxs(
|
|
15
16
|
"div",
|
|
@@ -22,7 +23,7 @@ function EventDaySeparator({
|
|
|
22
23
|
children: [
|
|
23
24
|
/* @__PURE__ */ jsx(Tag, { className: cn("font-semibold", size === "sm" ? "text-[13px]" : "text-sm"), children: label }),
|
|
24
25
|
count && /* @__PURE__ */ jsx("span", { className: cn("text-muted-foreground", size === "sm" ? "text-[11.5px]" : "text-xs"), children: count }),
|
|
25
|
-
/* @__PURE__ */ jsx(Separator, { className: "flex-1" })
|
|
26
|
+
/* @__PURE__ */ jsx(Separator, { className: cn("flex-1", rule === "lg" && "hidden lg:block") })
|
|
26
27
|
]
|
|
27
28
|
}
|
|
28
29
|
);
|
|
@@ -2,9 +2,20 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* EventHubHero — the hub's opening block: an eyebrow, a big
|
|
6
|
-
* intro
|
|
7
|
-
* stack, in the source design) on the right.
|
|
5
|
+
* EventHubHero — the hub's opening block. On desktop: an eyebrow, a big
|
|
6
|
+
* headline, an intro paragraph and a stats row on the left; an arbitrary slot
|
|
7
|
+
* (the poster stack, in the source design) on the right.
|
|
8
|
+
*
|
|
9
|
+
* BELOW `lg` IT IS A MASTHEAD, NOT A HERO. One headline line, the eyebrow
|
|
10
|
+
* demoted to a sub-line beneath it, no intro, and the figures as a swipeable
|
|
11
|
+
* rail of chips that bleeds to the screen edge. The first real content lands
|
|
12
|
+
* roughly 250px sooner than under the web-shaped hero — on a phone the page
|
|
13
|
+
* should show, not narrate. Same markup at every width; only the classes
|
|
14
|
+
* change, so the copy is authored once.
|
|
15
|
+
*
|
|
16
|
+
* A stat with `tone: "live"` is the one that is happening right now: its
|
|
17
|
+
* chip takes a `--success` border and value, the same live colour every
|
|
18
|
+
* events surface uses.
|
|
8
19
|
*
|
|
9
20
|
* All copy and stat values arrive pre-formatted — the DS holds no `Intl`
|
|
10
21
|
* locale and does not format numbers.
|
|
@@ -12,6 +23,8 @@ import * as React from 'react';
|
|
|
12
23
|
type EventHubHeroStat = {
|
|
13
24
|
value: string;
|
|
14
25
|
label: string;
|
|
26
|
+
/** `live` marks the figure that is happening right now. */
|
|
27
|
+
tone?: "default" | "live";
|
|
15
28
|
};
|
|
16
29
|
type EventHubHeroProps = {
|
|
17
30
|
/** Small caps-style label above the title, e.g. "Updated today". */
|
|
@@ -19,11 +32,19 @@ type EventHubHeroProps = {
|
|
|
19
32
|
title: string;
|
|
20
33
|
intro: string;
|
|
21
34
|
stats: EventHubHeroStat[];
|
|
35
|
+
/**
|
|
36
|
+
* Accessible name for the stats rail, e.g. "Key figures". When given, the
|
|
37
|
+
* rail is a named, focusable region so a keyboard can reach chips clipped
|
|
38
|
+
* by the phone's edge. Optional so existing consumers keep compiling — but
|
|
39
|
+
* pass it: without a name the rail cannot be focusable, and a phone reader
|
|
40
|
+
* on a keyboard cannot reach the last figures.
|
|
41
|
+
*/
|
|
42
|
+
statsLabel?: string;
|
|
22
43
|
/** The right-column slot — the poster stack in the source design. */
|
|
23
44
|
aside?: React.ReactNode;
|
|
24
45
|
className?: string;
|
|
25
46
|
};
|
|
26
|
-
declare function EventHubHero({ eyebrow, title, intro, stats, aside, className }: EventHubHeroProps): react_jsx_runtime.JSX.Element;
|
|
47
|
+
declare function EventHubHero({ eyebrow, title, intro, stats, statsLabel, aside, className, }: EventHubHeroProps): react_jsx_runtime.JSX.Element;
|
|
27
48
|
type EventHubHeroSkeletonProps = {
|
|
28
49
|
/** The right-column slot, e.g. a `PosterStack`-shaped placeholder. Mirrors `aside` on the real component. */
|
|
29
50
|
aside?: React.ReactNode;
|