@stack-spot/ai-chat-widget 1.0.0 → 1.1.1
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/CHANGELOG.md +17 -0
- package/dist/StackspotAIWidget.d.ts +20 -0
- package/dist/StackspotAIWidget.d.ts.map +1 -1
- package/dist/StackspotAIWidget.js +7 -3
- package/dist/StackspotAIWidget.js.map +1 -1
- package/dist/chat-interceptors/CustomInputs.d.ts +4 -1
- package/dist/chat-interceptors/CustomInputs.d.ts.map +1 -1
- package/dist/chat-interceptors/CustomInputs.js +10 -1
- package/dist/chat-interceptors/CustomInputs.js.map +1 -1
- package/dist/chat-interceptors/quick-command-questions.d.ts +10 -0
- package/dist/chat-interceptors/quick-command-questions.d.ts.map +1 -1
- package/dist/chat-interceptors/quick-command-questions.js +12 -2
- package/dist/chat-interceptors/quick-command-questions.js.map +1 -1
- package/dist/chat-interceptors/quick-commands.d.ts +11 -0
- package/dist/chat-interceptors/quick-commands.d.ts.map +1 -1
- package/dist/chat-interceptors/quick-commands.js +42 -3
- package/dist/chat-interceptors/quick-commands.js.map +1 -1
- package/dist/chat-interceptors/send-message.d.ts +10 -0
- package/dist/chat-interceptors/send-message.d.ts.map +1 -1
- package/dist/chat-interceptors/send-message.js +18 -0
- package/dist/chat-interceptors/send-message.js.map +1 -1
- package/dist/components/Accordion.d.ts +10 -0
- package/dist/components/Accordion.d.ts.map +1 -1
- package/dist/components/Accordion.js +3 -0
- package/dist/components/Accordion.js.map +1 -1
- package/dist/components/AdaptiveTextArea.d.ts +12 -0
- package/dist/components/AdaptiveTextArea.d.ts.map +1 -1
- package/dist/components/AdaptiveTextArea.js +3 -0
- package/dist/components/AdaptiveTextArea.js.map +1 -1
- package/dist/components/AutoFocus.d.ts +17 -0
- package/dist/components/AutoFocus.d.ts.map +1 -1
- package/dist/components/AutoFocus.js +6 -5
- package/dist/components/AutoFocus.js.map +1 -1
- package/dist/components/Fading.d.ts +19 -2
- package/dist/components/Fading.d.ts.map +1 -1
- package/dist/components/Fading.js +6 -4
- package/dist/components/Fading.js.map +1 -1
- package/dist/components/FadingOverflow.d.ts +25 -0
- package/dist/components/FadingOverflow.d.ts.map +1 -1
- package/dist/components/FadingOverflow.js +11 -2
- package/dist/components/FadingOverflow.js.map +1 -1
- package/dist/components/FallbackBoundary/index.d.ts +6 -0
- package/dist/components/FallbackBoundary/index.d.ts.map +1 -1
- package/dist/components/FallbackBoundary/index.js.map +1 -1
- package/dist/components/HistoryList.d.ts +15 -0
- package/dist/components/HistoryList.d.ts.map +1 -1
- package/dist/components/HistoryList.js +3 -1
- package/dist/components/HistoryList.js.map +1 -1
- package/dist/components/IconInput.d.ts +3 -0
- package/dist/components/IconInput.d.ts.map +1 -1
- package/dist/components/IconInput.js +3 -0
- package/dist/components/IconInput.js.map +1 -1
- package/dist/components/OverlayMenu.d.ts +11 -0
- package/dist/components/OverlayMenu.d.ts.map +1 -1
- package/dist/components/OverlayMenu.js +5 -1
- package/dist/components/OverlayMenu.js.map +1 -1
- package/dist/components/ProgressBar.d.ts +22 -0
- package/dist/components/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar.js +5 -0
- package/dist/components/ProgressBar.js.map +1 -1
- package/dist/components/QuickStartButton.d.ts.map +1 -1
- package/dist/components/QuickStartButton.js +3 -0
- package/dist/components/QuickStartButton.js.map +1 -1
- package/dist/components/RightPanelForm.d.ts +3 -0
- package/dist/components/RightPanelForm.d.ts.map +1 -1
- package/dist/components/RightPanelForm.js +3 -0
- package/dist/components/RightPanelForm.js.map +1 -1
- package/dist/components/RightPanelTabs.d.ts +3 -0
- package/dist/components/RightPanelTabs.d.ts.map +1 -1
- package/dist/components/RightPanelTabs.js +3 -0
- package/dist/components/RightPanelTabs.js.map +1 -1
- package/dist/components/TabManager.d.ts +6 -0
- package/dist/components/TabManager.d.ts.map +1 -1
- package/dist/components/TabManager.js +8 -0
- package/dist/components/TabManager.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +23 -0
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +4 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tooltip/TooltipAPI.d.ts +16 -0
- package/dist/components/Tooltip/TooltipAPI.d.ts.map +1 -1
- package/dist/components/Tooltip/TooltipAPI.js +17 -0
- package/dist/components/Tooltip/TooltipAPI.js.map +1 -1
- package/dist/components/Tooltip/types.d.ts +13 -0
- package/dist/components/Tooltip/types.d.ts.map +1 -1
- package/dist/components/form/DescribedCheckboxGroup.d.ts +4 -0
- package/dist/components/form/DescribedCheckboxGroup.d.ts.map +1 -1
- package/dist/components/form/DescribedCheckboxGroup.js +4 -0
- package/dist/components/form/DescribedCheckboxGroup.js.map +1 -1
- package/dist/components/form/DescribedRadioGroup.d.ts +4 -0
- package/dist/components/form/DescribedRadioGroup.d.ts.map +1 -1
- package/dist/components/form/DescribedRadioGroup.js +4 -0
- package/dist/components/form/DescribedRadioGroup.js.map +1 -1
- package/dist/components/form/types.d.ts +34 -0
- package/dist/components/form/types.d.ts.map +1 -1
- package/dist/context/AIWidgetProvider.d.ts +19 -0
- package/dist/context/AIWidgetProvider.d.ts.map +1 -1
- package/dist/context/AIWidgetProvider.js +19 -0
- package/dist/context/AIWidgetProvider.js.map +1 -1
- package/dist/context/hooks.d.ts +56 -0
- package/dist/context/hooks.d.ts.map +1 -1
- package/dist/context/hooks.js +56 -1
- package/dist/context/hooks.js.map +1 -1
- package/dist/features.d.ts +28 -0
- package/dist/features.d.ts.map +1 -1
- package/dist/features.js +1 -0
- package/dist/features.js.map +1 -1
- package/dist/right-panel/DefaultPanel.d.ts +3 -0
- package/dist/right-panel/DefaultPanel.d.ts.map +1 -1
- package/dist/right-panel/DefaultPanel.js +4 -3
- package/dist/right-panel/DefaultPanel.js.map +1 -1
- package/dist/right-panel/RightPanel.d.ts +3 -0
- package/dist/right-panel/RightPanel.d.ts.map +1 -1
- package/dist/right-panel/RightPanel.js +3 -0
- package/dist/right-panel/RightPanel.js.map +1 -1
- package/dist/right-panel/RightPanelProvider.d.ts +15 -0
- package/dist/right-panel/RightPanelProvider.d.ts.map +1 -1
- package/dist/right-panel/RightPanelProvider.js.map +1 -1
- package/dist/right-panel/hooks.d.ts +6 -0
- package/dist/right-panel/hooks.d.ts.map +1 -1
- package/dist/right-panel/hooks.js +6 -0
- package/dist/right-panel/hooks.js.map +1 -1
- package/dist/state/ChatEntry.d.ts +58 -2
- package/dist/state/ChatEntry.d.ts.map +1 -1
- package/dist/state/ChatEntry.js +20 -1
- package/dist/state/ChatEntry.js.map +1 -1
- package/dist/state/ChatState.d.ts +73 -8
- package/dist/state/ChatState.d.ts.map +1 -1
- package/dist/state/ChatState.js +24 -7
- package/dist/state/ChatState.js.map +1 -1
- package/dist/state/ChatTabsController.d.ts +31 -0
- package/dist/state/ChatTabsController.d.ts.map +1 -1
- package/dist/state/ChatTabsController.js +31 -0
- package/dist/state/ChatTabsController.js.map +1 -1
- package/dist/state/ObservableState.d.ts +14 -0
- package/dist/state/ObservableState.d.ts.map +1 -1
- package/dist/state/ObservableState.js +14 -0
- package/dist/state/ObservableState.js.map +1 -1
- package/dist/state/WidgetState.d.ts +5 -0
- package/dist/state/WidgetState.d.ts.map +1 -1
- package/dist/state/WidgetState.js +5 -0
- package/dist/state/WidgetState.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/chat.d.ts +13 -0
- package/dist/utils/chat.d.ts.map +1 -1
- package/dist/utils/chat.js +16 -1
- package/dist/utils/chat.js.map +1 -1
- package/dist/utils/date.d.ts +25 -0
- package/dist/utils/date.d.ts.map +1 -1
- package/dist/utils/date.js +25 -0
- package/dist/utils/date.js.map +1 -1
- package/dist/utils/download.d.ts +5 -0
- package/dist/utils/download.d.ts.map +1 -1
- package/dist/utils/download.js +5 -0
- package/dist/utils/download.js.map +1 -1
- package/dist/utils/knowledge-source.d.ts +10 -0
- package/dist/utils/knowledge-source.d.ts.map +1 -1
- package/dist/utils/knowledge-source.js +16 -0
- package/dist/utils/knowledge-source.js.map +1 -1
- package/dist/utils/string.d.ts +5 -0
- package/dist/utils/string.d.ts.map +1 -1
- package/dist/utils/string.js +5 -1
- package/dist/utils/string.js.map +1 -1
- package/dist/views/Agents.js +3 -0
- package/dist/views/Agents.js.map +1 -1
- package/dist/views/Chat/AgentInfo.d.ts +3 -0
- package/dist/views/Chat/AgentInfo.d.ts.map +1 -1
- package/dist/views/Chat/AgentInfo.js +3 -0
- package/dist/views/Chat/AgentInfo.js.map +1 -1
- package/dist/views/Chat/ChatMessage.d.ts +17 -2
- package/dist/views/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/views/Chat/ChatMessage.js +6 -32
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/Chat/ChatMessages.d.ts +3 -0
- package/dist/views/Chat/ChatMessages.d.ts.map +1 -1
- package/dist/views/Chat/ChatMessages.js +3 -0
- package/dist/views/Chat/ChatMessages.js.map +1 -1
- package/dist/views/Chat/chat-scroll.d.ts +1 -1
- package/dist/views/Chat/chat-scroll.js +1 -1
- package/dist/views/Chat/events.d.ts +22 -0
- package/dist/views/Chat/events.d.ts.map +1 -0
- package/dist/views/Chat/events.js +66 -0
- package/dist/views/Chat/events.js.map +1 -0
- package/dist/views/Chat/index.d.ts +6 -0
- package/dist/views/Chat/index.d.ts.map +1 -1
- package/dist/views/Chat/index.js +3 -0
- package/dist/views/Chat/index.js.map +1 -1
- package/dist/views/ChatHistory/ChatHistoryPanel.d.ts +3 -0
- package/dist/views/ChatHistory/ChatHistoryPanel.d.ts.map +1 -1
- package/dist/views/ChatHistory/ChatHistoryPanel.js +3 -0
- package/dist/views/ChatHistory/ChatHistoryPanel.js.map +1 -1
- package/dist/views/ChatHistory/HistoryItem.d.ts +3 -0
- package/dist/views/ChatHistory/HistoryItem.d.ts.map +1 -1
- package/dist/views/ChatHistory/HistoryItem.js +3 -0
- package/dist/views/ChatHistory/HistoryItem.js.map +1 -1
- package/dist/views/ChatHistory/index.d.ts +10 -2
- package/dist/views/ChatHistory/index.d.ts.map +1 -1
- package/dist/views/ChatHistory/index.js +3 -0
- package/dist/views/ChatHistory/index.js.map +1 -1
- package/dist/views/ChatHistory/utils.d.ts +14 -0
- package/dist/views/ChatHistory/utils.d.ts.map +1 -1
- package/dist/views/ChatHistory/utils.js +14 -0
- package/dist/views/ChatHistory/utils.js.map +1 -1
- package/dist/views/ChatTabSelection.d.ts +3 -0
- package/dist/views/ChatTabSelection.d.ts.map +1 -1
- package/dist/views/ChatTabSelection.js +3 -0
- package/dist/views/ChatTabSelection.js.map +1 -1
- package/dist/views/Editor.d.ts +3 -0
- package/dist/views/Editor.d.ts.map +1 -1
- package/dist/views/Editor.js +4 -0
- package/dist/views/Editor.js.map +1 -1
- package/dist/views/Home.d.ts +8 -0
- package/dist/views/Home.d.ts.map +1 -1
- package/dist/views/Home.js +5 -0
- package/dist/views/Home.js.map +1 -1
- package/dist/views/KSDocument.d.ts +3 -0
- package/dist/views/KSDocument.d.ts.map +1 -1
- package/dist/views/KSDocument.js +3 -0
- package/dist/views/KSDocument.js.map +1 -1
- package/dist/views/KnowledgeSources.js +3 -0
- package/dist/views/KnowledgeSources.js.map +1 -1
- package/dist/views/MessageInput/ButtonGroup.d.ts +22 -0
- package/dist/views/MessageInput/ButtonGroup.d.ts.map +1 -1
- package/dist/views/MessageInput/ButtonGroup.js +4 -0
- package/dist/views/MessageInput/ButtonGroup.js.map +1 -1
- package/dist/views/MessageInput/InfoBar.d.ts +7 -0
- package/dist/views/MessageInput/InfoBar.d.ts.map +1 -1
- package/dist/views/MessageInput/InfoBar.js +7 -0
- package/dist/views/MessageInput/InfoBar.js.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.d.ts +7 -0
- package/dist/views/MessageInput/QuickCommandSelector.d.ts.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.js +4 -0
- package/dist/views/MessageInput/QuickCommandSelector.js.map +1 -1
- package/dist/views/MessageInput/index.d.ts +8 -0
- package/dist/views/MessageInput/index.d.ts.map +1 -1
- package/dist/views/MessageInput/index.js +5 -0
- package/dist/views/MessageInput/index.js.map +1 -1
- package/dist/views/MinimizedHeader.d.ts +4 -0
- package/dist/views/MinimizedHeader.d.ts.map +1 -1
- package/dist/views/MinimizedHeader.js +4 -0
- package/dist/views/MinimizedHeader.js.map +1 -1
- package/dist/views/Stacks.d.ts +3 -0
- package/dist/views/Stacks.d.ts.map +1 -1
- package/dist/views/Stacks.js +3 -0
- package/dist/views/Stacks.js.map +1 -1
- package/dist/views/Workspaces.d.ts +3 -0
- package/dist/views/Workspaces.d.ts.map +1 -1
- package/dist/views/Workspaces.js +3 -0
- package/dist/views/Workspaces.js.map +1 -1
- package/package.json +9 -6
- package/src/StackspotAIWidget.tsx +23 -2
- package/src/chat-interceptors/CustomInputs.ts +14 -1
- package/src/chat-interceptors/quick-command-questions.ts +12 -2
- package/src/chat-interceptors/quick-commands.ts +42 -3
- package/src/chat-interceptors/send-message.ts +18 -0
- package/src/components/Accordion.tsx +10 -0
- package/src/components/AdaptiveTextArea.tsx +12 -0
- package/src/components/AutoFocus.tsx +19 -5
- package/src/components/Fading.tsx +25 -5
- package/src/components/FadingOverflow.tsx +31 -3
- package/src/components/FallbackBoundary/index.tsx +6 -0
- package/src/components/HistoryList.tsx +15 -1
- package/src/components/IconInput.tsx +3 -0
- package/src/components/OverlayMenu.tsx +17 -1
- package/src/components/ProgressBar.tsx +23 -0
- package/src/components/QuickStartButton.tsx +3 -0
- package/src/components/RightPanelForm.tsx +3 -0
- package/src/components/RightPanelTabs.tsx +3 -0
- package/src/components/TabManager.tsx +8 -0
- package/src/components/Tooltip/Tooltip.tsx +23 -0
- package/src/components/Tooltip/TooltipAPI.ts +17 -0
- package/src/components/Tooltip/types.ts +13 -0
- package/src/components/form/DescribedCheckboxGroup.tsx +4 -0
- package/src/components/form/DescribedRadioGroup.tsx +4 -0
- package/src/components/form/types.ts +34 -0
- package/src/context/AIWidgetProvider.tsx +19 -0
- package/src/context/hooks.ts +56 -1
- package/src/features.ts +29 -0
- package/src/right-panel/DefaultPanel.tsx +12 -13
- package/src/right-panel/RightPanel.tsx +3 -0
- package/src/right-panel/RightPanelProvider.tsx +15 -0
- package/src/right-panel/hooks.tsx +6 -0
- package/src/state/ChatEntry.ts +60 -2
- package/src/state/ChatState.ts +74 -9
- package/src/state/ChatTabsController.ts +31 -0
- package/src/state/ObservableState.ts +14 -0
- package/src/state/WidgetState.ts +5 -0
- package/src/types.ts +10 -0
- package/src/utils/chat.ts +16 -1
- package/src/utils/date.ts +25 -1
- package/src/utils/download.ts +5 -0
- package/src/utils/knowledge-source.ts +16 -0
- package/src/utils/string.ts +5 -1
- package/src/views/Agents.tsx +3 -0
- package/src/views/Chat/AgentInfo.tsx +3 -0
- package/src/views/Chat/ChatMessage.tsx +21 -32
- package/src/views/Chat/ChatMessages.tsx +3 -0
- package/src/views/Chat/chat-scroll.ts +1 -1
- package/src/views/Chat/events.ts +69 -0
- package/src/views/Chat/index.tsx +6 -0
- package/src/views/ChatHistory/ChatHistoryPanel.tsx +3 -0
- package/src/views/ChatHistory/HistoryItem.tsx +3 -0
- package/src/views/ChatHistory/index.tsx +11 -1
- package/src/views/ChatHistory/utils.ts +14 -0
- package/src/views/ChatTabSelection.tsx +3 -0
- package/src/views/Editor.tsx +4 -0
- package/src/views/Home.tsx +8 -0
- package/src/views/KSDocument.tsx +3 -0
- package/src/views/KnowledgeSources.tsx +3 -0
- package/src/views/MessageInput/ButtonGroup.tsx +22 -0
- package/src/views/MessageInput/InfoBar.tsx +7 -0
- package/src/views/MessageInput/QuickCommandSelector.tsx +7 -0
- package/src/views/MessageInput/index.tsx +8 -0
- package/src/views/MinimizedHeader.tsx +4 -0
- package/src/views/Stacks.tsx +3 -0
- package/src/views/Workspaces.tsx +3 -0
|
@@ -8,14 +8,37 @@ import { DefaultTooltip } from './style'
|
|
|
8
8
|
import { TooltipPosition } from './types'
|
|
9
9
|
|
|
10
10
|
interface Props extends WithChildren, WithStyle {
|
|
11
|
+
/**
|
|
12
|
+
* The content of the tooltip. Can be either a string or a Rect Element.
|
|
13
|
+
*/
|
|
11
14
|
content: React.ReactNode,
|
|
15
|
+
/**
|
|
16
|
+
* Where to position the tooltip relative to the element that triggered it.
|
|
17
|
+
*/
|
|
12
18
|
position?: TooltipPosition,
|
|
19
|
+
/**
|
|
20
|
+
* A tooltip can be triggered either by hovering an element or by clicking it.
|
|
21
|
+
* @default 'hover'
|
|
22
|
+
*/
|
|
13
23
|
triggeredBy?: 'click' | 'hover',
|
|
24
|
+
/**
|
|
25
|
+
* If true, no style is applied to the tooltip, letting you customize it however you want to.
|
|
26
|
+
*/
|
|
14
27
|
custom?: boolean,
|
|
28
|
+
/**
|
|
29
|
+
* Function to run whenever the tooltip is shown.
|
|
30
|
+
*/
|
|
15
31
|
onShow?: () => void,
|
|
32
|
+
/**
|
|
33
|
+
* Function to run whenever the tooltip is hidden.
|
|
34
|
+
*/
|
|
16
35
|
onHide?: () => void,
|
|
17
36
|
}
|
|
18
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Shows a tooltip for its children. This tooltip element is always reused and placed at a root level in order to not be cut out by
|
|
40
|
+
* hidden overflows in the children and its ascendants.
|
|
41
|
+
*/
|
|
19
42
|
export const Tooltip = forwardRef<HTMLDivElement, Props>((
|
|
20
43
|
{ content, custom, position, triggeredBy = 'hover', onHide, onShow, children, className, style },
|
|
21
44
|
ref,
|
|
@@ -2,13 +2,24 @@ import { delay } from '@stack-spot/portal-components'
|
|
|
2
2
|
import { animationTimeMS } from './style'
|
|
3
3
|
import { ShowOptions } from './types'
|
|
4
4
|
|
|
5
|
+
// the maximum amount of pixels a tooltip can get close to the screen edges.
|
|
5
6
|
const MARGIN_TO_CORNERS_PX = 10
|
|
6
7
|
|
|
7
8
|
function isRelative(element: HTMLElement) {
|
|
8
9
|
return ['relative', 'absolute', 'fixed'].includes(element.computedStyleMap().get('position')?.toString() ?? '')
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Allows interaction with the tooltip element.
|
|
14
|
+
*
|
|
15
|
+
* This places the tooltip element at the correct place, shows it, hides it and manages its contents.
|
|
16
|
+
*
|
|
17
|
+
* This also takes into account the screen edges, making adjustments to the tooltip position if it would overflow the screen.
|
|
18
|
+
*/
|
|
11
19
|
export class TooltipAPI {
|
|
20
|
+
/**
|
|
21
|
+
* A reference to the tooltip element in the HTML tree.
|
|
22
|
+
*/
|
|
12
23
|
tooltipRef: React.RefObject<HTMLDivElement>
|
|
13
24
|
private setContent: React.Dispatch<React.SetStateAction<React.ReactNode>>
|
|
14
25
|
private hideTimeoutId: number | undefined
|
|
@@ -28,6 +39,9 @@ export class TooltipAPI {
|
|
|
28
39
|
}
|
|
29
40
|
}
|
|
30
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Shows the tooltip with `content`. Its position is based on `position` and the position of the element referred by `anchor`.
|
|
44
|
+
*/
|
|
31
45
|
async show({ content, anchor, position = 'bottom', hideOnClickOutside }: ShowOptions) {
|
|
32
46
|
window.clearTimeout(this.hideTimeoutId)
|
|
33
47
|
this.hideTimeoutId = undefined
|
|
@@ -75,6 +89,9 @@ export class TooltipAPI {
|
|
|
75
89
|
}
|
|
76
90
|
}
|
|
77
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Hides the tooltip. After the animation, the content is removed.
|
|
94
|
+
*/
|
|
78
95
|
hide(): void {
|
|
79
96
|
if (!this.tooltipRef.current) return
|
|
80
97
|
this.tooltipRef.current.classList.remove('visible')
|
|
@@ -8,8 +8,21 @@ export interface BoxPosition {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface ShowOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The content of the tooltip. Can be either a string or a React Element.
|
|
13
|
+
*/
|
|
11
14
|
content: React.ReactNode,
|
|
15
|
+
/**
|
|
16
|
+
* The anchor to the tooltip. This is part of what defines the position where the tooltip will appear.
|
|
17
|
+
*/
|
|
12
18
|
anchor: HTMLElement,
|
|
19
|
+
/**
|
|
20
|
+
* The position relative to the element referred by `anchor`.
|
|
21
|
+
* @default bottom
|
|
22
|
+
*/
|
|
13
23
|
position?: TooltipPosition,
|
|
24
|
+
/**
|
|
25
|
+
* Whether or not to hide the tooltip when a click is detected outside of it.
|
|
26
|
+
*/
|
|
14
27
|
hideOnClickOutside?: boolean,
|
|
15
28
|
}
|
|
@@ -5,6 +5,10 @@ import { Accordion } from '../Accordion'
|
|
|
5
5
|
import { RadioCheckBox } from './styled'
|
|
6
6
|
import { CheckProps } from './types'
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Renders a checkbox group where each option has a label and a description.
|
|
10
|
+
* The description in placed under the label and checkbox as an accordion.
|
|
11
|
+
*/
|
|
8
12
|
export function DescribedCheckboxGroup<T>(
|
|
9
13
|
{ keygen, onChange, options, renderDescription, renderLabel, optionClassName, optionStyle, value, className, style }: CheckProps<T>,
|
|
10
14
|
) {
|
|
@@ -5,6 +5,10 @@ import { Accordion } from '../Accordion'
|
|
|
5
5
|
import { RadioCheckBox } from './styled'
|
|
6
6
|
import { RadioProps } from './types'
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Renders a radio button group where each option has a label and a description.
|
|
10
|
+
* The description in placed under the label and radio button as an accordion.
|
|
11
|
+
*/
|
|
8
12
|
export function DescribedRadioGroup<T>(
|
|
9
13
|
{ keygen, onChange, options, renderDescription, renderLabel, optionClassName, optionStyle, value, className, style }: RadioProps<T>,
|
|
10
14
|
) {
|
|
@@ -1,21 +1,55 @@
|
|
|
1
1
|
import { WithStyle } from '@stack-spot/portal-theme'
|
|
2
2
|
|
|
3
3
|
interface RadioCheckProps<T> extends WithStyle {
|
|
4
|
+
/**
|
|
5
|
+
* The options available.
|
|
6
|
+
*/
|
|
4
7
|
options: T[],
|
|
8
|
+
/**
|
|
9
|
+
* A function that renders an option as a label. This can either return a string or a React Element.
|
|
10
|
+
*/
|
|
5
11
|
renderLabel: (option: T) => React.ReactNode,
|
|
12
|
+
/**
|
|
13
|
+
* A function that renders an option as a description. This can either return a string or a React Element.
|
|
14
|
+
*/
|
|
6
15
|
renderDescription: (option: T) => React.ReactNode,
|
|
16
|
+
/**
|
|
17
|
+
* A function that gives a custom className to the rendered option.
|
|
18
|
+
*/
|
|
7
19
|
optionClassName?: (option: T) => string | undefined,
|
|
20
|
+
/**
|
|
21
|
+
* A function that gives a custom style to the rendered option.
|
|
22
|
+
*/
|
|
8
23
|
optionStyle?: (option: T) => React.CSSProperties | undefined,
|
|
24
|
+
/**
|
|
25
|
+
* A function that generates a unique id for the option.
|
|
26
|
+
*/
|
|
9
27
|
keygen: (option: T) => React.Key,
|
|
10
28
|
|
|
11
29
|
}
|
|
12
30
|
|
|
13
31
|
export interface RadioProps<T> extends RadioCheckProps<T> {
|
|
32
|
+
/**
|
|
33
|
+
* The current value of the radio group. This is one of the options.
|
|
34
|
+
*
|
|
35
|
+
* Comparisons use the same-value-zero algorithm (`===`).
|
|
36
|
+
*/
|
|
14
37
|
value: T | undefined,
|
|
38
|
+
/**
|
|
39
|
+
* A function to call whenever the value changes.
|
|
40
|
+
*/
|
|
15
41
|
onChange: (option: T) => void,
|
|
16
42
|
}
|
|
17
43
|
|
|
18
44
|
export interface CheckProps<T> extends RadioCheckProps<T> {
|
|
45
|
+
/**
|
|
46
|
+
* The current value of the checkbox group. This is sub-array of the array of options.
|
|
47
|
+
*
|
|
48
|
+
* Comparisons use the same-value-zero algorithm (`===`).
|
|
49
|
+
*/
|
|
19
50
|
value: T[],
|
|
51
|
+
/**
|
|
52
|
+
* A function to call whenever the value changes.
|
|
53
|
+
*/
|
|
20
54
|
onChange: (option: T[]) => void,
|
|
21
55
|
}
|
|
@@ -3,4 +3,23 @@ import { WidgetState } from '../state/WidgetState'
|
|
|
3
3
|
|
|
4
4
|
export const AIWidgetContext = createContext<WidgetState | undefined>(undefined)
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Creates a new context for the AI Chat Widget.
|
|
8
|
+
*
|
|
9
|
+
* This is not required, but makes it much easier to control the chat and is the only way to have multiple instances of the chat model in
|
|
10
|
+
* the same application.
|
|
11
|
+
*
|
|
12
|
+
* To control the chat widget in any component descendant from the `AIWidgetProvider`, you can call the hook `useWidget()`.
|
|
13
|
+
*
|
|
14
|
+
* Example:
|
|
15
|
+
* ```
|
|
16
|
+
* const widget = useMemo(() => new WidgetState(), [])
|
|
17
|
+
*
|
|
18
|
+
* return (
|
|
19
|
+
* <AIWidgetProvider value={widget}>
|
|
20
|
+
* {children}
|
|
21
|
+
* </AIWidgetProvider>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
6
25
|
export const AIWidgetProvider = AIWidgetContext.Provider
|
package/src/context/hooks.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
1
|
import { useContext, useEffect, useState } from 'react'
|
|
3
2
|
import { ChatEntry } from '../state/ChatEntry'
|
|
4
3
|
import { ChatProperties, ChatState, MessageInterceptor } from '../state/ChatState'
|
|
@@ -9,6 +8,9 @@ import { AIWidgetContext } from './AIWidgetProvider'
|
|
|
9
8
|
|
|
10
9
|
let globalWidgetState: WidgetState | undefined
|
|
11
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Returns the closest instance of a WidgetState (React Context). If no context is available, uses a global instance of the chat widget.
|
|
13
|
+
*/
|
|
12
14
|
export function useWidget(): WidgetState {
|
|
13
15
|
const fromContext = useContext(AIWidgetContext)
|
|
14
16
|
if (fromContext) return fromContext
|
|
@@ -25,11 +27,19 @@ function useObservableState<T, K extends keyof T>(state: ObservableState<T>, key
|
|
|
25
27
|
return value
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Watches one of the widget states.
|
|
32
|
+
* @param key the key watch changes for.
|
|
33
|
+
* @returns the value of the state referred by the key.
|
|
34
|
+
*/
|
|
28
35
|
export function useWidgetState<K extends keyof WidgetProperties>(key: K): WidgetProperties[K] {
|
|
29
36
|
const widget = useWidget()
|
|
30
37
|
return useObservableState(widget, key)
|
|
31
38
|
}
|
|
32
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Watches the tabs of a ChatState. The value is updated whenever a tab is added, removed or selected.
|
|
42
|
+
*/
|
|
33
43
|
export function useChatTabs(): { chats: ChatState[], active: string } {
|
|
34
44
|
const widget = useWidget()
|
|
35
45
|
const [tabs, setTabs] = useState<{ chats: ChatState[], active: string }>({
|
|
@@ -40,6 +50,13 @@ export function useChatTabs(): { chats: ChatState[], active: string } {
|
|
|
40
50
|
return tabs
|
|
41
51
|
}
|
|
42
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Gets a chat according to its identifier (conversation id).
|
|
55
|
+
*
|
|
56
|
+
* An error is thrown if the id doesn't correspond to any chat currently opened.
|
|
57
|
+
*
|
|
58
|
+
* @returns the chat state.
|
|
59
|
+
*/
|
|
43
60
|
export function useChat(chatId: string): ChatState {
|
|
44
61
|
const widget = useWidget()
|
|
45
62
|
const chat = widget.chatTabs.get(chatId)
|
|
@@ -47,21 +64,44 @@ export function useChat(chatId: string): ChatState {
|
|
|
47
64
|
return chat
|
|
48
65
|
}
|
|
49
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Watches the current chat (selected in the chat tabs.)
|
|
69
|
+
*
|
|
70
|
+
* The value changes whenever a new chat is selected.
|
|
71
|
+
*
|
|
72
|
+
* @returns the currently active chat.
|
|
73
|
+
*/
|
|
50
74
|
export function useCurrentChat(): ChatState {
|
|
51
75
|
const { active } = useChatTabs()
|
|
52
76
|
return useChat(active)
|
|
53
77
|
}
|
|
54
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Watches one of the chat states.
|
|
81
|
+
* @param chatId the id of chat to watch.
|
|
82
|
+
* @param key the key of the state to watch.
|
|
83
|
+
* @returns the value of the state referred by the key.
|
|
84
|
+
*/
|
|
55
85
|
export function useChatState<K extends keyof ChatProperties>(chatId: string, key: K): ChatProperties[K] {
|
|
56
86
|
const chat = useChat(chatId)
|
|
57
87
|
return useObservableState(chat, key)
|
|
58
88
|
}
|
|
59
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Watches one of the current chat states. This is the same as calling `useChatState` with the id of the current chat.
|
|
92
|
+
* @param key the key of the state to watch.
|
|
93
|
+
* @returns the value of the state referred by the key.
|
|
94
|
+
*/
|
|
60
95
|
export function useCurrentChatState<K extends keyof ChatProperties>(key: K): ChatProperties[K] {
|
|
61
96
|
const chat = useCurrentChat()
|
|
62
97
|
return useObservableState(chat, key)
|
|
63
98
|
}
|
|
64
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Watches a chat state for changes in the list of messages (chat entries).
|
|
102
|
+
* @param chatId the id of the chat to watch.
|
|
103
|
+
* @returns the list of messages in the chat.
|
|
104
|
+
*/
|
|
65
105
|
export function useChatMessages(chatId: string): ChatEntry[] {
|
|
66
106
|
const chat = useChat(chatId)
|
|
67
107
|
const [entries, setEntries] = useState(chat.getMessages())
|
|
@@ -72,17 +112,32 @@ export function useChatMessages(chatId: string): ChatEntry[] {
|
|
|
72
112
|
return entries
|
|
73
113
|
}
|
|
74
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Watches the chat state currently active for changes in the list of messages (chat entries). This is the same as calling `useChatMessages`
|
|
117
|
+
* with the id of the current chat.
|
|
118
|
+
* @returns the list of messages in the chat.
|
|
119
|
+
*/
|
|
75
120
|
export function useCurrentChatMessages(): ChatEntry[] {
|
|
76
121
|
const { active } = useChatTabs()
|
|
77
122
|
return useChatMessages(active)
|
|
78
123
|
}
|
|
79
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Watches a chat message (chat entry) for changes in its composition. This allows messages to be streamed: each part of the stream will
|
|
127
|
+
* change the current value of the entry.
|
|
128
|
+
* @param entry the message to watch.
|
|
129
|
+
* @returns the current value of the message.
|
|
130
|
+
*/
|
|
80
131
|
export function useChatEntry(entry: ChatEntry) {
|
|
81
132
|
const [content, setContent] = useState(entry.getValue())
|
|
82
133
|
useEffect(() => entry.onChange(setContent), [])
|
|
83
134
|
return content
|
|
84
135
|
}
|
|
85
136
|
|
|
137
|
+
/**
|
|
138
|
+
* This will create a new chat if none exists.
|
|
139
|
+
* @param interceptors the interceptors to add to the new chat.
|
|
140
|
+
*/
|
|
86
141
|
export function useFirstChat(interceptors: MessageInterceptor[]) {
|
|
87
142
|
const widget = useWidget()
|
|
88
143
|
const tabs = widget.chatTabs
|
package/src/features.ts
CHANGED
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
export interface MessageInputFeatures {
|
|
2
|
+
/**
|
|
3
|
+
* Enables stack selection.
|
|
4
|
+
* @default true
|
|
5
|
+
*/
|
|
2
6
|
stack?: boolean,
|
|
7
|
+
/**
|
|
8
|
+
* Enables workspace selection.
|
|
9
|
+
* @default true
|
|
10
|
+
*/
|
|
3
11
|
workspace?: boolean,
|
|
12
|
+
/**
|
|
13
|
+
* Enables knowledge source selection.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
4
16
|
knowledgeSource?: boolean,
|
|
17
|
+
/**
|
|
18
|
+
* Enables agent selection.
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
5
21
|
agent?: boolean,
|
|
22
|
+
/**
|
|
23
|
+
* Enables quick commands.
|
|
24
|
+
* @default true
|
|
25
|
+
*/
|
|
6
26
|
quickCommands?: boolean,
|
|
27
|
+
/**
|
|
28
|
+
* Enables the editor.
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
7
31
|
editor?: boolean,
|
|
8
32
|
}
|
|
9
33
|
|
|
10
34
|
export interface AIWidgetFeatures extends MessageInputFeatures {
|
|
35
|
+
/**
|
|
36
|
+
* Enables the chat history.
|
|
37
|
+
* @default true
|
|
38
|
+
*/
|
|
11
39
|
chatHistory?: boolean,
|
|
12
40
|
}
|
|
13
41
|
|
|
@@ -18,4 +46,5 @@ export const defaultFeatures: AIWidgetFeatures = {
|
|
|
18
46
|
agent: true,
|
|
19
47
|
chatHistory: true,
|
|
20
48
|
editor: true,
|
|
49
|
+
quickCommands: true,
|
|
21
50
|
}
|
|
@@ -3,9 +3,7 @@ import { Times } from '@citric/icons'
|
|
|
3
3
|
import { IconButton } from '@citric/ui'
|
|
4
4
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
5
5
|
import { styled } from 'styled-components'
|
|
6
|
-
import { AutoFocus } from '../components/AutoFocus'
|
|
7
6
|
import { WithChildren } from '../types'
|
|
8
|
-
import { panelAnimationTime } from './constants'
|
|
9
7
|
|
|
10
8
|
interface Props extends WithChildren {
|
|
11
9
|
title: React.ReactNode,
|
|
@@ -42,22 +40,23 @@ const PanelBox = styled.div`
|
|
|
42
40
|
}
|
|
43
41
|
`
|
|
44
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Default layout for a right panel.
|
|
45
|
+
*/
|
|
45
46
|
export const DefaultPanel = ({ description, onClose, title, children }: Props) => {
|
|
46
47
|
const t = useTranslate(dictionary)
|
|
47
48
|
|
|
48
49
|
return (
|
|
49
50
|
<PanelBox>
|
|
50
|
-
<
|
|
51
|
-
<
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
</header>
|
|
60
|
-
</AutoFocus>
|
|
51
|
+
<header>
|
|
52
|
+
<div className="title">
|
|
53
|
+
{typeof title === 'string' ? <Text appearance="h5">{title}</Text> : title}
|
|
54
|
+
{typeof description === 'string' ? <Text colorScheme="light.700">{description}</Text> : description}
|
|
55
|
+
</div>
|
|
56
|
+
<IconButton title={t.close} aria-label={t.close} onClick={onClose}>
|
|
57
|
+
<Times />
|
|
58
|
+
</IconButton>
|
|
59
|
+
</header>
|
|
61
60
|
<article>{children}</article>
|
|
62
61
|
</PanelBox>
|
|
63
62
|
)
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import { createContext, useMemo, useRef, useState } from 'react'
|
|
2
2
|
|
|
3
3
|
interface ContextValue {
|
|
4
|
+
/**
|
|
5
|
+
* The current content of the right panel.
|
|
6
|
+
*/
|
|
4
7
|
content?: React.ReactNode,
|
|
8
|
+
/**
|
|
9
|
+
* Sets the current content of the right panel.
|
|
10
|
+
*/
|
|
5
11
|
setContent?: (content: React.ReactNode) => void,
|
|
12
|
+
/**
|
|
13
|
+
* A reference to the right panel HTML Element.
|
|
14
|
+
*/
|
|
6
15
|
panel?: React.RefObject<HTMLDivElement>,
|
|
16
|
+
/**
|
|
17
|
+
* A reference to the chat window at the left of the right panel.
|
|
18
|
+
*/
|
|
7
19
|
chatWindow?: React.RefObject<HTMLDivElement>,
|
|
20
|
+
/**
|
|
21
|
+
* A function to run when the right panel is closed for the next time.
|
|
22
|
+
*/
|
|
8
23
|
onCloseNext: React.MutableRefObject<(() => void) | undefined>,
|
|
9
24
|
}
|
|
10
25
|
|
|
@@ -9,11 +9,17 @@ interface RightPanelOptions {
|
|
|
9
9
|
onClose?: () => void,
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* @returns teh current content of the right panel
|
|
14
|
+
*/
|
|
12
15
|
export function useRightPanelContent() {
|
|
13
16
|
const { content } = useContext(RightPanelContext)
|
|
14
17
|
return content
|
|
15
18
|
}
|
|
16
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Opens, closes or checks the visibility of the right panel.
|
|
22
|
+
*/
|
|
17
23
|
export function useRightPanel() {
|
|
18
24
|
const ctx = useContext(RightPanelContext)
|
|
19
25
|
const { panel, chatWindow, setContent } = ctx
|
package/src/state/ChatEntry.ts
CHANGED
|
@@ -3,10 +3,16 @@ import { pull } from 'lodash'
|
|
|
3
3
|
import { LabeledWithImage } from './types'
|
|
4
4
|
|
|
5
5
|
export interface SerializableAction {
|
|
6
|
+
/**
|
|
7
|
+
* The text for the button or anchor.
|
|
8
|
+
*/
|
|
6
9
|
title: string,
|
|
10
|
+
/**
|
|
11
|
+
* Links open new tabs with urls, while commands send text commands in the chat as if they were written by the user.
|
|
12
|
+
*/
|
|
7
13
|
type: 'link' | 'command',
|
|
8
14
|
/**
|
|
9
|
-
* The URL if the action is a link
|
|
15
|
+
* The URL if the action is a link. The content of the user message otherwise.
|
|
10
16
|
*/
|
|
11
17
|
exec: string,
|
|
12
18
|
}
|
|
@@ -26,23 +32,61 @@ export interface KnowledgeSource {
|
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
export interface TextChatEntry {
|
|
35
|
+
/**
|
|
36
|
+
* "text" for simple unformatted paragraphs. "md" for markdown.
|
|
37
|
+
*/
|
|
29
38
|
type: 'text' | 'md',
|
|
39
|
+
/**
|
|
40
|
+
* If the message was typed by the AI agent (bot), the user or the system (not currently in use).
|
|
41
|
+
*/
|
|
30
42
|
agentType: 'bot' | 'user' | 'system',
|
|
43
|
+
/**
|
|
44
|
+
* A set of buttons to go after the message.
|
|
45
|
+
*/
|
|
31
46
|
actions?: ChatAction[],
|
|
47
|
+
/**
|
|
48
|
+
* The content of the message.
|
|
49
|
+
*/
|
|
32
50
|
content: string,
|
|
51
|
+
/**
|
|
52
|
+
* The knowledge sources used to create the message.
|
|
53
|
+
*/
|
|
33
54
|
knowledgeSources?: KnowledgeSource[],
|
|
55
|
+
/**
|
|
56
|
+
* The date and time of the message. ISO string.
|
|
57
|
+
*/
|
|
34
58
|
updated?: string,
|
|
59
|
+
/**
|
|
60
|
+
* The agent who wrote the message. Undefined for the default agent or if the agentType is "user".
|
|
61
|
+
*/
|
|
35
62
|
agent?: LabeledWithImage,
|
|
63
|
+
/**
|
|
64
|
+
* The unique identifier of the message.
|
|
65
|
+
*/
|
|
36
66
|
messageId?: string,
|
|
67
|
+
/**
|
|
68
|
+
* If this is set, only an error message is rendered.
|
|
69
|
+
*/
|
|
37
70
|
error?: string,
|
|
71
|
+
/**
|
|
72
|
+
* A series of badges to display before the content.
|
|
73
|
+
*/
|
|
38
74
|
badges?: { color?: ColorPaletteName, label: string }[],
|
|
75
|
+
/**
|
|
76
|
+
* Whether or not to show this chat entry as a card.
|
|
77
|
+
*/
|
|
39
78
|
card?: boolean,
|
|
40
79
|
}
|
|
41
80
|
|
|
42
81
|
type ChatEntryListener = (value: TextChatEntry) => void
|
|
43
82
|
|
|
83
|
+
// this id is unique for each message and used for rendering. The `messageId`, which comes from the backend, is not always available and,
|
|
84
|
+
// therefore, can't be used for this purpose.
|
|
44
85
|
let nextId = 0
|
|
45
86
|
|
|
87
|
+
/**
|
|
88
|
+
* A message (entry) in the chat.
|
|
89
|
+
*/
|
|
46
90
|
export class ChatEntry {
|
|
47
91
|
readonly id: number
|
|
48
92
|
private value: TextChatEntry
|
|
@@ -50,13 +94,18 @@ export class ChatEntry {
|
|
|
50
94
|
|
|
51
95
|
/**
|
|
52
96
|
* @param value the value of the entry.
|
|
53
|
-
* @param isStreamed whether or not this entry is streamed. Defaults to false.
|
|
54
97
|
*/
|
|
55
98
|
constructor(value: TextChatEntry) {
|
|
56
99
|
this.id = nextId++
|
|
57
100
|
this.value = value
|
|
58
101
|
}
|
|
59
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Utility function to create a user entry.
|
|
105
|
+
* @param content the message's content.
|
|
106
|
+
* @param isMd whether or not this should be rendered as markdown.
|
|
107
|
+
* @returns a new ChatEntry.
|
|
108
|
+
*/
|
|
60
109
|
static createUserEntry(content: string, isMd = false) {
|
|
61
110
|
return new ChatEntry({
|
|
62
111
|
agentType: 'user',
|
|
@@ -66,6 +115,10 @@ export class ChatEntry {
|
|
|
66
115
|
})
|
|
67
116
|
}
|
|
68
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Utility function to create a streamed entry from the AI agent.
|
|
120
|
+
* @returns a new ChatEntry.
|
|
121
|
+
*/
|
|
69
122
|
static createStreamedBotEntry() {
|
|
70
123
|
return new ChatEntry({ agentType: 'bot', type: 'md', content: '' })
|
|
71
124
|
}
|
|
@@ -79,6 +132,11 @@ export class ChatEntry {
|
|
|
79
132
|
return this.value
|
|
80
133
|
}
|
|
81
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Watches the value of this ChatEntry.
|
|
137
|
+
* @param listener a function to call whenever the value changes.
|
|
138
|
+
* @returns a function that removes the listener.
|
|
139
|
+
*/
|
|
82
140
|
onChange(listener: ChatEntryListener) {
|
|
83
141
|
this.listeners.push(listener)
|
|
84
142
|
return () => {
|