@stack-spot/ai-chat-widget 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/StackspotAIWidget.d.ts +13 -0
- package/dist/StackspotAIWidget.d.ts.map +1 -0
- package/dist/StackspotAIWidget.js +32 -0
- package/dist/StackspotAIWidget.js.map +1 -0
- package/dist/chat-interceptors/quick-commands.d.ts +4 -0
- package/dist/chat-interceptors/quick-commands.d.ts.map +1 -0
- package/dist/chat-interceptors/quick-commands.js +11 -0
- package/dist/chat-interceptors/quick-commands.js.map +1 -0
- package/dist/chat-interceptors/send-message.d.ts +4 -0
- package/dist/chat-interceptors/send-message.d.ts.map +1 -0
- package/dist/chat-interceptors/send-message.js +36 -0
- package/dist/chat-interceptors/send-message.js.map +1 -0
- package/dist/components/Accordion.d.ts +10 -0
- package/dist/components/Accordion.d.ts.map +1 -0
- package/dist/components/Accordion.js +46 -0
- package/dist/components/Accordion.js.map +1 -0
- package/dist/components/AdaptiveTextArea.d.ts +10 -0
- package/dist/components/AdaptiveTextArea.d.ts.map +1 -0
- package/dist/components/AdaptiveTextArea.js +28 -0
- package/dist/components/AdaptiveTextArea.js.map +1 -0
- package/dist/components/Code.d.ts +19 -0
- package/dist/components/Code.d.ts.map +1 -0
- package/dist/components/Code.js +112 -0
- package/dist/components/Code.js.map +1 -0
- package/dist/components/Editor.d.ts +9 -0
- package/dist/components/Editor.d.ts.map +1 -0
- package/dist/components/Editor.js +2 -0
- package/dist/components/Editor.js.map +1 -0
- package/dist/components/FadingOverflow.d.ts +12 -0
- package/dist/components/FadingOverflow.d.ts.map +1 -0
- package/dist/components/FadingOverflow.js +216 -0
- package/dist/components/FadingOverflow.js.map +1 -0
- package/dist/components/FallbackBoundary/ErrorBoundary.d.ts +30 -0
- package/dist/components/FallbackBoundary/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/FallbackBoundary/ErrorBoundary.js +38 -0
- package/dist/components/FallbackBoundary/ErrorBoundary.js.map +1 -0
- package/dist/components/FallbackBoundary/Loading.d.ts +2 -0
- package/dist/components/FallbackBoundary/Loading.d.ts.map +1 -0
- package/dist/components/FallbackBoundary/Loading.js +12 -0
- package/dist/components/FallbackBoundary/Loading.js.map +1 -0
- package/dist/components/FallbackBoundary/index.d.ts +6 -0
- package/dist/components/FallbackBoundary/index.d.ts.map +1 -0
- package/dist/components/FallbackBoundary/index.js +9 -0
- package/dist/components/FallbackBoundary/index.js.map +1 -0
- package/dist/components/HistoryList.d.ts +13 -0
- package/dist/components/HistoryList.d.ts.map +1 -0
- package/dist/components/HistoryList.js +4 -0
- package/dist/components/HistoryList.js.map +1 -0
- package/dist/components/IconInput.d.ts +7 -0
- package/dist/components/IconInput.d.ts.map +1 -0
- package/dist/components/IconInput.js +58 -0
- package/dist/components/IconInput.js.map +1 -0
- package/dist/components/Markdown.d.ts +9 -0
- package/dist/components/Markdown.d.ts.map +1 -0
- package/dist/components/Markdown.js +17 -0
- package/dist/components/Markdown.js.map +1 -0
- package/dist/components/OverlayMenu.d.ts +9 -0
- package/dist/components/OverlayMenu.d.ts.map +1 -0
- package/dist/components/OverlayMenu.js +2 -0
- package/dist/components/OverlayMenu.js.map +1 -0
- package/dist/components/ProgressBar.d.ts +11 -0
- package/dist/components/ProgressBar.d.ts.map +1 -0
- package/dist/components/ProgressBar.js +126 -0
- package/dist/components/ProgressBar.js.map +1 -0
- package/dist/components/QuickStartButton.d.ts +8 -0
- package/dist/components/QuickStartButton.d.ts.map +1 -0
- package/dist/components/QuickStartButton.js +40 -0
- package/dist/components/QuickStartButton.js.map +1 -0
- package/dist/components/RightPanelForm.d.ts +5 -0
- package/dist/components/RightPanelForm.d.ts.map +1 -0
- package/dist/components/RightPanelForm.js +45 -0
- package/dist/components/RightPanelForm.js.map +1 -0
- package/dist/components/RightPanelTabs.d.ts +10 -0
- package/dist/components/RightPanelTabs.d.ts.map +1 -0
- package/dist/components/RightPanelTabs.js +20 -0
- package/dist/components/RightPanelTabs.js.map +1 -0
- package/dist/components/TabManager.d.ts +34 -0
- package/dist/components/TabManager.d.ts.map +1 -0
- package/dist/components/TabManager.js +158 -0
- package/dist/components/TabManager.js.map +1 -0
- package/dist/components/Tooltip/Tooltip.d.ts +11 -0
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip/Tooltip.js +9 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -0
- package/dist/components/Tooltip/TooltipAPI.d.ts +10 -0
- package/dist/components/Tooltip/TooltipAPI.d.ts.map +1 -0
- package/dist/components/Tooltip/TooltipAPI.js +48 -0
- package/dist/components/Tooltip/TooltipAPI.js.map +1 -0
- package/dist/components/Tooltip/context.d.ts +5 -0
- package/dist/components/Tooltip/context.d.ts.map +1 -0
- package/dist/components/Tooltip/context.js +18 -0
- package/dist/components/Tooltip/context.js.map +1 -0
- package/dist/components/Tooltip/index.d.ts +3 -0
- package/dist/components/Tooltip/index.d.ts.map +1 -0
- package/dist/components/Tooltip/index.js +3 -0
- package/dist/components/Tooltip/index.js.map +1 -0
- package/dist/components/Tooltip/style.d.ts +4 -0
- package/dist/components/Tooltip/style.d.ts.map +1 -0
- package/dist/components/Tooltip/style.js +23 -0
- package/dist/components/Tooltip/style.js.map +1 -0
- package/dist/components/Tooltip/types.d.ts +8 -0
- package/dist/components/Tooltip/types.d.ts.map +1 -0
- package/dist/components/Tooltip/types.js +2 -0
- package/dist/components/Tooltip/types.js.map +1 -0
- package/dist/components/form/DescribedCheckboxGroup.d.ts +3 -0
- package/dist/components/form/DescribedCheckboxGroup.d.ts.map +1 -0
- package/dist/components/form/DescribedCheckboxGroup.js +23 -0
- package/dist/components/form/DescribedCheckboxGroup.js.map +1 -0
- package/dist/components/form/DescribedRadioGroup.d.ts +3 -0
- package/dist/components/form/DescribedRadioGroup.d.ts.map +1 -0
- package/dist/components/form/DescribedRadioGroup.js +18 -0
- package/dist/components/form/DescribedRadioGroup.js.map +1 -0
- package/dist/components/form/styled.d.ts +2 -0
- package/dist/components/form/styled.d.ts.map +1 -0
- package/dist/components/form/styled.js +41 -0
- package/dist/components/form/styled.js.map +1 -0
- package/dist/components/form/types.d.ts +19 -0
- package/dist/components/form/types.d.ts.map +1 -0
- package/dist/components/form/types.js +2 -0
- package/dist/components/form/types.js.map +1 -0
- package/dist/context/AIWidgetProvider.d.ts +4 -0
- package/dist/context/AIWidgetProvider.d.ts.map +1 -0
- package/dist/context/AIWidgetProvider.js +4 -0
- package/dist/context/AIWidgetProvider.js.map +1 -0
- package/dist/context/hooks.d.ts +18 -0
- package/dist/context/hooks.d.ts.map +1 -0
- package/dist/context/hooks.js +82 -0
- package/dist/context/hooks.js.map +1 -0
- package/dist/features.d.ts +13 -0
- package/dist/features.d.ts.map +1 -0
- package/dist/features.js +6 -0
- package/dist/features.js.map +1 -0
- package/dist/hooks/chat-scroll.d.ts +7 -0
- package/dist/hooks/chat-scroll.d.ts.map +1 -0
- package/dist/hooks/chat-scroll.js +15 -0
- package/dist/hooks/chat-scroll.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.css +119 -0
- package/dist/right-panel/DefaultPanel.d.ts +9 -0
- package/dist/right-panel/DefaultPanel.d.ts.map +1 -0
- package/dist/right-panel/DefaultPanel.js +46 -0
- package/dist/right-panel/DefaultPanel.js.map +1 -0
- package/dist/right-panel/RightPanel.d.ts +2 -0
- package/dist/right-panel/RightPanel.d.ts.map +1 -0
- package/dist/right-panel/RightPanel.js +6 -0
- package/dist/right-panel/RightPanel.js.map +1 -0
- package/dist/right-panel/RightPanelProvider.d.ts +13 -0
- package/dist/right-panel/RightPanelProvider.d.ts.map +1 -0
- package/dist/right-panel/RightPanelProvider.js +10 -0
- package/dist/right-panel/RightPanelProvider.js.map +1 -0
- package/dist/right-panel/hooks.d.ts +13 -0
- package/dist/right-panel/hooks.d.ts.map +1 -0
- package/dist/right-panel/hooks.js +39 -0
- package/dist/right-panel/hooks.js.map +1 -0
- package/dist/state/ChatEntry.d.ts +48 -0
- package/dist/state/ChatEntry.d.ts.map +1 -0
- package/dist/state/ChatEntry.js +55 -0
- package/dist/state/ChatEntry.js.map +1 -0
- package/dist/state/ChatState.d.ts +46 -0
- package/dist/state/ChatState.d.ts.map +1 -0
- package/dist/state/ChatState.js +53 -0
- package/dist/state/ChatState.js.map +1 -0
- package/dist/state/ChatTabsController.d.ts +17 -0
- package/dist/state/ChatTabsController.d.ts.map +1 -0
- package/dist/state/ChatTabsController.js +47 -0
- package/dist/state/ChatTabsController.js.map +1 -0
- package/dist/state/ObservableState.d.ts +10 -0
- package/dist/state/ObservableState.d.ts.map +1 -0
- package/dist/state/ObservableState.js +25 -0
- package/dist/state/ObservableState.js.map +1 -0
- package/dist/state/WidgetState.d.ts +19 -0
- package/dist/state/WidgetState.d.ts.map +1 -0
- package/dist/state/WidgetState.js +29 -0
- package/dist/state/WidgetState.js.map +1 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/chat.d.ts +6 -0
- package/dist/utils/chat.d.ts.map +1 -0
- package/dist/utils/chat.js +26 -0
- package/dist/utils/chat.js.map +1 -0
- package/dist/utils/date.d.ts +6 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +38 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/views/Agents.d.ts +2 -0
- package/dist/views/Agents.d.ts.map +1 -0
- package/dist/views/Agents.js +2 -0
- package/dist/views/Agents.js.map +1 -0
- package/dist/views/Chat/AgentInfo.d.ts +6 -0
- package/dist/views/Chat/AgentInfo.d.ts.map +1 -0
- package/dist/views/Chat/AgentInfo.js +7 -0
- package/dist/views/Chat/AgentInfo.js.map +1 -0
- package/dist/views/Chat/ChatMessage.d.ts +6 -0
- package/dist/views/Chat/ChatMessage.d.ts.map +1 -0
- package/dist/views/Chat/ChatMessage.js +61 -0
- package/dist/views/Chat/ChatMessage.js.map +1 -0
- package/dist/views/Chat/ChatMessages.d.ts +7 -0
- package/dist/views/Chat/ChatMessages.d.ts.map +1 -0
- package/dist/views/Chat/ChatMessages.js +12 -0
- package/dist/views/Chat/ChatMessages.js.map +1 -0
- package/dist/views/Chat/index.d.ts +6 -0
- package/dist/views/Chat/index.d.ts.map +1 -0
- package/dist/views/Chat/index.js +8 -0
- package/dist/views/Chat/index.js.map +1 -0
- package/dist/views/Chat/styled.d.ts +2 -0
- package/dist/views/Chat/styled.d.ts.map +1 -0
- package/dist/views/Chat/styled.js +116 -0
- package/dist/views/Chat/styled.js.map +1 -0
- package/dist/views/ChatTabSelection.d.ts +8 -0
- package/dist/views/ChatTabSelection.d.ts.map +1 -0
- package/dist/views/ChatTabSelection.js +45 -0
- package/dist/views/ChatTabSelection.js.map +1 -0
- package/dist/views/Editor.d.ts +2 -0
- package/dist/views/Editor.d.ts.map +1 -0
- package/dist/views/Editor.js +2 -0
- package/dist/views/Editor.js.map +1 -0
- package/dist/views/Home.d.ts +6 -0
- package/dist/views/Home.d.ts.map +1 -0
- package/dist/views/Home.js +68 -0
- package/dist/views/Home.js.map +1 -0
- package/dist/views/KnowledgeSources.d.ts +2 -0
- package/dist/views/KnowledgeSources.d.ts.map +1 -0
- package/dist/views/KnowledgeSources.js +82 -0
- package/dist/views/KnowledgeSources.js.map +1 -0
- package/dist/views/MessageInput/ButtonGroup.d.ts +12 -0
- package/dist/views/MessageInput/ButtonGroup.d.ts.map +1 -0
- package/dist/views/MessageInput/ButtonGroup.js +22 -0
- package/dist/views/MessageInput/ButtonGroup.js.map +1 -0
- package/dist/views/MessageInput/InfoBar.d.ts +2 -0
- package/dist/views/MessageInput/InfoBar.d.ts.map +1 -0
- package/dist/views/MessageInput/InfoBar.js +28 -0
- package/dist/views/MessageInput/InfoBar.js.map +1 -0
- package/dist/views/MessageInput/dictionary.d.ts +2 -0
- package/dist/views/MessageInput/dictionary.d.ts.map +1 -0
- package/dist/views/MessageInput/dictionary.js +35 -0
- package/dist/views/MessageInput/dictionary.js.map +1 -0
- package/dist/views/MessageInput/index.d.ts +7 -0
- package/dist/views/MessageInput/index.d.ts.map +1 -0
- package/dist/views/MessageInput/index.js +43 -0
- package/dist/views/MessageInput/index.js.map +1 -0
- package/dist/views/MessageInput/styled.d.ts +2 -0
- package/dist/views/MessageInput/styled.d.ts.map +1 -0
- package/dist/views/MessageInput/styled.js +195 -0
- package/dist/views/MessageInput/styled.js.map +1 -0
- package/dist/views/MinimizedHeader.d.ts +3 -0
- package/dist/views/MinimizedHeader.d.ts.map +1 -0
- package/dist/views/MinimizedHeader.js +76 -0
- package/dist/views/MinimizedHeader.js.map +1 -0
- package/dist/views/Stacks.d.ts +2 -0
- package/dist/views/Stacks.d.ts.map +1 -0
- package/dist/views/Stacks.js +73 -0
- package/dist/views/Stacks.js.map +1 -0
- package/dist/views/Workspaces.d.ts +2 -0
- package/dist/views/Workspaces.d.ts.map +1 -0
- package/dist/views/Workspaces.js +59 -0
- package/dist/views/Workspaces.js.map +1 -0
- package/package.json +52 -0
- package/src/StackspotAIWidget.tsx +65 -0
- package/src/chat-interceptors/quick-commands.ts +12 -0
- package/src/chat-interceptors/send-message.ts +35 -0
- package/src/components/Accordion.tsx +64 -0
- package/src/components/AdaptiveTextArea.tsx +34 -0
- package/src/components/Code.tsx +201 -0
- package/src/components/Editor.tsx +12 -0
- package/src/components/FadingOverflow.tsx +234 -0
- package/src/components/FallbackBoundary/ErrorBoundary.tsx +48 -0
- package/src/components/FallbackBoundary/Loading.tsx +14 -0
- package/src/components/FallbackBoundary/index.tsx +15 -0
- package/src/components/HistoryList.tsx +16 -0
- package/src/components/IconInput.tsx +70 -0
- package/src/components/Markdown.tsx +53 -0
- package/src/components/OverlayMenu.tsx +10 -0
- package/src/components/ProgressBar.tsx +153 -0
- package/src/components/QuickStartButton.tsx +51 -0
- package/src/components/RightPanelForm.tsx +55 -0
- package/src/components/RightPanelTabs.tsx +39 -0
- package/src/components/TabManager.tsx +223 -0
- package/src/components/Tooltip/Tooltip.tsx +30 -0
- package/src/components/Tooltip/TooltipAPI.ts +46 -0
- package/src/components/Tooltip/context.tsx +24 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/Tooltip/style.tsx +25 -0
- package/src/components/Tooltip/types.ts +8 -0
- package/src/components/form/DescribedCheckboxGroup.tsx +39 -0
- package/src/components/form/DescribedRadioGroup.tsx +33 -0
- package/src/components/form/styled.ts +41 -0
- package/src/components/form/types.ts +21 -0
- package/src/context/AIWidgetProvider.tsx +6 -0
- package/src/context/hooks.ts +93 -0
- package/src/features.ts +18 -0
- package/src/hooks/chat-scroll.ts +14 -0
- package/src/index.ts +8 -0
- package/src/layout.css +119 -0
- package/src/right-panel/DefaultPanel.tsx +67 -0
- package/src/right-panel/RightPanel.tsx +6 -0
- package/src/right-panel/RightPanelProvider.tsx +20 -0
- package/src/right-panel/hooks.tsx +47 -0
- package/src/state/ChatEntry.ts +95 -0
- package/src/state/ChatState.ts +85 -0
- package/src/state/ChatTabsController.ts +55 -0
- package/src/state/ObservableState.ts +35 -0
- package/src/state/WidgetState.ts +42 -0
- package/src/types.ts +20 -0
- package/src/utils/chat.ts +30 -0
- package/src/utils/date.ts +40 -0
- package/src/views/Agents.tsx +1 -0
- package/src/views/Chat/AgentInfo.tsx +17 -0
- package/src/views/Chat/ChatMessage.tsx +89 -0
- package/src/views/Chat/ChatMessages.tsx +16 -0
- package/src/views/Chat/index.tsx +11 -0
- package/src/views/Chat/styled.ts +116 -0
- package/src/views/ChatTabSelection.tsx +65 -0
- package/src/views/Editor.tsx +1 -0
- package/src/views/Home.tsx +109 -0
- package/src/views/KnowledgeSources.tsx +115 -0
- package/src/views/MessageInput/ButtonGroup.tsx +84 -0
- package/src/views/MessageInput/InfoBar.tsx +69 -0
- package/src/views/MessageInput/dictionary.ts +36 -0
- package/src/views/MessageInput/index.tsx +79 -0
- package/src/views/MessageInput/styled.ts +196 -0
- package/src/views/MinimizedHeader.tsx +94 -0
- package/src/views/Stacks.tsx +104 -0
- package/src/views/Workspaces.tsx +88 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { IconBox } from '@citric/core'
|
|
2
|
+
import { ChevronDown, ChevronLeft, ChevronRight, ChevronUp } from '@citric/icons'
|
|
3
|
+
import { listToClass, theme, WithStyle } from '@stack-spot/portal-theme'
|
|
4
|
+
import { debounce } from 'lodash'
|
|
5
|
+
import { useEffect, useRef } from 'react'
|
|
6
|
+
import { styled } from 'styled-components'
|
|
7
|
+
import { WithChildren } from '../types'
|
|
8
|
+
|
|
9
|
+
type Side = 'top' | 'right' | 'left' | 'bottom'
|
|
10
|
+
type ScrollType = 'none' | 'wheel' | 'bar' | 'arrows'
|
|
11
|
+
|
|
12
|
+
interface Props extends WithChildren, WithStyle {
|
|
13
|
+
scroll?: ScrollType,
|
|
14
|
+
enableHorizontalScrollWithVerticalWheel?: boolean,
|
|
15
|
+
sides?: Side[],
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const MIN_CHECK_INTERVAL_MS = 20
|
|
19
|
+
const masks = {
|
|
20
|
+
right: 'linear-gradient(to left, rgb(0, 0, 0, 0) 0%, rgb(0, 0, 0) min(30%, 100px), rgba(0, 0, 0) 100%)',
|
|
21
|
+
left: 'linear-gradient(to right, rgb(0, 0, 0, 0) 0%, rgb(0, 0, 0) min(30%, 100px), rgba(0, 0, 0) 100%)',
|
|
22
|
+
top: 'linear-gradient(to bottom, rgb(0, 0, 0, 0) 0%, rgb(0, 0, 0) min(30%, 100px), rgba(0, 0, 0) 100%)',
|
|
23
|
+
bottom: 'linear-gradient(to top, rgb(0, 0, 0, 0) 0%, rgb(0, 0, 0) min(30%, 100px), rgba(0, 0, 0) 100%)',
|
|
24
|
+
horizontal: 'linear-gradient(to left, rgb(0, 0, 0, 0) 0%, rgb(0, 0, 0) min(30%, 100px), rgb(0, 0, 0) max(70%, calc(100% - 100px)), rgba(0, 0, 0, 0) 100%)',
|
|
25
|
+
vertical: 'linear-gradient(to top, rgb(0, 0, 0, 0) 0%, rgb(0, 0, 0) min(30%, 100px), rgb(0, 0, 0) max(70%, calc(100% - 100px)), rgba(0, 0, 0, 0) 100%)',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const OverflowBox = styled.div`
|
|
29
|
+
&.hidden-scroll-bars::-webkit-scrollbar, &.scroll-arrows ::-webkit-scrollbar {
|
|
30
|
+
width: 0;
|
|
31
|
+
height: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&.scroll-arrows {
|
|
35
|
+
position: relative;
|
|
36
|
+
|
|
37
|
+
> .content {
|
|
38
|
+
width: 100%;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.scroll-to-left, .scroll-to-right, .scroll-to-top, .scroll-to-bottom {
|
|
43
|
+
position: absolute;
|
|
44
|
+
top: 0;
|
|
45
|
+
bottom: 0;
|
|
46
|
+
left: 0;
|
|
47
|
+
right: 0;
|
|
48
|
+
width: 30px;
|
|
49
|
+
height: 30px;
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
justify-content: center;
|
|
53
|
+
opacity: 0;
|
|
54
|
+
pointer-events: none;
|
|
55
|
+
transition: opacity 0.3s;
|
|
56
|
+
|
|
57
|
+
${IconBox} {
|
|
58
|
+
background-color: ${theme.color.light[300]};
|
|
59
|
+
border-radius: 50%;
|
|
60
|
+
width: 16px;
|
|
61
|
+
height: 16px;
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&.visible {
|
|
68
|
+
opacity: 0.6;
|
|
69
|
+
pointer-events: auto;
|
|
70
|
+
|
|
71
|
+
&:hover {
|
|
72
|
+
opacity: 1;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.scroll-to-left {
|
|
78
|
+
right: unset;
|
|
79
|
+
height: unset;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.scroll-to-right {
|
|
83
|
+
left: unset;
|
|
84
|
+
height: unset;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.scroll-to-top {
|
|
88
|
+
bottom: unset;
|
|
89
|
+
width: unset;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.scroll-to-bottom {
|
|
93
|
+
top: unset;
|
|
94
|
+
width: unset;
|
|
95
|
+
}
|
|
96
|
+
`
|
|
97
|
+
|
|
98
|
+
const SCROLL_INTERVAL_MS = 20
|
|
99
|
+
const SCROLL_PX = 4
|
|
100
|
+
|
|
101
|
+
export const FadingOverflow = (
|
|
102
|
+
{ children, scroll = 'none', sides, enableHorizontalScrollWithVerticalWheel, className, ...props }: Props,
|
|
103
|
+
) => {
|
|
104
|
+
const ref = useRef<HTMLDivElement>(null)
|
|
105
|
+
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
if (!ref.current) return
|
|
108
|
+
const element = ref.current
|
|
109
|
+
const fadeTop = !sides || sides.includes('top')
|
|
110
|
+
const fadeRight = !sides || sides.includes('right')
|
|
111
|
+
const fadeBottom = !sides || sides.includes('bottom')
|
|
112
|
+
const fadeLeft = !sides || sides.includes('left')
|
|
113
|
+
let intervalId: number | undefined
|
|
114
|
+
const overflow = scroll === 'none' ? 'clip' : 'auto'
|
|
115
|
+
element.style.overflowX = (fadeLeft || fadeRight) ? overflow : ''
|
|
116
|
+
element.style.overflowY = (fadeTop || fadeBottom) ? overflow : ''
|
|
117
|
+
if (scroll === 'arrows' || scroll === 'wheel') element.classList.add('hidden-scroll-bars')
|
|
118
|
+
|
|
119
|
+
function stopScrolling() {
|
|
120
|
+
clearInterval(intervalId)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function checkOverflow() {
|
|
124
|
+
// masking (fading)
|
|
125
|
+
const overflowsRight = element.clientWidth < element.scrollWidth && element.scrollLeft < (element.scrollWidth - element.clientWidth)
|
|
126
|
+
const overflowsLeft = element.scrollLeft > 0
|
|
127
|
+
const overflowsTop = element.clientHeight < element.scrollHeight && element.scrollTop < (element.scrollHeight - element.clientHeight)
|
|
128
|
+
const overflowsBottom = element.scrollTop > 0
|
|
129
|
+
const masksToApply: string[] = []
|
|
130
|
+
if (overflowsLeft && fadeLeft && overflowsRight && fadeRight) masksToApply.push(masks.horizontal)
|
|
131
|
+
else {
|
|
132
|
+
if (overflowsRight && fadeRight) masksToApply.push(masks.right)
|
|
133
|
+
if (overflowsLeft && fadeLeft) masksToApply.push(masks.left)
|
|
134
|
+
}
|
|
135
|
+
if (overflowsTop && fadeTop && overflowsBottom && fadeBottom) masksToApply.push(masks.vertical)
|
|
136
|
+
else {
|
|
137
|
+
if (overflowsTop && fadeTop) masksToApply.push(masks.top)
|
|
138
|
+
if (overflowsBottom && fadeBottom) masksToApply.push(masks.bottom)
|
|
139
|
+
}
|
|
140
|
+
element.style.maskImage = masksToApply.join(', ')
|
|
141
|
+
|
|
142
|
+
// arrow buttons
|
|
143
|
+
if (scroll !== 'arrows') return
|
|
144
|
+
|
|
145
|
+
function startScrolling(side: Side) {
|
|
146
|
+
stopScrolling()
|
|
147
|
+
const direction = side === 'bottom' || side === 'top' ? 'scrollTop' : 'scrollLeft'
|
|
148
|
+
const multiplier = side === 'bottom' || side === 'right' ? 1 : -1
|
|
149
|
+
intervalId = window.setInterval(() => {
|
|
150
|
+
element[direction] += SCROLL_PX * multiplier
|
|
151
|
+
}, SCROLL_INTERVAL_MS)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const startScrollingBySide = {
|
|
155
|
+
left: () => startScrolling('left'),
|
|
156
|
+
right: () => startScrolling('right'),
|
|
157
|
+
top: () => startScrolling('top'),
|
|
158
|
+
bottom: () => startScrolling('bottom'),
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const scrollToMaxBySide = {
|
|
162
|
+
left: () => element.scrollLeft = 0,
|
|
163
|
+
right: () => element.scrollLeft = element.scrollWidth - element.clientWidth,
|
|
164
|
+
top: () => element.scrollTop = 0,
|
|
165
|
+
bottom: () => element.scrollTop = element.scrollHeight - element.clientHeight,
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function enableArrowButton(side: Side) {
|
|
169
|
+
const button = element.parentNode?.querySelector(`.scroll-to-${side}`)
|
|
170
|
+
if (button?.classList.contains('visible')) return
|
|
171
|
+
button?.classList.add('visible')
|
|
172
|
+
button?.addEventListener('mouseenter', startScrollingBySide[side])
|
|
173
|
+
button?.addEventListener('mouseleave', stopScrolling)
|
|
174
|
+
button?.addEventListener('click', scrollToMaxBySide[side])
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function disableArrowButton(side: Side) {
|
|
178
|
+
const button = element.parentNode?.querySelector(`.scroll-to-${side}`)
|
|
179
|
+
if (!button?.classList.contains('visible')) return
|
|
180
|
+
button?.classList.remove('visible')
|
|
181
|
+
stopScrolling()
|
|
182
|
+
button?.removeEventListener('mouseenter', startScrollingBySide[side])
|
|
183
|
+
button?.removeEventListener('mouseleave', stopScrolling)
|
|
184
|
+
button?.removeEventListener('click', scrollToMaxBySide[side])
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (overflowsRight && fadeRight) enableArrowButton('right')
|
|
188
|
+
else disableArrowButton('right')
|
|
189
|
+
if (overflowsLeft && fadeLeft) enableArrowButton('left')
|
|
190
|
+
else disableArrowButton('left')
|
|
191
|
+
if (overflowsTop && fadeTop) enableArrowButton('top')
|
|
192
|
+
else disableArrowButton('top')
|
|
193
|
+
if (overflowsBottom && fadeBottom) enableArrowButton('bottom')
|
|
194
|
+
else disableArrowButton('bottom')
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const debouncedCheck = debounce(checkOverflow, MIN_CHECK_INTERVAL_MS)
|
|
198
|
+
const resizeObserver = new ResizeObserver(debouncedCheck)
|
|
199
|
+
resizeObserver.observe(element)
|
|
200
|
+
element.addEventListener('scroll', debouncedCheck)
|
|
201
|
+
|
|
202
|
+
return () => {
|
|
203
|
+
stopScrolling()
|
|
204
|
+
resizeObserver.disconnect()
|
|
205
|
+
element.removeEventListener('scroll', debouncedCheck)
|
|
206
|
+
}
|
|
207
|
+
}, [sides, ref.current, scroll])
|
|
208
|
+
|
|
209
|
+
useEffect(() => {
|
|
210
|
+
if (!enableHorizontalScrollWithVerticalWheel || !ref.current) return
|
|
211
|
+
const element = ref.current
|
|
212
|
+
|
|
213
|
+
function scrollWithWheel(event: WheelEvent) {
|
|
214
|
+
if (event.deltaY) {
|
|
215
|
+
element.scrollLeft += event.deltaY
|
|
216
|
+
event.preventDefault()
|
|
217
|
+
event.stopPropagation()
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
element.addEventListener('wheel', scrollWithWheel)
|
|
222
|
+
return () => element.removeEventListener('wheel', scrollWithWheel)
|
|
223
|
+
}, [ref.current, enableHorizontalScrollWithVerticalWheel])
|
|
224
|
+
|
|
225
|
+
return scroll === 'arrows' ? (
|
|
226
|
+
<OverflowBox {...props} className={listToClass(['scroll-arrows', className])}>
|
|
227
|
+
<div className="content" ref={ref}>{children}</div>
|
|
228
|
+
<div className="scroll-to-left" aria-hidden><IconBox size="xs"><ChevronLeft /></IconBox></div>
|
|
229
|
+
<div className="scroll-to-right" aria-hidden><IconBox size="xs"><ChevronRight /></IconBox></div>
|
|
230
|
+
<div className="scroll-to-top" aria-hidden><IconBox size="xs"><ChevronUp /></IconBox></div>
|
|
231
|
+
<div className="scroll-to-bottom" aria-hidden><IconBox size="xs"><ChevronDown /></IconBox></div>
|
|
232
|
+
</OverflowBox>
|
|
233
|
+
) : <OverflowBox {...props} className={className} ref={ref}>{children}</OverflowBox>
|
|
234
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ErrorDescription, ErrorFeedback } from '@stack-spot/portal-components/error'
|
|
2
|
+
import { StackspotAPIError } from '@stack-spot/portal-network'
|
|
3
|
+
import { Component } from 'react'
|
|
4
|
+
|
|
5
|
+
interface State extends ErrorDescription {
|
|
6
|
+
hasError: boolean,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
children: React.ReactNode,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* An Error Boundary that renders an ErrorFeedback instead of its content if any of its children throws.
|
|
15
|
+
*
|
|
16
|
+
* To customize what properties are passed to the ErrorFeedback component, setup an error descriptor for the ErrorManager class. If you're
|
|
17
|
+
* using the component `Layout` or `RawLayout`, you can use the property `errorDescriptor`.
|
|
18
|
+
*
|
|
19
|
+
* To run an error handler every time an error is catch by this boundary, setup an error handler for the ErrorManager class. If you're
|
|
20
|
+
* using the component `Layout` or `RawLayout`, you can use the property `onError`.
|
|
21
|
+
*/
|
|
22
|
+
export class ErrorBoundary extends Component<Props, State> {
|
|
23
|
+
constructor(props: Props) {
|
|
24
|
+
super(props)
|
|
25
|
+
this.state = { hasError: false }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static getDerivedStateFromError(error: any) {
|
|
29
|
+
const message = error instanceof StackspotAPIError ? error.translate() : (error.message ?? `${error}`)
|
|
30
|
+
const code = error instanceof StackspotAPIError ? error.status : undefined
|
|
31
|
+
return { hasError: true, message, code }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
componentDidCatch(error: any, errorInfo: any) {
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.error(error, errorInfo)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
componentDidUpdate(prevProps: Readonly<Props>) {
|
|
40
|
+
if (this.props.children !== prevProps.children) this.setState({ hasError: false })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
render() {
|
|
44
|
+
return this.state.hasError
|
|
45
|
+
? <ErrorFeedback code={this.state.code} message={this.state.message} />
|
|
46
|
+
: this.props.children
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LoadingCircular } from '@citric/ui'
|
|
2
|
+
import styled from 'styled-components'
|
|
3
|
+
|
|
4
|
+
const LoadingBox = styled.div`
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
`
|
|
11
|
+
|
|
12
|
+
export const Loading = () => (
|
|
13
|
+
<LoadingBox><LoadingCircular /></LoadingBox>
|
|
14
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Suspense } from 'react'
|
|
2
|
+
import { WithChildren } from '../../types'
|
|
3
|
+
import { ErrorBoundary } from './ErrorBoundary'
|
|
4
|
+
import { Loading } from './Loading'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Fallbacks for errors and loadings (suspense).
|
|
8
|
+
*/
|
|
9
|
+
export const FallbackBoundary = ({ children }: WithChildren) => (
|
|
10
|
+
<ErrorBoundary>
|
|
11
|
+
<Suspense fallback={<Loading />}>
|
|
12
|
+
{children}
|
|
13
|
+
</Suspense>
|
|
14
|
+
</ErrorBoundary>
|
|
15
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/* eslint-disable no-empty-pattern */
|
|
2
|
+
import { WithStyle } from '@stack-spot/portal-theme'
|
|
3
|
+
import { ButtonAction } from '../types'
|
|
4
|
+
|
|
5
|
+
interface Props<T> extends WithStyle {
|
|
6
|
+
items: T[],
|
|
7
|
+
renderLabel: (item: T) => React.ReactElement,
|
|
8
|
+
getDate: (item: T) => Date,
|
|
9
|
+
keygen: (item: T) => React.Key,
|
|
10
|
+
getActions?: (item: T) => ButtonAction[],
|
|
11
|
+
onSelect?: (item: T) => void,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function HistoryList<T>({}: Props<T>) {
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { IconBox } from '@citric/core'
|
|
2
|
+
import { listToClass, theme } from '@stack-spot/portal-theme'
|
|
3
|
+
import { useMemo, useState } from 'react'
|
|
4
|
+
import { styled } from 'styled-components'
|
|
5
|
+
|
|
6
|
+
interface Props extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> {
|
|
7
|
+
icon: React.ReactElement,
|
|
8
|
+
onChange?: (value: string) => void,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const InputBox = styled.div`
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: row;
|
|
14
|
+
transition: border-color 0.3s, box-shadow 0.3s;
|
|
15
|
+
border: 1px solid ${theme.color.light[600]};
|
|
16
|
+
border-radius: 0.25rem;
|
|
17
|
+
background-color: ${theme.color.light[300]};
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
flex-shrink: 0;
|
|
20
|
+
|
|
21
|
+
&.focused {
|
|
22
|
+
border-color: ${theme.color.primary[500]};
|
|
23
|
+
box-shadow: 0 0 0 1px ${theme.color.primary[500]};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&.disabled {
|
|
27
|
+
background-color: ${theme.color.light[500]};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
${IconBox} {
|
|
31
|
+
width: 40px;
|
|
32
|
+
height: 40px;
|
|
33
|
+
border-radius: 0;
|
|
34
|
+
background-color: ${theme.color.light[600]};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
input {
|
|
38
|
+
padding: 8px;
|
|
39
|
+
border: none;
|
|
40
|
+
background-color: transparent;
|
|
41
|
+
flex: 1;
|
|
42
|
+
color: ${theme.color.light.contrastText};
|
|
43
|
+
|
|
44
|
+
&:focus {
|
|
45
|
+
outline: none;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
`
|
|
49
|
+
|
|
50
|
+
export const IconInput = ({ icon, onChange, style, className, disabled, onFocus, onBlur, ...props }: Props) => {
|
|
51
|
+
const [focused, setFocused] = useState(false)
|
|
52
|
+
|
|
53
|
+
const { focus, blur } = useMemo(() => ({
|
|
54
|
+
focus: (e: React.FocusEvent<HTMLInputElement, Element>) => {
|
|
55
|
+
setFocused(true)
|
|
56
|
+
onFocus?.(e)
|
|
57
|
+
},
|
|
58
|
+
blur: (e: React.FocusEvent<HTMLInputElement, Element>) => {
|
|
59
|
+
setFocused(false)
|
|
60
|
+
onBlur?.(e)
|
|
61
|
+
},
|
|
62
|
+
}), [])
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<InputBox style={style} className={listToClass([className, focused && !disabled && 'focused', disabled && 'disabled'])}>
|
|
66
|
+
<IconBox>{icon}</IconBox>
|
|
67
|
+
<input {...props} disabled={disabled} onFocus={focus} onBlur={blur} onChange={e => onChange?.(e.target.value)} />
|
|
68
|
+
</InputBox>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copied from the extension's webview.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Children, Fragment } from 'react'
|
|
6
|
+
import ReactMarkdown from 'react-markdown'
|
|
7
|
+
import remarkGfm from 'remark-gfm'
|
|
8
|
+
import { WithChildren } from '../types'
|
|
9
|
+
import { Code, Props as CodeProps } from './Code'
|
|
10
|
+
|
|
11
|
+
type Props = Omit<CodeProps, 'language'> & WithChildren<string>
|
|
12
|
+
|
|
13
|
+
const renderP = (child: any, key: number) => (
|
|
14
|
+
<Fragment key={key}>
|
|
15
|
+
{typeof child === 'string'
|
|
16
|
+
? child.split('\n').map((content, subKey, array) => (
|
|
17
|
+
<Fragment key={subKey}>
|
|
18
|
+
{content}
|
|
19
|
+
{subKey < array.length - 1 ? <br /> : null}
|
|
20
|
+
</Fragment>
|
|
21
|
+
)) : child}
|
|
22
|
+
</Fragment>
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
export const Markdown = (
|
|
26
|
+
{
|
|
27
|
+
onInsertCode,
|
|
28
|
+
onNewFile,
|
|
29
|
+
onCopyCode,
|
|
30
|
+
children,
|
|
31
|
+
}: Props,
|
|
32
|
+
) => (
|
|
33
|
+
<>
|
|
34
|
+
<ReactMarkdown
|
|
35
|
+
remarkPlugins={[[remarkGfm]]}
|
|
36
|
+
components={{
|
|
37
|
+
a: props => <a target="_blank" rel="noopener noreferrer" {...props} />,
|
|
38
|
+
code: props =>
|
|
39
|
+
<Code
|
|
40
|
+
{...props}
|
|
41
|
+
onInsertCode={onInsertCode}
|
|
42
|
+
onNewFile={onNewFile}
|
|
43
|
+
onCopyCode={onCopyCode}
|
|
44
|
+
showActionBar
|
|
45
|
+
/>,
|
|
46
|
+
pre: ({ children }) => <>{children}</>,
|
|
47
|
+
p: ({ children }) => <p>{Children.map(children, renderP)}</p>,
|
|
48
|
+
}}
|
|
49
|
+
>
|
|
50
|
+
{children}
|
|
51
|
+
</ReactMarkdown>
|
|
52
|
+
</>
|
|
53
|
+
)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/* eslint-disable no-empty-pattern */
|
|
2
|
+
import { WithStyle } from '@stack-spot/portal-theme'
|
|
3
|
+
import { ButtonAction, WithChildren } from '../types'
|
|
4
|
+
|
|
5
|
+
interface Props extends WithStyle, WithChildren {
|
|
6
|
+
position?: 'left' | 'top' | 'bottom' | 'right',
|
|
7
|
+
actions: ButtonAction[],
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const OverlayMenu = ({}: Props) => null
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { listToClass, theme, WithStyle } from '@stack-spot/portal-theme'
|
|
2
|
+
import { styled } from 'styled-components'
|
|
3
|
+
|
|
4
|
+
interface Props extends WithStyle {
|
|
5
|
+
visible?: boolean,
|
|
6
|
+
shimmer?: boolean,
|
|
7
|
+
foregroundColor?: string | string[],
|
|
8
|
+
backgroundColor?: string | string[],
|
|
9
|
+
shimmerColor?: string | string[],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function gradientFromColorArray(colors: string[]) {
|
|
13
|
+
if (colors.length === 1) return colors[0]
|
|
14
|
+
const step = 100 / (colors.length - 1)
|
|
15
|
+
const partials: string[] = []
|
|
16
|
+
let current = 0
|
|
17
|
+
for (const color of colors) {
|
|
18
|
+
partials.push(`${color} ${Math.ceil(current)}%`)
|
|
19
|
+
current += step
|
|
20
|
+
}
|
|
21
|
+
return `linear-gradient(to right, ${partials.join(', ')})`
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const SHIMMER_PADDING = '10px'
|
|
25
|
+
|
|
26
|
+
const Styled = styled.div<{ $bg: string[], $fg: string[], $shimmer: string[] }>`
|
|
27
|
+
margin: 7px 0;
|
|
28
|
+
opacity: 0;
|
|
29
|
+
transition: opacity 0.5s;
|
|
30
|
+
|
|
31
|
+
&.visible {
|
|
32
|
+
opacity: 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.shimmer {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
height: 10px;
|
|
40
|
+
position: relative;
|
|
41
|
+
padding: 0 ${SHIMMER_PADDING};
|
|
42
|
+
margin: 3px 0;
|
|
43
|
+
|
|
44
|
+
.progress-glow {
|
|
45
|
+
filter: blur(2px);
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: 0;
|
|
48
|
+
left: ${SHIMMER_PADDING};
|
|
49
|
+
bottom: 0;
|
|
50
|
+
right: ${SHIMMER_PADDING};
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
justify-content: center;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
|
|
56
|
+
&::before {
|
|
57
|
+
content: '';
|
|
58
|
+
height: 3px;
|
|
59
|
+
display: block;
|
|
60
|
+
width: 33%;
|
|
61
|
+
display: block;
|
|
62
|
+
animation: slide 3s infinite forwards;
|
|
63
|
+
background: ${({ $fg }) => gradientFromColorArray($fg)};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.colors {
|
|
68
|
+
position: absolute;
|
|
69
|
+
top: 0;
|
|
70
|
+
bottom: 0;
|
|
71
|
+
left: 0;
|
|
72
|
+
right: 0;
|
|
73
|
+
overflow: hidden;
|
|
74
|
+
filter: blur(10px);
|
|
75
|
+
|
|
76
|
+
${({ $shimmer }) => `
|
|
77
|
+
&:before {
|
|
78
|
+
content: '';
|
|
79
|
+
position: absolute;
|
|
80
|
+
top: 0;
|
|
81
|
+
bottom: 0;
|
|
82
|
+
width: ${$shimmer.length * 100}%;
|
|
83
|
+
background: ${gradientFromColorArray($shimmer)};
|
|
84
|
+
${$shimmer.length > 2 ? `animation: shimmer-slide ${$shimmer.length}s ease-in infinite alternate;` : ''}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@keyframes shimmer-slide {
|
|
88
|
+
from {
|
|
89
|
+
left: 0;
|
|
90
|
+
}
|
|
91
|
+
to {
|
|
92
|
+
left: -${($shimmer.length - 1) * 100}%;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.progress-bar {
|
|
100
|
+
height: 2px;
|
|
101
|
+
width: 100%;
|
|
102
|
+
background: ${({ $bg }) => gradientFromColorArray($bg)};
|
|
103
|
+
position: relative;
|
|
104
|
+
overflow-x: clip;
|
|
105
|
+
|
|
106
|
+
&:before {
|
|
107
|
+
content: '';
|
|
108
|
+
display: block;
|
|
109
|
+
width: 33%;
|
|
110
|
+
height: 100%;
|
|
111
|
+
background: ${({ $fg }) => gradientFromColorArray($fg)};
|
|
112
|
+
animation: slide 3s infinite forwards;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@keyframes slide {
|
|
116
|
+
from {
|
|
117
|
+
margin-left: -33%;
|
|
118
|
+
}
|
|
119
|
+
to {
|
|
120
|
+
margin-left: 100%;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
`
|
|
125
|
+
|
|
126
|
+
export const ProgressBar = ({
|
|
127
|
+
visible = true,
|
|
128
|
+
shimmer,
|
|
129
|
+
backgroundColor = shimmer ? 'rgba(255, 255, 255, 0.4)' : theme.color.light[500],
|
|
130
|
+
foregroundColor = shimmer ? ['#FFF0', '#FFF', '#FFF0'] : theme.color.primary[500],
|
|
131
|
+
shimmerColor = ['#ff6633', '#d668cd', '#ff6633', '#FFF8', '#299cf4'],
|
|
132
|
+
className,
|
|
133
|
+
style,
|
|
134
|
+
}: Props) => {
|
|
135
|
+
const $bg = Array.isArray(backgroundColor) ? backgroundColor : [backgroundColor]
|
|
136
|
+
const $fg = Array.isArray(foregroundColor) ? foregroundColor : [...$bg, foregroundColor, ...$bg]
|
|
137
|
+
const $shimmer = Array.isArray(shimmerColor) ? shimmerColor : [shimmerColor]
|
|
138
|
+
const progress = <div className="progress-bar"></div>
|
|
139
|
+
const result = shimmer
|
|
140
|
+
? (
|
|
141
|
+
<div className="shimmer">
|
|
142
|
+
<div className="colors"></div>
|
|
143
|
+
<div className="progress-glow"></div>
|
|
144
|
+
{progress}
|
|
145
|
+
</div>
|
|
146
|
+
)
|
|
147
|
+
: progress
|
|
148
|
+
return (
|
|
149
|
+
<Styled className={listToClass([className, visible && 'visible'])} style={style} $fg={$fg} $bg={$bg} $shimmer={$shimmer}>
|
|
150
|
+
{result}
|
|
151
|
+
</Styled>
|
|
152
|
+
)
|
|
153
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { IconBox, Text } from '@citric/core'
|
|
2
|
+
import { theme, WithStyle } from '@stack-spot/portal-theme'
|
|
3
|
+
import { styled } from 'styled-components'
|
|
4
|
+
import { ButtonAction } from '../types'
|
|
5
|
+
|
|
6
|
+
interface Props extends ButtonAction, WithStyle {
|
|
7
|
+
background?: string,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const QuickButton = styled.button<{ $color?: string, $bg?: string }>`
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
padding: 12px;
|
|
14
|
+
gap: 12px;
|
|
15
|
+
background-color: ${theme.color.light[500]};
|
|
16
|
+
border: none;
|
|
17
|
+
color: inherit;
|
|
18
|
+
flex: 1;
|
|
19
|
+
border-radius: 4px;
|
|
20
|
+
border: 2px solid;
|
|
21
|
+
border-color: ${theme.color.light[500]};
|
|
22
|
+
transition: border-color 0.3s;
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
text-align: left;
|
|
25
|
+
|
|
26
|
+
&:hover {
|
|
27
|
+
border-color: ${theme.color.light[600]};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
i {
|
|
31
|
+
border-radius: 2px;
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
background-color: ${({ $bg }) => $bg || 'transparent'};
|
|
36
|
+
${({ $color }) => $color
|
|
37
|
+
? `
|
|
38
|
+
svg {
|
|
39
|
+
fill: ${$color};
|
|
40
|
+
}`
|
|
41
|
+
: ''
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
`
|
|
45
|
+
|
|
46
|
+
export const QuickStartButton = ({ label, onClick, background, className, color, icon, style }: Props) => (
|
|
47
|
+
<QuickButton className={className} style={style} onClick={onClick} $color={color} $bg={background}>
|
|
48
|
+
<IconBox aria-hidden>{icon}</IconBox>
|
|
49
|
+
<Text>{label}</Text>
|
|
50
|
+
</QuickButton>
|
|
51
|
+
)
|