y-mxgraph 0.1.4 → 0.1.6

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/README.md CHANGED
@@ -29,13 +29,20 @@ import { Binding, LOCAL_ORIGIN } from 'y-mxgraph';
29
29
  const doc = new Y.Doc();
30
30
 
31
31
  App.main((app) => {
32
- // Ensure consistent initial files across clients. draw.io generates random diagram ids by default,
33
- // which can cause sync issues if clients start from different states. Use generateFileTemplate to create a unified template.
34
- if (!app.currentFile.data) {
35
- app.currentFile.data = Binding.generateFileTemplate('diagram-0');
32
+ const file = app.currentFile;
33
+
34
+ // If Y.Doc already has data (from other clients), use it
35
+ const mxfileMap = doc.getMap('mxfile');
36
+ const diagramMap = mxfileMap.get('diagram');
37
+ if (diagramMap && diagramMap.size > 0) {
38
+ const { doc2xml } = await import('y-mxgraph');
39
+ file.ui.setFileData(doc2xml(doc));
40
+ file.setData(doc2xml(doc));
41
+ } else if (!file.data) {
42
+ file.data = Binding.generateFileTemplate('diagram-0');
36
43
  }
37
44
 
38
- const binding = new Binding(app.currentFile, { doc });
45
+ const binding = new Binding(file, { doc });
39
46
 
40
47
  window.addEventListener('beforeunload', () => binding.destroy());
41
48
  });
@@ -72,6 +79,10 @@ pnpm --filter @y-mxgraph/demo dev
72
79
 
73
80
  # iframe mode (parent page runs WebRTC Provider, two iframes each run draw.io + y-mxgraph, synced via postMessage)
74
81
  # Visit http://localhost:5173/iframe-mode.html
82
+
83
+ # WebSocket server mode (centralized server with file persistence)
84
+ pnpm --filter @y-mxgraph/ws-demo server # Start server on port 1234
85
+ pnpm --filter @y-mxgraph/ws-demo dev # Start client on port 5174
75
86
  ```
76
87
 
77
88
  ## Docs
package/README.zh-CN.md CHANGED
@@ -63,9 +63,13 @@ pnpm --filter y-mxgraph build
63
63
  # 测试
64
64
  pnpm --filter y-mxgraph test
65
65
 
66
- # 启动 Demo
66
+ # 启动 Demo (WebRTC 模式)
67
67
  pnpm --filter @y-mxgraph/demo dev
68
68
 
69
+ # 启动 WebSocket 服务器 Demo (支持文件持久化)
70
+ pnpm --filter @y-mxgraph/ws-demo server # 启动服务器 (端口 1234)
71
+ pnpm --filter @y-mxgraph/ws-demo dev # 启动客户端 (端口 5174)
72
+
69
73
  # 启动文档
70
74
  pnpm --filter @y-mxgraph/docs dev
71
75
  ```
@@ -13,6 +13,11 @@ export interface BindDrawioFileOptions {
13
13
  }
14
14
  /**
15
15
  * Y-MXGraph 绑定类,管理 draw.io 文件与 Y.Doc 的双向同步
16
+ *
17
+ * 初始化流程对齐 y-prosemirror 等数据源:
18
+ * - 绑定时不向 Y.Doc 写入初始数据
19
+ * - 在第一次本地编辑时才初始化 Y.Doc
20
+ * - 新客户端加入时,同步已有的远端数据到本地
16
21
  */
17
22
  export declare class Binding {
18
23
  /** Y.Doc 实例,用于协同数据存储 */
@@ -21,6 +26,8 @@ export declare class Binding {
21
26
  private mxGraphModel;
22
27
  /** 本地变更抑制标志,防止循环同步 */
23
28
  private suppressLocalApply;
29
+ /** 初始化标志,标记 Y.Doc 是否已初始化 */
30
+ private docInitialized;
24
31
  /** mxGraph change 事件监听器 */
25
32
  private mxListener;
26
33
  /** Yjs 文档深度变更监听器 */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/binding/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOvD,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,iBAAiB,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC;IACX,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EACH,OAAO,GACP;QACE,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACP;AAED;;GAEG;AACH,qBAAa,OAAO;IAClB,wBAAwB;IACxB,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC;IACpB,6BAA6B;IAC7B,OAAO,CAAC,YAAY,CAAe;IACnC,sBAAsB;IACtB,OAAO,CAAC,kBAAkB,CAAS;IACnC,2BAA2B;IAC3B,OAAO,CAAC,UAAU,CAAa;IAC/B,oBAAoB;IACpB,OAAO,CAAC,WAAW,CAKT;IACV,gCAAgC;IAChC,OAAO,CAAC,mBAAmB,CAAC,CAAa;IACzC,yBAAyB;IACzB,OAAO,CAAC,kBAAkB,CAAC,CAAa;gBAE5B,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB;IAkF5D;;;OAGG;IACH,OAAO,CAAC,IAAI,UAAQ,GAAG,IAAI;IAS3B;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,oBAAoB,CAAC,SAAS,SAAc,GAAG,MAAM;IAa5D;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO;CAGzE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/binding/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOvD,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,iBAAiB,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC;IACX,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EACH,OAAO,GACP;QACE,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACP;AAED;;;;;;;GAOG;AACH,qBAAa,OAAO;IAClB,wBAAwB;IACxB,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC;IACpB,6BAA6B;IAC7B,OAAO,CAAC,YAAY,CAAe;IACnC,sBAAsB;IACtB,OAAO,CAAC,kBAAkB,CAAS;IACnC,4BAA4B;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,2BAA2B;IAC3B,OAAO,CAAC,UAAU,CAAa;IAC/B,oBAAoB;IACpB,OAAO,CAAC,WAAW,CAKT;IACV,gCAAgC;IAChC,OAAO,CAAC,mBAAmB,CAAC,CAAa;IACzC,yBAAyB;IACzB,OAAO,CAAC,kBAAkB,CAAC,CAAa;gBAE5B,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB;IA4G5D;;;OAGG;IACH,OAAO,CAAC,IAAI,UAAQ,GAAG,IAAI;IAS3B;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,oBAAoB,CAAC,SAAS,SAAc,GAAG,MAAM;IAa5D;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO;CAGzE"}
@@ -1 +1 @@
1
- {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../src/binding/patch.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,OAAO,EAEb,MAAM,kBAAkB,CAAC;AAO1B,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,QAAA,MAAM,WAAW,MAAM,CAAC;AACxB,QAAA,MAAM,WAAW,MAAM,CAAC;AACxB,QAAA,MAAM,WAAW,MAAM,CAAC;AAgDxB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,CAAC,WAAW,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;IAChC,CAAC,WAAW,CAAC,CAAC,EAAE;QACd,CAAC,GAAG,EAAE,MAAM,GAAG;YACb,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,KAAK,CAAC,EAAE;gBACN,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;gBACzB,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;gBACzC,CAAC,WAAW,CAAC,CAAC,EAAE;oBACd,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;iBACvC,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,QAqR/B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,aAAa,UAAQ,QAsDhE;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,CACd,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,QAAQ,CAC1E,EAAE,EACH,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,GAClB,SAAS,CAgSX"}
1
+ {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../src/binding/patch.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,OAAO,EAEb,MAAM,kBAAkB,CAAC;AAO1B,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,QAAA,MAAM,WAAW,MAAM,CAAC;AACxB,QAAA,MAAM,WAAW,MAAM,CAAC;AACxB,QAAA,MAAM,WAAW,MAAM,CAAC;AAgDxB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,CAAC,WAAW,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;IAChC,CAAC,WAAW,CAAC,CAAC,EAAE;QACd,CAAC,GAAG,EAAE,MAAM,GAAG;YACb,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,KAAK,CAAC,EAAE;gBACN,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;gBACzB,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;gBACzC,CAAC,WAAW,CAAC,CAAC,EAAE;oBACd,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;iBACvC,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,QA8R/B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,aAAa,UAAQ,QAyDhE;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,CACd,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,OAAO,GAAG,QAAQ,CAC1E,EAAE,EACH,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,GAClB,SAAS,CAoSX"}
@@ -1 +1 @@
1
- {"version":3,"file":"mxCell.d.ts","sourceRoot":"","sources":["../../src/models/mxCell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,GAAG,WAAW,CAAC;AAE5B,QAAA,MAAM,aAAa,eAAe,CAAC;AAGnC,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,CAAC,aAAa,CAAC,CAAC,EAAE,cAAc,CAAC;CAClC;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,CAAC,CAAC,UAAU,CAoBvD;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,2BA8BjD"}
1
+ {"version":3,"file":"mxCell.d.ts","sourceRoot":"","sources":["../../src/models/mxCell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,GAAG,WAAW,CAAC;AAE5B,QAAA,MAAM,aAAa,eAAe,CAAC;AAGnC,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,CAAC,aAAa,CAAC,CAAC,EAAE,cAAc,CAAC;CAClC;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,CAAC,CAAC,UAAU,CAoBvD;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,2BAmDjD"}
@@ -1 +1 @@
1
- {"version":3,"file":"mxfile.d.ts","sourceRoot":"","sources":["../../src/models/mxfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAMzB,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,WAAW,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,GAAG,WAAW,CAAC;AAC5B,eAAO,MAAM,eAAe,QAAuB,CAAC;AAEpD,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAErC,MAAM,WAAW,MAAO,SAAQ,cAAc;IAC5C,OAAO,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,kBAkB/C;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAgB3D"}
1
+ {"version":3,"file":"mxfile.d.ts","sourceRoot":"","sources":["../../src/models/mxfile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAMzB,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,WAAW,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,eAAO,MAAM,GAAG,WAAW,CAAC;AAC5B,eAAO,MAAM,eAAe,QAAuB,CAAC;AAEpD,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAErC,MAAM,WAAW,MAAO,SAAQ,cAAc;IAC5C,OAAO,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,kBAkB/C;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAqB3D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "y-mxgraph",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Yjs binding for draw.io (mxGraph) documents",
5
5
  "keywords": [
6
6
  "yjs",
@@ -28,6 +28,11 @@
28
28
  "types": "./index.d.ts"
29
29
  }
30
30
  },
31
+ "dependencies": {
32
+ "colord": "^2.9.3",
33
+ "lodash-es": "^4.17.21",
34
+ "xml-js": "^1.6.11"
35
+ },
31
36
  "peerDependencies": {
32
37
  "y-protocols": "^1.0.0",
33
38
  "yjs": "^13.6.0"
package/y-mxgraph.cjs.js CHANGED
@@ -85,12 +85,24 @@ function parse$3(object) {
85
85
  return xmlElement;
86
86
  }
87
87
  function serialize$2(xmlElement) {
88
- const attributes = {
88
+ const rawAttributes = {
89
89
  ...xmlElement.getAttributes()
90
90
  };
91
91
  let mxGeometry = null;
92
- if (mxGeometryAttributeKey in attributes) {
93
- const mxGeometryString = attributes[mxGeometryAttributeKey];
92
+ let mxGeometryString;
93
+ if (mxGeometryAttributeKey in rawAttributes) {
94
+ mxGeometryString = rawAttributes[mxGeometryAttributeKey];
95
+ delete rawAttributes[mxGeometryAttributeKey];
96
+ }
97
+ const attributes = {};
98
+ for (const [key2, value] of Object.entries(rawAttributes)) {
99
+ if (typeof value === "string") {
100
+ attributes[key2] = value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
101
+ } else if (value != null) {
102
+ attributes[key2] = String(value);
103
+ }
104
+ }
105
+ if (mxGeometryString) {
94
106
  try {
95
107
  const parsed = xmlJs.xml2js(mxGeometryString, { compact: true });
96
108
  mxGeometry = parsed[mxGeometryKey] ?? null;
@@ -100,7 +112,6 @@ function serialize$2(xmlElement) {
100
112
  } catch (e) {
101
113
  console.warn("[y-mxgraph] Failed to parse mxGeometry:", e);
102
114
  }
103
- delete attributes[mxGeometryAttributeKey];
104
115
  }
105
116
  const obj = {
106
117
  _attributes: attributes
@@ -189,11 +200,13 @@ function serializer(yMxFile) {
189
200
  const diagramOrder = yMxFile.get(
190
201
  diagramOrderKey
191
202
  );
203
+ const orderIds = diagramOrder ? diagramOrder.toArray() : [];
204
+ const ids = orderIds.length > 0 ? orderIds : diagrams ? Array.from(diagrams.keys()) : [];
192
205
  const obj = {
193
206
  _attributes: {
194
207
  pages: yMxFile.get("pages") || "1"
195
208
  },
196
- [key$1]: diagramOrder.map((id) => diagrams.get(id)).map((diagramElement) => serialize(diagramElement))
209
+ [key$1]: ids.map((id) => diagrams.get(id)).filter((d) => !!d).map((diagramElement) => serialize(diagramElement))
197
210
  };
198
211
  return obj;
199
212
  }
@@ -259,6 +272,12 @@ function applyFilePatch(doc, patch, options) {
259
272
  diagramOrderKey
260
273
  );
261
274
  ensureUniqueOrder(orderArr);
275
+ const currentOrder = orderArr.toArray();
276
+ if (currentOrder.length === 0 && diagramsMap && diagramsMap.size > 0) {
277
+ const allIds = Array.from(diagramsMap.keys());
278
+ orderArr.push(allIds);
279
+ }
280
+ ensureUniqueOrder(orderArr);
262
281
  const existingIds = orderArr.toArray();
263
282
  const existingIndex = /* @__PURE__ */ new Map();
264
283
  existingIds.forEach((id, idx) => existingIndex.set(id, idx));
@@ -478,7 +497,9 @@ function initDocSnapshot(doc, resetSnapshot = false) {
478
497
  const mxfile = doc.getMap(key);
479
498
  const diagramsMap = mxfile.get(key$1);
480
499
  const orderArr = mxfile.get(diagramOrderKey);
481
- const diagramOrder = resetSnapshot ? [] : orderArr ? orderArr.toArray().slice() : [];
500
+ const orderIds = orderArr ? orderArr.toArray() : [];
501
+ const allDiagramIds = orderIds.length > 0 ? orderIds : diagramsMap ? Array.from(diagramsMap.keys()) : [];
502
+ const diagramOrder = resetSnapshot ? [] : allDiagramIds.slice();
482
503
  const snap = {
483
504
  diagramOrder,
484
505
  cellsOrder: /* @__PURE__ */ new Map(),
@@ -551,7 +572,8 @@ function generatePatch(events, explicitDoc) {
551
572
  u.cells = u.cells || {};
552
573
  return u.cells;
553
574
  };
554
- const currDiagramOrder = orderArr.toArray();
575
+ const orderIds = orderArr.toArray();
576
+ const currDiagramOrder = orderIds.length > 0 ? orderIds : diagramsMap ? Array.from(diagramsMap.keys()) : [];
555
577
  const diagramsList = currDiagramOrder.map((id) => diagramsMap.get(id)).filter((d) => !!d);
556
578
  const currCellsOrder = /* @__PURE__ */ new Map();
557
579
  const cellAttrMap = /* @__PURE__ */ new Map();
@@ -1436,16 +1458,29 @@ function bindCollaborator(file, options) {
1436
1458
  class Binding {
1437
1459
  constructor(file, options) {
1438
1460
  this.suppressLocalApply = false;
1461
+ this.docInitialized = false;
1439
1462
  const { doc, awareness, undoManager, mouseMoveThrottle, cursor } = options;
1440
1463
  this.doc = doc;
1441
1464
  const ui = file.getUi();
1442
1465
  const graph = ui.editor.graph;
1443
1466
  this.mxGraphModel = graph.model;
1444
- const docHasData = doc.share.has(key);
1445
- if (!docHasData) {
1446
- xml2doc(file.data, doc);
1467
+ const mxfileMap = doc.getMap(key);
1468
+ const docHasData = mxfileMap.size > 0;
1469
+ this.docInitialized = docHasData;
1470
+ file.setShadowPages(file.ui.clonePages(file.ui.pages));
1471
+ if (docHasData) {
1472
+ initDocSnapshot(doc, false);
1473
+ const fullPatch = generatePatch([], doc);
1474
+ if (Object.keys(fullPatch).length > 0) {
1475
+ this.suppressLocalApply = true;
1476
+ try {
1477
+ file.patch([fullPatch]);
1478
+ } finally {
1479
+ this.suppressLocalApply = false;
1480
+ }
1481
+ }
1482
+ file.setShadowPages(file.ui.clonePages(file.ui.pages));
1447
1483
  }
1448
- initDocSnapshot(doc, docHasData);
1449
1484
  this.mxListener = () => {
1450
1485
  if (this.suppressLocalApply)
1451
1486
  return;
@@ -1453,16 +1488,31 @@ class Binding {
1453
1488
  file.shadowPages,
1454
1489
  file.ui.pages
1455
1490
  );
1491
+ const patchKeys = Object.keys(patch);
1492
+ if (patchKeys.length === 0)
1493
+ return;
1494
+ if (!this.docInitialized) {
1495
+ doc.transact(() => {
1496
+ xml2doc(file.data, doc);
1497
+ initDocSnapshot(doc, false);
1498
+ });
1499
+ this.docInitialized = true;
1500
+ }
1456
1501
  file.setShadowPages(file.ui.clonePages(file.ui.pages));
1457
1502
  applyFilePatch(doc, patch, { origin: LOCAL_ORIGIN });
1458
1503
  };
1459
1504
  this.mxGraphModel.addListener("change", this.mxListener);
1460
1505
  this.docObserver = (events, transaction) => {
1506
+ if (!this.docInitialized) {
1507
+ this.docInitialized = true;
1508
+ }
1461
1509
  if (transaction.local && transaction.origin === LOCAL_ORIGIN) {
1462
1510
  generatePatch(events);
1463
1511
  return;
1464
1512
  }
1465
1513
  const patch = generatePatch(events);
1514
+ if (Object.keys(patch).length === 0)
1515
+ return;
1466
1516
  this.suppressLocalApply = true;
1467
1517
  try {
1468
1518
  file.patch([patch]);
@@ -1471,19 +1521,7 @@ class Binding {
1471
1521
  this.suppressLocalApply = false;
1472
1522
  }
1473
1523
  };
1474
- doc.getMap(key).observeDeep(this.docObserver);
1475
- if (docHasData) {
1476
- const fullPatch = generatePatch([], doc);
1477
- if (Object.keys(fullPatch).length > 0) {
1478
- this.suppressLocalApply = true;
1479
- try {
1480
- file.patch([fullPatch]);
1481
- file.setShadowPages(file.ui.clonePages(file.ui.pages));
1482
- } finally {
1483
- this.suppressLocalApply = false;
1484
- }
1485
- }
1486
- }
1524
+ mxfileMap.observeDeep(this.docObserver);
1487
1525
  if (awareness) {
1488
1526
  this.cleanupCollaborator = bindCollaborator(file, {
1489
1527
  awareness,