@theoremjs/react 0.3.4-next.641.g6835640 → 0.3.4-next.645.gf4efc36

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/README.md CHANGED
@@ -172,7 +172,7 @@ The profile, the keys, and the system prompt stay on the server. The browser rec
172
172
  | `initialFiles` | The files that the composer starts with, staged to send. The component reads them once, when it mounts. |
173
173
  | `initialVoice` | The voice notes that the composer starts with, staged to send. The component reads them once, when it mounts. |
174
174
  | `initialPending` | The messages that the composer starts with set aside: queued, stashed, or steering, as `createComposerPendingMessage` from `@theoremjs/agents/interface` makes them. The component reads them once, when it mounts. |
175
- | `chatRef` | Sends a message from your code. See below. |
175
+ | `chatRef` | Sends a message, stops a reply, or focuses the composer from your code. See below. |
176
176
  | `composer` | `false` leaves the composer out. The chat is the transcript alone, and your own control sends through `chatRef`. Default: `true`. |
177
177
 
178
178
  ### Resume a conversation
@@ -204,7 +204,7 @@ A profile whose `providerContinuation.history` is `'stateless'` keeps no convers
204
204
  ### Send a message from your code
205
205
 
206
206
  `chatRef` gives you `send(text, files?)`. It sends the text and optional array of browser files as the user. Files use the same profile validation and encoding as composer attachments. When the reply is complete, it returns the blocks that the turn added. It returns `null` if the chat cannot accept a message now. This happens while a reply streams or waits for a gate.
207
- `chatRef` also gives you `stop()`. It stops the reply that streams, as the composer's stop button does.
207
+ `chatRef` also gives you `stop()`. It stops the reply that streams, as the composer's stop button does. And it gives you `focus()`, which puts the keyboard in the composer, for example after your own control clears the chat.
208
208
 
209
209
  ```tsx
210
210
  const chat = useRef<TheoremChatHandle>(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theoremjs/react",
3
- "version": "0.3.4-next.641.g6835640",
3
+ "version": "0.3.4-next.645.gf4efc36",
4
4
  "description": "React bindings for Theorem: headless hooks + transport, an Astryx chat UI, and a Web-standard server handler.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -60,8 +60,8 @@
60
60
  "@stylexjs/stylex": "0.19.0",
61
61
  "react": "^19.0.0",
62
62
  "react-dom": "^19.0.0",
63
- "@theoremjs/agents": "^0.3.4-next.641.g6835640",
64
- "@theoremjs/web": "^0.3.4-next.641.g6835640"
63
+ "@theoremjs/agents": "^0.3.4-next.645.gf4efc36",
64
+ "@theoremjs/web": "^0.3.4-next.645.gf4efc36"
65
65
  },
66
66
  "peerDependenciesMeta": {
67
67
  "@astryxdesign/core": {
@@ -101,7 +101,7 @@ export type TheoremChatProps = {
101
101
  * forget it.
102
102
  */
103
103
  onConversationChange?: (ref: string | undefined) => void;
104
- /** Lets the host send a message as the composer would; see {@link TheoremChatHandle}. */
104
+ /** Lets the host send a message as the composer would, stop a reply, or focus the composer; see {@link TheoremChatHandle}. */
105
105
  chatRef?: Ref<TheoremChatHandle>;
106
106
  /**
107
107
  * `false` leaves the composer out: the chat is the transcript alone, and your own control sends
@@ -118,6 +118,8 @@ export type TheoremChatHandle = {
118
118
  send: (text: string, files?: readonly File[]) => Promise<SentTurn | null>;
119
119
  /** Stops the reply that is streaming, as the composer's stop button does. */
120
120
  stop: () => void;
121
+ /** Puts the keyboard in the composer. */
122
+ focus: () => void;
121
123
  };
122
124
  /**
123
125
  * 50% of the chat's width, but never narrower than 640px (or the full width,
package/ui/TheoremChat.js CHANGED
@@ -70,14 +70,17 @@ function ChatBody({ transport, iface, placeholder, emptyState, density, maxWidth
70
70
  onTurnEvent,
71
71
  });
72
72
  const { sendText, handleStop } = chat;
73
- useImperativeHandle(chatRef, () => ({ send: sendText, stop: handleStop }), [
74
- sendText,
75
- handleStop,
76
- ]);
77
73
  const blocks = useMemo(() => [...chat.blocks, ...chat.streamBlocks], [chat.blocks, chat.streamBlocks]);
78
74
  const handle = t('@theorem.agent.handle', { handle: iface.identity.handle });
79
75
  const landing = blocks.length === 0;
80
76
  const inputRef = useRef(null);
77
+ useImperativeHandle(chatRef, () => ({
78
+ send: sendText,
79
+ stop: handleStop,
80
+ focus: () => {
81
+ inputRef.current?.focus();
82
+ },
83
+ }), [sendText, handleStop]);
81
84
  const composerRef = useGlide(landing, () => inputRef.current?.focus());
82
85
  const inspector = useTraceInspector(iface, transport.traces, trace);
83
86
  const header = _jsx(SidePanelHeader, { floating: true, children: inspector.toggle });