@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.
Files changed (73) hide show
  1. package/lib/active-cell-manager.js +4 -2
  2. package/lib/components/attachments.js +3 -3
  3. package/lib/components/chat.d.ts +3 -7
  4. package/lib/components/chat.js +9 -5
  5. package/lib/components/code-blocks/code-toolbar.js +8 -28
  6. package/lib/components/code-blocks/copy-button.js +4 -11
  7. package/lib/components/index.d.ts +1 -0
  8. package/lib/components/index.js +1 -0
  9. package/lib/components/input/buttons/attach-button.js +3 -10
  10. package/lib/components/input/buttons/cancel-button.js +6 -10
  11. package/lib/components/input/buttons/save-edit-button.js +6 -13
  12. package/lib/components/input/buttons/send-button.js +6 -23
  13. package/lib/components/input/buttons/stop-button.js +6 -23
  14. package/lib/components/input/chat-input.d.ts +0 -20
  15. package/lib/components/input/chat-input.js +21 -18
  16. package/lib/components/messages/footer.d.ts +5 -5
  17. package/lib/components/messages/footer.js +7 -2
  18. package/lib/components/messages/header.js +10 -8
  19. package/lib/components/messages/message-renderer.d.ts +0 -10
  20. package/lib/components/messages/message-renderer.js +5 -3
  21. package/lib/components/messages/message.d.ts +8 -4
  22. package/lib/components/messages/message.js +4 -2
  23. package/lib/components/messages/messages.d.ts +1 -39
  24. package/lib/components/messages/messages.js +31 -13
  25. package/lib/components/messages/navigation.d.ts +1 -2
  26. package/lib/components/messages/navigation.js +2 -1
  27. package/lib/components/messages/toolbar.js +12 -26
  28. package/lib/components/messages/welcome.d.ts +10 -2
  29. package/lib/components/messages/welcome.js +2 -1
  30. package/lib/components/mui-extras/tooltipped-button.d.ts +28 -1
  31. package/lib/components/mui-extras/tooltipped-button.js +34 -6
  32. package/lib/components/mui-extras/tooltipped-icon-button.d.ts +6 -1
  33. package/lib/components/mui-extras/tooltipped-icon-button.js +8 -7
  34. package/lib/context.d.ts +3 -2
  35. package/lib/context.js +9 -2
  36. package/lib/index.d.ts +1 -0
  37. package/lib/index.js +1 -0
  38. package/lib/tokens.d.ts +11 -0
  39. package/lib/tokens.js +9 -0
  40. package/lib/types.d.ts +4 -0
  41. package/lib/widgets/chat-widget.d.ts +5 -0
  42. package/lib/widgets/chat-widget.js +6 -0
  43. package/lib/widgets/multichat-panel.d.ts +1 -6
  44. package/lib/widgets/multichat-panel.js +3 -13
  45. package/package.json +1 -1
  46. package/src/active-cell-manager.ts +3 -1
  47. package/src/components/attachments.tsx +3 -3
  48. package/src/components/chat.tsx +13 -24
  49. package/src/components/code-blocks/code-toolbar.tsx +29 -55
  50. package/src/components/code-blocks/copy-button.tsx +13 -20
  51. package/src/components/index.ts +1 -0
  52. package/src/components/input/buttons/attach-button.tsx +5 -13
  53. package/src/components/input/buttons/cancel-button.tsx +11 -18
  54. package/src/components/input/buttons/save-edit-button.tsx +13 -22
  55. package/src/components/input/buttons/send-button.tsx +13 -34
  56. package/src/components/input/buttons/stop-button.tsx +13 -34
  57. package/src/components/input/chat-input.tsx +24 -38
  58. package/src/components/messages/footer.tsx +12 -10
  59. package/src/components/messages/header.tsx +23 -17
  60. package/src/components/messages/message-renderer.tsx +5 -13
  61. package/src/components/messages/message.tsx +4 -7
  62. package/src/components/messages/messages.tsx +73 -97
  63. package/src/components/messages/navigation.tsx +3 -3
  64. package/src/components/messages/toolbar.tsx +19 -33
  65. package/src/components/messages/welcome.tsx +13 -2
  66. package/src/components/mui-extras/tooltipped-button.tsx +44 -5
  67. package/src/components/mui-extras/tooltipped-icon-button.tsx +22 -6
  68. package/src/context.ts +15 -5
  69. package/src/index.ts +1 -0
  70. package/src/tokens.ts +24 -0
  71. package/src/types.ts +4 -0
  72. package/src/widgets/chat-widget.tsx +8 -0
  73. package/src/widgets/multichat-panel.tsx +7 -26
@@ -5,9 +5,11 @@
5
5
 
6
6
  // import EditIcon from '@mui/icons-material/Edit';
7
7
  import DeleteIcon from '@mui/icons-material/Delete';
8
- import { Box, IconButton, Tooltip } from '@mui/material';
8
+ import { Box } from '@mui/material';
9
9
  import React from 'react';
10
10
 
11
+ import { TooltippedIconButton } from '../mui-extras';
12
+
11
13
  const TOOLBAR_CLASS = 'jp-chat-toolbar';
12
14
 
13
15
  /**
@@ -18,43 +20,27 @@ export function MessageToolbar(props: MessageToolbar.IProps): JSX.Element {
18
20
 
19
21
  // if (props.edit !== undefined) {
20
22
  // const editButton = (
21
- // <Tooltip key="edit" title="Edit" placement="top" arrow>
22
- // <span>
23
- // <IconButton
24
- // onClick={props.edit}
25
- // aria-label="Edit"
26
- // sx={{
27
- // width: '24px',
28
- // height: '24px',
29
- // padding: 0,
30
- // lineHeight: 0
31
- // }}
32
- // >
33
- // <EditIcon sx={{ fontSize: '16px' }} />
34
- // </IconButton>
35
- // </span>
36
- // </Tooltip>
23
+ // <TooltippedIconButton
24
+ // tooltip={'edit'}
25
+ // onClick={props.edit}
26
+ // aria-label={'Edit'}
27
+ // inputToolbar={false}
28
+ // >
29
+ // <EditIcon />
30
+ // </TooltippedIconButton>
37
31
  // );
38
32
  // buttons.push(editButton);
39
33
  // }
40
34
  if (props.delete !== undefined) {
41
35
  const deleteButton = (
42
- <Tooltip key="delete" title="Delete" placement="top" arrow>
43
- <span>
44
- <IconButton
45
- onClick={props.delete}
46
- aria-label="Delete"
47
- sx={{
48
- width: '24px',
49
- height: '24px',
50
- padding: 0,
51
- lineHeight: 0
52
- }}
53
- >
54
- <DeleteIcon sx={{ fontSize: '16px' }} />
55
- </IconButton>
56
- </span>
57
- </Tooltip>
36
+ <TooltippedIconButton
37
+ tooltip={'Delete'}
38
+ onClick={props.delete}
39
+ aria-label={'Delete'}
40
+ inputToolbar={false}
41
+ >
42
+ <DeleteIcon />
43
+ </TooltippedIconButton>
58
44
  );
59
45
  buttons.push(deleteButton);
60
46
  }
@@ -6,17 +6,28 @@
6
6
  import { classes } from '@jupyterlab/ui-components';
7
7
  import React, { useEffect, useRef } from 'react';
8
8
 
9
+ import { useChatContext } from '../../context';
9
10
  import { MarkdownRenderer, MD_RENDERED_CLASS } from '../../markdown-renderer';
10
11
 
11
12
  const WELCOME_MESSAGE_CLASS = 'jp-chat-welcome-message';
12
13
 
14
+ /**
15
+ * The component props.
16
+ */
17
+ export interface IWelcomeMessageProps {
18
+ /**
19
+ * The content of the welcome message (markdown).
20
+ */
21
+ content: string;
22
+ }
23
+
13
24
  /**
14
25
  * The welcome message component.
15
26
  * This message is displayed on top of the chat messages, and is rendered using a
16
27
  * markdown renderer.
17
28
  */
18
- export function WelcomeMessage(props: MarkdownRenderer.IOptions): JSX.Element {
19
- const { rmRegistry } = props;
29
+ export function WelcomeMessage(props: IWelcomeMessageProps): JSX.Element {
30
+ const { rmRegistry } = useChatContext();
20
31
  const content = props.content + '\n----\n';
21
32
 
22
33
  // ref that tracks the content container to store the rendermime node in
@@ -3,17 +3,55 @@
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
5
 
6
- import { Button, ButtonProps, SxProps, TooltipProps } from '@mui/material';
6
+ import {
7
+ Button,
8
+ ButtonOwnProps,
9
+ ButtonProps,
10
+ SxProps,
11
+ TooltipProps
12
+ } from '@mui/material';
7
13
  import React from 'react';
8
14
 
9
15
  import { ContrastingTooltip } from './contrasting-tooltip';
10
16
 
11
- const TOOLTIPPED_WRAP_CLASS = 'jp-chat-tooltipped-wrap';
17
+ export const TOOLTIPPED_WRAP_CLASS = 'jp-chat-tooltipped-wrap';
18
+
19
+ export const DEFAULT_BUTTON_PROPS: Partial<ButtonOwnProps> = {
20
+ size: 'small',
21
+ variant: 'contained'
22
+ };
23
+
24
+ export const DEFAULT_BUTTON_SX = {
25
+ minWidth: '24px',
26
+ width: '24px',
27
+ height: '24px',
28
+ lineHeight: 0,
29
+ '&:disabled': {
30
+ opacity: 0.5
31
+ }
32
+ };
33
+
34
+ export const INPUT_TOOLBAR_BUTTON_SX = {
35
+ backgroundColor: 'var(--jp-brand-color1)',
36
+ color: 'white',
37
+ borderRadius: '4px',
38
+ boxShadow: 'none',
39
+ '&:hover': {
40
+ backgroundColor: 'var(--jp-brand-color0)',
41
+ boxShadow: 'none'
42
+ },
43
+ '&:disabled': {
44
+ backgroundColor: 'var(--jp-border-color2)',
45
+ color: 'var(--jp-ui-font-color3)',
46
+ opacity: 0.5
47
+ }
48
+ };
12
49
 
13
50
  export type TooltippedButtonProps = {
14
51
  onClick: React.MouseEventHandler<HTMLButtonElement>;
15
52
  tooltip: string;
16
53
  children: JSX.Element;
54
+ inputToolbar?: boolean;
17
55
  disabled?: boolean;
18
56
  placement?: TooltipProps['placement'];
19
57
  /**
@@ -76,15 +114,16 @@ export function TooltippedButton(props: TooltippedButtonProps): JSX.Element {
76
114
  */}
77
115
  <span style={{ cursor: 'default' }} className={TOOLTIPPED_WRAP_CLASS}>
78
116
  <Button
117
+ {...DEFAULT_BUTTON_PROPS}
79
118
  {...props.buttonProps}
80
119
  onClick={props.onClick}
81
120
  disabled={props.disabled}
82
121
  sx={{
83
- lineHeight: 0,
84
- ...(props.disabled && { opacity: 0.5 }),
122
+ ...DEFAULT_BUTTON_SX,
123
+ ...((props.inputToolbar ?? true) && INPUT_TOOLBAR_BUTTON_SX),
85
124
  ...props.sx
86
125
  }}
87
- aria-label={props['aria-label']}
126
+ aria-label={props['aria-label'] ?? props.tooltip}
88
127
  >
89
128
  {props.children}
90
129
  </Button>
@@ -4,20 +4,34 @@
4
4
  */
5
5
 
6
6
  import { classes } from '@jupyterlab/ui-components';
7
- import { IconButton, IconButtonProps, TooltipProps } from '@mui/material';
7
+ import {
8
+ IconButton,
9
+ IconButtonProps,
10
+ SvgIconOwnProps,
11
+ TooltipProps
12
+ } from '@mui/material';
8
13
  import React from 'react';
9
14
 
10
15
  import { ContrastingTooltip } from './contrasting-tooltip';
11
-
12
- const TOOLTIPPED_WRAP_CLASS = 'jp-chat-tooltipped-wrap';
16
+ import {
17
+ DEFAULT_BUTTON_PROPS,
18
+ DEFAULT_BUTTON_SX,
19
+ INPUT_TOOLBAR_BUTTON_SX,
20
+ TOOLTIPPED_WRAP_CLASS
21
+ } from './tooltipped-button';
13
22
 
14
23
  export type TooltippedIconButtonProps = {
15
24
  onClick: () => unknown;
16
25
  tooltip: string;
17
26
  children: JSX.Element;
18
27
  className?: string;
28
+ inputToolbar?: boolean;
19
29
  disabled?: boolean;
20
30
  placement?: TooltipProps['placement'];
31
+ /**
32
+ * The font size of the icon. By default it will be set to 'small'.
33
+ */
34
+ fontSize?: SvgIconOwnProps['fontSize'];
21
35
  /**
22
36
  * The offset of the tooltip popup.
23
37
  *
@@ -47,6 +61,8 @@ export type TooltippedIconButtonProps = {
47
61
  export function TooltippedIconButton(
48
62
  props: TooltippedIconButtonProps
49
63
  ): JSX.Element {
64
+ // Override the default icon font size from 'medium' to 'small'
65
+ props.children.props.fontSize = props.fontSize ?? 'small';
50
66
  return (
51
67
  <ContrastingTooltip
52
68
  title={props.tooltip}
@@ -73,13 +89,13 @@ export function TooltippedIconButton(
73
89
  */}
74
90
  <span className={classes(props.className, TOOLTIPPED_WRAP_CLASS)}>
75
91
  <IconButton
92
+ {...DEFAULT_BUTTON_PROPS}
76
93
  {...props.iconButtonProps}
77
94
  onClick={props.onClick}
78
95
  disabled={props.disabled}
79
96
  sx={{
80
- marginLeft: '8px',
81
- lineHeight: 0,
82
- ...(props.disabled && { opacity: 0.5 })
97
+ ...DEFAULT_BUTTON_SX,
98
+ ...((props.inputToolbar ?? true) && INPUT_TOOLBAR_BUTTON_SX)
83
99
  }}
84
100
  aria-label={props['aria-label']}
85
101
  >
package/src/context.ts CHANGED
@@ -2,9 +2,19 @@
2
2
  * Copyright (c) Jupyter Development Team.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
- import { createContext } from 'react';
6
- import { IAttachmentOpenerRegistry } from './registers';
7
5
 
8
- export const AttachmentOpenerContext = createContext<
9
- IAttachmentOpenerRegistry | undefined
10
- >(undefined);
6
+ import { createContext, useContext } from 'react';
7
+
8
+ import { Chat } from './components';
9
+
10
+ export const ChatReactContext = createContext<Chat.IChatProps | undefined>(
11
+ undefined
12
+ );
13
+
14
+ export function useChatContext(): Chat.IChatProps {
15
+ const context = useContext(ChatReactContext);
16
+ if (!context) {
17
+ throw new Error('The chat context is missing in the chat');
18
+ }
19
+ return context;
20
+ }
package/src/index.ts CHANGED
@@ -11,5 +11,6 @@ export * from './markdown-renderer';
11
11
  export * from './model';
12
12
  export * from './registers';
13
13
  export * from './selection-watcher';
14
+ export * from './tokens';
14
15
  export * from './types';
15
16
  export * from './widgets';
package/src/tokens.ts ADDED
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+
6
+ import { IWidgetTracker, MainAreaWidget } from '@jupyterlab/apputils';
7
+ import { Token } from '@lumino/coreutils';
8
+
9
+ import { ChatWidget } from './widgets';
10
+
11
+ /**
12
+ * the chat tracker type.
13
+ */
14
+ export type IChatTracker = IWidgetTracker<
15
+ ChatWidget | MainAreaWidget<ChatWidget>
16
+ >;
17
+
18
+ /**
19
+ * A chat tracker token.
20
+ */
21
+ export const IChatTracker = new Token<IChatTracker>(
22
+ '@jupyter/chat:IChatTracker',
23
+ 'The chat widget tracker'
24
+ );
package/src/types.ts CHANGED
@@ -52,6 +52,10 @@ export interface IConfig {
52
52
  * Whether to send typing notification.
53
53
  */
54
54
  sendTypingNotification?: boolean;
55
+ /**
56
+ * Whether to display deleted messages.
57
+ */
58
+ showDeleted?: boolean;
55
59
  }
56
60
 
57
61
  /**
@@ -15,6 +15,7 @@ import { Chat, IInputToolbarRegistry, MESSAGE_CLASS } from '../components';
15
15
  import { chatIcon } from '../icons';
16
16
  import { IChatModel } from '../model';
17
17
  import {
18
+ ChatArea,
18
19
  IFileAttachment,
19
20
  INotebookAttachment,
20
21
  INotebookAttachmentCell
@@ -71,6 +72,13 @@ export class ChatWidget extends ReactWidget {
71
72
  return this._chatOptions.model;
72
73
  }
73
74
 
75
+ /**
76
+ * The area where the chat is opened.
77
+ */
78
+ get area(): ChatArea | undefined {
79
+ return this._chatOptions.area;
80
+ }
81
+
74
82
  /**
75
83
  * Get the input toolbar registry (if it has been provided when creating the widget).
76
84
  */
@@ -8,8 +8,7 @@
8
8
  * Originally adapted from jupyterlab-chat's ChatPanel
9
9
  */
10
10
 
11
- import { InputDialog, IThemeManager } from '@jupyterlab/apputils';
12
- import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
11
+ import { InputDialog } from '@jupyterlab/apputils';
13
12
  import {
14
13
  addIcon,
15
14
  closeIcon,
@@ -34,11 +33,6 @@ import {
34
33
  } from '../components';
35
34
  import { chatIcon, readIcon } from '../icons';
36
35
  import { IChatModel } from '../model';
37
- import {
38
- IAttachmentOpenerRegistry,
39
- IChatCommandRegistry,
40
- IMessageFooterRegistry
41
- } from '../registers';
42
36
 
43
37
  const SIDEPANEL_CLASS = 'jp-chat-sidepanel';
44
38
  const ADD_BUTTON_CLASS = 'jp-chat-add';
@@ -58,13 +52,8 @@ export class MultiChatPanel extends SidePanel {
58
52
 
59
53
  this.addClass(SIDEPANEL_CLASS);
60
54
 
61
- this._rmRegistry = options.rmRegistry;
62
- this._themeManager = options.themeManager;
63
- this._chatCommandRegistry = options.chatCommandRegistry;
64
- this._attachmentOpenerRegistry = options.attachmentOpenerRegistry;
55
+ this._chatOptions = options;
65
56
  this._inputToolbarFactory = options.inputToolbarFactory;
66
- this._messageFooterRegistry = options.messageFooterRegistry;
67
- this._welcomeMessage = options.welcomeMessage;
68
57
 
69
58
  this._getChatNames = options.getChatNames;
70
59
  this._createModel = options.createModel;
@@ -149,13 +138,8 @@ export class MultiChatPanel extends SidePanel {
149
138
  // Create a new widget.
150
139
  const widget = new ChatWidget({
151
140
  model,
152
- rmRegistry: this._rmRegistry,
153
- themeManager: this._themeManager,
154
- chatCommandRegistry: this._chatCommandRegistry,
155
- attachmentOpenerRegistry: this._attachmentOpenerRegistry,
141
+ ...this._chatOptions,
156
142
  inputToolbarRegistry,
157
- messageFooterRegistry: this._messageFooterRegistry,
158
- welcomeMessage: this._welcomeMessage,
159
143
  area: 'sidebar'
160
144
  });
161
145
 
@@ -267,13 +251,8 @@ export class MultiChatPanel extends SidePanel {
267
251
  this
268
252
  );
269
253
  private _sectionAdded = new Signal<MultiChatPanel, ChatSection>(this);
270
- private _rmRegistry: IRenderMimeRegistry;
271
- private _themeManager?: IThemeManager | null;
272
- private _chatCommandRegistry?: IChatCommandRegistry;
273
- private _attachmentOpenerRegistry?: IAttachmentOpenerRegistry;
254
+ private _chatOptions: Omit<Chat.IOptions, 'model' | 'inputToolbarRegistry'>;
274
255
  private _inputToolbarFactory?: IInputToolbarRegistryFactory;
275
- private _messageFooterRegistry?: IMessageFooterRegistry;
276
- private _welcomeMessage?: string;
277
256
  private _updateChatListDebouncer: Debouncer;
278
257
 
279
258
  private _createModel?: (
@@ -568,7 +547,9 @@ function ChatSelect({
568
547
 
569
548
  return (
570
549
  <HTMLSelect onChange={handleChange} value="-">
571
- <option value="-">Open a chat</option>
550
+ <option value="-" disabled hidden>
551
+ Open a chat
552
+ </option>
572
553
  {Object.keys(chatNames).map(name => (
573
554
  <option value={chatNames[name]}>{name}</option>
574
555
  ))}