@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
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { Separator } from './chunk-WSRWFA6K.js';
|
|
2
2
|
import { Skeleton } from './chunk-QXHMPJ35.js';
|
|
3
3
|
import { cn } from './chunk-FEK5XGZW.js';
|
|
4
|
+
import { Radio } from 'lucide-react';
|
|
4
5
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
6
|
|
|
6
7
|
var LIVE_PUCK_PULSE_CLASS = "bm-timeline-live-puck-pulse";
|
|
7
|
-
|
|
8
|
+
var TIMELINE_MOBILE_GUTTER_CLASS = "w-[58px]";
|
|
9
|
+
function TimelineHourPuck({
|
|
10
|
+
time,
|
|
11
|
+
isLive,
|
|
12
|
+
liveLabel,
|
|
13
|
+
variant = "station",
|
|
14
|
+
className
|
|
15
|
+
}) {
|
|
16
|
+
const isChip = variant === "chip";
|
|
8
17
|
return /* @__PURE__ */ jsxs("span", { className: cn("relative flex justify-center", className), children: [
|
|
9
18
|
isLive && /* @__PURE__ */ jsx("style", { children: `
|
|
10
19
|
@keyframes ${LIVE_PUCK_PULSE_CLASS} {
|
|
@@ -18,23 +27,33 @@ function TimelineHourPuck({ time, isLive, liveLabel, className }) {
|
|
|
18
27
|
.${LIVE_PUCK_PULSE_CLASS} { animation: none; }
|
|
19
28
|
}
|
|
20
29
|
` }),
|
|
21
|
-
/* @__PURE__ */
|
|
30
|
+
/* @__PURE__ */ jsxs(
|
|
22
31
|
"span",
|
|
23
32
|
{
|
|
24
33
|
className: cn(
|
|
25
|
-
"whitespace-nowrap
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
"whitespace-nowrap font-mono tabular-nums",
|
|
35
|
+
isChip ? cn(
|
|
36
|
+
"inline-flex h-6 min-w-[58px] items-center justify-center gap-1 rounded-[7px] px-1 text-[12px] font-medium",
|
|
37
|
+
isLive ? cn("bg-success/10 text-success", LIVE_PUCK_PULSE_CLASS) : "bg-muted text-foreground"
|
|
38
|
+
) : cn(
|
|
39
|
+
"rounded-[7px] border bg-background px-[7px] py-[3px] text-[12.5px] font-medium",
|
|
40
|
+
isLive ? cn("border-success/40 text-success", LIVE_PUCK_PULSE_CLASS) : "border-border text-foreground"
|
|
41
|
+
)
|
|
28
42
|
),
|
|
29
|
-
children:
|
|
43
|
+
children: [
|
|
44
|
+
isChip && isLive && /* @__PURE__ */ jsx(Radio, { className: "h-2.5 w-2.5 shrink-0", "aria-hidden": true }),
|
|
45
|
+
time
|
|
46
|
+
]
|
|
30
47
|
}
|
|
31
48
|
),
|
|
32
49
|
isLive && !!liveLabel && /* @__PURE__ */ jsx(
|
|
33
50
|
"span",
|
|
34
51
|
{
|
|
35
52
|
className: cn(
|
|
36
|
-
|
|
37
|
-
|
|
53
|
+
isChip ? "sr-only" : cn(
|
|
54
|
+
"absolute top-[calc(100%+6px)] whitespace-nowrap bg-background px-1",
|
|
55
|
+
"text-[9.5px] font-extrabold tracking-[0.08em] text-success"
|
|
56
|
+
)
|
|
38
57
|
),
|
|
39
58
|
children: liveLabel
|
|
40
59
|
}
|
|
@@ -82,4 +101,4 @@ function TimelineBandSkeleton({ className }) {
|
|
|
82
101
|
] });
|
|
83
102
|
}
|
|
84
103
|
|
|
85
|
-
export { TimelineBand, TimelineBandSkeleton, TimelineHourPuck };
|
|
104
|
+
export { TIMELINE_MOBILE_GUTTER_CLASS, TimelineBand, TimelineBandSkeleton, TimelineHourPuck };
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { cn } from './chunk-FEK5XGZW.js';
|
|
2
|
+
import { useRef, useState, useEffect } from 'react';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var DRIFT_RAIL_DEFAULT_DURATION_SECONDS = 42;
|
|
6
|
+
var DRIFT_RAIL_RESUME_DELAY_MS = 3e3;
|
|
7
|
+
function DriftRail({
|
|
8
|
+
children,
|
|
9
|
+
reverse = false,
|
|
10
|
+
durationSeconds = DRIFT_RAIL_DEFAULT_DURATION_SECONDS,
|
|
11
|
+
pauseOnHover = true,
|
|
12
|
+
className
|
|
13
|
+
}) {
|
|
14
|
+
const scrollerRef = useRef(null);
|
|
15
|
+
const trackRef = useRef(null);
|
|
16
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
17
|
+
const [inView, setInView] = useState(true);
|
|
18
|
+
const [reducedMotion, setReducedMotion] = useState(false);
|
|
19
|
+
const heldUntil = useRef(0);
|
|
20
|
+
const mouseDrag = useRef(null);
|
|
21
|
+
const position = useRef(0);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
24
|
+
const query = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
25
|
+
setReducedMotion(query.matches);
|
|
26
|
+
const onChange = () => setReducedMotion(query.matches);
|
|
27
|
+
query.addEventListener("change", onChange);
|
|
28
|
+
return () => query.removeEventListener("change", onChange);
|
|
29
|
+
}, []);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const node = scrollerRef.current;
|
|
32
|
+
if (!node || typeof IntersectionObserver === "undefined") return void 0;
|
|
33
|
+
const observer = new IntersectionObserver(([entry]) => setInView(entry.isIntersecting), {
|
|
34
|
+
threshold: 0
|
|
35
|
+
});
|
|
36
|
+
observer.observe(node);
|
|
37
|
+
return () => observer.disconnect();
|
|
38
|
+
}, []);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const scroller = scrollerRef.current;
|
|
41
|
+
const track = trackRef.current;
|
|
42
|
+
if (!scroller || !track) return void 0;
|
|
43
|
+
let frame = 0;
|
|
44
|
+
let last = performance.now();
|
|
45
|
+
const drifting = !reducedMotion && inView && !(pauseOnHover && isHovered);
|
|
46
|
+
if (reverse && scroller.scrollLeft === 0) scroller.scrollLeft = track.scrollWidth / 2;
|
|
47
|
+
position.current = scroller.scrollLeft;
|
|
48
|
+
const tick = (now) => {
|
|
49
|
+
const half = track.scrollWidth / 2;
|
|
50
|
+
if (half > 0) {
|
|
51
|
+
const driftingNow = drifting && now >= heldUntil.current;
|
|
52
|
+
if (driftingNow) {
|
|
53
|
+
const perSecond = half / durationSeconds;
|
|
54
|
+
const delta = perSecond * (now - last) / 1e3;
|
|
55
|
+
position.current += reverse ? -delta : delta;
|
|
56
|
+
} else {
|
|
57
|
+
position.current = scroller.scrollLeft;
|
|
58
|
+
}
|
|
59
|
+
let wrapped = false;
|
|
60
|
+
if (position.current >= half) {
|
|
61
|
+
position.current -= half;
|
|
62
|
+
wrapped = true;
|
|
63
|
+
} else if (position.current < 0) {
|
|
64
|
+
position.current += half;
|
|
65
|
+
wrapped = true;
|
|
66
|
+
}
|
|
67
|
+
if (driftingNow || wrapped) scroller.scrollLeft = position.current;
|
|
68
|
+
}
|
|
69
|
+
last = now;
|
|
70
|
+
frame = requestAnimationFrame(tick);
|
|
71
|
+
};
|
|
72
|
+
frame = requestAnimationFrame(tick);
|
|
73
|
+
return () => cancelAnimationFrame(frame);
|
|
74
|
+
}, [durationSeconds, inView, isHovered, pauseOnHover, reducedMotion, reverse]);
|
|
75
|
+
const hold = () => {
|
|
76
|
+
heldUntil.current = Number.POSITIVE_INFINITY;
|
|
77
|
+
};
|
|
78
|
+
const release = () => {
|
|
79
|
+
heldUntil.current = performance.now() + DRIFT_RAIL_RESUME_DELAY_MS;
|
|
80
|
+
};
|
|
81
|
+
const onPointerDown = (event) => {
|
|
82
|
+
hold();
|
|
83
|
+
if (event.pointerType !== "mouse" || event.button !== 0 || !scrollerRef.current) return;
|
|
84
|
+
mouseDrag.current = {
|
|
85
|
+
startX: event.clientX,
|
|
86
|
+
startScroll: scrollerRef.current.scrollLeft,
|
|
87
|
+
pointerId: event.pointerId
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
const onPointerMove = (event) => {
|
|
91
|
+
var _a, _b, _c, _d;
|
|
92
|
+
const drag = mouseDrag.current;
|
|
93
|
+
if (!drag || event.pointerId !== drag.pointerId || !scrollerRef.current) return;
|
|
94
|
+
const dx = event.clientX - drag.startX;
|
|
95
|
+
if (Math.abs(dx) > 4 && !((_b = (_a = event.currentTarget).hasPointerCapture) == null ? void 0 : _b.call(_a, event.pointerId))) {
|
|
96
|
+
(_d = (_c = event.currentTarget).setPointerCapture) == null ? void 0 : _d.call(_c, event.pointerId);
|
|
97
|
+
event.currentTarget.dataset.dragging = "true";
|
|
98
|
+
}
|
|
99
|
+
scrollerRef.current.scrollLeft = drag.startScroll - dx;
|
|
100
|
+
};
|
|
101
|
+
const onPointerEnd = (event) => {
|
|
102
|
+
var _a, _b;
|
|
103
|
+
release();
|
|
104
|
+
const drag = mouseDrag.current;
|
|
105
|
+
mouseDrag.current = null;
|
|
106
|
+
if (drag && ((_b = (_a = event.currentTarget).hasPointerCapture) == null ? void 0 : _b.call(_a, event.pointerId))) {
|
|
107
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
108
|
+
}
|
|
109
|
+
delete event.currentTarget.dataset.dragging;
|
|
110
|
+
};
|
|
111
|
+
const onClickCapture = (event) => {
|
|
112
|
+
if (event.currentTarget.dataset.dragging === "true") {
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
event.stopPropagation();
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
return /* @__PURE__ */ jsx(
|
|
118
|
+
"div",
|
|
119
|
+
{
|
|
120
|
+
ref: scrollerRef,
|
|
121
|
+
onMouseEnter: () => setIsHovered(true),
|
|
122
|
+
onMouseLeave: () => setIsHovered(false),
|
|
123
|
+
onPointerDown,
|
|
124
|
+
onPointerMove,
|
|
125
|
+
onPointerUp: onPointerEnd,
|
|
126
|
+
onPointerCancel: onPointerEnd,
|
|
127
|
+
onWheel: () => {
|
|
128
|
+
release();
|
|
129
|
+
},
|
|
130
|
+
onDragStart: (event) => event.preventDefault(),
|
|
131
|
+
onClickCapture,
|
|
132
|
+
className: cn(
|
|
133
|
+
"overflow-x-auto overflow-y-hidden py-1.5 scrollbar-hide [touch-action:pan-x]",
|
|
134
|
+
"cursor-grab select-none data-[dragging=true]:cursor-grabbing",
|
|
135
|
+
className
|
|
136
|
+
),
|
|
137
|
+
children: /* @__PURE__ */ jsxs("div", { ref: trackRef, className: "flex w-max items-stretch gap-3.5", children: [
|
|
138
|
+
children,
|
|
139
|
+
/* @__PURE__ */ jsx("div", { className: "contents", "aria-hidden": "true", children })
|
|
140
|
+
] })
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export { DriftRail };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useState, useRef, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
function useDragSwipe({ threshold = 40, onSwipe, disabled }) {
|
|
4
|
+
const [dragX, setDragX] = useState(0);
|
|
5
|
+
const startX = useRef(null);
|
|
6
|
+
const pointerId = useRef(null);
|
|
7
|
+
const didDrag = useRef(false);
|
|
8
|
+
const onPointerDown = useCallback(
|
|
9
|
+
(event) => {
|
|
10
|
+
if (disabled || event.button !== 0) return;
|
|
11
|
+
startX.current = event.clientX;
|
|
12
|
+
pointerId.current = event.pointerId;
|
|
13
|
+
didDrag.current = false;
|
|
14
|
+
},
|
|
15
|
+
[disabled]
|
|
16
|
+
);
|
|
17
|
+
const onPointerMove = useCallback((event) => {
|
|
18
|
+
var _a, _b;
|
|
19
|
+
if (startX.current === null || event.pointerId !== pointerId.current) return;
|
|
20
|
+
const dx = event.clientX - startX.current;
|
|
21
|
+
if (!didDrag.current && Math.abs(dx) > 6) {
|
|
22
|
+
didDrag.current = true;
|
|
23
|
+
(_b = (_a = event.currentTarget).setPointerCapture) == null ? void 0 : _b.call(_a, event.pointerId);
|
|
24
|
+
}
|
|
25
|
+
if (didDrag.current) setDragX(dx);
|
|
26
|
+
}, []);
|
|
27
|
+
const end = useCallback(
|
|
28
|
+
(event, cancelled) => {
|
|
29
|
+
var _a, _b;
|
|
30
|
+
if (startX.current === null || event.pointerId !== pointerId.current) return;
|
|
31
|
+
const dx = event.clientX - startX.current;
|
|
32
|
+
startX.current = null;
|
|
33
|
+
pointerId.current = null;
|
|
34
|
+
if ((_b = (_a = event.currentTarget).hasPointerCapture) == null ? void 0 : _b.call(_a, event.pointerId)) {
|
|
35
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
36
|
+
}
|
|
37
|
+
setDragX(0);
|
|
38
|
+
if (!cancelled && didDrag.current && Math.abs(dx) >= threshold) {
|
|
39
|
+
onSwipe(dx < 0 ? 1 : -1);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
[onSwipe, threshold]
|
|
43
|
+
);
|
|
44
|
+
const onPointerUp = useCallback((event) => end(event, false), [end]);
|
|
45
|
+
const onPointerCancel = useCallback(
|
|
46
|
+
(event) => end(event, true),
|
|
47
|
+
[end]
|
|
48
|
+
);
|
|
49
|
+
const onDragStart = useCallback((event) => {
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
}, []);
|
|
52
|
+
const onClickCapture = useCallback((event) => {
|
|
53
|
+
if (didDrag.current) {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
didDrag.current = false;
|
|
57
|
+
}
|
|
58
|
+
}, []);
|
|
59
|
+
return {
|
|
60
|
+
dragX,
|
|
61
|
+
isDragging: dragX !== 0,
|
|
62
|
+
handlers: { onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onClickCapture, onDragStart }
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { useDragSwipe };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
|
|
3
|
+
function useMediaQuery(query) {
|
|
4
|
+
return useSyncExternalStore(
|
|
5
|
+
(onChange) => {
|
|
6
|
+
if (typeof window.matchMedia !== "function") return () => {
|
|
7
|
+
};
|
|
8
|
+
const mql = window.matchMedia(query);
|
|
9
|
+
mql.addEventListener("change", onChange);
|
|
10
|
+
return () => mql.removeEventListener("change", onChange);
|
|
11
|
+
},
|
|
12
|
+
() => typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false,
|
|
13
|
+
() => false
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
var DESKTOP_MEDIA_QUERY = "(min-width: 1024px)";
|
|
17
|
+
|
|
18
|
+
export { DESKTOP_MEDIA_QUERY, useMediaQuery };
|
|
@@ -3,10 +3,10 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const alertVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "success" | "warning" | "default" | "destructive" | null | undefined;
|
|
7
7
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
8
8
|
declare const Alert: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
9
|
-
variant?: "
|
|
9
|
+
variant?: "success" | "warning" | "default" | "destructive" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLDivElement>>;
|
|
11
11
|
declare const AlertTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLParagraphElement>>;
|
|
12
12
|
declare const AlertDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
|
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const badgeVariants: (props?: ({
|
|
7
|
-
variant?: "
|
|
7
|
+
variant?: "success" | "warning" | "default" | "destructive" | "outline" | "secondary" | "glass" | "overlay" | "brown" | null | undefined;
|
|
8
8
|
live?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "glass" | "overlay" | "brown" | "antagonist" | null | undefined;
|
|
7
7
|
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
8
8
|
fullWidth?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
@@ -3,12 +3,12 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const cardVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "outline" | "glass" | "muted" | "surface" | "elevated" | "elevatedPanel" | 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 Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
11
|
-
variant?: "
|
|
11
|
+
variant?: "outline" | "glass" | "muted" | "surface" | "elevated" | "elevatedPanel" | 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> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -57,7 +57,10 @@ function CategoryDeck({
|
|
|
57
57
|
{
|
|
58
58
|
className: cn(
|
|
59
59
|
"absolute left-1/2 top-0 aspect-[4/5] w-24 overflow-hidden rounded-[10px] bg-muted",
|
|
60
|
+
// Keyed to --foreground so the shadow is ink in light mode; in
|
|
61
|
+
// dark mode that same 18% is a light halo, so it drops to 7%.
|
|
60
62
|
"shadow-[0_10px_26px_color-mix(in_oklch,var(--foreground)_18%,transparent)]",
|
|
63
|
+
"dark:shadow-[0_10px_26px_color-mix(in_oklch,var(--foreground)_7%,transparent)]",
|
|
61
64
|
"sm:w-[120px]",
|
|
62
65
|
transform.rest,
|
|
63
66
|
transform.spread,
|
|
@@ -86,7 +89,13 @@ function CategoryDeck({
|
|
|
86
89
|
/* @__PURE__ */ jsx("div", { className: "truncate text-[14.5px] font-extrabold tracking-[-0.015em] sm:text-base", children: name }),
|
|
87
90
|
/* @__PURE__ */ jsx("div", { className: "truncate font-mono text-[11.5px] text-muted-foreground", children: meta })
|
|
88
91
|
] }),
|
|
89
|
-
/* @__PURE__ */ jsx(
|
|
92
|
+
/* @__PURE__ */ jsx(
|
|
93
|
+
ChevronRight,
|
|
94
|
+
{
|
|
95
|
+
className: "ml-auto h-4 w-4 shrink-0 text-muted-foreground",
|
|
96
|
+
"aria-hidden": true
|
|
97
|
+
}
|
|
98
|
+
)
|
|
90
99
|
] })
|
|
91
100
|
] });
|
|
92
101
|
const rootClasses = cn(
|
|
@@ -4,11 +4,11 @@ import { DialogProps } from '@radix-ui/react-dialog';
|
|
|
4
4
|
|
|
5
5
|
declare const Command: React.ForwardRefExoticComponent<Omit<{
|
|
6
6
|
children?: React.ReactNode;
|
|
7
|
-
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
7
|
+
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
8
8
|
ref?: React.Ref<HTMLDivElement>;
|
|
9
9
|
} & {
|
|
10
10
|
asChild?: boolean;
|
|
11
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
11
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
12
12
|
label?: string;
|
|
13
13
|
shouldFilter?: boolean;
|
|
14
14
|
filter?: (value: string, search: string, keywords?: string[]) => number;
|
|
@@ -28,61 +28,61 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
|
|
|
28
28
|
ref?: React.Ref<HTMLInputElement>;
|
|
29
29
|
} & {
|
|
30
30
|
asChild?: boolean;
|
|
31
|
-
}, "
|
|
31
|
+
}, "key" | "asChild" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
|
|
32
32
|
value?: string;
|
|
33
33
|
onValueChange?: (search: string) => void;
|
|
34
34
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
35
35
|
declare const CommandList: React.ForwardRefExoticComponent<Omit<{
|
|
36
36
|
children?: React.ReactNode;
|
|
37
|
-
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
37
|
+
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
38
38
|
ref?: React.Ref<HTMLDivElement>;
|
|
39
39
|
} & {
|
|
40
40
|
asChild?: boolean;
|
|
41
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
41
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
42
42
|
label?: string;
|
|
43
43
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
44
44
|
declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
45
45
|
children?: React.ReactNode;
|
|
46
|
-
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
46
|
+
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
47
47
|
ref?: React.Ref<HTMLDivElement>;
|
|
48
48
|
} & {
|
|
49
49
|
asChild?: boolean;
|
|
50
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
50
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
51
51
|
declare const CommandLoading: React.ForwardRefExoticComponent<Omit<{
|
|
52
52
|
children?: React.ReactNode;
|
|
53
|
-
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
53
|
+
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
54
54
|
ref?: React.Ref<HTMLDivElement>;
|
|
55
55
|
} & {
|
|
56
56
|
asChild?: boolean;
|
|
57
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
57
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
58
58
|
progress?: number;
|
|
59
59
|
label?: string;
|
|
60
60
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
61
61
|
declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
62
62
|
children?: React.ReactNode;
|
|
63
|
-
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
63
|
+
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
64
64
|
ref?: React.Ref<HTMLDivElement>;
|
|
65
65
|
} & {
|
|
66
66
|
asChild?: boolean;
|
|
67
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
67
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "heading" | "value"> & {
|
|
68
68
|
heading?: React.ReactNode;
|
|
69
69
|
value?: string;
|
|
70
70
|
forceMount?: boolean;
|
|
71
71
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
72
|
-
declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
72
|
+
declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
73
73
|
ref?: React.Ref<HTMLDivElement>;
|
|
74
74
|
} & {
|
|
75
75
|
asChild?: boolean;
|
|
76
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
76
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
77
77
|
alwaysRender?: boolean;
|
|
78
78
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
79
79
|
declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
80
80
|
children?: React.ReactNode;
|
|
81
|
-
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
81
|
+
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
82
82
|
ref?: React.Ref<HTMLDivElement>;
|
|
83
83
|
} & {
|
|
84
84
|
asChild?: boolean;
|
|
85
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
85
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "disabled" | "value"> & {
|
|
86
86
|
disabled?: boolean;
|
|
87
87
|
onSelect?: (value: string) => void;
|
|
88
88
|
value?: string;
|
|
@@ -3,9 +3,17 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
3
3
|
/**
|
|
4
4
|
* Coverflow — the busiest-events browser: a 3D perspective lane with a large
|
|
5
5
|
* lead poster flanked by up to three shrinking, desaturating posters on each
|
|
6
|
-
* side.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* side.
|
|
7
|
+
*
|
|
8
|
+
* NOTHING MOVES ON ITS OWN. The lane used to drift ±40px on a loop; it was
|
|
9
|
+
* removed at product request — a stage that sways is read as a carousel that
|
|
10
|
+
* is about to advance, and the reader waits for it instead of touching it.
|
|
11
|
+
* The stage is driven by the reader: a horizontal drag (touch, pen or mouse)
|
|
12
|
+
* steps the ring one card in the drag's direction and the lane follows the
|
|
13
|
+
* finger a little on the way, so the gesture has weight. The prev/next arrows
|
|
14
|
+
* stay for desktop and keyboard; below `lg` they are hidden so nothing sits
|
|
15
|
+
* over the lead card — the swipe is the control there, and every card is
|
|
16
|
+
* still a focusable, named button for keyboard and screen-reader users.
|
|
9
17
|
*
|
|
10
18
|
* IT IS A RING, NOT A LANE. A card's slot comes from `ringOffset` — the
|
|
11
19
|
* SIGNED SHORTEST WAY ROUND the list, not the raw `index - activeIndex`. With
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { useDragSwipe } from '../chunk-IYDH5IU6.js';
|
|
1
2
|
import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
|
|
2
3
|
import { cn } from '../chunk-FEK5XGZW.js';
|
|
3
|
-
import {
|
|
4
|
-
import { useId,
|
|
4
|
+
import { __spreadProps, __spreadValues, __objRest } from '../chunk-3GWWZKX7.js';
|
|
5
|
+
import { useId, useState } from 'react';
|
|
5
6
|
import { ChevronLeft, ChevronRight, Gift } from 'lucide-react';
|
|
6
7
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
8
|
|
|
@@ -21,10 +22,8 @@ var COVERFLOW_CARD_FOCUS_CLASS = "focus-visible:outline-none focus-visible:ring-
|
|
|
21
22
|
var COVERFLOW_SIDE_SHADOW_CLASS = "shadow-[0_11px_27px_oklch(0.3_0.02_60/0.22)]";
|
|
22
23
|
var COVERFLOW_LEAD_SHADOW_CLASS = "shadow-[0_24px_56px_oklch(0.28_0.03_45/0.32)]";
|
|
23
24
|
var COVERFLOW_PILL_CLASS = "inline-flex h-6 max-w-[85%] items-center gap-1 rounded-full px-2 text-[11px] font-semibold";
|
|
24
|
-
var COVERFLOW_DRIFT_DURATION_SECONDS = 26;
|
|
25
|
-
var COVERFLOW_DRIFT_PIXELS = 40;
|
|
26
25
|
var COVERFLOW_LEAD_Z_INDEX = 6;
|
|
27
|
-
var COVERFLOW_ARROW_CLASS = "absolute top-1/2 z-20
|
|
26
|
+
var COVERFLOW_ARROW_CLASS = "absolute top-1/2 z-20 hidden h-11 w-11 -translate-y-1/2 lg:flex cursor-pointer items-center justify-center rounded-full bg-background/85 text-foreground shadow-[var(--shadow-overlay)] backdrop-blur-sm transition-colors duration-150 hover:bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 motion-reduce:transition-none";
|
|
28
27
|
function wrapIndex(index, length) {
|
|
29
28
|
return (index % length + length) % length;
|
|
30
29
|
}
|
|
@@ -141,7 +140,6 @@ function Coverflow({
|
|
|
141
140
|
}) {
|
|
142
141
|
const scopeId = useId().replace(/[^a-zA-Z0-9]/g, "");
|
|
143
142
|
const scopeClass = `coverflow-${scopeId}`;
|
|
144
|
-
const containerRef = useRef(null);
|
|
145
143
|
const length = items.length;
|
|
146
144
|
const active = length > 0 ? wrapIndex(activeIndex, length) : 0;
|
|
147
145
|
const [step, setStep] = useState({ from: active, to: active, length });
|
|
@@ -150,21 +148,13 @@ function Coverflow({
|
|
|
150
148
|
step.length === length ? { from: step.to, to: active, length } : { from: active, to: active, length }
|
|
151
149
|
);
|
|
152
150
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
node.dataset.offscreen = entry.isIntersecting ? "false" : "true";
|
|
159
|
-
},
|
|
160
|
-
{ threshold: 0 }
|
|
161
|
-
);
|
|
162
|
-
observer.observe(node);
|
|
163
|
-
return () => observer.disconnect();
|
|
164
|
-
}, []);
|
|
151
|
+
const goTo = (index) => onActiveIndexChange == null ? void 0 : onActiveIndexChange(wrapIndex(index, length));
|
|
152
|
+
const { dragX, isDragging, handlers } = useDragSwipe({
|
|
153
|
+
onSwipe: (direction) => goTo(active + direction),
|
|
154
|
+
disabled: length < 2
|
|
155
|
+
});
|
|
165
156
|
if (length === 0) return null;
|
|
166
157
|
const activeItem = items[active];
|
|
167
|
-
const goTo = (index) => onActiveIndexChange == null ? void 0 : onActiveIndexChange(wrapIndex(index, length));
|
|
168
158
|
const activeDelta = ringOffset(step.to - step.from, length);
|
|
169
159
|
const visibleCards = items.map((item, index) => {
|
|
170
160
|
const offset = ringOffset(index - active, length);
|
|
@@ -208,28 +198,11 @@ function Coverflow({
|
|
|
208
198
|
--cf-tier-base: 0.5714;
|
|
209
199
|
}
|
|
210
200
|
}
|
|
211
|
-
.${scopeClass} .coverflow-lane {
|
|
212
|
-
animation: ${scopeClass}-drift ${COVERFLOW_DRIFT_DURATION_SECONDS}s ease-in-out infinite alternate;
|
|
213
|
-
}
|
|
214
|
-
.${scopeClass}[data-offscreen="true"] .coverflow-lane {
|
|
215
|
-
animation-play-state: paused;
|
|
216
|
-
}
|
|
217
|
-
@keyframes ${scopeClass}-drift {
|
|
218
|
-
from { transform: translateX(-${COVERFLOW_DRIFT_PIXELS}px); }
|
|
219
|
-
to { transform: translateX(${COVERFLOW_DRIFT_PIXELS}px); }
|
|
220
|
-
}
|
|
221
|
-
@media (prefers-reduced-motion: reduce) {
|
|
222
|
-
.${scopeClass} .coverflow-lane {
|
|
223
|
-
animation: none;
|
|
224
|
-
transform: none;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
201
|
` }),
|
|
228
202
|
/* @__PURE__ */ jsxs(
|
|
229
203
|
"div",
|
|
230
|
-
{
|
|
231
|
-
|
|
232
|
-
className: "relative flex h-[300px] items-center justify-center overflow-x-clip overflow-y-visible [perspective:900px] sm:h-[380px] sm:[perspective:1400px]",
|
|
204
|
+
__spreadProps(__spreadValues({}, handlers), {
|
|
205
|
+
className: "relative flex h-[300px] select-none items-center justify-center overflow-x-clip overflow-y-visible [touch-action:pan-y] [perspective:900px] sm:h-[380px] sm:[perspective:1400px]",
|
|
233
206
|
children: [
|
|
234
207
|
/* @__PURE__ */ jsx(
|
|
235
208
|
"div",
|
|
@@ -267,21 +240,31 @@ function Coverflow({
|
|
|
267
240
|
}
|
|
268
241
|
)
|
|
269
242
|
] }),
|
|
270
|
-
/* @__PURE__ */ jsx(
|
|
271
|
-
|
|
243
|
+
/* @__PURE__ */ jsx(
|
|
244
|
+
"div",
|
|
272
245
|
{
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
246
|
+
className: cn(
|
|
247
|
+
"coverflow-lane relative h-full w-full [transform-style:preserve-3d]",
|
|
248
|
+
!isDragging && "transition-transform duration-300 ease-out motion-reduce:transition-none"
|
|
249
|
+
),
|
|
250
|
+
style: { transform: `translateX(${dragX / 3}px)` },
|
|
251
|
+
children: visibleCards.map(({ item, index, offset, suppressTransition }) => /* @__PURE__ */ jsx(
|
|
252
|
+
CoverflowCard,
|
|
253
|
+
{
|
|
254
|
+
item,
|
|
255
|
+
index,
|
|
256
|
+
offset,
|
|
257
|
+
suppressTransition,
|
|
258
|
+
freeLabel,
|
|
259
|
+
onActivate: goTo,
|
|
260
|
+
linkComponent: LinkComponent
|
|
261
|
+
},
|
|
262
|
+
item.id
|
|
263
|
+
))
|
|
264
|
+
}
|
|
265
|
+
)
|
|
283
266
|
]
|
|
284
|
-
}
|
|
267
|
+
})
|
|
285
268
|
),
|
|
286
269
|
/* @__PURE__ */ jsxs("div", { className: "mt-4 space-y-4 text-center", children: [
|
|
287
270
|
/* @__PURE__ */ jsxs("div", { "aria-live": "polite", children: [
|