veryfront 0.1.1123 → 0.1.1124
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/esm/deno.js +1 -1
- package/esm/src/chat/message-prep.d.ts.map +1 -1
- package/esm/src/chat/message-prep.js +3 -6
- package/esm/src/chat/provider-errors.d.ts +3 -10
- package/esm/src/chat/provider-errors.d.ts.map +1 -1
- package/esm/src/chat/provider-errors.js +2 -9
- package/esm/src/embedding/veryfront-cloud/rag-store.d.ts.map +1 -1
- package/esm/src/embedding/veryfront-cloud/rag-store.js +5 -2
- package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts +3 -3
- package/esm/src/platform/adapters/veryfront-api-client/operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/operations.js +4 -4
- package/esm/src/platform/adapters/veryfront-api-client/retry-handler.d.ts +4 -15
- package/esm/src/platform/adapters/veryfront-api-client/retry-handler.d.ts.map +1 -1
- package/esm/src/platform/adapters/veryfront-api-client/retry-handler.js +6 -110
- package/esm/src/platform/adapters/veryfront-api-transport.d.ts +40 -0
- package/esm/src/platform/adapters/veryfront-api-transport.d.ts.map +1 -0
- package/esm/src/platform/adapters/veryfront-api-transport.js +142 -0
- package/esm/src/provider/runtime-loader/provider-http.d.ts.map +1 -1
- package/esm/src/provider/runtime-loader/provider-http.js +5 -1
- package/esm/src/react/components/ui/anchored-surface.d.ts +44 -0
- package/esm/src/react/components/ui/anchored-surface.d.ts.map +1 -0
- package/esm/src/react/components/ui/anchored-surface.js +58 -0
- package/esm/src/react/components/ui/collapsible.d.ts.map +1 -1
- package/esm/src/react/components/ui/collapsible.js +3 -9
- package/esm/src/react/components/ui/dialog.d.ts +4 -7
- package/esm/src/react/components/ui/dialog.d.ts.map +1 -1
- package/esm/src/react/components/ui/dialog.js +13 -59
- package/esm/src/react/components/ui/disclosure.d.ts +12 -0
- package/esm/src/react/components/ui/disclosure.d.ts.map +1 -0
- package/esm/src/react/components/ui/disclosure.js +22 -0
- package/esm/src/react/components/ui/drawer.d.ts +5 -7
- package/esm/src/react/components/ui/drawer.d.ts.map +1 -1
- package/esm/src/react/components/ui/drawer.js +13 -57
- package/esm/src/react/components/ui/dropdown-menu.d.ts +4 -7
- package/esm/src/react/components/ui/dropdown-menu.d.ts.map +1 -1
- package/esm/src/react/components/ui/dropdown-menu.js +12 -31
- package/esm/src/react/components/ui/modal-surface.d.ts +43 -0
- package/esm/src/react/components/ui/modal-surface.d.ts.map +1 -0
- package/esm/src/react/components/ui/modal-surface.js +83 -0
- package/esm/src/react/components/ui/popover.d.ts +4 -7
- package/esm/src/react/components/ui/popover.d.ts.map +1 -1
- package/esm/src/react/components/ui/popover.js +11 -31
- package/esm/src/server/handlers/dev/framework-candidates.generated.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/framework-candidates.generated.js +175 -49
- package/esm/src/utils/index.d.ts +1 -0
- package/esm/src/utils/index.d.ts.map +1 -1
- package/esm/src/utils/index.js +1 -0
- package/esm/src/utils/json.d.ts +19 -0
- package/esm/src/utils/json.d.ts.map +1 -0
- package/esm/src/utils/json.js +17 -0
- package/esm/src/utils/logger/redact.d.ts.map +1 -1
- package/esm/src/utils/logger/redact.js +7 -3
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/esm/src/workflow/backends/redis/index.d.ts.map +1 -1
- package/esm/src/workflow/backends/redis/index.js +6 -7
- package/package.json +5 -5
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared behavioral machinery for Popover and DropdownMenu.
|
|
3
|
+
* TODO(a11y): focus trap, portal + collision-aware positioning (flip/shift),
|
|
4
|
+
* aria-controls, side/align offsets.
|
|
5
|
+
* DropdownMenu: roving focus, typeahead, Tab, aria-activedescendant, sub menus.
|
|
6
|
+
* @module react/components/ui/anchored-surface
|
|
7
|
+
*/
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
import { cx as cn } from "./cva.js";
|
|
10
|
+
import { Slot } from "./slot.js";
|
|
11
|
+
import { Floating } from "./floating.js";
|
|
12
|
+
import { useDisclosure } from "./disclosure.js";
|
|
13
|
+
/**
|
|
14
|
+
* Creates a fresh context instance plus the AnchoredRoot, AnchoredTrigger, and
|
|
15
|
+
* AnchoredContent parts -- all bound to that context.
|
|
16
|
+
*
|
|
17
|
+
* Each skin (Popover, DropdownMenu) calls this ONCE at module scope so their
|
|
18
|
+
* contexts are distinct objects. This prevents cross-binding when one skin is
|
|
19
|
+
* nested inside the other or inside a modal skin: a DropdownMenuItem close
|
|
20
|
+
* call only affects the DropdownMenu whose context is in scope, never a
|
|
21
|
+
* Popover above it in the tree.
|
|
22
|
+
*/
|
|
23
|
+
export function createAnchoredSurfaceParts() {
|
|
24
|
+
const Context = React.createContext(null);
|
|
25
|
+
/**
|
|
26
|
+
* Anchor `<span>` + disclosure state + context provider.
|
|
27
|
+
* The span is the positioning anchor for `Floating`.
|
|
28
|
+
*/
|
|
29
|
+
function AnchoredRoot({ children, open, defaultOpen, onOpenChange }) {
|
|
30
|
+
const { open: isOpen, setOpen } = useDisclosure({ open, defaultOpen, onOpenChange });
|
|
31
|
+
const anchorRef = React.useRef(null);
|
|
32
|
+
const ctx = React.useMemo(() => ({ open: isOpen, setOpen, anchorRef }), [isOpen, setOpen]);
|
|
33
|
+
return (React.createElement("span", { ref: anchorRef, className: "relative inline-block" },
|
|
34
|
+
React.createElement(Context.Provider, { value: ctx }, children)));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Toggle trigger. Sets `aria-haspopup` and `aria-expanded`; toggles open on
|
|
38
|
+
* click. Skins differ only in the `haspopup` value they supply.
|
|
39
|
+
*/
|
|
40
|
+
function AnchoredTrigger({ children, asChild, onClick, haspopup, ...props }) {
|
|
41
|
+
const ctx = React.useContext(Context);
|
|
42
|
+
const Comp = asChild ? Slot : "button";
|
|
43
|
+
return (React.createElement(Comp, { ...(asChild ? {} : { type: "button" }), "aria-haspopup": haspopup, "aria-expanded": ctx?.open, onClick: (e) => {
|
|
44
|
+
onClick?.(e);
|
|
45
|
+
// Guard ctx before reading ctx.open (trigger may render outside a Root).
|
|
46
|
+
if (ctx)
|
|
47
|
+
ctx.setOpen(!ctx.open);
|
|
48
|
+
}, ...props }, children));
|
|
49
|
+
}
|
|
50
|
+
/** `Floating` wrapper with base classes. Skins extend via `className` and `role`. */
|
|
51
|
+
function AnchoredContent({ children, className, align, ...props }) {
|
|
52
|
+
const ctx = React.useContext(Context);
|
|
53
|
+
if (!ctx)
|
|
54
|
+
return null;
|
|
55
|
+
return (React.createElement(Floating, { anchorRef: ctx.anchorRef, open: ctx.open, align: align, onDismiss: () => ctx.setOpen(false), className: cn("z-50 overflow-hidden rounded-lg bg-[var(--popover)] text-[var(--foreground)] shadow-sm outline-none", className), ...props }, children));
|
|
56
|
+
}
|
|
57
|
+
return { Context, AnchoredRoot, AnchoredTrigger, AnchoredContent };
|
|
58
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collapsible.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/collapsible.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"collapsible.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/collapsible.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,yCAAyC;AACzC,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9F,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAUvC;AAED,gDAAgD;AAChD,MAAM,WAAW,uBAAwB,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAC5F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,uBAAuB,GAAG,KAAK,CAAC,YAAY,CAkB9C;AAED,sDAAsD;AACtD,wBAAgB,kBAAkB,CAChC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAC3D,KAAK,CAAC,YAAY,GAAG,IAAI,CAQ3B"}
|
|
@@ -11,18 +11,12 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import * as React from "react";
|
|
13
13
|
import { Slot } from "./slot.js";
|
|
14
|
+
import { useDisclosure } from "./disclosure.js";
|
|
14
15
|
const CollapsibleContext = React.createContext(null);
|
|
15
16
|
/** Collapsible root — owns open state. */
|
|
16
17
|
export function Collapsible({ open, defaultOpen, onOpenChange, disabled, children, ...props }) {
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const isOpen = isControlled ? open : internal;
|
|
20
|
-
const toggle = React.useCallback(() => {
|
|
21
|
-
const next = !isOpen;
|
|
22
|
-
if (!isControlled)
|
|
23
|
-
setInternal(next);
|
|
24
|
-
onOpenChange?.(next);
|
|
25
|
-
}, [isOpen, isControlled, onOpenChange]);
|
|
18
|
+
const { open: isOpen, setOpen } = useDisclosure({ open, defaultOpen, onOpenChange });
|
|
19
|
+
const toggle = React.useCallback(() => setOpen(!isOpen), [isOpen, setOpen]);
|
|
26
20
|
return (React.createElement("div", { "data-state": isOpen ? "open" : "closed", ...props },
|
|
27
21
|
React.createElement(CollapsibleContext.Provider, { value: { open: isOpen, toggle, disabled } }, children)));
|
|
28
22
|
}
|
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
* Trigger / Content + Header / Title / Description / Body / Footer / Action /
|
|
4
4
|
* Cancel / Close / Form). Classes ported 1:1 from Studio's `Dialog` (tokens
|
|
5
5
|
* remapped; `Heading` level 2 + `Text` inlined). Modal overlay + centered panel;
|
|
6
|
-
* dismisses on `Escape` and overlay click.
|
|
7
|
-
*
|
|
8
|
-
* TODO(a11y): focus trap + restore, `aria-labelledby`/`aria-describedby` wiring,
|
|
9
|
-
* scroll-lock, portal, enter/exit animation. Private to the chat module.
|
|
6
|
+
* dismisses on `Escape` and overlay click. A11y work tracked in modal-surface.tsx.
|
|
10
7
|
*
|
|
11
8
|
* @module react/components/ui/dialog
|
|
12
9
|
*/
|
|
@@ -20,9 +17,9 @@ export interface DialogProps {
|
|
|
20
17
|
onOpenChange?: (open: boolean) => void;
|
|
21
18
|
}
|
|
22
19
|
/** Dialog root — owns open state. */
|
|
23
|
-
export declare function Dialog(
|
|
20
|
+
export declare function Dialog(props: DialogProps): React.ReactElement;
|
|
24
21
|
/** Trigger — opens the dialog. `asChild` merges onto the child element. */
|
|
25
|
-
export declare function DialogTrigger(
|
|
22
|
+
export declare function DialogTrigger(props: React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
26
23
|
asChild?: boolean;
|
|
27
24
|
}): React.ReactElement;
|
|
28
25
|
/** Modal surface — overlay + centered panel, rendered while open. */
|
|
@@ -49,7 +46,7 @@ export declare function DialogAction({ isLoading, variant, size, type, ...props
|
|
|
49
46
|
/** Alternate button (secondary, default size) that closes the dialog. */
|
|
50
47
|
export declare function DialogCancel({ className, variant, size, onClick, ...props }: ButtonProps): React.ReactElement;
|
|
51
48
|
/** Closes the dialog. `asChild` merges onto the child element. */
|
|
52
|
-
export declare function DialogClose(
|
|
49
|
+
export declare function DialogClose(props: React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
53
50
|
asChild?: boolean;
|
|
54
51
|
}): React.ReactElement;
|
|
55
52
|
//# sourceMappingURL=dialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/dialog.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/dialog.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAU,KAAK,WAAW,EAAiB,MAAM,aAAa,CAAC;AAatE,oCAAoC;AACpC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,qCAAqC;AACrC,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,KAAK,CAAC,YAAY,CAE7D;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAC3B,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3E,KAAK,CAAC,YAAY,CAEpB;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAalE;AAED,8CAA8C;AAC9C,wBAAgB,YAAY,CAC1B,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAC5D,KAAK,CAAC,YAAY,CAEpB;AAED;qEACqE;AACrE,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,GAAG,KAAK,CAAC,YAAY,CAU/D;AAED,oDAAoD;AACpD,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC,GAAG,KAAK,CAAC,YAAY,CAUjE;AAED,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY,CAU3D;AAED,qDAAqD;AACrD,wBAAgB,YAAY,CAC1B,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAC5D,KAAK,CAAC,YAAY,CAEpB;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CACxB,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,kBAAkB,CAAC,eAAe,CAAC,GACjE,KAAK,CAAC,YAAY,CAEpB;AAED,0CAA0C;AAC1C,MAAM,WAAW,iBAAkB,SAAQ,WAAW;IACpD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,OAAmB,EACnB,IAAgB,EAChB,IAAe,EACf,GAAG,KAAK,EACT,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAUxC;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,OAAqB,EACrB,IAAgB,EAChB,OAAO,EACP,GAAG,KAAK,EACT,EAAE,WAAW,GAAG,KAAK,CAAC,YAAY,CAclC;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3E,KAAK,CAAC,YAAY,CAEpB"}
|
|
@@ -3,70 +3,29 @@
|
|
|
3
3
|
* Trigger / Content + Header / Title / Description / Body / Footer / Action /
|
|
4
4
|
* Cancel / Close / Form). Classes ported 1:1 from Studio's `Dialog` (tokens
|
|
5
5
|
* remapped; `Heading` level 2 + `Text` inlined). Modal overlay + centered panel;
|
|
6
|
-
* dismisses on `Escape` and overlay click.
|
|
7
|
-
*
|
|
8
|
-
* TODO(a11y): focus trap + restore, `aria-labelledby`/`aria-describedby` wiring,
|
|
9
|
-
* scroll-lock, portal, enter/exit animation. Private to the chat module.
|
|
6
|
+
* dismisses on `Escape` and overlay click. A11y work tracked in modal-surface.tsx.
|
|
10
7
|
*
|
|
11
8
|
* @module react/components/ui/dialog
|
|
12
9
|
*/
|
|
13
10
|
import * as React from "react";
|
|
14
11
|
import { cx as cn } from "./cva.js";
|
|
15
|
-
import { Slot } from "./slot.js";
|
|
16
12
|
import { ScrollFade } from "./scroll-fade.js";
|
|
17
13
|
import { Button, LoadingButton } from "./button.js";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
throw new Error("Dialog parts must be used within <Dialog>");
|
|
23
|
-
return ctx;
|
|
24
|
-
}
|
|
14
|
+
import { createModalSurfaceParts } from "./modal-surface.js";
|
|
15
|
+
// Per-skin context + machinery -- distinct from Drawer's instance so a
|
|
16
|
+
// DrawerClose nested inside a Dialog cannot accidentally close the Dialog.
|
|
17
|
+
const { ModalRoot: _Root, useModal: _hook, ModalTrigger: _Trigger, ModalClose: _Close, ModalContent: _Content, } = createModalSurfaceParts("Dialog");
|
|
25
18
|
/** Dialog root — owns open state. */
|
|
26
|
-
export function Dialog(
|
|
27
|
-
|
|
28
|
-
const isControlled = open !== undefined;
|
|
29
|
-
const isOpen = isControlled ? open : internal;
|
|
30
|
-
const setOpen = React.useCallback((next) => {
|
|
31
|
-
if (!isControlled)
|
|
32
|
-
setInternal(next);
|
|
33
|
-
onOpenChange?.(next);
|
|
34
|
-
}, [isControlled, onOpenChange]);
|
|
35
|
-
return (React.createElement(DialogContext.Provider, { value: { open: isOpen, setOpen } }, children));
|
|
19
|
+
export function Dialog(props) {
|
|
20
|
+
return React.createElement(_Root, { ...props });
|
|
36
21
|
}
|
|
37
22
|
/** Trigger — opens the dialog. `asChild` merges onto the child element. */
|
|
38
|
-
export function DialogTrigger(
|
|
39
|
-
|
|
40
|
-
const Comp = asChild ? Slot : "button";
|
|
41
|
-
return (React.createElement(Comp, { ...(asChild ? {} : { type: "button" }), onClick: (e) => {
|
|
42
|
-
onClick?.(e);
|
|
43
|
-
ctx.setOpen(true);
|
|
44
|
-
}, ...props }, children));
|
|
23
|
+
export function DialogTrigger(props) {
|
|
24
|
+
return React.createElement(_Trigger, { ...props });
|
|
45
25
|
}
|
|
46
26
|
/** Modal surface — overlay + centered panel, rendered while open. */
|
|
47
27
|
export function DialogContent({ className, children, ...props }) {
|
|
48
|
-
|
|
49
|
-
const panelRef = React.useRef(null);
|
|
50
|
-
React.useEffect(() => {
|
|
51
|
-
if (!ctx.open)
|
|
52
|
-
return;
|
|
53
|
-
const onKeyDown = (e) => {
|
|
54
|
-
if (e.key === "Escape")
|
|
55
|
-
ctx.setOpen(false);
|
|
56
|
-
};
|
|
57
|
-
document.addEventListener("keydown", onKeyDown);
|
|
58
|
-
// Focus the first focusable descendant on open (radix-like) — e.g. a
|
|
59
|
-
// CommandInput — falling back to the panel itself. Full focus-trap is TODO.
|
|
60
|
-
const panel = panelRef.current;
|
|
61
|
-
const focusable = panel?.querySelector('input:not([disabled]), textarea:not([disabled]), select:not([disabled]), button:not([disabled]), [href], [tabindex]:not([tabindex="-1"])');
|
|
62
|
-
(focusable ?? panel)?.focus();
|
|
63
|
-
return () => document.removeEventListener("keydown", onKeyDown);
|
|
64
|
-
}, [ctx.open]);
|
|
65
|
-
if (!ctx.open)
|
|
66
|
-
return null;
|
|
67
|
-
return (React.createElement("div", { className: "fixed inset-0 z-50" },
|
|
68
|
-
React.createElement("div", { className: "fixed inset-0 bg-[var(--overlay)]", onClick: () => ctx.setOpen(false) }),
|
|
69
|
-
React.createElement("div", { ref: panelRef, role: "dialog", "aria-modal": "true", tabIndex: -1, className: cn("fixed left-1/2 top-1/2 z-50 w-[calc(100%-3rem)] max-w-xl max-h-[85vh] -translate-x-1/2 -translate-y-1/2", "rounded-xl bg-[var(--dialog)] text-[var(--foreground)] shadow-lg outline-none overflow-hidden flex flex-col", className), ...props }, children)));
|
|
28
|
+
return (React.createElement(_Content, { className: cn("fixed left-1/2 top-1/2 z-50 w-[calc(100%-3rem)] max-w-xl max-h-[85vh] -translate-x-1/2 -translate-y-1/2", "rounded-xl bg-[var(--dialog)] text-[var(--foreground)] shadow-lg outline-none overflow-hidden flex flex-col", className), ...props }, children));
|
|
70
29
|
}
|
|
71
30
|
/** Left-aligned title + description block. */
|
|
72
31
|
export function DialogHeader({ className, ...props }) {
|
|
@@ -99,18 +58,13 @@ export function DialogAction({ isLoading, variant = "primary", size = "default",
|
|
|
99
58
|
}
|
|
100
59
|
/** Alternate button (secondary, default size) that closes the dialog. */
|
|
101
60
|
export function DialogCancel({ className, variant = "secondary", size = "default", onClick, ...props }) {
|
|
102
|
-
const ctx =
|
|
61
|
+
const ctx = _hook();
|
|
103
62
|
return (React.createElement(Button, { variant: variant, size: size, className: className, onClick: (e) => {
|
|
104
63
|
onClick?.(e);
|
|
105
64
|
ctx.setOpen(false);
|
|
106
65
|
}, ...props }));
|
|
107
66
|
}
|
|
108
67
|
/** Closes the dialog. `asChild` merges onto the child element. */
|
|
109
|
-
export function DialogClose(
|
|
110
|
-
|
|
111
|
-
const Comp = asChild ? Slot : "button";
|
|
112
|
-
return (React.createElement(Comp, { ...(asChild ? {} : { type: "button" }), onClick: (e) => {
|
|
113
|
-
onClick?.(e);
|
|
114
|
-
ctx.setOpen(false);
|
|
115
|
-
}, ...props }, children));
|
|
68
|
+
export function DialogClose(props) {
|
|
69
|
+
return React.createElement(_Close, { ...props });
|
|
116
70
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Options accepted by `useDisclosure`. */
|
|
2
|
+
export interface DisclosureOptions {
|
|
3
|
+
open?: boolean;
|
|
4
|
+
defaultOpen?: boolean;
|
|
5
|
+
onOpenChange?: (open: boolean) => void;
|
|
6
|
+
}
|
|
7
|
+
/** Returns `{ open, setOpen }`, handling controlled and uncontrolled usage. */
|
|
8
|
+
export declare function useDisclosure({ open, defaultOpen, onOpenChange }: DisclosureOptions): {
|
|
9
|
+
open: boolean;
|
|
10
|
+
setOpen: any;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=disclosure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disclosure.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/disclosure.ts"],"names":[],"mappings":"AAMA,2CAA2C;AAC3C,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,iBAAiB;;;EAiBnF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useDisclosure: shared controlled/uncontrolled open state for overlay surfaces.
|
|
3
|
+
* @module react/components/ui/disclosure
|
|
4
|
+
*/
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
/** Returns `{ open, setOpen }`, handling controlled and uncontrolled usage. */
|
|
7
|
+
export function useDisclosure({ open, defaultOpen, onOpenChange }) {
|
|
8
|
+
const [internal, setInternal] = React.useState(defaultOpen ?? false);
|
|
9
|
+
const isControlled = open !== undefined;
|
|
10
|
+
const isOpen = open ?? internal;
|
|
11
|
+
// Latest-ref pattern: setOpen keeps a stable identity across parent renders
|
|
12
|
+
// (so effect consumers do not re-register listeners) while always invoking
|
|
13
|
+
// the caller's current onOpenChange.
|
|
14
|
+
const onOpenChangeRef = React.useRef(onOpenChange);
|
|
15
|
+
onOpenChangeRef.current = onOpenChange;
|
|
16
|
+
const setOpen = React.useCallback((next) => {
|
|
17
|
+
if (!isControlled)
|
|
18
|
+
setInternal(next);
|
|
19
|
+
onOpenChangeRef.current?.(next);
|
|
20
|
+
}, [isControlled]);
|
|
21
|
+
return { open: isOpen, setOpen };
|
|
22
|
+
}
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
* Vaul-style component). Same API shape for the parts we need: Root / Trigger /
|
|
4
4
|
* Content (overlay + sheet + drag handle) / Title / Header / Body / Footer /
|
|
5
5
|
* Close. Surface classes ported 1:1 from Studio (tokens remapped). Slides up
|
|
6
|
-
* from the bottom; dismisses on `Escape` and overlay click.
|
|
7
|
-
*
|
|
8
|
-
* TODO(a11y): focus trap + restore, drag-to-dismiss / snap points, scroll-lock,
|
|
9
|
-
* portal, enter/exit animation. Private to the chat module.
|
|
6
|
+
* from the bottom; dismisses on `Escape` and overlay click. A11y work tracked
|
|
7
|
+
* in modal-surface.tsx.
|
|
10
8
|
*
|
|
11
9
|
* @module react/components/ui/drawer
|
|
12
10
|
*/
|
|
@@ -19,9 +17,9 @@ export interface DrawerProps {
|
|
|
19
17
|
onOpenChange?: (open: boolean) => void;
|
|
20
18
|
}
|
|
21
19
|
/** Drawer root — owns open state. */
|
|
22
|
-
export declare function Drawer(
|
|
20
|
+
export declare function Drawer(props: DrawerProps): React.ReactElement;
|
|
23
21
|
/** Trigger — opens the drawer. `asChild` merges onto the child element. */
|
|
24
|
-
export declare function DrawerTrigger(
|
|
22
|
+
export declare function DrawerTrigger(props: React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
25
23
|
asChild?: boolean;
|
|
26
24
|
}): React.ReactElement;
|
|
27
25
|
/** Bottom sheet — overlay + sliding surface with a drag handle. */
|
|
@@ -35,7 +33,7 @@ export declare function DrawerBody({ className, ...props }: React.HTMLAttributes
|
|
|
35
33
|
/** Sticky footer, full-width stacked actions. */
|
|
36
34
|
export declare function DrawerFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.ReactElement;
|
|
37
35
|
/** Closes the drawer. `asChild` merges onto the child element. */
|
|
38
|
-
export declare function DrawerClose(
|
|
36
|
+
export declare function DrawerClose(props: React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
39
37
|
asChild?: boolean;
|
|
40
38
|
}): React.ReactElement;
|
|
41
39
|
//# sourceMappingURL=drawer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/drawer.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/drawer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,oCAAoC;AACpC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,qCAAqC;AACrC,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,KAAK,CAAC,YAAY,CAE7D;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAC3B,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3E,KAAK,CAAC,YAAY,CAEpB;AAED,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAkBlE;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,GAAG,KAAK,CAAC,YAAY,CAO/D;AAED,6BAA6B;AAC7B,wBAAgB,YAAY,CAC1B,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAC5D,KAAK,CAAC,YAAY,CAEpB;AAED,4BAA4B;AAC5B,wBAAgB,UAAU,CACxB,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAC5D,KAAK,CAAC,YAAY,CAOpB;AAED,iDAAiD;AACjD,wBAAgB,YAAY,CAC1B,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAC5D,KAAK,CAAC,YAAY,CAUpB;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3E,KAAK,CAAC,YAAY,CAEpB"}
|
|
@@ -3,67 +3,28 @@
|
|
|
3
3
|
* Vaul-style component). Same API shape for the parts we need: Root / Trigger /
|
|
4
4
|
* Content (overlay + sheet + drag handle) / Title / Header / Body / Footer /
|
|
5
5
|
* Close. Surface classes ported 1:1 from Studio (tokens remapped). Slides up
|
|
6
|
-
* from the bottom; dismisses on `Escape` and overlay click.
|
|
7
|
-
*
|
|
8
|
-
* TODO(a11y): focus trap + restore, drag-to-dismiss / snap points, scroll-lock,
|
|
9
|
-
* portal, enter/exit animation. Private to the chat module.
|
|
6
|
+
* from the bottom; dismisses on `Escape` and overlay click. A11y work tracked
|
|
7
|
+
* in modal-surface.tsx.
|
|
10
8
|
*
|
|
11
9
|
* @module react/components/ui/drawer
|
|
12
10
|
*/
|
|
13
11
|
import * as React from "react";
|
|
14
12
|
import { cx as cn } from "./cva.js";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (!ctx)
|
|
20
|
-
throw new Error("Drawer parts must be used within <Drawer>");
|
|
21
|
-
return ctx;
|
|
22
|
-
}
|
|
13
|
+
import { createModalSurfaceParts } from "./modal-surface.js";
|
|
14
|
+
// Per-skin context + machinery -- distinct from Dialog's instance so a
|
|
15
|
+
// DialogClose nested inside a Drawer cannot accidentally close the Drawer.
|
|
16
|
+
const { ModalRoot: _Root, ModalTrigger: _Trigger, ModalClose: _Close, ModalContent: _Content } = createModalSurfaceParts("Drawer");
|
|
23
17
|
/** Drawer root — owns open state. */
|
|
24
|
-
export function Drawer(
|
|
25
|
-
|
|
26
|
-
const isControlled = open !== undefined;
|
|
27
|
-
const isOpen = isControlled ? open : internal;
|
|
28
|
-
const setOpen = React.useCallback((next) => {
|
|
29
|
-
if (!isControlled)
|
|
30
|
-
setInternal(next);
|
|
31
|
-
onOpenChange?.(next);
|
|
32
|
-
}, [isControlled, onOpenChange]);
|
|
33
|
-
return (React.createElement(DrawerContext.Provider, { value: { open: isOpen, setOpen } }, children));
|
|
18
|
+
export function Drawer(props) {
|
|
19
|
+
return React.createElement(_Root, { ...props });
|
|
34
20
|
}
|
|
35
21
|
/** Trigger — opens the drawer. `asChild` merges onto the child element. */
|
|
36
|
-
export function DrawerTrigger(
|
|
37
|
-
|
|
38
|
-
const Comp = asChild ? Slot : "button";
|
|
39
|
-
return (React.createElement(Comp, { ...(asChild ? {} : { type: "button" }), onClick: (e) => {
|
|
40
|
-
onClick?.(e);
|
|
41
|
-
ctx.setOpen(true);
|
|
42
|
-
}, ...props }, children));
|
|
22
|
+
export function DrawerTrigger(props) {
|
|
23
|
+
return React.createElement(_Trigger, { ...props });
|
|
43
24
|
}
|
|
44
25
|
/** Bottom sheet — overlay + sliding surface with a drag handle. */
|
|
45
26
|
export function DrawerContent({ children, className, ...props }) {
|
|
46
|
-
|
|
47
|
-
const sheetRef = React.useRef(null);
|
|
48
|
-
React.useEffect(() => {
|
|
49
|
-
if (!ctx.open)
|
|
50
|
-
return;
|
|
51
|
-
const onKeyDown = (e) => {
|
|
52
|
-
if (e.key === "Escape")
|
|
53
|
-
ctx.setOpen(false);
|
|
54
|
-
};
|
|
55
|
-
document.addEventListener("keydown", onKeyDown);
|
|
56
|
-
const focusable = sheetRef.current?.querySelector('input:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href], [tabindex]:not([tabindex="-1"])');
|
|
57
|
-
(focusable ?? sheetRef.current)?.focus();
|
|
58
|
-
return () => document.removeEventListener("keydown", onKeyDown);
|
|
59
|
-
}, [ctx.open]);
|
|
60
|
-
if (!ctx.open)
|
|
61
|
-
return null;
|
|
62
|
-
return (React.createElement("div", { className: "fixed inset-0 z-50" },
|
|
63
|
-
React.createElement("div", { className: "fixed inset-0 bg-[var(--overlay)]", onClick: () => ctx.setOpen(false) }),
|
|
64
|
-
React.createElement("div", { ref: sheetRef, role: "dialog", "aria-modal": "true", tabIndex: -1, className: cn("fixed inset-x-0 bottom-0 z-50 flex flex-col max-h-[85vh] w-full rounded-t-xl bg-[var(--drawer)] text-[var(--foreground)] outline-none", className), ...props },
|
|
65
|
-
React.createElement("div", { "aria-hidden": "true", className: "mx-auto mt-3 h-[3px] w-[30px] shrink-0 rounded-full bg-[var(--outline-border)]" }),
|
|
66
|
-
children)));
|
|
27
|
+
return (React.createElement(_Content, { className: cn("fixed inset-x-0 bottom-0 z-50 flex flex-col max-h-[85vh] w-full rounded-t-xl bg-[var(--drawer)] text-[var(--foreground)] outline-none", className), lead: React.createElement("div", { "aria-hidden": "true", className: "mx-auto mt-3 h-[3px] w-[30px] shrink-0 rounded-full bg-[var(--outline-border)]" }), ...props }, children));
|
|
67
28
|
}
|
|
68
29
|
/** Drawer title — 18px medium (Studio Heading-ish). Add `sr-only` to hide. */
|
|
69
30
|
export function DrawerTitle({ className, ...props }) {
|
|
@@ -82,11 +43,6 @@ export function DrawerFooter({ className, ...props }) {
|
|
|
82
43
|
return (React.createElement("div", { className: cn("shrink-0 px-4 pb-4 pt-3 flex flex-col gap-3 [&>button]:w-full", className), ...props }));
|
|
83
44
|
}
|
|
84
45
|
/** Closes the drawer. `asChild` merges onto the child element. */
|
|
85
|
-
export function DrawerClose(
|
|
86
|
-
|
|
87
|
-
const Comp = asChild ? Slot : "button";
|
|
88
|
-
return (React.createElement(Comp, { ...(asChild ? {} : { type: "button" }), onClick: (e) => {
|
|
89
|
-
onClick?.(e);
|
|
90
|
-
ctx.setOpen(false);
|
|
91
|
-
}, ...props }, children));
|
|
46
|
+
export function DrawerClose(props) {
|
|
47
|
+
return React.createElement(_Close, { ...props });
|
|
92
48
|
}
|
|
@@ -3,11 +3,8 @@
|
|
|
3
3
|
* shape (Root / Trigger / Content / Group / Item / ItemMeta / Separator /
|
|
4
4
|
* Label). Classes are ported 1:1 from Studio's `DropdownMenu` (token names
|
|
5
5
|
* remapped to veryfront's `[var(--token)]` vocabulary). Opens below the
|
|
6
|
-
* trigger; dismisses on outside-click, `Escape`, and item select.
|
|
7
|
-
*
|
|
8
|
-
* TODO(a11y): roving focus + arrow-key navigation, typeahead, `Tab` handling,
|
|
9
|
-
* portal + collision-aware positioning (flip/shift), `aria-activedescendant`,
|
|
10
|
-
* RadioItem/CheckboxItem/Sub menus. Private to the chat module.
|
|
6
|
+
* trigger; dismisses on outside-click, `Escape`, and item select. A11y work
|
|
7
|
+
* tracked in anchored-surface.tsx.
|
|
11
8
|
*
|
|
12
9
|
* @module react/components/ui/dropdown-menu
|
|
13
10
|
*/
|
|
@@ -20,9 +17,9 @@ export interface DropdownMenuProps {
|
|
|
20
17
|
onOpenChange?: (open: boolean) => void;
|
|
21
18
|
}
|
|
22
19
|
/** DropdownMenu root — owns open state and the positioning anchor. */
|
|
23
|
-
export declare function DropdownMenu(
|
|
20
|
+
export declare function DropdownMenu(props: DropdownMenuProps): React.ReactElement;
|
|
24
21
|
/** Trigger — toggles the menu. `asChild` merges onto the child element. */
|
|
25
|
-
export declare function DropdownMenuTrigger(
|
|
22
|
+
export declare function DropdownMenuTrigger(props: React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
26
23
|
asChild?: boolean;
|
|
27
24
|
}): React.ReactElement;
|
|
28
25
|
/** Props accepted by `<DropdownMenuContent>`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/dropdown-menu.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/dropdown-menu.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAEzE;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3E,KAAK,CAAC,YAAY,CAEpB;AAED,iDAAiD;AACjD,MAAM,WAAW,wBAAyB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACpF,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;CACzB;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,SAAS,EACT,KAAe,EACf,GAAG,KAAK,EACT,EAAE,wBAAwB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAWtD;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAC/B,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE,KAAK,CAAC,YAAY,CAMpB;AAED,8CAA8C;AAC9C,MAAM,WAAW,qBAAsB,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAC1F,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,iEAAiE;AACjE,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,EACP,GAAG,KAAK,EACT,EAAE,qBAAqB,GAAG,KAAK,CAAC,YAAY,CAyB5C;AAED,mEAAmE;AACnE,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,KAAK,CAAC,YAAY,CAWrB;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,CACnC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACpC,KAAK,CAAC,YAAY,CAEpB;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,KAAK,CAAC,YAAY,CAWrB"}
|
|
@@ -3,48 +3,29 @@
|
|
|
3
3
|
* shape (Root / Trigger / Content / Group / Item / ItemMeta / Separator /
|
|
4
4
|
* Label). Classes are ported 1:1 from Studio's `DropdownMenu` (token names
|
|
5
5
|
* remapped to veryfront's `[var(--token)]` vocabulary). Opens below the
|
|
6
|
-
* trigger; dismisses on outside-click, `Escape`, and item select.
|
|
7
|
-
*
|
|
8
|
-
* TODO(a11y): roving focus + arrow-key navigation, typeahead, `Tab` handling,
|
|
9
|
-
* portal + collision-aware positioning (flip/shift), `aria-activedescendant`,
|
|
10
|
-
* RadioItem/CheckboxItem/Sub menus. Private to the chat module.
|
|
6
|
+
* trigger; dismisses on outside-click, `Escape`, and item select. A11y work
|
|
7
|
+
* tracked in anchored-surface.tsx.
|
|
11
8
|
*
|
|
12
9
|
* @module react/components/ui/dropdown-menu
|
|
13
10
|
*/
|
|
14
11
|
import * as React from "react";
|
|
15
12
|
import { cx as cn } from "./cva.js";
|
|
16
13
|
import { Slot } from "./slot.js";
|
|
17
|
-
import {
|
|
18
|
-
|
|
14
|
+
import { createAnchoredSurfaceParts } from "./anchored-surface.js";
|
|
15
|
+
// Per-skin context + machinery -- distinct from Popover's instance so a
|
|
16
|
+
// Popover nested inside a DropdownMenu cannot accidentally close the menu.
|
|
17
|
+
const { Context: _ctx, AnchoredRoot: _Root, AnchoredTrigger: _Trigger, AnchoredContent: _Content } = createAnchoredSurfaceParts();
|
|
19
18
|
/** DropdownMenu root — owns open state and the positioning anchor. */
|
|
20
|
-
export function DropdownMenu(
|
|
21
|
-
|
|
22
|
-
const isControlled = open !== undefined;
|
|
23
|
-
const isOpen = isControlled ? open : internal;
|
|
24
|
-
const setOpen = React.useCallback((next) => {
|
|
25
|
-
if (!isControlled)
|
|
26
|
-
setInternal(next);
|
|
27
|
-
onOpenChange?.(next);
|
|
28
|
-
}, [isControlled, onOpenChange]);
|
|
29
|
-
const anchorRef = React.useRef(null);
|
|
30
|
-
return (React.createElement("span", { ref: anchorRef, className: "relative inline-block" },
|
|
31
|
-
React.createElement(MenuContext.Provider, { value: { open: isOpen, setOpen, anchorRef } }, children)));
|
|
19
|
+
export function DropdownMenu(props) {
|
|
20
|
+
return React.createElement(_Root, { ...props });
|
|
32
21
|
}
|
|
33
22
|
/** Trigger — toggles the menu. `asChild` merges onto the child element. */
|
|
34
|
-
export function DropdownMenuTrigger(
|
|
35
|
-
|
|
36
|
-
const Comp = asChild ? Slot : "button";
|
|
37
|
-
return (React.createElement(Comp, { ...(asChild ? {} : { type: "button" }), "aria-haspopup": "menu", "aria-expanded": ctx?.open, onClick: (e) => {
|
|
38
|
-
onClick?.(e);
|
|
39
|
-
ctx?.setOpen(!ctx.open);
|
|
40
|
-
}, ...props }, children));
|
|
23
|
+
export function DropdownMenuTrigger(props) {
|
|
24
|
+
return React.createElement(_Trigger, { ...props, haspopup: "menu" });
|
|
41
25
|
}
|
|
42
26
|
/** Menu surface — rendered below the trigger while open. No border (Studio). */
|
|
43
27
|
export function DropdownMenuContent({ children, className, align = "start", ...props }) {
|
|
44
|
-
|
|
45
|
-
if (!ctx)
|
|
46
|
-
return null;
|
|
47
|
-
return (React.createElement(Floating, { anchorRef: ctx.anchorRef, open: ctx.open, align: align, onDismiss: () => ctx.setOpen(false), role: "menu", className: cn("z-50 min-w-[260px] overflow-hidden rounded-lg bg-[var(--popover)] p-2.5 shadow-sm outline-none", className), ...props }, children));
|
|
28
|
+
return (React.createElement(_Content, { role: "menu", align: align, className: cn("min-w-[260px] p-2.5", className), ...props }, children));
|
|
48
29
|
}
|
|
49
30
|
/** Groups related items with a tight inner gap (Studio: `gap-px p-0.5`). */
|
|
50
31
|
export function DropdownMenuGroup({ children, className }) {
|
|
@@ -52,7 +33,7 @@ export function DropdownMenuGroup({ children, className }) {
|
|
|
52
33
|
}
|
|
53
34
|
/** A selectable menu item. Icons render at `size-3.5` (14px). */
|
|
54
35
|
export function DropdownMenuItem({ children, className, onSelect, onClick, disabled, asChild, ...props }) {
|
|
55
|
-
const ctx = React.useContext(
|
|
36
|
+
const ctx = React.useContext(_ctx);
|
|
56
37
|
const Comp = asChild ? Slot : "button";
|
|
57
38
|
return (React.createElement(Comp, { ...(asChild ? {} : { type: "button" }), role: "menuitem", "aria-disabled": disabled || undefined, className: cn("relative flex w-full cursor-pointer select-none items-center gap-2.5 rounded-md px-3 h-[36px] text-base font-normal text-left text-[var(--foreground)] outline-none transition-colors", "hover:bg-[var(--tertiary)] focus:bg-[var(--tertiary)] dark:hover:bg-[var(--accent)] dark:focus:bg-[var(--accent)]", "disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-3.5 [&_svg]:shrink-0", className), onClick: (e) => {
|
|
58
39
|
if (disabled)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared behavioral machinery for Dialog and Drawer.
|
|
3
|
+
* TODO(a11y): focus trap, aria-labelledby, scroll-lock, portal, animation.
|
|
4
|
+
* Drawer: drag-to-dismiss / snap points.
|
|
5
|
+
* @module react/components/ui/modal-surface
|
|
6
|
+
*/
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { type DisclosureOptions } from "./disclosure.js";
|
|
9
|
+
/** Open/close state shared between a modal skin's Root and its parts. */
|
|
10
|
+
export interface ModalState {
|
|
11
|
+
open: boolean;
|
|
12
|
+
setOpen: (open: boolean) => void;
|
|
13
|
+
}
|
|
14
|
+
/** Props for the shared modal content shell. */
|
|
15
|
+
export interface ModalContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
16
|
+
/** Extra node rendered before `children` -- used by Drawer for the drag handle. */
|
|
17
|
+
lead?: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
type ModalBtnProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
20
|
+
asChild?: boolean;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Creates a fresh context instance plus the Root, useModal, ModalTrigger,
|
|
24
|
+
* ModalClose, and ModalContent parts -- all bound to that context.
|
|
25
|
+
*
|
|
26
|
+
* Each skin (Dialog, Drawer) calls this ONCE at module scope so their contexts
|
|
27
|
+
* are distinct objects. This prevents cross-binding when one skin is nested
|
|
28
|
+
* inside the other: a DrawerClose inside a Dialog will only close the Drawer,
|
|
29
|
+
* never the Dialog, because the two contexts cannot overlap.
|
|
30
|
+
*
|
|
31
|
+
* @param name - Component name used in the thrown error (e.g. "Dialog").
|
|
32
|
+
*/
|
|
33
|
+
export declare function createModalSurfaceParts(name: string): {
|
|
34
|
+
ModalRoot: ({ children, open, defaultOpen, onOpenChange }: DisclosureOptions & {
|
|
35
|
+
children: React.ReactNode;
|
|
36
|
+
}) => React.ReactElement;
|
|
37
|
+
useModal: () => ModalState;
|
|
38
|
+
ModalTrigger: ({ children, asChild, onClick, ...props }: ModalBtnProps) => React.ReactElement;
|
|
39
|
+
ModalClose: ({ children, asChild, onClick, ...props }: ModalBtnProps) => React.ReactElement;
|
|
40
|
+
ModalContent: ({ className, children, lead, ...props }: ModalContentProps) => React.ReactElement | null;
|
|
41
|
+
};
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=modal-surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal-surface.d.ts","sourceRoot":"","sources":["../../../../../src/src/react/components/ui/modal-surface.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,KAAK,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AAExE,yEAAyE;AACzE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAClC;AAED,gDAAgD;AAChD,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC7E,mFAAmF;IACnF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB;AAED,KAAK,aAAa,GAAG,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAsB3F;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM;+DAKD,iBAAiB,GAAG;QACjE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;KAC3B,KACA,KAAK,CAAC,YAAY;oBAOA,UAAU;6DAQa,aAAa,KACtD,KAAK,CAAC,YAAY;2DAmBuB,aAAa,KACtD,KAAK,CAAC,YAAY;4DAmBsB,iBAAiB,KACzD,KAAK,CAAC,YAAY,GAAG,IAAI;EA2B7B"}
|