@bearmenu/ui 0.8.17 → 0.8.19
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-WYTJR2YU.js → chunk-5CPBSNWQ.js} +6 -1
- package/dist/chunk-BRXI6EDO.js +84 -0
- package/dist/{chunk-54FQQZZJ.js → chunk-EQYB4Q77.js} +1 -1
- package/dist/chunk-QRSIJC4X.js +156 -0
- package/dist/components/concept-compare-rail.js +2 -2
- package/dist/components/concept-compare.js +2 -2
- package/dist/components/event-card.d.ts +22 -4
- package/dist/components/event-card.js +95 -50
- package/dist/components/event-day-header.d.ts +5 -3
- package/dist/components/event-day-header.js +12 -4
- package/dist/components/event-hub-hero.d.ts +12 -2
- package/dist/components/event-hub-hero.js +11 -5
- package/dist/components/event-tonight-strip.d.ts +50 -0
- package/dist/components/event-tonight-strip.js +67 -0
- package/dist/components/menu-family-block.js +4 -3
- package/dist/components/menu-hub-hero.d.ts +7 -1
- package/dist/components/menu-hub-hero.js +2 -1
- package/dist/components/poster-stack.d.ts +36 -3
- package/dist/components/poster-stack.js +87 -48
- package/dist/components/snap-rail.d.ts +2 -2
- package/dist/components/snap-rail.js +1 -1
- package/dist/components/timeline-day.d.ts +54 -0
- package/dist/components/timeline-day.js +65 -0
- package/dist/components/timeline-hour-puck.d.ts +47 -0
- package/dist/components/timeline-hour-puck.js +3 -0
- package/dist/components/timeline-hour.d.ts +96 -0
- package/dist/components/{timeline-band.js → timeline-hour.js} +2 -1
- package/dist/components/timeline-playhead.js +1 -3
- package/package.json +1 -1
- package/src/components/event-card.tsx +70 -13
- package/src/components/event-day-header.tsx +19 -7
- package/src/components/event-hub-hero.tsx +25 -3
- package/src/components/event-tonight-strip.stories.tsx +78 -0
- package/src/components/event-tonight-strip.test.tsx +49 -0
- package/src/components/event-tonight-strip.tsx +134 -0
- package/src/components/menu-family-block.tsx +13 -6
- package/src/components/menu-hub-hero.test.tsx +13 -0
- package/src/components/menu-hub-hero.tsx +9 -2
- package/src/components/poster-stack.stories.tsx +43 -1
- package/src/components/poster-stack.tsx +104 -19
- package/src/components/snap-rail.tsx +6 -1
- package/src/components/timeline-day.stories.tsx +201 -0
- package/src/components/timeline-day.test.tsx +78 -0
- package/src/components/timeline-day.tsx +114 -0
- package/src/components/timeline-hour-puck.tsx +142 -0
- package/src/components/timeline-hour.tsx +266 -0
- package/src/components/timeline-playhead.tsx +1 -1
- package/dist/chunk-NSNEANOQ.js +0 -104
- package/dist/components/hour-band.d.ts +0 -66
- package/dist/components/hour-band.js +0 -81
- package/dist/components/hour-group.d.ts +0 -67
- package/dist/components/hour-group.js +0 -59
- package/dist/components/timeline-band.d.ts +0 -64
- package/src/components/hour-band.stories.tsx +0 -182
- package/src/components/hour-band.tsx +0 -146
- package/src/components/hour-group.stories.tsx +0 -100
- package/src/components/hour-group.tsx +0 -124
- package/src/components/timeline-band.stories.tsx +0 -206
- package/src/components/timeline-band.tsx +0 -247
|
@@ -12,6 +12,9 @@ var snapRailVariants = cva(
|
|
|
12
12
|
{
|
|
13
13
|
variants: {
|
|
14
14
|
itemWidth: {
|
|
15
|
+
/** Square door tiles — three and a third per phone screen, so the
|
|
16
|
+
* cut fourth says "swipe"; more as the viewport widens. */
|
|
17
|
+
xs: "[&>*]:w-[30%] sm:[&>*]:w-[22%] md:[&>*]:w-[18%]",
|
|
15
18
|
sm: "[&>*]:w-[46%]",
|
|
16
19
|
md: "[&>*]:w-[60%]",
|
|
17
20
|
lg: "[&>*]:w-[80%]",
|
|
@@ -25,7 +28,9 @@ var snapRailVariants = cva(
|
|
|
25
28
|
bleed: {
|
|
26
29
|
none: "",
|
|
27
30
|
card: "-mx-3.5 px-3.5 scroll-px-3.5",
|
|
28
|
-
page
|
|
31
|
+
/** The consumer's page gutter, read from `--page-gutter` (16px on a
|
|
32
|
+
* phone, 24px from md) — a fixed `-mx-4` was 8px short at md. */
|
|
33
|
+
page: "-mx-[var(--page-gutter,1rem)] px-[var(--page-gutter,1rem)] scroll-px-[var(--page-gutter,1rem)]"
|
|
29
34
|
}
|
|
30
35
|
},
|
|
31
36
|
defaultVariants: {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { cn } from './chunk-FEK5XGZW.js';
|
|
2
|
+
import { Radio } from 'lucide-react';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var LIVE_PUCK_PULSE_CLASS = "bm-timeline-live-puck-pulse";
|
|
6
|
+
var TIMELINE_MOBILE_GUTTER_CLASS = "w-[58px]";
|
|
7
|
+
function TimelineHourPuck({
|
|
8
|
+
time,
|
|
9
|
+
isLive,
|
|
10
|
+
liveLabel,
|
|
11
|
+
variant = "responsive",
|
|
12
|
+
className
|
|
13
|
+
}) {
|
|
14
|
+
const chipClasses = cn(
|
|
15
|
+
"inline-flex h-6 min-w-[58px] items-center justify-center gap-1 rounded-[7px] border border-transparent px-1 text-[12px] font-medium",
|
|
16
|
+
isLive ? cn("bg-success/10 text-success", LIVE_PUCK_PULSE_CLASS) : "bg-muted text-foreground"
|
|
17
|
+
);
|
|
18
|
+
const stationClasses = cn(
|
|
19
|
+
"rounded-[7px] border bg-background px-[7px] py-[3px] text-[12.5px] font-medium",
|
|
20
|
+
isLive ? cn("border-success/40 text-success", LIVE_PUCK_PULSE_CLASS) : "border-border text-foreground"
|
|
21
|
+
);
|
|
22
|
+
const glyphClasses = "h-2.5 w-2.5 shrink-0";
|
|
23
|
+
const labelHiddenClasses = "sr-only";
|
|
24
|
+
const labelStationClasses = cn(
|
|
25
|
+
"absolute top-[calc(100%+6px)] whitespace-nowrap bg-background px-1",
|
|
26
|
+
"text-[9.5px] font-extrabold tracking-[0.08em] text-success"
|
|
27
|
+
);
|
|
28
|
+
const labelResponsiveClasses = cn(
|
|
29
|
+
"absolute -m-px h-px w-px overflow-hidden whitespace-nowrap p-0 [clip:rect(0,0,0,0)]",
|
|
30
|
+
"lg:m-0 lg:h-auto lg:w-auto lg:overflow-visible lg:px-1 lg:[clip:auto]",
|
|
31
|
+
"lg:top-[calc(100%+6px)] lg:bg-background lg:text-[9.5px] lg:font-extrabold lg:tracking-[0.08em] lg:text-success"
|
|
32
|
+
);
|
|
33
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("relative flex justify-center", className), children: [
|
|
34
|
+
isLive && /* @__PURE__ */ jsx("style", { children: `
|
|
35
|
+
@keyframes ${LIVE_PUCK_PULSE_CLASS} {
|
|
36
|
+
0%, 100% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--success) 40%, transparent); }
|
|
37
|
+
50% { box-shadow: 0 0 0 4px color-mix(in oklch, var(--success) 0%, transparent); }
|
|
38
|
+
}
|
|
39
|
+
.${LIVE_PUCK_PULSE_CLASS} {
|
|
40
|
+
animation: ${LIVE_PUCK_PULSE_CLASS} 2.4s ease-in-out infinite;
|
|
41
|
+
}
|
|
42
|
+
@media (prefers-reduced-motion: reduce) {
|
|
43
|
+
.${LIVE_PUCK_PULSE_CLASS} { animation: none; }
|
|
44
|
+
}
|
|
45
|
+
` }),
|
|
46
|
+
/* @__PURE__ */ jsxs(
|
|
47
|
+
"span",
|
|
48
|
+
{
|
|
49
|
+
className: cn(
|
|
50
|
+
"whitespace-nowrap font-mono tabular-nums",
|
|
51
|
+
variant === "chip" && chipClasses,
|
|
52
|
+
variant === "station" && stationClasses,
|
|
53
|
+
variant === "responsive" && cn(
|
|
54
|
+
chipClasses,
|
|
55
|
+
// The station look from `lg`: bordered, background-filled,
|
|
56
|
+
// content-width. Every chip utility above has an `lg:` twin.
|
|
57
|
+
// `min-w-max`, NOT `min-w-0`: the host centres the puck inside
|
|
58
|
+
// a zero-width flex box, and a flex item allowed to shrink to 0
|
|
59
|
+
// collapses to a 24px square behind its own text.
|
|
60
|
+
"lg:h-auto lg:min-w-max lg:shrink-0 lg:gap-0 lg:border-border lg:bg-background lg:px-[7px] lg:py-[3px] lg:text-[12.5px] lg:text-foreground",
|
|
61
|
+
isLive && "lg:border-success/40 lg:bg-background lg:text-success"
|
|
62
|
+
)
|
|
63
|
+
),
|
|
64
|
+
children: [
|
|
65
|
+
isLive && variant !== "station" && /* @__PURE__ */ jsx(Radio, { className: cn(glyphClasses, variant === "responsive" && "lg:hidden"), "aria-hidden": true }),
|
|
66
|
+
time
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
),
|
|
70
|
+
isLive && !!liveLabel && /* @__PURE__ */ jsx(
|
|
71
|
+
"span",
|
|
72
|
+
{
|
|
73
|
+
className: cn(
|
|
74
|
+
variant === "chip" && labelHiddenClasses,
|
|
75
|
+
variant === "station" && labelStationClasses,
|
|
76
|
+
variant === "responsive" && labelResponsiveClasses
|
|
77
|
+
),
|
|
78
|
+
children: liveLabel
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
] });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { TIMELINE_MOBILE_GUTTER_CLASS, TimelineHourPuck };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { TimelineHourPuck, TIMELINE_MOBILE_GUTTER_CLASS } from './chunk-BRXI6EDO.js';
|
|
2
|
+
import { Separator } from './chunk-NWZGSLPU.js';
|
|
3
|
+
import { Skeleton } from './chunk-XBBEX4SF.js';
|
|
4
|
+
import { cn } from './chunk-FEK5XGZW.js';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
var HEADING_CENTRE_LG = "lg:top-[30px]";
|
|
9
|
+
function TimelineHour({
|
|
10
|
+
time,
|
|
11
|
+
role = "hour",
|
|
12
|
+
isLive,
|
|
13
|
+
liveLabel,
|
|
14
|
+
countLabel,
|
|
15
|
+
note,
|
|
16
|
+
layout = "cards",
|
|
17
|
+
children,
|
|
18
|
+
overflow,
|
|
19
|
+
className
|
|
20
|
+
}) {
|
|
21
|
+
const isHero = role === "hero";
|
|
22
|
+
const isContinuation = role === "continuation";
|
|
23
|
+
const isUnscheduled = role === "unscheduled";
|
|
24
|
+
const hasStation = !isUnscheduled;
|
|
25
|
+
const isCards = layout === "cards";
|
|
26
|
+
const items = React.Children.toArray(children);
|
|
27
|
+
const overflowItems = React.Children.toArray(overflow);
|
|
28
|
+
return /* @__PURE__ */ jsxs(
|
|
29
|
+
"section",
|
|
30
|
+
{
|
|
31
|
+
"data-timeline-hour": role,
|
|
32
|
+
className: cn(
|
|
33
|
+
"relative flex flex-col pt-2.5",
|
|
34
|
+
// The phone gutter: the puck's column plus the 12px gap `HourBand` had.
|
|
35
|
+
hasStation && "pl-[70px] lg:pl-0",
|
|
36
|
+
"lg:pt-[22px]",
|
|
37
|
+
isHero ? cn(
|
|
38
|
+
// The lane. Placed by the grid, not by source order; `self-start`
|
|
39
|
+
// is load-bearing — a stretched item would be the day's full
|
|
40
|
+
// height and never stick.
|
|
41
|
+
// Longhands, not `grid-row`: a `/` inside an arbitrary value
|
|
42
|
+
// collides with the opacity-modifier parse.
|
|
43
|
+
"lg:col-start-1 lg:row-start-1 lg:[grid-row-end:span_var(--timeline-rows)] lg:self-start",
|
|
44
|
+
"lg:sticky lg:top-[var(--timeline-lane-top)] lg:pt-3.5"
|
|
45
|
+
) : "lg:col-start-3",
|
|
46
|
+
className
|
|
47
|
+
),
|
|
48
|
+
children: [
|
|
49
|
+
hasStation && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
TimelineHourPuck,
|
|
52
|
+
{
|
|
53
|
+
time,
|
|
54
|
+
isLive,
|
|
55
|
+
liveLabel,
|
|
56
|
+
className: cn(
|
|
57
|
+
"absolute left-0 top-2.5",
|
|
58
|
+
TIMELINE_MOBILE_GUTTER_CLASS,
|
|
59
|
+
// Out on the spine, centred on the heading rule.
|
|
60
|
+
"lg:left-[calc(var(--timeline-spine)*-0.5)] lg:w-0 lg:-translate-y-1/2",
|
|
61
|
+
HEADING_CENTRE_LG,
|
|
62
|
+
isContinuation && "invisible lg:visible",
|
|
63
|
+
isHero && "lg:hidden"
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
/* @__PURE__ */ jsx(
|
|
68
|
+
Separator,
|
|
69
|
+
{
|
|
70
|
+
orientation: "vertical",
|
|
71
|
+
className: cn(
|
|
72
|
+
"absolute -bottom-2.5 left-[29px] top-10 h-auto -translate-x-1/2 lg:hidden",
|
|
73
|
+
isLive && "bg-success/30"
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
] }),
|
|
78
|
+
/* @__PURE__ */ jsxs(
|
|
79
|
+
"div",
|
|
80
|
+
{
|
|
81
|
+
className: cn(
|
|
82
|
+
"items-center gap-2.5",
|
|
83
|
+
isUnscheduled ? "flex h-4" : "hidden lg:flex lg:h-4",
|
|
84
|
+
isHero && "lg:hidden"
|
|
85
|
+
),
|
|
86
|
+
children: [
|
|
87
|
+
isUnscheduled && /* @__PURE__ */ jsx("span", { className: "font-mono text-[11.5px] text-muted-foreground tabular-nums lg:text-xs", children: time }),
|
|
88
|
+
/* @__PURE__ */ jsx(Separator, { className: "flex-1" }),
|
|
89
|
+
countLabel && /* @__PURE__ */ jsx("span", { className: "text-[10.5px] text-muted-foreground/70 lg:text-[11px]", children: countLabel })
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
),
|
|
93
|
+
/* @__PURE__ */ jsx(
|
|
94
|
+
"div",
|
|
95
|
+
{
|
|
96
|
+
className: cn(
|
|
97
|
+
"flex min-w-0 flex-col",
|
|
98
|
+
isCards && "gap-4 pb-2 lg:grid lg:grid-cols-2 lg:gap-5 lg:pb-0 lg:pt-3.5 xl:grid-cols-3",
|
|
99
|
+
isCards && isHero && "lg:flex lg:pt-0",
|
|
100
|
+
isUnscheduled && isCards && "pt-3.5"
|
|
101
|
+
),
|
|
102
|
+
children: isCards ? items : items.map((child, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
103
|
+
index > 0 && /* @__PURE__ */ jsx(Separator, {}),
|
|
104
|
+
child
|
|
105
|
+
] }, index))
|
|
106
|
+
}
|
|
107
|
+
),
|
|
108
|
+
overflowItems.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 pb-2 lg:gap-0 lg:pb-0 lg:pt-2", children: overflowItems.map((child, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
109
|
+
index > 0 && /* @__PURE__ */ jsx(Separator, { className: "hidden lg:block" }),
|
|
110
|
+
child
|
|
111
|
+
] }, index)) }),
|
|
112
|
+
note && /* @__PURE__ */ jsx("p", { className: "pt-[9px] text-[11.5px] text-muted-foreground", children: note })
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
function TimelineHourSkeleton({ cardCount = 2, className }) {
|
|
118
|
+
return /* @__PURE__ */ jsxs(
|
|
119
|
+
"div",
|
|
120
|
+
{
|
|
121
|
+
"aria-hidden": "true",
|
|
122
|
+
className: cn("relative flex flex-col pl-[70px] pt-2.5 lg:col-start-3 lg:pl-0 lg:pt-[22px]", className),
|
|
123
|
+
children: [
|
|
124
|
+
/* @__PURE__ */ jsx(
|
|
125
|
+
Skeleton,
|
|
126
|
+
{
|
|
127
|
+
className: cn(
|
|
128
|
+
"absolute left-0 top-2.5 h-6 rounded-[7px]",
|
|
129
|
+
TIMELINE_MOBILE_GUTTER_CLASS,
|
|
130
|
+
"lg:left-[calc(var(--timeline-spine)*-0.5)] lg:h-[26px] lg:w-14 lg:-translate-x-1/2 lg:-translate-y-1/2",
|
|
131
|
+
HEADING_CENTRE_LG
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
/* @__PURE__ */ jsx(
|
|
136
|
+
Separator,
|
|
137
|
+
{
|
|
138
|
+
orientation: "vertical",
|
|
139
|
+
className: "absolute -bottom-2.5 left-[29px] top-10 h-auto -translate-x-1/2 lg:hidden"
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
/* @__PURE__ */ jsxs("div", { className: "hidden h-4 items-center gap-2.5 lg:flex", children: [
|
|
143
|
+
/* @__PURE__ */ jsx(Separator, { className: "flex-1" }),
|
|
144
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-12" })
|
|
145
|
+
] }),
|
|
146
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 pb-2 lg:grid lg:grid-cols-2 lg:gap-5 lg:pb-0 lg:pt-3.5 xl:grid-cols-3", children: Array.from({ length: cardCount }, (_, index) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
147
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "aspect-[4/3] w-full rounded-xl" }),
|
|
148
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-4/5" }),
|
|
149
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-1/2" })
|
|
150
|
+
] }, index)) })
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export { TimelineHour, TimelineHourSkeleton };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { ConceptCompareRail } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
export { ConceptCompareRail } from '../chunk-EQYB4Q77.js';
|
|
2
|
+
import '../chunk-5CPBSNWQ.js';
|
|
3
3
|
import '../chunk-SWD6CJ35.js';
|
|
4
4
|
import '../chunk-FEK5XGZW.js';
|
|
5
5
|
import '../chunk-MMUBH76A.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Separator } from '../chunk-NWZGSLPU.js';
|
|
2
|
-
import { ConceptCompareRail } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
2
|
+
import { ConceptCompareRail } from '../chunk-EQYB4Q77.js';
|
|
3
|
+
import '../chunk-5CPBSNWQ.js';
|
|
4
4
|
import { PhotoGround, PHOTO_GROUND } from '../chunk-SWD6CJ35.js';
|
|
5
5
|
import { Skeleton } from '../chunk-XBBEX4SF.js';
|
|
6
6
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
@@ -37,8 +37,22 @@ type EventCardProps = {
|
|
|
37
37
|
* `Coverflow`) — it crops less than `3/4` and is not the same as it.
|
|
38
38
|
*/
|
|
39
39
|
posterAspect?: "4/3" | "3/4" | "4/5";
|
|
40
|
-
/**
|
|
41
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Larger title — the featured/highlight slot. Never a clamp: the title
|
|
42
|
+
* wraps in full either way. `"lg"` applies it from the `lg` breakpoint
|
|
43
|
+
* only: the timeline's day hero is an ordinary card in the phone column and
|
|
44
|
+
* the lane's feature poster on desktop, one node.
|
|
45
|
+
*/
|
|
46
|
+
emphasis?: boolean | "lg";
|
|
47
|
+
/**
|
|
48
|
+
* `card` (default) at every width. `row-lg`: the card below `lg`, and from
|
|
49
|
+
* `lg` the compact row `EventCompactRow` draws — a 64px portrait poster
|
|
50
|
+
* beside the text, overlay pills off, the fee as a chip on the tags row.
|
|
51
|
+
* The timeline demotes an hour's later events to rows on desktop only, and
|
|
52
|
+
* a server render cannot swap components per viewport; this is the one
|
|
53
|
+
* node that paints both.
|
|
54
|
+
*/
|
|
55
|
+
density?: "card" | "row-lg";
|
|
42
56
|
/** Top-left overlay pill (the design's "Busy" hype marker). Include its icon. */
|
|
43
57
|
badge?: React.ReactNode;
|
|
44
58
|
/** Bottom-left overlay pill naming the category. Include its icon. */
|
|
@@ -59,8 +73,12 @@ type EventCardProps = {
|
|
|
59
73
|
* locale, and "is this live" depends on the app's clock, not the DS's.
|
|
60
74
|
*/
|
|
61
75
|
liveStatus?: string;
|
|
62
|
-
/**
|
|
63
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Hide the day/time line — the timeline supplies its own hour heading.
|
|
78
|
+
* `"below-lg"` hides it on the phone only: the desktop lane's hero sits
|
|
79
|
+
* beside whatever hour is passing and has to carry its own start time.
|
|
80
|
+
*/
|
|
81
|
+
hideWhen?: boolean | "below-lg";
|
|
64
82
|
/**
|
|
65
83
|
* Already over — dims the poster, mutes the title and shows the `endedLabel`
|
|
66
84
|
* chip. Never row-level opacity, which composites the text below AA. Same
|
|
@@ -20,6 +20,7 @@ var EventCard = memo(function EventCard2({
|
|
|
20
20
|
formatters,
|
|
21
21
|
posterAspect = "4/3",
|
|
22
22
|
emphasis,
|
|
23
|
+
density = "card",
|
|
23
24
|
badge,
|
|
24
25
|
tagLabel,
|
|
25
26
|
tags,
|
|
@@ -39,7 +40,8 @@ var EventCard = memo(function EventCard2({
|
|
|
39
40
|
var _a;
|
|
40
41
|
const [imgError, setImgError] = useState(false);
|
|
41
42
|
const showEnded = isEnded && !!endedLabel;
|
|
42
|
-
const time = hideWhen ? "" : formatters.time(event.starts_at);
|
|
43
|
+
const time = hideWhen === true ? "" : formatters.time(event.starts_at);
|
|
44
|
+
const isRowLg = density === "row-lg";
|
|
43
45
|
const fee = resolveEventEntryFee(event);
|
|
44
46
|
const showPoster = !!event.poster_url && !imgError;
|
|
45
47
|
const venue = (_a = event.place_name) != null ? _a : event.location;
|
|
@@ -50,7 +52,9 @@ var EventCard = memo(function EventCard2({
|
|
|
50
52
|
className: cn(
|
|
51
53
|
"relative overflow-hidden rounded-xl bg-muted",
|
|
52
54
|
isEnded && "opacity-45",
|
|
53
|
-
posterAspect === "3/4" ? "aspect-[3/4]" : posterAspect === "4/5" ? "aspect-[4/5]" : "aspect-[4/3]"
|
|
55
|
+
posterAspect === "3/4" ? "aspect-[3/4]" : posterAspect === "4/5" ? "aspect-[4/5]" : "aspect-[4/3]",
|
|
56
|
+
// The compact row's poster from `lg`: 64px, portrait, tighter radius.
|
|
57
|
+
isRowLg && "lg:aspect-[4/5] lg:w-16 lg:shrink-0 lg:rounded-[10px]"
|
|
54
58
|
),
|
|
55
59
|
children: [
|
|
56
60
|
showPoster ? (
|
|
@@ -68,62 +72,103 @@ var EventCard = memo(function EventCard2({
|
|
|
68
72
|
}
|
|
69
73
|
)
|
|
70
74
|
) : fallback,
|
|
71
|
-
/* @__PURE__ */ jsxs(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
),
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
75
|
+
/* @__PURE__ */ jsxs(
|
|
76
|
+
"div",
|
|
77
|
+
{
|
|
78
|
+
className: cn(
|
|
79
|
+
"absolute inset-x-2 top-2 flex items-start justify-between gap-2",
|
|
80
|
+
isRowLg && "lg:hidden"
|
|
81
|
+
),
|
|
82
|
+
children: [
|
|
83
|
+
badge ? /* @__PURE__ */ jsx("span", { className: cn(PILL_BASE, "bg-black/55 text-white"), children: badge }) : /* @__PURE__ */ jsx("span", {}),
|
|
84
|
+
fee.kind === "free" && /* @__PURE__ */ jsxs(
|
|
85
|
+
"span",
|
|
86
|
+
{
|
|
87
|
+
className: cn(
|
|
88
|
+
PILL_BASE,
|
|
89
|
+
"bg-success font-bold text-success-foreground"
|
|
90
|
+
),
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ jsx(Gift, { className: "h-3 w-3", "aria-hidden": true }),
|
|
93
|
+
labels.free
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
),
|
|
100
|
+
tagLabel && /* @__PURE__ */ jsx(
|
|
101
|
+
"div",
|
|
102
|
+
{
|
|
103
|
+
className: cn(
|
|
104
|
+
"absolute inset-x-2 bottom-2 flex gap-1",
|
|
105
|
+
isRowLg && "lg:hidden"
|
|
106
|
+
),
|
|
107
|
+
children: /* @__PURE__ */ jsx("span", { className: cn(PILL_BASE, "bg-black/55 text-white"), children: tagLabel })
|
|
108
|
+
}
|
|
109
|
+
)
|
|
88
110
|
]
|
|
89
111
|
}
|
|
90
112
|
),
|
|
91
|
-
/* @__PURE__ */
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 flex-col", isRowLg && "lg:flex-1"), children: [
|
|
114
|
+
/* @__PURE__ */ jsx(
|
|
115
|
+
"h3",
|
|
116
|
+
{
|
|
117
|
+
className: cn(
|
|
118
|
+
"mt-2.5 leading-[1.35]",
|
|
119
|
+
emphasis === true ? "text-lg font-bold tracking-[-0.02em]" : "text-sm font-semibold",
|
|
120
|
+
emphasis === "lg" && "lg:text-lg lg:font-bold lg:tracking-[-0.02em]",
|
|
121
|
+
isRowLg && "lg:mt-0 lg:text-[13.5px]",
|
|
122
|
+
isEnded && "text-muted-foreground"
|
|
123
|
+
),
|
|
124
|
+
children: event.title
|
|
125
|
+
}
|
|
126
|
+
),
|
|
127
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex min-w-0 items-center gap-1 text-xs font-medium text-foreground/85", children: [
|
|
128
|
+
/* @__PURE__ */ jsx(MapPin, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
|
|
129
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: venue })
|
|
130
|
+
] }),
|
|
131
|
+
hideWhen !== true && /* @__PURE__ */ jsxs(
|
|
132
|
+
"div",
|
|
133
|
+
{
|
|
134
|
+
className: cn(
|
|
135
|
+
"mt-[3px] flex items-center gap-1.5 text-xs text-muted-foreground",
|
|
136
|
+
hideWhen === "below-lg" && "hidden lg:flex"
|
|
137
|
+
),
|
|
138
|
+
children: [
|
|
139
|
+
/* @__PURE__ */ jsx("span", { children: dayLabel != null ? dayLabel : formatters.day(event.starts_at) }),
|
|
140
|
+
time && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
141
|
+
/* @__PURE__ */ jsx("span", { className: "text-border", "aria-hidden": true, children: "\xB7" }),
|
|
142
|
+
/* @__PURE__ */ jsx("span", { children: time })
|
|
143
|
+
] }),
|
|
144
|
+
showPrice && fee.kind === "paid" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
145
|
+
/* @__PURE__ */ jsx("span", { className: "text-border", "aria-hidden": true, children: "\xB7" }),
|
|
146
|
+
/* @__PURE__ */ jsx("span", { children: formatters.price(fee.amountRon) })
|
|
147
|
+
] })
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
),
|
|
151
|
+
(tags && tags.length > 0 || isRowLg && fee.kind === "free") && /* @__PURE__ */ jsxs(TagGroup, { className: "mt-1.5", children: [
|
|
152
|
+
tags == null ? void 0 : tags.map((tag) => /* @__PURE__ */ jsx(Tag, { size: "sm", children: tag }, tag)),
|
|
153
|
+
isRowLg && fee.kind === "free" && /* @__PURE__ */ jsxs(Tag, { size: "sm", variant: "success", className: "hidden font-bold lg:inline-flex", children: [
|
|
154
|
+
/* @__PURE__ */ jsx(Gift, { className: "h-3 w-3", "aria-hidden": true }),
|
|
155
|
+
labels.free
|
|
156
|
+
] })
|
|
157
|
+
] }),
|
|
158
|
+
liveStatus && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5 text-xs font-bold text-success", children: [
|
|
159
|
+
/* @__PURE__ */ jsx(Radio, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
|
|
160
|
+
liveStatus
|
|
111
161
|
] }),
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
/* @__PURE__ */ jsx("span", { children: formatters.price(fee.amountRon) })
|
|
115
|
-
] })
|
|
116
|
-
] }),
|
|
117
|
-
tags && tags.length > 0 && /* @__PURE__ */ jsx(TagGroup, { className: "mt-1.5", children: tags.map((tag) => /* @__PURE__ */ jsx(Tag, { size: "sm", children: tag }, tag)) }),
|
|
118
|
-
liveStatus && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5 text-xs font-bold text-success", children: [
|
|
119
|
-
/* @__PURE__ */ jsx(Radio, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
|
|
120
|
-
liveStatus
|
|
121
|
-
] }),
|
|
122
|
-
showEnded && /* @__PURE__ */ jsx("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx(Tag, { size: "sm", variant: "default", className: "font-extrabold", children: endedLabel }) })
|
|
162
|
+
showEnded && /* @__PURE__ */ jsx("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx(Tag, { size: "sm", variant: "default", className: "font-extrabold", children: endedLabel }) })
|
|
163
|
+
] })
|
|
123
164
|
] });
|
|
124
165
|
const rootClasses = cn(
|
|
125
166
|
"flex min-w-0 flex-col text-left",
|
|
167
|
+
// The compact row from `lg`: poster beside text, the row's own padding
|
|
168
|
+
// and negative gutter so the hover wash bleeds like `EventCompactRow`'s.
|
|
169
|
+
isRowLg && "lg:-mx-2.5 lg:flex-row lg:items-start lg:gap-[11px] lg:rounded-lg lg:px-2.5 lg:py-2",
|
|
126
170
|
(href || onClick) && "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-xl",
|
|
171
|
+
(href || onClick) && isRowLg && "lg:hover:bg-foreground/5",
|
|
127
172
|
className
|
|
128
173
|
);
|
|
129
174
|
if (href) {
|
|
@@ -37,10 +37,12 @@ type EventDayHeaderProps = {
|
|
|
37
37
|
*/
|
|
38
38
|
action?: React.ReactNode;
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* `sm`: the phone scale (30px day number, 15px weekday, 11.5px meta).
|
|
41
|
+
* `default`: the desktop scale (58 / 18 / 12.5). `responsive`: `sm` below
|
|
42
|
+
* `lg` and `default` from it, in one node — for a server render that
|
|
43
|
+
* cannot know the viewport.
|
|
42
44
|
*/
|
|
43
|
-
size?: "sm" | "default";
|
|
45
|
+
size?: "sm" | "default" | "responsive";
|
|
44
46
|
href?: string;
|
|
45
47
|
linkComponent?: React.ComponentType<EventDayHeaderLinkProps>;
|
|
46
48
|
onClick?: () => void;
|
|
@@ -21,6 +21,7 @@ function EventDayHeader({
|
|
|
21
21
|
}) {
|
|
22
22
|
const isInteractive = !!href || !!onClick;
|
|
23
23
|
const large = size === "default";
|
|
24
|
+
const responsive = size === "responsive";
|
|
24
25
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
25
26
|
/* @__PURE__ */ jsx(
|
|
26
27
|
"div",
|
|
@@ -29,16 +30,21 @@ function EventDayHeader({
|
|
|
29
30
|
"font-black leading-[0.82] tracking-[-0.05em] tabular-nums",
|
|
30
31
|
// `sm` is the phone scale: 30px, the design's app day head. 40px
|
|
31
32
|
// was a page-scale number that took a third of a 390px row.
|
|
32
|
-
large ? "text-[58px]" : "text-[30px] leading-[0.86]"
|
|
33
|
+
large ? "text-[58px]" : "text-[30px] leading-[0.86]",
|
|
34
|
+
responsive && "lg:text-[58px] lg:leading-[0.82]"
|
|
33
35
|
),
|
|
34
36
|
children: dayNumber
|
|
35
37
|
}
|
|
36
38
|
),
|
|
37
|
-
/* @__PURE__ */ jsxs("div", { className: large ? "pb-1" : "pb-0.5", children: [
|
|
39
|
+
/* @__PURE__ */ jsxs("div", { className: cn(large ? "pb-1" : "pb-0.5", responsive && "lg:pb-1"), children: [
|
|
38
40
|
/* @__PURE__ */ jsx(
|
|
39
41
|
"div",
|
|
40
42
|
{
|
|
41
|
-
className: cn(
|
|
43
|
+
className: cn(
|
|
44
|
+
"font-extrabold tracking-[-0.015em]",
|
|
45
|
+
large ? "text-lg" : "text-[15px]",
|
|
46
|
+
responsive && "lg:text-lg"
|
|
47
|
+
),
|
|
42
48
|
children: weekday
|
|
43
49
|
}
|
|
44
50
|
),
|
|
@@ -47,7 +53,8 @@ function EventDayHeader({
|
|
|
47
53
|
{
|
|
48
54
|
className: cn(
|
|
49
55
|
"mt-0.5 text-muted-foreground",
|
|
50
|
-
large ? "whitespace-nowrap text-[12.5px]" : "text-[11.5px]"
|
|
56
|
+
large ? "whitespace-nowrap text-[12.5px]" : "text-[11.5px]",
|
|
57
|
+
responsive && "lg:whitespace-nowrap lg:text-[12.5px]"
|
|
51
58
|
),
|
|
52
59
|
children: meta
|
|
53
60
|
}
|
|
@@ -67,6 +74,7 @@ function EventDayHeader({
|
|
|
67
74
|
className: cn(
|
|
68
75
|
"relative flex w-full items-end gap-3 pb-3 pt-[18px]",
|
|
69
76
|
large && "gap-[18px] pb-4",
|
|
77
|
+
responsive && "lg:gap-[18px] lg:pb-4",
|
|
70
78
|
className
|
|
71
79
|
),
|
|
72
80
|
children: [
|
|
@@ -42,14 +42,24 @@ type EventHubHeroProps = {
|
|
|
42
42
|
statsLabel?: string;
|
|
43
43
|
/** The right-column slot — the poster stack in the source design. */
|
|
44
44
|
aside?: React.ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* The hub's tonight state strip. The figures say scale; this says what is
|
|
47
|
+
* on right now, and it is the one thing on the first screen a reader can
|
|
48
|
+
* tap into the timeline. On a phone it follows the aside — title, figures,
|
|
49
|
+
* posters, then the one line that says what is on — and from `lg` it is a
|
|
50
|
+
* content-width row under both columns.
|
|
51
|
+
*/
|
|
52
|
+
footer?: React.ReactNode;
|
|
45
53
|
className?: string;
|
|
46
54
|
};
|
|
47
|
-
declare function EventHubHero({ eyebrow, title, intro, stats, statsLabel, aside, className, }: EventHubHeroProps): react_jsx_runtime.JSX.Element;
|
|
55
|
+
declare function EventHubHero({ eyebrow, title, intro, stats, statsLabel, aside, footer, className, }: EventHubHeroProps): react_jsx_runtime.JSX.Element;
|
|
48
56
|
type EventHubHeroSkeletonProps = {
|
|
49
57
|
/** The right-column slot, e.g. a `PosterStack`-shaped placeholder. Mirrors `aside` on the real component. */
|
|
50
58
|
aside?: React.ReactNode;
|
|
59
|
+
/** Reserves the `footer` row — the tonight strip's 52px. */
|
|
60
|
+
footer?: boolean;
|
|
51
61
|
className?: string;
|
|
52
62
|
};
|
|
53
|
-
declare function EventHubHeroSkeleton({ aside, className }: EventHubHeroSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
63
|
+
declare function EventHubHeroSkeleton({ aside, footer, className }: EventHubHeroSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
54
64
|
|
|
55
65
|
export { EventHubHero, type EventHubHeroProps, EventHubHeroSkeleton, type EventHubHeroSkeletonProps, type EventHubHeroStat };
|