@grackle-ai/web-components 0.107.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rush/temp/3ae72563f781afd72723475938136f113846603e.untar.log +10 -0
- package/.rush/temp/bc1d5bf9201ce71abeaeaddd096deb9b0805d703.untar.log +10 -0
- package/.rush/temp/operation/_phase_build/all.log +18 -0
- package/.rush/temp/operation/_phase_build/log-chunks.jsonl +18 -0
- package/.rush/temp/operation/_phase_build/state.json +3 -0
- package/.rush/temp/operation/_phase_test/all.log +121 -0
- package/.rush/temp/operation/_phase_test/log-chunks.jsonl +121 -0
- package/.rush/temp/operation/_phase_test/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +938 -0
- package/.storybook/main.ts +22 -0
- package/.storybook/preview.tsx +30 -0
- package/config/rig.json +4 -0
- package/config/rush-project.json +12 -0
- package/dist/index.css +1 -0
- package/dist/index.js +39221 -0
- package/eslint.config.cjs +5 -0
- package/package.json +83 -0
- package/rush-logs/web-components._phase_build.cache.log +4 -0
- package/rush-logs/web-components._phase_test.cache.log +4 -0
- package/src/components/chat/ChatInput.module.scss +81 -0
- package/src/components/chat/ChatInput.stories.tsx +91 -0
- package/src/components/chat/ChatInput.tsx +168 -0
- package/src/components/chat/index.ts +6 -0
- package/src/components/dag/DagView.module.scss +149 -0
- package/src/components/dag/DagView.stories.tsx +125 -0
- package/src/components/dag/DagView.tsx +109 -0
- package/src/components/dag/TaskNode.stories.tsx +133 -0
- package/src/components/dag/TaskNode.tsx +40 -0
- package/src/components/dag/useDagLayout.ts +139 -0
- package/src/components/display/Breadcrumbs.module.scss +71 -0
- package/src/components/display/Breadcrumbs.stories.tsx +80 -0
- package/src/components/display/Breadcrumbs.tsx +46 -0
- package/src/components/display/Button.module.scss +110 -0
- package/src/components/display/Button.stories.tsx +88 -0
- package/src/components/display/Button.tsx +40 -0
- package/src/components/display/ConfirmDialog.module.scss +67 -0
- package/src/components/display/ConfirmDialog.stories.tsx +81 -0
- package/src/components/display/ConfirmDialog.tsx +88 -0
- package/src/components/display/CopyButton.module.scss +41 -0
- package/src/components/display/CopyButton.stories.tsx +78 -0
- package/src/components/display/CopyButton.tsx +64 -0
- package/src/components/display/DemoBanner.module.scss +37 -0
- package/src/components/display/DemoBanner.stories.tsx +40 -0
- package/src/components/display/DemoBanner.tsx +23 -0
- package/src/components/display/EventHoverRow.module.scss +102 -0
- package/src/components/display/EventHoverRow.stories.tsx +99 -0
- package/src/components/display/EventHoverRow.tsx +154 -0
- package/src/components/display/EventRenderer.module.scss +272 -0
- package/src/components/display/EventRenderer.stories.tsx +186 -0
- package/src/components/display/EventRenderer.tsx +271 -0
- package/src/components/display/EventStream.module.scss +93 -0
- package/src/components/display/EventStream.stories.tsx +249 -0
- package/src/components/display/EventStream.tsx +369 -0
- package/src/components/display/FloatingActionBar.module.scss +107 -0
- package/src/components/display/FloatingActionBar.stories.tsx +122 -0
- package/src/components/display/FloatingActionBar.tsx +119 -0
- package/src/components/display/SessionAttemptSelector.module.scss +50 -0
- package/src/components/display/SessionAttemptSelector.stories.tsx +78 -0
- package/src/components/display/SessionAttemptSelector.tsx +49 -0
- package/src/components/display/SessionPicker.module.scss +200 -0
- package/src/components/display/SessionPicker.stories.tsx +169 -0
- package/src/components/display/SessionPicker.tsx +214 -0
- package/src/components/display/Skeleton.module.scss +58 -0
- package/src/components/display/Skeleton.stories.tsx +94 -0
- package/src/components/display/Skeleton.tsx +127 -0
- package/src/components/display/Spinner.module.scss +41 -0
- package/src/components/display/Spinner.stories.tsx +66 -0
- package/src/components/display/Spinner.tsx +32 -0
- package/src/components/display/SplashScreen.module.scss +20 -0
- package/src/components/display/SplashScreen.stories.tsx +26 -0
- package/src/components/display/SplashScreen.tsx +16 -0
- package/src/components/display/SplitButton.module.scss +166 -0
- package/src/components/display/SplitButton.stories.tsx +95 -0
- package/src/components/display/SplitButton.tsx +128 -0
- package/src/components/display/Tooltip.module.scss +84 -0
- package/src/components/display/Tooltip.stories.tsx +240 -0
- package/src/components/display/Tooltip.tsx +184 -0
- package/src/components/display/extractText.test.tsx +48 -0
- package/src/components/display/index.ts +20 -0
- package/src/components/editable/EditableCheckbox.stories.tsx +54 -0
- package/src/components/editable/EditableCheckbox.tsx +39 -0
- package/src/components/editable/EditableField.module.scss +135 -0
- package/src/components/editable/EditableSelect.tsx +164 -0
- package/src/components/editable/EditableTextArea.stories.tsx +50 -0
- package/src/components/editable/EditableTextArea.tsx +148 -0
- package/src/components/editable/EditableTextField.stories.tsx +62 -0
- package/src/components/editable/EditableTextField.tsx +153 -0
- package/src/components/editable/EnvironmentSelect.module.scss +17 -0
- package/src/components/editable/EnvironmentSelect.stories.tsx +61 -0
- package/src/components/editable/EnvironmentSelect.tsx +87 -0
- package/src/components/editable/index.ts +13 -0
- package/src/components/editable/useEditableField.test.tsx +233 -0
- package/src/components/editable/useEditableField.ts +173 -0
- package/src/components/index.ts +20 -0
- package/src/components/knowledge/KnowledgeDetailPanel.module.scss +162 -0
- package/src/components/knowledge/KnowledgeDetailPanel.stories.tsx +208 -0
- package/src/components/knowledge/KnowledgeDetailPanel.tsx +122 -0
- package/src/components/knowledge/KnowledgeGraph.module.scss +110 -0
- package/src/components/knowledge/KnowledgeGraph.stories.tsx +180 -0
- package/src/components/knowledge/KnowledgeGraph.tsx +455 -0
- package/src/components/knowledge/KnowledgeNav.module.scss +130 -0
- package/src/components/knowledge/KnowledgeNav.stories.tsx +108 -0
- package/src/components/knowledge/KnowledgeNav.tsx +138 -0
- package/src/components/knowledge/index.ts +3 -0
- package/src/components/layout/AppNav.module.scss +82 -0
- package/src/components/layout/AppNav.stories.tsx +115 -0
- package/src/components/layout/AppNav.tsx +133 -0
- package/src/components/layout/BottomStatusBar.module.scss +58 -0
- package/src/components/layout/BottomStatusBar.stories.tsx +35 -0
- package/src/components/layout/BottomStatusBar.tsx +206 -0
- package/src/components/layout/Sidebar.module.scss +60 -0
- package/src/components/layout/Sidebar.stories.tsx +46 -0
- package/src/components/layout/Sidebar.tsx +84 -0
- package/src/components/layout/StatusBar.module.scss +108 -0
- package/src/components/layout/StatusBar.stories.tsx +119 -0
- package/src/components/layout/StatusBar.tsx +70 -0
- package/src/components/layout/index.ts +9 -0
- package/src/components/lists/EnvironmentNav.module.scss +118 -0
- package/src/components/lists/EnvironmentNav.stories.tsx +121 -0
- package/src/components/lists/EnvironmentNav.tsx +133 -0
- package/src/components/lists/FindingsNav.module.scss +126 -0
- package/src/components/lists/FindingsNav.tsx +146 -0
- package/src/components/lists/TaskList.module.scss +206 -0
- package/src/components/lists/TaskList.stories.tsx +401 -0
- package/src/components/lists/TaskList.tsx +509 -0
- package/src/components/lists/index.ts +6 -0
- package/src/components/lists/listHelpers.tsx +130 -0
- package/src/components/notifications/Callout.module.scss +83 -0
- package/src/components/notifications/Callout.stories.tsx +81 -0
- package/src/components/notifications/Callout.tsx +64 -0
- package/src/components/notifications/Toast.module.scss +86 -0
- package/src/components/notifications/Toast.stories.tsx +71 -0
- package/src/components/notifications/Toast.tsx +51 -0
- package/src/components/notifications/ToastContainer.module.scss +23 -0
- package/src/components/notifications/ToastContainer.stories.tsx +66 -0
- package/src/components/notifications/ToastContainer.tsx +29 -0
- package/src/components/notifications/UpdateBanner.stories.tsx +77 -0
- package/src/components/notifications/UpdateBanner.test.tsx +64 -0
- package/src/components/notifications/UpdateBanner.tsx +44 -0
- package/src/components/notifications/index.ts +8 -0
- package/src/components/panels/AboutPanel.stories.tsx +70 -0
- package/src/components/panels/AboutPanel.tsx +66 -0
- package/src/components/panels/AppearancePanel.stories.tsx +45 -0
- package/src/components/panels/AppearancePanel.tsx +97 -0
- package/src/components/panels/CredentialProvidersPanel.stories.tsx +62 -0
- package/src/components/panels/CredentialProvidersPanel.tsx +111 -0
- package/src/components/panels/EnvironmentEditPanel.module.scss +170 -0
- package/src/components/panels/EnvironmentEditPanel.stories.tsx +206 -0
- package/src/components/panels/EnvironmentEditPanel.tsx +785 -0
- package/src/components/panels/FindingsPanel.module.scss +94 -0
- package/src/components/panels/FindingsPanel.stories.tsx +109 -0
- package/src/components/panels/FindingsPanel.tsx +76 -0
- package/src/components/panels/KeyboardShortcutsPanel.module.scss +65 -0
- package/src/components/panels/KeyboardShortcutsPanel.stories.tsx +40 -0
- package/src/components/panels/KeyboardShortcutsPanel.tsx +104 -0
- package/src/components/panels/PluginsPanel.tsx +77 -0
- package/src/components/panels/SettingsPanel.module.scss +336 -0
- package/src/components/panels/TaskActionButtons.module.scss +22 -0
- package/src/components/panels/TaskActionButtons.stories.tsx +125 -0
- package/src/components/panels/TaskActionButtons.tsx +87 -0
- package/src/components/panels/TaskEditPanel.module.scss +202 -0
- package/src/components/panels/TaskEditPanel.stories.tsx +75 -0
- package/src/components/panels/TaskEditPanel.tsx +328 -0
- package/src/components/panels/TaskOverviewPanel.module.scss +236 -0
- package/src/components/panels/TaskOverviewPanel.stories.tsx +219 -0
- package/src/components/panels/TaskOverviewPanel.tsx +270 -0
- package/src/components/panels/TokensPanel.stories.tsx +131 -0
- package/src/components/panels/TokensPanel.tsx +143 -0
- package/src/components/panels/WorkpadPanel.module.scss +39 -0
- package/src/components/panels/WorkpadPanel.stories.tsx +56 -0
- package/src/components/panels/WorkpadPanel.tsx +63 -0
- package/src/components/panels/index.ts +13 -0
- package/src/components/personas/McpToolSelector.module.scss +109 -0
- package/src/components/personas/McpToolSelector.stories.tsx +129 -0
- package/src/components/personas/McpToolSelector.tsx +180 -0
- package/src/components/personas/PersonaManager.module.scss +233 -0
- package/src/components/personas/PersonaManager.stories.tsx +139 -0
- package/src/components/personas/PersonaManager.tsx +122 -0
- package/src/components/schedules/ScheduleManager.module.scss +98 -0
- package/src/components/schedules/ScheduleManager.stories.tsx +78 -0
- package/src/components/schedules/ScheduleManager.tsx +160 -0
- package/src/components/settings/SettingsNav.module.scss +82 -0
- package/src/components/settings/SettingsNav.stories.tsx +83 -0
- package/src/components/settings/SettingsNav.tsx +104 -0
- package/src/components/streams/StreamDetailPanel.module.scss +206 -0
- package/src/components/streams/StreamDetailPanel.stories.tsx +132 -0
- package/src/components/streams/StreamDetailPanel.tsx +119 -0
- package/src/components/streams/StreamList.module.scss +92 -0
- package/src/components/streams/StreamList.stories.tsx +99 -0
- package/src/components/streams/StreamList.tsx +114 -0
- package/src/components/streams/index.ts +10 -0
- package/src/components/tools/AgentToolCard.module.scss +118 -0
- package/src/components/tools/AgentToolCard.stories.tsx +304 -0
- package/src/components/tools/AgentToolCard.tsx +247 -0
- package/src/components/tools/FileEditCard.stories.tsx +138 -0
- package/src/components/tools/FileEditCard.tsx +160 -0
- package/src/components/tools/FileReadCard.stories.tsx +120 -0
- package/src/components/tools/FileReadCard.tsx +106 -0
- package/src/components/tools/FindingCard.stories.tsx +124 -0
- package/src/components/tools/FindingCard.tsx +178 -0
- package/src/components/tools/GenericToolCard.stories.tsx +80 -0
- package/src/components/tools/GenericToolCard.tsx +111 -0
- package/src/components/tools/IpcCard.stories.tsx +129 -0
- package/src/components/tools/IpcCard.tsx +178 -0
- package/src/components/tools/KnowledgeCard.stories.tsx +112 -0
- package/src/components/tools/KnowledgeCard.tsx +165 -0
- package/src/components/tools/MetadataCard.stories.tsx +32 -0
- package/src/components/tools/MetadataCard.tsx +39 -0
- package/src/components/tools/SearchCard.stories.tsx +74 -0
- package/src/components/tools/SearchCard.tsx +86 -0
- package/src/components/tools/ShellCard.stories.tsx +112 -0
- package/src/components/tools/ShellCard.tsx +106 -0
- package/src/components/tools/TaskCard.stories.tsx +123 -0
- package/src/components/tools/TaskCard.tsx +203 -0
- package/src/components/tools/TodoCard.module.scss +131 -0
- package/src/components/tools/TodoCard.stories.tsx +202 -0
- package/src/components/tools/TodoCard.tsx +200 -0
- package/src/components/tools/ToolCard.stories.tsx +177 -0
- package/src/components/tools/ToolCard.tsx +60 -0
- package/src/components/tools/ToolCardProps.ts +20 -0
- package/src/components/tools/ToolSearchCard.stories.tsx +81 -0
- package/src/components/tools/ToolSearchCard.tsx +86 -0
- package/src/components/tools/WorkpadCard.stories.tsx +106 -0
- package/src/components/tools/WorkpadCard.tsx +125 -0
- package/src/components/tools/classifyTool.test.ts +44 -0
- package/src/components/tools/classifyTool.ts +134 -0
- package/src/components/tools/parseDiff.ts +95 -0
- package/src/components/tools/parseShellOutput.ts +28 -0
- package/src/components/tools/toolCardHelpers.test.ts +53 -0
- package/src/components/tools/toolCards.module.scss +234 -0
- package/src/components/workspace/WorkspaceBoard.module.scss +238 -0
- package/src/components/workspace/WorkspaceBoard.stories.tsx +240 -0
- package/src/components/workspace/WorkspaceBoard.tsx +232 -0
- package/src/components/workspace/WorkspaceFormFields.module.scss +79 -0
- package/src/components/workspace/WorkspaceFormFields.stories.tsx +133 -0
- package/src/components/workspace/WorkspaceFormFields.tsx +185 -0
- package/src/context/GrackleContext.ts +28 -0
- package/src/context/GrackleContextTypes.ts +64 -0
- package/src/context/SidebarContext.tsx +53 -0
- package/src/context/ThemeContext.tsx +21 -0
- package/src/context/ToastContext.tsx +56 -0
- package/src/hooks/types.ts +864 -0
- package/src/hooks/useEventSelection.test.ts +204 -0
- package/src/hooks/useEventSelection.ts +158 -0
- package/src/hooks/useSmartScroll.ts +151 -0
- package/src/hooks/useTheme.ts +228 -0
- package/src/index.ts +210 -0
- package/src/mocks/MockGrackleProvider.tsx +1397 -0
- package/src/mocks/mockData.ts +1966 -0
- package/src/mocks/mockKnowledgeData.ts +294 -0
- package/src/scss.d.ts +12 -0
- package/src/styles/global.scss +244 -0
- package/src/styles/mixins.scss +278 -0
- package/src/styles/prism-theme.scss +148 -0
- package/src/styles/theme.scss +1102 -0
- package/src/test-utils/storybook-decorators.tsx +50 -0
- package/src/test-utils/storybook-helpers.ts +262 -0
- package/src/themes.ts +142 -0
- package/src/utils/boardColumns.ts +141 -0
- package/src/utils/breadcrumbs.test.ts +285 -0
- package/src/utils/breadcrumbs.ts +222 -0
- package/src/utils/dashboard.test.ts +156 -0
- package/src/utils/dashboard.ts +195 -0
- package/src/utils/eventContent.test.ts +353 -0
- package/src/utils/eventContent.ts +209 -0
- package/src/utils/findingCategory.ts +33 -0
- package/src/utils/format.ts +27 -0
- package/src/utils/iconSize.ts +18 -0
- package/src/utils/navigation.ts +205 -0
- package/src/utils/route-config.test.ts +128 -0
- package/src/utils/scrollUtils.test.ts +65 -0
- package/src/utils/scrollUtils.ts +49 -0
- package/src/utils/sessionEvents.test.ts +302 -0
- package/src/utils/sessionEvents.ts +233 -0
- package/src/utils/taskStatus.tsx +137 -0
- package/src/utils/time.ts +92 -0
- package/tsconfig.json +8 -0
- package/vite.config.ts +20 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
@use '../../styles/mixins' as *;
|
|
2
|
+
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Environment Edit Panel — full-panel create/edit form for environments
|
|
5
|
+
// =============================================================================
|
|
6
|
+
|
|
7
|
+
.container {
|
|
8
|
+
flex: 1;
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Header
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
.header {
|
|
19
|
+
@include surface-panel;
|
|
20
|
+
padding: var(--space-sm) var(--space-md);
|
|
21
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
justify-content: space-between;
|
|
25
|
+
gap: var(--space-md);
|
|
26
|
+
flex-shrink: 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.headerTitle {
|
|
30
|
+
font-size: var(--font-size-sm);
|
|
31
|
+
color: var(--text-secondary);
|
|
32
|
+
font-family: var(--font-mono);
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
gap: var(--space-sm);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.badge {
|
|
39
|
+
background: var(--accent-green-dim);
|
|
40
|
+
color: var(--accent-green);
|
|
41
|
+
border: 1px solid var(--accent-green);
|
|
42
|
+
border-radius: var(--radius-full);
|
|
43
|
+
padding: 1px var(--space-sm);
|
|
44
|
+
font-size: var(--font-size-xs);
|
|
45
|
+
font-family: var(--font-mono);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.headerActions {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
gap: var(--space-sm);
|
|
52
|
+
flex-shrink: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Form body
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
.body {
|
|
60
|
+
flex: 1;
|
|
61
|
+
overflow: auto;
|
|
62
|
+
padding: var(--space-lg);
|
|
63
|
+
width: 100%;
|
|
64
|
+
|
|
65
|
+
@include mobile {
|
|
66
|
+
padding: var(--space-md);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.formContent {
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
gap: var(--space-lg);
|
|
74
|
+
max-width: 680px;
|
|
75
|
+
|
|
76
|
+
@include mobile {
|
|
77
|
+
max-width: 100%;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.section {
|
|
82
|
+
display: flex;
|
|
83
|
+
flex-direction: column;
|
|
84
|
+
gap: var(--space-sm);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.label {
|
|
88
|
+
font-size: 11px;
|
|
89
|
+
color: var(--text-tertiary);
|
|
90
|
+
text-transform: uppercase;
|
|
91
|
+
letter-spacing: 0.05em;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.nameInput {
|
|
95
|
+
@include input-field;
|
|
96
|
+
font-size: var(--font-size-lg);
|
|
97
|
+
font-weight: var(--font-weight-bold);
|
|
98
|
+
color: var(--text-primary);
|
|
99
|
+
padding: var(--space-sm) var(--space-md);
|
|
100
|
+
width: 100%;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.fieldInput {
|
|
104
|
+
@include input-field;
|
|
105
|
+
font-size: var(--font-size-sm);
|
|
106
|
+
color: var(--text-secondary);
|
|
107
|
+
padding: var(--space-sm) var(--space-md);
|
|
108
|
+
width: 100%;
|
|
109
|
+
max-width: 400px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.adapterSelect {
|
|
113
|
+
@include input-field;
|
|
114
|
+
font-size: var(--font-size-sm);
|
|
115
|
+
color: var(--text-secondary);
|
|
116
|
+
padding: var(--space-xs) var(--space-sm);
|
|
117
|
+
width: 100%;
|
|
118
|
+
max-width: 320px;
|
|
119
|
+
cursor: pointer;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.readOnlyValue {
|
|
123
|
+
font-size: var(--font-size-sm);
|
|
124
|
+
color: var(--text-secondary);
|
|
125
|
+
padding: var(--space-xs) 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// Codespace picker
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
.codespaceSection {
|
|
133
|
+
display: flex;
|
|
134
|
+
flex-direction: column;
|
|
135
|
+
gap: var(--space-sm);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.codespaceActions {
|
|
139
|
+
display: flex;
|
|
140
|
+
align-items: center;
|
|
141
|
+
gap: var(--space-sm);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.creatingHint {
|
|
145
|
+
font-size: var(--font-size-sm);
|
|
146
|
+
color: var(--accent-blue);
|
|
147
|
+
animation: pulse 2s ease-in-out infinite;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.errorHint {
|
|
151
|
+
font-size: var(--font-size-sm);
|
|
152
|
+
color: var(--accent-red);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@keyframes pulse {
|
|
156
|
+
0%, 100% { opacity: 1; }
|
|
157
|
+
50% { opacity: 0.5; }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
// Buttons
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
.btnPrimary {
|
|
165
|
+
@include btn-primary;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.btnGhost {
|
|
169
|
+
@include btn-ghost(var(--text-secondary));
|
|
170
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { expect, fn, userEvent } from "@storybook/test";
|
|
3
|
+
import { EnvironmentEditPanel } from "./EnvironmentEditPanel.js";
|
|
4
|
+
import { buildEnvironment } from "../../test-utils/storybook-helpers.js";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof EnvironmentEditPanel> = {
|
|
7
|
+
title: "App/Panels/EnvironmentEditPanel",
|
|
8
|
+
component: EnvironmentEditPanel,
|
|
9
|
+
args: {
|
|
10
|
+
mode: "new",
|
|
11
|
+
environments: [],
|
|
12
|
+
onAddEnvironment: fn(),
|
|
13
|
+
onUpdateEnvironment: fn(),
|
|
14
|
+
onListCodespaces: fn(),
|
|
15
|
+
codespaces: [],
|
|
16
|
+
codespaceError: "",
|
|
17
|
+
codespaceListError: "",
|
|
18
|
+
codespaceCreating: false,
|
|
19
|
+
onCreateCodespace: fn(),
|
|
20
|
+
onShowToast: fn(),
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default meta;
|
|
25
|
+
type Story = StoryObj<typeof EnvironmentEditPanel>;
|
|
26
|
+
|
|
27
|
+
/** The create form renders with default local adapter and an empty name input. */
|
|
28
|
+
export const DefaultCreateForm: Story = {
|
|
29
|
+
play: async ({ canvas }) => {
|
|
30
|
+
// Panel should be visible with form elements
|
|
31
|
+
await expect(canvas.getByTestId("env-create-panel")).toBeInTheDocument();
|
|
32
|
+
await expect(canvas.getByTestId("env-create-name")).toBeInTheDocument();
|
|
33
|
+
await expect(canvas.getByTestId("env-create-submit")).toBeInTheDocument();
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** Adapter type dropdown defaults to "local". */
|
|
38
|
+
export const AdapterDefaultsToLocal: Story = {
|
|
39
|
+
play: async ({ canvas }) => {
|
|
40
|
+
const adapterSelect = canvas.getByTestId("env-create-adapter") as HTMLSelectElement;
|
|
41
|
+
await expect(adapterSelect.value).toBe("local");
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** Create button is disabled when the name input is empty. */
|
|
46
|
+
export const CreateDisabledWhenEmpty: Story = {
|
|
47
|
+
play: async ({ canvas }) => {
|
|
48
|
+
const createButton = canvas.getByTestId("env-create-submit");
|
|
49
|
+
await expect(createButton).toBeDisabled();
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Create button is enabled when a name is provided for the local adapter. */
|
|
54
|
+
export const CreateEnabledWhenNameFilled: Story = {
|
|
55
|
+
play: async ({ canvas }) => {
|
|
56
|
+
const nameInput = canvas.getByTestId("env-create-name");
|
|
57
|
+
await userEvent.type(nameInput, "my-local");
|
|
58
|
+
|
|
59
|
+
const createButton = canvas.getByTestId("env-create-submit");
|
|
60
|
+
await expect(createButton).toBeEnabled();
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** SSH adapter requires a host field — Create stays disabled without it. */
|
|
65
|
+
export const SshRequiresHost: Story = {
|
|
66
|
+
play: async ({ canvas }) => {
|
|
67
|
+
// Select SSH adapter
|
|
68
|
+
const adapterSelect = canvas.getByTestId("env-create-adapter");
|
|
69
|
+
await userEvent.selectOptions(adapterSelect, "ssh");
|
|
70
|
+
|
|
71
|
+
// Fill name but leave host empty
|
|
72
|
+
const nameInput = canvas.getByTestId("env-create-name");
|
|
73
|
+
await userEvent.type(nameInput, "my-ssh");
|
|
74
|
+
|
|
75
|
+
const createButton = canvas.getByTestId("env-create-submit");
|
|
76
|
+
await expect(createButton).toBeDisabled();
|
|
77
|
+
|
|
78
|
+
// Fill host — now it should be enabled
|
|
79
|
+
const hostInput = canvas.getByTestId("env-create-host");
|
|
80
|
+
await userEvent.type(hostInput, "192.168.1.10");
|
|
81
|
+
await expect(createButton).toBeEnabled();
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** Create button is disabled when port value is out of the valid range (1-65535). */
|
|
86
|
+
export const PortValidation: Story = {
|
|
87
|
+
play: async ({ canvas }) => {
|
|
88
|
+
const nameInput = canvas.getByTestId("env-create-name");
|
|
89
|
+
await userEvent.type(nameInput, "port-test");
|
|
90
|
+
|
|
91
|
+
const portInput = canvas.getByTestId("env-create-port");
|
|
92
|
+
const createButton = canvas.getByTestId("env-create-submit");
|
|
93
|
+
|
|
94
|
+
// Out-of-range low value
|
|
95
|
+
await userEvent.type(portInput, "0");
|
|
96
|
+
await expect(createButton).toBeDisabled();
|
|
97
|
+
|
|
98
|
+
// Clear and try out-of-range high value
|
|
99
|
+
await userEvent.clear(portInput);
|
|
100
|
+
await userEvent.type(portInput, "99999");
|
|
101
|
+
await expect(createButton).toBeDisabled();
|
|
102
|
+
|
|
103
|
+
// Valid boundary: 1
|
|
104
|
+
await userEvent.clear(portInput);
|
|
105
|
+
await userEvent.type(portInput, "1");
|
|
106
|
+
await expect(createButton).toBeEnabled();
|
|
107
|
+
|
|
108
|
+
// Valid boundary: 65535
|
|
109
|
+
await userEvent.clear(portInput);
|
|
110
|
+
await userEvent.type(portInput, "65535");
|
|
111
|
+
await expect(createButton).toBeEnabled();
|
|
112
|
+
|
|
113
|
+
// Clearing port (optional) keeps button enabled
|
|
114
|
+
await userEvent.clear(portInput);
|
|
115
|
+
await expect(createButton).toBeEnabled();
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/** Switching adapter type shows the correct conditional fields. */
|
|
120
|
+
export const SwitchingAdapterShowsFields: Story = {
|
|
121
|
+
play: async ({ canvas }) => {
|
|
122
|
+
const adapterSelect = canvas.getByTestId("env-create-adapter");
|
|
123
|
+
|
|
124
|
+
// Local shows host and port
|
|
125
|
+
await expect(canvas.getByTestId("env-create-host")).toBeInTheDocument();
|
|
126
|
+
await expect(canvas.getByTestId("env-create-port")).toBeInTheDocument();
|
|
127
|
+
|
|
128
|
+
// Switch to SSH — shows host, user, port, identity file
|
|
129
|
+
await userEvent.selectOptions(adapterSelect, "ssh");
|
|
130
|
+
await expect(canvas.getByTestId("env-create-host")).toBeInTheDocument();
|
|
131
|
+
await expect(canvas.getByTestId("env-create-user")).toBeInTheDocument();
|
|
132
|
+
await expect(canvas.getByTestId("env-create-port")).toBeInTheDocument();
|
|
133
|
+
await expect(canvas.getByTestId("env-create-identity")).toBeInTheDocument();
|
|
134
|
+
|
|
135
|
+
// Switch to Docker — shows image and repo
|
|
136
|
+
await userEvent.selectOptions(adapterSelect, "docker");
|
|
137
|
+
await expect(canvas.getByTestId("env-create-image")).toBeInTheDocument();
|
|
138
|
+
await expect(canvas.getByTestId("env-create-repo")).toBeInTheDocument();
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/** When codespace listing fails, a manual entry input appears and the select dropdown is hidden. */
|
|
143
|
+
export const CodespaceManualEntry: Story = {
|
|
144
|
+
args: {
|
|
145
|
+
codespaceListError: "Could not find the `gh` CLI.",
|
|
146
|
+
},
|
|
147
|
+
play: async ({ canvas }) => {
|
|
148
|
+
// Select codespace adapter
|
|
149
|
+
const adapterSelect = canvas.getByTestId("env-create-adapter");
|
|
150
|
+
await userEvent.selectOptions(adapterSelect, "codespace");
|
|
151
|
+
|
|
152
|
+
// Manual input fallback should appear
|
|
153
|
+
await expect(canvas.getByTestId("env-codespace-manual")).toBeInTheDocument();
|
|
154
|
+
|
|
155
|
+
// Error message should be visible
|
|
156
|
+
await expect(canvas.getByText(/gh/)).toBeInTheDocument();
|
|
157
|
+
|
|
158
|
+
// Select dropdown should NOT be in the document when list error is present
|
|
159
|
+
const selectEl = canvas.queryByTestId("env-codespace-select");
|
|
160
|
+
await expect(selectEl).not.toBeInTheDocument();
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/** Manual codespace entry enables the Create button when name and codespace are filled. */
|
|
165
|
+
export const CodespaceManualEntryEnablesCreate: Story = {
|
|
166
|
+
args: {
|
|
167
|
+
codespaceListError: "Could not find the `gh` CLI.",
|
|
168
|
+
},
|
|
169
|
+
play: async ({ canvas }) => {
|
|
170
|
+
// Select codespace adapter
|
|
171
|
+
const adapterSelect = canvas.getByTestId("env-create-adapter");
|
|
172
|
+
await userEvent.selectOptions(adapterSelect, "codespace");
|
|
173
|
+
|
|
174
|
+
// Fill environment name
|
|
175
|
+
const nameInput = canvas.getByTestId("env-create-name");
|
|
176
|
+
await userEvent.type(nameInput, "my-cs");
|
|
177
|
+
|
|
178
|
+
// Fill manual codespace name
|
|
179
|
+
const manualInput = canvas.getByTestId("env-codespace-manual");
|
|
180
|
+
await userEvent.type(manualInput, "my-codespace-name");
|
|
181
|
+
|
|
182
|
+
// Create button should be enabled
|
|
183
|
+
const createButton = canvas.getByTestId("env-create-submit");
|
|
184
|
+
await expect(createButton).toBeEnabled();
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/** Edit mode renders pre-populated fields for an existing environment. */
|
|
189
|
+
export const EditModeLocal: Story = {
|
|
190
|
+
args: {
|
|
191
|
+
mode: "edit",
|
|
192
|
+
environmentId: "env-local-01",
|
|
193
|
+
environments: [
|
|
194
|
+
buildEnvironment({
|
|
195
|
+
id: "env-local-01",
|
|
196
|
+
displayName: "My Local Env",
|
|
197
|
+
adapterType: "local",
|
|
198
|
+
adapterConfig: '{"host":"127.0.0.1","port":7434}',
|
|
199
|
+
}),
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
play: async ({ canvas }) => {
|
|
203
|
+
await expect(canvas.getByTestId("env-edit-panel")).toBeInTheDocument();
|
|
204
|
+
await expect(canvas.getByText("local")).toBeInTheDocument();
|
|
205
|
+
},
|
|
206
|
+
};
|