inline-chat-kit 0.59.2 → 0.61.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.
@@ -1,4 +1,5 @@
1
1
  import { HTMLAttributes, ReactNode } from 'react';
2
+ import { ButtonVariant } from '../Button/Button';
2
3
  export type ChatHeaderVariant = "plain" | "glass" | "bordered";
3
4
  export type ChatHeaderSize = "s" | "m" | "l";
4
5
  /**
@@ -36,6 +37,12 @@ export interface ChatHeaderAction {
36
37
  disabled?: boolean;
37
38
  /** Stays visible when the rest collapse. For the one action that matters. */
38
39
  pinned?: boolean;
40
+ /**
41
+ * How it is drawn while it is in the header. `"secondary"` — naked until
42
+ * touched — by default; `"primary"` for the one a host wants to stand out.
43
+ * Folded into the menu, every action is a menu item and this does not apply.
44
+ */
45
+ variant?: Exclude<ButtonVariant, "glass">;
39
46
  }
40
47
  export interface ChatHeaderProps extends Omit<HTMLAttributes<HTMLElement>, "title" | "children"> {
41
48
  /** What the conversation is about, so the reader can see where they are. */
@@ -24,5 +24,7 @@ export interface AddCardsOverlayProps {
24
24
  showInlineGlyph: boolean;
25
25
  showButtons: boolean;
26
26
  ac: InlineAnimConfig | undefined;
27
+ /** How big the composer's controls are, in pixels — `--ick-composer-control`. 28 by default. */
28
+ control?: number;
27
29
  }
28
- export declare function AddCardsOverlay({ isAddOpen, setIsAddOpen, onAdd, items, showInlineGlyph, showButtons, ac, }: AddCardsOverlayProps): React.JSX.Element;
30
+ export declare function AddCardsOverlay({ isAddOpen, setIsAddOpen, onAdd, items, showInlineGlyph, control, showButtons, ac, }: AddCardsOverlayProps): React.JSX.Element;
@@ -132,6 +132,13 @@ export interface ChatInputProps {
132
132
  menu?: ComposerMenuItem[] | false;
133
133
  /** Every word the composer says. See `ChatLabels`. */
134
134
  labels?: Partial<ChatInputLabels>;
135
+ /**
136
+ * Given, watched for: called once the bubble has come to rest at its place
137
+ * — within a few pixels of it, which the eye reads as arrived, rather than
138
+ * when the spring finally stops, most of a second later. Called at once if
139
+ * it never moves. Keep it stable. See `ChatTurnRow`'s `answerAfterTravel`.
140
+ */
141
+ onLanded?: () => void;
135
142
  animationConfig?: InlineAnimConfig;
136
143
  style?: React.CSSProperties;
137
144
  }
@@ -0,0 +1,18 @@
1
+ import { RefObject } from 'react';
2
+ /** What the composer's controls were before they were a token, and still are by default. */
3
+ export declare const COMPOSER_CONTROL = 28;
4
+ /**
5
+ * `--ick-composer-control` in pixels, for the parts of the composer Motion
6
+ * animates.
7
+ *
8
+ * The row of controls opens and closes by animating each one's width from
9
+ * nothing to its size, and a spring can only run between two numbers — not to
10
+ * `var(--…)`, and not to `2rem`. So the token is laid out once, on a probe as
11
+ * wide as it says, and read back. Everything that is not animated uses the
12
+ * token itself.
13
+ *
14
+ * Read again when the pointer changes, because the touch block of the tokens
15
+ * sets its own value. A host that changes the token at runtime remounts the
16
+ * composer, or does not need the row to follow until the next one.
17
+ */
18
+ export declare function useComposerControl(ref: RefObject<HTMLElement | null>): number;
@@ -33,6 +33,28 @@ export interface ChatTurnRowProps {
33
33
  onArtifactChange?: (artifactId: string | null) => void;
34
34
  /** Stagger for the entrance, in seconds. */
35
35
  entranceDelay?: number;
36
+ /**
37
+ * How the row arrives. `"rise"` (the default): it fades in from a little
38
+ * above its place, which is how a new turn reads as arriving. `"fade"`: in
39
+ * place, opacity only.
40
+ *
41
+ * A composer docked at the bottom edge is what the second is for. It is not
42
+ * arriving anywhere — it is the box the reader types into, there a moment
43
+ * ago — so rising into place read as the input jumping 16px up and back on
44
+ * every send.
45
+ */
46
+ entrance?: "rise" | "fade";
47
+ /**
48
+ * Hold the answer back until the sent message has finished travelling.
49
+ *
50
+ * Docked, a sent message travels from the composer at the bottom to the top
51
+ * of the view, and its answer's "…" appeared at the top the moment it was
52
+ * sent — two things moving in opposite directions, the answer starting
53
+ * above a question that had not arrived yet. Held, the question lands
54
+ * first and the answer begins under it. The answer still takes its room the
55
+ * whole time, invisibly, so where the view is anchored does not change.
56
+ */
57
+ answerAfterTravel?: boolean;
36
58
  /** Passed through to the highlighter over the answer. */
37
59
  selectionMode?: "marker" | "precise";
38
60
  /**
@@ -145,4 +167,4 @@ export interface ChatTurnRowProps {
145
167
  labels?: ChatLabels;
146
168
  className?: string;
147
169
  }
148
- export declare const ChatTurnRow: import('react').MemoExoticComponent<({ turn, isActiveInput, inputRef, placeholder, animationConfig, foldMotion, openArtifactId, onOpenArtifact, onArtifactChange, entranceDelay, selectionMode, highlights, questionAlign, onDraft, onSubmit, onStop, busy, onEdit, onCancelEdit, onCopy, onHighlight, onReplyInThread, onRegenerate, onShowVersion, onFeedback, feedback, answerActions, onAnswerQuestion, onEditQuestion, onDecideApproval, renderPart, composerMenu, labels, className, onTranscribe, }: ChatTurnRowProps) => import("react").JSX.Element>;
170
+ export declare const ChatTurnRow: import('react').MemoExoticComponent<({ turn, isActiveInput, inputRef, placeholder, animationConfig, foldMotion, openArtifactId, onOpenArtifact, onArtifactChange, entranceDelay, entrance, answerAfterTravel, selectionMode, highlights, questionAlign, onDraft, onSubmit, onStop, busy, onEdit, onCancelEdit, onCopy, onHighlight, onReplyInThread, onRegenerate, onShowVersion, onFeedback, feedback, answerActions, onAnswerQuestion, onEditQuestion, onDecideApproval, renderPart, composerMenu, labels, className, onTranscribe, }: ChatTurnRowProps) => import("react").JSX.Element>;
@@ -0,0 +1,102 @@
1
+ import { ButtonHTMLAttributes, ComponentType, MouseEventHandler, ReactNode, RefAttributes } from 'react';
2
+ import { ButtonSize, ButtonVariant } from '../Button/Button';
3
+ /**
4
+ * What every button the kit draws is for — the same names it carries in
5
+ * `data-ick-role`. A host's button can switch on it.
6
+ *
7
+ * `send`, `stop` and `save` are listed because they are roles, but they are
8
+ * never handed to a host's component: the composer's glyph morphs between the
9
+ * three inside the button, and that animation is the kit's. They are themed
10
+ * through the `--ick-btn-primary-*` tokens on `[data-ick-role="send"]` and its
11
+ * siblings instead.
12
+ */
13
+ export type KitButtonRole = "send" | "stop" | "save" | "add" | "dictate" | "cancel-edit" | "add-close" | "read-more" | "message-action" | "answer-action" | "suggestion" | "back" | "header-action" | "header-more" | "header-menu-item" | "approval-once" | "approval-always" | "approval-deny" | "question-next" | "highlight-action" | "thread-save" | "thread-close" | "pane-expand" | "pane-close" | "remove-attachment";
14
+ /**
15
+ * The box the kit has laid out for a button. A hint: a host's button is free
16
+ * to draw its own corners.
17
+ *
18
+ * - `square` — an icon on its own. The box is as wide as it is tall.
19
+ * - `pill` — a short text button standing on its own, as a chip: an opener in
20
+ * an empty conversation, an action over a highlight, "Read more".
21
+ * - `default` — a text button in a row of actions.
22
+ */
23
+ export type KitButtonShape = "pill" | "square" | "default";
24
+ /**
25
+ * Everything the kit hands a host's button.
26
+ *
27
+ * The kit owns the layout and the behaviour: the box this button sits in, its
28
+ * size, where it goes, how it arrives and leaves, its 44px hit area on a
29
+ * touch screen, and what it does when pressed. The host owns the paint:
30
+ * colour, border, radius, font, shadow, what hover and press look like, and
31
+ * the focus ring.
32
+ *
33
+ * So a host's component has to:
34
+ *
35
+ * - **forward its ref** to the element (`forwardRef`) — focus is moved to it,
36
+ * and the header's "…" menu is anchored by it;
37
+ * - **render a `<button>`** — the kit relies on its keyboard behaviour;
38
+ * - **spread what it does not use** onto that `<button>`: the `aria-*`,
39
+ * `data-*`, `title`, `role`, `tabIndex`, `type`, `onClick` and the other
40
+ * handlers. `kitRole`, `variant`, `size`, `shape`, `icon`, `iconRight`,
41
+ * `loading` and `pressed` are the kit's words for things and are not
42
+ * attributes: take them out first;
43
+ * - **fill the box it is given** — the kit sets its height, and on `square`
44
+ * its width, and positions it. Nothing the host draws should move it;
45
+ * - **show focus** — the kit's own ring is not drawn on a host's button.
46
+ *
47
+ * In development the kit warns, once per role, about a button that breaks one
48
+ * of the first two rules, drops the `aria-*` or `data-ick-*` it was given, or
49
+ * shows no change on keyboard focus.
50
+ */
51
+ export interface KitButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type" | "children" | "disabled" | "onClick"> {
52
+ /** What the button is for. Also on the element as `data-ick-role`. */
53
+ kitRole: KitButtonRole;
54
+ /** What the kit would have drawn: a hint for picking the host's own variant. */
55
+ variant: ButtonVariant;
56
+ /** Which step of `--ick-control-*` the box is. The box is sized already. */
57
+ size: ButtonSize;
58
+ shape: KitButtonShape;
59
+ /** Leading icon. With no `children` it is the whole button, and `aria-label` names it. */
60
+ icon?: ReactNode;
61
+ iconRight?: ReactNode;
62
+ children?: ReactNode;
63
+ disabled?: boolean;
64
+ /** Working: draw a spinner if you have one. `disabled` and `aria-busy` are set too. */
65
+ loading?: boolean;
66
+ /** A toggle that is on. `aria-pressed` is set too. */
67
+ pressed?: boolean;
68
+ /** Always `"button"`. A host's button inside a form must not submit it. */
69
+ type: "button";
70
+ onClick?: MouseEventHandler<HTMLButtonElement>;
71
+ "data-ick-role": KitButtonRole;
72
+ "data-ick-variant": ButtonVariant;
73
+ /** Which of several the role is — `copy`, `edit`, a header action's `id`. */
74
+ "data-ick-action"?: string;
75
+ /** Anything else the kit marks a button with, such as `data-voice` on the microphone. */
76
+ [data: `data-${string}`]: string | number | boolean | undefined;
77
+ }
78
+ /** A host's button, as the kit takes it. It must forward its ref. */
79
+ export type KitButtonComponent = ComponentType<KitButtonProps & RefAttributes<HTMLButtonElement>>;
80
+ /**
81
+ * The components a host can draw in place of the kit's.
82
+ *
83
+ * One, so far: `Button`, used for every button the kit draws but the
84
+ * composer's send / stop / save glyph.
85
+ */
86
+ export interface ChatComponents {
87
+ Button?: KitButtonComponent;
88
+ }
89
+ /**
90
+ * Hands a host's components to every kit component beneath it, the way
91
+ * `LabelsProvider` hands it the words. `ChatExperience` sets one up from its
92
+ * `components` prop; a host assembling the pieces itself — `ChatTurnRow`,
93
+ * `ChatHeader`, `Approval` — wraps them in this.
94
+ *
95
+ * Nests: an inner provider's components override the outer one's, one by one.
96
+ */
97
+ export declare function ComponentsProvider({ components, children, }: {
98
+ components?: ChatComponents;
99
+ children?: ReactNode;
100
+ }): import("react").JSX.Element;
101
+ /** The host's components, where there are any. */
102
+ export declare function useChatComponents(): ChatComponents;
package/dist/demo.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { et as e, n as t, t as n } from "./ChatExperience-umh3nGe_.js";
2
+ import { n as e, t, tt as n } from "./ChatExperience-BQgjY0-K.js";
3
3
  import { useCallback as r, useRef as i, useState as a } from "react";
4
4
  import { jsx as o, jsxs as s } from "react/jsx-runtime";
5
5
  import { AnimatePresence as c, motion as l } from "motion/react";
@@ -151,7 +151,7 @@ var h = {
151
151
  offsetOut: -10,
152
152
  blurOut: 10
153
153
  };
154
- function v({ logo: t, back: n, onStart: r, welcome: i = "Welcome", title: a = "This is inline chat experience", version: c = "v1.0.0", description: u = "Exploration of having the input be the same as response. Or better said input morphing into chat bubble and maintains the continuous experience.", status: d = h, motionConfig: f }) {
154
+ function v({ logo: e, back: t, onStart: r, welcome: i = "Welcome", title: a = "This is inline chat experience", version: c = "v1.0.0", description: u = "Exploration of having the input be the same as response. Or better said input morphing into chat bubble and maintains the continuous experience.", status: d = h, motionConfig: f }) {
155
155
  let m = {
156
156
  ..._,
157
157
  ...f
@@ -204,9 +204,9 @@ function v({ logo: t, back: n, onStart: r, welcome: i = "Welcome", title: a = "T
204
204
  children: [
205
205
  /* @__PURE__ */ s("div", {
206
206
  className: g.infoContainer,
207
- children: [t && /* @__PURE__ */ o(l.div, {
207
+ children: [e && /* @__PURE__ */ o(l.div, {
208
208
  variants: y,
209
- children: t
209
+ children: e
210
210
  }), /* @__PURE__ */ s("div", {
211
211
  className: g.content,
212
212
  children: [/* @__PURE__ */ s("div", {
@@ -253,12 +253,12 @@ function v({ logo: t, back: n, onStart: r, welcome: i = "Welcome", title: a = "T
253
253
  /* @__PURE__ */ s(l.div, {
254
254
  variants: y,
255
255
  className: g.buttonWrapper,
256
- children: [/* @__PURE__ */ o(e, {
256
+ children: [/* @__PURE__ */ o(n, {
257
257
  variant: "glass",
258
258
  size: "m",
259
259
  onClick: r,
260
260
  children: "Start experience"
261
- }), n]
261
+ }), t]
262
262
  })
263
263
  ]
264
264
  })
@@ -585,9 +585,9 @@ async function* H(e, { signal: t }) {
585
585
  }
586
586
  }
587
587
  var U = { plan: "ick-plan-nXLe" }, W = 8e3, G = 900;
588
- function K({ logo: e, back: s, backHref: l = "/", backLabel: f = "Back to home", skipIntro: p = !1, theme: m, onThemeChange: h, cursor: g = !0, animationConfig: _, foldMotion: y, feedDelay: b, introMotion: x, composer: S = "inline" }) {
588
+ function K({ logo: n, back: s, backHref: l = "/", backLabel: f = "Back to home", skipIntro: p = !1, theme: m, onThemeChange: h, cursor: g = !0, animationConfig: _, foldMotion: y, feedDelay: b, introMotion: x, composer: S = "inline" }) {
589
589
  let [C, w] = a(p), [T, D] = a(S), O = T === "docked";
590
- t(m === void 0 ? void 0 : m);
590
+ e(m === void 0 ? void 0 : m);
591
591
  let k = i({}), A = r((e, t, n, r, i) => {
592
592
  let a = {
593
593
  ...k.current[n] ?? {},
@@ -639,7 +639,7 @@ function K({ logo: e, back: s, backHref: l = "/", backLabel: f = "Back to home",
639
639
  }, []);
640
640
  return /* @__PURE__ */ o(c, {
641
641
  mode: "wait",
642
- children: C ? /* @__PURE__ */ o(n, {
642
+ children: C ? /* @__PURE__ */ o(t, {
643
643
  onSend: B,
644
644
  onTranscribe: H,
645
645
  onThreadReply: V,
@@ -692,7 +692,7 @@ function K({ logo: e, back: s, backHref: l = "/", backLabel: f = "Back to home",
692
692
  onEditQuestion: j,
693
693
  onDecideApproval: M
694
694
  }, "chat") : /* @__PURE__ */ o(v, {
695
- logo: e,
695
+ logo: n,
696
696
  back: s,
697
697
  onStart: () => w(!0),
698
698
  motionConfig: x
package/dist/index.d.ts CHANGED
@@ -11,6 +11,8 @@ export { mergeParts } from './turnParts/turnParts';
11
11
  export type { CustomPart, CustomPartContext, TurnPart, TurnPartUpdate } from './turnParts/turnParts';
12
12
  export { LabelsProvider, defaultLabels } from './labels/labels';
13
13
  export type { ChatLabels, AnswerActionsLabels, ApprovalLabels, BranchLabels, ChainLabels, ChatInputLabels, ContextLabels, ReasoningLabels, SourcesLabels, TaskListLabels, ToolLabels, VoiceLabels, } from './labels/labels';
14
+ export { ComponentsProvider } from './components/components';
15
+ export type { ChatComponents, KitButtonComponent, KitButtonProps, KitButtonRole, KitButtonShape, } from './components/components';
14
16
  export type { ChatAnnouncements, ChatTurn, SendContext, SendHandler, UseChatTurnsOptions, UseChatTurnsResult, } from './useChatTurns/useChatTurns';
15
17
  export { useVoiceInput } from './voice/useVoiceInput';
16
18
  export type { TranscribeContext, TranscribeHandler, UseVoiceInputOptions, VoiceInput, VoiceState, } from './voice/useVoiceInput';