@bearmenu/ui 0.8.49 → 0.8.50
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-QY66ME5B.js → chunk-CZ2HC7WY.js} +24 -6
- package/dist/components/alert.d.ts +2 -2
- package/dist/components/avatar.d.ts +2 -2
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/banner.d.ts +1 -1
- package/dist/components/button.d.ts +2 -2
- package/dist/components/card.d.ts +2 -2
- package/dist/components/command.d.ts +3 -3
- package/dist/components/concept-compare.d.ts +1 -1
- package/dist/components/doorway-tiles.d.ts +1 -1
- package/dist/components/empty-state.d.ts +2 -2
- package/dist/components/event-detail-panel.d.ts +12 -2
- package/dist/components/event-detail-panel.js +15 -3
- package/dist/components/grade-atom.d.ts +1 -1
- package/dist/components/item.d.ts +2 -2
- package/dist/components/kitchen-dossier.d.ts +1 -1
- package/dist/components/menu-dead-end.d.ts +1 -1
- package/dist/components/menu-family-block.d.ts +2 -2
- package/dist/components/menu-family-block.js +3 -1
- package/dist/components/menu-family-card.d.ts +1 -1
- package/dist/components/menu-filter-chips.d.ts +1 -1
- package/dist/components/menu-group-rows.d.ts +1 -1
- package/dist/components/menu-index-header.d.ts +1 -1
- package/dist/components/menu-index-list.d.ts +1 -1
- package/dist/components/menu-intent-hero.d.ts +1 -1
- package/dist/components/menu-item.d.ts +1 -1
- package/dist/components/menu-kitchen-list.d.ts +9 -2
- package/dist/components/menu-kitchen-list.js +3 -1
- package/dist/components/menu-mocks.d.ts +1 -1
- package/dist/components/menu-types.d.ts +1 -1
- package/dist/components/open-now-list.d.ts +1 -1
- package/dist/components/place-about-tab.d.ts +1 -1
- package/dist/components/place-card.d.ts +1 -1
- package/dist/components/place-details-mobile.d.ts +1 -1
- package/dist/components/place-schedule-week.d.ts +1 -1
- package/dist/components/place-types.d.ts +1 -1
- package/dist/components/qa-block.d.ts +1 -1
- 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/toggle.d.ts +1 -1
- package/dist/components/top-comparison.d.ts +1 -1
- package/dist/components/top-cross-link.d.ts +1 -1
- package/dist/components/top-ranking-entry.d.ts +1 -1
- package/dist/components/top-ranking-hero.d.ts +1 -1
- package/dist/components/top-types.d.ts +1 -1
- package/dist/components/venue-grade-dimensions.d.ts +1 -1
- package/dist/components/venue-quotes.d.ts +1 -1
- package/dist/components/venue-wall.d.ts +1 -1
- package/dist/{place-types-DCVqWmk_.d.ts → place-types-Dzy6FH67.d.ts} +1 -1
- package/package.json +1 -1
- package/src/components/event-detail-panel.test.tsx +35 -0
- package/src/components/event-detail-panel.tsx +32 -10
- package/src/components/menu-kitchen-list.test.tsx +39 -0
- package/src/components/menu-kitchen-list.tsx +36 -7
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { GradeAtom } from './chunk-YE4ZQUTI.js';
|
|
2
|
+
import { showsGradeAtom } from './chunk-I5V446BX.js';
|
|
1
3
|
import { Separator } from './chunk-NWZGSLPU.js';
|
|
2
4
|
import { Skeleton } from './chunk-XBBEX4SF.js';
|
|
3
5
|
import { cn } from './chunk-FEK5XGZW.js';
|
|
4
6
|
import { __objRest, __spreadValues } from './chunk-MMUBH76A.js';
|
|
5
|
-
import {
|
|
7
|
+
import { Clock, Check, MessageSquare, ChevronRight, Star } from 'lucide-react';
|
|
6
8
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
9
|
|
|
8
10
|
function DefaultLink(_a) {
|
|
@@ -41,6 +43,25 @@ function MenuKitchenList({
|
|
|
41
43
|
)
|
|
42
44
|
] });
|
|
43
45
|
}
|
|
46
|
+
function gradeShown(place, labels) {
|
|
47
|
+
var _a;
|
|
48
|
+
return labels.grade !== void 0 && showsGradeAtom((_a = place.reviews_digest) == null ? void 0 : _a.grade, "xs");
|
|
49
|
+
}
|
|
50
|
+
function KitchenRating({
|
|
51
|
+
place,
|
|
52
|
+
labels
|
|
53
|
+
}) {
|
|
54
|
+
var _a;
|
|
55
|
+
const grade = (_a = place.reviews_digest) == null ? void 0 : _a.grade;
|
|
56
|
+
if (labels.grade && showsGradeAtom(grade, "xs")) {
|
|
57
|
+
return /* @__PURE__ */ jsx(GradeAtom, { grade, labels: labels.grade, size: "xs", className: "shrink-0" });
|
|
58
|
+
}
|
|
59
|
+
if (!place.rating) return null;
|
|
60
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
61
|
+
/* @__PURE__ */ jsx(Star, { className: "h-[11px] w-[11px] shrink-0", "aria-hidden": true }),
|
|
62
|
+
place.rating.rating
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
44
65
|
function KitchenRow({
|
|
45
66
|
kitchen,
|
|
46
67
|
labels,
|
|
@@ -99,11 +120,8 @@ function KitchenRow({
|
|
|
99
120
|
children: [
|
|
100
121
|
/* @__PURE__ */ jsx("span", { className: "truncate text-[14.5px] font-bold tracking-[-0.01em] lg:line-clamp-2 lg:whitespace-normal lg:text-[15.5px] lg:leading-tight", children: place.name }),
|
|
101
122
|
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 truncate text-xs text-muted-foreground", children: [
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
place.rating.rating,
|
|
105
|
-
kitchen.metaLabel && " \xB7 "
|
|
106
|
-
] }),
|
|
123
|
+
/* @__PURE__ */ jsx(KitchenRating, { place, labels }),
|
|
124
|
+
kitchen.metaLabel && (gradeShown(place, labels) || place.rating) && " \xB7 ",
|
|
107
125
|
kitchen.metaLabel
|
|
108
126
|
] }),
|
|
109
127
|
kitchen.hoursLabel && /* @__PURE__ */ jsxs(
|
|
@@ -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?: "default" | "destructive" | "warning" | "success" | 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?: "default" | "destructive" | "warning" | "success" | 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?: "
|
|
8
|
+
tone?: "muted" | "brown" | "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?: "
|
|
14
|
+
tone?: "muted" | "brown" | "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?: "
|
|
7
|
+
variant?: "default" | "destructive" | "warning" | "success" | "secondary" | "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?: "
|
|
34
|
+
tone?: "destructive" | "warning" | "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,8 +3,8 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
7
|
-
size?: "
|
|
6
|
+
variant?: "default" | "destructive" | "warning" | "link" | "secondary" | "outline" | "ghost" | "glass" | "overlay" | "ink" | "brown" | "cta" | null | undefined;
|
|
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;
|
|
10
10
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -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?: "muted" | "outline" | "glass" | "section" | "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?: "muted" | "outline" | "glass" | "section" | "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>>;
|
|
@@ -28,7 +28,7 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
|
|
|
28
28
|
ref?: React.Ref<HTMLInputElement>;
|
|
29
29
|
} & {
|
|
30
30
|
asChild?: boolean;
|
|
31
|
-
}, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "
|
|
31
|
+
}, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "value" | "type"> & {
|
|
32
32
|
value?: string;
|
|
33
33
|
onValueChange?: (search: string) => void;
|
|
34
34
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -64,7 +64,7 @@ declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
|
64
64
|
ref?: React.Ref<HTMLDivElement>;
|
|
65
65
|
} & {
|
|
66
66
|
asChild?: boolean;
|
|
67
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key">, "
|
|
67
|
+
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key">, "heading" | "value"> & {
|
|
68
68
|
heading?: React.ReactNode;
|
|
69
69
|
value?: string;
|
|
70
70
|
forceMount?: boolean;
|
|
@@ -82,7 +82,7 @@ declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
|
82
82
|
ref?: React.Ref<HTMLDivElement>;
|
|
83
83
|
} & {
|
|
84
84
|
asChild?: boolean;
|
|
85
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key">, "
|
|
85
|
+
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key">, "onSelect" | "value" | "disabled"> & {
|
|
86
86
|
disabled?: boolean;
|
|
87
87
|
onSelect?: (value: string) => void;
|
|
88
88
|
value?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { MenuConceptPreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
3
3
|
import 'react';
|
|
4
|
-
import '../place-types-
|
|
4
|
+
import '../place-types-Dzy6FH67.js';
|
|
5
5
|
import '../lib/grade.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -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, "
|
|
57
|
-
declare const ErrorEmptyState: React.ForwardRefExoticComponent<Omit<EmptyStateProps, "
|
|
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>>;
|
|
58
58
|
|
|
59
59
|
export { EmptyState, ErrorEmptyState, SearchEmptyState };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { G as GradeAtomLabels, a as PlaceGrade } from '../place-types-Dzy6FH67.js';
|
|
3
4
|
import { EventPreview, EventFormatters } from './event-types.js';
|
|
5
|
+
import '../lib/grade.js';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* EventDetailPanel — the BODY of the event detail sheet, and the body the
|
|
@@ -51,7 +53,13 @@ type EventDetailVenue = {
|
|
|
51
53
|
name: string;
|
|
52
54
|
/** Address line, e.g. "Str. Iuliu Maniu 5". */
|
|
53
55
|
address?: string;
|
|
54
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* The venue's BearMenu grade. Shown as the grade pill in the rating's place
|
|
58
|
+
* when `labels.grade` is given; the star `ratingLabel` then stays only for a
|
|
59
|
+
* venue without a grade.
|
|
60
|
+
*/
|
|
61
|
+
grade?: PlaceGrade;
|
|
62
|
+
/** e.g. "4.7" — Google's rating, rendered with a star. The fallback for an ungraded venue. */
|
|
55
63
|
ratingLabel?: string;
|
|
56
64
|
/** e.g. "open until 20:00" — appended to the meta row when given. */
|
|
57
65
|
openLabel?: string;
|
|
@@ -66,6 +74,8 @@ type EventDetailVenue = {
|
|
|
66
74
|
href?: string;
|
|
67
75
|
};
|
|
68
76
|
type EventDetailPanelLabels = {
|
|
77
|
+
/** The venue's grade pill. Optional: without it the venue shows the star, as before. */
|
|
78
|
+
grade?: GradeAtomLabels;
|
|
69
79
|
free: string;
|
|
70
80
|
liveNow: string;
|
|
71
81
|
/** The ended chip, e.g. "Ended". */
|
|
@@ -208,7 +218,7 @@ type EventDetailChipRowProps = Pick<EventDetailPanelProps, "event" | "formatters
|
|
|
208
218
|
declare function EventDetailChipRow({ event, labels, formatters, status, soonLabel, hype, tags, className, }: EventDetailChipRowProps): react_jsx_runtime.JSX.Element;
|
|
209
219
|
type EventDetailVenueCardProps = {
|
|
210
220
|
venue: EventDetailVenue;
|
|
211
|
-
labels: Pick<EventDetailPanelLabels, "venueNoPage">;
|
|
221
|
+
labels: Pick<EventDetailPanelLabels, "venueNoPage" | "grade">;
|
|
212
222
|
linkComponent?: React.ComponentType<EventDetailPanelLinkProps>;
|
|
213
223
|
/** Thumbnail size in px: 52 in the sheet, 64 on the page. */
|
|
214
224
|
thumbnailSize?: 52 | 64;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { GradeAtom } from '../chunk-YE4ZQUTI.js';
|
|
2
|
+
import { showsGradeAtom } from '../chunk-I5V446BX.js';
|
|
1
3
|
import { resolveEventEntryFee } from '../chunk-DNSXMHYX.js';
|
|
2
4
|
import { Separator } from '../chunk-NWZGSLPU.js';
|
|
3
5
|
import { EventPosterFallback } from '../chunk-FDITZ2VM.js';
|
|
@@ -463,7 +465,9 @@ function EventDetailVenueCard({
|
|
|
463
465
|
action,
|
|
464
466
|
className
|
|
465
467
|
}) {
|
|
466
|
-
const
|
|
468
|
+
const showGrade = labels.grade !== void 0 && showsGradeAtom(venue.grade, "xs");
|
|
469
|
+
const hasRating = showGrade || Boolean(venue.ratingLabel);
|
|
470
|
+
const meta = venue.href && (venue.address || hasRating || venue.openLabel);
|
|
467
471
|
const main = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
468
472
|
/* @__PURE__ */ jsxs(
|
|
469
473
|
"div",
|
|
@@ -501,8 +505,16 @@ function EventDetailVenueCard({
|
|
|
501
505
|
/* @__PURE__ */ jsx("div", { className: "truncate text-sm font-bold", children: venue.name }),
|
|
502
506
|
venue.href ? meta && /* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-1.5 text-xs text-muted-foreground", children: [
|
|
503
507
|
venue.address && /* @__PURE__ */ jsx("span", { className: "truncate", children: venue.address }),
|
|
504
|
-
venue.address &&
|
|
505
|
-
|
|
508
|
+
venue.address && hasRating && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-border", children: "\xB7" }),
|
|
509
|
+
showGrade && labels.grade && venue.grade ? /* @__PURE__ */ jsx(
|
|
510
|
+
GradeAtom,
|
|
511
|
+
{
|
|
512
|
+
grade: venue.grade,
|
|
513
|
+
labels: labels.grade,
|
|
514
|
+
size: "xs",
|
|
515
|
+
className: "shrink-0"
|
|
516
|
+
}
|
|
517
|
+
) : venue.ratingLabel && /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-1", children: [
|
|
506
518
|
/* @__PURE__ */ jsx(Star, { className: "h-[11px] w-[11px]", "aria-hidden": true }),
|
|
507
519
|
venue.ratingLabel
|
|
508
520
|
] }),
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import 'react/jsx-runtime';
|
|
2
2
|
import '../lib/grade.js';
|
|
3
|
-
export {
|
|
3
|
+
export { i as GradeAtom, G as GradeAtomLabels, j as GradeAtomProps, k as GradeAtomSize } from '../place-types-Dzy6FH67.js';
|
|
@@ -3,12 +3,12 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const itemVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "
|
|
6
|
+
variant?: "default" | "muted" | "outline" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
interactive?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
declare const Item: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
11
|
-
variant?: "default" | "
|
|
11
|
+
variant?: "default" | "muted" | "outline" | null | undefined;
|
|
12
12
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
13
13
|
interactive?: boolean | null | undefined;
|
|
14
14
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { MenuVenueSignature, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
4
|
-
import { P as PlacePreview, C as CitedText,
|
|
4
|
+
import { P as PlacePreview, C as CitedText, b as PlaceGradeDimensions } from '../place-types-Dzy6FH67.js';
|
|
5
5
|
import { VenueGradeDimensionKey } from './venue-grade-dimensions.js';
|
|
6
6
|
import '../lib/grade.js';
|
|
7
7
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { MenuKitchenListLabels } from './menu-kitchen-list.js';
|
|
3
3
|
import { MenuFamilyBlockPreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
4
|
-
import '
|
|
5
|
-
import '../place-types-DCVqWmk_.js';
|
|
4
|
+
import '../place-types-Dzy6FH67.js';
|
|
6
5
|
import '../lib/grade.js';
|
|
6
|
+
import 'react';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* MenuFamilyBlock — the cuisines index's family card. One photograph is the ground.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { MenuKitchenList } from '../chunk-
|
|
1
|
+
import { MenuKitchenList } from '../chunk-CZ2HC7WY.js';
|
|
2
2
|
import { HueChip } from '../chunk-6VOWT4YR.js';
|
|
3
|
+
import '../chunk-YE4ZQUTI.js';
|
|
4
|
+
import '../chunk-I5V446BX.js';
|
|
3
5
|
import { Separator } from '../chunk-NWZGSLPU.js';
|
|
4
6
|
import { PhotoGround, PHOTO_GROUND } from '../chunk-SWD6CJ35.js';
|
|
5
7
|
import { Skeleton } from '../chunk-XBBEX4SF.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { MenuFamilyPreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
3
3
|
import 'react';
|
|
4
|
-
import '../place-types-
|
|
4
|
+
import '../place-types-Dzy6FH67.js';
|
|
5
5
|
import '../lib/grade.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { MenuIndexEntry, MenuLinkComponent } from './menu-types.js';
|
|
3
3
|
import 'react';
|
|
4
|
-
import '../place-types-
|
|
4
|
+
import '../place-types-Dzy6FH67.js';
|
|
5
5
|
import '../lib/grade.js';
|
|
6
6
|
|
|
7
7
|
type MenuIndexHeaderProps = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { MenuIndexEntry, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
3
3
|
import 'react';
|
|
4
|
-
import '../place-types-
|
|
4
|
+
import '../place-types-Dzy6FH67.js';
|
|
5
5
|
import '../lib/grade.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
import { MenuItemPreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
4
|
-
import '../place-types-
|
|
4
|
+
import '../place-types-Dzy6FH67.js';
|
|
5
5
|
import '../lib/grade.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { G as GradeAtomLabels } from '../place-types-Dzy6FH67.js';
|
|
2
3
|
import { MenuKitchenPreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
3
|
-
import 'react';
|
|
4
|
-
import '../place-types-DCVqWmk_.js';
|
|
5
4
|
import '../lib/grade.js';
|
|
5
|
+
import 'react';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* MenuKitchenList — the intent page's spine.
|
|
@@ -53,6 +53,13 @@ type MenuKitchenListLabels = {
|
|
|
53
53
|
openNow: string;
|
|
54
54
|
/** Reveals the next page of rows, e.g. "Show 10 more". */
|
|
55
55
|
showMore?: string;
|
|
56
|
+
/**
|
|
57
|
+
* The grade pill's labels. With them, a graded venue shows its BearMenu
|
|
58
|
+
* grade where the Google star was; the star stays only for a venue with no
|
|
59
|
+
* grade. Optional so existing callers keep compiling — without it every row
|
|
60
|
+
* shows the star, as before.
|
|
61
|
+
*/
|
|
62
|
+
grade?: GradeAtomLabels;
|
|
56
63
|
};
|
|
57
64
|
/**
|
|
58
65
|
* `wide` (default): the intent page's full-width list — from `lg` the venue
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { MenuKitchenList, MenuKitchenListSkeleton } from '../chunk-
|
|
1
|
+
export { MenuKitchenList, MenuKitchenListSkeleton } from '../chunk-CZ2HC7WY.js';
|
|
2
|
+
import '../chunk-YE4ZQUTI.js';
|
|
3
|
+
import '../chunk-I5V446BX.js';
|
|
2
4
|
import '../chunk-NWZGSLPU.js';
|
|
3
5
|
import '../chunk-XBBEX4SF.js';
|
|
4
6
|
import '../chunk-FEK5XGZW.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MenuFamilyBlockPreview, MenuConceptPreview, MenuFamilyPreview, MenuFilterChip, MenuIndexEntry, MenuIntentFigure, MenuItemPreview, MenuKitchenPreview, MenuLoosenOption, QaItem, MenuVenuePreview } from './menu-types.js';
|
|
2
2
|
import { DoorwayTile } from './doorway-tiles.js';
|
|
3
|
-
import { P as PlacePreview } from '../place-types-
|
|
3
|
+
import { P as PlacePreview } from '../place-types-Dzy6FH67.js';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'react/jsx-runtime';
|
|
6
6
|
import '../lib/grade.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentType, CSSProperties, ReactNode } from 'react';
|
|
2
|
-
import { M as MenuSizeAndPrice, P as PlacePreview } from '../place-types-
|
|
2
|
+
import { M as MenuSizeAndPrice, P as PlacePreview } from '../place-types-Dzy6FH67.js';
|
|
3
3
|
import 'react/jsx-runtime';
|
|
4
4
|
import '../lib/grade.js';
|
|
5
5
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { MenuVenuePreview, MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
3
3
|
import 'react';
|
|
4
|
-
import '../place-types-
|
|
4
|
+
import '../place-types-Dzy6FH67.js';
|
|
5
5
|
import '../lib/grade.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { P as PlacePreview,
|
|
2
|
+
import { P as PlacePreview, c as PlaceAboutTabLabels, d as PlaceLinkKind } from '../place-types-Dzy6FH67.js';
|
|
3
3
|
import '../lib/grade.js';
|
|
4
4
|
|
|
5
5
|
interface PlaceAboutTabProps {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React$1 from 'react';
|
|
3
3
|
import { ReactNode, MouseEvent } from 'react';
|
|
4
|
-
import { P as PlacePreview,
|
|
4
|
+
import { P as PlacePreview, e as PlaceCardLabels } from '../place-types-Dzy6FH67.js';
|
|
5
5
|
import '../lib/grade.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { P as PlacePreview,
|
|
2
|
+
import { P as PlacePreview, f as PlaceDetailsMobileLabels } from '../place-types-Dzy6FH67.js';
|
|
3
3
|
import '../lib/grade.js';
|
|
4
4
|
|
|
5
5
|
interface PlaceDetailsMobileProps {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { g as PlaceSchedule, h as PlaceScheduleWeekLabels } from '../place-types-Dzy6FH67.js';
|
|
3
3
|
import '../lib/grade.js';
|
|
4
4
|
|
|
5
5
|
interface PlaceScheduleWeekProps {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { C as CitedText,
|
|
1
|
+
export { C as CitedText, l as CitedValue, M as MenuSizeAndPrice, c as PlaceAboutTabLabels, e as PlaceCardLabels, f as PlaceDetailsMobileLabels, a as PlaceGrade, b as PlaceGradeDimensions, m as PlaceHourBlock, d as PlaceLinkKind, n as PlaceMustTry, P as PlacePreview, o as PlacePriceRange, p as PlaceReviewsDigest, g as PlaceSchedule, h as PlaceScheduleWeekLabels, W as WeekdayKey } from '../place-types-Dzy6FH67.js';
|
|
2
2
|
import 'react/jsx-runtime';
|
|
3
3
|
import '../lib/grade.js';
|
|
@@ -4,11 +4,11 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
|
|
5
5
|
declare const spinnerVariants: (props?: ({
|
|
6
6
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
7
|
-
tone?: "
|
|
7
|
+
tone?: "default" | "destructive" | "inherit" | "primary" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const Spinner: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
|
|
10
10
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
11
|
-
tone?: "
|
|
11
|
+
tone?: "default" | "destructive" | "inherit" | "primary" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
/** Visually-hidden label for screen readers. Defaults to "Loading". */
|
|
14
14
|
label?: string;
|
package/dist/components/tag.d.ts
CHANGED
|
@@ -3,11 +3,11 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const tagVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "default" | "destructive" | "warning" | "success" | "primary" | "outline" | "quiet" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const Tag: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
|
|
10
|
-
variant?: "
|
|
10
|
+
variant?: "default" | "destructive" | "warning" | "success" | "primary" | "outline" | "quiet" | null | undefined;
|
|
11
11
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
onRemove?: () => void;
|
|
@@ -22,9 +22,9 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
22
22
|
* Weights are 400 / 600 / 700. 500 is not in the system.
|
|
23
23
|
*/
|
|
24
24
|
declare const textVariants: (props?: ({
|
|
25
|
-
variant?: "
|
|
26
|
-
color?: "
|
|
27
|
-
weight?: "bold" | "
|
|
25
|
+
variant?: "small" | "display" | "h1" | "h2" | "h3" | "h4" | "body-lg" | "body" | "body-sm" | "caption" | "label" | "overline" | null | undefined;
|
|
26
|
+
color?: "default" | "destructive" | "inherit" | "muted" | "primary" | "primary-foreground" | null | undefined;
|
|
27
|
+
weight?: "bold" | "normal" | "medium" | "semibold" | null | undefined;
|
|
28
28
|
leading?: "none" | "normal" | "tight" | "snug" | "relaxed" | "loose" | null | undefined;
|
|
29
29
|
tracking?: "normal" | "tight" | "wide" | "wider" | null | undefined;
|
|
30
30
|
wrap?: "balance" | "pretty" | "nowrap" | null | undefined;
|
|
@@ -11,7 +11,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
11
11
|
* `data-[state=on]:` utilities sort after `hover:` and still win while on.
|
|
12
12
|
*/
|
|
13
13
|
declare const toggleVariants: (props?: ({
|
|
14
|
-
variant?: "
|
|
14
|
+
variant?: "default" | "tab" | "outline" | "chip" | "segmented" | null | undefined;
|
|
15
15
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
16
16
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
17
17
|
/**
|
|
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { MenuLinkComponent } from './menu-types.js';
|
|
3
3
|
import { TopComparisonRow } from './top-types.js';
|
|
4
4
|
import 'react';
|
|
5
|
-
import '../place-types-
|
|
5
|
+
import '../place-types-Dzy6FH67.js';
|
|
6
6
|
import '../lib/grade.js';
|
|
7
7
|
|
|
8
8
|
type TopComparisonLabels = {
|
|
@@ -3,7 +3,7 @@ import { MenuItemLabels } from './menu-item.js';
|
|
|
3
3
|
import { MenuItemPreview, MenuLinkComponent } from './menu-types.js';
|
|
4
4
|
import { TopRankEntry } from './top-types.js';
|
|
5
5
|
import 'react';
|
|
6
|
-
import '../place-types-
|
|
6
|
+
import '../place-types-Dzy6FH67.js';
|
|
7
7
|
import '../lib/grade.js';
|
|
8
8
|
|
|
9
9
|
type TopRankingEntryLabels = {
|
|
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { MenuLinkComponent } from './menu-types.js';
|
|
3
3
|
import { TopExit } from './top-types.js';
|
|
4
4
|
import 'react';
|
|
5
|
-
import '../place-types-
|
|
5
|
+
import '../place-types-Dzy6FH67.js';
|
|
6
6
|
import '../lib/grade.js';
|
|
7
7
|
|
|
8
8
|
type TopRankingHeroProps = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { MenuLinkComponent, MenuLinkProps } from './menu-types.js';
|
|
3
|
-
import { P as PlacePreview } from '../place-types-
|
|
3
|
+
import { P as PlacePreview } from '../place-types-Dzy6FH67.js';
|
|
4
4
|
import 'react';
|
|
5
5
|
import '../lib/grade.js';
|
|
6
6
|
|
|
@@ -332,4 +332,4 @@ type PlaceDetailsMobileLabels = PlaceAboutTabLabels & {
|
|
|
332
332
|
noImageAvailable: string;
|
|
333
333
|
};
|
|
334
334
|
|
|
335
|
-
export { type CitedText as C,
|
|
335
|
+
export { type CitedText as C, type GradeAtomLabels as G, type MenuSizeAndPrice as M, type PlacePreview as P, type WeekdayKey as W, type PlaceGrade as a, type PlaceGradeDimensions as b, type PlaceAboutTabLabels as c, type PlaceLinkKind as d, type PlaceCardLabels as e, type PlaceDetailsMobileLabels as f, type PlaceSchedule as g, type PlaceScheduleWeekLabels as h, GradeAtom as i, type GradeAtomProps as j, type GradeAtomSize as k, type CitedValue as l, type PlaceHourBlock as m, type PlaceMustTry as n, type PlacePriceRange as o, type PlaceReviewsDigest as p };
|
package/package.json
CHANGED
|
@@ -84,6 +84,41 @@ describe("EventDetailPanel", () => {
|
|
|
84
84
|
expect(screen.getByText(labels.venueNoPage)).toBeInTheDocument();
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
+
it("shows the venue's BearMenu grade instead of the Google star when given", () => {
|
|
88
|
+
const venue = {
|
|
89
|
+
name: "Sophie",
|
|
90
|
+
address: "Str. 5",
|
|
91
|
+
ratingLabel: "4.7",
|
|
92
|
+
href: "/places/sophie",
|
|
93
|
+
grade: { overall: 8.7, show_number: true },
|
|
94
|
+
};
|
|
95
|
+
const gradeLabels = {
|
|
96
|
+
soft: "Few reviews",
|
|
97
|
+
bands: {
|
|
98
|
+
exceptional: "Exceptional",
|
|
99
|
+
great: "Great",
|
|
100
|
+
good: "Good",
|
|
101
|
+
decent: "Decent",
|
|
102
|
+
weak: "Weak",
|
|
103
|
+
},
|
|
104
|
+
aria: (value: string) => `Grade ${value}`,
|
|
105
|
+
capped: "Capped",
|
|
106
|
+
};
|
|
107
|
+
const { container, rerender } = render(
|
|
108
|
+
<EventDetailPanel
|
|
109
|
+
{...base}
|
|
110
|
+
labels={{ ...labels, grade: gradeLabels }}
|
|
111
|
+
venue={venue}
|
|
112
|
+
/>,
|
|
113
|
+
);
|
|
114
|
+
expect(container.textContent).toMatch(/8[.,]7/);
|
|
115
|
+
expect(container.textContent).not.toContain("4.7");
|
|
116
|
+
|
|
117
|
+
// No grade labels: exactly the old card.
|
|
118
|
+
rerender(<EventDetailPanel {...base} venue={venue} />);
|
|
119
|
+
expect(container.textContent).toContain("4.7");
|
|
120
|
+
});
|
|
121
|
+
|
|
87
122
|
it("previews five performers and reveals the rest on request", () => {
|
|
88
123
|
const performers = ["A", "B", "C", "D", "E", "F", "G"];
|
|
89
124
|
render(
|
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
Unplug,
|
|
15
15
|
User,
|
|
16
16
|
} from "lucide-react";
|
|
17
|
+
import { showsGradeAtom } from "../lib/grade";
|
|
17
18
|
import { cn } from "../lib/utils";
|
|
19
|
+
import { GradeAtom, type GradeAtomLabels } from "./grade-atom";
|
|
20
|
+
import type { PlaceGrade } from "./place-types";
|
|
18
21
|
import { Button } from "./button";
|
|
19
22
|
import { EventPosterFallback } from "./event-poster-fallback";
|
|
20
23
|
import { Separator } from "./separator";
|
|
@@ -81,7 +84,13 @@ export type EventDetailVenue = {
|
|
|
81
84
|
name: string;
|
|
82
85
|
/** Address line, e.g. "Str. Iuliu Maniu 5". */
|
|
83
86
|
address?: string;
|
|
84
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* The venue's BearMenu grade. Shown as the grade pill in the rating's place
|
|
89
|
+
* when `labels.grade` is given; the star `ratingLabel` then stays only for a
|
|
90
|
+
* venue without a grade.
|
|
91
|
+
*/
|
|
92
|
+
grade?: PlaceGrade;
|
|
93
|
+
/** e.g. "4.7" — Google's rating, rendered with a star. The fallback for an ungraded venue. */
|
|
85
94
|
ratingLabel?: string;
|
|
86
95
|
/** e.g. "open until 20:00" — appended to the meta row when given. */
|
|
87
96
|
openLabel?: string;
|
|
@@ -97,6 +106,8 @@ export type EventDetailVenue = {
|
|
|
97
106
|
};
|
|
98
107
|
|
|
99
108
|
export type EventDetailPanelLabels = {
|
|
109
|
+
/** The venue's grade pill. Optional: without it the venue shows the star, as before. */
|
|
110
|
+
grade?: GradeAtomLabels;
|
|
100
111
|
free: string;
|
|
101
112
|
liveNow: string;
|
|
102
113
|
/** The ended chip, e.g. "Ended". */
|
|
@@ -752,7 +763,7 @@ export function EventDetailChipRow({
|
|
|
752
763
|
|
|
753
764
|
export type EventDetailVenueCardProps = {
|
|
754
765
|
venue: EventDetailVenue;
|
|
755
|
-
labels: Pick<EventDetailPanelLabels, "venueNoPage">;
|
|
766
|
+
labels: Pick<EventDetailPanelLabels, "venueNoPage" | "grade">;
|
|
756
767
|
linkComponent?: React.ComponentType<EventDetailPanelLinkProps>;
|
|
757
768
|
/** Thumbnail size in px: 52 in the sheet, 64 on the page. */
|
|
758
769
|
thumbnailSize?: 52 | 64;
|
|
@@ -774,8 +785,10 @@ export function EventDetailVenueCard({
|
|
|
774
785
|
action,
|
|
775
786
|
className,
|
|
776
787
|
}: EventDetailVenueCardProps) {
|
|
777
|
-
const
|
|
778
|
-
|
|
788
|
+
const showGrade =
|
|
789
|
+
labels.grade !== undefined && showsGradeAtom(venue.grade, "xs");
|
|
790
|
+
const hasRating = showGrade || Boolean(venue.ratingLabel);
|
|
791
|
+
const meta = venue.href && (venue.address || hasRating || venue.openLabel);
|
|
779
792
|
// The main area (thumb, name, meta, chevron) is the link; `action` sits
|
|
780
793
|
// BESIDE it, never inside — an anchor cannot contain another control, and a
|
|
781
794
|
// page's "Open in Maps" must not navigate to the venue instead.
|
|
@@ -816,16 +829,25 @@ export function EventDetailVenueCard({
|
|
|
816
829
|
{venue.address && (
|
|
817
830
|
<span className="truncate">{venue.address}</span>
|
|
818
831
|
)}
|
|
819
|
-
{venue.address &&
|
|
832
|
+
{venue.address && hasRating && (
|
|
820
833
|
<span aria-hidden className="text-border">
|
|
821
834
|
·
|
|
822
835
|
</span>
|
|
823
836
|
)}
|
|
824
|
-
{
|
|
825
|
-
<
|
|
826
|
-
|
|
827
|
-
{
|
|
828
|
-
|
|
837
|
+
{showGrade && labels.grade && venue.grade ? (
|
|
838
|
+
<GradeAtom
|
|
839
|
+
grade={venue.grade}
|
|
840
|
+
labels={labels.grade}
|
|
841
|
+
size="xs"
|
|
842
|
+
className="shrink-0"
|
|
843
|
+
/>
|
|
844
|
+
) : (
|
|
845
|
+
venue.ratingLabel && (
|
|
846
|
+
<span className="inline-flex shrink-0 items-center gap-1">
|
|
847
|
+
<Star className="h-[11px] w-[11px]" aria-hidden />
|
|
848
|
+
{venue.ratingLabel}
|
|
849
|
+
</span>
|
|
850
|
+
)
|
|
829
851
|
)}
|
|
830
852
|
{venue.openLabel && (
|
|
831
853
|
<>
|
|
@@ -24,6 +24,45 @@ const kitchen: MenuKitchenPreview = {
|
|
|
24
24
|
},
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
const gradeLabels = {
|
|
28
|
+
soft: "Few reviews",
|
|
29
|
+
bands: { exceptional: "Exceptional", great: "Great", good: "Good", decent: "Decent", weak: "Weak" },
|
|
30
|
+
aria: (value: string) => `Grade ${value}`,
|
|
31
|
+
capped: "Capped",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
describe("MenuKitchenList rating", () => {
|
|
35
|
+
const graded = {
|
|
36
|
+
...kitchen,
|
|
37
|
+
place: {
|
|
38
|
+
...kitchen.place,
|
|
39
|
+
rating: { rating: 4.8, count: 900 },
|
|
40
|
+
reviews_digest: { grade: { overall: 8.7, show_number: true } },
|
|
41
|
+
},
|
|
42
|
+
} as MenuKitchenPreview;
|
|
43
|
+
|
|
44
|
+
it("shows the BearMenu grade instead of the Google star when the venue has one", () => {
|
|
45
|
+
const { container } = render(
|
|
46
|
+
<MenuKitchenList kitchens={[graded]} labels={{ ...labels, grade: gradeLabels }} />
|
|
47
|
+
);
|
|
48
|
+
expect(container.textContent).toMatch(/8[.,]7/);
|
|
49
|
+
expect(container.textContent).not.toContain("4.8");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("keeps the star for a venue with no grade", () => {
|
|
53
|
+
const ungraded = { ...graded, place: { ...graded.place, reviews_digest: undefined } };
|
|
54
|
+
const { container } = render(
|
|
55
|
+
<MenuKitchenList kitchens={[ungraded]} labels={{ ...labels, grade: gradeLabels }} />
|
|
56
|
+
);
|
|
57
|
+
expect(container.textContent).toContain("4.8");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("keeps the star for callers that pass no grade labels", () => {
|
|
61
|
+
const { container } = render(<MenuKitchenList kitchens={[graded]} labels={labels} />);
|
|
62
|
+
expect(container.textContent).toContain("4.8");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
27
66
|
describe("MenuKitchenList", () => {
|
|
28
67
|
/**
|
|
29
68
|
* The reason this component exists rather than a flag on `RankedVenueList`.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Check, ChevronRight, Clock, MessageSquare, Star } from "lucide-react";
|
|
2
|
+
import { showsGradeAtom } from "../lib/grade";
|
|
2
3
|
import { cn } from "../lib/utils";
|
|
4
|
+
import { GradeAtom, type GradeAtomLabels } from "./grade-atom";
|
|
3
5
|
import { Separator } from "./separator";
|
|
4
6
|
import { Skeleton } from "./skeleton";
|
|
5
7
|
import type { MenuKitchenPreview, MenuLinkComponent, MenuLinkProps } from "./menu-types";
|
|
@@ -59,6 +61,13 @@ export type MenuKitchenListLabels = {
|
|
|
59
61
|
openNow: string;
|
|
60
62
|
/** Reveals the next page of rows, e.g. "Show 10 more". */
|
|
61
63
|
showMore?: string;
|
|
64
|
+
/**
|
|
65
|
+
* The grade pill's labels. With them, a graded venue shows its BearMenu
|
|
66
|
+
* grade where the Google star was; the star stays only for a venue with no
|
|
67
|
+
* grade. Optional so existing callers keep compiling — without it every row
|
|
68
|
+
* shows the star, as before.
|
|
69
|
+
*/
|
|
70
|
+
grade?: GradeAtomLabels;
|
|
62
71
|
};
|
|
63
72
|
|
|
64
73
|
/**
|
|
@@ -127,6 +136,31 @@ export function MenuKitchenList({
|
|
|
127
136
|
);
|
|
128
137
|
}
|
|
129
138
|
|
|
139
|
+
function gradeShown(place: MenuKitchenPreview["place"], labels: MenuKitchenListLabels) {
|
|
140
|
+
return labels.grade !== undefined && showsGradeAtom(place.reviews_digest?.grade, "xs");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** BearMenu's grade when the venue has one; Google's star only without it. */
|
|
144
|
+
function KitchenRating({
|
|
145
|
+
place,
|
|
146
|
+
labels,
|
|
147
|
+
}: {
|
|
148
|
+
place: MenuKitchenPreview["place"];
|
|
149
|
+
labels: MenuKitchenListLabels;
|
|
150
|
+
}) {
|
|
151
|
+
const grade = place.reviews_digest?.grade;
|
|
152
|
+
if (labels.grade && showsGradeAtom(grade, "xs")) {
|
|
153
|
+
return <GradeAtom grade={grade} labels={labels.grade} size="xs" className="shrink-0" />;
|
|
154
|
+
}
|
|
155
|
+
if (!place.rating) return null;
|
|
156
|
+
return (
|
|
157
|
+
<>
|
|
158
|
+
<Star className="h-[11px] w-[11px] shrink-0" aria-hidden />
|
|
159
|
+
{place.rating.rating}
|
|
160
|
+
</>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
130
164
|
function KitchenRow({
|
|
131
165
|
kitchen,
|
|
132
166
|
labels,
|
|
@@ -189,13 +223,8 @@ function KitchenRow({
|
|
|
189
223
|
{place.name}
|
|
190
224
|
</span>
|
|
191
225
|
<span className="flex items-center gap-1 truncate text-xs text-muted-foreground">
|
|
192
|
-
{place
|
|
193
|
-
|
|
194
|
-
<Star className="h-[11px] w-[11px] shrink-0" aria-hidden />
|
|
195
|
-
{place.rating.rating}
|
|
196
|
-
{kitchen.metaLabel && " · "}
|
|
197
|
-
</>
|
|
198
|
-
)}
|
|
226
|
+
<KitchenRating place={place} labels={labels} />
|
|
227
|
+
{kitchen.metaLabel && (gradeShown(place, labels) || place.rating) && " · "}
|
|
199
228
|
{kitchen.metaLabel}
|
|
200
229
|
</span>
|
|
201
230
|
{kitchen.hoursLabel && (
|