@lokvis/ui-react 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/LICENSE +21 -0
  2. package/dist/components/AssetPanel.d.ts +2 -2
  3. package/dist/components/AssetPanel.d.ts.map +1 -1
  4. package/dist/components/AssetPanel.js +80 -7
  5. package/dist/components/AssetPanel.js.map +1 -1
  6. package/dist/components/Canvas.d.ts +9 -1
  7. package/dist/components/Canvas.d.ts.map +1 -1
  8. package/dist/components/Canvas.js +41 -3
  9. package/dist/components/Canvas.js.map +1 -1
  10. package/dist/components/CommandPalette.d.ts +48 -0
  11. package/dist/components/CommandPalette.d.ts.map +1 -0
  12. package/dist/components/CommandPalette.js +154 -0
  13. package/dist/components/CommandPalette.js.map +1 -0
  14. package/dist/components/CompareSlider.d.ts +25 -0
  15. package/dist/components/CompareSlider.d.ts.map +1 -0
  16. package/dist/components/CompareSlider.js +106 -0
  17. package/dist/components/CompareSlider.js.map +1 -0
  18. package/dist/components/DownloadPanel.d.ts +20 -0
  19. package/dist/components/DownloadPanel.d.ts.map +1 -0
  20. package/dist/components/DownloadPanel.js +169 -0
  21. package/dist/components/DownloadPanel.js.map +1 -0
  22. package/dist/components/ErrorBanner.d.ts +22 -0
  23. package/dist/components/ErrorBanner.d.ts.map +1 -0
  24. package/dist/components/ErrorBanner.js +47 -0
  25. package/dist/components/ErrorBanner.js.map +1 -0
  26. package/dist/components/ExifPanel.d.ts +26 -0
  27. package/dist/components/ExifPanel.d.ts.map +1 -0
  28. package/dist/components/ExifPanel.js +104 -0
  29. package/dist/components/ExifPanel.js.map +1 -0
  30. package/dist/components/GlobalDropzone.d.ts +37 -0
  31. package/dist/components/GlobalDropzone.d.ts.map +1 -0
  32. package/dist/components/GlobalDropzone.js +154 -0
  33. package/dist/components/GlobalDropzone.js.map +1 -0
  34. package/dist/components/HistoryPanel.d.ts +17 -7
  35. package/dist/components/HistoryPanel.d.ts.map +1 -1
  36. package/dist/components/HistoryPanel.js +74 -62
  37. package/dist/components/HistoryPanel.js.map +1 -1
  38. package/dist/components/Inspector.d.ts.map +1 -1
  39. package/dist/components/Inspector.js +3 -1
  40. package/dist/components/Inspector.js.map +1 -1
  41. package/dist/components/PipelineBar.d.ts.map +1 -1
  42. package/dist/components/PipelineBar.js +4 -3
  43. package/dist/components/PipelineBar.js.map +1 -1
  44. package/dist/components/ProgressBar.d.ts +18 -0
  45. package/dist/components/ProgressBar.d.ts.map +1 -0
  46. package/dist/components/ProgressBar.js +35 -0
  47. package/dist/components/ProgressBar.js.map +1 -0
  48. package/dist/components/StatusBar.d.ts +8 -2
  49. package/dist/components/StatusBar.d.ts.map +1 -1
  50. package/dist/components/StatusBar.js +59 -4
  51. package/dist/components/StatusBar.js.map +1 -1
  52. package/dist/components/ThemeToggle.d.ts +20 -0
  53. package/dist/components/ThemeToggle.d.ts.map +1 -0
  54. package/dist/components/ThemeToggle.js +60 -0
  55. package/dist/components/ThemeToggle.js.map +1 -0
  56. package/dist/components/WorkflowEditor.d.ts +24 -0
  57. package/dist/components/WorkflowEditor.d.ts.map +1 -0
  58. package/dist/components/WorkflowEditor.js +160 -0
  59. package/dist/components/WorkflowEditor.js.map +1 -0
  60. package/dist/components/WorkflowTemplates.d.ts +23 -0
  61. package/dist/components/WorkflowTemplates.d.ts.map +1 -0
  62. package/dist/components/WorkflowTemplates.js +32 -0
  63. package/dist/components/WorkflowTemplates.js.map +1 -0
  64. package/dist/components/Workspace.d.ts +48 -2
  65. package/dist/components/Workspace.d.ts.map +1 -1
  66. package/dist/components/Workspace.js +80 -5
  67. package/dist/components/Workspace.js.map +1 -1
  68. package/dist/data/workflow-templates.d.ts +42 -0
  69. package/dist/data/workflow-templates.d.ts.map +1 -0
  70. package/dist/data/workflow-templates.js +112 -0
  71. package/dist/data/workflow-templates.js.map +1 -0
  72. package/dist/hooks/useDebouncedRun.d.ts +49 -0
  73. package/dist/hooks/useDebouncedRun.d.ts.map +1 -0
  74. package/dist/hooks/useDebouncedRun.js +117 -0
  75. package/dist/hooks/useDebouncedRun.js.map +1 -0
  76. package/dist/hooks/useLokvis.js +1 -1
  77. package/dist/hooks/useMediaQuery.d.ts +27 -0
  78. package/dist/hooks/useMediaQuery.d.ts.map +1 -0
  79. package/dist/hooks/useMediaQuery.js +41 -0
  80. package/dist/hooks/useMediaQuery.js.map +1 -0
  81. package/dist/hooks/useShareLink.d.ts +58 -0
  82. package/dist/hooks/useShareLink.d.ts.map +1 -0
  83. package/dist/hooks/useShareLink.js +120 -0
  84. package/dist/hooks/useShareLink.js.map +1 -0
  85. package/dist/hooks/useTheme.d.ts +30 -0
  86. package/dist/hooks/useTheme.d.ts.map +1 -0
  87. package/dist/hooks/useTheme.js +105 -0
  88. package/dist/hooks/useTheme.js.map +1 -0
  89. package/dist/hooks/useWorkflowProgress.d.ts +28 -0
  90. package/dist/hooks/useWorkflowProgress.d.ts.map +1 -0
  91. package/dist/hooks/useWorkflowProgress.js +25 -0
  92. package/dist/hooks/useWorkflowProgress.js.map +1 -0
  93. package/dist/hooks/useWorkflows.d.ts +86 -0
  94. package/dist/hooks/useWorkflows.d.ts.map +1 -0
  95. package/dist/hooks/useWorkflows.js +247 -0
  96. package/dist/hooks/useWorkflows.js.map +1 -0
  97. package/dist/index.d.ts +26 -0
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +26 -0
  100. package/dist/index.js.map +1 -1
  101. package/dist/store/assets-slice.d.ts.map +1 -1
  102. package/dist/store/assets-slice.js +19 -0
  103. package/dist/store/assets-slice.js.map +1 -1
  104. package/dist/store/history-slice.d.ts +18 -0
  105. package/dist/store/history-slice.d.ts.map +1 -0
  106. package/dist/store/history-slice.js +42 -0
  107. package/dist/store/history-slice.js.map +1 -0
  108. package/dist/store/index.d.ts +1 -0
  109. package/dist/store/index.d.ts.map +1 -1
  110. package/dist/store/index.js +3 -0
  111. package/dist/store/index.js.map +1 -1
  112. package/dist/store/runtime-slice.d.ts +10 -2
  113. package/dist/store/runtime-slice.d.ts.map +1 -1
  114. package/dist/store/runtime-slice.js +77 -28
  115. package/dist/store/runtime-slice.js.map +1 -1
  116. package/dist/store/types.d.ts +70 -1
  117. package/dist/store/types.d.ts.map +1 -1
  118. package/dist/store/types.js +10 -0
  119. package/dist/store/types.js.map +1 -1
  120. package/dist/store/workflow-slice.d.ts +1 -1
  121. package/dist/store/workflow-slice.d.ts.map +1 -1
  122. package/dist/store/workflow-slice.js +167 -20
  123. package/dist/store/workflow-slice.js.map +1 -1
  124. package/dist/store.d.ts +76 -0
  125. package/dist/store.d.ts.map +1 -0
  126. package/dist/store.js +217 -0
  127. package/dist/store.js.map +1 -0
  128. package/package.json +9 -6
  129. package/src/components/AssetPanel.tsx +154 -12
  130. package/src/components/Canvas.tsx +85 -7
  131. package/src/components/CommandPalette.tsx +300 -0
  132. package/src/components/CompareSlider.tsx +186 -0
  133. package/src/components/DownloadPanel.tsx +252 -0
  134. package/src/components/ErrorBanner.tsx +95 -0
  135. package/src/components/ExifPanel.tsx +187 -0
  136. package/src/components/GlobalDropzone.tsx +220 -0
  137. package/src/components/HistoryPanel.tsx +231 -104
  138. package/src/components/Inspector.tsx +7 -2
  139. package/src/components/PipelineBar.tsx +13 -12
  140. package/src/components/ProgressBar.tsx +104 -0
  141. package/src/components/StatusBar.tsx +124 -5
  142. package/src/components/ThemeToggle.tsx +122 -0
  143. package/src/components/WorkflowEditor.tsx +382 -0
  144. package/src/components/WorkflowTemplates.tsx +101 -0
  145. package/src/components/Workspace.tsx +207 -9
  146. package/src/data/workflow-templates.ts +137 -0
  147. package/src/hooks/useDebouncedRun.ts +151 -0
  148. package/src/hooks/useLokvis.ts +1 -1
  149. package/src/hooks/useMediaQuery.ts +53 -0
  150. package/src/hooks/useShareLink.ts +158 -0
  151. package/src/hooks/useTheme.ts +116 -0
  152. package/src/hooks/useWorkflowProgress.ts +41 -0
  153. package/src/hooks/useWorkflows.ts +326 -0
  154. package/src/index.ts +32 -0
  155. package/src/store/assets-slice.ts +19 -0
  156. package/src/store/history-slice.ts +65 -0
  157. package/src/store/index.ts +3 -0
  158. package/src/store/runtime-slice.ts +89 -32
  159. package/src/store/types.ts +71 -1
  160. package/src/store/workflow-slice.ts +178 -20
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lokvis Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * AssetPanel - 左侧资产面板
3
3
  *
4
- * 紧凑布局:section header + 上传按钮 + 资产列表。
5
- * 支持拖拽导入、点击选择、缩略图预览。
4
+ * 紧凑布局:section header + 上传按钮 + 筛选 + 资产列表。
5
+ * 支持拖拽导入、点击选择、缩略图预览、按类型/关键词筛选、删除(W6.5)。
6
6
  */
7
7
  import * as React from 'react';
8
8
  export interface AssetPanelProps {
@@ -1 +1 @@
1
- {"version":3,"file":"AssetPanel.d.ts","sourceRoot":"","sources":["../../src/components/AssetPanel.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAc,EAAE,EAAE,eAAe,qBAwI7D"}
1
+ {"version":3,"file":"AssetPanel.d.ts","sourceRoot":"","sources":["../../src/components/AssetPanel.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAaD,wBAAgB,UAAU,CAAC,EAAE,SAAc,EAAE,EAAE,eAAe,qBAyQ7D"}
@@ -2,11 +2,22 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /**
3
3
  * AssetPanel - 左侧资产面板
4
4
  *
5
- * 紧凑布局:section header + 上传按钮 + 资产列表。
6
- * 支持拖拽导入、点击选择、缩略图预览。
5
+ * 紧凑布局:section header + 上传按钮 + 筛选 + 资产列表。
6
+ * 支持拖拽导入、点击选择、缩略图预览、按类型/关键词筛选、删除(W6.5)。
7
7
  */
8
8
  import * as React from 'react';
9
+ import { Icon } from '@lokvis/ui-core';
9
10
  import { useWorkspaceStore } from '../store/index.js';
11
+ /** 类型筛选 chip 显示名 */
12
+ const TYPE_LABEL = {
13
+ image: 'Image',
14
+ video: 'Video',
15
+ audio: 'Audio',
16
+ pdf: 'PDF',
17
+ text: 'Text',
18
+ data: 'Data',
19
+ unknown: 'Other',
20
+ };
10
21
  export function AssetPanel({ className = '' }) {
11
22
  const assets = useWorkspaceStore((s) => s.assets);
12
23
  const selectedAssetId = useWorkspaceStore((s) => s.selectedAssetId);
@@ -17,6 +28,11 @@ export function AssetPanel({ className = '' }) {
17
28
  const setThumbnail = useWorkspaceStore((s) => s.setThumbnail);
18
29
  const runtime = useWorkspaceStore((s) => s.runtime);
19
30
  const [dragging, setDragging] = React.useState(false);
31
+ // W6.5 筛选:类型 + 关键词(纯 UI 状态,不入 store)
32
+ const [filterType, setFilterType] = React.useState('all');
33
+ const [searchQuery, setSearchQuery] = React.useState('');
34
+ // B2 修复:跟踪 in-flight exportAsset,避免同一 asset 跨 effect 重跑并发发起
35
+ const inflightRef = React.useRef(new Set());
20
36
  async function handleFiles(files) {
21
37
  if (!files)
22
38
  return;
@@ -25,27 +41,71 @@ export function AssetPanel({ className = '' }) {
25
41
  await importFiles(arr);
26
42
  }
27
43
  // 自动生成缩略图
44
+ // B2 修复:
45
+ // - cancelled flag:effect 重跑/卸载时,await 完成的 exportAsset 不再创建
46
+ // ObjectURL 也不 setThumbnail,避免覆盖更新值与孤儿 URL
47
+ // - inflightRef:同一 asset 在上一轮 effect 还在 await 时,新一轮 effect
48
+ // 不再重复发起(批量导入 assets 频繁变化场景)
28
49
  React.useEffect(() => {
29
50
  if (!runtime)
30
51
  return;
52
+ let cancelled = false;
53
+ const inflight = inflightRef.current;
31
54
  for (const asset of assets) {
32
55
  if (thumbnails[asset.id])
33
56
  continue;
34
57
  if (asset.type !== 'image')
35
58
  continue;
59
+ if (inflight.has(asset.id))
60
+ continue;
61
+ inflight.add(asset.id);
36
62
  (async () => {
37
63
  try {
38
64
  const blob = await runtime.exportAsset(asset.id);
65
+ // effect 已过期或资产已删除:不创建 ObjectURL(零泄漏)
66
+ if (cancelled)
67
+ return;
39
68
  const url = URL.createObjectURL(blob);
69
+ if (cancelled) {
70
+ // 双重检查:await 与 createObjectURL 之间可能被取消
71
+ URL.revokeObjectURL(url);
72
+ return;
73
+ }
40
74
  setThumbnail(asset.id, url);
41
75
  }
42
76
  catch {
43
- // ignore
77
+ // ignore export 失败
78
+ }
79
+ finally {
80
+ inflight.delete(asset.id);
44
81
  }
45
82
  })();
46
83
  }
84
+ return () => {
85
+ cancelled = true;
86
+ };
47
87
  // eslint-disable-next-line react-hooks/exhaustive-deps
48
88
  }, [assets, runtime]);
89
+ // 资产中实际存在的类型(仅展示有意义的 chip,避免空类型噪音)
90
+ const availableTypes = React.useMemo(() => {
91
+ const set = new Set();
92
+ for (const a of assets)
93
+ set.add(a.type);
94
+ return Array.from(set);
95
+ }, [assets]);
96
+ // 筛选后的资产列表
97
+ const filteredAssets = React.useMemo(() => {
98
+ let result = assets;
99
+ if (filterType !== 'all') {
100
+ result = result.filter((a) => a.type === filterType);
101
+ }
102
+ const q = searchQuery.trim().toLowerCase();
103
+ if (q) {
104
+ result = result.filter((a) => a.metadata.format.toLowerCase().includes(q) ||
105
+ a.metadata.mimeType.toLowerCase().includes(q));
106
+ }
107
+ return result;
108
+ }, [assets, filterType, searchQuery]);
49
109
  return (_jsxs("aside", { className: `flex w-56 shrink-0 flex-col border-r border-zinc-200 dark:border-zinc-800 ${className}`, onDragOver: (e) => {
50
110
  e.preventDefault();
51
111
  setDragging(true);
@@ -53,17 +113,30 @@ export function AssetPanel({ className = '' }) {
53
113
  e.preventDefault();
54
114
  setDragging(false);
55
115
  void handleFiles(e.dataTransfer.files);
56
- }, children: [_jsxs("div", { className: "flex items-center justify-between px-3 h-10 shrink-0 border-b border-zinc-200 dark:border-zinc-800", children: [_jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wider text-zinc-400", children: "Assets" }), _jsx("span", { className: "text-[11px] tabular-nums text-zinc-400", children: assets.length })] }), _jsxs("label", { className: `m-2 block cursor-pointer rounded-lg border border-dashed px-2 py-3 text-center transition-all ${dragging
116
+ }, children: [_jsxs("div", { className: "flex items-center justify-between px-3 h-10 shrink-0 border-b border-zinc-200 dark:border-zinc-800", children: [_jsx("span", { className: "text-[11px] font-semibold uppercase tracking-wider text-zinc-400", children: "Assets" }), _jsx("span", { className: "text-[11px] tabular-nums text-zinc-400", children: filterType === 'all' && !searchQuery
117
+ ? assets.length
118
+ : `${filteredAssets.length}/${assets.length}` })] }), _jsxs("label", { className: `m-2 block cursor-pointer rounded-lg border border-dashed px-2 py-3 text-center transition-all ${dragging
57
119
  ? 'border-indigo-400 bg-indigo-50 text-indigo-600 dark:bg-indigo-950/30'
58
- : 'border-zinc-200 text-zinc-400 hover:border-indigo-300 hover:bg-indigo-50/50 hover:text-indigo-500 dark:border-zinc-700 dark:hover:border-indigo-800 dark:hover:bg-indigo-950/20'}`, children: [_jsx("input", { type: "file", multiple: true, className: "hidden", onChange: (e) => handleFiles(e.target.files) }), _jsx("svg", { className: "mx-auto h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4.5v15m7.5-7.5h-15" }) }), _jsx("span", { className: "mt-1 block text-[10px] font-medium", children: dragging ? 'Drop here' : 'Add files' })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-2 pb-2", children: assets.length === 0 ? (_jsx("p", { className: "px-1 py-4 text-center text-[10px] text-zinc-400", children: "No assets imported" })) : (_jsx("ul", { className: "space-y-1", children: assets.map((asset) => {
120
+ : 'border-zinc-200 text-zinc-400 hover:border-indigo-300 hover:bg-indigo-50/50 hover:text-indigo-500 dark:border-zinc-700 dark:hover:border-indigo-800 dark:hover:bg-indigo-950/20'}`, children: [_jsx("input", { type: "file", multiple: true, className: "hidden", onChange: (e) => handleFiles(e.target.files) }), _jsx(Icon, { size: 16, className: "mx-auto", children: _jsx("path", { d: "M12 4.5v15m7.5-7.5h-15" }) }), _jsx("span", { className: "mt-1 block text-[10px] font-medium", children: dragging ? 'Drop here' : 'Add files' })] }), assets.length > 0 && (_jsxs("div", { className: "px-2 pb-2 space-y-1.5", children: [_jsxs("div", { role: "radiogroup", "aria-label": "Filter by type", className: "flex flex-wrap gap-1", children: [_jsx("button", { type: "button", role: "radio", "aria-checked": filterType === 'all', onClick: () => setFilterType('all'), className: `rounded px-1.5 py-0.5 text-[10px] font-medium transition-colors ${filterType === 'all'
121
+ ? 'bg-indigo-100 text-indigo-700 dark:bg-indigo-950/50 dark:text-indigo-300'
122
+ : 'bg-zinc-100 text-zinc-500 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-400 dark:hover:bg-zinc-700'}`, children: "All" }), availableTypes.map((t) => (_jsx("button", { type: "button", role: "radio", "aria-checked": filterType === t, onClick: () => setFilterType(t), className: `rounded px-1.5 py-0.5 text-[10px] font-medium transition-colors ${filterType === t
123
+ ? 'bg-indigo-100 text-indigo-700 dark:bg-indigo-950/50 dark:text-indigo-300'
124
+ : 'bg-zinc-100 text-zinc-500 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-400 dark:hover:bg-zinc-700'}`, children: TYPE_LABEL[t] }, t)))] }), _jsxs("div", { className: "relative", children: [_jsxs(Icon, { size: 11, className: "absolute left-1.5 top-1/2 -translate-y-1/2 text-zinc-400 pointer-events-none", children: [_jsx("circle", { cx: "10", cy: "10", r: "6" }), _jsx("path", { d: "m20 20-5-5" })] }), _jsx("input", { type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Filter by type...", "aria-label": "Filter assets by format", className: "w-full rounded bg-zinc-100 py-1 pl-6 pr-1.5 text-[10px] text-zinc-700 placeholder:text-zinc-400 focus:outline-none focus:ring-1 focus:ring-indigo-300 dark:bg-zinc-800 dark:text-zinc-200 dark:placeholder:text-zinc-500" })] })] })), _jsx("div", { className: "flex-1 overflow-y-auto px-2 pb-2", children: assets.length === 0 ? (_jsx("p", { className: "px-1 py-4 text-center text-[10px] text-zinc-400", children: "No assets imported" })) : filteredAssets.length === 0 ? (_jsx("p", { className: "px-1 py-4 text-center text-[10px] text-zinc-400", children: "No assets match filter" })) : (_jsx("ul", { className: "space-y-1", children: filteredAssets.map((asset) => {
59
125
  const selected = asset.id === selectedAssetId;
60
126
  const thumb = thumbnails[asset.id];
61
- return (_jsxs("li", { onClick: () => selectAsset(asset.id), className: `group flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-xs transition-all ${selected
127
+ return (_jsxs("li", {
128
+ // M3: 键盘可达 —— tabIndex + role + onKeyDown(Enter/Space 选中)
129
+ tabIndex: 0, role: "button", "aria-pressed": selected, "aria-label": `Select asset ${asset.metadata.format}`, onClick: () => selectAsset(asset.id), onKeyDown: (e) => {
130
+ if (e.key === 'Enter' || e.key === ' ') {
131
+ e.preventDefault();
132
+ selectAsset(asset.id);
133
+ }
134
+ }, className: `group flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-xs transition-all focus:outline-none focus:ring-2 focus:ring-indigo-300 ${selected
62
135
  ? 'bg-indigo-50 ring-1 ring-indigo-200 dark:bg-indigo-950/30 dark:ring-indigo-800'
63
136
  : 'hover:bg-zinc-50 dark:hover:bg-zinc-800'}`, children: [_jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded bg-zinc-100 dark:bg-zinc-800", children: thumb ? (_jsx("img", { src: thumb, alt: "", className: "h-full w-full object-cover" })) : (_jsx("span", { className: "text-[10px] font-medium text-zinc-400", children: asset.metadata.format.slice(0, 3).toUpperCase() })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-[11px] font-medium", children: asset.metadata.format }), _jsxs("div", { className: "text-[10px] text-zinc-400", children: [(asset.metadata.size / 1024).toFixed(1), " KB"] })] }), _jsx("button", { type: "button", onClick: (e) => {
64
137
  e.stopPropagation();
65
138
  void removeAsset(asset.id);
66
- }, className: "shrink-0 rounded p-0.5 text-zinc-300 opacity-0 transition-all hover:bg-red-50 hover:text-red-500 group-hover:opacity-100 dark:text-zinc-600 dark:hover:bg-red-950/30", "aria-label": "Remove asset", children: _jsx("svg", { className: "h-3 w-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) })] }, asset.id));
139
+ }, className: "shrink-0 rounded p-0.5 text-zinc-300 opacity-0 transition-all hover:bg-red-50 hover:text-red-500 focus:opacity-100 group-hover:opacity-100 dark:text-zinc-600 dark:hover:bg-red-950/30", "aria-label": `Remove asset ${asset.metadata.format}`, children: _jsx(Icon, { size: 12, children: _jsx("path", { d: "M6 18L18 6M6 6l12 12" }) }) })] }, asset.id));
67
140
  }) })) })] }));
68
141
  }
69
142
  //# sourceMappingURL=AssetPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AssetPanel.js","sourceRoot":"","sources":["../../src/components/AssetPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AssetPanel.js","sourceRoot":"","sources":["../../src/components/AssetPanel.tsx"],"names":[],"mappings":"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"}
@@ -3,10 +3,18 @@
3
3
  *
4
4
  * 只负责展示当前选中资产的预览,以及空状态引导。
5
5
  * 工作流节点链已移至独立的 PipelineBar 组件。
6
+ *
7
+ * W9.4: 当存在 lastOutputIds 时,可切换到 CompareSlider 模式,
8
+ * 并排展示 before/after。
6
9
  */
7
10
  import * as React from 'react';
8
11
  export interface CanvasProps {
9
12
  className?: string;
13
+ /**
14
+ * 是否启用 before/after 对比模式(W9.4)。
15
+ * 默认 true;关闭后即使有 outputs 也只显示单图预览。
16
+ */
17
+ enableCompare?: boolean;
10
18
  }
11
- export declare function Canvas({ className }: CanvasProps): React.JSX.Element;
19
+ export declare function Canvas({ className, enableCompare }: CanvasProps): React.JSX.Element;
12
20
  //# sourceMappingURL=Canvas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Canvas.d.ts","sourceRoot":"","sources":["../../src/components/Canvas.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,MAAM,CAAC,EAAE,SAAc,EAAE,EAAE,WAAW,qBA4GrD"}
1
+ {"version":3,"file":"Canvas.d.ts","sourceRoot":"","sources":["../../src/components/Canvas.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,MAAM,CAAC,EAAE,SAAc,EAAE,aAAoB,EAAE,EAAE,WAAW,qBAgL3E"}
@@ -4,20 +4,54 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
4
4
  *
5
5
  * 只负责展示当前选中资产的预览,以及空状态引导。
6
6
  * 工作流节点链已移至独立的 PipelineBar 组件。
7
+ *
8
+ * W9.4: 当存在 lastOutputIds 时,可切换到 CompareSlider 模式,
9
+ * 并排展示 before/after。
7
10
  */
8
11
  import * as React from 'react';
12
+ import { Icon } from '@lokvis/ui-core';
9
13
  import { useWorkspaceStore } from '../store/index.js';
10
- export function Canvas({ className = '' }) {
14
+ import { CompareSlider } from './CompareSlider.js';
15
+ export function Canvas({ className = '', enableCompare = true }) {
11
16
  const selectedAssetId = useWorkspaceStore((s) => s.selectedAssetId);
12
17
  const assets = useWorkspaceStore((s) => s.assets);
13
18
  const thumbnails = useWorkspaceStore((s) => s.thumbnails);
14
19
  const importFiles = useWorkspaceStore((s) => s.importFiles);
20
+ const lastOutputIds = useWorkspaceStore((s) => s.lastOutputIds);
21
+ const selectedOutputId = useWorkspaceStore((s) => s.selectedOutputId);
15
22
  const selected = assets.find((a) => a.id === selectedAssetId);
16
23
  const preview = selected ? thumbnails[selected.id] : undefined;
24
+ // W9.4 是否有可对比的输出
25
+ const outputId = selectedOutputId ?? lastOutputIds[0] ?? null;
26
+ const outputThumbnail = outputId ? thumbnails[outputId] : undefined;
27
+ const canCompare = enableCompare && !!(preview && outputThumbnail);
28
+ // W9.4 默认开启 compare 模式:当 outputs 生成后,用户首次希望对比
29
+ // 切换状态由用户控制,直到下次 outputs 重新生成时再默认开启
30
+ const [compareMode, setCompareMode] = React.useState(false);
31
+ // 记录上次已自动切到 compare 模式的 outputId。
32
+ // 修复 review:原 effect 依赖 [lastOutputIds, preview, outputThumbnail],
33
+ // 当用户手动切到 Single 后再切换选中资产,preview 变化会触发 effect
34
+ // 把 compareMode 强制重置为 true,覆盖用户选择。
35
+ // 现在仅在 outputId 真正变化(新 run 完成 / 切换输出)且 preview/outputThumbnail
36
+ // 都就绪时才自动切换;同一 outputId 下 preview / outputThumbnail 的异步变化
37
+ // 不会覆盖用户已选择的 Single 模式。
38
+ const lastAutoSwitchedOutputId = React.useRef(null);
39
+ React.useEffect(() => {
40
+ if (outputId !== null &&
41
+ outputId !== lastAutoSwitchedOutputId.current &&
42
+ preview &&
43
+ outputThumbnail) {
44
+ lastAutoSwitchedOutputId.current = outputId;
45
+ setCompareMode(true);
46
+ }
47
+ }, [outputId, preview, outputThumbnail]);
17
48
  // 全局拖拽支持(直接拖到画布区)
18
49
  const [dragOver, setDragOver] = React.useState(false);
19
50
  return (_jsx("main", { className: `relative flex flex-1 flex-col overflow-hidden ${className}`, onDragOver: (e) => { e.preventDefault(); setDragOver(true); }, onDragLeave: () => setDragOver(false), onDrop: (e) => {
20
51
  e.preventDefault();
52
+ // stopPropagation 防止事件冒泡到 window 的 GlobalDropzone 监听,
53
+ // 否则文件会被导入两次(Canvas 处理一次 + GlobalDropzone 再处理一次)
54
+ e.stopPropagation();
21
55
  setDragOver(false);
22
56
  if (e.dataTransfer.files.length > 0) {
23
57
  void importFiles(Array.from(e.dataTransfer.files));
@@ -25,9 +59,13 @@ export function Canvas({ className = '' }) {
25
59
  }, children: _jsxs("div", { className: "relative flex flex-1 items-center justify-center bg-zinc-50 dark:bg-zinc-950", children: [_jsx("div", { className: "absolute inset-0 opacity-[0.35]", style: {
26
60
  backgroundImage: 'radial-gradient(circle, #d4d4d8 1px, transparent 1px)',
27
61
  backgroundSize: '20px 20px',
28
- } }), dragOver && (_jsx("div", { className: "absolute inset-4 z-10 rounded-xl border-2 border-dashed border-indigo-400 bg-indigo-50/80 flex items-center justify-center dark:border-indigo-600 dark:bg-indigo-950/60", children: _jsxs("div", { className: "text-center", children: [_jsx("svg", { className: "mx-auto h-8 w-8 text-indigo-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5m-13.5-9L12 3m0 0 4.5 4.5M12 3v13.5" }) }), _jsx("p", { className: "mt-2 text-sm font-medium text-indigo-600 dark:text-indigo-400", children: "Drop files to import" })] }) })), selected ? (preview ? (_jsxs("div", { className: "relative", children: [_jsx("img", { src: preview, alt: selected.metadata.format, className: "max-h-[calc(100%-4rem)] max-w-[calc(100%-4rem)] rounded-lg object-contain shadow-2xl shadow-black/10 ring-1 ring-black/5 dark:shadow-black/30" }), _jsx("div", { className: "absolute bottom-2 left-2 rounded-lg bg-white/90 px-2.5 py-1 text-[11px] text-zinc-600 shadow-sm backdrop-blur-sm dark:bg-zinc-900/90 dark:text-zinc-300", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium", children: selected.metadata.format.toUpperCase() }), selected.metadata.dimensions && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-zinc-300", children: "\u00B7" }), _jsxs("span", { children: [selected.metadata.dimensions.width, " x ", selected.metadata.dimensions.height] })] })), _jsx("span", { className: "text-zinc-300", children: "\u00B7" }), _jsxs("span", { children: [(selected.metadata.size / 1024).toFixed(1), " KB"] })] }) })] })) : (_jsxs("div", { className: "flex flex-col items-center gap-3", children: [_jsx("div", { className: "h-28 w-28 animate-pulse rounded-xl bg-zinc-200 dark:bg-zinc-800" }), _jsx("span", { className: "text-xs text-zinc-400", children: "Loading preview..." })] }))) : (_jsxs("div", { className: "relative flex flex-col items-center gap-5 px-6 text-center", children: [_jsx("div", { className: "flex h-20 w-20 items-center justify-center rounded-2xl bg-white shadow-sm ring-1 ring-zinc-200/80 dark:bg-zinc-800 dark:ring-zinc-700", children: _jsx("svg", { className: "h-9 w-9 text-zinc-300 dark:text-zinc-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" }) }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-zinc-500 dark:text-zinc-400", children: "No asset selected" }), _jsx("p", { className: "mt-1.5 text-xs text-zinc-400 dark:text-zinc-500", children: assets.length === 0
62
+ } }), canCompare && (_jsxs("div", { className: "absolute top-2 right-2 z-20 flex items-center gap-1 rounded-md bg-white/90 p-0.5 shadow-sm backdrop-blur-sm dark:bg-zinc-900/90", children: [_jsx("button", { type: "button", onClick: () => setCompareMode(false), "aria-pressed": !compareMode, className: `rounded px-2 py-1 text-[10px] font-medium transition-colors ${!compareMode
63
+ ? 'bg-indigo-100 text-indigo-700 dark:bg-indigo-950/50 dark:text-indigo-300'
64
+ : 'text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800'}`, children: "Single" }), _jsx("button", { type: "button", onClick: () => setCompareMode(true), "aria-pressed": compareMode, className: `rounded px-2 py-1 text-[10px] font-medium transition-colors ${compareMode
65
+ ? 'bg-indigo-100 text-indigo-700 dark:bg-indigo-950/50 dark:text-indigo-300'
66
+ : 'text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800'}`, children: "Compare" })] })), dragOver && (_jsx("div", { className: "absolute inset-4 z-10 rounded-xl border-2 border-dashed border-indigo-400 bg-indigo-50/80 flex items-center justify-center dark:border-indigo-600 dark:bg-indigo-950/60", children: _jsxs("div", { className: "text-center", children: [_jsx(Icon, { size: 32, className: "mx-auto text-indigo-500", strokeWidth: 1.5, children: _jsx("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.5m-13.5-9L12 3m0 0 4.5 4.5M12 3v13.5" }) }), _jsx("p", { className: "mt-2 text-sm font-medium text-indigo-600 dark:text-indigo-400", children: "Drop files to import" })] }) })), compareMode && canCompare ? (_jsx("div", { className: "relative flex max-h-[calc(100%-4rem)] max-w-[calc(100%-4rem)] items-center justify-center", children: _jsx(CompareSlider, { className: "max-h-[calc(100vh-12rem)] max-w-full" }) })) : selected ? (preview ? (_jsxs("div", { className: "relative", children: [_jsx("img", { src: preview, alt: selected.metadata.format, className: "max-h-[calc(100%-4rem)] max-w-[calc(100%-4rem)] rounded-lg object-contain shadow-2xl shadow-black/10 ring-1 ring-black/5 dark:shadow-black/30" }), _jsx("div", { className: "absolute bottom-2 left-2 rounded-lg bg-white/90 px-2.5 py-1 text-[11px] text-zinc-600 shadow-sm backdrop-blur-sm dark:bg-zinc-900/90 dark:text-zinc-300", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium", children: selected.metadata.format.toUpperCase() }), selected.metadata.dimensions && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-zinc-300", children: "\u00B7" }), _jsxs("span", { children: [selected.metadata.dimensions.width, " x ", selected.metadata.dimensions.height] })] })), _jsx("span", { className: "text-zinc-300", children: "\u00B7" }), _jsxs("span", { children: [(selected.metadata.size / 1024).toFixed(1), " KB"] })] }) })] })) : (_jsxs("div", { className: "flex flex-col items-center gap-3", children: [_jsx("div", { className: "h-28 w-28 animate-pulse rounded-xl bg-zinc-200 dark:bg-zinc-800" }), _jsx("span", { className: "text-xs text-zinc-400", children: "Loading preview..." })] }))) : (_jsxs("div", { className: "relative flex flex-col items-center gap-5 px-6 text-center", children: [_jsx("div", { className: "flex h-20 w-20 items-center justify-center rounded-2xl bg-white shadow-sm ring-1 ring-zinc-200/80 dark:bg-zinc-800 dark:ring-zinc-700", children: _jsx(Icon, { size: 36, className: "text-zinc-300 dark:text-zinc-600", strokeWidth: 1.5, children: _jsx("path", { d: "m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" }) }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-zinc-500 dark:text-zinc-400", children: "No asset selected" }), _jsx("p", { className: "mt-1.5 text-xs text-zinc-400 dark:text-zinc-500", children: assets.length === 0
29
67
  ? 'Import files to get started, or drag them here'
30
- : 'Select an asset from the left panel' })] }), assets.length === 0 && (_jsxs("label", { className: "mt-2 inline-flex items-center gap-1.5 rounded-lg bg-indigo-600 px-4 py-2 text-xs font-medium text-white shadow-sm cursor-pointer transition-colors hover:bg-indigo-500", children: [_jsx("svg", { className: "h-3.5 w-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4.5v15m7.5-7.5h-15" }) }), "Import Files", _jsx("input", { type: "file", multiple: true, className: "hidden", onChange: (e) => {
68
+ : 'Select an asset from the left panel' })] }), assets.length === 0 && (_jsxs("label", { className: "mt-2 inline-flex items-center gap-1.5 rounded-lg bg-indigo-600 px-4 py-2 text-xs font-medium text-white shadow-sm cursor-pointer transition-colors hover:bg-indigo-500", children: [_jsx(Icon, { size: 14, children: _jsx("path", { d: "M12 4.5v15m7.5-7.5h-15" }) }), "Import Files", _jsx("input", { type: "file", multiple: true, className: "hidden", onChange: (e) => {
31
69
  if (e.target.files)
32
70
  void importFiles(Array.from(e.target.files));
33
71
  } })] }))] }))] }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"Canvas.js","sourceRoot":"","sources":["../../src/components/Canvas.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Canvas.js","sourceRoot":"","sources":["../../src/components/Canvas.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * CommandPalette - ⌘K 工具选择器(W9.2)
3
+ *
4
+ * Command Palette 风格的快捷工具入口:
5
+ * - ⌘K / Ctrl+K 打开
6
+ * - ESC 关闭
7
+ * - 输入关键词过滤能力列表
8
+ * - ↑↓ 选择,Enter 添加到工作流,or 鼠标点击
9
+ *
10
+ * 数据源:`store.capabilities`,与 Inspector 右侧能力列表同源。
11
+ * 选中后调用 `store.addNode(cap.name)` 添加到工作流,并关闭面板。
12
+ *
13
+ * 实现:基于 ui-core 的 Dialog 组件提供模态基底 + 焦点 trap。
14
+ */
15
+ import * as React from 'react';
16
+ export interface CommandPaletteProps {
17
+ /** 是否打开(受控) */
18
+ open: boolean;
19
+ /** 关闭回调 */
20
+ onClose: () => void;
21
+ className?: string;
22
+ }
23
+ export declare function CommandPalette({ open, onClose, className }: CommandPaletteProps): React.JSX.Element;
24
+ /**
25
+ * useCommandPalette - 在组件中注册 ⌘K / Ctrl+K 全局快捷键打开面板。
26
+ *
27
+ * 返回 [open, setOpen]。在 useEffect 中绑定 keydown 监听。
28
+ * 兼容 macOS(⌘K)与 Windows/Linux(Ctrl+K)。Shift+⌘K / Ctrl+Shift+K 也触发,
29
+ * 方便用户在 ⌘K 被浏览器拦截时使用。
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * const [open, setOpen] = useCommandPalette();
34
+ * // 或禁用快捷键(仍可受控使用 open/setOpen):
35
+ * const [open, setOpen] = useCommandPalette({ enabled: false });
36
+ * return (
37
+ * <>
38
+ * <CommandPalette open={open} onClose={() => setOpen(false)} />
39
+ * </>
40
+ * );
41
+ * ```
42
+ */
43
+ export interface UseCommandPaletteOptions {
44
+ /** 是否注册 ⌘K 全局快捷键(默认 true)。设为 false 时仍可受控使用 open/setOpen */
45
+ enabled?: boolean;
46
+ }
47
+ export declare function useCommandPalette(options?: UseCommandPaletteOptions): [boolean, React.Dispatch<React.SetStateAction<boolean>>];
48
+ //# sourceMappingURL=CommandPalette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette.d.ts","sourceRoot":"","sources":["../../src/components/CommandPalette.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,mBAAmB;IAClC,eAAe;IACf,IAAI,EAAE,OAAO,CAAC;IACd,WAAW;IACX,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAc,EAAE,EAAE,mBAAmB,qBAiOpF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,wBAAwB;IACvC,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,wBAA6B,GACrC,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAkB1D"}
@@ -0,0 +1,154 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * CommandPalette - ⌘K 工具选择器(W9.2)
4
+ *
5
+ * Command Palette 风格的快捷工具入口:
6
+ * - ⌘K / Ctrl+K 打开
7
+ * - ESC 关闭
8
+ * - 输入关键词过滤能力列表
9
+ * - ↑↓ 选择,Enter 添加到工作流,or 鼠标点击
10
+ *
11
+ * 数据源:`store.capabilities`,与 Inspector 右侧能力列表同源。
12
+ * 选中后调用 `store.addNode(cap.name)` 添加到工作流,并关闭面板。
13
+ *
14
+ * 实现:基于 ui-core 的 Dialog 组件提供模态基底 + 焦点 trap。
15
+ */
16
+ import * as React from 'react';
17
+ import { Dialog, Icon } from '@lokvis/ui-core';
18
+ import { useWorkspaceStore } from '../store/index.js';
19
+ export function CommandPalette({ open, onClose, className = '' }) {
20
+ const capabilities = useWorkspaceStore((s) => s.capabilities);
21
+ const addNode = useWorkspaceStore((s) => s.addNode);
22
+ const undo = useWorkspaceStore((s) => s.undo);
23
+ const redo = useWorkspaceStore((s) => s.redo);
24
+ const clearWorkflow = useWorkspaceStore((s) => s.clearWorkflow);
25
+ const running = useWorkspaceStore((s) => s.running);
26
+ const [query, setQuery] = React.useState('');
27
+ const [activeIndex, setActiveIndex] = React.useState(0);
28
+ const inputRef = React.useRef(null);
29
+ const listRef = React.useRef(null);
30
+ const commands = React.useMemo(() => {
31
+ const caps = capabilities.map((cap) => ({ kind: 'capability', cap }));
32
+ const actions = [
33
+ {
34
+ kind: 'action',
35
+ id: 'undo',
36
+ label: 'Undo',
37
+ description: '回退到上一步历史',
38
+ run: () => void undo(),
39
+ disabled: false,
40
+ },
41
+ {
42
+ kind: 'action',
43
+ id: 'redo',
44
+ label: 'Redo',
45
+ description: '重做一步',
46
+ run: () => void redo(),
47
+ disabled: false,
48
+ },
49
+ {
50
+ kind: 'action',
51
+ id: 'clear',
52
+ label: 'Clear Workflow',
53
+ description: '清空当前工作流节点',
54
+ run: () => clearWorkflow(),
55
+ disabled: running,
56
+ },
57
+ ];
58
+ return [...caps, ...actions];
59
+ }, [capabilities, undo, redo, clearWorkflow, running]);
60
+ const filtered = React.useMemo(() => {
61
+ const q = query.trim().toLowerCase();
62
+ if (!q)
63
+ return commands;
64
+ return commands.filter((cmd) => {
65
+ if (cmd.kind === 'capability') {
66
+ return (cmd.cap.name.toLowerCase().includes(q) ||
67
+ cmd.cap.description.toLowerCase().includes(q));
68
+ }
69
+ return cmd.label.toLowerCase().includes(q) || cmd.description.toLowerCase().includes(q);
70
+ });
71
+ }, [commands, query]);
72
+ // 打开时重置 query + activeIndex + 聚焦输入
73
+ React.useEffect(() => {
74
+ if (!open)
75
+ return;
76
+ setQuery('');
77
+ setActiveIndex(0);
78
+ // Dialog 聚焦首个可聚焦元素(input)后,input ref 才有值
79
+ // 用 timer 句柄 + cleanup 避免卸载后 setState 警告
80
+ const t = setTimeout(() => inputRef.current?.focus(), 0);
81
+ return () => clearTimeout(t);
82
+ }, [open]);
83
+ // filtered 变化时校正 activeIndex 越界
84
+ React.useEffect(() => {
85
+ if (activeIndex >= filtered.length) {
86
+ setActiveIndex(filtered.length === 0 ? 0 : filtered.length - 1);
87
+ }
88
+ }, [filtered.length, activeIndex]);
89
+ // 滚动 active 项进入视区
90
+ React.useEffect(() => {
91
+ if (!open || !listRef.current)
92
+ return;
93
+ const active = listRef.current.querySelector(`[data-index="${activeIndex}"]`);
94
+ active?.scrollIntoView({ block: 'nearest' });
95
+ }, [activeIndex, open]);
96
+ function handleSelect(cmd) {
97
+ if (cmd.kind === 'capability') {
98
+ addNode(cmd.cap.name);
99
+ }
100
+ else {
101
+ if (cmd.disabled)
102
+ return;
103
+ cmd.run();
104
+ }
105
+ onClose();
106
+ }
107
+ function handleKeyDown(e) {
108
+ if (e.key === 'ArrowDown') {
109
+ e.preventDefault();
110
+ setActiveIndex((i) => (i + 1) % Math.max(1, filtered.length));
111
+ }
112
+ else if (e.key === 'ArrowUp') {
113
+ e.preventDefault();
114
+ setActiveIndex((i) => (i - 1 + filtered.length) % Math.max(1, filtered.length));
115
+ }
116
+ else if (e.key === 'Enter') {
117
+ e.preventDefault();
118
+ const cmd = filtered[activeIndex];
119
+ if (cmd)
120
+ handleSelect(cmd);
121
+ }
122
+ }
123
+ return (_jsx(Dialog, { open: open, onClose: onClose, size: "md", closeOnOverlay: true, children: _jsxs("div", { className: `-mx-5 -my-5 ${className}`, children: [_jsxs("div", { className: "flex items-center gap-2 border-b border-zinc-200 px-4 py-3 dark:border-zinc-800", children: [_jsxs(Icon, { size: 16, className: "text-zinc-400", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("path", { d: "m21 21-4.3-4.3" })] }), _jsx("input", { ref: inputRef, type: "text", value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search commands or capabilities...", "aria-label": "Search commands", className: "flex-1 bg-transparent text-sm text-zinc-900 placeholder:text-zinc-400 focus:outline-none dark:text-zinc-100", autoComplete: "off", spellCheck: false }), _jsx("kbd", { className: "rounded border border-zinc-200 px-1.5 py-0.5 text-[9px] font-medium text-zinc-400 dark:border-zinc-700 dark:text-zinc-500", children: "ESC" })] }), _jsx("ul", { ref: listRef, className: "max-h-80 overflow-y-auto py-1", role: "listbox", "aria-label": "Available commands", children: filtered.length === 0 ? (_jsx("li", { className: "px-4 py-6 text-center text-xs text-zinc-400", children: "No matching commands" })) : (filtered.map((cmd, i) => {
124
+ const isActive = i === activeIndex;
125
+ const isCap = cmd.kind === 'capability';
126
+ const primary = isCap ? cmd.cap.name : cmd.label;
127
+ const secondary = isCap ? cmd.cap.description : cmd.description;
128
+ const disabled = !isCap && cmd.disabled;
129
+ return (_jsx("li", { "data-index": i, role: "option", "aria-selected": isActive, "aria-disabled": disabled, children: _jsxs("button", { type: "button", onMouseEnter: () => setActiveIndex(i), onClick: () => !disabled && handleSelect(cmd), disabled: disabled, className: `flex w-full items-center gap-3 px-4 py-2 text-left transition-colors ${isActive && !disabled
130
+ ? 'bg-indigo-50 dark:bg-indigo-950/30'
131
+ : ''} ${disabled ? 'cursor-not-allowed opacity-40' : 'hover:bg-zinc-50 dark:hover:bg-zinc-800/50'}`, children: [_jsx("span", { className: `flex h-6 w-6 shrink-0 items-center justify-center rounded ${isCap
132
+ ? 'bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400'
133
+ : 'bg-indigo-100 text-indigo-600 dark:bg-indigo-950/50 dark:text-indigo-400'}`, children: _jsx(Icon, { size: 12, strokeWidth: 2, children: isCap ? (_jsx("path", { d: "M12 4.5v15m7.5-7.5h-15" })) : (_jsx("path", { d: "M13 2L3 14h7l-1 8 10-12h-7l1-8z" })) }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { className: "truncate text-xs font-medium text-zinc-900 dark:text-zinc-100", children: primary }), isCap && (_jsx("span", { className: "shrink-0 rounded px-1 py-0.5 text-[9px] font-medium uppercase bg-zinc-100 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400", children: cmd.cap.performance }))] }), _jsx("p", { className: "truncate text-[10px] text-zinc-500 dark:text-zinc-400", children: secondary })] })] }) }, isCap ? `cap:${cmd.cap.name}` : `act:${cmd.id}`));
134
+ })) }), _jsxs("div", { className: "flex items-center justify-between border-t border-zinc-200 px-4 py-2 text-[10px] text-zinc-400 dark:border-zinc-800", children: [_jsxs("span", { className: "flex items-center gap-1", children: [_jsx("kbd", { className: "rounded border border-zinc-200 px-1 dark:border-zinc-700", children: "\u2191\u2193" }), _jsx("span", { children: "navigate" }), _jsx("kbd", { className: "ml-2 rounded border border-zinc-200 px-1 dark:border-zinc-700", children: "\u21B5" }), _jsx("span", { children: "select" })] }), _jsxs("span", { children: [filtered.length, " command", filtered.length !== 1 ? 's' : ''] })] })] }) }));
135
+ }
136
+ export function useCommandPalette(options = {}) {
137
+ const { enabled = true } = options;
138
+ const [open, setOpen] = React.useState(false);
139
+ React.useEffect(() => {
140
+ if (!enabled)
141
+ return;
142
+ const onKey = (e) => {
143
+ // ⌘K (mac) / Ctrl+K (win/linux),忽略纯 K(避免拦截输入)
144
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
145
+ e.preventDefault();
146
+ setOpen((v) => !v);
147
+ }
148
+ };
149
+ document.addEventListener('keydown', onKey);
150
+ return () => document.removeEventListener('keydown', onKey);
151
+ }, [enabled]);
152
+ return [open, setOpen];
153
+ }
154
+ //# sourceMappingURL=CommandPalette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandPalette.js","sourceRoot":"","sources":["../../src/components/CommandPalette.tsx"],"names":[],"mappings":"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"}