@jupyter/chat 0.1.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/__tests__/model.spec.d.ts +1 -0
- package/lib/__tests__/model.spec.js +72 -0
- package/lib/__tests__/widgets.spec.d.ts +1 -0
- package/lib/__tests__/widgets.spec.js +33 -0
- package/lib/components/chat-input.d.ts +33 -0
- package/lib/components/chat-input.js +60 -0
- package/lib/components/chat-messages.d.ts +32 -0
- package/lib/components/chat-messages.js +162 -0
- package/lib/components/chat.d.ts +43 -0
- package/lib/components/chat.js +100 -0
- package/lib/components/copy-button.d.ts +6 -0
- package/lib/components/copy-button.js +35 -0
- package/lib/components/jl-theme-provider.d.ts +6 -0
- package/lib/components/jl-theme-provider.js +19 -0
- package/lib/components/mui-extras/stacking-alert.d.ts +28 -0
- package/lib/components/mui-extras/stacking-alert.js +56 -0
- package/lib/components/rendermime-markdown.d.ts +12 -0
- package/lib/components/rendermime-markdown.js +54 -0
- package/lib/components/scroll-container.d.ts +23 -0
- package/lib/components/scroll-container.js +51 -0
- package/lib/components/toolbar.d.ts +11 -0
- package/lib/components/toolbar.js +30 -0
- package/lib/icons.d.ts +2 -0
- package/lib/icons.js +11 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +10 -0
- package/lib/model.d.ts +177 -0
- package/lib/model.js +128 -0
- package/lib/theme-provider.d.ts +3 -0
- package/lib/theme-provider.js +133 -0
- package/lib/types.d.ts +49 -0
- package/lib/types.js +5 -0
- package/lib/widgets/chat-error.d.ts +2 -0
- package/lib/widgets/chat-error.js +26 -0
- package/lib/widgets/chat-sidebar.d.ts +4 -0
- package/lib/widgets/chat-sidebar.js +15 -0
- package/lib/widgets/chat-widget.d.ts +19 -0
- package/lib/widgets/chat-widget.js +28 -0
- package/package.json +209 -0
- package/src/__tests__/model.spec.ts +84 -0
- package/src/__tests__/widgets.spec.ts +43 -0
- package/src/components/chat-input.tsx +143 -0
- package/src/components/chat-messages.tsx +283 -0
- package/src/components/chat.tsx +179 -0
- package/src/components/copy-button.tsx +55 -0
- package/src/components/jl-theme-provider.tsx +28 -0
- package/src/components/mui-extras/stacking-alert.tsx +105 -0
- package/src/components/rendermime-markdown.tsx +88 -0
- package/src/components/scroll-container.tsx +74 -0
- package/src/components/toolbar.tsx +50 -0
- package/src/icons.ts +15 -0
- package/src/index.ts +11 -0
- package/src/model.ts +272 -0
- package/src/theme-provider.ts +137 -0
- package/src/types/mui.d.ts +18 -0
- package/src/types/svg.d.ts +17 -0
- package/src/types.ts +58 -0
- package/src/widgets/chat-error.tsx +43 -0
- package/src/widgets/chat-sidebar.tsx +30 -0
- package/src/widgets/chat-widget.tsx +51 -0
- package/style/base.css +13 -0
- package/style/chat-settings.css +10 -0
- package/style/chat.css +53 -0
- package/style/icons/chat.svg +6 -0
- package/style/index.css +6 -0
- package/style/index.js +6 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Theme, createTheme } from '@mui/material/styles';
|
|
7
|
+
|
|
8
|
+
function getCSSVariable(name: string): string {
|
|
9
|
+
return getComputedStyle(document.body).getPropertyValue(name).trim();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function pollUntilReady(): Promise<void> {
|
|
13
|
+
while (!document.body.hasAttribute('data-jp-theme-light')) {
|
|
14
|
+
await new Promise(resolve => setTimeout(resolve, 100)); // Wait 100ms
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function getJupyterLabTheme(): Promise<Theme> {
|
|
19
|
+
await pollUntilReady();
|
|
20
|
+
const light = document.body.getAttribute('data-jp-theme-light');
|
|
21
|
+
return createTheme({
|
|
22
|
+
spacing: 4,
|
|
23
|
+
components: {
|
|
24
|
+
MuiButton: {
|
|
25
|
+
defaultProps: {
|
|
26
|
+
size: 'small'
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
MuiFilledInput: {
|
|
30
|
+
defaultProps: {
|
|
31
|
+
margin: 'dense'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
MuiFormControl: {
|
|
35
|
+
defaultProps: {
|
|
36
|
+
margin: 'dense',
|
|
37
|
+
size: 'small'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
MuiFormHelperText: {
|
|
41
|
+
defaultProps: {
|
|
42
|
+
margin: 'dense'
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
MuiIconButton: {
|
|
46
|
+
defaultProps: {
|
|
47
|
+
size: 'small'
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
MuiInputBase: {
|
|
51
|
+
defaultProps: {
|
|
52
|
+
margin: 'dense',
|
|
53
|
+
size: 'small'
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
MuiInputLabel: {
|
|
57
|
+
defaultProps: {
|
|
58
|
+
margin: 'dense'
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
MuiListItem: {
|
|
62
|
+
defaultProps: {
|
|
63
|
+
dense: true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
MuiOutlinedInput: {
|
|
67
|
+
defaultProps: {
|
|
68
|
+
margin: 'dense'
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
MuiFab: {
|
|
72
|
+
defaultProps: {
|
|
73
|
+
size: 'small'
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
MuiTable: {
|
|
77
|
+
defaultProps: {
|
|
78
|
+
size: 'small'
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
MuiTextField: {
|
|
82
|
+
defaultProps: {
|
|
83
|
+
margin: 'dense',
|
|
84
|
+
size: 'small'
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
MuiToolbar: {
|
|
88
|
+
defaultProps: {
|
|
89
|
+
variant: 'dense'
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
palette: {
|
|
94
|
+
background: {
|
|
95
|
+
paper: getCSSVariable('--jp-layout-color1'),
|
|
96
|
+
default: getCSSVariable('--jp-layout-color1')
|
|
97
|
+
},
|
|
98
|
+
mode: light === 'true' ? 'light' : 'dark',
|
|
99
|
+
primary: {
|
|
100
|
+
main: getCSSVariable('--jp-brand-color1'),
|
|
101
|
+
light: getCSSVariable('--jp-brand-color2'),
|
|
102
|
+
dark: getCSSVariable('--jp-brand-color0')
|
|
103
|
+
},
|
|
104
|
+
error: {
|
|
105
|
+
main: getCSSVariable('--jp-error-color1'),
|
|
106
|
+
light: getCSSVariable('--jp-error-color2'),
|
|
107
|
+
dark: getCSSVariable('--jp-error-color0')
|
|
108
|
+
},
|
|
109
|
+
warning: {
|
|
110
|
+
main: getCSSVariable('--jp-warn-color1'),
|
|
111
|
+
light: getCSSVariable('--jp-warn-color2'),
|
|
112
|
+
dark: getCSSVariable('--jp-warn-color0')
|
|
113
|
+
},
|
|
114
|
+
success: {
|
|
115
|
+
main: getCSSVariable('--jp-success-color1'),
|
|
116
|
+
light: getCSSVariable('--jp-success-color2'),
|
|
117
|
+
dark: getCSSVariable('--jp-success-color0')
|
|
118
|
+
},
|
|
119
|
+
text: {
|
|
120
|
+
primary: getCSSVariable('--jp-ui-font-color1'),
|
|
121
|
+
secondary: getCSSVariable('--jp-ui-font-color2'),
|
|
122
|
+
disabled: getCSSVariable('--jp-ui-font-color3')
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
shape: {
|
|
126
|
+
borderRadius: 2
|
|
127
|
+
},
|
|
128
|
+
typography: {
|
|
129
|
+
fontFamily: getCSSVariable('--jp-ui-font-family'),
|
|
130
|
+
fontSize: 12,
|
|
131
|
+
htmlFontSize: 16,
|
|
132
|
+
button: {
|
|
133
|
+
textTransform: 'capitalize'
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ReactEventHandler } from 'react';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Workaround for https://github.com/mui/material-ui/issues/35287.
|
|
10
|
+
*/
|
|
11
|
+
declare global {
|
|
12
|
+
namespace React {
|
|
13
|
+
interface DOMAttributes<T> {
|
|
14
|
+
onResize?: ReactEventHandler<T> | undefined;
|
|
15
|
+
onResizeCapture?: ReactEventHandler<T> | undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Excerpted from @jupyterlab/ui-components
|
|
7
|
+
|
|
8
|
+
// including this file in a package allows for the use of import statements
|
|
9
|
+
// with svg files. Example: `import xSvg from 'path/xSvg.svg'`
|
|
10
|
+
|
|
11
|
+
// for use with raw-loader in Webpack.
|
|
12
|
+
// The svg will be imported as a raw string
|
|
13
|
+
|
|
14
|
+
declare module '*.svg' {
|
|
15
|
+
const value: string; // @ts-ignore
|
|
16
|
+
export default value;
|
|
17
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The user description.
|
|
8
|
+
*/
|
|
9
|
+
export interface IUser {
|
|
10
|
+
username: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
display_name?: string;
|
|
13
|
+
initials?: string;
|
|
14
|
+
color?: string;
|
|
15
|
+
avatar_url?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The configuration interface.
|
|
20
|
+
*/
|
|
21
|
+
export interface IConfig {
|
|
22
|
+
sendWithShiftEnter?: boolean;
|
|
23
|
+
lastRead?: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The chat message decription.
|
|
28
|
+
*/
|
|
29
|
+
export interface IChatMessage {
|
|
30
|
+
type: 'msg';
|
|
31
|
+
body: string;
|
|
32
|
+
id: string;
|
|
33
|
+
time: number;
|
|
34
|
+
sender: IUser | string;
|
|
35
|
+
raw_time?: boolean;
|
|
36
|
+
deleted?: boolean;
|
|
37
|
+
edited?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The chat history interface.
|
|
42
|
+
*/
|
|
43
|
+
export interface IChatHistory {
|
|
44
|
+
messages: IChatMessage[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The content of a new message.
|
|
49
|
+
*/
|
|
50
|
+
export interface INewMessage {
|
|
51
|
+
body: string;
|
|
52
|
+
id?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* An empty interface to describe optional settings taht could be fetched from server.
|
|
57
|
+
*/
|
|
58
|
+
export interface ISettings {}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IThemeManager, ReactWidget } from '@jupyterlab/apputils';
|
|
7
|
+
import { Alert, Box } from '@mui/material';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
import { JlThemeProvider } from '../components/jl-theme-provider';
|
|
11
|
+
import { chatIcon } from '../icons';
|
|
12
|
+
|
|
13
|
+
export function buildErrorWidget(
|
|
14
|
+
themeManager: IThemeManager | null
|
|
15
|
+
): ReactWidget {
|
|
16
|
+
const ErrorWidget = ReactWidget.create(
|
|
17
|
+
<JlThemeProvider themeManager={themeManager}>
|
|
18
|
+
<Box
|
|
19
|
+
sx={{
|
|
20
|
+
width: '100%',
|
|
21
|
+
height: '100%',
|
|
22
|
+
boxSizing: 'border-box',
|
|
23
|
+
background: 'var(--jp-layout-color0)',
|
|
24
|
+
display: 'flex',
|
|
25
|
+
flexDirection: 'column'
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
<Box sx={{ padding: 4 }}>
|
|
29
|
+
<Alert severity="error">
|
|
30
|
+
There seems to be a problem with the Chat backend, please look at
|
|
31
|
+
the JupyterLab server logs or contact your administrator to correct
|
|
32
|
+
this problem.
|
|
33
|
+
</Alert>
|
|
34
|
+
</Box>
|
|
35
|
+
</Box>
|
|
36
|
+
</JlThemeProvider>
|
|
37
|
+
);
|
|
38
|
+
ErrorWidget.id = 'jupyter-chat::chat';
|
|
39
|
+
ErrorWidget.title.icon = chatIcon;
|
|
40
|
+
ErrorWidget.title.caption = 'Jupyter Chat'; // TODO: i18n
|
|
41
|
+
|
|
42
|
+
return ErrorWidget;
|
|
43
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IThemeManager, ReactWidget } from '@jupyterlab/apputils';
|
|
7
|
+
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
import { Chat } from '../components/chat';
|
|
11
|
+
import { chatIcon } from '../icons';
|
|
12
|
+
import { IChatModel } from '../model';
|
|
13
|
+
|
|
14
|
+
export function buildChatSidebar(
|
|
15
|
+
chatModel: IChatModel,
|
|
16
|
+
themeManager: IThemeManager | null,
|
|
17
|
+
rmRegistry: IRenderMimeRegistry
|
|
18
|
+
): ReactWidget {
|
|
19
|
+
const ChatWidget = ReactWidget.create(
|
|
20
|
+
<Chat
|
|
21
|
+
model={chatModel}
|
|
22
|
+
themeManager={themeManager}
|
|
23
|
+
rmRegistry={rmRegistry}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
ChatWidget.id = 'jupyter-chat::side-panel';
|
|
27
|
+
ChatWidget.title.icon = chatIcon;
|
|
28
|
+
ChatWidget.title.caption = 'Jupyter Chat'; // TODO: i18n
|
|
29
|
+
return ChatWidget;
|
|
30
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IThemeManager, ReactWidget } from '@jupyterlab/apputils';
|
|
7
|
+
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
import { Chat } from '../components/chat';
|
|
11
|
+
import { chatIcon } from '../icons';
|
|
12
|
+
import { IChatModel } from '../model';
|
|
13
|
+
|
|
14
|
+
export class ChatWidget extends ReactWidget {
|
|
15
|
+
constructor(options: Chat.IOptions) {
|
|
16
|
+
super();
|
|
17
|
+
|
|
18
|
+
this.id = 'jupyter-chat::widget';
|
|
19
|
+
this.title.icon = chatIcon;
|
|
20
|
+
this.title.caption = 'Jupyter Chat'; // TODO: i18n
|
|
21
|
+
|
|
22
|
+
this._model = options.model;
|
|
23
|
+
this._themeManager = options?.themeManager || null;
|
|
24
|
+
this._rmRegistry = options.rmRegistry;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Gte the model of the widget.
|
|
29
|
+
*/
|
|
30
|
+
get model(): IChatModel {
|
|
31
|
+
return this._model;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
render() {
|
|
35
|
+
return (
|
|
36
|
+
<Chat
|
|
37
|
+
model={this._model}
|
|
38
|
+
themeManager={this._themeManager}
|
|
39
|
+
rmRegistry={this._rmRegistry}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private readonly _model: IChatModel;
|
|
45
|
+
private _themeManager: IThemeManager | null;
|
|
46
|
+
private _rmRegistry: IRenderMimeRegistry;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export namespace ChatWidget {
|
|
50
|
+
export interface IOptions extends Chat.IOptions {}
|
|
51
|
+
}
|
package/style/base.css
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
See the JupyterLab Developer Guide for useful CSS Patterns:
|
|
8
|
+
|
|
9
|
+
https://jupyterlab.readthedocs.io/en/stable/developer/css.html
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
@import url('./chat.css');
|
|
13
|
+
@import url('./chat-settings.css');
|
package/style/chat.css
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Jupyter Development Team.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
.jp-chat-rendermime-markdown {
|
|
7
|
+
position: relative;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.jp-chat-rendermime-markdown .jp-RenderedHTMLCommon {
|
|
11
|
+
padding-right: 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.jp-chat-rendermime-markdown pre {
|
|
15
|
+
background-color: var(--jp-cell-editor-background);
|
|
16
|
+
overflow-x: auto;
|
|
17
|
+
white-space: pre;
|
|
18
|
+
margin: 0;
|
|
19
|
+
padding: 4px 2px 0 6px;
|
|
20
|
+
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.jp-chat-rendermime-markdown pre > code {
|
|
24
|
+
background-color: inherit;
|
|
25
|
+
overflow-x: inherit;
|
|
26
|
+
white-space: inherit;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.jp-chat-rendermime-markdown mjx-container {
|
|
30
|
+
font-size: 119%;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.jp-chat-toolbar {
|
|
34
|
+
display: none;
|
|
35
|
+
position: absolute;
|
|
36
|
+
right: 2px;
|
|
37
|
+
top: 2px;
|
|
38
|
+
font-size: var(--jp-ui-font-size0);
|
|
39
|
+
color: var(--jp-ui-font-color3);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.jp-chat-rendermime-markdown:hover .jp-chat-toolbar {
|
|
43
|
+
display: inherit;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.jp-chat-toolbar:hover {
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
color: var(--jp-ui-font-color2);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.jp-chat-toolbar > .jp-ToolbarButtonComponent {
|
|
52
|
+
margin-top: 0px;
|
|
53
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="16" viewBox="0 0 24 24" width="16">
|
|
2
|
+
<g class="jp-icon3" fill="#616161">
|
|
3
|
+
<path d="M0 0h24v24H0V0z" fill="none"/>
|
|
4
|
+
<path d="M15 4v7H5.17L4 12.17V4h11m1-2H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm5 4h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1z"/>
|
|
5
|
+
</g>
|
|
6
|
+
</svg>
|
package/style/index.css
ADDED