@bearmenu/ui 0.8.4 → 0.8.7

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.
Files changed (150) hide show
  1. package/dist/chunk-637L7XQ3.js +85 -0
  2. package/dist/chunk-6XMYEZVR.js +26 -0
  3. package/dist/chunk-DNSXMHYX.js +8 -0
  4. package/dist/chunk-FDITZ2VM.js +16 -0
  5. package/dist/chunk-GPH6L4DX.js +55 -0
  6. package/dist/{chunk-N2KNBPAQ.js → chunk-QXHMPJ35.js} +1 -0
  7. package/dist/chunk-TT3WFS6S.js +379 -0
  8. package/dist/chunk-UXWAOISG.js +170 -0
  9. package/dist/{chunk-UZ3PCIE5.js → chunk-XWMRABZW.js} +2 -2
  10. package/dist/{chunk-VBA45GLP.js → chunk-ZDAHKI3A.js} +12 -2
  11. package/dist/components/card.d.ts +2 -2
  12. package/dist/components/card.js +4 -127
  13. package/dist/components/category-deck.d.ts +50 -0
  14. package/dist/components/category-deck.js +128 -0
  15. package/dist/components/concept-card.d.ts +43 -0
  16. package/dist/components/concept-card.js +81 -0
  17. package/dist/components/coverflow.d.ts +123 -0
  18. package/dist/components/coverflow.js +300 -0
  19. package/dist/components/day-rail-chip.d.ts +82 -0
  20. package/dist/components/day-rail-chip.js +105 -0
  21. package/dist/components/drift-rail.d.ts +28 -0
  22. package/dist/components/drift-rail.js +3 -0
  23. package/dist/components/event-card.d.ts +97 -0
  24. package/dist/components/event-card.js +164 -0
  25. package/dist/components/event-compact-row.d.ts +73 -0
  26. package/dist/components/event-compact-row.js +134 -0
  27. package/dist/components/event-day-header.d.ts +65 -0
  28. package/dist/components/event-day-header.js +95 -0
  29. package/dist/components/event-day-separator.d.ts +46 -0
  30. package/dist/components/event-day-separator.js +50 -0
  31. package/dist/components/event-detail-panel.d.ts +80 -0
  32. package/dist/components/event-detail-panel.js +251 -0
  33. package/dist/components/event-hub-hero.d.ts +34 -0
  34. package/dist/components/event-hub-hero.js +57 -0
  35. package/dist/components/event-index-row.d.ts +68 -0
  36. package/dist/components/event-index-row.js +84 -0
  37. package/dist/components/event-list-row-wide.d.ts +101 -0
  38. package/dist/components/event-list-row-wide.js +218 -0
  39. package/dist/components/event-list-row.d.ts +82 -0
  40. package/dist/components/event-list-row.js +173 -0
  41. package/dist/components/event-poster-fallback.d.ts +20 -0
  42. package/dist/components/event-poster-fallback.js +3 -0
  43. package/dist/components/event-types.d.ts +122 -0
  44. package/dist/components/event-types.js +2 -0
  45. package/dist/components/events-empty-state.d.ts +44 -0
  46. package/dist/components/events-empty-state.js +73 -0
  47. package/dist/components/facet-group.d.ts +93 -0
  48. package/dist/components/facet-group.js +222 -0
  49. package/dist/components/featured-rail-item.d.ts +42 -0
  50. package/dist/components/featured-rail-item.js +88 -0
  51. package/dist/components/hour-band.d.ts +68 -0
  52. package/dist/components/hour-band.js +53 -0
  53. package/dist/components/hour-group.d.ts +67 -0
  54. package/dist/components/hour-group.js +59 -0
  55. package/dist/components/motion-icon-controls.js +3 -379
  56. package/dist/components/multi-select-combobox.js +1 -1
  57. package/dist/components/place-about-tab.js +3 -3
  58. package/dist/components/place-details-mobile.js +3 -3
  59. package/dist/components/poster-stack.d.ts +30 -0
  60. package/dist/components/poster-stack.js +104 -0
  61. package/dist/components/poster-tape.d.ts +36 -0
  62. package/dist/components/poster-tape.js +64 -0
  63. package/dist/components/poster-wall.d.ts +25 -0
  64. package/dist/components/poster-wall.js +183 -0
  65. package/dist/components/quiet-stretch.d.ts +43 -0
  66. package/dist/components/quiet-stretch.js +54 -0
  67. package/dist/components/section-header.d.ts +53 -0
  68. package/dist/components/section-header.js +63 -0
  69. package/dist/components/segmented-nav.d.ts +62 -0
  70. package/dist/components/segmented-nav.js +54 -0
  71. package/dist/components/skeleton-card.js +1 -1
  72. package/dist/components/skeleton.d.ts +17 -0
  73. package/dist/components/skeleton.js +1 -1
  74. package/dist/components/tag-group.js +3 -26
  75. package/dist/components/tag.d.ts +2 -2
  76. package/dist/components/tag.js +1 -1
  77. package/dist/components/timeline-band.d.ts +46 -0
  78. package/dist/components/timeline-band.js +5 -0
  79. package/dist/components/venue-events-block.d.ts +143 -0
  80. package/dist/components/venue-events-block.js +222 -0
  81. package/dist/components/weekend-panel.d.ts +44 -0
  82. package/dist/components/weekend-panel.js +231 -0
  83. package/package.json +1 -1
  84. package/src/components/card.tsx +44 -1
  85. package/src/components/category-deck.stories.tsx +96 -0
  86. package/src/components/category-deck.tsx +227 -0
  87. package/src/components/concept-card.stories.tsx +80 -0
  88. package/src/components/concept-card.tsx +143 -0
  89. package/src/components/coverflow.stories.tsx +240 -0
  90. package/src/components/coverflow.test.tsx +193 -0
  91. package/src/components/coverflow.tsx +550 -0
  92. package/src/components/day-rail-chip.stories.tsx +145 -0
  93. package/src/components/day-rail-chip.tsx +201 -0
  94. package/src/components/drift-rail.stories.tsx +92 -0
  95. package/src/components/drift-rail.tsx +86 -0
  96. package/src/components/event-card.stories.tsx +248 -0
  97. package/src/components/event-card.test.tsx +188 -0
  98. package/src/components/event-card.tsx +329 -0
  99. package/src/components/event-compact-row.stories.tsx +221 -0
  100. package/src/components/event-compact-row.test.tsx +51 -0
  101. package/src/components/event-compact-row.tsx +270 -0
  102. package/src/components/event-day-header.stories.tsx +124 -0
  103. package/src/components/event-day-header.tsx +180 -0
  104. package/src/components/event-day-separator.stories.tsx +70 -0
  105. package/src/components/event-day-separator.tsx +95 -0
  106. package/src/components/event-detail-panel.stories.tsx +191 -0
  107. package/src/components/event-detail-panel.tsx +360 -0
  108. package/src/components/event-hub-hero.stories.tsx +66 -0
  109. package/src/components/event-hub-hero.tsx +110 -0
  110. package/src/components/event-index-row.stories.tsx +116 -0
  111. package/src/components/event-index-row.tsx +181 -0
  112. package/src/components/event-list-row-wide.stories.tsx +204 -0
  113. package/src/components/event-list-row-wide.tsx +386 -0
  114. package/src/components/event-list-row.stories.tsx +159 -0
  115. package/src/components/event-list-row.tsx +335 -0
  116. package/src/components/event-poster-fallback.stories.tsx +52 -0
  117. package/src/components/event-poster-fallback.tsx +31 -0
  118. package/src/components/event-types.ts +137 -0
  119. package/src/components/events-empty-state.stories.tsx +59 -0
  120. package/src/components/events-empty-state.tsx +131 -0
  121. package/src/components/facet-group.stories.tsx +247 -0
  122. package/src/components/facet-group.test.tsx +225 -0
  123. package/src/components/facet-group.tsx +352 -0
  124. package/src/components/featured-rail-item.stories.tsx +86 -0
  125. package/src/components/featured-rail-item.tsx +153 -0
  126. package/src/components/hour-band.stories.tsx +159 -0
  127. package/src/components/hour-band.tsx +126 -0
  128. package/src/components/hour-group.stories.tsx +100 -0
  129. package/src/components/hour-group.tsx +124 -0
  130. package/src/components/poster-stack.stories.tsx +68 -0
  131. package/src/components/poster-stack.tsx +155 -0
  132. package/src/components/poster-tape.stories.tsx +70 -0
  133. package/src/components/poster-tape.tsx +122 -0
  134. package/src/components/poster-wall.stories.tsx +95 -0
  135. package/src/components/poster-wall.tsx +220 -0
  136. package/src/components/quiet-stretch.stories.tsx +62 -0
  137. package/src/components/quiet-stretch.tsx +115 -0
  138. package/src/components/section-header.stories.tsx +70 -0
  139. package/src/components/section-header.tsx +134 -0
  140. package/src/components/segmented-nav.stories.tsx +118 -0
  141. package/src/components/segmented-nav.tsx +113 -0
  142. package/src/components/skeleton.tsx +18 -0
  143. package/src/components/tag.tsx +11 -1
  144. package/src/components/timeline-band.stories.tsx +206 -0
  145. package/src/components/timeline-band.tsx +207 -0
  146. package/src/components/venue-events-block.stories.tsx +216 -0
  147. package/src/components/venue-events-block.tsx +408 -0
  148. package/src/components/weekend-panel.stories.tsx +92 -0
  149. package/src/components/weekend-panel.tsx +322 -0
  150. package/src/globals.css +19 -0
@@ -0,0 +1,46 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ElementType } from 'react';
3
+
4
+ /**
5
+ * EventDaySeparator — the day divider in the list view (as opposed to
6
+ * `<EventDayHeader>`, the timeline's oversized day-number header — the two
7
+ * live on different surfaces with different densities, not a size variant of
8
+ * one component).
9
+ *
10
+ * Both `label` and `count` are caller-composed strings, same reasoning as
11
+ * `<EventDayHeader>`'s `meta`: "Today · Thursday 3 September" / "15 events"
12
+ * don't decompose into parts without baking in English clause order.
13
+ *
14
+ * Renders the label as a real heading (`as`, default `h2`) so a list of these
15
+ * gives the page a document outline instead of being purely decorative rules.
16
+ *
17
+ * NOTE ON WEIGHT: this heading is deliberately SMALLER and lighter than the
18
+ * row titles beneath it. The boundary is already the strongest structural
19
+ * event on the page — a rule to the right edge, 24px of air above it, a muted
20
+ * count beside it — so it needs no ink on top of that. And the day is chrome
21
+ * on a scan surface where the events are the content: when the chrome is the
22
+ * heaviest thing on screen, the eye lands on the same repeated word every
23
+ * eight rows and nothing in the actual inventory ever wins. If the boundary
24
+ * ever needs to read louder, the levers are the rule and the air (move the
25
+ * `<Separator>` above the label), not the weight.
26
+ */
27
+ type EventDaySeparatorProps = {
28
+ label: string;
29
+ count?: string;
30
+ size?: "sm" | "default";
31
+ /** Heading level for `label`. Defaults to `h2`. */
32
+ as?: ElementType;
33
+ className?: string;
34
+ };
35
+ declare function EventDaySeparator({ label, count, size, as: Tag, className, }: EventDaySeparatorProps): react_jsx_runtime.JSX.Element;
36
+ type EventDaySeparatorSkeletonProps = {
37
+ /** Matches `EventDaySeparatorProps["size"]`. */
38
+ size?: "sm" | "default";
39
+ /** Shows the count placeholder — omit for label-only separators. */
40
+ showCount?: boolean;
41
+ className?: string;
42
+ };
43
+ /** Mirrors `<EventDaySeparator>`'s geometry exactly so nothing shifts when data lands. */
44
+ declare function EventDaySeparatorSkeleton({ size, showCount, className, }: EventDaySeparatorSkeletonProps): react_jsx_runtime.JSX.Element;
45
+
46
+ export { EventDaySeparator, type EventDaySeparatorProps, EventDaySeparatorSkeleton, type EventDaySeparatorSkeletonProps };
@@ -0,0 +1,50 @@
1
+ import { Separator } from '../chunk-WSRWFA6K.js';
2
+ import { Skeleton } from '../chunk-QXHMPJ35.js';
3
+ import { cn } from '../chunk-FEK5XGZW.js';
4
+ import '../chunk-3GWWZKX7.js';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function EventDaySeparator({
8
+ label,
9
+ count,
10
+ size = "default",
11
+ as: Tag = "h2",
12
+ className
13
+ }) {
14
+ return /* @__PURE__ */ jsxs(
15
+ "div",
16
+ {
17
+ className: cn(
18
+ "flex items-center gap-[11px]",
19
+ size === "sm" ? "pt-[18px] pb-1" : "pt-6 pb-2",
20
+ className
21
+ ),
22
+ children: [
23
+ /* @__PURE__ */ jsx(Tag, { className: cn("font-semibold", size === "sm" ? "text-[13px]" : "text-sm"), children: label }),
24
+ count && /* @__PURE__ */ jsx("span", { className: cn("text-muted-foreground", size === "sm" ? "text-[11.5px]" : "text-xs"), children: count }),
25
+ /* @__PURE__ */ jsx(Separator, { className: "flex-1" })
26
+ ]
27
+ }
28
+ );
29
+ }
30
+ function EventDaySeparatorSkeleton({
31
+ size = "default",
32
+ showCount = true,
33
+ className
34
+ }) {
35
+ const isSm = size === "sm";
36
+ return /* @__PURE__ */ jsxs(
37
+ "div",
38
+ {
39
+ "aria-hidden": "true",
40
+ className: cn("flex items-center gap-[11px]", isSm ? "pt-[18px] pb-1" : "pt-6 pb-2", className),
41
+ children: [
42
+ /* @__PURE__ */ jsx(Skeleton, { className: cn(isSm ? "h-3" : "h-3.5", "w-40") }),
43
+ showCount && /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-16" }),
44
+ /* @__PURE__ */ jsx(Separator, { className: "flex-1" })
45
+ ]
46
+ }
47
+ );
48
+ }
49
+
50
+ export { EventDaySeparator, EventDaySeparatorSkeleton };
@@ -0,0 +1,80 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { EventPreview, EventFormatters } from './event-types.js';
4
+
5
+ /**
6
+ * EventDetailPanel — the BODY of the event detail sheet.
7
+ *
8
+ * Deliberately not a sheet. The design opens this as a side sheet over a dimmed
9
+ * page on desktop and a bottom sheet on mobile, and the DS already ships `Sheet`
10
+ * and `Drawer`; owning sheet mechanics a third time here would fork them. The
11
+ * consuming app mounts this inside whichever container the breakpoint calls for.
12
+ *
13
+ * This is the terminal surface for acting on an event, which is why the cards
14
+ * that open it carry no actions of their own — the footer is where booking and
15
+ * directions live.
16
+ *
17
+ * Everything is injected: strings via `labels`, times via `formatters`, and the
18
+ * close/share affordances as `headerActions` so the sheet container owns
19
+ * dismissal (bearmenu sheets close by drag handle, not by back navigation).
20
+ */
21
+ type EventDetailPanelLinkProps = {
22
+ href: string;
23
+ className?: string;
24
+ children: React.ReactNode;
25
+ };
26
+ type EventDetailVenue = {
27
+ name: string;
28
+ /** Address plus opening line, composed by the caller. */
29
+ meta?: string;
30
+ ratingLabel?: string;
31
+ thumbnailUrl?: string;
32
+ href?: string;
33
+ };
34
+ type EventDetailPanelLabels = {
35
+ free: string;
36
+ liveNow: string;
37
+ /** Section heading above the venue card. */
38
+ venueHeading: string;
39
+ /** Section heading above the description. */
40
+ aboutHeading: string;
41
+ };
42
+ type EventDetailPanelProps = {
43
+ event: EventPreview;
44
+ labels: EventDetailPanelLabels;
45
+ formatters: EventFormatters;
46
+ /**
47
+ * The date line, composed by the caller — the design reads
48
+ * "Saturday, September 5 · Starts at 20:00", whose clause order and
49
+ * preposition are locale-dependent.
50
+ */
51
+ dateLine: string;
52
+ venue?: EventDetailVenue;
53
+ /** Category chips beside the live/price chips. */
54
+ tags?: string[];
55
+ isLive?: boolean;
56
+ /** Close and share controls, positioned over the poster by this component. */
57
+ headerActions?: React.ReactNode;
58
+ /** Footer actions — the booking CTA and directions. Rendered in a sticky footer. */
59
+ footer?: React.ReactNode;
60
+ /** An external link row, e.g. "View on Instagram". */
61
+ externalLink?: React.ReactNode;
62
+ /** `compact` is the mobile bottom sheet: tighter type and padding, same 4:5 poster. */
63
+ size?: "compact" | "default";
64
+ linkComponent?: React.ComponentType<EventDetailPanelLinkProps>;
65
+ className?: string;
66
+ /** Rendered instead of the poster when it's absent. Defaults to `<EventPosterFallback />`. */
67
+ fallback?: React.ReactNode;
68
+ };
69
+ declare function EventDetailPanel({ event, labels, formatters, dateLine, venue, tags, isLive, headerActions, footer, externalLink, size, linkComponent: LinkComponent, className, fallback, }: EventDetailPanelProps): react_jsx_runtime.JSX.Element;
70
+ type EventDetailPanelSkeletonProps = {
71
+ /** `compact` is the mobile bottom sheet: tighter type and padding, same 4:5 poster. */
72
+ size?: "compact" | "default";
73
+ /** Close and share controls, positioned over the poster — same slot as the real component. */
74
+ headerActions?: React.ReactNode;
75
+ className?: string;
76
+ };
77
+ /** Mirrors `<EventDetailPanel>`'s geometry exactly: the hero scrolls away with the body, the footer is sticky. */
78
+ declare function EventDetailPanelSkeleton({ size, headerActions, className, }: EventDetailPanelSkeletonProps): react_jsx_runtime.JSX.Element;
79
+
80
+ export { EventDetailPanel, type EventDetailPanelLabels, type EventDetailPanelLinkProps, type EventDetailPanelProps, EventDetailPanelSkeleton, type EventDetailPanelSkeletonProps, type EventDetailVenue };
@@ -0,0 +1,251 @@
1
+ import { Separator } from '../chunk-WSRWFA6K.js';
2
+ import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
3
+ import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
4
+ import { Skeleton } from '../chunk-QXHMPJ35.js';
5
+ import { cn } from '../chunk-FEK5XGZW.js';
6
+ import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
7
+ import { Star, ChevronRight, Calendar, Radio } from 'lucide-react';
8
+ import { jsxs, jsx } from 'react/jsx-runtime';
9
+
10
+ function DefaultLink(_a) {
11
+ var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
12
+ return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
13
+ }
14
+ var CHIP = "inline-flex items-center gap-1 rounded-full border border-border px-2.5 text-xs";
15
+ function EventDetailPanel({
16
+ event,
17
+ labels,
18
+ formatters,
19
+ dateLine,
20
+ venue,
21
+ tags,
22
+ isLive,
23
+ headerActions,
24
+ footer,
25
+ externalLink,
26
+ size = "default",
27
+ linkComponent: LinkComponent = DefaultLink,
28
+ className,
29
+ fallback = /* @__PURE__ */ jsx(EventPosterFallback, {})
30
+ }) {
31
+ const compact = size === "compact";
32
+ const fee = resolveEventEntryFee(event);
33
+ const venueCard = venue && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-[13px] border border-border p-2.5", children: [
34
+ /* @__PURE__ */ jsx(
35
+ "div",
36
+ {
37
+ className: cn(
38
+ "shrink-0 overflow-hidden rounded-[10px] bg-muted",
39
+ compact ? "h-12 w-12" : "h-[52px] w-[52px]"
40
+ ),
41
+ children: venue.thumbnailUrl && // eslint-disable-next-line @next/next/no-img-element
42
+ /* @__PURE__ */ jsx(
43
+ "img",
44
+ {
45
+ src: venue.thumbnailUrl,
46
+ alt: "",
47
+ className: "h-full w-full object-cover",
48
+ loading: "lazy",
49
+ decoding: "async"
50
+ }
51
+ )
52
+ }
53
+ ),
54
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
55
+ /* @__PURE__ */ jsx("div", { className: cn("font-bold", compact ? "text-[13.5px]" : "text-sm"), children: venue.name }),
56
+ venue.meta && /* @__PURE__ */ jsx("div", { className: cn("text-muted-foreground", compact ? "text-[11.5px]" : "text-xs"), children: venue.meta }),
57
+ venue.ratingLabel && /* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex items-center gap-1 text-xs font-bold", children: [
58
+ /* @__PURE__ */ jsx(Star, { className: "h-3 w-3", "aria-hidden": true }),
59
+ venue.ratingLabel
60
+ ] })
61
+ ] }),
62
+ /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": true })
63
+ ] });
64
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full flex-col overflow-hidden bg-card", className), children: [
65
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
66
+ /* @__PURE__ */ jsxs("div", { className: "relative aspect-[4/5] shrink-0 overflow-hidden bg-muted", children: [
67
+ event.poster_url ? (
68
+ // eslint-disable-next-line @next/next/no-img-element
69
+ /* @__PURE__ */ jsx(
70
+ "img",
71
+ {
72
+ src: event.poster_url,
73
+ alt: event.title,
74
+ className: "h-full w-full object-cover",
75
+ loading: "eager",
76
+ decoding: "async"
77
+ }
78
+ )
79
+ ) : fallback,
80
+ headerActions
81
+ ] }),
82
+ /* @__PURE__ */ jsxs(
83
+ "div",
84
+ {
85
+ className: cn(
86
+ "flex flex-col gap-3.5",
87
+ compact ? "px-4 pt-4" : "px-[22px] pt-5"
88
+ ),
89
+ children: [
90
+ /* @__PURE__ */ jsx(
91
+ "h2",
92
+ {
93
+ className: cn(
94
+ "font-extrabold leading-[1.25] tracking-[-0.02em]",
95
+ compact ? "text-xl" : "text-[21px]"
96
+ ),
97
+ children: event.title
98
+ }
99
+ ),
100
+ /* @__PURE__ */ jsxs(
101
+ "div",
102
+ {
103
+ className: cn(
104
+ "flex items-center gap-1.5 text-muted-foreground",
105
+ compact ? "text-[12.5px]" : "text-[13px]"
106
+ ),
107
+ children: [
108
+ /* @__PURE__ */ jsx(Calendar, { className: compact ? "h-3.5 w-3.5" : "h-4 w-4", "aria-hidden": true }),
109
+ dateLine
110
+ ]
111
+ }
112
+ ),
113
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1.5", children: [
114
+ isLive && /* @__PURE__ */ jsxs(
115
+ "span",
116
+ {
117
+ className: cn(
118
+ CHIP,
119
+ "h-7 border-success/30 bg-success/10 font-semibold text-success"
120
+ ),
121
+ children: [
122
+ /* @__PURE__ */ jsx(Radio, { className: "h-3 w-3", "aria-hidden": true }),
123
+ labels.liveNow
124
+ ]
125
+ }
126
+ ),
127
+ tags == null ? void 0 : tags.map((tag) => /* @__PURE__ */ jsx("span", { className: cn(CHIP, "h-7"), children: tag }, tag)),
128
+ fee.kind === "free" && /* @__PURE__ */ jsx("span", { className: cn(CHIP, "h-7 border-success/40 font-semibold text-success"), children: labels.free }),
129
+ fee.kind === "paid" && /* @__PURE__ */ jsx("span", { className: cn(CHIP, "h-7"), children: formatters.price(fee.amountRon) })
130
+ ] }),
131
+ venue && /* @__PURE__ */ jsxs("div", { children: [
132
+ /* @__PURE__ */ jsx("div", { className: "pb-2 text-[13px] font-extrabold", children: labels.venueHeading }),
133
+ venue.href ? /* @__PURE__ */ jsx(LinkComponent, { href: venue.href, className: "block", children: venueCard }) : venueCard
134
+ ] }),
135
+ event.description && /* @__PURE__ */ jsxs("div", { children: [
136
+ /* @__PURE__ */ jsx("div", { className: "pb-1.5 text-[13px] font-extrabold", children: labels.aboutHeading }),
137
+ /* @__PURE__ */ jsx(
138
+ "p",
139
+ {
140
+ className: cn(
141
+ "leading-[1.6] text-muted-foreground",
142
+ compact ? "text-[13px]" : "text-[13.5px]"
143
+ ),
144
+ children: event.description
145
+ }
146
+ )
147
+ ] }),
148
+ externalLink,
149
+ /* @__PURE__ */ jsx("div", { className: "h-2", "aria-hidden": true })
150
+ ]
151
+ }
152
+ )
153
+ ] }),
154
+ footer && /* @__PURE__ */ jsxs(
155
+ "div",
156
+ {
157
+ className: cn(
158
+ "sticky bottom-0 flex shrink-0 gap-2.5 bg-card",
159
+ compact ? "px-4 pt-3 pb-[max(1.375rem,env(safe-area-inset-bottom))]" : "px-[22px] pt-4 pb-[max(1.25rem,env(safe-area-inset-bottom))]"
160
+ ),
161
+ children: [
162
+ /* @__PURE__ */ jsx(Separator, { className: "absolute inset-x-0 top-0" }),
163
+ footer
164
+ ]
165
+ }
166
+ )
167
+ ] });
168
+ }
169
+ function EventDetailPanelSkeleton({
170
+ size = "default",
171
+ headerActions,
172
+ className
173
+ }) {
174
+ const compact = size === "compact";
175
+ return /* @__PURE__ */ jsxs(
176
+ "div",
177
+ {
178
+ "aria-hidden": "true",
179
+ className: cn("flex h-full flex-col overflow-hidden bg-card", className),
180
+ children: [
181
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
182
+ /* @__PURE__ */ jsx("div", { className: "relative aspect-[4/5] shrink-0 overflow-hidden bg-muted", children: headerActions }),
183
+ /* @__PURE__ */ jsxs(
184
+ "div",
185
+ {
186
+ className: cn(
187
+ "flex flex-col gap-3.5",
188
+ compact ? "px-4 pt-4" : "px-[22px] pt-5"
189
+ ),
190
+ children: [
191
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("w-3/4", compact ? "h-5" : "h-[21px]") }),
192
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
193
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("shrink-0 rounded-full", compact ? "h-3.5 w-3.5" : "h-4 w-4") }),
194
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("w-48", compact ? "h-[12.5px]" : "h-[13px]") })
195
+ ] }),
196
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1.5", children: [
197
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-20 rounded-full" }),
198
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-16 rounded-full" })
199
+ ] }),
200
+ /* @__PURE__ */ jsxs("div", { children: [
201
+ /* @__PURE__ */ jsx(Skeleton, { className: "mb-2 h-[13px] w-28" }),
202
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-[13px] border border-border p-2.5", children: [
203
+ /* @__PURE__ */ jsx(
204
+ Skeleton,
205
+ {
206
+ className: cn(
207
+ "shrink-0 rounded-[10px]",
208
+ compact ? "h-12 w-12" : "h-[52px] w-[52px]"
209
+ )
210
+ }
211
+ ),
212
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
213
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("w-1/2", compact ? "h-[13.5px]" : "h-3.5") }),
214
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("mt-1 w-3/4", compact ? "h-[11.5px]" : "h-3") })
215
+ ] }),
216
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-4 shrink-0 rounded-full" })
217
+ ] })
218
+ ] }),
219
+ /* @__PURE__ */ jsxs("div", { children: [
220
+ /* @__PURE__ */ jsx(Skeleton, { className: "mb-1.5 h-[13px] w-32" }),
221
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
222
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("w-full", compact ? "h-[13px]" : "h-[13.5px]") }),
223
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("w-full", compact ? "h-[13px]" : "h-[13.5px]") }),
224
+ /* @__PURE__ */ jsx(Skeleton, { className: cn("w-2/3", compact ? "h-[13px]" : "h-[13.5px]") })
225
+ ] })
226
+ ] }),
227
+ /* @__PURE__ */ jsx("div", { className: "h-2", "aria-hidden": true })
228
+ ]
229
+ }
230
+ )
231
+ ] }),
232
+ /* @__PURE__ */ jsxs(
233
+ "div",
234
+ {
235
+ className: cn(
236
+ "sticky bottom-0 flex shrink-0 gap-2.5 bg-card",
237
+ compact ? "px-4 pt-3 pb-[max(1.375rem,env(safe-area-inset-bottom))]" : "px-[22px] pt-4 pb-[max(1.25rem,env(safe-area-inset-bottom))]"
238
+ ),
239
+ children: [
240
+ /* @__PURE__ */ jsx(Separator, { className: "absolute inset-x-0 top-0" }),
241
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-[46px] flex-1 rounded-xl" }),
242
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-[46px] w-24 rounded-xl" })
243
+ ]
244
+ }
245
+ )
246
+ ]
247
+ }
248
+ );
249
+ }
250
+
251
+ export { EventDetailPanel, EventDetailPanelSkeleton };
@@ -0,0 +1,34 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ /**
5
+ * EventHubHero — the hub's opening block: an eyebrow, a big headline, an
6
+ * intro line and a stats row on the left; an arbitrary slot (the poster
7
+ * stack, in the source design) on the right. Stacks on mobile.
8
+ *
9
+ * All copy and stat values arrive pre-formatted — the DS holds no `Intl`
10
+ * locale and does not format numbers.
11
+ */
12
+ type EventHubHeroStat = {
13
+ value: string;
14
+ label: string;
15
+ };
16
+ type EventHubHeroProps = {
17
+ /** Small caps-style label above the title, e.g. "Updated today". */
18
+ eyebrow: string;
19
+ title: string;
20
+ intro: string;
21
+ stats: EventHubHeroStat[];
22
+ /** The right-column slot — the poster stack in the source design. */
23
+ aside?: React.ReactNode;
24
+ className?: string;
25
+ };
26
+ declare function EventHubHero({ eyebrow, title, intro, stats, aside, className }: EventHubHeroProps): react_jsx_runtime.JSX.Element;
27
+ type EventHubHeroSkeletonProps = {
28
+ /** The right-column slot, e.g. a `PosterStack`-shaped placeholder. Mirrors `aside` on the real component. */
29
+ aside?: React.ReactNode;
30
+ className?: string;
31
+ };
32
+ declare function EventHubHeroSkeleton({ aside, className }: EventHubHeroSkeletonProps): react_jsx_runtime.JSX.Element;
33
+
34
+ export { EventHubHero, type EventHubHeroProps, EventHubHeroSkeleton, type EventHubHeroSkeletonProps, type EventHubHeroStat };
@@ -0,0 +1,57 @@
1
+ import { Skeleton } from '../chunk-QXHMPJ35.js';
2
+ import { cn } from '../chunk-FEK5XGZW.js';
3
+ import '../chunk-3GWWZKX7.js';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ function EventHubHero({ eyebrow, title, intro, stats, aside, className }) {
7
+ return /* @__PURE__ */ jsxs(
8
+ "div",
9
+ {
10
+ className: cn(
11
+ "grid grid-cols-1 gap-8 lg:grid-cols-[1fr_620px] lg:items-center lg:gap-10",
12
+ className
13
+ ),
14
+ children: [
15
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
16
+ /* @__PURE__ */ jsx("p", { className: "text-[11.5px] font-extrabold tracking-[0.12em] text-muted-foreground", children: eyebrow }),
17
+ /* @__PURE__ */ jsx("h1", { className: "text-[31px] font-black leading-[1.05] tracking-[-0.035em] text-foreground md:text-[42px] md:tracking-[-0.04em]", children: title }),
18
+ /* @__PURE__ */ jsx("p", { className: "max-w-[520px] text-[14px] leading-[1.6] text-muted-foreground md:text-[15px] md:leading-[1.65]", children: intro }),
19
+ /* @__PURE__ */ jsx("div", { className: "flex gap-[22px] pt-1.5 md:gap-[30px]", children: stats.map((stat) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
20
+ /* @__PURE__ */ jsx("span", { className: "text-[24px] font-black leading-none tracking-[-0.03em] tabular-nums text-foreground md:text-[30px]", children: stat.value }),
21
+ /* @__PURE__ */ jsx("span", { className: "mt-1 text-[11px] text-muted-foreground md:mt-[5px] md:text-[12.5px]", children: stat.label })
22
+ ] }, stat.label)) })
23
+ ] }),
24
+ aside && /* @__PURE__ */ jsx("div", { className: "min-w-0", children: aside })
25
+ ]
26
+ }
27
+ );
28
+ }
29
+ function EventHubHeroSkeleton({ aside, className }) {
30
+ return /* @__PURE__ */ jsxs(
31
+ "div",
32
+ {
33
+ "aria-hidden": "true",
34
+ className: cn(
35
+ "grid grid-cols-1 gap-8 lg:grid-cols-[1fr_620px] lg:items-center lg:gap-10",
36
+ className
37
+ ),
38
+ 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-[31px] w-full max-w-[420px] md:h-[42px]" }),
42
+ /* @__PURE__ */ jsxs("div", { className: "flex max-w-[520px] flex-col gap-1.5", children: [
43
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-[14px] w-full md:h-[15px]" }),
44
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-[14px] w-4/5 md:h-[15px]" })
45
+ ] }),
46
+ /* @__PURE__ */ jsx("div", { className: "flex gap-[22px] pt-1.5 md:gap-[30px]", children: Array.from({ length: 3 }, (_, index) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
47
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-[24px] w-10 md:h-[30px]" }),
48
+ /* @__PURE__ */ jsx(Skeleton, { className: "mt-1 h-[11px] w-16 md:mt-[5px] md:h-[12.5px]" })
49
+ ] }, index)) })
50
+ ] }),
51
+ aside && /* @__PURE__ */ jsx("div", { className: "min-w-0", children: aside })
52
+ ]
53
+ }
54
+ );
55
+ }
56
+
57
+ export { EventHubHero, EventHubHeroSkeleton };
@@ -0,0 +1,68 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, ComponentType } from 'react';
3
+
4
+ /**
5
+ * EventIndexRow — the row of an exhaustive, crawlable event index.
6
+ *
7
+ * NOT `<EventListRowWide>`: that row belongs to the list VIEW, and it carries
8
+ * a price column and a Reserve chip because the list view is where you act.
9
+ * This row makes no claim to be operable — it is a catalogue entry. Its only
10
+ * affordances are two real links: the title (stretched over the whole row via
11
+ * `after:absolute after:inset-0`) and the venue (escaping that overlay with
12
+ * `relative z-10`, the same nested-link pattern `<EventListRowWide>` uses for
13
+ * `menuHref`). That venue link is why this could not be a variant of
14
+ * `<EventCompactRow>` or `<EventListRow>`: both wrap their entire body in one
15
+ * anchor, so a second link inside would be a nested `<a>` — invalid HTML that
16
+ * browsers unnest, breaking both links.
17
+ *
18
+ * NO `"use client"`, AND THAT IS LOAD-BEARING. This row's surface is a
19
+ * server-only prerendered page carrying ~50 of them, and every sibling row in
20
+ * this family is a client component for one reason: `useState` to catch
21
+ * `<img onError>`. Here the fallback is layered BEHIND the poster instead, so
22
+ * a failed image reveals the designed gradient with no JS at all. The
23
+ * consequence to accept: an image that returns 200 but decodes to garbage
24
+ * shows an empty box rather than the fallback.
25
+ *
26
+ * THE DESCRIPTION IS NEVER TRUNCATED IN THE MARKUP — it is clamped with CSS
27
+ * (`line-clamp`), so the full text stays in the DOM. Callers must pass the
28
+ * whole string. On this surface that is the entire point: the text is the
29
+ * page's body copy, and a row that cut it at N characters would be deleting
30
+ * the thing the section exists to carry.
31
+ *
32
+ * ROW RULES: this row draws its own top rule, same as `<EventListRow>` and
33
+ * `<EventListRowWide>`. Pass `hideRule` on the first row under a heading that
34
+ * already ends in one (`<EventDaySeparator>` does), or you get two rules a few
35
+ * pixels apart.
36
+ */
37
+ type EventIndexRowLinkProps = {
38
+ href: string;
39
+ className?: string;
40
+ children: ReactNode;
41
+ };
42
+ type EventIndexRowProps = {
43
+ /** Rendered inside `as` and allowed to WRAP — a document-outline heading is never truncated. */
44
+ title: string;
45
+ /** Heading level for `title`. Defaults to `h3`, one below the group headings. */
46
+ as?: "h2" | "h3" | "h4";
47
+ href: string;
48
+ /** Leading emphasised fact on the meta line — caller-composed date + time, e.g. "26 iulie, 20:00–23:00". */
49
+ when: string;
50
+ venue?: string;
51
+ /** Makes the venue a real second link. Omit for a venue with no place page. */
52
+ venueHref?: string;
53
+ /** Plain text, never a chip: "intrare liberă" / "bilet 40 lei". */
54
+ fee?: string;
55
+ /** Display labels. `EventPreview.tags` is taxonomy coordinates the DS cannot translate, so the caller resolves and caps them. */
56
+ tags?: string[];
57
+ /** FULL text. Clamped to 3 lines (mobile) / 2 (md+) in CSS only. */
58
+ description?: string;
59
+ posterUrl?: string;
60
+ fallback?: ReactNode;
61
+ /** Suppresses the top rule. Use on the first row under a heading that draws its own. */
62
+ hideRule?: boolean;
63
+ linkComponent?: ComponentType<EventIndexRowLinkProps>;
64
+ className?: string;
65
+ };
66
+ declare function EventIndexRow({ title, as: Heading, href, when, venue, venueHref, fee, tags, description, posterUrl, fallback, hideRule, linkComponent: LinkComponent, className, }: EventIndexRowProps): react_jsx_runtime.JSX.Element;
67
+
68
+ export { EventIndexRow, type EventIndexRowLinkProps, type EventIndexRowProps };