@lokvis/ui-react 0.2.1 → 0.2.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/dist/components/AssetPanel.d.ts.map +1 -1
- package/dist/components/AssetPanel.js +14 -14
- package/dist/components/AssetPanel.js.map +1 -1
- package/dist/components/Canvas.d.ts +4 -4
- package/dist/components/Canvas.d.ts.map +1 -1
- package/dist/components/Canvas.js +8 -8
- package/dist/components/Canvas.js.map +1 -1
- package/dist/components/CommandPalette.d.ts +7 -7
- package/dist/components/CommandPalette.d.ts.map +1 -1
- package/dist/components/CommandPalette.js +10 -10
- package/dist/components/CommandPalette.js.map +1 -1
- package/dist/components/CompareSlider.d.ts +6 -6
- package/dist/components/CompareSlider.d.ts.map +1 -1
- package/dist/components/CompareSlider.js +7 -7
- package/dist/components/CompareSlider.js.map +1 -1
- package/dist/components/DownloadPanel.d.ts +3 -3
- package/dist/components/DownloadPanel.d.ts.map +1 -1
- package/dist/components/DownloadPanel.js +9 -9
- package/dist/components/DownloadPanel.js.map +1 -1
- package/dist/components/ErrorBanner.d.ts +2 -2
- package/dist/components/ErrorBanner.d.ts.map +1 -1
- package/dist/components/ErrorBanner.js +3 -3
- package/dist/components/ErrorBanner.js.map +1 -1
- package/dist/components/ExifPanel.d.ts +1 -1
- package/dist/components/ExifPanel.d.ts.map +1 -1
- package/dist/components/ExifPanel.js +2 -2
- package/dist/components/ExifPanel.js.map +1 -1
- package/dist/components/GlobalDropzone.d.ts +5 -5
- package/dist/components/GlobalDropzone.d.ts.map +1 -1
- package/dist/components/GlobalDropzone.js +6 -6
- package/dist/components/GlobalDropzone.js.map +1 -1
- package/dist/components/HistoryPanel.d.ts +2 -2
- package/dist/components/HistoryPanel.d.ts.map +1 -1
- package/dist/components/HistoryPanel.js +23 -23
- package/dist/components/HistoryPanel.js.map +1 -1
- package/dist/components/Inspector.d.ts.map +1 -1
- package/dist/components/Inspector.js +6 -6
- package/dist/components/Inspector.js.map +1 -1
- package/dist/components/ParamForm.d.ts.map +1 -1
- package/dist/components/ParamForm.js +7 -7
- package/dist/components/ParamForm.js.map +1 -1
- package/dist/components/PipelineBar.d.ts.map +1 -1
- package/dist/components/PipelineBar.js +13 -13
- package/dist/components/PipelineBar.js.map +1 -1
- package/dist/components/ProgressBar.d.ts +4 -4
- package/dist/components/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar.js +8 -8
- package/dist/components/ProgressBar.js.map +1 -1
- package/dist/components/StatusBar.d.ts +3 -3
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +11 -11
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/components/ThemeToggle.d.ts +4 -4
- package/dist/components/ThemeToggle.d.ts.map +1 -1
- package/dist/components/ThemeToggle.js +7 -7
- package/dist/components/ThemeToggle.js.map +1 -1
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +2 -2
- package/dist/components/Toolbar.js.map +1 -1
- package/dist/components/WorkflowEditor.d.ts +6 -6
- package/dist/components/WorkflowEditor.d.ts.map +1 -1
- package/dist/components/WorkflowEditor.js +25 -25
- package/dist/components/WorkflowEditor.js.map +1 -1
- package/dist/components/WorkflowTemplates.d.ts +2 -2
- package/dist/components/WorkflowTemplates.d.ts.map +1 -1
- package/dist/components/WorkflowTemplates.js +3 -3
- package/dist/components/WorkflowTemplates.js.map +1 -1
- package/dist/components/Workspace.d.ts +22 -22
- package/dist/components/Workspace.d.ts.map +1 -1
- package/dist/components/Workspace.js +30 -30
- package/dist/components/Workspace.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/components/AssetPanel.tsx +263 -263
- package/src/components/Canvas.tsx +174 -174
- package/src/components/CommandPalette.tsx +242 -242
- package/src/components/CompareSlider.tsx +163 -163
- package/src/components/DownloadPanel.tsx +203 -203
- package/src/components/ErrorBanner.tsx +64 -64
- package/src/components/ExifPanel.tsx +154 -154
- package/src/components/GlobalDropzone.tsx +170 -170
- package/src/components/HistoryPanel.tsx +219 -219
- package/src/components/Inspector.tsx +136 -136
- package/src/components/ParamForm.tsx +136 -136
- package/src/components/PipelineBar.tsx +98 -98
- package/src/components/ProgressBar.tsx +78 -78
- package/src/components/StatusBar.tsx +148 -148
- package/src/components/ThemeToggle.tsx +98 -98
- package/src/components/Toolbar.tsx +65 -65
- package/src/components/WorkflowEditor.tsx +321 -321
- package/src/components/WorkflowTemplates.tsx +77 -77
- package/src/components/Workspace.tsx +223 -223
- package/src/css-modules.d.ts +3 -0
- package/src/index.ts +4 -0
|
@@ -10,117 +10,117 @@ import { Icon } from '@lokvis/ui-core';
|
|
|
10
10
|
import { useWorkspaceStore } from '../store/index.js';
|
|
11
11
|
|
|
12
12
|
export interface PipelineBarProps {
|
|
13
|
-
|
|
13
|
+
className?: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function PipelineBar({ className = '' }: PipelineBarProps) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
const nodes = useWorkspaceStore((s) => s.nodes);
|
|
18
|
+
const selectedNodeId = useWorkspaceStore((s) => s.selectedNodeId);
|
|
19
|
+
const selectNode = useWorkspaceStore((s) => s.selectNode);
|
|
20
|
+
const removeNode = useWorkspaceStore((s) => s.removeNode);
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
return (
|
|
23
|
+
<div className={`flex h-10 shrink-0 items-center gap-2 border-t border-[var(--lokvis-border)] bg-[var(--lokvis-surface)] px-3 ${className}`}>
|
|
24
|
+
<span className="text-[10px] font-semibold uppercase tracking-wider text-[var(--lokvis-fg-subtle)] shrink-0">
|
|
25
|
+
Pipeline
|
|
26
|
+
</span>
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
{nodes.length === 0 ? (
|
|
29
|
+
<span className="text-[11px] text-[var(--lokvis-fg-subtle)]">
|
|
30
|
+
Empty — add capabilities from the right panel
|
|
31
|
+
</span>
|
|
32
|
+
) : (
|
|
33
|
+
<div className="flex flex-1 items-center gap-1 overflow-x-auto min-w-0">
|
|
34
|
+
{/* Source indicator */}
|
|
35
|
+
<div className="flex items-center gap-1 rounded-md bg-[var(--lokvis-surface-muted)] px-2 py-1 text-[10px] font-medium text-[var(--lokvis-fg-muted)] shrink-0">
|
|
36
|
+
<Icon size={12}><path d="M12 4.5v15m7.5-7.5h-15" /></Icon>
|
|
37
|
+
Source
|
|
38
|
+
</div>
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
{/* Arrow */}
|
|
41
|
+
<Icon size={12} className="shrink-0 text-[var(--lokvis-fg-subtle)]">
|
|
42
|
+
<path d="m9 5 7 7-7 7" />
|
|
43
|
+
</Icon>
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
45
|
+
{/* Nodes */}
|
|
46
|
+
{nodes.map((node, i) => {
|
|
47
|
+
const selected = node.id === selectedNodeId;
|
|
48
|
+
return (
|
|
49
|
+
<React.Fragment key={node.id}>
|
|
50
|
+
<button
|
|
51
|
+
type="button"
|
|
52
|
+
onClick={() => selectNode(node.id)}
|
|
53
|
+
className={`group flex shrink-0 items-center gap-1.5 rounded-md px-2.5 py-1 text-[11px] font-medium transition-all ${
|
|
54
|
+
selected
|
|
55
|
+
? 'bg-[var(--lokvis-primary)]/15 text-[var(--lokvis-primary)] ring-1 ring-[var(--lokvis-primary)]/50'
|
|
56
|
+
: node.status === 'running'
|
|
57
|
+
? 'bg-[var(--lokvis-warning)]/15 text-[var(--lokvis-warning)]'
|
|
58
|
+
: node.status === 'success'
|
|
59
|
+
? 'bg-[var(--lokvis-success)]/15 text-[var(--lokvis-success)]'
|
|
60
|
+
: node.status === 'failed'
|
|
61
|
+
? 'bg-[var(--lokvis-danger)]/15 text-[var(--lokvis-danger)]'
|
|
62
|
+
: 'bg-[var(--lokvis-surface-muted)] text-[var(--lokvis-fg-muted)] hover:bg-[var(--lokvis-border)]'
|
|
63
|
+
}`}
|
|
64
|
+
>
|
|
65
|
+
<span className="font-mono">{node.capability}</span>
|
|
66
|
+
<StatusDot status={node.status} />
|
|
67
|
+
<span
|
|
68
|
+
onClick={(e) => {
|
|
69
|
+
e.stopPropagation();
|
|
70
|
+
removeNode(node.id);
|
|
71
|
+
}}
|
|
72
|
+
className="ml-0.5 rounded p-0.5 opacity-0 transition-opacity group-hover:opacity-100 hover:bg-[var(--lokvis-danger)]/15 hover:text-[var(--lokvis-danger)]"
|
|
73
|
+
role="button"
|
|
74
|
+
aria-label="Remove step"
|
|
75
|
+
>
|
|
76
|
+
<Icon size={10} strokeWidth={3}><path d="M6 18L18 6M6 6l12 12" /></Icon>
|
|
77
|
+
</span>
|
|
78
|
+
</button>
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
80
|
+
{/* Arrow between nodes */}
|
|
81
|
+
{i < nodes.length - 1 && (
|
|
82
|
+
<Icon size={12} className="shrink-0 text-[var(--lokvis-fg-subtle)]">
|
|
83
|
+
<path d="m9 5 7 7-7 7" />
|
|
84
|
+
</Icon>
|
|
85
|
+
)}
|
|
86
|
+
</React.Fragment>
|
|
87
|
+
);
|
|
88
|
+
})}
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
90
|
+
{/* Output indicator */}
|
|
91
|
+
<Icon size={12} className="shrink-0 text-[var(--lokvis-fg-subtle)]">
|
|
92
|
+
<path d="m9 5 7 7-7 7" />
|
|
93
|
+
</Icon>
|
|
94
|
+
<div className="flex items-center gap-1 rounded-md bg-[var(--lokvis-surface-muted)] px-2 py-1 text-[10px] font-medium text-[var(--lokvis-fg-muted)] shrink-0">
|
|
95
|
+
<Icon size={12}><path d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" /></Icon>
|
|
96
|
+
Output
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
101
|
+
{/* Step count */}
|
|
102
|
+
{nodes.length > 0 && (
|
|
103
|
+
<span className="shrink-0 text-[10px] tabular-nums text-[var(--lokvis-fg-subtle)]">
|
|
104
|
+
{nodes.length} step{nodes.length !== 1 ? 's' : ''}
|
|
105
|
+
</span>
|
|
106
|
+
)}
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
function StatusDot({ status }: { status: string }) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
112
|
+
const color =
|
|
113
|
+
status === 'running'
|
|
114
|
+
? 'bg-[var(--lokvis-warning)]'
|
|
115
|
+
: status === 'success'
|
|
116
|
+
? 'bg-[var(--lokvis-success)]'
|
|
117
|
+
: status === 'failed'
|
|
118
|
+
? 'bg-[var(--lokvis-danger)]'
|
|
119
|
+
: status === 'pending'
|
|
120
|
+
? 'bg-[var(--lokvis-fg-subtle)]'
|
|
121
|
+
: 'bg-[var(--lokvis-fg-subtle)]';
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
const animate = status === 'running' ? 'animate-pulse' : '';
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
return <span className={`h-1.5 w-1.5 rounded-full shrink-0 ${color} ${animate}`} />;
|
|
126
126
|
}
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* ProgressBar - 工作流执行进度条 + 取消按钮(W11.6)
|
|
3
3
|
*
|
|
4
4
|
* 展示:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* - 节点完成进度(成功数 / 总数)
|
|
6
|
+
* - 横向进度条(running 时动画)
|
|
7
|
+
* - Cancel 按钮(调用 cancelRun)
|
|
8
|
+
* - 状态消息(statusMessage)
|
|
9
9
|
*
|
|
10
10
|
* 仅在 running 或最近一次执行有结果时显示。
|
|
11
11
|
*
|
|
@@ -17,88 +17,88 @@ import { useWorkspaceStore } from '../store/index.js';
|
|
|
17
17
|
import { useWorkflowProgress } from '../hooks/useWorkflowProgress.js';
|
|
18
18
|
|
|
19
19
|
export interface ProgressBarProps {
|
|
20
|
-
|
|
20
|
+
className?: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function ProgressBar({ className = '' }: ProgressBarProps) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const running = useWorkspaceStore((s) => s.running);
|
|
25
|
+
const statusMessage = useWorkspaceStore((s) => s.statusMessage);
|
|
26
|
+
const cancelRun = useWorkspaceStore((s) => s.cancelRun);
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
// 进度计算抽取到共享 hook(与 StatusBar 共用,避免重复逻辑)
|
|
29
|
+
const { total, done, failedCount, pct, hasFailure } = useWorkflowProgress();
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
// 没有节点或未运行且无最近结果时不渲染
|
|
32
|
+
if (total === 0) return null;
|
|
33
|
+
if (!running && done === 0) return null;
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
35
|
+
return (
|
|
36
|
+
<div
|
|
37
|
+
className={`flex items-center gap-2 border-b border-[var(--lokvis-border)] bg-[var(--lokvis-surface)] px-3 py-1.5 ${className}`}
|
|
38
|
+
role="status"
|
|
39
|
+
aria-live="polite"
|
|
40
|
+
aria-label={`工作流进度:${done} / ${total}`}
|
|
41
|
+
>
|
|
42
|
+
{/* 进度条 */}
|
|
43
|
+
<div className="relative h-1.5 flex-1 overflow-hidden rounded-full bg-[var(--lokvis-border)]">
|
|
44
|
+
<div
|
|
45
|
+
className={`absolute inset-y-0 left-0 transition-all duration-300 ${
|
|
46
|
+
hasFailure
|
|
47
|
+
? 'bg-[var(--lokvis-danger)]'
|
|
48
|
+
: running
|
|
49
|
+
? 'bg-[var(--lokvis-primary)]'
|
|
50
|
+
: 'bg-[var(--lokvis-success)]'
|
|
51
|
+
} ${running ? 'animate-pulse' : ''}`}
|
|
52
|
+
style={{ width: `${pct}%` }}
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
{/* 计数 */}
|
|
57
|
+
<span className="shrink-0 text-[10px] font-medium tabular-nums text-[var(--lokvis-fg-muted)]">
|
|
58
|
+
{done}/{total}
|
|
59
|
+
{failedCount > 0 && (
|
|
60
|
+
<span className="ml-1 text-[var(--lokvis-danger)]">({failedCount} failed)</span>
|
|
61
|
+
)}
|
|
62
|
+
</span>
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
{/* 状态消息(running 时显示) */}
|
|
65
|
+
{running && statusMessage && (
|
|
66
|
+
<span className="hidden shrink-0 truncate text-[10px] text-[var(--lokvis-fg-subtle)] sm:inline">
|
|
67
|
+
{statusMessage}
|
|
68
|
+
</span>
|
|
69
|
+
)}
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
{/* Cancel 按钮(仅 running 时) */}
|
|
72
|
+
{running && (
|
|
73
|
+
<button
|
|
74
|
+
type="button"
|
|
75
|
+
onClick={() => void cancelRun()}
|
|
76
|
+
aria-label="取消运行"
|
|
77
|
+
title="取消运行"
|
|
78
|
+
className="flex shrink-0 items-center gap-1 rounded-md bg-[var(--lokvis-danger)]/10 px-2 py-0.5 text-[10px] font-medium text-[var(--lokvis-danger)] transition-colors hover:bg-[var(--lokvis-danger)]/15"
|
|
79
|
+
>
|
|
80
|
+
<Icon size={10} strokeWidth={3}><path d="M6 6l12 12M6 18L18 6" /></Icon>
|
|
81
|
+
Cancel
|
|
82
|
+
</button>
|
|
83
|
+
)}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
{/* 完成图标(非 running 且有结果) */}
|
|
86
|
+
{!running && done === total && (
|
|
87
|
+
<span
|
|
88
|
+
className={`flex shrink-0 items-center gap-1 text-[10px] font-medium ${
|
|
89
|
+
hasFailure ? 'text-[var(--lokvis-danger)]' : 'text-[var(--lokvis-success)]'
|
|
90
|
+
}`}
|
|
91
|
+
>
|
|
92
|
+
<Icon size={10} strokeWidth={3}>
|
|
93
|
+
{hasFailure ? (
|
|
94
|
+
<path d="M12 2L2 22h20L12 2zM12 9v5M12 17v.01" />
|
|
95
|
+
) : (
|
|
96
|
+
<path d="M20 6L9 17l-5-5" />
|
|
97
|
+
)}
|
|
98
|
+
</Icon>
|
|
99
|
+
{hasFailure ? 'Failed' : 'Done'}
|
|
100
|
+
</span>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
104
|
}
|