@arronqzy/react-view 1.0.3 → 1.0.7

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 (43) hide show
  1. package/dist/styles.css +555 -15
  2. package/package.json +14 -7
  3. package/readme.md +74 -5
  4. package/src/core/template.tsx +12 -2
  5. package/src/panel/ReactViewOnlinePreview.tsx +18 -8
  6. package/src/panel/ReactViewPanel.tsx +403 -177
  7. package/src/panel/ai/AssistantChatPanel.tsx +895 -0
  8. package/src/panel/ai/AssistantMarkdown.tsx +256 -0
  9. package/src/panel/ai/applyAssistantAction.ts +652 -0
  10. package/src/panel/ai/revealConfigField.ts +137 -0
  11. package/src/panel/components/ConfigHintIcon.tsx +50 -0
  12. package/src/panel/components/ElementsLayer.tsx +39 -22
  13. package/src/panel/components/MaterialSidebar.tsx +157 -109
  14. package/src/panel/components/MoveableLayer.tsx +75 -61
  15. package/src/panel/components/PanelCanvas.tsx +81 -64
  16. package/src/panel/components/PanelConfigSidebar.tsx +471 -448
  17. package/src/panel/components/SelectLayer.tsx +1 -0
  18. package/src/panel/components/ViewElementScopePanel.tsx +13 -12
  19. package/src/panel/components/WorkspaceConfigSidebar.tsx +5 -2
  20. package/src/panel/components/WorkspaceProjectNav.tsx +25 -14
  21. package/src/panel/components/WorkspaceStageSplit.tsx +3 -1
  22. package/src/panel/components/scope-config/ScopeConfigContext.tsx +9 -0
  23. package/src/panel/components/scope-config/ScopeTemplatePreviewHost.tsx +242 -0
  24. package/src/panel/components/scope-config/ScopeTemplateUsageHint.tsx +12 -0
  25. package/src/panel/components/scope-config/ScopeTemplateWarningsPanel.tsx +6 -3
  26. package/src/panel/components/table/ConditionEditor.tsx +205 -0
  27. package/src/panel/components/table/JsonCodeEditor.tsx +115 -0
  28. package/src/panel/components/table/PanelConfigTableSection.tsx +2192 -0
  29. package/src/panel/components/table/TableNodeContent.tsx +544 -0
  30. package/src/panel/constants/messages.ts +76 -34
  31. package/src/panel/hooks/usePanelElements.ts +64 -52
  32. package/src/panel/hooks/useRafThrottledScroll.ts +30 -0
  33. package/src/panel/hooks/useWorkspaceProjects.ts +11 -8
  34. package/src/panel/types.ts +6 -0
  35. package/src/panel/utils/chartOptionBuilder.ts +12 -1
  36. package/src/panel/utils/panelElementDefaults.ts +69 -39
  37. package/src/panel/utils/scope-field-labels.ts +51 -37
  38. package/src/panel/utils/scope-template-chart.ts +92 -0
  39. package/src/panel/utils/scope-template-preview.ts +128 -0
  40. package/src/panel/utils/scope-template-spread.ts +252 -0
  41. package/src/panel/utils/scope-template-warnings.ts +131 -11
  42. package/src/panel/utils/scope-template.ts +105 -3
  43. package/src/tailwind.css +36 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arronqzy/react-view",
3
- "version": "1.0.3",
3
+ "version": "1.0.7",
4
4
  "files": [
5
5
  "src",
6
6
  "dist",
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@scena/react-ruler": "^0.19.0",
18
+ "@tanstack/react-virtual": "^3.13.2",
18
19
  "react-infinite-viewer": "^0.28.1",
19
- "react-zoom-pan-pinch": "^4.0.3",
20
20
  "react-moveable": "^0.56.0",
21
21
  "react-selecto": "^1.26.3",
22
22
  "rxjs": "^7.8.2",
@@ -26,10 +26,17 @@
26
26
  "infinite-viewer": "^0.29.1",
27
27
  "echarts": "^6.0.0",
28
28
  "uuid": "^13.0.0",
29
- "@arronqzy/ui": "1.0.0",
30
- "@arronqzy/blueprint-dsl": "1.0.1",
31
- "@arronqzy/react-blueprint": "1.0.1",
32
- "@arronqzy/rx-store": "1.0.1"
29
+ "@uiw/react-codemirror": "^4.23.8",
30
+ "@codemirror/lang-json": "^6.0.1",
31
+ "@codemirror/theme-one-dark": "^6.1.2",
32
+ "@codemirror/view": "^6.36.2",
33
+ "@arronqzy/ui": "1.0.3",
34
+ "@arronqzy/blueprint-dsl": "1.0.3",
35
+ "@arronqzy/i18n": "0.1.1",
36
+ "@arronqzy/rx-store": "1.0.2",
37
+ "@arronqzy/webllm-assistant": "0.1.1",
38
+ "@arronqzy/react-blueprint": "1.0.4",
39
+ "@arronqzy/view-table": "0.1.1"
33
40
  },
34
41
  "devDependencies": {
35
42
  "@types/react": "^19.0.1",
@@ -39,7 +46,7 @@
39
46
  "typescript": "^5.5.4",
40
47
  "@arronqzy/eslint-config": "0.0.0",
41
48
  "@arronqzy/typescript-config": "1.0.0",
42
- "@arronqzy/tailwind": "1.0.1"
49
+ "@arronqzy/tailwind": "1.0.2"
43
50
  },
44
51
  "scripts": {
45
52
  "lint": "eslint \"src/**/*.{ts,tsx}\"",
package/readme.md CHANGED
@@ -1,17 +1,75 @@
1
1
  # @arronqzy/react-view
2
2
 
3
- ## Tailwind 使用方式
3
+ Abuilder 的**视图编辑器** React 包,提供可视化画布、图层、物料、在线预览与工作区管理能力。
4
4
 
5
- 本包内已内置 Tailwind 配置,并提供可直接引入的样式产物:
5
+ ## 功能概览
6
6
 
7
- - 生成样式:`pnpm -C packages/react-view build:css`
8
- - 使用样式:在你的应用入口中引入
7
+ - **无限画布**:平移、缩放、标尺、框选与 Moveable 拖拽/缩放/旋转
8
+ - **图层系统**:多图层、映射图层、主图层、锁定与合并
9
+ - **物料节点**:图表(ECharts)、文本、图片、音视频、几何、网格、引用节点等
10
+ - **Scope 模版**:节点属性支持 `{scope.xxx}` 表达式与解析预览
11
+ - **工作区**:IndexedDB 持久化、多项目切换、同步与在线预览
12
+ - **蓝图联动**:与 `@arronqzy/react-blueprint` 分屏编辑,运行时 Scope 回写视图
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ pnpm add @arronqzy/react-view
18
+ ```
19
+
20
+ 依赖 React 19,并需引入样式:
9
21
 
10
22
  ```ts
11
23
  import "@arronqzy/react-view/styles.css";
12
24
  ```
13
25
 
14
- 如果你希望由应用侧的 Tailwind 来扫描本包源码(不引入上面的 `styles.css`),请把本包路径加入应用的 `content` 配置,例如:
26
+ ## 使用
27
+
28
+ ### 完整编辑器面板
29
+
30
+ ```tsx
31
+ import { ReactViewPanel } from "@arronqzy/react-view";
32
+ import "@arronqzy/react-view/styles.css";
33
+
34
+ export function Editor() {
35
+ return <ReactViewPanel className="h-screen" initialZoom={1} />;
36
+ }
37
+ ```
38
+
39
+ ### 在线预览
40
+
41
+ ```tsx
42
+ import { ReactViewOnlinePreview } from "@arronqzy/react-view";
43
+
44
+ <ReactViewOnlinePreview projectId="your-project-id" />
45
+ ```
46
+
47
+ URL 参数解析:
48
+
49
+ ```ts
50
+ import { parseOnlinePreviewSearchParams } from "@arronqzy/react-view";
51
+
52
+ const params = parseOnlinePreviewSearchParams("?preview=online&projectId=xxx");
53
+ ```
54
+
55
+ ## 核心导出
56
+
57
+ | 导出 | 说明 |
58
+ |------|------|
59
+ | `ReactViewPanel` | 主编辑面板(画布 + 配置侧栏 + 蓝图分屏) |
60
+ | `ReactViewOnlinePreview` | 只读在线预览页 |
61
+ | `parseOnlinePreviewSearchParams` | 解析预览 URL 参数 |
62
+ | `createView` / `createAction` 等 | 视图 DSL 与指令扩展(`src/core`) |
63
+
64
+ ## 样式与 Tailwind
65
+
66
+ 本包内置 Tailwind 配置,构建产物为 `dist/styles.css`:
67
+
68
+ ```bash
69
+ pnpm -C packages/react-view build:css
70
+ ```
71
+
72
+ 若由应用侧 Tailwind 扫描源码,请将本包加入 `content`:
15
73
 
16
74
  ```ts
17
75
  content: [
@@ -19,3 +77,14 @@ content: [
19
77
  "./node_modules/@arronqzy/react-view/src/**/*.{ts,tsx}",
20
78
  ]
21
79
  ```
80
+
81
+ ## 依赖关系
82
+
83
+ - `@arronqzy/ui` — 基础 UI 组件
84
+ - `@arronqzy/rx-store` — 画布状态与历史
85
+ - `@arronqzy/react-blueprint` — 蓝图编辑与执行
86
+ - `@arronqzy/blueprint-dsl` — 蓝图运行时
87
+
88
+ ## 许可证
89
+
90
+ MIT
@@ -1,6 +1,16 @@
1
- import { JSX, useRef } from "react";
1
+ import { JSX } from "react";
2
2
  import { instructions } from "./instructions";
3
3
 
4
+ function isDevMode(): boolean {
5
+ try {
6
+ return Boolean(
7
+ (import.meta as { env?: { DEV?: boolean } }).env?.DEV
8
+ );
9
+ } catch {
10
+ return false;
11
+ }
12
+ }
13
+
4
14
  /**
5
15
  * 事件需要补齐
6
16
  * @param props
@@ -15,7 +25,7 @@ export const Template = (
15
25
  if (props?.id) {
16
26
  instructions.execute(props.id + "click", { e });
17
27
  } else {
18
- if (import.meta.env.DEV) {
28
+ if (isDevMode()) {
19
29
  console.warn("Template 缺少 id,无法触发事件");
20
30
  }
21
31
  }
@@ -1,4 +1,5 @@
1
1
  import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
2
+ import { useI18n } from "@arronqzy/i18n/react";
2
3
  import {
3
4
  BlueprintGraph,
4
5
  documentToRunnableGraph,
@@ -10,6 +11,7 @@ import {
10
11
  import type { LibraryBlueprintResolver, PageLifecyclePhase } from "@arronqzy/blueprint-dsl";
11
12
  import type { State } from "@arronqzy/rx-store";
12
13
  import { ElementsLayer } from "./components/ElementsLayer";
14
+ import type { TableCellActionHandler } from "./components/table/TableNodeContent";
13
15
  import type { PanelElement } from "./types";
14
16
  import {
15
17
  clearViewElementScopes,
@@ -63,6 +65,8 @@ export function ReactViewOnlinePreview({
63
65
  projectId,
64
66
  previewInstanceId,
65
67
  }: ReactViewOnlinePreviewProps) {
68
+ const { t } = useI18n();
69
+
66
70
  const [loadError, setLoadError] = useState<string | null>(null);
67
71
  const [panelState, setPanelState] = useState<State | null>(null);
68
72
  const [projectRevision, setProjectRevision] = useState(0);
@@ -91,14 +95,14 @@ export function ReactViewOnlinePreview({
91
95
  const loadProject = useCallback(async () => {
92
96
  const record = await loadWorkspaceRecord(projectId);
93
97
  if (!record) {
94
- setLoadError("工作区不存在或已被删除");
98
+ setLoadError(t("panel.messages.workspaceNotFound"));
95
99
  setPanelState(null);
96
100
  return;
97
101
  }
98
102
 
99
103
  const normalized = normalizeImportedPanelState(record.panelState);
100
104
  if (!normalized) {
101
- setLoadError("工作区数据格式无效");
105
+ setLoadError(t("panel.messages.workspaceDataInvalid"));
102
106
  setPanelState(null);
103
107
  return;
104
108
  }
@@ -107,7 +111,7 @@ export function ReactViewOnlinePreview({
107
111
  clearViewElementScopes();
108
112
  setPanelState(normalized);
109
113
  setBlueprintGraph(BlueprintGraph.fromDocument(record.blueprintDocument));
110
- document.title = record.productName.trim() || record.name || "预览";
114
+ document.title = record.productName.trim() || record.name || t("panel.workspace.previewDocTitle");
111
115
  applyTitleIcon(record.titleIconDataUrl);
112
116
  setProjectRevision((v) => v + 1);
113
117
  }, [projectId]);
@@ -228,7 +232,7 @@ export function ReactViewOnlinePreview({
228
232
  const lifecycleReady =
229
233
  !!panelState && layerElements.length > 0 && layoutReady;
230
234
 
231
- useBlueprintPageLifecycle({
235
+ const { triggerBlueprintNode } = useBlueprintPageLifecycle({
232
236
  graph: blueprintGraph,
233
237
  active: true,
234
238
  enabled: lifecycleReady,
@@ -249,7 +253,12 @@ export function ReactViewOnlinePreview({
249
253
 
250
254
  const noopUpdate = useCallback((_id: string, _patch: Partial<PanelElement>) => {}, []);
251
255
  const noopSelect = useCallback((_ids: string[]) => {}, []);
252
-
256
+ const onTableCellAction = useCallback<TableCellActionHandler>(
257
+ (payload) => {
258
+ void triggerBlueprintNode(payload.blueprintNodeId, payload);
259
+ },
260
+ [triggerBlueprintNode]
261
+ );
253
262
  if (loadError) {
254
263
  return (
255
264
  <div className="flex min-h-[100vh] w-full items-center justify-center bg-white px-6 text-center text-sm text-gray-600">
@@ -261,7 +270,7 @@ export function ReactViewOnlinePreview({
261
270
  if (!panelState) {
262
271
  return (
263
272
  <div className="flex min-h-[100vh] w-full items-center justify-center bg-white text-sm text-gray-600">
264
- 加载预览中…
273
+ {t("panel.workspace.previewLoading")}
265
274
  </div>
266
275
  );
267
276
  }
@@ -269,9 +278,9 @@ export function ReactViewOnlinePreview({
269
278
  if (layerElements.length === 0) {
270
279
  return (
271
280
  <div className="flex min-h-[100vh] w-full flex-col items-center justify-center gap-2 bg-white px-6 text-center text-sm text-gray-600">
272
- <div>当前工作区没有可预览的视图节点</div>
281
+ <div>{t("panel.workspace.previewNoNodes")}</div>
273
282
  <div className="text-xs text-gray-400">
274
- 请先在编辑器中点击「同步」或「创建工作区」后再预览
283
+ {t("panel.workspace.previewHint")}
275
284
  </div>
276
285
  </div>
277
286
  );
@@ -309,6 +318,7 @@ export function ReactViewOnlinePreview({
309
318
  layerLocked
310
319
  previewMode
311
320
  previewLayoutKey={layoutRevision}
321
+ onTableCellAction={onTableCellAction}
312
322
  />
313
323
  </div>
314
324
  </div>