@bearmenu/ui 0.8.6 → 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/button.d.ts +1 -1
- package/dist/components/card.d.ts +2 -2
- package/dist/components/category-deck.js +10 -1
- package/dist/components/command.d.ts +15 -15
- package/dist/components/coverflow.d.ts +11 -3
- package/dist/components/coverflow.js +34 -51
- 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 +68 -35
- package/dist/components/event-compact-row.d.ts +34 -6
- package/dist/components/event-compact-row.js +120 -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/event-types.d.ts +5 -1
- 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/item.d.ts +2 -2
- 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/spinner.d.ts +2 -2
- package/dist/components/tag.d.ts +2 -2
- package/dist/components/text.d.ts +3 -3
- 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.test.tsx +11 -0
- package/src/components/event-card.tsx +67 -14
- package/src/components/event-compact-row.stories.tsx +30 -0
- package/src/components/event-compact-row.test.tsx +100 -0
- package/src/components/event-compact-row.tsx +166 -40
- 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/event-types.ts +5 -1
- 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
|
@@ -3,7 +3,15 @@ import { cn } from '../chunk-FEK5XGZW.js';
|
|
|
3
3
|
import '../chunk-3GWWZKX7.js';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
|
-
function EventHubHero({
|
|
6
|
+
function EventHubHero({
|
|
7
|
+
eyebrow,
|
|
8
|
+
title,
|
|
9
|
+
intro,
|
|
10
|
+
stats,
|
|
11
|
+
statsLabel,
|
|
12
|
+
aside,
|
|
13
|
+
className
|
|
14
|
+
}) {
|
|
7
15
|
return /* @__PURE__ */ jsxs(
|
|
8
16
|
"div",
|
|
9
17
|
{
|
|
@@ -12,14 +20,69 @@ function EventHubHero({ eyebrow, title, intro, stats, aside, className }) {
|
|
|
12
20
|
className
|
|
13
21
|
),
|
|
14
22
|
children: [
|
|
15
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
16
|
-
/* @__PURE__ */ jsx(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 lg:gap-4", children: [
|
|
24
|
+
/* @__PURE__ */ jsx(
|
|
25
|
+
"p",
|
|
26
|
+
{
|
|
27
|
+
className: cn(
|
|
28
|
+
"order-2 text-[13px] text-muted-foreground",
|
|
29
|
+
"lg:order-none lg:text-[11.5px] lg:font-extrabold lg:tracking-[0.12em]"
|
|
30
|
+
),
|
|
31
|
+
children: eyebrow
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
/* @__PURE__ */ jsx(
|
|
35
|
+
"h1",
|
|
36
|
+
{
|
|
37
|
+
className: cn(
|
|
38
|
+
"order-1 text-[26px] font-black leading-[1.1] tracking-[-0.035em] text-foreground",
|
|
39
|
+
"lg:order-none lg:text-[42px] lg:leading-[1.05] lg:tracking-[-0.04em]"
|
|
40
|
+
),
|
|
41
|
+
children: title
|
|
42
|
+
}
|
|
43
|
+
),
|
|
44
|
+
/* @__PURE__ */ jsx("p", { className: "hidden max-w-[520px] text-[15px] leading-[1.65] text-muted-foreground lg:order-none lg:block", children: intro }),
|
|
45
|
+
/* @__PURE__ */ jsx(
|
|
46
|
+
"div",
|
|
47
|
+
{
|
|
48
|
+
role: statsLabel ? "region" : void 0,
|
|
49
|
+
"aria-label": statsLabel,
|
|
50
|
+
tabIndex: statsLabel ? 0 : void 0,
|
|
51
|
+
className: cn(
|
|
52
|
+
"order-3 -mx-4 flex gap-2 overflow-x-auto px-4 pt-2 scrollbar-hide",
|
|
53
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
54
|
+
"lg:order-none lg:mx-0 lg:gap-[30px] lg:overflow-visible lg:px-0 lg:pt-1.5"
|
|
55
|
+
),
|
|
56
|
+
children: stats.map((stat) => {
|
|
57
|
+
const isLive = stat.tone === "live";
|
|
58
|
+
return /* @__PURE__ */ jsxs(
|
|
59
|
+
"div",
|
|
60
|
+
{
|
|
61
|
+
className: cn(
|
|
62
|
+
"flex min-w-[106px] shrink-0 flex-col rounded-[14px] border bg-card px-[13px] py-2.5",
|
|
63
|
+
isLive ? "border-success/40" : "border-border",
|
|
64
|
+
"lg:min-w-0 lg:rounded-none lg:border-0 lg:bg-transparent lg:p-0"
|
|
65
|
+
),
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ jsx(
|
|
68
|
+
"span",
|
|
69
|
+
{
|
|
70
|
+
className: cn(
|
|
71
|
+
"text-[19px] font-black leading-none tracking-[-0.02em] tabular-nums",
|
|
72
|
+
isLive ? "text-success" : "text-foreground",
|
|
73
|
+
"lg:text-[30px] lg:tracking-[-0.03em]"
|
|
74
|
+
),
|
|
75
|
+
children: stat.value
|
|
76
|
+
}
|
|
77
|
+
),
|
|
78
|
+
/* @__PURE__ */ jsx("span", { className: "mt-0.5 text-[11px] text-muted-foreground lg:mt-[5px] lg:text-[12.5px]", children: stat.label })
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
stat.label
|
|
82
|
+
);
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
)
|
|
23
86
|
] }),
|
|
24
87
|
aside && /* @__PURE__ */ jsx("div", { className: "min-w-0", children: aside })
|
|
25
88
|
]
|
|
@@ -36,17 +99,24 @@ function EventHubHeroSkeleton({ aside, className }) {
|
|
|
36
99
|
className
|
|
37
100
|
),
|
|
38
101
|
children: [
|
|
39
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
40
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-[11.5px] w-28" }),
|
|
41
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-[
|
|
42
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
43
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-[
|
|
44
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-[
|
|
102
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 lg:gap-4", children: [
|
|
103
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "order-2 h-[13px] w-40 lg:order-none lg:h-[11.5px] lg:w-28" }),
|
|
104
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "order-1 h-[26px] w-full max-w-[420px] lg:order-none lg:h-[42px]" }),
|
|
105
|
+
/* @__PURE__ */ jsxs("div", { className: "hidden max-w-[520px] flex-col gap-1.5 lg:flex", children: [
|
|
106
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[15px] w-full" }),
|
|
107
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[15px] w-4/5" })
|
|
45
108
|
] }),
|
|
46
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
109
|
+
/* @__PURE__ */ jsx("div", { className: "order-3 -mx-4 flex gap-2 overflow-hidden px-4 pt-2 lg:order-none lg:mx-0 lg:gap-[30px] lg:px-0 lg:pt-1.5", children: Array.from({ length: 4 }, (_, index) => /* @__PURE__ */ jsxs(
|
|
110
|
+
"div",
|
|
111
|
+
{
|
|
112
|
+
className: "flex min-w-[106px] shrink-0 flex-col rounded-[14px] border border-border bg-card px-[13px] py-2.5 lg:min-w-0 lg:rounded-none lg:border-0 lg:bg-transparent lg:p-0",
|
|
113
|
+
children: [
|
|
114
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[19px] w-8 lg:h-[30px] lg:w-10" }),
|
|
115
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "mt-0.5 h-[11px] w-16 lg:mt-[5px] lg:h-[12.5px]" })
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
index
|
|
119
|
+
)) })
|
|
50
120
|
] }),
|
|
51
121
|
aside && /* @__PURE__ */ jsx("div", { className: "min-w-0", children: aside })
|
|
52
122
|
]
|
|
@@ -21,11 +21,17 @@ import { EventPreview, EventListRowLabels, EventDateBadgeFormatters } from './ev
|
|
|
21
21
|
* has the width for one and its row root is a container rather than a single
|
|
22
22
|
* anchor. If a CTA comes back here, it has to be a real one, not a span.
|
|
23
23
|
*
|
|
24
|
-
* NOTE ON WEIGHT:
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
24
|
+
* NOTE ON WEIGHT: the title and the fee are the only bold things in this row.
|
|
25
|
+
* Eight of these stack per screen, and at that density hierarchy comes from
|
|
26
|
+
* size and ink tier as much as weight — so everything below the title line is
|
|
27
|
+
* regular, muted, and small. The fee is bold because it is the row's one
|
|
28
|
+
* inducement, and it sits on the TITLE line, right-aligned, where a price is
|
|
29
|
+
* read against the thing it buys rather than lost among the meta.
|
|
30
|
+
*
|
|
31
|
+
* NOTE ON THE DATE BADGE: `hideDate` drops it. Inside a dated group — the list
|
|
32
|
+
* view's "Today · Monday 7 September" separators — every row's badge repeats
|
|
33
|
+
* the heading eight times per screen; the heading carries the date and the
|
|
34
|
+
* rows carry the time. The badge stays available for undated lists.
|
|
29
35
|
*
|
|
30
36
|
* Same contract as the rest: DS-owned view model, injected labels and
|
|
31
37
|
* formatters, plain `<img>`, anchor whenever `href` is given.
|
|
@@ -67,16 +73,23 @@ type EventListRowProps = {
|
|
|
67
73
|
* line. Same prop and same reason as `EventListRowWide` and `EventIndexRow`.
|
|
68
74
|
*/
|
|
69
75
|
hideRule?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Drops the leading date badge. Pass it when the rows sit under a dated
|
|
78
|
+
* heading that already names the day; the row then leads with its poster.
|
|
79
|
+
*/
|
|
80
|
+
hideDate?: boolean;
|
|
70
81
|
};
|
|
71
82
|
declare const EventListRow: React$1.NamedExoticComponent<EventListRowProps>;
|
|
72
83
|
type EventListRowSkeletonProps = {
|
|
73
84
|
/** Matches `EventListRowProps["hideRule"]` — drop the top rule on the first row of a day group. */
|
|
74
85
|
hideRule?: boolean;
|
|
86
|
+
/** Matches `EventListRowProps["hideDate"]`. */
|
|
87
|
+
hideDate?: boolean;
|
|
75
88
|
/** Reserve the chip line. Matches the real row, where it collapses on events with no live status and no tags. */
|
|
76
89
|
showTags?: boolean;
|
|
77
90
|
className?: string;
|
|
78
91
|
};
|
|
79
92
|
/** Mirrors `<EventListRow>`'s geometry exactly so nothing shifts when data lands. */
|
|
80
|
-
declare function EventListRowSkeleton({ hideRule, showTags, className, }: EventListRowSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
93
|
+
declare function EventListRowSkeleton({ hideRule, hideDate, showTags, className, }: EventListRowSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
81
94
|
|
|
82
95
|
export { EventListRow, type EventListRowLinkProps, type EventListRowProps, EventListRowSkeleton, type EventListRowSkeletonProps };
|
|
@@ -27,7 +27,8 @@ var EventListRow = memo(function EventListRow2({
|
|
|
27
27
|
priority,
|
|
28
28
|
tags,
|
|
29
29
|
fallback = /* @__PURE__ */ jsx(EventPosterFallback, {}),
|
|
30
|
-
hideRule
|
|
30
|
+
hideRule,
|
|
31
|
+
hideDate
|
|
31
32
|
}) {
|
|
32
33
|
var _a;
|
|
33
34
|
const [imgError, setImgError] = useState(false);
|
|
@@ -37,10 +38,13 @@ var EventListRow = memo(function EventListRow2({
|
|
|
37
38
|
const priceText = fee.kind === "free" ? labels.free : fee.kind === "paid" ? formatters.price(fee.amountRon) : void 0;
|
|
38
39
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39
40
|
!hideRule && /* @__PURE__ */ jsx(Separator, { className: "absolute inset-x-0 top-0" }),
|
|
40
|
-
/* @__PURE__ */ jsxs(
|
|
41
|
+
!hideDate && /* @__PURE__ */ jsxs(
|
|
41
42
|
"div",
|
|
42
43
|
{
|
|
43
|
-
className: cn(
|
|
44
|
+
className: cn(
|
|
45
|
+
"w-[42px] shrink-0 rounded-[9px] py-1.5 text-center",
|
|
46
|
+
isLive && "bg-success/10"
|
|
47
|
+
),
|
|
44
48
|
children: [
|
|
45
49
|
/* @__PURE__ */ jsx(
|
|
46
50
|
"div",
|
|
@@ -65,7 +69,7 @@ var EventListRow = memo(function EventListRow2({
|
|
|
65
69
|
]
|
|
66
70
|
}
|
|
67
71
|
),
|
|
68
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-
|
|
72
|
+
/* @__PURE__ */ jsx("div", { className: "aspect-[4/5] w-[58px] shrink-0 overflow-hidden rounded-[10px] bg-muted", children: showPoster ? (
|
|
69
73
|
// eslint-disable-next-line @next/next/no-img-element
|
|
70
74
|
/* @__PURE__ */ jsx(
|
|
71
75
|
"img",
|
|
@@ -80,38 +84,64 @@ var EventListRow = memo(function EventListRow2({
|
|
|
80
84
|
)
|
|
81
85
|
) : fallback }),
|
|
82
86
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
-
|
|
85
|
-
/* @__PURE__ */ jsx(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2.5", children: [
|
|
88
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 text-[14px] font-bold leading-[1.3] tracking-[-0.01em]", children: event.title }),
|
|
89
|
+
isSoldOut ? /* @__PURE__ */ jsx(
|
|
90
|
+
Tag,
|
|
91
|
+
{
|
|
92
|
+
size: "sm",
|
|
93
|
+
variant: "quiet",
|
|
94
|
+
className: "shrink-0 whitespace-nowrap",
|
|
95
|
+
children: labels.soldOut
|
|
96
|
+
}
|
|
97
|
+
) : priceText && /* @__PURE__ */ jsx(
|
|
91
98
|
"span",
|
|
92
99
|
{
|
|
93
100
|
className: cn(
|
|
94
|
-
"shrink-0 tabular-nums",
|
|
95
|
-
fee.kind === "free"
|
|
101
|
+
"shrink-0 text-[13.5px] font-extrabold tabular-nums",
|
|
102
|
+
fee.kind === "free" ? "text-success" : "text-foreground"
|
|
96
103
|
),
|
|
97
104
|
children: priceText
|
|
98
105
|
}
|
|
99
106
|
)
|
|
100
107
|
] }),
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5 text-[11.5px] text-muted-foreground", children: [
|
|
109
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 font-mono tabular-nums", children: formatters.time(event.starts_at) }),
|
|
110
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-border", children: "\xB7" }),
|
|
111
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1", children: [
|
|
112
|
+
/* @__PURE__ */ jsx(MapPin, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
|
|
113
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: venue })
|
|
105
114
|
] }),
|
|
106
|
-
|
|
107
|
-
|
|
115
|
+
isLive && /* @__PURE__ */ jsxs(
|
|
116
|
+
Tag,
|
|
117
|
+
{
|
|
118
|
+
size: "sm",
|
|
119
|
+
variant: "success",
|
|
120
|
+
className: "shrink-0 whitespace-nowrap font-extrabold",
|
|
121
|
+
children: [
|
|
122
|
+
/* @__PURE__ */ jsx(Radio, { className: "h-2.5 w-2.5", "aria-hidden": true }),
|
|
123
|
+
labels.liveNow
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
] }),
|
|
128
|
+
tags && tags.length > 0 && /* @__PURE__ */ jsx(TagGroup, { className: "mt-1.5 h-[22px] overflow-hidden", children: tags.map((tag) => /* @__PURE__ */ jsx(
|
|
129
|
+
Tag,
|
|
130
|
+
{
|
|
131
|
+
size: "sm",
|
|
132
|
+
variant: "quiet",
|
|
133
|
+
className: "shrink-0 whitespace-nowrap",
|
|
134
|
+
children: tag
|
|
135
|
+
},
|
|
136
|
+
tag
|
|
137
|
+
)) })
|
|
108
138
|
] })
|
|
109
139
|
] });
|
|
110
140
|
const rootClasses = cn(
|
|
111
|
-
// `py-
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
"relative flex w-full items-start gap-3 py-
|
|
141
|
+
// `py-[11px]`: the poster is 72px tall and a one-line title, meta and a
|
|
142
|
+
// chip line come to ~70px, so the row is poster-driven at ~94px — about
|
|
143
|
+
// eight per screen, which is the list view's reason to exist.
|
|
144
|
+
"relative flex w-full items-start gap-3 py-[11px] text-left",
|
|
115
145
|
isSoldOut && "opacity-60",
|
|
116
146
|
(href || onClick) && "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
117
147
|
className
|
|
@@ -128,12 +158,21 @@ var EventListRow = memo(function EventListRow2({
|
|
|
128
158
|
);
|
|
129
159
|
}
|
|
130
160
|
if (onClick) {
|
|
131
|
-
return /* @__PURE__ */ jsx(
|
|
161
|
+
return /* @__PURE__ */ jsx(
|
|
162
|
+
"button",
|
|
163
|
+
{
|
|
164
|
+
type: "button",
|
|
165
|
+
className: rootClasses,
|
|
166
|
+
onClick: (e) => onClick(event, e),
|
|
167
|
+
children: body
|
|
168
|
+
}
|
|
169
|
+
);
|
|
132
170
|
}
|
|
133
171
|
return /* @__PURE__ */ jsx("div", { className: rootClasses, children: body });
|
|
134
172
|
});
|
|
135
173
|
function EventListRowSkeleton({
|
|
136
174
|
hideRule,
|
|
175
|
+
hideDate,
|
|
137
176
|
showTags = true,
|
|
138
177
|
className
|
|
139
178
|
}) {
|
|
@@ -141,24 +180,29 @@ function EventListRowSkeleton({
|
|
|
141
180
|
"div",
|
|
142
181
|
{
|
|
143
182
|
"aria-hidden": "true",
|
|
144
|
-
className: cn(
|
|
183
|
+
className: cn(
|
|
184
|
+
"relative flex w-full items-start gap-3 py-[11px] text-left",
|
|
185
|
+
className
|
|
186
|
+
),
|
|
145
187
|
children: [
|
|
146
188
|
!hideRule && /* @__PURE__ */ jsx(Separator, { className: "absolute inset-x-0 top-0" }),
|
|
147
|
-
/* @__PURE__ */ jsxs("div", { className: "w-[42px] shrink-0 rounded-[9px] py-1.5 text-center", children: [
|
|
189
|
+
!hideDate && /* @__PURE__ */ jsxs("div", { className: "w-[42px] shrink-0 rounded-[9px] py-1.5 text-center", children: [
|
|
148
190
|
/* @__PURE__ */ jsx(Skeleton, { className: "mx-auto h-4 w-5" }),
|
|
149
191
|
/* @__PURE__ */ jsx(Skeleton, { className: "mx-auto mt-[3px] h-[10px] w-6" })
|
|
150
192
|
] }),
|
|
151
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "aspect-
|
|
193
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "aspect-[4/5] w-[58px] shrink-0 rounded-[10px]" }),
|
|
152
194
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
153
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
154
|
-
/* @__PURE__ */
|
|
155
|
-
|
|
195
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2.5", children: [
|
|
196
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
|
|
197
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[14px] w-full" }),
|
|
198
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[14px] w-2/3" })
|
|
199
|
+
] }),
|
|
200
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[13.5px] w-12 shrink-0" })
|
|
156
201
|
] }),
|
|
157
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-
|
|
202
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-1.5", children: [
|
|
158
203
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-10" }),
|
|
159
204
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-3 shrink-0 rounded-full" }),
|
|
160
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
|
|
161
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "ml-auto h-3 w-12" })
|
|
205
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" })
|
|
162
206
|
] }),
|
|
163
207
|
showTags && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 flex items-center gap-1.5", children: [
|
|
164
208
|
/* @__PURE__ */ jsx(Skeleton, { className: "h-[22px] w-14 rounded-full" }),
|
|
@@ -71,7 +71,11 @@ declare function resolveEventEntryFee(event: EventPreview): EventEntryFee;
|
|
|
71
71
|
* locale and no currency of its own.
|
|
72
72
|
*/
|
|
73
73
|
type EventFormatters = {
|
|
74
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* e.g. `"20:00"`. Return `""` when the event's hour is not known: the card
|
|
76
|
+
* and the compact row then print the day (or the venue) ALONE, with no
|
|
77
|
+
* separator — never a placeholder word and never "00:00".
|
|
78
|
+
*/
|
|
75
79
|
time: (isoDateTime: string) => string;
|
|
76
80
|
/** e.g. `"Sat, Sep 5"` — used when a card appears outside its own day section. */
|
|
77
81
|
day: (isoDateTime: string) => string;
|
|
@@ -4,65 +4,63 @@ import * as React from 'react';
|
|
|
4
4
|
/**
|
|
5
5
|
* HourBand — one hour on the timeline's axis, with that hour's events beside it.
|
|
6
6
|
*
|
|
7
|
-
* The
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* timestamp, which is why `EventCard` has
|
|
7
|
+
* The mobile timeline is an app list, not a page: a 58px gutter carrying a
|
|
8
|
+
* filled hour chip with a hairline dropping from beneath it, and the hour's
|
|
9
|
+
* rows to the right, separated by hairlines of their own. The rows carry no
|
|
10
|
+
* timestamp — this band IS the timestamp, which is why `EventCard` has
|
|
11
|
+
* `hideWhen` and `EventCompactRow` has `hideTime`.
|
|
11
12
|
*
|
|
12
|
-
* The
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* Sharing the object changes this gutter's pixels: the mobile puck now carries
|
|
18
|
-
* a border, which is what makes it read as clipped onto the rail rather than
|
|
19
|
-
* text floating over it, and matches the station on the desktop spine.
|
|
13
|
+
* The chip is the shared `TimelineHourPuck` in its `chip` variant, so the
|
|
14
|
+
* desktop spine's station and this gutter's label are one object with two
|
|
15
|
+
* looks rather than two objects that drift. The hairline starts BELOW the chip
|
|
16
|
+
* rather than running behind it: a chip is a label at the top of its hour, a
|
|
17
|
+
* station is a tick on a continuous rail, and the two read differently.
|
|
20
18
|
*
|
|
21
|
-
* `isLive`
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* `isLive` tints the chip and the hairline with `--success`; the live label is
|
|
20
|
+
* kept for screen readers (the chip variant hides it visually). The playhead —
|
|
21
|
+
* the exact current time — is a separate `TimelinePlayhead` rendered between
|
|
22
|
+
* bands by the caller, because an hour spans sixty minutes and "now" is one of
|
|
23
|
+
* them.
|
|
24
24
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* with the rows beside it.
|
|
33
|
-
*
|
|
34
|
-
* 24px leaves ~12px of real clearance at the widest label. Do not tighten it
|
|
35
|
-
* back without re-deriving against a 12-hour locale: a 24-hour one ("09:00")
|
|
36
|
-
* is ~30px narrower and hides the problem completely.
|
|
25
|
+
* ROWS ARE SEPARATED HERE, NOT IN THE ROW. `EventCompactRow` deliberately
|
|
26
|
+
* draws no divider (its container does — see its docblock), so this band wraps
|
|
27
|
+
* each child and rules between them. The wrapper, not the child, carries the
|
|
28
|
+
* rule, so the row's own negative-margin hover wash is untouched. Children are
|
|
29
|
+
* read with `Children.toArray`, which drops `null`/`false` so a conditional
|
|
30
|
+
* first row never inherits a rule meant for a second; pass rows as siblings,
|
|
31
|
+
* not inside a fragment — a fragment is one child and gets one wrapper.
|
|
37
32
|
*/
|
|
38
33
|
type HourBandProps = {
|
|
39
34
|
/** The hour, already formatted and localised — "20:00". */
|
|
40
35
|
time: string;
|
|
41
36
|
/** Marks this as the hour currently in progress. */
|
|
42
37
|
isLive?: boolean;
|
|
43
|
-
/**
|
|
38
|
+
/** Screen-reader text for the live hour, e.g. "Now on". Required to render it. */
|
|
44
39
|
liveLabel?: string;
|
|
45
|
-
/** The hour's events. */
|
|
40
|
+
/** The hour's events. Each direct child is one row or card. */
|
|
46
41
|
children: React.ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* `rows` (default): compact rows, ruled between with a Separator. `cards`:
|
|
44
|
+
* poster cards, stacked with a 16px gap and no rules — a card is its own
|
|
45
|
+
* frame, and a hairline between two posters reads as a third object.
|
|
46
|
+
*/
|
|
47
|
+
layout?: "rows" | "cards";
|
|
47
48
|
className?: string;
|
|
48
49
|
};
|
|
49
|
-
declare function HourBand({ time, isLive, liveLabel, children, className }: HourBandProps): react_jsx_runtime.JSX.Element;
|
|
50
|
+
declare function HourBand({ time, isLive, liveLabel, children, layout, className, }: HourBandProps): react_jsx_runtime.JSX.Element;
|
|
50
51
|
type HourBandSkeletonProps = {
|
|
51
|
-
/**
|
|
52
|
+
/** Rows to reserve space for. */
|
|
52
53
|
cardCount?: number;
|
|
53
54
|
className?: string;
|
|
54
55
|
};
|
|
55
56
|
/**
|
|
56
|
-
* The mobile timeline's loading state, mirroring `HourBand` exactly — same
|
|
57
|
-
* gutter, same hairline, same
|
|
58
|
-
*
|
|
59
|
-
* The puck is omitted rather than blocked out: the hour is not known until the
|
|
60
|
-
* data arrives, and a grey lozenge on the axis reads as a real, unreadable
|
|
61
|
-
* timestamp. The hairline alone still says "this is a time axis".
|
|
57
|
+
* The mobile timeline's loading state, mirroring `HourBand` exactly — same
|
|
58
|
+
* gutter, same hairline, same row rhythm — so nothing jumps when data lands.
|
|
62
59
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
60
|
+
* The chip is blocked out at its real size rather than omitted: it is a fixed
|
|
61
|
+
* 58x24 lozenge, so a grey one reads as "a time goes here" without inventing
|
|
62
|
+
* a time. Row footprints mirror `EventCompactRowSkeleton`.
|
|
65
63
|
*/
|
|
66
|
-
declare function HourBandSkeleton({ cardCount, className }: HourBandSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
64
|
+
declare function HourBandSkeleton({ cardCount, className, }: HourBandSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
67
65
|
|
|
68
66
|
export { HourBand, type HourBandProps, HourBandSkeleton, type HourBandSkeletonProps };
|
|
@@ -1,52 +1,80 @@
|
|
|
1
|
-
import { TimelineHourPuck } from '../chunk-
|
|
1
|
+
import { TimelineHourPuck, TIMELINE_MOBILE_GUTTER_CLASS } from '../chunk-3TNPSN4D.js';
|
|
2
2
|
import { Separator } from '../chunk-WSRWFA6K.js';
|
|
3
3
|
import { Skeleton } from '../chunk-QXHMPJ35.js';
|
|
4
4
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
5
5
|
import '../chunk-3GWWZKX7.js';
|
|
6
|
+
import * as React from 'react';
|
|
6
7
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
8
|
|
|
8
|
-
function HourBand({
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
function HourBand({
|
|
10
|
+
time,
|
|
11
|
+
isLive,
|
|
12
|
+
liveLabel,
|
|
13
|
+
children,
|
|
14
|
+
layout = "rows",
|
|
15
|
+
className
|
|
16
|
+
}) {
|
|
17
|
+
const isCards = layout === "cards";
|
|
18
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex gap-3 pt-2.5", className), children: [
|
|
19
|
+
/* @__PURE__ */ jsxs("div", { className: cn("relative shrink-0", TIMELINE_MOBILE_GUTTER_CLASS), children: [
|
|
13
20
|
/* @__PURE__ */ jsx(
|
|
14
21
|
TimelineHourPuck,
|
|
15
22
|
{
|
|
16
23
|
time,
|
|
17
24
|
isLive,
|
|
18
25
|
liveLabel,
|
|
19
|
-
|
|
26
|
+
variant: "chip"
|
|
27
|
+
}
|
|
28
|
+
),
|
|
29
|
+
/* @__PURE__ */ jsx(
|
|
30
|
+
Separator,
|
|
31
|
+
{
|
|
32
|
+
orientation: "vertical",
|
|
33
|
+
className: cn(
|
|
34
|
+
"absolute bottom-[-10px] left-1/2 top-[30px] h-auto -translate-x-1/2",
|
|
35
|
+
isLive && "bg-success/30"
|
|
36
|
+
)
|
|
20
37
|
}
|
|
21
38
|
)
|
|
22
39
|
] }),
|
|
23
40
|
/* @__PURE__ */ jsx(
|
|
24
41
|
"div",
|
|
25
42
|
{
|
|
26
|
-
className: cn(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
className: cn("flex min-w-0 flex-1 flex-col", isCards && "gap-4 pb-2"),
|
|
44
|
+
children: React.Children.toArray(children).map((child, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
45
|
+
!isCards && index > 0 && /* @__PURE__ */ jsx(Separator, {}),
|
|
46
|
+
child
|
|
47
|
+
] }, index))
|
|
31
48
|
}
|
|
32
49
|
)
|
|
33
50
|
] });
|
|
34
51
|
}
|
|
35
|
-
function HourBandSkeleton({
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
function HourBandSkeleton({
|
|
53
|
+
cardCount = 2,
|
|
54
|
+
className
|
|
55
|
+
}) {
|
|
56
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex gap-3 pt-2.5", className), "aria-hidden": "true", children: [
|
|
57
|
+
/* @__PURE__ */ jsxs("div", { className: cn("relative shrink-0", TIMELINE_MOBILE_GUTTER_CLASS), children: [
|
|
58
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-[58px] rounded-[7px]" }),
|
|
59
|
+
/* @__PURE__ */ jsx(
|
|
60
|
+
Separator,
|
|
61
|
+
{
|
|
62
|
+
orientation: "vertical",
|
|
63
|
+
className: "absolute bottom-[-10px] left-1/2 top-[30px] h-auto -translate-x-1/2"
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
] }),
|
|
67
|
+
/* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 flex-col", children: Array.from({ length: cardCount }).map((_, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
68
|
+
index > 0 && /* @__PURE__ */ jsx(Separator, {}),
|
|
69
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 py-[11px]", children: [
|
|
70
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "aspect-[4/5] w-16 shrink-0 rounded-[10px]" }),
|
|
71
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
72
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-[14px] w-3/4" }),
|
|
73
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "mt-1.5 h-[11.5px] w-1/2" }),
|
|
74
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "mt-2 h-[22px] w-16 rounded-full" })
|
|
75
|
+
] })
|
|
76
|
+
] })
|
|
77
|
+
] }, index)) })
|
|
50
78
|
] });
|
|
51
79
|
}
|
|
52
80
|
|
|
@@ -3,12 +3,12 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const itemVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "
|
|
6
|
+
variant?: "default" | "outline" | "muted" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
interactive?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
declare const Item: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
11
|
-
variant?: "default" | "
|
|
11
|
+
variant?: "default" | "outline" | "muted" | null | undefined;
|
|
12
12
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
13
13
|
interactive?: boolean | null | undefined;
|
|
14
14
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DriftRail } from '../chunk-
|
|
1
|
+
import { DriftRail } from '../chunk-AHL45DD2.js';
|
|
2
2
|
import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
|
|
3
3
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
4
4
|
import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
|