@bearmenu/ui 0.8.51 → 0.8.53
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-GIJGVFGC.js +177 -0
- package/dist/chunk-H4ORZT2D.js +14 -0
- package/dist/chunk-RKNPPYRU.js +86 -0
- package/dist/{chunk-S5GDARLW.js → chunk-WY2FP76J.js} +28 -5
- package/dist/components/category-deck.d.ts +6 -1
- package/dist/components/category-deck.js +39 -35
- package/dist/components/event-card.d.ts +7 -0
- package/dist/components/event-card.js +9 -0
- package/dist/components/event-compact-row.d.ts +6 -0
- package/dist/components/event-compact-row.js +5 -3
- package/dist/components/event-hub-hero.d.ts +5 -0
- package/dist/components/event-hub-hero.js +14 -3
- package/dist/components/event-list-row-wide.d.ts +6 -0
- package/dist/components/event-list-row-wide.js +5 -3
- package/dist/components/event-tonight-strip.d.ts +3 -1
- package/dist/components/event-tonight-strip.js +3 -2
- package/dist/components/facet-group.d.ts +9 -2
- package/dist/components/facet-group.js +108 -10
- package/dist/components/featured-rail-item.d.ts +3 -1
- package/dist/components/featured-rail-item.js +3 -1
- package/dist/components/filter-option-chip.d.ts +15 -0
- package/dist/components/filter-option-chip.js +3 -0
- package/dist/components/filter-option-group.d.ts +37 -0
- package/dist/components/filter-option-group.js +10 -0
- package/dist/components/filter-panel-footer.d.ts +15 -0
- package/dist/components/filter-panel-footer.js +63 -0
- package/dist/components/kitchen-dossier.d.ts +7 -1
- package/dist/components/kitchen-dossier.js +2 -1
- package/dist/components/menu-hub-hero.d.ts +7 -1
- package/dist/components/menu-hub-hero.js +2 -0
- package/dist/components/place-card.d.ts +7 -0
- package/dist/components/place-card.js +11 -3
- package/dist/components/poster-stack.d.ts +2 -0
- package/dist/components/poster-stack.js +2 -1
- package/dist/components/section-header.d.ts +6 -1
- package/dist/components/section-header.js +4 -2
- package/dist/components/timeline-day.js +1 -1
- package/dist/components/timeline-hour.d.ts +13 -1
- package/dist/components/timeline-hour.js +1 -1
- package/package.json +6 -6
- package/src/components/category-deck.tsx +11 -0
- package/src/components/event-card.test.tsx +6 -0
- package/src/components/event-card.tsx +17 -0
- package/src/components/event-compact-row.tsx +34 -24
- package/src/components/event-hub-hero.tsx +15 -1
- package/src/components/event-list-row-wide.tsx +25 -15
- package/src/components/event-tonight-strip.test.tsx +12 -0
- package/src/components/event-tonight-strip.tsx +8 -1
- package/src/components/facet-group.tsx +153 -54
- package/src/components/featured-rail-item.tsx +5 -0
- package/src/components/filter-option-chip.test.tsx +50 -0
- package/src/components/filter-option-chip.tsx +81 -0
- package/src/components/filter-option-group.stories.tsx +250 -0
- package/src/components/filter-option-group.test.tsx +100 -0
- package/src/components/filter-option-group.tsx +231 -0
- package/src/components/filter-panel-footer.tsx +63 -0
- package/src/components/kitchen-dossier.tsx +14 -1
- package/src/components/menu-hub-hero.tsx +13 -0
- package/src/components/place-card.stories.tsx +10 -0
- package/src/components/place-card.test.tsx +31 -0
- package/src/components/place-card.tsx +22 -6
- package/src/components/poster-stack.tsx +3 -0
- package/src/components/section-header.tsx +8 -1
- package/src/components/timeline-day.stories.tsx +30 -0
- package/src/components/timeline-day.test.tsx +24 -0
- package/src/components/timeline-hour.tsx +40 -6
- package/src/lib/poster-overlay-frame.tsx +26 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { FilterOptionChip } from './chunk-RKNPPYRU.js';
|
|
2
|
+
import { Separator } from './chunk-NWZGSLPU.js';
|
|
3
|
+
import { Button } from './chunk-GHKTVHQG.js';
|
|
4
|
+
import { Text } from './chunk-ZLMRVBD7.js';
|
|
5
|
+
import { Badge } from './chunk-RYPPN2GZ.js';
|
|
6
|
+
import { cn } from './chunk-FEK5XGZW.js';
|
|
7
|
+
import { useId, useState } from 'react';
|
|
8
|
+
import { ChevronDown } from 'lucide-react';
|
|
9
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
10
|
+
|
|
11
|
+
function FilterOptionGroup({
|
|
12
|
+
title,
|
|
13
|
+
options,
|
|
14
|
+
value,
|
|
15
|
+
onValueChange,
|
|
16
|
+
selection = "multiple",
|
|
17
|
+
name,
|
|
18
|
+
defaultOpen = false,
|
|
19
|
+
collapsible = true,
|
|
20
|
+
visibleLimit = 6,
|
|
21
|
+
showAllLabel,
|
|
22
|
+
showLessLabel,
|
|
23
|
+
children,
|
|
24
|
+
footer,
|
|
25
|
+
clearLabel,
|
|
26
|
+
onClear,
|
|
27
|
+
summaryValues = value,
|
|
28
|
+
className,
|
|
29
|
+
divider = true,
|
|
30
|
+
disabled
|
|
31
|
+
}) {
|
|
32
|
+
const id = useId();
|
|
33
|
+
const [isOpen, setOpen] = useState(defaultOpen);
|
|
34
|
+
const open = !collapsible || isOpen;
|
|
35
|
+
const [expanded, setExpanded] = useState([]);
|
|
36
|
+
const selected = options.filter(
|
|
37
|
+
(option) => summaryValues.includes(option.value)
|
|
38
|
+
);
|
|
39
|
+
const sections = [];
|
|
40
|
+
for (const option of options) {
|
|
41
|
+
const last = sections[sections.length - 1];
|
|
42
|
+
if (!last || last.label !== option.section)
|
|
43
|
+
sections.push({ label: option.section, options: [option] });
|
|
44
|
+
else last.options.push(option);
|
|
45
|
+
}
|
|
46
|
+
const heading = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
47
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
48
|
+
/* @__PURE__ */ jsx(
|
|
49
|
+
Text,
|
|
50
|
+
{
|
|
51
|
+
as: "span",
|
|
52
|
+
id: `${id}-title`,
|
|
53
|
+
className: "block",
|
|
54
|
+
variant: "body-sm",
|
|
55
|
+
weight: "semibold",
|
|
56
|
+
children: title
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
!open && selected.length > 0 && /* @__PURE__ */ jsx(
|
|
60
|
+
Text,
|
|
61
|
+
{
|
|
62
|
+
as: "span",
|
|
63
|
+
variant: "caption",
|
|
64
|
+
color: "muted",
|
|
65
|
+
className: "mt-1 block leading-relaxed [overflow-wrap:anywhere]",
|
|
66
|
+
children: selected.map((option) => option.label).join(" \xB7 ")
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
] }),
|
|
70
|
+
selected.length > 0 && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "tabular-nums", children: selected.length }),
|
|
71
|
+
collapsible && /* @__PURE__ */ jsx(
|
|
72
|
+
ChevronDown,
|
|
73
|
+
{
|
|
74
|
+
"aria-hidden": true,
|
|
75
|
+
className: cn(
|
|
76
|
+
"size-4 shrink-0 text-muted-foreground transition-transform motion-reduce:transition-none",
|
|
77
|
+
open && "rotate-180"
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
] });
|
|
82
|
+
return /* @__PURE__ */ jsxs("section", { className: cn("min-w-0", className), children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("div", { className: "py-2", children: [
|
|
84
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
85
|
+
collapsible ? /* @__PURE__ */ jsx(
|
|
86
|
+
"button",
|
|
87
|
+
{
|
|
88
|
+
type: "button",
|
|
89
|
+
onClick: () => setOpen((previous) => !previous),
|
|
90
|
+
"aria-expanded": open,
|
|
91
|
+
"aria-controls": id,
|
|
92
|
+
className: "flex min-h-11 min-w-0 flex-1 items-center gap-3 rounded-lg py-2 text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
|
|
93
|
+
children: heading
|
|
94
|
+
}
|
|
95
|
+
) : /* @__PURE__ */ jsx("div", { className: "flex min-h-11 min-w-0 flex-1 items-center gap-3 py-2", children: heading }),
|
|
96
|
+
onClear && clearLabel && summaryValues.length > 0 && /* @__PURE__ */ jsx(
|
|
97
|
+
Button,
|
|
98
|
+
{
|
|
99
|
+
type: "button",
|
|
100
|
+
variant: "ghost",
|
|
101
|
+
className: "min-h-11 shrink-0 px-2 text-xs",
|
|
102
|
+
onClick: onClear,
|
|
103
|
+
children: clearLabel
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
] }),
|
|
107
|
+
/* @__PURE__ */ jsxs("div", { id, hidden: !open, children: [
|
|
108
|
+
children,
|
|
109
|
+
sections.map((section, index) => {
|
|
110
|
+
var _a;
|
|
111
|
+
const sectionId = `${id}-section-${index}`;
|
|
112
|
+
const key = (_a = section.label) != null ? _a : "";
|
|
113
|
+
const isExpanded = expanded.includes(key);
|
|
114
|
+
const limit = showAllLabel ? visibleLimit : Infinity;
|
|
115
|
+
const visible = isExpanded ? section.options : section.options.filter(
|
|
116
|
+
(option, i) => i < limit || value.includes(option.value)
|
|
117
|
+
);
|
|
118
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
119
|
+
section.label && /* @__PURE__ */ jsx(
|
|
120
|
+
Text,
|
|
121
|
+
{
|
|
122
|
+
as: "h4",
|
|
123
|
+
id: sectionId,
|
|
124
|
+
variant: "caption",
|
|
125
|
+
weight: "semibold",
|
|
126
|
+
color: "muted",
|
|
127
|
+
className: "mt-3 mb-1",
|
|
128
|
+
children: section.label
|
|
129
|
+
}
|
|
130
|
+
),
|
|
131
|
+
/* @__PURE__ */ jsx(
|
|
132
|
+
"fieldset",
|
|
133
|
+
{
|
|
134
|
+
"aria-labelledby": `${id}-title${section.label ? ` ${sectionId}` : ""}`,
|
|
135
|
+
disabled,
|
|
136
|
+
className: "m-0 flex min-w-0 flex-wrap gap-2 border-0 px-0 pt-2 pb-3",
|
|
137
|
+
children: visible.map((option) => /* @__PURE__ */ jsx(
|
|
138
|
+
FilterOptionChip,
|
|
139
|
+
{
|
|
140
|
+
label: option.label,
|
|
141
|
+
count: option.count,
|
|
142
|
+
icon: option.icon,
|
|
143
|
+
type: selection === "single" ? "radio" : "checkbox",
|
|
144
|
+
name: selection === "single" ? name != null ? name : id : void 0,
|
|
145
|
+
value: option.value,
|
|
146
|
+
checked: value.includes(option.value),
|
|
147
|
+
onChange: (event) => onValueChange(
|
|
148
|
+
selection === "single" ? [option.value] : event.target.checked ? [...value, option.value] : value.filter((item) => item !== option.value)
|
|
149
|
+
)
|
|
150
|
+
},
|
|
151
|
+
option.value
|
|
152
|
+
))
|
|
153
|
+
}
|
|
154
|
+
),
|
|
155
|
+
section.options.length > limit && /* @__PURE__ */ jsx(
|
|
156
|
+
Button,
|
|
157
|
+
{
|
|
158
|
+
type: "button",
|
|
159
|
+
variant: "link",
|
|
160
|
+
"aria-expanded": isExpanded,
|
|
161
|
+
onClick: () => setExpanded(
|
|
162
|
+
(previous) => isExpanded ? previous.filter((item) => item !== key) : [...previous, key]
|
|
163
|
+
),
|
|
164
|
+
className: "mb-1 min-h-11 px-0",
|
|
165
|
+
children: isExpanded ? showLessLabel : typeof showAllLabel === "function" ? showAllLabel(section.options.length) : showAllLabel
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
] }, key);
|
|
169
|
+
}),
|
|
170
|
+
footer
|
|
171
|
+
] })
|
|
172
|
+
] }),
|
|
173
|
+
divider && /* @__PURE__ */ jsx(Separator, {})
|
|
174
|
+
] });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export { FilterOptionGroup };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
function PosterOverlayFrame({
|
|
4
|
+
overlay,
|
|
5
|
+
children
|
|
6
|
+
}) {
|
|
7
|
+
if (!overlay) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
8
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative shrink-0", children: [
|
|
9
|
+
children,
|
|
10
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-[1]", "aria-hidden": "true", children: overlay })
|
|
11
|
+
] });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { PosterOverlayFrame };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { cn } from './chunk-FEK5XGZW.js';
|
|
2
|
+
import { __objRest, __spreadProps, __spreadValues } from './chunk-MMUBH76A.js';
|
|
3
|
+
import { useId } from 'react';
|
|
4
|
+
import { Check } from 'lucide-react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function FilterOptionChip(_a) {
|
|
8
|
+
var _b = _a, {
|
|
9
|
+
label,
|
|
10
|
+
type = "checkbox",
|
|
11
|
+
count,
|
|
12
|
+
icon,
|
|
13
|
+
className,
|
|
14
|
+
id,
|
|
15
|
+
disabled
|
|
16
|
+
} = _b, input = __objRest(_b, [
|
|
17
|
+
"label",
|
|
18
|
+
"type",
|
|
19
|
+
"count",
|
|
20
|
+
"icon",
|
|
21
|
+
"className",
|
|
22
|
+
"id",
|
|
23
|
+
"disabled"
|
|
24
|
+
]);
|
|
25
|
+
var _a2;
|
|
26
|
+
const generatedId = useId();
|
|
27
|
+
const inputId = id != null ? id : generatedId;
|
|
28
|
+
return /* @__PURE__ */ jsxs(
|
|
29
|
+
"label",
|
|
30
|
+
{
|
|
31
|
+
htmlFor: inputId,
|
|
32
|
+
className: cn(
|
|
33
|
+
"relative inline-flex max-w-full min-w-0",
|
|
34
|
+
disabled && "cursor-not-allowed opacity-50",
|
|
35
|
+
className
|
|
36
|
+
),
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ jsx(
|
|
39
|
+
"input",
|
|
40
|
+
__spreadProps(__spreadValues({}, input), {
|
|
41
|
+
id: inputId,
|
|
42
|
+
type,
|
|
43
|
+
disabled,
|
|
44
|
+
"aria-label": (_a2 = input["aria-label"]) != null ? _a2 : label,
|
|
45
|
+
className: "peer sr-only"
|
|
46
|
+
})
|
|
47
|
+
),
|
|
48
|
+
/* @__PURE__ */ jsxs(
|
|
49
|
+
"span",
|
|
50
|
+
{
|
|
51
|
+
className: cn(
|
|
52
|
+
"flex min-h-11 min-w-0 max-w-full cursor-pointer items-center gap-2 rounded-2xl border border-border bg-background px-3 py-2 text-sm text-foreground",
|
|
53
|
+
"transition-colors hover:bg-muted motion-reduce:transition-none",
|
|
54
|
+
"peer-checked:border-primary peer-checked:bg-primary/10 peer-checked:shadow-[inset_0_0_0_1px_var(--primary)] peer-checked:text-primary",
|
|
55
|
+
"peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-ring",
|
|
56
|
+
"peer-disabled:pointer-events-none peer-disabled:cursor-not-allowed",
|
|
57
|
+
"[&_.filter-check]:hidden peer-checked:[&_.filter-check]:block peer-checked:[&_.filter-icon]:hidden"
|
|
58
|
+
),
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ jsx(
|
|
61
|
+
Check,
|
|
62
|
+
{
|
|
63
|
+
"aria-hidden": true,
|
|
64
|
+
className: "filter-check size-4 shrink-0",
|
|
65
|
+
strokeWidth: 2.5
|
|
66
|
+
}
|
|
67
|
+
),
|
|
68
|
+
icon && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "filter-icon shrink-0 [&>svg]:size-4", children: icon }),
|
|
69
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 [overflow-wrap:anywhere]", children: label }),
|
|
70
|
+
count != null && /* @__PURE__ */ jsx(
|
|
71
|
+
"span",
|
|
72
|
+
{
|
|
73
|
+
"aria-hidden": true,
|
|
74
|
+
className: "shrink-0 text-xs tabular-nums text-muted-foreground",
|
|
75
|
+
children: count
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export { FilterOptionChip };
|
|
@@ -16,6 +16,7 @@ function ruleFromLg(items) {
|
|
|
16
16
|
function TimelineHour({
|
|
17
17
|
time,
|
|
18
18
|
role = "hour",
|
|
19
|
+
tone = "default",
|
|
19
20
|
isLive,
|
|
20
21
|
liveLabel,
|
|
21
22
|
countLabel,
|
|
@@ -28,6 +29,7 @@ function TimelineHour({
|
|
|
28
29
|
const isHero = role === "hero";
|
|
29
30
|
const isContinuation = role === "continuation";
|
|
30
31
|
const isUnscheduled = role === "unscheduled";
|
|
32
|
+
const isLiveGroup = isUnscheduled && tone === "live";
|
|
31
33
|
const hasStation = !isUnscheduled;
|
|
32
34
|
const isCards = layout === "cards";
|
|
33
35
|
const items = React.Children.toArray(children);
|
|
@@ -36,10 +38,12 @@ function TimelineHour({
|
|
|
36
38
|
"section",
|
|
37
39
|
{
|
|
38
40
|
"data-timeline-hour": role,
|
|
41
|
+
"data-tone": isLiveGroup ? "live" : void 0,
|
|
39
42
|
className: cn(
|
|
40
43
|
"relative flex flex-col pt-2.5",
|
|
41
44
|
// The phone gutter: the puck's column plus the 12px gap `HourBand` had.
|
|
42
|
-
|
|
45
|
+
// A live group keeps it so its cards align with the hours' cards.
|
|
46
|
+
(hasStation || isLiveGroup) && "pl-[70px] lg:pl-0",
|
|
43
47
|
"lg:pt-[22px]",
|
|
44
48
|
isHero ? cn(
|
|
45
49
|
// The lane. Placed by the grid, not by source order; `self-start`
|
|
@@ -88,12 +92,31 @@ function TimelineHour({
|
|
|
88
92
|
className: cn(
|
|
89
93
|
"items-center gap-2.5",
|
|
90
94
|
isUnscheduled ? "flex h-4" : "hidden lg:flex lg:h-4",
|
|
91
|
-
isHero && "lg:hidden"
|
|
95
|
+
isHero && "lg:hidden",
|
|
96
|
+
// The heading spans the gutter; only the cards sit inset.
|
|
97
|
+
isLiveGroup && "-ml-[70px] lg:ml-0"
|
|
92
98
|
),
|
|
93
99
|
children: [
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
isLiveGroup ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-xs font-semibold text-success", children: [
|
|
101
|
+
/* @__PURE__ */ jsx(
|
|
102
|
+
"span",
|
|
103
|
+
{
|
|
104
|
+
"aria-hidden": "true",
|
|
105
|
+
className: "size-1.5 shrink-0 animate-pulse rounded-full bg-success motion-reduce:animate-none"
|
|
106
|
+
}
|
|
107
|
+
),
|
|
108
|
+
time
|
|
109
|
+
] }) : isUnscheduled && /* @__PURE__ */ jsx("span", { className: "font-mono text-[11.5px] text-muted-foreground tabular-nums lg:text-xs", children: time }),
|
|
110
|
+
/* @__PURE__ */ jsx(Separator, { className: cn("flex-1", isLiveGroup && "bg-success/30") }),
|
|
111
|
+
countLabel && /* @__PURE__ */ jsx(
|
|
112
|
+
"span",
|
|
113
|
+
{
|
|
114
|
+
className: cn(
|
|
115
|
+
isLiveGroup ? "text-xs text-muted-foreground" : "text-[10.5px] text-muted-foreground/70 lg:text-[11px]"
|
|
116
|
+
),
|
|
117
|
+
children: countLabel
|
|
118
|
+
}
|
|
119
|
+
)
|
|
97
120
|
]
|
|
98
121
|
}
|
|
99
122
|
),
|
|
@@ -38,9 +38,14 @@ type CategoryDeckProps = {
|
|
|
38
38
|
/** Defaults to a plain `<a>`. Pass `next/link` in a Next app. */
|
|
39
39
|
linkComponent?: React.ComponentType<CategoryDeckLinkProps>;
|
|
40
40
|
onClick?: (mouseEvent: React.MouseEvent) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Decoration laid over the fan's box, unclipped (it may cross the box's
|
|
43
|
+
* edge), above the cards. Absolutely positioned, `aria-hidden`, no layout.
|
|
44
|
+
*/
|
|
45
|
+
overlay?: React.ReactNode;
|
|
41
46
|
className?: string;
|
|
42
47
|
};
|
|
43
|
-
declare function CategoryDeck({ name, meta, posters, href, linkComponent: LinkComponent, onClick, className, }: CategoryDeckProps): react_jsx_runtime.JSX.Element;
|
|
48
|
+
declare function CategoryDeck({ name, meta, posters, href, linkComponent: LinkComponent, onClick, overlay, className, }: CategoryDeckProps): react_jsx_runtime.JSX.Element;
|
|
44
49
|
type CategoryDeckSkeletonProps = {
|
|
45
50
|
className?: string;
|
|
46
51
|
};
|
|
@@ -39,6 +39,7 @@ function CategoryDeck({
|
|
|
39
39
|
href,
|
|
40
40
|
linkComponent: LinkComponent = DefaultLink,
|
|
41
41
|
onClick,
|
|
42
|
+
overlay,
|
|
42
43
|
className
|
|
43
44
|
}) {
|
|
44
45
|
const slots = Array.from(
|
|
@@ -49,41 +50,44 @@ function CategoryDeck({
|
|
|
49
50
|
}
|
|
50
51
|
);
|
|
51
52
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
52
|
-
/* @__PURE__ */
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
53
|
+
/* @__PURE__ */ jsxs("div", { className: "relative h-[150px] sm:h-[186px]", "aria-hidden": true, children: [
|
|
54
|
+
slots.map((poster, index) => {
|
|
55
|
+
var _a;
|
|
56
|
+
const transform = DECK_CARD_TRANSFORMS[index];
|
|
57
|
+
return /* @__PURE__ */ jsx(
|
|
58
|
+
"div",
|
|
59
|
+
{
|
|
60
|
+
className: cn(
|
|
61
|
+
"absolute left-1/2 top-0 aspect-[4/5] w-24 overflow-hidden rounded-[10px] bg-muted",
|
|
62
|
+
// Keyed to --foreground so the shadow is ink in light mode; in
|
|
63
|
+
// dark mode that same 18% is a light halo, so it drops to 7%.
|
|
64
|
+
"shadow-[0_10px_26px_color-mix(in_oklch,var(--foreground)_18%,transparent)]",
|
|
65
|
+
"dark:shadow-[0_10px_26px_color-mix(in_oklch,var(--foreground)_7%,transparent)]",
|
|
66
|
+
"sm:w-[120px]",
|
|
67
|
+
transform.rest,
|
|
68
|
+
transform.spread,
|
|
69
|
+
transform.z,
|
|
70
|
+
DECK_TRANSITION
|
|
71
|
+
),
|
|
72
|
+
children: poster.content ? poster.content : poster.src ? (
|
|
73
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
74
|
+
/* @__PURE__ */ jsx(
|
|
75
|
+
"img",
|
|
76
|
+
{
|
|
77
|
+
src: poster.src,
|
|
78
|
+
alt: (_a = poster.alt) != null ? _a : "",
|
|
79
|
+
loading: "lazy",
|
|
80
|
+
decoding: "async",
|
|
81
|
+
className: "h-full w-full object-cover"
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
) : /* @__PURE__ */ jsx("div", { className: "h-full w-full bg-muted" })
|
|
85
|
+
},
|
|
86
|
+
index
|
|
87
|
+
);
|
|
88
|
+
}),
|
|
89
|
+
overlay && /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute inset-0 z-[3] block", "aria-hidden": true, children: overlay })
|
|
90
|
+
] }),
|
|
87
91
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-[9px] pt-3.5", children: [
|
|
88
92
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
89
93
|
/* @__PURE__ */ jsx("div", { className: "truncate text-[14.5px] font-extrabold tracking-[-0.015em] sm:text-base", children: name }),
|
|
@@ -57,6 +57,13 @@ type EventCardProps = {
|
|
|
57
57
|
badge?: React.ReactNode;
|
|
58
58
|
/** Bottom-left overlay pill naming the category. Include its icon. */
|
|
59
59
|
tagLabel?: React.ReactNode;
|
|
60
|
+
/**
|
|
61
|
+
* Decorative overlay inside the poster box (which is `relative` and clips),
|
|
62
|
+
* for a caller's absolutely positioned ornament. Rendered after the pills,
|
|
63
|
+
* hidden on the compact row's 64px poster. Must be `aria-hidden` and
|
|
64
|
+
* pointer-transparent; it never takes layout.
|
|
65
|
+
*/
|
|
66
|
+
posterOverlay?: React.ReactNode;
|
|
60
67
|
/**
|
|
61
68
|
* Caller-supplied display labels, rendered as small chips in the text area
|
|
62
69
|
* beneath the venue/meta line. `EventPreview.tags` is taxonomy coordinates
|
|
@@ -23,6 +23,7 @@ var EventCard = memo(function EventCard2({
|
|
|
23
23
|
density = "card",
|
|
24
24
|
badge,
|
|
25
25
|
tagLabel,
|
|
26
|
+
posterOverlay,
|
|
26
27
|
tags,
|
|
27
28
|
liveStatus,
|
|
28
29
|
hideWhen,
|
|
@@ -106,6 +107,14 @@ var EventCard = memo(function EventCard2({
|
|
|
106
107
|
),
|
|
107
108
|
children: /* @__PURE__ */ jsx("span", { className: cn(PILL_BASE, "bg-black/55 text-white"), children: tagLabel })
|
|
108
109
|
}
|
|
110
|
+
),
|
|
111
|
+
posterOverlay && /* @__PURE__ */ jsx(
|
|
112
|
+
"div",
|
|
113
|
+
{
|
|
114
|
+
className: cn("pointer-events-none absolute inset-0", isRowLg && "lg:hidden"),
|
|
115
|
+
"aria-hidden": "true",
|
|
116
|
+
children: posterOverlay
|
|
117
|
+
}
|
|
109
118
|
)
|
|
110
119
|
]
|
|
111
120
|
}
|
|
@@ -87,6 +87,12 @@ type EventCompactRowProps = {
|
|
|
87
87
|
priority?: boolean;
|
|
88
88
|
/** Rendered in place of the poster when it is absent or fails to load. Defaults to `<EventPosterFallback />`. */
|
|
89
89
|
fallback?: React.ReactNode;
|
|
90
|
+
/**
|
|
91
|
+
* Decoration laid over the poster's box, unclipped (it may cross the
|
|
92
|
+
* poster's edge), above the row. Absolutely positioned, `aria-hidden`,
|
|
93
|
+
* pointer-transparent; it takes no layout.
|
|
94
|
+
*/
|
|
95
|
+
posterOverlay?: React.ReactNode;
|
|
90
96
|
};
|
|
91
97
|
declare const EventCompactRow: React$1.NamedExoticComponent<EventCompactRowProps>;
|
|
92
98
|
type EventCompactRowSkeletonProps = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TagGroup } from '../chunk-PX6RICS5.js';
|
|
2
|
+
import { PosterOverlayFrame } from '../chunk-H4ORZT2D.js';
|
|
2
3
|
import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
|
|
3
4
|
import { Tag } from '../chunk-MWB7S54O.js';
|
|
4
5
|
import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
|
|
@@ -30,7 +31,8 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
30
31
|
onClick,
|
|
31
32
|
className,
|
|
32
33
|
priority,
|
|
33
|
-
fallback = /* @__PURE__ */ jsx(EventPosterFallback, {})
|
|
34
|
+
fallback = /* @__PURE__ */ jsx(EventPosterFallback, {}),
|
|
35
|
+
posterOverlay
|
|
34
36
|
}) {
|
|
35
37
|
var _a;
|
|
36
38
|
const [imgError, setImgError] = useState(false);
|
|
@@ -43,7 +45,7 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
43
45
|
const showEnded = isEnded && !!endedLabel;
|
|
44
46
|
const separator = /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-border", children: "\xB7" });
|
|
45
47
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
46
|
-
/* @__PURE__ */ jsx(
|
|
48
|
+
/* @__PURE__ */ jsx(PosterOverlayFrame, { overlay: posterOverlay, children: /* @__PURE__ */ jsx(
|
|
47
49
|
"div",
|
|
48
50
|
{
|
|
49
51
|
className: cn(
|
|
@@ -71,7 +73,7 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
71
73
|
fallback
|
|
72
74
|
)
|
|
73
75
|
}
|
|
74
|
-
),
|
|
76
|
+
) }),
|
|
75
77
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
76
78
|
/* @__PURE__ */ jsx(
|
|
77
79
|
"div",
|
|
@@ -25,6 +25,11 @@ type EventHubHeroStat = {
|
|
|
25
25
|
label: string;
|
|
26
26
|
/** `live` marks the figure that is happening right now. */
|
|
27
27
|
tone?: "default" | "live";
|
|
28
|
+
/**
|
|
29
|
+
* Decoration beside the figure, absolutely positioned just past its right
|
|
30
|
+
* edge: no layout. Decorative and `aria-hidden`.
|
|
31
|
+
*/
|
|
32
|
+
adornment?: React.ReactNode;
|
|
28
33
|
};
|
|
29
34
|
type EventHubHeroProps = {
|
|
30
35
|
/** Small caps-style label above the title, e.g. "Updated today". */
|
|
@@ -68,15 +68,26 @@ function EventHubHero({
|
|
|
68
68
|
"lg:min-w-0 lg:rounded-none lg:border-0 lg:bg-transparent lg:p-0"
|
|
69
69
|
),
|
|
70
70
|
children: [
|
|
71
|
-
/* @__PURE__ */
|
|
71
|
+
/* @__PURE__ */ jsxs(
|
|
72
72
|
"span",
|
|
73
73
|
{
|
|
74
74
|
className: cn(
|
|
75
75
|
"text-[19px] font-black leading-none tracking-[-0.02em] tabular-nums",
|
|
76
76
|
isLive ? "text-success" : "text-foreground",
|
|
77
|
-
"lg:text-[30px] lg:tracking-[-0.03em]"
|
|
77
|
+
"lg:text-[30px] lg:tracking-[-0.03em]",
|
|
78
|
+
stat.adornment && "relative w-fit"
|
|
78
79
|
),
|
|
79
|
-
children:
|
|
80
|
+
children: [
|
|
81
|
+
stat.value,
|
|
82
|
+
stat.adornment && /* @__PURE__ */ jsx(
|
|
83
|
+
"span",
|
|
84
|
+
{
|
|
85
|
+
className: "pointer-events-none absolute left-full top-1/2 ml-1.5 -translate-y-1/2",
|
|
86
|
+
"aria-hidden": true,
|
|
87
|
+
children: stat.adornment
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
]
|
|
80
91
|
}
|
|
81
92
|
),
|
|
82
93
|
/* @__PURE__ */ jsx("span", { className: "mt-0.5 text-[11px] text-muted-foreground lg:mt-[5px] lg:text-[12.5px]", children: stat.label })
|
|
@@ -86,6 +86,12 @@ type EventListRowWideProps = {
|
|
|
86
86
|
* line. Same prop and same reason as `EventIndexRow`.
|
|
87
87
|
*/
|
|
88
88
|
hideRule?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Decoration laid over the thumbnail's box, unclipped (it may cross the
|
|
91
|
+
* thumbnail's edge). Absolutely positioned, `aria-hidden`,
|
|
92
|
+
* pointer-transparent; it takes no layout.
|
|
93
|
+
*/
|
|
94
|
+
posterOverlay?: ReactNode;
|
|
89
95
|
};
|
|
90
96
|
declare const EventListRowWide: React$1.NamedExoticComponent<EventListRowWideProps>;
|
|
91
97
|
type EventListRowWideSkeletonProps = {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PosterOverlayFrame } from '../chunk-H4ORZT2D.js';
|
|
1
2
|
import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
|
|
2
3
|
import { Tag } from '../chunk-MWB7S54O.js';
|
|
3
4
|
import { Separator } from '../chunk-NWZGSLPU.js';
|
|
@@ -30,7 +31,8 @@ var EventListRowWide = memo(function EventListRowWide2({
|
|
|
30
31
|
className,
|
|
31
32
|
priority,
|
|
32
33
|
fallback = /* @__PURE__ */ jsx(EventPosterFallback, {}),
|
|
33
|
-
hideRule
|
|
34
|
+
hideRule,
|
|
35
|
+
posterOverlay
|
|
34
36
|
}) {
|
|
35
37
|
var _a, _b;
|
|
36
38
|
const [imgError, setImgError] = useState(false);
|
|
@@ -69,7 +71,7 @@ var EventListRowWide = memo(function EventListRowWide2({
|
|
|
69
71
|
]
|
|
70
72
|
}
|
|
71
73
|
),
|
|
72
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-square w-[104px] shrink-0 overflow-hidden rounded-[10px] bg-muted", children: showPoster ? (
|
|
74
|
+
/* @__PURE__ */ jsx(PosterOverlayFrame, { overlay: posterOverlay, children: /* @__PURE__ */ jsx("div", { className: "aspect-square w-[104px] shrink-0 overflow-hidden rounded-[10px] bg-muted", children: showPoster ? (
|
|
73
75
|
// eslint-disable-next-line @next/next/no-img-element
|
|
74
76
|
/* @__PURE__ */ jsx(
|
|
75
77
|
"img",
|
|
@@ -82,7 +84,7 @@ var EventListRowWide = memo(function EventListRowWide2({
|
|
|
82
84
|
onError: () => setImgError(true)
|
|
83
85
|
}
|
|
84
86
|
)
|
|
85
|
-
) : fallback }),
|
|
87
|
+
) : fallback }) }),
|
|
86
88
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
87
89
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
88
90
|
href ? /* @__PURE__ */ jsx(
|
|
@@ -40,9 +40,11 @@ type EventTonightStripProps = {
|
|
|
40
40
|
href?: string;
|
|
41
41
|
/** Defaults to a plain `<a>`. Pass `next/link` in a Next app. */
|
|
42
42
|
linkComponent?: React.ComponentType<EventTonightStripLinkProps>;
|
|
43
|
+
/** Replaces the pulsing dot of the `live` tone, in the dot's own slot. Decorative. */
|
|
44
|
+
liveIndicator?: React.ReactNode;
|
|
43
45
|
className?: string;
|
|
44
46
|
};
|
|
45
|
-
declare function EventTonightStrip({ tone, lead, details, actionLabel, href, linkComponent: LinkComponent, className, }: EventTonightStripProps): react_jsx_runtime.JSX.Element;
|
|
47
|
+
declare function EventTonightStrip({ tone, lead, details, actionLabel, href, linkComponent: LinkComponent, liveIndicator, className, }: EventTonightStripProps): react_jsx_runtime.JSX.Element;
|
|
46
48
|
declare function EventTonightStripSkeleton({ className }: {
|
|
47
49
|
className?: string;
|
|
48
50
|
}): react_jsx_runtime.JSX.Element;
|