@qilin-agent/client-ui-primitives 0.0.0-stage → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +61 -0
  3. package/README.md +187 -2
  4. package/README.zh.md +188 -0
  5. package/lib/Button.module.css +79 -0
  6. package/lib/Checkbox.module.css +28 -0
  7. package/lib/CommandText.module.css +12 -0
  8. package/lib/ConnectionIndicator.module.css +123 -0
  9. package/lib/DiffBlock.module.css +109 -0
  10. package/lib/DisclosureRow.module.css +84 -0
  11. package/lib/FileTypeIcon.module.css +50 -0
  12. package/lib/HoverCard.module.css +70 -0
  13. package/lib/ImageLightbox.module.css +48 -0
  14. package/lib/ImagePreview.module.css +24 -0
  15. package/lib/Input.module.css +38 -0
  16. package/lib/JsonTree.module.css +345 -0
  17. package/lib/Menu.module.css +274 -0
  18. package/lib/MenuGroup.module.css +37 -0
  19. package/lib/MenuSurface.module.css +49 -0
  20. package/lib/Modal.module.css +103 -0
  21. package/lib/OnboardingSurface.module.css +29 -0
  22. package/lib/PathLabel.module.css +28 -0
  23. package/lib/Pill.module.css +27 -0
  24. package/lib/ReadBlock.module.css +111 -0
  25. package/lib/RiskConfirmation.module.css +73 -0
  26. package/lib/SearchBlock.module.css +112 -0
  27. package/lib/SegmentedControl.module.css +76 -0
  28. package/lib/ShortcutKeys.module.css +33 -0
  29. package/lib/StateDot.module.css +73 -0
  30. package/lib/Switch.module.css +50 -0
  31. package/lib/Tag.module.css +57 -0
  32. package/lib/TerminalBlock.module.css +205 -0
  33. package/lib/TextShimmer.module.css +88 -0
  34. package/lib/Toast.module.css +76 -0
  35. package/lib/Tooltip.module.css +52 -0
  36. package/lib/WebBlock.module.css +141 -0
  37. package/lib/index.js +10647 -0
  38. package/lib/markdown/CodeBlock.module.css +130 -0
  39. package/lib/markdown/JsonBlock.module.css +32 -0
  40. package/lib/markdown/MarkdownText.module.css +485 -0
  41. package/lib/markdown/mermaid.module.css +49 -0
  42. package/lib/settings-form/SettingsForm.module.css +53 -0
  43. package/lib/settings-form/fields.module.css +145 -0
  44. package/lib/types/Button.d.ts +18 -0
  45. package/lib/types/Checkbox.d.ts +20 -0
  46. package/lib/types/CodeFileIcon.d.ts +12 -0
  47. package/lib/types/CommandText.d.ts +16 -0
  48. package/lib/types/ConnectionIndicator.d.ts +26 -0
  49. package/lib/types/DiffBlock.d.ts +52 -0
  50. package/lib/types/DisclosureRow.d.ts +36 -0
  51. package/lib/types/FileTypeIcon.d.ts +43 -0
  52. package/lib/types/FoldToggle.d.ts +20 -0
  53. package/lib/types/HoverCard.d.ts +32 -0
  54. package/lib/types/ImageLightbox.d.ts +27 -0
  55. package/lib/types/ImagePreview.d.ts +12 -0
  56. package/lib/types/Input.d.ts +12 -0
  57. package/lib/types/JsonTree.d.ts +59 -0
  58. package/lib/types/LinkIcon.d.ts +49 -0
  59. package/lib/types/Menu.d.ts +133 -0
  60. package/lib/types/MenuGroup.d.ts +22 -0
  61. package/lib/types/MenuSurface.d.ts +16 -0
  62. package/lib/types/Modal.d.ts +44 -0
  63. package/lib/types/OnboardingSurface.d.ts +11 -0
  64. package/lib/types/PathLabel.d.ts +13 -0
  65. package/lib/types/Pill.d.ts +13 -0
  66. package/lib/types/QilinSeal.d.ts +18 -0
  67. package/lib/types/ReadBlock.d.ts +47 -0
  68. package/lib/types/ReferenceIcon.d.ts +16 -0
  69. package/lib/types/RiskConfirmation.d.ts +20 -0
  70. package/lib/types/SearchBlock.d.ts +72 -0
  71. package/lib/types/SegmentedControl.d.ts +35 -0
  72. package/lib/types/ShortcutKeys.d.ts +11 -0
  73. package/lib/types/SiteGlyph.d.ts +25 -0
  74. package/lib/types/StateDot.d.ts +18 -0
  75. package/lib/types/Switch.d.ts +20 -0
  76. package/lib/types/Tag.d.ts +32 -0
  77. package/lib/types/TerminalBlock.d.ts +68 -0
  78. package/lib/types/TextShimmer.d.ts +22 -0
  79. package/lib/types/Toast.d.ts +36 -0
  80. package/lib/types/Tooltip.d.ts +45 -0
  81. package/lib/types/WebBlock.d.ts +61 -0
  82. package/lib/types/ansi.d.ts +17 -0
  83. package/lib/types/clipboard.d.ts +9 -0
  84. package/lib/types/code-file-icon-artwork.d.ts +54 -0
  85. package/lib/types/code-file-types.d.ts +30 -0
  86. package/lib/types/darwin-desktop.d.ts +18 -0
  87. package/lib/types/file-size.d.ts +17 -0
  88. package/lib/types/focus.d.ts +9 -0
  89. package/lib/types/head-tail-cap.d.ts +23 -0
  90. package/lib/types/icons/index.d.ts +211 -0
  91. package/lib/types/icons/props.d.ts +9 -0
  92. package/lib/types/index.d.ts +92 -0
  93. package/lib/types/input-modality.d.ts +19 -0
  94. package/lib/types/keyboard-composition.d.ts +11 -0
  95. package/lib/types/markdown/CodeBlock.d.ts +30 -0
  96. package/lib/types/markdown/JsonBlock.d.ts +8 -0
  97. package/lib/types/markdown/MarkdownDelegate.d.ts +46 -0
  98. package/lib/types/markdown/MarkdownText.d.ts +54 -0
  99. package/lib/types/markdown/cjkFriendlyStrong.d.ts +9 -0
  100. package/lib/types/markdown/file-link.d.ts +13 -0
  101. package/lib/types/markdown/highlight.d.ts +142 -0
  102. package/lib/types/markdown/incremental.d.ts +80 -0
  103. package/lib/types/markdown/katex.d.ts +27 -0
  104. package/lib/types/markdown/local-image-syntax.d.ts +10 -0
  105. package/lib/types/markdown/mathCompatibility.d.ts +11 -0
  106. package/lib/types/markdown/mermaid.d.ts +39 -0
  107. package/lib/types/markdown/parse.d.ts +25 -0
  108. package/lib/types/markdown/plain-text.d.ts +22 -0
  109. package/lib/types/markdown/render.d.ts +158 -0
  110. package/lib/types/markdown/useViewportHighlighting.d.ts +11 -0
  111. package/lib/types/overlay-top-margin.d.ts +8 -0
  112. package/lib/types/pointer-grace.d.ts +22 -0
  113. package/lib/types/rank-by-name.d.ts +22 -0
  114. package/lib/types/relative-time.d.ts +23 -0
  115. package/lib/types/seal-geometry.d.ts +27 -0
  116. package/lib/types/seal-glyphs.d.ts +9 -0
  117. package/lib/types/settings-form/SettingsForm.d.ts +46 -0
  118. package/lib/types/settings-form/fields.d.ts +70 -0
  119. package/lib/types/settings-form/form-model.d.ts +214 -0
  120. package/lib/types/use-copy-feedback.d.ts +14 -0
  121. package/lib/types/useAnchoredMaxHeight.d.ts +11 -0
  122. package/lib/types/useAnchoredPosition.d.ts +34 -0
  123. package/lib/types/useDismissOnOutsidePointer.d.ts +11 -0
  124. package/lib/types/useModalLayer.d.ts +27 -0
  125. package/lib/types/user-text.d.ts +37 -0
  126. package/lib/user-text.module.css +43 -0
  127. package/package.json +63 -3
@@ -0,0 +1,142 @@
1
+ /**
2
+ * The client's ONE syntax highlighter: a synchronous fine-grained shiki core
3
+ * (JavaScript regex engine — no oniguruma WASM, bundle-friendly) with an
4
+ * explicit grammar allowlist and a CSS-variables theme. Colors live in the
5
+ * theme package's token sheets as `--shiki-*` custom properties (light and
6
+ * dark blocks), never here — the repo's tokens-only styling rule.
7
+ *
8
+ * Only the three markdown-fence and `run_code` grammars (TypeScript, shell,
9
+ * JSON) load into the singleton at boot — the set every session renders. The
10
+ * read card's wider extension set (the file-extension language hints the read
11
+ * tool's `langFromPath` emits — `packages/fs/tool-fs`: python, rust, yaml,
12
+ * markup, …) is imported lazily and registered the first time such a language
13
+ * is requested, so a session that never opens a read card in one of those
14
+ * languages pays neither the ~1.6 MB of grammar modules nor their synchronous
15
+ * init. The first render of a lazy language falls back to plain text while its
16
+ * grammar loads, then {@link onGrammarLoaded} notifies subscribers to re-render
17
+ * with highlighting. An unknown or absent language falls back to plain text (no
18
+ * highlighting, still monospace) — never an error.
19
+ */
20
+ import type { CSSProperties } from 'react';
21
+ /**
22
+ * Whether a language hint can use the shared syntax highlighter.
23
+ * @param lang - Language hint from a code surface.
24
+ * @returns Whether the hint resolves to a supported grammar.
25
+ */
26
+ export declare function supportsHighlighting(lang: string | undefined): boolean;
27
+ /**
28
+ * Subscribe to lazy-grammar load completions; `listener` fires after a
29
+ * {@link LAZY_GRAMMARS} grammar finishes registering on the singleton, so a
30
+ * caller that rendered its plain fallback while the grammar loaded can
31
+ * re-highlight. Uses the `useSyncExternalStore` subscribe signature; pair it with
32
+ * {@link grammarLoadCount} as the snapshot. Returns an unsubscribe function.
33
+ * @param listener - invoked (no args) on each grammar-load completion.
34
+ * @returns a disposer that removes the listener.
35
+ */
36
+ export declare function subscribeGrammarLoaded(listener: () => void): () => void;
37
+ /**
38
+ * The lazy-grammar load counter — a value that changes on every load, so a
39
+ * `useSyncExternalStore` snapshot re-renders the subscriber when a grammar
40
+ * registers. Opaque: only its identity across renders matters.
41
+ * @returns the current load count.
42
+ */
43
+ export declare function grammarLoadCount(): number;
44
+ /**
45
+ * Highlight `code` into shiki's HTML (a single `<pre class="shiki">` tree)
46
+ * when `lang` maps to a registered grammar; `undefined` means the caller
47
+ * renders its plain fallback. A lazy grammar not yet loaded returns `undefined`
48
+ * for this call and loads in the background; subscribe with
49
+ * {@link onGrammarLoaded} to re-highlight once it registers.
50
+ * @param code - the source text.
51
+ * @param lang - the language hint (a markdown fence info string or a fixed caller id).
52
+ * @returns the highlighted HTML, or `undefined` for unknown or not-yet-loaded languages.
53
+ */
54
+ export declare function highlightToHtml(code: string, lang: string | undefined): string | undefined;
55
+ /**
56
+ * One highlighted run of a line: the text and the inline style shiki assigned
57
+ * it. The css-variables theme colors every run through a `--shiki-*` custom
58
+ * property, so `style.color` is always present; it is held as a style object
59
+ * rather than a bare color so a run spreads onto a `<span style>` uniformly.
60
+ */
61
+ export interface HighlightSpan {
62
+ text: string;
63
+ style: CSSProperties;
64
+ }
65
+ /**
66
+ * Incremental highlighter for one growing streaming fence. TextMate
67
+ * tokenization is line-based and forward-only — a line's tokens depend only on
68
+ * its own text and the grammar state entering it — so appended text never
69
+ * changes a completed line's tokens. The session caches the spans of every
70
+ * completed line together with the grammar state after them;
71
+ * {@link updateFrame} reports only newly completed lines plus the still-growing
72
+ * last line, while {@link update} materializes the complete compatibility
73
+ * result. Per-call tokenization cost therefore excludes the completed prefix,
74
+ * and the result equals a from-scratch tokenization of the same code.
75
+ * Non-append input and a change of resolved grammar reset the cache and
76
+ * re-tokenize fully, so any input stays correct.
77
+ */
78
+ export declare class StreamingHighlightSession {
79
+ /** Grammar id the cache was built with; a different resolution resets it. */
80
+ private resolved;
81
+ /** Newline-terminated source prefix covered by {@link spans}. */
82
+ private prefix;
83
+ /** Cached spans, one entry per completed line of {@link prefix}. */
84
+ private spans;
85
+ /** Grammar state after {@link prefix}; undefined = the grammar's initial state. */
86
+ private state;
87
+ private lastCode;
88
+ private lastLang;
89
+ private lastResult;
90
+ private generation;
91
+ private lastFrame;
92
+ private reset;
93
+ /** Tokenize `text` with `resolved`, resuming from the cached grammar state when one exists. */
94
+ private tokenize;
95
+ /**
96
+ * Tokenize one update as a delta for a retained renderer.
97
+ * @param code - the fence text accumulated so far.
98
+ * @param lang - the language hint.
99
+ * @returns Newly completed lines plus the current tail, or `undefined` for the plain arm.
100
+ */
101
+ updateFrame(code: string, lang: string | undefined): StreamingHighlightFrame | undefined;
102
+ /**
103
+ * Tokenize the fence's current text into per-line highlighted runs;
104
+ * `undefined` means the caller renders its plain fallback. Idempotent per
105
+ * (`code`, `lang`) input — repeated calls return the identical result array —
106
+ * and a retained line keeps its span-array identity across growing calls, so
107
+ * a React caller can reuse cached line elements. A lazy grammar not yet
108
+ * loaded returns `undefined` and loads in the background exactly as
109
+ * {@link highlightToHtml} does; the next call after it registers highlights.
110
+ * @param code - the fence text accumulated so far (display-trimmed, no synthetic trailing newline).
111
+ * @param lang - the language hint (a markdown fence info string).
112
+ * @returns one entry per line of `code` (each an array of runs), or `undefined` for unknown or not-yet-loaded languages.
113
+ */
114
+ update(code: string, lang: string | undefined): readonly HighlightSpan[][] | undefined;
115
+ }
116
+ /** One retained-renderer update from {@link StreamingHighlightSession.updateFrame}. */
117
+ export interface StreamingHighlightFrame {
118
+ /** Changes whenever prior completed lines must be discarded. */
119
+ readonly generation: number;
120
+ /** Completed lines added since the preceding frame in this generation. */
121
+ readonly appended: readonly HighlightSpan[][];
122
+ /** The still-growing final line or lines, replaced by the next frame. */
123
+ readonly tail: readonly HighlightSpan[][];
124
+ }
125
+ /**
126
+ * Tokenize `code` into per-line highlighted runs when `lang` maps to a
127
+ * registered grammar; `undefined` means the caller renders its plain fallback.
128
+ * A line-numbered view needs the token runs split per line (one gutter number
129
+ * per line), which the single-`<pre>` {@link highlightToHtml} does not expose,
130
+ * so this returns shiki's own 2D line/token structure narrowed to what a run
131
+ * renders. Each run's color is a `--shiki-*` custom property, keeping token
132
+ * colors on the theme package's sheets exactly as the HTML path does; the
133
+ * markup font-style bits the theme lets through (bold/italic/underline in
134
+ * markdown scopes) are dropped — the line-numbered file view renders
135
+ * color-only runs. The trailing newline shiki appends as a final empty line
136
+ * is dropped so the run count matches the caller's own line array.
137
+ * @param code - the source text.
138
+ * @param lang - the language hint (a file-extension-derived language id).
139
+ * @returns one entry per source line (each an array of runs), or `undefined` for unknown or not-yet-loaded languages.
140
+ */
141
+ export declare function highlightLines(code: string, lang: string | undefined): HighlightSpan[][] | undefined;
142
+ //# sourceMappingURL=highlight.d.ts.map
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Incremental block-level markdown parsing for an append-only text stream.
3
+ *
4
+ * Re-parsing the whole accumulated document on every streaming chunk is
5
+ * quadratic in the final reply length. CommonMark block parsing is line-based
6
+ * and appended text can only reshape the parse frontier — the last top-level
7
+ * block (a paragraph becoming a setext heading or a table, or a list
8
+ * continuing after a blank line) — so earlier blocks are final. This parser
9
+ * therefore freezes all but the trailing {@link UNSTABLE_TAIL_BLOCKS} blocks
10
+ * and re-parses only the source tail behind them. A final unclosed top-level
11
+ * fence cannot freeze as a block, so its completed content lines use a second
12
+ * frontier: only the last completed line and current partial line return
13
+ * through the caller's grammar. Each source region is therefore parsed a
14
+ * bounded number of times over the stream instead of once per chunk.
15
+ *
16
+ * The block freeze boundary comes from the parser's own `position` offsets.
17
+ * The cut sits at the *end offset* of the last frozen block (not the next
18
+ * block's start): a following block's start offset excludes up to three spaces
19
+ * of insignificant leading indentation, which is harmless to drop, but
20
+ * cutting at the previous end also keeps the inter-block blank lines in the
21
+ * tail so the sliced source stays verbatim. Fence scanning only recognizes a
22
+ * parser-confirmed code node and closing delimiter; ambiguous input returns to
23
+ * the normal tail parse.
24
+ *
25
+ * Known deviation, shared with any prefix-freeze scheme: micromark resolves
26
+ * reference-style links and footnotes document-wide at parse time, so a
27
+ * reference whose definition lands on the other side of the freeze boundary
28
+ * renders literally until the settled full parse self-heals it.
29
+ */
30
+ import type { Root, RootContent } from 'mdast';
31
+ /** A top-level mdast block plus a render key that is stable across chunks. */
32
+ export interface PositionedBlock {
33
+ /** The parsed block. Positions inside it are relative to its parse slice. */
34
+ readonly node: RootContent;
35
+ /**
36
+ * The block's start offset in the full source text. Stable from the frame
37
+ * a block first appears through freezing, so React reconciles rather than
38
+ * remounts when a block crosses the freeze boundary.
39
+ */
40
+ readonly key: number;
41
+ }
42
+ /** One {@link IncrementalMarkdownParser.update} result. */
43
+ export interface IncrementalBlocks {
44
+ /** Blocks that can no longer change; grows monotonically per generation. */
45
+ readonly frozen: readonly PositionedBlock[];
46
+ /** The re-parsed unstable tail (at most {@link UNSTABLE_TAIL_BLOCKS} blocks plus growth). */
47
+ readonly tail: readonly PositionedBlock[];
48
+ /** Bumped whenever non-append input discards the frozen prefix; callers drop caches keyed on it. */
49
+ readonly generation: number;
50
+ }
51
+ /**
52
+ * Append-only incremental parser over a caller-supplied grammar. One instance
53
+ * accumulates one streaming document; non-append input resets it.
54
+ */
55
+ export declare class IncrementalMarkdownParser {
56
+ private readonly parse;
57
+ private prevText;
58
+ private tailStart;
59
+ private frozen;
60
+ private generation;
61
+ private cached;
62
+ private openFence;
63
+ /** @param parse - Grammar shared with whatever renders the blocks, so boundaries agree. */
64
+ constructor(parse: (text: string) => Root);
65
+ /** Parse one unclosed-fence content slice through the caller's grammar. */
66
+ private fenceValue;
67
+ /** Recognize the parsed tail's final unclosed fence and prepare its incremental content frontier. */
68
+ private openFenceState;
69
+ /** Extend a recognized unclosed fence without parsing its completed content prefix again. */
70
+ private updateOpenFence;
71
+ /**
72
+ * Fold the current accumulated text and return the frozen/tail split.
73
+ * Idempotent for identical input (the previous result is returned as-is),
74
+ * so callers may invoke it from render paths that re-execute.
75
+ * @param text - The full accumulated markdown source.
76
+ * @returns Frozen and tail blocks with stream-stable render keys.
77
+ */
78
+ update(text: string): IncrementalBlocks;
79
+ }
80
+ //# sourceMappingURL=incremental.d.ts.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * TeX-to-React via KaTeX, replicating the rehype-katex pipeline this renderer
3
+ * replaced: the same three-arm error chain (strict render, `strict: 'ignore'`
4
+ * retry, error span) and a DOM-identical element tree, so settled math keeps
5
+ * its exact markup. KaTeX emits an HTML string; the browser's own HTML parser
6
+ * (`DOMParser`, applying the spec's SVG/MathML foreign-content attribute
7
+ * adjustments KaTeX output relies on) turns it into a tree this module maps
8
+ * onto React elements — KaTeX output is a static span/MathML/SVG vocabulary
9
+ * with no raw user HTML, the same trust shiki's tree gets in CodeBlock.
10
+ *
11
+ * React 18 has no MathML support, so the `.katex-mathml` subtree's elements
12
+ * land in the HTML namespace — exactly as they did under the replaced
13
+ * hast-util-to-jsx-runtime pipeline. The visual arm is the `.katex-html`
14
+ * span tree; the MathML arm serves assistive technology, which reads it by
15
+ * tag name regardless of namespace.
16
+ */
17
+ import type { ReactNode } from 'react';
18
+ /**
19
+ * Render TeX source to React elements through KaTeX.
20
+ * @param value - The TeX source (math node value; fenced `math` blocks append
21
+ * their trailing newline to match the replaced pipeline's text extraction).
22
+ * @param displayMode - Display (block) versus inline rendering.
23
+ * @returns KaTeX's element tree, or the error span when the source does not
24
+ * parse (colored with KaTeX's stock `errorColor`, matching rehype-katex).
25
+ */
26
+ export declare function renderTexToReact(value: string, displayMode: boolean): ReactNode;
27
+ //# sourceMappingURL=katex.d.ts.map
@@ -0,0 +1,10 @@
1
+ /** Recover standalone local image references with bare spaces without changing code or source offsets. */
2
+ import type { Root } from 'mdast';
3
+ /**
4
+ * Recover only unambiguous, unescaped image-only paragraphs containing a local path with spaces.
5
+ * @param root - Parsed Markdown tree, modified in place.
6
+ * @param source - Original source used to distinguish authored syntax from escaped examples.
7
+ * @returns The same root with recovered image nodes.
8
+ */
9
+ export declare function recoverLocalImages(root: Root, source: string): Root;
10
+ //# sourceMappingURL=local-image-syntax.d.ts.map
@@ -0,0 +1,11 @@
1
+ /** Extend upstream dollar-only math syntax with TeX delimiters while reusing its token vocabulary. */
2
+ import type { Extension } from 'micromark-util-types';
3
+ /**
4
+ * TeX backslash delimiters and same-line display-dollar blocks as a micromark
5
+ * syntax extension reusing `micromark-extension-math`'s token vocabulary; the
6
+ * caller must also register `math()` on the same parse so the emitted tokens
7
+ * compile to standard math nodes.
8
+ * @returns The micromark syntax extension.
9
+ */
10
+ export declare function mathCompatibility(): Extension;
11
+ //# sourceMappingURL=mathCompatibility.d.ts.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Mermaid diagram rendering for markdown fences: a ```mermaid fence renders
3
+ * as a static SVG diagram through the `mermaid` library, loaded lazily on
4
+ * the first diagram (the library and its graph deps are heavy; the Vite
5
+ * build splits the dynamic import into its own chunk).
6
+ *
7
+ * Security posture (mirrors the vendored sidebar implementation this was
8
+ * absorbed from): `securityLevel: 'strict'` (labels escaped, no raw-HTML
9
+ * foreignObject), `htmlLabels: false` keeps node text as real SVG text,
10
+ * `bindFunctions` is never applied (static diagrams), the emitted SVG is
11
+ * sanitized (allowlist strip of scripts, event handlers, foreignObject,
12
+ * and external references) before it reaches `dangerouslySetInnerHTML`,
13
+ * and `suppressErrorRendering` keeps mermaid's error dump out of the
14
+ * document body. A failed render falls back to the fenced source block.
15
+ */
16
+ import { type ReactNode } from 'react';
17
+ /** Strip everything the diagram contract does not allow from an emitted SVG.
18
+ * @param svg - the library's emitted SVG document string.
19
+ * @returns the sanitized SVG string.
20
+ */
21
+ export declare function sanitizeMermaidSvg(svg: string): string;
22
+ /**
23
+ * Render one mermaid fence as a static sanitized SVG diagram.
24
+ * @param props - the fenced diagram source and the code-block labels for the fallback.
25
+ * @returns the diagram, its loading state, or the fenced source fallback.
26
+ */
27
+ export interface MermaidDiagramProps {
28
+ /** The fenced diagram source between the fences (info string stripped). */
29
+ readonly code: string;
30
+ /** Copy-control labels for the fallback source block. */
31
+ readonly copyLabel: string;
32
+ readonly copiedLabel: string;
33
+ /** Alt text naming the on-page diagram stage. */
34
+ readonly diagramLabel: string;
35
+ /** Alt text naming the enlarged overlay copy. */
36
+ readonly enlargedLabel: string;
37
+ }
38
+ export declare function MermaidDiagram({ code, copyLabel, copiedLabel, diagramLabel, enlargedLabel }: MermaidDiagramProps): ReactNode;
39
+ //# sourceMappingURL=mermaid.d.ts.map
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The markdown renderer's two mdast grammars, one per rendering arm. Each
3
+ * arm is internally consistent — the incremental tail parses, the one-shot
4
+ * parses, and the plain-text projection of a given grammar always agree on
5
+ * where blocks start and end — and the settled grammar is the streaming one
6
+ * plus the math extensions, so the arms differ only where TeX delimiters
7
+ * begin a math construct (a `$$` block is a paragraph while streaming and a
8
+ * math block once settled, by design).
9
+ */
10
+ import type { Root } from 'mdast';
11
+ /**
12
+ * Parse GFM markdown (the streaming arm's grammar: no math, so incomplete
13
+ * TeX never flashes KaTeX errors mid-stream).
14
+ * @param text - Markdown source.
15
+ * @returns The mdast root.
16
+ */
17
+ export declare function parseGfm(text: string): Root;
18
+ /**
19
+ * Parse GFM markdown plus TeX math with the compatibility delimiters
20
+ * (the settled arm's grammar).
21
+ * @param text - Markdown source.
22
+ * @returns The mdast root.
23
+ */
24
+ export declare function parseGfmWithMath(text: string): Root;
25
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Markdown-to-plain-text projection for compact summaries and labels.
3
+ * Parsing shares the renderer's streaming GFM grammar ({@link parseGfm}), so
4
+ * the projection strips exactly the markup the renderer would draw; raw HTML
5
+ * stays literal, links keep their labels, images keep alt text, and code
6
+ * keeps its source text.
7
+ */
8
+ /** Amount of parsed Markdown content returned by the extractor. */
9
+ export type MarkdownPlainTextMode = 'all' | 'first-line' | 'first-paragraph';
10
+ /** Options for {@link extractMarkdownPlainText}. */
11
+ export interface MarkdownPlainTextOptions {
12
+ /** Projection boundary; defaults to the complete document. */
13
+ mode?: MarkdownPlainTextMode;
14
+ }
15
+ /**
16
+ * Parse GFM Markdown, remove its presentation markup, and preserve raw HTML literally.
17
+ * @param markdown - Markdown source.
18
+ * @param options - Optional extraction boundary.
19
+ * @returns Plain text for the whole document, first visible line, or first semantic paragraph.
20
+ */
21
+ export declare function extractMarkdownPlainText(markdown: string, options?: MarkdownPlainTextOptions): string;
22
+ //# sourceMappingURL=plain-text.d.ts.map
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Direct mdast→React markdown renderer. Replaces the react-markdown /
3
+ * remark-rehype pipeline with one switch over parsed nodes so streaming can
4
+ * cache frozen blocks as React elements; the rendered DOM is pinned
5
+ * byte-for-byte by `tests/fixtures/markdown-dom` and must not drift.
6
+ *
7
+ * External link and image destinations pass a protocol allowlist; settled
8
+ * local file links use an explicit owner callback. Images additionally require
9
+ * absolute HTTP(S), raw HTML renders as literal text (no HTML enters the
10
+ * DOM), and KaTeX runs without trusted commands. Fragment-anchor URLs fail
11
+ * the allowlist, so footnote references and back-references render as plain
12
+ * text rather than in-page links.
13
+ *
14
+ * Merge-extensible node unions fall through the documented default (render
15
+ * nothing) rather than ending in assertNever: grammars registered elsewhere
16
+ * may add node types this renderer has no mapping for.
17
+ */
18
+ import type { ReactNode } from 'react';
19
+ import type * as Md from 'mdast';
20
+ import type { PositionedBlock } from './incremental.ts';
21
+ /** Copy-button labels forwarded to fence CodeBlocks (this package is cordis-free, so copy arrives via props). */
22
+ export interface MarkdownCodeLabels {
23
+ /** Copy-button idle label. */
24
+ copyLabel: string;
25
+ /** Copy-button label during the post-copy confirmation window. */
26
+ copiedLabel: string;
27
+ }
28
+ /** Localized alt text for a rendered Mermaid diagram. */
29
+ export interface MarkdownMermaidLabels {
30
+ /** Alt text naming the on-page diagram stage. */
31
+ diagramLabel: string;
32
+ /** Alt text naming the enlarged overlay copy. */
33
+ enlargedLabel: string;
34
+ }
35
+ /** Localized chrome for a Markdown document. */
36
+ export interface MarkdownLabels {
37
+ code: MarkdownCodeLabels;
38
+ mermaid: MarkdownMermaidLabels;
39
+ footnotes: string;
40
+ }
41
+ /** Link/image reference targets collected from a document (first definition per identifier wins, as in CommonMark). */
42
+ export interface ReferenceTargets {
43
+ /** Link/image definitions keyed by upper-cased identifier. */
44
+ definitions: Map<string, Md.Definition>;
45
+ /** Footnote definitions keyed by upper-cased identifier. */
46
+ footnotes: Map<string, Md.FootnoteDefinition>;
47
+ }
48
+ /**
49
+ * Create an empty {@link ReferenceTargets}.
50
+ * @returns Fresh empty maps.
51
+ */
52
+ export declare function createReferenceTargets(): ReferenceTargets;
53
+ /**
54
+ * Record every definition and footnote definition under `nodes` into
55
+ * `targets`, depth-first, keeping the first definition per identifier.
56
+ * @param nodes - Subtrees to walk (top-level blocks or any nested children).
57
+ * @param targets - Accumulator, typically shared across incremental segments.
58
+ */
59
+ export declare function collectReferenceTargets(nodes: readonly Md.RootContent[], targets: ReferenceTargets): void;
60
+ /**
61
+ * Local-path image vocabulary for image destinations: the owner maps an
62
+ * authored destination that fails the remote-URL allowlist (an absolute local
63
+ * file path, for example) to a displayable URL it can vouch for. Absent
64
+ * wherever no such vocabulary exists, authored local destinations keep their
65
+ * documented fallback (the image's alt text). Rewritten destinations must be
66
+ * absolute; the renderer re-checks their protocol before emitting them.
67
+ */
68
+ export interface MarkdownPathImages {
69
+ /**
70
+ * Resolve one authored image destination.
71
+ * @param value - The destination exactly as the markdown author wrote it.
72
+ * @returns A displayable absolute URL, or undefined when the destination
73
+ * names no displayable image — it then stays inert alt text.
74
+ */
75
+ resolve(value: string): string | undefined;
76
+ }
77
+ /**
78
+ * File-mention affordance for inline code: the owner resolves an authored
79
+ * token to the file it names, using its own vocabulary of real files — the
80
+ * renderer never guesses at what looks like a path.
81
+ */
82
+ export interface MarkdownFileMentions {
83
+ /**
84
+ * Resolve one inline-code token.
85
+ * @param value - The authored token, exactly as written.
86
+ * @returns The opener with its accessible label and full-path title, or
87
+ * undefined when the token names no known file — it then stays inert code.
88
+ */
89
+ resolve(value: string): {
90
+ open: () => void;
91
+ label: string;
92
+ title: string;
93
+ } | undefined;
94
+ }
95
+ /**
96
+ * One render pass's state: immutable options and targets plus the footnote
97
+ * numbering accumulated in document order while references render.
98
+ */
99
+ export interface MarkdownRenderContext {
100
+ /** Streaming arm: fences highlight incrementally as they grow; TeX (including ```math fences) stays literal until the settled pass. */
101
+ readonly streaming: boolean;
102
+ /** Localized fence copy-button labels. */
103
+ readonly labels: MarkdownLabels;
104
+ /** Inside a blockquote's children: tables there always fill the quote's width. */
105
+ readonly inBlockquote?: boolean;
106
+ /** Inline-code file mentions; absent wherever no opener vocabulary exists. */
107
+ readonly fileMentions: MarkdownFileMentions | undefined;
108
+ /** Local-path image vocabulary; absent wherever no rewriting owner exists. */
109
+ readonly pathImages: MarkdownPathImages | undefined;
110
+ /**
111
+ * Owner-supplied renderer for one authored raw-HTML run. Absent — the default
112
+ * — keeps the run as literal text, which is what every consumer that renders
113
+ * untrusted model output gets unless it installs a sanitizer of its own.
114
+ */
115
+ readonly html: MarkdownHtmlRenderer | undefined;
116
+ /** Inside an anchor's children: interactive mentions must not nest there. */
117
+ readonly inLink?: boolean;
118
+ /** Reference targets visible to this pass. */
119
+ readonly targets: ReferenceTargets;
120
+ /** Footnote identifiers in first-reference order; a footnote's number is its 1-based index here. */
121
+ readonly footnoteOrder: string[];
122
+ /** References rendered per identifier; drives the section's back-reference count. */
123
+ readonly footnoteCounts: Map<string, number>;
124
+ }
125
+ /**
126
+ * Owner-side renderer for authored raw HTML in a Markdown source.
127
+ * @param source - the raw HTML run exactly as the stream carried it.
128
+ * @returns the element to render in the run's place.
129
+ */
130
+ export type MarkdownHtmlRenderer = (source: string) => ReactNode;
131
+ /**
132
+ * Render top-level blocks. Nodes that render nothing (definitions, unmapped
133
+ * types) are dropped rather than kept as null placeholders, matching the
134
+ * replaced pipeline's child lists so separator newlines land identically.
135
+ * @param blocks - Blocks with their stream-stable render keys.
136
+ * @param context - The pass state; footnote numbering mutates in document order.
137
+ * @returns One React node per rendered block.
138
+ */
139
+ export declare function renderBlocks(blocks: readonly PositionedBlock[], context: MarkdownRenderContext): ReactNode[];
140
+ /**
141
+ * Interleave the newline text nodes the replaced pipeline emitted between
142
+ * block-level children. They are invisible between elements but coalesce
143
+ * into adjacent literal raw-HTML text, where the DOM parity fixtures pin
144
+ * them.
145
+ * @param elements - Rendered block children with empty renders already dropped.
146
+ * @param edges - Also emit the leading and trailing newline (hast's loose wrap).
147
+ * @returns The interleaved children.
148
+ */
149
+ export declare function wrapBlockChildren(elements: readonly ReactNode[], edges: boolean): ReactNode[];
150
+ /**
151
+ * Render the trailing footnote section for every footnote referenced during
152
+ * the pass, in first-reference order, with one plain-text back-reference
153
+ * marker per rendered reference.
154
+ * @param context - The pass state after all blocks rendered.
155
+ * @returns The section, or null when no referenced footnote has a definition.
156
+ */
157
+ export declare function renderFootnoteSection(context: MarkdownRenderContext): ReactNode | null;
158
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1,11 @@
1
+ import type { RefObject } from 'react';
2
+ /**
3
+ * Activate one supported code surface when it first intersects the viewport.
4
+ * Activation lasts for the component lifetime; browsers without
5
+ * IntersectionObserver activate immediately.
6
+ * @param target - Code surface whose plain rendering reserves its geometry.
7
+ * @param lang - Optional language hint.
8
+ * @returns Whether this component may build highlighted output.
9
+ */
10
+ export declare function useViewportHighlighting(target: RefObject<Element>, lang: string | undefined): boolean;
11
+ //# sourceMappingURL=useViewportHighlighting.d.ts.map
@@ -0,0 +1,8 @@
1
+ /** Shared viewport inset for overlays, derived from the desktop frame's reserved top strip. */
2
+ /**
3
+ * Resolve the top margin an overlay keeps from the viewport edge.
4
+ * @param min - the overlay's own viewport margin in px, used as the floor.
5
+ * @returns the larger of `min` and the frame clearance plus 20px; fullscreen keeps only the 20px gap.
6
+ */
7
+ export declare function overlayTopMargin(min: number): number;
8
+ //# sourceMappingURL=overlay-top-margin.d.ts.map
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Grace before a pointer-dismissed popup closes. Covers the anchor->popup gap
3
+ * (8px for HoverCard, 4px for Menu) at a hand's travel speed without leaving a
4
+ * popup lingering once the pointer has genuinely moved on.
5
+ */
6
+ export declare const POINTER_GRACE_MS = 200;
7
+ /** Cancelable delayed close for a pointer-dismissed popup. */
8
+ export interface PointerGrace {
9
+ /** Schedule the close {@link POINTER_GRACE_MS} from now, replacing any pending one. */
10
+ arm: () => void;
11
+ /** Abort a pending close (the pointer came back). */
12
+ cancel: () => void;
13
+ }
14
+ /**
15
+ * Delay a pointer-dismissed popup's close so the pointer can cross the gap
16
+ * between anchor and popup. A pending close is dropped on unmount.
17
+ * @param close - runs when the grace elapses with no re-entry; read at fire
18
+ * time, so callers may pass a fresh closure each render.
19
+ * @returns the {@link PointerGrace} handle.
20
+ */
21
+ export declare function usePointerGrace(close: () => void): PointerGrace;
22
+ //# sourceMappingURL=pointer-grace.d.ts.map
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Shared ranking for `/` menu candidates: the query must be a
3
+ * case-insensitive ordered subsequence of the candidate name or, when the
4
+ * candidate carries one, of its display label (a localized title). Prefix
5
+ * hits rank first, then the strongest alignment score over either key, then
6
+ * the source order of the input. Decision record:
7
+ * .agents/notes/archived/feature/2026-08-04-web-slash-command-fuzzy-discovery.md
8
+ */
9
+ /**
10
+ * Rank named items by a menu query.
11
+ * @param items - candidates in source order (a host catalog, then client
12
+ * contributions); an item's optional `label` is a second search key beside
13
+ * its name.
14
+ * @param rawQuery - the text typed after the trigger, matched case-insensitively.
15
+ * @returns the matching items: prefix hits first, then by alignment score,
16
+ * then in source order. The input list itself for an empty query.
17
+ */
18
+ export declare function rankByName<T extends {
19
+ readonly name: string;
20
+ readonly label?: string;
21
+ }>(items: readonly T[], rawQuery: string): readonly T[];
22
+ //# sourceMappingURL=rank-by-name.d.ts.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Compact relative-time bucketing shared by every surface that dates a
3
+ * session. Bucketing is here so two surfaces naming the same session agree;
4
+ * the words stay in each plugin's own dictionary, per locale-owned copy.
5
+ *
6
+ * @module @qilin-agent/client-ui-primitives/relative-time
7
+ */
8
+ /** Relative-time bucket of a dated row's trailing label. */
9
+ export type RelativeTimeUnit = 'now' | 'minutes' | 'hours' | 'days' | 'months' | 'years';
10
+ /** Structured relative time: the bucket plus its magnitude (0 for 'now'). */
11
+ export interface RelativeTime {
12
+ unit: RelativeTimeUnit;
13
+ n: number;
14
+ }
15
+ /**
16
+ * Compact relative time, as a structured bucket the renderer localizes
17
+ * ("now"/"5min"/"3h"/"2d"/"4mo"/"1y" in en).
18
+ * @param at - epoch ms of the dated moment.
19
+ * @param now - current epoch ms (injected for pure rendering).
20
+ * @returns the row's trailing time bucket and magnitude.
21
+ */
22
+ export declare function relativeTime(at: number, now: number): RelativeTime;
23
+ //# sourceMappingURL=relative-time.d.ts.map
@@ -0,0 +1,27 @@
1
+ /** Seal geometry: the cinnabar body, its gold hairline ring, and the two glyph cells. */
2
+ /** The seal body: a rounded square filling the viewBox. */
3
+ export declare const SEAL_BODY: {
4
+ readonly inset: 0;
5
+ readonly side: 24;
6
+ readonly radius: 5.2;
7
+ };
8
+ /** The gold hairline ring inside the body, close to its edge. */
9
+ export declare const SEAL_RING: {
10
+ readonly inset: 0.94;
11
+ readonly side: 22.13;
12
+ readonly radius: 4.31;
13
+ readonly stroke: 0.375;
14
+ };
15
+ /** The glyph cells: side by side and centered vertically in the body. */
16
+ export declare const SEAL_CELL: {
17
+ size: number;
18
+ top: number;
19
+ lefts: readonly [2.28, 12.12];
20
+ };
21
+ /**
22
+ * Placement transform for one glyph cell.
23
+ * @param left - left edge of the cell in viewBox units.
24
+ * @returns the transform placing the unit-box outline into that cell.
25
+ */
26
+ export declare function cellTransform(left: number): string;
27
+ //# sourceMappingURL=seal-geometry.d.ts.map