@stephen-netu/design-system 0.2.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/d0-data-viz/BarChart.test.js +53 -0
- package/dist/d0-data-viz/CheckpointBar.test.js +83 -0
- package/dist/d0-data-viz/CheckpointPill.svelte +1 -1
- package/dist/d0-data-viz/CheckpointPill.test.js +78 -0
- package/dist/d0-data-viz/ConnectionHealth.test.js +70 -0
- package/dist/d0-data-viz/MetricCard.test.js +57 -0
- package/dist/d0-data-viz/SparkLine.test.js +47 -0
- package/dist/d0-data-viz/StorageMap.test.js +63 -0
- package/dist/d0-data-viz/Timeline.test.js +62 -0
- package/dist/d0-data-viz/WorldLineTimeline.test.js +99 -0
- package/dist/d0-data-viz/checkpoint-types.js +1 -1
- package/dist/d0-data-viz/storage-map-types.d.ts.map +1 -1
- package/dist/d0-data-viz/storage-map-types.js +6 -3
- package/dist/d0-data-viz/theme-integration.js +1 -1
- package/dist/demos/AmbientPrimitivesDemo.svelte +103 -0
- package/dist/demos/AmbientPrimitivesDemo.svelte.d.ts +5 -0
- package/dist/demos/AmbientPrimitivesDemo.svelte.d.ts.map +1 -0
- package/dist/demos/NodepadBlocksShowcase.svelte +2 -1
- package/dist/demos/NodepadBlocksShowcase.svelte.d.ts.map +1 -1
- package/dist/demos/index.d.ts +1 -0
- package/dist/demos/index.d.ts.map +1 -1
- package/dist/demos/index.js +1 -0
- package/dist/editor/CodeEditor.svelte +83 -26
- package/dist/editor/CodeEditor.svelte.d.ts +0 -1
- package/dist/editor/CodeEditor.svelte.d.ts.map +1 -1
- package/dist/editor/ExternalChangeDialog.svelte +117 -0
- package/dist/editor/ExternalChangeDialog.svelte.d.ts +13 -0
- package/dist/editor/ExternalChangeDialog.svelte.d.ts.map +1 -0
- package/dist/editor/MarkdownEditor.svelte +104 -617
- package/dist/editor/MarkdownEditor.svelte.d.ts +1 -1
- package/dist/editor/MarkdownEditor.svelte.d.ts.map +1 -1
- package/dist/editor/codemirror-config.d.ts +36 -0
- package/dist/editor/codemirror-config.d.ts.map +1 -0
- package/dist/editor/codemirror-config.js +87 -0
- package/dist/editor/components/CorrectionTooltip.svelte +180 -159
- package/dist/editor/components/CorrectionTooltip.svelte.d.ts +7 -23
- package/dist/editor/components/CorrectionTooltip.svelte.d.ts.map +1 -1
- package/dist/editor/extensions/autocomplete.d.ts +2 -2
- package/dist/editor/extensions/autocomplete.d.ts.map +1 -1
- package/dist/editor/extensions/autocomplete.test.js +121 -0
- package/dist/editor/extensions/spellcheck.d.ts +21 -3
- package/dist/editor/extensions/spellcheck.d.ts.map +1 -1
- package/dist/editor/extensions/spellcheck.js +51 -9
- package/dist/editor/extensions/spellcheck.test.js +168 -0
- package/dist/editor/extensions/types.d.ts +2 -1
- package/dist/editor/extensions/types.d.ts.map +1 -1
- package/dist/editor/index.d.ts +2 -1
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/editor/index.js +1 -0
- package/dist/editor/markdown-preview.d.ts +9 -0
- package/dist/editor/markdown-preview.d.ts.map +1 -0
- package/dist/editor/markdown-preview.js +19 -0
- package/dist/editor/markdown-preview.test.js +38 -0
- package/dist/editor/useCodeMirror.d.ts +23 -0
- package/dist/editor/useCodeMirror.d.ts.map +1 -0
- package/dist/editor/useCodeMirror.js +40 -0
- package/dist/editor/useFilePersistence.d.ts +32 -0
- package/dist/editor/useFilePersistence.d.ts.map +1 -0
- package/dist/editor/useFilePersistence.js +117 -0
- package/dist/fabric/ai/ChatPanel.svelte +61 -62
- package/dist/fabric/ai/ChatPanel.svelte.d.ts.map +1 -1
- package/dist/fabric/ai/ResearchPanel.svelte +31 -24
- package/dist/fabric/data/FileTree.svelte +195 -0
- package/dist/fabric/data/FileTree.svelte.d.ts +19 -0
- package/dist/fabric/data/FileTree.svelte.d.ts.map +1 -0
- package/dist/fabric/data/FileTree.test.js +127 -0
- package/dist/fabric/data/index.d.ts +5 -9
- package/dist/fabric/data/index.d.ts.map +1 -1
- package/dist/fabric/data/index.js +4 -1
- package/dist/fabric/index.d.ts +1 -0
- package/dist/fabric/index.d.ts.map +1 -1
- package/dist/fabric/index.js +2 -0
- package/dist/fabric/input/KeyboardShortcuts.svelte +23 -21
- package/dist/fabric/layout/CollapsiblePanel.svelte +8 -10
- package/dist/fabric/navigation/ActivityRail.svelte +3 -5
- package/dist/fabric/navigation/ActivityRail.svelte.d.ts.map +1 -1
- package/dist/g0-generative/components/Text.svelte +38 -0
- package/dist/g0-generative/components/Text.svelte.d.ts +9 -0
- package/dist/g0-generative/components/Text.svelte.d.ts.map +1 -0
- package/dist/g0-generative/index.d.ts +1 -0
- package/dist/g0-generative/index.d.ts.map +1 -1
- package/dist/g0-generative/index.js +1 -0
- package/dist/g0-generative/library/ComponentLibrary.d.ts +4 -0
- package/dist/g0-generative/library/ComponentLibrary.d.ts.map +1 -1
- package/dist/g0-generative/library/ComponentLibrary.js +10 -0
- package/dist/g0-generative/library/ComponentLibrary.test.js +135 -0
- package/dist/g0-generative/renderer/OpenUIRenderer.svelte +16 -56
- package/dist/g0-generative/renderer/OpenUIRenderer.svelte.d.ts.map +1 -1
- package/dist/g0-generative/renderer/OpenUIRenderer.test.js +143 -0
- package/dist/g0-geo/SovereignMap.svelte +13 -13
- package/dist/g0-geo/SovereignMap.svelte.d.ts.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/l0-layout/block-writer/BlockContent.svelte +23 -22
- package/dist/l0-layout/block-writer/BlockContent.svelte.d.ts.map +1 -1
- package/dist/l0-layout/block-writer/BlockContent.test.js +47 -0
- package/dist/l0-layout/block-writer/markdown.js +11 -11
- package/dist/l0-layout/block-writer/markdown.test.js +81 -0
- package/dist/l0-layout/card/StackedCard.svelte +87 -0
- package/dist/l0-layout/card/StackedCard.svelte.d.ts +9 -0
- package/dist/l0-layout/card/StackedCard.svelte.d.ts.map +1 -0
- package/dist/l0-layout/card/StackedCard.test.js +29 -0
- package/dist/l0-layout/index.d.ts +1 -0
- package/dist/l0-layout/index.d.ts.map +1 -1
- package/dist/l0-layout/index.js +1 -0
- package/dist/l0-layout/kanban/KanbanBoard.svelte +1 -1
- package/dist/l0-layout/kanban/KanbanColumn.svelte +1 -1
- package/dist/n1-flow-canvas/FlowCanvas.svelte +50 -6
- package/dist/n1-flow-canvas/FlowCanvas.svelte.d.ts.map +1 -1
- package/dist/n1-flow-canvas/index.d.ts +2 -0
- package/dist/n1-flow-canvas/index.d.ts.map +1 -1
- package/dist/n1-flow-canvas/index.js +1 -0
- package/dist/n1-flow-canvas/pipeline-adapter.d.ts +37 -0
- package/dist/n1-flow-canvas/pipeline-adapter.d.ts.map +1 -0
- package/dist/n1-flow-canvas/pipeline-adapter.js +160 -0
- package/dist/n2-manifold-disk/ManifoldDisk.svelte +62 -35
- package/dist/n2-manifold-disk/ManifoldDisk.svelte.d.ts.map +1 -1
- package/dist/n4-adaptive-manifold/AdaptiveManifold.svelte +23 -19
- package/dist/n4-adaptive-manifold/AdaptiveManifold.svelte.d.ts.map +1 -1
- package/dist/n4-adaptive-manifold/types.d.ts +3 -0
- package/dist/n4-adaptive-manifold/types.d.ts.map +1 -1
- package/dist/p0-primitives/ThemeProvider.svelte +28 -7
- package/dist/p0-primitives/ThemeProvider.svelte.d.ts +5 -0
- package/dist/p0-primitives/ThemeProvider.svelte.d.ts.map +1 -1
- package/dist/p0-primitives/canvas-theme.d.ts +21 -1
- package/dist/p0-primitives/canvas-theme.d.ts.map +1 -1
- package/dist/p0-primitives/canvas-theme.js +78 -23
- package/dist/p0-primitives/debug.d.ts +6 -0
- package/dist/p0-primitives/debug.d.ts.map +1 -0
- package/dist/p0-primitives/debug.js +21 -0
- package/dist/p0-primitives/theme.d.ts.map +1 -1
- package/dist/p0-primitives/theme.js +11 -31
- package/dist/p0-primitives/tokens/ambient.css +76 -0
- package/dist/p0-primitives/tokens/tokens.css +124 -29
- package/dist/p0-primitives/utils/index.d.ts +2 -0
- package/dist/p0-primitives/utils/index.d.ts.map +1 -1
- package/dist/p0-primitives/utils/index.js +1 -0
- package/dist/p0-primitives/utils/reveal.d.ts +15 -0
- package/dist/p0-primitives/utils/reveal.d.ts.map +1 -0
- package/dist/p0-primitives/utils/reveal.js +29 -0
- package/dist/p0-primitives/utils/reveal.test.js +95 -0
- package/dist/s0-state/SyncStatus.svelte +1 -1
- package/dist/s0-state/index.d.ts +2 -1
- package/dist/s0-state/index.d.ts.map +1 -1
- package/dist/s0-state/index.js +2 -0
- package/dist/s0-state/modal-stack-store.svelte.d.ts +3 -3
- package/dist/s0-state/modal-stack-store.svelte.js +2 -2
- package/dist/spatial/ForceSimulation.svelte.js +1 -1
- package/dist/spatial/ParticleAssembleMark.svelte +285 -0
- package/dist/spatial/ParticleAssembleMark.svelte.d.ts +24 -0
- package/dist/spatial/ParticleAssembleMark.svelte.d.ts.map +1 -0
- package/dist/spatial/ZoneTiler.test.js +90 -0
- package/dist/spatial/index.js +1 -0
- package/dist/spatial/particle-assemble-math.d.ts +22 -0
- package/dist/spatial/particle-assemble-math.d.ts.map +1 -0
- package/dist/spatial/particle-assemble-math.js +26 -0
- package/dist/spatial/particle-assemble-math.test.js +56 -0
- package/dist/t0-transport/substrate.svelte.d.ts.map +1 -1
- package/dist/t0-transport/substrate.svelte.js +10 -4
- package/dist/u0-primitives/LockIndicator.svelte +16 -14
- package/dist/u0-primitives/VerticalToolbar.svelte +24 -21
- package/dist/u0-primitives/accordion/Accordion.svelte +8 -7
- package/dist/u0-primitives/animated-icon/AnimatedIcon.svelte +3 -3
- package/dist/u0-primitives/animated-icon/AnimatedIcon.test.js +82 -0
- package/dist/u0-primitives/avatar/Avatar.svelte +14 -14
- package/dist/u0-primitives/avatar/Avatar.test.js +81 -0
- package/dist/u0-primitives/badge/Badge.svelte +6 -4
- package/dist/u0-primitives/badge/ValidityBadge.svelte +4 -27
- package/dist/u0-primitives/button/Button.svelte +15 -12
- package/dist/u0-primitives/card/Card.svelte +37 -15
- package/dist/u0-primitives/card/Card.test.js +86 -0
- package/dist/u0-primitives/command-palette/CommandPalette.svelte +48 -43
- package/dist/u0-primitives/command-palette/CommandPalette.test.js +202 -0
- package/dist/u0-primitives/dropdown/Dropdown.svelte +20 -25
- package/dist/u0-primitives/grant-badge/GrantStatusBadge.svelte +2 -2
- package/dist/u0-primitives/index.d.ts +6 -0
- package/dist/u0-primitives/index.d.ts.map +1 -1
- package/dist/u0-primitives/index.js +8 -0
- package/dist/u0-primitives/input/Input.svelte +77 -24
- package/dist/u0-primitives/input/Input.svelte.d.ts +2 -10
- package/dist/u0-primitives/input/Input.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/input/Input.test.js +81 -1
- package/dist/u0-primitives/live-dot/LiveDot.svelte +56 -0
- package/dist/u0-primitives/live-dot/LiveDot.svelte.d.ts +11 -0
- package/dist/u0-primitives/live-dot/LiveDot.svelte.d.ts.map +1 -0
- package/dist/u0-primitives/live-dot/LiveDot.test.js +41 -0
- package/dist/u0-primitives/live-dot/index.d.ts +3 -0
- package/dist/u0-primitives/live-dot/index.d.ts.map +1 -0
- package/dist/u0-primitives/live-dot/index.js +1 -0
- package/dist/u0-primitives/modal/Modal.svelte +22 -19
- package/dist/u0-primitives/modal/Modal.test.js +1 -1
- package/dist/u0-primitives/spinner/Spinner.svelte +11 -79
- package/dist/u0-primitives/spinner/Spinner.svelte.d.ts.map +1 -1
- package/dist/u0-primitives/steps/Steps.svelte +18 -19
- package/dist/u0-primitives/surface-state/SurfaceState.svelte +7 -7
- package/dist/u0-primitives/tabs/Tabs.svelte +13 -11
- package/dist/u0-primitives/theme-swatch-group/ThemeSwatchGroup.svelte +94 -0
- package/dist/u0-primitives/theme-swatch-group/ThemeSwatchGroup.svelte.d.ts +16 -0
- package/dist/u0-primitives/theme-swatch-group/ThemeSwatchGroup.svelte.d.ts.map +1 -0
- package/dist/u0-primitives/theme-swatch-group/ThemeSwatchGroup.test.js +48 -0
- package/dist/u0-primitives/theme-swatch-group/index.d.ts +3 -0
- package/dist/u0-primitives/theme-swatch-group/index.d.ts.map +1 -0
- package/dist/u0-primitives/theme-swatch-group/index.js +1 -0
- package/dist/u0-primitives/toggle/Toggle.svelte +10 -11
- package/dist/u0-primitives/tooltip/Tooltip.svelte +9 -9
- package/dist/u0-primitives/web-components/button-component.d.ts +5 -1
- package/dist/u0-primitives/web-components/button-component.d.ts.map +1 -1
- package/dist/u0-primitives/web-components/button-component.js +72 -33
- package/dist/u0-primitives/web-components/index.d.ts +3 -0
- package/dist/u0-primitives/web-components/index.d.ts.map +1 -0
- package/dist/u0-primitives/web-components/index.js +2 -0
- package/dist/u0-primitives/web-components/input-component.d.ts +5 -1
- package/dist/u0-primitives/web-components/input-component.d.ts.map +1 -1
- package/dist/u0-primitives/web-components/input-component.js +56 -39
- package/dist/u0-primitives/web-components/web-components.test.js +96 -0
- package/dist/u0-primitives/window-frame/WindowFrame.svelte +87 -0
- package/dist/u0-primitives/window-frame/WindowFrame.svelte.d.ts +10 -0
- package/dist/u0-primitives/window-frame/WindowFrame.svelte.d.ts.map +1 -0
- package/dist/u0-primitives/window-frame/WindowFrame.test.js +31 -0
- package/dist/u0-primitives/window-frame/index.d.ts +3 -0
- package/dist/u0-primitives/window-frame/index.d.ts.map +1 -0
- package/dist/u0-primitives/window-frame/index.js +1 -0
- package/dist/x0-enchanted-blocks/components/NodepadBlock.svelte +11 -2
- package/dist/x0-enchanted-blocks/components/NodepadBlock.svelte.d.ts.map +1 -1
- package/package.json +44 -28
- package/src/p0-primitives/tokens/ambient.css +76 -0
- package/src/p0-primitives/tokens/tokens.css +124 -29
- package/src/p0-primitives/tokens/tokens.json +42 -24
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
transition: border-color var(--transition-fast), background-color var(--transition-fast), color var(--transition-fast);
|
|
95
95
|
background: transparent;
|
|
96
96
|
color: var(--color-text-primary);
|
|
97
|
-
padding: 0 var(--
|
|
97
|
+
padding: 0 var(--ui-pad-x);
|
|
98
98
|
line-height: 1;
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -142,20 +142,23 @@
|
|
|
142
142
|
|
|
143
143
|
/* --- Variants --- */
|
|
144
144
|
|
|
145
|
+
/* Primary = inverted neutral (high-contrast), NOT an accent fill.
|
|
146
|
+
Locked rule: accent = live edge, never a fill. Accent shows on
|
|
147
|
+
:focus-visible. Reads as primary under any theme and any user accent. */
|
|
145
148
|
.variant-primary {
|
|
146
|
-
background: var(--color-
|
|
149
|
+
background: var(--color-text-primary);
|
|
147
150
|
color: var(--color-bg-app);
|
|
148
|
-
border-color: var(--color-
|
|
151
|
+
border-color: var(--color-text-primary);
|
|
149
152
|
}
|
|
150
153
|
|
|
151
154
|
.variant-primary:hover:not(:disabled) {
|
|
152
|
-
background: var(--color-
|
|
153
|
-
border-color: var(--color-
|
|
155
|
+
background: var(--color-text-secondary);
|
|
156
|
+
border-color: var(--color-text-secondary);
|
|
154
157
|
}
|
|
155
158
|
|
|
156
159
|
.variant-primary.is-pressed:not(:disabled) {
|
|
157
|
-
background: var(--color-
|
|
158
|
-
border-color: var(--color-
|
|
160
|
+
background: var(--color-text-secondary);
|
|
161
|
+
border-color: var(--color-text-secondary);
|
|
159
162
|
}
|
|
160
163
|
|
|
161
164
|
.variant-secondary {
|
|
@@ -195,18 +198,18 @@
|
|
|
195
198
|
}
|
|
196
199
|
|
|
197
200
|
.variant-danger:hover:not(:disabled) {
|
|
198
|
-
background:
|
|
201
|
+
background: color-mix(in srgb, var(--color-error) 12%, transparent);
|
|
199
202
|
}
|
|
200
203
|
|
|
201
204
|
.variant-danger.is-pressed:not(:disabled) {
|
|
202
|
-
background:
|
|
205
|
+
background: color-mix(in srgb, var(--color-error) 22%, transparent);
|
|
203
206
|
}
|
|
204
207
|
|
|
205
208
|
/* --- Sizes --- */
|
|
206
209
|
|
|
207
|
-
.size-sm { height:
|
|
208
|
-
.size-md { height:
|
|
209
|
-
.size-lg { height:
|
|
210
|
+
.size-sm { height: calc(var(--ui-control-h) - 4px); font-size: var(--ui-font-sm); }
|
|
211
|
+
.size-md { height: var(--ui-control-h); font-size: var(--ui-font); }
|
|
212
|
+
.size-lg { height: calc(var(--ui-control-h) + 6px); font-size: var(--ui-font); }
|
|
210
213
|
|
|
211
214
|
/* --- Loading Spinner --- */
|
|
212
215
|
|
|
@@ -96,24 +96,26 @@
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
.ds-card-header {
|
|
99
|
-
padding: var(--
|
|
99
|
+
padding: var(--ui-pad-y) var(--ui-pad-x);
|
|
100
100
|
border-bottom: var(--border-width-thin) solid var(--border-default);
|
|
101
|
+
font-family: var(--font-mono);
|
|
101
102
|
font-weight: 600;
|
|
102
103
|
background: var(--color-bg-panel);
|
|
103
|
-
font-size: var(--
|
|
104
|
+
font-size: var(--ui-label);
|
|
104
105
|
text-transform: uppercase;
|
|
105
|
-
letter-spacing: 0.
|
|
106
|
+
letter-spacing: 0.08em;
|
|
107
|
+
color: var(--color-text-secondary);
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
.ds-card-content {
|
|
109
|
-
padding: var(--
|
|
111
|
+
padding: var(--ui-pad-x);
|
|
110
112
|
flex: 1;
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
.ds-card-footer {
|
|
114
|
-
padding: var(--
|
|
116
|
+
padding: var(--ui-pad-y) var(--ui-pad-x);
|
|
115
117
|
border-top: var(--border-width-thin) solid var(--border-default);
|
|
116
|
-
background: var(--color-
|
|
118
|
+
background: var(--color-bg-panel);
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
/* --- Variants --- */
|
|
@@ -129,11 +131,12 @@
|
|
|
129
131
|
border-color: var(--border-subtle);
|
|
130
132
|
}
|
|
131
133
|
|
|
134
|
+
/* 'glass' kept as an API alias but DE-GLASSED: opaque elevated panel,
|
|
135
|
+
no backdrop-filter. Blur = web2/Material; INSTRUMENT builds depth from
|
|
136
|
+
border + contrast, never frosted translucency. */
|
|
132
137
|
.variant-glass {
|
|
133
|
-
background:
|
|
134
|
-
|
|
135
|
-
-webkit-backdrop-filter: blur(var(--blur-md));
|
|
136
|
-
border: var(--border-width-thin) solid rgba(255, 255, 255, 0.08);
|
|
138
|
+
background: var(--color-bg-panel-elevated);
|
|
139
|
+
border: var(--border-width-thin) solid var(--border-default);
|
|
137
140
|
color: var(--color-text-primary);
|
|
138
141
|
}
|
|
139
142
|
|
|
@@ -149,10 +152,11 @@
|
|
|
149
152
|
);
|
|
150
153
|
}
|
|
151
154
|
|
|
155
|
+
/* Hazard = destructive semantics → FIXED error hue, never the user accent. */
|
|
152
156
|
.variant-hazard {
|
|
153
|
-
background: var(--color-
|
|
154
|
-
border-color: var(--color-
|
|
155
|
-
color: var(--color-
|
|
157
|
+
background: color-mix(in srgb, var(--color-error) 8%, transparent);
|
|
158
|
+
border-color: var(--color-error);
|
|
159
|
+
color: var(--color-error);
|
|
156
160
|
}
|
|
157
161
|
|
|
158
162
|
/* --- Interactive --- */
|
|
@@ -200,8 +204,26 @@
|
|
|
200
204
|
}
|
|
201
205
|
|
|
202
206
|
.is-selected.variant-hazard {
|
|
203
|
-
border-color: var(--color-
|
|
204
|
-
background: var(--color-
|
|
207
|
+
border-color: var(--color-error);
|
|
208
|
+
background: color-mix(in srgb, var(--color-error) 14%, transparent);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/* Hazard interactive states kept on the fixed error hue — never the user accent. */
|
|
212
|
+
.variant-hazard.is-interactive:hover {
|
|
213
|
+
border-color: var(--color-error);
|
|
214
|
+
background: color-mix(in srgb, var(--color-error) 12%, transparent);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.variant-hazard.is-interactive:focus-visible .ds-card-ring,
|
|
218
|
+
.is-selected.variant-hazard .ds-card-ring {
|
|
219
|
+
border-color: var(--color-error);
|
|
220
|
+
background: repeating-linear-gradient(
|
|
221
|
+
45deg,
|
|
222
|
+
transparent 0,
|
|
223
|
+
transparent var(--border-width-default),
|
|
224
|
+
var(--color-error) var(--border-width-default),
|
|
225
|
+
var(--color-error) var(--blur-md)
|
|
226
|
+
);
|
|
205
227
|
}
|
|
206
228
|
|
|
207
229
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { afterEach, describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { cleanup, render, fireEvent } from '@testing-library/svelte';
|
|
3
|
+
import { createRawSnippet } from 'svelte';
|
|
4
|
+
import Card from './Card.svelte';
|
|
5
|
+
const textSnippet = (text) => createRawSnippet(() => ({ render: () => `<span>${text}</span>` }));
|
|
6
|
+
describe('Card', () => {
|
|
7
|
+
afterEach(() => cleanup());
|
|
8
|
+
it('renders the ds-card root element', () => {
|
|
9
|
+
const { container } = render(Card);
|
|
10
|
+
expect(container.querySelector('.ds-card')).not.toBeNull();
|
|
11
|
+
});
|
|
12
|
+
it('defaults to the elevated variant', () => {
|
|
13
|
+
const { container } = render(Card);
|
|
14
|
+
expect(container.querySelector('.variant-elevated')).not.toBeNull();
|
|
15
|
+
});
|
|
16
|
+
it('applies the requested variant class', () => {
|
|
17
|
+
const { container } = render(Card, { variant: 'hazard' });
|
|
18
|
+
expect(container.querySelector('.variant-hazard')).not.toBeNull();
|
|
19
|
+
});
|
|
20
|
+
it('applies a custom class', () => {
|
|
21
|
+
const { container } = render(Card, { class: 'my-card' });
|
|
22
|
+
expect(container.querySelector('.my-card')).not.toBeNull();
|
|
23
|
+
});
|
|
24
|
+
it('applies an inline style', () => {
|
|
25
|
+
const { container } = render(Card, { style: 'width: 200px' });
|
|
26
|
+
expect(container.querySelector('.ds-card').getAttribute('style')).toContain('width: 200px');
|
|
27
|
+
});
|
|
28
|
+
it('renders children content', () => {
|
|
29
|
+
const { container } = render(Card, { children: textSnippet('body') });
|
|
30
|
+
const content = container.querySelector('.ds-card-content');
|
|
31
|
+
expect(content).not.toBeNull();
|
|
32
|
+
expect(content.textContent).toContain('body');
|
|
33
|
+
});
|
|
34
|
+
it('renders header and footer snippets', () => {
|
|
35
|
+
const { container } = render(Card, {
|
|
36
|
+
header: textSnippet('head'),
|
|
37
|
+
footer: textSnippet('foot')
|
|
38
|
+
});
|
|
39
|
+
expect(container.querySelector('.ds-card-header').textContent).toContain('head');
|
|
40
|
+
expect(container.querySelector('.ds-card-footer').textContent).toContain('foot');
|
|
41
|
+
});
|
|
42
|
+
it('is not interactive by default (no button role)', () => {
|
|
43
|
+
const { container } = render(Card);
|
|
44
|
+
expect(container.querySelector('[role="button"]')).toBeNull();
|
|
45
|
+
expect(container.querySelector('.is-interactive')).toBeNull();
|
|
46
|
+
});
|
|
47
|
+
it('becomes interactive when an onclick handler is provided', () => {
|
|
48
|
+
const { container } = render(Card, { onclick: vi.fn() });
|
|
49
|
+
const card = container.querySelector('.ds-card');
|
|
50
|
+
expect(card.getAttribute('role')).toBe('button');
|
|
51
|
+
expect(card.getAttribute('tabindex')).toBe('0');
|
|
52
|
+
expect(container.querySelector('.is-interactive')).not.toBeNull();
|
|
53
|
+
});
|
|
54
|
+
it('becomes interactive for the interactive variant without onclick', () => {
|
|
55
|
+
const { container } = render(Card, { variant: 'interactive' });
|
|
56
|
+
expect(container.querySelector('[role="button"]')).not.toBeNull();
|
|
57
|
+
});
|
|
58
|
+
it('calls onclick when an interactive card is clicked', async () => {
|
|
59
|
+
const handleClick = vi.fn();
|
|
60
|
+
const { container } = render(Card, { onclick: handleClick });
|
|
61
|
+
await fireEvent.click(container.querySelector('.ds-card'));
|
|
62
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
63
|
+
});
|
|
64
|
+
it('triggers onclick on Enter key when interactive', async () => {
|
|
65
|
+
const handleClick = vi.fn();
|
|
66
|
+
const { container } = render(Card, { onclick: handleClick });
|
|
67
|
+
await fireEvent.keyDown(container.querySelector('.ds-card'), { key: 'Enter' });
|
|
68
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
69
|
+
});
|
|
70
|
+
it('triggers onclick on Space key when interactive', async () => {
|
|
71
|
+
const handleClick = vi.fn();
|
|
72
|
+
const { container } = render(Card, { onclick: handleClick });
|
|
73
|
+
await fireEvent.keyDown(container.querySelector('.ds-card'), { key: ' ' });
|
|
74
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
75
|
+
});
|
|
76
|
+
it('reflects selection via the is-selected class and aria-pressed', () => {
|
|
77
|
+
const { container } = render(Card, { selected: true, onclick: vi.fn() });
|
|
78
|
+
const card = container.querySelector('.ds-card');
|
|
79
|
+
expect(card.classList.contains('is-selected')).toBe(true);
|
|
80
|
+
expect(card.getAttribute('aria-pressed')).toBe('true');
|
|
81
|
+
});
|
|
82
|
+
it('renders the selection ring when selected', () => {
|
|
83
|
+
const { container } = render(Card, { selected: true });
|
|
84
|
+
expect(container.querySelector('.ds-card-ring')).not.toBeNull();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -396,21 +396,21 @@
|
|
|
396
396
|
bottom: 100%;
|
|
397
397
|
left: 0;
|
|
398
398
|
right: 0;
|
|
399
|
-
margin-bottom:
|
|
400
|
-
background: var(--color-bg-panel-elevated
|
|
401
|
-
border:
|
|
402
|
-
border-radius:
|
|
403
|
-
box-shadow:
|
|
399
|
+
margin-bottom: 2px;
|
|
400
|
+
background: var(--color-bg-panel-elevated);
|
|
401
|
+
border: var(--border-width-default) solid var(--border-default);
|
|
402
|
+
border-radius: 0;
|
|
403
|
+
box-shadow: none;
|
|
404
404
|
overflow: hidden;
|
|
405
405
|
z-index: 100;
|
|
406
406
|
}
|
|
407
|
-
|
|
407
|
+
|
|
408
408
|
.input-bar {
|
|
409
409
|
display: flex;
|
|
410
410
|
align-items: center;
|
|
411
411
|
gap: var(--space-2);
|
|
412
|
-
padding: var(--
|
|
413
|
-
border-bottom: 1px solid var(--border-
|
|
412
|
+
padding: var(--ui-pad-y) var(--ui-pad-x);
|
|
413
|
+
border-bottom: 1px solid var(--border-default);
|
|
414
414
|
}
|
|
415
415
|
|
|
416
416
|
.input-bar.executing {
|
|
@@ -448,42 +448,48 @@
|
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
.spinner {
|
|
451
|
-
width:
|
|
452
|
-
height:
|
|
453
|
-
border:
|
|
454
|
-
border-top-color: var(--color-accent
|
|
451
|
+
width: 14px;
|
|
452
|
+
height: 14px;
|
|
453
|
+
border: 1.5px solid var(--border-default);
|
|
454
|
+
border-top-color: var(--color-accent);
|
|
455
455
|
border-radius: 50%;
|
|
456
456
|
animation: spin 0.8s linear infinite;
|
|
457
457
|
}
|
|
458
|
-
|
|
458
|
+
|
|
459
459
|
@keyframes spin {
|
|
460
460
|
to { transform: rotate(360deg); }
|
|
461
461
|
}
|
|
462
|
-
|
|
462
|
+
|
|
463
463
|
.command-list,
|
|
464
464
|
.suggestion-list {
|
|
465
465
|
list-style: none;
|
|
466
466
|
margin: 0;
|
|
467
|
-
padding:
|
|
468
|
-
max-height:
|
|
467
|
+
padding: 0;
|
|
468
|
+
max-height: 220px;
|
|
469
469
|
overflow-y: auto;
|
|
470
470
|
}
|
|
471
|
-
|
|
471
|
+
|
|
472
472
|
.command-list li,
|
|
473
473
|
.suggestion-list li {
|
|
474
474
|
display: flex;
|
|
475
475
|
align-items: center;
|
|
476
476
|
gap: var(--space-3);
|
|
477
|
-
|
|
477
|
+
height: var(--ui-row-h);
|
|
478
|
+
padding: 0 var(--ui-pad-x);
|
|
478
479
|
cursor: pointer;
|
|
479
|
-
|
|
480
|
+
border-bottom: 1px solid var(--border-default);
|
|
481
|
+
transition: background var(--transition-fast) linear;
|
|
480
482
|
}
|
|
481
|
-
|
|
483
|
+
|
|
484
|
+
.command-list li:last-child,
|
|
485
|
+
.suggestion-list li:last-child { border-bottom: 0; }
|
|
486
|
+
|
|
482
487
|
.command-list li:hover,
|
|
483
488
|
.command-list li.selected,
|
|
484
489
|
.suggestion-list li:hover,
|
|
485
490
|
.suggestion-list li.selected {
|
|
486
|
-
background: var(--color-accent-subtle
|
|
491
|
+
background: var(--color-accent-subtle);
|
|
492
|
+
box-shadow: inset 2px 0 0 var(--color-accent);
|
|
487
493
|
}
|
|
488
494
|
|
|
489
495
|
.command-name {
|
|
@@ -512,26 +518,25 @@
|
|
|
512
518
|
}
|
|
513
519
|
|
|
514
520
|
.param-chip {
|
|
515
|
-
font-size: var(--
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
background: var(--color-bg-panel
|
|
519
|
-
color: var(--color-text-tertiary
|
|
521
|
+
font-size: var(--ui-label);
|
|
522
|
+
font-family: var(--font-mono);
|
|
523
|
+
padding: 2px var(--ui-pad-y);
|
|
524
|
+
background: var(--color-bg-panel);
|
|
525
|
+
color: var(--color-text-tertiary);
|
|
520
526
|
border: 1px solid transparent;
|
|
521
527
|
}
|
|
522
|
-
|
|
528
|
+
|
|
523
529
|
.param-chip.required {
|
|
524
|
-
border-color: var(--color-accent-muted
|
|
530
|
+
border-color: var(--color-accent-muted);
|
|
525
531
|
}
|
|
526
|
-
|
|
532
|
+
|
|
527
533
|
.param-chip.filled {
|
|
528
|
-
background: var(--color-accent-subtle
|
|
529
|
-
color: var(--color-accent
|
|
534
|
+
background: var(--color-accent-subtle);
|
|
535
|
+
color: var(--color-accent);
|
|
530
536
|
}
|
|
531
|
-
|
|
537
|
+
|
|
532
538
|
.param-chip.current {
|
|
533
|
-
border-color: var(--color-accent
|
|
534
|
-
box-shadow: 0 0 0 1px var(--color-accent);
|
|
539
|
+
border-color: var(--color-accent);
|
|
535
540
|
}
|
|
536
541
|
|
|
537
542
|
.feedback {
|
|
@@ -541,13 +546,13 @@
|
|
|
541
546
|
}
|
|
542
547
|
|
|
543
548
|
.feedback.success {
|
|
544
|
-
color: var(--color-success
|
|
545
|
-
background:
|
|
549
|
+
color: var(--color-success);
|
|
550
|
+
background: color-mix(in srgb, var(--color-success) 10%, transparent);
|
|
546
551
|
}
|
|
547
|
-
|
|
552
|
+
|
|
548
553
|
.feedback.error {
|
|
549
|
-
color: var(--color-error
|
|
550
|
-
background:
|
|
554
|
+
color: var(--color-error);
|
|
555
|
+
background: color-mix(in srgb, var(--color-error) 10%, transparent);
|
|
551
556
|
}
|
|
552
557
|
|
|
553
558
|
.help {
|
|
@@ -560,10 +565,10 @@
|
|
|
560
565
|
}
|
|
561
566
|
|
|
562
567
|
kbd {
|
|
563
|
-
background: var(--color-bg-canvas
|
|
564
|
-
padding:
|
|
565
|
-
border
|
|
568
|
+
background: var(--color-bg-canvas);
|
|
569
|
+
padding: 1px 5px;
|
|
570
|
+
border: 1px solid var(--border-subtle);
|
|
566
571
|
font-family: var(--font-mono);
|
|
567
|
-
font-size:
|
|
572
|
+
font-size: var(--ui-label);
|
|
568
573
|
}
|
|
569
574
|
</style>
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { afterEach, describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { cleanup, render, fireEvent } from '@testing-library/svelte';
|
|
3
|
+
import CommandPalette from './CommandPalette.svelte';
|
|
4
|
+
const sampleCommands = [
|
|
5
|
+
{
|
|
6
|
+
id: 'grove.invite',
|
|
7
|
+
path: ['grove', 'invite'],
|
|
8
|
+
description: 'Invite a user to the grove',
|
|
9
|
+
parameters: [
|
|
10
|
+
{ name: 'user', description: 'User to invite', required: true, paramType: 'user' },
|
|
11
|
+
{ name: 'role', description: 'Role to assign', required: false, paramType: 'string' },
|
|
12
|
+
],
|
|
13
|
+
requiredCapabilities: ['grove.manage'],
|
|
14
|
+
contexts: ['grove'],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'agent.mode',
|
|
18
|
+
path: ['agent', 'mode'],
|
|
19
|
+
description: 'Switch agent mode',
|
|
20
|
+
parameters: [
|
|
21
|
+
{ name: 'mode', description: 'Mode name', required: true, paramType: 'choice', choices: ['fast', 'deep'] },
|
|
22
|
+
],
|
|
23
|
+
requiredCapabilities: [],
|
|
24
|
+
contexts: ['agent'],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'task.create',
|
|
28
|
+
path: ['task', 'create'],
|
|
29
|
+
description: 'Create a new task',
|
|
30
|
+
parameters: [
|
|
31
|
+
{ name: 'title', description: 'Task title', required: true, paramType: 'string' },
|
|
32
|
+
],
|
|
33
|
+
requiredCapabilities: ['task.write'],
|
|
34
|
+
contexts: ['global'],
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
function renderPalette(props = {}) {
|
|
38
|
+
return render(CommandPalette, {
|
|
39
|
+
props: {
|
|
40
|
+
commands: sampleCommands,
|
|
41
|
+
context: { realmId: 'r1' },
|
|
42
|
+
onExecute: vi.fn().mockResolvedValue({ success: true, message: 'Done' }),
|
|
43
|
+
onClose: vi.fn(),
|
|
44
|
+
...props,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async function openPalette(container) {
|
|
49
|
+
await fireEvent.keyDown(window, { key: '/' });
|
|
50
|
+
}
|
|
51
|
+
describe('CommandPalette', () => {
|
|
52
|
+
afterEach(() => cleanup());
|
|
53
|
+
it('does not render when closed', () => {
|
|
54
|
+
const { container } = renderPalette();
|
|
55
|
+
expect(container.querySelector('.command-palette')).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
it('renders the palette container when open', async () => {
|
|
58
|
+
const { container } = renderPalette();
|
|
59
|
+
await openPalette(container);
|
|
60
|
+
expect(container.querySelector('.command-palette')).not.toBeNull();
|
|
61
|
+
});
|
|
62
|
+
it('has role="dialog" on the palette container', async () => {
|
|
63
|
+
const { container } = renderPalette();
|
|
64
|
+
await openPalette(container);
|
|
65
|
+
expect(container.querySelector('.command-palette').getAttribute('role')).toBe('dialog');
|
|
66
|
+
});
|
|
67
|
+
it('shows the command list with commands when open', async () => {
|
|
68
|
+
const { container } = renderPalette();
|
|
69
|
+
await openPalette(container);
|
|
70
|
+
expect(container.querySelectorAll('[role="option"]').length).toBe(3);
|
|
71
|
+
});
|
|
72
|
+
it('renders command list with role="listbox"', async () => {
|
|
73
|
+
const { container } = renderPalette();
|
|
74
|
+
await openPalette(container);
|
|
75
|
+
expect(container.querySelector('[role="listbox"]')).not.toBeNull();
|
|
76
|
+
});
|
|
77
|
+
it('renders each command option with role="option"', async () => {
|
|
78
|
+
const { container } = renderPalette();
|
|
79
|
+
await openPalette(container);
|
|
80
|
+
const options = container.querySelectorAll('[role="option"]');
|
|
81
|
+
expect(options.length).toBe(3);
|
|
82
|
+
});
|
|
83
|
+
it('clicking a command selects it and shows parameter chips', async () => {
|
|
84
|
+
const { container } = renderPalette();
|
|
85
|
+
await openPalette(container);
|
|
86
|
+
const options = container.querySelectorAll('[role="option"]');
|
|
87
|
+
await fireEvent.click(options[0]);
|
|
88
|
+
expect(container.querySelectorAll('.param-chip').length).toBe(2);
|
|
89
|
+
});
|
|
90
|
+
it('shows parameter chips for the active command', async () => {
|
|
91
|
+
const { container } = renderPalette();
|
|
92
|
+
await openPalette(container);
|
|
93
|
+
await fireEvent.click(container.querySelectorAll('[role="option"]')[0]);
|
|
94
|
+
const chips = container.querySelectorAll('.param-chip');
|
|
95
|
+
expect(chips[0].textContent).toContain('user');
|
|
96
|
+
expect(chips[1].textContent).toContain('role');
|
|
97
|
+
});
|
|
98
|
+
it('displays keyboard help text', async () => {
|
|
99
|
+
const { container } = renderPalette();
|
|
100
|
+
await openPalette(container);
|
|
101
|
+
const help = container.querySelector('.help');
|
|
102
|
+
expect(help).not.toBeNull();
|
|
103
|
+
expect(help.textContent).toContain('Enter');
|
|
104
|
+
expect(help.textContent).toContain('Esc');
|
|
105
|
+
});
|
|
106
|
+
it('calls onClose when Escape is pressed in browse mode', async () => {
|
|
107
|
+
const handleClose = vi.fn();
|
|
108
|
+
const { container } = renderPalette({ onClose: handleClose });
|
|
109
|
+
await openPalette(container);
|
|
110
|
+
await fireEvent.keyDown(window, { key: 'Escape' });
|
|
111
|
+
expect(handleClose).toHaveBeenCalledTimes(1);
|
|
112
|
+
});
|
|
113
|
+
it('shows commands when open in browse mode', async () => {
|
|
114
|
+
const { container } = renderPalette();
|
|
115
|
+
await openPalette(container);
|
|
116
|
+
const options = container.querySelectorAll('[role="option"]');
|
|
117
|
+
expect(options.length).toBe(3);
|
|
118
|
+
});
|
|
119
|
+
it('marks required parameters with the required class', async () => {
|
|
120
|
+
const { container } = renderPalette();
|
|
121
|
+
await openPalette(container);
|
|
122
|
+
await fireEvent.click(container.querySelectorAll('[role="option"]')[0]);
|
|
123
|
+
const chips = container.querySelectorAll('.param-chip');
|
|
124
|
+
expect(chips[0].classList.contains('required')).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
it('marks the current parameter with the current class', async () => {
|
|
127
|
+
const { container } = renderPalette();
|
|
128
|
+
await openPalette(container);
|
|
129
|
+
await fireEvent.click(container.querySelectorAll('[role="option"]')[0]);
|
|
130
|
+
const chips = container.querySelectorAll('.param-chip');
|
|
131
|
+
expect(chips[0].classList.contains('current')).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
it('marks a filled parameter with the filled class', async () => {
|
|
134
|
+
const { container } = renderPalette();
|
|
135
|
+
await openPalette(container);
|
|
136
|
+
await fireEvent.click(container.querySelectorAll('[role="option"]')[0]);
|
|
137
|
+
const input = container.querySelector('input');
|
|
138
|
+
await fireEvent.input(input, { target: { value: 'alice' } });
|
|
139
|
+
await fireEvent.keyDown(input, { key: 'Enter' });
|
|
140
|
+
const chips = container.querySelectorAll('.param-chip');
|
|
141
|
+
expect(chips[0].classList.contains('filled')).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
it('shows success feedback after successful command execution', async () => {
|
|
144
|
+
const handleExecute = vi.fn().mockResolvedValue({ success: true, message: 'Invited!' });
|
|
145
|
+
const { container } = renderPalette({ onExecute: handleExecute });
|
|
146
|
+
await openPalette(container);
|
|
147
|
+
await fireEvent.click(container.querySelectorAll('[role="option"]')[0]);
|
|
148
|
+
const input = container.querySelector('input');
|
|
149
|
+
await fireEvent.input(input, { target: { value: 'alice' } });
|
|
150
|
+
await fireEvent.keyDown(input, { key: 'Enter' });
|
|
151
|
+
await new Promise(r => setTimeout(r, 50));
|
|
152
|
+
const feedback = container.querySelector('.feedback');
|
|
153
|
+
expect(feedback).not.toBeNull();
|
|
154
|
+
expect(feedback.classList.contains('success')).toBe(true);
|
|
155
|
+
expect(feedback.textContent).toBe('Invited!');
|
|
156
|
+
});
|
|
157
|
+
it('shows error feedback after failed command execution', async () => {
|
|
158
|
+
const handleExecute = vi.fn().mockResolvedValue({ success: false, message: 'No permission' });
|
|
159
|
+
const { container } = renderPalette({ onExecute: handleExecute });
|
|
160
|
+
await openPalette(container);
|
|
161
|
+
await fireEvent.click(container.querySelectorAll('[role="option"]')[0]);
|
|
162
|
+
const input = container.querySelector('input');
|
|
163
|
+
await fireEvent.input(input, { target: { value: 'alice' } });
|
|
164
|
+
await fireEvent.keyDown(input, { key: 'Enter' });
|
|
165
|
+
await new Promise(r => setTimeout(r, 50));
|
|
166
|
+
const feedback = container.querySelector('.feedback');
|
|
167
|
+
expect(feedback).not.toBeNull();
|
|
168
|
+
expect(feedback.classList.contains('error')).toBe(true);
|
|
169
|
+
expect(feedback.textContent).toBe('No permission');
|
|
170
|
+
});
|
|
171
|
+
it('selects a command on Enter key in browse mode', async () => {
|
|
172
|
+
const { container } = renderPalette();
|
|
173
|
+
await openPalette(container);
|
|
174
|
+
const options = container.querySelectorAll('[role="option"]');
|
|
175
|
+
await fireEvent.keyDown(options[0], { key: 'Enter' });
|
|
176
|
+
expect(container.querySelectorAll('.param-chip').length).toBe(2);
|
|
177
|
+
});
|
|
178
|
+
it('has aria-label on the dialog', async () => {
|
|
179
|
+
const { container } = renderPalette();
|
|
180
|
+
await openPalette(container);
|
|
181
|
+
expect(container.querySelector('.command-palette').getAttribute('aria-label')).toBe('Command palette');
|
|
182
|
+
});
|
|
183
|
+
it('has aria-selected on command options', async () => {
|
|
184
|
+
const { container } = renderPalette();
|
|
185
|
+
await openPalette(container);
|
|
186
|
+
const options = container.querySelectorAll('[role="option"]');
|
|
187
|
+
expect(options[0].getAttribute('aria-selected')).toBe('true');
|
|
188
|
+
expect(options[1].getAttribute('aria-selected')).toBe('false');
|
|
189
|
+
});
|
|
190
|
+
it('renders the slash prefix in browse mode', async () => {
|
|
191
|
+
const { container } = renderPalette();
|
|
192
|
+
await openPalette(container);
|
|
193
|
+
expect(container.querySelector('.slash')).not.toBeNull();
|
|
194
|
+
});
|
|
195
|
+
it('renders command prefix when a command is active', async () => {
|
|
196
|
+
const { container } = renderPalette();
|
|
197
|
+
await openPalette(container);
|
|
198
|
+
await fireEvent.click(container.querySelectorAll('[role="option"]')[0]);
|
|
199
|
+
expect(container.querySelector('.command-prefix')).not.toBeNull();
|
|
200
|
+
expect(container.querySelector('.command-prefix').textContent).toBe('/grove,invite');
|
|
201
|
+
});
|
|
202
|
+
});
|