@bpmn-nova/react 0.3.2-preview → 0.3.4-preview

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/llms-full.txt CHANGED
@@ -44,6 +44,20 @@ yarn add @bpmn-nova/vue@preview
44
44
 
45
45
  Replace `vue` with `react` or `studio` only when the selected framework branch requires it. Run one installation command, not all three.
46
46
 
47
+ In TypeScript host code, import shared BPMN model types from that same selected public package. Vue and React explicitly re-export `BpmnEdge`, `BpmnNode`, `EdgeType`, `ElementSelection`, `EngineId`, `LayoutOptions`, `NodeType`, and `ProcessModel`; do not add a direct Studio dependency only to obtain these types:
48
+
49
+ ```ts
50
+ import type {
51
+ BpmnNode,
52
+ EdgeType,
53
+ ElementSelection,
54
+ NodeType,
55
+ ProcessModel,
56
+ } from '@bpmn-nova/vue'
57
+ ```
58
+
59
+ Use `@bpmn-nova/react` instead in a React application.
60
+
47
61
  This step is complete when the application manifest contains exactly the selected direct BPMN Nova dependency and the package manager finishes without peer-dependency errors.
48
62
 
49
63
  ## 3. Select the visual Interface
@@ -59,6 +73,8 @@ Choose the smallest Interface that owns the required experience:
59
73
 
60
74
  Use `engine="flowable"` or `engine="activiti"` explicitly from the host workflow engine. Do not infer the engine from BPMN XML namespace declarations alone.
61
75
 
76
+ Studio modes are presentation state: `design` means editable process design, `viewer` means read-only process viewing, and `instance` means approval trace. Observe the actual Shell state through `subscribeMode()` or framework mode events; never store it in the BPMN model.
77
+
62
78
  ## 4. Mount a minimal integration
63
79
 
64
80
  Every branch must import its own public `styles.css` exactly once and provide a height through the complete parent layout chain.
@@ -88,7 +104,7 @@ function handleChange(model, reason, xml) {
88
104
  engine="flowable"
89
105
  mode="design"
90
106
  :allowed-edge-types="['sequenceFlow']"
91
- :allowed-modes="['design']"
107
+ :allowed-modes="['design', 'viewer']"
92
108
  theme="auto"
93
109
  @change="handleChange"
94
110
  />
@@ -113,7 +129,7 @@ export function WorkflowEditor({ initialXml, saveDraft }) {
113
129
  engine="flowable"
114
130
  mode="design"
115
131
  allowedEdgeTypes={['sequenceFlow']}
116
- allowedModes={['design']}
132
+ allowedModes={['design', 'viewer']}
117
133
  theme="auto"
118
134
  onChange={(model, reason, xml) => saveDraft(xml)}
119
135
  />
@@ -140,7 +156,7 @@ const shell = createStudioShell({
140
156
  container: document.querySelector('#workflow-studio'),
141
157
  studio,
142
158
  mode: 'design',
143
- allowedModes: ['design'],
159
+ allowedModes: ['design', 'viewer'],
144
160
  theme: 'auto',
145
161
  })
146
162
 
@@ -180,17 +196,25 @@ This step is complete when the workbench is visible, the initial XML is rendered
180
196
  <template #header-start="{ state, actions }">
181
197
  <!-- Host back action, business icon, process name, and type -->
182
198
  </template>
199
+ <template #header-actions="{ actions, mode }">
200
+ <!-- Host Validate / Save / Publish actions. Validation calls actions.validate(). -->
201
+ </template>
183
202
  </BpmnStudio>
184
203
  ```
185
204
 
186
- - Vue uses native `#header-start` / `#header` slots. React uses `headerStart` / `header` render props. Core uses `slots.headerStart` / `slots.header`.
187
- - Header Start replaces only the Nova Brand. A complete Header replacement calls the public Actions Interface for undo, redo, layout, fit, validation, BPMN import/export, and SVG export.
205
+ - Vue uses native `#header-start` / `#header-actions` / `#header` slots. React uses `headerStart` / `headerActions` / `header` render props. Core uses matching DOM Slots.
206
+ - Vue supports `v-model:mode` and `mode-change`; React supports `mode` and `onModeChange`. Framework Header contexts expose the actual reactive `mode`. Core Slots use `getMode()` / `subscribeMode()`.
207
+ - Header Start replaces only the Nova Brand. Header Actions replaces only the default Validate / Import / Export group, so a host can compose Validate / Save / Publish without rebuilding the editing tools. A complete Header replacement calls the public Actions Interface.
208
+ - `actions.validate()` updates Nova's default status summary before emitting a read-only validation result with `source: 'toolbar'`; `shell.validate()` and framework Handle/Expose methods use `source: 'api'`. Vue receives `validation`, React receives `onValidation`, and Core uses `subscribeValidation()`. `valid` means there are no errors; warnings do not block publishing by default.
209
+ - The default Header does not duplicate Fit; use the footer control or `fitView()`.
188
210
  - `regions` can hide `header`, `left`, `right`, or `footer` without leaving an empty layout track. Prop changes update the existing Shell; do not rebuild the Canvas.
189
211
  - Put a host-owned properties panel beside the Nova root. Use `selection-change` / `onSelectionChange` as its source of truth because it covers nodes, edges, multi-selection, clearing, and keyboard selection. Do not substitute `element-click` / `onElementClick`.
190
212
  - Join host business configuration by stable BPMN element ID. Saving, publishing, authorization, upload, and server transactions remain host responsibilities.
191
213
  - `theme="auto"` explicitly follows the system theme. The compatibility default remains `light`.
192
214
  - Vue and React both export standalone `BpmnPalettePanel` for a fully custom layout. Pass the same external Studio Controller to Canvas, Palette, and Properties.
193
215
 
216
+ For a host-owned definition-time subtitle, pass `nodeSubtitleResolver` to Studio, Canvas, or Viewer. Return `undefined` for Nova's default subtitle, `null` to remove the row, or a string (including an empty string) as the override. After data inside a stable closure or Map changes, call `refreshPresentation()` on the component handle or Shell. This refresh must not be implemented by mutating a node, re-importing XML, or remounting the component. The resolver applies only to standard Design/Viewer task and container cards and standard SVG fallback; a complete custom renderer wins, and Instance runtime summaries are never overridden.
217
+
194
218
  ## 5. Keep model ownership deterministic
195
219
 
196
220
  - Treat `xml` and `model` as external replacement inputs. Use the emitted/exported XML as the draft output.
@@ -203,9 +227,9 @@ This step is complete when edit, undo, redo, save, reload, and intentional exter
203
227
 
204
228
  ## 6. Add host constraints before business use
205
229
 
206
- Production workflow applications usually support a subset of BPMN. Configure `allowedNodeTypes` and `allowedEdgeTypes` on the Studio Controller or framework `BpmnStudio`; these reject unsupported imported models and block node/edge creation outside the host contract. Configure matching Palette and Properties registries when the host needs custom labels or business fields.
230
+ Production workflow applications usually support a subset of BPMN. Configure `allowedNodeTypes` and `allowedEdgeTypes` on the Studio Controller or framework `BpmnStudio`; these reject unsupported imported models and block node/edge creation outside the host contract. The node allowlist filters Palette entries, but one allowed node type may still have multiple Palette presets. Configure matching Palette and Properties registries when the host needs custom labels or business fields.
207
231
 
208
- Use `allowedModes` to expose only host-authorized workbench modes. Pass real Runtime data for instance mode; absence of Runtime data means no approval trace rather than demo business data.
232
+ Use `allowedModes` to expose only host-authorized workbench modes. Runtime changes use `setAllowedModes()` rather than rebuilding the Studio; invalid, empty, or duplicate lists are errors. Pass real Runtime data for instance mode; absence of Runtime data means no approval trace rather than demo business data.
209
233
 
210
234
  Runtime snapshots store asset references only. The host supplies `runtimeAssetResolver`. BPMN Nova does not execute workflow engines, submit approvals, upload/store attachments, issue permissions, or export PNG/PDF.
211
235
 
@@ -220,10 +244,11 @@ Run the target application's existing non-destructive quality commands, includin
220
244
  3. Create, connect, edit, delete, Undo, and Redo work in design mode.
221
245
  4. Change output is persisted and reloads to the same process.
222
246
  5. Intentional external XML replacement loads once and resets history once.
223
- 6. Disallowed node types are unavailable and rejected by import/creation commands; disallowed modes are not rendered and `setMode()` leaves the current mode unchanged.
247
+ 6. Disallowed node types are unavailable and rejected by import/creation commands; disallowed modes are not rendered and `setMode()` returns `false` without changing state.
224
248
  7. Theme changes update the existing instance.
225
249
  8. Unmount/remount leaves no duplicate listeners, overlays, or framework instances.
226
250
  9. Browser Console has no errors.
251
+ 10. If a subtitle resolver is used, verify override, `undefined`, `null`, SVG parity, and that `refreshPresentation()` preserves XML, history, selection, scope, zoom, pan, theme, and mode. Verify Instance summaries are unchanged.
227
252
 
228
253
  The installation is complete only when the package is present, the production build succeeds, and the relevant browser checks pass. Report any unverified branch explicitly.
229
254
 
@@ -244,7 +269,7 @@ The installation is complete only when the package is present, the production bu
244
269
  BPMN Nova 提供可嵌入的流程设计器、只读 Viewer、运行态审批轨迹、实例级主题、纯 SVG 导出,以及 React / Vue 适配。项目使用独立的 DOM / SVG 渲染实现,不依赖 `bpmn-js`,并为 Flowable 与 Activiti 提供 XML Profile 和属性扩展。
245
270
 
246
271
  > [!IMPORTANT]
247
- > 当前版本为 `0.3.2-preview`。它适合 SDK 评估、产品集成验证和企业审批原型;公开 Interface、BPMN XML round-trip 与引擎兼容能力仍在持续稳定中,建议使用 `@preview` 安装并在生产接入前完成目标流程验证。
272
+ > 当前版本为 `0.3.4-preview`。它适合 SDK 评估、产品集成验证和企业审批原型;公开 Interface、BPMN XML round-trip 与引擎兼容能力仍在持续稳定中,建议使用 `@preview` 安装并在生产接入前完成目标流程验证。
248
273
 
249
274
  AI 或代码生成工具接入必须从 [`llms.txt`](llms.txt) 的完整安装流程开始;需要全部接口与定制上下文时再读取 [`llms-full.txt`](llms-full.txt)。这两份文件也会随三个公开 npm 包发布。
250
275
 
@@ -336,6 +361,20 @@ JavaScript 入口不会自动注入 CSS。使用视觉组件时,请显式导
336
361
 
337
362
  设计、Viewer、Runtime、Theme、SVG Export、Flowable 和 Activiti 继续保持独立内部 Module,但统一由 Studio 根入口或受支持子路径暴露,不再单独发布。一个业务项目只直接安装上述三个包之一。
338
363
 
364
+ TypeScript 宿主也从所选框架包导入公共模型类型,无需为类型再直接安装 Studio。例如 Vue 项目可以直接导入:
365
+
366
+ ```ts
367
+ import type {
368
+ BpmnNode,
369
+ EdgeType,
370
+ ElementSelection,
371
+ NodeType,
372
+ ProcessModel,
373
+ } from '@bpmn-nova/vue'
374
+ ```
375
+
376
+ React 项目将入口替换为 `@bpmn-nova/react`。两个 Adapter 还显式重导出 `BpmnEdge`、`EngineId` 与 `LayoutOptions`。
377
+
339
378
  ## 快速开始
340
379
 
341
380
  视觉组件依赖容器尺寸,请先提供明确高度:
@@ -476,7 +515,7 @@ function onChange(model, reason, nextXml) {
476
515
  </template>
477
516
  ```
478
517
 
479
- Vue Expose 提供与 Vanilla 实例对应的 ActionsXML、视图、主题和 SVG 导出方法。
518
+ Vue Expose 提供与 Vanilla 实例对应的 Actions、校验、XML、视图、主题和 SVG 导出方法。
480
519
 
481
520
  ### 嵌入现有业务设计工作台
482
521
 
@@ -495,19 +534,66 @@ Vue Expose 提供与 Vanilla 实例对应的 Actions、XML、视图、主题和
495
534
  theme="auto"
496
535
  @change="handleChange"
497
536
  @selection-change="handleSelectionChange"
537
+ @validation="handleValidation"
498
538
  >
499
539
  <template #header-start="{ state, actions }">
500
540
  <!-- 返回、业务图标、流程名称和类型 -->
501
541
  </template>
542
+ <template #header-actions="{ actions, mode }">
543
+ <button type="button" :disabled="mode !== 'design'" @click="actions.validate()">校验</button>
544
+ <button type="button" :disabled="mode !== 'design'" @click="saveDraft(actions.exportXml())">保存</button>
545
+ <button type="button" :disabled="mode !== 'design'" @click="publishProcess(actions)">发布</button>
546
+ </template>
502
547
  </BpmnStudio>
503
548
  ```
504
549
 
505
- `header-start` 只替换 Nova Brand,`header` 可替换整个 Header;完整替换时通过 `actions` 调用编辑能力。`regions` 隐藏区域后不会保留 Grid 空白,也不会重建 Canvas。React 提供等价的 `headerStart` / `header` Render Prop,Core 提供 `slots.headerStart` / `slots.header`。
550
+ `header-start` 只替换 Nova Brand;`header-actions` 只替换默认的“校验 / 导入 / 导出”动作组,适合宿主组合“校验 / 保存 / 发布”;`header` 可替换整个 Header。`regions` 隐藏区域后不会保留 Grid 空白,也不会重建 Canvas。React 提供等价的 `headerStart` / `headerActions` / `header` Render Prop,Core 提供同名 DOM Slots。默认 Header 的最佳视图只保留在底部缩放区。
551
+
552
+ `actions.validate()` 会先更新 Nova 默认状态栏,再发送 `validation` 事件并返回 issues;公开 `validate()` 使用相同流程。`valid` 只在存在 error 时为 `false`,warning 会展示和上报但不默认阻止发布。
553
+
554
+ 发布事务由宿主实现,并可以直接复用同一个 Header Action 完成“校验后发布”:
555
+
556
+ ```js
557
+ async function publishProcess(actions) {
558
+ const issues = actions.validate()
559
+ if (issues.some((issue) => issue.level === 'error')) return
560
+ await publishXml(actions.exportXml())
561
+ }
562
+ ```
506
563
 
507
564
  宿主右侧属性面板应位于 Nova 外部,并以 `selection-change` / `onSelectionChange` 为状态来源、以稳定 BPMN Element ID 关联业务配置。`element-click` 不能替代选择事件。Nova 不拥有宿主的保存、发布、权限或服务端事务。
508
565
 
509
566
  `theme="auto"` 是显式启用系统主题适配;为了兼容已有接入,未传 Theme 时仍默认为 `light`。Vue 包同时提供独立的 `BpmnPalettePanel`,用于完全自定义布局。
510
567
 
568
+ Shell 的 `design`、`viewer`、`instance` 分别表示流程设计、流程展示和审批轨迹。宿主可以观察并在运行时调整可用模式,而不会写入 BPMN Model 或 Undo/Redo History:
569
+
570
+ ```js
571
+ const offMode = shell.subscribeMode(({ mode, previousMode, source }) => {
572
+ console.log(previousMode, mode, source)
573
+ })
574
+
575
+ shell.setMode('viewer') // 成功切换返回 true
576
+ shell.setAllowedModes(['design', 'viewer'])
577
+ ```
578
+
579
+ 业务系统只需要覆盖标准节点卡片的定义态副标题时,可以提供轻量 Resolver。`undefined` 保留 Nova 默认值,`null` 隐藏副标题行,字符串替换显示值;外部 Map 等数据变化后显式调用 `refreshPresentation()`。该刷新不改 XML、历史、选择或视口,且不会覆盖 `instance` 的运行事实。
580
+
581
+ ```js
582
+ const subtitles = new Map()
583
+ const shell = createStudioShell({
584
+ container,
585
+ studio,
586
+ nodeSubtitleResolver: ({ node }) => subtitles.has(node.id)
587
+ ? subtitles.get(node.id)
588
+ : undefined,
589
+ })
590
+
591
+ subtitles.set('ServiceTask_Archive', '归档到采购系统')
592
+ shell.refreshPresentation()
593
+ ```
594
+
595
+ `allowedNodeTypes` 会过滤 Palette 和所有建模入口;一个节点类型仍可能由多个 Palette Preset 创建。副标题 Resolver 只是视觉投影,不能替代标准 BPMN Candidate 配置或 Runtime Snapshot。
596
+
511
597
  ## 审批动作、图文与附件
512
598
 
513
599
  Runtime Snapshot 使用动作描述提交、通过、驳回、加签、转办等事实。内容只保存安全文本和资源引用,不保存 URL、Base64、`Blob`、Markdown 或 HTML。
@@ -661,11 +747,13 @@ shell.openSvgExportPreview()
661
747
  | Properties | 注册 Provider、Group、Entry、Data Provider、校验和自定义组件 |
662
748
  | Icons | 覆盖内置图标或注册业务图标 |
663
749
  | Node Renderer | 自定义 Canvas / Viewer 节点内容和运行态摘要 |
750
+ | Node Subtitle Resolver | 轻量覆盖 Design / Viewer 标准节点副标题并无历史刷新 |
664
751
  | Runtime Details Renderer | 自定义 Popover / Bottom Sheet 审批详情 |
665
752
  | Runtime Timeline Renderer | 自定义移动时间线条目、动作和资源布局 |
666
753
  | Runtime Transition Renderer | 自定义驳回、退回和异常线路 |
667
754
  | SVG Renderer | 为自定义节点或时间线提供纯 SVG 导出视觉 |
668
755
  | Context Menu / Slot | 扩展设计器操作、工具区和宿主内容 |
756
+ | Studio Mode Interface | 观察并运行时控制设计、展示与审批轨迹模式 |
669
757
  | React / Vue Bridge | 通过 Props、Ref / Expose 与组合式接口接入上述能力 |
670
758
 
671
759
  完整接口和示例见[自定义指南](docs/CUSTOMIZATION.md)与[组件参数](docs/COMPONENTS.md)。
@@ -761,6 +849,14 @@ npm test
761
849
 
762
850
  已经安装三个公开包之一且与目标技术栈匹配时,沿用现有入口。React 和 Vue 同时存在但无法确定目标应用时先询问用户。`@bpmn-nova/core`、`designer`、`viewer`、`runtime`、`theme`、`export-svg`、`properties` 等历史入口不参与选择;这些能力已经收进 Studio,并通过根入口或受支持子路径提供。
763
851
 
852
+ TypeScript 代码必须从已经选择的公开包导入共享类型。React/Vue Adapter 均显式重导出 `BpmnEdge`、`BpmnNode`、`EdgeType`、`ElementSelection`、`EngineId`、`LayoutOptions`、`NodeType` 和 `ProcessModel`;不要仅为了这些类型安装或声明 `@bpmn-nova/studio`:
853
+
854
+ ```ts
855
+ import type { BpmnNode, ElementSelection, NodeType, EdgeType, ProcessModel } from '@bpmn-nova/vue'
856
+ ```
857
+
858
+ React 应用把入口替换为 `@bpmn-nova/react`。
859
+
764
860
  所有示例都必须满足:
765
861
 
766
862
  - 导入对应公开包的 `styles.css`。
@@ -808,7 +904,7 @@ const shell = createStudioShell({
808
904
  container: document.querySelector('#studio'),
809
905
  studio,
810
906
  mode: 'design',
811
- allowedModes: ['design'],
907
+ allowedModes: ['design', 'viewer'],
812
908
  theme: 'auto',
813
909
  })
814
910
 
@@ -827,6 +923,10 @@ export function disposeWorkflow() {
827
923
 
828
924
  Shell 负责界面组合,Controller 负责模型、命令、选择和历史。外部传入的 Controller 不会因 Shell 销毁而自动销毁。
829
925
 
926
+ Mode 是 Shell 展示状态。`design`、`viewer`、`instance` 分别表示流程设计、流程展示和审批轨迹;使用 `getMode()` / `setMode()` / `setAllowedModes()` / `subscribeMode()` 与宿主状态同步,不要把 Mode 写进 BPMN Model 或 Studio State。
927
+
928
+ 定义态业务摘要使用同步 `nodeSubtitleResolver`,按稳定 `node.id` 查询宿主数据。返回 `undefined` 保留 Nova 默认副标题,`null` 删除该行,字符串覆盖显示。外部 Map 更新后调用 `refreshPresentation()`;不要调用 `updateNode()`、重新导入 XML 或重建组件来刷新纯视觉摘要。Instance 模式继续完全使用 Runtime Presentation。
929
+
830
930
  ### 2.2 独立 Designer 或 Viewer
831
931
 
832
932
  独立能力仍由 Studio 提供,不要安装旧包:
@@ -870,12 +970,13 @@ npm install @bpmn-nova/react@preview
870
970
  ```
871
971
 
872
972
  ```jsx
873
- import { useRef } from 'react'
973
+ import { useRef, useState } from 'react'
874
974
  import { BpmnStudio } from '@bpmn-nova/react'
875
975
  import '@bpmn-nova/react/styles.css'
876
976
 
877
977
  export function WorkflowEditor({ initialXml }) {
878
978
  const studioRef = useRef(null)
979
+ const [mode, setMode] = useState('design')
879
980
 
880
981
  return (
881
982
  <div style={{ height: 720 }}>
@@ -883,18 +984,19 @@ export function WorkflowEditor({ initialXml }) {
883
984
  ref={studioRef}
884
985
  xml={initialXml}
885
986
  engine="flowable"
886
- mode="design"
887
- allowedModes={['design']}
987
+ mode={mode}
988
+ allowedModes={['design', 'viewer']}
888
989
  theme="auto"
889
990
  propertiesProfile="business"
890
991
  onChange={(model, reason, nextXml) => saveDraft(nextXml)}
992
+ onModeChange={(event) => setMode(event.mode)}
891
993
  />
892
994
  </div>
893
995
  )
894
996
  }
895
997
  ```
896
998
 
897
- 需要只读或审批轨迹时使用 React 包导出的 `BpmnViewer`,传入 `model`、`runtime`、`projection`、`runtimeAssetResolver` 和 `runtimeAppearance`。Ref 可访问 `exportXml()`、`exportSvg()`、`openSvgExportPreview()`、`fitView()` 和 `setTheme()`;实际可用方法以类型声明为准。
999
+ 需要只读或审批轨迹时使用 React 包导出的 `BpmnViewer`,传入 `model`、`runtime`、`projection`、`runtimeAssetResolver` 和 `runtimeAppearance`。Ref 可访问实际 `mode`、`setMode()`、`refreshPresentation()`、`exportXml()`、`exportSvg()`、`openSvgExportPreview()`、`fitView()` 和 `setTheme()`;Header Render Context 同步提供 `mode`。实际可用方法以类型声明为准。
898
1000
 
899
1001
  不要在 React effect 中每次渲染都重新创建 Vanilla 实例。优先使用 Adapter 组件,让属性变化更新现有实例。
900
1002
 
@@ -912,6 +1014,7 @@ import '@bpmn-nova/vue/styles.css'
912
1014
 
913
1015
  const props = defineProps({ initialXml: String })
914
1016
  const studioRef = ref(null)
1017
+ const mode = ref('design')
915
1018
  const onChange = (model, reason, nextXml) => saveDraft(nextXml)
916
1019
  </script>
917
1020
 
@@ -921,23 +1024,28 @@ const onChange = (model, reason, nextXml) => saveDraft(nextXml)
921
1024
  ref="studioRef"
922
1025
  :xml="props.initialXml"
923
1026
  engine="flowable"
924
- mode="design"
925
- :allowed-modes="['design']"
1027
+ v-model:mode="mode"
1028
+ :allowed-modes="['design', 'viewer']"
926
1029
  theme="auto"
927
1030
  properties-profile="business"
928
1031
  @change="onChange"
1032
+ @mode-change="event => console.log(event.source)"
929
1033
  />
930
1034
  </div>
931
1035
  </template>
932
1036
  ```
933
1037
 
934
- 需要只读或审批轨迹时使用 Vue 包导出的 `BpmnViewer`。事件使用 kebab-caseExpose 提供的实例能力以包内类型声明为准。不要在 watcher 中重复挂载组件,主题、Runtime、Projection 和 Regions 应通过响应式属性更新。
1038
+ 需要只读或审批轨迹时使用 Vue 包导出的 `BpmnViewer`。事件使用 kebab-case,`v-model:mode` 由 `update:mode` 驱动,`mode-change` 提供来源与前后值;Expose 包含 `getMode()`、`setMode()` 与 `refreshPresentation()`。不要在 watcher 中重复挂载组件,Mode、Theme、Runtime、Projection、RegionsResolver 应通过响应式属性或轻量刷新更新。
935
1039
 
936
1040
  ### 4.1 宿主工作台组合规则
937
1041
 
938
1042
  默认 `BpmnStudio` 是完整工作台。只有宿主明确拥有自己的区域时才配置 `regions`;例如 DX 复用自己的业务属性面板时使用 `regions: { right: 'hidden' }`,并把该面板放在 Nova 外部。隐藏区域不保留 Grid 轨道。
939
1043
 
940
- Vue 使用原生 `#header-start` / `#header`,React 使用 `headerStart` / `header` Render Prop。Header Start 只替换 Brand,完整 Header 通过公开 `StudioShellActions` 重建所需编辑操作。不要创建第二个 Vue App 或 React Root 挂载 Header。
1044
+ Vue 使用原生 `#header-start` / `#header-actions` / `#header`,React 使用 `headerStart` / `headerActions` / `header` Render Prop。Header Start 只替换 Brand,Header Actions 只替换默认“校验 / 导入 / 导出”动作组,完整 Header 通过公开 `StudioShellActions` 重建所需编辑操作。不要创建第二个 Vue App 或 React Root 挂载 Header。
1045
+
1046
+ 宿主通常在 Header Actions 中组合“校验 / 保存 / 发布”。校验按钮调用 `actions.validate()`:Nova 先更新默认状态栏,再通过 Vue `validation`、React `onValidation` 或 Core `subscribeValidation()` 发送只读结果。程序化 `validate()` 的来源为 `api`,Header Action 的来源为 `toolbar`;`valid` 仅在存在 error 时为 `false`。保存、发布、权限和服务端事务始终留在宿主。顶部不再重复渲染最佳视图,底部缩放区及 `fitView()` Interface 继续可用。
1047
+
1048
+ Header Slot/Render Context 的 `mode` 是当前实际模式。宿主用它显隐保存、发布按钮或外部属性面板;不要从 Nova Header DOM 读取选中按钮。运行时改变 `allowedModes` 会原地更新默认模式按钮,移除当前模式时只回退一次。
941
1049
 
942
1050
  外部业务属性面板必须以 `selection-change` / `onSelectionChange` 为状态来源,以稳定 BPMN Element ID 关联业务配置。该事件覆盖节点、连线、多选、清空和键盘选择;`element-click` / `onElementClick` 只是点击观察事件。保存草稿、发布、权限和服务端事务属于宿主,不要写入 Nova Actions。
943
1051
 
@@ -949,7 +1057,7 @@ Vue 使用原生 `#header-start` / `#header`,React 使用 `headerStart` / `hea
949
1057
 
950
1058
  React/Vue 包重新导出创建外部 Controller、Palette、Properties、Context Menu、Icon 和 Template Registry 所需的公开函数,因此高级接入仍只需要直接安装对应 Adapter 包。
951
1059
 
952
- 生产工作流通常只支持 BPMN 子集。通过 Controller 或 `BpmnStudio` 的 `allowedNodeTypes` 与 `allowedEdgeTypes` 声明节点、连线白名单;该限制会校验初始/外部模型,并约束创建、快捷新增、模板和节点类型转换。通过 `allowedModes` 限制工作台可切换模式。实例模式没有 Runtime 时保持空运行事实,不会自动加载演示数据。
1060
+ 生产工作流通常只支持 BPMN 子集。通过 Controller 或 `BpmnStudio` 的 `allowedNodeTypes` 与 `allowedEdgeTypes` 声明节点、连线白名单;该限制会校验初始/外部模型,并约束创建、快捷新增、模板和节点类型转换。Palette 会服从节点白名单,但同一节点类型可以有多个 Preset。通过 `allowedModes` 限制工作台可切换模式。实例模式没有 Runtime 时保持空运行事实,不会自动加载演示数据。
953
1061
 
954
1062
  ## 5. Runtime Snapshot 与审批动作
955
1063
 
@@ -1136,7 +1244,7 @@ BPMN Nova 负责 BPMN 建模、XML 导入导出、只读展示、运行态审批
1136
1244
 
1137
1245
  # BPMN Nova 快速开始
1138
1246
 
1139
- 本文面向通过 NPM 集成 BPMN Nova 的应用开发者。版本 `0.3.2-preview` 要求现代浏览器;Node.js 18+ 用于构建、SSR 和开发工具。
1247
+ 本文面向通过 NPM 集成 BPMN Nova 的应用开发者。版本 `0.3.4-preview` 要求现代浏览器;Node.js 18+ 用于构建、SSR 和开发工具。
1140
1248
 
1141
1249
  ## 1. 按语言与框架选择入口
1142
1250
 
@@ -1152,6 +1260,20 @@ JavaScript 与 TypeScript 使用相同的包和导入方式。所有公开包都
1152
1260
 
1153
1261
  Core、Viewer、Runtime、Theme 等目录不再是可直接安装的 NPM 包。Vanilla 项目从 Studio 根入口或受支持子路径导入;React/Vue 项目使用对应 Adapter。
1154
1262
 
1263
+ React/Vue Adapter 同时是公共 TypeScript 类型门面。模型、选区与图元类型从所选 Adapter 直接导入,不需要额外安装 Studio:
1264
+
1265
+ ```ts
1266
+ import type {
1267
+ BpmnNode,
1268
+ EdgeType,
1269
+ ElementSelection,
1270
+ NodeType,
1271
+ ProcessModel,
1272
+ } from '@bpmn-nova/vue'
1273
+ ```
1274
+
1275
+ React 项目使用 `@bpmn-nova/react`;两个入口还重导出 `BpmnEdge`、`EngineId` 和 `LayoutOptions`。
1276
+
1155
1277
  每个视觉包都有自己的完整样式入口。JavaScript 不会隐式插入 CSS:
1156
1278
 
1157
1279
  ```js
@@ -1205,7 +1327,7 @@ const shell = createStudioShell({
1205
1327
  container: document.querySelector('#studio'),
1206
1328
  studio,
1207
1329
  mode: 'design',
1208
- allowedModes: ['design'],
1330
+ allowedModes: ['design', 'viewer'],
1209
1331
  theme: 'auto',
1210
1332
  })
1211
1333
 
@@ -1226,6 +1348,38 @@ function dispose() {
1226
1348
 
1227
1349
  Controller 持有模型、命令、选择、历史与作用域;Shell 只负责组合 Canvas、Palette、Properties 和 Viewer。销毁 Shell 不会自动销毁外部传入的 Controller。
1228
1350
 
1351
+ 宿主可观察实际 Mode,并在运行时调整白名单:
1352
+
1353
+ ```js
1354
+ const offMode = shell.subscribeMode(({ mode, source }) => {
1355
+ externalProperties.hidden = mode !== 'design'
1356
+ console.log(source)
1357
+ })
1358
+
1359
+ shell.setMode('viewer')
1360
+ shell.setAllowedModes(['design', 'viewer'])
1361
+ ```
1362
+
1363
+ `design` 是流程设计,`viewer` 是流程展示,`instance` 是审批轨迹。Mode 只属于 Shell 展示状态,不会进入 BPMN Model 或撤销历史。
1364
+
1365
+ 业务数据需要显示在标准节点副标题时,传入同步 `nodeSubtitleResolver`;闭包中的 Map 更新后调用无历史刷新:
1366
+
1367
+ ```js
1368
+ const subtitles = new Map()
1369
+ const shell = createStudioShell({
1370
+ container,
1371
+ studio,
1372
+ nodeSubtitleResolver: ({ node }) => subtitles.has(node.id)
1373
+ ? subtitles.get(node.id)
1374
+ : undefined,
1375
+ })
1376
+
1377
+ subtitles.set('ServiceTask_Archive', '归档到采购系统')
1378
+ shell.refreshPresentation()
1379
+ ```
1380
+
1381
+ `undefined` 使用 Nova 默认值,`null` 删除该行。该 Resolver 只影响 Design/Viewer 与 SVG 标准视觉;Instance 仍由 Runtime Snapshot/Presentation 决定。`allowedNodeTypes` 会过滤 Palette,但同一节点类型可以继续提供多个业务 Preset。
1382
+
1229
1383
  ## 4. XML 导入与导出
1230
1384
 
1231
1385
  ```js
@@ -1244,7 +1398,7 @@ const activitiXml = studio.exportXml('activiti')
1244
1398
  const issues = studio.model.nodes.length ? [] : ['流程没有节点']
1245
1399
  ```
1246
1400
 
1247
- 独立 `BpmnDesigner` 提供内置 `validate()`;Studio 当前通过属性规则和命令约束模型,宿主也可以添加自己的发布校验。
1401
+ 独立 `BpmnDesigner` 提供纯校验 `validate()`。完整 Studio 则通过 `actions.validate()` 或 Shell/框架公开的 `validate()` 执行 Nova 校验、更新内部状态摘要、发送校验事件并返回 issues;宿主仍可在发布前追加自己的业务规则。
1248
1402
 
1249
1403
  `allowedNodeTypes` 与 `allowedEdgeTypes` 是完整模型约束:初始模型和后续导入包含白名单外节点或连线时会拒绝,Palette、连接、快捷新增、模板及节点类型转换也使用同一约束。只有确实支持全部 Nova 图元的宿主才省略它们。
1250
1404
 
@@ -1325,12 +1479,14 @@ npm install @bpmn-nova/react@preview
1325
1479
  ```
1326
1480
 
1327
1481
  ```jsx
1328
- import { useRef } from 'react'
1482
+ import { useCallback, useRef, useState } from 'react'
1329
1483
  import { BpmnStudio } from '@bpmn-nova/react'
1330
1484
  import '@bpmn-nova/react/styles.css'
1331
1485
 
1332
1486
  export function WorkflowEditor({ initialXml }) {
1333
1487
  const ref = useRef(null)
1488
+ const [mode, setMode] = useState('design')
1489
+ const subtitleResolver = useCallback(({ node, defaultSubtitle }) => defaultSubtitle, [])
1334
1490
 
1335
1491
  return (
1336
1492
  <div style={{ height: 720 }}>
@@ -1338,12 +1494,14 @@ export function WorkflowEditor({ initialXml }) {
1338
1494
  ref={ref}
1339
1495
  xml={initialXml}
1340
1496
  engine="flowable"
1341
- mode="design"
1342
- allowedModes={['design']}
1497
+ mode={mode}
1498
+ allowedModes={['design', 'viewer']}
1499
+ nodeSubtitleResolver={subtitleResolver}
1343
1500
  propertiesProfile="business"
1344
1501
  theme="auto"
1345
1502
  onChange={(model, reason, nextXml) => saveDraft(nextXml)}
1346
1503
  onSelectionChange={(selection, element) => console.log(element)}
1504
+ onModeChange={(event) => setMode(event.mode)}
1347
1505
  />
1348
1506
  </div>
1349
1507
  )
@@ -1357,7 +1515,7 @@ const { studio, state, commands } = useBpmnStudio({ model })
1357
1515
  return <BpmnStudio studio={studio} />
1358
1516
  ```
1359
1517
 
1360
- Ref 可访问 `studio`、`shell`、`actions`、`exportXml()`、`fitView()` 和 `setTheme()`。
1518
+ Ref 可访问 `studio`、`shell`、`actions`、实际 `mode`、`setMode()`、`validate()`、`refreshPresentation()`、`exportXml()`、`fitView()` 和 `setTheme()`。`onValidation` 在 Nova 内部状态展示完成后收到校验结果;Header Render Context 同样提供响应式实际 `mode`。
1361
1519
 
1362
1520
  ## 8. Vue 3.3+
1363
1521
 
@@ -1375,6 +1533,7 @@ import '@bpmn-nova/vue/styles.css'
1375
1533
 
1376
1534
  const props = defineProps({ initialXml: String })
1377
1535
  const studioRef = ref(null)
1536
+ const mode = ref('design')
1378
1537
  const onChange = (model, reason, nextXml) => saveDraft(nextXml)
1379
1538
  </script>
1380
1539
 
@@ -1384,17 +1543,19 @@ const onChange = (model, reason, nextXml) => saveDraft(nextXml)
1384
1543
  ref="studioRef"
1385
1544
  :xml="props.initialXml"
1386
1545
  engine="flowable"
1387
- mode="design"
1388
- :allowed-modes="['design']"
1546
+ v-model:mode="mode"
1547
+ :allowed-modes="['design', 'viewer']"
1389
1548
  properties-profile="business"
1390
1549
  theme="auto"
1391
1550
  @change="onChange"
1551
+ @mode-change="event => console.log(event.source)"
1552
+ @validation="event => console.log(event.valid, event.issues)"
1392
1553
  />
1393
1554
  </div>
1394
1555
  </template>
1395
1556
  ```
1396
1557
 
1397
- Vue 事件使用 kebab-case:`change`、`selection-change`、`scope-change`、`element-click` 和 `trace-click`。Expose 提供 `getStudio()`、`getShell()`、`getActions()`、`exportXml()`、`fitView()` 与 `setTheme()`。
1558
+ Vue 事件使用 kebab-case:`change`、`selection-change`、`scope-change`、`element-click`、`trace-click`、`update:mode`、`mode-change` 和 `validation`。Expose 提供 `getStudio()`、`getShell()`、`getActions()`、`getMode()`、`setMode()`、`validate()`、`refreshPresentation()`、`exportXml()`、`fitView()` 与 `setTheme()`;Header Slot Context 的 `mode` 为响应式实际状态。
1398
1559
 
1399
1560
  框架组件把 `xml`/`model` 作为外部替换输入,把 `change`/`onChange` 的 XML 作为草稿输出。完全相同的导出 XML 回写会被忽略并保留 Undo/Redo;不同 XML 表示宿主有意加载另一流程或服务器 revision,会替换模型并重置历史。React/Vue 包也重新导出了外部 Controller 和各类 Registry 的创建函数,高级接入无需直接安装 Studio。
1400
1561
 
@@ -1415,14 +1576,28 @@ Vue 事件使用 kebab-case:`change`、`selection-change`、`scope-change`、`
1415
1576
  theme="auto"
1416
1577
  @change="handleChange"
1417
1578
  @selection-change="handleSelectionChange"
1579
+ @validation="handleValidation"
1418
1580
  >
1419
1581
  <template #header-start="{ state, actions }">
1420
1582
  <!-- 返回、业务图标、流程名称、类型 -->
1421
1583
  </template>
1584
+ <template #header-actions="{ actions, mode }">
1585
+ <button type="button" :disabled="mode !== 'design'" @click="actions.validate()">校验</button>
1586
+ <button type="button" :disabled="mode !== 'design'" @click="saveDraft(actions.exportXml())">保存</button>
1587
+ <button type="button" :disabled="mode !== 'design'" @click="publishProcess(actions)">发布</button>
1588
+ </template>
1422
1589
  </BpmnStudio>
1423
1590
  ```
1424
1591
 
1425
- Vue 的 `#header-start` 只替换 Brand,`#header` 替换完整 Header;React 使用等价的 `headerStart` / `header` Render Prop。完整 Header 中使用公开 Actions 执行编辑操作。`regions` 属性变化会原地更新区域,不重建 Canvas。
1592
+ Vue 的 `#header-start` 只替换 Brand,`#header-actions` 只替换默认“校验 / 导入 / 导出”动作组,`#header` 替换完整 Header;React 使用等价的 `headerStart` / `headerActions` / `header` Render Prop。顶部最佳视图已去重,底部入口与 `fitView()` 保留。`actions.validate()` 先展示 Nova 内部结果,再发送 `validation` / `onValidation`,最后返回 issues。`regions` 属性变化会原地更新区域,不重建 Canvas。
1593
+
1594
+ ```js
1595
+ async function publishProcess(actions) {
1596
+ const issues = actions.validate()
1597
+ if (issues.some((issue) => issue.level === 'error')) return
1598
+ await publishXml(actions.exportXml())
1599
+ }
1600
+ ```
1426
1601
 
1427
1602
  把宿主属性面板放在 Nova 外部,以 `selection-change` / `onSelectionChange` 作为状态来源,并用稳定 BPMN Element ID 关联业务配置。该事件覆盖节点、连线、多选、清空和键盘选择;`element-click` 不能替代选择状态。Nova 不负责保存、发布、权限或服务端事务。
1428
1603
 
@@ -1485,7 +1660,7 @@ BPMN Nova 主题应挂在组件根容器。自定义 Renderer 不要修改 `docu
1485
1660
 
1486
1661
  # BPMN Nova 组件参数
1487
1662
 
1488
- 本手册记录 `0.3.2-preview` 的公开组件参数、回调和实例方法。所有视觉组件都需要具有实际尺寸的容器,并显式导入所属包的 `styles.css`。
1663
+ 本手册记录 `0.3.4-preview` 的公开组件参数、回调和实例方法。所有视觉组件都需要具有实际尺寸的容器,并显式导入所属包的 `styles.css`。
1489
1664
 
1490
1665
  ## 按项目环境阅读
1491
1666
 
@@ -1561,16 +1736,19 @@ Controller 不创建 DOM,负责模型、命令、历史、选择与子流程
1561
1736
  | `templateRegistry` | `TemplateRegistry` | 默认 Registry | 企业模板入口 |
1562
1737
  | `contextMenuRegistry` | `ContextMenuRegistry` | 默认 Registry | 右键动作入口 |
1563
1738
  | `rendererOptions` | `DiagramRendererOptions` | `{}` | 节点与 Runtime Renderer 配置 |
1739
+ | `nodeSubtitleResolver` | `NodeSubtitleResolver` | 无 | 覆盖 Design/Viewer 标准节点副标题;不影响 Instance |
1564
1740
  | `slots` | `StudioShellSlots` | `{}` | 局部 UI 替换 |
1565
1741
  | `regions` | `StudioShellRegions` | 全部 `default` | 原地隐藏 Header、Palette、Properties 或 Statusbar;隐藏后不保留轨道 |
1566
1742
  | `layout` | `Function` | 默认三栏布局 | 完整布局替换 |
1567
1743
  | `onThemeChange` | `(state) => void` | 无 | 主题模式解析变化回调 |
1568
1744
 
1569
- 实例方法包括 `getRegions()`、`setRegions()`、`setMode()`、`setRuntime()`、`setProjection()`、`setTheme()`、`setRuntimeAppearance()`、`fitView()`、`zoomBy()`、`exportSvg()`、`openSvgExportPreview()` 和 `destroy()`。
1745
+ 实例方法包括 `getMode()`、`getAllowedModes()`、`setMode()`、`setAllowedModes()`、`subscribeMode()`、`validate()`、`subscribeValidation()`、`getRegions()`、`setRegions()`、`setRuntime()`、`setProjection()`、`refreshPresentation()`、`setTheme()`、`setRuntimeAppearance()`、`fitView()`、`zoomBy()`、`exportSvg()`、`openSvgExportPreview()` 和 `destroy()`。`setMode()` 仅在真实成功切换时返回 `true`;Mode Event 的 `source` 为 `toolbar | api | allowed-modes`。
1570
1746
 
1571
1747
  `shell.actions` 是默认 Header 与宿主自定义 Header 共用的稳定 Interface,提供 `undo()`、`redo()`、`beautify()`、`rerouteEdges()`、`fitView()`、`validate()`、`importXml()`、`exportXml()`、`exportSvg()` 和 `openSvgExportPreview()`。它不包含保存、发布、权限或文件上传等宿主业务动作。
1572
1748
 
1573
- `slots.headerStart` 只替换 Nova Brand,保留默认模式区和工具区;`slots.header` 完整替换 Header,且优先级更高。Slot Context 提供 `studio`、`shell`、`canvas`、`actions`、`getState()` 和 `subscribe()`。`regions.header = 'hidden'` 的优先级最高。`layout()` 与 `regions` 不能同时使用。
1749
+ `slots.headerStart` 只替换 Nova Brand;`slots.headerActions` 只替换默认“校验 / 导入 / 导出”动作组;`slots.header` 完整替换 Header,且优先级更高。Slot Context 提供 `studio`、`shell`、`canvas`、`actions`、`getState()`、`subscribe()`、`getMode()`、`getAllowedModes()`、`subscribeMode()` 和 `subscribeValidation()`。默认 Header 的最佳视图只保留在底部缩放区。`regions.header = 'hidden'` 的优先级最高。`layout()` 与 `regions` 不能同时使用。
1750
+
1751
+ `actions.validate()` 先更新 Nova 默认状态栏,再发送一次来源为 `toolbar` 的 Validation Event 并返回 issues;实例 `validate()` 的来源为 `api`。事件 `valid` 只由 error 决定,warning 不默认阻止发布。
1574
1752
 
1575
1753
  ## `BpmnDesigner`
1576
1754
 
@@ -1611,13 +1789,14 @@ new BpmnDesigner(options)
1611
1789
  | `runtimeDetailsRenderer` | `RuntimeDetailsRenderer \| null` | 默认 Renderer | 替换或关闭节点详情 |
1612
1790
  | `runtimeTransitionDetailsRenderer` | `RuntimeTransitionDetailsRenderer \| null` | 默认 Renderer | 替换或关闭异常转移详情 |
1613
1791
  | `nodeRenderers` | `Record<string, NodeRenderer>` | `{}` | 按节点类型替换内部内容 |
1792
+ | `nodeSubtitleResolver` | `NodeSubtitleResolver` | 无 | 定义态标准节点副标题视觉投影 |
1614
1793
  | `onTraceClick` | `(event) => void` | 无 | 统一节点、线路、Visit、Transition 点击 |
1615
1794
  | `onElementClick` | `(payload) => void` | 无 | 基础元素点击 |
1616
1795
  | `onProjectionChange` | `({ requested, active }) => void` | 无 | 实际投影变化 |
1617
1796
  | `theme` | `NovaThemeInput` | `light` | 实例主题 |
1618
1797
  | `runtimeAppearance` | `RuntimeAppearanceOptions` | 默认映射 | Runtime 语义外观 |
1619
1798
 
1620
- 实例方法:`setModel()`、`setRuntime()`、`setProjection()`、`setDisplayOptions()`、`setTheme()`、`setRuntimeAppearance()`、`fitView()`、`openRuntimeDetails()`、`openRuntimeTransitionDetails()`、`closeRuntimeDetails()` 和 `destroy()`。
1799
+ 实例方法:`setModel()`、`setRuntime()`、`setProjection()`、`setDisplayOptions()`、`refreshPresentation()`、`setTheme()`、`setRuntimeAppearance()`、`fitView()`、`openRuntimeDetails()`、`openRuntimeTransitionDetails()`、`closeRuntimeDetails()` 和 `destroy()`。Compact Runtime Timeline 中 `refreshPresentation()` 安全 No-op。
1621
1800
 
1622
1801
  ## `BpmnCanvas`
1623
1802
 
@@ -1626,6 +1805,7 @@ new BpmnDesigner(options)
1626
1805
  | `container` | `HTMLElement` | 必填 | 画布容器 |
1627
1806
  | `studio` | `BpmnStudioController` | 必填 | Controller |
1628
1807
  | `rendererOptions` | `DiagramRendererOptions` | `{}` | Renderer 配置 |
1808
+ | `nodeSubtitleResolver` | `NodeSubtitleResolver` | 无 | 标准节点副标题 Resolver |
1629
1809
  | `interactions` | `InteractionController \| null` | `null` | Palette 拖放协议 |
1630
1810
  | `selectionToolbar` | `HTMLElement \| SelectionToolbarSlot \| null` | 默认工具栏 | 框选工具栏替换 |
1631
1811
  | `contextMenu` | `HTMLElement \| ContextMenuSlot \| null` | 默认菜单 | 右键菜单替换 |
@@ -1633,7 +1813,7 @@ new BpmnDesigner(options)
1633
1813
  | `pointerMode` | `'select' \| 'marquee' \| 'pan'` | `'select'` | 指针模式 |
1634
1814
  | `theme` | `NovaThemeInput` | `light` | 实例主题 |
1635
1815
 
1636
- 常用方法:`clientToWorld()`、`fitView()`、`fitSelection()`、`setPointerMode()`、`zoomBy()`、`actualSize()` 和 `destroy()`。
1816
+ 常用方法:`clientToWorld()`、`fitView()`、`fitSelection()`、`setPointerMode()`、`zoomBy()`、`actualSize()`、`refreshPresentation()` 和 `destroy()`。
1637
1817
 
1638
1818
  ## `PalettePanel`
1639
1819
 
@@ -1678,14 +1858,17 @@ new BpmnDesigner(options)
1678
1858
  | `allowedNodeTypes` | 创建内部 Controller 时使用的完整模型节点白名单 |
1679
1859
  | `allowedEdgeTypes` | 创建内部 Controller 时使用的完整模型连线白名单 |
1680
1860
  | `allowedModes` | Shell 显示并允许切换的工作台模式 |
1861
+ | `mode` / `onModeChange` | 受控输入与实际 Mode 事件;Header Render Context 同步提供 `mode` |
1862
+ | `nodeSubtitleResolver` | Design/Viewer 标准节点副标题 Resolver |
1681
1863
  | `contextMenuRegistry` | 自定义右键动作 Registry |
1682
1864
  | `regions` | 默认 Shell 区域显隐;属性变化原地调用 `setRegions()` |
1683
- | `headerStart` / `header` | React Node 或 Render Prop;使用 Portal 保留宿主 Context |
1865
+ | `headerStart` / `headerActions` / `header` | React Node 或 Render Prop;使用 Portal 保留宿主 Context |
1866
+ | `onValidation` | Nova 内部校验展示完成后的只读结果事件 |
1684
1867
  | `onChange(model, reason, xml)` | 模型变化 |
1685
1868
  | `onSelectionChange(selection, element)` | 选择变化 |
1686
1869
  | `onScopeChange(activeScopeId, scopePath, state)` | 子流程作用域变化 |
1687
1870
 
1688
- Ref:`studio`、`shell`、`actions`、`exportXml()`、`fitView()`、`setTheme()`。
1871
+ Ref:`studio`、`shell`、`actions`、`mode`、`getMode()`、`setMode()`、`setAllowedModes()`、`validate()`、`refreshPresentation()`、`exportXml()`、`fitView()`、`setTheme()`。
1689
1872
 
1690
1873
  `xml`/`model` 是外部替换输入。回写与最近导出完全相同的 XML 不会重复导入或清空 Undo/Redo;不同 XML 会替换模型和历史。React/Vue 包均重新导出创建外部 Controller 与 Palette、Properties、Context Menu、Icon、Template Registry 所需的公开函数。
1691
1874
 
@@ -1695,7 +1878,7 @@ Props:`model`、`xml`、`engine`、`theme`、`onChange`、`onSelectionChange`
1695
1878
 
1696
1879
  ### `BpmnViewer`
1697
1880
 
1698
- 接受除 `container/model` 外的 `ViewerOptions`,并通过 `model` 或 `xml` 输入流程。Ref:`instance`、`fitView()`、`setProjection()`、`setRuntime()`、`setDisplayOptions()`、`setTheme()`。
1881
+ 接受除 `container/model` 外的 `ViewerOptions`,并通过 `model` 或 `xml` 输入流程。Ref:`instance`、`fitView()`、`refreshPresentation()`、`setProjection()`、`setRuntime()`、`setDisplayOptions()`、`setTheme()`。
1699
1882
 
1700
1883
  ### `BpmnCanvas` / `BpmnPalettePanel` / `BpmnPropertiesPanel`
1701
1884
 
@@ -1705,11 +1888,11 @@ Props:`model`、`xml`、`engine`、`theme`、`onChange`、`onSelectionChange`
1705
1888
 
1706
1889
  Vue 组件与 React 使用同一底层接口,主要差异为:
1707
1890
 
1708
- - Studio 提供原生 `#header-start` 和 `#header` Slot,通过 Teleport 保留宿主 provide/inject、响应式状态和生命周期。
1709
- - `slotsConfig` 继续保留,作为高级 Core DOM Slot 入口;原生完整 Header、Core 完整 Header、原生 Header Start、Core Header Start 依次降级。
1710
- - 事件为 `change`、`selection-change`、`scope-change`、`element-click`、`trace-click`。
1891
+ - Studio 提供原生 `#header-start`、`#header-actions` 和 `#header` Slot,通过 Teleport 保留宿主 provide/inject、响应式状态和生命周期。
1892
+ - `slotsConfig` 继续保留,作为高级 Core DOM Slot 入口;完整 Header 高于局部 Header Slots,原生局部 Slot 高于对应 Core Slot。
1893
+ - 事件为 `change`、`selection-change`、`scope-change`、`element-click`、`trace-click`、`update:mode`、`mode-change`、`validation`;支持 `v-model:mode`。
1711
1894
  - `BpmnDesigner` 发出 `change`、`selection-change`。
1712
- - Ref Expose 使用 `getStudio()`、`getShell()`、`getActions()` 或 `getInstance()`,不直接暴露可替换字段。
1895
+ - Header Slot Context 的 `mode` 是响应式实际状态。Ref Expose 使用 `getStudio()`、`getShell()`、`getActions()`、`getMode()`、`setMode()`、`setAllowedModes()`、`validate()`、`refreshPresentation()` 或 `getInstance()`,不直接暴露可替换字段。
1713
1896
 
1714
1897
  Vue 提供 `BpmnStudio`、`BpmnDesigner`、`BpmnViewer`、`BpmnCanvas`、`BpmnPalettePanel`、`BpmnPropertiesPanel` 和 `useBpmnStudio()`。独立 `BpmnPalettePanel` 复用外部 Studio;传入 Registry 时不会隐式注册 Providers,未传 Registry 时才用 Providers 创建默认 Registry。
1715
1898
 
@@ -1733,7 +1916,23 @@ Runtime Details、Timeline 和 Transition Details 组件通过对应 `createReac
1733
1916
 
1734
1917
  <!-- SOURCE: docs/API.md -->
1735
1918
 
1736
- # BPMN Nova v0.3.2 Preview API
1919
+ # BPMN Nova v0.3.4 Preview API
1920
+
1921
+ ## Framework Adapter 类型门面
1922
+
1923
+ React/Vue 项目只直接依赖对应 Adapter。两个 Adapter 的根声明入口显式重导出 `BpmnEdge`、`BpmnNode`、`EdgeType`、`ElementSelection`、`EngineId`、`LayoutOptions`、`NodeType` 和 `ProcessModel`,宿主无需仅为这些公共类型增加 Studio 直依赖:
1924
+
1925
+ ```ts
1926
+ import type {
1927
+ BpmnNode,
1928
+ EdgeType,
1929
+ ElementSelection,
1930
+ NodeType,
1931
+ ProcessModel,
1932
+ } from '@bpmn-nova/vue'
1933
+ ```
1934
+
1935
+ React 使用相同名称,并将入口替换为 `@bpmn-nova/react`。这些是 TypeScript-only export,不会增加 Adapter 的浏览器运行时代码。
1737
1936
 
1738
1937
  ## Designer
1739
1938
 
@@ -1845,6 +2044,69 @@ const shell = createStudioShell({
1845
2044
 
1846
2045
  React/Vue Adapter 的 `BpmnStudio` 接受同名 `allowedNodeTypes`、`allowedEdgeTypes` 和 `allowedModes`。框架 `xml`/`model` 是外部替换输入;回写与当前导出完全相同的 XML 不会重新导入或清空历史,不同 XML 会替换模型并重置历史。
1847
2046
 
2047
+ ### Studio Mode Interface
2048
+
2049
+ ```ts
2050
+ type StudioMode = 'design' | 'viewer' | 'instance'
2051
+ type StudioModeChangeSource = 'toolbar' | 'api' | 'allowed-modes'
2052
+
2053
+ interface StudioModeChangeEvent {
2054
+ readonly mode: StudioMode
2055
+ readonly previousMode: StudioMode
2056
+ readonly source: StudioModeChangeSource
2057
+ readonly allowedModes: readonly StudioMode[]
2058
+ }
2059
+ ```
2060
+
2061
+ ```js
2062
+ shell.getMode()
2063
+ shell.getAllowedModes()
2064
+ shell.setMode('viewer')
2065
+ shell.setAllowedModes(['design', 'viewer'])
2066
+ const off = shell.subscribeMode((event) => console.log(event))
2067
+ ```
2068
+
2069
+ `setMode()` 只在完成一次真实切换时返回 `true`。同模式、不允许的模式或已销毁 Shell 返回 `false`,不重建也不发事件。`setAllowedModes()` 先完整校验非空、唯一且已知的 Mode;移除当前 Mode 时回退到新列表首项,只发送一次 `allowed-modes` 事件。事件在新视图挂载和 Shell UI 同步后发送,Mode 不进入 Controller State 或 History。
2070
+
2071
+ ### Studio Validation Interface
2072
+
2073
+ ```ts
2074
+ type StudioValidationSource = 'toolbar' | 'api'
2075
+
2076
+ interface StudioValidationEvent {
2077
+ readonly source: StudioValidationSource
2078
+ readonly valid: boolean
2079
+ readonly errorCount: number
2080
+ readonly warningCount: number
2081
+ readonly issues: readonly StudioValidationIssue[]
2082
+ }
2083
+ ```
2084
+
2085
+ `shell.actions.validate()` 用于默认或宿主 Header,来源为 `toolbar`;`shell.validate()` 用于程序调用,来源为 `api`。两者都会先运行纯 `studio.validate()`,同步更新 Nova 默认状态栏,再向 `subscribeValidation()` Listener 发送一次只读结果,最后返回兼容的 issues 数组。`valid` 等价于 `errorCount === 0`,warning 不默认阻止保存或发布。隐藏或替换默认 Footer 时事件与返回值不受影响,只是不再强制显示 Nova 状态摘要。
2086
+
2087
+ Vue 将事件透传为 `validation` 并 Expose `validate()`;React 使用 `onValidation` 和 Ref `validate()`。Listener 异常不会阻断其他 Listener、内部状态展示或返回值。
2088
+
2089
+ ### Node Subtitle Resolver 与刷新
2090
+
2091
+ ```ts
2092
+ interface NodeSubtitleResolverContext {
2093
+ readonly node: BpmnNode
2094
+ readonly definition: NodeDefinition
2095
+ readonly model: ProcessModel
2096
+ readonly mode: 'design' | 'viewer'
2097
+ readonly surface: 'canvas' | 'svg-export'
2098
+ readonly defaultSubtitle: string
2099
+ }
2100
+
2101
+ type NodeSubtitleResolver = (
2102
+ context: Readonly<NodeSubtitleResolverContext>,
2103
+ ) => string | null | undefined
2104
+ ```
2105
+
2106
+ `undefined` 保留默认值,`null` 删除副标题行,字符串替换视觉值;空字符串是显式字符串,不等同于隐藏。Resolver 必须同步,异常、Promise 或非法返回会抛出包含节点 ID 的错误。它只作用于 Design/Viewer 的标准任务和容器卡片;事件、网关、泳道等不会新增副标题槽,完整自定义 Renderer 优先,Instance 始终使用 Runtime Presentation。
2107
+
2108
+ `DiagramRenderer`、`BpmnCanvas`、`BpmnViewer` 与 `BpmnStudioShell` 均提供 `refreshPresentation()`。该方法先计算全部目标节点,再原位更新 DOM;失败时保持上一版视觉,不调用 Model Mutation、History、完整 Viewer Refresh 或 `fitView()`。SVG Export 使用同一默认规则和 Resolver,标准降级路径失败时直接 Reject。
2109
+
1848
2110
  ## Studio Shell 区域、Actions 与 Header Slot
1849
2111
 
1850
2112
  默认 Shell 是完整工作台。`regions` 只控制默认布局中的区域,`hidden` 不保留行列轨道:
@@ -1866,9 +2128,13 @@ const shell = createStudioShell({
1866
2128
  studio,
1867
2129
  regions: { right: 'hidden' },
1868
2130
  slots: {
1869
- headerStart({ container, studio, shell, canvas, actions, getState, subscribe }) {
2131
+ headerStart({ container, studio, shell, canvas, actions, getState, subscribe, getMode, getAllowedModes, subscribeMode, subscribeValidation }) {
1870
2132
  // 只替换 Brand;默认模式区和编辑工具继续保留。
1871
2133
  },
2134
+ headerActions({ container, actions, getMode, subscribeMode }) {
2135
+ // 替换默认“校验 / 导入 / 导出”,挂载宿主“校验 / 保存 / 发布”。
2136
+ // 校验调用 actions.validate();保存与发布调用宿主服务。
2137
+ },
1872
2138
  },
1873
2139
  })
1874
2140
 
@@ -1876,7 +2142,7 @@ shell.getRegions()
1876
2142
  shell.setRegions({ right: 'default' })
1877
2143
  ```
1878
2144
 
1879
- `slots.header` 完整替换 Header,并高于 `slots.headerStart`;`regions.header = 'hidden'` 的优先级最高。`layout()` 与 `regions` 互斥。
2145
+ `slots.headerActions` 只替换 Header 最右侧默认动作组,可与 `slots.headerStart` 同时使用;`slots.header` 完整替换 Header,并高于两个局部 Slot;`regions.header = 'hidden'` 的优先级最高。未提供 `headerActions` 时仍显示“校验 / 导入 / 导出”。顶部不再重复渲染最佳视图,底部缩放区与 `fitView()` Interface 保持不变。`layout()` 与 `regions` 互斥。
1880
2146
 
1881
2147
  ```ts
1882
2148
  interface StudioShellActions {
@@ -1893,9 +2159,9 @@ interface StudioShellActions {
1893
2159
  }
1894
2160
  ```
1895
2161
 
1896
- 默认 Header 与宿主 Header 都调用 `shell.actions`。Actions 保留 Controller 的返回值与异常语义,但不处理文件选择、保存草稿、发布、权限或宿主 API。
2162
+ 默认 Header 与宿主 Header 都调用 `shell.actions`。保存草稿、发布、权限和宿主服务不进入 Actions;宿主通过 `headerActions` 闭包调用自己的业务方法,并使用 `actions.exportXml()` 获取草稿。
1897
2163
 
1898
- Vue `BpmnStudio` 提供 `#header-start` / `#header` 与 `getActions()`;React 提供 `headerStart` / `header` Render Prop 与 Ref `actions`。框架插槽的 `state` 会随 Controller 事件更新,Undo/Redo 禁用状态可以直接绑定 `state.canUndo/canRedo`。
2164
+ Vue `BpmnStudio` 提供 `#header-start` / `#header-actions` / `#header` 与 `getActions()`;React 提供 `headerStart` / `headerActions` / `header` Render Prop 与 Ref `actions`。Core Slot 可通过 `getMode()` / `subscribeMode()` / `subscribeValidation()` 观察 Shell,框架 Slot/Render Context 直接提供响应式实际 `mode`。框架插槽的 `state` 会随 Controller 事件更新,Undo/Redo 禁用状态可以直接绑定 `state.canUndo/canRedo`。
1899
2165
 
1900
2166
  ## Group 与 Pool / Lane
1901
2167
 
@@ -2458,7 +2724,7 @@ shell.setRegions({ right: 'default' })
2458
2724
 
2459
2725
  `header`、`left`、`right`、`footer` 均接受 `default | hidden`。隐藏区域不占 Grid 轨道、不显示边框,也不保留可聚焦控件。Viewer/Instance 的只读布局仍会隐藏 Palette;区域配置只能进一步隐藏。
2460
2726
 
2461
- 局部内容替换使用 `slots.left`、`slots.right`、`slots.headerStart`、`slots.header` 和 `slots.footer`。`headerStart` 只替换默认 Brand,保留模式区和工具区;`header` 替换完整 Header,优先级高于 `headerStart`。回调收到 `studio`、`shell`、`actions`、`getState()`、`subscribe()`、注册表、交互控制器和 Canvas。
2727
+ 局部内容替换使用 `slots.left`、`slots.right`、`slots.headerStart`、`slots.headerActions`、`slots.header` 和 `slots.footer`。`headerStart` 只替换默认 Brand;`headerActions` 只替换最右侧默认“校验 / 导入 / 导出”动作组;`header` 替换完整 Header,优先级高于两个局部 Slot。回调收到 `studio`、`shell`、`actions`、`getState()`、`subscribe()`、注册表、交互控制器和 Canvas。
2462
2728
 
2463
2729
  ```js
2464
2730
  createStudioShell({
@@ -2468,6 +2734,9 @@ createStudioShell({
2468
2734
  headerStart({ container, actions, getState, subscribe }) {
2469
2735
  // 挂载返回入口、业务图标、流程名称和类型;返回卸载函数。
2470
2736
  },
2737
+ headerActions({ container, actions, getMode, subscribeMode }) {
2738
+ // 挂载校验 / 保存 / 发布;校验调用 actions.validate(),其余调用宿主服务。
2739
+ },
2471
2740
  left({ container, studio, interactions, canvas }) {
2472
2741
  // 挂载任意 Vanilla / React / Vue UI,返回卸载函数。
2473
2742
  },
@@ -2478,9 +2747,19 @@ createStudioShell({
2478
2747
  });
2479
2748
  ```
2480
2749
 
2481
- 默认 Header 和完整自定义 Header 共用 `shell.actions`:撤销/重做、布局/布线、最佳视图、结构校验、BPMN XML 导入导出及 SVG 导出。Actions 不拥有宿主的保存草稿、发布、权限、文件选择或服务端事务。
2750
+ 默认 Header 和宿主 Header Slots 共用 `shell.actions`:撤销/重做、布局/布线、最佳视图、结构校验、BPMN XML 导入导出及 SVG 导出。顶部不再重复显示最佳视图,底部缩放区和程序化 `fitView()` 继续可用。Actions 不拥有宿主的保存草稿、发布、权限、文件选择或服务端事务。
2482
2751
 
2483
- React 使用 `headerStart` / `header` Render Prop Portal;Vue 使用 `#header-start` / `#header` Named Slot 和 Teleport。两者都在宿主应用树内渲染,不创建独立 React Root 或 Vue App,因此 Context、provide/inject、响应式状态和生命周期继续有效。Vue 原有 `slotsConfig`、React 原有 `slots` 仍作为 Core DOM 接口保留。
2752
+ `actions.validate()` 会先更新 Nova 默认状态栏,再发送 `toolbar` 来源的 Validation Event,并返回 issues。程序化 `shell.validate()` 使用 `api` 来源;两者都可由 `shell.subscribeValidation()` 观察。`valid` 表示不存在 error,warning 仍会显示并随事件返回。
2753
+
2754
+ ```js
2755
+ async function publishProcess(actions) {
2756
+ const issues = actions.validate()
2757
+ if (issues.some((issue) => issue.level === 'error')) return
2758
+ await publishXml(actions.exportXml())
2759
+ }
2760
+ ```
2761
+
2762
+ React 使用 `headerStart` / `headerActions` / `header` Render Prop 和 Portal;Vue 使用 `#header-start` / `#header-actions` / `#header` Named Slot 和 Teleport。两者都在宿主应用树内渲染,不创建独立 React Root 或 Vue App,因此 Context、provide/inject、响应式状态和生命周期继续有效。Vue 原有 `slotsConfig`、React 原有 `slots` 仍作为 Core DOM 接口保留。
2484
2763
 
2485
2764
  若整个三栏结构都要自定义,使用 `layout({ container, mount, ...services })`。`mount.canvas()`、`mount.palette()`、`mount.properties()` 可分别挂载官方实现,也可只使用 Controller 自行实现。`layout()` 与 `regions` 是互斥 Interface,同时传入会抛出配置错误。
2486
2765
 
@@ -2570,6 +2849,32 @@ const canvasRef = ref(null)
2570
2849
 
2571
2850
  创建外部 Controller 的一方负责在页面卸载时销毁它;Canvas 和 Palette Adapter 不销毁外部 Controller。
2572
2851
 
2852
+ ### 只覆盖标准节点副标题
2853
+
2854
+ 不需要复制整个节点 Renderer 时,优先使用 `nodeSubtitleResolver`。它复用 Nova 的默认标题、图标、端口、Tooltip、ARIA 与 SVG 布局,只替换标准任务和容器卡片的定义态副标题:
2855
+
2856
+ ```js
2857
+ const summaries = new Map()
2858
+ const shell = createStudioShell({
2859
+ container,
2860
+ studio,
2861
+ nodeSubtitleResolver({ node, definition, model, mode, surface, defaultSubtitle }) {
2862
+ if (!summaries.has(node.id)) return undefined
2863
+ return summaries.get(node.id)
2864
+ },
2865
+ })
2866
+
2867
+ summaries.set('ServiceTask_Archive', '1 条归档规则')
2868
+ shell.refreshPresentation()
2869
+
2870
+ summaries.set('ServiceTask_Archive', null) // 删除副标题行
2871
+ shell.refreshPresentation()
2872
+ ```
2873
+
2874
+ 返回 `undefined` 恢复权威默认值,返回 `null` 隐藏,字符串(包括 `''`)是显式覆盖。Resolver 必须同步且只读;异常、Promise 或非法值会带节点 ID 失败。刷新会先解析全部节点再更新,因此不会留下局部视觉,也不会改变 XML、Undo/Redo、Selection、Scope、Zoom/Pan 或 Mode。
2875
+
2876
+ 优先级为“成功的完整自定义 Renderer > Subtitle Resolver > Nova 默认副标题”。HTML Renderer 没有 SVG 适配而回退到标准导出视觉时,SVG 会应用 Resolver;Instance 不调用 Resolver,等待、会签、驳回和重新进入摘要继续来自 Runtime Presentation。业务候选人摘要不能写入标准 `candidateUsers/candidateGroups` 来冒充执行配置。
2877
+
2573
2878
  HTML 节点内容不会被复制到导出的 SVG。需要保持品牌视觉时,应为同一节点类型提供纯 SVG 适配;Renderer 接收 `SVGGElement`、具体主题快照与 Icon Registry,只能创建 SVG Primitive,不能使用 `foreignObject`:
2574
2879
 
2575
2880
  ```js
@@ -2745,7 +3050,7 @@ createStudioShell({
2745
3050
 
2746
3051
  # BPMN Nova NPM 包与发布
2747
3052
 
2748
- 版本:`0.3.2-preview`。BPMN Nova 只发布三个 `@bpmn-nova` 公共包,均使用 ESM、附带 TypeScript 声明、采用 Apache-2.0 License,并通过 `preview` dist-tag 发布。
3053
+ 版本:`0.3.4-preview`。BPMN Nova 只发布三个 `@bpmn-nova` 公共包,均使用 ESM、附带 TypeScript 声明、采用 Apache-2.0 License,并通过 `preview` dist-tag 发布。
2749
3054
 
2750
3055
  ## 公共包
2751
3056
 
@@ -2757,7 +3062,9 @@ createStudioShell({
2757
3062
  | React 18+ | `npm install @bpmn-nova/react@preview` | React 组件、Hook 与 Ref;依赖 Studio |
2758
3063
  | Vue 3.3+ | `npm install @bpmn-nova/vue@preview` | Vue 组件、Composable 与 Expose;依赖 Studio |
2759
3064
 
2760
- Core、Model、Renderer、Runtime、Theme、Properties 和引擎 Profile 是源码内部 Module,不再是可独立安装或独立发布的产品。React/Vue 各自只依赖完全相同版本的 `@bpmn-nova/studio`,并通过 peer dependency 使用宿主框架。
3065
+ Core、Model、Renderer、Runtime、Theme、Properties、Node Presentation 和引擎 Profile 是源码内部 Module,不再是可独立安装或独立发布的产品。`NodeSubtitleResolver` 类型从 Studio 根入口公开,但 `node-presentation` 没有 npm 子路径或独立版本。React/Vue 各自只依赖完全相同版本的 `@bpmn-nova/studio`,并通过 peer dependency 使用宿主框架。
3066
+
3067
+ React/Vue 的声明入口显式重导出宿主常用的 Core 类型:`BpmnEdge`、`BpmnNode`、`EdgeType`、`ElementSelection`、`EngineId`、`LayoutOptions`、`NodeType` 和 `ProcessModel`。业务项目必须从自己选择的 Adapter 导入这些类型,不应仅为类型在 manifest 中增加 Studio 直依赖。
2761
3068
 
2762
3069
  ## Studio 子路径
2763
3070
 
@@ -2780,7 +3087,7 @@ JavaScript 不会隐式插入 CSS。Studio 项目导入 `@bpmn-nova/studio/style
2780
3087
 
2781
3088
  源码目录保留当前 Module 边界和相对引用,以便 Playground 无需安装 workspace 包即可运行。发布构建执行以下操作:
2782
3089
 
2783
- 1. 将 Core、Model、Renderer、Runtime、Properties、Theme、引擎 Profile 和 SVG Export 复制到 `packages/studio/dist/modules`。
3090
+ 1. 将 Core、Model、Renderer、Runtime、Properties、Node Presentation、Theme、引擎 Profile 和 SVG Export 复制到 `packages/studio/dist/modules`。
2784
3091
  2. 将 Studio 中跨 Module 的源码引用改写为 `dist` 内部相对路径。
2785
3092
  3. 生成 Studio 根入口和受支持子路径所需的 JavaScript 与声明文件。
2786
3093
  4. 将 React/Vue 产物的运行时和类型导入统一改写到 `@bpmn-nova/studio`。
@@ -2828,6 +3135,7 @@ git diff --check
2828
3135
  - Studio、React、Vue 样式子路径存在。
2829
3136
  - 三个包都能直接读取 `llms.txt` 和 `llms-full.txt`,不需要访问源码仓库。
2830
3137
  - TypeScript 能解析 Options、Runtime、Theme、Ref/Expose 等声明。
3138
+ - TypeScript 能从三个公开入口解析 Mode Event、`NodeSubtitleResolver` 与 `refreshPresentation()`,无需导入内部 Module。
2831
3139
  - React/Vue Adapter 可以复用 Studio,不会安装历史内部包。
2832
3140
 
2833
3141
  ## 发布顺序
@@ -2845,14 +3153,14 @@ git diff --check
2845
3153
  发布后核对:
2846
3154
 
2847
3155
  ```bash
2848
- npm view @bpmn-nova/studio@0.3.2-preview version
2849
- npm view @bpmn-nova/react@0.3.2-preview version
2850
- npm view @bpmn-nova/vue@0.3.2-preview version
3156
+ npm view @bpmn-nova/studio@0.3.4-preview version
3157
+ npm view @bpmn-nova/react@0.3.4-preview version
3158
+ npm view @bpmn-nova/vue@0.3.4-preview version
2851
3159
  ```
2852
3160
 
2853
3161
  ## Registry 清理说明
2854
3162
 
2855
- Registry 清理是不可逆的外部操作,不由构建脚本自动执行。只有在三个 `0.3.2-preview` 新产物发布、安装和子路径验证均成功后,才能在获得单独明确授权的情况下执行:
3163
+ Registry 清理是不可逆的外部操作,不由构建脚本自动执行。只有在三个 `0.3.4-preview` 新产物发布、安装和子路径验证均成功后,才能在获得单独明确授权的情况下执行:
2856
3164
 
2857
3165
  1. 删除 Studio、React、Vue 的旧 `0.3.0-preview` 版本。
2858
3166
  2. 按反向依赖顺序删除旧的内部包:Designer/Viewer/Properties 聚合层,Renderer/Provider/Model 层,最后 Runtime/Theme/Core 等基础层。