@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.
Files changed (66) hide show
  1. package/lib/__tests__/model.spec.d.ts +1 -0
  2. package/lib/__tests__/model.spec.js +72 -0
  3. package/lib/__tests__/widgets.spec.d.ts +1 -0
  4. package/lib/__tests__/widgets.spec.js +33 -0
  5. package/lib/components/chat-input.d.ts +33 -0
  6. package/lib/components/chat-input.js +60 -0
  7. package/lib/components/chat-messages.d.ts +32 -0
  8. package/lib/components/chat-messages.js +162 -0
  9. package/lib/components/chat.d.ts +43 -0
  10. package/lib/components/chat.js +100 -0
  11. package/lib/components/copy-button.d.ts +6 -0
  12. package/lib/components/copy-button.js +35 -0
  13. package/lib/components/jl-theme-provider.d.ts +6 -0
  14. package/lib/components/jl-theme-provider.js +19 -0
  15. package/lib/components/mui-extras/stacking-alert.d.ts +28 -0
  16. package/lib/components/mui-extras/stacking-alert.js +56 -0
  17. package/lib/components/rendermime-markdown.d.ts +12 -0
  18. package/lib/components/rendermime-markdown.js +54 -0
  19. package/lib/components/scroll-container.d.ts +23 -0
  20. package/lib/components/scroll-container.js +51 -0
  21. package/lib/components/toolbar.d.ts +11 -0
  22. package/lib/components/toolbar.js +30 -0
  23. package/lib/icons.d.ts +2 -0
  24. package/lib/icons.js +11 -0
  25. package/lib/index.d.ts +6 -0
  26. package/lib/index.js +10 -0
  27. package/lib/model.d.ts +177 -0
  28. package/lib/model.js +128 -0
  29. package/lib/theme-provider.d.ts +3 -0
  30. package/lib/theme-provider.js +133 -0
  31. package/lib/types.d.ts +49 -0
  32. package/lib/types.js +5 -0
  33. package/lib/widgets/chat-error.d.ts +2 -0
  34. package/lib/widgets/chat-error.js +26 -0
  35. package/lib/widgets/chat-sidebar.d.ts +4 -0
  36. package/lib/widgets/chat-sidebar.js +15 -0
  37. package/lib/widgets/chat-widget.d.ts +19 -0
  38. package/lib/widgets/chat-widget.js +28 -0
  39. package/package.json +209 -0
  40. package/src/__tests__/model.spec.ts +84 -0
  41. package/src/__tests__/widgets.spec.ts +43 -0
  42. package/src/components/chat-input.tsx +143 -0
  43. package/src/components/chat-messages.tsx +283 -0
  44. package/src/components/chat.tsx +179 -0
  45. package/src/components/copy-button.tsx +55 -0
  46. package/src/components/jl-theme-provider.tsx +28 -0
  47. package/src/components/mui-extras/stacking-alert.tsx +105 -0
  48. package/src/components/rendermime-markdown.tsx +88 -0
  49. package/src/components/scroll-container.tsx +74 -0
  50. package/src/components/toolbar.tsx +50 -0
  51. package/src/icons.ts +15 -0
  52. package/src/index.ts +11 -0
  53. package/src/model.ts +272 -0
  54. package/src/theme-provider.ts +137 -0
  55. package/src/types/mui.d.ts +18 -0
  56. package/src/types/svg.d.ts +17 -0
  57. package/src/types.ts +58 -0
  58. package/src/widgets/chat-error.tsx +43 -0
  59. package/src/widgets/chat-sidebar.tsx +30 -0
  60. package/src/widgets/chat-widget.tsx +51 -0
  61. package/style/base.css +13 -0
  62. package/style/chat-settings.css +10 -0
  63. package/style/chat.css +53 -0
  64. package/style/icons/chat.svg +6 -0
  65. package/style/index.css +6 -0
  66. 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');
@@ -0,0 +1,10 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+
6
+ .jp-chat-SettingsHeader {
7
+ font-size: var(--jp-ui-font-size3);
8
+ font-weight: 400;
9
+ color: var(--jp-ui-font-color1);
10
+ }
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>
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+
6
+ @import url('base.css');
package/style/index.js ADDED
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+
6
+ import './base.css';