@jupyter/chat 0.19.0-alpha.0 → 0.19.0-alpha.2
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/active-cell-manager.js +4 -2
- package/lib/components/attachments.js +3 -3
- package/lib/components/chat.d.ts +3 -7
- package/lib/components/chat.js +9 -5
- package/lib/components/code-blocks/code-toolbar.js +8 -28
- package/lib/components/code-blocks/copy-button.js +4 -11
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +1 -0
- package/lib/components/input/buttons/attach-button.js +3 -10
- package/lib/components/input/buttons/cancel-button.js +6 -10
- package/lib/components/input/buttons/save-edit-button.js +6 -13
- package/lib/components/input/buttons/send-button.js +6 -23
- package/lib/components/input/buttons/stop-button.js +6 -23
- package/lib/components/input/chat-input.d.ts +0 -20
- package/lib/components/input/chat-input.js +21 -18
- package/lib/components/messages/footer.d.ts +5 -5
- package/lib/components/messages/footer.js +7 -2
- package/lib/components/messages/header.js +10 -8
- package/lib/components/messages/message-renderer.d.ts +0 -10
- package/lib/components/messages/message-renderer.js +5 -3
- package/lib/components/messages/message.d.ts +8 -4
- package/lib/components/messages/message.js +4 -2
- package/lib/components/messages/messages.d.ts +1 -39
- package/lib/components/messages/messages.js +31 -13
- package/lib/components/messages/navigation.d.ts +1 -2
- package/lib/components/messages/navigation.js +2 -1
- package/lib/components/messages/toolbar.js +12 -26
- package/lib/components/messages/welcome.d.ts +10 -2
- package/lib/components/messages/welcome.js +2 -1
- package/lib/components/mui-extras/tooltipped-button.d.ts +28 -1
- package/lib/components/mui-extras/tooltipped-button.js +34 -6
- package/lib/components/mui-extras/tooltipped-icon-button.d.ts +6 -1
- package/lib/components/mui-extras/tooltipped-icon-button.js +8 -7
- package/lib/context.d.ts +3 -2
- package/lib/context.js +9 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/tokens.d.ts +11 -0
- package/lib/tokens.js +9 -0
- package/lib/types.d.ts +4 -0
- package/lib/widgets/chat-widget.d.ts +5 -0
- package/lib/widgets/chat-widget.js +6 -0
- package/lib/widgets/multichat-panel.d.ts +1 -6
- package/lib/widgets/multichat-panel.js +3 -13
- package/package.json +1 -1
- package/src/active-cell-manager.ts +3 -1
- package/src/components/attachments.tsx +3 -3
- package/src/components/chat.tsx +13 -24
- package/src/components/code-blocks/code-toolbar.tsx +29 -55
- package/src/components/code-blocks/copy-button.tsx +13 -20
- package/src/components/index.ts +1 -0
- package/src/components/input/buttons/attach-button.tsx +5 -13
- package/src/components/input/buttons/cancel-button.tsx +11 -18
- package/src/components/input/buttons/save-edit-button.tsx +13 -22
- package/src/components/input/buttons/send-button.tsx +13 -34
- package/src/components/input/buttons/stop-button.tsx +13 -34
- package/src/components/input/chat-input.tsx +24 -38
- package/src/components/messages/footer.tsx +12 -10
- package/src/components/messages/header.tsx +23 -17
- package/src/components/messages/message-renderer.tsx +5 -13
- package/src/components/messages/message.tsx +4 -7
- package/src/components/messages/messages.tsx +73 -97
- package/src/components/messages/navigation.tsx +3 -3
- package/src/components/messages/toolbar.tsx +19 -33
- package/src/components/messages/welcome.tsx +13 -2
- package/src/components/mui-extras/tooltipped-button.tsx +44 -5
- package/src/components/mui-extras/tooltipped-icon-button.tsx +22 -6
- package/src/context.ts +15 -5
- package/src/index.ts +1 -0
- package/src/tokens.ts +24 -0
- package/src/types.ts +4 -0
- package/src/widgets/chat-widget.tsx +8 -0
- package/src/widgets/multichat-panel.tsx +7 -26
|
@@ -29,9 +29,11 @@ export class ActiveCellManager {
|
|
|
29
29
|
* Handle the change of active notebook cell.
|
|
30
30
|
*/
|
|
31
31
|
this._onActiveCellChanged = (_, activeCell) => {
|
|
32
|
-
var _a;
|
|
32
|
+
var _a, _b;
|
|
33
33
|
if (this._activeCell !== activeCell) {
|
|
34
|
-
(_a = this._activeCell) === null || _a === void 0 ? void 0 : _a.
|
|
34
|
+
if (!((_a = this._activeCell) === null || _a === void 0 ? void 0 : _a.disposed)) {
|
|
35
|
+
(_b = this._activeCell) === null || _b === void 0 ? void 0 : _b.model.stateChanged.disconnect(this._cellStateChange);
|
|
36
|
+
}
|
|
35
37
|
this._activeCell = activeCell;
|
|
36
38
|
activeCell === null || activeCell === void 0 ? void 0 : activeCell.ready.then(() => {
|
|
37
39
|
var _a;
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import CloseIcon from '@mui/icons-material/Close';
|
|
6
6
|
import { Box, Button, Tooltip } from '@mui/material';
|
|
7
|
-
import React
|
|
7
|
+
import React from 'react';
|
|
8
8
|
import { PathExt } from '@jupyterlab/coreutils';
|
|
9
9
|
import { UUID } from '@lumino/coreutils';
|
|
10
|
-
import {
|
|
10
|
+
import { useChatContext } from '../context';
|
|
11
11
|
const ATTACHMENT_CLASS = 'jp-chat-attachment';
|
|
12
12
|
const ATTACHMENT_CLICKABLE_CLASS = 'jp-chat-attachment-clickable';
|
|
13
13
|
const REMOVE_BUTTON_CLASS = 'jp-chat-attachment-remove';
|
|
@@ -52,7 +52,7 @@ export function AttachmentPreviewList(props) {
|
|
|
52
52
|
*/
|
|
53
53
|
export function AttachmentPreview(props) {
|
|
54
54
|
const remove_tooltip = 'Remove attachment';
|
|
55
|
-
const attachmentOpenerRegistry =
|
|
55
|
+
const { attachmentOpenerRegistry } = useChatContext();
|
|
56
56
|
const isClickable = !!(attachmentOpenerRegistry === null || attachmentOpenerRegistry === void 0 ? void 0 : attachmentOpenerRegistry.get(props.attachment.type));
|
|
57
57
|
return (React.createElement(Box, { className: ATTACHMENT_CLASS, sx: {
|
|
58
58
|
border: '1px solid var(--jp-border-color1)',
|
package/lib/components/chat.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { IInputToolbarRegistry } from './input';
|
|
|
5
5
|
import { IChatModel } from '../model';
|
|
6
6
|
import { IAttachmentOpenerRegistry, IChatCommandRegistry, IMessageFooterRegistry } from '../registers';
|
|
7
7
|
import { ChatArea } from '../types';
|
|
8
|
-
export declare function ChatBody(props: Chat.
|
|
8
|
+
export declare function ChatBody(props: Chat.IChatProps): JSX.Element;
|
|
9
9
|
export declare function Chat(props: Chat.IOptions): JSX.Element;
|
|
10
10
|
/**
|
|
11
11
|
* The chat UI namespace
|
|
@@ -14,7 +14,7 @@ export declare namespace Chat {
|
|
|
14
14
|
/**
|
|
15
15
|
* The props for the chat body component.
|
|
16
16
|
*/
|
|
17
|
-
interface
|
|
17
|
+
interface IChatProps {
|
|
18
18
|
/**
|
|
19
19
|
* The chat model.
|
|
20
20
|
*/
|
|
@@ -51,15 +51,11 @@ export declare namespace Chat {
|
|
|
51
51
|
/**
|
|
52
52
|
* The options to build the Chat UI.
|
|
53
53
|
*/
|
|
54
|
-
interface IOptions extends
|
|
54
|
+
interface IOptions extends IChatProps {
|
|
55
55
|
/**
|
|
56
56
|
* The theme manager.
|
|
57
57
|
*/
|
|
58
58
|
themeManager?: IThemeManager | null;
|
|
59
|
-
/**
|
|
60
|
-
* The view to render.
|
|
61
|
-
*/
|
|
62
|
-
chatView?: View;
|
|
63
59
|
/**
|
|
64
60
|
* A settings panel that can be used for dedicated settings (e.g. jupyter-ai)
|
|
65
61
|
*/
|
package/lib/components/chat.js
CHANGED
|
@@ -10,7 +10,7 @@ import React, { useState } from 'react';
|
|
|
10
10
|
import { ChatInput, InputToolbarRegistry } from './input';
|
|
11
11
|
import { JlThemeProvider } from './jl-theme-provider';
|
|
12
12
|
import { ChatMessages } from './messages';
|
|
13
|
-
import {
|
|
13
|
+
import { ChatReactContext } from '../context';
|
|
14
14
|
export function ChatBody(props) {
|
|
15
15
|
const { model } = props;
|
|
16
16
|
let { inputToolbarRegistry } = props;
|
|
@@ -19,18 +19,22 @@ export function ChatBody(props) {
|
|
|
19
19
|
}
|
|
20
20
|
// const horizontalPadding = props.area === 'main' ? 8 : 4;
|
|
21
21
|
const horizontalPadding = 4;
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
const contextValue = {
|
|
23
|
+
...props,
|
|
24
|
+
inputToolbarRegistry
|
|
25
|
+
};
|
|
26
|
+
return (React.createElement(ChatReactContext.Provider, { value: contextValue },
|
|
27
|
+
React.createElement(ChatMessages, null),
|
|
24
28
|
React.createElement(ChatInput, { sx: {
|
|
25
29
|
paddingLeft: horizontalPadding,
|
|
26
30
|
paddingRight: horizontalPadding,
|
|
27
31
|
paddingTop: 0,
|
|
28
32
|
paddingBottom: 0
|
|
29
|
-
}, model: model.input
|
|
33
|
+
}, model: model.input })));
|
|
30
34
|
}
|
|
31
35
|
export function Chat(props) {
|
|
32
36
|
var _a;
|
|
33
|
-
const [view, setView] = useState(
|
|
37
|
+
const [view, setView] = useState(Chat.View.chat);
|
|
34
38
|
return (React.createElement(JlThemeProvider, { themeManager: (_a = props.themeManager) !== null && _a !== void 0 ? _a : null },
|
|
35
39
|
React.createElement(Box
|
|
36
40
|
// Add .jp-ThemedContainer for CSS compatibility in both JL <4.3.0 and >=4.3.0.
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
import { addAboveIcon, addBelowIcon } from '@jupyterlab/ui-components';
|
|
6
|
-
import { Box
|
|
6
|
+
import { Box } from '@mui/material';
|
|
7
7
|
import React, { useEffect, useState } from 'react';
|
|
8
8
|
import { CopyButton } from './copy-button';
|
|
9
|
+
import { TooltippedIconButton } from '../mui-extras';
|
|
9
10
|
import { replaceCellIcon } from '../../icons';
|
|
10
11
|
const CODE_TOOLBAR_CLASS = 'jp-chat-code-toolbar';
|
|
11
12
|
const CODE_TOOLBAR_ITEM_CLASS = 'jp-chat-code-toolbar-item';
|
|
@@ -63,29 +64,15 @@ function InsertAboveButton(props) {
|
|
|
63
64
|
const tooltip = props.activeCellAvailable
|
|
64
65
|
? 'Insert above active cell'
|
|
65
66
|
: 'Insert above active cell (no active cell)';
|
|
66
|
-
return (React.createElement(
|
|
67
|
-
React.createElement("
|
|
68
|
-
React.createElement(IconButton, { className: props.className, onClick: () => { var _a; return (_a = props.activeCellManager) === null || _a === void 0 ? void 0 : _a.insertAbove(props.content); }, disabled: !props.activeCellAvailable, "aria-label": tooltip, sx: {
|
|
69
|
-
lineHeight: 0,
|
|
70
|
-
'&.Mui-disabled': {
|
|
71
|
-
opacity: 0.5
|
|
72
|
-
}
|
|
73
|
-
} },
|
|
74
|
-
React.createElement(addAboveIcon.react, { height: "16px", width: "16px" })))));
|
|
67
|
+
return (React.createElement(TooltippedIconButton, { className: props.className, tooltip: tooltip, onClick: () => { var _a; return (_a = props.activeCellManager) === null || _a === void 0 ? void 0 : _a.insertAbove(props.content); }, disabled: !props.activeCellAvailable, inputToolbar: false },
|
|
68
|
+
React.createElement(addAboveIcon.react, { height: "16px", width: "16px" })));
|
|
75
69
|
}
|
|
76
70
|
function InsertBelowButton(props) {
|
|
77
71
|
const tooltip = props.activeCellAvailable
|
|
78
72
|
? 'Insert below active cell'
|
|
79
73
|
: 'Insert below active cell (no active cell)';
|
|
80
|
-
return (React.createElement(
|
|
81
|
-
React.createElement("
|
|
82
|
-
React.createElement(IconButton, { className: props.className, disabled: !props.activeCellAvailable, onClick: () => { var _a; return (_a = props.activeCellManager) === null || _a === void 0 ? void 0 : _a.insertBelow(props.content); }, "aria-label": tooltip, sx: {
|
|
83
|
-
lineHeight: 0,
|
|
84
|
-
'&.Mui-disabled': {
|
|
85
|
-
opacity: 0.5
|
|
86
|
-
}
|
|
87
|
-
} },
|
|
88
|
-
React.createElement(addBelowIcon.react, { height: "16px", width: "16px" })))));
|
|
74
|
+
return (React.createElement(TooltippedIconButton, { className: props.className, tooltip: tooltip, disabled: !props.activeCellAvailable, onClick: () => { var _a; return (_a = props.activeCellManager) === null || _a === void 0 ? void 0 : _a.insertBelow(props.content); }, inputToolbar: false },
|
|
75
|
+
React.createElement(addBelowIcon.react, { height: "16px", width: "16px" })));
|
|
89
76
|
}
|
|
90
77
|
function ReplaceButton(props) {
|
|
91
78
|
var _a, _b;
|
|
@@ -111,13 +98,6 @@ function ReplaceButton(props) {
|
|
|
111
98
|
(_c = props.activeCellManager) === null || _c === void 0 ? void 0 : _c.replace(props.content);
|
|
112
99
|
}
|
|
113
100
|
};
|
|
114
|
-
return (React.createElement(
|
|
115
|
-
React.createElement("
|
|
116
|
-
React.createElement(IconButton, { className: props.className, disabled: disabled, onClick: replace, "aria-label": tooltip, sx: {
|
|
117
|
-
lineHeight: 0,
|
|
118
|
-
'&.Mui-disabled': {
|
|
119
|
-
opacity: 0.5
|
|
120
|
-
}
|
|
121
|
-
} },
|
|
122
|
-
React.createElement(replaceCellIcon.react, { height: "16px", width: "16px" })))));
|
|
101
|
+
return (React.createElement(TooltippedIconButton, { className: props.className, tooltip: tooltip, disabled: disabled, onClick: replace, inputToolbar: false },
|
|
102
|
+
React.createElement(replaceCellIcon.react, { height: "16px", width: "16px" })));
|
|
123
103
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright (c) Jupyter Development Team.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
import React, { useState, useCallback, useRef } from 'react';
|
|
6
5
|
import { copyIcon } from '@jupyterlab/ui-components';
|
|
7
|
-
import {
|
|
6
|
+
import React, { useState, useCallback, useRef } from 'react';
|
|
7
|
+
import { TooltippedIconButton } from '../mui-extras';
|
|
8
8
|
var CopyStatus;
|
|
9
9
|
(function (CopyStatus) {
|
|
10
10
|
CopyStatus[CopyStatus["None"] = 0] = "None";
|
|
@@ -42,13 +42,6 @@ export function CopyButton(props) {
|
|
|
42
42
|
timeoutId.current = window.setTimeout(() => setCopyStatus(CopyStatus.None), 1000);
|
|
43
43
|
}, [copyStatus, props.value]);
|
|
44
44
|
const tooltip = COPYBTN_TEXT_BY_STATUS[copyStatus];
|
|
45
|
-
return (React.createElement(
|
|
46
|
-
React.createElement("
|
|
47
|
-
React.createElement(IconButton, { disabled: isCopyDisabled, className: props.className, onClick: copy, "aria-label": "Copy to clipboard", sx: {
|
|
48
|
-
lineHeight: 0,
|
|
49
|
-
'&.Mui-disabled': {
|
|
50
|
-
opacity: 0.5
|
|
51
|
-
}
|
|
52
|
-
} },
|
|
53
|
-
React.createElement(copyIcon.react, { height: "16px", width: "16px" })))));
|
|
45
|
+
return (React.createElement(TooltippedIconButton, { disabled: isCopyDisabled, className: props.className, tooltip: tooltip, placement: "top", onClick: copy, "aria-label": "Copy to clipboard", inputToolbar: false },
|
|
46
|
+
React.createElement(copyIcon.react, { height: "16px", width: "16px" })));
|
|
54
47
|
}
|
package/lib/components/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { FileDialog } from '@jupyterlab/filebrowser';
|
|
6
6
|
import AttachFileIcon from '@mui/icons-material/AttachFile';
|
|
7
7
|
import React from 'react';
|
|
8
|
-
import {
|
|
8
|
+
import { TooltippedIconButton } from '../../mui-extras';
|
|
9
9
|
const ATTACH_BUTTON_CLASS = 'jp-chat-attach-button';
|
|
10
10
|
/**
|
|
11
11
|
* The attach button.
|
|
@@ -38,16 +38,9 @@ export function AttachButton(props) {
|
|
|
38
38
|
console.warn('Error selecting files to attach', e);
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
-
return (React.createElement(
|
|
42
|
-
size: 'small',
|
|
43
|
-
variant: 'text',
|
|
41
|
+
return (React.createElement(TooltippedIconButton, { onClick: onclick, tooltip: tooltip, iconButtonProps: {
|
|
44
42
|
title: tooltip,
|
|
45
43
|
className: ATTACH_BUTTON_CLASS
|
|
46
|
-
}, sx: {
|
|
47
|
-
width: '24px',
|
|
48
|
-
height: '24px',
|
|
49
|
-
minWidth: '24px',
|
|
50
|
-
color: 'gray'
|
|
51
44
|
} },
|
|
52
|
-
React.createElement(AttachFileIcon,
|
|
45
|
+
React.createElement(AttachFileIcon, null)));
|
|
53
46
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
import CloseIcon from '@mui/icons-material/Close';
|
|
6
|
-
import { IconButton, Tooltip } from '@mui/material';
|
|
7
6
|
import React from 'react';
|
|
7
|
+
import { TooltippedIconButton } from '../../mui-extras';
|
|
8
8
|
const CANCEL_BUTTON_CLASS = 'jp-chat-cancel-button';
|
|
9
9
|
/**
|
|
10
10
|
* The cancel button.
|
|
@@ -14,13 +14,9 @@ export function CancelButton(props) {
|
|
|
14
14
|
return React.createElement(React.Fragment, null);
|
|
15
15
|
}
|
|
16
16
|
const tooltip = 'Cancel editing';
|
|
17
|
-
return (React.createElement(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
padding: 0,
|
|
23
|
-
lineHeight: 0
|
|
24
|
-
} },
|
|
25
|
-
React.createElement(CloseIcon, { sx: { fontSize: '16px' } })))));
|
|
17
|
+
return (React.createElement(TooltippedIconButton, { onClick: props.model.cancel, tooltip: tooltip, iconButtonProps: {
|
|
18
|
+
title: tooltip,
|
|
19
|
+
className: CANCEL_BUTTON_CLASS
|
|
20
|
+
} },
|
|
21
|
+
React.createElement(CloseIcon, null)));
|
|
26
22
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
import CheckIcon from '@mui/icons-material/Check';
|
|
6
|
-
import { IconButton, Tooltip } from '@mui/material';
|
|
7
6
|
import React, { useEffect, useState } from 'react';
|
|
7
|
+
import { TooltippedIconButton } from '../../mui-extras';
|
|
8
8
|
const SAVE_EDIT_BUTTON_CLASS = 'jp-chat-save-edit-button';
|
|
9
9
|
/**
|
|
10
10
|
* The save edit button.
|
|
@@ -36,16 +36,9 @@ export function SaveEditButton(props) {
|
|
|
36
36
|
await (chatCommandRegistry === null || chatCommandRegistry === void 0 ? void 0 : chatCommandRegistry.onSubmit(model));
|
|
37
37
|
model.send(model.value);
|
|
38
38
|
}
|
|
39
|
-
return (React.createElement(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
padding: 0,
|
|
45
|
-
lineHeight: 0,
|
|
46
|
-
'&.Mui-disabled': {
|
|
47
|
-
opacity: 0.5
|
|
48
|
-
}
|
|
49
|
-
} },
|
|
50
|
-
React.createElement(CheckIcon, { sx: { fontSize: '16px' } })))));
|
|
39
|
+
return (React.createElement(TooltippedIconButton, { onClick: save, tooltip: tooltip, disabled: disabled, iconButtonProps: {
|
|
40
|
+
title: tooltip,
|
|
41
|
+
className: SAVE_EDIT_BUTTON_CLASS
|
|
42
|
+
}, "aria-label": tooltip },
|
|
43
|
+
React.createElement(CheckIcon, null)));
|
|
51
44
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
|
|
6
|
-
import { Button, Tooltip } from '@mui/material';
|
|
7
6
|
import React, { useEffect, useState } from 'react';
|
|
7
|
+
import { TooltippedIconButton } from '../../mui-extras';
|
|
8
8
|
const SEND_BUTTON_CLASS = 'jp-chat-send-button';
|
|
9
9
|
/**
|
|
10
10
|
* The send button.
|
|
@@ -51,26 +51,9 @@ export function SendButton(props) {
|
|
|
51
51
|
model.value = '';
|
|
52
52
|
model.focus();
|
|
53
53
|
}
|
|
54
|
-
return (React.createElement(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
minWidth: '24px',
|
|
60
|
-
width: '24px',
|
|
61
|
-
height: '24px',
|
|
62
|
-
borderRadius: '4px',
|
|
63
|
-
boxShadow: 'none',
|
|
64
|
-
lineHeight: 0,
|
|
65
|
-
'&:hover': {
|
|
66
|
-
backgroundColor: 'var(--jp-brand-color0)',
|
|
67
|
-
boxShadow: 'none'
|
|
68
|
-
},
|
|
69
|
-
'&.Mui-disabled': {
|
|
70
|
-
backgroundColor: 'var(--jp-border-color2)',
|
|
71
|
-
color: 'var(--jp-ui-font-color3)',
|
|
72
|
-
opacity: 0.5
|
|
73
|
-
}
|
|
74
|
-
} },
|
|
75
|
-
React.createElement(ArrowUpwardIcon, { sx: { fontSize: '16px' } })))));
|
|
54
|
+
return (React.createElement(TooltippedIconButton, { onClick: send, tooltip: tooltip, disabled: disabled, iconButtonProps: {
|
|
55
|
+
title: tooltip,
|
|
56
|
+
className: SEND_BUTTON_CLASS
|
|
57
|
+
}, "aria-label": tooltip },
|
|
58
|
+
React.createElement(ArrowUpwardIcon, null)));
|
|
76
59
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
import StopIcon from '@mui/icons-material/Stop';
|
|
6
|
-
import { Button, Tooltip } from '@mui/material';
|
|
7
6
|
import React, { useEffect, useState } from 'react';
|
|
7
|
+
import { TooltippedIconButton } from '../../mui-extras';
|
|
8
8
|
const STOP_BUTTON_CLASS = 'jp-chat-stop-button';
|
|
9
9
|
/**
|
|
10
10
|
* The stop button.
|
|
@@ -38,26 +38,9 @@ export function StopButton(props) {
|
|
|
38
38
|
// This will need to be implemented based on how the chat model handles stopping AI responses
|
|
39
39
|
console.log('Stop button clicked');
|
|
40
40
|
}
|
|
41
|
-
return (React.createElement(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
minWidth: '24px',
|
|
47
|
-
width: '24px',
|
|
48
|
-
height: '24px',
|
|
49
|
-
borderRadius: '4px',
|
|
50
|
-
boxShadow: 'none',
|
|
51
|
-
lineHeight: 0,
|
|
52
|
-
'&:hover': {
|
|
53
|
-
backgroundColor: 'var(--jp-error-color0)',
|
|
54
|
-
boxShadow: 'none'
|
|
55
|
-
},
|
|
56
|
-
'&.Mui-disabled': {
|
|
57
|
-
backgroundColor: 'var(--jp-border-color2)',
|
|
58
|
-
color: 'var(--jp-ui-font-color3)',
|
|
59
|
-
opacity: 0.5
|
|
60
|
-
}
|
|
61
|
-
} },
|
|
62
|
-
React.createElement(StopIcon, { sx: { fontSize: '16px' } })))));
|
|
41
|
+
return (React.createElement(TooltippedIconButton, { onClick: stop, tooltip: tooltip, disabled: disabled, iconButtonProps: {
|
|
42
|
+
title: tooltip,
|
|
43
|
+
className: STOP_BUTTON_CLASS
|
|
44
|
+
}, "aria-label": tooltip },
|
|
45
|
+
React.createElement(StopIcon, null)));
|
|
63
46
|
}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { SxProps, Theme } from '@mui/material';
|
|
3
|
-
import { IInputToolbarRegistry } from '.';
|
|
4
3
|
import { IInputModel } from '../../input-model';
|
|
5
|
-
import { IChatCommandRegistry } from '../../registers';
|
|
6
|
-
import { ChatArea } from '../../types';
|
|
7
|
-
import { IChatModel } from '../../model';
|
|
8
4
|
export declare function ChatInput(props: ChatInput.IProps): JSX.Element;
|
|
9
5
|
/**
|
|
10
6
|
* The chat input namespace.
|
|
@@ -18,10 +14,6 @@ export declare namespace ChatInput {
|
|
|
18
14
|
* The input model.
|
|
19
15
|
*/
|
|
20
16
|
model: IInputModel;
|
|
21
|
-
/**
|
|
22
|
-
* The toolbar registry.
|
|
23
|
-
*/
|
|
24
|
-
toolbarRegistry: IInputToolbarRegistry;
|
|
25
17
|
/**
|
|
26
18
|
* The function to be called to cancel editing.
|
|
27
19
|
*/
|
|
@@ -30,18 +22,6 @@ export declare namespace ChatInput {
|
|
|
30
22
|
* Custom mui/material styles.
|
|
31
23
|
*/
|
|
32
24
|
sx?: SxProps<Theme>;
|
|
33
|
-
/**
|
|
34
|
-
* Chat command registry.
|
|
35
|
-
*/
|
|
36
|
-
chatCommandRegistry?: IChatCommandRegistry;
|
|
37
|
-
/**
|
|
38
|
-
* The area where the chat is displayed.
|
|
39
|
-
*/
|
|
40
|
-
area?: ChatArea;
|
|
41
|
-
/**
|
|
42
|
-
* The chat model.
|
|
43
|
-
*/
|
|
44
|
-
chatModel?: IChatModel;
|
|
45
25
|
/**
|
|
46
26
|
* Whether the input is in edit mode (editing an existing message).
|
|
47
27
|
* Defaults to false (new message mode).
|
|
@@ -5,18 +5,21 @@
|
|
|
5
5
|
import { Autocomplete, Box, TextField } from '@mui/material';
|
|
6
6
|
import clsx from 'clsx';
|
|
7
7
|
import React, { useEffect, useRef, useState } from 'react';
|
|
8
|
+
import { useChatCommands } from './use-chat-commands';
|
|
8
9
|
import { AttachmentPreviewList } from '../attachments';
|
|
9
|
-
import {
|
|
10
|
+
import { useChatContext } from '../../context';
|
|
10
11
|
import { InputWritingIndicator } from './writing-indicator';
|
|
11
12
|
const INPUT_BOX_CLASS = 'jp-chat-input-container';
|
|
12
13
|
const INPUT_TEXTFIELD_CLASS = 'jp-chat-input-textfield';
|
|
13
14
|
const INPUT_TOOLBAR_CLASS = 'jp-chat-input-toolbar';
|
|
14
15
|
export function ChatInput(props) {
|
|
15
16
|
var _a;
|
|
16
|
-
const { model
|
|
17
|
+
const { model } = props;
|
|
18
|
+
const { area, chatCommandRegistry, inputToolbarRegistry } = useChatContext();
|
|
19
|
+
const chatModel = useChatContext().model;
|
|
17
20
|
const [input, setInput] = useState(model.value);
|
|
18
21
|
const inputRef = useRef();
|
|
19
|
-
const chatCommands = useChatCommands(model,
|
|
22
|
+
const chatCommands = useChatCommands(model, chatCommandRegistry);
|
|
20
23
|
const [sendWithShiftEnter, setSendWithShiftEnter] = useState((_a = model.config.sendWithShiftEnter) !== null && _a !== void 0 ? _a : false);
|
|
21
24
|
const [attachments, setAttachments] = useState(model.attachments);
|
|
22
25
|
const [toolbarElements, setToolbarElements] = useState([]);
|
|
@@ -69,20 +72,20 @@ export function ChatInput(props) {
|
|
|
69
72
|
*/
|
|
70
73
|
useEffect(() => {
|
|
71
74
|
const updateToolbar = () => {
|
|
72
|
-
setToolbarElements(
|
|
75
|
+
setToolbarElements((inputToolbarRegistry === null || inputToolbarRegistry === void 0 ? void 0 : inputToolbarRegistry.getItems()) || []);
|
|
73
76
|
};
|
|
74
|
-
|
|
77
|
+
inputToolbarRegistry === null || inputToolbarRegistry === void 0 ? void 0 : inputToolbarRegistry.itemsChanged.connect(updateToolbar);
|
|
75
78
|
updateToolbar();
|
|
76
79
|
return () => {
|
|
77
|
-
|
|
80
|
+
inputToolbarRegistry === null || inputToolbarRegistry === void 0 ? void 0 : inputToolbarRegistry.itemsChanged.disconnect(updateToolbar);
|
|
78
81
|
};
|
|
79
|
-
}, [
|
|
82
|
+
}, [inputToolbarRegistry]);
|
|
80
83
|
/**
|
|
81
84
|
* Handle the changes in the writers list.
|
|
82
85
|
*/
|
|
83
86
|
useEffect(() => {
|
|
84
87
|
var _a;
|
|
85
|
-
if (!
|
|
88
|
+
if (!chatModel) {
|
|
86
89
|
return;
|
|
87
90
|
}
|
|
88
91
|
const updateWriters = (_, writers) => {
|
|
@@ -90,14 +93,14 @@ export function ChatInput(props) {
|
|
|
90
93
|
setWriters(writers);
|
|
91
94
|
};
|
|
92
95
|
// Set initial writers state
|
|
93
|
-
const initialWriters =
|
|
96
|
+
const initialWriters = chatModel.writers;
|
|
94
97
|
setWriters(initialWriters);
|
|
95
|
-
(_a =
|
|
98
|
+
(_a = chatModel.writersChanged) === null || _a === void 0 ? void 0 : _a.connect(updateWriters);
|
|
96
99
|
return () => {
|
|
97
|
-
var _a
|
|
98
|
-
(
|
|
100
|
+
var _a;
|
|
101
|
+
(_a = chatModel === null || chatModel === void 0 ? void 0 : chatModel.writersChanged) === null || _a === void 0 ? void 0 : _a.disconnect(updateWriters);
|
|
99
102
|
};
|
|
100
|
-
}, [
|
|
103
|
+
}, [chatModel]);
|
|
101
104
|
const inputExists = !!input.trim();
|
|
102
105
|
/**
|
|
103
106
|
* `handleKeyDown()`: callback invoked when the user presses any key in the
|
|
@@ -106,7 +109,6 @@ export function ChatInput(props) {
|
|
|
106
109
|
* component.
|
|
107
110
|
*/
|
|
108
111
|
async function handleKeyDown(event) {
|
|
109
|
-
var _a;
|
|
110
112
|
/**
|
|
111
113
|
* IMPORTANT: This statement ensures that arrow keys can be used to navigate
|
|
112
114
|
* the multiline input when the chat commands menu is closed.
|
|
@@ -151,13 +153,13 @@ export function ChatInput(props) {
|
|
|
151
153
|
if ((sendWithShiftEnter && event.shiftKey) ||
|
|
152
154
|
(!sendWithShiftEnter && !event.shiftKey)) {
|
|
153
155
|
// Run all command providers
|
|
154
|
-
await (
|
|
156
|
+
await (chatCommandRegistry === null || chatCommandRegistry === void 0 ? void 0 : chatCommandRegistry.onSubmit(model));
|
|
155
157
|
model.send(model.value);
|
|
156
158
|
event.stopPropagation();
|
|
157
159
|
event.preventDefault();
|
|
158
160
|
}
|
|
159
161
|
}
|
|
160
|
-
const horizontalPadding =
|
|
162
|
+
const horizontalPadding = area === 'sidebar' ? 1.5 : 2;
|
|
161
163
|
return (React.createElement(Box, { sx: props.sx, className: clsx(INPUT_BOX_CLASS), "data-input-id": model.id },
|
|
162
164
|
React.createElement(Box, { sx: {
|
|
163
165
|
border: '1px solid',
|
|
@@ -186,9 +188,10 @@ export function ChatInput(props) {
|
|
|
186
188
|
padding: 0
|
|
187
189
|
}
|
|
188
190
|
}
|
|
189
|
-
}, renderInput: params => (React.createElement(TextField, { ...params, fullWidth: true, variant: "standard", className: INPUT_TEXTFIELD_CLASS, multiline: true, onKeyDown: handleKeyDown, placeholder: "Type a chat message, @ to mention...", inputRef: inputRef, onFocus: () => setIsFocused(true), onBlur: () => setIsFocused(false), onSelect: () => { var _a, _b; return (model.cursorIndex = (_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.selectionStart) !== null && _b !== void 0 ? _b : null); }, sx: {
|
|
191
|
+
}, renderInput: params => (React.createElement(TextField, { ...params, fullWidth: true, variant: "standard", className: INPUT_TEXTFIELD_CLASS, multiline: true, maxRows: 10, onKeyDown: handleKeyDown, placeholder: "Type a chat message, @ to mention...", inputRef: inputRef, onFocus: () => setIsFocused(true), onBlur: () => setIsFocused(false), onSelect: () => { var _a, _b; return (model.cursorIndex = (_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.selectionStart) !== null && _b !== void 0 ? _b : null); }, sx: {
|
|
190
192
|
padding: 1.5,
|
|
191
193
|
margin: 0,
|
|
194
|
+
boxSizing: 'border-box',
|
|
192
195
|
backgroundColor: 'var(--jp-layout-color0)',
|
|
193
196
|
transition: 'background-color 0.2s ease',
|
|
194
197
|
'& .MuiInputBase-root': {
|
|
@@ -232,6 +235,6 @@ export function ChatInput(props) {
|
|
|
232
235
|
borderColor: 'var(--jp-border-color1)',
|
|
233
236
|
backgroundColor: 'var(--jp-layout-color0)',
|
|
234
237
|
transition: 'background-color 0.2s ease'
|
|
235
|
-
} }, toolbarElements.map((item, index) => (React.createElement(item.element, { key: index, model: model, chatCommandRegistry:
|
|
238
|
+
} }, toolbarElements.map((item, index) => (React.createElement(item.element, { key: index, model: model, chatCommandRegistry: chatCommandRegistry, chatModel: chatModel, edit: props.edit }))))),
|
|
236
239
|
React.createElement(InputWritingIndicator, { writers: writers })));
|
|
237
240
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import {
|
|
2
|
+
import { IChatMessage } from '../../types';
|
|
3
3
|
/**
|
|
4
4
|
* The chat footer component properties.
|
|
5
5
|
*/
|
|
6
|
-
export interface IMessageFootersProps
|
|
6
|
+
export interface IMessageFootersProps {
|
|
7
7
|
/**
|
|
8
|
-
* The chat
|
|
8
|
+
* The chat model.
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
message: IChatMessage;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* The chat footer component, which displays footer components on a row according to
|
|
14
14
|
* their respective positions.
|
|
15
15
|
*/
|
|
16
|
-
export declare function MessageFooterComponent(props: IMessageFootersProps): JSX.Element;
|
|
16
|
+
export declare function MessageFooterComponent(props: IMessageFootersProps): JSX.Element | null;
|
|
@@ -4,14 +4,19 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { Box } from '@mui/material';
|
|
6
6
|
import React from 'react';
|
|
7
|
+
import { useChatContext } from '../../context';
|
|
7
8
|
/**
|
|
8
9
|
* The chat footer component, which displays footer components on a row according to
|
|
9
10
|
* their respective positions.
|
|
10
11
|
*/
|
|
11
12
|
export function MessageFooterComponent(props) {
|
|
12
13
|
var _a, _b, _c;
|
|
13
|
-
const { message
|
|
14
|
-
const
|
|
14
|
+
const { message } = props;
|
|
15
|
+
const { model, messageFooterRegistry } = useChatContext();
|
|
16
|
+
if (!messageFooterRegistry) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const footer = messageFooterRegistry.getFooter();
|
|
15
20
|
return (React.createElement(Box, { sx: { display: 'flex', justifyContent: 'space-between' } },
|
|
16
21
|
((_a = footer.left) === null || _a === void 0 ? void 0 : _a.component) ? (React.createElement(footer.left.component, { message: message, model: model })) : (React.createElement("div", null)),
|
|
17
22
|
((_b = footer.center) === null || _b === void 0 ? void 0 : _b.component) ? (React.createElement(footer.center.component, { message: message, model: model })) : (React.createElement("div", null)),
|
|
@@ -12,12 +12,14 @@ const MESSAGE_TIME_CLASS = 'jp-chat-message-time';
|
|
|
12
12
|
*/
|
|
13
13
|
export function ChatMessageHeader(props) {
|
|
14
14
|
var _a, _b;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const message = props.message;
|
|
16
|
+
// Don't render header for stacked messages not deleted or edited.
|
|
17
|
+
if (message.stacked && !message.deleted && !message.edited) {
|
|
17
18
|
return React.createElement(React.Fragment, null);
|
|
18
19
|
}
|
|
20
|
+
// Flag to display only the deleted or edited information (stacked message).
|
|
21
|
+
const onlyState = message.stacked && (message.deleted || message.edited);
|
|
19
22
|
const [datetime, setDatetime] = useState({});
|
|
20
|
-
const message = props.message;
|
|
21
23
|
const sender = message.sender;
|
|
22
24
|
/**
|
|
23
25
|
* Effect: update cached datetime strings upon receiving a new message.
|
|
@@ -61,9 +63,9 @@ export function ChatMessageHeader(props) {
|
|
|
61
63
|
'& > :not(:last-child)': {
|
|
62
64
|
marginRight: 3
|
|
63
65
|
},
|
|
64
|
-
marginBottom: message.stacked ? '0px' : '12px'
|
|
66
|
+
marginBottom: message.stacked || props.isCurrentUser ? '0px' : '12px'
|
|
65
67
|
} },
|
|
66
|
-
avatar,
|
|
68
|
+
!props.isCurrentUser && !onlyState && avatar,
|
|
67
69
|
React.createElement(Box, { sx: {
|
|
68
70
|
display: 'flex',
|
|
69
71
|
flexGrow: 1,
|
|
@@ -72,7 +74,7 @@ export function ChatMessageHeader(props) {
|
|
|
72
74
|
alignItems: 'center'
|
|
73
75
|
} },
|
|
74
76
|
React.createElement(Box, { sx: { display: 'flex', alignItems: 'center' } },
|
|
75
|
-
!
|
|
77
|
+
!onlyState && !props.isCurrentUser && (React.createElement(Typography, { sx: {
|
|
76
78
|
fontWeight: 700,
|
|
77
79
|
color: 'var(--jp-ui-font-color1)',
|
|
78
80
|
paddingRight: '0.5em'
|
|
@@ -81,9 +83,9 @@ export function ChatMessageHeader(props) {
|
|
|
81
83
|
fontStyle: 'italic',
|
|
82
84
|
fontSize: 'var(--jp-content-font-size0)'
|
|
83
85
|
} }, message.deleted ? '(message deleted)' : '(edited)'))),
|
|
84
|
-
React.createElement(Typography, { className: MESSAGE_TIME_CLASS, sx: {
|
|
86
|
+
!onlyState && (React.createElement(Typography, { className: MESSAGE_TIME_CLASS, sx: {
|
|
85
87
|
fontSize: '0.8em',
|
|
86
88
|
color: 'var(--jp-ui-font-color2)',
|
|
87
89
|
fontWeight: 300
|
|
88
|
-
}, title: message.raw_time ? 'Unverified time' : '' }, `${datetime[message.time]}${message.raw_time ? '*' : ''}`))));
|
|
90
|
+
}, title: message.raw_time ? 'Unverified time' : '' }, `${datetime[message.time]}${message.raw_time ? '*' : ''}`)))));
|
|
89
91
|
}
|