@bearmenu/ui 0.8.50 → 0.8.52

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 (65) hide show
  1. package/dist/chunk-H4ORZT2D.js +14 -0
  2. package/dist/{chunk-S5GDARLW.js → chunk-WY2FP76J.js} +28 -5
  3. package/dist/components/alert.d.ts +2 -2
  4. package/dist/components/avatar.d.ts +2 -2
  5. package/dist/components/badge.d.ts +1 -1
  6. package/dist/components/banner.d.ts +1 -1
  7. package/dist/components/button.d.ts +1 -1
  8. package/dist/components/card.d.ts +2 -2
  9. package/dist/components/category-deck.d.ts +6 -1
  10. package/dist/components/category-deck.js +39 -35
  11. package/dist/components/empty-state.d.ts +2 -2
  12. package/dist/components/event-card.d.ts +7 -0
  13. package/dist/components/event-card.js +9 -0
  14. package/dist/components/event-compact-row.d.ts +6 -0
  15. package/dist/components/event-compact-row.js +5 -3
  16. package/dist/components/event-hub-hero.d.ts +5 -0
  17. package/dist/components/event-hub-hero.js +14 -3
  18. package/dist/components/event-list-row-wide.d.ts +6 -0
  19. package/dist/components/event-list-row-wide.js +5 -3
  20. package/dist/components/event-tonight-strip.d.ts +3 -1
  21. package/dist/components/event-tonight-strip.js +3 -2
  22. package/dist/components/featured-rail-item.d.ts +3 -1
  23. package/dist/components/featured-rail-item.js +3 -1
  24. package/dist/components/item.d.ts +2 -2
  25. package/dist/components/kitchen-dossier.d.ts +7 -1
  26. package/dist/components/kitchen-dossier.js +2 -1
  27. package/dist/components/menu-hub-hero.d.ts +7 -1
  28. package/dist/components/menu-hub-hero.js +2 -0
  29. package/dist/components/place-card.d.ts +7 -0
  30. package/dist/components/place-card.js +10 -2
  31. package/dist/components/poster-stack.d.ts +2 -0
  32. package/dist/components/poster-stack.js +2 -1
  33. package/dist/components/section-header.d.ts +6 -1
  34. package/dist/components/section-header.js +4 -2
  35. package/dist/components/sliding-panels.d.ts +6 -0
  36. package/dist/components/sliding-panels.js +13 -3
  37. package/dist/components/spinner.d.ts +2 -2
  38. package/dist/components/tag.d.ts +2 -2
  39. package/dist/components/text.d.ts +3 -3
  40. package/dist/components/timeline-day.js +1 -1
  41. package/dist/components/timeline-hour.d.ts +13 -1
  42. package/dist/components/timeline-hour.js +1 -1
  43. package/package.json +1 -1
  44. package/src/components/category-deck.tsx +11 -0
  45. package/src/components/event-card.test.tsx +6 -0
  46. package/src/components/event-card.tsx +17 -0
  47. package/src/components/event-compact-row.tsx +34 -24
  48. package/src/components/event-hub-hero.tsx +15 -1
  49. package/src/components/event-list-row-wide.tsx +25 -15
  50. package/src/components/event-tonight-strip.test.tsx +12 -0
  51. package/src/components/event-tonight-strip.tsx +8 -1
  52. package/src/components/featured-rail-item.tsx +5 -0
  53. package/src/components/kitchen-dossier.tsx +14 -1
  54. package/src/components/menu-hub-hero.tsx +13 -0
  55. package/src/components/place-card.stories.tsx +10 -0
  56. package/src/components/place-card.test.tsx +31 -0
  57. package/src/components/place-card.tsx +22 -6
  58. package/src/components/poster-stack.tsx +3 -0
  59. package/src/components/section-header.tsx +8 -1
  60. package/src/components/sliding-panels.test.tsx +26 -4
  61. package/src/components/sliding-panels.tsx +15 -4
  62. package/src/components/timeline-day.stories.tsx +30 -0
  63. package/src/components/timeline-day.test.tsx +24 -0
  64. package/src/components/timeline-hour.tsx +40 -6
  65. package/src/lib/poster-overlay-frame.tsx +26 -0
@@ -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 };
@@ -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
- hasStation && "pl-[70px] lg:pl-0",
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
- isUnscheduled && /* @__PURE__ */ jsx("span", { className: "font-mono text-[11.5px] text-muted-foreground tabular-nums lg:text-xs", children: time }),
95
- /* @__PURE__ */ jsx(Separator, { className: "flex-1" }),
96
- countLabel && /* @__PURE__ */ jsx("span", { className: "text-[10.5px] text-muted-foreground/70 lg:text-[11px]", children: countLabel })
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
  ),
@@ -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?: "default" | "destructive" | "warning" | "success" | null | undefined;
6
+ variant?: "default" | "success" | "warning" | "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?: "default" | "destructive" | "warning" | "success" | null | undefined;
9
+ variant?: "default" | "success" | "warning" | "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>>;
@@ -5,13 +5,13 @@ import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const avatarVariants: (props?: ({
7
7
  size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
8
- tone?: "muted" | "brown" | "teal" | "green" | "blue" | "violet" | "rose" | null | undefined;
8
+ tone?: "brown" | "muted" | "teal" | "green" | "blue" | "violet" | "rose" | null | undefined;
9
9
  } & class_variance_authority_types.ClassProp) | undefined) => string;
10
10
  type AvatarSize = NonNullable<VariantProps<typeof avatarVariants>["size"]>;
11
11
  type AvatarTone = NonNullable<VariantProps<typeof avatarVariants>["tone"]>;
12
12
  declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & VariantProps<(props?: ({
13
13
  size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
14
- tone?: "muted" | "brown" | "teal" | "green" | "blue" | "violet" | "rose" | null | undefined;
14
+ tone?: "brown" | "muted" | "teal" | "green" | "blue" | "violet" | "rose" | null | undefined;
15
15
  } & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLSpanElement>>;
16
16
  declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
17
17
  declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
@@ -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?: "default" | "destructive" | "warning" | "success" | "secondary" | "outline" | "glass" | "overlay" | "brown" | "code" | "onPrimary" | "confirmed" | "pending" | "completed" | "assignee" | "softSuccess" | "softWarning" | "softDestructive" | "softNeutral" | null | undefined;
7
+ variant?: "secondary" | "default" | "success" | "warning" | "destructive" | "outline" | "glass" | "overlay" | "brown" | "code" | "onPrimary" | "confirmed" | "pending" | "completed" | "assignee" | "softSuccess" | "softWarning" | "softDestructive" | "softNeutral" | null | undefined;
8
8
  size?: "status" | "chip" | null | undefined;
9
9
  live?: boolean | null | undefined;
10
10
  } & class_variance_authority_types.ClassProp) | undefined) => string;
@@ -31,7 +31,7 @@ import { VariantProps } from 'class-variance-authority';
31
31
  * right edge, centred on the text, and never wraps under it.
32
32
  */
33
33
  declare const bannerVariants: (props?: ({
34
- tone?: "destructive" | "warning" | "info" | null | undefined;
34
+ tone?: "warning" | "destructive" | "info" | null | undefined;
35
35
  } & class_variance_authority_types.ClassProp) | undefined) => string;
36
36
  type BannerProps = Omit<React.HTMLAttributes<HTMLDivElement>, "title"> & VariantProps<typeof bannerVariants> & {
37
37
  /**
@@ -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?: "default" | "destructive" | "warning" | "link" | "secondary" | "outline" | "ghost" | "glass" | "overlay" | "ink" | "brown" | "cta" | null | undefined;
6
+ variant?: "secondary" | "default" | "link" | "warning" | "destructive" | "outline" | "ghost" | "glass" | "overlay" | "ink" | "brown" | "cta" | null | undefined;
7
7
  size?: "default" | "icon" | "cta" | "xs" | "sm" | "lg" | "pill" | "cta-sm" | "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?: "muted" | "outline" | "glass" | "section" | "surface" | "elevated" | "elevatedPanel" | null | undefined;
6
+ variant?: "outline" | "glass" | "section" | "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?: "muted" | "outline" | "glass" | "section" | "surface" | "elevated" | "elevatedPanel" | null | undefined;
11
+ variant?: "outline" | "glass" | "section" | "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>>;
@@ -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__ */ jsx("div", { className: "relative h-[150px] sm:h-[186px]", "aria-hidden": true, children: slots.map((poster, index) => {
53
- var _a;
54
- const transform = DECK_CARD_TRANSFORMS[index];
55
- return /* @__PURE__ */ jsx(
56
- "div",
57
- {
58
- className: cn(
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%.
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)]",
64
- "sm:w-[120px]",
65
- transform.rest,
66
- transform.spread,
67
- transform.z,
68
- DECK_TRANSITION
69
- ),
70
- children: poster.content ? poster.content : poster.src ? (
71
- // eslint-disable-next-line @next/next/no-img-element
72
- /* @__PURE__ */ jsx(
73
- "img",
74
- {
75
- src: poster.src,
76
- alt: (_a = poster.alt) != null ? _a : "",
77
- loading: "lazy",
78
- decoding: "async",
79
- className: "h-full w-full object-cover"
80
- }
81
- )
82
- ) : /* @__PURE__ */ jsx("div", { className: "h-full w-full bg-muted" })
83
- },
84
- index
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 }),
@@ -53,7 +53,7 @@ interface EmptyStateProps {
53
53
  * louder than a load failure the user can retry.
54
54
  */
55
55
  declare const EmptyState: React.ForwardRefExoticComponent<EmptyStateProps & React.RefAttributes<HTMLDivElement>>;
56
- declare const SearchEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "variant" | "icon"> & React.RefAttributes<HTMLDivElement>>;
57
- declare const ErrorEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "variant" | "icon"> & React.RefAttributes<HTMLDivElement>>;
56
+ declare const SearchEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "icon" | "variant"> & React.RefAttributes<HTMLDivElement>>;
57
+ declare const ErrorEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "icon" | "variant"> & React.RefAttributes<HTMLDivElement>>;
58
58
 
59
59
  export { EmptyState, ErrorEmptyState, SearchEmptyState };
@@ -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__ */ jsx(
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: stat.value
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;
@@ -3,7 +3,7 @@ import { cn } from '../chunk-FEK5XGZW.js';
3
3
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
4
4
  import * as React from 'react';
5
5
  import { Clock, CalendarDays, ChevronRight } from 'lucide-react';
6
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
 
8
8
  function DefaultLink(_a) {
9
9
  var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
@@ -16,10 +16,11 @@ function EventTonightStrip({
16
16
  actionLabel,
17
17
  href,
18
18
  linkComponent: LinkComponent = DefaultLink,
19
+ liveIndicator,
19
20
  className
20
21
  }) {
21
22
  const interactive = !!href;
22
- const mark = tone === "live" ? /* @__PURE__ */ jsxs("span", { className: "relative flex h-2.5 w-2.5", "aria-hidden": true, children: [
23
+ const mark = tone === "live" && liveIndicator ? /* @__PURE__ */ jsx("span", { className: "flex h-4 w-4 items-center justify-center", "aria-hidden": true, children: liveIndicator }) : tone === "live" ? /* @__PURE__ */ jsxs("span", { className: "relative flex h-2.5 w-2.5", "aria-hidden": true, children: [
23
24
  /* @__PURE__ */ jsx("span", { className: "absolute inline-flex h-full w-full rounded-full bg-success/40 motion-live-pulse motion-reduce:animate-none" }),
24
25
  /* @__PURE__ */ jsx("span", { className: "relative inline-flex h-2.5 w-2.5 rounded-full bg-success" })
25
26
  ] }) : tone === "tonight" ? /* @__PURE__ */ jsx(Clock, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": true }) : /* @__PURE__ */ jsx(
@@ -24,6 +24,8 @@ type FeaturedRailItemProps = {
24
24
  note: string;
25
25
  /** Top-left overlay pill. Include its icon. */
26
26
  tagLabel?: React.ReactNode;
27
+ /** Decorative overlay inside the poster box (`relative`, clipping): an absolutely positioned, `aria-hidden` ornament. */
28
+ posterOverlay?: React.ReactNode;
27
29
  posterUrl?: string;
28
30
  href?: string;
29
31
  /** Defaults to a plain `<a>`. Pass `next/link` in a Next app. */
@@ -33,7 +35,7 @@ type FeaturedRailItemProps = {
33
35
  /** Rendered instead of the poster when it's absent or failed to load. Defaults to `<EventPosterFallback />`. */
34
36
  fallback?: ReactNode;
35
37
  };
36
- declare function FeaturedRailItem({ title, venue, note, tagLabel, posterUrl, href, linkComponent: LinkComponent, onClick, className, fallback, }: FeaturedRailItemProps): react_jsx_runtime.JSX.Element;
38
+ declare function FeaturedRailItem({ title, venue, note, tagLabel, posterOverlay, posterUrl, href, linkComponent: LinkComponent, onClick, className, fallback, }: FeaturedRailItemProps): react_jsx_runtime.JSX.Element;
37
39
  type FeaturedRailItemSkeletonProps = {
38
40
  className?: string;
39
41
  };
@@ -14,6 +14,7 @@ function FeaturedRailItem({
14
14
  venue,
15
15
  note,
16
16
  tagLabel,
17
+ posterOverlay,
17
18
  posterUrl,
18
19
  href,
19
20
  linkComponent: LinkComponent = DefaultLink,
@@ -40,7 +41,8 @@ function FeaturedRailItem({
40
41
  }
41
42
  )
42
43
  ) : fallback,
43
- tagLabel && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-2 top-2 flex items-start", children: /* @__PURE__ */ jsx("span", { className: "inline-flex h-6 max-w-full items-center gap-1 rounded-full bg-black/55 px-2 text-[11px] font-semibold text-white", children: tagLabel }) })
44
+ tagLabel && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-2 top-2 flex items-start", children: /* @__PURE__ */ jsx("span", { className: "inline-flex h-6 max-w-full items-center gap-1 rounded-full bg-black/55 px-2 text-[11px] font-semibold text-white", children: tagLabel }) }),
45
+ posterOverlay
44
46
  ] }),
45
47
  /* @__PURE__ */ jsxs("div", { className: "px-0.5 pt-2.5", children: [
46
48
  /* @__PURE__ */ jsx("h3", { className: "text-[13.5px] font-bold leading-[1.3]", children: title }),
@@ -3,12 +3,12 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const itemVariants: (props?: ({
6
- variant?: "default" | "muted" | "outline" | null | undefined;
6
+ variant?: "default" | "outline" | "muted" | null | undefined;
7
7
  size?: "default" | "sm" | "lg" | null | undefined;
8
8
  interactive?: boolean | null | undefined;
9
9
  } & class_variance_authority_types.ClassProp) | undefined) => string;
10
10
  declare const Item: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
11
- variant?: "default" | "muted" | "outline" | null | undefined;
11
+ variant?: "default" | "outline" | "muted" | null | undefined;
12
12
  size?: "default" | "sm" | "lg" | null | undefined;
13
13
  interactive?: boolean | null | undefined;
14
14
  } & class_variance_authority_types.ClassProp) | undefined) => string> & {
@@ -83,9 +83,15 @@ type KitchenDossierProps = {
83
83
  partDurationMs?: number;
84
84
  /** The foot's action — pass a rendered link or button. */
85
85
  action?: ReactNode;
86
+ /**
87
+ * Drawn in place of the open-until pill's dot, in the dot's slot (roughly
88
+ * 16-22px square). Decorative and `aria-hidden`; only rendered with
89
+ * `labels.openUntil`.
90
+ */
91
+ openIndicator?: ReactNode;
86
92
  linkComponent?: MenuLinkComponent;
87
93
  className?: string;
88
94
  };
89
- declare function KitchenDossier({ place, href, meta, signature, quotes, grade, labels, formatPrice, formatScore, partDurationMs, action, linkComponent: LinkComponent, className, }: KitchenDossierProps): react_jsx_runtime.JSX.Element;
95
+ declare function KitchenDossier({ place, href, meta, signature, quotes, grade, labels, formatPrice, formatScore, partDurationMs, action, openIndicator, linkComponent: LinkComponent, className, }: KitchenDossierProps): react_jsx_runtime.JSX.Element;
90
96
 
91
97
  export { KitchenDossier, type KitchenDossierLabels, type KitchenDossierLinkProps, type KitchenDossierProps };
@@ -32,6 +32,7 @@ function KitchenDossier({
32
32
  formatScore,
33
33
  partDurationMs,
34
34
  action,
35
+ openIndicator,
35
36
  linkComponent: LinkComponent = DefaultLink,
36
37
  className
37
38
  }) {
@@ -129,7 +130,7 @@ function KitchenDossier({
129
130
  }
130
131
  ),
131
132
  /* @__PURE__ */ jsx("div", { className: "relative min-h-[184px] flex-1", children: labels.openUntil && /* @__PURE__ */ jsxs("span", { className: "absolute left-0 top-3 inline-flex h-[30px] items-center gap-[7px] rounded-full bg-[oklch(0.16_0.012_55_/_0.78)] px-3 text-[11.5px] font-bold text-white", children: [
132
- /* @__PURE__ */ jsx("i", { className: "h-[7px] w-[7px] rounded-full bg-success", "aria-hidden": true }),
133
+ openIndicator ? /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-center justify-center", "aria-hidden": true, children: openIndicator }) : /* @__PURE__ */ jsx("i", { className: "h-[7px] w-[7px] rounded-full bg-success", "aria-hidden": true }),
133
134
  labels.openUntil
134
135
  ] }) }),
135
136
  /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col gap-3.5", children: [
@@ -64,8 +64,14 @@ type MenuHubHeroProps = {
64
64
  * `h2` so the document has one h1, not two.
65
65
  */
66
66
  headingLevel?: "h1" | "h2";
67
+ /**
68
+ * A decorative layer over the photographs and their scrim, under the text:
69
+ * fill the banner with `absolute inset-0`. Clipped by the banner's rounded
70
+ * edge. Decorative and `aria-hidden`.
71
+ */
72
+ sceneOverlay?: React.ReactNode;
67
73
  className?: string;
68
74
  };
69
- declare function MenuHubHero({ kicker, kickerIcon, headline, body, figures, proof, proofIcon, action, backgroundUrl, tileUrls, headingLevel: Heading, className, }: MenuHubHeroProps): react_jsx_runtime.JSX.Element;
75
+ declare function MenuHubHero({ kicker, kickerIcon, headline, body, figures, proof, proofIcon, action, backgroundUrl, tileUrls, headingLevel: Heading, sceneOverlay, className, }: MenuHubHeroProps): react_jsx_runtime.JSX.Element;
70
76
 
71
77
  export { MenuHubHero, type MenuHubHeroFigure, type MenuHubHeroProps };
@@ -16,6 +16,7 @@ function MenuHubHero({
16
16
  backgroundUrl,
17
17
  tileUrls,
18
18
  headingLevel: Heading = "h1",
19
+ sceneOverlay,
19
20
  className
20
21
  }) {
21
22
  return /* @__PURE__ */ jsxs(
@@ -81,6 +82,7 @@ function MenuHubHero({
81
82
  )
82
83
  }
83
84
  ),
85
+ sceneOverlay && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-0", children: sceneOverlay }),
84
86
  /* @__PURE__ */ jsxs("div", { className: "relative z-[1] flex w-full flex-col justify-center gap-3 p-5 text-white lg:gap-4 lg:px-12 lg:py-11", children: [
85
87
  kicker && /* @__PURE__ */ jsxs("span", { className: "inline-flex w-max items-center gap-[7px] rounded-full bg-white/15 px-3 py-1.5 text-[11px] font-extrabold tracking-[0.11em]", children: [
86
88
  kickerIcon,