@jupyter/chat 0.3.0 → 0.4.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/lib/components/chat-input.js +18 -3
- package/lib/model.d.ts +17 -0
- package/lib/model.js +13 -0
- package/package.json +2 -15
- package/src/components/chat-input.tsx +24 -3
- package/src/model.ts +25 -0
|
@@ -15,11 +15,26 @@ export function ChatInput(props) {
|
|
|
15
15
|
const autocompletion = useRef();
|
|
16
16
|
const [input, setInput] = useState(props.value || '');
|
|
17
17
|
const [sendWithShiftEnter, setSendWithShiftEnter] = useState((_a = model.config.sendWithShiftEnter) !== null && _a !== void 0 ? _a : false);
|
|
18
|
+
// store reference to the input element to enable focusing it easily
|
|
19
|
+
const inputRef = useRef();
|
|
18
20
|
useEffect(() => {
|
|
19
|
-
|
|
21
|
+
var _a;
|
|
22
|
+
const configChanged = (_, config) => {
|
|
20
23
|
var _a;
|
|
21
24
|
setSendWithShiftEnter((_a = config.sendWithShiftEnter) !== null && _a !== void 0 ? _a : false);
|
|
22
|
-
}
|
|
25
|
+
};
|
|
26
|
+
model.configChanged.connect(configChanged);
|
|
27
|
+
const focusInputElement = () => {
|
|
28
|
+
if (inputRef.current) {
|
|
29
|
+
inputRef.current.focus();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
(_a = model.focusInputSignal) === null || _a === void 0 ? void 0 : _a.connect(focusInputElement);
|
|
33
|
+
return () => {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
(_a = model.configChanged) === null || _a === void 0 ? void 0 : _a.disconnect(configChanged);
|
|
36
|
+
(_b = model.focusInputSignal) === null || _b === void 0 ? void 0 : _b.disconnect(focusInputElement);
|
|
37
|
+
};
|
|
23
38
|
}, [model]);
|
|
24
39
|
// The autocomplete commands options.
|
|
25
40
|
const [commandOptions, setCommandOptions] = useState([]);
|
|
@@ -131,7 +146,7 @@ export function ChatInput(props) {
|
|
|
131
146
|
padding: 2
|
|
132
147
|
}
|
|
133
148
|
}
|
|
134
|
-
}, renderInput: params => (React.createElement(TextField, { ...params, fullWidth: true, variant: "outlined", multiline: true, onKeyDown: handleKeyDown, placeholder: "Start chatting", InputProps: {
|
|
149
|
+
}, renderInput: params => (React.createElement(TextField, { ...params, fullWidth: true, variant: "outlined", multiline: true, onKeyDown: handleKeyDown, placeholder: "Start chatting", inputRef: inputRef, InputProps: {
|
|
135
150
|
...params.InputProps,
|
|
136
151
|
endAdornment: (React.createElement(InputAdornment, { position: "end" },
|
|
137
152
|
props.onCancel && (React.createElement(IconButton, { size: "small", color: "primary", onClick: onCancel, title: 'Cancel edition', className: clsx(CANCEL_BUTTON_CLASS) },
|
package/lib/model.d.ts
CHANGED
|
@@ -51,6 +51,10 @@ export interface IChatModel extends IDisposable {
|
|
|
51
51
|
* A signal emitting when the viewport change.
|
|
52
52
|
*/
|
|
53
53
|
readonly viewportChanged?: ISignal<IChatModel, number[]>;
|
|
54
|
+
/**
|
|
55
|
+
* A signal emitting when the focus is requested on the input.
|
|
56
|
+
*/
|
|
57
|
+
readonly focusInputSignal?: ISignal<IChatModel, void>;
|
|
54
58
|
/**
|
|
55
59
|
* Send a message, to be defined depending on the chosen technology.
|
|
56
60
|
* Default to no-op.
|
|
@@ -104,6 +108,10 @@ export interface IChatModel extends IDisposable {
|
|
|
104
108
|
* @param count - the number of messages to delete.
|
|
105
109
|
*/
|
|
106
110
|
messagesDeleted(index: number, count: number): void;
|
|
111
|
+
/**
|
|
112
|
+
* Function to request the focus on the input of the chat.
|
|
113
|
+
*/
|
|
114
|
+
focusInput(): void;
|
|
107
115
|
}
|
|
108
116
|
/**
|
|
109
117
|
* The default chat model implementation.
|
|
@@ -166,6 +174,10 @@ export declare class ChatModel implements IChatModel {
|
|
|
166
174
|
* A signal emitting when the viewport change.
|
|
167
175
|
*/
|
|
168
176
|
get viewportChanged(): ISignal<IChatModel, number[]>;
|
|
177
|
+
/**
|
|
178
|
+
* A signal emitting when the focus is requested on the input.
|
|
179
|
+
*/
|
|
180
|
+
get focusInputSignal(): ISignal<IChatModel, void>;
|
|
169
181
|
/**
|
|
170
182
|
* Send a message, to be defined depending on the chosen technology.
|
|
171
183
|
* Default to no-op.
|
|
@@ -207,6 +219,10 @@ export declare class ChatModel implements IChatModel {
|
|
|
207
219
|
* @param count - the number of messages to delete.
|
|
208
220
|
*/
|
|
209
221
|
messagesDeleted(index: number, count: number): void;
|
|
222
|
+
/**
|
|
223
|
+
* Function to request the focus on the input of the chat.
|
|
224
|
+
*/
|
|
225
|
+
focusInput(): void;
|
|
210
226
|
/**
|
|
211
227
|
* Add unread messages to the list.
|
|
212
228
|
* @param indexes - list of new indexes.
|
|
@@ -236,6 +252,7 @@ export declare class ChatModel implements IChatModel {
|
|
|
236
252
|
private _configChanged;
|
|
237
253
|
private _unreadChanged;
|
|
238
254
|
private _viewportChanged;
|
|
255
|
+
private _focusInputSignal;
|
|
239
256
|
}
|
|
240
257
|
/**
|
|
241
258
|
* The chat model namespace.
|
package/lib/model.js
CHANGED
|
@@ -24,6 +24,7 @@ export class ChatModel {
|
|
|
24
24
|
this._configChanged = new Signal(this);
|
|
25
25
|
this._unreadChanged = new Signal(this);
|
|
26
26
|
this._viewportChanged = new Signal(this);
|
|
27
|
+
this._focusInputSignal = new Signal(this);
|
|
27
28
|
const config = (_a = options.config) !== null && _a !== void 0 ? _a : {};
|
|
28
29
|
// Stack consecutive messages from the same user by default.
|
|
29
30
|
this._config = { stackMessages: true, ...config };
|
|
@@ -172,6 +173,12 @@ export class ChatModel {
|
|
|
172
173
|
get viewportChanged() {
|
|
173
174
|
return this._viewportChanged;
|
|
174
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* A signal emitting when the focus is requested on the input.
|
|
178
|
+
*/
|
|
179
|
+
get focusInputSignal() {
|
|
180
|
+
return this._focusInputSignal;
|
|
181
|
+
}
|
|
175
182
|
/**
|
|
176
183
|
* Send a message, to be defined depending on the chosen technology.
|
|
177
184
|
* Default to no-op.
|
|
@@ -268,6 +275,12 @@ export class ChatModel {
|
|
|
268
275
|
this._messages.splice(index, count);
|
|
269
276
|
this._messagesUpdated.emit();
|
|
270
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* Function to request the focus on the input of the chat.
|
|
280
|
+
*/
|
|
281
|
+
focusInput() {
|
|
282
|
+
this._focusInputSignal.emit();
|
|
283
|
+
}
|
|
271
284
|
/**
|
|
272
285
|
* Add unread messages to the list.
|
|
273
286
|
* @param indexes - list of new indexes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyter/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A package that provides UI components that can be used to create a chat in a Jupyterlab extension.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"react-dom": "^18.2.0"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
+
"@jupyterlab/testing": "^4.2.0",
|
|
73
74
|
"@types/jest": "^29.2.0",
|
|
74
75
|
"@types/json-schema": "^7.0.11",
|
|
75
76
|
"@types/react": "^18.2.0",
|
|
@@ -102,20 +103,6 @@
|
|
|
102
103
|
"publishConfig": {
|
|
103
104
|
"access": "public"
|
|
104
105
|
},
|
|
105
|
-
"jupyterlab": {
|
|
106
|
-
"discovery": {
|
|
107
|
-
"server": {
|
|
108
|
-
"managers": [
|
|
109
|
-
"pip"
|
|
110
|
-
],
|
|
111
|
-
"base": {
|
|
112
|
-
"name": "jupyter_chat"
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
"extension": false,
|
|
117
|
-
"schemaDir": "schema"
|
|
118
|
-
},
|
|
119
106
|
"eslintIgnore": [
|
|
120
107
|
"node_modules",
|
|
121
108
|
"dist",
|
|
@@ -18,7 +18,11 @@ import { Send, Cancel } from '@mui/icons-material';
|
|
|
18
18
|
import clsx from 'clsx';
|
|
19
19
|
import { IChatModel } from '../model';
|
|
20
20
|
import { IAutocompletionRegistry } from '../registry';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
AutocompleteCommand,
|
|
23
|
+
IAutocompletionCommandsProps,
|
|
24
|
+
IConfig
|
|
25
|
+
} from '../types';
|
|
22
26
|
|
|
23
27
|
const INPUT_BOX_CLASS = 'jp-chat-input-container';
|
|
24
28
|
const SEND_BUTTON_CLASS = 'jp-chat-send-button';
|
|
@@ -32,10 +36,26 @@ export function ChatInput(props: ChatInput.IProps): JSX.Element {
|
|
|
32
36
|
model.config.sendWithShiftEnter ?? false
|
|
33
37
|
);
|
|
34
38
|
|
|
39
|
+
// store reference to the input element to enable focusing it easily
|
|
40
|
+
const inputRef = useRef<HTMLInputElement>();
|
|
41
|
+
|
|
35
42
|
useEffect(() => {
|
|
36
|
-
|
|
43
|
+
const configChanged = (_: IChatModel, config: IConfig) => {
|
|
37
44
|
setSendWithShiftEnter(config.sendWithShiftEnter ?? false);
|
|
38
|
-
}
|
|
45
|
+
};
|
|
46
|
+
model.configChanged.connect(configChanged);
|
|
47
|
+
|
|
48
|
+
const focusInputElement = () => {
|
|
49
|
+
if (inputRef.current) {
|
|
50
|
+
inputRef.current.focus();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
model.focusInputSignal?.connect(focusInputElement);
|
|
54
|
+
|
|
55
|
+
return () => {
|
|
56
|
+
model.configChanged?.disconnect(configChanged);
|
|
57
|
+
model.focusInputSignal?.disconnect(focusInputElement);
|
|
58
|
+
};
|
|
39
59
|
}, [model]);
|
|
40
60
|
|
|
41
61
|
// The autocomplete commands options.
|
|
@@ -177,6 +197,7 @@ export function ChatInput(props: ChatInput.IProps): JSX.Element {
|
|
|
177
197
|
multiline
|
|
178
198
|
onKeyDown={handleKeyDown}
|
|
179
199
|
placeholder="Start chatting"
|
|
200
|
+
inputRef={inputRef}
|
|
180
201
|
InputProps={{
|
|
181
202
|
...params.InputProps,
|
|
182
203
|
endAdornment: (
|
package/src/model.ts
CHANGED
|
@@ -75,6 +75,11 @@ export interface IChatModel extends IDisposable {
|
|
|
75
75
|
*/
|
|
76
76
|
readonly viewportChanged?: ISignal<IChatModel, number[]>;
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* A signal emitting when the focus is requested on the input.
|
|
80
|
+
*/
|
|
81
|
+
readonly focusInputSignal?: ISignal<IChatModel, void>;
|
|
82
|
+
|
|
78
83
|
/**
|
|
79
84
|
* Send a message, to be defined depending on the chosen technology.
|
|
80
85
|
* Default to no-op.
|
|
@@ -139,6 +144,11 @@ export interface IChatModel extends IDisposable {
|
|
|
139
144
|
* @param count - the number of messages to delete.
|
|
140
145
|
*/
|
|
141
146
|
messagesDeleted(index: number, count: number): void;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Function to request the focus on the input of the chat.
|
|
150
|
+
*/
|
|
151
|
+
focusInput(): void;
|
|
142
152
|
}
|
|
143
153
|
|
|
144
154
|
/**
|
|
@@ -328,6 +338,13 @@ export class ChatModel implements IChatModel {
|
|
|
328
338
|
return this._viewportChanged;
|
|
329
339
|
}
|
|
330
340
|
|
|
341
|
+
/**
|
|
342
|
+
* A signal emitting when the focus is requested on the input.
|
|
343
|
+
*/
|
|
344
|
+
get focusInputSignal(): ISignal<IChatModel, void> {
|
|
345
|
+
return this._focusInputSignal;
|
|
346
|
+
}
|
|
347
|
+
|
|
331
348
|
/**
|
|
332
349
|
* Send a message, to be defined depending on the chosen technology.
|
|
333
350
|
* Default to no-op.
|
|
@@ -435,6 +452,13 @@ export class ChatModel implements IChatModel {
|
|
|
435
452
|
this._messagesUpdated.emit();
|
|
436
453
|
}
|
|
437
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Function to request the focus on the input of the chat.
|
|
457
|
+
*/
|
|
458
|
+
focusInput(): void {
|
|
459
|
+
this._focusInputSignal.emit();
|
|
460
|
+
}
|
|
461
|
+
|
|
438
462
|
/**
|
|
439
463
|
* Add unread messages to the list.
|
|
440
464
|
* @param indexes - list of new indexes.
|
|
@@ -498,6 +522,7 @@ export class ChatModel implements IChatModel {
|
|
|
498
522
|
private _configChanged = new Signal<IChatModel, IConfig>(this);
|
|
499
523
|
private _unreadChanged = new Signal<IChatModel, number[]>(this);
|
|
500
524
|
private _viewportChanged = new Signal<IChatModel, number[]>(this);
|
|
525
|
+
private _focusInputSignal = new Signal<ChatModel, void>(this);
|
|
501
526
|
}
|
|
502
527
|
|
|
503
528
|
/**
|