@next-bricks/diagram 0.65.2 → 0.66.0

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 (47) hide show
  1. package/dist/bricks.json +3 -3
  2. package/dist/chunks/551.6afac48c.js +2 -0
  3. package/dist/chunks/551.6afac48c.js.map +1 -0
  4. package/dist/chunks/5670.3f0c377e.js +3 -0
  5. package/dist/chunks/5670.3f0c377e.js.map +1 -0
  6. package/dist/chunks/{7304.da01ff98.js → 7304.2ae2d399.js} +2 -2
  7. package/dist/chunks/7304.2ae2d399.js.map +1 -0
  8. package/dist/chunks/9711.dac4a790.js +2 -0
  9. package/dist/chunks/9711.dac4a790.js.map +1 -0
  10. package/dist/chunks/{eo-display-canvas.1dbece57.js → eo-display-canvas.331140e5.js} +2 -2
  11. package/dist/chunks/{eo-display-canvas.1dbece57.js.map → eo-display-canvas.331140e5.js.map} +1 -1
  12. package/dist/chunks/eo-draw-canvas.d66c3fcc.js +2 -0
  13. package/dist/chunks/eo-draw-canvas.d66c3fcc.js.map +1 -0
  14. package/dist/chunks/{main.64e4345c.js → main.6c3da929.js} +2 -2
  15. package/dist/chunks/{main.64e4345c.js.map → main.6c3da929.js.map} +1 -1
  16. package/dist/examples.json +3 -3
  17. package/dist/{index.55260b97.js → index.af95d6cd.js} +2 -2
  18. package/dist/{index.55260b97.js.map → index.af95d6cd.js.map} +1 -1
  19. package/dist/manifest.json +187 -180
  20. package/dist/types.json +5342 -5159
  21. package/dist-types/draw-canvas/CellComponent.d.ts +4 -2
  22. package/dist-types/draw-canvas/NodeComponent.d.ts +2 -1
  23. package/dist-types/draw-canvas/decorators/DecoratorGroup.d.ts +3 -0
  24. package/dist-types/draw-canvas/decorators/index.d.ts +1 -1
  25. package/dist-types/draw-canvas/index.d.ts +3 -1
  26. package/dist-types/draw-canvas/interfaces.d.ts +7 -1
  27. package/dist-types/draw-canvas/processors/asserts.d.ts +1 -0
  28. package/dist-types/draw-canvas/processors/{computeContainerRect.d.ts → computeBoundingBox.d.ts} +3 -1
  29. package/dist-types/draw-canvas/processors/handleKeyboard.d.ts +2 -2
  30. package/dist-types/draw-canvas/processors/initaliContainerLayout.d.ts +1 -2
  31. package/dist-types/draw-canvas/processors/initaliGroupLayout.d.ts +7 -0
  32. package/dist-types/draw-canvas/processors/isLocked.d.ts +1 -1
  33. package/dist-types/draw-canvas/processors/staggeredLayout.d.ts +3 -3
  34. package/dist-types/draw-canvas/reducers/interfaces.d.ts +2 -1
  35. package/docs/eo-draw-canvas.md +26 -4
  36. package/package.json +2 -2
  37. package/dist/chunks/296.d133f1de.js +0 -2
  38. package/dist/chunks/296.d133f1de.js.map +0 -1
  39. package/dist/chunks/5670.f356b145.js +0 -3
  40. package/dist/chunks/5670.f356b145.js.map +0 -1
  41. package/dist/chunks/7304.da01ff98.js.map +0 -1
  42. package/dist/chunks/9711.e769a674.js +0 -2
  43. package/dist/chunks/9711.e769a674.js.map +0 -1
  44. package/dist/chunks/eo-draw-canvas.276d3b61.js +0 -2
  45. package/dist/chunks/eo-draw-canvas.276d3b61.js.map +0 -1
  46. /package/dist/chunks/{5670.f356b145.js.LICENSE.txt → 5670.3f0c377e.js.LICENSE.txt} +0 -0
  47. /package/dist-types/draw-canvas/processors/{computeContainerRect.spec.d.ts → computeBoundingBox.spec.d.ts} +0 -0
@@ -5,10 +5,10 @@
5
5
  "diagram.editable-label": {
6
6
  "doc": "构件 `diagram.editable-label`\n\n## Examples\n\n### Basic\n\n```yaml preview\nbrick: diagram.editable-label\nproperties:\n type: line\n label: Relation\nevents:\n label.change:\n action: message.success\n args:\n - \"<% `Label changed to: ${EVENT.detail}` %>\"\n# -- YAML DELIMITER (1nbbm8) --\n# <diagram.editable-label\n# type=\"line\"\n# label=\"Relation\"\n# id=\"brick-1\"\n# ></diagram.editable-label>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"label.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"success\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Label changed to: ${EVENT.detail}` %>\",\n# });\n# });\n# </script>\n# \n```\n"
7
7
  },
8
- "eo-draw-canvas": {
9
- "doc": "用于手工绘图的画布。\n\n注意:将配套另外一个用于展示的画布构件。\n\n## Examples\n\n### Basic\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"container-1\",\n decorator: \"container\",\n view: {\n direction: \"left\",\n text: \"上层服务\" ,\n level: 1\n },\n },\n {\n type: \"decorator\",\n id: \"container-2\",\n decorator: \"container\",\n view: {\n direction: \"left\",\n text: \"应用\" ,\n level: 2\n },\n },\n {\n type: \"edge\", \n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"edge\",\n source: \"Z\", \n target: \"W\",\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n }\n },\n ].concat(\n [\"A\",\"B\",\"X\", \"Y\", \"Z\", \"W\",].map((id) => ({\n type: \"node\",\n id,\n containerId: [\"W\",\"Z\",\"X\",\"Y\"].includes(id)?\"container-1\":\"container-2\",\n data: {\n name: `Node ${id}`,\n }, \n view: {\n x: [\"A\",\"B\",\"Z\",\"X\",\"Y\"].includes(id)?null:Math.round(\n id === \"X\"\n ? 200 + Math.random() * 200\n : id === \"Y\"\n ? Math.random() * 300\n : 300 + Math.random() * 300\n ),\n y: [\"A\",\"B\",\"Z\",\"X\",\"Y\"].includes(id)?null:(id === \"X\" ? 0 : 300) + Math.round((Math.random() * 200)),\n width: 60,\n height: 60,\n }\n }))\n ).concat([\n {\n type: \"decorator\",\n id: \"text-1\",\n decorator: \"text\", \n view: {\n x: 300,\n y: 120,\n width: 100,\n height: 20,\n text: \"Hello\\nWorld!\",\n style: {\n // 垂直书写(从右到左)\n writingMode: \"vertical-rl\",\n },\n },\n },\n ])\n %>\n - name: dragging\n - name: activeTarget\n - name: contextMenuDetail\n - name: scale\n value: 1\n children:\n - brick: div\n properties:\n style:\n width: 200px\n display: flex\n flexDirection: column\n gap: 1em\n border-right: \"1px solid var(--palette-gray-6)\"\n overflow: scroll\n children:\n - brick: eo-button\n properties:\n textContent: Add random nodes\n events:\n click:\n target: eo-draw-canvas\n method: addNodes\n args:\n - |\n <%\n ((...seeds) => seeds.map((seed) => ({\n id: seed,\n data: {\n name: String(seed),\n },\n })))(\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n )\n %>\n callback:\n success:\n action: console.log\n args:\n - Added nodes\n - <% EVENT.detail %>\n - brick: eo-button\n properties:\n textContent: Add nodes to container-1\n events:\n click:\n target: eo-draw-canvas\n method: addNodes\n args:\n - |\n <%\n ((...seeds) => seeds.map((seed) => ({\n id: seed,\n containerId: \"container-1\",\n data: {\n name: String(seed),\n },\n })))(\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n )\n %>\n callback:\n success:\n action: console.log\n args:\n - Added nodes\n - <% EVENT.detail %>\n - brick: eo-button\n properties:\n textContent: \"Add edge: Y => Z\"\n events:\n click:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: Y\n target: Z\n data:\n virtual: true\n - brick: :forEach\n dataSource:\n - X\n - Y\n children:\n - brick: eo-button\n properties:\n textContent: <% `Add nodes below ${ITEM}` %>\n events:\n click:\n target: eo-draw-canvas\n method: updateCells\n args:\n - |\n <%\n CTX.initialCells.concat([\n {\n type: \"edge\",\n source: ITEM,\n target: \"U\",\n },\n {\n type: \"edge\",\n source: ITEM,\n target: \"V\",\n },\n {\n type: \"node\",\n id: \"U\",\n data: {\n name: \"U\"\n }\n },\n {\n type: \"node\",\n id: \"V\",\n data: {\n name: \"V\"\n }\n },\n ])\n %>\n - reason: add-related-nodes\n parent: <% ITEM %>\n callback:\n success:\n action: console.log\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag nodes below\n - brick: :forEach\n dataSource: |\n <%\n [\"A\", \"B\", \"C\"].map((id) => ({\n type: \"node\",\n id,\n data: {\n name: `Node ${id}`,\n },\n }))\n %>\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% ITEM.data.name %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, ...ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropNode\n args:\n - position: <% EVENT.detail %>\n id: <% ITEM.id %>\n data: <% ITEM.data %>\n callback:\n success:\n if: <% EVENT.detail %>\n then:\n action: message.success\n args:\n - <% JSON.stringify(EVENT.detail) %>\n else:\n action: message.warn\n args:\n - Unexpected drop position\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag decorators below\n - brick: :forEach\n dataSource:\n - area\n - text\n - line\n - rect\n - container.top\n - container.right\n - container.bottom\n - container.left\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% _.upperFirst(ITEM) %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, type: \"decorator\", decorator: ITEM.split(\".\")[0]} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropDecorator\n args:\n - |\n <%\n ITEM === \"line\"\n ? {\n position: EVENT.detail,\n decorator: ITEM.split(\".\")[0],\n }\n : {\n position: EVENT.detail,\n decorator: ITEM.split(\".\")[0],\n text: _.upperFirst(ITEM),\n direction: ITEM.split(\".\").pop(),\n }\n %>\n callback:\n success:\n if: <% !EVENT.detail %>\n action: message.warn\n args:\n - Unexpected drop position\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n allowEdgeToArea: true\n dragBehavior: lasso\n layoutOptions:\n # initialLayout: layered-architecture\n initialLayout: layered-staggered\n snap:\n # grid: true\n object: true\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: '<% `Node ${DATA.node.id}${DATA.node.locked ? \" (locked)\" : \"\"}` %>'\n status: |\n <%=\n (CTX.activeTarget?.type === \"multi\"\n ? CTX.activeTarget.targets\n : CTX.activeTarget\n ? [CTX.activeTarget]\n : []\n ).some((target) => (\n target.type === \"node\" && target.id === DATA.node.id\n ))\n ? \"highlighted\"\n : \"default\"\n %>\n defaultEdgeLines:\n - if: <% DATA.edge.data?.virtual %>\n dashed: true\n - if: <% !DATA.edge.data?.virtual %>\n dotted: true\n showStartArrow: true\n markers:\n - placement: start\n type: circle\n - placement: end\n type: arrow\n cells: <% CTX.initialCells %>\n lineConnector: true\n lineSettings:\n type: polyline\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cells.move:\n action: message.info\n args:\n - <% `You just moved ${EVENT.detail.length} cells` %>\n cell.resize:\n action: message.info\n args:\n - <% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\n cells.delete:\n action: message.warn\n args:\n - |\n <% `You wanna delete ${EVENT.detail.length} cells?` %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - contextMenuDetail\n - <% EVENT.detail %>\n edge.add:\n action: message.info\n args:\n - |\n <% `Added an nice edge: ${JSON.stringify(EVENT.detail)}` %>\n edge.view.change:\n action: message.info\n args:\n - |\n <% `Edge view changed: ${JSON.stringify(EVENT.detail)}` %>\n decorator.view.change:\n action: message.info\n args:\n - |\n <% `Decorator view changed: ${JSON.stringify(EVENT.detail)}` %>\n decorator.text.change:\n action: message.info\n args:\n - <% JSON.stringify(EVENT.detail) %>\n node.container.change:\n action: message.info\n args:\n - <% JSON.stringify(EVENT.detail) %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n- brick: diagram.experimental-node\n properties:\n usage: dragging\n textContent: |\n <%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\" ? \"Text\" : null) : CTX.dragging?.data.name %>\n decorator: |\n <%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %>\n style: |\n <%=\n {\n left: `${CTX.dragging?.position[0]}px`,\n top: `${CTX.dragging?.position[1]}px`,\n transform: `scale(${CTX.scale})`,\n transformOrigin: \"0 0\",\n padding: CTX.dragging?.decorator === \"text\" ? \"0.5em\" : \"0\"\n }\n %>\n hidden: <%= !CTX.dragging %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n !CTX.contextMenuDetail\n ? []\n : CTX.contextMenuDetail.target?.type === \"multi\"\n ? [\n {\n text: \"锁定/取消锁定\",\n event: \"toggle-lock\",\n },\n ]\n : [\n ...(CTX.contextMenuDetail.locked ? [] : [{\n text: \"添加边\",\n event: \"add-edge\",\n },{\n text: \"移除\",\n event: \"remove\"\n }]),\n {\n text: \"锁定/取消锁定\",\n event: \"toggle-lock\",\n },\n ].filter((action) =>\n CTX.contextMenuDetail.cell.type === \"node\" || (\n CTX.contextMenuDetail.cell.type === \"decorator\" &&\n CTX.contextMenuDetail.cell.decorator === \"area\"\n ) || action.event !== \"add-edge\"\n )\n %>\n events:\n remove:\n target: eo-draw-canvas\n method: updateCells\n args:\n - |\n <%\n CTX.initialCells.filter((cell) =>\n !(\n CTX.contextMenuDetail.cell.type === \"edge\"\n ? cell.type === \"edge\" && CTX.contextMenuDetail.cell.source === cell.source && CTX.contextMenuDetail.cell.target === cell.target\n : cell.id === CTX.contextMenuDetail.cell.id ||\n (cell.type === \"edge\" && (\n CTX.contextMenuDetail.cell.id === cell.source ||\n CTX.contextMenuDetail.cell.id === cell.target))\n )\n )\n %>\n add-edge:\n target: eo-draw-canvas\n method: manuallyConnectNodes\n args:\n - <% CTX.contextMenuDetail.cell.id %>\n callback:\n success:\n - target: eo-draw-canvas\n method: addEdge\n args:\n - source: <% EVENT.detail.source.id %>\n target: <% EVENT.detail.target.id %>\n toggle-lock:\n target: eo-draw-canvas\n method: toggleLock\n args:\n - <% CTX.contextMenuDetail.target %>\n callback:\n success:\n action: console.log\n args:\n - \"Updated cells after toggle lock:\"\n - <% EVENT.detail %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div\n# style=\"\n# width: 200px;\n# display: flex;\n# flex-direction: column;\n# gap: 1em;\n# border-right: 1px solid var(--palette-gray-6);\n# overflow: scroll;\n# \"\n# >\n# <eo-button id=\"brick-1\">Add random nodes</eo-button>\n# <eo-button id=\"brick-2\">Add nodes to container-1</eo-button>\n# <eo-button id=\"brick-3\">Add edge: Y =&gt; Z</eo-button>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag nodes below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag decorators below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# </div>\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# allow-edge-to-area\n# drag-behavior=\"lasso\"\n# id=\"brick-7\"\n# ></eo-draw-canvas>\n# </div>\n# </div>\n# <diagram.experimental-node\n# usage=\"dragging\"\n# decorator='&lt;%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %&gt;\n# '\n# hidden=\"&lt;%= !CTX.dragging %&gt;\"\n# >\n# &lt;%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\"\n# ? \"Text\" : null) : CTX.dragging?.data.name %&gt;\n# </diagram.experimental-node>\n# <eo-context-menu\n# actions='&lt;%=\n# !CTX.contextMenuDetail\n# ? []\n# : CTX.contextMenuDetail.target?.type === \"multi\"\n# ? [\n# {\n# text: \"锁定/取消锁定\",\n# event: \"toggle-lock\",\n# },\n# ]\n# : [\n# ...(CTX.contextMenuDetail.locked ? [] : [{\n# text: \"添加边\",\n# event: \"add-edge\",\n# },{\n# text: \"移除\",\n# event: \"remove\"\n# }]),\n# {\n# text: \"锁定/取消锁定\",\n# event: \"toggle-lock\",\n# },\n# ].filter((action) =&gt;\n# CTX.contextMenuDetail.cell.type === \"node\" || (\n# CTX.contextMenuDetail.cell.type === \"decorator\" &amp;&amp;\n# CTX.contextMenuDetail.cell.decorator === \"area\"\n# ) || action.event !== \"add-edge\"\n# )\n# %&gt;\n# '\n# id=\"brick-8\"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<%\\n ((...seeds) => seeds.map((seed) => ({\\n id: seed,\\n data: {\\n name: String(seed),\\n },\\n })))(\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n )\\n%>\\n\"\n# );\n# });\n# \n# const brick_2 = document.getElementById(\"brick-2\");\n# brick_2.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n ((...seeds) => seeds.map((seed) => ({\\n id: seed,\\n containerId: \"container-1\",\\n data: {\\n name: String(seed),\\n },\\n })))(\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n )\\n%>\\n'\n# );\n# });\n# \n# const brick_3 = document.getElementById(\"brick-3\");\n# brick_3.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addEdge({ source: \"Y\", target: \"Z\", data: { virtual: true } });\n# });\n# \n# const brick_4 = document.getElementById(\"brick-4\");\n# brick_4.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.updateCells(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n CTX.initialCells.concat([\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"U\",\\n },\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"V\",\\n },\\n {\\n type: \"node\",\\n id: \"U\",\\n data: {\\n name: \"U\"\\n }\\n },\\n {\\n type: \"node\",\\n id: \"V\",\\n data: {\\n name: \"V\"\\n }\\n },\\n ])\\n%>\\n',\n# { reason: \"add-related-nodes\", parent: \"<% ITEM %>\" }\n# );\n# });\n# \n# const brick_5 = document.getElementById(\"brick-5\");\n# brick_5.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropNode({\n# position: \"<% EVENT.detail %>\",\n# id: \"<% ITEM.id %>\",\n# data: \"<% ITEM.data %>\",\n# });\n# });\n# \n# const brick_6 = document.getElementById(\"brick-6\");\n# brick_6.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropDecorator(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n ITEM === \"line\"\\n ? {\\n position: EVENT.detail,\\n decorator: ITEM.split(\".\")[0],\\n }\\n : {\\n position: EVENT.detail,\\n decorator: ITEM.split(\".\")[0],\\n text: _.upperFirst(ITEM),\\n direction: ITEM.split(\".\").pop(),\\n }\\n%>\\n'\n# );\n# });\n# \n# const brick_7 = document.getElementById(\"brick-7\");\n# brick_7.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_7.layoutOptions = {\n# initialLayout: \"layered-staggered\",\n# snap: {\n# object: true,\n# },\n# };\n# brick_7.defaultNodeSize = [60, 60];\n# brick_7.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent:\n# '<% `Node ${DATA.node.id}${DATA.node.locked ? \" (locked)\" : \"\"}` %>',\n# status:\n# '<%=\\n (CTX.activeTarget?.type === \"multi\"\\n ? CTX.activeTarget.targets\\n : CTX.activeTarget\\n ? [CTX.activeTarget]\\n : []\\n ).some((target) => (\\n target.type === \"node\" && target.id === DATA.node.id\\n ))\\n ? \"highlighted\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_7.defaultEdgeLines = [\n# {\n# if: \"<% DATA.edge.data?.virtual %>\",\n# dashed: true,\n# },\n# {\n# if: \"<% !DATA.edge.data?.virtual %>\",\n# dotted: true,\n# showStartArrow: true,\n# markers: [\n# {\n# placement: \"start\",\n# type: \"circle\",\n# },\n# {\n# placement: \"end\",\n# type: \"arrow\",\n# },\n# ],\n# },\n# ];\n# brick_7.cells = \"<% CTX.initialCells %>\";\n# brick_7.lineConnector = true;\n# brick_7.lineSettings = {\n# type: \"polyline\",\n# };\n# brick_7.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_7.addEventListener(\"cells.move\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `You just moved ${EVENT.detail.length} cells` %>\",\n# });\n# });\n# brick_7.addEventListener(\"cell.resize\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\",\n# });\n# });\n# brick_7.addEventListener(\"cells.delete\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"warn\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `You wanna delete ${EVENT.detail.length} cells?` %>\\n\",\n# });\n# });\n# brick_7.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_7.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_7.addEventListener(\"edge.add\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Added an nice edge: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_7.addEventListener(\"edge.view.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Edge view changed: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_7.addEventListener(\"decorator.view.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `Decorator view changed: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_7.addEventListener(\"decorator.text.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% JSON.stringify(EVENT.detail) %>\",\n# });\n# });\n# brick_7.addEventListener(\"node.container.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% JSON.stringify(EVENT.detail) %>\",\n# });\n# });\n# brick_7.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_8 = document.getElementById(\"brick-8\");\n# brick_8.addEventListener(\"remove\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.updateCells(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n CTX.initialCells.filter((cell) =>\\n !(\\n CTX.contextMenuDetail.cell.type === \"edge\"\\n ? cell.type === \"edge\" && CTX.contextMenuDetail.cell.source === cell.source && CTX.contextMenuDetail.cell.target === cell.target\\n : cell.id === CTX.contextMenuDetail.cell.id ||\\n (cell.type === \"edge\" && (\\n CTX.contextMenuDetail.cell.id === cell.source ||\\n CTX.contextMenuDetail.cell.id === cell.target))\\n )\\n )\\n%>\\n'\n# );\n# });\n# brick_8.addEventListener(\"add-edge\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.manuallyConnectNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.contextMenuDetail.cell.id %>\"\n# );\n# });\n# brick_8.addEventListener(\"toggle-lock\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.toggleLock(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.contextMenuDetail.target %>\"\n# );\n# });\n# </script>\n# \n```\n\n### Line labels\n\n设置连线文字。\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n flexDirection: column\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n description: \"X->Y\",\n placement: \"end\",\n view: {\n type: \"polyline\"\n }\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\"\n },\n {\n type: \"node\",\n id: \"X\",\n data: {\n name: \"Node X\",\n },\n view: {\n x: 100,\n y: 100,\n width: 60,\n height: 60,\n }\n },\n {\n type: \"node\",\n id: \"Y\",\n data: {\n name: \"Node Y\",\n },\n view: {\n x: 0,\n y: 300,\n width: 60,\n height: 60,\n }\n },\n {\n type: \"node\",\n id: \"Z\",\n data: {\n name: \"Node Z\",\n },\n view: {\n x: 300,\n y: 200,\n width: 60,\n height: 60,\n }\n },\n ]\n %>\n - name: activeTarget\n - name: scale\n value: 1\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n dragBehavior: lasso\n layoutOptions:\n snap:\n object: true\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n (CTX.activeTarget?.type === \"multi\"\n ? CTX.activeTarget.targets\n : CTX.activeTarget\n ? [CTX.activeTarget]\n : []\n ).some((target) => (\n target.type === \"node\" && target.id === DATA.node.id\n ))\n ? \"highlighted\"\n : \"default\"\n %>\n cells: <% CTX.initialCells %>\n lineConnector: true\n defaultEdgeLines:\n - callLabelOnDoubleClick: enableEditing\n label:\n placement: <% DATA.edge.placement %>\n offset: 10\n useBrick:\n brick: diagram.editable-label\n properties:\n label: <% DATA.edge.description %>\n type: line\n # Set `readOnly: true` for eo-display-canvas\n # readOnly: true\n events:\n label.change:\n # Make sure only trigger update if label actually changed\n if: <% (DATA.edge.description || \"\") !== (EVENT.detail || \"\") %>\n action: context.replace\n args:\n - initialCells\n - |-\n <%\n CTX.initialCells.map((edge) =>\n edge.type === \"edge\" &&\n edge.source === DATA.edge.source &&\n edge.target === DATA.edge.target\n ? { ...edge, description: EVENT.detail }\n : edge\n )\n %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.delete:\n action: message.warn\n args:\n - |\n <% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; flex-direction: column; height: 600px; gap: 1em\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# drag-behavior=\"lasso\"\n# id=\"brick-1\"\n# ></eo-draw-canvas>\n# </div>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_1.layoutOptions = {\n# snap: {\n# object: true,\n# },\n# };\n# brick_1.defaultNodeSize = [60, 60];\n# brick_1.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n (CTX.activeTarget?.type === \"multi\"\\n ? CTX.activeTarget.targets\\n : CTX.activeTarget\\n ? [CTX.activeTarget]\\n : []\\n ).some((target) => (\\n target.type === \"node\" && target.id === DATA.node.id\\n ))\\n ? \"highlighted\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_1.cells = \"<% CTX.initialCells %>\";\n# brick_1.lineConnector = true;\n# brick_1.defaultEdgeLines = [\n# {\n# callLabelOnDoubleClick: \"enableEditing\",\n# label: {\n# placement: \"<% DATA.edge.placement %>\",\n# offset: 10,\n# useBrick: {\n# brick: \"diagram.editable-label\",\n# properties: {\n# label: \"<% DATA.edge.description %>\",\n# type: \"line\",\n# },\n# events: {\n# \"label.change\": {\n# if: '<% (DATA.edge.description || \"\") !== (EVENT.detail || \"\") %>',\n# action: \"context.replace\",\n# args: [\n# \"initialCells\",\n# '<%\\n CTX.initialCells.map((edge) =>\\n edge.type === \"edge\" &&\\n edge.source === DATA.edge.source &&\\n edge.target === DATA.edge.target\\n ? { ...edge, description: EVENT.detail }\\n : edge\\n )\\n%>',\n# ],\n# },\n# },\n# },\n# },\n# },\n# ];\n# brick_1.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_1.addEventListener(\"cell.delete\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"warn\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# '<% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\\n',\n# });\n# });\n# brick_1.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# </script>\n# \n```\n\n### Line settings\n\n设置属性 `lineSettings` 来调整新的连线的样式,例如使用折线或直线。注意,该设置不影响已有的 edge 的连线样式。\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n flexDirection: column\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n decorator: \"line\",\n id: \"line-1\",\n view: {\n source: {\n x: 200,\n y: 200,\n },\n target: {\n x: 250,\n y: 150,\n },\n // type: \"polyline\",\n vertices: [\n {\n x: 180,\n y: 125,\n },\n ],\n markers: [{\n placement: \"end\",\n type: \"arrow\",\n }],\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"node\",\n id: \"X\",\n data: {\n name: \"Node X\",\n },\n view: {\n x: 100,\n y: 100,\n width: 60,\n height: 60,\n }\n },\n {\n type: \"node\",\n id: \"Y\",\n data: {\n name: \"Node Y\",\n },\n view: {\n x: 0,\n y: 300,\n width: 60,\n height: 60,\n }\n },\n {\n type: \"node\",\n id: \"Z\",\n data: {\n name: \"Node Z\",\n },\n view: {\n x: 300,\n y: 200,\n width: 60,\n height: 60,\n }\n },\n ]\n %>\n - name: dragging\n - name: activeTarget\n - name: targetCell\n - name: scale\n value: 1\n - name: lineType\n value: polyline\n children:\n - brick: div\n children:\n - brick: eo-radio\n properties:\n type: button\n value: polyline\n options:\n - polyline\n - curve\n - straight\n events:\n change:\n action: context.replace\n args:\n - lineType\n - <% EVENT.detail.value %>\n - brick: div\n properties:\n style:\n flex: 1\n minHeight: 0\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n dragBehavior: lasso\n layoutOptions:\n snap:\n object: true\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n (CTX.activeTarget?.type === \"multi\"\n ? CTX.activeTarget.targets\n : CTX.activeTarget\n ? [CTX.activeTarget]\n : []\n ).some((target) => (\n target.type === \"node\" && target.id === DATA.node.id\n ))\n ? \"highlighted\"\n : \"default\"\n %>\n cells: <% CTX.initialCells %>\n defaultEdgeLines:\n - jumps: true\n lineConnector: true\n lineSettings: |\n <%= { type: CTX.lineType } %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n edge.add:\n action: message.info\n args:\n - |\n <% `Added an nice edge: ${JSON.stringify(EVENT.detail)}` %>\n edge.view.change:\n action: message.info\n args:\n - |\n <% `Edge view changed: ${JSON.stringify(EVENT.detail)}` %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n- brick: diagram.experimental-node\n properties:\n usage: dragging\n textContent: |\n <%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\" ? \"Text\" : null) : CTX.dragging?.data.name %>\n decorator: |\n <%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %>\n style: |\n <%=\n {\n left: `${CTX.dragging?.position[0]}px`,\n top: `${CTX.dragging?.position[1]}px`,\n transform: `scale(${CTX.scale})`,\n transformOrigin: \"0 0\",\n padding: CTX.dragging?.decorator === \"text\" ? \"0.5em\" : \"0\"\n }\n %>\n hidden: <%= !CTX.dragging %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n ([\"node\"].includes(CTX.targetCell?.type )||CTX.targetCell?.decorator==\"area\") ? [\n {\n text: \"添加边\",\n event: \"add-edge\",\n }\n ] : [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n events:\n add-edge:\n target: eo-draw-canvas\n method: manuallyConnectNodes\n args:\n - <% CTX.targetCell.id %>\n callback:\n success:\n - target: eo-draw-canvas\n method: addEdge\n args:\n - source: <% EVENT.detail.source.id %>\n target: <% EVENT.detail.target.id %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; flex-direction: column; height: 600px; gap: 1em\">\n# <div>\n# <eo-radio\n# type=\"button\"\n# value=\"polyline\"\n# options=\"polyline,curve,straight\"\n# id=\"brick-1\"\n# ></eo-radio>\n# </div>\n# <div style=\"flex: 1; min-height: 0\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# drag-behavior=\"lasso\"\n# id=\"brick-2\"\n# ></eo-draw-canvas>\n# </div>\n# </div>\n# <diagram.experimental-node\n# usage=\"dragging\"\n# decorator='&lt;%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %&gt;\n# '\n# hidden=\"&lt;%= !CTX.dragging %&gt;\"\n# >\n# &lt;%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\"\n# ? \"Text\" : null) : CTX.dragging?.data.name %&gt;\n# </diagram.experimental-node>\n# <eo-context-menu\n# actions='&lt;%=\n# ([\"node\"].includes(CTX.targetCell?.type )||CTX.targetCell?.decorator==\"area\") ? [\n# {\n# text: \"添加边\",\n# event: \"add-edge\",\n# }\n# ] : [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# '\n# id=\"brick-3\"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_2 = document.getElementById(\"brick-2\");\n# brick_2.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_2.layoutOptions = {\n# snap: {\n# object: true,\n# },\n# };\n# brick_2.defaultNodeSize = [60, 60];\n# brick_2.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n (CTX.activeTarget?.type === \"multi\"\\n ? CTX.activeTarget.targets\\n : CTX.activeTarget\\n ? [CTX.activeTarget]\\n : []\\n ).some((target) => (\\n target.type === \"node\" && target.id === DATA.node.id\\n ))\\n ? \"highlighted\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_2.cells = \"<% CTX.initialCells %>\";\n# brick_2.defaultEdgeLines = [\n# {\n# jumps: true,\n# },\n# ];\n# brick_2.lineConnector = true;\n# brick_2.lineSettings = \"<%= { type: CTX.lineType } %>\\n\";\n# brick_2.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_2.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_2.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_2.addEventListener(\"edge.add\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Added an nice edge: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_2.addEventListener(\"edge.view.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Edge view changed: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_2.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_3 = document.getElementById(\"brick-3\");\n# brick_3.addEventListener(\"add-edge\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.manuallyConnectNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.targetCell.id %>\"\n# );\n# });\n# </script>\n# \n```\n\n### Force layout\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"area-1\",\n decorator: \"area\",\n view: {\n x: 10,\n y: 20,\n width: 400,\n height: 300,\n },\n },\n {\n type: \"decorator\",\n id: \"container-1\",\n decorator: \"container\",\n view: {\n x: 50,\n y: 400,\n width: 280,\n height: 120,\n direction: \"top\",\n text: \" 上层服务\"\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n }\n },\n ].concat(\n [\"X\", \"Y\", \"Z\", \"W\"].map((id) => ({\n type: \"node\",\n id,\n containerId: [\"X\",\"Y\",\"Z\"].includes(id)?\"container-1\":undefined,\n data: {\n name: `Node ${id}`,\n },\n view: {\n width: 60,\n height: 60,\n }\n }))\n ).concat([\n {\n type: \"decorator\",\n id: \"text-1\",\n decorator: \"text\",\n view: {\n x: 100,\n y: 120,\n width: 100,\n height: 20,\n text: \"Hello!\"\n },\n },\n ])\n %>\n - name: dragging\n - name: activeTarget\n - name: targetCell\n - name: scale\n value: 1\n children:\n - brick: div\n properties:\n style:\n width: 180px\n display: flex\n flexDirection: column\n gap: 1em\n children:\n - brick: eo-button\n properties:\n textContent: Add random nodes\n events:\n click:\n target: eo-draw-canvas\n method: addNodes\n args:\n - |\n <%\n ((...seeds) => seeds.map((seed) => ({\n id: seed,\n data: {\n name: String(seed),\n },\n })))(\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n )\n %>\n callback:\n success:\n action: console.log\n args:\n - Added nodes\n - <% EVENT.detail %>\n - brick: eo-button\n properties:\n textContent: \"Add edge: Y => Z\"\n events:\n click:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: Y\n target: Z\n data:\n virtual: true\n - brick: :forEach\n dataSource:\n - X\n - Y\n children:\n - brick: eo-button\n properties:\n textContent: <% `Add nodes below ${ITEM}` %>\n events:\n click:\n target: eo-draw-canvas\n method: updateCells\n args:\n - |\n <%\n CTX.initialCells.concat([\n {\n type: \"edge\",\n source: ITEM,\n target: \"U\",\n },\n {\n type: \"edge\",\n source: ITEM,\n target: \"V\",\n },\n {\n type: \"node\",\n id: \"U\",\n data: {\n name: \"U\"\n }\n },\n {\n type: \"node\",\n id: \"V\",\n data: {\n name: \"V\"\n }\n },\n ])\n %>\n - reason: add-related-nodes\n parent: <% ITEM %>\n callback:\n success:\n action: console.log\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag nodes below\n - brick: :forEach\n dataSource: |\n <%\n [\"A\", \"B\", \"C\"].map((id) => ({\n type: \"node\",\n id,\n data: {\n name: `Node ${id}`,\n },\n }))\n %>\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% ITEM.data.name %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, ...ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropNode\n args:\n - position: <% EVENT.detail %>\n id: <% ITEM.id %>\n data: <% ITEM.data %>\n callback:\n success:\n if: <% EVENT.detail %>\n then:\n action: message.success\n args:\n - <% JSON.stringify(EVENT.detail) %>\n else:\n action: message.warn\n args:\n - Unexpected drop position\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag decorators below\n - brick: :forEach\n dataSource:\n - area\n - text\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% _.upperFirst(ITEM) %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, type: \"decorator\", decorator: ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropDecorator\n args:\n - position: <% EVENT.detail %>\n decorator: <% ITEM %>\n text: '<% ITEM === \"text\" ? \"Text\" : undefined %>'\n callback:\n success:\n if: <% !EVENT.detail %>\n action: message.warn\n args:\n - Unexpected drop position\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n layout: force\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\n ? \"highlighted\"\n // : CTX.unrelated.some(n =>\n // n.type === \"node\" && n.id === DATA.node.id\n // )\n // ? \"faded\"\n : \"default\"\n %>\n defaultEdgeLines:\n - if: <% DATA.edge.data?.virtual %>\n dashed: true\n cells: <% CTX.initialCells %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.move:\n action: message.info\n args:\n - <% `You just moved ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.x)}, ${Math.round(EVENT.detail.y)})` %>\n cell.resize:\n action: message.info\n args:\n - <% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\n cell.delete:\n action: message.warn\n args:\n - |\n <% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n decorator.text.change:\n action: message.info\n args:\n - <% JSON.stringify(EVENT.detail) %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n- brick: diagram.experimental-node\n properties:\n usage: dragging\n textContent: |\n <%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\" ? \"Text\" : null) : CTX.dragging?.data.name %>\n decorator: |\n <%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %>\n style: |\n <%=\n {\n left: `${CTX.dragging?.position[0]}px`,\n top: `${CTX.dragging?.position[1]}px`,\n transform: `scale(${CTX.scale})`,\n transformOrigin: \"0 0\",\n padding: CTX.dragging?.decorator === \"text\" ? \"0.5em\" : \"0\"\n }\n %>\n hidden: <%= !CTX.dragging %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n CTX.targetCell?.type === \"node\" ? [\n {\n text: \"添加边\",\n event: \"add-edge\",\n }\n ] : [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n events:\n add-edge:\n target: eo-draw-canvas\n method: manuallyConnectNodes\n args:\n - <% CTX.targetCell.id %>\n callback:\n success:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: <% EVENT.detail.source.id %>\n target: <% EVENT.detail.target.id %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div style=\"width: 180px; display: flex; flex-direction: column; gap: 1em\">\n# <eo-button id=\"brick-1\">Add random nodes</eo-button>\n# <eo-button id=\"brick-2\">Add edge: Y =&gt; Z</eo-button>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag nodes below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag decorators below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# </div>\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# layout=\"force\"\n# id=\"brick-6\"\n# ></eo-draw-canvas>\n# </div>\n# </div>\n# <diagram.experimental-node\n# usage=\"dragging\"\n# decorator='&lt;%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %&gt;\n# '\n# hidden=\"&lt;%= !CTX.dragging %&gt;\"\n# >\n# &lt;%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\"\n# ? \"Text\" : null) : CTX.dragging?.data.name %&gt;\n# </diagram.experimental-node>\n# <eo-context-menu\n# actions='&lt;%=\n# CTX.targetCell?.type === \"node\" ? [\n# {\n# text: \"添加边\",\n# event: \"add-edge\",\n# }\n# ] : [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# '\n# id=\"brick-7\"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<%\\n ((...seeds) => seeds.map((seed) => ({\\n id: seed,\\n data: {\\n name: String(seed),\\n },\\n })))(\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n )\\n%>\\n\"\n# );\n# });\n# \n# const brick_2 = document.getElementById(\"brick-2\");\n# brick_2.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addEdge({ source: \"Y\", target: \"Z\", data: { virtual: true } });\n# });\n# \n# const brick_3 = document.getElementById(\"brick-3\");\n# brick_3.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.updateCells(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n CTX.initialCells.concat([\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"U\",\\n },\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"V\",\\n },\\n {\\n type: \"node\",\\n id: \"U\",\\n data: {\\n name: \"U\"\\n }\\n },\\n {\\n type: \"node\",\\n id: \"V\",\\n data: {\\n name: \"V\"\\n }\\n },\\n ])\\n%>\\n',\n# { reason: \"add-related-nodes\", parent: \"<% ITEM %>\" }\n# );\n# });\n# \n# const brick_4 = document.getElementById(\"brick-4\");\n# brick_4.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_4.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_4.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropNode({\n# position: \"<% EVENT.detail %>\",\n# id: \"<% ITEM.id %>\",\n# data: \"<% ITEM.data %>\",\n# });\n# });\n# \n# const brick_5 = document.getElementById(\"brick-5\");\n# brick_5.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropDecorator({\n# position: \"<% EVENT.detail %>\",\n# decorator: \"<% ITEM %>\",\n# text: '<% ITEM === \"text\" ? \"Text\" : undefined %>',\n# });\n# });\n# \n# const brick_6 = document.getElementById(\"brick-6\");\n# brick_6.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_6.defaultNodeSize = [60, 60];\n# brick_6.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\\n ? \"highlighted\"\\n // : CTX.unrelated.some(n =>\\n // n.type === \"node\" && n.id === DATA.node.id\\n // )\\n // ? \"faded\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_6.defaultEdgeLines = [\n# {\n# if: \"<% DATA.edge.data?.virtual %>\",\n# dashed: true,\n# },\n# ];\n# brick_6.cells = \"<% CTX.initialCells %>\";\n# brick_6.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"cell.move\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just moved ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.x)}, ${Math.round(EVENT.detail.y)})` %>\",\n# });\n# });\n# brick_6.addEventListener(\"cell.resize\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\",\n# });\n# });\n# brick_6.addEventListener(\"cell.delete\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"warn\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# '<% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\\n',\n# });\n# });\n# brick_6.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_6.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"decorator.text.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% JSON.stringify(EVENT.detail) %>\",\n# });\n# });\n# brick_6.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_7 = document.getElementById(\"brick-7\");\n# brick_7.addEventListener(\"add-edge\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.manuallyConnectNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.targetCell.id %>\"\n# );\n# });\n# </script>\n# \n```\n\n### Dagre layout\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"area-1\",\n decorator: \"area\",\n view: {\n x: 10,\n y: 20,\n width: 400,\n height: 300,\n },\n },\n {\n type: \"decorator\",\n id: \"container-1\",\n decorator: \"container\",\n view: {\n x: 50,\n y: 400,\n width: 280,\n height: 120,\n direction: \"top\",\n text: \" 上层服务\"\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n }\n },\n {\n type: \"edge\",\n source: \"Z\",\n target: \"W\",\n },\n ].concat(\n [\"X\", \"Y\", \"Z\", \"W\"].map((id) => ({\n type: \"node\",\n id,\n containerId: [\"W\",\"Z\"].includes(id)?\"container-1\":undefined,\n data: {\n name: `Node ${id}`,\n },\n view: {\n width: 60,\n height: 60,\n }\n }))\n )\n %>\n - name: dragging\n - name: activeTarget\n - name: targetCell\n - name: scale\n value: 1\n children:\n - brick: div\n properties:\n style:\n width: 180px\n display: flex\n flexDirection: column\n gap: 1em\n children:\n - brick: eo-button\n properties:\n textContent: Add random nodes\n events:\n click:\n target: eo-draw-canvas\n method: addNodes\n args:\n - |\n <%\n ((...seeds) => seeds.map((seed) => ({\n id: seed,\n data: {\n name: String(seed),\n },\n })))(\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n )\n %>\n callback:\n success:\n action: console.log\n args:\n - Added nodes\n - <% EVENT.detail %>\n - brick: eo-button\n properties:\n textContent: \"Add edge: Y => Z\"\n events:\n click:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: Y\n target: Z\n data:\n virtual: true\n - brick: :forEach\n dataSource:\n - X\n - Y\n children:\n - brick: eo-button\n properties:\n textContent: <% `Add nodes below ${ITEM}` %>\n events:\n click:\n target: eo-draw-canvas\n method: updateCells\n args:\n - |\n <%\n CTX.initialCells.concat([\n {\n type: \"edge\",\n source: ITEM,\n target: \"U\",\n },\n {\n type: \"edge\",\n source: ITEM,\n target: \"V\",\n },\n {\n type: \"node\",\n id: \"U\",\n data: {\n name: \"U\"\n }\n },\n {\n type: \"node\",\n id: \"V\",\n data: {\n name: \"V\"\n }\n },\n ])\n %>\n - reason: add-related-nodes\n parent: <% ITEM %>\n callback:\n success:\n action: console.log\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag nodes below\n - brick: :forEach\n dataSource: |\n <%\n [\"A\", \"B\", \"C\"].map((id) => ({\n type: \"node\",\n id,\n data: {\n name: `Node ${id}`,\n },\n }))\n %>\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% ITEM.data.name %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, ...ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropNode\n args:\n - position: <% EVENT.detail %>\n id: <% ITEM.id %>\n data: <% ITEM.data %>\n callback:\n success:\n if: <% EVENT.detail %>\n then:\n action: message.success\n args:\n - <% JSON.stringify(EVENT.detail) %>\n else:\n action: message.warn\n args:\n - Unexpected drop position\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag decorators below\n - brick: :forEach\n dataSource:\n - area\n - text\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% _.upperFirst(ITEM) %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, type: \"decorator\", decorator: ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropDecorator\n args:\n - position: <% EVENT.detail %>\n decorator: <% ITEM %>\n text: '<% ITEM === \"text\" ? \"Text\" : undefined %>'\n callback:\n success:\n if: <% !EVENT.detail %>\n action: message.warn\n args:\n - Unexpected drop position\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n layout: dagre\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\n ? \"highlighted\"\n // : CTX.unrelated.some(n =>\n // n.type === \"node\" && n.id === DATA.node.id\n // )\n // ? \"faded\"\n : \"default\"\n %>\n defaultEdgeLines:\n - dashed: <% !!DATA.edge.data?.virtual %>\n strokeColor: var(--palette-blue-6)\n overrides:\n active:\n strokeWidth: <% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>\n strokeColor: cyan\n cells: <% CTX.initialCells %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.move:\n action: message.info\n args:\n - <% `You just moved ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.x)}, ${Math.round(EVENT.detail.y)})` %>\n cell.resize:\n action: message.info\n args:\n - <% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\n cell.delete:\n action: message.warn\n args:\n - |\n <% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n decorator.text.change:\n action: message.info\n args:\n - <% JSON.stringify(EVENT.detail) %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n- brick: diagram.experimental-node\n properties:\n usage: dragging\n textContent: |\n <%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\" ? \"Text\" : null) : CTX.dragging?.data.name %>\n decorator: |\n <%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %>\n style: |\n <%=\n {\n left: `${CTX.dragging?.position[0]}px`,\n top: `${CTX.dragging?.position[1]}px`,\n transform: `scale(${CTX.scale})`,\n transformOrigin: \"0 0\",\n padding: CTX.dragging?.decorator === \"text\" ? \"0.5em\" : \"0\"\n }\n %>\n hidden: <%= !CTX.dragging %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n CTX.targetCell?.type === \"node\" ? [\n {\n text: \"添加边\",\n event: \"add-edge\",\n }\n ] : [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n events:\n add-edge:\n target: eo-draw-canvas\n method: manuallyConnectNodes\n args:\n - <% CTX.targetCell.id %>\n callback:\n success:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: <% EVENT.detail.source.id %>\n target: <% EVENT.detail.target.id %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div style=\"width: 180px; display: flex; flex-direction: column; gap: 1em\">\n# <eo-button id=\"brick-1\">Add random nodes</eo-button>\n# <eo-button id=\"brick-2\">Add edge: Y =&gt; Z</eo-button>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag nodes below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag decorators below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# </div>\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# layout=\"dagre\"\n# id=\"brick-6\"\n# ></eo-draw-canvas>\n# </div>\n# </div>\n# <diagram.experimental-node\n# usage=\"dragging\"\n# decorator='&lt;%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %&gt;\n# '\n# hidden=\"&lt;%= !CTX.dragging %&gt;\"\n# >\n# &lt;%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\"\n# ? \"Text\" : null) : CTX.dragging?.data.name %&gt;\n# </diagram.experimental-node>\n# <eo-context-menu\n# actions='&lt;%=\n# CTX.targetCell?.type === \"node\" ? [\n# {\n# text: \"添加边\",\n# event: \"add-edge\",\n# }\n# ] : [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# '\n# id=\"brick-7\"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<%\\n ((...seeds) => seeds.map((seed) => ({\\n id: seed,\\n data: {\\n name: String(seed),\\n },\\n })))(\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n )\\n%>\\n\"\n# );\n# });\n# \n# const brick_2 = document.getElementById(\"brick-2\");\n# brick_2.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addEdge({ source: \"Y\", target: \"Z\", data: { virtual: true } });\n# });\n# \n# const brick_3 = document.getElementById(\"brick-3\");\n# brick_3.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.updateCells(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n CTX.initialCells.concat([\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"U\",\\n },\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"V\",\\n },\\n {\\n type: \"node\",\\n id: \"U\",\\n data: {\\n name: \"U\"\\n }\\n },\\n {\\n type: \"node\",\\n id: \"V\",\\n data: {\\n name: \"V\"\\n }\\n },\\n ])\\n%>\\n',\n# { reason: \"add-related-nodes\", parent: \"<% ITEM %>\" }\n# );\n# });\n# \n# const brick_4 = document.getElementById(\"brick-4\");\n# brick_4.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_4.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_4.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropNode({\n# position: \"<% EVENT.detail %>\",\n# id: \"<% ITEM.id %>\",\n# data: \"<% ITEM.data %>\",\n# });\n# });\n# \n# const brick_5 = document.getElementById(\"brick-5\");\n# brick_5.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropDecorator({\n# position: \"<% EVENT.detail %>\",\n# decorator: \"<% ITEM %>\",\n# text: '<% ITEM === \"text\" ? \"Text\" : undefined %>',\n# });\n# });\n# \n# const brick_6 = document.getElementById(\"brick-6\");\n# brick_6.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_6.defaultNodeSize = [60, 60];\n# brick_6.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\\n ? \"highlighted\"\\n // : CTX.unrelated.some(n =>\\n // n.type === \"node\" && n.id === DATA.node.id\\n // )\\n // ? \"faded\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_6.defaultEdgeLines = [\n# {\n# dashed: \"<% !!DATA.edge.data?.virtual %>\",\n# strokeColor: \"var(--palette-blue-6)\",\n# overrides: {\n# active: {\n# strokeWidth: \"<% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>\",\n# strokeColor: \"cyan\",\n# },\n# },\n# },\n# ];\n# brick_6.cells = \"<% CTX.initialCells %>\";\n# brick_6.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"cell.move\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just moved ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.x)}, ${Math.round(EVENT.detail.y)})` %>\",\n# });\n# });\n# brick_6.addEventListener(\"cell.resize\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\",\n# });\n# });\n# brick_6.addEventListener(\"cell.delete\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"warn\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# '<% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\\n',\n# });\n# });\n# brick_6.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_6.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"decorator.text.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% JSON.stringify(EVENT.detail) %>\",\n# });\n# });\n# brick_6.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_7 = document.getElementById(\"brick-7\");\n# brick_7.addEventListener(\"add-edge\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.manuallyConnectNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.targetCell.id %>\"\n# );\n# });\n# </script>\n# \n```\n"
10
- },
11
8
  "eo-display-canvas": {
12
9
  "doc": "用于展示查看的画布构件。\n\n## Examples\n\n### Basic\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"area-1\",\n decorator: \"area\",\n view: {\n x: 10,\n y: 20,\n width: 400,\n height: 300,\n },\n },\n {\n type: \"decorator\",\n id: \"container-1\",\n decorator: \"container\",\n view: {\n x: 50,\n y: 400,\n width: 280,\n height: 120,\n direction: \"top\",\n text: \" 上层服务\"\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n data: {\n virtual: false,\n showStartArrow: false,\n strokeColor:\"red\",\n strokeWidth: 5,\n }\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"W\",\n data: {\n virtual: false,\n showStartArrow: true,\n strokeColor:\"pink\",\n animate:{\n useAnimate: true,\n duration: 4\n }\n }\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n showStartArrow: true,\n strokeColor:\"blue\",\n animate:{\n useAnimate: true\n }\n }\n },\n {\n type: \"edge\",\n source: \"W\",\n target: \"Z\",\n view: {\n entryPosition: { x: 0, y: 0.5 },\n exitPosition: {x: 0.5, y: 0}\n }\n }\n ].concat(\n [\"X\", \"Y\", \"Z\", \"W\"].map((id) => ({\n type: \"node\",\n id,\n containerId: [\"X\",\"Y\",\"Z\"].includes(id)?\"container-1\":undefined,\n data: {\n name: `Node ${id}`,\n },\n view: {\n x: Math.round(\n id === \"X\"\n ? 200 + Math.random() * 200\n : id === \"Y\"\n ? Math.random() * 300\n : 300 + Math.random() * 300\n ),\n y: (id === \"X\" ? 0 : 300) + Math.round((Math.random() * 200)),\n width: 60,\n height: 60,\n }\n }))\n ).concat([\n {\n type: \"decorator\",\n id: \"text-1\",\n decorator: \"text\",\n view: {\n x: 100,\n y: 120,\n width: 100,\n height: 20,\n text: \"Hello!\"\n },\n },\n ])\n %>\n - name: activeTarget\n - name: targetCell\n children:\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-display-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\n ? \"highlighted\"\n // : CTX.unrelated.some(n =>\n // n.type === \"node\" && n.id === DATA.node.id\n // )\n // ? \"faded\"\n : \"default\"\n %>\n defaultEdgeLines:\n - if: true\n dashed: <% DATA.edge?.data?.virtual %>\n strokeColor: <% DATA.edge?.data?.strokeColor %>\n showStartArrow: <% DATA.edge?.data?.showStartArrow %>\n strokeWidth: <% DATA.edge?.data?.strokeWidth %>\n animate: <% DATA.edge?.data?.animate %>\n showStartArrow: true\n markers:\n - placement: end\n type: circle\n - placement: start\n type: arrow\n cells: <% CTX.initialCells %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-display-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# id=\"brick-1\"\n# ></eo-display-canvas>\n# </div>\n# </div>\n# <eo-context-menu\n# actions=\"&lt;%=\n# [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# \"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_1.defaultNodeSize = [60, 60];\n# brick_1.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\\n ? \"highlighted\"\\n // : CTX.unrelated.some(n =>\\n // n.type === \"node\" && n.id === DATA.node.id\\n // )\\n // ? \"faded\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_1.defaultEdgeLines = [\n# {\n# if: true,\n# dashed: \"<% DATA.edge?.data?.virtual %>\",\n# strokeColor: \"<% DATA.edge?.data?.strokeColor %>\",\n# showStartArrow: true,\n# strokeWidth: \"<% DATA.edge?.data?.strokeWidth %>\",\n# animate: \"<% DATA.edge?.data?.animate %>\",\n# markers: [\n# {\n# placement: \"end\",\n# type: \"circle\",\n# },\n# {\n# placement: \"start\",\n# type: \"arrow\",\n# },\n# ],\n# },\n# ];\n# brick_1.cells = \"<% CTX.initialCells %>\";\n# brick_1.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_1.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_1.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# </script>\n# \n```\n\n### Force layout\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"area-1\",\n decorator: \"area\",\n view: {\n x: 10,\n y: 20,\n width: 400,\n height: 300,\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n }\n },\n ].concat(\n [\"X\", \"Y\", \"Z\", \"W\"].map((id) => ({\n type: \"node\",\n id,\n data: {\n name: `Node ${id}`,\n },\n view: {\n width: 60,\n height: 60,\n }\n }))\n ).concat([\n {\n type: \"decorator\",\n id: \"text-1\",\n decorator: \"text\",\n view: {\n x: 100,\n y: 120,\n width: 100,\n height: 20,\n text: \"Hello!\"\n },\n },\n ])\n %>\n - name: activeTarget\n - name: targetCell\n children:\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-display-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n layout: force\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\n ? \"highlighted\"\n // : CTX.unrelated.some(n =>\n // n.type === \"node\" && n.id === DATA.node.id\n // )\n // ? \"faded\"\n : \"default\"\n %>\n defaultEdgeLines:\n - if: <% DATA.edge.data?.virtual %>\n dashed: true\n cells: <% CTX.initialCells %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-display-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# layout=\"force\"\n# id=\"brick-1\"\n# ></eo-display-canvas>\n# </div>\n# </div>\n# <eo-context-menu\n# actions=\"&lt;%=\n# [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# \"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_1.defaultNodeSize = [60, 60];\n# brick_1.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\\n ? \"highlighted\"\\n // : CTX.unrelated.some(n =>\\n // n.type === \"node\" && n.id === DATA.node.id\\n // )\\n // ? \"faded\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_1.defaultEdgeLines = [\n# {\n# if: \"<% DATA.edge.data?.virtual %>\",\n# dashed: true,\n# },\n# ];\n# brick_1.cells = \"<% CTX.initialCells %>\";\n# brick_1.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_1.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_1.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# </script>\n# \n```\n\n### Dagre layout\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"area-1\",\n decorator: \"area\",\n view: {\n x: 10,\n y: 20,\n width: 400,\n height: 300,\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n view: {\n type: \"polyline\"\n }\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n }\n },\n {\n type: \"edge\",\n source: \"Z\",\n target: \"W\",\n },\n ].concat(\n [\"X\", \"Y\", \"Z\", \"W\"].map((id) => ({\n type: \"node\",\n id,\n data: {\n name: `Node ${id}`,\n },\n view: {\n width: 60,\n height: 60,\n }\n }))\n )\n %>\n - name: activeTarget\n - name: targetCell\n children:\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-display-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n layout: dagre\n layoutOptions:\n ranksep: 80\n nodesep: 80\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\n ? \"highlighted\"\n // : CTX.unrelated.some(n =>\n // n.type === \"node\" && n.id === DATA.node.id\n // )\n // ? \"faded\"\n : \"default\"\n %>\n defaultEdgeLines:\n - dashed: <% !!DATA.edge.data?.virtual %>\n strokeColor: var(--palette-blue-6)\n overrides:\n active:\n strokeWidth: <% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>\n strokeColor: cyan\n activeRelated:\n strokeWidth: <% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>\n motion:\n shape: '<% DATA.edge.data?.virtual ? \"dot\" : \"triangle\" %>'\n cells: <% CTX.initialCells %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-display-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# layout=\"dagre\"\n# id=\"brick-1\"\n# ></eo-display-canvas>\n# </div>\n# </div>\n# <eo-context-menu\n# actions=\"&lt;%=\n# [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# \"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_1.layoutOptions = {\n# ranksep: 80,\n# nodesep: 80,\n# };\n# brick_1.defaultNodeSize = [60, 60];\n# brick_1.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\\n ? \"highlighted\"\\n // : CTX.unrelated.some(n =>\\n // n.type === \"node\" && n.id === DATA.node.id\\n // )\\n // ? \"faded\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_1.defaultEdgeLines = [\n# {\n# dashed: \"<% !!DATA.edge.data?.virtual %>\",\n# strokeColor: \"var(--palette-blue-6)\",\n# overrides: {\n# active: {\n# strokeWidth: \"<% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>\",\n# strokeColor: \"cyan\",\n# },\n# activeRelated: {\n# strokeWidth: \"<% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>\",\n# motion: {\n# shape: '<% DATA.edge.data?.virtual ? \"dot\" : \"triangle\" %>',\n# },\n# },\n# },\n# },\n# ];\n# brick_1.cells = \"<% CTX.initialCells %>\";\n# brick_1.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_1.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_1.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# </script>\n# \n```\n\n### Degraded diagram\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n ((...seeds) => seeds.map((seed) => ({\n type: \"node\",\n id: seed,\n data: {\n name: seed,\n },\n })))(\n ...(\n new Array(500).fill(null).map((_, i) => String(i))\n )\n )\n %>\n - name: activeTarget\n - name: targetCell\n children:\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-display-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n layout: force\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\n ? \"highlighted\"\n // : CTX.unrelated.some(n =>\n // n.type === \"node\" && n.id === DATA.node.id\n // )\n // ? \"faded\"\n : \"default\"\n %>\n defaultEdgeLines:\n - if: true\n dashed: <% DATA.edge?.data?.virtual %>\n strokeColor: <% DATA.edge?.data?.strokeColor %>\n showStartArrow: <% DATA.edge?.data?.showStartArrow %>\n strokeWidth: <% DATA.edge?.data?.strokeWidth %>\n animate: <% DATA.edge?.data?.animate %>\n cells: <% CTX.initialCells %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-display-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# layout=\"force\"\n# id=\"brick-1\"\n# ></eo-display-canvas>\n# </div>\n# </div>\n# <eo-context-menu\n# actions=\"&lt;%=\n# [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# \"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_1.defaultNodeSize = [60, 60];\n# brick_1.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\\n ? \"highlighted\"\\n // : CTX.unrelated.some(n =>\\n // n.type === \"node\" && n.id === DATA.node.id\\n // )\\n // ? \"faded\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_1.defaultEdgeLines = [\n# {\n# if: true,\n# dashed: \"<% DATA.edge?.data?.virtual %>\",\n# strokeColor: \"<% DATA.edge?.data?.strokeColor %>\",\n# showStartArrow: \"<% DATA.edge?.data?.showStartArrow %>\",\n# strokeWidth: \"<% DATA.edge?.data?.strokeWidth %>\",\n# animate: \"<% DATA.edge?.data?.animate %>\",\n# },\n# ];\n# brick_1.cells = \"<% CTX.initialCells %>\";\n# brick_1.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_1.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_1.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# </script>\n# \n```\n"
10
+ },
11
+ "eo-draw-canvas": {
12
+ "doc": "用于手工绘图的画布。\n\n注意:将配套另外一个用于展示的画布构件。\n\n## Examples\n\n### Basic\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"container-1\",\n decorator: \"container\",\n view: {\n direction: \"left\",\n text: \"上层服务\" ,\n level: 1\n },\n },\n {\n type: \"decorator\",\n id: \"container-2\",\n decorator: \"container\",\n view: {\n direction: \"left\",\n text: \"应用\" ,\n level: 2\n },\n },\n {\n type: \"decorator\",\n id: \"group-1\",\n decorator: \"group\",\n containerId: \"container-2\",\n view: {\n usePlus: true, \n },\n },\n {\n type: \"node\",\n id: \"G\",\n groupId: \"group-1\",\n data: {\n name: `Node G`, \n }, \n view: {\n width: 60,\n height: 60,\n }\n },\n {\n type: \"edge\", \n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"edge\",\n source: \"Z\", \n target: \"W\",\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n }\n },\n ].concat(\n [\"A\",\"B\",\"C\",\"S\",\"D\",\"F\",\"X\", \"Y\", \"Z\", \"W\"].map((id) => ({\n type: \"node\",\n id,\n containerId: [\"W\",\"Z\",\"X\",\"Y\", \"W\"].includes(id)?\"container-1\":([\"A\",\"B\",].includes(id)?\"container-2\":null),\n groupId: [\"C\",\"S\",\"D\",\"F\",].includes(id)?\"group-1\":null,\n data: {\n name: `Node ${id}`,\n }, \n view: {\n x: [\"A\",\"B\",\"C\",\"S\",\"D\",\"F\",\"Z\",\"X\",\"Y\",].includes(id)?null:Math.round(\n id === \"X\"\n ? 200 + Math.random() * 200\n : id === \"Y\"\n ? Math.random() * 300\n : 300 + Math.random() * 300\n ),\n y: [\"A\",\"B\",\"C\",\"S\",\"D\",\"F\",\"Z\",\"X\",\"Y\"].includes(id)?null:(id === \"X\" ? 0 : 300) + Math.round((Math.random() * 200)),\n width: 60,\n height: 60,\n }\n }))\n ).concat([\n {\n type: \"decorator\",\n id: \"text-1\",\n decorator: \"text\", \n view: {\n x: 300,\n y: 120,\n width: 100,\n height: 20,\n text: \"Hello\\nWorld!\",\n style: {\n // 垂直书写(从右到左)\n writingMode: \"vertical-rl\",\n },\n },\n },\n ])\n %>\n - name: dragging\n - name: activeTarget\n - name: contextMenuDetail\n - name: scale\n value: 1\n children:\n - brick: div\n properties:\n style:\n width: 200px\n display: flex\n flexDirection: column\n gap: 1em\n border-right: \"1px solid var(--palette-gray-6)\"\n overflow: scroll\n children:\n - brick: eo-button\n properties:\n textContent: Add random nodes\n events:\n click:\n target: eo-draw-canvas\n method: addNodes\n args:\n - |\n <%\n ((...seeds) => seeds.map((seed) => ({\n id: seed,\n data: {\n name: String(seed),\n },\n })))(\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n )\n %>\n callback:\n success:\n action: console.log\n args:\n - Added nodes\n - <% EVENT.detail %>\n - brick: eo-button\n properties:\n textContent: Add nodes to container-1\n events:\n click:\n target: eo-draw-canvas\n method: addNodes\n args:\n - |\n <%\n ((...seeds) => seeds.map((seed) => ({\n id: seed,\n containerId: \"container-1\",\n data: {\n name: String(seed),\n },\n })))(\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n )\n %>\n callback:\n success:\n action: console.log\n args:\n - Added nodes\n - <% EVENT.detail %>\n - brick: eo-button\n properties:\n textContent: \"Add edge: Y => Z\"\n events:\n click:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: Y\n target: Z\n data:\n virtual: true\n - brick: :forEach\n dataSource:\n - X\n - Y\n children:\n - brick: eo-button\n properties:\n textContent: <% `Add nodes below ${ITEM}` %>\n events:\n click:\n target: eo-draw-canvas\n method: updateCells\n args:\n - |\n <%\n CTX.initialCells.concat([\n {\n type: \"edge\",\n source: ITEM,\n target: \"U\",\n },\n {\n type: \"edge\",\n source: ITEM,\n target: \"V\",\n },\n {\n type: \"node\",\n id: \"U\",\n data: {\n name: \"U\"\n }\n },\n {\n type: \"node\",\n id: \"V\",\n data: {\n name: \"V\"\n }\n },\n ])\n %>\n - reason: add-related-nodes\n parent: <% ITEM %>\n callback:\n success:\n action: console.log\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag nodes below\n - brick: :forEach\n dataSource: |\n <%\n [\"A\", \"B\", \"C\"].map((id) => ({\n type: \"node\",\n id,\n data: {\n name: `Node ${id}`,\n },\n }))\n %>\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% ITEM.data.name %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, ...ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropNode\n args:\n - position: <% EVENT.detail %>\n id: <% ITEM.id %>\n data: <% ITEM.data %>\n callback:\n success:\n if: <% EVENT.detail %>\n then:\n action: message.success\n args:\n - <% JSON.stringify(EVENT.detail) %>\n else:\n action: message.warn\n args:\n - Unexpected drop position\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag decorators below\n - brick: :forEach\n dataSource:\n - area\n - text\n - line\n - rect\n - container.top\n - container.right\n - container.bottom\n - container.left\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% _.upperFirst(ITEM) %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, type: \"decorator\", decorator: ITEM.split(\".\")[0]} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropDecorator\n args:\n - |\n <%\n ITEM === \"line\"\n ? {\n position: EVENT.detail,\n decorator: ITEM.split(\".\")[0],\n }\n : {\n position: EVENT.detail,\n decorator: ITEM.split(\".\")[0],\n text: _.upperFirst(ITEM),\n direction: ITEM.split(\".\").pop(),\n }\n %>\n callback:\n success:\n if: <% !EVENT.detail %>\n action: message.warn\n args:\n - Unexpected drop position\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n allowEdgeToArea: true\n dragBehavior: lasso\n layoutOptions:\n # initialLayout: layered-architecture\n initialLayout: layered-staggered\n snap:\n # grid: true\n object: true\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: '<% `Node ${DATA.node.id}${DATA.node.locked ? \" (locked)\" : \"\"}` %>'\n status: |\n <%=\n (CTX.activeTarget?.type === \"multi\"\n ? CTX.activeTarget.targets\n : CTX.activeTarget\n ? [CTX.activeTarget]\n : []\n ).some((target) => (\n target.type === \"node\" && target.id === DATA.node.id\n ))\n ? \"highlighted\"\n : \"default\"\n %>\n defaultEdgeLines:\n - if: <% DATA.edge.data?.virtual %>\n dashed: true\n - if: <% !DATA.edge.data?.virtual %>\n dotted: true\n showStartArrow: true\n markers:\n - placement: start\n type: circle\n - placement: end\n type: arrow\n cells: <% CTX.initialCells %>\n lineConnector: true\n lineSettings:\n type: polyline\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cells.move:\n action: message.info\n args:\n - <% `You just moved ${EVENT.detail.length} cells` %>\n cell.resize:\n action: message.info\n args:\n - <% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\n cells.delete:\n action: message.warn\n args:\n - |\n <% `You wanna delete ${EVENT.detail.length} cells?` %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - contextMenuDetail\n - <% EVENT.detail %>\n edge.add:\n action: message.info\n args:\n - |\n <% `Added an nice edge: ${JSON.stringify(EVENT.detail)}` %>\n edge.view.change:\n action: message.info\n args:\n - |\n <% `Edge view changed: ${JSON.stringify(EVENT.detail)}` %>\n decorator.view.change:\n action: message.info\n args:\n - |\n <% `Decorator view changed: ${JSON.stringify(EVENT.detail)}` %>\n decorator.text.change:\n action: message.info\n args:\n - <% JSON.stringify(EVENT.detail) %>\n node.container.change:\n action: message.info\n args:\n - <% JSON.stringify(EVENT.detail) %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n- brick: diagram.experimental-node\n properties:\n usage: dragging\n textContent: |\n <%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\" ? \"Text\" : null) : CTX.dragging?.data.name %>\n decorator: |\n <%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %>\n style: |\n <%=\n {\n left: `${CTX.dragging?.position[0]}px`,\n top: `${CTX.dragging?.position[1]}px`,\n transform: `scale(${CTX.scale})`,\n transformOrigin: \"0 0\",\n padding: CTX.dragging?.decorator === \"text\" ? \"0.5em\" : \"0\"\n }\n %>\n hidden: <%= !CTX.dragging %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n !CTX.contextMenuDetail\n ? []\n : CTX.contextMenuDetail.target?.type === \"multi\"\n ? [\n {\n text: \"锁定/取消锁定\",\n event: \"toggle-lock\",\n },\n ]\n : [\n ...(CTX.contextMenuDetail.locked ? [] : [{\n text: \"添加边\",\n event: \"add-edge\",\n },{\n text: \"移除\",\n event: \"remove\"\n }]),\n {\n text: \"锁定/取消锁定\",\n event: \"toggle-lock\",\n },\n ].filter((action) =>\n CTX.contextMenuDetail.cell.type === \"node\" || (\n CTX.contextMenuDetail.cell.type === \"decorator\" &&\n CTX.contextMenuDetail.cell.decorator === \"area\"\n ) || action.event !== \"add-edge\"\n )\n %>\n events:\n remove:\n target: eo-draw-canvas\n method: updateCells\n args:\n - |\n <%\n CTX.initialCells.filter((cell) =>\n !(\n CTX.contextMenuDetail.cell.type === \"edge\"\n ? cell.type === \"edge\" && CTX.contextMenuDetail.cell.source === cell.source && CTX.contextMenuDetail.cell.target === cell.target\n : cell.id === CTX.contextMenuDetail.cell.id ||\n (cell.type === \"edge\" && (\n CTX.contextMenuDetail.cell.id === cell.source ||\n CTX.contextMenuDetail.cell.id === cell.target))\n )\n )\n %>\n add-edge:\n target: eo-draw-canvas\n method: manuallyConnectNodes\n args:\n - <% CTX.contextMenuDetail.cell.id %>\n callback:\n success:\n - target: eo-draw-canvas\n method: addEdge\n args:\n - source: <% EVENT.detail.source.id %>\n target: <% EVENT.detail.target.id %>\n toggle-lock:\n target: eo-draw-canvas\n method: toggleLock\n args:\n - <% CTX.contextMenuDetail.target %>\n callback:\n success:\n action: console.log\n args:\n - \"Updated cells after toggle lock:\"\n - <% EVENT.detail %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div\n# style=\"\n# width: 200px;\n# display: flex;\n# flex-direction: column;\n# gap: 1em;\n# border-right: 1px solid var(--palette-gray-6);\n# overflow: scroll;\n# \"\n# >\n# <eo-button id=\"brick-1\">Add random nodes</eo-button>\n# <eo-button id=\"brick-2\">Add nodes to container-1</eo-button>\n# <eo-button id=\"brick-3\">Add edge: Y =&gt; Z</eo-button>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag nodes below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag decorators below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# </div>\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# allow-edge-to-area\n# drag-behavior=\"lasso\"\n# id=\"brick-7\"\n# ></eo-draw-canvas>\n# </div>\n# </div>\n# <diagram.experimental-node\n# usage=\"dragging\"\n# decorator='&lt;%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %&gt;\n# '\n# hidden=\"&lt;%= !CTX.dragging %&gt;\"\n# >\n# &lt;%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\"\n# ? \"Text\" : null) : CTX.dragging?.data.name %&gt;\n# </diagram.experimental-node>\n# <eo-context-menu\n# actions='&lt;%=\n# !CTX.contextMenuDetail\n# ? []\n# : CTX.contextMenuDetail.target?.type === \"multi\"\n# ? [\n# {\n# text: \"锁定/取消锁定\",\n# event: \"toggle-lock\",\n# },\n# ]\n# : [\n# ...(CTX.contextMenuDetail.locked ? [] : [{\n# text: \"添加边\",\n# event: \"add-edge\",\n# },{\n# text: \"移除\",\n# event: \"remove\"\n# }]),\n# {\n# text: \"锁定/取消锁定\",\n# event: \"toggle-lock\",\n# },\n# ].filter((action) =&gt;\n# CTX.contextMenuDetail.cell.type === \"node\" || (\n# CTX.contextMenuDetail.cell.type === \"decorator\" &amp;&amp;\n# CTX.contextMenuDetail.cell.decorator === \"area\"\n# ) || action.event !== \"add-edge\"\n# )\n# %&gt;\n# '\n# id=\"brick-8\"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<%\\n ((...seeds) => seeds.map((seed) => ({\\n id: seed,\\n data: {\\n name: String(seed),\\n },\\n })))(\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n )\\n%>\\n\"\n# );\n# });\n# \n# const brick_2 = document.getElementById(\"brick-2\");\n# brick_2.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n ((...seeds) => seeds.map((seed) => ({\\n id: seed,\\n containerId: \"container-1\",\\n data: {\\n name: String(seed),\\n },\\n })))(\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n )\\n%>\\n'\n# );\n# });\n# \n# const brick_3 = document.getElementById(\"brick-3\");\n# brick_3.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addEdge({ source: \"Y\", target: \"Z\", data: { virtual: true } });\n# });\n# \n# const brick_4 = document.getElementById(\"brick-4\");\n# brick_4.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.updateCells(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n CTX.initialCells.concat([\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"U\",\\n },\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"V\",\\n },\\n {\\n type: \"node\",\\n id: \"U\",\\n data: {\\n name: \"U\"\\n }\\n },\\n {\\n type: \"node\",\\n id: \"V\",\\n data: {\\n name: \"V\"\\n }\\n },\\n ])\\n%>\\n',\n# { reason: \"add-related-nodes\", parent: \"<% ITEM %>\" }\n# );\n# });\n# \n# const brick_5 = document.getElementById(\"brick-5\");\n# brick_5.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropNode({\n# position: \"<% EVENT.detail %>\",\n# id: \"<% ITEM.id %>\",\n# data: \"<% ITEM.data %>\",\n# });\n# });\n# \n# const brick_6 = document.getElementById(\"brick-6\");\n# brick_6.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropDecorator(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n ITEM === \"line\"\\n ? {\\n position: EVENT.detail,\\n decorator: ITEM.split(\".\")[0],\\n }\\n : {\\n position: EVENT.detail,\\n decorator: ITEM.split(\".\")[0],\\n text: _.upperFirst(ITEM),\\n direction: ITEM.split(\".\").pop(),\\n }\\n%>\\n'\n# );\n# });\n# \n# const brick_7 = document.getElementById(\"brick-7\");\n# brick_7.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_7.layoutOptions = {\n# initialLayout: \"layered-staggered\",\n# snap: {\n# object: true,\n# },\n# };\n# brick_7.defaultNodeSize = [60, 60];\n# brick_7.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent:\n# '<% `Node ${DATA.node.id}${DATA.node.locked ? \" (locked)\" : \"\"}` %>',\n# status:\n# '<%=\\n (CTX.activeTarget?.type === \"multi\"\\n ? CTX.activeTarget.targets\\n : CTX.activeTarget\\n ? [CTX.activeTarget]\\n : []\\n ).some((target) => (\\n target.type === \"node\" && target.id === DATA.node.id\\n ))\\n ? \"highlighted\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_7.defaultEdgeLines = [\n# {\n# if: \"<% DATA.edge.data?.virtual %>\",\n# dashed: true,\n# },\n# {\n# if: \"<% !DATA.edge.data?.virtual %>\",\n# dotted: true,\n# showStartArrow: true,\n# markers: [\n# {\n# placement: \"start\",\n# type: \"circle\",\n# },\n# {\n# placement: \"end\",\n# type: \"arrow\",\n# },\n# ],\n# },\n# ];\n# brick_7.cells = \"<% CTX.initialCells %>\";\n# brick_7.lineConnector = true;\n# brick_7.lineSettings = {\n# type: \"polyline\",\n# };\n# brick_7.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_7.addEventListener(\"cells.move\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `You just moved ${EVENT.detail.length} cells` %>\",\n# });\n# });\n# brick_7.addEventListener(\"cell.resize\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\",\n# });\n# });\n# brick_7.addEventListener(\"cells.delete\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"warn\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `You wanna delete ${EVENT.detail.length} cells?` %>\\n\",\n# });\n# });\n# brick_7.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_7.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_7.addEventListener(\"edge.add\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Added an nice edge: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_7.addEventListener(\"edge.view.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Edge view changed: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_7.addEventListener(\"decorator.view.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `Decorator view changed: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_7.addEventListener(\"decorator.text.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% JSON.stringify(EVENT.detail) %>\",\n# });\n# });\n# brick_7.addEventListener(\"node.container.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% JSON.stringify(EVENT.detail) %>\",\n# });\n# });\n# brick_7.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_8 = document.getElementById(\"brick-8\");\n# brick_8.addEventListener(\"remove\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.updateCells(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n CTX.initialCells.filter((cell) =>\\n !(\\n CTX.contextMenuDetail.cell.type === \"edge\"\\n ? cell.type === \"edge\" && CTX.contextMenuDetail.cell.source === cell.source && CTX.contextMenuDetail.cell.target === cell.target\\n : cell.id === CTX.contextMenuDetail.cell.id ||\\n (cell.type === \"edge\" && (\\n CTX.contextMenuDetail.cell.id === cell.source ||\\n CTX.contextMenuDetail.cell.id === cell.target))\\n )\\n )\\n%>\\n'\n# );\n# });\n# brick_8.addEventListener(\"add-edge\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.manuallyConnectNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.contextMenuDetail.cell.id %>\"\n# );\n# });\n# brick_8.addEventListener(\"toggle-lock\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.toggleLock(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.contextMenuDetail.target %>\"\n# );\n# });\n# </script>\n# \n```\n\n### Line labels\n\n设置连线文字。\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n flexDirection: column\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n description: \"X->Y\",\n placement: \"end\",\n view: {\n type: \"polyline\"\n }\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\"\n },\n {\n type: \"node\",\n id: \"X\",\n data: {\n name: \"Node X\",\n },\n view: {\n x: 100,\n y: 100,\n width: 60,\n height: 60,\n }\n },\n {\n type: \"node\",\n id: \"Y\",\n data: {\n name: \"Node Y\",\n },\n view: {\n x: 0,\n y: 300,\n width: 60,\n height: 60,\n }\n },\n {\n type: \"node\",\n id: \"Z\",\n data: {\n name: \"Node Z\",\n },\n view: {\n x: 300,\n y: 200,\n width: 60,\n height: 60,\n }\n },\n ]\n %>\n - name: activeTarget\n - name: scale\n value: 1\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n dragBehavior: lasso\n layoutOptions:\n snap:\n object: true\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n (CTX.activeTarget?.type === \"multi\"\n ? CTX.activeTarget.targets\n : CTX.activeTarget\n ? [CTX.activeTarget]\n : []\n ).some((target) => (\n target.type === \"node\" && target.id === DATA.node.id\n ))\n ? \"highlighted\"\n : \"default\"\n %>\n cells: <% CTX.initialCells %>\n lineConnector: true\n defaultEdgeLines:\n - callLabelOnDoubleClick: enableEditing\n label:\n placement: <% DATA.edge.placement %>\n offset: 10\n useBrick:\n brick: diagram.editable-label\n properties:\n label: <% DATA.edge.description %>\n type: line\n # Set `readOnly: true` for eo-display-canvas\n # readOnly: true\n events:\n label.change:\n # Make sure only trigger update if label actually changed\n if: <% (DATA.edge.description || \"\") !== (EVENT.detail || \"\") %>\n action: context.replace\n args:\n - initialCells\n - |-\n <%\n CTX.initialCells.map((edge) =>\n edge.type === \"edge\" &&\n edge.source === DATA.edge.source &&\n edge.target === DATA.edge.target\n ? { ...edge, description: EVENT.detail }\n : edge\n )\n %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.delete:\n action: message.warn\n args:\n - |\n <% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; flex-direction: column; height: 600px; gap: 1em\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# drag-behavior=\"lasso\"\n# id=\"brick-1\"\n# ></eo-draw-canvas>\n# </div>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_1.layoutOptions = {\n# snap: {\n# object: true,\n# },\n# };\n# brick_1.defaultNodeSize = [60, 60];\n# brick_1.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n (CTX.activeTarget?.type === \"multi\"\\n ? CTX.activeTarget.targets\\n : CTX.activeTarget\\n ? [CTX.activeTarget]\\n : []\\n ).some((target) => (\\n target.type === \"node\" && target.id === DATA.node.id\\n ))\\n ? \"highlighted\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_1.cells = \"<% CTX.initialCells %>\";\n# brick_1.lineConnector = true;\n# brick_1.defaultEdgeLines = [\n# {\n# callLabelOnDoubleClick: \"enableEditing\",\n# label: {\n# placement: \"<% DATA.edge.placement %>\",\n# offset: 10,\n# useBrick: {\n# brick: \"diagram.editable-label\",\n# properties: {\n# label: \"<% DATA.edge.description %>\",\n# type: \"line\",\n# },\n# events: {\n# \"label.change\": {\n# if: '<% (DATA.edge.description || \"\") !== (EVENT.detail || \"\") %>',\n# action: \"context.replace\",\n# args: [\n# \"initialCells\",\n# '<%\\n CTX.initialCells.map((edge) =>\\n edge.type === \"edge\" &&\\n edge.source === DATA.edge.source &&\\n edge.target === DATA.edge.target\\n ? { ...edge, description: EVENT.detail }\\n : edge\\n )\\n%>',\n# ],\n# },\n# },\n# },\n# },\n# },\n# ];\n# brick_1.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_1.addEventListener(\"cell.delete\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"warn\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# '<% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\\n',\n# });\n# });\n# brick_1.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# </script>\n# \n```\n\n### Line settings\n\n设置属性 `lineSettings` 来调整新的连线的样式,例如使用折线或直线。注意,该设置不影响已有的 edge 的连线样式。\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n flexDirection: column\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n decorator: \"line\",\n id: \"line-1\",\n view: {\n source: {\n x: 200,\n y: 200,\n },\n target: {\n x: 250,\n y: 150,\n },\n // type: \"polyline\",\n vertices: [\n {\n x: 180,\n y: 125,\n },\n ],\n markers: [{\n placement: \"end\",\n type: \"arrow\",\n }],\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"node\",\n id: \"X\",\n data: {\n name: \"Node X\",\n },\n view: {\n x: 100,\n y: 100,\n width: 60,\n height: 60,\n }\n },\n {\n type: \"node\",\n id: \"Y\",\n data: {\n name: \"Node Y\",\n },\n view: {\n x: 0,\n y: 300,\n width: 60,\n height: 60,\n }\n },\n {\n type: \"node\",\n id: \"Z\",\n data: {\n name: \"Node Z\",\n },\n view: {\n x: 300,\n y: 200,\n width: 60,\n height: 60,\n }\n },\n ]\n %>\n - name: dragging\n - name: activeTarget\n - name: targetCell\n - name: scale\n value: 1\n - name: lineType\n value: polyline\n children:\n - brick: div\n children:\n - brick: eo-radio\n properties:\n type: button\n value: polyline\n options:\n - polyline\n - curve\n - straight\n events:\n change:\n action: context.replace\n args:\n - lineType\n - <% EVENT.detail.value %>\n - brick: div\n properties:\n style:\n flex: 1\n minHeight: 0\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n dragBehavior: lasso\n layoutOptions:\n snap:\n object: true\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n (CTX.activeTarget?.type === \"multi\"\n ? CTX.activeTarget.targets\n : CTX.activeTarget\n ? [CTX.activeTarget]\n : []\n ).some((target) => (\n target.type === \"node\" && target.id === DATA.node.id\n ))\n ? \"highlighted\"\n : \"default\"\n %>\n cells: <% CTX.initialCells %>\n defaultEdgeLines:\n - jumps: true\n lineConnector: true\n lineSettings: |\n <%= { type: CTX.lineType } %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n edge.add:\n action: message.info\n args:\n - |\n <% `Added an nice edge: ${JSON.stringify(EVENT.detail)}` %>\n edge.view.change:\n action: message.info\n args:\n - |\n <% `Edge view changed: ${JSON.stringify(EVENT.detail)}` %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n- brick: diagram.experimental-node\n properties:\n usage: dragging\n textContent: |\n <%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\" ? \"Text\" : null) : CTX.dragging?.data.name %>\n decorator: |\n <%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %>\n style: |\n <%=\n {\n left: `${CTX.dragging?.position[0]}px`,\n top: `${CTX.dragging?.position[1]}px`,\n transform: `scale(${CTX.scale})`,\n transformOrigin: \"0 0\",\n padding: CTX.dragging?.decorator === \"text\" ? \"0.5em\" : \"0\"\n }\n %>\n hidden: <%= !CTX.dragging %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n ([\"node\"].includes(CTX.targetCell?.type )||CTX.targetCell?.decorator==\"area\") ? [\n {\n text: \"添加边\",\n event: \"add-edge\",\n }\n ] : [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n events:\n add-edge:\n target: eo-draw-canvas\n method: manuallyConnectNodes\n args:\n - <% CTX.targetCell.id %>\n callback:\n success:\n - target: eo-draw-canvas\n method: addEdge\n args:\n - source: <% EVENT.detail.source.id %>\n target: <% EVENT.detail.target.id %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; flex-direction: column; height: 600px; gap: 1em\">\n# <div>\n# <eo-radio\n# type=\"button\"\n# value=\"polyline\"\n# options=\"polyline,curve,straight\"\n# id=\"brick-1\"\n# ></eo-radio>\n# </div>\n# <div style=\"flex: 1; min-height: 0\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# drag-behavior=\"lasso\"\n# id=\"brick-2\"\n# ></eo-draw-canvas>\n# </div>\n# </div>\n# <diagram.experimental-node\n# usage=\"dragging\"\n# decorator='&lt;%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %&gt;\n# '\n# hidden=\"&lt;%= !CTX.dragging %&gt;\"\n# >\n# &lt;%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\"\n# ? \"Text\" : null) : CTX.dragging?.data.name %&gt;\n# </diagram.experimental-node>\n# <eo-context-menu\n# actions='&lt;%=\n# ([\"node\"].includes(CTX.targetCell?.type )||CTX.targetCell?.decorator==\"area\") ? [\n# {\n# text: \"添加边\",\n# event: \"add-edge\",\n# }\n# ] : [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# '\n# id=\"brick-3\"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_2 = document.getElementById(\"brick-2\");\n# brick_2.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_2.layoutOptions = {\n# snap: {\n# object: true,\n# },\n# };\n# brick_2.defaultNodeSize = [60, 60];\n# brick_2.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n (CTX.activeTarget?.type === \"multi\"\\n ? CTX.activeTarget.targets\\n : CTX.activeTarget\\n ? [CTX.activeTarget]\\n : []\\n ).some((target) => (\\n target.type === \"node\" && target.id === DATA.node.id\\n ))\\n ? \"highlighted\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_2.cells = \"<% CTX.initialCells %>\";\n# brick_2.defaultEdgeLines = [\n# {\n# jumps: true,\n# },\n# ];\n# brick_2.lineConnector = true;\n# brick_2.lineSettings = \"<%= { type: CTX.lineType } %>\\n\";\n# brick_2.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_2.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_2.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_2.addEventListener(\"edge.add\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Added an nice edge: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_2.addEventListener(\"edge.view.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% `Edge view changed: ${JSON.stringify(EVENT.detail)}` %>\\n\",\n# });\n# });\n# brick_2.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_3 = document.getElementById(\"brick-3\");\n# brick_3.addEventListener(\"add-edge\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.manuallyConnectNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.targetCell.id %>\"\n# );\n# });\n# </script>\n# \n```\n\n### Force layout\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"area-1\",\n decorator: \"area\",\n view: {\n x: 10,\n y: 20,\n width: 400,\n height: 300,\n },\n },\n {\n type: \"decorator\",\n id: \"container-1\",\n decorator: \"container\",\n view: {\n x: 50,\n y: 400,\n width: 280,\n height: 120,\n direction: \"top\",\n text: \" 上层服务\"\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n }\n },\n ].concat(\n [\"X\", \"Y\", \"Z\", \"W\"].map((id) => ({\n type: \"node\",\n id,\n containerId: [\"X\",\"Y\",\"Z\"].includes(id)?\"container-1\":undefined,\n data: {\n name: `Node ${id}`,\n },\n view: {\n width: 60,\n height: 60,\n }\n }))\n ).concat([\n {\n type: \"decorator\",\n id: \"text-1\",\n decorator: \"text\",\n view: {\n x: 100,\n y: 120,\n width: 100,\n height: 20,\n text: \"Hello!\"\n },\n },\n ])\n %>\n - name: dragging\n - name: activeTarget\n - name: targetCell\n - name: scale\n value: 1\n children:\n - brick: div\n properties:\n style:\n width: 180px\n display: flex\n flexDirection: column\n gap: 1em\n children:\n - brick: eo-button\n properties:\n textContent: Add random nodes\n events:\n click:\n target: eo-draw-canvas\n method: addNodes\n args:\n - |\n <%\n ((...seeds) => seeds.map((seed) => ({\n id: seed,\n data: {\n name: String(seed),\n },\n })))(\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n )\n %>\n callback:\n success:\n action: console.log\n args:\n - Added nodes\n - <% EVENT.detail %>\n - brick: eo-button\n properties:\n textContent: \"Add edge: Y => Z\"\n events:\n click:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: Y\n target: Z\n data:\n virtual: true\n - brick: :forEach\n dataSource:\n - X\n - Y\n children:\n - brick: eo-button\n properties:\n textContent: <% `Add nodes below ${ITEM}` %>\n events:\n click:\n target: eo-draw-canvas\n method: updateCells\n args:\n - |\n <%\n CTX.initialCells.concat([\n {\n type: \"edge\",\n source: ITEM,\n target: \"U\",\n },\n {\n type: \"edge\",\n source: ITEM,\n target: \"V\",\n },\n {\n type: \"node\",\n id: \"U\",\n data: {\n name: \"U\"\n }\n },\n {\n type: \"node\",\n id: \"V\",\n data: {\n name: \"V\"\n }\n },\n ])\n %>\n - reason: add-related-nodes\n parent: <% ITEM %>\n callback:\n success:\n action: console.log\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag nodes below\n - brick: :forEach\n dataSource: |\n <%\n [\"A\", \"B\", \"C\"].map((id) => ({\n type: \"node\",\n id,\n data: {\n name: `Node ${id}`,\n },\n }))\n %>\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% ITEM.data.name %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, ...ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropNode\n args:\n - position: <% EVENT.detail %>\n id: <% ITEM.id %>\n data: <% ITEM.data %>\n callback:\n success:\n if: <% EVENT.detail %>\n then:\n action: message.success\n args:\n - <% JSON.stringify(EVENT.detail) %>\n else:\n action: message.warn\n args:\n - Unexpected drop position\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag decorators below\n - brick: :forEach\n dataSource:\n - area\n - text\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% _.upperFirst(ITEM) %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, type: \"decorator\", decorator: ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropDecorator\n args:\n - position: <% EVENT.detail %>\n decorator: <% ITEM %>\n text: '<% ITEM === \"text\" ? \"Text\" : undefined %>'\n callback:\n success:\n if: <% !EVENT.detail %>\n action: message.warn\n args:\n - Unexpected drop position\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n layout: force\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\n ? \"highlighted\"\n // : CTX.unrelated.some(n =>\n // n.type === \"node\" && n.id === DATA.node.id\n // )\n // ? \"faded\"\n : \"default\"\n %>\n defaultEdgeLines:\n - if: <% DATA.edge.data?.virtual %>\n dashed: true\n cells: <% CTX.initialCells %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.move:\n action: message.info\n args:\n - <% `You just moved ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.x)}, ${Math.round(EVENT.detail.y)})` %>\n cell.resize:\n action: message.info\n args:\n - <% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\n cell.delete:\n action: message.warn\n args:\n - |\n <% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n decorator.text.change:\n action: message.info\n args:\n - <% JSON.stringify(EVENT.detail) %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n- brick: diagram.experimental-node\n properties:\n usage: dragging\n textContent: |\n <%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\" ? \"Text\" : null) : CTX.dragging?.data.name %>\n decorator: |\n <%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %>\n style: |\n <%=\n {\n left: `${CTX.dragging?.position[0]}px`,\n top: `${CTX.dragging?.position[1]}px`,\n transform: `scale(${CTX.scale})`,\n transformOrigin: \"0 0\",\n padding: CTX.dragging?.decorator === \"text\" ? \"0.5em\" : \"0\"\n }\n %>\n hidden: <%= !CTX.dragging %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n CTX.targetCell?.type === \"node\" ? [\n {\n text: \"添加边\",\n event: \"add-edge\",\n }\n ] : [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n events:\n add-edge:\n target: eo-draw-canvas\n method: manuallyConnectNodes\n args:\n - <% CTX.targetCell.id %>\n callback:\n success:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: <% EVENT.detail.source.id %>\n target: <% EVENT.detail.target.id %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div style=\"width: 180px; display: flex; flex-direction: column; gap: 1em\">\n# <eo-button id=\"brick-1\">Add random nodes</eo-button>\n# <eo-button id=\"brick-2\">Add edge: Y =&gt; Z</eo-button>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag nodes below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag decorators below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# </div>\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# layout=\"force\"\n# id=\"brick-6\"\n# ></eo-draw-canvas>\n# </div>\n# </div>\n# <diagram.experimental-node\n# usage=\"dragging\"\n# decorator='&lt;%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %&gt;\n# '\n# hidden=\"&lt;%= !CTX.dragging %&gt;\"\n# >\n# &lt;%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\"\n# ? \"Text\" : null) : CTX.dragging?.data.name %&gt;\n# </diagram.experimental-node>\n# <eo-context-menu\n# actions='&lt;%=\n# CTX.targetCell?.type === \"node\" ? [\n# {\n# text: \"添加边\",\n# event: \"add-edge\",\n# }\n# ] : [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# '\n# id=\"brick-7\"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<%\\n ((...seeds) => seeds.map((seed) => ({\\n id: seed,\\n data: {\\n name: String(seed),\\n },\\n })))(\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n )\\n%>\\n\"\n# );\n# });\n# \n# const brick_2 = document.getElementById(\"brick-2\");\n# brick_2.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addEdge({ source: \"Y\", target: \"Z\", data: { virtual: true } });\n# });\n# \n# const brick_3 = document.getElementById(\"brick-3\");\n# brick_3.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.updateCells(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n CTX.initialCells.concat([\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"U\",\\n },\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"V\",\\n },\\n {\\n type: \"node\",\\n id: \"U\",\\n data: {\\n name: \"U\"\\n }\\n },\\n {\\n type: \"node\",\\n id: \"V\",\\n data: {\\n name: \"V\"\\n }\\n },\\n ])\\n%>\\n',\n# { reason: \"add-related-nodes\", parent: \"<% ITEM %>\" }\n# );\n# });\n# \n# const brick_4 = document.getElementById(\"brick-4\");\n# brick_4.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_4.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_4.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropNode({\n# position: \"<% EVENT.detail %>\",\n# id: \"<% ITEM.id %>\",\n# data: \"<% ITEM.data %>\",\n# });\n# });\n# \n# const brick_5 = document.getElementById(\"brick-5\");\n# brick_5.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropDecorator({\n# position: \"<% EVENT.detail %>\",\n# decorator: \"<% ITEM %>\",\n# text: '<% ITEM === \"text\" ? \"Text\" : undefined %>',\n# });\n# });\n# \n# const brick_6 = document.getElementById(\"brick-6\");\n# brick_6.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_6.defaultNodeSize = [60, 60];\n# brick_6.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\\n ? \"highlighted\"\\n // : CTX.unrelated.some(n =>\\n // n.type === \"node\" && n.id === DATA.node.id\\n // )\\n // ? \"faded\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_6.defaultEdgeLines = [\n# {\n# if: \"<% DATA.edge.data?.virtual %>\",\n# dashed: true,\n# },\n# ];\n# brick_6.cells = \"<% CTX.initialCells %>\";\n# brick_6.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"cell.move\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just moved ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.x)}, ${Math.round(EVENT.detail.y)})` %>\",\n# });\n# });\n# brick_6.addEventListener(\"cell.resize\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\",\n# });\n# });\n# brick_6.addEventListener(\"cell.delete\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"warn\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# '<% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\\n',\n# });\n# });\n# brick_6.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_6.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"decorator.text.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% JSON.stringify(EVENT.detail) %>\",\n# });\n# });\n# brick_6.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_7 = document.getElementById(\"brick-7\");\n# brick_7.addEventListener(\"add-edge\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.manuallyConnectNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.targetCell.id %>\"\n# );\n# });\n# </script>\n# \n```\n\n### Dagre layout\n\n```yaml preview minHeight=\"600px\"\n- brick: div\n properties:\n style:\n display: flex\n height: 600px\n gap: 1em\n context:\n - name: initialCells\n value: |\n <%\n [\n {\n type: \"decorator\",\n id: \"area-1\",\n decorator: \"area\",\n view: {\n x: 10,\n y: 20,\n width: 400,\n height: 300,\n },\n },\n {\n type: \"decorator\",\n id: \"container-1\",\n decorator: \"container\",\n view: {\n x: 50,\n y: 400,\n width: 280,\n height: 120,\n direction: \"top\",\n text: \" 上层服务\"\n },\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Y\",\n },\n {\n type: \"edge\",\n source: \"X\",\n target: \"Z\",\n data: {\n virtual: true,\n }\n },\n {\n type: \"edge\",\n source: \"Z\",\n target: \"W\",\n },\n ].concat(\n [\"X\", \"Y\", \"Z\", \"W\"].map((id) => ({\n type: \"node\",\n id,\n containerId: [\"W\",\"Z\"].includes(id)?\"container-1\":undefined,\n data: {\n name: `Node ${id}`,\n },\n view: {\n width: 60,\n height: 60,\n }\n }))\n )\n %>\n - name: dragging\n - name: activeTarget\n - name: targetCell\n - name: scale\n value: 1\n children:\n - brick: div\n properties:\n style:\n width: 180px\n display: flex\n flexDirection: column\n gap: 1em\n children:\n - brick: eo-button\n properties:\n textContent: Add random nodes\n events:\n click:\n target: eo-draw-canvas\n method: addNodes\n args:\n - |\n <%\n ((...seeds) => seeds.map((seed) => ({\n id: seed,\n data: {\n name: String(seed),\n },\n })))(\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n Math.round(Math.random() * 1e6),\n )\n %>\n callback:\n success:\n action: console.log\n args:\n - Added nodes\n - <% EVENT.detail %>\n - brick: eo-button\n properties:\n textContent: \"Add edge: Y => Z\"\n events:\n click:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: Y\n target: Z\n data:\n virtual: true\n - brick: :forEach\n dataSource:\n - X\n - Y\n children:\n - brick: eo-button\n properties:\n textContent: <% `Add nodes below ${ITEM}` %>\n events:\n click:\n target: eo-draw-canvas\n method: updateCells\n args:\n - |\n <%\n CTX.initialCells.concat([\n {\n type: \"edge\",\n source: ITEM,\n target: \"U\",\n },\n {\n type: \"edge\",\n source: ITEM,\n target: \"V\",\n },\n {\n type: \"node\",\n id: \"U\",\n data: {\n name: \"U\"\n }\n },\n {\n type: \"node\",\n id: \"V\",\n data: {\n name: \"V\"\n }\n },\n ])\n %>\n - reason: add-related-nodes\n parent: <% ITEM %>\n callback:\n success:\n action: console.log\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag nodes below\n - brick: :forEach\n dataSource: |\n <%\n [\"A\", \"B\", \"C\"].map((id) => ({\n type: \"node\",\n id,\n data: {\n name: `Node ${id}`,\n },\n }))\n %>\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% ITEM.data.name %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, ...ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropNode\n args:\n - position: <% EVENT.detail %>\n id: <% ITEM.id %>\n data: <% ITEM.data %>\n callback:\n success:\n if: <% EVENT.detail %>\n then:\n action: message.success\n args:\n - <% JSON.stringify(EVENT.detail) %>\n else:\n action: message.warn\n args:\n - Unexpected drop position\n - brick: hr\n properties:\n style:\n width: 100%\n - brick: h3\n properties:\n textContent: Drag decorators below\n - brick: :forEach\n dataSource:\n - area\n - text\n children:\n - brick: diagram.experimental-node\n properties:\n textContent: <% _.upperFirst(ITEM) %>\n usage: library\n events:\n drag.move:\n action: context.replace\n args:\n - dragging\n - |\n <% {position: EVENT.detail, type: \"decorator\", decorator: ITEM} %>\n drag.end:\n - action: context.replace\n args:\n - dragging\n - null\n - target: eo-draw-canvas\n method: dropDecorator\n args:\n - position: <% EVENT.detail %>\n decorator: <% ITEM %>\n text: '<% ITEM === \"text\" ? \"Text\" : undefined %>'\n callback:\n success:\n if: <% !EVENT.detail %>\n action: message.warn\n args:\n - Unexpected drop position\n - brick: div\n properties:\n style:\n flex: 1\n minWidth: 0\n children:\n - brick: eo-draw-canvas\n properties:\n style:\n width: 100%\n height: 100%\n activeTarget: <%= CTX.activeTarget %>\n fadeUnrelatedCells: true\n layout: dagre\n # Initial nodes only\n defaultNodeSize: [60, 60]\n defaultNodeBricks:\n - useBrick:\n brick: diagram.experimental-node\n properties:\n textContent: <% `Node ${DATA.node.id}` %>\n status: |\n <%=\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\n ? \"highlighted\"\n // : CTX.unrelated.some(n =>\n // n.type === \"node\" && n.id === DATA.node.id\n // )\n // ? \"faded\"\n : \"default\"\n %>\n defaultEdgeLines:\n - dashed: <% !!DATA.edge.data?.virtual %>\n strokeColor: var(--palette-blue-6)\n overrides:\n active:\n strokeWidth: <% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>\n strokeColor: cyan\n cells: <% CTX.initialCells %>\n events:\n activeTarget.change:\n action: context.replace\n args:\n - activeTarget\n - <% EVENT.detail %>\n cell.move:\n action: message.info\n args:\n - <% `You just moved ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.x)}, ${Math.round(EVENT.detail.y)})` %>\n cell.resize:\n action: message.info\n args:\n - <% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\n cell.delete:\n action: message.warn\n args:\n - |\n <% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\n cell.contextmenu:\n - target: eo-context-menu\n method: open\n args:\n - position:\n - <% EVENT.detail.clientX %>\n - <% EVENT.detail.clientY %>\n - action: context.replace\n args:\n - targetCell\n - <% EVENT.detail.cell %>\n decorator.text.change:\n action: message.info\n args:\n - <% JSON.stringify(EVENT.detail) %>\n scale.change:\n action: context.replace\n args:\n - scale\n - <% EVENT.detail %>\n- brick: diagram.experimental-node\n properties:\n usage: dragging\n textContent: |\n <%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\" ? \"Text\" : null) : CTX.dragging?.data.name %>\n decorator: |\n <%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %>\n style: |\n <%=\n {\n left: `${CTX.dragging?.position[0]}px`,\n top: `${CTX.dragging?.position[1]}px`,\n transform: `scale(${CTX.scale})`,\n transformOrigin: \"0 0\",\n padding: CTX.dragging?.decorator === \"text\" ? \"0.5em\" : \"0\"\n }\n %>\n hidden: <%= !CTX.dragging %>\n- brick: eo-context-menu\n properties:\n actions: |\n <%=\n CTX.targetCell?.type === \"node\" ? [\n {\n text: \"添加边\",\n event: \"add-edge\",\n }\n ] : [\n {\n text: `Test ${CTX.targetCell?.type}`,\n event: `test-${CTX.targetCell?.type}`,\n }\n ]\n %>\n events:\n add-edge:\n target: eo-draw-canvas\n method: manuallyConnectNodes\n args:\n - <% CTX.targetCell.id %>\n callback:\n success:\n target: eo-draw-canvas\n method: addEdge\n args:\n - source: <% EVENT.detail.source.id %>\n target: <% EVENT.detail.target.id %>\n# -- YAML DELIMITER (1nbbm8) --\n# <div style=\"display: flex; height: 600px; gap: 1em\">\n# <div style=\"width: 180px; display: flex; flex-direction: column; gap: 1em\">\n# <eo-button id=\"brick-1\">Add random nodes</eo-button>\n# <eo-button id=\"brick-2\">Add edge: Y =&gt; Z</eo-button>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag nodes below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# <hr style=\"width: 100%\" />\n# <h3>Drag decorators below</h3>\n# <!-- WARN: \":forEach\" is not supported in HTML mode, please try YAML. -->\n# </div>\n# <div style=\"flex: 1; min-width: 0\">\n# <eo-draw-canvas\n# style=\"width: 100%; height: 100%\"\n# fade-unrelated-cells\n# layout=\"dagre\"\n# id=\"brick-6\"\n# ></eo-draw-canvas>\n# </div>\n# </div>\n# <diagram.experimental-node\n# usage=\"dragging\"\n# decorator='&lt;%= CTX.dragging?.type === \"decorator\" ? CTX.dragging.decorator : null %&gt;\n# '\n# hidden=\"&lt;%= !CTX.dragging %&gt;\"\n# >\n# &lt;%= CTX.dragging?.type === \"decorator\" ? (CTX.dragging.decorator === \"text\"\n# ? \"Text\" : null) : CTX.dragging?.data.name %&gt;\n# </diagram.experimental-node>\n# <eo-context-menu\n# actions='&lt;%=\n# CTX.targetCell?.type === \"node\" ? [\n# {\n# text: \"添加边\",\n# event: \"add-edge\",\n# }\n# ] : [\n# {\n# text: `Test ${CTX.targetCell?.type}`,\n# event: `test-${CTX.targetCell?.type}`,\n# }\n# ]\n# %&gt;\n# '\n# id=\"brick-7\"\n# ></eo-context-menu>\n# \n# <script>\n# const brick_1 = document.getElementById(\"brick-1\");\n# brick_1.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<%\\n ((...seeds) => seeds.map((seed) => ({\\n id: seed,\\n data: {\\n name: String(seed),\\n },\\n })))(\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n Math.round(Math.random() * 1e6),\\n )\\n%>\\n\"\n# );\n# });\n# \n# const brick_2 = document.getElementById(\"brick-2\");\n# brick_2.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.addEdge({ source: \"Y\", target: \"Z\", data: { virtual: true } });\n# });\n# \n# const brick_3 = document.getElementById(\"brick-3\");\n# brick_3.addEventListener(\"click\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.updateCells(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# '<%\\n CTX.initialCells.concat([\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"U\",\\n },\\n {\\n type: \"edge\",\\n source: ITEM,\\n target: \"V\",\\n },\\n {\\n type: \"node\",\\n id: \"U\",\\n data: {\\n name: \"U\"\\n }\\n },\\n {\\n type: \"node\",\\n id: \"V\",\\n data: {\\n name: \"V\"\\n }\\n },\\n ])\\n%>\\n',\n# { reason: \"add-related-nodes\", parent: \"<% ITEM %>\" }\n# );\n# });\n# \n# const brick_4 = document.getElementById(\"brick-4\");\n# brick_4.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_4.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_4.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropNode({\n# position: \"<% EVENT.detail %>\",\n# id: \"<% ITEM.id %>\",\n# data: \"<% ITEM.data %>\",\n# });\n# });\n# \n# const brick_5 = document.getElementById(\"brick-5\");\n# brick_5.addEventListener(\"drag.move\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_5.addEventListener(\"drag.end\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.dropDecorator({\n# position: \"<% EVENT.detail %>\",\n# decorator: \"<% ITEM %>\",\n# text: '<% ITEM === \"text\" ? \"Text\" : undefined %>',\n# });\n# });\n# \n# const brick_6 = document.getElementById(\"brick-6\");\n# brick_6.activeTarget = \"<%= CTX.activeTarget %>\";\n# brick_6.defaultNodeSize = [60, 60];\n# brick_6.defaultNodeBricks = [\n# {\n# useBrick: {\n# brick: \"diagram.experimental-node\",\n# properties: {\n# textContent: \"<% `Node ${DATA.node.id}` %>\",\n# status:\n# '<%=\\n CTX.activeTarget?.type === \"node\" && CTX.activeTarget.id === DATA.node.id\\n ? \"highlighted\"\\n // : CTX.unrelated.some(n =>\\n // n.type === \"node\" && n.id === DATA.node.id\\n // )\\n // ? \"faded\"\\n : \"default\"\\n%>\\n',\n# },\n# },\n# },\n# ];\n# brick_6.defaultEdgeLines = [\n# {\n# dashed: \"<% !!DATA.edge.data?.virtual %>\",\n# strokeColor: \"var(--palette-blue-6)\",\n# overrides: {\n# active: {\n# strokeWidth: \"<% 2 * (DATA.edge?.data?.strokeWidth ?? 1) %>\",\n# strokeColor: \"cyan\",\n# },\n# },\n# },\n# ];\n# brick_6.cells = \"<% CTX.initialCells %>\";\n# brick_6.addEventListener(\"activeTarget.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"cell.move\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just moved ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.x)}, ${Math.round(EVENT.detail.y)})` %>\",\n# });\n# });\n# brick_6.addEventListener(\"cell.resize\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# \"<% `You just resized ${EVENT.detail.type} ${EVENT.detail.id} to (${Math.round(EVENT.detail.width)}, ${Math.round(EVENT.detail.height)})` %>\",\n# });\n# });\n# brick_6.addEventListener(\"cell.delete\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"warn\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message:\n# '<% `You wanna delete ${EVENT.detail.type} ${EVENT.detail.type === \"edge\" ? `(${EVENT.detail.source} => ${EVENT.detail.target})` : EVENT.detail.id}?` %>\\n',\n# });\n# });\n# brick_6.addEventListener(\"cell.contextmenu\", (e) => {\n# const brick = document.querySelector(\"eo-context-menu\");\n# brick.open({\n# position: [\"<% EVENT.detail.clientX %>\", \"<% EVENT.detail.clientY %>\"],\n# });\n# });\n# brick_6.addEventListener(\"cell.contextmenu\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# brick_6.addEventListener(\"decorator.text.change\", (e) => {\n# const message = document.createElement(\"basic.show-notification\");\n# message.resolve({\n# type: \"info\",\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# message: \"<% JSON.stringify(EVENT.detail) %>\",\n# });\n# });\n# brick_6.addEventListener(\"scale.change\", (e) => {\n# // WARN: encountered incompatible event handlers in HTML mode, please try YAML.\n# });\n# \n# const brick_7 = document.getElementById(\"brick-7\");\n# brick_7.addEventListener(\"add-edge\", (e) => {\n# const brick = document.querySelector(\"eo-draw-canvas\");\n# brick.manuallyConnectNodes(\n# /* WARN: incompatible expressions in HTML, please try YAML: */\n# \"<% CTX.targetCell.id %>\"\n# );\n# });\n# </script>\n# \n```\n"
13
13
  }
14
14
  }