@deepseek-ai/dsh-client-ui-primitives 0.1.3-alpha.2 → 0.1.5-alpha.2

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.
@@ -8,11 +8,12 @@
8
8
  with the markdown 0.875 ladder without shrinking every other xs-13 use. */
9
9
  --dsl-code-block-banner-font: 11px/18px var(--dsw-font-family);
10
10
  --dsl-code-block-content-font: var(--dsw-font-markdown-code-block);
11
+ --dsl-code-block-background: var(--dsw-alias-markdown-code-block);
11
12
 
12
13
  position: relative;
13
14
  margin: 16px 0;
14
15
  color: var(--dsw-alias-label-primary);
15
- background: var(--dsw-alias-markdown-code-block);
16
+ background: var(--dsl-code-block-background);
16
17
  border-radius: var(--dsl-code-block-border-radius);
17
18
  }
18
19
 
@@ -75,7 +76,7 @@
75
76
  overflow-x: auto;
76
77
  white-space: pre-wrap;
77
78
  word-break: break-all;
78
- background: var(--dsw-alias-markdown-code-block);
79
+ background: var(--dsl-code-block-background);
79
80
  /* Bottom radii live on <pre>: overflow:hidden on .block would kill the
80
81
  sticky banner, and this opaque fill otherwise squares off the wrapper. */
81
82
  border-bottom-left-radius: var(--dsl-code-block-border-radius);
@@ -84,7 +85,7 @@
84
85
 
85
86
  /* Shiki inlines its theme background var; route it to the repo token. */
86
87
  .block :where(pre.shiki) {
87
- background: var(--dsw-alias-markdown-code-block) !important;
88
+ background: var(--dsl-code-block-background) !important;
88
89
  }
89
90
 
90
91
  .block :where(pre) code {
@@ -96,3 +97,28 @@
96
97
  .plain {
97
98
  color: var(--dsw-alias-label-primary);
98
99
  }
100
+
101
+ .numbered :where(pre) code {
102
+ display: block;
103
+ counter-reset: source-line;
104
+ white-space: normal;
105
+ }
106
+
107
+ .numbered :where(pre) code > :global(.line) {
108
+ position: relative;
109
+ display: block;
110
+ min-height: 1lh;
111
+ padding-inline-start: calc(var(--dsl-code-block-line-number-width) + 12px);
112
+ counter-increment: source-line;
113
+ white-space: var(--dsl-code-block-line-white-space, pre-wrap);
114
+ }
115
+
116
+ .numbered :where(pre) code > :global(.line)::before {
117
+ position: absolute;
118
+ inset-inline-start: 0;
119
+ width: var(--dsl-code-block-line-number-width);
120
+ color: var(--dsw-alias-label-tertiary);
121
+ text-align: end;
122
+ content: counter(source-line);
123
+ user-select: none;
124
+ }
@@ -0,0 +1,12 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { IconProps } from './icons/props.ts';
3
+ import type { CodeFileType } from './code-file-types.ts';
4
+ /**
5
+ * Render one full-color square code-file glyph from the embedded icon set.
6
+ * @param props - Detailed code type, optional size, and optional CSS class.
7
+ * @returns The selected decorative SVG with its identifying palette intact.
8
+ */
9
+ export declare function CodeFileIcon({ type, size, className }: IconProps & {
10
+ readonly type: CodeFileType;
11
+ }): ReactNode;
12
+ //# sourceMappingURL=CodeFileIcon.d.ts.map
@@ -0,0 +1,43 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type CodeFileType, type FileTypeProjectContext } from './code-file-types.ts';
3
+ import type { IconProps } from './icons/props.ts';
4
+ /** File categories with distinct 28px glyphs. */
5
+ export type FileType = CodeFileType | 'code' | 'excel' | 'folder' | 'html' | 'image' | 'markdown' | 'other' | 'pdf' | 'ppt' | 'video' | 'word';
6
+ /** Compatibility name for consumers that pass an already resolved category. */
7
+ export type FileTypeKind = FileType;
8
+ type ClassifiedFileType = Exclude<FileType, 'folder'>;
9
+ export type { CodeFileType, FileTypeProjectContext } from './code-file-types.ts';
10
+ /** Props for {@link FileTypeIcon}: either a path to classify or an already resolved kind. */
11
+ export type FileTypeIconProps = IconProps & ({
12
+ /** File path or name to classify. */
13
+ readonly path: string;
14
+ /** Optional project-file snapshot for context-sensitive code icons such as Flutter. */
15
+ readonly context?: FileTypeProjectContext | undefined;
16
+ } | {
17
+ /** Explicit category for callers that already resolved the file type. */
18
+ readonly kind: FileTypeKind;
19
+ });
20
+ /**
21
+ * Extract the final suffix from a file path without changing its case.
22
+ * A leading dot starts a suffix, while a missing or trailing dot returns an empty string.
23
+ * @param path - File path or basename using either path separator.
24
+ * @returns The characters after the basename's final dot.
25
+ */
26
+ export declare function fileExtension(path: string): string;
27
+ /**
28
+ * Classify a file path or name for file-card presentation.
29
+ * Matching is case-insensitive and applies code filename rules before extension rules;
30
+ * unknown names fall back to `other`.
31
+ * @param path - File path or basename using either path separator.
32
+ * @param context - Optional project files used by context-sensitive code mappings.
33
+ * @returns The file's closed presentation category.
34
+ */
35
+ export declare function classifyFileType(path: string, context?: FileTypeProjectContext): ClassifiedFileType;
36
+ /**
37
+ * Render a decorative file-type glyph for a path or an explicitly resolved kind.
38
+ * @param props - Path or kind selection, optional project context, size, and CSS class.
39
+ * @returns The category-colored SVG; the caller owns the accessible name and may override
40
+ * the color through `--dsh-file-type-icon-color`.
41
+ */
42
+ export declare function FileTypeIcon(props: FileTypeIconProps): ReactNode;
43
+ //# sourceMappingURL=FileTypeIcon.d.ts.map
@@ -26,13 +26,16 @@ export interface MenuLabel {
26
26
  export type MenuEntry = MenuItem | MenuSeparator | MenuLabel;
27
27
  /**
28
28
  * Render an anchored dropdown menu.
29
+ * @param props.autoFocus - focus the first item on open and enable arrow-key navigation; Escape focuses the anchor's first button.
29
30
  * @param props.open - whether the list is showing (owner-controlled).
30
31
  * @param props.anchor - the trigger element (rendered in place).
31
32
  * @param props.items - selectable rows and optional separators.
32
33
  * @param props.selectedId - row shown as selected.
33
34
  * @param props.selectedIds - rows shown as selected when a menu contains independent option groups.
34
35
  * @param props.onSelect - row click callback (not called for disabled rows or submenu parents that only open children).
35
- * @param props.onClose - invoked on outside click or Escape.
36
+ * @param props.onClose - invoked on outside click, Escape, or a window blur
37
+ * that moved focus into an iframe (the only signal a pointerdown inside a
38
+ * cross-origin iframe leaves).
36
39
  * @param props.align - list alignment against the anchor (default 'start').
37
40
  * @param props.side - open below (`bottom`, default) or above (`top`) the anchor.
38
41
  * @param props.portal - render the list into document.body, fixed-positioned
@@ -59,8 +62,9 @@ export type MenuEntry = MenuItem | MenuSeparator | MenuLabel;
59
62
  * crowds the cell).
60
63
  * @returns anchor wrapper with the conditional list.
61
64
  */
62
- export declare function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose, align, side, portal, closeOnPointerLeave, dense, compact, selection, getAnchorRect, footer, className }: {
65
+ export declare function Menu({ open, anchor, items, selectedId, selectedIds, onSelect, onClose, align, side, portal, closeOnPointerLeave, dense, compact, autoFocus, selection, getAnchorRect, footer, className }: {
63
66
  open: boolean;
67
+ autoFocus?: boolean;
64
68
  anchor: ReactNode;
65
69
  items: readonly MenuEntry[];
66
70
  footer?: readonly MenuEntry[];
@@ -76,6 +80,6 @@ export declare function Menu({ open, anchor, items, selectedId, selectedIds, onS
76
80
  compact?: boolean;
77
81
  selection?: 'check' | 'fill';
78
82
  getAnchorRect?: () => DOMRect | null;
79
- className?: string;
83
+ className?: string | undefined;
80
84
  }): import("react").JSX.Element;
81
85
  //# sourceMappingURL=Menu.d.ts.map
@@ -0,0 +1,30 @@
1
+ /** Code and configuration categories with embedded full-color glyphs. */
2
+ export declare const CODE_FILE_TYPES: readonly ["angular", "c", "clojure", "cmake", "cpp", "csharp", "css", "dart", "docker", "elixir", "env", "erlang", "flutter", "git", "go", "graphql", "haskell", "ini", "java", "javascript", "json", "kotlin", "lua", "makefile", "node", "objective-c", "perl", "php", "powershell", "protobuf", "python", "r", "react", "ruby", "rust", "scala", "shell", "solidity", "sql", "svelte", "swift", "toml", "typescript", "vue", "wasm", "xml", "yaml", "zig"];
3
+ /** A code or configuration file category with its own full-color square glyph. */
4
+ export type CodeFileType = typeof CODE_FILE_TYPES[number];
5
+ /** Optional project files used by context-sensitive code-icon rules. */
6
+ export interface FileTypeProjectContext {
7
+ /** Text content keyed by project-relative or basename path. */
8
+ readonly files: Readonly<Record<string, string | undefined>>;
9
+ }
10
+ /**
11
+ * Test whether a resolved file type uses the full-color code-icon set.
12
+ * @param type - Resolved file-type string.
13
+ * @returns Whether the value is a detailed code-file type.
14
+ */
15
+ export declare function isCodeFileType(type: string): type is CodeFileType;
16
+ /**
17
+ * Test whether an extension belonged to the established coarse LinkIcon code category.
18
+ * @param extension - Extension without a leading dot.
19
+ * @returns Whether clickable links keep the code glyph for this extension.
20
+ */
21
+ export declare function isLinkCodeExtension(extension: string): boolean;
22
+ /**
23
+ * Resolve the most specific code/configuration icon according to the supplied map priority.
24
+ * @param name - Lowercase basename.
25
+ * @param extension - Lowercase extension without the leading dot.
26
+ * @param context - Optional project-file snapshot for context-sensitive matches.
27
+ * @returns The detailed code type, or null when the traditional file classifier owns the path.
28
+ */
29
+ export declare function classifyCodeFileType(name: string, extension: string, context?: FileTypeProjectContext): CodeFileType | null;
30
+ //# sourceMappingURL=code-file-types.d.ts.map
@@ -43,7 +43,8 @@ export declare const IconCloseOutline16: ({ size, className }: IconProps) => imp
43
43
  export declare const IconCloseFill14: ({ size, className }: IconProps) => import("react").JSX.Element;
44
44
  /** ic_ds_copy_outline_16 */
45
45
  export declare const IconCopyOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
46
- /** ic_ds_refresh_outline_16 */
46
+ /** ic_ds_refresh_outline_16, inset 10%: the exported glyph fills its box edge
47
+ * to edge, one visual size above the neighbouring 16px glyphs. */
47
48
  export declare const IconRefreshOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
48
49
  /** ic_ds_refresh_outline_14 */
49
50
  export declare const IconRefreshOutline14: ({ size, className }: IconProps) => import("react").JSX.Element;
@@ -135,6 +136,10 @@ export declare const IconDataOutline16: ({ size, className }: IconProps) => impo
135
136
  export declare const IconDatabaseOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
136
137
  /** Thin-stroke clock: outlined dial with square-cut hour and minute hands. */
137
138
  export declare const IconClockOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
139
+ /** Thin-stroke gauge: dial arc open at the bottom, filled hub, square-cut needle to the upper right.
140
+ * The dial center sits at y=8.75, not 8: the bottom opening leaves the glyph top-heavy, and the
141
+ * 0.75 drop optically centers the drawn extent in the 16 box. */
142
+ export declare const IconGaugeOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
138
143
  /** ic_send_outline_14 (figma extract): thin-stroke upward send arrow. */
139
144
  export declare const IconSendOutline14: ({ size, className }: IconProps) => import("react").JSX.Element;
140
145
  /** ic_queue_outline_14 (figma extract): open chat bubble with two queued lines. */
@@ -32,12 +32,13 @@ export { ReferenceIcon } from './ReferenceIcon.tsx';
32
32
  export type { ReferenceIconKind, ReferenceIconProps } from './ReferenceIcon.tsx';
33
33
  export { LinkIcon, classifyLinkPath } from './LinkIcon.tsx';
34
34
  export type { LinkIconKind, LinkIconProps } from './LinkIcon.tsx';
35
+ export { FileTypeIcon, classifyFileType, fileExtension } from './FileTypeIcon.tsx';
36
+ export type { CodeFileType, FileType, FileTypeIconProps, FileTypeKind, FileTypeProjectContext, } from './FileTypeIcon.tsx';
35
37
  export { projectUserText } from './user-text.tsx';
36
38
  export { Tooltip } from './Tooltip.tsx';
37
39
  export type { TooltipSide } from './Tooltip.tsx';
38
40
  export { Toast } from './Toast.tsx';
39
41
  export { fileSizeText } from './file-size.ts';
40
- export { DocumentFileIcon } from './DocumentFileIcon.tsx';
41
42
  export { writeClipboard } from './clipboard.ts';
42
43
  export { relativeTime } from './relative-time.ts';
43
44
  export { rankByName } from './rank-by-name.ts';
@@ -58,7 +59,7 @@ export { CodeBlock } from './markdown/CodeBlock.tsx';
58
59
  export type { CodeBlockProps } from './markdown/CodeBlock.tsx';
59
60
  export { JsonBlock } from './markdown/JsonBlock.tsx';
60
61
  export { MarkdownText } from './markdown/MarkdownText.tsx';
61
- export type { MarkdownCodeLabels, MarkdownFileMentions, MarkdownLabels } from './markdown/MarkdownText.tsx';
62
+ export type { MarkdownCodeLabels, MarkdownFileMentions, MarkdownLabels, MarkdownPathImages } from './markdown/MarkdownText.tsx';
62
63
  export { extractMarkdownPlainText } from './markdown/plain-text.ts';
63
64
  export type { MarkdownPlainTextMode, MarkdownPlainTextOptions } from './markdown/plain-text.ts';
64
65
  export * from './icons/index.tsx';
@@ -14,10 +14,12 @@ export interface CodeBlockProps {
14
14
  streaming?: boolean | undefined;
15
15
  /** Extra class merged onto the wrapper (callers position; this component draws). */
16
16
  className?: string | undefined;
17
+ /** Show a numbered gutter without adding numbers to copied source. Defaults to false. */
18
+ lineNumbers?: boolean | undefined;
17
19
  /** Copy-button idle label; the owner passes localized copy (this package is cordis-free, so copy arrives via props). */
18
20
  copyLabel: string;
19
21
  /** Copy-button label during the post-copy confirmation window. */
20
22
  copiedLabel: string;
21
23
  }
22
- export declare function CodeBlock({ code, lang, streaming, className, copyLabel, copiedLabel }: CodeBlockProps): import("react").JSX.Element;
24
+ export declare function CodeBlock({ code, lang, streaming, className, lineNumbers, copyLabel, copiedLabel }: CodeBlockProps): import("react").JSX.Element;
23
25
  //# sourceMappingURL=CodeBlock.d.ts.map
@@ -10,9 +10,9 @@
10
10
  * other side of the freeze boundary renders literally until the settled
11
11
  * full parse self-heals it.
12
12
  */
13
- import type { MarkdownFileMentions, MarkdownLabels } from './render.tsx';
13
+ import type { MarkdownFileMentions, MarkdownLabels, MarkdownPathImages } from './render.tsx';
14
14
  import 'katex/dist/katex.min.css';
15
- export type { MarkdownCodeLabels, MarkdownFileMentions, MarkdownLabels } from './render.tsx';
15
+ export type { MarkdownCodeLabels, MarkdownFileMentions, MarkdownLabels, MarkdownPathImages } from './render.tsx';
16
16
  /**
17
17
  * Render untrusted assistant-authored Markdown as semantic React elements.
18
18
  * @param props - Markdown source text preserved by the session projection;
@@ -22,18 +22,21 @@ export type { MarkdownCodeLabels, MarkdownFileMentions, MarkdownLabels } from '.
22
22
  * `labels` forwards localized fence and footnote chrome — pass a
23
23
  * reference-stable object (memoized per locale revision), because a new
24
24
  * identity discards the streaming render cache mid-message. `fileMentions`
25
- * links inline-code tokens its resolver recognizes as real files; this is
26
- * the single streaming gate — it applies to settled renders only, because a
25
+ * links inline-code tokens its resolver recognizes as real files, and
26
+ * `pathImages` rewrites image destinations that are local file paths into
27
+ * displayable URLs its resolver vouches for; both vocabularies are the
28
+ * single streaming gate — they apply to settled renders only, because a
27
29
  * streaming message's vocabulary is not final and frozen cached elements
28
30
  * must not bake in handlers that could go stale.
29
31
  * @returns A GFM document with TeX math rendered through KaTeX; raw HTML,
30
32
  * relative links, and unsafe protocols are disabled, while absolute HTTP(S)
31
33
  * images render directly.
32
34
  */
33
- export declare const MarkdownText: import("react").MemoExoticComponent<({ text, streaming, labels, fileMentions }: {
35
+ export declare const MarkdownText: import("react").MemoExoticComponent<({ text, streaming, labels, fileMentions, pathImages }: {
34
36
  text: string;
35
37
  streaming?: boolean;
36
38
  labels: MarkdownLabels;
37
39
  fileMentions?: MarkdownFileMentions | undefined;
40
+ pathImages?: MarkdownPathImages | undefined;
38
41
  }) => import("react").JSX.Element>;
39
42
  //# sourceMappingURL=MarkdownText.d.ts.map
@@ -49,6 +49,23 @@ export declare function createReferenceTargets(): ReferenceTargets;
49
49
  * @param targets - Accumulator, typically shared across incremental segments.
50
50
  */
51
51
  export declare function collectReferenceTargets(nodes: readonly Md.RootContent[], targets: ReferenceTargets): void;
52
+ /**
53
+ * Local-path image vocabulary for image destinations: the owner maps an
54
+ * authored destination that fails the remote-URL allowlist (an absolute local
55
+ * file path, for example) to a displayable URL it can vouch for. Absent
56
+ * wherever no such vocabulary exists, authored local destinations keep their
57
+ * documented fallback (the image's alt text). Rewritten destinations must be
58
+ * absolute; the renderer re-checks their protocol before emitting them.
59
+ */
60
+ export interface MarkdownPathImages {
61
+ /**
62
+ * Resolve one authored image destination.
63
+ * @param value - The destination exactly as the markdown author wrote it.
64
+ * @returns A displayable absolute URL, or undefined when the destination
65
+ * names no displayable image — it then stays inert alt text.
66
+ */
67
+ resolve(value: string): string | undefined;
68
+ }
52
69
  /**
53
70
  * File-mention affordance for inline code: the owner resolves an authored
54
71
  * token to the file it names, using its own vocabulary of real files — the
@@ -80,6 +97,8 @@ export interface MarkdownRenderContext {
80
97
  readonly inBlockquote?: boolean;
81
98
  /** Inline-code file mentions; absent wherever no opener vocabulary exists. */
82
99
  readonly fileMentions: MarkdownFileMentions | undefined;
100
+ /** Local-path image vocabulary; absent wherever no rewriting owner exists. */
101
+ readonly pathImages: MarkdownPathImages | undefined;
83
102
  /** Inside an anchor's children: interactive mentions must not nest there. */
84
103
  readonly inLink?: boolean;
85
104
  /** Reference targets visible to this pass. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-primitives",
3
3
  "description": "Pure React atoms for the dsh web UI: controls, icons, markdown, and JSON inspectors (zero cordis)",
4
- "version": "0.1.3-alpha.2",
4
+ "version": "0.1.5-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -22,31 +22,29 @@
22
22
  "./package.json": "./package.json"
23
23
  },
24
24
  "license": "MIT",
25
- "dependencies": {
26
- "@shikijs/langs": "^4.3.1",
27
- "@types/mdast": "^4.0.4",
28
- "anser": "^2.3.5",
25
+ "devDependencies": {
26
+ "@types/react": "~18.3.1",
27
+ "@types/react-dom": "~18.3.0",
28
+ "react": "^18.2.0",
29
29
  "clsx": "^2.0.0",
30
+ "react-dom": "^18.2.0",
31
+ "anser": "^2.3.5",
30
32
  "katex": "^0.16.47",
31
- "mdast-util-from-markdown": "^2.0.3",
32
- "mdast-util-gfm": "^3.1.0",
33
- "mdast-util-math": "^3.0.0",
34
33
  "micromark-core-commonmark": "^2.0.3",
35
- "micromark-extension-gfm": "^3.0.0",
36
- "micromark-extension-math": "^3.1.0",
37
- "micromark-factory-space": "^2.0.1",
38
34
  "micromark-util-character": "^2.1.1",
39
35
  "micromark-util-classify-character": "^2.0.1",
40
- "micromark-util-sanitize-uri": "^2.0.1",
41
36
  "micromark-util-symbol": "^2.0.1",
42
37
  "micromark-util-types": "^2.0.2",
43
- "react": "^18.2.0",
44
- "react-dom": "^18.2.0",
45
- "shiki": "^4.3.1"
46
- },
47
- "devDependencies": {
48
- "@types/react": "~18.3.1",
49
- "@types/react-dom": "~18.3.0",
38
+ "shiki": "^4.3.1",
39
+ "@shikijs/langs": "^4.3.1",
40
+ "@types/mdast": "^4.0.4",
41
+ "micromark-factory-space": "^2.0.1",
42
+ "micromark-extension-math": "^3.1.0",
43
+ "mdast-util-from-markdown": "^2.0.3",
44
+ "mdast-util-gfm": "^3.1.0",
45
+ "mdast-util-math": "^3.0.0",
46
+ "micromark-extension-gfm": "^3.0.0",
47
+ "micromark-util-sanitize-uri": "^2.0.1",
50
48
  "@deepseek-ai/cordis": "^4.0.2"
51
49
  },
52
50
  "files": [
@@ -1,9 +0,0 @@
1
- /**
2
- * Render the DeepSeek Web document glyph used by generic-file cards.
3
- * @param props - optional CSS class for sizing and placement.
4
- * @returns a decorative document SVG with an instance-safe gradient id.
5
- */
6
- export declare function DocumentFileIcon({ className }: {
7
- readonly className?: string | undefined;
8
- }): import("react").JSX.Element;
9
- //# sourceMappingURL=DocumentFileIcon.d.ts.map