@danxbot/ui 18.4.0 → 19.0.0

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.
@@ -18,6 +18,7 @@ declare const dialog: import("tailwind-variants").TVReturnType<{
18
18
  popup: string;
19
19
  header: string;
20
20
  title: string;
21
+ description: string;
21
22
  body: string;
22
23
  };
23
24
  };
@@ -47,6 +48,7 @@ declare const dialog: import("tailwind-variants").TVReturnType<{
47
48
  popup: string;
48
49
  header: string;
49
50
  title: string;
51
+ description: string;
50
52
  body: string;
51
53
  };
52
54
  };
@@ -76,6 +78,7 @@ declare const dialog: import("tailwind-variants").TVReturnType<{
76
78
  popup: string;
77
79
  header: string;
78
80
  title: string;
81
+ description: string;
79
82
  body: string;
80
83
  };
81
84
  };
@@ -99,11 +102,19 @@ export interface DialogProps extends VariantProps<typeof dialog> {
99
102
  actions?: ReactNode;
100
103
  /** Hide the corner close button — for a dialog that must be answered. */
101
104
  hideClose?: boolean;
105
+ /**
106
+ * The host's own controls, in the header row beside the title and before the
107
+ * corner close button (DX-4398). For a dialog whose one header bar carries its
108
+ * working controls — a viewer's navigation and zoom — instead of a header plus
109
+ * a toolbar row costing the content vertical space. Omitted: the header is
110
+ * exactly the title block.
111
+ */
112
+ headerActions?: ReactNode;
102
113
  className?: string;
103
114
  children?: ReactNode;
104
115
  ref?: Ref<HTMLDivElement>;
105
116
  }
106
- export declare function Dialog({ trigger, open, onOpenChange, title, description, actions, hideClose, size, className, children, ref, }: DialogProps): import("react").JSX.Element;
117
+ export declare function Dialog({ trigger, open, onOpenChange, title, description, actions, hideClose, headerActions, size, className, children, ref, }: DialogProps): import("react").JSX.Element;
107
118
  /** Closes the nearest Dialog. Wrap any button: `<DialogClose>{<Button/>}</DialogClose>`. */
108
119
  export declare function DialogClose({ children }: {
109
120
  children: ReactNode;
@@ -1,4 +1,4 @@
1
- import type { ReactNode, Ref } from "react";
1
+ import { type ReactNode, type Ref } from "react";
2
2
  export interface PopoverProps {
3
3
  trigger: ReactNode;
4
4
  /**
@@ -1,6 +1,11 @@
1
1
  import { type ReactNode, type Ref } from "react";
2
2
  import type { ChatFile } from "./types";
3
3
  import type { IconName } from "../Icon";
4
+ export declare function TileMedia({ file, iconSize, className }: {
5
+ file: ChatFile;
6
+ iconSize: "sm" | "lg";
7
+ className?: string;
8
+ }): import("react").JSX.Element;
4
9
  export type AttachmentLayout = "tile" | "row";
5
10
  export interface AttachmentProps {
6
11
  file: ChatFile;
@@ -86,29 +91,6 @@ export interface AttachmentActionProps {
86
91
  * />
87
92
  */
88
93
  export declare function AttachmentAction({ icon, label, onClick, disabled, tinted, }: AttachmentActionProps): import("react").JSX.Element;
89
- export interface AttachmentPreviewProps {
90
- file: ChatFile | null;
91
- onOpenChange: (open: boolean) => void;
92
- onDownload?: (file: ChatFile) => void;
93
- /** Renders the body for a file this component cannot show itself. */
94
- renderBody?: (file: ChatFile) => ReactNode;
95
- }
96
- /**
97
- * A file, opened.
98
- *
99
- * Deliberately narrow about what it displays: images, video, and anything the
100
- * consumer hands it through `renderBody`. It does NOT attempt to preview PDFs
101
- * or office documents by embedding them — an iframe pointed at an arbitrary
102
- * attachment is a security surface, and a half-working preview is worse than an
103
- * honest "open it" because people trust what they see.
104
- *
105
- * VIDEO IS NOT THAT SURFACE. A native `<video>` (through `VideoPlayer`) is the
106
- * browser decoding a media stream inside its own sandbox, not a document
107
- * embedded from elsewhere, so it is allowed where an iframe or <object> is not.
108
- * Video is recognised by mime type OR extension, because attachments from chat
109
- * integrations arrive as `application/octet-stream`.
110
- */
111
- export declare function AttachmentPreview({ file: openFile, onOpenChange, onDownload, renderBody, }: AttachmentPreviewProps): import("react").JSX.Element;
112
94
  export interface AttachmentListProps {
113
95
  files: ChatFile[];
114
96
  layout?: AttachmentLayout;
@@ -0,0 +1,2 @@
1
+ import type { FileViewerProps } from "./types";
2
+ export declare function FileViewer({ open, onOpenChange, files, initialFileId, initialPageId, onFrameChange, title, subtitle, onDownload, markLabel, headerActions, overlay, renderBody, }: FileViewerProps): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ export interface PageNumberJumpFieldProps {
2
+ /** Attempts the jump for the typed number; returns whether a match was found.
3
+ `false` renders `noMatch(typed)` as the inline error. */
4
+ onJump: (pageNumber: number) => boolean;
5
+ /** The error line for a page number that did not match, phrased by the caller —
6
+ one names the document ("No page 999 in report.pdf."), another does not. */
7
+ noMatch: (typed: string) => string;
8
+ }
9
+ export declare function PageNumberJumpField({ onJump, noMatch }: PageNumberJumpFieldProps): import("react").JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { type ReactNode } from "react";
2
+ import type { ViewerFile, ViewerFrame } from "./types";
3
+ import type { useViewerZoom } from "./use-viewer-zoom";
4
+ export declare function FrameNav({ frame, onGo }: {
5
+ frame: ViewerFrame;
6
+ onGo: (next: number) => void;
7
+ }): import("react").JSX.Element;
8
+ export interface ViewerControlsProps {
9
+ frame: ViewerFrame;
10
+ frames: ViewerFrame[];
11
+ go: (index: number) => void;
12
+ zoom: ReturnType<typeof useViewerZoom>;
13
+ zoomable: boolean;
14
+ markLabel: string;
15
+ headerActions?: (frame: ViewerFrame) => ReactNode;
16
+ onDownload?: (file: ViewerFile) => void;
17
+ /** In the overflow popover: the entries say what they are, not just draw it. */
18
+ labelled?: boolean;
19
+ }
20
+ export declare function ViewerControls({ frame, frames, go, zoom, zoomable, markLabel, headerActions, onDownload, labelled }: ViewerControlsProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import type { ViewerFrame } from "./types";
2
+ export interface ViewerRailProps {
3
+ frames: ViewerFrame[];
4
+ index: number;
5
+ markLabel: string;
6
+ onSelect: (index: number) => void;
7
+ /** Collapsed by the header toggle. Stays in the DOM, so a host can re-open it. */
8
+ hidden: boolean;
9
+ }
10
+ export declare function ViewerRail({ frames, index, markLabel, onSelect, hidden }: ViewerRailProps): import("react").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { type ReactNode } from "react";
2
+ import type { useViewerZoom, ViewerFit } from "./use-viewer-zoom";
3
+ import type { ViewerFile, ViewerFrame } from "./types";
4
+ export type ViewerZoom = ReturnType<typeof useViewerZoom>;
5
+ /** How a frame is shown. `fit` is null for everything the camera does not move. */
6
+ export interface StageKind {
7
+ kind: "zoom" | "video" | "file" | "custom";
8
+ /** How the frame opens; null for everything the camera does not move. */
9
+ fit: ViewerFit | null;
10
+ }
11
+ export declare function stageKindOf(frame: ViewerFrame, custom: ReactNode): StageKind;
12
+ export interface ViewerStageProps {
13
+ frame: ViewerFrame;
14
+ /** What `stageKindOf` said about this frame (the shell already needed it). */
15
+ kind: StageKind["kind"];
16
+ /** The host's `renderBody(file)` result for a pageless file. */
17
+ custom: ReactNode;
18
+ zoom: ViewerZoom;
19
+ onDownload?: (file: ViewerFile) => void;
20
+ overlay: ReactNode;
21
+ }
22
+ export declare function ViewerStage({ frame, kind, custom, zoom, onDownload, overlay }: ViewerStageProps): import("react").JSX.Element;
@@ -0,0 +1,27 @@
1
+ import type { ViewerFile, ViewerFrame } from "./types";
2
+ /** Where the reader is. The ids are the truth; `index` only says where to land
3
+ when both have vanished (the nearest position). */
4
+ export interface Cursor {
5
+ fileId: string;
6
+ pageId: string | null;
7
+ index: number;
8
+ }
9
+ export declare function framesOf(files: readonly ViewerFile[]): ViewerFrame[];
10
+ export declare function cursorOf(frame: ViewerFrame): Cursor;
11
+ /** A stable identity for the frame on the stage, for keys and change detection. */
12
+ export declare function frameKeyOf(frame: ViewerFrame): string;
13
+ /** The frame the cursor names, else the one nearest its last index. */
14
+ export declare function resolveCursor(frames: readonly ViewerFrame[], cursor: Cursor | null): ViewerFrame | null;
15
+ export interface Start {
16
+ fileId?: string | null;
17
+ pageId?: string | null;
18
+ }
19
+ /**
20
+ * Where a viewer opens: the frame whose page id is `pageId` (inside `fileId`
21
+ * when given), else the first marked frame (inside `fileId` when given), else
22
+ * the first frame (of `fileId` when given). An id that matches nothing falls
23
+ * through to the next rule — a stale deep link opens the document, not nothing.
24
+ */
25
+ export declare function startFrame(frames: readonly ViewerFrame[], start: Start): ViewerFrame | null;
26
+ /** The frame's name, for a screen reader and for an alt attribute. */
27
+ export declare function frameLabel(frame: ViewerFrame): string;
@@ -0,0 +1,3 @@
1
+ export { FileViewer } from "./FileViewer";
2
+ export { PageNumberJumpField, type PageNumberJumpFieldProps } from "./PageNumberJumpField";
3
+ export type { FileViewerProps, ViewerFile, ViewerFrame, ViewerPage } from "./types";
@@ -0,0 +1,70 @@
1
+ import type { ReactNode } from "react";
2
+ import type { ChatFile } from "../chat/types";
3
+ /** One already-rendered page image of a multi-page document. */
4
+ export interface ViewerPage {
5
+ /** Stable identity: the consumer's own id for the page, never an index. */
6
+ id: string;
7
+ /** The full-size rendered page image. */
8
+ url: string;
9
+ /** A smaller render for the rail. Falls back to `url`. */
10
+ thumbUrl?: string | null;
11
+ /** The number as printed in the document. Null or absent when none was recorded. */
12
+ number?: number | null;
13
+ /** Draw this page as one of the ones worth looking at (see `markLabel`). */
14
+ marked?: boolean;
15
+ }
16
+ /** A file the viewer can show. Every ChatFile is a valid ViewerFile. */
17
+ export interface ViewerFile extends ChatFile {
18
+ /**
19
+ * Already-rendered page images, in document order. One or more entries make
20
+ * the file a paged document: one frame per page. Absent or empty: the file is
21
+ * ONE frame, shown by kind (image, video, anything else).
22
+ */
23
+ pages?: ViewerPage[];
24
+ }
25
+ /** What is on the stage. Handed to every render slot and to `onFrameChange`. */
26
+ export interface ViewerFrame {
27
+ file: ViewerFile;
28
+ /** The page of `file` on the stage; null when `file` has no pages. */
29
+ page: ViewerPage | null;
30
+ /** Zero-based position among all frames. */
31
+ index: number;
32
+ /** How many frames there are. */
33
+ total: number;
34
+ }
35
+ export interface FileViewerProps {
36
+ open: boolean;
37
+ onOpenChange: (open: boolean) => void;
38
+ /** Every file the reader may step through, in order. */
39
+ files: ViewerFile[];
40
+ /**
41
+ * Where to open. Read each time `open` turns true, never afterwards: the
42
+ * frame whose page id is `initialPageId` (inside `initialFileId` when given),
43
+ * else the first marked frame (inside `initialFileId` when given), else the
44
+ * first frame (of `initialFileId` when given).
45
+ */
46
+ initialFileId?: string | null;
47
+ initialPageId?: string | null;
48
+ /** Told when the frame on the stage changes. Observes; the viewer owns the position. */
49
+ onFrameChange?: (frame: ViewerFrame) => void;
50
+ /** The heading. Defaults to the current file's name. */
51
+ title?: ReactNode;
52
+ /** A quieter second line. Defaults to the current file's size, when known. */
53
+ subtitle?: ReactNode;
54
+ /** Offers Download for the current file. Omitted: no Download anywhere. */
55
+ onDownload?: (file: ViewerFile) => void;
56
+ /** What a mark means, as an adjective: "cited", "flagged". Default "marked". */
57
+ markLabel?: string;
58
+ /**
59
+ * The host's own header controls for the current frame. Mounted in exactly one
60
+ * place: inline from `lg` up, inside the overflow popover below it. A control
61
+ * with its own state therefore remounts, and starts over, when the layout
62
+ * crosses `lg` or the overflow popover closes: state a host needs to keep
63
+ * belongs above the viewer.
64
+ */
65
+ headerActions?: (frame: ViewerFrame) => ReactNode;
66
+ /** A host panel floating over the stage for the current frame (gpt-manager's quote panel). */
67
+ overlay?: (frame: ViewerFrame) => ReactNode;
68
+ /** Replaces the built-in stage for a file without pages. Null or undefined keeps the built-in. */
69
+ renderBody?: (file: ViewerFile) => ReactNode;
70
+ }
@@ -0,0 +1,13 @@
1
+ import type { ViewerFile, ViewerFrame } from "./types";
2
+ export interface UseFrameCursorOptions {
3
+ open: boolean;
4
+ files: ViewerFile[];
5
+ initialFileId?: string | null;
6
+ initialPageId?: string | null;
7
+ onFrameChange?: (frame: ViewerFrame) => void;
8
+ }
9
+ export declare function useFrameCursor({ open, files, initialFileId, initialPageId, onFrameChange }: UseFrameCursorOptions): {
10
+ frames: ViewerFrame[];
11
+ frame: ViewerFrame | null;
12
+ go: (next: number) => void;
13
+ };
@@ -0,0 +1,24 @@
1
+ export interface ViewerKeyActions {
2
+ go: (index: number) => void;
3
+ index: number;
4
+ total: number;
5
+ /** Null when the frame is not zoomable: the zoom keys are then not handled. */
6
+ zoom: {
7
+ zoomIn: () => void;
8
+ zoomOut: () => void;
9
+ reset: () => void;
10
+ } | null;
11
+ }
12
+ /**
13
+ * The viewer's keyboard (DX-4398): Arrow, PageUp/PageDown, Home and End step
14
+ * frames; `+`, `-` and `0` zoom. Returns the callback ref for the Dialog popup.
15
+ *
16
+ * A NATIVE listener on the popup element, not a document one and not a React
17
+ * `onKeyDown`: Base UI's popup stops propagation of the arrow, Home, End and Page
18
+ * keys (they belong to composite widgets), so by the time a key reached
19
+ * `document` it was gone. On the popup itself it runs first. It only ever sees
20
+ * keys aimed at the viewer's own DOM: a key inside a portalled Popover (the
21
+ * overflow menu) has a target outside the popup, so it never gets here. Escape is
22
+ * not handled: it is the Dialog's.
23
+ */
24
+ export declare function useViewerKeys(actions: ViewerKeyActions): import("react").Dispatch<import("react").SetStateAction<HTMLDivElement | null>>;
@@ -0,0 +1,29 @@
1
+ import { type CameraState, type ScaleBounds, type Size } from "../graph-explorer/camera-math";
2
+ /** The zoom range of the viewer: far enough out to see a wide page whole, far
3
+ enough in to read a signature. */
4
+ export declare const VIEWER_ZOOM_BOUNDS: ScaleBounds;
5
+ export type ViewerFit = "width" | "contain";
6
+ export interface UseViewerZoomOptions {
7
+ /** Changing this is a different frame: refit. */
8
+ frameKey: string;
9
+ /** How the frame opens. Null: the frame is not zoomable (video, a plain file). */
10
+ fit: ViewerFit | null;
11
+ }
12
+ export declare function useViewerZoom({ frameKey, fit }: UseViewerZoomOptions): {
13
+ camera: CameraState;
14
+ /** Whole-number percent, null until the frame has been measured. */
15
+ percent: number | null;
16
+ measured: boolean;
17
+ atFit: boolean;
18
+ canToggle: boolean;
19
+ panning: boolean;
20
+ bindViewport: (node: HTMLElement | null) => (() => void) | undefined;
21
+ setContentSize: (next: Size) => void;
22
+ zoomIn: () => void;
23
+ zoomOut: () => void;
24
+ reset: () => void;
25
+ toggleActual: (point?: {
26
+ x: number;
27
+ y: number;
28
+ }) => void;
29
+ };
@@ -55,6 +55,16 @@ export interface FitOptions extends ScaleBounds {
55
55
  export declare function unionBox(boxes: readonly Box[]): Box | null;
56
56
  /** A camera that fits the whole of `box` inside `viewport`, centred, padded. */
57
57
  export declare function fitBox(box: Box, viewport: Size, options?: FitOptions): CameraState;
58
+ /**
59
+ * A camera that makes `content` exactly as wide as `viewport` and starts at its
60
+ * top (DX-4398) — how a document page is read: the width fits, the length
61
+ * scrolls, and the top is where a page starts. Horizontally centred, which only
62
+ * shows once `bounds` clamp the page narrower than the viewport. Never an
63
+ * unbounded scale: a 10px-wide page stops at `maxScale`, a 100000px-wide one at
64
+ * `minScale`. Zero-size content (an image not measured yet) is a finite 100%
65
+ * camera at the origin, never NaN.
66
+ */
67
+ export declare function fitWidth(content: Size, viewport: Size, bounds?: ScaleBounds): CameraState;
58
68
  /**
59
69
  * Which viewport edges have `box`'s content extending past them at `camera`'s
60
70
  * current position/scale — the input `fitBoxWithFloor` (below) needs to
@@ -1,5 +1,5 @@
1
1
  export { GraphExplorer, type GraphExplorerProps } from "./GraphExplorer";
2
2
  export { frameBoxFor, layoutExplorerTree, neighbourhoodTree, edgePath } from "./tree-layout";
3
- export { CAMERA_DEFAULTS, centerOn, clampScale, fitBox, fitBoxWithFloor, toContentPoint, toScreenPoint, unionBox, zoomAtPoint, } from "./camera-math";
3
+ export { CAMERA_DEFAULTS, centerOn, clampScale, fitBox, fitBoxWithFloor, fitWidth, toContentPoint, toScreenPoint, unionBox, zoomAtPoint, } from "./camera-math";
4
4
  export type { Box, CameraState, FitOptions, FitWithFloorOptions, FitWithFloorResult, FrameOverflow, Point, ScaleBounds, Size, } from "./camera-math";
5
5
  export type { CrossLink, ExplorerLayout, ExplorerNodeRenderContext, ExplorerNodeRenderer, ExplorerTree, GraphExplorerVariant, TreeNode, } from "./types";
@@ -1,8 +1,6 @@
1
1
  import { type Box, type CameraState, type FrameOverflow } from "./camera-math";
2
- export interface CameraClickEvent {
3
- /** Client coordinates, for the caller to hit-test against its own elements. */
4
- target: HTMLElement;
5
- }
2
+ import { type ViewportClickEvent } from "./viewport-gesture";
3
+ export type CameraClickEvent = ViewportClickEvent;
6
4
  export interface UseCameraOptions {
7
5
  /** Content-space bounding box of the whole drawing. Drives `fitAll`. */
8
6
  contentBox: Box;
@@ -73,7 +71,7 @@ export interface UseCameraResult {
73
71
  * re-derives this from raw `camera` state itself.
74
72
  */
75
73
  frameOverflow: FrameOverflow;
76
- bindViewport: (node: HTMLDivElement | null) => void;
74
+ bindViewport: (node: HTMLElement | null) => (() => void) | undefined;
77
75
  zoomIn: () => void;
78
76
  zoomOut: () => void;
79
77
  fitAll: () => void;
@@ -0,0 +1,32 @@
1
+ import { type CameraState, type ScaleBounds, type Size } from "./camera-math";
2
+ /** How far a pointer may travel and still resolve to a click on release — below
3
+ the jitter of a resting hand, above the travel of a deliberate press. */
4
+ export declare const CLICK_DISTANCE = 5;
5
+ export interface ViewportClickEvent {
6
+ /** The element under the pointer at release, for the caller to hit-test. */
7
+ target: HTMLElement;
8
+ }
9
+ export interface UseViewportGestureOptions {
10
+ /** The camera right now. Read at the start of a pan and on every resume. */
11
+ camera: CameraState;
12
+ /** Wheel, pan and pinch write the camera through this. Wheel and pinch use
13
+ the updater form: they compound on whatever is current. */
14
+ setCamera: (next: CameraState | ((current: CameraState) => CameraState)) => void;
15
+ /** Wheel and pinch never leave these. */
16
+ zoomBounds: ScaleBounds;
17
+ /** A new gesture is starting: stop any programmatic move in flight. */
18
+ onGestureStart?: () => void;
19
+ /** A press that released without travelling past `CLICK_DISTANCE`. */
20
+ onClick?: (event: ViewportClickEvent) => void;
21
+ /** The viewport's content-box size, on observe and on every change. */
22
+ onResize?: (size: Size) => void;
23
+ /** Nothing pans, zooms or clicks. */
24
+ disabled?: boolean;
25
+ }
26
+ export interface UseViewportGestureResult {
27
+ /** A pointer is actively panning or pinching right now. */
28
+ panning: boolean;
29
+ /** Callback ref for the clipping viewport element. */
30
+ bindViewport: (node: HTMLElement | null) => (() => void) | undefined;
31
+ }
32
+ export declare function useViewportGesture(options: UseViewportGestureOptions): UseViewportGestureResult;
@@ -0,0 +1,18 @@
1
+ /** The scopes of every Popover whose content the reader is inside, outermost first. */
2
+ export declare const PopoverScopeContext: import("react").Context<readonly symbol[]>;
3
+ interface OpenPopover {
4
+ scope: symbol;
5
+ close: () => void;
6
+ /** Hide or show the popover without unmounting it. */
7
+ setCovered: (covered: boolean) => void;
8
+ /** How many open dialogs inside it are covering it right now. */
9
+ covers: number;
10
+ }
11
+ /** A Popover is open. Returns the call that says it no longer is. */
12
+ export declare function registerOpenPopover(entry: OpenPopover): () => void;
13
+ /** A Dialog is opening inside `ancestry`: close every open Popover outside it. */
14
+ export declare function dismissPopoversOutside(ancestry: readonly symbol[]): void;
15
+ /** A Dialog is open inside `ancestry`: hide those popovers until it closes.
16
+ Returns the call that says it has. */
17
+ export declare function coverPopovers(ancestry: readonly symbol[]): () => void;
18
+ export {};
@@ -856,6 +856,15 @@ export declare const coreIcons: {
856
856
  }], readonly ["path", {
857
857
  readonly d: "M14 20h7";
858
858
  }]];
859
+ readonly maximize: readonly [readonly ["path", {
860
+ readonly d: "M8 3H5a2 2 0 0 0-2 2v3";
861
+ }], readonly ["path", {
862
+ readonly d: "M21 8V5a2 2 0 0 0-2-2h-3";
863
+ }], readonly ["path", {
864
+ readonly d: "M3 16v3a2 2 0 0 0 2 2h3";
865
+ }], readonly ["path", {
866
+ readonly d: "M16 21h3a2 2 0 0 0 2-2v-3";
867
+ }]];
859
868
  readonly "maximize-2": readonly [readonly ["path", {
860
869
  readonly d: "M15 3h6v6";
861
870
  }], readonly ["path", {
@@ -916,6 +925,15 @@ export declare const coreIcons: {
916
925
  }], readonly ["path", {
917
926
  readonly d: "M21 15H3";
918
927
  }]];
928
+ readonly scan: readonly [readonly ["path", {
929
+ readonly d: "M3 7V5a2 2 0 0 1 2-2h2";
930
+ }], readonly ["path", {
931
+ readonly d: "M17 3h2a2 2 0 0 1 2 2v2";
932
+ }], readonly ["path", {
933
+ readonly d: "M21 17v2a2 2 0 0 1-2 2h-2";
934
+ }], readonly ["path", {
935
+ readonly d: "M7 21H5a2 2 0 0 1-2-2v-2";
936
+ }]];
919
937
  readonly table: readonly [readonly ["path", {
920
938
  readonly d: "M12 3v18";
921
939
  }], readonly ["rect", {
@@ -929,6 +947,41 @@ export declare const coreIcons: {
929
947
  }], readonly ["path", {
930
948
  readonly d: "M3 15h18";
931
949
  }]];
950
+ readonly "zoom-in": readonly [readonly ["circle", {
951
+ readonly cx: "11";
952
+ readonly cy: "11";
953
+ readonly r: "8";
954
+ }], readonly ["line", {
955
+ readonly x1: "21";
956
+ readonly x2: "16.65";
957
+ readonly y1: "21";
958
+ readonly y2: "16.65";
959
+ }], readonly ["line", {
960
+ readonly x1: "11";
961
+ readonly x2: "11";
962
+ readonly y1: "8";
963
+ readonly y2: "14";
964
+ }], readonly ["line", {
965
+ readonly x1: "8";
966
+ readonly x2: "14";
967
+ readonly y1: "11";
968
+ readonly y2: "11";
969
+ }]];
970
+ readonly "zoom-out": readonly [readonly ["circle", {
971
+ readonly cx: "11";
972
+ readonly cy: "11";
973
+ readonly r: "8";
974
+ }], readonly ["line", {
975
+ readonly x1: "21";
976
+ readonly x2: "16.65";
977
+ readonly y1: "21";
978
+ readonly y2: "16.65";
979
+ }], readonly ["line", {
980
+ readonly x1: "8";
981
+ readonly x2: "14";
982
+ readonly y1: "11";
983
+ readonly y2: "11";
984
+ }]];
932
985
  readonly activity: readonly [readonly ["path", {
933
986
  readonly d: "M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2";
934
987
  }]];
@@ -119,8 +119,9 @@ export { Message, MessagePartView, ToolCall, type MessageProps, type MessageActi
119
119
  export { MessageScroller, type MessageScrollerProps, } from "./components/chat/MessageScroller";
120
120
  export { Composer, type ComposerProps } from "./components/chat/Composer";
121
121
  export { StreamingMarkdown, type StreamingMarkdownProps, } from "./components/chat/StreamingMarkdown";
122
- export { Attachment, AttachmentAction, AttachmentList, AttachmentPreview, type AttachmentProps, type AttachmentActionProps, type AttachmentListProps, type AttachmentPreviewProps, type AttachmentLayout, } from "./components/chat/Attachment";
122
+ export { Attachment, AttachmentAction, AttachmentList, type AttachmentProps, type AttachmentActionProps, type AttachmentListProps, type AttachmentLayout, } from "./components/chat/Attachment";
123
123
  export { FileCover, type FileCoverProps } from "./components/chat/FileCover";
124
+ export { FileViewer, PageNumberJumpField, type FileViewerProps, type PageNumberJumpFieldProps, type ViewerFile, type ViewerFrame, type ViewerPage, } from "./components/file-viewer";
124
125
  export { fileIconFor, type FileIdentity } from "./components/chat/file-icon";
125
126
  export { VideoPlayer, type VideoPlayerProps, type VideoTrack } from "./components/VideoPlayer";
126
127
  export { ModelSelector, type ModelSelectorProps, type ChatModel, } from "./components/chat/ModelSelector";
@@ -155,7 +156,7 @@ export { ProvenanceDisclosure, ProvenanceDetail, ProvenanceBadge, ConfidenceRead
155
156
  export { confidenceLevel, CONFIDENCE_LEVEL_LABELS, type ConfidenceLevel } from "./lib/confidence";
156
157
  export { createSimStore, resetSimStores, useSimSettings, setSimSettings, getNetworkSpeed, getDataSource, simulateLatency, SimNetworkError, type SimStore, type SimStoreOptions, type SimSettings, type NetworkSpeed, type DataSource, type SimNamespace, } from "./lib/sim";
157
158
  export { NodeCanvas, LAYOUT_DEFAULTS, edgePath, layoutGraph, neighbourhood, type NodeCanvasProps, type CanvasCycleScope, type CanvasEdge, type CanvasGraph, type CanvasGroup, type CanvasLayout, type CanvasNode, type CanvasOrientation, type CanvasPlacedEdge, type CanvasScope, type LayoutOptions, type NodeRenderContext, type NodeRenderer, type PlacedNode, } from "./components/node-canvas";
158
- export { GraphExplorer, frameBoxFor, layoutExplorerTree, neighbourhoodTree, CAMERA_DEFAULTS, centerOn, clampScale, fitBox, fitBoxWithFloor, toContentPoint, toScreenPoint, unionBox, zoomAtPoint, type GraphExplorerProps, type Box, type CameraState, type FitOptions, type FitWithFloorOptions, type FitWithFloorResult, type FrameOverflow, type Point, type ScaleBounds, type Size, type CrossLink, type ExplorerLayout, type ExplorerNodeRenderContext, type ExplorerNodeRenderer, type ExplorerTree, type GraphExplorerVariant, type TreeNode as ExplorerTreeNode, } from "./components/graph-explorer";
159
+ export { GraphExplorer, frameBoxFor, layoutExplorerTree, neighbourhoodTree, CAMERA_DEFAULTS, centerOn, clampScale, fitBox, fitBoxWithFloor, fitWidth, toContentPoint, toScreenPoint, unionBox, zoomAtPoint, type GraphExplorerProps, type Box, type CameraState, type FitOptions, type FitWithFloorOptions, type FitWithFloorResult, type FrameOverflow, type Point, type ScaleBounds, type Size, type CrossLink, type ExplorerLayout, type ExplorerNodeRenderContext, type ExplorerNodeRenderer, type ExplorerTree, type GraphExplorerVariant, type TreeNode as ExplorerTreeNode, } from "./components/graph-explorer";
159
160
  export { FocusWeb, CENTER_POSITION, PARENT_POSITION, WIDE_RING_THRESHOLD, layoutRing, type FocusNodeRenderContext, type FocusNodeRenderer, type FocusNodeRole, type FocusWebNode, type FocusWebNodeLook, type FocusWebProps, type PlacedRingNode, } from "./components/focus-web";
160
161
  export { SequenceDiagram, type SequenceDiagramProps, type SequenceStep, } from "./components/SequenceDiagram";
161
162
  export { OpenApiViewer, type OpenApiViewerProps, OperationCard, type OperationCardProps, OperationHeader, type OperationHeaderProps, OperationDetail, type OperationDetailProps, SchemaView, type SchemaViewProps, groupOperations, isHttpMethod, mergedParameters, operationAnchorId, resolveSchema, resolveWebhooks, schemaToExample, type SchemaResolution, HTTP_METHODS, type HttpMethod, type OpenApiDocument, type OpenApiMediaType, type OpenApiOperation, type OpenApiParameter, type OpenApiParameterLocation, type OpenApiPathItem, type OpenApiRequestBody, type OpenApiResponse, type OpenApiSchema, type OpenApiSecurityRequirement, type OpenApiSecurityScheme, type OpenApiTag, type OperationGroup, type ResolvedOperation, } from "./components/openapi";
@@ -0,0 +1,3 @@
1
+ export declare const INTERACTIVE_SELECTOR = "button, a, input, textarea, select, [role='button']";
2
+ /** True when `target` is, or is inside, a control. */
3
+ export declare function isInteractiveTarget(target: EventTarget | null): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danxbot/ui",
3
- "version": "18.4.0",
3
+ "version": "19.0.0",
4
4
  "type": "module",
5
5
  "description": "Danxbot — a domain-agnostic React design system with motion as a first-class primitive.",
6
6
  "license": "MIT",