@arronqzy/react-view 1.0.38 → 1.0.40
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/styles.css +316 -241
- package/package.json +5 -5
- package/readme.md +15 -12
- package/src/index.ts +23 -1
- package/src/panel/ReactViewPanel.tsx +140 -90
- package/src/panel/components/ElementsLayer.tsx +1 -1
- package/src/panel/components/MaterialSidebar.tsx +304 -264
- package/src/panel/components/MoveableLayer.tsx +11 -2
- package/src/panel/components/PanelCanvas.tsx +1 -0
- package/src/panel/components/PanelConfigSidebar.tsx +49 -65
- package/src/panel/components/PanelLayerDock.tsx +397 -316
- package/src/panel/components/PanelRulers.tsx +169 -42
- package/src/panel/components/SelectLayer.tsx +2 -2
- package/src/panel/components/WorkspaceProjectNav.tsx +1 -1
- package/src/panel/hooks/useWorkspaceProjects.ts +228 -52
- package/src/panel/icons.tsx +117 -0
- package/src/panel/library/abuilder-storage.ts +101 -3
- package/src/panel/library/abuilder-view-handle.ts +100 -0
- package/src/panel/library/event-subscription.ts +70 -5
- package/src/panel/library/workspace-project-sync.ts +7 -1
- package/src/panel/library/workspace-storage.ts +58 -4
- package/src/tailwind.css +66 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arronqzy/react-view",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.40",
|
|
4
4
|
"files": [
|
|
5
5
|
"src",
|
|
6
6
|
"dist",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"@codemirror/theme-one-dark": "^6.1.2",
|
|
32
32
|
"@codemirror/view": "^6.36.2",
|
|
33
33
|
"@arronqzy/blueprint-dsl": "1.0.17",
|
|
34
|
-
"@arronqzy/ui": "1.0.
|
|
34
|
+
"@arronqzy/ui": "1.0.11",
|
|
35
35
|
"@arronqzy/i18n": "0.1.17",
|
|
36
|
-
"@arronqzy/react-blueprint": "1.0.
|
|
36
|
+
"@arronqzy/react-blueprint": "1.0.25",
|
|
37
37
|
"@arronqzy/rx-store": "1.0.8",
|
|
38
38
|
"@arronqzy/view-scene3d": "0.1.5",
|
|
39
|
-
"@arronqzy/
|
|
40
|
-
"@arronqzy/
|
|
39
|
+
"@arronqzy/view-table": "0.1.8",
|
|
40
|
+
"@arronqzy/webllm-assistant": "0.1.16"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/react": "^19.0.1",
|
package/readme.md
CHANGED
|
@@ -57,7 +57,8 @@ export function Editor({ workspace }: { workspace?: WorkspaceProjectRecord | nul
|
|
|
57
57
|
|------|------|------|
|
|
58
58
|
| `className` | 根节点 class | — |
|
|
59
59
|
| `initialZoom` | 初始缩放 | `1` |
|
|
60
|
-
| `initialWorkspace` |
|
|
60
|
+
| `initialWorkspace` | 挂载后加载的完整工作区。空则空白画布。带 `id` 时默认同步进 IndexedDB | — |
|
|
61
|
+
| `workspaceId` | 按 IndexedDB id 打开(不 remount) | — |
|
|
61
62
|
|
|
62
63
|
## 在线预览
|
|
63
64
|
|
|
@@ -89,7 +90,7 @@ parseOnlinePreviewSearchParams("?preview=online&projectId=xxx");
|
|
|
89
90
|
|
|
90
91
|
## 工作区事件
|
|
91
92
|
|
|
92
|
-
|
|
93
|
+
回调带完整工作区,用来写自己的后端。`initialWorkspace` 会默认同步进 IndexedDB;本地副本可用导出的 list / get / delete / clear 清理。
|
|
93
94
|
|
|
94
95
|
```ts
|
|
95
96
|
import {
|
|
@@ -111,10 +112,12 @@ syncSub.unsubscribe();
|
|
|
111
112
|
| 事件 | 常量 | 何时触发 |
|
|
112
113
|
|------|------|----------|
|
|
113
114
|
| `workspace:add` | `AbuilderEvents.workspaceAdd` | 创建成功 |
|
|
114
|
-
| `workspace:sync` | `AbuilderEvents.workspaceSync` |
|
|
115
|
+
| `workspace:sync` | `AbuilderEvents.workspaceSync` | 同步成功(载荷含 `nameSpace`) |
|
|
115
116
|
| `workspace:delete` | `AbuilderEvents.workspaceDelete` | 删除工作区,参数 `{ ids, nameSpace }` |
|
|
117
|
+
| `blueprint-library:changed` | `AbuilderEvents.blueprintLibraryChanged` | 蓝图库变更 |
|
|
118
|
+
| `api-collection:changed` | `AbuilderEvents.apiCollectionChanged` | 接口集合变更 |
|
|
116
119
|
|
|
117
|
-
`workspace:add` / `workspace:sync`
|
|
120
|
+
`workspace:add` / `workspace:sync` 的参数字段:上述工作区字段 + `nameSpace`。可用 `addEventSubscription(event, cb, { nameSpace })` 过滤。
|
|
118
121
|
|
|
119
122
|
校验:
|
|
120
123
|
|
|
@@ -155,14 +158,14 @@ const dataUrl = await getPreviewSnapshot({
|
|
|
155
158
|
| `addEventSubscription` / `AbuilderEvents` | 工作区事件 |
|
|
156
159
|
| `getPreviewSnapshot` | 预览截图 data URL |
|
|
157
160
|
| `parseWorkspaceData` 等 | 校验 / 解析 / 空工作区 |
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `clearAbuilderStorage` |
|
|
164
|
-
|
|
165
|
-
|
|
161
|
+
| `putWorkspaceProject` / `upsertWorkspaceProject` / `list` / `get` / `delete` / `clear` | 工作区完整 CRUD |
|
|
162
|
+
| `putBlueprintLibraryRecord` / `list` / `get` / `delete` / `clear` | 蓝图库完整 CRUD |
|
|
163
|
+
| `putExecutionRunRecord` / `list` / `get` / `delete` / `clear` / `purge*` / `trim*` | 执行日志 |
|
|
164
|
+
| `putApiCollection` / `upsertApiCollectionFromJson` / `list` / `delete` / `clear` | 接口集合 |
|
|
165
|
+
| `getCurrentWorkspace` / `openWorkspace` / `createWorkspace` / `saveWorkspace` / `syncWorkspace` | 命令式操作已挂载面板 |
|
|
166
|
+
| `clearAbuilderStorage` | 一次清空四类数据 |
|
|
167
|
+
|
|
168
|
+
本地数据函数的 `nameSpace` 要和面板一致。面板 `ref` 类型为 `AbuilderViewHandle`。
|
|
166
169
|
| `createView` / `createAction` | 视图 DSL 扩展点(`src/core`) |
|
|
167
170
|
|
|
168
171
|
## 样式
|
package/src/index.ts
CHANGED
|
@@ -12,28 +12,38 @@ export {
|
|
|
12
12
|
export type {
|
|
13
13
|
AbuilderEventName,
|
|
14
14
|
AbuilderEventPayloadMap,
|
|
15
|
+
AddEventSubscriptionOptions,
|
|
15
16
|
WorkspaceAddEventPayload,
|
|
16
17
|
WorkspaceSyncEventPayload,
|
|
17
18
|
WorkspaceDeleteEventPayload,
|
|
19
|
+
BlueprintLibraryChangedEventPayload,
|
|
18
20
|
ApiCollectionUploadStartEventPayload,
|
|
19
21
|
ApiCollectionUploadSuccessEventPayload,
|
|
22
|
+
ApiCollectionChangedEventPayload,
|
|
20
23
|
WorkspaceData,
|
|
21
24
|
} from "./panel/library/event-subscription";
|
|
22
25
|
export type { WorkspaceProjectRecord } from "./panel/library/workspace-project-db";
|
|
23
26
|
export {
|
|
24
27
|
listWorkspaceProjects,
|
|
25
28
|
getWorkspaceProject,
|
|
29
|
+
putWorkspaceProject,
|
|
30
|
+
upsertWorkspaceProject,
|
|
26
31
|
deleteWorkspaceProject,
|
|
27
32
|
clearWorkspaceProjects,
|
|
28
33
|
} from "./panel/library/workspace-storage";
|
|
29
|
-
export type {
|
|
34
|
+
export type {
|
|
35
|
+
WorkspaceProjectListItem,
|
|
36
|
+
PutWorkspaceProjectOptions,
|
|
37
|
+
} from "./panel/library/workspace-storage";
|
|
30
38
|
export {
|
|
31
39
|
listBlueprintLibrary,
|
|
32
40
|
getBlueprintLibraryRecord,
|
|
41
|
+
putBlueprintLibraryRecord,
|
|
33
42
|
deleteBlueprintLibraryRecord,
|
|
34
43
|
clearBlueprintLibrary,
|
|
35
44
|
listExecutionRunRecords,
|
|
36
45
|
getExecutionRunRecord,
|
|
46
|
+
putExecutionRunRecord,
|
|
37
47
|
deleteExecutionRunRecord,
|
|
38
48
|
clearAllExecutionRunRecords,
|
|
39
49
|
purgeExecutionRunsOlderThan,
|
|
@@ -41,6 +51,8 @@ export {
|
|
|
41
51
|
readExecutionLogSettings,
|
|
42
52
|
writeExecutionLogSettings,
|
|
43
53
|
listApiCollectionRecords,
|
|
54
|
+
putApiCollection,
|
|
55
|
+
upsertApiCollectionFromJson,
|
|
44
56
|
deleteApiCollection,
|
|
45
57
|
clearApiCollections,
|
|
46
58
|
clearAbuilderStorage,
|
|
@@ -52,6 +64,16 @@ export type {
|
|
|
52
64
|
ExecutionRunRecord,
|
|
53
65
|
ExecutionLogSettings,
|
|
54
66
|
ApiCollectionRecord,
|
|
67
|
+
UpsertApiCollectionInput,
|
|
68
|
+
UpsertApiCollectionResult,
|
|
55
69
|
} from "./panel/library/abuilder-storage";
|
|
70
|
+
export {
|
|
71
|
+
getCurrentWorkspace,
|
|
72
|
+
openWorkspace,
|
|
73
|
+
createWorkspace,
|
|
74
|
+
saveWorkspace,
|
|
75
|
+
syncWorkspace,
|
|
76
|
+
} from "./panel/library/abuilder-view-handle";
|
|
77
|
+
export type { AbuilderViewHandle } from "./panel/library/abuilder-view-handle";
|
|
56
78
|
export { getPreviewSnapshot } from "./panel/library/preview-snapshot";
|
|
57
79
|
export type { GetPreviewSnapshotOptions } from "./panel/library/preview-snapshot";
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useImperativeHandle,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from "react";
|
|
10
|
+
import {
|
|
11
|
+
registerAbuilderViewHandle,
|
|
12
|
+
type AbuilderViewHandle,
|
|
13
|
+
} from "./library/abuilder-view-handle";
|
|
2
14
|
import { useI18n } from "@arronqzy/i18n/react";
|
|
3
15
|
import { relocalizeMessage, type Locale } from "@arronqzy/i18n";
|
|
4
16
|
import type { State } from "@arronqzy/rx-store";
|
|
@@ -99,13 +111,16 @@ import { PANEL_Z_INDEX } from "./constants/zIndex";
|
|
|
99
111
|
import { useRafThrottledScroll } from "./hooks/useRafThrottledScroll";
|
|
100
112
|
import {
|
|
101
113
|
IconBackward,
|
|
114
|
+
IconBlueprint,
|
|
102
115
|
IconBringFront,
|
|
103
116
|
IconClose,
|
|
104
117
|
IconForward,
|
|
105
118
|
IconImage,
|
|
106
119
|
IconLayers,
|
|
120
|
+
IconMoon,
|
|
107
121
|
IconRedo,
|
|
108
122
|
IconSendBack,
|
|
123
|
+
IconSun,
|
|
109
124
|
IconUndo,
|
|
110
125
|
} from "./icons";
|
|
111
126
|
import {
|
|
@@ -126,7 +141,6 @@ import {
|
|
|
126
141
|
ResizableHandle,
|
|
127
142
|
ResizablePanel,
|
|
128
143
|
ResizablePanelGroup,
|
|
129
|
-
Switch,
|
|
130
144
|
Toaster,
|
|
131
145
|
Tooltip,
|
|
132
146
|
TooltipContent,
|
|
@@ -141,6 +155,11 @@ export type ReactViewPanelProps = {
|
|
|
141
155
|
className?: string;
|
|
142
156
|
/** 外部传入的完整工作区数据,挂载后按这份数据完整渲染;空则显示空白,不自动打开 IndexedDB 记录 */
|
|
143
157
|
initialWorkspace?: WorkspaceProjectRecord | null;
|
|
158
|
+
/**
|
|
159
|
+
* 按 IndexedDB id 打开工作区(不 remount)。
|
|
160
|
+
* 与 `initialWorkspace` 同时存在时:首次优先完整记录;之后 id 变化从 IndexedDB 打开。
|
|
161
|
+
*/
|
|
162
|
+
workspaceId?: string | null;
|
|
144
163
|
/** 界面语言;省略时按 localStorage / 浏览器语言解析 */
|
|
145
164
|
locale?: Locale | null;
|
|
146
165
|
onLocaleChange?: (locale: Locale) => void;
|
|
@@ -156,14 +175,18 @@ export type ReactViewPanelProps = {
|
|
|
156
175
|
packageVersion?: string | null;
|
|
157
176
|
};
|
|
158
177
|
|
|
159
|
-
function ReactViewPanelInner(
|
|
178
|
+
const ReactViewPanelInner = forwardRef<AbuilderViewHandle, ReactViewPanelProps>(function ReactViewPanelInner(
|
|
179
|
+
{
|
|
160
180
|
initialZoom = 1,
|
|
161
181
|
className,
|
|
162
182
|
initialWorkspace = null,
|
|
183
|
+
workspaceId = null,
|
|
163
184
|
nameSpace = null,
|
|
164
185
|
packageName = null,
|
|
165
186
|
packageVersion = null,
|
|
166
|
-
}: ReactViewPanelProps
|
|
187
|
+
}: ReactViewPanelProps,
|
|
188
|
+
ref
|
|
189
|
+
) {
|
|
167
190
|
const { t, locale, setLocale } = useI18n();
|
|
168
191
|
const messages = useMemo(() => getPanelMessages(t), [t]);
|
|
169
192
|
const THEME_STORAGE_KEY = appStorageKey("panel:theme", nameSpace);
|
|
@@ -1076,9 +1099,26 @@ function ReactViewPanelInner({
|
|
|
1076
1099
|
panelRevision: `${historyCursor}|${allElements.length}`,
|
|
1077
1100
|
onProjectApplied: handleWorkspaceProjectApplied,
|
|
1078
1101
|
initialWorkspace,
|
|
1102
|
+
workspaceId,
|
|
1079
1103
|
nameSpace,
|
|
1080
1104
|
});
|
|
1081
1105
|
|
|
1106
|
+
const viewHandle = useMemo<AbuilderViewHandle>(
|
|
1107
|
+
() => ({
|
|
1108
|
+
getNameSpace: () => nameSpace ?? null,
|
|
1109
|
+
getCurrentWorkspace: () => workspaceProjects.getCurrentWorkspaceRecord(),
|
|
1110
|
+
openWorkspace: (idOrRecord) => workspaceProjects.handleOpenProject(idOrRecord),
|
|
1111
|
+
createWorkspace: () => workspaceProjects.handleCreateProject(),
|
|
1112
|
+
saveWorkspace: () => workspaceProjects.handleSaveProject(),
|
|
1113
|
+
syncWorkspace: () => workspaceProjects.handleSyncProject(),
|
|
1114
|
+
}),
|
|
1115
|
+
[nameSpace, workspaceProjects]
|
|
1116
|
+
);
|
|
1117
|
+
|
|
1118
|
+
useImperativeHandle(ref, () => viewHandle, [viewHandle]);
|
|
1119
|
+
|
|
1120
|
+
useEffect(() => registerAbuilderViewHandle(viewHandle), [viewHandle]);
|
|
1121
|
+
|
|
1082
1122
|
useEffect(() => {
|
|
1083
1123
|
registerPreviewSnapshotProvider(async () => {
|
|
1084
1124
|
return captureEditorPreviewSnapshot({
|
|
@@ -1869,13 +1909,37 @@ function ReactViewPanelInner({
|
|
|
1869
1909
|
</Tooltip>
|
|
1870
1910
|
</TooltipProvider>
|
|
1871
1911
|
<style>{`
|
|
1872
|
-
|
|
1912
|
+
/* 功能说明视觉层次:主标签醒目、辅助说明更轻(类苹果) */
|
|
1913
|
+
.panel-font-root {
|
|
1914
|
+
font-size: var(--panel-font-px);
|
|
1915
|
+
font-weight: 400;
|
|
1916
|
+
letter-spacing: -0.011em;
|
|
1917
|
+
}
|
|
1918
|
+
.panel-font-root [data-typo="title"] {
|
|
1919
|
+
font-size: calc(var(--panel-font-px) * 1.08) !important;
|
|
1920
|
+
font-weight: 600 !important;
|
|
1921
|
+
letter-spacing: -0.022em;
|
|
1922
|
+
}
|
|
1923
|
+
.panel-font-root [data-typo="label"] {
|
|
1873
1924
|
font-size: var(--panel-font-px) !important;
|
|
1925
|
+
font-weight: 510 !important;
|
|
1926
|
+
letter-spacing: -0.015em;
|
|
1927
|
+
}
|
|
1928
|
+
.panel-font-root [data-typo="caption"] {
|
|
1929
|
+
font-size: calc(var(--panel-font-px) * 0.85) !important;
|
|
1930
|
+
font-weight: 400 !important;
|
|
1931
|
+
letter-spacing: -0.008em;
|
|
1932
|
+
}
|
|
1933
|
+
.panel-font-root [data-typo="micro"] {
|
|
1934
|
+
font-size: calc(var(--panel-font-px) * 0.77) !important;
|
|
1935
|
+
font-weight: 400 !important;
|
|
1874
1936
|
}
|
|
1875
1937
|
/* 画布节点、富文本内容使用各自的字号,不被编辑器 UI 字号强制覆盖 */
|
|
1876
1938
|
.panel-font-root [data-workspace-region="view"] :is(span, label, p, strong, button, input, textarea, select, option, a, li),
|
|
1877
1939
|
.panel-font-root [data-panel-user-text] :is(span, label, p, strong, button, input, textarea, select, option, a, li) {
|
|
1878
1940
|
font-size: inherit !important;
|
|
1941
|
+
font-weight: inherit !important;
|
|
1942
|
+
letter-spacing: inherit !important;
|
|
1879
1943
|
}
|
|
1880
1944
|
.panel-font-root :is(input, textarea):focus,
|
|
1881
1945
|
.panel-font-root :is(input, textarea):focus-visible {
|
|
@@ -1909,7 +1973,7 @@ function ReactViewPanelInner({
|
|
|
1909
1973
|
box-shadow: 0 0 0 1px hsl(var(--primary) / 0.45) inset !important;
|
|
1910
1974
|
}
|
|
1911
1975
|
`}</style>
|
|
1912
|
-
<nav className="panel-font-root relative z-30 flex items-center gap-2 border-b border-border bg-background/
|
|
1976
|
+
<nav className="panel-font-root relative z-30 flex h-10 shrink-0 items-center gap-2.5 border-b border-border/70 bg-background/80 px-3 text-foreground backdrop-blur-md supports-[backdrop-filter]:bg-background/70">
|
|
1913
1977
|
<PanelMenubar
|
|
1914
1978
|
t={t}
|
|
1915
1979
|
handleExport={handleExport}
|
|
@@ -1963,8 +2027,8 @@ function ReactViewPanelInner({
|
|
|
1963
2027
|
</Button>
|
|
1964
2028
|
</nav>
|
|
1965
2029
|
<ResizablePanelGroup direction="horizontal" className="min-h-0 w-full flex-1">
|
|
1966
|
-
<ResizablePanel defaultSize={
|
|
1967
|
-
<div className="panel-font-root h-full">
|
|
2030
|
+
<ResizablePanel defaultSize={16} minSize={12} maxSize={28}>
|
|
2031
|
+
<div className="panel-font-root h-full min-w-0">
|
|
1968
2032
|
<MaterialSidebar
|
|
1969
2033
|
layers={layers}
|
|
1970
2034
|
allElements={allElements}
|
|
@@ -2035,8 +2099,8 @@ function ReactViewPanelInner({
|
|
|
2035
2099
|
/>
|
|
2036
2100
|
</div>
|
|
2037
2101
|
</ResizablePanel>
|
|
2038
|
-
<ResizableHandle withHandle />
|
|
2039
|
-
<ResizablePanel defaultSize={
|
|
2102
|
+
<ResizableHandle withHandle className="opacity-70 transition-opacity hover:opacity-100" />
|
|
2103
|
+
<ResizablePanel defaultSize={68} minSize={40}>
|
|
2040
2104
|
{/* Center workspace */}
|
|
2041
2105
|
<div
|
|
2042
2106
|
className="panel-font-root min-w-0 h-full"
|
|
@@ -2054,18 +2118,18 @@ function ReactViewPanelInner({
|
|
|
2054
2118
|
clearSelection();
|
|
2055
2119
|
}}
|
|
2056
2120
|
>
|
|
2057
|
-
<div className="relative flex h-full flex-col overflow-hidden
|
|
2121
|
+
<div className="relative flex h-full flex-col overflow-hidden bg-background">
|
|
2058
2122
|
<div
|
|
2059
|
-
className="relative flex items-center gap-2 border-b border-border bg-
|
|
2123
|
+
className="relative flex items-center gap-2 border-b border-border/60 bg-muted/15 px-3 py-1.5 text-foreground"
|
|
2060
2124
|
style={{ zIndex: PANEL_Z_INDEX.toolbar }}
|
|
2061
2125
|
>
|
|
2062
2126
|
<Input
|
|
2063
2127
|
value={displayProductName}
|
|
2064
2128
|
onChange={(e) => setProductName(e.target.value)}
|
|
2065
2129
|
placeholder={t("panel.menubar.productNamePlaceholder")}
|
|
2066
|
-
className="h-7 w-[
|
|
2130
|
+
className="h-7 w-[200px] rounded-md border-border/70 bg-background/80 text-xs shadow-none focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none"
|
|
2067
2131
|
/>
|
|
2068
|
-
<span className="text-[11px] text-muted-foreground">{t("panel.menubar.productName")}</span>
|
|
2132
|
+
<span className="hidden text-[11px] text-muted-foreground sm:inline">{t("panel.menubar.productName")}</span>
|
|
2069
2133
|
<TooltipProvider delayDuration={150}>
|
|
2070
2134
|
<Tooltip>
|
|
2071
2135
|
<TooltipTrigger asChild>
|
|
@@ -2200,60 +2264,45 @@ function ReactViewPanelInner({
|
|
|
2200
2264
|
</DropdownMenuContent>
|
|
2201
2265
|
</DropdownMenu>
|
|
2202
2266
|
<div className="flex-1" />
|
|
2203
|
-
<div
|
|
2204
|
-
data-blueprint-toggle
|
|
2205
|
-
className="flex shrink-0 items-center gap-2 rounded-md border border-border bg-muted/30 px-2 py-1"
|
|
2206
|
-
>
|
|
2207
|
-
<span className="text-[11px] text-muted-foreground">{t("panel.menubar.blueprint")}</span>
|
|
2208
|
-
<Switch
|
|
2209
|
-
checked={blueprintOpen}
|
|
2210
|
-
onCheckedChange={setBlueprintOpen}
|
|
2211
|
-
aria-label={t("panel.menubar.showBlueprintPanel")}
|
|
2212
|
-
/>
|
|
2213
|
-
</div>
|
|
2214
2267
|
<TooltipProvider delayDuration={150}>
|
|
2215
|
-
<
|
|
2216
|
-
<
|
|
2217
|
-
<
|
|
2218
|
-
<
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
<div
|
|
2268
|
+
<div className="inline-flex items-center gap-1">
|
|
2269
|
+
<Tooltip>
|
|
2270
|
+
<TooltipTrigger asChild>
|
|
2271
|
+
<button
|
|
2272
|
+
type="button"
|
|
2273
|
+
data-blueprint-toggle
|
|
2274
|
+
onClick={() => setBlueprintOpen((v) => !v)}
|
|
2275
|
+
aria-label={t("panel.menubar.showBlueprintPanel")}
|
|
2276
|
+
aria-pressed={blueprintOpen}
|
|
2225
2277
|
className={[
|
|
2226
|
-
"
|
|
2227
|
-
|
|
2278
|
+
"inline-flex h-7 w-7 items-center justify-center rounded-md border transition-colors",
|
|
2279
|
+
blueprintOpen
|
|
2280
|
+
? "border-primary/50 bg-primary/15 text-primary"
|
|
2281
|
+
: "border-border/70 bg-background/80 text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
|
2228
2282
|
].join(" ")}
|
|
2229
2283
|
>
|
|
2230
|
-
{
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
</div>
|
|
2253
|
-
</div>
|
|
2254
|
-
</TooltipTrigger>
|
|
2255
|
-
<TooltipContent className="z-[10000]">{t("panel.menubar.toggleThemeHint")}</TooltipContent>
|
|
2256
|
-
</Tooltip>
|
|
2284
|
+
<IconBlueprint active={blueprintOpen} />
|
|
2285
|
+
</button>
|
|
2286
|
+
</TooltipTrigger>
|
|
2287
|
+
<TooltipContent className="z-[10000]">
|
|
2288
|
+
{t("panel.menubar.showBlueprintPanel")}
|
|
2289
|
+
</TooltipContent>
|
|
2290
|
+
</Tooltip>
|
|
2291
|
+
<Tooltip>
|
|
2292
|
+
<TooltipTrigger asChild>
|
|
2293
|
+
<button
|
|
2294
|
+
type="button"
|
|
2295
|
+
onClick={() => applyTheme(!isDark)}
|
|
2296
|
+
aria-label={t("panel.menubar.toggleTheme")}
|
|
2297
|
+
aria-pressed={isDark}
|
|
2298
|
+
className="inline-flex h-7 w-7 items-center justify-center rounded-md border border-border/70 bg-background/80 text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
|
|
2299
|
+
>
|
|
2300
|
+
{isDark ? <IconMoon /> : <IconSun />}
|
|
2301
|
+
</button>
|
|
2302
|
+
</TooltipTrigger>
|
|
2303
|
+
<TooltipContent className="z-[10000]">{t("panel.menubar.toggleThemeHint")}</TooltipContent>
|
|
2304
|
+
</Tooltip>
|
|
2305
|
+
</div>
|
|
2257
2306
|
<Tooltip>
|
|
2258
2307
|
<TooltipTrigger asChild>
|
|
2259
2308
|
<button
|
|
@@ -2266,13 +2315,11 @@ function ReactViewPanelInner({
|
|
|
2266
2315
|
</TooltipTrigger>
|
|
2267
2316
|
<TooltipContent className="z-[10000]">{t("panel.menubar.zoomOutCanvas")}</TooltipContent>
|
|
2268
2317
|
</Tooltip>
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
</span>
|
|
2275
|
-
<TooltipProvider delayDuration={150}>
|
|
2318
|
+
<span className="w-20 text-center text-xs">
|
|
2319
|
+
{zoom.x === zoom.y
|
|
2320
|
+
? `${(zoom.x * 100).toFixed(0)}%`
|
|
2321
|
+
: `${(zoom.x * 100).toFixed(0)}%×${(zoom.y * 100).toFixed(0)}%`}
|
|
2322
|
+
</span>
|
|
2276
2323
|
<Tooltip>
|
|
2277
2324
|
<TooltipTrigger asChild>
|
|
2278
2325
|
<button
|
|
@@ -2704,9 +2751,9 @@ function ReactViewPanelInner({
|
|
|
2704
2751
|
</div>
|
|
2705
2752
|
</div>
|
|
2706
2753
|
</ResizablePanel>
|
|
2707
|
-
<ResizableHandle withHandle />
|
|
2708
|
-
<ResizablePanel defaultSize={20} minSize={
|
|
2709
|
-
<div className="panel-font-root h-full">
|
|
2754
|
+
<ResizableHandle withHandle className="opacity-70 transition-opacity hover:opacity-100" />
|
|
2755
|
+
<ResizablePanel defaultSize={20} minSize={16} maxSize={32}>
|
|
2756
|
+
<div className="panel-font-root h-full min-w-0">
|
|
2710
2757
|
<WorkspaceConfigSidebar
|
|
2711
2758
|
configFocus={sidebarConfigFocus}
|
|
2712
2759
|
executionLog={executionLogView}
|
|
@@ -2798,10 +2845,16 @@ function ReactViewPanelInner({
|
|
|
2798
2845
|
open={apiCollectionManagerOpen}
|
|
2799
2846
|
onOpenChange={setApiCollectionManagerOpen}
|
|
2800
2847
|
onUploadStart={(info) => {
|
|
2801
|
-
emitAbuilderEvent(AbuilderEvents.apiCollectionUploadStart,
|
|
2848
|
+
emitAbuilderEvent(AbuilderEvents.apiCollectionUploadStart, {
|
|
2849
|
+
...info,
|
|
2850
|
+
nameSpace: nameSpace ?? null,
|
|
2851
|
+
});
|
|
2802
2852
|
}}
|
|
2803
2853
|
onUploadSuccess={(info) => {
|
|
2804
|
-
emitAbuilderEvent(AbuilderEvents.apiCollectionUploadSuccess,
|
|
2854
|
+
emitAbuilderEvent(AbuilderEvents.apiCollectionUploadSuccess, {
|
|
2855
|
+
...info,
|
|
2856
|
+
nameSpace: nameSpace ?? null,
|
|
2857
|
+
});
|
|
2805
2858
|
}}
|
|
2806
2859
|
onSyncCollection={(record) => {
|
|
2807
2860
|
const patches = buildApiCollectionSyncPatches({
|
|
@@ -2846,17 +2899,14 @@ function ReactViewPanelInner({
|
|
|
2846
2899
|
<Toaster />
|
|
2847
2900
|
</div>
|
|
2848
2901
|
);
|
|
2849
|
-
}
|
|
2850
|
-
|
|
2851
|
-
export
|
|
2852
|
-
locale,
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
</I18nRoot>
|
|
2861
|
-
);
|
|
2862
|
-
}
|
|
2902
|
+
});
|
|
2903
|
+
|
|
2904
|
+
export const ReactViewPanel = forwardRef<AbuilderViewHandle, ReactViewPanelProps>(
|
|
2905
|
+
function ReactViewPanel({ locale, onLocaleChange, nameSpace, ...rest }, ref) {
|
|
2906
|
+
return (
|
|
2907
|
+
<I18nRoot locale={locale} onLocaleChange={onLocaleChange} nameSpace={nameSpace}>
|
|
2908
|
+
<ReactViewPanelInner ref={ref} nameSpace={nameSpace} {...rest} />
|
|
2909
|
+
</I18nRoot>
|
|
2910
|
+
);
|
|
2911
|
+
}
|
|
2912
|
+
);
|
|
@@ -957,7 +957,7 @@ const PanelElementNode = React.memo(function PanelElementNode({
|
|
|
957
957
|
className={[
|
|
958
958
|
"absolute select-none",
|
|
959
959
|
previewMode ? "" : "rv-selectable",
|
|
960
|
-
!previewMode && isSelected ? "
|
|
960
|
+
!previewMode && isSelected ? "rv-node-selected" : "",
|
|
961
961
|
hasViewEvent ? "cursor-pointer" : "",
|
|
962
962
|
].join(" ")}
|
|
963
963
|
data-element-id={el.id}
|