@stack-spot/ai-chat-widget 0.11.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 +65 -25
- 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 +32 -10
- 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 +13 -1
- package/dist/components/AdaptiveTextArea.d.ts.map +1 -1
- package/dist/components/AdaptiveTextArea.js +9 -4
- package/dist/components/AdaptiveTextArea.js.map +1 -1
- package/dist/components/AutoFocus.d.ts +23 -0
- package/dist/components/AutoFocus.d.ts.map +1 -0
- package/dist/components/AutoFocus.js +16 -0
- package/dist/components/AutoFocus.js.map +1 -0
- package/dist/components/Fading.d.ts +32 -0
- package/dist/components/Fading.d.ts.map +1 -0
- package/dist/components/Fading.js +33 -0
- package/dist/components/Fading.js.map +1 -0
- 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/ErrorBoundary.d.ts +3 -0
- package/dist/components/FallbackBoundary/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/FallbackBoundary/ErrorBoundary.js +18 -4
- package/dist/components/FallbackBoundary/ErrorBoundary.js.map +1 -1
- package/dist/components/FallbackBoundary/Loading.js +1 -1
- package/dist/components/FallbackBoundary/Loading.js.map +1 -1
- package/dist/components/FallbackBoundary/index.d.ts +12 -1
- package/dist/components/FallbackBoundary/index.d.ts.map +1 -1
- package/dist/components/FallbackBoundary/index.js +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 +12 -1
- package/dist/components/OverlayMenu.d.ts.map +1 -1
- package/dist/components/OverlayMenu.js +31 -10
- 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 +8 -4
- 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 +26 -1
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +18 -5
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/Tooltip/TooltipAPI.d.ts +18 -2
- package/dist/components/Tooltip/TooltipAPI.d.ts.map +1 -1
- package/dist/components/Tooltip/TooltipAPI.js +68 -51
- 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/layout.css +5 -0
- package/dist/regex.d.ts +2 -0
- package/dist/regex.d.ts.map +1 -0
- package/dist/regex.js +2 -0
- package/dist/regex.js.map +1 -0
- 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 +3 -0
- 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/constants.d.ts +2 -0
- package/dist/right-panel/constants.d.ts.map +1 -0
- package/dist/right-panel/constants.js +2 -0
- package/dist/right-panel/constants.js.map +1 -0
- 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 +8 -1
- 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 +15 -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/utils/url.d.ts +2 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/url.js +8 -0
- package/dist/utils/url.js.map +1 -0
- 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 +9 -13
- 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 +5 -1
- 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 +13 -1
- 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 +13 -0
- package/dist/views/MessageInput/QuickCommandSelector.d.ts.map +1 -0
- package/dist/views/MessageInput/QuickCommandSelector.js +141 -0
- package/dist/views/MessageInput/QuickCommandSelector.js.map +1 -0
- 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 +11 -4
- package/dist/views/MessageInput/index.js.map +1 -1
- package/dist/views/MessageInput/styled.d.ts.map +1 -1
- package/dist/views/MessageInput/styled.js +137 -0
- package/dist/views/MessageInput/styled.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 +66 -26
- package/src/chat-interceptors/send-message.ts +41 -11
- package/src/components/Accordion.tsx +10 -0
- package/src/components/AdaptiveTextArea.tsx +21 -4
- package/src/components/AutoFocus.tsx +34 -0
- package/src/components/Fading.tsx +66 -0
- package/src/components/FadingOverflow.tsx +31 -3
- package/src/components/FallbackBoundary/ErrorBoundary.tsx +26 -3
- package/src/components/FallbackBoundary/Loading.tsx +1 -1
- package/src/components/FallbackBoundary/index.tsx +13 -2
- package/src/components/HistoryList.tsx +15 -1
- package/src/components/IconInput.tsx +3 -0
- package/src/components/OverlayMenu.tsx +76 -20
- package/src/components/ProgressBar.tsx +23 -0
- package/src/components/QuickStartButton.tsx +3 -0
- package/src/components/RightPanelForm.tsx +15 -9
- package/src/components/RightPanelTabs.tsx +3 -0
- package/src/components/TabManager.tsx +8 -0
- package/src/components/Tooltip/Tooltip.tsx +47 -5
- package/src/components/Tooltip/TooltipAPI.ts +59 -42
- 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/layout.css +5 -0
- package/src/regex.ts +1 -0
- package/src/right-panel/DefaultPanel.tsx +4 -0
- package/src/right-panel/RightPanel.tsx +3 -0
- package/src/right-panel/RightPanelProvider.tsx +15 -0
- package/src/right-panel/constants.ts +1 -0
- package/src/right-panel/hooks.tsx +8 -1
- 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 +15 -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/utils/url.ts +8 -0
- package/src/views/Agents.tsx +3 -0
- package/src/views/Chat/AgentInfo.tsx +3 -0
- package/src/views/Chat/ChatMessage.tsx +31 -18
- 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 +6 -2
- package/src/views/ChatHistory/HistoryItem.tsx +14 -2
- 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 +217 -0
- package/src/views/MessageInput/index.tsx +16 -4
- package/src/views/MessageInput/styled.ts +137 -0
- package/src/views/MinimizedHeader.tsx +4 -0
- package/src/views/Stacks.tsx +3 -0
- package/src/views/Workspaces.tsx +3 -0
|
@@ -1,9 +1,46 @@
|
|
|
1
1
|
import { aiClient, StackspotAPIError } from '@stack-spot/portal-network'
|
|
2
|
-
import {
|
|
2
|
+
import { ChatResponse3 } from '@stack-spot/portal-network/api/ai'
|
|
3
|
+
import { ChatEntry, KnowledgeSource, TextChatEntry } from '../state/ChatEntry'
|
|
3
4
|
import { ChatState } from '../state/ChatState'
|
|
5
|
+
import { LabeledWithImage } from '../state/types'
|
|
4
6
|
import { buildConversationContext } from '../utils/chat'
|
|
5
7
|
import { genericSourcesToKnowledgeSources } from '../utils/knowledge-source'
|
|
6
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
|
+
*/
|
|
17
|
+
function createEntryValueFromChatResponse(
|
|
18
|
+
response: Partial<ChatResponse3>,
|
|
19
|
+
knowledgeSources: KnowledgeSource[] | undefined,
|
|
20
|
+
agent: LabeledWithImage | undefined,
|
|
21
|
+
includeDate = false,
|
|
22
|
+
): TextChatEntry {
|
|
23
|
+
return {
|
|
24
|
+
agentType: 'bot',
|
|
25
|
+
type: 'md',
|
|
26
|
+
content: response.answer ?? '',
|
|
27
|
+
messageId: response.message_id ?? undefined,
|
|
28
|
+
knowledgeSources,
|
|
29
|
+
agent: agent,
|
|
30
|
+
updated: includeDate ? new Date().toISOString() : undefined,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
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
|
+
*/
|
|
7
44
|
export async function sendMessageInterceptor(entry: ChatEntry, chat: ChatState, signal: AbortSignal) {
|
|
8
45
|
const { agentType, content } = entry.getValue()
|
|
9
46
|
if (agentType !== 'user') return
|
|
@@ -20,18 +57,11 @@ export async function sendMessageInterceptor(entry: ChatEntry, chat: ChatState,
|
|
|
20
57
|
if (value.sources?.length !== knowledgeSources?.length) {
|
|
21
58
|
knowledgeSources = genericSourcesToKnowledgeSources(value.sources)
|
|
22
59
|
}
|
|
23
|
-
botEntry.setValue(
|
|
24
|
-
agentType: 'bot',
|
|
25
|
-
type: 'md',
|
|
26
|
-
content: value.answer ?? '',
|
|
27
|
-
messageId: value.message_id ?? undefined,
|
|
28
|
-
knowledgeSources,
|
|
29
|
-
updated: new Date().toISOString(),
|
|
30
|
-
agent: chat.get('agent'),
|
|
31
|
-
})
|
|
60
|
+
botEntry.setValue(createEntryValueFromChatResponse(value, knowledgeSources, chat.get('agent')))
|
|
32
61
|
})
|
|
33
62
|
try {
|
|
34
|
-
await stream.getValue()
|
|
63
|
+
const finalValue = await stream.getValue()
|
|
64
|
+
botEntry.setValue(createEntryValueFromChatResponse(finalValue, knowledgeSources, chat.get('agent'), true))
|
|
35
65
|
aiClient.chat.invalidate({ conversationId: chat.id })
|
|
36
66
|
if (isFirstMessage) aiClient.chats.invalidate()
|
|
37
67
|
} catch (error: any) {
|
|
@@ -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 (
|
|
@@ -1,15 +1,32 @@
|
|
|
1
|
+
/* eslint-disable react/display-name */
|
|
1
2
|
import { Textarea } from '@citric/core'
|
|
2
|
-
import { useEffect, useRef } from 'react'
|
|
3
|
+
import { forwardRef, useEffect, useRef } from 'react'
|
|
3
4
|
import { PropsOf } from '../types'
|
|
4
5
|
|
|
5
6
|
interface Props extends PropsOf<typeof Textarea> {
|
|
7
|
+
/**
|
|
8
|
+
* A function to run whenever the height of the text area increases.
|
|
9
|
+
*/
|
|
6
10
|
onIncreaseSize?: () => void,
|
|
11
|
+
/**
|
|
12
|
+
* A function to run whenever the text area value becomes empty.
|
|
13
|
+
*/
|
|
7
14
|
onResetSize?: () => void,
|
|
15
|
+
/**
|
|
16
|
+
* The maximum height this textarea can get to.
|
|
17
|
+
*/
|
|
8
18
|
maxHeight?: number,
|
|
9
19
|
}
|
|
10
20
|
|
|
11
|
-
|
|
12
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The adaptive textarea grows in height whenever needed until the maximum height is reached.
|
|
23
|
+
*/
|
|
24
|
+
export const AdaptiveTextArea = forwardRef<HTMLTextAreaElement, Props>((
|
|
25
|
+
{ value, onIncreaseSize, onResetSize, maxHeight, style, ...props },
|
|
26
|
+
externalRef,
|
|
27
|
+
) => {
|
|
28
|
+
const localRef = useRef<HTMLTextAreaElement>(null)
|
|
29
|
+
const ref = externalRef as React.RefObject<HTMLTextAreaElement> ?? localRef
|
|
13
30
|
|
|
14
31
|
useEffect(() => {
|
|
15
32
|
if (!ref.current) return
|
|
@@ -31,4 +48,4 @@ export const AdaptiveTextArea = ({ value, onIncreaseSize, onResetSize, maxHeight
|
|
|
31
48
|
}, [value, maxHeight])
|
|
32
49
|
|
|
33
50
|
return <Textarea {...props} ref={ref} value={value} style={{ ...style, maxHeight }} />
|
|
34
|
-
}
|
|
51
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* eslint-disable react/display-name */
|
|
2
|
+
import { focusFirstChild, TagPriorityElement } from '@stack-spot/portal-components'
|
|
3
|
+
import { forwardRef, RefObject, useEffect, useRef } from 'react'
|
|
4
|
+
|
|
5
|
+
interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/**
|
|
7
|
+
* A delay in ms to focus the first focusable element.
|
|
8
|
+
*/
|
|
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,
|
|
20
|
+
}
|
|
21
|
+
|
|
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) => {
|
|
26
|
+
const localRef = useRef<HTMLDivElement>(null)
|
|
27
|
+
const ref = externalRef as RefObject<HTMLDivElement> ?? localRef
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
setTimeout(() => focusFirstChild(ref.current, { priority, ignore }), delay)
|
|
31
|
+
}, [])
|
|
32
|
+
|
|
33
|
+
return <div ref={ref} {...props}>{children}</div>
|
|
34
|
+
})
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* eslint-disable react/display-name */
|
|
2
|
+
import { WithStyle } from '@stack-spot/portal-theme'
|
|
3
|
+
import { forwardRef, useEffect, useRef, useState } from 'react'
|
|
4
|
+
import { WithChildren } from '../types'
|
|
5
|
+
|
|
6
|
+
interface Props extends WithChildren, WithStyle {
|
|
7
|
+
/**
|
|
8
|
+
* Whether or not the content is visible.
|
|
9
|
+
*/
|
|
10
|
+
visible: boolean,
|
|
11
|
+
/**
|
|
12
|
+
* Duration of the animation in ms.
|
|
13
|
+
* @default 300
|
|
14
|
+
*/
|
|
15
|
+
duration?: number,
|
|
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,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const Fading = forwardRef<HTMLDivElement, Props>((
|
|
35
|
+
{ visible, children, duration = 300, afterFadeIn, afterFadeOut, beforeFadeIn, beforeFadeOut, className, style },
|
|
36
|
+
ref,
|
|
37
|
+
) => {
|
|
38
|
+
const [isOpaque, setOpaque] = useState(visible)
|
|
39
|
+
const [isRendered, setRendered] = useState(visible)
|
|
40
|
+
const previous = useRef(visible)
|
|
41
|
+
const timeout = useRef<number[]>([])
|
|
42
|
+
const opacity: React.CSSProperties = { transition: `opacity ${duration / 1000}s`, opacity: isOpaque ? 1 : 0 }
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (previous.current === visible) return
|
|
46
|
+
timeout.current.forEach(window.clearTimeout)
|
|
47
|
+
timeout.current = []
|
|
48
|
+
if (visible) {
|
|
49
|
+
setRendered(true)
|
|
50
|
+
if (afterFadeIn) timeout.current.push(window.setTimeout(afterFadeIn, duration))
|
|
51
|
+
beforeFadeIn?.()
|
|
52
|
+
timeout.current.push(window.setTimeout(() => setOpaque(true), 0))
|
|
53
|
+
|
|
54
|
+
} else {
|
|
55
|
+
setOpaque(false)
|
|
56
|
+
beforeFadeOut?.()
|
|
57
|
+
timeout.current.push(window.setTimeout(() => {
|
|
58
|
+
setRendered(false)
|
|
59
|
+
afterFadeOut?.()
|
|
60
|
+
}, duration))
|
|
61
|
+
}
|
|
62
|
+
previous.current = visible
|
|
63
|
+
}, [visible])
|
|
64
|
+
|
|
65
|
+
return isRendered ? <div ref={ref} className={className} style={{ ...style, ...opacity }}>{children}</div> : null
|
|
66
|
+
})
|
|
@@ -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
|
) => {
|
|
@@ -1,15 +1,29 @@
|
|
|
1
|
+
import { IconBox, Text } from '@citric/core'
|
|
2
|
+
import { TimesCircle } from '@citric/icons'
|
|
1
3
|
import { ErrorDescription, ErrorFeedback } from '@stack-spot/portal-components/error'
|
|
2
4
|
import { StackspotAPIError } from '@stack-spot/portal-network'
|
|
3
5
|
import { Component } from 'react'
|
|
6
|
+
import { styled } from 'styled-components'
|
|
4
7
|
|
|
5
8
|
interface State extends ErrorDescription {
|
|
6
9
|
hasError: boolean,
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
interface Props {
|
|
13
|
+
mini?: boolean,
|
|
14
|
+
message?: string,
|
|
10
15
|
children: React.ReactNode,
|
|
11
16
|
}
|
|
12
17
|
|
|
18
|
+
const ErrorBox = styled.div`
|
|
19
|
+
width: 100%;
|
|
20
|
+
height: 100%;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
align-items: center;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
`
|
|
26
|
+
|
|
13
27
|
/**
|
|
14
28
|
* An Error Boundary that renders an ErrorFeedback instead of its content if any of its children throws.
|
|
15
29
|
*
|
|
@@ -40,9 +54,18 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
40
54
|
if (this.props.children !== prevProps.children) this.setState({ hasError: false })
|
|
41
55
|
}
|
|
42
56
|
|
|
57
|
+
private renderError() {
|
|
58
|
+
return this.props.mini
|
|
59
|
+
? (
|
|
60
|
+
<ErrorBox className="error">
|
|
61
|
+
<IconBox size="lg" colorIcon="danger.500"><TimesCircle /></IconBox>
|
|
62
|
+
<Text colorScheme="light.700">{this.props.message || this.state.message}</Text>
|
|
63
|
+
</ErrorBox>
|
|
64
|
+
)
|
|
65
|
+
: <ErrorFeedback className="error" code={this.state.code} message={this.props.message || this.state.message} />
|
|
66
|
+
}
|
|
67
|
+
|
|
43
68
|
render() {
|
|
44
|
-
return this.state.hasError
|
|
45
|
-
? <ErrorFeedback code={this.state.code} message={this.state.message} />
|
|
46
|
-
: this.props.children
|
|
69
|
+
return this.state.hasError ? this.renderError() : this.props.children
|
|
47
70
|
}
|
|
48
71
|
}
|
|
@@ -3,11 +3,22 @@ import { WithChildren } from '../../types'
|
|
|
3
3
|
import { ErrorBoundary } from './ErrorBoundary'
|
|
4
4
|
import { Loading } from './Loading'
|
|
5
5
|
|
|
6
|
+
interface Props extends WithChildren {
|
|
7
|
+
/**
|
|
8
|
+
* Use this to show errors in small spaces.
|
|
9
|
+
*/
|
|
10
|
+
mini?: boolean,
|
|
11
|
+
/**
|
|
12
|
+
* Replaces the error message with this text.
|
|
13
|
+
*/
|
|
14
|
+
message?: string,
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
/**
|
|
7
18
|
* Fallbacks for errors and loadings (suspense).
|
|
8
19
|
*/
|
|
9
|
-
export const FallbackBoundary = ({ children }:
|
|
10
|
-
<ErrorBoundary>
|
|
20
|
+
export const FallbackBoundary = ({ children, mini, message }: Props) => (
|
|
21
|
+
<ErrorBoundary mini={mini} message={message}>
|
|
11
22
|
<Suspense fallback={<Loading />}>
|
|
12
23
|
{children}
|
|
13
24
|
</Suspense>
|
|
@@ -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,7 +1,8 @@
|
|
|
1
|
-
/* eslint-disable
|
|
1
|
+
/* eslint-disable react/display-name */
|
|
2
2
|
import { IconBox, Text } from '@citric/core'
|
|
3
|
+
import { useKeyboardControls } from '@stack-spot/portal-components'
|
|
3
4
|
import { theme, WithStyle } from '@stack-spot/portal-theme'
|
|
4
|
-
import {
|
|
5
|
+
import { forwardRef, RefObject, useCallback, useRef } from 'react'
|
|
5
6
|
import { styled } from 'styled-components'
|
|
6
7
|
import { ButtonAction, WithChildren } from '../types'
|
|
7
8
|
import { Tooltip } from './Tooltip'
|
|
@@ -9,10 +10,27 @@ import { useTooltip } from './Tooltip/context'
|
|
|
9
10
|
import { TooltipPosition } from './Tooltip/types'
|
|
10
11
|
|
|
11
12
|
interface Props extends WithStyle, WithChildren {
|
|
13
|
+
/**
|
|
14
|
+
* The position of the menu relative to its children.
|
|
15
|
+
*/
|
|
12
16
|
position?: TooltipPosition,
|
|
17
|
+
/**
|
|
18
|
+
* The actions of the menu.
|
|
19
|
+
*/
|
|
13
20
|
actions: ButtonAction[],
|
|
14
21
|
}
|
|
15
22
|
|
|
23
|
+
interface MenuProps {
|
|
24
|
+
/**
|
|
25
|
+
* The actions of the menu.
|
|
26
|
+
*/
|
|
27
|
+
actions: ButtonAction[],
|
|
28
|
+
/**
|
|
29
|
+
* A reference to the HTML element that triggered the menu.
|
|
30
|
+
*/
|
|
31
|
+
trigger: RefObject<HTMLDivElement>,
|
|
32
|
+
}
|
|
33
|
+
|
|
16
34
|
const MenuList = styled.ul`
|
|
17
35
|
margin: 0;
|
|
18
36
|
padding: 0;
|
|
@@ -37,8 +55,9 @@ const MenuList = styled.ul`
|
|
|
37
55
|
gap: 8px;
|
|
38
56
|
background-color: transparent;
|
|
39
57
|
border: none;
|
|
58
|
+
outline: none;
|
|
40
59
|
|
|
41
|
-
&:hover {
|
|
60
|
+
&:hover, &:focus {
|
|
42
61
|
background-color: ${theme.color.light[500]};
|
|
43
62
|
}
|
|
44
63
|
}
|
|
@@ -53,25 +72,62 @@ const StyledButton = styled.button<{ $color: string | undefined }>`
|
|
|
53
72
|
}
|
|
54
73
|
`
|
|
55
74
|
|
|
56
|
-
|
|
75
|
+
const Menu = ({ actions, trigger }: MenuProps) => {
|
|
57
76
|
const tooltip = useTooltip()
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
))
|
|
70
|
-
return <MenuList>{items}</MenuList>
|
|
71
|
-
}, [actions])
|
|
77
|
+
const ref = useRef<HTMLUListElement>(null)
|
|
78
|
+
|
|
79
|
+
useKeyboardControls({
|
|
80
|
+
querySelectors: 'button',
|
|
81
|
+
onPressEscape: () => {
|
|
82
|
+
tooltip.hide()
|
|
83
|
+
trigger.current?.focus()
|
|
84
|
+
},
|
|
85
|
+
ref,
|
|
86
|
+
}, [])
|
|
87
|
+
|
|
72
88
|
return (
|
|
73
|
-
<
|
|
89
|
+
<MenuList ref={ref}>
|
|
90
|
+
{actions.map(({ label, onClick, className, color, icon, style }) => (
|
|
91
|
+
<li key={label} className={className} style={style}>
|
|
92
|
+
<StyledButton $color={color} onClick={() => {
|
|
93
|
+
onClick()
|
|
94
|
+
tooltip.hide()
|
|
95
|
+
}}>
|
|
96
|
+
<IconBox>{icon}</IconBox>
|
|
97
|
+
<Text>{label}</Text>
|
|
98
|
+
</StyledButton>
|
|
99
|
+
</li>
|
|
100
|
+
))}
|
|
101
|
+
</MenuList>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
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
|
+
*/
|
|
110
|
+
export const OverlayMenu = forwardRef<HTMLDivElement, Props>(({ actions, children, className, position, style }, externalRef) => {
|
|
111
|
+
const localRef = useRef<HTMLDivElement>(null)
|
|
112
|
+
const ref = externalRef as RefObject<HTMLDivElement> ?? localRef
|
|
113
|
+
const tooltip = useTooltip()
|
|
114
|
+
|
|
115
|
+
const onShow = useCallback(() => {
|
|
116
|
+
tooltip.tooltipRef.current?.querySelector('button')?.focus()
|
|
117
|
+
}, [])
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<Tooltip
|
|
121
|
+
content={<Menu actions={actions} trigger={ref} />}
|
|
122
|
+
custom
|
|
123
|
+
position={position}
|
|
124
|
+
className={className}
|
|
125
|
+
style={style}
|
|
126
|
+
triggeredBy="click"
|
|
127
|
+
onShow={onShow}
|
|
128
|
+
ref={ref}
|
|
129
|
+
>
|
|
74
130
|
{children}
|
|
75
131
|
</Tooltip>
|
|
76
132
|
)
|
|
77
|
-
}
|
|
133
|
+
})
|
|
@@ -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,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Card } from '@citric/ui'
|
|
2
2
|
import { styled } from 'styled-components'
|
|
3
3
|
import { PropsOf } from '../types'
|
|
4
|
+
import { AutoFocus } from './AutoFocus'
|
|
4
5
|
import { FallbackBoundary } from './FallbackBoundary'
|
|
5
6
|
|
|
6
7
|
const Form = styled.form`
|
|
@@ -40,16 +41,21 @@ const Form = styled.form`
|
|
|
40
41
|
}
|
|
41
42
|
`
|
|
42
43
|
|
|
44
|
+
/**
|
|
45
|
+
* A form that goes into a right panel. This controls style, errors, loading focus and form submission.
|
|
46
|
+
*/
|
|
43
47
|
export const RightPanelForm = ({ children, onSubmit, ...props }: PropsOf<typeof Form>) => (
|
|
44
48
|
<FallbackBoundary>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
e
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
<AutoFocus>
|
|
50
|
+
<Form
|
|
51
|
+
{...props}
|
|
52
|
+
onSubmit={(e) => {
|
|
53
|
+
e.preventDefault()
|
|
54
|
+
onSubmit?.(e)
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
{children}
|
|
58
|
+
</Form>
|
|
59
|
+
</AutoFocus>
|
|
54
60
|
</FallbackBoundary>
|
|
55
61
|
)
|
|
@@ -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 }) => (
|