@bearmenu/ui 0.8.13 → 0.8.15

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 (294) hide show
  1. package/README.md +0 -1
  2. package/dist/{chunk-66MAPLXS.js → chunk-2ADCZXZJ.js} +1 -1
  3. package/dist/{chunk-2DEIXTBN.js → chunk-2ZXIXQIU.js} +1 -1
  4. package/dist/{chunk-YOKHBAIH.js → chunk-4OF4T4AI.js} +12 -11
  5. package/dist/{chunk-MZL7CGCL.js → chunk-4XDJXMLF.js} +2 -2
  6. package/dist/{chunk-VAXOQS7W.js → chunk-5FCC5L5F.js} +3 -3
  7. package/dist/{chunk-YYGB4G4Q.js → chunk-CZK2MRS2.js} +1 -1
  8. package/dist/chunk-DJD3EMPK.js +126 -0
  9. package/dist/chunk-EZG2NELX.js +5 -0
  10. package/dist/{chunk-VG3PND3D.js → chunk-FMTJGO76.js} +1 -1
  11. package/dist/{chunk-UXWAOISG.js → chunk-FVSKGCK3.js} +2 -2
  12. package/dist/{chunk-2XCZJWTV.js → chunk-GNCWJWFE.js} +1 -1
  13. package/dist/{chunk-X3WMRKOW.js → chunk-HDR7V6IZ.js} +1 -1
  14. package/dist/{chunk-HSIYYA2E.js → chunk-HQU6QVAN.js} +5 -5
  15. package/dist/chunk-I5V446BX.js +27 -0
  16. package/dist/{chunk-WCTHZKU7.js → chunk-ICOU5QHT.js} +1 -1
  17. package/dist/{chunk-G7IFL4Z4.js → chunk-L3VEMP5A.js} +57 -9
  18. package/dist/chunk-LQWGZIYA.js +5 -0
  19. package/dist/{chunk-XNA2INVQ.js → chunk-MCOHLWRS.js} +2 -2
  20. package/dist/{chunk-3GWWZKX7.js → chunk-MMUBH76A.js} +21 -1
  21. package/dist/{chunk-ZDAHKI3A.js → chunk-MWB7S54O.js} +1 -1
  22. package/dist/{chunk-D5QHEHXJ.js → chunk-NMEVJT5Q.js} +1 -1
  23. package/dist/{chunk-3TNPSN4D.js → chunk-NSNEANOQ.js} +2 -2
  24. package/dist/{chunk-WSRWFA6K.js → chunk-NWZGSLPU.js} +1 -1
  25. package/dist/{chunk-LEAYBICI.js → chunk-OIV7B44M.js} +1 -1
  26. package/dist/{chunk-2CXU5WZO.js → chunk-P43B3ONY.js} +1 -1
  27. package/dist/{chunk-FRPPIXMY.js → chunk-PDTPO6NG.js} +1 -1
  28. package/dist/{chunk-6XMYEZVR.js → chunk-PX6RICS5.js} +1 -1
  29. package/dist/{chunk-6TEEY5YA.js → chunk-S33K4RC5.js} +1 -1
  30. package/dist/{chunk-3VMDCCCX.js → chunk-SC2VUTUI.js} +1 -1
  31. package/dist/{chunk-3NMG3KNA.js → chunk-SXQZ7DLH.js} +3 -3
  32. package/dist/{chunk-UDTG3RSE.js → chunk-T6S2ZBV6.js} +2 -2
  33. package/dist/{chunk-R47NEOSI.js → chunk-V4E333QS.js} +29 -4
  34. package/dist/{chunk-FKNBZF5T.js → chunk-WYTJR2YU.js} +1 -1
  35. package/dist/{chunk-QXHMPJ35.js → chunk-XBBEX4SF.js} +1 -1
  36. package/dist/chunk-XCB3F6SF.js +16 -0
  37. package/dist/{chunk-7BWTYWM3.js → chunk-ZLMRVBD7.js} +1 -1
  38. package/dist/{chunk-P7XTW2CG.js → chunk-ZLPWEHZO.js} +1 -1
  39. package/dist/components/accordion.js +1 -1
  40. package/dist/components/alert-dialog.js +3 -3
  41. package/dist/components/alert.js +2 -2
  42. package/dist/components/aspect-ratio.js +2 -2
  43. package/dist/components/avatar.js +1 -1
  44. package/dist/components/badge.js +2 -2
  45. package/dist/components/breadcrumb.js +1 -1
  46. package/dist/components/button-group.js +1 -1
  47. package/dist/components/button.d.ts +4 -0
  48. package/dist/components/button.js +3 -3
  49. package/dist/components/calendar.js +3 -3
  50. package/dist/components/card.js +3 -3
  51. package/dist/components/carousel.js +3 -3
  52. package/dist/components/category-deck.js +2 -2
  53. package/dist/components/checkbox.js +2 -2
  54. package/dist/components/circular-progress.js +1 -1
  55. package/dist/components/collapsible.js +1 -1
  56. package/dist/components/combobox.js +6 -6
  57. package/dist/components/command.js +3 -3
  58. package/dist/components/concept-card.js +2 -2
  59. package/dist/components/concept-compare-rail.js +3 -3
  60. package/dist/components/concept-compare.d.ts +2 -1
  61. package/dist/components/concept-compare.js +5 -5
  62. package/dist/components/concept-convergence.js +4 -4
  63. package/dist/components/convergence.js +3 -3
  64. package/dist/components/coverflow.js +1 -1
  65. package/dist/components/currency-input.js +2 -2
  66. package/dist/components/date-input.js +2 -2
  67. package/dist/components/day-rail-chip.js +2 -2
  68. package/dist/components/description-list.js +1 -1
  69. package/dist/components/dialog.js +2 -2
  70. package/dist/components/doorway-tiles.d.ts +57 -0
  71. package/dist/components/doorway-tiles.js +86 -0
  72. package/dist/components/drawer.js +1 -1
  73. package/dist/components/drift-rail.js +1 -1
  74. package/dist/components/dropdown-menu.js +1 -1
  75. package/dist/components/empty-state.js +4 -4
  76. package/dist/components/event-card.js +4 -4
  77. package/dist/components/event-compact-row.js +4 -4
  78. package/dist/components/event-day-header.js +2 -2
  79. package/dist/components/event-day-separator.js +3 -3
  80. package/dist/components/event-detail-panel.js +5 -5
  81. package/dist/components/event-hub-hero.js +2 -2
  82. package/dist/components/event-index-row.js +4 -4
  83. package/dist/components/event-list-row-wide.js +6 -6
  84. package/dist/components/event-list-row.js +5 -5
  85. package/dist/components/event-poster-fallback.js +1 -1
  86. package/dist/components/event-types.js +1 -1
  87. package/dist/components/events-empty-state.js +1 -1
  88. package/dist/components/explainer-steps.js +1 -1
  89. package/dist/components/facet-group.js +2 -2
  90. package/dist/components/featured-rail-item.js +2 -2
  91. package/dist/components/field.js +2 -2
  92. package/dist/components/filter-category-row.js +3 -3
  93. package/dist/components/form.js +2 -2
  94. package/dist/components/glass-ground.js +2 -2
  95. package/dist/components/grade-atom.d.ts +3 -0
  96. package/dist/components/grade-atom.js +4 -0
  97. package/dist/components/hour-band.js +4 -4
  98. package/dist/components/hour-group.js +4 -4
  99. package/dist/components/hub-surface.js +1 -1
  100. package/dist/components/hue-chip.js +1 -1
  101. package/dist/components/icon.js +1 -1
  102. package/dist/components/input-group.js +1 -1
  103. package/dist/components/input-otp.js +1 -1
  104. package/dist/components/input.js +2 -2
  105. package/dist/components/item.js +1 -1
  106. package/dist/components/kbd.js +1 -1
  107. package/dist/components/kitchen-dossier.d.ts +2 -1
  108. package/dist/components/kitchen-dossier.js +4 -4
  109. package/dist/components/label.js +2 -2
  110. package/dist/components/lazy-markdown.js +1 -1
  111. package/dist/components/link-button.js +3 -3
  112. package/dist/components/markdown-renderer.js +1 -1
  113. package/dist/components/menu-dead-end.d.ts +2 -1
  114. package/dist/components/menu-dead-end.js +1 -1
  115. package/dist/components/menu-family-block.d.ts +2 -1
  116. package/dist/components/menu-family-block.js +15 -9
  117. package/dist/components/menu-family-card.d.ts +2 -1
  118. package/dist/components/menu-family-card.js +1 -1
  119. package/dist/components/menu-field.js +1 -1
  120. package/dist/components/menu-filter-chips.d.ts +2 -1
  121. package/dist/components/menu-filter-chips.js +3 -3
  122. package/dist/components/menu-group-rows.d.ts +2 -1
  123. package/dist/components/menu-group-rows.js +2 -2
  124. package/dist/components/menu-hub-hero.js +1 -1
  125. package/dist/components/menu-index-header.d.ts +2 -1
  126. package/dist/components/menu-index-header.js +2 -2
  127. package/dist/components/menu-index-list.d.ts +2 -1
  128. package/dist/components/menu-index-list.js +5 -5
  129. package/dist/components/menu-intent-hero.d.ts +3 -2
  130. package/dist/components/menu-intent-hero.js +1 -1
  131. package/dist/components/menu-item.d.ts +2 -1
  132. package/dist/components/menu-item.js +4 -4
  133. package/dist/components/menu-kitchen-list.d.ts +2 -1
  134. package/dist/components/menu-kitchen-list.js +4 -4
  135. package/dist/components/menu-mocks.d.ts +16 -5
  136. package/dist/components/menu-mocks.js +23 -2
  137. package/dist/components/menu-types.d.ts +21 -34
  138. package/dist/components/motion-icon-actions.d.ts +27 -0
  139. package/dist/components/motion-icon-actions.js +336 -0
  140. package/dist/components/motion-icon-controls.js +3 -3
  141. package/dist/components/motion-icon-set.d.ts +13 -1
  142. package/dist/components/motion-icon-set.js +197 -6
  143. package/dist/components/motion-icon.d.ts +15 -1
  144. package/dist/components/motion-icon.js +2 -2
  145. package/dist/components/multi-select-combobox.js +8 -8
  146. package/dist/components/multi-select-menu.js +2 -2
  147. package/dist/components/native-select.js +1 -1
  148. package/dist/components/open-now-list.d.ts +2 -1
  149. package/dist/components/open-now-list.js +2 -2
  150. package/dist/components/pagination.js +3 -3
  151. package/dist/components/phone-frame.js +1 -1
  152. package/dist/components/photo-ground.js +1 -1
  153. package/dist/components/place-about-tab.d.ts +2 -1
  154. package/dist/components/place-about-tab.js +6 -6
  155. package/dist/components/place-card.d.ts +94 -12
  156. package/dist/components/place-card.js +203 -128
  157. package/dist/components/place-details-mobile.d.ts +2 -1
  158. package/dist/components/place-details-mobile.js +7 -7
  159. package/dist/components/place-schedule-week.d.ts +2 -1
  160. package/dist/components/place-schedule-week.js +3 -3
  161. package/dist/components/place-types.d.ts +3 -265
  162. package/dist/components/popover.js +2 -2
  163. package/dist/components/poster-stack.js +1 -1
  164. package/dist/components/poster-tape.js +1 -1
  165. package/dist/components/poster-wall.d.ts +22 -6
  166. package/dist/components/poster-wall.js +197 -12
  167. package/dist/components/progress.js +1 -1
  168. package/dist/components/qa-block.d.ts +2 -1
  169. package/dist/components/qa-block.js +1 -1
  170. package/dist/components/quiet-stretch.js +1 -1
  171. package/dist/components/radio-group.js +1 -1
  172. package/dist/components/rating.js +1 -1
  173. package/dist/components/scroll-area.js +1 -1
  174. package/dist/components/scroll-fade.js +2 -2
  175. package/dist/components/search-bar.js +1 -1
  176. package/dist/components/searchable-select.js +6 -6
  177. package/dist/components/section-header.js +2 -2
  178. package/dist/components/segmented-nav.d.ts +24 -4
  179. package/dist/components/segmented-nav.js +11 -2
  180. package/dist/components/select.js +1 -1
  181. package/dist/components/selection-bar.js +1 -1
  182. package/dist/components/separator.js +2 -2
  183. package/dist/components/sheet.js +1 -1
  184. package/dist/components/signature-chip.js +3 -3
  185. package/dist/components/skeleton-card.js +3 -3
  186. package/dist/components/skeleton.js +2 -2
  187. package/dist/components/slider.js +1 -1
  188. package/dist/components/sliding-panels.js +3 -3
  189. package/dist/components/snap-rail.js +2 -2
  190. package/dist/components/sonner.js +1 -1
  191. package/dist/components/sort-option-list.js +1 -1
  192. package/dist/components/spinner.js +1 -1
  193. package/dist/components/stat-banner.js +1 -1
  194. package/dist/components/stepper.js +1 -1
  195. package/dist/components/sticky-container.js +1 -1
  196. package/dist/components/story.js +1 -1
  197. package/dist/components/switch.js +1 -1
  198. package/dist/components/table.js +1 -1
  199. package/dist/components/tabs.js +2 -2
  200. package/dist/components/tag-group.js +2 -2
  201. package/dist/components/tag.js +2 -2
  202. package/dist/components/text.js +2 -2
  203. package/dist/components/textarea.js +1 -1
  204. package/dist/components/timeline-band.js +4 -4
  205. package/dist/components/timeline-playhead.js +4 -4
  206. package/dist/components/toggle-group.js +2 -2
  207. package/dist/components/toggle.js +2 -2
  208. package/dist/components/tooltip.js +1 -1
  209. package/dist/components/top-comparison.d.ts +2 -1
  210. package/dist/components/top-comparison.js +1 -1
  211. package/dist/components/top-cross-link.d.ts +2 -1
  212. package/dist/components/top-cross-link.js +1 -1
  213. package/dist/components/top-ranking-entry.d.ts +2 -1
  214. package/dist/components/top-ranking-entry.js +6 -6
  215. package/dist/components/top-ranking-hero.d.ts +2 -1
  216. package/dist/components/top-ranking-hero.js +1 -1
  217. package/dist/components/top-ranking-legend.js +1 -1
  218. package/dist/components/top-types.d.ts +3 -1
  219. package/dist/components/use-mobile.js +1 -1
  220. package/dist/components/venue-events-block.js +5 -5
  221. package/dist/components/venue-grade-dimensions.d.ts +2 -1
  222. package/dist/components/venue-grade-dimensions.js +1 -1
  223. package/dist/components/venue-quotes.d.ts +2 -1
  224. package/dist/components/venue-quotes.js +1 -1
  225. package/dist/components/venue-wall.d.ts +2 -1
  226. package/dist/components/venue-wall.js +1 -1
  227. package/dist/components/weekday-theme-banner.js +1 -1
  228. package/dist/components/weekend-panel.js +4 -4
  229. package/dist/hooks/use-drag-swipe.js +1 -1
  230. package/dist/hooks/use-haptic.js +2 -2
  231. package/dist/hooks/use-media-query.js +1 -1
  232. package/dist/hooks/use-mobile.js +1 -1
  233. package/dist/hooks/use-mounted-theme.js +1 -1
  234. package/dist/hooks/use-sticky.js +1 -1
  235. package/dist/lib/card-hover.js +2 -18
  236. package/dist/lib/grade.d.ts +54 -0
  237. package/dist/lib/grade.js +2 -0
  238. package/dist/lib/icon-depth.d.ts +35 -0
  239. package/dist/lib/icon-depth.js +2 -0
  240. package/dist/lib/icon-registry.js +1 -1
  241. package/dist/lib/motion.js +2 -2
  242. package/dist/lib/overlay-pill.d.ts +30 -0
  243. package/dist/lib/overlay-pill.js +2 -0
  244. package/dist/lib/utils.js +1 -1
  245. package/dist/place-types-BHdeMMiG.d.ts +317 -0
  246. package/package.json +1 -1
  247. package/src/components/button.tsx +5 -1
  248. package/src/components/colour-dictionary.stories.tsx +268 -82
  249. package/src/components/doorway-tiles.stories.tsx +83 -0
  250. package/src/components/doorway-tiles.test.tsx +51 -0
  251. package/src/components/doorway-tiles.tsx +225 -0
  252. package/src/components/grade-atom.stories.tsx +81 -0
  253. package/src/components/grade-atom.tsx +256 -0
  254. package/src/components/hue-chip.stories.tsx +2 -2
  255. package/src/components/menu-family-block.stories.tsx +29 -0
  256. package/src/components/menu-family-block.test.tsx +51 -0
  257. package/src/components/menu-family-block.tsx +20 -4
  258. package/src/components/menu-intent-hero.tsx +1 -1
  259. package/src/components/menu-mocks.ts +39 -3
  260. package/src/components/menu-types.ts +17 -33
  261. package/src/components/motion-icon-actions.test.tsx +115 -0
  262. package/src/components/motion-icon-actions.tsx +580 -0
  263. package/src/components/motion-icon-controls.test.tsx +1 -0
  264. package/src/components/motion-icon-controls.tsx +18 -13
  265. package/src/components/motion-icon-set.stories.tsx +62 -3
  266. package/src/components/motion-icon-set.tsx +349 -2
  267. package/src/components/motion-icon.test.tsx +180 -1
  268. package/src/components/motion-icon.tsx +97 -8
  269. package/src/components/place-card.stories.tsx +66 -76
  270. package/src/components/place-card.test.tsx +188 -100
  271. package/src/components/place-card.tsx +356 -148
  272. package/src/components/place-types.ts +17 -4
  273. package/src/components/poster-wall.stories.tsx +84 -0
  274. package/src/components/poster-wall.test.tsx +94 -3
  275. package/src/components/poster-wall.tsx +257 -9
  276. package/src/components/segmented-nav.stories.tsx +72 -1
  277. package/src/components/segmented-nav.test.tsx +96 -0
  278. package/src/components/segmented-nav.tsx +36 -4
  279. package/src/globals.css +26 -0
  280. package/src/hooks/use-haptic.test.tsx +80 -0
  281. package/src/hooks/use-haptic.ts +45 -4
  282. package/src/lib/grade.test.ts +82 -0
  283. package/src/lib/grade.ts +76 -0
  284. package/src/lib/icon-depth.ts +35 -0
  285. package/src/lib/overlay-pill.ts +29 -0
  286. package/dist/components/haptic-button.d.ts +0 -12
  287. package/dist/components/haptic-button.js +0 -17
  288. package/dist/components/menu-family-tiles.d.ts +0 -19
  289. package/dist/components/menu-family-tiles.js +0 -57
  290. package/src/components/haptic-button.stories.tsx +0 -41
  291. package/src/components/haptic-button.tsx +0 -19
  292. package/src/components/menu-family-tiles.stories.tsx +0 -54
  293. package/src/components/menu-family-tiles.test.tsx +0 -30
  294. package/src/components/menu-family-tiles.tsx +0 -132
@@ -1,145 +1,220 @@
1
- import { Text } from '../chunk-7BWTYWM3.js';
1
+ import { HOVER_IMAGE_MOTION, HOVER_IMAGE_WRAPPER, HOVER_MOTION, HOVER_LIFT_GRID_GROUP } from '../chunk-XCB3F6SF.js';
2
+ import { NEUTRAL_ICON_FILTER } from '../chunk-LQWGZIYA.js';
3
+ import { OVERLAY_PILL } from '../chunk-EZG2NELX.js';
4
+ import { GradeAtom } from '../chunk-DJD3EMPK.js';
5
+ import { showsGradeAtom } from '../chunk-I5V446BX.js';
6
+ import { Separator } from '../chunk-NWZGSLPU.js';
7
+ import { springSnappy } from '../chunk-OIV7B44M.js';
8
+ import { Skeleton } from '../chunk-XBBEX4SF.js';
9
+ import { Badge } from '../chunk-P43B3ONY.js';
2
10
  import { cn } from '../chunk-FEK5XGZW.js';
3
- import '../chunk-3GWWZKX7.js';
4
- import { memo, useState } from 'react';
5
- import { UtensilsCrossed, Star, Wine, MapPin, Clock } from 'lucide-react';
6
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
11
+ import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
12
+ import { forwardRef, memo, useState, useMemo } from 'react';
13
+ import { UtensilsCrossed, MapPin, Star } from 'lucide-react';
14
+ import { motion } from 'framer-motion';
15
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
16
 
17
+ var DefaultLink = forwardRef(function DefaultLink2(_a, ref) {
18
+ var _b = _a, { href } = _b, props = __objRest(_b, ["href"]);
19
+ return /* @__PURE__ */ jsx("a", __spreadValues({ ref, href }, props));
20
+ });
21
+ function DefaultImage({ src, alt, priority, className, onError }) {
22
+ return (
23
+ // eslint-disable-next-line @next/next/no-img-element
24
+ /* @__PURE__ */ jsx(
25
+ "img",
26
+ {
27
+ src,
28
+ alt,
29
+ loading: priority ? "eager" : "lazy",
30
+ decoding: "async",
31
+ className,
32
+ onError
33
+ }
34
+ )
35
+ );
36
+ }
8
37
  function formatDistance(meters) {
9
- return meters ? `${(meters / 1e3).toFixed(1)} km` : "\u2014";
38
+ if (meters < 1e3) return `${Math.round(meters)} m`;
39
+ return `${(meters / 1e3).toFixed(1)} km`;
10
40
  }
11
- function formatRating(rating) {
12
- return (rating == null ? void 0 : rating.rating) ? rating.rating.toFixed(1) : null;
41
+ function HeadlineRating({ place, labels }) {
42
+ var _a, _b;
43
+ const grade = (_a = place.reviews_digest) == null ? void 0 : _a.grade;
44
+ if (showsGradeAtom(grade, "xs")) return /* @__PURE__ */ jsx(GradeAtom, { grade, labels: labels.grade, size: "xs" });
45
+ const rating = (_b = place.rating) == null ? void 0 : _b.rating;
46
+ if (rating === void 0) return null;
47
+ return /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1 text-xs font-medium text-foreground", children: [
48
+ /* @__PURE__ */ jsx(Star, { className: "h-3 w-3 fill-current", "aria-hidden": true }),
49
+ /* @__PURE__ */ jsx("span", { className: "tabular-nums", children: rating.toFixed(1) })
50
+ ] });
13
51
  }
52
+ function PriceLevel({ level, label }) {
53
+ const filled = Math.min(Math.max(Math.round(level), 1), 4);
54
+ return /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", "aria-label": label, children: [
55
+ "$".repeat(filled),
56
+ /* @__PURE__ */ jsx("span", { className: "opacity-30", children: "$".repeat(4 - filled) })
57
+ ] });
58
+ }
59
+ var STATIC_ROOT_CLASSES = `group relative flex w-full select-none flex-col ${HOVER_MOTION} ${HOVER_LIFT_GRID_GROUP}`;
60
+ var ROOT_CLASSES = `${STATIC_ROOT_CLASSES} cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:rounded-xl`;
61
+ var DEFAULT_SIZES = "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw";
14
62
  var PlaceCard = memo(function PlaceCard2({
15
63
  place,
16
64
  labels,
17
- onClick,
18
- className,
19
- priority
65
+ priority = false,
66
+ imageSizes = DEFAULT_SIZES,
67
+ href,
68
+ linkComponent: LinkComponent = DefaultLink,
69
+ imageComponent: ImageComponent = DefaultImage,
70
+ onOpen,
71
+ footer,
72
+ photoOverlay,
73
+ className
20
74
  }) {
21
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
75
+ var _a, _b, _c, _d, _e, _f, _g, _h;
22
76
  const [imgError, setImgError] = useState(false);
23
- const ratingDisplay = formatRating(place.rating);
24
- const reviewCount = (_b = place.review_count) != null ? _b : (_a = place.rating) == null ? void 0 : _a.count;
25
- const showHeader = !!place.thumbnail_url && !imgError;
26
- const distanceMeters = (_d = (_c = place.location) == null ? void 0 : _c.distance) == null ? void 0 : _d.meters;
27
- const schedule = (_g = (_e = place.today_schedule) == null ? void 0 : _e[0]) != null ? _g : (_f = place.hours) == null ? void 0 : _f[0];
28
- const scheduleHour = place.open_now ? schedule == null ? void 0 : schedule.closes_at : schedule == null ? void 0 : schedule.opens_at;
29
- const scheduleLabel = place.open_now ? labels.until : labels.opensAt;
30
- const sharedClasses = cn(
31
- "glass rounded-3xl border border-transparent bg-transparent p-0 text-left text-card-foreground transition-transform duration-300 ease-in-out hover:border-border/20 h-full flex flex-col w-full",
32
- onClick && "cursor-pointer [@media(hover:hover)]:hover:-translate-y-1 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
33
- className
34
- );
35
- const content = /* @__PURE__ */ jsxs("div", { className: "p-4 flex-1 flex flex-col", children: [
36
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 mb-3", children: [
37
- /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-lg bg-primary/10 flex items-center justify-center overflow-hidden flex-shrink-0", children: showHeader ? (
38
- // eslint-disable-next-line @next/next/no-img-element
39
- /* @__PURE__ */ jsx(
40
- "img",
41
- {
42
- src: place.thumbnail_url,
43
- alt: place.name,
44
- title: place.name,
45
- width: 48,
46
- height: 48,
47
- loading: priority ? "eager" : "lazy",
48
- decoding: "async",
49
- className: "w-full h-full object-cover",
50
- onError: () => setImgError(true)
51
- }
52
- )
53
- ) : /* @__PURE__ */ jsx(
54
- UtensilsCrossed,
55
- {
56
- className: "w-6 h-6 text-primary/60",
57
- "aria-hidden": "true"
58
- }
59
- ) }),
60
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
61
- /* @__PURE__ */ jsx(Text, { as: "h3", weight: "bold", leading: "tight", color: "default", className: "text-lg mb-2", children: place.name }),
62
- ratingDisplay !== null && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
63
- /* @__PURE__ */ jsx(Star, { className: "w-4 h-4 fill-primary text-primary", "aria-hidden": "true" }),
64
- /* @__PURE__ */ jsx("span", { className: "font-semibold text-sm", children: ratingDisplay }),
65
- reviewCount !== void 0 && reviewCount !== null && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
66
- "(",
67
- reviewCount,
68
- ")"
69
- ] })
70
- ] })
71
- ] })
72
- ] }),
73
- (place.price_dishes || place.price_drinks) && /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 text-xs", children: [
74
- ((_h = place.price_dishes) == null ? void 0 : _h.price_range_low) != null && ((_i = place.price_dishes) == null ? void 0 : _i.price_range_high) != null && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-primary", children: [
75
- /* @__PURE__ */ jsx(UtensilsCrossed, { className: "w-4 h-4", "aria-hidden": "true" }),
76
- /* @__PURE__ */ jsxs("span", { children: [
77
- place.price_dishes.price_range_low,
78
- "-",
79
- place.price_dishes.price_range_high,
80
- " ",
81
- labels.currency
82
- ] })
77
+ const MotionLink = useMemo(() => motion.create(LinkComponent), [LinkComponent]);
78
+ const coverUrl = imgError ? void 0 : place.cover_url;
79
+ const cuisine = (_a = place.cuisines) == null ? void 0 : _a[0];
80
+ const distance = (_c = (_b = place.location) == null ? void 0 : _b.distance) == null ? void 0 : _c.meters;
81
+ const neighbourhood = (_e = (_d = place.areas) == null ? void 0 : _d[0]) == null ? void 0 : _e.name;
82
+ const priceLevel = (_h = (_f = place.price_dishes) == null ? void 0 : _f.price_score) != null ? _h : (_g = place.price_drinks) == null ? void 0 : _g.price_score;
83
+ const showPrice = priceLevel !== void 0 && priceLevel > 0;
84
+ const ariaLabel = labels.viewDetails(place.name);
85
+ const handleKeyDown = (e) => {
86
+ if (e.key === "Enter" || e.key === " ") {
87
+ e.preventDefault();
88
+ onOpen == null ? void 0 : onOpen(place);
89
+ }
90
+ };
91
+ const handleAnchorClick = (e) => {
92
+ if (!onOpen || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
93
+ e.preventDefault();
94
+ onOpen(place);
95
+ };
96
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
97
+ /* @__PURE__ */ jsxs(
98
+ "div",
99
+ {
100
+ className: cn(
101
+ "relative aspect-[4/3] w-full overflow-hidden rounded-xl",
102
+ HOVER_IMAGE_WRAPPER
103
+ ),
104
+ children: [
105
+ coverUrl ? /* @__PURE__ */ jsx(
106
+ ImageComponent,
107
+ {
108
+ src: coverUrl,
109
+ alt: place.name,
110
+ sizes: imageSizes,
111
+ priority,
112
+ className: `absolute inset-0 h-full w-full object-cover ${HOVER_IMAGE_MOTION} motion-image-enter`,
113
+ onError: () => setImgError(true)
114
+ }
115
+ ) : (
116
+ /* The neutral grey placeholder every card type shares. The glyph
117
+ sits at `--accent` (the brand brown) rather than `text-muted-
118
+ foreground`, so it reads as intentional instead of as a washed-out
119
+ failed image. */
120
+ /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center bg-gradient-to-br from-muted to-border", children: /* @__PURE__ */ jsx(
121
+ UtensilsCrossed,
122
+ {
123
+ className: "h-10 w-10 text-[color:var(--accent)]",
124
+ style: { filter: NEUTRAL_ICON_FILTER },
125
+ "aria-hidden": true
126
+ }
127
+ ) })
128
+ ),
129
+ place.open_now === true && /* @__PURE__ */ jsx(
130
+ "span",
131
+ {
132
+ className: "absolute right-2.5 top-2.5 h-2 w-2 rounded-full bg-green-500 ring-2 ring-white/70",
133
+ "aria-hidden": true
134
+ }
135
+ ),
136
+ place.open_now === false && /* `Badge variant="overlay"` + the shared cover geometry: this pill and
137
+ the caller's `photoOverlay` sit on the same photo and must match. */
138
+ /* @__PURE__ */ jsx(Badge, { variant: "overlay", className: cn(OVERLAY_PILL, "absolute right-2 top-2"), children: labels.closed })
139
+ ]
140
+ }
141
+ ),
142
+ /* @__PURE__ */ jsxs("div", { className: "mt-2.5 flex flex-col", children: [
143
+ /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-baseline justify-between gap-2", children: [
144
+ /* @__PURE__ */ jsx("p", { className: "min-w-0 line-clamp-1 text-sm font-semibold text-foreground", children: place.name }),
145
+ /* @__PURE__ */ jsx(HeadlineRating, { place, labels })
83
146
  ] }),
84
- ((_j = place.price_drinks) == null ? void 0 : _j.price_range_low) != null && ((_k = place.price_drinks) == null ? void 0 : _k.price_range_high) != null && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-primary", children: [
85
- /* @__PURE__ */ jsx(Wine, { className: "w-4 h-4", "aria-hidden": "true" }),
86
- /* @__PURE__ */ jsxs("span", { children: [
87
- place.price_drinks.price_range_low,
88
- "-",
89
- place.price_drinks.price_range_high,
90
- " ",
91
- labels.currency
92
- ] })
93
- ] })
94
- ] }) }),
95
- /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-primary", children: [
96
- distanceMeters !== void 0 && distanceMeters !== null && /* @__PURE__ */ jsxs(Fragment, { children: [
97
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
98
- /* @__PURE__ */ jsx(MapPin, { className: "w-3 h-3", "aria-hidden": "true" }),
99
- /* @__PURE__ */ jsx("span", { className: "text-xs", children: formatDistance(distanceMeters) })
147
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
148
+ (cuisine || showPrice) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
149
+ cuisine && /* @__PURE__ */ jsx("span", { className: "capitalize", children: cuisine }),
150
+ cuisine && showPrice && /* @__PURE__ */ jsx("span", { className: "text-border", children: "\xB7" }),
151
+ showPrice && /* @__PURE__ */ jsx(PriceLevel, { level: priceLevel, label: labels.priceLevel(priceLevel) })
100
152
  ] }),
101
- /* @__PURE__ */ jsx("span", { children: "\xB7" })
153
+ distance !== void 0 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
154
+ /* @__PURE__ */ jsx(MapPin, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
155
+ /* @__PURE__ */ jsx("span", { children: formatDistance(distance) })
156
+ ] }) : neighbourhood ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
157
+ /* @__PURE__ */ jsx(MapPin, { className: "h-3 w-3 shrink-0", "aria-hidden": true }),
158
+ /* @__PURE__ */ jsx("span", { className: "line-clamp-1", children: neighbourhood })
159
+ ] }) : null
102
160
  ] }),
103
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
104
- /* @__PURE__ */ jsx(
105
- Clock,
106
- {
107
- className: cn(
108
- "w-3 h-3",
109
- place.open_now ? "text-green-500" : "text-muted-foreground"
110
- ),
111
- "aria-hidden": "true"
112
- }
113
- ),
114
- /* @__PURE__ */ jsx(
115
- "span",
116
- {
117
- className: cn(
118
- "text-xs",
119
- place.open_now ? "text-green-500" : "text-muted-foreground"
120
- ),
121
- children: place.open_now ? labels.open : labels.closed
122
- }
123
- ),
124
- scheduleHour != null && /* @__PURE__ */ jsx(
125
- "span",
126
- {
127
- className: cn(
128
- "text-xs",
129
- place.open_now ? "text-green-500" : "text-muted-foreground"
130
- ),
131
- children: `\xB7 ${scheduleLabel} ${String(scheduleHour).padStart(2, "0")}:00`
132
- }
133
- )
161
+ footer && /* @__PURE__ */ jsxs(Fragment, { children: [
162
+ /* @__PURE__ */ jsx(Separator, { className: "my-2" }),
163
+ /* @__PURE__ */ jsx("div", { children: footer })
134
164
  ] })
135
- ] }) }),
136
- place.description && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(Text, { as: "p", variant: "caption", color: "muted", className: "line-clamp-2", children: place.description }) })
165
+ ] })
166
+ ] });
167
+ return /* @__PURE__ */ jsxs("div", { className: cn("group/card relative w-full", className), children: [
168
+ href ? /* @__PURE__ */ jsx(
169
+ MotionLink,
170
+ {
171
+ href,
172
+ "aria-label": ariaLabel,
173
+ onClick: handleAnchorClick,
174
+ whileTap: { scale: 0.98 },
175
+ transition: springSnappy,
176
+ className: ROOT_CLASSES,
177
+ children: body
178
+ }
179
+ ) : onOpen ? /* @__PURE__ */ jsx(
180
+ motion.div,
181
+ {
182
+ role: "button",
183
+ tabIndex: 0,
184
+ "aria-label": ariaLabel,
185
+ onClick: () => onOpen(place),
186
+ onKeyDown: handleKeyDown,
187
+ whileTap: { scale: 0.98 },
188
+ transition: springSnappy,
189
+ className: ROOT_CLASSES,
190
+ children: body
191
+ }
192
+ ) : (
193
+ /* Neither destination nor handler (a fixture in a marketing hero): a
194
+ plain block, not a focusable control that announces and does nothing. */
195
+ /* @__PURE__ */ jsx("div", { className: STATIC_ROOT_CLASSES, children: body })
196
+ ),
197
+ photoOverlay && /* @__PURE__ */ jsx("div", { className: cn("absolute left-2 top-2 z-10", HOVER_MOTION, HOVER_LIFT_GRID_GROUP), children: photoOverlay })
137
198
  ] });
138
- if (onClick) {
139
- return /* @__PURE__ */ jsx("button", { type: "button", className: sharedClasses, onClick: () => onClick(place), children: content });
140
- }
141
- return /* @__PURE__ */ jsx("div", { className: sharedClasses, children: content });
142
199
  });
143
- PlaceCard.displayName = "PlaceCard";
200
+ function PlaceCardSkeleton({ footer, className }) {
201
+ return /* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: cn("flex w-full flex-col", className), children: [
202
+ /* @__PURE__ */ jsx(Skeleton, { className: "aspect-[4/3] w-full rounded-xl" }),
203
+ /* @__PURE__ */ jsxs("div", { className: "mt-2.5 flex flex-col", children: [
204
+ /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center justify-between gap-2", children: [
205
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/5" }),
206
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-9 rounded-md" })
207
+ ] }),
208
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
209
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-2/5" }),
210
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-1/3" })
211
+ ] }),
212
+ footer && /* @__PURE__ */ jsxs(Fragment, { children: [
213
+ /* @__PURE__ */ jsx(Separator, { className: "my-2" }),
214
+ /* @__PURE__ */ jsx("div", { children: footer })
215
+ ] })
216
+ ] })
217
+ ] });
218
+ }
144
219
 
145
- export { PlaceCard };
220
+ export { PlaceCard, PlaceCardSkeleton };
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { PlacePreview, PlaceDetailsMobileLabels } from './place-types.js';
2
+ import { P as PlacePreview, e as PlaceDetailsMobileLabels } from '../place-types-BHdeMMiG.js';
3
+ import '../lib/grade.js';
3
4
 
4
5
  interface PlaceDetailsMobileProps {
5
6
  place: PlacePreview;
@@ -1,11 +1,11 @@
1
- import { PlaceAboutTab } from '../chunk-HSIYYA2E.js';
2
- import '../chunk-VG3PND3D.js';
3
- import '../chunk-ZDAHKI3A.js';
4
- import '../chunk-WSRWFA6K.js';
5
- import { Text } from '../chunk-7BWTYWM3.js';
6
- import { Badge } from '../chunk-2CXU5WZO.js';
1
+ import { PlaceAboutTab } from '../chunk-HQU6QVAN.js';
2
+ import '../chunk-FMTJGO76.js';
3
+ import '../chunk-MWB7S54O.js';
4
+ import '../chunk-NWZGSLPU.js';
5
+ import { Text } from '../chunk-ZLMRVBD7.js';
6
+ import { Badge } from '../chunk-P43B3ONY.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
8
- import '../chunk-3GWWZKX7.js';
8
+ import '../chunk-MMUBH76A.js';
9
9
  import { useState } from 'react';
10
10
  import { UtensilsCrossed, Star, DollarSign, Clock, Info, MessageSquare, CalendarDays } from 'lucide-react';
11
11
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { PlaceSchedule, PlaceScheduleWeekLabels } from './place-types.js';
2
+ import { f as PlaceSchedule, g as PlaceScheduleWeekLabels } from '../place-types-BHdeMMiG.js';
3
+ import '../lib/grade.js';
3
4
 
4
5
  interface PlaceScheduleWeekProps {
5
6
  schedule?: PlaceSchedule;
@@ -1,4 +1,4 @@
1
- export { PlaceScheduleWeek } from '../chunk-VG3PND3D.js';
2
- import '../chunk-7BWTYWM3.js';
1
+ export { PlaceScheduleWeek } from '../chunk-FMTJGO76.js';
2
+ import '../chunk-ZLMRVBD7.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
- import '../chunk-3GWWZKX7.js';
4
+ import '../chunk-MMUBH76A.js';