inline-chat-kit 0.49.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.
- package/CHANGELOG.md +2111 -0
- package/LICENSE +21 -0
- package/README.md +1430 -0
- package/dist/AnswerActions/AnswerActions.d.ts +35 -0
- package/dist/Approval/Approval.d.ts +42 -0
- package/dist/Artifact/ArtifactCard.d.ts +45 -0
- package/dist/Artifact/ArtifactPane.d.ts +50 -0
- package/dist/Artifact/ChatLayout.d.ts +35 -0
- package/dist/Artifact/useArtifacts.d.ts +21 -0
- package/dist/Attachments/Attachments.d.ts +50 -0
- package/dist/Branch/Branch.d.ts +28 -0
- package/dist/Button/Button.d.ts +23 -0
- package/dist/ChainOfThought/ChainOfThought.d.ts +49 -0
- package/dist/ChatHeader/ChatHeader.d.ts +89 -0
- package/dist/ChatInput/AddCardsOverlay.d.ts +11 -0
- package/dist/ChatInput/ChatInput.d.ts +118 -0
- package/dist/ChatInput/HoverActionsRow.d.ts +13 -0
- package/dist/ChatInput/MorphGlyph.d.ts +15 -0
- package/dist/ChatTurnRow/ChatTurnRow.d.ts +115 -0
- package/dist/Chip/Chip.d.ts +7 -0
- package/dist/CodeBlock/CodeBlock.d.ts +24 -0
- package/dist/CodeBlock/grammars.d.ts +16 -0
- package/dist/CodeBlock/highlight.d.ts +38 -0
- package/dist/Context/Context.d.ts +36 -0
- package/dist/Conversation/Conversation.d.ts +64 -0
- package/dist/CustomCursor/CustomCursor.d.ts +1 -0
- package/dist/EmptyState/EmptyState.d.ts +24 -0
- package/dist/GlassButton/GlassButton.d.ts +19 -0
- package/dist/InlineCitation/InlineCitation.d.ts +30 -0
- package/dist/Loader/Loader.d.ts +23 -0
- package/dist/QuestionCard/QuestionCard.d.ts +32 -0
- package/dist/QuestionCard/parts.d.ts +84 -0
- package/dist/QuestionCard/types.d.ts +54 -0
- package/dist/QuestionGroup/QuestionGroup.d.ts +87 -0
- package/dist/Reasoning/Reasoning.d.ts +37 -0
- package/dist/ReplyThreadPopup/ReplyThreadPopup.d.ts +18 -0
- package/dist/Sources/Sources.d.ts +46 -0
- package/dist/SystemMessage/SystemMessage.d.ts +39 -0
- package/dist/TaskList/TaskList.d.ts +42 -0
- package/dist/TextHighlighter/TextHighlighter.d.ts +17 -0
- package/dist/Tool/Tool.d.ts +41 -0
- package/dist/announce/announce.d.ts +27 -0
- package/dist/disclosure/DisclosureBody.d.ts +22 -0
- package/dist/disclosure/DisclosureHeader.d.ts +42 -0
- package/dist/disclosure/useDisclosure.d.ts +30 -0
- package/dist/duration/formatDuration.d.ts +9 -0
- package/dist/grammars-B19jp7qm.js +3181 -0
- package/dist/grammars-B19jp7qm.js.map +1 -0
- package/dist/index.d.ts +80 -0
- package/dist/inline-chat-kit.css +2 -0
- package/dist/inline-chat-kit.js +5314 -0
- package/dist/inline-chat-kit.js.map +1 -0
- package/dist/markdown/parse.d.ts +105 -0
- package/dist/markdown/parseMarkdown.d.ts +47 -0
- package/dist/radiusCorrection/useCorrectedRadius.d.ts +24 -0
- package/dist/reducedMotion/reducedMotion.d.ts +3 -0
- package/dist/stateGlyph/StateGlyph.d.ts +23 -0
- package/dist/turnParts/turnParts.d.ts +156 -0
- package/dist/useChatTurns/useChatTurns.d.ts +127 -0
- package/dist/voice/useVoiceInput.d.ts +79 -0
- package/package.json +95 -0
- package/theming.md +234 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export type Verdict = "up" | "down";
|
|
3
|
+
export interface AnswerActionsProps extends Omit<HTMLAttributes<HTMLDivElement>, "onCopy"> {
|
|
4
|
+
/** The answer these act on. Copy takes it; the callbacks receive it. */
|
|
5
|
+
text: string;
|
|
6
|
+
/** Defaults to the clipboard. */
|
|
7
|
+
onCopy?: (text: string) => void;
|
|
8
|
+
/** Omit and no regenerate button is drawn. */
|
|
9
|
+
onRegenerate?: () => void;
|
|
10
|
+
/**
|
|
11
|
+
* Omit and no thumbs are drawn. Called with `null` when a verdict is taken
|
|
12
|
+
* back — pressing the one already given is how somebody undoes it.
|
|
13
|
+
*/
|
|
14
|
+
onFeedback?: (verdict: Verdict | null) => void;
|
|
15
|
+
/** Controlled, for a host that stores the verdict. */
|
|
16
|
+
feedback?: Verdict | null;
|
|
17
|
+
/** Anything else, after the built-in controls. */
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Invisible until hovered or focused. It still occupies its space and still
|
|
21
|
+
* hit-tests, so nothing shifts and nothing is unreachable — `:focus-within`
|
|
22
|
+
* brings it back for anyone arriving by keyboard.
|
|
23
|
+
*/
|
|
24
|
+
reveal?: boolean;
|
|
25
|
+
/** While an answer is being regenerated. */
|
|
26
|
+
busy?: boolean;
|
|
27
|
+
labels?: Partial<Record<"copy" | "copied" | "regenerate" | "up" | "down", string>>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* What you can do to an answer once it has arrived.
|
|
31
|
+
*
|
|
32
|
+
* The input has had a hover row since the beginning; the answer had nothing,
|
|
33
|
+
* which is backwards — the answer is the part worth keeping.
|
|
34
|
+
*/
|
|
35
|
+
export declare function AnswerActions({ text, onCopy, onRegenerate, onFeedback, feedback, children, reveal, busy, labels, className, ...rest }: AnswerActionsProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
/** Once, every time from now on, or not at all. */
|
|
3
|
+
export type Decision = "once" | "always" | "denied";
|
|
4
|
+
type Labels = Record<"once" | "always" | "deny", string> & Record<"allowedOnce" | "allowedAlways" | "wasDenied" | "pending", string>;
|
|
5
|
+
export interface ApprovalProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
|
|
6
|
+
/** What is being asked. One line: "Run a command in your shell". */
|
|
7
|
+
title: ReactNode;
|
|
8
|
+
/** Why it is being asked, or what it will touch. */
|
|
9
|
+
description?: ReactNode;
|
|
10
|
+
/**
|
|
11
|
+
* The thing itself — usually a `<Tool>` or a `<CodeBlock>`.
|
|
12
|
+
*
|
|
13
|
+
* Somebody deciding needs to see what they are deciding about, and a name is
|
|
14
|
+
* not that. An approval with nothing under it is asking for a signature on a
|
|
15
|
+
* blank page.
|
|
16
|
+
*/
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
/** `null` while it is still being asked. */
|
|
19
|
+
decision?: Decision | null;
|
|
20
|
+
onDecide?: (decision: Decision) => void;
|
|
21
|
+
/** Nothing can be decided from here — a record of a decision already made. */
|
|
22
|
+
readOnly?: boolean;
|
|
23
|
+
labels?: Partial<Labels>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* "It wants to do this. Is that all right?"
|
|
27
|
+
*
|
|
28
|
+
* The one pattern from a coding agent that generalises to any agent that acts,
|
|
29
|
+
* and the only component in this kit whose whole job is to slow somebody down
|
|
30
|
+
* for a moment.
|
|
31
|
+
*
|
|
32
|
+
* Three decisions rather than two, because "yes" and "yes forever" are not the
|
|
33
|
+
* same answer and a UI offering one button for both collects the wrong one.
|
|
34
|
+
* **Allow once is the primary**: the narrow permission is the one that should
|
|
35
|
+
* be easiest to give, and the standing one should cost a moment's thought.
|
|
36
|
+
*
|
|
37
|
+
* Decided, it stops being a set of buttons and becomes a record of what was
|
|
38
|
+
* decided. Leaving live controls under a decision already made invites a
|
|
39
|
+
* second, contradictory one.
|
|
40
|
+
*/
|
|
41
|
+
export declare function Approval({ title, description, children, decision, onDecide, readOnly, labels, className, ...rest }: ApprovalProps): import("react").JSX.Element;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Code, or everything else.
|
|
4
|
+
*
|
|
5
|
+
* Two, because they are drawn differently and nothing else is: code goes
|
|
6
|
+
* through the highlighter, prose keeps its line breaks and does not. An
|
|
7
|
+
* `image` kind can be added the day something needs one — it is a third
|
|
8
|
+
* preview, not a third idea.
|
|
9
|
+
*/
|
|
10
|
+
export type ArtifactKind = "code" | "text";
|
|
11
|
+
/** Being written, or written. A file does not fail the way a call does. */
|
|
12
|
+
export type ArtifactState = "writing" | "done";
|
|
13
|
+
export interface ArtifactCardProps extends Omit<HTMLAttributes<HTMLDivElement>, "title" | "content" | "onSelect"> {
|
|
14
|
+
/** What the pane opens. The card and the pane share nothing else. */
|
|
15
|
+
id: string;
|
|
16
|
+
title: ReactNode;
|
|
17
|
+
/** What it is, in a word or two — "Training plan", "12 lines of Python". */
|
|
18
|
+
meta?: ReactNode;
|
|
19
|
+
kind?: ArtifactKind;
|
|
20
|
+
/** The fence's language, for `kind="code"`. */
|
|
21
|
+
lang?: string;
|
|
22
|
+
/** What was written. Absent while it is still being written. */
|
|
23
|
+
content?: string;
|
|
24
|
+
state?: ArtifactState;
|
|
25
|
+
/**
|
|
26
|
+
* How much of it the card shows before the cut.
|
|
27
|
+
*
|
|
28
|
+
* The whole point of an artifact is that it is bigger than the answer, so
|
|
29
|
+
* the card is a window rather than the thing. Poured out in full it is not
|
|
30
|
+
* an artifact, it is a long message.
|
|
31
|
+
*/
|
|
32
|
+
lines?: number;
|
|
33
|
+
/** Open it. Without one the card is a record rather than a control. */
|
|
34
|
+
onOpen?: (id: string) => void;
|
|
35
|
+
/** True while its pane is the one on screen. */
|
|
36
|
+
open?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* What the answer produced, in the transcript.
|
|
40
|
+
*
|
|
41
|
+
* A window onto it and a way in — not the thing itself. Press it and the pane
|
|
42
|
+
* beside the conversation shows the whole of it; the card stays where it is,
|
|
43
|
+
* because it is the line of the transcript that says the artifact was made.
|
|
44
|
+
*/
|
|
45
|
+
export declare function ArtifactCard({ id, title, meta, kind, lang, content, state, lines, onOpen, open, className, ...rest }: ArtifactCardProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface ArtifactPaneProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
3
|
+
title: ReactNode;
|
|
4
|
+
/** What it is, under the title. */
|
|
5
|
+
meta?: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* What the host renders. Absent, the pane shows its own skeleton — an
|
|
8
|
+
* artifact usually arrives before it is finished, and a pane that opens
|
|
9
|
+
* empty reads as broken rather than as early.
|
|
10
|
+
*/
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
onClose?: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* The one prop that changes behaviour, and it is not about position.
|
|
15
|
+
*
|
|
16
|
+
* Below the layout's breakpoint the pane covers the conversation instead of
|
|
17
|
+
* standing beside it, and covering changes what it *is*: focus has to be
|
|
18
|
+
* held inside it and Escape has to close it, because there is nothing usable
|
|
19
|
+
* behind it. Beside the conversation both would be wrong — trapping focus
|
|
20
|
+
* would lock a reader out of the chat they are still reading.
|
|
21
|
+
*
|
|
22
|
+
* `<ChatLayout>` sets it from its own width. Set it yourself only if you are
|
|
23
|
+
* placing the pane without one.
|
|
24
|
+
*/
|
|
25
|
+
modal?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Widened. The pane draws the control; `ChatLayout` owns the width, because
|
|
28
|
+
* how much room the pane takes is a fact about the layout.
|
|
29
|
+
*/
|
|
30
|
+
expanded?: boolean;
|
|
31
|
+
onToggleExpanded?: () => void;
|
|
32
|
+
closeLabel?: string;
|
|
33
|
+
expandLabel?: string;
|
|
34
|
+
collapseLabel?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* What the answer produced, in full, beside the conversation.
|
|
38
|
+
*
|
|
39
|
+
* The kit decides that it is on the right and that the conversation makes room
|
|
40
|
+
* for it — this is a pattern rather than a slot, and a chat where the pane
|
|
41
|
+
* arrives somewhere different each time is a chat nobody learns. What the kit
|
|
42
|
+
* does **not** decide is the content: a plan, a document, a table, a diagram.
|
|
43
|
+
* That is the host's, and it is why this takes children.
|
|
44
|
+
*
|
|
45
|
+
* The part worth having in a library is not the box. It is what happens on
|
|
46
|
+
* open: focus has to move here or a keyboard reader is left behind in the
|
|
47
|
+
* conversation, and it must **not** be trapped unless the pane is covering
|
|
48
|
+
* that conversation. Every host gets one of those two wrong.
|
|
49
|
+
*/
|
|
50
|
+
export declare function ArtifactPane({ title, meta, children, onClose, modal, expanded, onToggleExpanded, closeLabel, expandLabel, collapseLabel, className, ...rest }: ArtifactPaneProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export interface PaneState {
|
|
3
|
+
/** The pane is covering the conversation rather than standing beside it. */
|
|
4
|
+
narrow: boolean;
|
|
5
|
+
/** It has been widened. Meaningless while `narrow`, which is already full. */
|
|
6
|
+
expanded: boolean;
|
|
7
|
+
toggleExpanded: () => void;
|
|
8
|
+
}
|
|
9
|
+
export interface ChatLayoutProps extends HTMLAttributes<HTMLDivElement> {
|
|
10
|
+
/** The conversation, and whatever else belongs above and below it. */
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* The pane, when one is open.
|
|
14
|
+
*
|
|
15
|
+
* Given `narrow`, so it can hold focus and answer Escape once it is covering
|
|
16
|
+
* the conversation rather than standing beside it — the one thing about a
|
|
17
|
+
* pane that is not a matter of taste. And given `expanded` with the control
|
|
18
|
+
* for it, because the *width* belongs to the layout while the button that
|
|
19
|
+
* changes it belongs in the pane's own header, where somebody can find it.
|
|
20
|
+
*/
|
|
21
|
+
pane?: (state: PaneState) => ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Where the pane goes, decided once.
|
|
25
|
+
*
|
|
26
|
+
* The kit takes this decision rather than handing over a slot. A preview pane
|
|
27
|
+
* is one of the few patterns every AI chat now has, and the value of a pattern
|
|
28
|
+
* is that it is the same every time: ask for a plan, get a card, press it, the
|
|
29
|
+
* plan opens on the right. A kit that let each host place it would be shipping
|
|
30
|
+
* four chats that behave differently and calling it flexibility.
|
|
31
|
+
*
|
|
32
|
+
* What is left open is the part that actually differs — what is *in* the pane.
|
|
33
|
+
* See `ArtifactPane`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function ChatLayout({ children, pane, className, ...rest }: ChatLayoutProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface Artifacts {
|
|
2
|
+
/** The one on screen, or `null`. */
|
|
3
|
+
openId: string | null;
|
|
4
|
+
open: (id: string) => void;
|
|
5
|
+
close: () => void;
|
|
6
|
+
/** Press the card that is already open and it closes, which is what a reader expects. */
|
|
7
|
+
toggle: (id: string) => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Which artifact is open.
|
|
11
|
+
*
|
|
12
|
+
* A hook rather than state inside the pane, for the reason `useChatTurns` is a
|
|
13
|
+
* hook: the card in the transcript and the pane beside it are in different
|
|
14
|
+
* parts of the tree and both need the answer. A pane that owned it could not
|
|
15
|
+
* tell a card it was the open one, and a card that owned it could not be told
|
|
16
|
+
* the pane had closed.
|
|
17
|
+
*
|
|
18
|
+
* One at a time. A stack of open artifacts is a tab bar, and a tab bar is a
|
|
19
|
+
* product's decision about how many things somebody is holding at once.
|
|
20
|
+
*/
|
|
21
|
+
export declare function useArtifacts(initial?: string | null): Artifacts;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
|
+
/** Something sent along with a message. */
|
|
3
|
+
export interface Attachment {
|
|
4
|
+
id: string;
|
|
5
|
+
/** The filename, shown when there is no picture to show instead. */
|
|
6
|
+
name: string;
|
|
7
|
+
/**
|
|
8
|
+
* What to draw for it. An object URL, a data URL, or a remote one.
|
|
9
|
+
*
|
|
10
|
+
* Only used when `type` is an image. Anything else gets its name and a
|
|
11
|
+
* glyph, because a thumbnail of a PDF at 64px is a grey rectangle.
|
|
12
|
+
*/
|
|
13
|
+
url?: string;
|
|
14
|
+
/** The MIME type. Decides between a picture and a name. */
|
|
15
|
+
type?: string;
|
|
16
|
+
/** In bytes. Shown beside the name. */
|
|
17
|
+
size?: number;
|
|
18
|
+
}
|
|
19
|
+
type Labels = {
|
|
20
|
+
remove: string;
|
|
21
|
+
};
|
|
22
|
+
export interface AttachmentsProps extends Omit<HTMLAttributes<HTMLUListElement>, "onRemove"> {
|
|
23
|
+
attachments: Attachment[];
|
|
24
|
+
/**
|
|
25
|
+
* Leave it out and they are a record rather than a control — which is what
|
|
26
|
+
* they are once the message has been sent.
|
|
27
|
+
*/
|
|
28
|
+
onRemove?: (id: string) => void;
|
|
29
|
+
labels?: Partial<Labels>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `1.2 MB`, and nothing for a size nobody supplied.
|
|
33
|
+
*
|
|
34
|
+
* Powers of two, because that is what a file browser says and this number is
|
|
35
|
+
* only ever compared to one of those.
|
|
36
|
+
*/
|
|
37
|
+
export declare function formatSize(bytes?: number): string;
|
|
38
|
+
/**
|
|
39
|
+
* What is going along with the message.
|
|
40
|
+
*
|
|
41
|
+
* An image shows itself; everything else shows its name, because a thumbnail
|
|
42
|
+
* of a PDF at this size is a grey rectangle with a corner turned down and
|
|
43
|
+
* tells you less than the filename does.
|
|
44
|
+
*
|
|
45
|
+
* The same row draws them in the composer and under the message once it has
|
|
46
|
+
* been sent — with `onRemove` in the first case and without in the second,
|
|
47
|
+
* which is the whole difference between a control and a record.
|
|
48
|
+
*/
|
|
49
|
+
export declare function Attachments({ attachments, onRemove, labels, className, ...rest }: AttachmentsProps): import("react").JSX.Element | null;
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
|
+
type Labels = {
|
|
3
|
+
previous: string;
|
|
4
|
+
next: string;
|
|
5
|
+
/** `{index}` and `{total}` are filled in. */
|
|
6
|
+
position: string;
|
|
7
|
+
};
|
|
8
|
+
export interface BranchProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
9
|
+
/** How many answers this turn has had. */
|
|
10
|
+
total: number;
|
|
11
|
+
/** Which one is on screen, from zero. */
|
|
12
|
+
index: number;
|
|
13
|
+
onSelect: (index: number) => void;
|
|
14
|
+
labels?: Partial<Labels>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Which answer you are looking at, and how to reach the others.
|
|
18
|
+
*
|
|
19
|
+
* Regenerating used to overwrite: the answer you were comparing against was
|
|
20
|
+
* gone the moment the second one started. But the reason anybody presses
|
|
21
|
+
* regenerate is to find out whether a second attempt is better, and there is
|
|
22
|
+
* no better once the first has been thrown away.
|
|
23
|
+
*
|
|
24
|
+
* So it draws nothing at all for a turn with one answer. A control that says
|
|
25
|
+
* "1 of 1" is a control offering to take you nowhere.
|
|
26
|
+
*/
|
|
27
|
+
export declare function Branch({ total, index, onSelect, labels, className, ...rest }: BranchProps): import("react").JSX.Element | null;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export type ButtonVariant = "primary" | "secondary" | "outline" | "ghost" | "glass";
|
|
3
|
+
/**
|
|
4
|
+
* Heights: xs 24, s 28, m 32, l 40, xl 48.
|
|
5
|
+
*
|
|
6
|
+
* One scale, from two that disagreed — the round icon button was 28 with no
|
|
7
|
+
* say in the matter, and the glass pill offered 32/40/48 under the names
|
|
8
|
+
* s/m/l. Both sets of values survive; only the glass names moved up one step,
|
|
9
|
+
* which is what the deprecated `GlassButton` wrapper exists to absorb.
|
|
10
|
+
*/
|
|
11
|
+
export type ButtonSize = "xs" | "s" | "m" | "l" | "xl";
|
|
12
|
+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
13
|
+
variant?: ButtonVariant;
|
|
14
|
+
size?: ButtonSize;
|
|
15
|
+
/** Leading icon. On its own it makes a square button; give it an aria-label. */
|
|
16
|
+
icon?: ReactNode;
|
|
17
|
+
/** Trailing icon. */
|
|
18
|
+
iconRight?: ReactNode;
|
|
19
|
+
/** Replaces the content with a spinner and refuses interaction. */
|
|
20
|
+
loading?: boolean;
|
|
21
|
+
children?: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
export declare const Button: import('react').ForwardRefExoticComponent<ButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { WorkState } from '../stateGlyph/StateGlyph';
|
|
3
|
+
/** One step of a derivation: what was worked out, and the working. */
|
|
4
|
+
export interface Thought {
|
|
5
|
+
id: string;
|
|
6
|
+
/** What this step established. One line. */
|
|
7
|
+
label: ReactNode;
|
|
8
|
+
/** The working behind it. Prose, or anything you want drawn — a `Tool`, say. */
|
|
9
|
+
body?: ReactNode;
|
|
10
|
+
/** Defaults to `done`: a step you can read is a step that happened. */
|
|
11
|
+
state?: WorkState;
|
|
12
|
+
}
|
|
13
|
+
type Labels = {
|
|
14
|
+
/** Followed by the count: "Thought through 4 steps". */
|
|
15
|
+
through: string;
|
|
16
|
+
step: string;
|
|
17
|
+
steps: string;
|
|
18
|
+
thinking: string;
|
|
19
|
+
};
|
|
20
|
+
export interface ChainOfThoughtProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
|
|
21
|
+
steps: Thought[];
|
|
22
|
+
/** The chain as a whole. `thinking` holds it open and narrates the last step. */
|
|
23
|
+
state?: "thinking" | "done";
|
|
24
|
+
/** How long the whole chain took, in ms. */
|
|
25
|
+
duration?: number;
|
|
26
|
+
open?: boolean;
|
|
27
|
+
defaultOpen?: boolean;
|
|
28
|
+
onOpenChange?: (open: boolean) => void;
|
|
29
|
+
labels?: Partial<Labels>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* How the answer was arrived at, step by step.
|
|
33
|
+
*
|
|
34
|
+
* The third thing in this kit that draws a sequence, and the line between them
|
|
35
|
+
* is worth stating because it is the only reason there are three:
|
|
36
|
+
*
|
|
37
|
+
* - **`Reasoning`** is prose. The model talking to itself, unstructured.
|
|
38
|
+
* - **`TaskList`** is a plan. Known up front, forward-looking, fixed order,
|
|
39
|
+
* items changing state as work happens.
|
|
40
|
+
* - **`ChainOfThought`** is a derivation. Backward-looking, and it *grows* —
|
|
41
|
+
* each step follows from the one above it, which is what the line down the
|
|
42
|
+
* side is drawing. A step carries its own working, not a footnote.
|
|
43
|
+
*
|
|
44
|
+
* Open while it thinks and folded away once the answer starts, on the same
|
|
45
|
+
* terms as `Reasoning`: the chain's preference, overruled for good by anybody
|
|
46
|
+
* who touches it.
|
|
47
|
+
*/
|
|
48
|
+
export declare function ChainOfThought({ steps, state, duration, open, defaultOpen, onOpenChange, labels, className, ...rest }: ChainOfThoughtProps): import("react").JSX.Element;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export type ChatHeaderVariant = "plain" | "glass" | "bordered";
|
|
3
|
+
export type ChatHeaderSize = "s" | "m" | "l";
|
|
4
|
+
/**
|
|
5
|
+
* One action in the end region.
|
|
6
|
+
*
|
|
7
|
+
* Described rather than handed over as a node, and the reason is not tidiness:
|
|
8
|
+
* a header that is given arbitrary children cannot fold them into an overflow
|
|
9
|
+
* menu when the space runs out, because it has no idea what any of them are —
|
|
10
|
+
* no label to list, no icon to draw. Everything `collapseActionsAt` does
|
|
11
|
+
* depends on this shape.
|
|
12
|
+
*/
|
|
13
|
+
export interface ChatHeaderAction {
|
|
14
|
+
/** Stable across renders. Also the React key and the menu item's id. */
|
|
15
|
+
id: string;
|
|
16
|
+
/**
|
|
17
|
+
* The accessible name, and the text used in the overflow menu.
|
|
18
|
+
*
|
|
19
|
+
* Not optional. An icon button has no name of its own, and a header full of
|
|
20
|
+
* unlabelled glyphs is a header a screen reader reads as "button, button,
|
|
21
|
+
* button".
|
|
22
|
+
*/
|
|
23
|
+
label: string;
|
|
24
|
+
icon: ReactNode;
|
|
25
|
+
onClick?: () => void;
|
|
26
|
+
/** Renders an anchor rather than a button. Navigation is not a click. */
|
|
27
|
+
href?: string;
|
|
28
|
+
/**
|
|
29
|
+
* A number worth showing on the glyph — saved bookmarks, unread replies.
|
|
30
|
+
* It is folded into the accessible name too: the badge is decorative, and a
|
|
31
|
+
* reader who cannot see it would otherwise lose the count entirely.
|
|
32
|
+
*/
|
|
33
|
+
count?: number;
|
|
34
|
+
/** A toggle rather than a command. Renders `aria-pressed`. */
|
|
35
|
+
active?: boolean;
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
/** Stays visible when the rest collapse. For the one action that matters. */
|
|
38
|
+
pinned?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface ChatHeaderProps extends Omit<HTMLAttributes<HTMLElement>, "title" | "children"> {
|
|
41
|
+
/** What the conversation is about, so the reader can see where they are. */
|
|
42
|
+
title?: ReactNode;
|
|
43
|
+
/** The second line: the model, a count, a state. */
|
|
44
|
+
subtitle?: ReactNode;
|
|
45
|
+
/** Logo or agent avatar, drawn before the title. */
|
|
46
|
+
avatar?: ReactNode;
|
|
47
|
+
/**
|
|
48
|
+
* How the title is exposed to assistive technology. A heading is what makes
|
|
49
|
+
* the conversation reachable by heading navigation; the level belongs to the
|
|
50
|
+
* host's document, not to us, so it is a prop. `false` renders plain text.
|
|
51
|
+
*/
|
|
52
|
+
headingLevel?: 1 | 2 | 3 | 4 | 5 | 6 | false;
|
|
53
|
+
/** Long titles get an ellipsis rather than a second line. */
|
|
54
|
+
truncate?: boolean;
|
|
55
|
+
/** Renders a back button. */
|
|
56
|
+
onBack?: () => void;
|
|
57
|
+
/** Renders a back link instead — navigation belongs in an anchor. */
|
|
58
|
+
backHref?: string;
|
|
59
|
+
backLabel?: string;
|
|
60
|
+
/** The managed actions. These are what collapse. */
|
|
61
|
+
actions?: ChatHeaderAction[];
|
|
62
|
+
overflowLabel?: string;
|
|
63
|
+
variant?: ChatHeaderVariant;
|
|
64
|
+
size?: ChatHeaderSize;
|
|
65
|
+
/** `center` is the native/mobile arrangement: title centred, actions apart. */
|
|
66
|
+
align?: "start" | "center";
|
|
67
|
+
sticky?: boolean;
|
|
68
|
+
/** Grow a border and a backdrop once the conversation has scrolled under it. */
|
|
69
|
+
elevateOnScroll?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Width, in pixels, below which unpinned actions fold into an overflow menu.
|
|
72
|
+
* `false` never folds. Measured on the header itself, not the viewport, so
|
|
73
|
+
* a header in a narrow panel collapses on its own terms.
|
|
74
|
+
*/
|
|
75
|
+
collapseActionsAt?: number | false;
|
|
76
|
+
/**
|
|
77
|
+
* Render as `<header>`, which is a `banner` landmark at the top level of a
|
|
78
|
+
* page. Set `false` for a header inside a panel or a card, where claiming
|
|
79
|
+
* the page's banner would be a lie.
|
|
80
|
+
*/
|
|
81
|
+
landmark?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Anything the kit should not manage — a segmented control, a model picker.
|
|
84
|
+
* Sits in the end region before the actions, and never collapses: the kit
|
|
85
|
+
* cannot summarise what it cannot read.
|
|
86
|
+
*/
|
|
87
|
+
children?: ReactNode;
|
|
88
|
+
}
|
|
89
|
+
export declare const ChatHeader: import('react').ForwardRefExoticComponent<ChatHeaderProps & import('react').RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { InlineAnimConfig } from './ChatInput';
|
|
3
|
+
export interface AddCardsOverlayProps {
|
|
4
|
+
isAddOpen: boolean;
|
|
5
|
+
setIsAddOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
6
|
+
onAdd?: (label?: string) => void;
|
|
7
|
+
showInlineGlyph: boolean;
|
|
8
|
+
showButtons: boolean;
|
|
9
|
+
ac: InlineAnimConfig | undefined;
|
|
10
|
+
}
|
|
11
|
+
export declare function AddCardsOverlay({ isAddOpen, setIsAddOpen, onAdd, showInlineGlyph, showButtons, ac, }: AddCardsOverlayProps): React.JSX.Element;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Attachment } from '../Attachments/Attachments';
|
|
2
|
+
import { TranscribeHandler } from '../voice/useVoiceInput';
|
|
3
|
+
export type ChatInputState = "idle" | "typing" | "responding" | "resting";
|
|
4
|
+
export interface InlineAnimConfig {
|
|
5
|
+
bubble: {
|
|
6
|
+
stiffness: number;
|
|
7
|
+
damping: number;
|
|
8
|
+
mass: number;
|
|
9
|
+
};
|
|
10
|
+
button: {
|
|
11
|
+
stiffness: number;
|
|
12
|
+
damping: number;
|
|
13
|
+
mass: number;
|
|
14
|
+
staggerEnter: number;
|
|
15
|
+
staggerExit: number;
|
|
16
|
+
};
|
|
17
|
+
addButton: {
|
|
18
|
+
duration: number;
|
|
19
|
+
visualDuration: number;
|
|
20
|
+
bounce: number;
|
|
21
|
+
};
|
|
22
|
+
enterButton: {
|
|
23
|
+
duration: number;
|
|
24
|
+
visualDuration: number;
|
|
25
|
+
bounce: number;
|
|
26
|
+
};
|
|
27
|
+
ripple: {
|
|
28
|
+
scaleX: number;
|
|
29
|
+
duration: number;
|
|
30
|
+
pulseDuration: number;
|
|
31
|
+
};
|
|
32
|
+
wrap: {
|
|
33
|
+
nearThreshold: number;
|
|
34
|
+
exitThreshold: number;
|
|
35
|
+
preExpandHeight: number;
|
|
36
|
+
slideInDelay: number;
|
|
37
|
+
/**
|
|
38
|
+
* How long the controls take to leave when the composer grows into a
|
|
39
|
+
* second line, in seconds.
|
|
40
|
+
*
|
|
41
|
+
* It was a literal `0.15` in three places, which is why the exit could not
|
|
42
|
+
* be tuned while everything around it could: the dial reached the springs
|
|
43
|
+
* that bring the row back and nothing that takes it away.
|
|
44
|
+
*/
|
|
45
|
+
exitDuration: number;
|
|
46
|
+
};
|
|
47
|
+
actions: {
|
|
48
|
+
staggerDelay: number;
|
|
49
|
+
duration: number;
|
|
50
|
+
stiffness: number;
|
|
51
|
+
damping: number;
|
|
52
|
+
};
|
|
53
|
+
addCards: {
|
|
54
|
+
staggerDelay: number;
|
|
55
|
+
stiffness: number;
|
|
56
|
+
damping: number;
|
|
57
|
+
inputScale: number;
|
|
58
|
+
inputBlur: number;
|
|
59
|
+
angle1: number;
|
|
60
|
+
angle2: number;
|
|
61
|
+
angle3: number;
|
|
62
|
+
hoverPull: number;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export declare const defaultInlineAnimConfig: InlineAnimConfig;
|
|
66
|
+
export interface ChatInputHandle {
|
|
67
|
+
focus: (options?: FocusOptions) => void;
|
|
68
|
+
setValue: (value: string) => void;
|
|
69
|
+
getValue: () => string;
|
|
70
|
+
}
|
|
71
|
+
export interface ChatInputProps {
|
|
72
|
+
state: ChatInputState;
|
|
73
|
+
value: string;
|
|
74
|
+
onChange: (value: string) => void;
|
|
75
|
+
/**
|
|
76
|
+
* What was typed, and what is going with it.
|
|
77
|
+
*
|
|
78
|
+
* The second argument is the whole reason attachments exist: before it, one
|
|
79
|
+
* could be picked and shown in the composer and then quietly dropped on
|
|
80
|
+
* send, which is worse than not offering it.
|
|
81
|
+
*/
|
|
82
|
+
onSubmit: (value: string, attachments: Attachment[]) => void;
|
|
83
|
+
onStop?: () => void;
|
|
84
|
+
onAdd?: () => void;
|
|
85
|
+
/**
|
|
86
|
+
* What is attached, controlled. Leave it out and the composer keeps its own
|
|
87
|
+
* — the same rule `useDisclosure` follows.
|
|
88
|
+
*/
|
|
89
|
+
attachments?: Attachment[];
|
|
90
|
+
/**
|
|
91
|
+
* Files somebody picked. Given, this is called instead of the composer
|
|
92
|
+
* attaching them itself — for a host that wants to upload first and attach
|
|
93
|
+
* the URL it gets back.
|
|
94
|
+
*/
|
|
95
|
+
onAttach?: (files: File[]) => void;
|
|
96
|
+
onRemoveAttachment?: (id: string) => void;
|
|
97
|
+
/** Passed to the file picker. Defaults to images. */
|
|
98
|
+
accept?: string;
|
|
99
|
+
/** More than one at a time. Off by default. */
|
|
100
|
+
multiple?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Audio in, words out. Given, the composer offers a microphone where the
|
|
103
|
+
* send glyph would be while there is nothing to send; left out, there is no
|
|
104
|
+
* microphone at all — the same rule `onRemove` follows on `<Attachments>`.
|
|
105
|
+
*
|
|
106
|
+
* The kit records and hands over a `Blob`; what it does with the audio is
|
|
107
|
+
* the half a host owns. See `useVoiceInput`.
|
|
108
|
+
*/
|
|
109
|
+
onTranscribe?: TranscribeHandler;
|
|
110
|
+
onCopy?: (value: string) => void;
|
|
111
|
+
onEdit?: (value: string) => void;
|
|
112
|
+
onCancelEdit?: () => void;
|
|
113
|
+
isEditing?: boolean;
|
|
114
|
+
placeholder?: string;
|
|
115
|
+
animationConfig?: InlineAnimConfig;
|
|
116
|
+
style?: React.CSSProperties;
|
|
117
|
+
}
|
|
118
|
+
export declare const ChatInput: import('react').ForwardRefExoticComponent<ChatInputProps & import('react').RefAttributes<ChatInputHandle>>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { InlineAnimConfig } from './ChatInput';
|
|
3
|
+
export interface HoverActionsRowProps {
|
|
4
|
+
showActions: boolean;
|
|
5
|
+
showReadMore: boolean;
|
|
6
|
+
isExpanded: boolean;
|
|
7
|
+
setIsExpanded: React.Dispatch<React.SetStateAction<boolean>>;
|
|
8
|
+
onCopy?: (value: string) => void;
|
|
9
|
+
onEdit?: (value: string) => void;
|
|
10
|
+
value: string;
|
|
11
|
+
ac: InlineAnimConfig | undefined;
|
|
12
|
+
}
|
|
13
|
+
export declare function HoverActionsRow({ showActions, showReadMore, isExpanded, setIsExpanded, onCopy, onEdit, value, ac, }: HoverActionsRowProps): React.JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Glyph slot for the send/stop/check action. Static Lucide icons swap
|
|
3
|
+
* with a vertical slide + fade — outgoing slides up and out, incoming
|
|
4
|
+
* slides up from below. Single slot, single transition.
|
|
5
|
+
*/
|
|
6
|
+
export interface MorphGlyphProps {
|
|
7
|
+
mode: "send" | "stop" | "check" | "mic";
|
|
8
|
+
/** Icon colour. Inherits from whatever contains it unless set. */
|
|
9
|
+
color?: string;
|
|
10
|
+
/** Slide duration in seconds. */
|
|
11
|
+
duration?: number;
|
|
12
|
+
/** Icon pixel size. */
|
|
13
|
+
size?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function MorphGlyph({ mode, color, duration, size, }: MorphGlyphProps): import("react").JSX.Element;
|