@d34dman/flowdrop 0.0.61 → 0.0.63
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/README.md +6 -0
- package/dist/adapters/WorkflowAdapter.d.ts +1 -1
- package/dist/adapters/agentspec/AgentSpecAdapter.js +3 -1
- package/dist/api/client.d.ts +4 -0
- package/dist/api/client.js +6 -1
- package/dist/api/enhanced-client.js +7 -6
- package/dist/components/App.svelte +143 -219
- package/dist/components/CanvasBanner.stories.svelte +25 -0
- package/dist/components/CanvasBanner.stories.svelte.d.ts +27 -0
- package/dist/components/CanvasBanner.svelte +2 -2
- package/dist/components/ConfigForm.svelte +37 -36
- package/dist/components/ConfigPanel.stories.svelte +38 -0
- package/dist/components/ConfigPanel.stories.svelte.d.ts +27 -0
- package/dist/components/ConfigPanel.svelte +2 -2
- package/dist/components/ConnectionLine.svelte +2 -2
- package/dist/components/FlowDropZone.svelte +18 -2
- package/dist/components/FlowDropZone.svelte.d.ts +2 -0
- package/dist/components/LoadingSpinner.stories.svelte +30 -0
- package/dist/components/LoadingSpinner.stories.svelte.d.ts +27 -0
- package/dist/components/Logo.stories.svelte +22 -0
- package/dist/components/Logo.stories.svelte.d.ts +27 -0
- package/dist/components/Logo.svelte +33 -13
- package/dist/components/Logo.svelte.d.ts +1 -1
- package/dist/components/MarkdownDisplay.stories.svelte +21 -0
- package/dist/components/MarkdownDisplay.stories.svelte.d.ts +27 -0
- package/dist/components/MarkdownDisplay.svelte +4 -3
- package/dist/components/Navbar.stories.svelte +41 -0
- package/dist/components/Navbar.stories.svelte.d.ts +27 -0
- package/dist/components/Navbar.svelte +4 -4
- package/dist/components/NodeSidebar.svelte +12 -12
- package/dist/components/NodeStatusOverlay.stories.svelte +74 -0
- package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +27 -0
- package/dist/components/PipelineStatus.svelte +11 -4
- package/dist/components/PortCoordinateTracker.svelte +1 -1
- package/dist/components/SchemaForm.stories.svelte +101 -0
- package/dist/components/SchemaForm.stories.svelte.d.ts +27 -0
- package/dist/components/SchemaForm.svelte +17 -12
- package/dist/components/SettingsModal.svelte +3 -3
- package/dist/components/SettingsPanel.svelte +23 -22
- package/dist/components/StatusIcon.stories.svelte +60 -0
- package/dist/components/StatusIcon.stories.svelte.d.ts +27 -0
- package/dist/components/StatusIcon.svelte +7 -0
- package/dist/components/StatusLabel.stories.svelte +17 -0
- package/dist/components/StatusLabel.stories.svelte.d.ts +27 -0
- package/dist/components/ThemeToggle.stories.svelte +25 -0
- package/dist/components/ThemeToggle.stories.svelte.d.ts +27 -0
- package/dist/components/ThemeToggle.svelte +8 -8
- package/dist/components/UniversalNode.svelte +1 -1
- package/dist/components/WorkflowEditor.svelte +298 -298
- package/dist/components/form/FormAutocomplete.svelte +20 -19
- package/dist/components/form/FormCheckboxGroup.stories.svelte +28 -0
- package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormField.svelte +3 -3
- package/dist/components/form/FormFieldLight.svelte +2 -2
- package/dist/components/form/FormFieldWrapper.stories.svelte +31 -0
- package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormFieldset.svelte +7 -7
- package/dist/components/form/FormNumberField.stories.svelte +33 -0
- package/dist/components/form/FormNumberField.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormRangeField.stories.svelte +31 -0
- package/dist/components/form/FormRangeField.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormSelect.stories.svelte +50 -0
- package/dist/components/form/FormSelect.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormTemplateEditor.svelte +2 -1
- package/dist/components/form/FormTextField.stories.svelte +30 -0
- package/dist/components/form/FormTextField.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormTextarea.stories.svelte +31 -0
- package/dist/components/form/FormTextarea.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormToggle.stories.svelte +30 -0
- package/dist/components/form/FormToggle.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormUISchemaRenderer.svelte +1 -1
- package/dist/components/form/types.d.ts +15 -47
- package/dist/components/interrupt/ChoicePrompt.stories.svelte +43 -0
- package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +27 -0
- package/dist/components/interrupt/ChoicePrompt.svelte +24 -24
- package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +49 -0
- package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +27 -0
- package/dist/components/interrupt/ConfirmationPrompt.svelte +19 -19
- package/dist/components/interrupt/FormPrompt.svelte +15 -15
- package/dist/components/interrupt/InterruptBubble.svelte +202 -236
- package/dist/components/interrupt/InterruptBubble.svelte.d.ts +1 -1
- package/dist/components/interrupt/ReviewPrompt.stories.svelte +46 -0
- package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +27 -0
- package/dist/components/interrupt/ReviewPrompt.svelte +842 -0
- package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +23 -0
- package/dist/components/interrupt/TextInputPrompt.stories.svelte +34 -0
- package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +27 -0
- package/dist/components/interrupt/TextInputPrompt.svelte +21 -21
- package/dist/components/nodes/GatewayNode.stories.svelte +76 -0
- package/dist/components/nodes/GatewayNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/GatewayNode.svelte +19 -17
- package/dist/components/nodes/IdeaNode.stories.svelte +48 -0
- package/dist/components/nodes/IdeaNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/IdeaNode.svelte +10 -26
- package/dist/components/nodes/NotesNode.stories.svelte +69 -0
- package/dist/components/nodes/NotesNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/NotesNode.svelte +8 -8
- package/dist/components/nodes/SimpleNode.stories.svelte +101 -0
- package/dist/components/nodes/SimpleNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/SimpleNode.svelte +16 -24
- package/dist/components/nodes/SquareNode.stories.svelte +56 -0
- package/dist/components/nodes/SquareNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/SquareNode.svelte +13 -21
- package/dist/components/nodes/TerminalNode.stories.svelte +25 -0
- package/dist/components/nodes/TerminalNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/TerminalNode.svelte +7 -7
- package/dist/components/nodes/ToolNode.stories.svelte +71 -0
- package/dist/components/nodes/ToolNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/ToolNode.svelte +7 -15
- package/dist/components/nodes/WorkflowNode.stories.svelte +50 -0
- package/dist/components/nodes/WorkflowNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/WorkflowNode.svelte +13 -13
- package/dist/components/playground/ChatPanel.svelte +48 -48
- package/dist/components/playground/ExecutionLogs.svelte +23 -23
- package/dist/components/playground/InputCollector.svelte +24 -24
- package/dist/components/playground/MessageBubble.stories.svelte +49 -0
- package/dist/components/playground/MessageBubble.stories.svelte.d.ts +27 -0
- package/dist/components/playground/MessageBubble.svelte +49 -46
- package/dist/components/playground/Playground.svelte +194 -129
- package/dist/components/playground/PlaygroundModal.svelte +5 -5
- package/dist/components/playground/SessionManager.svelte +26 -26
- package/dist/config/constants.d.ts +22 -0
- package/dist/config/constants.js +22 -0
- package/dist/config/endpoints.d.ts +19 -0
- package/dist/config/runtimeConfig.js +2 -1
- package/dist/core/index.d.ts +5 -2
- package/dist/core/index.js +9 -1
- package/dist/editor/index.d.ts +13 -9
- package/dist/editor/index.js +15 -11
- package/dist/form/code.d.ts +2 -1
- package/dist/form/code.js +1 -3
- package/dist/form/markdown.d.ts +2 -1
- package/dist/form/markdown.js +1 -3
- package/dist/helpers/workflowEditorHelper.js +18 -33
- package/dist/mocks/app-forms.js +1 -0
- package/dist/mocks/app-navigation.js +3 -1
- package/dist/mocks/app-stores.d.ts +4 -4
- package/dist/playground/index.d.ts +4 -3
- package/dist/playground/index.js +12 -10
- package/dist/playground/mount.js +6 -13
- package/dist/services/agentSpecExecutionService.js +2 -1
- package/dist/services/api.js +10 -18
- package/dist/services/apiVariableService.js +2 -1
- package/dist/services/autoSaveService.d.ts +3 -3
- package/dist/services/autoSaveService.js +21 -17
- package/dist/services/categoriesApi.js +13 -5
- package/dist/services/draftStorage.js +5 -4
- package/dist/services/dynamicSchemaService.js +4 -4
- package/dist/services/globalSave.d.ts +60 -11
- package/dist/services/globalSave.js +160 -83
- package/dist/services/historyService.d.ts +2 -1
- package/dist/services/historyService.js +7 -3
- package/dist/services/interruptService.js +9 -8
- package/dist/services/nodeExecutionService.js +14 -6
- package/dist/services/playgroundService.js +2 -1
- package/dist/services/portConfigApi.js +11 -7
- package/dist/services/toastService.d.ts +1 -1
- package/dist/services/toastService.js +6 -5
- package/dist/services/variableService.js +3 -2
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.js +1 -1
- package/dist/stores/{categoriesStore.d.ts → categoriesStore.svelte.d.ts} +3 -3
- package/dist/stores/{categoriesStore.js → categoriesStore.svelte.js} +15 -18
- package/dist/stores/editorStateMachine.svelte.d.ts +42 -0
- package/dist/stores/editorStateMachine.svelte.js +132 -0
- package/dist/stores/{historyStore.d.ts → historyStore.svelte.d.ts} +18 -15
- package/dist/stores/{historyStore.js → historyStore.svelte.js} +40 -21
- package/dist/stores/{interruptStore.d.ts → interruptStore.svelte.d.ts} +16 -15
- package/dist/stores/{interruptStore.js → interruptStore.svelte.js} +85 -94
- package/dist/stores/{playgroundStore.d.ts → playgroundStore.svelte.d.ts} +41 -33
- package/dist/stores/{playgroundStore.js → playgroundStore.svelte.js} +164 -84
- package/dist/stores/{portCoordinateStore.d.ts → portCoordinateStore.svelte.d.ts} +10 -4
- package/dist/stores/{portCoordinateStore.js → portCoordinateStore.svelte.js} +38 -35
- package/dist/stores/{settingsStore.d.ts → settingsStore.svelte.d.ts} +45 -28
- package/dist/stores/{settingsStore.js → settingsStore.svelte.js} +169 -128
- package/dist/stores/{workflowStore.d.ts → workflowStore.svelte.d.ts} +101 -65
- package/dist/stores/{workflowStore.js → workflowStore.svelte.js} +285 -239
- package/dist/stories/CanvasDecorator.svelte +50 -0
- package/dist/stories/CanvasDecorator.svelte.d.ts +8 -0
- package/dist/stories/NodeDecorator.svelte +74 -0
- package/dist/stories/NodeDecorator.svelte.d.ts +8 -0
- package/dist/stories/utils.d.ts +93 -0
- package/dist/stories/utils.js +122 -0
- package/dist/styles/base.css +114 -61
- package/dist/styles/toast.css +2 -2
- package/dist/styles/tokens.css +250 -185
- package/dist/svelte-app.d.ts +0 -6
- package/dist/svelte-app.js +13 -31
- package/dist/types/index.d.ts +2 -0
- package/dist/types/interrupt.d.ts +89 -5
- package/dist/types/interrupt.js +13 -1
- package/dist/types/playground.d.ts +5 -0
- package/dist/types/settings.js +1 -1
- package/dist/utils/colors.js +4 -4
- package/dist/utils/connections.js +33 -8
- package/dist/utils/icons.js +1 -1
- package/dist/utils/logger.d.ts +47 -0
- package/dist/utils/logger.js +72 -0
- package/dist/utils/nodeWrapper.js +1 -1
- package/dist/utils/sanitize.d.ts +19 -0
- package/dist/utils/sanitize.js +31 -0
- package/dist/utils/validation.d.ts +29 -0
- package/dist/utils/validation.js +39 -0
- package/package.json +243 -232
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import Icon from '@iconify/svelte';
|
|
11
11
|
import { slide } from 'svelte/transition';
|
|
12
12
|
import type { PlaygroundMessage, PlaygroundMessageLevel } from '../../types/playground.js';
|
|
13
|
-
import {
|
|
13
|
+
import { getLogMessages } from '../../stores/playgroundStore.svelte.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Component props
|
|
@@ -37,19 +37,19 @@
|
|
|
37
37
|
*/
|
|
38
38
|
const filteredLogs = $derived(
|
|
39
39
|
levelFilter === 'all'
|
|
40
|
-
?
|
|
41
|
-
:
|
|
40
|
+
? getLogMessages()
|
|
41
|
+
: getLogMessages().filter((log) => log.metadata?.level === levelFilter)
|
|
42
42
|
);
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Count of logs by level
|
|
46
46
|
*/
|
|
47
47
|
const logCounts = $derived({
|
|
48
|
-
all:
|
|
49
|
-
info:
|
|
50
|
-
warning:
|
|
51
|
-
error:
|
|
52
|
-
debug:
|
|
48
|
+
all: getLogMessages().length,
|
|
49
|
+
info: getLogMessages().filter((l) => l.metadata?.level === 'info').length,
|
|
50
|
+
warning: getLogMessages().filter((l) => l.metadata?.level === 'warning').length,
|
|
51
|
+
error: getLogMessages().filter((l) => l.metadata?.level === 'error').length,
|
|
52
|
+
debug: getLogMessages().filter((l) => l.metadata?.level === 'debug').length
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
/**
|
|
@@ -247,7 +247,7 @@
|
|
|
247
247
|
align-items: center;
|
|
248
248
|
justify-content: space-between;
|
|
249
249
|
width: 100%;
|
|
250
|
-
padding: var(--fd-space-
|
|
250
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
251
251
|
border: none;
|
|
252
252
|
background: transparent;
|
|
253
253
|
cursor: pointer;
|
|
@@ -261,7 +261,7 @@
|
|
|
261
261
|
.execution-logs__title {
|
|
262
262
|
display: flex;
|
|
263
263
|
align-items: center;
|
|
264
|
-
gap: var(--fd-space-
|
|
264
|
+
gap: var(--fd-space-xs);
|
|
265
265
|
font-size: var(--fd-text-sm);
|
|
266
266
|
font-weight: 500;
|
|
267
267
|
color: var(--fd-foreground);
|
|
@@ -273,7 +273,7 @@
|
|
|
273
273
|
justify-content: center;
|
|
274
274
|
min-width: 1.25rem;
|
|
275
275
|
height: 1.25rem;
|
|
276
|
-
padding: 0 var(--fd-space-
|
|
276
|
+
padding: 0 var(--fd-space-3xs);
|
|
277
277
|
border-radius: var(--fd-radius-full);
|
|
278
278
|
font-size: var(--fd-text-xs);
|
|
279
279
|
font-weight: 600;
|
|
@@ -310,18 +310,18 @@
|
|
|
310
310
|
display: flex;
|
|
311
311
|
align-items: center;
|
|
312
312
|
justify-content: space-between;
|
|
313
|
-
padding: var(--fd-space-
|
|
313
|
+
padding: var(--fd-space-xs) var(--fd-space-xl);
|
|
314
314
|
background-color: var(--fd-background);
|
|
315
315
|
border-bottom: 1px solid var(--fd-border);
|
|
316
316
|
}
|
|
317
317
|
|
|
318
318
|
.execution-logs__filters {
|
|
319
319
|
display: flex;
|
|
320
|
-
gap: var(--fd-space-
|
|
320
|
+
gap: var(--fd-space-3xs);
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
.execution-logs__filter {
|
|
324
|
-
padding: var(--fd-space-
|
|
324
|
+
padding: var(--fd-space-3xs) var(--fd-space-xs);
|
|
325
325
|
border: 1px solid transparent;
|
|
326
326
|
border-radius: var(--fd-radius-md);
|
|
327
327
|
background: transparent;
|
|
@@ -360,8 +360,8 @@
|
|
|
360
360
|
display: flex;
|
|
361
361
|
align-items: center;
|
|
362
362
|
justify-content: center;
|
|
363
|
-
width:
|
|
364
|
-
height:
|
|
363
|
+
width: var(--fd-playground-icon-btn-size);
|
|
364
|
+
height: var(--fd-playground-icon-btn-size);
|
|
365
365
|
border: 1px solid var(--fd-border);
|
|
366
366
|
border-radius: var(--fd-radius-md);
|
|
367
367
|
background: var(--fd-background);
|
|
@@ -383,25 +383,25 @@
|
|
|
383
383
|
/* Logs List */
|
|
384
384
|
.execution-logs__list {
|
|
385
385
|
overflow-y: auto;
|
|
386
|
-
font-family:
|
|
386
|
+
font-family: var(--fd-font-mono);
|
|
387
387
|
font-size: var(--fd-text-xs);
|
|
388
|
-
line-height:
|
|
388
|
+
line-height: var(--fd-leading-normal);
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
.execution-logs__empty {
|
|
392
392
|
display: flex;
|
|
393
393
|
align-items: center;
|
|
394
394
|
justify-content: center;
|
|
395
|
-
gap: var(--fd-space-
|
|
396
|
-
padding: var(--fd-space-
|
|
395
|
+
gap: var(--fd-space-xs);
|
|
396
|
+
padding: var(--fd-space-4xl);
|
|
397
397
|
color: var(--fd-muted-foreground);
|
|
398
398
|
}
|
|
399
399
|
|
|
400
400
|
.execution-logs__entry {
|
|
401
401
|
display: flex;
|
|
402
402
|
align-items: flex-start;
|
|
403
|
-
gap: var(--fd-space-
|
|
404
|
-
padding: var(--fd-space-
|
|
403
|
+
gap: var(--fd-space-xs);
|
|
404
|
+
padding: var(--fd-space-3xs) var(--fd-space-xl);
|
|
405
405
|
border-bottom: 1px solid var(--fd-border-muted);
|
|
406
406
|
background-color: var(--fd-background);
|
|
407
407
|
}
|
|
@@ -464,7 +464,7 @@
|
|
|
464
464
|
|
|
465
465
|
.execution-logs__entry-node {
|
|
466
466
|
flex-shrink: 0;
|
|
467
|
-
padding: 0.125rem var(--fd-space-
|
|
467
|
+
padding: 0.125rem var(--fd-space-3xs);
|
|
468
468
|
background-color: var(--fd-secondary);
|
|
469
469
|
border-radius: var(--fd-radius-sm);
|
|
470
470
|
color: var(--fd-muted-foreground);
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import Icon from '@iconify/svelte';
|
|
11
11
|
import { slide } from 'svelte/transition';
|
|
12
12
|
import type { PlaygroundInputField } from '../../types/playground.js';
|
|
13
|
-
import {
|
|
13
|
+
import { getInputFields, getHasChatInput } from '../../stores/playgroundStore.svelte.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Component props
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
*/
|
|
42
42
|
$effect(() => {
|
|
43
43
|
// Only initialize once when we have input fields and haven't initialized yet
|
|
44
|
-
if (
|
|
44
|
+
if (getInputFields().length > 0 && !hasInitializedDefaults) {
|
|
45
45
|
hasInitializedDefaults = true;
|
|
46
46
|
|
|
47
47
|
// Only set values if there are actual defaults to set
|
|
48
48
|
const initialValues: Record<string, unknown> = {};
|
|
49
49
|
let hasDefaults = false;
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
getInputFields().forEach((field) => {
|
|
52
52
|
if (field.defaultValue !== undefined) {
|
|
53
53
|
initialValues[`${field.nodeId}:${field.fieldId}`] = field.defaultValue;
|
|
54
54
|
hasDefaults = true;
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
*/
|
|
118
118
|
function resetToDefaults(): void {
|
|
119
119
|
const defaultValues: Record<string, unknown> = {};
|
|
120
|
-
|
|
120
|
+
getInputFields().forEach((field) => {
|
|
121
121
|
if (field.defaultValue !== undefined) {
|
|
122
122
|
defaultValues[`${field.nodeId}:${field.fieldId}`] = field.defaultValue;
|
|
123
123
|
}
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
}
|
|
128
128
|
</script>
|
|
129
129
|
|
|
130
|
-
{#if
|
|
130
|
+
{#if getInputFields().length > 0}
|
|
131
131
|
<div class="input-collector" class:input-collector--expanded={isExpanded}>
|
|
132
132
|
<!-- Header -->
|
|
133
133
|
<button
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
<div class="input-collector__title">
|
|
140
140
|
<Icon icon="mdi:form-textbox" />
|
|
141
141
|
<span>Workflow Inputs</span>
|
|
142
|
-
<span class="input-collector__count">{
|
|
142
|
+
<span class="input-collector__count">{getInputFields().length}</span>
|
|
143
143
|
</div>
|
|
144
144
|
<Icon
|
|
145
145
|
icon="mdi:chevron-down"
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
<!-- Content -->
|
|
151
151
|
{#if isExpanded}
|
|
152
152
|
<div class="input-collector__content" transition:slide={{ duration: 200 }}>
|
|
153
|
-
{#if
|
|
153
|
+
{#if getHasChatInput()}
|
|
154
154
|
<div class="input-collector__hint">
|
|
155
155
|
<Icon icon="mdi:information-outline" />
|
|
156
156
|
<span>Chat input will be collected from the message field below</span>
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
{/if}
|
|
159
159
|
|
|
160
160
|
<div class="input-collector__fields">
|
|
161
|
-
{#each
|
|
161
|
+
{#each getInputFields() as field (field.nodeId + ':' + field.fieldId)}
|
|
162
162
|
<div class="input-collector__field">
|
|
163
163
|
<label class="input-collector__label" for="input-{field.nodeId}-{field.fieldId}">
|
|
164
164
|
{field.label}
|
|
@@ -264,7 +264,7 @@
|
|
|
264
264
|
align-items: center;
|
|
265
265
|
justify-content: space-between;
|
|
266
266
|
width: 100%;
|
|
267
|
-
padding: var(--fd-space-
|
|
267
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
268
268
|
border: none;
|
|
269
269
|
background: transparent;
|
|
270
270
|
cursor: pointer;
|
|
@@ -278,7 +278,7 @@
|
|
|
278
278
|
.input-collector__title {
|
|
279
279
|
display: flex;
|
|
280
280
|
align-items: center;
|
|
281
|
-
gap: var(--fd-space-
|
|
281
|
+
gap: var(--fd-space-xs);
|
|
282
282
|
font-size: var(--fd-text-sm);
|
|
283
283
|
font-weight: 500;
|
|
284
284
|
color: var(--fd-foreground);
|
|
@@ -290,7 +290,7 @@
|
|
|
290
290
|
justify-content: center;
|
|
291
291
|
min-width: 1.25rem;
|
|
292
292
|
height: 1.25rem;
|
|
293
|
-
padding: 0 var(--fd-space-
|
|
293
|
+
padding: 0 var(--fd-space-3xs);
|
|
294
294
|
border-radius: var(--fd-radius-full);
|
|
295
295
|
font-size: var(--fd-text-xs);
|
|
296
296
|
font-weight: 600;
|
|
@@ -309,15 +309,15 @@
|
|
|
309
309
|
|
|
310
310
|
/* Content */
|
|
311
311
|
.input-collector__content {
|
|
312
|
-
padding: 0 var(--fd-space-
|
|
312
|
+
padding: 0 var(--fd-space-xl) var(--fd-space-xl);
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
.input-collector__hint {
|
|
316
316
|
display: flex;
|
|
317
317
|
align-items: center;
|
|
318
|
-
gap: var(--fd-space-
|
|
319
|
-
padding: var(--fd-space-
|
|
320
|
-
margin-bottom: var(--fd-space-
|
|
318
|
+
gap: var(--fd-space-xs);
|
|
319
|
+
padding: var(--fd-space-xs) var(--fd-space-md);
|
|
320
|
+
margin-bottom: var(--fd-space-xl);
|
|
321
321
|
background-color: var(--fd-info-muted);
|
|
322
322
|
border-radius: var(--fd-radius-lg);
|
|
323
323
|
font-size: var(--fd-text-sm);
|
|
@@ -328,13 +328,13 @@
|
|
|
328
328
|
.input-collector__fields {
|
|
329
329
|
display: flex;
|
|
330
330
|
flex-direction: column;
|
|
331
|
-
gap: var(--fd-space-
|
|
331
|
+
gap: var(--fd-space-xl);
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
.input-collector__field {
|
|
335
335
|
display: flex;
|
|
336
336
|
flex-direction: column;
|
|
337
|
-
gap: var(--fd-space-
|
|
337
|
+
gap: var(--fd-space-3xs);
|
|
338
338
|
}
|
|
339
339
|
|
|
340
340
|
.input-collector__label {
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
.input-collector__input,
|
|
351
351
|
.input-collector__select,
|
|
352
352
|
.input-collector__textarea {
|
|
353
|
-
padding: var(--fd-space-
|
|
353
|
+
padding: var(--fd-space-xs) var(--fd-space-md);
|
|
354
354
|
border: 1px solid var(--fd-border);
|
|
355
355
|
border-radius: var(--fd-radius-lg);
|
|
356
356
|
font-size: var(--fd-text-sm);
|
|
@@ -387,7 +387,7 @@
|
|
|
387
387
|
.input-collector__checkbox-wrapper {
|
|
388
388
|
display: flex;
|
|
389
389
|
align-items: center;
|
|
390
|
-
gap: var(--fd-space-
|
|
390
|
+
gap: var(--fd-space-xs);
|
|
391
391
|
cursor: pointer;
|
|
392
392
|
}
|
|
393
393
|
|
|
@@ -411,16 +411,16 @@
|
|
|
411
411
|
|
|
412
412
|
/* Actions */
|
|
413
413
|
.input-collector__actions {
|
|
414
|
-
margin-top: var(--fd-space-
|
|
415
|
-
padding-top: var(--fd-space-
|
|
414
|
+
margin-top: var(--fd-space-xl);
|
|
415
|
+
padding-top: var(--fd-space-xl);
|
|
416
416
|
border-top: 1px solid var(--fd-border-muted);
|
|
417
417
|
}
|
|
418
418
|
|
|
419
419
|
.input-collector__reset {
|
|
420
420
|
display: flex;
|
|
421
421
|
align-items: center;
|
|
422
|
-
gap: var(--fd-space-
|
|
423
|
-
padding: var(--fd-space-
|
|
422
|
+
gap: var(--fd-space-3xs);
|
|
423
|
+
padding: var(--fd-space-3xs) var(--fd-space-md);
|
|
424
424
|
border: 1px solid var(--fd-border);
|
|
425
425
|
border-radius: var(--fd-radius-md);
|
|
426
426
|
background: var(--fd-background);
|
|
@@ -438,7 +438,7 @@
|
|
|
438
438
|
/* Responsive */
|
|
439
439
|
@media (max-width: 640px) {
|
|
440
440
|
.input-collector__content {
|
|
441
|
-
padding: 0 var(--fd-space-
|
|
441
|
+
padding: 0 var(--fd-space-md) var(--fd-space-md);
|
|
442
442
|
}
|
|
443
443
|
}
|
|
444
444
|
</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
|
+
import MessageBubble from "./MessageBubble.svelte";
|
|
4
|
+
|
|
5
|
+
const { Story } = defineMeta({
|
|
6
|
+
title: "Playground/MessageBubble",
|
|
7
|
+
component: MessageBubble,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "padded",
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<Story name="User Message" args={{
|
|
16
|
+
message: {
|
|
17
|
+
id: "msg-1",
|
|
18
|
+
role: "user",
|
|
19
|
+
content: "Can you process this workflow for me?",
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
},
|
|
22
|
+
}} />
|
|
23
|
+
|
|
24
|
+
<Story name="Assistant Message" args={{
|
|
25
|
+
message: {
|
|
26
|
+
id: "msg-2",
|
|
27
|
+
role: "assistant",
|
|
28
|
+
content: "I've processed the workflow successfully. Here are the results:\n\n- **Step 1**: Data validated\n- **Step 2**: Transformation applied\n- **Step 3**: Output generated\n\nAll checks passed.",
|
|
29
|
+
timestamp: new Date().toISOString(),
|
|
30
|
+
},
|
|
31
|
+
}} />
|
|
32
|
+
|
|
33
|
+
<Story name="System Message" args={{
|
|
34
|
+
message: {
|
|
35
|
+
id: "msg-3",
|
|
36
|
+
role: "system",
|
|
37
|
+
content: "Workflow execution started",
|
|
38
|
+
timestamp: new Date().toISOString(),
|
|
39
|
+
},
|
|
40
|
+
}} />
|
|
41
|
+
|
|
42
|
+
<Story name="Log Message" args={{
|
|
43
|
+
message: {
|
|
44
|
+
id: "msg-4",
|
|
45
|
+
role: "log",
|
|
46
|
+
content: "[INFO] Processing node: data-transform-1",
|
|
47
|
+
timestamp: new Date().toISOString(),
|
|
48
|
+
},
|
|
49
|
+
}} />
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default MessageBubble;
|
|
2
|
+
type MessageBubble = SvelteComponent<{
|
|
3
|
+
[x: string]: never;
|
|
4
|
+
}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {}> & {
|
|
7
|
+
$$bindings?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
declare const MessageBubble: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
[x: string]: never;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}, {}, string>;
|
|
14
|
+
import MessageBubble from "./MessageBubble.svelte";
|
|
15
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
16
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
17
|
+
$$bindings?: Bindings;
|
|
18
|
+
} & Exports;
|
|
19
|
+
(internal: unknown, props: {
|
|
20
|
+
$$events?: Events;
|
|
21
|
+
$$slots?: Slots;
|
|
22
|
+
}): Exports & {
|
|
23
|
+
$set?: any;
|
|
24
|
+
$on?: any;
|
|
25
|
+
};
|
|
26
|
+
z_$$bindings?: Bindings;
|
|
27
|
+
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<script lang="ts">
|
|
12
12
|
import Icon from '@iconify/svelte';
|
|
13
13
|
import { marked } from 'marked';
|
|
14
|
+
import { sanitizeHtml } from '../../utils/sanitize.js';
|
|
14
15
|
import type {
|
|
15
16
|
PlaygroundMessage,
|
|
16
17
|
PlaygroundMessageMetadata,
|
|
@@ -56,7 +57,9 @@
|
|
|
56
57
|
* Render content as markdown or plain text
|
|
57
58
|
*/
|
|
58
59
|
const renderedContent = $derived(
|
|
59
|
-
enableMarkdown && message.role !== 'log'
|
|
60
|
+
enableMarkdown && message.role !== 'log'
|
|
61
|
+
? sanitizeHtml(marked.parse(message.content || '') as string)
|
|
62
|
+
: message.content
|
|
60
63
|
);
|
|
61
64
|
|
|
62
65
|
/**
|
|
@@ -193,7 +196,7 @@
|
|
|
193
196
|
<!-- Message Text -->
|
|
194
197
|
<div class="message-bubble__text">
|
|
195
198
|
{#if enableMarkdown && message.role !== 'log'}
|
|
196
|
-
<!-- Markdown content -
|
|
199
|
+
<!-- Markdown content - sanitized with DOMPurify to prevent XSS -->
|
|
197
200
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
198
201
|
{@html renderedContent}
|
|
199
202
|
{:else}
|
|
@@ -225,9 +228,9 @@
|
|
|
225
228
|
<style>
|
|
226
229
|
.message-bubble {
|
|
227
230
|
display: flex;
|
|
228
|
-
gap: var(--fd-space-
|
|
229
|
-
padding: var(--fd-space-
|
|
230
|
-
margin-bottom: var(--fd-space-
|
|
231
|
+
gap: var(--fd-space-md);
|
|
232
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
233
|
+
margin-bottom: var(--fd-space-xs);
|
|
231
234
|
border-radius: var(--fd-radius-xl);
|
|
232
235
|
animation: fadeIn 0.2s ease-out;
|
|
233
236
|
}
|
|
@@ -248,7 +251,7 @@
|
|
|
248
251
|
background-color: var(--fd-muted);
|
|
249
252
|
border: 1px solid var(--fd-border);
|
|
250
253
|
color: var(--fd-foreground);
|
|
251
|
-
margin-left: var(--fd-space-
|
|
254
|
+
margin-left: var(--fd-space-4xl);
|
|
252
255
|
flex-direction: row-reverse;
|
|
253
256
|
}
|
|
254
257
|
|
|
@@ -256,14 +259,14 @@
|
|
|
256
259
|
background-color: var(--fd-card);
|
|
257
260
|
border: 1px solid var(--fd-border);
|
|
258
261
|
color: var(--fd-card-foreground);
|
|
259
|
-
margin-right: var(--fd-space-
|
|
262
|
+
margin-right: var(--fd-space-4xl);
|
|
260
263
|
}
|
|
261
264
|
|
|
262
265
|
.message-bubble--system {
|
|
263
266
|
background-color: var(--fd-muted);
|
|
264
267
|
border: 1px solid var(--fd-border);
|
|
265
268
|
color: var(--fd-muted-foreground);
|
|
266
|
-
margin: 0 var(--fd-space-
|
|
269
|
+
margin: 0 var(--fd-space-xl);
|
|
267
270
|
font-size: var(--fd-text-sm);
|
|
268
271
|
}
|
|
269
272
|
|
|
@@ -271,9 +274,9 @@
|
|
|
271
274
|
background-color: var(--fd-muted);
|
|
272
275
|
border: 1px solid var(--fd-border);
|
|
273
276
|
color: var(--fd-muted-foreground);
|
|
274
|
-
margin: 0 var(--fd-space-
|
|
277
|
+
margin: 0 var(--fd-space-xl);
|
|
275
278
|
font-size: var(--fd-text-sm);
|
|
276
|
-
font-family:
|
|
279
|
+
font-family: var(--fd-font-mono);
|
|
277
280
|
}
|
|
278
281
|
|
|
279
282
|
.message-bubble--log-error {
|
|
@@ -289,14 +292,14 @@
|
|
|
289
292
|
}
|
|
290
293
|
|
|
291
294
|
.message-bubble--last {
|
|
292
|
-
margin-bottom: var(--fd-space-
|
|
295
|
+
margin-bottom: var(--fd-space-xl);
|
|
293
296
|
}
|
|
294
297
|
|
|
295
298
|
/* Avatar */
|
|
296
299
|
.message-bubble__avatar {
|
|
297
300
|
flex-shrink: 0;
|
|
298
|
-
width:
|
|
299
|
-
height:
|
|
301
|
+
width: var(--fd-space-4xl);
|
|
302
|
+
height: var(--fd-space-4xl);
|
|
300
303
|
display: flex;
|
|
301
304
|
align-items: center;
|
|
302
305
|
justify-content: center;
|
|
@@ -322,8 +325,8 @@
|
|
|
322
325
|
.message-bubble--log .message-bubble__avatar {
|
|
323
326
|
background-color: var(--fd-secondary);
|
|
324
327
|
color: var(--fd-muted-foreground);
|
|
325
|
-
width:
|
|
326
|
-
height:
|
|
328
|
+
width: var(--fd-space-3xl);
|
|
329
|
+
height: var(--fd-space-3xl);
|
|
327
330
|
font-size: var(--fd-text-sm);
|
|
328
331
|
}
|
|
329
332
|
|
|
@@ -337,8 +340,8 @@
|
|
|
337
340
|
.message-bubble__header {
|
|
338
341
|
display: flex;
|
|
339
342
|
align-items: center;
|
|
340
|
-
gap: var(--fd-space-
|
|
341
|
-
margin-bottom: var(--fd-space-
|
|
343
|
+
gap: var(--fd-space-xs);
|
|
344
|
+
margin-bottom: var(--fd-space-3xs);
|
|
342
345
|
}
|
|
343
346
|
|
|
344
347
|
.message-bubble--user .message-bubble__header {
|
|
@@ -366,10 +369,10 @@
|
|
|
366
369
|
.message-bubble__log-level {
|
|
367
370
|
display: flex;
|
|
368
371
|
align-items: center;
|
|
369
|
-
gap: var(--fd-space-
|
|
372
|
+
gap: var(--fd-space-3xs);
|
|
370
373
|
font-size: var(--fd-text-xs);
|
|
371
374
|
font-weight: 600;
|
|
372
|
-
padding: 0.125rem var(--fd-space-
|
|
375
|
+
padding: 0.125rem var(--fd-space-3xs);
|
|
373
376
|
border-radius: var(--fd-radius-sm);
|
|
374
377
|
text-transform: uppercase;
|
|
375
378
|
letter-spacing: 0.05em;
|
|
@@ -398,7 +401,7 @@
|
|
|
398
401
|
.message-bubble__timestamp {
|
|
399
402
|
font-size: var(--fd-text-xs);
|
|
400
403
|
color: var(--fd-muted-foreground);
|
|
401
|
-
font-family:
|
|
404
|
+
font-family: var(--fd-font-mono);
|
|
402
405
|
}
|
|
403
406
|
|
|
404
407
|
.message-bubble--user .message-bubble__timestamp {
|
|
@@ -407,19 +410,19 @@
|
|
|
407
410
|
|
|
408
411
|
/* Message text */
|
|
409
412
|
.message-bubble__text {
|
|
410
|
-
line-height:
|
|
413
|
+
line-height: var(--fd-leading-relaxed);
|
|
411
414
|
word-break: break-word;
|
|
412
415
|
}
|
|
413
416
|
|
|
414
417
|
.message-bubble--log .message-bubble__text {
|
|
415
418
|
font-size: var(--fd-text-sm);
|
|
416
|
-
line-height:
|
|
419
|
+
line-height: var(--fd-leading-tight);
|
|
417
420
|
white-space: pre-wrap;
|
|
418
421
|
}
|
|
419
422
|
|
|
420
423
|
/* Markdown styling for message content */
|
|
421
424
|
.message-bubble__text :global(p) {
|
|
422
|
-
margin: 0 0 var(--fd-space-
|
|
425
|
+
margin: 0 0 var(--fd-space-md) 0;
|
|
423
426
|
}
|
|
424
427
|
|
|
425
428
|
.message-bubble__text :global(p:last-child) {
|
|
@@ -432,7 +435,7 @@
|
|
|
432
435
|
.message-bubble__text :global(h4),
|
|
433
436
|
.message-bubble__text :global(h5),
|
|
434
437
|
.message-bubble__text :global(h6) {
|
|
435
|
-
margin: var(--fd-space-
|
|
438
|
+
margin: var(--fd-space-xl) 0 var(--fd-space-xs) 0;
|
|
436
439
|
font-weight: 600;
|
|
437
440
|
line-height: 1.3;
|
|
438
441
|
}
|
|
@@ -460,31 +463,31 @@
|
|
|
460
463
|
|
|
461
464
|
.message-bubble__text :global(ul),
|
|
462
465
|
.message-bubble__text :global(ol) {
|
|
463
|
-
margin: var(--fd-space-
|
|
464
|
-
padding-left: var(--fd-space-
|
|
466
|
+
margin: var(--fd-space-xs) 0;
|
|
467
|
+
padding-left: var(--fd-space-3xl);
|
|
465
468
|
}
|
|
466
469
|
|
|
467
470
|
.message-bubble__text :global(li) {
|
|
468
|
-
margin: var(--fd-space-
|
|
471
|
+
margin: var(--fd-space-3xs) 0;
|
|
469
472
|
}
|
|
470
473
|
|
|
471
474
|
.message-bubble__text :global(code) {
|
|
472
475
|
background-color: var(--fd-secondary);
|
|
473
|
-
padding: 0.125rem var(--fd-space-
|
|
476
|
+
padding: 0.125rem var(--fd-space-3xs);
|
|
474
477
|
border-radius: var(--fd-radius-sm);
|
|
475
|
-
font-family:
|
|
478
|
+
font-family: var(--fd-font-mono);
|
|
476
479
|
font-size: 0.875em;
|
|
477
480
|
}
|
|
478
481
|
|
|
479
482
|
.message-bubble__text :global(pre) {
|
|
480
483
|
background-color: var(--fd-foreground);
|
|
481
484
|
color: var(--fd-background);
|
|
482
|
-
padding: var(--fd-space-
|
|
485
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
483
486
|
border-radius: var(--fd-radius-lg);
|
|
484
487
|
overflow-x: auto;
|
|
485
|
-
margin: var(--fd-space-
|
|
488
|
+
margin: var(--fd-space-md) 0;
|
|
486
489
|
font-size: var(--fd-text-sm);
|
|
487
|
-
line-height:
|
|
490
|
+
line-height: var(--fd-leading-normal);
|
|
488
491
|
}
|
|
489
492
|
|
|
490
493
|
.message-bubble__text :global(pre code) {
|
|
@@ -497,8 +500,8 @@
|
|
|
497
500
|
|
|
498
501
|
.message-bubble__text :global(blockquote) {
|
|
499
502
|
border-left: 3px solid var(--fd-border-strong);
|
|
500
|
-
padding-left: var(--fd-space-
|
|
501
|
-
margin: var(--fd-space-
|
|
503
|
+
padding-left: var(--fd-space-xl);
|
|
504
|
+
margin: var(--fd-space-md) 0;
|
|
502
505
|
color: var(--fd-muted-foreground);
|
|
503
506
|
font-style: italic;
|
|
504
507
|
}
|
|
@@ -515,20 +518,20 @@
|
|
|
515
518
|
.message-bubble__text :global(hr) {
|
|
516
519
|
border: none;
|
|
517
520
|
border-top: 1px solid var(--fd-border);
|
|
518
|
-
margin: var(--fd-space-
|
|
521
|
+
margin: var(--fd-space-xl) 0;
|
|
519
522
|
}
|
|
520
523
|
|
|
521
524
|
.message-bubble__text :global(table) {
|
|
522
525
|
border-collapse: collapse;
|
|
523
526
|
width: 100%;
|
|
524
|
-
margin: var(--fd-space-
|
|
527
|
+
margin: var(--fd-space-md) 0;
|
|
525
528
|
font-size: var(--fd-text-sm);
|
|
526
529
|
}
|
|
527
530
|
|
|
528
531
|
.message-bubble__text :global(th),
|
|
529
532
|
.message-bubble__text :global(td) {
|
|
530
533
|
border: 1px solid var(--fd-border);
|
|
531
|
-
padding: var(--fd-space-
|
|
534
|
+
padding: var(--fd-space-xs) var(--fd-space-md);
|
|
532
535
|
text-align: left;
|
|
533
536
|
}
|
|
534
537
|
|
|
@@ -549,8 +552,8 @@
|
|
|
549
552
|
.message-bubble__footer {
|
|
550
553
|
display: flex;
|
|
551
554
|
align-items: center;
|
|
552
|
-
gap: var(--fd-space-
|
|
553
|
-
margin-top: var(--fd-space-
|
|
555
|
+
gap: var(--fd-space-md);
|
|
556
|
+
margin-top: var(--fd-space-xs);
|
|
554
557
|
font-size: var(--fd-text-xs);
|
|
555
558
|
color: var(--fd-muted-foreground);
|
|
556
559
|
}
|
|
@@ -563,7 +566,7 @@
|
|
|
563
566
|
.message-bubble__duration {
|
|
564
567
|
display: flex;
|
|
565
568
|
align-items: center;
|
|
566
|
-
gap: var(--fd-space-
|
|
569
|
+
gap: var(--fd-space-3xs);
|
|
567
570
|
}
|
|
568
571
|
|
|
569
572
|
/* Responsive */
|
|
@@ -590,16 +593,16 @@
|
|
|
590
593
|
display: flex;
|
|
591
594
|
align-items: center;
|
|
592
595
|
justify-content: center;
|
|
593
|
-
gap: var(--fd-space-
|
|
594
|
-
padding: var(--fd-space-
|
|
595
|
-
margin: var(--fd-space-
|
|
596
|
+
gap: var(--fd-space-3xs);
|
|
597
|
+
padding: var(--fd-space-3xs) var(--fd-space-md);
|
|
598
|
+
margin: var(--fd-space-3xs) 0;
|
|
596
599
|
font-size: var(--fd-text-xs);
|
|
597
600
|
color: var(--fd-muted-foreground);
|
|
598
601
|
text-align: center;
|
|
599
602
|
}
|
|
600
603
|
|
|
601
604
|
.system-notice--last {
|
|
602
|
-
margin-bottom: var(--fd-space-
|
|
605
|
+
margin-bottom: var(--fd-space-md);
|
|
603
606
|
}
|
|
604
607
|
|
|
605
608
|
/* Icon styling - using :global for Iconify component */
|
|
@@ -611,14 +614,14 @@
|
|
|
611
614
|
|
|
612
615
|
.system-notice__text {
|
|
613
616
|
color: var(--fd-muted-foreground);
|
|
614
|
-
line-height:
|
|
617
|
+
line-height: var(--fd-leading-tight);
|
|
615
618
|
}
|
|
616
619
|
|
|
617
620
|
.system-notice__timestamp {
|
|
618
621
|
flex-shrink: 0;
|
|
619
622
|
font-size: 0.625rem;
|
|
620
623
|
color: var(--fd-border-strong);
|
|
621
|
-
font-family:
|
|
624
|
+
font-family: var(--fd-font-mono);
|
|
622
625
|
}
|
|
623
626
|
|
|
624
627
|
/* Responsive: hide timestamp on small screens for compactness */
|