@arronqzy/react-view 1.0.21 → 1.0.23
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/package.json +11 -11
- package/readme.md +6 -1
- package/src/panel/I18nRoot.tsx +14 -2
- package/src/panel/ReactViewOnlinePreview.tsx +29 -18
- package/src/panel/ReactViewPanel.tsx +154 -1006
- package/src/panel/components/PanelConfigSidebar.tsx +297 -3712
- package/src/panel/components/PanelHistoryPopover.tsx +163 -0
- package/src/panel/components/PanelLayerDock.tsx +412 -0
- package/src/panel/components/PanelMenubar.tsx +149 -0
- package/src/panel/components/PanelWorkspaceDialogs.tsx +271 -0
- package/src/panel/components/config/PanelConfigAudioSection.tsx +334 -0
- package/src/panel/components/config/PanelConfigChartSection.tsx +799 -0
- package/src/panel/components/config/PanelConfigGeometrySection.tsx +233 -0
- package/src/panel/components/config/PanelConfigGridChildSpan.tsx +70 -0
- package/src/panel/components/config/PanelConfigGridSection.tsx +118 -0
- package/src/panel/components/config/PanelConfigMultiSelect.tsx +1291 -0
- package/src/panel/components/config/PanelConfigNodeInfo.tsx +169 -0
- package/src/panel/components/config/PanelConfigReferenceSection.tsx +99 -0
- package/src/panel/components/config/PanelConfigScene3dSection.tsx +6 -2
- package/src/panel/components/config/PanelConfigStyleSections.tsx +249 -0
- package/src/panel/components/config/PanelConfigTextSection.tsx +268 -0
- package/src/panel/components/config/PanelConfigVideoSection.tsx +133 -0
- package/src/panel/components/config/PanelConfigViewportSection.tsx +139 -0
- package/src/panel/components/config/helpers.ts +85 -0
- package/src/panel/hooks/useWorkspaceProjects.ts +112 -34
- package/src/panel/icons.tsx +160 -0
- package/src/panel/index.tsx +15 -1
- package/src/panel/library/parse-workspace-data.ts +142 -0
- package/src/panel/library/workspace-project-cache.ts +13 -4
- package/src/panel/library/workspace-project-db.ts +24 -13
- package/src/panel/library/workspace-project-sync.ts +17 -6
- package/src/panel/utils/outputScale.ts +9 -4
- package/src/panel/utils/panelSelection.ts +57 -0
- package/src/panel/utils/panelStateIO.ts +18 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arronqzy/react-view",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.23",
|
|
4
4
|
"files": [
|
|
5
5
|
"src",
|
|
6
6
|
"dist",
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
"@codemirror/lang-json": "^6.0.1",
|
|
31
31
|
"@codemirror/theme-one-dark": "^6.1.2",
|
|
32
32
|
"@codemirror/view": "^6.36.2",
|
|
33
|
-
"@arronqzy/ui": "1.0.
|
|
34
|
-
"@arronqzy/blueprint-dsl": "1.0.
|
|
35
|
-
"@arronqzy/
|
|
36
|
-
"@arronqzy/
|
|
37
|
-
"@arronqzy/
|
|
38
|
-
"@arronqzy/
|
|
39
|
-
"@arronqzy/
|
|
40
|
-
"@arronqzy/
|
|
33
|
+
"@arronqzy/ui": "1.0.7",
|
|
34
|
+
"@arronqzy/blueprint-dsl": "1.0.12",
|
|
35
|
+
"@arronqzy/react-blueprint": "1.0.14",
|
|
36
|
+
"@arronqzy/view-table": "0.1.6",
|
|
37
|
+
"@arronqzy/view-scene3d": "0.1.3",
|
|
38
|
+
"@arronqzy/i18n": "0.1.9",
|
|
39
|
+
"@arronqzy/webllm-assistant": "0.1.11",
|
|
40
|
+
"@arronqzy/rx-store": "1.0.6"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/react": "^19.0.1",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"eslint": "^8.57.0",
|
|
47
47
|
"typescript": "^5.5.4",
|
|
48
48
|
"@arronqzy/eslint-config": "0.0.0",
|
|
49
|
-
"@arronqzy/
|
|
50
|
-
"@arronqzy/
|
|
49
|
+
"@arronqzy/tailwind": "1.0.2",
|
|
50
|
+
"@arronqzy/typescript-config": "1.0.0"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"lint": "eslint \"src/**/*.{ts,tsx}\"",
|
package/readme.md
CHANGED
|
@@ -147,7 +147,12 @@ const dataUrl = await getPreviewSnapshot({
|
|
|
147
147
|
| `parseOnlinePreviewSearchParams` | 解析预览 URL 参数 |
|
|
148
148
|
| `addEventSubscription` | 订阅工作区事件,返回 `{ unsubscribe }` |
|
|
149
149
|
| `AbuilderEvents` | 工作区事件名常量 |
|
|
150
|
-
| `getPreviewSnapshot` | 获取预览画面 base64
|
|
150
|
+
| `getPreviewSnapshot` | 获取预览画面 base64 缩略图(仅本包 / `@arronqzy/abuilder`) |
|
|
151
|
+
| `parseWorkspaceData` / `validateWorkspaceData` | 解析或校验完整工作区;`parse` 的 `value` 可作 `initialWorkspace` |
|
|
152
|
+
| `parseViewData` / `validateViewData` | 解析或校验视图 `panelState` |
|
|
153
|
+
| `parseBlueprintData` / `validateBlueprintData` | 解析或校验蓝图文档 |
|
|
154
|
+
| `createEmptyWorkspace` | 构造空工作区记录 |
|
|
155
|
+
| `createWorkspaceProjectId` | 生成工作区 ID |
|
|
151
156
|
| `WorkspaceData` / `WorkspaceProjectRecord` | 完整工作区数据类型 |
|
|
152
157
|
| `createView` / `createAction` 等 | 视图 DSL 与指令扩展(`src/core`) |
|
|
153
158
|
|
package/src/panel/I18nRoot.tsx
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { I18nProvider } from "@arronqzy/i18n/react";
|
|
2
|
+
import { LOCALE_STORAGE_KEY } from "@arronqzy/i18n";
|
|
3
|
+
import { appStorageKey } from "@arronqzy/blueprint-dsl";
|
|
2
4
|
import type { Locale } from "@arronqzy/i18n";
|
|
3
5
|
import type { ReactNode } from "react";
|
|
4
6
|
|
|
@@ -6,12 +8,22 @@ export type I18nRootProps = {
|
|
|
6
8
|
children: ReactNode;
|
|
7
9
|
locale?: Locale | null;
|
|
8
10
|
onLocaleChange?: (locale: Locale) => void;
|
|
11
|
+
nameSpace?: string | null;
|
|
9
12
|
};
|
|
10
13
|
|
|
11
14
|
/** Ensures panel / preview subtree always has i18n context (host apps, duplicate package graphs). */
|
|
12
|
-
export function I18nRoot({
|
|
15
|
+
export function I18nRoot({
|
|
16
|
+
children,
|
|
17
|
+
locale,
|
|
18
|
+
onLocaleChange,
|
|
19
|
+
nameSpace,
|
|
20
|
+
}: I18nRootProps) {
|
|
13
21
|
return (
|
|
14
|
-
<I18nProvider
|
|
22
|
+
<I18nProvider
|
|
23
|
+
locale={locale}
|
|
24
|
+
onLocaleChange={onLocaleChange}
|
|
25
|
+
storageKey={appStorageKey(LOCALE_STORAGE_KEY, nameSpace)}
|
|
26
|
+
>
|
|
15
27
|
{children}
|
|
16
28
|
</I18nProvider>
|
|
17
29
|
);
|
|
@@ -54,6 +54,7 @@ export type ReactViewOnlinePreviewProps = {
|
|
|
54
54
|
workspace?: WorkspaceProjectRecord | null;
|
|
55
55
|
locale?: Locale | null;
|
|
56
56
|
onLocaleChange?: (locale: Locale) => void;
|
|
57
|
+
nameSpace?: string | null;
|
|
57
58
|
};
|
|
58
59
|
|
|
59
60
|
function applyTitleIcon(titleIconDataUrl?: string) {
|
|
@@ -68,20 +69,24 @@ function applyTitleIcon(titleIconDataUrl?: string) {
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
async function loadWorkspaceRecord(
|
|
72
|
-
|
|
72
|
+
async function loadWorkspaceRecord(
|
|
73
|
+
projectId: string,
|
|
74
|
+
nameSpace?: string | null
|
|
75
|
+
): Promise<WorkspaceProjectRecord | null> {
|
|
76
|
+
const fromDb = await getWorkspaceProject(projectId, nameSpace);
|
|
73
77
|
if (fromDb) return fromDb;
|
|
74
|
-
return readWorkspacePreviewCache(projectId);
|
|
78
|
+
return readWorkspacePreviewCache(projectId, nameSpace);
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
export function ReactViewOnlinePreview({
|
|
78
82
|
locale,
|
|
79
83
|
onLocaleChange,
|
|
84
|
+
nameSpace,
|
|
80
85
|
...rest
|
|
81
86
|
}: ReactViewOnlinePreviewProps) {
|
|
82
87
|
return (
|
|
83
|
-
<I18nRoot locale={locale} onLocaleChange={onLocaleChange}>
|
|
84
|
-
<ReactViewOnlinePreviewInner {...rest} />
|
|
88
|
+
<I18nRoot locale={locale} onLocaleChange={onLocaleChange} nameSpace={nameSpace}>
|
|
89
|
+
<ReactViewOnlinePreviewInner nameSpace={nameSpace} {...rest} />
|
|
85
90
|
</I18nRoot>
|
|
86
91
|
);
|
|
87
92
|
}
|
|
@@ -90,6 +95,7 @@ function ReactViewOnlinePreviewInner({
|
|
|
90
95
|
projectId,
|
|
91
96
|
previewInstanceId,
|
|
92
97
|
workspace = null,
|
|
98
|
+
nameSpace = null,
|
|
93
99
|
}: ReactViewOnlinePreviewProps) {
|
|
94
100
|
const { t } = useI18n();
|
|
95
101
|
|
|
@@ -102,7 +108,7 @@ function ReactViewOnlinePreviewInner({
|
|
|
102
108
|
>([]);
|
|
103
109
|
const [layoutRevision, setLayoutRevision] = useState(0);
|
|
104
110
|
const [layoutReady, setLayoutReady] = useState(false);
|
|
105
|
-
const [outputScale, setOutputScale] = useState(() => readOutputScale());
|
|
111
|
+
const [outputScale, setOutputScale] = useState(() => readOutputScale(nameSpace));
|
|
106
112
|
const [fillScale, setFillScale] = useState({ scaleX: 1, scaleY: 1 });
|
|
107
113
|
|
|
108
114
|
const sceneRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -122,7 +128,9 @@ function ReactViewOnlinePreviewInner({
|
|
|
122
128
|
setPanelState(normalized);
|
|
123
129
|
setBlueprintGraph(BlueprintGraph.fromDocument(record.blueprintDocument));
|
|
124
130
|
document.title =
|
|
125
|
-
record.productName
|
|
131
|
+
(typeof record.productName === "string" ? record.productName : "").trim() ||
|
|
132
|
+
record.name ||
|
|
133
|
+
t("panel.workspace.previewDocTitle");
|
|
126
134
|
applyTitleIcon(record.titleIconDataUrl);
|
|
127
135
|
setProjectRevision((v) => v + 1);
|
|
128
136
|
return true;
|
|
@@ -141,7 +149,7 @@ function ReactViewOnlinePreviewInner({
|
|
|
141
149
|
return;
|
|
142
150
|
}
|
|
143
151
|
|
|
144
|
-
const record = await loadWorkspaceRecord(projectId);
|
|
152
|
+
const record = await loadWorkspaceRecord(projectId, nameSpace);
|
|
145
153
|
if (!record) {
|
|
146
154
|
setLoadError(t("panel.messages.workspaceNotFound"));
|
|
147
155
|
setPanelState(null);
|
|
@@ -149,7 +157,7 @@ function ReactViewOnlinePreviewInner({
|
|
|
149
157
|
}
|
|
150
158
|
|
|
151
159
|
applyWorkspaceRecord(record);
|
|
152
|
-
}, [applyWorkspaceRecord, projectId, t, workspace]);
|
|
160
|
+
}, [applyWorkspaceRecord, nameSpace, projectId, t, workspace]);
|
|
153
161
|
|
|
154
162
|
useEffect(() => {
|
|
155
163
|
void loadProject();
|
|
@@ -159,8 +167,8 @@ function ReactViewOnlinePreviewInner({
|
|
|
159
167
|
if (workspace || !projectId) return;
|
|
160
168
|
return subscribeWorkspaceProjectUpdates(projectId, () => {
|
|
161
169
|
void loadProject();
|
|
162
|
-
});
|
|
163
|
-
}, [loadProject, projectId, workspace]);
|
|
170
|
+
}, nameSpace);
|
|
171
|
+
}, [loadProject, nameSpace, projectId, workspace]);
|
|
164
172
|
|
|
165
173
|
const layers = useMemo(
|
|
166
174
|
() => (panelState ? parsePanelLayers(panelState) : []),
|
|
@@ -177,13 +185,13 @@ function ReactViewOnlinePreviewInner({
|
|
|
177
185
|
|
|
178
186
|
useEffect(() => {
|
|
179
187
|
let cancelled = false;
|
|
180
|
-
void listBlueprintLibrary().then((items) => {
|
|
188
|
+
void listBlueprintLibrary(nameSpace).then((items) => {
|
|
181
189
|
if (!cancelled) setBlueprintLibraryItems(items);
|
|
182
190
|
});
|
|
183
191
|
return () => {
|
|
184
192
|
cancelled = true;
|
|
185
193
|
};
|
|
186
|
-
}, [projectRevision]);
|
|
194
|
+
}, [nameSpace, projectRevision]);
|
|
187
195
|
|
|
188
196
|
const blueprintLibraryNameById = useMemo(
|
|
189
197
|
() => new Map(blueprintLibraryItems.map((item) => [item.id, item.name])),
|
|
@@ -192,13 +200,13 @@ function ReactViewOnlinePreviewInner({
|
|
|
192
200
|
|
|
193
201
|
const resolveLibraryBlueprint = useCallback<LibraryBlueprintResolver>(
|
|
194
202
|
async (libraryBlueprintId) => {
|
|
195
|
-
const record = await getBlueprintLibraryRecord(libraryBlueprintId);
|
|
203
|
+
const record = await getBlueprintLibraryRecord(libraryBlueprintId, nameSpace);
|
|
196
204
|
if (!record) return null;
|
|
197
|
-
const items = await listBlueprintLibrary();
|
|
205
|
+
const items = await listBlueprintLibrary(nameSpace);
|
|
198
206
|
const nameById = new Map(items.map((item) => [item.id, item.name]));
|
|
199
207
|
return documentToRunnableGraph(record.document, { libraryNameById: nameById });
|
|
200
208
|
},
|
|
201
|
-
[]
|
|
209
|
+
[nameSpace]
|
|
202
210
|
);
|
|
203
211
|
|
|
204
212
|
const handleViewScopeUpdate = useCallback(
|
|
@@ -251,7 +259,7 @@ function ReactViewOnlinePreviewInner({
|
|
|
251
259
|
);
|
|
252
260
|
|
|
253
261
|
const applySceneFit = useCallback(() => {
|
|
254
|
-
const enabled = readOutputScale();
|
|
262
|
+
const enabled = readOutputScale(nameSpace);
|
|
255
263
|
setOutputScale(enabled);
|
|
256
264
|
const fill = applyPreviewSceneFill(
|
|
257
265
|
sceneRef.current,
|
|
@@ -262,7 +270,7 @@ function ReactViewOnlinePreviewInner({
|
|
|
262
270
|
setFillScale({ scaleX: fill.scaleX, scaleY: fill.scaleY });
|
|
263
271
|
setLayoutRevision((v) => v + 1);
|
|
264
272
|
notifyPreviewLayoutChanged();
|
|
265
|
-
}, [sceneBounds.height, sceneBounds.width]);
|
|
273
|
+
}, [nameSpace, sceneBounds.height, sceneBounds.width]);
|
|
266
274
|
|
|
267
275
|
useLayoutEffect(() => {
|
|
268
276
|
if (!panelState || layerElements.length === 0) return;
|
|
@@ -451,13 +459,16 @@ function ReactViewOnlinePreviewInner({
|
|
|
451
459
|
export function parseOnlinePreviewSearchParams(search: string): {
|
|
452
460
|
projectId: string;
|
|
453
461
|
previewInstanceId?: string;
|
|
462
|
+
nameSpace?: string;
|
|
454
463
|
} | null {
|
|
455
464
|
const params = new URLSearchParams(search);
|
|
456
465
|
if (params.get("preview") !== "online") return null;
|
|
457
466
|
const projectId = params.get("projectId") ?? params.get("id");
|
|
458
467
|
if (!projectId) return null;
|
|
468
|
+
const nameSpace = (params.get("ns") ?? params.get("nameSpace") ?? "").trim();
|
|
459
469
|
return {
|
|
460
470
|
projectId,
|
|
461
471
|
previewInstanceId: params.get("pid") ?? undefined,
|
|
472
|
+
nameSpace: nameSpace || undefined,
|
|
462
473
|
};
|
|
463
474
|
}
|