@bearmenu/ui 0.8.33 → 0.8.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GESB7GCF.js → chunk-6W25S5CF.js} +1 -1
- package/dist/chunk-LY67SOFC.js +142 -0
- package/dist/{chunk-ZU4NAYN7.js → chunk-NIAL4ZU2.js} +13 -1
- package/dist/{chunk-JWTN7MNK.js → chunk-TVEIUTBQ.js} +2 -2
- package/dist/{chunk-ZJMCU7MI.js → chunk-VCRXL7H5.js} +1 -1
- package/dist/chunk-XLHMF6F5.js +127 -0
- package/dist/{chunk-VSRGEB36.js → chunk-XNBDACL7.js} +1 -1
- package/dist/components/action-bar.d.ts +67 -0
- package/dist/components/action-bar.js +43 -0
- package/dist/components/activity-row.d.ts +38 -0
- package/dist/components/activity-row.js +43 -0
- package/dist/components/alert.d.ts +2 -2
- package/dist/components/avatar.d.ts +4 -1
- package/dist/components/avatar.js +39 -5
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/booking-row.d.ts +11 -1
- package/dist/components/booking-row.js +4 -1
- package/dist/components/button.d.ts +2 -2
- package/dist/components/combobox.js +2 -2
- package/dist/components/command.d.ts +15 -15
- package/dist/components/command.js +2 -2
- package/dist/components/concept-convergence.js +2 -2
- package/dist/components/currency-input.js +4 -142
- package/dist/components/dialog.d.ts +6 -0
- package/dist/components/dialog.js +1 -1
- package/dist/components/drawer.d.ts +6 -0
- package/dist/components/drawer.js +3 -127
- package/dist/components/empty-state.d.ts +2 -2
- package/dist/components/filter-category-row.js +1 -1
- package/dist/components/menu-item.js +3 -3
- package/dist/components/menu-pick-row.d.ts +47 -0
- package/dist/components/menu-pick-row.js +49 -0
- package/dist/components/multi-select-combobox.js +3 -3
- package/dist/components/place-card.js +1 -1
- package/dist/components/place-details-mobile.js +1 -1
- package/dist/components/qr-panel.d.ts +31 -0
- package/dist/components/qr-panel.js +33 -0
- package/dist/components/reconcile-bar.d.ts +47 -0
- package/dist/components/reconcile-bar.js +60 -0
- package/dist/components/responsive-overlay.d.ts +59 -0
- package/dist/components/responsive-overlay.js +132 -0
- package/dist/components/searchable-select.js +2 -2
- package/dist/components/signature-chip.js +2 -2
- package/dist/components/spinner.d.ts +2 -2
- package/dist/components/split-share-row.d.ts +77 -0
- package/dist/components/split-share-row.js +101 -0
- package/dist/components/table-ledger-card.d.ts +80 -0
- package/dist/components/table-ledger-card.js +84 -0
- package/dist/components/table-trigger-band.d.ts +56 -0
- package/dist/components/table-trigger-band.js +43 -0
- package/dist/components/tag.d.ts +2 -2
- package/dist/components/text.d.ts +2 -2
- package/dist/components/toggle.d.ts +1 -1
- package/dist/components/top-ranking-entry.js +3 -3
- package/dist/components/venue-events-block.js +1 -1
- package/package.json +23 -207
- package/src/components/action-bar.stories.tsx +78 -0
- package/src/components/action-bar.tsx +80 -0
- package/src/components/activity-row.stories.tsx +78 -0
- package/src/components/activity-row.tsx +65 -0
- package/src/components/avatar.stories.tsx +55 -0
- package/src/components/avatar.tsx +63 -19
- package/src/components/badge.stories.tsx +41 -0
- package/src/components/badge.tsx +13 -0
- package/src/components/booking-row.tsx +13 -0
- package/src/components/dialog.tsx +8 -2
- package/src/components/drawer.tsx +8 -2
- package/src/components/menu-pick-row.stories.tsx +71 -0
- package/src/components/menu-pick-row.tsx +76 -0
- package/src/components/qr-panel.stories.tsx +39 -0
- package/src/components/qr-panel.tsx +52 -0
- package/src/components/reconcile-bar.stories.tsx +57 -0
- package/src/components/reconcile-bar.tsx +80 -0
- package/src/components/responsive-overlay.stories.tsx +91 -0
- package/src/components/responsive-overlay.test.tsx +162 -0
- package/src/components/responsive-overlay.tsx +232 -0
- package/src/components/shared-table-primitives.test.tsx +482 -0
- package/src/components/split-share-row.stories.tsx +114 -0
- package/src/components/split-share-row.tsx +150 -0
- package/src/components/table-ledger-card.stories.tsx +120 -0
- package/src/components/table-ledger-card.tsx +138 -0
- package/src/components/table-trigger-band.stories.tsx +76 -0
- package/src/components/table-trigger-band.tsx +75 -0
- package/src/globals.css +44 -0
- package/src/test/setup.ts +11 -0
|
@@ -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-
|
|
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-
|
|
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,6 +1,6 @@
|
|
|
1
1
|
import { Popover, PopoverTrigger, PopoverContent } from '../chunk-2ADCZXZJ.js';
|
|
2
|
-
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
2
|
+
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../chunk-VCRXL7H5.js';
|
|
3
|
+
import '../chunk-TVEIUTBQ.js';
|
|
4
4
|
import { Button } from '../chunk-5SGKGFMN.js';
|
|
5
5
|
import '../chunk-RIH2IS7X.js';
|
|
6
6
|
import '../chunk-5YNIQ2BL.js';
|
|
@@ -4,11 +4,11 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
|
|
5
5
|
declare const spinnerVariants: (props?: ({
|
|
6
6
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
7
|
-
tone?: "
|
|
7
|
+
tone?: "primary" | "default" | "inherit" | "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?: "
|
|
11
|
+
tone?: "primary" | "default" | "inherit" | "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 };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { CurrencyInput } from '../chunk-LY67SOFC.js';
|
|
2
|
+
import '../chunk-GTQSGDYF.js';
|
|
3
|
+
import { Checkbox } from '../chunk-L3CDXVEP.js';
|
|
4
|
+
import { cn } from '../chunk-FEK5XGZW.js';
|
|
5
|
+
import { __objRest, __spreadProps, __spreadValues } from '../chunk-MMUBH76A.js';
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
var SplitShareRow = React.forwardRef(
|
|
10
|
+
(_a, ref) => {
|
|
11
|
+
var _b = _a, {
|
|
12
|
+
className,
|
|
13
|
+
person,
|
|
14
|
+
amount,
|
|
15
|
+
editable = false,
|
|
16
|
+
amountValue = null,
|
|
17
|
+
onAmountChange,
|
|
18
|
+
currency = "lei",
|
|
19
|
+
locale,
|
|
20
|
+
checked,
|
|
21
|
+
onCheckedChange,
|
|
22
|
+
includeLabel,
|
|
23
|
+
amountLabel,
|
|
24
|
+
disabled = false
|
|
25
|
+
} = _b, props = __objRest(_b, [
|
|
26
|
+
"className",
|
|
27
|
+
"person",
|
|
28
|
+
"amount",
|
|
29
|
+
"editable",
|
|
30
|
+
"amountValue",
|
|
31
|
+
"onAmountChange",
|
|
32
|
+
"currency",
|
|
33
|
+
"locale",
|
|
34
|
+
"checked",
|
|
35
|
+
"onCheckedChange",
|
|
36
|
+
"includeLabel",
|
|
37
|
+
"amountLabel",
|
|
38
|
+
"disabled"
|
|
39
|
+
]);
|
|
40
|
+
const amountId = React.useId();
|
|
41
|
+
return /* @__PURE__ */ jsxs(
|
|
42
|
+
"div",
|
|
43
|
+
__spreadProps(__spreadValues({
|
|
44
|
+
ref,
|
|
45
|
+
"data-slot": "split-share-row",
|
|
46
|
+
"data-checked": checked ? "" : void 0,
|
|
47
|
+
className: cn(
|
|
48
|
+
"flex items-center gap-3 rounded-xl border border-border bg-card px-3 py-2.5",
|
|
49
|
+
className
|
|
50
|
+
)
|
|
51
|
+
}, props), {
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 order-2", children: person }),
|
|
54
|
+
editable ? /* @__PURE__ */ jsxs("span", { className: "order-3 shrink-0", children: [
|
|
55
|
+
/* @__PURE__ */ jsx("label", { htmlFor: amountId, className: "sr-only", children: amountLabel }),
|
|
56
|
+
/* @__PURE__ */ jsx(
|
|
57
|
+
CurrencyInput,
|
|
58
|
+
{
|
|
59
|
+
id: amountId,
|
|
60
|
+
value: amountValue,
|
|
61
|
+
onChange: (next) => onAmountChange == null ? void 0 : onAmountChange(next),
|
|
62
|
+
currency,
|
|
63
|
+
locale,
|
|
64
|
+
disabled,
|
|
65
|
+
className: "h-9 w-24 rounded-lg border border-border bg-surface-2 text-right text-[13px] font-bold tabular-nums focus-within:ring-2 focus-within:ring-ring"
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
] }) : /* @__PURE__ */ jsx(
|
|
69
|
+
"span",
|
|
70
|
+
{
|
|
71
|
+
"data-slot": "split-share-amount",
|
|
72
|
+
className: cn(
|
|
73
|
+
"order-3 shrink-0 rounded-lg bg-surface-2 px-2.5 py-1 text-[13px] font-bold tabular-nums md:bg-transparent md:px-0",
|
|
74
|
+
// Only the amount goes quiet when someone is out of the split.
|
|
75
|
+
// Dimming the whole row takes the name under 4.5:1 with it.
|
|
76
|
+
checked === false && "text-muted-foreground"
|
|
77
|
+
),
|
|
78
|
+
children: amount
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
onCheckedChange ? /* @__PURE__ */ jsx(
|
|
82
|
+
Checkbox,
|
|
83
|
+
{
|
|
84
|
+
checked,
|
|
85
|
+
onCheckedChange: (next) => onCheckedChange(next === true),
|
|
86
|
+
disabled,
|
|
87
|
+
"aria-label": includeLabel,
|
|
88
|
+
className: cn(
|
|
89
|
+
"relative order-4 size-6 rounded-full md:order-1 md:size-5 md:rounded-md",
|
|
90
|
+
"before:absolute before:-inset-2.5 before:content-[''] md:before:-inset-3"
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
) : null
|
|
94
|
+
]
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
SplitShareRow.displayName = "SplitShareRow";
|
|
100
|
+
|
|
101
|
+
export { SplitShareRow };
|