@bearmenu/ui 0.1.1 → 0.5.1

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 (118) hide show
  1. package/dist/{chunk-2CUFS5LF.js → chunk-2BMJRXQX.js} +1 -1
  2. package/dist/chunk-HLQ2IRE7.js +279 -0
  3. package/dist/chunk-IQASCH2V.js +25 -0
  4. package/dist/{chunk-UXAYXRFN.js → chunk-QJ54Z7TC.js} +15 -1
  5. package/dist/{chunk-X6GATUI2.js → chunk-UISA4CIG.js} +1 -0
  6. package/dist/components/alert-dialog.js +1 -1
  7. package/dist/components/alert.d.ts +1 -1
  8. package/dist/components/badge.d.ts +1 -1
  9. package/dist/components/button.d.ts +1 -1
  10. package/dist/components/button.js +1 -1
  11. package/dist/components/calendar.d.ts +9 -7
  12. package/dist/components/calendar.js +153 -39
  13. package/dist/components/card.d.ts +2 -1
  14. package/dist/components/card.js +1 -1
  15. package/dist/components/carousel.js +1 -1
  16. package/dist/components/checkbox.js +3 -25
  17. package/dist/components/command.d.ts +13 -13
  18. package/dist/components/dropdown-menu.js +1 -1
  19. package/dist/components/empty-state.js +1 -1
  20. package/dist/components/haptic-button.js +1 -1
  21. package/dist/components/link-button.js +1 -1
  22. package/dist/components/multi-select-combobox.js +1 -1
  23. package/dist/components/multi-select-menu.d.ts +26 -0
  24. package/dist/components/multi-select-menu.js +71 -0
  25. package/dist/components/pagination.js +1 -1
  26. package/dist/components/phone-frame.d.ts +17 -0
  27. package/dist/components/phone-frame.js +41 -0
  28. package/dist/components/place-about-tab.d.ts +17 -0
  29. package/dist/components/place-about-tab.js +6 -0
  30. package/dist/components/place-card.d.ts +17 -0
  31. package/dist/components/place-card.js +145 -0
  32. package/dist/components/place-details-mobile.d.ts +18 -0
  33. package/dist/components/place-details-mobile.js +187 -0
  34. package/dist/components/place-types.d.ts +145 -0
  35. package/dist/components/place-types.js +1 -0
  36. package/dist/components/search-bar.js +1 -1
  37. package/dist/components/searchable-select.js +1 -1
  38. package/dist/components/skeleton-card.js +1 -1
  39. package/dist/components/skeleton.js +1 -1
  40. package/dist/components/sliding-panels.js +1 -1
  41. package/dist/components/sonner.js +11 -2
  42. package/dist/components/tabs.js +1 -1
  43. package/dist/components/text.d.ts +3 -3
  44. package/dist/components/toaster.js +1 -1
  45. package/package.json +28 -9
  46. package/src/components/accordion.stories.tsx +51 -0
  47. package/src/components/alert-dialog.stories.tsx +45 -0
  48. package/src/components/alert.stories.tsx +85 -0
  49. package/src/components/aspect-ratio.stories.tsx +47 -0
  50. package/src/components/avatar.stories.tsx +66 -0
  51. package/src/components/badge.stories.tsx +60 -0
  52. package/src/components/breadcrumb.stories.tsx +63 -0
  53. package/src/components/button.stories.tsx +115 -0
  54. package/src/components/button.tsx +1 -1
  55. package/src/components/calendar.stories.tsx +47 -0
  56. package/src/components/calendar.tsx +160 -40
  57. package/src/components/card.stories.tsx +72 -0
  58. package/src/components/card.tsx +13 -1
  59. package/src/components/carousel.stories.tsx +62 -0
  60. package/src/components/checkbox.stories.tsx +54 -0
  61. package/src/components/checkbox.tsx +1 -1
  62. package/src/components/collapsible.stories.tsx +34 -0
  63. package/src/components/command.stories.tsx +64 -0
  64. package/src/components/currency-input.stories.tsx +50 -0
  65. package/src/components/dialog.stories.tsx +75 -0
  66. package/src/components/drawer.stories.tsx +47 -0
  67. package/src/components/dropdown-menu.stories.tsx +64 -0
  68. package/src/components/dropdown-menu.tsx +1 -1
  69. package/src/components/empty-state.stories.tsx +67 -0
  70. package/src/components/form.stories.tsx +73 -0
  71. package/src/components/haptic-button.stories.tsx +41 -0
  72. package/src/components/input-otp.stories.tsx +42 -0
  73. package/src/components/input.stories.tsx +41 -0
  74. package/src/components/label.stories.tsx +35 -0
  75. package/src/components/markdown-renderer.stories.tsx +45 -0
  76. package/src/components/multi-select-combobox.stories.tsx +78 -0
  77. package/src/components/multi-select-menu.tsx +96 -0
  78. package/src/components/pagination.stories.tsx +48 -0
  79. package/src/components/phone-frame.stories.tsx +51 -0
  80. package/src/components/phone-frame.test.tsx +82 -0
  81. package/src/components/phone-frame.tsx +59 -0
  82. package/src/components/place-about-tab.stories.tsx +164 -0
  83. package/src/components/place-about-tab.test.tsx +325 -0
  84. package/src/components/place-about-tab.tsx +474 -0
  85. package/src/components/place-card.stories.tsx +120 -0
  86. package/src/components/place-card.test.tsx +187 -0
  87. package/src/components/place-card.tsx +187 -0
  88. package/src/components/place-details-mobile.tsx +251 -0
  89. package/src/components/place-types.ts +127 -0
  90. package/src/components/popover.stories.tsx +42 -0
  91. package/src/components/progress.stories.tsx +35 -0
  92. package/src/components/radio-group.stories.tsx +46 -0
  93. package/src/components/rating.stories.tsx +45 -0
  94. package/src/components/scroll-area.stories.tsx +48 -0
  95. package/src/components/search-bar.stories.tsx +92 -0
  96. package/src/components/searchable-select.stories.tsx +55 -0
  97. package/src/components/select.stories.tsx +92 -0
  98. package/src/components/separator.stories.tsx +33 -0
  99. package/src/components/sheet.stories.tsx +95 -0
  100. package/src/components/skeleton-card.stories.tsx +53 -0
  101. package/src/components/skeleton.stories.tsx +42 -0
  102. package/src/components/skeleton.tsx +1 -0
  103. package/src/components/slider.stories.tsx +27 -0
  104. package/src/components/sliding-panels.stories.tsx +68 -0
  105. package/src/components/sonner.tsx +17 -2
  106. package/src/components/sticky-container.stories.tsx +33 -0
  107. package/src/components/switch.stories.tsx +35 -0
  108. package/src/components/table.stories.tsx +60 -0
  109. package/src/components/tabs.stories.tsx +53 -0
  110. package/src/components/tabs.tsx +1 -1
  111. package/src/components/text.stories.tsx +82 -0
  112. package/src/components/textarea.stories.tsx +35 -0
  113. package/src/components/toast.stories.tsx +63 -0
  114. package/src/components/toggle-group.stories.tsx +60 -0
  115. package/src/components/toggle.stories.tsx +48 -0
  116. package/src/components/tooltip.stories.tsx +71 -0
  117. package/src/globals.css +21 -2
  118. package/src/test/setup.ts +9 -0
@@ -8,6 +8,7 @@ declare const CardHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<H
8
8
  declare const CardTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
9
9
  declare const CardDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
10
10
  declare const CardContent: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
11
+ declare const CardAction: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
11
12
  declare const CardFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
12
13
 
13
- export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
14
+ export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
@@ -1,4 +1,4 @@
1
- export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '../chunk-UXAYXRFN.js';
1
+ export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '../chunk-QJ54Z7TC.js';
2
2
  import '../chunk-4KOMHDZD.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
4
  import '../chunk-3GWWZKX7.js';
@@ -1,4 +1,4 @@
1
- import { Button } from '../chunk-2CUFS5LF.js';
1
+ import { Button } from '../chunk-2BMJRXQX.js';
2
2
  import '../chunk-R47NEOSI.js';
3
3
  import { cn } from '../chunk-FEK5XGZW.js';
4
4
  import { __objRest, __spreadProps, __spreadValues } from '../chunk-3GWWZKX7.js';
@@ -1,25 +1,3 @@
1
- import { cn } from '../chunk-FEK5XGZW.js';
2
- import { __objRest, __spreadProps, __spreadValues } from '../chunk-3GWWZKX7.js';
3
- import * as React from 'react';
4
- import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
5
- import { Check } from 'lucide-react';
6
- import { jsx } from 'react/jsx-runtime';
7
-
8
- var Checkbox = React.forwardRef((_a, ref) => {
9
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
10
- return /* @__PURE__ */ jsx(
11
- CheckboxPrimitive.Root,
12
- __spreadProps(__spreadValues({
13
- ref,
14
- className: cn(
15
- "peer h-5 w-5 shrink-0 rounded-md border border-border glass transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary data-[state=checked]:shadow-lg data-[state=checked]:shadow-primary/20 hover:border-accent/50 hover:shadow-md",
16
- className
17
- )
18
- }, props), {
19
- children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, { className: cn("flex items-center justify-center text-current"), children: /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 animate-in zoom-in-50 duration-200" }) })
20
- })
21
- );
22
- });
23
- Checkbox.displayName = CheckboxPrimitive.Root.displayName;
24
-
25
- export { Checkbox };
1
+ export { Checkbox } from '../chunk-IQASCH2V.js';
2
+ import '../chunk-FEK5XGZW.js';
3
+ import '../chunk-3GWWZKX7.js';
@@ -4,11 +4,11 @@ import { DialogProps } from '@radix-ui/react-dialog';
4
4
 
5
5
  declare const Command: React.ForwardRefExoticComponent<Omit<{
6
6
  children?: React.ReactNode;
7
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
7
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
8
8
  ref?: React.Ref<HTMLDivElement>;
9
9
  } & {
10
10
  asChild?: boolean;
11
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & {
11
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
12
12
  label?: string;
13
13
  shouldFilter?: boolean;
14
14
  filter?: (value: string, search: string, keywords?: string[]) => number;
@@ -25,51 +25,51 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
25
25
  ref?: React.Ref<HTMLInputElement>;
26
26
  } & {
27
27
  asChild?: boolean;
28
- }, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
28
+ }, "key" | "asChild" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
29
29
  value?: string;
30
30
  onValueChange?: (search: string) => void;
31
31
  } & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
32
32
  declare const CommandList: React.ForwardRefExoticComponent<Omit<{
33
33
  children?: React.ReactNode;
34
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
34
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
35
35
  ref?: React.Ref<HTMLDivElement>;
36
36
  } & {
37
37
  asChild?: boolean;
38
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & {
38
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
39
39
  label?: string;
40
40
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
41
41
  declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
42
42
  children?: React.ReactNode;
43
- } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
43
+ } & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
44
44
  ref?: React.Ref<HTMLDivElement>;
45
45
  } & {
46
46
  asChild?: boolean;
47
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
47
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
48
48
  declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
49
49
  children?: React.ReactNode;
50
- } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
50
+ } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
51
51
  ref?: React.Ref<HTMLDivElement>;
52
52
  } & {
53
53
  asChild?: boolean;
54
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key">, "heading" | "value"> & {
54
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "heading" | "value"> & {
55
55
  heading?: React.ReactNode;
56
56
  value?: string;
57
57
  forceMount?: boolean;
58
58
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
59
- declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
59
+ declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
60
60
  ref?: React.Ref<HTMLDivElement>;
61
61
  } & {
62
62
  asChild?: boolean;
63
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key"> & {
63
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
64
64
  alwaysRender?: boolean;
65
65
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
66
66
  declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
67
67
  children?: React.ReactNode;
68
- } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement> | "key"> & {
68
+ } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
69
69
  ref?: React.Ref<HTMLDivElement>;
70
70
  } & {
71
71
  asChild?: boolean;
72
- }, keyof React.HTMLAttributes<HTMLDivElement> | "asChild" | "key">, "onSelect" | "disabled" | "value"> & {
72
+ }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "disabled" | "value"> & {
73
73
  disabled?: boolean;
74
74
  onSelect?: (value: string) => void;
75
75
  value?: string;
@@ -67,7 +67,7 @@ function DropdownMenuCheckboxItem(_a) {
67
67
  var _b = _a, {
68
68
  className,
69
69
  children,
70
- checked
70
+ checked = false
71
71
  } = _b, props = __objRest(_b, [
72
72
  "className",
73
73
  "children",
@@ -1,5 +1,5 @@
1
1
  import { Text } from '../chunk-4KOMHDZD.js';
2
- import { Button } from '../chunk-2CUFS5LF.js';
2
+ import { Button } from '../chunk-2BMJRXQX.js';
3
3
  import '../chunk-R47NEOSI.js';
4
4
  import { cn } from '../chunk-FEK5XGZW.js';
5
5
  import { __objRest, __spreadProps, __spreadValues } from '../chunk-3GWWZKX7.js';
@@ -1,4 +1,4 @@
1
- import { Button } from '../chunk-2CUFS5LF.js';
1
+ import { Button } from '../chunk-2BMJRXQX.js';
2
2
  import { useHaptic } from '../chunk-R47NEOSI.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
4
  import { __objRest, __spreadValues } from '../chunk-3GWWZKX7.js';
@@ -1,4 +1,4 @@
1
- import { Button } from '../chunk-2CUFS5LF.js';
1
+ import { Button } from '../chunk-2BMJRXQX.js';
2
2
  import '../chunk-R47NEOSI.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
4
  import { __objRest, __spreadProps, __spreadValues } from '../chunk-3GWWZKX7.js';
@@ -2,7 +2,7 @@ import { Popover, PopoverTrigger, PopoverContent } from '../chunk-4UO73SKC.js';
2
2
  import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-7H54PTVH.js';
3
3
  import '../chunk-4AVS6CV4.js';
4
4
  import { Badge } from '../chunk-NKHH23YK.js';
5
- import { Button } from '../chunk-2CUFS5LF.js';
5
+ import { Button } from '../chunk-2BMJRXQX.js';
6
6
  import '../chunk-R47NEOSI.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
8
8
  import '../chunk-3GWWZKX7.js';
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ interface MultiSelectMenuOption {
5
+ value: string;
6
+ label: React.ReactNode;
7
+ disabled?: boolean;
8
+ }
9
+ interface MultiSelectMenuProps {
10
+ options: MultiSelectMenuOption[];
11
+ selected: string[];
12
+ onSelectedChange: (values: string[]) => void;
13
+ /** Trigger element rendered via Radix `asChild` — typically a Button. */
14
+ trigger: React.ReactNode;
15
+ /** Optional heading rendered above the option list. */
16
+ label?: string;
17
+ align?: "start" | "center" | "end";
18
+ /** Pixel width of the popover content. Defaults to 220. */
19
+ width?: number;
20
+ /** className for the popover content. */
21
+ contentClassName?: string;
22
+ emptyText?: string;
23
+ }
24
+ declare function MultiSelectMenu({ options, selected, onSelectedChange, trigger, label, align, width, contentClassName, emptyText, }: MultiSelectMenuProps): react_jsx_runtime.JSX.Element;
25
+
26
+ export { MultiSelectMenu, type MultiSelectMenuOption, type MultiSelectMenuProps };
@@ -0,0 +1,71 @@
1
+ import { Popover, PopoverTrigger, PopoverContent } from '../chunk-4UO73SKC.js';
2
+ import { Checkbox } from '../chunk-IQASCH2V.js';
3
+ import { cn } from '../chunk-FEK5XGZW.js';
4
+ import '../chunk-3GWWZKX7.js';
5
+ import * as React from 'react';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ function MultiSelectMenu({
9
+ options,
10
+ selected,
11
+ onSelectedChange,
12
+ trigger,
13
+ label,
14
+ align = "end",
15
+ width = 220,
16
+ contentClassName,
17
+ emptyText = "No options"
18
+ }) {
19
+ const selectedSet = React.useMemo(() => new Set(selected), [selected]);
20
+ function handleToggle(value) {
21
+ const next = new Set(selectedSet);
22
+ if (next.has(value)) {
23
+ next.delete(value);
24
+ } else {
25
+ next.add(value);
26
+ }
27
+ onSelectedChange(Array.from(next));
28
+ }
29
+ return /* @__PURE__ */ jsxs(Popover, { children: [
30
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }),
31
+ /* @__PURE__ */ jsxs(
32
+ PopoverContent,
33
+ {
34
+ align,
35
+ className: cn("p-2", contentClassName),
36
+ style: { width },
37
+ children: [
38
+ label && /* @__PURE__ */ jsx("div", { className: "text-foreground px-2 py-1.5 text-sm font-semibold", children: label }),
39
+ /* @__PURE__ */ jsx("div", { role: "group", "aria-label": label, className: "flex flex-col gap-0.5", children: options.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground px-2 py-1.5 text-sm", children: emptyText }) : options.map((option) => {
40
+ const checked = selectedSet.has(option.value);
41
+ return /* @__PURE__ */ jsxs(
42
+ "label",
43
+ {
44
+ className: cn(
45
+ "flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-sm select-none",
46
+ "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
47
+ option.disabled && "pointer-events-none opacity-50"
48
+ ),
49
+ children: [
50
+ /* @__PURE__ */ jsx(
51
+ Checkbox,
52
+ {
53
+ checked,
54
+ onCheckedChange: () => handleToggle(option.value),
55
+ disabled: option.disabled,
56
+ "aria-label": typeof option.label === "string" ? option.label : option.value
57
+ }
58
+ ),
59
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: option.label })
60
+ ]
61
+ },
62
+ option.value
63
+ );
64
+ }) })
65
+ ]
66
+ }
67
+ )
68
+ ] });
69
+ }
70
+
71
+ export { MultiSelectMenu };
@@ -1,4 +1,4 @@
1
- import { buttonVariants } from '../chunk-2CUFS5LF.js';
1
+ import { buttonVariants } from '../chunk-2BMJRXQX.js';
2
2
  import '../chunk-R47NEOSI.js';
3
3
  import { cn } from '../chunk-FEK5XGZW.js';
4
4
  import { __objRest, __spreadValues, __spreadProps } from '../chunk-3GWWZKX7.js';
@@ -0,0 +1,17 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface PhoneFrameProps {
4
+ children: React.ReactNode;
5
+ className?: string;
6
+ /** Outer frame width in pixels. Height derives from iPhone 17 Pro Max aspect. Default 220. */
7
+ width?: number;
8
+ /**
9
+ * When set, children are rendered at this virtual viewport width and CSS-scaled
10
+ * to fit the actual frame. Use this to render mobile UIs at native sizing
11
+ * (e.g. 390 for iPhone 13/14/15) while displaying inside a smaller frame.
12
+ */
13
+ mobileViewportWidth?: number;
14
+ }
15
+ declare function PhoneFrame({ children, className, width, mobileViewportWidth, }: PhoneFrameProps): react_jsx_runtime.JSX.Element;
16
+
17
+ export { PhoneFrame, type PhoneFrameProps };
@@ -0,0 +1,41 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import '../chunk-3GWWZKX7.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ var SCREEN_ASPECT = 956 / 440;
6
+ var FRAME_PADDING = 6;
7
+ function PhoneFrame({
8
+ children,
9
+ className,
10
+ width = 220,
11
+ mobileViewportWidth
12
+ }) {
13
+ const screenHeight = Math.round(width * SCREEN_ASPECT);
14
+ const innerWidth = width - FRAME_PADDING * 2;
15
+ const scale = mobileViewportWidth ? innerWidth / mobileViewportWidth : 1;
16
+ const viewportHeight = mobileViewportWidth ? screenHeight / scale : screenHeight;
17
+ return /* @__PURE__ */ jsx("div", { className: cn("relative mx-auto shrink-0", className), style: { width }, children: /* @__PURE__ */ jsxs("div", { className: "rounded-[2.5rem] border-[1.5px] border-white/15 bg-black/80 p-1.5 shadow-2xl shadow-black/40", children: [
18
+ /* @__PURE__ */ jsx("div", { className: "absolute top-[10px] left-1/2 -translate-x-1/2 w-[68px] h-[20px] bg-black rounded-full z-10" }),
19
+ /* @__PURE__ */ jsx(
20
+ "div",
21
+ {
22
+ className: "rounded-[2rem] overflow-hidden bg-background relative",
23
+ style: { height: screenHeight },
24
+ children: mobileViewportWidth ? /* @__PURE__ */ jsx(
25
+ "div",
26
+ {
27
+ style: {
28
+ width: mobileViewportWidth,
29
+ height: viewportHeight,
30
+ transform: `scale(${scale})`,
31
+ transformOrigin: "top left"
32
+ },
33
+ children
34
+ }
35
+ ) : children
36
+ }
37
+ )
38
+ ] }) });
39
+ }
40
+
41
+ export { PhoneFrame };
@@ -0,0 +1,17 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { PlacePreview, PlaceAboutTabLabels, PlaceLinkKind } from './place-types.js';
3
+
4
+ interface PlaceAboutTabProps {
5
+ place: PlacePreview;
6
+ labels: PlaceAboutTabLabels;
7
+ /** Slot for an embedded map (FE only). Omit to skip the map row. */
8
+ mapSlot?: React.ReactNode;
9
+ /** Slot for an embedded busyness chart. Rendered only when both this prop and `place.busyness` are present. */
10
+ busynessSlot?: React.ReactNode;
11
+ /** Fires when the user clicks a contact link (phone/website/social). The URL is what the caller passed in. */
12
+ onLinkClick?: (kind: PlaceLinkKind, url: string) => void;
13
+ className?: string;
14
+ }
15
+ declare function PlaceAboutTab({ place, labels, mapSlot, busynessSlot, onLinkClick, className, }: PlaceAboutTabProps): react_jsx_runtime.JSX.Element;
16
+
17
+ export { PlaceAboutTab, type PlaceAboutTabProps };
@@ -0,0 +1,6 @@
1
+ export { PlaceAboutTab } from '../chunk-HLQ2IRE7.js';
2
+ import '../chunk-QJ54Z7TC.js';
3
+ import '../chunk-4KOMHDZD.js';
4
+ import '../chunk-NKHH23YK.js';
5
+ import '../chunk-FEK5XGZW.js';
6
+ import '../chunk-3GWWZKX7.js';
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import { PlacePreview, PlaceCardLabels } from './place-types.js';
3
+
4
+ interface PlaceCardProps {
5
+ place: PlacePreview;
6
+ labels: PlaceCardLabels;
7
+ /** Locale tag (e.g. `"en"`, `"ro"`). Reserved for future Intl number/distance formatting. */
8
+ locale?: string;
9
+ /** Optional click handler. When omitted the card renders as a non-interactive div. */
10
+ onClick?: (place: PlacePreview) => void;
11
+ className?: string;
12
+ /** Forwarded to the thumbnail's `loading` attribute (`"eager"` when true). */
13
+ priority?: boolean;
14
+ }
15
+ declare const PlaceCard: React.NamedExoticComponent<PlaceCardProps>;
16
+
17
+ export { PlaceCard, type PlaceCardProps };
@@ -0,0 +1,145 @@
1
+ import { Text } from '../chunk-4KOMHDZD.js';
2
+ 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';
7
+
8
+ function formatDistance(meters) {
9
+ return meters ? `${(meters / 1e3).toFixed(1)} km` : "\u2014";
10
+ }
11
+ function formatRating(rating) {
12
+ return (rating == null ? void 0 : rating.rating) ? rating.rating.toFixed(1) : null;
13
+ }
14
+ var PlaceCard = memo(function PlaceCard2({
15
+ place,
16
+ labels,
17
+ onClick,
18
+ className,
19
+ priority
20
+ }) {
21
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
22
+ 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-medium 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
+ ] })
83
+ ] }),
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) })
100
+ ] }),
101
+ /* @__PURE__ */ jsx("span", { children: "\xB7" })
102
+ ] }),
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
+ )
134
+ ] })
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 }) })
137
+ ] });
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
+ });
143
+ PlaceCard.displayName = "PlaceCard";
144
+
145
+ export { PlaceCard };
@@ -0,0 +1,18 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { PlacePreview, PlaceDetailsMobileLabels } from './place-types.js';
3
+
4
+ interface PlaceDetailsMobileProps {
5
+ place: PlacePreview;
6
+ labels: PlaceDetailsMobileLabels;
7
+ /** Pre-resolved cover image URL. When omitted or it 404s, an icon fallback renders. */
8
+ coverImageUrl?: string;
9
+ className?: string;
10
+ }
11
+ /**
12
+ * Read-only mobile preview of a place's details page with the About tab selected.
13
+ * Used in admin's live profile preview (inside `<PhoneFrame>`). Pure presentational
14
+ * — all i18n via `labels`, no router/analytics. Tabs are visual only.
15
+ */
16
+ declare function PlaceDetailsMobile({ place, labels, coverImageUrl, className, }: PlaceDetailsMobileProps): react_jsx_runtime.JSX.Element;
17
+
18
+ export { PlaceDetailsMobile, type PlaceDetailsMobileProps };