@bearmenu/ui 0.8.32 → 0.8.34

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 (101) hide show
  1. package/dist/{chunk-5HHRVJOT.js → chunk-5SGKGFMN.js} +1 -1
  2. package/dist/{chunk-GESB7GCF.js → chunk-6W25S5CF.js} +1 -1
  3. package/dist/chunk-LY67SOFC.js +142 -0
  4. package/dist/{chunk-ZU4NAYN7.js → chunk-NIAL4ZU2.js} +13 -1
  5. package/dist/{chunk-JWTN7MNK.js → chunk-TVEIUTBQ.js} +2 -2
  6. package/dist/{chunk-ZJMCU7MI.js → chunk-VCRXL7H5.js} +1 -1
  7. package/dist/chunk-XLHMF6F5.js +127 -0
  8. package/dist/{chunk-VSRGEB36.js → chunk-XNBDACL7.js} +1 -1
  9. package/dist/components/action-bar.d.ts +67 -0
  10. package/dist/components/action-bar.js +43 -0
  11. package/dist/components/activity-row.d.ts +38 -0
  12. package/dist/components/activity-row.js +43 -0
  13. package/dist/components/alert-dialog.js +1 -1
  14. package/dist/components/alert.d.ts +2 -2
  15. package/dist/components/avatar.d.ts +4 -1
  16. package/dist/components/avatar.js +39 -5
  17. package/dist/components/badge.d.ts +1 -1
  18. package/dist/components/badge.js +1 -1
  19. package/dist/components/booking-row.js +1 -1
  20. package/dist/components/button.d.ts +2 -2
  21. package/dist/components/button.js +1 -1
  22. package/dist/components/calendar.js +1 -1
  23. package/dist/components/carousel.js +1 -1
  24. package/dist/components/coach-marks.js +1 -1
  25. package/dist/components/combobox.js +3 -3
  26. package/dist/components/command.d.ts +15 -15
  27. package/dist/components/command.js +2 -2
  28. package/dist/components/concept-convergence.js +2 -2
  29. package/dist/components/currency-input.js +4 -142
  30. package/dist/components/dialog.d.ts +6 -0
  31. package/dist/components/dialog.js +1 -1
  32. package/dist/components/drawer.d.ts +6 -0
  33. package/dist/components/drawer.js +3 -127
  34. package/dist/components/empty-state.d.ts +2 -2
  35. package/dist/components/empty-state.js +1 -1
  36. package/dist/components/event-detail-panel.js +1 -1
  37. package/dist/components/event-list-row-wide.js +1 -1
  38. package/dist/components/filter-category-row.js +1 -1
  39. package/dist/components/hold-countdown.js +1 -1
  40. package/dist/components/link-button.js +1 -1
  41. package/dist/components/menu-family-block.js +1 -1
  42. package/dist/components/menu-index-list.js +1 -1
  43. package/dist/components/menu-item.js +3 -3
  44. package/dist/components/menu-pick-row.d.ts +47 -0
  45. package/dist/components/menu-pick-row.js +49 -0
  46. package/dist/components/multi-select-combobox.js +4 -4
  47. package/dist/components/pagination.js +1 -1
  48. package/dist/components/place-card.js +1 -1
  49. package/dist/components/place-details-mobile.js +1 -1
  50. package/dist/components/qr-panel.d.ts +31 -0
  51. package/dist/components/qr-panel.js +33 -0
  52. package/dist/components/reconcile-bar.d.ts +47 -0
  53. package/dist/components/reconcile-bar.js +60 -0
  54. package/dist/components/responsive-overlay.d.ts +59 -0
  55. package/dist/components/responsive-overlay.js +132 -0
  56. package/dist/components/searchable-select.js +3 -3
  57. package/dist/components/signature-chip.js +2 -2
  58. package/dist/components/sliding-panels.js +1 -1
  59. package/dist/components/spinner.d.ts +2 -2
  60. package/dist/components/split-share-row.d.ts +77 -0
  61. package/dist/components/split-share-row.js +101 -0
  62. package/dist/components/table-ledger-card.d.ts +80 -0
  63. package/dist/components/table-ledger-card.js +84 -0
  64. package/dist/components/table-trigger-band.d.ts +56 -0
  65. package/dist/components/table-trigger-band.js +43 -0
  66. package/dist/components/tag.d.ts +2 -2
  67. package/dist/components/text.d.ts +2 -2
  68. package/dist/components/toggle.d.ts +1 -1
  69. package/dist/components/top-ranking-entry.js +3 -3
  70. package/dist/components/venue-events-block.js +1 -1
  71. package/package.json +10 -1
  72. package/src/components/action-bar.stories.tsx +78 -0
  73. package/src/components/action-bar.tsx +80 -0
  74. package/src/components/activity-row.stories.tsx +78 -0
  75. package/src/components/activity-row.tsx +65 -0
  76. package/src/components/avatar.stories.tsx +55 -0
  77. package/src/components/avatar.tsx +63 -19
  78. package/src/components/badge.stories.tsx +41 -0
  79. package/src/components/badge.tsx +13 -0
  80. package/src/components/button.tsx +1 -1
  81. package/src/components/dialog.tsx +8 -2
  82. package/src/components/drawer.tsx +8 -2
  83. package/src/components/hold-countdown.tsx +1 -1
  84. package/src/components/menu-pick-row.stories.tsx +71 -0
  85. package/src/components/menu-pick-row.tsx +76 -0
  86. package/src/components/qr-panel.stories.tsx +39 -0
  87. package/src/components/qr-panel.tsx +52 -0
  88. package/src/components/reconcile-bar.stories.tsx +57 -0
  89. package/src/components/reconcile-bar.tsx +80 -0
  90. package/src/components/responsive-overlay.stories.tsx +91 -0
  91. package/src/components/responsive-overlay.test.tsx +162 -0
  92. package/src/components/responsive-overlay.tsx +232 -0
  93. package/src/components/shared-table-primitives.test.tsx +482 -0
  94. package/src/components/split-share-row.stories.tsx +114 -0
  95. package/src/components/split-share-row.tsx +150 -0
  96. package/src/components/table-ledger-card.stories.tsx +120 -0
  97. package/src/components/table-ledger-card.tsx +138 -0
  98. package/src/components/table-trigger-band.stories.tsx +76 -0
  99. package/src/components/table-trigger-band.tsx +75 -0
  100. package/src/globals.css +62 -0
  101. package/src/test/setup.ts +11 -0
@@ -0,0 +1,47 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * MenuPickRow — a dish in the add-an-item overlay (16-shared-table.html T3):
5
+ * its name, its price, and a disc that adds it.
6
+ *
7
+ * The disc is the control and the row is not: a whole-row target would make
8
+ * "read the menu" and "add this" the same gesture, and a reader scrolling a
9
+ * long menu would add things by accident. It is 44×44 as the accessibility
10
+ * floor asks, with the drawn 28px disc inside it.
11
+ *
12
+ * A tap adds one unit. There is no stepper and no quantity anywhere in the
13
+ * shared table — one row per unit, so removing one is removing one thing and
14
+ * never an arithmetic edit (the board's ruling 3). `selected` is therefore
15
+ * "this dish is on the table", not a count; a caller showing a second unit
16
+ * shows a second row.
17
+ */
18
+ type MenuPickRowProps = Omit<React.HTMLAttributes<HTMLDivElement>, "onToggle"> & {
19
+ /** The dish. */
20
+ label: React.ReactNode;
21
+ /** Its price, formatted by the caller. */
22
+ price: React.ReactNode;
23
+ /** Is it on the table already? Fills the disc. */
24
+ selected?: boolean;
25
+ onToggle?: () => void;
26
+ /** The disc's accessible name when it would add — "Add Papanași". Injected. */
27
+ addLabel?: string;
28
+ /** Its name when it would remove — "Remove Papanași". Injected. */
29
+ removeLabel?: string;
30
+ disabled?: boolean;
31
+ };
32
+ declare const MenuPickRow: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "onToggle"> & {
33
+ /** The dish. */
34
+ label: React.ReactNode;
35
+ /** Its price, formatted by the caller. */
36
+ price: React.ReactNode;
37
+ /** Is it on the table already? Fills the disc. */
38
+ selected?: boolean;
39
+ onToggle?: () => void;
40
+ /** The disc's accessible name when it would add — "Add Papanași". Injected. */
41
+ addLabel?: string;
42
+ /** Its name when it would remove — "Remove Papanași". Injected. */
43
+ removeLabel?: string;
44
+ disabled?: boolean;
45
+ } & React.RefAttributes<HTMLDivElement>>;
46
+
47
+ export { MenuPickRow, type MenuPickRowProps };
@@ -0,0 +1,49 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
3
+ import * as React from 'react';
4
+ import { Plus } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var MenuPickRow = React.forwardRef(
8
+ (_a, ref) => {
9
+ var _b = _a, { className, label, price, selected = false, onToggle, addLabel, removeLabel, disabled = false } = _b, props = __objRest(_b, ["className", "label", "price", "selected", "onToggle", "addLabel", "removeLabel", "disabled"]);
10
+ return /* @__PURE__ */ jsxs(
11
+ "div",
12
+ __spreadProps(__spreadValues({
13
+ ref,
14
+ "data-slot": "menu-pick-row",
15
+ "data-selected": selected ? "" : void 0,
16
+ className: cn("flex items-center gap-3 py-2.5", className)
17
+ }, props), {
18
+ children: [
19
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-[14px] font-bold", children: label }),
20
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[14px] font-bold tabular-nums", children: price }),
21
+ /* @__PURE__ */ jsx(
22
+ "button",
23
+ {
24
+ type: "button",
25
+ onClick: onToggle,
26
+ disabled,
27
+ "aria-pressed": selected,
28
+ "aria-label": selected ? removeLabel : addLabel,
29
+ className: "grid size-11 shrink-0 place-items-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
30
+ children: /* @__PURE__ */ jsx(
31
+ "span",
32
+ {
33
+ className: cn(
34
+ "grid size-7 place-items-center rounded-full border transition-colors",
35
+ selected ? "border-transparent bg-primary text-primary-foreground" : "border-border bg-background text-muted-foreground"
36
+ ),
37
+ children: /* @__PURE__ */ jsx(Plus, { className: "size-4", "aria-hidden": true, strokeWidth: 2.5 })
38
+ }
39
+ )
40
+ }
41
+ )
42
+ ]
43
+ })
44
+ );
45
+ }
46
+ );
47
+ MenuPickRow.displayName = "MenuPickRow";
48
+
49
+ export { MenuPickRow };
@@ -1,11 +1,11 @@
1
1
  import { Checkbox } from '../chunk-L3CDXVEP.js';
2
2
  import { Popover, PopoverTrigger, PopoverContent } from '../chunk-2ADCZXZJ.js';
3
- import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-ZJMCU7MI.js';
4
- import '../chunk-JWTN7MNK.js';
5
- import { Button } from '../chunk-5HHRVJOT.js';
3
+ import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-VCRXL7H5.js';
4
+ import '../chunk-TVEIUTBQ.js';
5
+ import { Button } from '../chunk-5SGKGFMN.js';
6
6
  import '../chunk-RIH2IS7X.js';
7
7
  import '../chunk-5YNIQ2BL.js';
8
- import { Badge } from '../chunk-ZU4NAYN7.js';
8
+ import { Badge } from '../chunk-NIAL4ZU2.js';
9
9
  import { cn } from '../chunk-FEK5XGZW.js';
10
10
  import '../chunk-MMUBH76A.js';
11
11
  import * as React from 'react';
@@ -1,4 +1,4 @@
1
- import { buttonVariants } from '../chunk-5HHRVJOT.js';
1
+ import { buttonVariants } from '../chunk-5SGKGFMN.js';
2
2
  import '../chunk-RIH2IS7X.js';
3
3
  import '../chunk-5YNIQ2BL.js';
4
4
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -6,7 +6,7 @@ import { showsGradeAtom } from '../chunk-I5V446BX.js';
6
6
  import { Separator } from '../chunk-NWZGSLPU.js';
7
7
  import { springSnappy } from '../chunk-OIV7B44M.js';
8
8
  import { Skeleton } from '../chunk-XBBEX4SF.js';
9
- import { Badge } from '../chunk-ZU4NAYN7.js';
9
+ import { Badge } from '../chunk-NIAL4ZU2.js';
10
10
  import { cn } from '../chunk-FEK5XGZW.js';
11
11
  import { __objRest, __spreadValues } from '../chunk-MMUBH76A.js';
12
12
  import { forwardRef, memo, useState, useMemo } from 'react';
@@ -3,7 +3,7 @@ import '../chunk-FMTJGO76.js';
3
3
  import '../chunk-MWB7S54O.js';
4
4
  import '../chunk-NWZGSLPU.js';
5
5
  import { Text } from '../chunk-ZLMRVBD7.js';
6
- import { Badge } from '../chunk-ZU4NAYN7.js';
6
+ import { Badge } from '../chunk-NIAL4ZU2.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
8
8
  import '../chunk-MMUBH76A.js';
9
9
  import { useState } from 'react';
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * QrPanel — the frame around the code that gets a phone onto a shared table
5
+ * (16-shared-table.html T8).
6
+ *
7
+ * The code arrives as `children`: an `img` with a data URL, an inline `svg`,
8
+ * whatever the caller's QR library returns. The design system imports no QR
9
+ * library — a dependency that ships in every consumer's bundle to serve one
10
+ * sheet is the wrong trade, and the app already has `qrcode`.
11
+ *
12
+ * The white plate is not decoration. A QR reader needs the quiet zone and the
13
+ * light module ground to decode, so the plate stays white in dark mode too and
14
+ * the padding is the quiet zone, not padding taste. Its hairline is a neutral
15
+ * alpha rather than `--border`: the plate is always white, so a themed border
16
+ * would put a dark ring on it in dark mode.
17
+ *
18
+ * The caption sits OUTSIDE the plate, on the sheet's own ground (T8), which is
19
+ * also what lets it use `--muted-foreground` instead of an ink picked to work
20
+ * on white.
21
+ */
22
+ type QrPanelProps = React.HTMLAttributes<HTMLDivElement> & {
23
+ /** The line under the code — "Scan with a phone camera to join". */
24
+ caption?: React.ReactNode;
25
+ };
26
+ declare const QrPanel: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
27
+ /** The line under the code — "Scan with a phone camera to join". */
28
+ caption?: React.ReactNode;
29
+ } & React.RefAttributes<HTMLDivElement>>;
30
+
31
+ export { QrPanel, type QrPanelProps };
@@ -0,0 +1,33 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
3
+ import * as React from 'react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var QrPanel = React.forwardRef(
7
+ (_a, ref) => {
8
+ var _b = _a, { className, caption, children } = _b, props = __objRest(_b, ["className", "caption", "children"]);
9
+ return /* @__PURE__ */ jsxs(
10
+ "div",
11
+ __spreadProps(__spreadValues({
12
+ ref,
13
+ "data-slot": "qr-panel",
14
+ className: cn("flex flex-col items-center gap-3", className)
15
+ }, props), {
16
+ children: [
17
+ /* @__PURE__ */ jsx(
18
+ "div",
19
+ {
20
+ "data-slot": "qr-panel-plate",
21
+ className: "rounded-2xl border border-black/10 bg-white p-5",
22
+ children: /* @__PURE__ */ jsx("div", { "data-slot": "qr-panel-code", className: "[&>*]:block [&>*]:size-full max-w-[220px]", children })
23
+ }
24
+ ),
25
+ caption ? /* @__PURE__ */ jsx("p", { className: "text-center text-[12.5px] leading-normal text-muted-foreground", children: caption }) : null
26
+ ]
27
+ })
28
+ );
29
+ }
30
+ );
31
+ QrPanel.displayName = "QrPanel";
32
+
33
+ export { QrPanel };
@@ -0,0 +1,47 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+ import * as React from 'react';
3
+ import { VariantProps } from 'class-variance-authority';
4
+
5
+ /**
6
+ * ReconcileBar — does the split add up? The shared-table board puts it under
7
+ * every split, in both states (16-shared-table.html T6, X10): "The amounts add
8
+ * up · 120 / 120" on a green ground, "10 lei short of the item total ·
9
+ * 110 / 120" on the warning one.
10
+ *
11
+ * It is the whole answer to "can I save this", so it says the running figure
12
+ * and the target side by side and never makes the reader do the subtraction.
13
+ * The numbers are `tabular-nums`: they change on every keystroke in the custom
14
+ * mode, and proportional digits make the bar twitch while someone types.
15
+ *
16
+ * `message` is injected — the shortfall is money and money is formatted in the
17
+ * caller's locale, which the design system does not know.
18
+ */
19
+ declare const reconcileBarVariants: (props?: ({
20
+ tone?: "short" | "ok" | null | undefined;
21
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
22
+ type ReconcileBarProps = Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & VariantProps<typeof reconcileBarVariants> & {
23
+ /**
24
+ * "The amounts add up", "**10 lei short** of the item total". The caller
25
+ * carries the weight — the shortfall is bold, the rest is not.
26
+ */
27
+ message: React.ReactNode;
28
+ /** What the shares come to now, formatted by the caller. */
29
+ current: React.ReactNode;
30
+ /** What they have to come to — the item's line total. */
31
+ target: React.ReactNode;
32
+ };
33
+ declare const ReconcileBar: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & VariantProps<(props?: ({
34
+ tone?: "short" | "ok" | null | undefined;
35
+ } & class_variance_authority_types.ClassProp) | undefined) => string> & {
36
+ /**
37
+ * "The amounts add up", "**10 lei short** of the item total". The caller
38
+ * carries the weight — the shortfall is bold, the rest is not.
39
+ */
40
+ message: React.ReactNode;
41
+ /** What the shares come to now, formatted by the caller. */
42
+ current: React.ReactNode;
43
+ /** What they have to come to — the item's line total. */
44
+ target: React.ReactNode;
45
+ } & React.RefAttributes<HTMLDivElement>>;
46
+
47
+ export { ReconcileBar, type ReconcileBarProps, reconcileBarVariants };
@@ -0,0 +1,60 @@
1
+ import { cn } from '../chunk-FEK5XGZW.js';
2
+ import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
3
+ import * as React from 'react';
4
+ import { cva } from 'class-variance-authority';
5
+ import { TriangleAlert, Check } from 'lucide-react';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ var reconcileBarVariants = cva(
9
+ "flex items-center gap-2.5 rounded-xl px-3.5 py-3 text-[12.5px] leading-normal [&>svg]:size-4 [&>svg]:shrink-0",
10
+ {
11
+ variants: {
12
+ tone: {
13
+ ok: "bg-success/15 text-success-ink",
14
+ // `--warning-deep` and `--warning-ink` are the tokens for exactly this:
15
+ // the solid `--warning` is tuned as a fill and falls short of AA as ink
16
+ // on its own wash. Both have dark twins, so there is no `dark:` branch.
17
+ short: "bg-warning-deep/15 text-warning-ink"
18
+ }
19
+ },
20
+ defaultVariants: { tone: "ok" }
21
+ }
22
+ );
23
+ var TONE_ICON = {
24
+ ok: /* @__PURE__ */ jsx(Check, { "aria-hidden": true, strokeWidth: 3 }),
25
+ short: /* @__PURE__ */ jsx(TriangleAlert, { "aria-hidden": true })
26
+ };
27
+ var ReconcileBar = React.forwardRef(
28
+ (_a, ref) => {
29
+ var _b = _a, { className, tone, message, current, target } = _b, props = __objRest(_b, ["className", "tone", "message", "current", "target"]);
30
+ return /* @__PURE__ */ jsxs(
31
+ "div",
32
+ __spreadProps(__spreadValues({
33
+ ref,
34
+ "data-slot": "reconcile-bar",
35
+ "data-tone": tone != null ? tone : "ok",
36
+ className: cn(reconcileBarVariants({ tone }), className)
37
+ }, props), {
38
+ children: [
39
+ TONE_ICON[tone != null ? tone : "ok"],
40
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: message }),
41
+ /* @__PURE__ */ jsxs(
42
+ "span",
43
+ {
44
+ "data-slot": "reconcile-bar-figures",
45
+ className: "shrink-0 text-[12px] font-bold tabular-nums",
46
+ children: [
47
+ current,
48
+ /* @__PURE__ */ jsx("span", { className: "px-1.5 opacity-60", children: "/" }),
49
+ target
50
+ ]
51
+ }
52
+ )
53
+ ]
54
+ })
55
+ );
56
+ }
57
+ );
58
+ ReconcileBar.displayName = "ReconcileBar";
59
+
60
+ export { ReconcileBar, reconcileBarVariants };
@@ -0,0 +1,59 @@
1
+ import * as React from 'react';
2
+ import { DialogContent } from './dialog.js';
3
+ import 'react/jsx-runtime';
4
+ import 'class-variance-authority/types';
5
+ import '@radix-ui/react-dialog';
6
+ import 'class-variance-authority';
7
+
8
+ type ResponsiveOverlayProps = {
9
+ open: boolean;
10
+ onOpenChange: (open: boolean) => void;
11
+ /** The overlay's name — "Add an item", "Split this item", "Invite people". */
12
+ title: React.ReactNode;
13
+ /** The one line under it — "Table 18 · from the menu". Optional, never two lines. */
14
+ subtitle?: React.ReactNode;
15
+ /** The scrolling body. */
16
+ children: React.ReactNode;
17
+ /** The closing band — an `ActionBar`, usually. */
18
+ footer?: React.ReactNode;
19
+ /**
20
+ * The close button's accessible name. Injected, like every label here: the
21
+ * design system holds no copy and no i18n.
22
+ */
23
+ closeLabel?: string;
24
+ /** Widths for the desktop dialog. Mobile is always the full-width drawer. */
25
+ size?: React.ComponentPropsWithoutRef<typeof DialogContent>["size"];
26
+ /** Classes for the panel itself — the dialog box or the drawer sheet. */
27
+ className?: string;
28
+ /** Classes for the scrolling body. */
29
+ bodyClassName?: string;
30
+ };
31
+ /**
32
+ * ResponsiveOverlay — one overlay authored once: a `Drawer` under md, a
33
+ * `Dialog` from md.
34
+ *
35
+ * The shared-table board draws the same chrome on T1, T3, T5, T6 and T8
36
+ * (16-shared-table.html) and the two widths never disagree about it: the
37
+ * title and its one-line subtitle top left, a round close top right, the body,
38
+ * and a footer band carrying the note and the actions. What differs is the
39
+ * container — a sheet that a thumb drags down, or a box in the middle of the
40
+ * screen — and that is the only thing this component switches.
41
+ *
42
+ * The scrim is `--scrim-overlay`. bearmenu-fe's `globals.css` loads after the
43
+ * design system's and defines a `--scrim` of its own — an opaque photo hue —
44
+ * so an overlay that reached for `bg-scrim` would paint that colour over the
45
+ * whole page at full alpha. The two drawer/dialog primitives still carry their
46
+ * older `bg-black/…`; this component states the token explicitly rather than
47
+ * changing theirs underneath every other caller.
48
+ *
49
+ * It resolves the width with `useMediaQuery`, which is mobile-first: the
50
+ * drawer is what the server and the first client frame render. A wide screen
51
+ * that arrives with the overlay already open — an invite link opened on a
52
+ * laptop — therefore shows the sheet for one frame before the dialog replaces
53
+ * it. That is the library's documented convention for every breakpoint-
54
+ * switching component, and a second breakpoint hook with different semantics
55
+ * would be a worse thing to own than one frame.
56
+ */
57
+ declare const ResponsiveOverlay: React.ForwardRefExoticComponent<ResponsiveOverlayProps & React.RefAttributes<HTMLDivElement>>;
58
+
59
+ export { ResponsiveOverlay, type ResponsiveOverlayProps };
@@ -0,0 +1,132 @@
1
+ import { useMediaQuery } from '../chunk-OPVKL4VS.js';
2
+ import { Drawer, DrawerContent, DrawerTitle, DrawerDescription } from '../chunk-XLHMF6F5.js';
3
+ import { Dialog, DialogContent, DialogTitle, DialogDescription } from '../chunk-TVEIUTBQ.js';
4
+ import { cn } from '../chunk-FEK5XGZW.js';
5
+ import '../chunk-MMUBH76A.js';
6
+ import * as React from 'react';
7
+ import { X } from 'lucide-react';
8
+ import { jsx, jsxs } from 'react/jsx-runtime';
9
+
10
+ var MD_MEDIA_QUERY = "(min-width: 768px)";
11
+ function useFocusReturn(open) {
12
+ const openerRef = React.useRef(null);
13
+ const wasOpen = React.useRef(false);
14
+ React.useEffect(() => {
15
+ if (open) {
16
+ wasOpen.current = true;
17
+ return;
18
+ }
19
+ if (wasOpen.current) {
20
+ wasOpen.current = false;
21
+ const opener = openerRef.current;
22
+ if (opener && opener.isConnected) {
23
+ requestAnimationFrame(() => opener.focus());
24
+ }
25
+ }
26
+ const track = (event) => {
27
+ const target = event.target;
28
+ if (target instanceof HTMLElement) openerRef.current = target;
29
+ };
30
+ if (document.activeElement instanceof HTMLElement && document.activeElement !== document.body) {
31
+ openerRef.current = document.activeElement;
32
+ }
33
+ document.addEventListener("focusin", track);
34
+ return () => document.removeEventListener("focusin", track);
35
+ }, [open]);
36
+ }
37
+ var ResponsiveOverlay = React.forwardRef(
38
+ ({
39
+ open,
40
+ onOpenChange,
41
+ title,
42
+ subtitle,
43
+ children,
44
+ footer,
45
+ closeLabel = "Close",
46
+ size = "lg",
47
+ className,
48
+ bodyClassName
49
+ }, ref) => {
50
+ const isWide = useMediaQuery(MD_MEDIA_QUERY);
51
+ const titleId = React.useId();
52
+ const subtitleId = React.useId();
53
+ useFocusReturn(open);
54
+ const header = /* @__PURE__ */ jsxs("div", { "data-slot": "responsive-overlay-header", className: "flex items-start gap-3 px-5 pt-5", children: [
55
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
56
+ isWide ? /* @__PURE__ */ jsx(DialogTitle, { id: titleId, className: "text-[19px] font-bold leading-tight", children: title }) : /* @__PURE__ */ jsx(DrawerTitle, { id: titleId, className: "text-[19px] font-bold leading-tight", children: title }),
57
+ subtitle ? isWide ? /* @__PURE__ */ jsx(DialogDescription, { id: subtitleId, className: "mt-1 text-[13px] text-muted-foreground", children: subtitle }) : /* @__PURE__ */ jsx(DrawerDescription, { id: subtitleId, className: "mt-1 text-[13px] text-muted-foreground", children: subtitle }) : null
58
+ ] }),
59
+ /* @__PURE__ */ jsxs(
60
+ "button",
61
+ {
62
+ type: "button",
63
+ "data-slot": "responsive-overlay-close",
64
+ onClick: () => onOpenChange(false),
65
+ className: "-m-1.5 grid size-11 shrink-0 place-items-center rounded-full text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
66
+ children: [
67
+ /* @__PURE__ */ jsx("span", { className: "grid size-8 place-items-center rounded-full bg-surface-2 transition-colors hover:bg-muted", children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": true }) }),
68
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: closeLabel })
69
+ ]
70
+ }
71
+ )
72
+ ] });
73
+ const body = /* @__PURE__ */ jsx(
74
+ "div",
75
+ {
76
+ "data-slot": "responsive-overlay-body",
77
+ className: cn("min-h-0 flex-1 overflow-y-auto px-5 py-4", bodyClassName),
78
+ children
79
+ }
80
+ );
81
+ const foot = footer ? /* @__PURE__ */ jsx(
82
+ "div",
83
+ {
84
+ "data-slot": "responsive-overlay-footer",
85
+ className: "shrink-0 border-t border-border bg-surface-2",
86
+ children: footer
87
+ }
88
+ ) : null;
89
+ if (isWide) {
90
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
91
+ DialogContent,
92
+ {
93
+ ref,
94
+ size,
95
+ showCloseButton: false,
96
+ overlayClassName: "bg-scrim-overlay backdrop-blur-none",
97
+ "aria-labelledby": titleId,
98
+ "aria-describedby": subtitle ? subtitleId : void 0,
99
+ className: cn(
100
+ // The dialog's own `grid gap-4 p-6` would put air between the
101
+ // header, the body and the band the frames draw flush.
102
+ "flex max-h-[85vh] flex-col gap-0 overflow-hidden p-0",
103
+ className
104
+ ),
105
+ children: [
106
+ header,
107
+ body,
108
+ foot
109
+ ]
110
+ }
111
+ ) });
112
+ }
113
+ return /* @__PURE__ */ jsx(Drawer, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
114
+ DrawerContent,
115
+ {
116
+ ref,
117
+ overlayClassName: "bg-scrim-overlay",
118
+ "aria-labelledby": titleId,
119
+ "aria-describedby": subtitle ? subtitleId : void 0,
120
+ className: cn("flex max-h-[85vh] flex-col p-0", className),
121
+ children: [
122
+ header,
123
+ body,
124
+ foot
125
+ ]
126
+ }
127
+ ) });
128
+ }
129
+ );
130
+ ResponsiveOverlay.displayName = "ResponsiveOverlay";
131
+
132
+ export { ResponsiveOverlay };
@@ -1,7 +1,7 @@
1
1
  import { Popover, PopoverTrigger, PopoverContent } from '../chunk-2ADCZXZJ.js';
2
- import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-ZJMCU7MI.js';
3
- import '../chunk-JWTN7MNK.js';
4
- import { Button } from '../chunk-5HHRVJOT.js';
2
+ import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-VCRXL7H5.js';
3
+ import '../chunk-TVEIUTBQ.js';
4
+ import { Button } from '../chunk-5SGKGFMN.js';
5
5
  import '../chunk-RIH2IS7X.js';
6
6
  import '../chunk-5YNIQ2BL.js';
7
7
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -1,4 +1,4 @@
1
- export { SignatureChip } from '../chunk-GESB7GCF.js';
2
- import '../chunk-ZU4NAYN7.js';
1
+ export { SignatureChip } from '../chunk-6W25S5CF.js';
2
+ import '../chunk-NIAL4ZU2.js';
3
3
  import '../chunk-FEK5XGZW.js';
4
4
  import '../chunk-MMUBH76A.js';
@@ -1,4 +1,4 @@
1
- import { Button } from '../chunk-5HHRVJOT.js';
1
+ import { Button } from '../chunk-5SGKGFMN.js';
2
2
  import '../chunk-RIH2IS7X.js';
3
3
  import '../chunk-5YNIQ2BL.js';
4
4
  import { cn } from '../chunk-FEK5XGZW.js';
@@ -4,11 +4,11 @@ import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const spinnerVariants: (props?: ({
6
6
  size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
7
- tone?: "inherit" | "default" | "destructive" | "primary" | null | undefined;
7
+ tone?: "default" | "inherit" | "primary" | "destructive" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  declare const Spinner: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
10
10
  size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
11
- tone?: "inherit" | "default" | "destructive" | "primary" | null | undefined;
11
+ tone?: "default" | "inherit" | "primary" | "destructive" | null | undefined;
12
12
  } & class_variance_authority_types.ClassProp) | undefined) => string> & {
13
13
  /** Visually-hidden label for screen readers. Defaults to "Loading". */
14
14
  label?: string;
@@ -0,0 +1,77 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * SplitShareRow — one person's share of a split item (16-shared-table.html,
5
+ * T6 and X10). Include them or leave them out, and in the custom mode set what
6
+ * they had.
7
+ *
8
+ * The board draws one row two ways and they are the same component: under md a
9
+ * full-width row with the check on the trailing edge, where a thumb is; from md
10
+ * a tile in a three-up grid with a square checkbox leading, where an eye scans
11
+ * a column. Both are CSS on one DOM — the order flips with `order`, the check's
12
+ * radius with a breakpoint — so there is no JS measurement and no flash.
13
+ *
14
+ * The amount sits in a soft pill under md whether or not it is editable, as the
15
+ * frames draw it; from md a fixed amount is plain text and only an editable one
16
+ * keeps the pill, plus a hairline and a focus ring, because on a wide screen
17
+ * nothing else would say "you can type here".
18
+ *
19
+ * The numeral is the bold sans and only the caller's currency suffix is mono,
20
+ * as the board draws money everywhere.
21
+ *
22
+ * The parent owns the grid (`grid md:grid-cols-3`) and the arithmetic. This row
23
+ * reports what it was given and never rounds: allocations are integer minor
24
+ * units and must sum to the line total exactly.
25
+ */
26
+ type SplitShareRowProps = Omit<React.HTMLAttributes<HTMLDivElement>, "onChange" | "children"> & {
27
+ /** Avatar and name, composed by the caller — the design system holds no participant shape. */
28
+ person: React.ReactNode;
29
+ /** The share as the caller formatted it. Shown when `editable` is false. */
30
+ amount: React.ReactNode;
31
+ /** Swaps the amount for a `CurrencyInput`. The custom mode, and only it. */
32
+ editable?: boolean;
33
+ /** The editable value in major units, as `CurrencyInput` takes it. */
34
+ amountValue?: number | null;
35
+ onAmountChange?: (value: number | null) => void;
36
+ /** Passed through to `CurrencyInput` for the editable amount. */
37
+ currency?: string;
38
+ locale?: string;
39
+ /** Is this person in the split? Omit the handler for a row that cannot be excluded. */
40
+ checked?: boolean;
41
+ onCheckedChange?: (checked: boolean) => void;
42
+ /**
43
+ * The checkbox's accessible name — "Include Ana in the split". Injected;
44
+ * the design system holds no copy.
45
+ */
46
+ includeLabel?: string;
47
+ /** The editable amount's accessible name — "Ana's share". */
48
+ amountLabel?: string;
49
+ disabled?: boolean;
50
+ };
51
+ declare const SplitShareRow: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & {
52
+ /** Avatar and name, composed by the caller — the design system holds no participant shape. */
53
+ person: React.ReactNode;
54
+ /** The share as the caller formatted it. Shown when `editable` is false. */
55
+ amount: React.ReactNode;
56
+ /** Swaps the amount for a `CurrencyInput`. The custom mode, and only it. */
57
+ editable?: boolean;
58
+ /** The editable value in major units, as `CurrencyInput` takes it. */
59
+ amountValue?: number | null;
60
+ onAmountChange?: (value: number | null) => void;
61
+ /** Passed through to `CurrencyInput` for the editable amount. */
62
+ currency?: string;
63
+ locale?: string;
64
+ /** Is this person in the split? Omit the handler for a row that cannot be excluded. */
65
+ checked?: boolean;
66
+ onCheckedChange?: (checked: boolean) => void;
67
+ /**
68
+ * The checkbox's accessible name — "Include Ana in the split". Injected;
69
+ * the design system holds no copy.
70
+ */
71
+ includeLabel?: string;
72
+ /** The editable amount's accessible name — "Ana's share". */
73
+ amountLabel?: string;
74
+ disabled?: boolean;
75
+ } & React.RefAttributes<HTMLDivElement>>;
76
+
77
+ export { SplitShareRow, type SplitShareRowProps };