@qilin-agent/client-ui-primitives 3.1.7 → 3.1.8
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/README.i18n.yaml +8 -8
- package/README.md +11 -4
- package/README.zh.md +12 -4
- package/lib/AnimatedRows.module.css +7 -0
- package/lib/Button.module.css +6 -3
- package/lib/DetailDocument.module.css +67 -0
- package/lib/HoverCard.module.css +3 -3
- package/lib/ImageLightbox.module.css +1 -1
- package/lib/InlineEditor.module.css +1 -1
- package/lib/Input.module.css +2 -2
- package/lib/Menu.module.css +127 -78
- package/lib/MenuSurface.module.css +23 -7
- package/lib/QuotePreview.module.css +89 -0
- package/lib/RowDragPreview.module.css +12 -0
- package/lib/SegmentedTabs.module.css +4 -1
- package/lib/Tag.module.css +1 -1
- package/lib/TerminalBlock.module.css +1 -1
- package/lib/Toast.module.css +28 -0
- package/lib/UserMessageBubble.module.css +11 -0
- package/lib/index.js +2094 -1115
- package/lib/markdown/CodeBlock.module.css +23 -0
- package/lib/markdown/JsonBlock.module.css +1 -1
- package/lib/markdown/MarkdownText.module.css +11 -7
- package/lib/settings-form/fields.module.css +2 -2
- package/lib/types/AnimatedRows.d.ts +46 -0
- package/lib/types/Button.d.ts +13 -4
- package/lib/types/DetailDocument.d.ts +79 -0
- package/lib/types/ImageLightbox.d.ts +3 -1
- package/lib/types/Menu.d.ts +25 -9
- package/lib/types/MenuSurface.d.ts +9 -0
- package/lib/types/QuotePreview.d.ts +26 -0
- package/lib/types/SegmentedTabs.d.ts +3 -1
- package/lib/types/Toast.d.ts +19 -1
- package/lib/types/Tooltip.d.ts +13 -8
- package/lib/types/UserMessageBubble.d.ts +11 -0
- package/lib/types/code-highlighting.d.ts +12 -0
- package/lib/types/focus.d.ts +8 -0
- package/lib/types/icons/index.d.ts +8 -0
- package/lib/types/icons/shared-artwork.d.ts +1 -0
- package/lib/types/index.d.ts +20 -4
- package/lib/types/markdown/MarkdownDelegate.d.ts +19 -2
- package/lib/types/markdown/MarkdownText.d.ts +3 -1
- package/lib/types/markdown/file-link.d.ts +13 -3
- package/lib/types/markdown/mathCompatibility.d.ts +12 -5
- package/lib/types/markdown/render.d.ts +2 -1
- package/lib/types/markdown/windows-path-destinations.d.ts +12 -0
- package/lib/types/motion.d.ts +13 -0
- package/lib/types/overlay-top-margin.d.ts +10 -2
- package/lib/types/quote-text.d.ts +69 -0
- package/lib/types/use-clipboard-copy.d.ts +14 -0
- package/lib/types/useAnchoredPosition.d.ts +31 -18
- package/lib/types/useRowDragPreview.d.ts +20 -0
- package/lib/types/user-text.d.ts +24 -2
- package/package.json +8 -6
- package/lib/types/use-copy-feedback.d.ts +0 -14
|
@@ -104,6 +104,29 @@
|
|
|
104
104
|
color: var(--qilin-alias-label-primary);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
/* Line-level hover: the source line under the pointer takes the interactive
|
|
108
|
+
wash so a reader can follow one line across a wide block. The rule paints a
|
|
109
|
+
background only — selection, the copy button's textContent read, and the
|
|
110
|
+
gutter's counters are untouched. Shiki, the plain arm, and the streaming arm
|
|
111
|
+
all emit one `span.line` per source line, so the selector covers every arm. */
|
|
112
|
+
.block :where(pre) code > :global(.line) {
|
|
113
|
+
border-radius: 4px;
|
|
114
|
+
transition: background-color 120ms ease;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@media (hover: hover) {
|
|
118
|
+
.block :where(pre) code > :global(.line):hover {
|
|
119
|
+
background-color: var(--qilin-alias-interactive-bg-hover);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* A reader who asked for less motion gets the wash without the fade. */
|
|
124
|
+
@media (prefers-reduced-motion: reduce) {
|
|
125
|
+
.block :where(pre) code > :global(.line) {
|
|
126
|
+
transition: none;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
107
130
|
.numbered :where(pre) code {
|
|
108
131
|
display: block;
|
|
109
132
|
counter-reset: source-line;
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
max-height: 200px;
|
|
24
24
|
overflow: auto;
|
|
25
25
|
background: var(--qilin-alias-markdown-code-block);
|
|
26
|
-
border:
|
|
26
|
+
border: 1px solid var(--qilin-alias-border-l1);
|
|
27
27
|
border-radius: 6px;
|
|
28
28
|
font-family: var(--ds-font-family-code);
|
|
29
29
|
font-size: 11px;
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
.markdown hr {
|
|
144
144
|
display: block;
|
|
145
145
|
border: none;
|
|
146
|
-
height:
|
|
146
|
+
height: 1px;
|
|
147
147
|
margin: 32px 0;
|
|
148
148
|
background: var(--qilin-alias-border-l2);
|
|
149
149
|
}
|
|
@@ -168,7 +168,7 @@
|
|
|
168
168
|
font-family: var(--ds-font-family-code);
|
|
169
169
|
font-size: 0.875em !important;
|
|
170
170
|
background-color: var(--qilin-alias-markdown-inline-code);
|
|
171
|
-
border:
|
|
171
|
+
border: 1px solid var(--qilin-alias-border-l1);
|
|
172
172
|
border-radius: 6px;
|
|
173
173
|
padding: 0 5px;
|
|
174
174
|
}
|
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
.tableScroll th {
|
|
245
245
|
text-align: start;
|
|
246
246
|
padding: 10px 16px;
|
|
247
|
-
border-bottom:
|
|
247
|
+
border-bottom: 1px solid var(--qilin-alias-border-l3);
|
|
248
248
|
border-top: none;
|
|
249
249
|
font: var(--qilin-font-markdown-table-head);
|
|
250
250
|
max-width: 320px;
|
|
@@ -254,7 +254,7 @@
|
|
|
254
254
|
|
|
255
255
|
.tableScroll td {
|
|
256
256
|
padding: 10px 16px;
|
|
257
|
-
border-bottom:
|
|
257
|
+
border-bottom: 1px solid var(--qilin-alias-border-l2);
|
|
258
258
|
font: var(--qilin-font-markdown-table);
|
|
259
259
|
max-width: 320px;
|
|
260
260
|
max-width: min(30vw, 320px);
|
|
@@ -305,10 +305,14 @@
|
|
|
305
305
|
on hover/focus. An underline at rest reads badly inside the code chip, where
|
|
306
306
|
it collides with monospace descenders and the pill background. */
|
|
307
307
|
.fileMention {
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
/* A mention of a file the agent produced highlights its code chip: the
|
|
309
|
+
negative margins fill the chip's own padding so the accent pill covers
|
|
310
|
+
the whole chip rather than nesting inside it. */
|
|
311
|
+
margin: 0 -5px;
|
|
312
|
+
padding: 0 5px;
|
|
310
313
|
border: none;
|
|
311
|
-
|
|
314
|
+
border-radius: 6px;
|
|
315
|
+
background: var(--qilin-specific-bubble-highlight);
|
|
312
316
|
font: inherit;
|
|
313
317
|
font-weight: 500;
|
|
314
318
|
color: var(--qilin-alias-link);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
.field + .field {
|
|
11
|
-
border-top:
|
|
11
|
+
border-top: 1px solid var(--qilin-alias-border-l2);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
.head {
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
.input {
|
|
108
108
|
height: 34px;
|
|
109
109
|
padding: 0 12px;
|
|
110
|
-
border:
|
|
110
|
+
border: 1px solid var(--qilin-alias-border-l4);
|
|
111
111
|
border-radius: var(--qilin-radius-md);
|
|
112
112
|
background: var(--qilin-alias-bg-layer-3);
|
|
113
113
|
font: inherit;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** React-commit-driven movement and entry/exit fades for keyed rows. */
|
|
2
|
+
import { Component, type AriaRole, type ReactNode } from 'react';
|
|
3
|
+
/** Keyed row content, list semantics, and animation readiness. */
|
|
4
|
+
export interface AnimatedRowsProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
className: string;
|
|
7
|
+
role?: AriaRole;
|
|
8
|
+
label?: string;
|
|
9
|
+
/** Unique DOM-order keys matching the rendered data-row-key attributes. */
|
|
10
|
+
rowKeys: readonly string[];
|
|
11
|
+
ready: boolean;
|
|
12
|
+
/** Changes that replace the view or reveal hidden rows settle immediately. */
|
|
13
|
+
resetKey: string;
|
|
14
|
+
}
|
|
15
|
+
interface RowPosition {
|
|
16
|
+
element: HTMLElement;
|
|
17
|
+
rect: DOMRect;
|
|
18
|
+
opacity: number;
|
|
19
|
+
}
|
|
20
|
+
interface RowSnapshot {
|
|
21
|
+
positions: Map<string, RowPosition>;
|
|
22
|
+
removed: Map<string, RowPosition>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Animates keyed rows only when their rendered membership or order changes.
|
|
26
|
+
* Motion starts after the first pointer or keyboard input inside the mounted list.
|
|
27
|
+
* The parent supplies a positioned container for the inert exit overlay.
|
|
28
|
+
*/
|
|
29
|
+
export declare class AnimatedRows extends Component<AnimatedRowsProps> {
|
|
30
|
+
private armed;
|
|
31
|
+
private readonly list;
|
|
32
|
+
private readonly overlay;
|
|
33
|
+
private readonly movements;
|
|
34
|
+
private readonly exits;
|
|
35
|
+
getSnapshotBeforeUpdate(previous: AnimatedRowsProps): RowSnapshot | null;
|
|
36
|
+
componentDidUpdate(previous: AnimatedRowsProps, _state: unknown, snapshot: RowSnapshot | null): void;
|
|
37
|
+
componentWillUnmount(): void;
|
|
38
|
+
private readPositions;
|
|
39
|
+
private move;
|
|
40
|
+
private cancelMovements;
|
|
41
|
+
private removeExit;
|
|
42
|
+
private clear;
|
|
43
|
+
render(): ReactNode;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=AnimatedRows.d.ts.map
|
package/lib/types/Button.d.ts
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactNode } from 'react';
|
|
2
2
|
/** Visual variant, each backed by its --qilin-alias-button-* token family. */
|
|
3
3
|
export type ButtonVariant = 'primary' | 'ghost' | 'outline' | 'toolbar';
|
|
4
|
+
/** Props accepted by {@link Button}. */
|
|
5
|
+
export type ButtonProps = {
|
|
6
|
+
variant?: ButtonVariant;
|
|
7
|
+
size?: 'md' | 'sm';
|
|
8
|
+
icon?: ReactNode;
|
|
9
|
+
className?: string | undefined;
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
} & ButtonHTMLAttributes<HTMLButtonElement>;
|
|
4
12
|
/**
|
|
5
13
|
* Render a button.
|
|
6
14
|
* @param props.variant - visual family (default 'ghost').
|
|
7
15
|
* @param props.size - 'md' 36px capsule (figma Button) or 'sm' 28px compact.
|
|
8
16
|
* @param props.icon - optional leading 16px icon node.
|
|
17
|
+
* @param ref - native button for focus management and overlay anchors.
|
|
9
18
|
* @returns the button element; native button attributes pass through.
|
|
10
19
|
*/
|
|
11
|
-
export declare
|
|
20
|
+
export declare const Button: import("react").ForwardRefExoticComponent<{
|
|
12
21
|
variant?: ButtonVariant;
|
|
13
|
-
size?:
|
|
22
|
+
size?: "md" | "sm";
|
|
14
23
|
icon?: ReactNode;
|
|
15
24
|
className?: string | undefined;
|
|
16
25
|
children?: ReactNode;
|
|
17
|
-
} & ButtonHTMLAttributes<HTMLButtonElement>
|
|
26
|
+
} & ButtonHTMLAttributes<HTMLButtonElement> & import("react").RefAttributes<HTMLButtonElement>>;
|
|
18
27
|
//# sourceMappingURL=Button.d.ts.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type MarkdownLabels, type MarkdownPathImages } from './markdown/MarkdownText.tsx';
|
|
3
|
+
/** One read of a long Markdown description, such as a plugin's detail document. */
|
|
4
|
+
export type DetailDocumentState = {
|
|
5
|
+
readonly status: 'loading';
|
|
6
|
+
} | {
|
|
7
|
+
readonly status: 'found';
|
|
8
|
+
readonly markdown: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly status: 'none';
|
|
11
|
+
} | {
|
|
12
|
+
readonly status: 'error';
|
|
13
|
+
readonly message: string;
|
|
14
|
+
};
|
|
15
|
+
/** A read as owners track it: in flight, settled with a document or none, or failed with a localized message. */
|
|
16
|
+
export type DetailDocumentRead = undefined | {
|
|
17
|
+
readonly status: 'loading';
|
|
18
|
+
} | {
|
|
19
|
+
readonly status: 'ready';
|
|
20
|
+
readonly markdown: string | undefined;
|
|
21
|
+
} | {
|
|
22
|
+
readonly status: 'error';
|
|
23
|
+
readonly message: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The state {@link DetailDocument} shows for an owner's read: loading until it settles, then the document, none, or the
|
|
27
|
+
* failure.
|
|
28
|
+
* @param read - the owner's read; undefined before it starts.
|
|
29
|
+
* @returns the state to show.
|
|
30
|
+
*/
|
|
31
|
+
export declare function detailDocumentState(read: DetailDocumentRead): DetailDocumentState;
|
|
32
|
+
/** Translated strings of a detail document's chrome, as an owner's dictionary supplies them. */
|
|
33
|
+
export interface DetailDocumentCopy {
|
|
34
|
+
readonly title: string;
|
|
35
|
+
readonly loading: string;
|
|
36
|
+
readonly retry: string;
|
|
37
|
+
readonly copy: string;
|
|
38
|
+
readonly copied: string;
|
|
39
|
+
/** Alt text naming an on-page Mermaid diagram. */
|
|
40
|
+
readonly diagram: string;
|
|
41
|
+
/** Alt text naming an enlarged Mermaid diagram. */
|
|
42
|
+
readonly enlarged: string;
|
|
43
|
+
readonly footnotes: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Assemble reference-stable labels for {@link DetailDocument} from translated strings.
|
|
47
|
+
* @param copy - the translated strings.
|
|
48
|
+
* @returns labels that keep their identity while the strings stay equal.
|
|
49
|
+
*/
|
|
50
|
+
export declare function useDetailDocumentLabels(copy: DetailDocumentCopy): DetailDocumentLabels;
|
|
51
|
+
/** Localized chrome of a detail document. */
|
|
52
|
+
export interface DetailDocumentLabels {
|
|
53
|
+
/** Accessible name of the scrollable document region; the section shows no heading of its own. */
|
|
54
|
+
readonly title: string;
|
|
55
|
+
/** Accessible name of the loading placeholder. */
|
|
56
|
+
readonly loading: string;
|
|
57
|
+
/** Retry button text. */
|
|
58
|
+
readonly retry: string;
|
|
59
|
+
readonly markdown: MarkdownLabels;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A section showing a long Markdown description, without a heading of its own: three skeleton lines while it loads, the
|
|
63
|
+
* document once found, or the owner's failure message with a retry. Nothing renders for `none`. A document taller than
|
|
64
|
+
* the section's height limit scrolls inside it, and the scroll region, named by `labels.title`, takes keyboard focus.
|
|
65
|
+
* Raw HTML is omitted, relative links stay text, and only images the owner's `images` resolver accepts, or absolute
|
|
66
|
+
* HTTP(S) images, load.
|
|
67
|
+
* @param props.state - the read to show.
|
|
68
|
+
* @param props.labels - localized region name, placeholder name, retry text, and Markdown chrome; keep `markdown` reference-stable.
|
|
69
|
+
* @param props.images - resolves the document's relative image destinations to displayable URLs.
|
|
70
|
+
* @param props.onRetry - reads the document again after a failure.
|
|
71
|
+
* @returns the section, or null.
|
|
72
|
+
*/
|
|
73
|
+
export declare function DetailDocument({ state, labels, images, onRetry }: {
|
|
74
|
+
readonly state: DetailDocumentState;
|
|
75
|
+
readonly labels: DetailDocumentLabels;
|
|
76
|
+
readonly images?: MarkdownPathImages | undefined;
|
|
77
|
+
readonly onRetry: () => void;
|
|
78
|
+
}): ReactNode;
|
|
79
|
+
//# sourceMappingURL=DetailDocument.d.ts.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
1
2
|
/** Lightbox strings the owner resolves from its own locale namespace. */
|
|
2
3
|
export interface ImageLightboxLabels {
|
|
3
4
|
/** Accessible name of the preview dialog. */
|
|
@@ -18,10 +19,11 @@ export interface ImageLightboxLabels {
|
|
|
18
19
|
* @param props.onClose - dismiss callback owned by the opener.
|
|
19
20
|
* @returns the modal preview dialog.
|
|
20
21
|
*/
|
|
21
|
-
export declare function ImageLightbox({ src, alt, labels, onClose }: {
|
|
22
|
+
export declare function ImageLightbox({ src, alt, labels, onClose, contextMenuProps }: {
|
|
22
23
|
src: string;
|
|
23
24
|
alt: string;
|
|
24
25
|
labels: ImageLightboxLabels;
|
|
25
26
|
onClose: () => void;
|
|
27
|
+
contextMenuProps?: Pick<HTMLAttributes<HTMLElement>, 'onContextMenu' | 'onKeyDown' | 'tabIndex'> | undefined;
|
|
26
28
|
}): import("react").ReactPortal;
|
|
27
29
|
//# sourceMappingURL=ImageLightbox.d.ts.map
|
package/lib/types/Menu.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface MenuItem {
|
|
|
14
14
|
/** Destructive row: error-colored text/icon and danger hover fill. */
|
|
15
15
|
danger?: boolean;
|
|
16
16
|
/** Nested card opened to the right on hover/focus. */
|
|
17
|
-
submenu?: readonly
|
|
17
|
+
submenu?: readonly MenuEntry[];
|
|
18
18
|
}
|
|
19
19
|
/** Hairline between item groups (not selectable). */
|
|
20
20
|
export interface MenuSeparator {
|
|
@@ -41,6 +41,12 @@ export interface MenuItemButtonProps {
|
|
|
41
41
|
current?: boolean;
|
|
42
42
|
/** Whether the row cannot be activated. */
|
|
43
43
|
disabled?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Why the disabled row cannot be activated. The row then stays hoverable and
|
|
46
|
+
* focusable, shows the reason in a tooltip, and exposes it as the row's
|
|
47
|
+
* description; an enabled row ignores it.
|
|
48
|
+
*/
|
|
49
|
+
disabledReason?: string | undefined;
|
|
44
50
|
/** Destructive row: error-colored text/icon and danger hover fill. */
|
|
45
51
|
danger?: boolean;
|
|
46
52
|
/**
|
|
@@ -64,12 +70,13 @@ export interface MenuItemButtonProps {
|
|
|
64
70
|
* @param props.icon - optional leading icon.
|
|
65
71
|
* @param props.current - whether the row identifies the currently displayed page or view.
|
|
66
72
|
* @param props.disabled - whether the row cannot be activated.
|
|
73
|
+
* @param props.disabledReason - why a disabled row cannot be activated, shown in a tooltip and read as its description.
|
|
67
74
|
* @param props.danger - whether to use the destructive row colors.
|
|
68
75
|
* @param props.separatorBefore - whether this row starts a new group (hairline above it).
|
|
69
76
|
* @param props.onSelect - row activation callback.
|
|
70
77
|
* @returns one menu-item row.
|
|
71
78
|
*/
|
|
72
|
-
export declare function MenuItemButton({ children, shortcut, icon, current, disabled, danger, separatorBefore, onSelect, }: MenuItemButtonProps): import("react").JSX.Element;
|
|
79
|
+
export declare function MenuItemButton({ children, shortcut, icon, current, disabled, disabledReason, danger, separatorBefore, onSelect, }: MenuItemButtonProps): import("react").JSX.Element;
|
|
73
80
|
/**
|
|
74
81
|
* Render an anchored dropdown menu. While the list is open its keys mirror the
|
|
75
82
|
* composer's: Tab settles the focused row — from the trigger, Tab enters the
|
|
@@ -77,6 +84,9 @@ export declare function MenuItemButton({ children, shortcut, icon, current, disa
|
|
|
77
84
|
* anchor's first button, and selecting a row does the same — the rows unmount
|
|
78
85
|
* with the list. Only a keyboard on the trigger or inside the list is
|
|
79
86
|
* intercepted; Tab presses elsewhere on the page stay the browser's.
|
|
87
|
+
* @param props.contextual - cursor positioning, context dismissal, and per-divider icon alignment.
|
|
88
|
+
* @param props.exiting - retain an inert popup during dismissal or replacement fade.
|
|
89
|
+
* @param props.returnFocus - original control captured before asynchronous menu preparation.
|
|
80
90
|
* @param props.autoFocus - focus the first item on open; the arrow keys walk the list either way.
|
|
81
91
|
* @param props.open - whether the list is showing (owner-controlled).
|
|
82
92
|
* @param props.anchor - the trigger element (rendered in place).
|
|
@@ -90,9 +100,9 @@ export declare function MenuItemButton({ children, shortcut, icon, current, disa
|
|
|
90
100
|
* @param props.align - list alignment against the anchor (default 'start').
|
|
91
101
|
* @param props.side - open below (`bottom`, default) or above (`top`) the anchor.
|
|
92
102
|
* @param props.portal - render the list into document.body, fixed-positioned
|
|
93
|
-
*
|
|
94
|
-
* ancestor's overflow clipping would crop the
|
|
95
|
-
* keeps the pure-CSS in-place behavior.
|
|
103
|
+
* synchronously (follows movement, resizing, and browser zoom while open)
|
|
104
|
+
* and clamped inside the visual viewport. Use when an ancestor's overflow clipping would crop the
|
|
105
|
+
* in-place list; default false keeps the pure-CSS in-place behavior.
|
|
96
106
|
* @param props.closeOnPointerLeave - close the list once the pointer has left
|
|
97
107
|
* both trigger and list for the pointer grace (default false keeps it open
|
|
98
108
|
* until outside click/Escape/selection). The grace makes the 4px trigger->list
|
|
@@ -103,11 +113,11 @@ export declare function MenuItemButton({ children, shortcut, icon, current, disa
|
|
|
103
113
|
* directly (e.g. from a host-owned trigger button) instead of measuring the
|
|
104
114
|
* Menu's own wrapper span. Required when the wrapper isn't itself laid out at
|
|
105
115
|
* the trigger (render-prop anchors, effect-positioned proxies — measuring the
|
|
106
|
-
* wrapper there races the host's layout effects). Called
|
|
107
|
-
*
|
|
116
|
+
* wrapper there races the host's layout effects). Called while tracking the
|
|
117
|
+
* anchor and on scroll/resize; return null to defer placement.
|
|
108
118
|
* @param props.minWidthFromAnchor - in portal mode, keep the menu at least as wide as its anchor, bounded by viewport margins.
|
|
109
119
|
* @param props.footer - rows pinned below the scrolling items area, separated
|
|
110
|
-
* by a hairline;
|
|
120
|
+
* by a hairline; contextual menus reuse an explicit leading separator. These rows stay visible while the items above scroll.
|
|
111
121
|
* @param props.children - component rows rendered after `items` in the same
|
|
112
122
|
* list, each a `role="menuitem"` button such as {@link MenuItemButton}; they
|
|
113
123
|
* share the keyboard walk, the submenu exclusivity, and the post-selection
|
|
@@ -122,8 +132,14 @@ export declare function MenuItemButton({ children, shortcut, icon, current, disa
|
|
|
122
132
|
* document.body outside the owner's DOM subtree.
|
|
123
133
|
* @returns anchor wrapper with the conditional list.
|
|
124
134
|
*/
|
|
125
|
-
export declare function Menu({ open, anchor, items, children, selectedId, selectedIds, onSelect, onClose, align, side, portal, closeOnPointerLeave, dense, compact, autoFocus, selection, getAnchorRect, minWidthFromAnchor, footer, className, listClassName }: {
|
|
135
|
+
export declare function Menu({ open, anchor, items, children, selectedId, selectedIds, onSelect, onClose, align, side, portal, closeOnPointerLeave, dense, compact, autoFocus, selection, getAnchorRect, minWidthFromAnchor, footer, className, listClassName, contextual, exiting, returnFocus }: {
|
|
126
136
|
open: boolean;
|
|
137
|
+
/** Pointer-positioned popup: cursor clearance, grouped icons, and context gestures. */
|
|
138
|
+
contextual?: boolean;
|
|
139
|
+
/** Resolve the original control for focus restoration and inert/hidden dismissal. */
|
|
140
|
+
returnFocus?: (() => HTMLElement | null) | undefined;
|
|
141
|
+
/** Retain a dismissed context popup during its short fade. */
|
|
142
|
+
exiting?: 'dismiss' | 'replace' | undefined;
|
|
127
143
|
autoFocus?: boolean;
|
|
128
144
|
anchor: ReactNode;
|
|
129
145
|
items?: readonly MenuEntry[];
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
/** Shared menu material and the macOS backing that lets Chromium blur transparent windows. */
|
|
2
2
|
import { type ComponentPropsWithoutRef } from 'react';
|
|
3
|
+
/** Context-menu transition durations in milliseconds, shared with its lifecycle owner. */
|
|
4
|
+
export declare const MENU_TRANSITION_MS: Readonly<{
|
|
5
|
+
enter: 40;
|
|
6
|
+
dismiss: 80;
|
|
7
|
+
replace: 10;
|
|
8
|
+
prepare: 20;
|
|
9
|
+
}>;
|
|
3
10
|
/** Menu containers preserve native div props and refs. */
|
|
4
11
|
export interface MenuSurfaceProps extends ComponentPropsWithoutRef<'div'> {
|
|
5
12
|
/** Match the shared compact menu's smaller outer radius. */
|
|
6
13
|
compact?: boolean;
|
|
14
|
+
/** Fade direct content, material, and native backing without isolating the material's backdrop. */
|
|
15
|
+
phase?: 'enter' | 'dismiss' | 'replace' | undefined;
|
|
7
16
|
}
|
|
8
17
|
/**
|
|
9
18
|
* Paint a menu and, on macOS, an opaque backing behind the page content within its bounds.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
/** Localized names of the quote controls; a caller owns every string. */
|
|
3
|
+
export interface QuotePreviewLabels {
|
|
4
|
+
/** Accessible name of the copy control. */
|
|
5
|
+
readonly copy: string;
|
|
6
|
+
/** Accessible name after an accepted copy. */
|
|
7
|
+
readonly copied: string;
|
|
8
|
+
/** Accessible name of the jump control. */
|
|
9
|
+
readonly jump: string;
|
|
10
|
+
}
|
|
11
|
+
/** Presentation inputs for one quoted excerpt. */
|
|
12
|
+
export interface QuotePreviewProps {
|
|
13
|
+
/** Excerpt text as decoded from the message, without its source marker line. */
|
|
14
|
+
readonly text: string;
|
|
15
|
+
/** Localized control names. */
|
|
16
|
+
readonly labels: QuotePreviewLabels;
|
|
17
|
+
/** Reveal the quoted source; omission hides the jump control. */
|
|
18
|
+
readonly onJump?: (() => void) | undefined;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Render one quoted excerpt with its copy and optional jump controls.
|
|
22
|
+
* @param props - excerpt text, control names, and the reveal action.
|
|
23
|
+
* @returns the quote surface, with the full text on hover while clipped.
|
|
24
|
+
*/
|
|
25
|
+
export declare function QuotePreview({ text, labels, onJump }: QuotePreviewProps): JSX.Element;
|
|
26
|
+
//# sourceMappingURL=QuotePreview.d.ts.map
|
|
@@ -14,13 +14,15 @@ export interface SegmentedTab<Value extends string = string> {
|
|
|
14
14
|
* Keyboard selection also moves focus; only the selected tab is a tab stop.
|
|
15
15
|
* @param props.label - localized accessible name for the tab list.
|
|
16
16
|
* @param props.className - layout placement; panels remain caller-owned.
|
|
17
|
+
* @param props.size - `sm` draws 30px tabs with a 2px inset (34px tall); the default `md` draws 34px tabs with a 4px inset (42px tall).
|
|
17
18
|
* @returns the tab list, without its panels.
|
|
18
19
|
*/
|
|
19
|
-
export declare function SegmentedTabs<Value extends string>({ items, value, onChange, label, className }: {
|
|
20
|
+
export declare function SegmentedTabs<Value extends string>({ items, value, onChange, label, className, size }: {
|
|
20
21
|
items: readonly [SegmentedTab<Value>, ...SegmentedTab<Value>[]];
|
|
21
22
|
value: Value;
|
|
22
23
|
onChange: (value: Value) => void;
|
|
23
24
|
label: string;
|
|
24
25
|
className?: string | undefined;
|
|
26
|
+
size?: 'sm' | 'md' | undefined;
|
|
25
27
|
}): ReactNode;
|
|
26
28
|
//# sourceMappingURL=SegmentedTabs.d.ts.map
|
package/lib/types/Toast.d.ts
CHANGED
|
@@ -7,6 +7,16 @@ import type { ReactNode } from 'react';
|
|
|
7
7
|
* transformed or filtered ancestor cannot trap the fixed banner in that
|
|
8
8
|
* ancestor's box.
|
|
9
9
|
*
|
|
10
|
+
* Actions extend the sentence with inline choices: each renders its plain-text
|
|
11
|
+
* `prefix` (a connective such as "or") followed by its localized `label` as
|
|
12
|
+
* clickable text inside the banner. Each press is the owner's to handle (undo
|
|
13
|
+
* the reported change, then unmount the toast). The banner surface stays
|
|
14
|
+
* click-through — only the action text takes the pointer — and a fully faded
|
|
15
|
+
* banner takes no input at all.
|
|
16
|
+
*
|
|
17
|
+
* With an unchanged holdMs, a parent rerender does not extend the lifetime:
|
|
18
|
+
* the completion call reaches the latest onDone handler.
|
|
19
|
+
*
|
|
10
20
|
* The hold is the owner's to set, because how long a banner has to stay
|
|
11
21
|
* depends on how much there is to read: a one-line limit lands in the default
|
|
12
22
|
* window, while a failure that names what broke does not. One value drives
|
|
@@ -18,6 +28,9 @@ import type { ReactNode } from 'react';
|
|
|
18
28
|
* under `tone="success"`, which brings its own glyph.
|
|
19
29
|
* @param props.tone - 'success' renders the success check as the leading
|
|
20
30
|
* glyph; omitted, the icon seat keeps its warning tint.
|
|
31
|
+
* @param props.actions - optional inline actions continuing the sentence;
|
|
32
|
+
* each renders its plain-text `prefix` followed by its localized `label`
|
|
33
|
+
* as clickable text flowing after `text` as one sentence.
|
|
21
34
|
* @param props.holdMs - full-opacity hold before the fade; defaults to 3000.
|
|
22
35
|
* @param props.anchor - optional element whose horizontal center the banner
|
|
23
36
|
* follows (e.g. the composer card, so the banner centers over the chat column
|
|
@@ -25,12 +38,17 @@ import type { ReactNode } from 'react';
|
|
|
25
38
|
* @param props.onDone - called once the fade completes; unmount the toast here.
|
|
26
39
|
* @returns the floating banner.
|
|
27
40
|
*/
|
|
28
|
-
export declare function Toast({ text, icon, tone, anchor, holdMs, onDone }: {
|
|
41
|
+
export declare function Toast({ text, icon, tone, anchor, holdMs, actions, onDone }: {
|
|
29
42
|
text: string;
|
|
30
43
|
icon?: ReactNode;
|
|
31
44
|
tone?: 'success';
|
|
32
45
|
anchor?: HTMLElement | null;
|
|
33
46
|
holdMs?: number;
|
|
47
|
+
actions?: readonly {
|
|
48
|
+
label: string;
|
|
49
|
+
prefix?: string;
|
|
50
|
+
onClick: () => void;
|
|
51
|
+
}[];
|
|
34
52
|
onDone: () => void;
|
|
35
53
|
}): import("react").ReactPortal;
|
|
36
54
|
//# sourceMappingURL=Toast.d.ts.map
|
package/lib/types/Tooltip.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Anchor-preserving tooltips; an optional body portal escapes clipping containers and stacking contexts that cap the bubble's z-index. */
|
|
2
|
-
import type { FocusEventHandler, MouseEventHandler, ReactElement, Ref } from 'react';
|
|
2
|
+
import type { FocusEventHandler, MouseEventHandler, PointerEventHandler, ReactElement, Ref } from 'react';
|
|
3
3
|
import { type TooltipSide } from './tooltip-placement.ts';
|
|
4
4
|
export type { TooltipSide } from './tooltip-placement.ts';
|
|
5
5
|
/**
|
|
@@ -11,8 +11,9 @@ export declare const TooltipSuppression: import("react").Context<((suppressed: b
|
|
|
11
11
|
interface AnchorProps {
|
|
12
12
|
'aria-describedby'?: string | undefined;
|
|
13
13
|
ref?: Ref<HTMLElement> | undefined;
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
onPointerEnter?: PointerEventHandler | undefined;
|
|
15
|
+
onPointerLeave?: PointerEventHandler | undefined;
|
|
16
|
+
onPointerDown?: PointerEventHandler | undefined;
|
|
16
17
|
onClick?: MouseEventHandler | undefined;
|
|
17
18
|
onFocus?: FocusEventHandler | undefined;
|
|
18
19
|
onBlur?: FocusEventHandler | undefined;
|
|
@@ -37,17 +38,20 @@ type TooltipLabel = string | (() => string);
|
|
|
37
38
|
* toggling never remounts it (which would cut its CSS transitions).
|
|
38
39
|
* @param props.maxWidth - bubble width cap in pixels, for labels long enough that the default
|
|
39
40
|
* half-viewport cap would render a slab wider than the surface the anchor sits on; always bounded by viewport margins.
|
|
40
|
-
* @param props.openOnClick - clicking also pins the bubble for reading; another click, Escape,
|
|
41
|
+
* @param props.openOnClick - clicking or tapping also pins the bubble for reading; another click, Escape,
|
|
41
42
|
* Tab, or an outside pointerdown dismisses it. Defaults to false for ordinary action tooltips.
|
|
43
|
+
* @param props.onlyWhenClipped - show the bubble only when the anchor or an HTML element inside it
|
|
44
|
+
* overflows horizontally, measured when the bubble is about to show; for labels that repeat
|
|
45
|
+
* text an ellipsis may cut off. Defaults to false.
|
|
42
46
|
* @param props.children - a single anchor element; its own ref (callback or object) is forwarded alongside the tooltip's.
|
|
43
|
-
* An anchor that accepts no ref still positions the bubble: a raise records the element the event ran on.
|
|
44
47
|
* @returns the cloned anchor plus a fixed-position bubble, optionally portaled to the body.
|
|
45
48
|
* The bubble stays hidden until ResizeObserver supplies its size for viewport fitting; clicking the
|
|
46
49
|
* anchor dismisses the bubble unless openOnClick is enabled, and focus arriving after a pointer
|
|
47
|
-
* interaction (a closing menu refocusing its trigger) never raises it.
|
|
48
|
-
*
|
|
50
|
+
* interaction (a closing menu refocusing its trigger) never raises it. Touch cannot trigger hover
|
|
51
|
+
* tooltips; tapping still invokes the child's action and can open an openOnClick explanation.
|
|
52
|
+
* When no side fits, the viewport-bounded fallback may overlap the anchor; oversized content is scrollable when pinned.
|
|
49
53
|
*/
|
|
50
|
-
export declare function Tooltip({ label, shortcutKeys, side, align, delayMs, focusDelayMs, gap, disabled, portal, maxWidth, openOnClick, children }: {
|
|
54
|
+
export declare function Tooltip({ label, shortcutKeys, side, align, delayMs, focusDelayMs, gap, disabled, portal, maxWidth, openOnClick, onlyWhenClipped, children }: {
|
|
51
55
|
label: TooltipLabel;
|
|
52
56
|
shortcutKeys?: readonly string[] | undefined;
|
|
53
57
|
side?: TooltipSide;
|
|
@@ -59,6 +63,7 @@ export declare function Tooltip({ label, shortcutKeys, side, align, delayMs, foc
|
|
|
59
63
|
portal?: boolean;
|
|
60
64
|
maxWidth?: number;
|
|
61
65
|
openOnClick?: boolean;
|
|
66
|
+
onlyWhenClipped?: boolean;
|
|
62
67
|
children: ReactElement<AnchorProps>;
|
|
63
68
|
}): import("react").JSX.Element;
|
|
64
69
|
//# sourceMappingURL=Tooltip.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Shared user-message background, typography, and content inset. */
|
|
2
|
+
import type { ComponentPropsWithoutRef } from 'react';
|
|
3
|
+
/** Native div attributes for user-authored message content. */
|
|
4
|
+
export type UserMessageBubbleProps = ComponentPropsWithoutRef<'div'>;
|
|
5
|
+
/**
|
|
6
|
+
* Render user-style message content without row placement or actions.
|
|
7
|
+
* @param props - Native div attributes and the caller-owned content.
|
|
8
|
+
* @returns A theme-aware message surface that wraps its content.
|
|
9
|
+
*/
|
|
10
|
+
export declare function UserMessageBubble({ className, ...props }: UserMessageBubbleProps): import("react").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=UserMessageBubble.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type HighlightSpan } from './markdown/highlight.ts';
|
|
2
|
+
export { CODE_HIGHLIGHT_EXTENSIONS, languageForPath } from '@qilin-agent/util-code-language';
|
|
3
|
+
/** Highlight one source fragment into one token list per line. */
|
|
4
|
+
export type CodeHighlighter = (code: string) => HighlightSpan[][] | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Bind the shared lazy highlighter to one language and refresh after its grammar loads.
|
|
7
|
+
* @param language - grammar hint selected from the source filename.
|
|
8
|
+
* @returns a stable fragment highlighter; unknown and loading grammars return `undefined` for plain-text fallback.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useCodeHighlighter(language: string | undefined): CodeHighlighter;
|
|
11
|
+
export type { HighlightSpan };
|
|
12
|
+
//# sourceMappingURL=code-highlighting.d.ts.map
|
package/lib/types/focus.d.ts
CHANGED
|
@@ -6,4 +6,12 @@
|
|
|
6
6
|
* @param options - browser focus options, including scroll preservation.
|
|
7
7
|
*/
|
|
8
8
|
export declare function focusWithoutRing(element: HTMLElement, options?: FocusOptions): void;
|
|
9
|
+
/**
|
|
10
|
+
* Whether this browser runs on a touch-first mobile device.
|
|
11
|
+
*
|
|
12
|
+
* The answer is cached, so a caller must not expect it to follow a viewport
|
|
13
|
+
* resize. It drives input-shape choices only; layout reacts to container width.
|
|
14
|
+
* @returns `true` on a mobile browser, `false` on a desktop one.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isMobileDevice(): boolean;
|
|
9
17
|
//# sourceMappingURL=focus.d.ts.map
|
|
@@ -178,6 +178,10 @@ export declare const IconPaperclipOutlineMedium: (props: IconProps) => import("r
|
|
|
178
178
|
export declare const IconLoadingOutlineRegular: (props: IconProps) => import("react").JSX.Element;
|
|
179
179
|
/** Medium IconLoadingOutline artwork with a 1.3px stroke. */
|
|
180
180
|
export declare const IconLoadingOutlineMedium: (props: IconProps) => import("react").JSX.Element;
|
|
181
|
+
/** Regular one-pixel IconSaveOutline artwork. */
|
|
182
|
+
export declare const IconSaveOutlineRegular: (props: IconProps) => import("react").JSX.Element;
|
|
183
|
+
/** Medium IconSaveOutline artwork with a 1.3px stroke. */
|
|
184
|
+
export declare const IconSaveOutlineMedium: (props: IconProps) => import("react").JSX.Element;
|
|
181
185
|
/** Regular one-pixel IconDownloadOutline artwork. */
|
|
182
186
|
export declare const IconDownloadOutlineRegular: (props: IconProps) => import("react").JSX.Element;
|
|
183
187
|
/** Medium IconDownloadOutline artwork with a 1.3px stroke. */
|
|
@@ -270,6 +274,10 @@ export declare const IconQueueOutlineMedium: (props: IconProps) => import("react
|
|
|
270
274
|
export declare const IconChecklistOutlineRegular: (props: IconProps) => import("react").JSX.Element;
|
|
271
275
|
/** Medium IconChecklistOutline artwork with a 1.3px stroke. */
|
|
272
276
|
export declare const IconChecklistOutlineMedium: (props: IconProps) => import("react").JSX.Element;
|
|
277
|
+
/** Regular one-pixel IconDragHandleOutline artwork. */
|
|
278
|
+
export declare const IconDragHandleOutlineRegular: (props: IconProps) => import("react").JSX.Element;
|
|
279
|
+
/** Medium IconDragHandleOutline artwork with a 1.3px stroke. */
|
|
280
|
+
export declare const IconDragHandleOutlineMedium: (props: IconProps) => import("react").JSX.Element;
|
|
273
281
|
/** Regular one-pixel IconListPenOutline artwork. */
|
|
274
282
|
export declare const IconListPenOutlineRegular: (props: IconProps) => import("react").JSX.Element;
|
|
275
283
|
/** Medium IconListPenOutline artwork with a 1.3px stroke. */
|
|
@@ -38,6 +38,7 @@ export declare const BrowseOutlineArtwork: ({ size, className, strokeWidth }: We
|
|
|
38
38
|
* @param props - Size, optional CSS class, and inherited stroke width.
|
|
39
39
|
* @returns The decorative SVG artwork.
|
|
40
40
|
*/
|
|
41
|
+
export declare const DragHandleOutlineArtwork: ({ size, className, strokeWidth }: WeightedArtworkProps) => import("react").JSX.Element;
|
|
41
42
|
export declare const FolderCloseArtwork: ({ size, className, strokeWidth }: WeightedArtworkProps) => import("react").JSX.Element;
|
|
42
43
|
export {};
|
|
43
44
|
//# sourceMappingURL=shared-artwork.d.ts.map
|