@llmnative/react 1.33.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -327,6 +327,31 @@ export interface I18nDict {
327
327
  breadcrumbs: {
328
328
  label: string;
329
329
  };
330
+ /** CR-109 — ChatReasoning and ChatQuestions (code blocks of ChatMarkdown use `code`). */
331
+ chat: {
332
+ reasoning: string;
333
+ reasoningStreaming: string;
334
+ reasoningFor: string;
335
+ durationSeconds: string;
336
+ durationMinutes: string;
337
+ questions: string;
338
+ questionTab: string;
339
+ review: string;
340
+ reviewHint: string;
341
+ other: string;
342
+ otherPlaceholder: string;
343
+ recommended: string;
344
+ chooseOne: string;
345
+ chooseMany: string;
346
+ keyboardHint: string;
347
+ /** CR-110 — hint while typing the free-text answer (Enter adds a line). */
348
+ textKeyboardHint: string;
349
+ next: string;
350
+ back: string;
351
+ submit: string;
352
+ noAnswer: string;
353
+ answered: string;
354
+ };
330
355
  }
331
356
  type DeepPartial<T> = {
332
357
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
@@ -74,6 +74,13 @@ export { default as MarkdownReader } from './widgets/MarkdownReader';
74
74
  export type { MarkdownReaderProps } from './widgets/MarkdownReader';
75
75
  export * from './widgets/Prompt';
76
76
  export * from './widgets/Chatbot';
77
+ export { default as ChatMarkdown } from './widgets/chat/ChatMarkdown';
78
+ export type { ChatMarkdownProps, ChatMarkdownClassNames } from './widgets/chat/ChatMarkdown';
79
+ export { default as ChatReasoning } from './widgets/chat/ChatReasoning';
80
+ export type { ChatReasoningProps, ChatReasoningClassNames } from './widgets/chat/ChatReasoning';
81
+ export { default as ChatQuestions } from './widgets/chat/ChatQuestions';
82
+ export type { ChatQuestion, ChatQuestionOption, ChatQuestionAnswer, ChatQuestionsNumbering, ChatQuestionsProps, ChatQuestionsClassNames } from './widgets/chat/ChatQuestions';
83
+ export { repairStreamingMarkdown } from '../libs/streamingMarkdown';
77
84
  export { default as TabDynamic } from './widgets/TabDynamic';
78
85
  export { default as Component } from './Component';
79
86
  export { ComponentBlock } from './Component';
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { UIProps } from '../..';
3
- declare const LANGUAGES: Record<string, () => Promise<unknown>>;
4
3
  declare const THEMES: {
5
4
  prism: string;
6
5
  dark: string;
@@ -11,7 +10,7 @@ declare const THEMES: {
11
10
  tomorrow: string;
12
11
  twilight: string;
13
12
  };
14
- type PrismLanguage = keyof typeof LANGUAGES;
13
+ type PrismLanguage = string;
15
14
  type PrismTheme = keyof typeof THEMES;
16
15
  export type PrismBackground = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark' | 'white' | 'black' | 'transparent' | 'default';
17
16
  interface CodeProps extends UIProps {
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { type Components } from 'react-markdown';
3
+ /** Classes for the parts of a `ChatMarkdown`, added to the defaults. */
4
+ export interface ChatMarkdownClassNames {
5
+ root?: string;
6
+ paragraph?: string;
7
+ heading?: string;
8
+ list?: string;
9
+ blockquote?: string;
10
+ /** The scrolling box around a table. */
11
+ tableWrapper?: string;
12
+ table?: string;
13
+ th?: string;
14
+ td?: string;
15
+ codeBlock?: string;
16
+ codeHeader?: string;
17
+ code?: string;
18
+ inlineCode?: string;
19
+ link?: string;
20
+ }
21
+ export interface ChatMarkdownProps {
22
+ /** GitHub-flavoured Markdown of the message. */
23
+ content: string;
24
+ /**
25
+ * The text is still arriving: what its end left open (a code fence, a table header, `**bold`,
26
+ * a link) is closed before rendering, so the layout does not jump. Leave it off for a finished message.
27
+ */
28
+ streaming?: boolean;
29
+ /** `muted` for secondary text, such as the reasoning of the model. */
30
+ tone?: 'default' | 'muted';
31
+ /** Syntax highlighting of fenced code (Prism, loaded on demand). Default `true`. */
32
+ highlight?: boolean;
33
+ /** Called on a link to a route of the app (not an address, not `#anchor`); it prevents the navigation. */
34
+ onLinkClick?: (href: string, event: React.MouseEvent<HTMLAnchorElement>) => void;
35
+ /** Overrides of single elements, as in `react-markdown`. */
36
+ components?: Components;
37
+ className?: string;
38
+ classNames?: ChatMarkdownClassNames;
39
+ }
40
+ /**
41
+ * CR-109 — Markdown of a chat message: GFM (tables, task lists, strikethrough, autolinks), compact
42
+ * spacing, tables that scroll inside themselves, code with highlighting and a copy button, links to
43
+ * addresses in a new tab. Sanitized (`rehype-sanitize`): raw HTML and `javascript:` links are dropped.
44
+ * With `streaming` the end of the text is repaired as it arrives.
45
+ */
46
+ export default function ChatMarkdown({ content, streaming, tone, highlight, onLinkClick, components, className, classNames, }: ChatMarkdownProps): React.JSX.Element;
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ /** A choice of a question. */
3
+ export interface ChatQuestionOption {
4
+ /** What the answer says; it is the value returned when chosen. */
5
+ label: string;
6
+ /** A line under the label. */
7
+ description?: string;
8
+ }
9
+ /**
10
+ * A question of the model, in the shape of the `question` tool of opencode and of MCP elicitation.
11
+ */
12
+ export interface ChatQuestion {
13
+ /** Returned with the answer, to match it to the question. */
14
+ id?: string;
15
+ /** Short title: the label of its tab. */
16
+ header?: string;
17
+ question: string;
18
+ /** The choices. Without them the question takes a free-text answer. */
19
+ options?: ChatQuestionOption[];
20
+ /** More than one choice. */
21
+ multiple?: boolean;
22
+ /**
23
+ * The choice the model recommends: its index (from 0) or its label. A label ending with
24
+ * "(Recommended)" is recognised too.
25
+ */
26
+ recommended?: number | string;
27
+ /** Offers "Other" with a free-text answer. Default: `allowOther` of the component. */
28
+ custom?: boolean;
29
+ }
30
+ /** The answer to one question: the chosen labels and/or the free text. */
31
+ export interface ChatQuestionAnswer {
32
+ id?: string;
33
+ header?: string;
34
+ values: string[];
35
+ }
36
+ /** How the choices are numbered: 1-2-3 or A-B-C. */
37
+ export type ChatQuestionsNumbering = 'numeric' | 'alpha';
38
+ /** Classes for the parts of a `ChatQuestions`, added to the defaults. */
39
+ export interface ChatQuestionsClassNames {
40
+ root?: string;
41
+ tabs?: string;
42
+ tab?: string;
43
+ panel?: string;
44
+ question?: string;
45
+ option?: string;
46
+ /** Added to a chosen option. */
47
+ optionSelected?: string;
48
+ footer?: string;
49
+ /** The answered state. */
50
+ summary?: string;
51
+ }
52
+ export interface ChatQuestionsProps {
53
+ questions: ChatQuestion[];
54
+ /**
55
+ * All the answers, in the order of the questions. May return a promise: the form waits for it and
56
+ * shows the answered state when it resolves (it stays open when it rejects).
57
+ */
58
+ onSubmit?: (answers: ChatQuestionAnswer[]) => void | Promise<unknown>;
59
+ /** Numbering of the choices. Default: as the labels are written ("A) …", "1. …"), else numeric. */
60
+ numbering?: ChatQuestionsNumbering;
61
+ /** "Other" with a free-text answer on every question (a question can override it with `custom`). Default `true`. */
62
+ allowOther?: boolean;
63
+ /** Answers already given: the component shows them, read-only, instead of the form. */
64
+ answers?: ChatQuestionAnswer[];
65
+ /** Shows the form without letting it change or be sent. */
66
+ disabled?: boolean;
67
+ /** Puts the focus on the first choice when it appears, so the number keys work at once. */
68
+ autoFocus?: boolean;
69
+ /** Text of the submit button. */
70
+ submitLabel?: string;
71
+ className?: string;
72
+ classNames?: ChatQuestionsClassNames;
73
+ }
74
+ /**
75
+ * CR-109 — Questions of the model the user answers with a click: one tab per question, numbered
76
+ * choices (the recommended one stands out), single or multiple choice, "Other" with free text, a
77
+ * review and one submit for all the answers. Keyboard: number (or letter) keys choose, arrows move
78
+ * between tabs and choices, Enter continues. With `answers` it shows a set already answered.
79
+ *
80
+ * CR-110 — The free text ("Other", or a question without options) is a textarea that grows with
81
+ * the text (two lines, then up to a height and it scrolls; resizable vertically): Enter adds a
82
+ * line, Ctrl/Cmd+Enter continues or sends.
83
+ */
84
+ export default function ChatQuestions({ questions, onSubmit, numbering, allowOther, answers, disabled, autoFocus, submitLabel, className, classNames, }: ChatQuestionsProps): React.JSX.Element | null;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { type I18nDict } from '../../../I18n';
3
+ /** Classes for the parts of a `ChatReasoning`, added to the defaults. */
4
+ export interface ChatReasoningClassNames {
5
+ root?: string;
6
+ /** The summary line that opens and closes the block. */
7
+ trigger?: string;
8
+ content?: string;
9
+ }
10
+ export interface ChatReasoningProps {
11
+ /** The reasoning of the model, as Markdown. */
12
+ content: string;
13
+ /** The reasoning is still arriving: the block is open (unless the user closed it) and its end is repaired. */
14
+ streaming?: boolean;
15
+ /** How long the model reasoned, in seconds: the summary says "Reasoned for 12 s". */
16
+ duration?: number;
17
+ /** Open when it is not streaming. Default `false`. */
18
+ defaultOpen?: boolean;
19
+ /** Controlled open state; with it, the block opens and closes only through `onOpenChange`. */
20
+ open?: boolean;
21
+ onOpenChange?: (open: boolean) => void;
22
+ /** Replaces the summary text. */
23
+ label?: React.ReactNode;
24
+ /** Icon of the summary line. Default `brain`. */
25
+ icon?: string;
26
+ className?: string;
27
+ classNames?: ChatReasoningClassNames;
28
+ }
29
+ /** `12` → "12 s", `75` → "1 min 15 s", in the words of the dictionary. */
30
+ export declare function formatReasoningDuration(seconds: number, dict: I18nDict['chat']): string;
31
+ /**
32
+ * CR-109 — The reasoning of the model, in a block of its own: closed by default behind a summary line
33
+ * ("Reasoning", "Reasoned for 12 s"), open while it streams, its Markdown in a muted tone.
34
+ */
35
+ export default function ChatReasoning({ content, streaming, duration, defaultOpen, open, onOpenChange, label, icon, className, classNames, }: ChatReasoningProps): React.JSX.Element;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Prism loaded on demand, shared by `Code` and `ChatMarkdown`.
3
+ *
4
+ * The core and each language pack are imported lazily the first time they are needed, so the root
5
+ * bundle does not carry the grammars.
6
+ */
7
+ export declare const PRISM_LANGUAGES: Record<string, () => Promise<unknown>>;
8
+ /** The Prism grammar name for a fence language, or `undefined` when Prism has no grammar for it. */
9
+ export declare function resolvePrismLanguage(language: string | undefined): string | undefined;
10
+ export declare function loadPrismLanguage(language: string, loaded?: Set<string>): Promise<void>;
11
+ /** Minimal shape of the Prism object used by the framework. */
12
+ export interface PrismLike {
13
+ languages: Record<string, unknown>;
14
+ highlight: (code: string, grammar: unknown, language: string) => string;
15
+ highlightElement: (element: Element) => void;
16
+ }
17
+ /** Loads the Prism core (once), with the global the language packs extend. */
18
+ export declare function loadPrism(): Promise<PrismLike>;
19
+ /** Loads the scoped Prism themes of `Code` (lazy, once). */
20
+ export declare function ensurePrismStyles(): Promise<void>;
21
+ /**
22
+ * Highlights `code` as HTML (Prism escapes the text), or `null` when the language has no grammar or
23
+ * Prism cannot load.
24
+ */
25
+ export declare function highlightCode(code: string, language: string | undefined): Promise<string | null>;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CR-109 — Markdown that is still arriving.
3
+ *
4
+ * A model streams Markdown a few characters at a time, so the text on screen is often cut in the
5
+ * middle of a construct: a code fence not yet closed, a table with only its header, `**bold` without
6
+ * its closing marks, a link without `)`. Rendered as is, the rest of the message turns into code, the
7
+ * table shows as a line of pipes until its delimiter row arrives, and markers flash as text.
8
+ *
9
+ * `repairStreamingMarkdown` closes what the tail of the text left open, so each partial text renders
10
+ * as close as possible to its final form. It only looks at the end of the text, never changes what is
11
+ * already complete, and is meant for text that is still streaming: a finished message is rendered
12
+ * as written.
13
+ */
14
+ /** Closes the constructs the end of a streaming Markdown text left open (see the module comment). */
15
+ export declare function repairStreamingMarkdown(text: string): string;