@bearmenu/ui 0.8.15 → 0.8.17
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/README.md +1 -0
- package/dist/{chunk-ZLPWEHZO.js → chunk-54FQQZZJ.js} +1 -1
- package/dist/{chunk-5FCC5L5F.js → chunk-5LTILG3L.js} +29 -6
- package/dist/{chunk-P43B3ONY.js → chunk-5XREWOBB.js} +3 -1
- package/dist/{chunk-V4E333QS.js → chunk-5YNIQ2BL.js} +7 -29
- package/dist/{chunk-CLLY6XB3.js → chunk-6VOWT4YR.js} +6 -3
- package/dist/{chunk-S33K4RC5.js → chunk-BKKQ7GCZ.js} +1 -1
- package/dist/chunk-QY66ME5B.js +207 -0
- package/dist/chunk-RIH2IS7X.js +29 -0
- package/dist/{chunk-T6S2ZBV6.js → chunk-SDWN6L4O.js} +1 -1
- package/dist/{chunk-CNJQUHCU.js → chunk-SWD6CJ35.js} +2 -1
- package/dist/{chunk-HDR7V6IZ.js → chunk-TIQNM4XD.js} +8 -1
- package/dist/components/alert-dialog.js +3 -2
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/button.d.ts +5 -1
- package/dist/components/button.js +3 -2
- package/dist/components/calendar.js +3 -2
- package/dist/components/carousel.js +3 -2
- package/dist/components/coach-marks.d.ts +63 -0
- package/dist/components/coach-marks.js +162 -0
- package/dist/components/combobox.js +3 -2
- package/dist/components/concept-compare-rail.js +2 -2
- package/dist/components/concept-compare.js +2 -2
- package/dist/components/concept-convergence.js +2 -2
- package/dist/components/date-input.d.ts +1 -1
- package/dist/components/doorway-tiles.d.ts +11 -0
- package/dist/components/doorway-tiles.js +5 -3
- package/dist/components/empty-state.js +3 -2
- package/dist/components/event-detail-panel.js +4 -3
- package/dist/components/event-index-row.js +1 -1
- package/dist/components/event-list-row-wide.js +4 -3
- package/dist/components/event-list-row.js +1 -1
- package/dist/components/facet-group.d.ts +8 -1
- package/dist/components/facet-group.js +3 -0
- package/dist/components/filter-category-row.js +1 -1
- package/dist/components/haptic-switch.d.ts +35 -0
- package/dist/components/haptic-switch.js +3 -0
- package/dist/components/hue-chip.js +1 -1
- package/dist/components/item.js +4 -1
- package/dist/components/kitchen-dossier.js +2 -2
- package/dist/components/link-button.js +3 -2
- package/dist/components/menu-family-block.d.ts +8 -1
- package/dist/components/menu-family-block.js +103 -69
- package/dist/components/menu-family-card.js +2 -2
- package/dist/components/menu-filter-chips.d.ts +12 -3
- package/dist/components/menu-filter-chips.js +22 -4
- package/dist/components/menu-index-list.js +3 -2
- package/dist/components/menu-item.js +3 -3
- package/dist/components/menu-kitchen-list.d.ts +14 -2
- package/dist/components/menu-kitchen-list.js +1 -1
- package/dist/components/multi-select-combobox.js +4 -3
- package/dist/components/pagination.js +3 -2
- package/dist/components/photo-ground.d.ts +7 -1
- package/dist/components/photo-ground.js +1 -1
- package/dist/components/place-card.js +2 -2
- package/dist/components/place-details-mobile.js +1 -1
- package/dist/components/searchable-select.js +3 -2
- package/dist/components/section-header.d.ts +7 -1
- package/dist/components/section-header.js +11 -7
- package/dist/components/signature-chip.js +2 -2
- package/dist/components/sliding-panels.js +3 -2
- package/dist/components/switch.d.ts +7 -1
- package/dist/components/switch.js +33 -24
- package/dist/components/toggle-group.js +9 -4
- package/dist/components/toggle.d.ts +1 -1
- package/dist/components/toggle.js +1 -1
- package/dist/components/top-ranking-entry.js +3 -3
- package/dist/hooks/use-haptic.d.ts +9 -1
- package/dist/hooks/use-haptic.js +1 -1
- package/package.json +1 -1
- package/src/components/badge.stories.tsx +31 -1
- package/src/components/badge.tsx +2 -0
- package/src/components/button.stories.tsx +5 -4
- package/src/components/button.test.tsx +11 -1
- package/src/components/button.tsx +41 -6
- package/src/components/coach-marks.stories.tsx +79 -0
- package/src/components/coach-marks.test.tsx +140 -0
- package/src/components/coach-marks.tsx +252 -0
- package/src/components/doorway-tiles.stories.tsx +34 -0
- package/src/components/doorway-tiles.test.tsx +27 -0
- package/src/components/doorway-tiles.tsx +30 -2
- package/src/components/facet-group.tsx +9 -0
- package/src/components/haptic-switch.test.tsx +134 -0
- package/src/components/haptic-switch.tsx +62 -0
- package/src/components/hue-chip.test.tsx +6 -3
- package/src/components/hue-chip.tsx +5 -2
- package/src/components/item.tsx +4 -1
- package/src/components/menu-family-block.stories.tsx +12 -0
- package/src/components/menu-family-block.tsx +53 -20
- package/src/components/menu-filter-chips.tsx +32 -4
- package/src/components/menu-kitchen-list.tsx +45 -6
- package/src/components/photo-ground.tsx +7 -0
- package/src/components/section-header.test.tsx +15 -0
- package/src/components/section-header.tsx +26 -12
- package/src/components/switch.tsx +29 -18
- package/src/components/toggle-group.stories.tsx +37 -1
- package/src/components/toggle-group.tsx +11 -6
- package/src/components/toggle.tsx +8 -0
- package/src/hooks/use-haptic.test.tsx +54 -59
- package/src/hooks/use-haptic.ts +18 -44
- package/dist/chunk-SXQZ7DLH.js +0 -167
|
@@ -1,80 +1,75 @@
|
|
|
1
|
-
import { describe, it, expect, vi,
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from "vitest";
|
|
2
2
|
import { act, renderHook } from "@testing-library/react";
|
|
3
|
-
import { useHaptic } from "./use-haptic";
|
|
3
|
+
import { isIos, useHaptic } from "./use-haptic";
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const IOS_UA =
|
|
6
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 26_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Mobile/15E148 Safari/604.1";
|
|
7
|
+
const IPAD_AS_MAC_UA =
|
|
8
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Safari/605.1.15";
|
|
6
9
|
|
|
7
|
-
describe("
|
|
10
|
+
describe("isIos", () => {
|
|
8
11
|
afterEach(() => {
|
|
9
12
|
vi.restoreAllMocks();
|
|
10
13
|
});
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
afterEach(() => {
|
|
18
|
-
Reflect.deleteProperty(HTMLInputElement.prototype, "switch");
|
|
19
|
-
hapticSwitch()?.parentElement?.remove();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("reports support", () => {
|
|
23
|
-
const { result } = renderHook(() => useHaptic());
|
|
24
|
-
expect(result.current.isSupported).toBe(true);
|
|
25
|
-
});
|
|
15
|
+
it("is false in jsdom", () => {
|
|
16
|
+
expect(isIos()).toBe(false);
|
|
17
|
+
});
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
it("matches an iPhone user agent", () => {
|
|
20
|
+
vi.spyOn(navigator, "userAgent", "get").mockReturnValue(IOS_UA);
|
|
21
|
+
expect(isIos()).toBe(true);
|
|
22
|
+
});
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
it("matches an iPad presenting as a Mac by its touch points", () => {
|
|
25
|
+
vi.spyOn(navigator, "userAgent", "get").mockReturnValue(IPAD_AS_MAC_UA);
|
|
26
|
+
vi.spyOn(navigator, "platform", "get").mockReturnValue("MacIntel");
|
|
27
|
+
Object.defineProperty(navigator, "maxTouchPoints", { value: 5, configurable: true });
|
|
28
|
+
expect(isIos()).toBe(true);
|
|
29
|
+
Reflect.deleteProperty(navigator, "maxTouchPoints");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
describe("useHaptic", () => {
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
vi.restoreAllMocks();
|
|
36
|
+
Reflect.deleteProperty(navigator, "vibrate");
|
|
37
|
+
});
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
it("reports support on iOS without adding anything to the DOM — the switch lives in the control", () => {
|
|
40
|
+
vi.spyOn(navigator, "userAgent", "get").mockReturnValue(IOS_UA);
|
|
41
|
+
const debug = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
42
|
+
const { result } = renderHook(() => useHaptic());
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
expect(result.current.isSupported).toBe(true);
|
|
45
|
+
expect(result.current.platform).toBe("ios");
|
|
46
|
+
act(() => result.current.trigger("light"));
|
|
47
|
+
expect(document.body.querySelector("input[switch]")).toBeNull();
|
|
48
|
+
expect(debug).toHaveBeenCalled();
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const { result } = renderHook(() => useHaptic());
|
|
51
|
+
it("reports no support without any haptic API", () => {
|
|
52
|
+
const debug = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
53
|
+
const { result } = renderHook(() => useHaptic());
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
expect(debug).toHaveBeenCalled();
|
|
60
|
-
});
|
|
55
|
+
expect(result.current.isSupported).toBe(false);
|
|
56
|
+
act(() => result.current.trigger("light"));
|
|
57
|
+
expect(debug).toHaveBeenCalled();
|
|
61
58
|
});
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
});
|
|
60
|
+
it("vibrates through navigator.vibrate where it exists", () => {
|
|
61
|
+
const vibrate = vi.fn();
|
|
62
|
+
Object.defineProperty(navigator, "vibrate", { value: vibrate, configurable: true });
|
|
63
|
+
const { result } = renderHook(() => useHaptic());
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Object.defineProperty(HTMLInputElement.prototype, "switch", { value: false, configurable: true });
|
|
72
|
-
const { result } = renderHook(() => useHaptic());
|
|
65
|
+
act(() => result.current.trigger("medium"));
|
|
66
|
+
expect(vibrate).toHaveBeenCalledWith(20);
|
|
67
|
+
});
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
69
|
+
it("keeps trigger referentially stable across renders", () => {
|
|
70
|
+
const { result, rerender } = renderHook(() => useHaptic());
|
|
71
|
+
const first = result.current.trigger;
|
|
72
|
+
rerender();
|
|
73
|
+
expect(result.current.trigger).toBe(first);
|
|
79
74
|
});
|
|
80
75
|
});
|
package/src/hooks/use-haptic.ts
CHANGED
|
@@ -10,6 +10,21 @@ interface HapticAPI {
|
|
|
10
10
|
trigger: (style: HapticStyle) => void;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* iOS Safari, including iPadOS masquerading as a Mac. Haptics there come from
|
|
15
|
+
* `HapticSwitch`, not from `trigger`: WebKit has no Vibration API, and since
|
|
16
|
+
* iOS 26.5 the only haptic it plays is a native switch flipping under the
|
|
17
|
+
* user's own finger — a programmatic click on the switch or its label no
|
|
18
|
+
* longer counts (WebKit #65327).
|
|
19
|
+
*/
|
|
20
|
+
export function isIos(): boolean {
|
|
21
|
+
if (typeof navigator === "undefined") return false;
|
|
22
|
+
return (
|
|
23
|
+
/iPad|iPhone|iPod/.test(navigator.userAgent) ||
|
|
24
|
+
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
13
28
|
export const useHaptic = (): HapticAPI => {
|
|
14
29
|
const [platform, setPlatform] = useState<"ios" | "android" | "desktop" | "unknown">("unknown");
|
|
15
30
|
const [isSupported, setIsSupported] = useState(false);
|
|
@@ -17,10 +32,9 @@ export const useHaptic = (): HapticAPI => {
|
|
|
17
32
|
useEffect(() => {
|
|
18
33
|
// Detect platform
|
|
19
34
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
20
|
-
const isIOS = /iphone|ipad|ipod/.test(userAgent);
|
|
21
35
|
const isAndroid = /android/.test(userAgent);
|
|
22
36
|
|
|
23
|
-
if (
|
|
37
|
+
if (isIos()) {
|
|
24
38
|
setPlatform("ios");
|
|
25
39
|
} else if (isAndroid) {
|
|
26
40
|
setPlatform("android");
|
|
@@ -32,7 +46,7 @@ export const useHaptic = (): HapticAPI => {
|
|
|
32
46
|
const hasVibration = "vibrate" in navigator;
|
|
33
47
|
const hasTelegram = typeof window !== "undefined" && window.Telegram?.WebApp?.HapticFeedback;
|
|
34
48
|
|
|
35
|
-
setIsSupported(hasVibration || !!hasTelegram ||
|
|
49
|
+
setIsSupported(hasVibration || !!hasTelegram || isIos());
|
|
36
50
|
}, []);
|
|
37
51
|
|
|
38
52
|
const trigger = useCallback((style: HapticStyle) => {
|
|
@@ -48,12 +62,7 @@ export const useHaptic = (): HapticAPI => {
|
|
|
48
62
|
return;
|
|
49
63
|
}
|
|
50
64
|
|
|
51
|
-
// iOS
|
|
52
|
-
if (supportsSwitchHaptic()) {
|
|
53
|
-
triggerSwitchHaptic();
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
65
|
+
// iOS: nothing to call — see HapticSwitch, which sits inside the control
|
|
57
66
|
// No haptic support - silently fail
|
|
58
67
|
console.debug("Haptic feedback not supported on this device");
|
|
59
68
|
}, []);
|
|
@@ -108,41 +117,6 @@ function triggerVibrationAPI(style: HapticStyle) {
|
|
|
108
117
|
navigator.vibrate(patterns[style]);
|
|
109
118
|
}
|
|
110
119
|
|
|
111
|
-
// Switch implementation (iOS 18+ Safari and home-screen PWAs)
|
|
112
|
-
//
|
|
113
|
-
// WebKit plays the system "toggle" haptic when an `<input type="checkbox" switch>`
|
|
114
|
-
// flips through its label, and a programmatic `label.click()` counts. One hidden
|
|
115
|
-
// switch appended to the body doubles as a haptic trigger. It is the only haptic
|
|
116
|
-
// WebKit exposes, so every style collapses to that one tick here.
|
|
117
|
-
// https://github.com/ionic-team/ionic-framework/issues/29942
|
|
118
|
-
let hapticSwitch: HTMLLabelElement | null = null;
|
|
119
|
-
|
|
120
|
-
function supportsSwitchHaptic(): boolean {
|
|
121
|
-
return typeof HTMLInputElement !== "undefined" && "switch" in HTMLInputElement.prototype;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function getHapticSwitch(): HTMLLabelElement {
|
|
125
|
-
if (hapticSwitch?.isConnected) return hapticSwitch;
|
|
126
|
-
|
|
127
|
-
const label = document.createElement("label");
|
|
128
|
-
const input = document.createElement("input");
|
|
129
|
-
input.type = "checkbox";
|
|
130
|
-
input.setAttribute("switch", "");
|
|
131
|
-
input.tabIndex = -1;
|
|
132
|
-
label.setAttribute("aria-hidden", "true");
|
|
133
|
-
label.style.cssText =
|
|
134
|
-
"position:fixed;top:0;left:0;width:1px;height:1px;overflow:hidden;opacity:0;pointer-events:none";
|
|
135
|
-
label.appendChild(input);
|
|
136
|
-
document.body.appendChild(label);
|
|
137
|
-
|
|
138
|
-
hapticSwitch = label;
|
|
139
|
-
return label;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function triggerSwitchHaptic() {
|
|
143
|
-
getHapticSwitch().click();
|
|
144
|
-
}
|
|
145
|
-
|
|
146
120
|
// Extend Window interface for TypeScript
|
|
147
121
|
declare global {
|
|
148
122
|
interface Window {
|
package/dist/chunk-SXQZ7DLH.js
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { Separator } from './chunk-NWZGSLPU.js';
|
|
2
|
-
import { Skeleton } from './chunk-XBBEX4SF.js';
|
|
3
|
-
import { cn } from './chunk-FEK5XGZW.js';
|
|
4
|
-
import { __objRest, __spreadValues } from './chunk-MMUBH76A.js';
|
|
5
|
-
import { Star, Clock, Check, MessageSquare, ChevronRight } from 'lucide-react';
|
|
6
|
-
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
|
|
8
|
-
function DefaultLink(_a) {
|
|
9
|
-
var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
|
|
10
|
-
return /* @__PURE__ */ jsx("a", __spreadValues({ href }, props));
|
|
11
|
-
}
|
|
12
|
-
function MenuKitchenList({
|
|
13
|
-
kitchens,
|
|
14
|
-
labels,
|
|
15
|
-
onShowMore,
|
|
16
|
-
linkComponent = DefaultLink,
|
|
17
|
-
className
|
|
18
|
-
}) {
|
|
19
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", className), children: [
|
|
20
|
-
/* @__PURE__ */ jsx("ol", { children: kitchens.map((kitchen, index) => /* @__PURE__ */ jsxs("li", { className: "[&:first-child>div]:pt-0", children: [
|
|
21
|
-
index > 0 && /* @__PURE__ */ jsx(Separator, {}),
|
|
22
|
-
/* @__PURE__ */ jsx(KitchenRow, { kitchen, labels, linkComponent })
|
|
23
|
-
] }, kitchen.place.slug)) }),
|
|
24
|
-
onShowMore && labels.showMore && /* @__PURE__ */ jsx(
|
|
25
|
-
"button",
|
|
26
|
-
{
|
|
27
|
-
type: "button",
|
|
28
|
-
onClick: onShowMore,
|
|
29
|
-
className: "mt-2 self-start rounded-md py-2 text-[13px] font-bold text-accent transition-colors hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none",
|
|
30
|
-
children: labels.showMore
|
|
31
|
-
}
|
|
32
|
-
)
|
|
33
|
-
] });
|
|
34
|
-
}
|
|
35
|
-
function KitchenRow({
|
|
36
|
-
kitchen,
|
|
37
|
-
labels,
|
|
38
|
-
linkComponent: LinkComponent
|
|
39
|
-
}) {
|
|
40
|
-
const { place, dish } = kitchen;
|
|
41
|
-
const openNow = place.open_now === true;
|
|
42
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative flex flex-wrap items-center gap-[11px] py-3 transition-colors hover:bg-muted/30 motion-reduce:transition-none lg:flex-nowrap lg:gap-4 lg:py-3.5", children: [
|
|
43
|
-
/* @__PURE__ */ jsx(
|
|
44
|
-
LinkComponent,
|
|
45
|
-
{
|
|
46
|
-
href: kitchen.href,
|
|
47
|
-
"aria-label": labels.openVenue(place.name),
|
|
48
|
-
className: "absolute inset-0 z-[1] rounded-xl focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
|
|
49
|
-
}
|
|
50
|
-
),
|
|
51
|
-
/* @__PURE__ */ jsxs("span", { className: "relative h-[46px] w-[46px] shrink-0 overflow-hidden rounded-[11px] bg-[repeating-linear-gradient(135deg,oklch(0.78_0.018_55)_0_8px,oklch(0.84_0.012_58)_8px_16px)] lg:h-[58px] lg:w-[58px] lg:rounded-[13px]", children: [
|
|
52
|
-
place.thumbnail_url && // eslint-disable-next-line @next/next/no-img-element
|
|
53
|
-
/* @__PURE__ */ jsx(
|
|
54
|
-
"img",
|
|
55
|
-
{
|
|
56
|
-
src: place.thumbnail_url,
|
|
57
|
-
alt: "",
|
|
58
|
-
loading: "lazy",
|
|
59
|
-
decoding: "async",
|
|
60
|
-
className: "h-full w-full object-cover"
|
|
61
|
-
}
|
|
62
|
-
),
|
|
63
|
-
/* @__PURE__ */ jsx(
|
|
64
|
-
"span",
|
|
65
|
-
{
|
|
66
|
-
title: openNow ? labels.openNow : void 0,
|
|
67
|
-
className: cn(
|
|
68
|
-
"absolute right-[5px] top-[5px] h-[7px] w-[7px] rounded-full ring-2 ring-white/85",
|
|
69
|
-
openNow ? "bg-[var(--free,oklch(0.55_0.13_155))]" : "bg-[oklch(0.8_0.01_60)]"
|
|
70
|
-
)
|
|
71
|
-
}
|
|
72
|
-
)
|
|
73
|
-
] }),
|
|
74
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5 lg:w-[226px] lg:flex-none", children: [
|
|
75
|
-
/* @__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 }),
|
|
76
|
-
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 truncate text-xs text-muted-foreground", children: [
|
|
77
|
-
place.rating && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
78
|
-
/* @__PURE__ */ jsx(Star, { className: "h-[11px] w-[11px] shrink-0", "aria-hidden": true }),
|
|
79
|
-
place.rating.rating,
|
|
80
|
-
kitchen.metaLabel && " \xB7 "
|
|
81
|
-
] }),
|
|
82
|
-
kitchen.metaLabel
|
|
83
|
-
] }),
|
|
84
|
-
kitchen.hoursLabel && /* @__PURE__ */ jsxs(
|
|
85
|
-
"span",
|
|
86
|
-
{
|
|
87
|
-
className: cn(
|
|
88
|
-
"mt-[3px] inline-flex h-[21px] w-max items-center gap-[5px] rounded-md px-2 text-[10.5px] font-bold",
|
|
89
|
-
openNow ? "bg-[oklch(0.96_0.02_155)] text-[var(--free,oklch(0.45_0.13_155))]" : "bg-muted text-muted-foreground"
|
|
90
|
-
),
|
|
91
|
-
children: [
|
|
92
|
-
/* @__PURE__ */ jsx(Clock, { className: "h-2.5 w-2.5 shrink-0", "aria-hidden": true }),
|
|
93
|
-
kitchen.hoursLabel
|
|
94
|
-
]
|
|
95
|
-
}
|
|
96
|
-
)
|
|
97
|
-
] }),
|
|
98
|
-
dish && /* DESKTOP ONLY, where it is a column of its own beside the venue.
|
|
99
|
-
On the phone it wrapped to a third line under the row — kicker, dish,
|
|
100
|
-
mention count — which turned a four-line venue row into a seven-line
|
|
101
|
-
block and, ten rows down, buried the venue names the list exists to
|
|
102
|
-
be scanned for. The dish is not what a reader is choosing here; it is
|
|
103
|
-
one tap away on the venue's own page, with room to state it.
|
|
104
|
-
|
|
105
|
-
`order-5` puts it last in the visual order without moving it in the
|
|
106
|
-
DOM, where it belongs to the venue. */
|
|
107
|
-
/* @__PURE__ */ jsxs("div", { className: "hidden min-w-0 basis-full pl-[57px] lg:order-none lg:block lg:flex-1 lg:basis-auto lg:pl-0", children: [
|
|
108
|
-
/* @__PURE__ */ jsxs(
|
|
109
|
-
"span",
|
|
110
|
-
{
|
|
111
|
-
className: cn(
|
|
112
|
-
"flex items-center gap-1.5 text-[9px] font-extrabold uppercase tracking-[0.1em]",
|
|
113
|
-
dish.matched ? "text-accent" : "text-[oklch(0.72_0.01_60)]"
|
|
114
|
-
),
|
|
115
|
-
children: [
|
|
116
|
-
dish.kicker,
|
|
117
|
-
dish.matched && dish.matchLabel && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-[5px] bg-accent-subtle px-1.5 py-px text-[10.5px] font-bold normal-case tracking-normal text-accent", children: [
|
|
118
|
-
/* @__PURE__ */ jsx(Check, { className: "h-2.5 w-2.5 shrink-0", "aria-hidden": true }),
|
|
119
|
-
dish.matchLabel
|
|
120
|
-
] })
|
|
121
|
-
]
|
|
122
|
-
}
|
|
123
|
-
),
|
|
124
|
-
dish.href ? /* @__PURE__ */ jsx(
|
|
125
|
-
LinkComponent,
|
|
126
|
-
{
|
|
127
|
-
href: dish.href,
|
|
128
|
-
"aria-label": labels.openDish(dish.name),
|
|
129
|
-
className: "relative z-[2] mt-0.5 block truncate font-serif text-[13.5px] italic underline decoration-[oklch(0.84_0.01_60)] decoration-1 underline-offset-[3px] transition-colors hover:text-accent hover:decoration-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none lg:text-[15px]",
|
|
130
|
-
children: dish.name
|
|
131
|
-
}
|
|
132
|
-
) : /* @__PURE__ */ jsx("span", { className: "mt-0.5 block truncate font-serif text-[13.5px] italic lg:text-[15px]", children: dish.name }),
|
|
133
|
-
dish.meta && /* @__PURE__ */ jsxs("span", { className: "mt-[3px] flex items-center gap-1 text-[11.5px] text-muted-foreground", children: [
|
|
134
|
-
!dish.matched && /* @__PURE__ */ jsx(MessageSquare, { className: "h-2.5 w-2.5 shrink-0", "aria-hidden": true }),
|
|
135
|
-
dish.meta
|
|
136
|
-
] })
|
|
137
|
-
] }),
|
|
138
|
-
/* @__PURE__ */ jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-[11px] lg:ml-0", children: [
|
|
139
|
-
kitchen.priceLabel && /* @__PURE__ */ jsx("span", { className: "text-base font-extrabold tabular-nums text-accent", children: kitchen.priceLabel }),
|
|
140
|
-
/* @__PURE__ */ jsx(ChevronRight, { className: "h-[15px] w-[15px] shrink-0 text-muted-foreground", "aria-hidden": true })
|
|
141
|
-
] })
|
|
142
|
-
] });
|
|
143
|
-
}
|
|
144
|
-
function MenuKitchenListSkeleton({
|
|
145
|
-
rows = 10,
|
|
146
|
-
className
|
|
147
|
-
}) {
|
|
148
|
-
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", className), "aria-hidden": true, children: Array.from({ length: rows }, (_, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
149
|
-
index > 0 && /* @__PURE__ */ jsx(Separator, {}),
|
|
150
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-[11px] py-3 lg:flex-nowrap lg:gap-4 lg:py-3.5", children: [
|
|
151
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-[46px] w-[46px] rounded-[11px] lg:h-[58px] lg:w-[58px] lg:rounded-[13px]" }),
|
|
152
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5 lg:w-[226px] lg:flex-none", children: [
|
|
153
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-[60%]" }),
|
|
154
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-[45%]" }),
|
|
155
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-[21px] w-[120px] rounded-md" })
|
|
156
|
-
] }),
|
|
157
|
-
/* @__PURE__ */ jsxs("div", { className: "hidden min-w-0 basis-full pl-[57px] lg:order-none lg:block lg:flex-1 lg:basis-auto lg:pl-0", children: [
|
|
158
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-[90px]" }),
|
|
159
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "mt-1.5 h-4 w-[70%]" }),
|
|
160
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "mt-1.5 h-3 w-[40%]" })
|
|
161
|
-
] }),
|
|
162
|
-
/* @__PURE__ */ jsx(Skeleton, { className: "ml-auto h-5 w-[56px] lg:ml-0" })
|
|
163
|
-
] })
|
|
164
|
-
] }, index)) });
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export { MenuKitchenList, MenuKitchenListSkeleton };
|