@stack-spot/ai-chat-widget 1.0.0 → 1.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/CHANGELOG.md +9 -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 +14 -0
- 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 +6 -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 +14 -0
- 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
|
@@ -26,23 +26,44 @@ import { Stacks } from './views/Stacks'
|
|
|
26
26
|
import { Workspaces } from './views/Workspaces'
|
|
27
27
|
|
|
28
28
|
export interface AIWidgetProps {
|
|
29
|
+
/**
|
|
30
|
+
* The features to enable or disable.
|
|
31
|
+
*/
|
|
29
32
|
features?: AIWidgetFeatures,
|
|
33
|
+
/**
|
|
34
|
+
* The name of the user currently logged in.
|
|
35
|
+
*/
|
|
30
36
|
username: string,
|
|
37
|
+
/**
|
|
38
|
+
* Chat interceptors allows you to intercept chat messages, interpret them, modify them and even change the chat flow. See
|
|
39
|
+
* {@link ChatState} for more details.
|
|
40
|
+
*/
|
|
31
41
|
interceptors?: MessageInterceptor[],
|
|
42
|
+
/**
|
|
43
|
+
* A custom view to show when the chat has no messages to display.
|
|
44
|
+
*/
|
|
32
45
|
children?: React.ReactNode,
|
|
46
|
+
/**
|
|
47
|
+
* If the chat can be minimized, this set of functions tells what to do when minimization related buttons are clicked.
|
|
48
|
+
*/
|
|
33
49
|
minimizedActions?: MinimizedActions,
|
|
34
50
|
}
|
|
35
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Renders a Chat Widget according to the closest model found in the React tree (AIWidgetProvider). If no model is found, a global version
|
|
54
|
+
* of the Chat Widget will be instantiated and used.
|
|
55
|
+
*/
|
|
36
56
|
export const StackspotAIWidget = (
|
|
37
57
|
{ username, features = defaultFeatures, interceptors: userInterceptors = [], minimizedActions = {}, children }: AIWidgetProps,
|
|
38
58
|
) => {
|
|
39
59
|
const widget = useWidget()
|
|
40
60
|
const interceptors: MessageInterceptor[] = useMemo(
|
|
41
|
-
() => [
|
|
61
|
+
() => features.quickCommands ? [
|
|
42
62
|
...userInterceptors,
|
|
43
63
|
quickCommandQuestionsInterceptor,
|
|
44
64
|
createQuickCommandInterceptor(widget, () => loader.__getMonacoInstance()?.editor),
|
|
45
|
-
sendMessageInterceptor
|
|
65
|
+
sendMessageInterceptor,
|
|
66
|
+
] : [...userInterceptors, sendMessageInterceptor],
|
|
46
67
|
[],
|
|
47
68
|
)
|
|
48
69
|
useFirstChat(interceptors)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CustomInputResponse } from '@stack-spot/portal-network/api/ai'
|
|
2
2
|
import { Dictionary, translate } from '@stack-spot/portal-translate'
|
|
3
3
|
import { ChatEntry } from '../state/ChatEntry'
|
|
4
|
+
import { ChatState } from '../state/ChatState'
|
|
4
5
|
import { LabeledWithImage } from '../state/types'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
const CUSTOM_INPUTS_KEY = 'customInputs'
|
|
7
8
|
|
|
8
9
|
export class CustomInputs {
|
|
9
10
|
private value: Record<string, string> = {}
|
|
@@ -21,6 +22,18 @@ export class CustomInputs {
|
|
|
21
22
|
})
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
static getCustomInputsFromChat(chat: ChatState): CustomInputs | undefined {
|
|
26
|
+
return chat.interceptorMemory.get(CUSTOM_INPUTS_KEY)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static setCustomInputsForChat(inputs: CustomInputs, chat: ChatState): void {
|
|
30
|
+
chat.interceptorMemory.set(CUSTOM_INPUTS_KEY, inputs)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static deleteCustomInputsFromChat(chat: ChatState): void {
|
|
34
|
+
chat.interceptorMemory.delete(CUSTOM_INPUTS_KEY)
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
ask(): ChatEntry {
|
|
25
38
|
if (this.index >= this.inputs.length) throw new Error('No more questions to ask.')
|
|
26
39
|
const t = translate(dictionary)
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { ChatEntry } from '../state/ChatEntry'
|
|
2
2
|
import { ChatState } from '../state/ChatState'
|
|
3
|
-
import {
|
|
3
|
+
import { CustomInputs } from './CustomInputs'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* This chat interceptor is responsible for interrupting the normal flow of the chat and asking questions about the variables (custom
|
|
7
|
+
* inputs) needed to run the quick command previously typed.
|
|
8
|
+
*
|
|
9
|
+
* The first question is actually asked by the `quickCommandInterceptor`, this registers all answers and asks the next questions (if any).
|
|
10
|
+
*
|
|
11
|
+
* @param entry the chat entry.
|
|
12
|
+
* @param chat the chat state.
|
|
13
|
+
* @returns false if, and only if, this entry is an answer to a quick command question (custom input). Undefined otherwise.
|
|
14
|
+
*/
|
|
5
15
|
export function quickCommandQuestionsInterceptor(entry: ChatEntry, chat: ChatState) {
|
|
6
16
|
const { agentType, content } = entry.getValue()
|
|
7
17
|
if (agentType !== 'user') return
|
|
8
|
-
const customInputs =
|
|
18
|
+
const customInputs = CustomInputs.getCustomInputsFromChat(chat)
|
|
9
19
|
if (!customInputs) return
|
|
10
20
|
if (content === '/skip') customInputs.skip()
|
|
11
21
|
else customInputs.answer(content)
|
|
@@ -11,7 +11,7 @@ import { LabeledWithImage } from '../state/types'
|
|
|
11
11
|
import { WidgetState } from '../state/WidgetState'
|
|
12
12
|
import { buildConversationContext } from '../utils/chat'
|
|
13
13
|
import { getSizeOfString } from '../utils/string'
|
|
14
|
-
import {
|
|
14
|
+
import { CustomInputs } from './CustomInputs'
|
|
15
15
|
|
|
16
16
|
type SlugExecution = Record<string, string | QuickCommandFetchResponseResult | QuickCommandPromptResponse2>
|
|
17
17
|
|
|
@@ -25,16 +25,35 @@ interface QCContext {
|
|
|
25
25
|
signal: AbortSignal,
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* While the quick command is running, if it takes more than `progressMessageDelayMS` a progress message is shown.
|
|
30
|
+
* This progress message is shown immediately if one of the steps is of type "LLM".
|
|
31
|
+
*/
|
|
28
32
|
const progressMessageDelayMS = 1000
|
|
29
33
|
|
|
34
|
+
/**
|
|
35
|
+
* This creates a chat interceptor for interpreting and running quick commands. We need a function to create the interceptor because, for
|
|
36
|
+
* quick commands, we need access to the full widget state and the editor, which are not provided to a chat interceptor.
|
|
37
|
+
*
|
|
38
|
+
* The quick command interceptor intercepts all user messages (trimmed) that matches the quick command regex. It fetches the quick command
|
|
39
|
+
* from the backend, runs all of its steps and outputs the final response (in the chat or in the editor).
|
|
40
|
+
*
|
|
41
|
+
* @param widget the full widget state.
|
|
42
|
+
* @param getEditor a function that returns the editor instance (monaco).
|
|
43
|
+
* @returns the quick commands chat interceptor.
|
|
44
|
+
*/
|
|
30
45
|
export function createQuickCommandInterceptor(widget: WidgetState, getEditor: () => typeof editor | undefined) {
|
|
46
|
+
/**
|
|
47
|
+
* This creates a CustomInputs instance in the current chat, which activates the `quickCommandQuestionsInterceptor`. In summary, this asks
|
|
48
|
+
* the first question, wait for all answers to be given and fills the result map in the context passed as parameter.
|
|
49
|
+
*/
|
|
31
50
|
async function computeCustomInputs(ctx: QCContext) {
|
|
32
51
|
const { chat, qc: { custom_inputs: inputs, name, slug } } = ctx
|
|
33
52
|
if (!inputs?.length) return
|
|
34
53
|
chat.set('isLoading', false)
|
|
35
54
|
const t = translate(dictionary)
|
|
36
55
|
const customInputs = new CustomInputs(inputs, chat.get('agent'))
|
|
37
|
-
|
|
56
|
+
CustomInputs.setCustomInputsForChat(customInputs, chat)
|
|
38
57
|
chat.pushMessage(new ChatEntry({
|
|
39
58
|
agentType: 'bot',
|
|
40
59
|
type: 'text',
|
|
@@ -43,10 +62,13 @@ export function createQuickCommandInterceptor(widget: WidgetState, getEditor: ()
|
|
|
43
62
|
chat.pushMessage(customInputs.ask())
|
|
44
63
|
const inputsValues = await customInputs.getValue()
|
|
45
64
|
chat.set('isLoading', true)
|
|
46
|
-
|
|
65
|
+
CustomInputs.deleteCustomInputsFromChat(chat)
|
|
47
66
|
ctx.resultMap = { ...ctx.resultMap, ...inputsValues }
|
|
48
67
|
}
|
|
49
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Runs a fetch step of a quick command and puts the result in the `resultMap` of the context passed as parameter.
|
|
71
|
+
*/
|
|
50
72
|
async function runFetchStep(ctx: QCContext, stepIndex: number) {
|
|
51
73
|
const { qc: { slug, steps }, code, context, resultMap, executionId, signal } = ctx
|
|
52
74
|
const step = steps![stepIndex]
|
|
@@ -65,6 +87,9 @@ export function createQuickCommandInterceptor(widget: WidgetState, getEditor: ()
|
|
|
65
87
|
}
|
|
66
88
|
}
|
|
67
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Runs an LLM step of a quick command and puts the result in the `resultMap` of the context passed as parameter.
|
|
92
|
+
*/
|
|
68
93
|
async function runLLMStep(
|
|
69
94
|
{ qc: { slug, steps }, code, context, executionId, resultMap, signal }: QCContext,
|
|
70
95
|
stepIndex: number,
|
|
@@ -146,6 +171,7 @@ export function createQuickCommandInterceptor(widget: WidgetState, getEditor: ()
|
|
|
146
171
|
widget.chatTabs.select(ctx.chat.id)
|
|
147
172
|
ctx.context.conversation_id = ctx.chat.id
|
|
148
173
|
} else {
|
|
174
|
+
// if we're running a command in teh editor, we don't need to open a new tab, we just need to run it in a new conversation context.
|
|
149
175
|
ctx.context.conversation_id = ulid()
|
|
150
176
|
}
|
|
151
177
|
}
|
|
@@ -170,6 +196,9 @@ export function createQuickCommandInterceptor(widget: WidgetState, getEditor: ()
|
|
|
170
196
|
return formatResult(ctx)
|
|
171
197
|
}
|
|
172
198
|
|
|
199
|
+
/**
|
|
200
|
+
* This registers a quick command event in the backend (analytics).
|
|
201
|
+
*/
|
|
173
202
|
async function registerAnalyticsEvent({ qc, executionId, code = '', context }: QCContext, status: string, start: number) {
|
|
174
203
|
const now = new Date().getTime()
|
|
175
204
|
try {
|
|
@@ -197,6 +226,9 @@ export function createQuickCommandInterceptor(widget: WidgetState, getEditor: ()
|
|
|
197
226
|
}
|
|
198
227
|
}
|
|
199
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Writes the result in the chat or in the editor.
|
|
231
|
+
*/
|
|
200
232
|
function outputResult({ qc, chat, code }: QCContext, result: string) {
|
|
201
233
|
if (qc.return_type === 'CHAT') {
|
|
202
234
|
chat.pushMessage(new ChatEntry({
|
|
@@ -216,6 +248,13 @@ export function createQuickCommandInterceptor(widget: WidgetState, getEditor: ()
|
|
|
216
248
|
}
|
|
217
249
|
}
|
|
218
250
|
|
|
251
|
+
/**
|
|
252
|
+
* The chat interceptor itself.
|
|
253
|
+
* @param entry the chat entry.
|
|
254
|
+
* @param chat the chat state.
|
|
255
|
+
* @param signal a signal that can be canceled by the user.
|
|
256
|
+
* @returns false if, and only if, this entry (trimmed) matches the quick command regex. Undefined otherwise.
|
|
257
|
+
*/
|
|
219
258
|
async function quickCommandInterceptor(entry: ChatEntry, chat: ChatState, signal: AbortSignal) {
|
|
220
259
|
const { agentType, content } = entry.getValue()
|
|
221
260
|
if (agentType !== 'user' || !quickCommandRegex.test(content.trim())) return
|
|
@@ -6,6 +6,14 @@ import { LabeledWithImage } from '../state/types'
|
|
|
6
6
|
import { buildConversationContext } from '../utils/chat'
|
|
7
7
|
import { genericSourcesToKnowledgeSources } from '../utils/knowledge-source'
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Transforms a chat response from the backend into a chat entry that can be added to the chat.
|
|
11
|
+
* @param response the original response.
|
|
12
|
+
* @param knowledgeSources the knowledge sources already in format used by the chat.
|
|
13
|
+
* @param agent the current chat agent.
|
|
14
|
+
* @param includeDate whether or not to include the date in the chat entry.
|
|
15
|
+
* @returns the TextChatEntry to build a ChatEntry.
|
|
16
|
+
*/
|
|
9
17
|
function createEntryValueFromChatResponse(
|
|
10
18
|
response: Partial<ChatResponse3>,
|
|
11
19
|
knowledgeSources: KnowledgeSource[] | undefined,
|
|
@@ -23,6 +31,16 @@ function createEntryValueFromChatResponse(
|
|
|
23
31
|
}
|
|
24
32
|
}
|
|
25
33
|
|
|
34
|
+
/**
|
|
35
|
+
* The chat interceptor that sends the message to the AI agent, interprets the response and adds it to the chat.
|
|
36
|
+
*
|
|
37
|
+
* The message added to the chat is streamed, i.e. it changes over time, until it's completed.
|
|
38
|
+
*
|
|
39
|
+
* @param entry the chat entry.
|
|
40
|
+
* @param chat the chat state.
|
|
41
|
+
* @param signal a signal that can be canceled by the user.
|
|
42
|
+
* @returns undefined
|
|
43
|
+
*/
|
|
26
44
|
export async function sendMessageInterceptor(entry: ChatEntry, chat: ChatState, signal: AbortSignal) {
|
|
27
45
|
const { agentType, content } = entry.getValue()
|
|
28
46
|
if (agentType !== 'user') return
|
|
@@ -9,7 +9,14 @@ import { styled } from 'styled-components'
|
|
|
9
9
|
import { WithChildren } from '../types'
|
|
10
10
|
|
|
11
11
|
interface Props extends WithStyle, Required<WithChildren> {
|
|
12
|
+
/**
|
|
13
|
+
* The header of the accordion (always rendered). The body (hidden part) must be passed as the children.
|
|
14
|
+
*/
|
|
12
15
|
header: React.ReactNode,
|
|
16
|
+
/**
|
|
17
|
+
* Whether or not to start expanded.
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
13
20
|
startExpanded?: boolean,
|
|
14
21
|
}
|
|
15
22
|
|
|
@@ -48,6 +55,9 @@ const StyledAccordion = styled.div`
|
|
|
48
55
|
}
|
|
49
56
|
`
|
|
50
57
|
|
|
58
|
+
/**
|
|
59
|
+
* A component that can have it's content shown or hidden (animated).
|
|
60
|
+
*/
|
|
51
61
|
export const Accordion = ({ children, header, className, startExpanded, style }: Props) => {
|
|
52
62
|
const [expanded, setExpanded] = useState(startExpanded)
|
|
53
63
|
return (
|
|
@@ -4,11 +4,23 @@ import { forwardRef, useEffect, useRef } from 'react'
|
|
|
4
4
|
import { PropsOf } from '../types'
|
|
5
5
|
|
|
6
6
|
interface Props extends PropsOf<typeof Textarea> {
|
|
7
|
+
/**
|
|
8
|
+
* A function to run whenever the height of the text area increases.
|
|
9
|
+
*/
|
|
7
10
|
onIncreaseSize?: () => void,
|
|
11
|
+
/**
|
|
12
|
+
* A function to run whenever the text area value becomes empty.
|
|
13
|
+
*/
|
|
8
14
|
onResetSize?: () => void,
|
|
15
|
+
/**
|
|
16
|
+
* The maximum height this textarea can get to.
|
|
17
|
+
*/
|
|
9
18
|
maxHeight?: number,
|
|
10
19
|
}
|
|
11
20
|
|
|
21
|
+
/**
|
|
22
|
+
* The adaptive textarea grows in height whenever needed until the maximum height is reached.
|
|
23
|
+
*/
|
|
12
24
|
export const AdaptiveTextArea = forwardRef<HTMLTextAreaElement, Props>((
|
|
13
25
|
{ value, onIncreaseSize, onResetSize, maxHeight, style, ...props },
|
|
14
26
|
externalRef,
|
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
/* eslint-disable react/display-name */
|
|
2
|
+
import { focusFirstChild, TagPriorityElement } from '@stack-spot/portal-components'
|
|
2
3
|
import { forwardRef, RefObject, useEffect, useRef } from 'react'
|
|
3
4
|
|
|
4
5
|
interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/**
|
|
7
|
+
* A delay in ms to focus the first focusable element.
|
|
8
|
+
*/
|
|
5
9
|
delay?: number,
|
|
10
|
+
/**
|
|
11
|
+
* Instead of focusing the first element overall, focus the first according to this list of priorities.
|
|
12
|
+
*
|
|
13
|
+
* 'other' means elements that are normally not focusable, but have positive tabIndex values.
|
|
14
|
+
*/
|
|
15
|
+
priority?: TagPriorityElement[],
|
|
16
|
+
/**
|
|
17
|
+
* Ignores any element that matches this query selector.
|
|
18
|
+
*/
|
|
19
|
+
ignore?: string,
|
|
6
20
|
}
|
|
7
21
|
|
|
8
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Focus the first focusable child as soon as the component mounts.
|
|
24
|
+
*/
|
|
25
|
+
export const AutoFocus = forwardRef<HTMLDivElement, Props>(({ children, delay = 0, priority, ignore, ...props }, externalRef) => {
|
|
9
26
|
const localRef = useRef<HTMLDivElement>(null)
|
|
10
27
|
const ref = externalRef as RefObject<HTMLDivElement> ?? localRef
|
|
11
28
|
|
|
12
29
|
useEffect(() => {
|
|
13
|
-
setTimeout(() => {
|
|
14
|
-
// fixme: we should actually call `focusFirstChild` from the component lib, but, it's bugged
|
|
15
|
-
(ref.current?.querySelector('a, button, input, select, textarea') as HTMLElement)?.focus()
|
|
16
|
-
}, delay)
|
|
30
|
+
setTimeout(() => focusFirstChild(ref.current, { priority, ignore }), delay)
|
|
17
31
|
}, [])
|
|
18
32
|
|
|
19
33
|
return <div ref={ref} {...props}>{children}</div>
|
|
@@ -4,18 +4,35 @@ import { forwardRef, useEffect, useRef, useState } from 'react'
|
|
|
4
4
|
import { WithChildren } from '../types'
|
|
5
5
|
|
|
6
6
|
interface Props extends WithChildren, WithStyle {
|
|
7
|
+
/**
|
|
8
|
+
* Whether or not the content is visible.
|
|
9
|
+
*/
|
|
7
10
|
visible: boolean,
|
|
8
11
|
/**
|
|
9
12
|
* Duration of the animation in ms.
|
|
10
13
|
* @default 300
|
|
11
14
|
*/
|
|
12
15
|
duration?: number,
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Function to run right before animation to show the content starts.
|
|
18
|
+
*/
|
|
19
|
+
beforeFadeIn?: () => void,
|
|
20
|
+
/**
|
|
21
|
+
* Function to run right before animation to hide the content starts.
|
|
22
|
+
*/
|
|
23
|
+
beforeFadeOut?: () => void,
|
|
24
|
+
/**
|
|
25
|
+
* Function to run right after the animation to show the content ends.
|
|
26
|
+
*/
|
|
27
|
+
afterFadeIn?: () => void,
|
|
28
|
+
/**
|
|
29
|
+
* Function to run right after the animation to hide the content ends.
|
|
30
|
+
*/
|
|
31
|
+
afterFadeOut?: () => void,
|
|
15
32
|
}
|
|
16
33
|
|
|
17
34
|
export const Fading = forwardRef<HTMLDivElement, Props>((
|
|
18
|
-
{ visible, children, duration = 300,
|
|
35
|
+
{ visible, children, duration = 300, afterFadeIn, afterFadeOut, beforeFadeIn, beforeFadeOut, className, style },
|
|
19
36
|
ref,
|
|
20
37
|
) => {
|
|
21
38
|
const [isOpaque, setOpaque] = useState(visible)
|
|
@@ -30,13 +47,16 @@ export const Fading = forwardRef<HTMLDivElement, Props>((
|
|
|
30
47
|
timeout.current = []
|
|
31
48
|
if (visible) {
|
|
32
49
|
setRendered(true)
|
|
50
|
+
if (afterFadeIn) timeout.current.push(window.setTimeout(afterFadeIn, duration))
|
|
51
|
+
beforeFadeIn?.()
|
|
33
52
|
timeout.current.push(window.setTimeout(() => setOpaque(true), 0))
|
|
34
|
-
|
|
53
|
+
|
|
35
54
|
} else {
|
|
36
55
|
setOpaque(false)
|
|
56
|
+
beforeFadeOut?.()
|
|
37
57
|
timeout.current.push(window.setTimeout(() => {
|
|
38
58
|
setRendered(false)
|
|
39
|
-
|
|
59
|
+
afterFadeOut?.()
|
|
40
60
|
}, duration))
|
|
41
61
|
}
|
|
42
62
|
previous.current = visible
|
|
@@ -10,12 +10,38 @@ type Side = 'top' | 'right' | 'left' | 'bottom'
|
|
|
10
10
|
type ScrollType = 'none' | 'wheel' | 'bar' | 'arrows'
|
|
11
11
|
|
|
12
12
|
interface Props extends WithChildren, WithStyle {
|
|
13
|
+
/**
|
|
14
|
+
* How to scroll the content.
|
|
15
|
+
* - none: overflow is hidden. No scrolling.
|
|
16
|
+
* - wheel: the content is solely scrollable through the mouse wheel and keyboard arrows, no scroll bars are rendered.
|
|
17
|
+
* - bar: this is the normal browser scroll. The content will be scrollable through the mouse wheel, keyboard and scrollbar.
|
|
18
|
+
* - arrows: arrows will be placed in the far edges of the sides that must be scrolled. The content is scrolled through the mouse wheel,
|
|
19
|
+
* keyboard and these arrows. Hovering an arrow slowly scrolls the content, clicking the arrow fully scrolls the content in its direction.
|
|
20
|
+
* There are no scrollbars in this scenario.
|
|
21
|
+
* @default 'none'
|
|
22
|
+
*/
|
|
13
23
|
scroll?: ScrollType,
|
|
24
|
+
/**
|
|
25
|
+
* If true, a horizontal scroll can be performed by using the vertical mouse wheel.
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
14
28
|
enableHorizontalScrollWithVerticalWheel?: boolean,
|
|
29
|
+
/**
|
|
30
|
+
* Which sides to fade when the content overflows.
|
|
31
|
+
*
|
|
32
|
+
* Important: it seems the current solution doesn't support mixing vertical and horizontal scrolls. I'm not sure if this is possible, I
|
|
33
|
+
* believed combining linear gradients would work, but it doesn't.
|
|
34
|
+
*/
|
|
15
35
|
sides?: Side[],
|
|
16
36
|
}
|
|
17
37
|
|
|
38
|
+
// Scrolling can be very fast, this sets a lower limit for us to run listeners without impacting performance.
|
|
18
39
|
const MIN_CHECK_INTERVAL_MS = 20
|
|
40
|
+
// The interval which to scroll the content when a scroll arrow is hovered.
|
|
41
|
+
const SCROLL_INTERVAL_MS = 20
|
|
42
|
+
// This sets the speed of the scroll when the user hovers a scroll arrow.
|
|
43
|
+
const SCROLL_PX = 4
|
|
44
|
+
// Fade masks
|
|
19
45
|
const masks = {
|
|
20
46
|
right: 'linear-gradient(to left, rgb(0, 0, 0, 0) 0%, rgb(0, 0, 0) min(30%, 100px), rgba(0, 0, 0) 100%)',
|
|
21
47
|
left: 'linear-gradient(to right, rgb(0, 0, 0, 0) 0%, rgb(0, 0, 0) min(30%, 100px), rgba(0, 0, 0) 100%)',
|
|
@@ -95,9 +121,11 @@ const OverflowBox = styled.div`
|
|
|
95
121
|
}
|
|
96
122
|
`
|
|
97
123
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
124
|
+
/**
|
|
125
|
+
* This component applies a fading graphical effect to its content if it overflows in any of the sides specified by the props.
|
|
126
|
+
*
|
|
127
|
+
* This also controls how this overflow is scrolled, introducing a new scrolling technique, which applies arrows to the overflowing side.
|
|
128
|
+
*/
|
|
101
129
|
export const FadingOverflow = (
|
|
102
130
|
{ children, scroll = 'none', sides, enableHorizontalScrollWithVerticalWheel, className, ...props }: Props,
|
|
103
131
|
) => {
|
|
@@ -4,7 +4,13 @@ import { ErrorBoundary } from './ErrorBoundary'
|
|
|
4
4
|
import { Loading } from './Loading'
|
|
5
5
|
|
|
6
6
|
interface Props extends WithChildren {
|
|
7
|
+
/**
|
|
8
|
+
* Use this to show errors in small spaces.
|
|
9
|
+
*/
|
|
7
10
|
mini?: boolean,
|
|
11
|
+
/**
|
|
12
|
+
* Replaces the error message with this text.
|
|
13
|
+
*/
|
|
8
14
|
message?: string,
|
|
9
15
|
}
|
|
10
16
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-empty-pattern */
|
|
2
1
|
import { Text } from '@citric/core'
|
|
3
2
|
import { theme, WithStyle } from '@stack-spot/portal-theme'
|
|
4
3
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
@@ -10,9 +9,21 @@ import { subtractDays } from '../utils/date'
|
|
|
10
9
|
type HistorySectionName = 'today' | 'yesterday' | 'last7' | 'last30' | 'older'
|
|
11
10
|
|
|
12
11
|
interface Props<T> extends WithStyle {
|
|
12
|
+
/**
|
|
13
|
+
* The items in the history.
|
|
14
|
+
*/
|
|
13
15
|
items: T[],
|
|
16
|
+
/**
|
|
17
|
+
* A function to render an item.
|
|
18
|
+
*/
|
|
14
19
|
renderItem: (item: T) => React.ReactNode,
|
|
20
|
+
/**
|
|
21
|
+
* A function that returns the date of the item.
|
|
22
|
+
*/
|
|
15
23
|
getDate: (item: T) => Date,
|
|
24
|
+
/**
|
|
25
|
+
* A function that returns a unique id for the item.
|
|
26
|
+
*/
|
|
16
27
|
keygen: (item: T) => React.Key,
|
|
17
28
|
}
|
|
18
29
|
|
|
@@ -53,6 +64,9 @@ function dateToSectionName(date: Date): HistorySectionName {
|
|
|
53
64
|
return date.getTime() >= last30Days.getTime() ? 'last30' : 'older'
|
|
54
65
|
}
|
|
55
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Renders a history list, where the items are combined into sections according to their dates.
|
|
69
|
+
*/
|
|
56
70
|
export function HistoryList<T>({ getDate, items, keygen, className, style, renderItem }: Props<T>) {
|
|
57
71
|
const t = useTranslate(dictionary)
|
|
58
72
|
const sections = useMemo(() => {
|
|
@@ -47,6 +47,9 @@ const InputBox = styled.div`
|
|
|
47
47
|
}
|
|
48
48
|
`
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* A text input with an icon at the left side.
|
|
52
|
+
*/
|
|
50
53
|
export const IconInput = ({ icon, onChange, style, className, disabled, onFocus, onBlur, ...props }: Props) => {
|
|
51
54
|
const [focused, setFocused] = useState(false)
|
|
52
55
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/* eslint-disable react/display-name */
|
|
2
|
-
/* eslint-disable no-empty-pattern */
|
|
3
2
|
import { IconBox, Text } from '@citric/core'
|
|
4
3
|
import { useKeyboardControls } from '@stack-spot/portal-components'
|
|
5
4
|
import { theme, WithStyle } from '@stack-spot/portal-theme'
|
|
@@ -11,12 +10,24 @@ import { useTooltip } from './Tooltip/context'
|
|
|
11
10
|
import { TooltipPosition } from './Tooltip/types'
|
|
12
11
|
|
|
13
12
|
interface Props extends WithStyle, WithChildren {
|
|
13
|
+
/**
|
|
14
|
+
* The position of the menu relative to its children.
|
|
15
|
+
*/
|
|
14
16
|
position?: TooltipPosition,
|
|
17
|
+
/**
|
|
18
|
+
* The actions of the menu.
|
|
19
|
+
*/
|
|
15
20
|
actions: ButtonAction[],
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
interface MenuProps {
|
|
24
|
+
/**
|
|
25
|
+
* The actions of the menu.
|
|
26
|
+
*/
|
|
19
27
|
actions: ButtonAction[],
|
|
28
|
+
/**
|
|
29
|
+
* A reference to the HTML element that triggered the menu.
|
|
30
|
+
*/
|
|
20
31
|
trigger: RefObject<HTMLDivElement>,
|
|
21
32
|
}
|
|
22
33
|
|
|
@@ -91,6 +102,11 @@ const Menu = ({ actions, trigger }: MenuProps) => {
|
|
|
91
102
|
)
|
|
92
103
|
}
|
|
93
104
|
|
|
105
|
+
/**
|
|
106
|
+
* A floating menu that shows up when the user clicks the children.
|
|
107
|
+
*
|
|
108
|
+
* This uses the tooltip component to build the menu.
|
|
109
|
+
*/
|
|
94
110
|
export const OverlayMenu = forwardRef<HTMLDivElement, Props>(({ actions, children, className, position, style }, externalRef) => {
|
|
95
111
|
const localRef = useRef<HTMLDivElement>(null)
|
|
96
112
|
const ref = externalRef as RefObject<HTMLDivElement> ?? localRef
|
|
@@ -2,10 +2,28 @@ import { listToClass, theme, WithStyle } from '@stack-spot/portal-theme'
|
|
|
2
2
|
import { styled } from 'styled-components'
|
|
3
3
|
|
|
4
4
|
interface Props extends WithStyle {
|
|
5
|
+
/**
|
|
6
|
+
* Whether or not the progress bar is visible.
|
|
7
|
+
*/
|
|
5
8
|
visible?: boolean,
|
|
9
|
+
/**
|
|
10
|
+
* When true, the progress bar becomes very colorful and bright.
|
|
11
|
+
*/
|
|
6
12
|
shimmer?: boolean,
|
|
13
|
+
/**
|
|
14
|
+
* Color to use in the progress bar that appears in the foreground. Arrays create linear gradients.
|
|
15
|
+
* @default primary.500 if shimmer is false, white otherwise.
|
|
16
|
+
*/
|
|
7
17
|
foregroundColor?: string | string[],
|
|
18
|
+
/**
|
|
19
|
+
* Color to use in the progress bar that appears in the background. Arrays create linear gradients.
|
|
20
|
+
* @default light.500 if shimmer is false, a transparent white otherwise.
|
|
21
|
+
*/
|
|
8
22
|
backgroundColor?: string | string[],
|
|
23
|
+
/**
|
|
24
|
+
* Only useful if `shimmer` is true. This allows to customize the colors in the shimmering effect. Arrays create linear gradients.
|
|
25
|
+
* @default ['#ff6633', '#d668cd', '#ff6633', '#FFF8', '#299cf4']
|
|
26
|
+
*/
|
|
9
27
|
shimmerColor?: string | string[],
|
|
10
28
|
}
|
|
11
29
|
|
|
@@ -21,6 +39,7 @@ function gradientFromColorArray(colors: string[]) {
|
|
|
21
39
|
return `linear-gradient(to right, ${partials.join(', ')})`
|
|
22
40
|
}
|
|
23
41
|
|
|
42
|
+
// the shimmering effect requires more space
|
|
24
43
|
const SHIMMER_PADDING = '10px'
|
|
25
44
|
|
|
26
45
|
const Styled = styled.div<{ $bg: string[], $fg: string[], $shimmer: string[] }>`
|
|
@@ -123,6 +142,10 @@ const Styled = styled.div<{ $bg: string[], $fg: string[], $shimmer: string[] }>`
|
|
|
123
142
|
}
|
|
124
143
|
`
|
|
125
144
|
|
|
145
|
+
/**
|
|
146
|
+
* A progress bar with indefinite progress report. This renders a narrower bar on top of larger one that animates from the left to the
|
|
147
|
+
* right.
|
|
148
|
+
*/
|
|
126
149
|
export const ProgressBar = ({
|
|
127
150
|
visible = true,
|
|
128
151
|
shimmer,
|
|
@@ -41,6 +41,9 @@ const Form = styled.form`
|
|
|
41
41
|
}
|
|
42
42
|
`
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* A form that goes into a right panel. This controls style, errors, loading focus and form submission.
|
|
46
|
+
*/
|
|
44
47
|
export const RightPanelForm = ({ children, onSubmit, ...props }: PropsOf<typeof Form>) => (
|
|
45
48
|
<FallbackBoundary>
|
|
46
49
|
<AutoFocus>
|
|
@@ -24,6 +24,9 @@ const StyledTabsItem = styled(TabsItem)`
|
|
|
24
24
|
overflow: hidden;
|
|
25
25
|
`
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Tabs for the right panel content.
|
|
29
|
+
*/
|
|
27
30
|
export const RightPanelTabs = ({ tabs }: Props) => {
|
|
28
31
|
const [currentTab, setCurrentTab] = useState(0)
|
|
29
32
|
const tabItems = useMemo(() => tabs.map(({ content, title }) => (
|
|
@@ -41,7 +41,9 @@ interface Props<T, Key extends React.Key> {
|
|
|
41
41
|
renderLabel: (tab: T) => React.ReactElement,
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// The size of extra buttons placed after the tabs.
|
|
44
45
|
const EXTRA_BTN_SIZE = 24
|
|
46
|
+
// The margin of extra buttons placed after the tabs.
|
|
45
47
|
const EXTRA_BTN_MARGIN = 8
|
|
46
48
|
|
|
47
49
|
const Tabs = styled.nav<{ $numberOfExtraButtons: number }>`
|
|
@@ -161,6 +163,12 @@ const Tabs = styled.nav<{ $numberOfExtraButtons: number }>`
|
|
|
161
163
|
}
|
|
162
164
|
`
|
|
163
165
|
|
|
166
|
+
/**
|
|
167
|
+
* Renders and manages a list of tabs. With this, tabs can be selected and removed. Furthermore, extra buttons can be placed after all tabs,
|
|
168
|
+
* e.g. a button to add more tabs.
|
|
169
|
+
*
|
|
170
|
+
* Used for the chat tabs.
|
|
171
|
+
*/
|
|
164
172
|
export function TabManager<T, Key extends React.Key>(
|
|
165
173
|
{ active, tabs, keygen, onRemove, onSelect, renderLabel, buttons = [] }: Props<T, Key>,
|
|
166
174
|
) {
|