@dou-ui/flow 0.0.0-stage → 0.1.0-alpha.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 (173) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/collaboration/index.js +360 -0
  4. package/dist/collaboration/index.js.map +1 -0
  5. package/dist/collaboration/peers.js +76 -0
  6. package/dist/collaboration/peers.js.map +1 -0
  7. package/dist/components/default-node.js +6 -0
  8. package/dist/components/default-node.js.map +1 -0
  9. package/dist/components/default-node.vue_vue_type_script_setup_true_lang.js +87 -0
  10. package/dist/components/default-node.vue_vue_type_script_setup_true_lang.js.map +1 -0
  11. package/dist/components/default-node2.js +116 -0
  12. package/dist/components/default-node2.js.map +1 -0
  13. package/dist/components/flow-controls.js +6 -0
  14. package/dist/components/flow-controls.js.map +1 -0
  15. package/dist/components/flow-controls.vue_vue_type_script_setup_true_lang.js +148 -0
  16. package/dist/components/flow-controls.vue_vue_type_script_setup_true_lang.js.map +1 -0
  17. package/dist/components/flow-menu.js +6 -0
  18. package/dist/components/flow-menu.js.map +1 -0
  19. package/dist/components/flow-menu.vue_vue_type_script_setup_true_lang.js +52 -0
  20. package/dist/components/flow-menu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  21. package/dist/components/flow-minimap.js +6 -0
  22. package/dist/components/flow-minimap.js.map +1 -0
  23. package/dist/components/flow-minimap.vue_vue_type_script_setup_true_lang.js +238 -0
  24. package/dist/components/flow-minimap.vue_vue_type_script_setup_true_lang.js.map +1 -0
  25. package/dist/components/flow-port.js +6 -0
  26. package/dist/components/flow-port.js.map +1 -0
  27. package/dist/components/flow-port.vue_vue_type_script_setup_true_lang.js +57 -0
  28. package/dist/components/flow-port.vue_vue_type_script_setup_true_lang.js.map +1 -0
  29. package/dist/components/flow-quick-add.js +6 -0
  30. package/dist/components/flow-quick-add.js.map +1 -0
  31. package/dist/components/flow-quick-add.vue_vue_type_script_setup_true_lang.js +126 -0
  32. package/dist/components/flow-quick-add.vue_vue_type_script_setup_true_lang.js.map +1 -0
  33. package/dist/components/flow-toolbar.js +6 -0
  34. package/dist/components/flow-toolbar.js.map +1 -0
  35. package/dist/components/flow-toolbar.vue_vue_type_script_setup_true_lang.js +161 -0
  36. package/dist/components/flow-toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  37. package/dist/components/group-node.js +6 -0
  38. package/dist/components/group-node.js.map +1 -0
  39. package/dist/components/group-node.vue_vue_type_script_setup_true_lang.js +84 -0
  40. package/dist/components/group-node.vue_vue_type_script_setup_true_lang.js.map +1 -0
  41. package/dist/components/group-node2.js +42 -0
  42. package/dist/components/group-node2.js.map +1 -0
  43. package/dist/components/node-view.js +6 -0
  44. package/dist/components/node-view.js.map +1 -0
  45. package/dist/components/node-view.vue_vue_type_script_setup_true_lang.js +179 -0
  46. package/dist/components/node-view.vue_vue_type_script_setup_true_lang.js.map +1 -0
  47. package/dist/context.js +13 -0
  48. package/dist/context.js.map +1 -0
  49. package/dist/core/clipboard.js +37 -0
  50. package/dist/core/clipboard.js.map +1 -0
  51. package/dist/core/connect.js +74 -0
  52. package/dist/core/connect.js.map +1 -0
  53. package/dist/core/edge-types.js +240 -0
  54. package/dist/core/edge-types.js.map +1 -0
  55. package/dist/core/extension.js +63 -0
  56. package/dist/core/extension.js.map +1 -0
  57. package/dist/core/geometry.js +232 -0
  58. package/dist/core/geometry.js.map +1 -0
  59. package/dist/core/groups.js +76 -0
  60. package/dist/core/groups.js.map +1 -0
  61. package/dist/core/history.js +79 -0
  62. package/dist/core/history.js.map +1 -0
  63. package/dist/core/model.js +21 -0
  64. package/dist/core/model.js.map +1 -0
  65. package/dist/core/node-types.js +32 -0
  66. package/dist/core/node-types.js.map +1 -0
  67. package/dist/core/order.js +42 -0
  68. package/dist/core/order.js.map +1 -0
  69. package/dist/core/transaction.js +288 -0
  70. package/dist/core/transaction.js.map +1 -0
  71. package/dist/document.js +220 -0
  72. package/dist/document.js.map +1 -0
  73. package/dist/export/color.js +38 -0
  74. package/dist/export/color.js.map +1 -0
  75. package/dist/export/context.js +223 -0
  76. package/dist/export/context.js.map +1 -0
  77. package/dist/export/draw.js +249 -0
  78. package/dist/export/draw.js.map +1 -0
  79. package/dist/flow-editor.js +6 -0
  80. package/dist/flow-editor.js.map +1 -0
  81. package/dist/flow-editor.vue_vue_type_script_setup_true_lang.js +3721 -0
  82. package/dist/flow-editor.vue_vue_type_script_setup_true_lang.js.map +1 -0
  83. package/dist/index.js +31 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/kit.js +234 -0
  86. package/dist/kit.js.map +1 -0
  87. package/dist/layers.js +150 -0
  88. package/dist/layers.js.map +1 -0
  89. package/dist/locale.js +426 -0
  90. package/dist/locale.js.map +1 -0
  91. package/dist/style.css +1 -0
  92. package/dist/style.d.ts +1 -0
  93. package/dist/style.js +8 -0
  94. package/dist/types/collaboration/index.d.ts +42 -0
  95. package/dist/types/collaboration/peers.d.ts +27 -0
  96. package/dist/types/components/default-node.d.ts +18 -0
  97. package/dist/types/components/default-node.vue.d.ts +6 -0
  98. package/dist/types/components/flow-controls.vue.d.ts +8 -0
  99. package/dist/types/components/flow-menu.vue.d.ts +29 -0
  100. package/dist/types/components/flow-minimap.vue.d.ts +8 -0
  101. package/dist/types/components/flow-port.vue.d.ts +9 -0
  102. package/dist/types/components/flow-quick-add.vue.d.ts +31 -0
  103. package/dist/types/components/flow-toolbar.vue.d.ts +25 -0
  104. package/dist/types/components/group-node.d.ts +13 -0
  105. package/dist/types/components/group-node.vue.d.ts +6 -0
  106. package/dist/types/components/node-view.vue.d.ts +28 -0
  107. package/dist/types/context.d.ts +362 -0
  108. package/dist/types/core/clipboard.d.ts +9 -0
  109. package/dist/types/core/connect.d.ts +63 -0
  110. package/dist/types/core/edge-types.d.ts +50 -0
  111. package/dist/types/core/extension.d.ts +141 -0
  112. package/dist/types/core/geometry.d.ts +63 -0
  113. package/dist/types/core/groups.d.ts +23 -0
  114. package/dist/types/core/history.d.ts +24 -0
  115. package/dist/types/core/menu.d.ts +40 -0
  116. package/dist/types/core/model.d.ts +87 -0
  117. package/dist/types/core/node-types.d.ts +103 -0
  118. package/dist/types/core/order.d.ts +7 -0
  119. package/dist/types/core/transaction.d.ts +97 -0
  120. package/dist/types/document.d.ts +57 -0
  121. package/dist/types/export/color.d.ts +7 -0
  122. package/dist/types/export/context.d.ts +90 -0
  123. package/dist/types/export/draw.d.ts +72 -0
  124. package/dist/types/flow-editor.vue.d.ts +63 -0
  125. package/dist/types/index.d.ts +202 -0
  126. package/dist/types/kit.d.ts +22 -0
  127. package/dist/types/layers.d.ts +24 -0
  128. package/dist/types/locale.d.ts +172 -0
  129. package/dist/types/whiteboard/board-draft.vue.d.ts +3 -0
  130. package/dist/types/whiteboard/board-node.vue.d.ts +19 -0
  131. package/dist/types/whiteboard/connector.d.ts +12 -0
  132. package/dist/types/whiteboard/draw.d.ts +5 -0
  133. package/dist/types/whiteboard/image.d.ts +27 -0
  134. package/dist/types/whiteboard/index.d.ts +6 -0
  135. package/dist/types/whiteboard/ink.d.ts +30 -0
  136. package/dist/types/whiteboard/kit.d.ts +36 -0
  137. package/dist/types/whiteboard/model.d.ts +79 -0
  138. package/dist/types/whiteboard/pen.d.ts +7 -0
  139. package/dist/types/whiteboard/state.d.ts +37 -0
  140. package/dist/types/whiteboard/transform.d.ts +67 -0
  141. package/dist/types/whiteboard/whiteboard-toolbar.vue.d.ts +3 -0
  142. package/dist/whiteboard/board-draft.js +6 -0
  143. package/dist/whiteboard/board-draft.js.map +1 -0
  144. package/dist/whiteboard/board-draft.vue_vue_type_script_setup_true_lang.js +58 -0
  145. package/dist/whiteboard/board-draft.vue_vue_type_script_setup_true_lang.js.map +1 -0
  146. package/dist/whiteboard/board-node.js +6 -0
  147. package/dist/whiteboard/board-node.js.map +1 -0
  148. package/dist/whiteboard/board-node.vue_vue_type_script_setup_true_lang.js +332 -0
  149. package/dist/whiteboard/board-node.vue_vue_type_script_setup_true_lang.js.map +1 -0
  150. package/dist/whiteboard/connector.js +180 -0
  151. package/dist/whiteboard/connector.js.map +1 -0
  152. package/dist/whiteboard/draw.js +68 -0
  153. package/dist/whiteboard/draw.js.map +1 -0
  154. package/dist/whiteboard/image.js +104 -0
  155. package/dist/whiteboard/image.js.map +1 -0
  156. package/dist/whiteboard/index.js +5 -0
  157. package/dist/whiteboard/ink.js +168 -0
  158. package/dist/whiteboard/ink.js.map +1 -0
  159. package/dist/whiteboard/kit.js +406 -0
  160. package/dist/whiteboard/kit.js.map +1 -0
  161. package/dist/whiteboard/model.js +52 -0
  162. package/dist/whiteboard/model.js.map +1 -0
  163. package/dist/whiteboard/pen.js +88 -0
  164. package/dist/whiteboard/pen.js.map +1 -0
  165. package/dist/whiteboard/state.js +26 -0
  166. package/dist/whiteboard/state.js.map +1 -0
  167. package/dist/whiteboard/transform.js +256 -0
  168. package/dist/whiteboard/transform.js.map +1 -0
  169. package/dist/whiteboard/whiteboard-toolbar.js +6 -0
  170. package/dist/whiteboard/whiteboard-toolbar.js.map +1 -0
  171. package/dist/whiteboard/whiteboard-toolbar.vue_vue_type_script_setup_true_lang.js +171 -0
  172. package/dist/whiteboard/whiteboard-toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  173. package/package.json +74 -4
package/dist/kit.js ADDED
@@ -0,0 +1,234 @@
1
+ import { defaultNode } from "./components/default-node2.js";
2
+ import { bezierEdge, stepEdge, straightEdge } from "./core/edge-types.js";
3
+ import { defineFlowExtension } from "./core/extension.js";
4
+ import { groupNode } from "./components/group-node2.js";
5
+ import { layers, stacking } from "./layers.js";
6
+ import { ClipboardPasteIcon, CopyIcon, CopyPlusIcon, EditIcon, FocusIcon, GroupIcon, HierarchyHorizontalIcon, MoreHorizontalIcon, ScissorsIcon, SquareDashedIcon, TrashIcon, UngroupIcon } from "@dou-ui/icons";
7
+ // src/kit.ts
8
+ /** Copy, paste, delete and the rest, on right click. */
9
+ var editMenu = defineFlowExtension({
10
+ name: "edit-menu",
11
+ priority: 0,
12
+ contextMenu(ctx, target) {
13
+ const t = ctx.messages.value;
14
+ const editable = !ctx.readonly.value;
15
+ const items = [];
16
+ if (target.kind === "canvas") {
17
+ if (editable) items.push({
18
+ key: "paste",
19
+ label: t.paste,
20
+ icon: ClipboardPasteIcon,
21
+ shortcut: "mod+v",
22
+ run: () => void ctx.paste(target.point)
23
+ });
24
+ items.push({
25
+ key: "select-all",
26
+ label: t.selectAll,
27
+ icon: SquareDashedIcon,
28
+ shortcut: "mod+a",
29
+ disabled: !ctx.doc.value.nodes.length,
30
+ run: ctx.selectAll
31
+ });
32
+ if (editable) items.push({
33
+ key: "tidy",
34
+ label: t.tidy,
35
+ icon: HierarchyHorizontalIcon,
36
+ divided: true,
37
+ disabled: !ctx.doc.value.nodes.length,
38
+ run: () => ctx.tidy()
39
+ });
40
+ items.push({
41
+ key: "fit",
42
+ label: t.fit,
43
+ icon: FocusIcon,
44
+ divided: !editable,
45
+ disabled: !ctx.doc.value.nodes.length,
46
+ run: () => ctx.fit()
47
+ });
48
+ return items;
49
+ }
50
+ if (target.kind === "node") {
51
+ items.push({
52
+ key: "copy",
53
+ label: t.copy,
54
+ icon: CopyIcon,
55
+ shortcut: "mod+c",
56
+ run: ctx.copy
57
+ });
58
+ if (!editable) return items;
59
+ const selected = ctx.selection.value.nodes;
60
+ const locked = (selected.includes(target.node.id) ? selected : [target.node.id]).every((id) => ctx.doc.value.nodes.find((n) => n.id === id)?.locked);
61
+ items.push({
62
+ key: "cut",
63
+ label: t.cut,
64
+ icon: ScissorsIcon,
65
+ shortcut: "mod+x",
66
+ disabled: locked,
67
+ run: ctx.cut
68
+ }, {
69
+ key: "duplicate",
70
+ label: t.duplicate,
71
+ icon: CopyPlusIcon,
72
+ shortcut: "mod+d",
73
+ run: ctx.duplicate
74
+ }, {
75
+ key: "delete",
76
+ label: t.delete,
77
+ icon: TrashIcon,
78
+ shortcut: "delete",
79
+ tone: "danger",
80
+ divided: true,
81
+ disabled: locked,
82
+ run: ctx.deleteSelection
83
+ });
84
+ return items;
85
+ }
86
+ if (!editable) return items;
87
+ const edge = target.edge;
88
+ items.push({
89
+ key: "edit-label",
90
+ label: t.editLabel,
91
+ icon: EditIcon,
92
+ shortcut: "enter",
93
+ run: () => ctx.editLabel(edge.id)
94
+ }, {
95
+ key: "delete",
96
+ label: t.delete,
97
+ icon: TrashIcon,
98
+ shortcut: "delete",
99
+ tone: "danger",
100
+ divided: true,
101
+ run: ctx.deleteSelection
102
+ });
103
+ return items;
104
+ }
105
+ });
106
+ /** Duplicate, delete and the node menu, over the selected nodes; delete over selected edges. */
107
+ var editToolbar = defineFlowExtension({
108
+ name: "edit-toolbar",
109
+ priority: 0,
110
+ edgeToolbarItems(ctx) {
111
+ return [{
112
+ key: "delete",
113
+ label: ctx.messages.value.delete,
114
+ icon: TrashIcon,
115
+ shortcut: "delete",
116
+ run: ctx.deleteSelection
117
+ }];
118
+ },
119
+ toolbarItems(ctx, nodes) {
120
+ const t = ctx.messages.value;
121
+ const first = nodes[0];
122
+ const more = ctx.menuItems({
123
+ kind: "node",
124
+ node: first,
125
+ point: {
126
+ x: first.x,
127
+ y: first.y
128
+ }
129
+ });
130
+ return [
131
+ {
132
+ key: "duplicate",
133
+ label: t.duplicate,
134
+ icon: CopyPlusIcon,
135
+ shortcut: "mod+d",
136
+ run: ctx.duplicate
137
+ },
138
+ {
139
+ key: "delete",
140
+ label: t.delete,
141
+ icon: TrashIcon,
142
+ shortcut: "delete",
143
+ disabled: nodes.every((node) => node.locked),
144
+ run: ctx.deleteSelection
145
+ },
146
+ ...more.length ? [{
147
+ key: "more",
148
+ label: t.more,
149
+ icon: MoreHorizontalIcon,
150
+ children: more
151
+ }] : []
152
+ ];
153
+ }
154
+ });
155
+ /** Group nodes: the type, Ctrl / ⌘ + G to group the selection, with Shift to ungroup. */
156
+ var groups = defineFlowExtension({
157
+ name: "groups",
158
+ priority: 0,
159
+ nodeTypes: [groupNode],
160
+ keymap: (ctx) => ({
161
+ "mod+g": () => ctx.groupNodes() !== null,
162
+ "mod+shift+g": () => {
163
+ const ids = ctx.selection.value.nodes;
164
+ const containers = ids.filter((id) => {
165
+ const node = ctx.doc.value.nodes.find((n) => n.id === id);
166
+ return node && ctx.isContainer(node);
167
+ });
168
+ if (containers.length) return containers.filter((id) => ctx.ungroupNode(id)).length > 0;
169
+ return ctx.leaveGroup(ids) > 0;
170
+ }
171
+ }),
172
+ contextMenu(ctx, target) {
173
+ if (target.kind !== "node" || ctx.readonly.value) return [];
174
+ const t = ctx.messages.value;
175
+ const tree = ctx.tree.value;
176
+ const parents = new Set(tree.topmost(ctx.selection.value.nodes).map((id) => tree.parentOf(id)));
177
+ const items = [{
178
+ key: "group",
179
+ label: t.makeGroup,
180
+ icon: GroupIcon,
181
+ shortcut: "mod+g",
182
+ disabled: parents.size > 1,
183
+ run: () => void ctx.groupNodes()
184
+ }];
185
+ if (ctx.isContainer(target.node)) items.push({
186
+ key: "ungroup",
187
+ label: t.ungroup,
188
+ icon: UngroupIcon,
189
+ shortcut: "mod+shift+g",
190
+ run: () => void ctx.ungroupNode(target.node.id)
191
+ });
192
+ if (tree.parentOf(target.node.id)) items.push({
193
+ key: "leave-group",
194
+ label: t.leaveGroup,
195
+ icon: UngroupIcon,
196
+ shortcut: ctx.isContainer(target.node) ? void 0 : "mod+shift+g",
197
+ run: () => void ctx.leaveGroup()
198
+ });
199
+ return items;
200
+ }
201
+ });
202
+ /**
203
+ * The editor's built-in parts as extensions: the default node type, the
204
+ * `bezier`, `step` and `straight` edge types, group nodes, stacking order,
205
+ * the context menu and the toolbar over selected nodes. Pass it along with
206
+ * your own extensions, e.g. `[flowKit(), aiNodes]`; without `extensions`
207
+ * the editor uses it alone.
208
+ */
209
+ function flowKit(options = {}) {
210
+ const { menu = true, toolbar = true, group = true, layers: layered = true } = options;
211
+ const kit = [
212
+ defineFlowExtension({
213
+ name: "default-node",
214
+ nodeTypes: [defaultNode]
215
+ }),
216
+ defineFlowExtension({
217
+ name: "default-edges",
218
+ edgeTypes: [
219
+ bezierEdge,
220
+ stepEdge,
221
+ straightEdge
222
+ ]
223
+ }),
224
+ stacking
225
+ ];
226
+ if (menu) kit.push(editMenu);
227
+ if (toolbar) kit.push(editToolbar);
228
+ if (group) kit.push(groups);
229
+ if (layered) kit.push(layers);
230
+ return kit;
231
+ }
232
+ export { flowKit };
233
+
234
+ //# sourceMappingURL=kit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kit.js","names":[],"sources":["../src/kit.ts"],"sourcesContent":["import type { ContextMenuItem } from 'dou-ui'\nimport {\n ClipboardPasteIcon,\n CopyIcon,\n CopyPlusIcon,\n EditIcon,\n GroupIcon,\n FocusIcon,\n HierarchyHorizontalIcon,\n MoreHorizontalIcon,\n ScissorsIcon,\n SquareDashedIcon,\n TrashIcon,\n UngroupIcon,\n} from '@dou-ui/icons'\nimport { defaultNode } from './components/default-node'\nimport { groupNode } from './components/group-node'\nimport { bezierEdge, stepEdge, straightEdge } from './core/edge-types'\nimport { defineFlowExtension, type FlowExtension } from './core/extension'\nimport { layers, stacking } from './layers'\n\nexport interface FlowKitOptions {\n /** The built-in context menu items: copy, paste, delete and so on. */\n menu?: boolean\n /** The toolbar over the selected nodes: duplicate, delete and more. */\n toolbar?: boolean\n /** The `group` node type, with its menu items and `mod+g` / `mod+shift+g`. */\n group?: boolean\n /**\n * Moving nodes up and down the stack: menu items and `mod+]` / `mod+[`,\n * with Shift for the very top or bottom.\n */\n layers?: boolean\n}\n\n/** Copy, paste, delete and the rest, on right click. */\nconst editMenu = defineFlowExtension({\n name: 'edit-menu',\n // Last, so extensions' own items come first.\n priority: 0,\n contextMenu(ctx, target) {\n const t = ctx.messages.value\n const editable = !ctx.readonly.value\n const items: ContextMenuItem[] = []\n if (target.kind === 'canvas') {\n if (editable)\n items.push({\n key: 'paste',\n label: t.paste,\n icon: ClipboardPasteIcon,\n shortcut: 'mod+v',\n run: () => void ctx.paste(target.point),\n })\n items.push({\n key: 'select-all',\n label: t.selectAll,\n icon: SquareDashedIcon,\n shortcut: 'mod+a',\n disabled: !ctx.doc.value.nodes.length,\n run: ctx.selectAll,\n })\n if (editable)\n items.push({\n key: 'tidy',\n label: t.tidy,\n icon: HierarchyHorizontalIcon,\n divided: true,\n disabled: !ctx.doc.value.nodes.length,\n run: () => ctx.tidy(),\n })\n items.push({\n key: 'fit',\n label: t.fit,\n icon: FocusIcon,\n divided: !editable,\n disabled: !ctx.doc.value.nodes.length,\n run: () => ctx.fit(),\n })\n return items\n }\n if (target.kind === 'node') {\n items.push({ key: 'copy', label: t.copy, icon: CopyIcon, shortcut: 'mod+c', run: ctx.copy })\n if (!editable) return items\n // The menu acts on the selection, which the node just joined if it wasn't in it.\n const selected = ctx.selection.value.nodes\n const ids = selected.includes(target.node.id) ? selected : [target.node.id]\n const locked = ids.every((id) => ctx.doc.value.nodes.find((n) => n.id === id)?.locked)\n items.push(\n {\n key: 'cut',\n label: t.cut,\n icon: ScissorsIcon,\n shortcut: 'mod+x',\n disabled: locked,\n run: ctx.cut,\n },\n {\n key: 'duplicate',\n label: t.duplicate,\n icon: CopyPlusIcon,\n shortcut: 'mod+d',\n run: ctx.duplicate,\n },\n {\n key: 'delete',\n label: t.delete,\n icon: TrashIcon,\n shortcut: 'delete',\n tone: 'danger',\n divided: true,\n disabled: locked,\n run: ctx.deleteSelection,\n },\n )\n return items\n }\n if (!editable) return items\n const edge = target.edge\n items.push(\n {\n key: 'edit-label',\n label: t.editLabel,\n icon: EditIcon,\n shortcut: 'enter',\n run: () => ctx.editLabel(edge.id),\n },\n {\n key: 'delete',\n label: t.delete,\n icon: TrashIcon,\n shortcut: 'delete',\n tone: 'danger',\n divided: true,\n run: ctx.deleteSelection,\n },\n )\n return items\n },\n})\n\n/** Duplicate, delete and the node menu, over the selected nodes; delete over selected edges. */\nconst editToolbar = defineFlowExtension({\n name: 'edit-toolbar',\n priority: 0,\n edgeToolbarItems(ctx) {\n const t = ctx.messages.value\n return [\n {\n key: 'delete',\n label: t.delete,\n icon: TrashIcon,\n shortcut: 'delete',\n run: ctx.deleteSelection,\n },\n ]\n },\n toolbarItems(ctx, nodes) {\n const t = ctx.messages.value\n // the node menu, as a right click on the first selected node opens it\n const first = nodes[0]!\n const more = ctx.menuItems({ kind: 'node', node: first, point: { x: first.x, y: first.y } })\n return [\n {\n key: 'duplicate',\n label: t.duplicate,\n icon: CopyPlusIcon,\n shortcut: 'mod+d',\n run: ctx.duplicate,\n },\n {\n key: 'delete',\n label: t.delete,\n icon: TrashIcon,\n shortcut: 'delete',\n disabled: nodes.every((node) => node.locked),\n run: ctx.deleteSelection,\n },\n ...(more.length\n ? [{ key: 'more', label: t.more, icon: MoreHorizontalIcon, children: more }]\n : []),\n ]\n },\n})\n\n/** Group nodes: the type, Ctrl / ⌘ + G to group the selection, with Shift to ungroup. */\nconst groups = defineFlowExtension({\n name: 'groups',\n priority: 0,\n nodeTypes: [groupNode],\n keymap: (ctx) => ({\n 'mod+g': () => ctx.groupNodes() !== null,\n // A group goes away; a node inside one comes out of it.\n 'mod+shift+g': () => {\n const ids = ctx.selection.value.nodes\n const containers = ids.filter((id) => {\n const node = ctx.doc.value.nodes.find((n) => n.id === id)\n return node && ctx.isContainer(node)\n })\n if (containers.length) return containers.filter((id) => ctx.ungroupNode(id)).length > 0\n return ctx.leaveGroup(ids) > 0\n },\n }),\n contextMenu(ctx, target) {\n if (target.kind !== 'node' || ctx.readonly.value) return []\n const t = ctx.messages.value\n const tree = ctx.tree.value\n const parents = new Set(tree.topmost(ctx.selection.value.nodes).map((id) => tree.parentOf(id)))\n const items: ContextMenuItem[] = [\n {\n key: 'group',\n label: t.makeGroup,\n icon: GroupIcon,\n shortcut: 'mod+g',\n // Nodes from different groups can't share a new frame.\n disabled: parents.size > 1,\n run: () => void ctx.groupNodes(),\n },\n ]\n if (ctx.isContainer(target.node))\n items.push({\n key: 'ungroup',\n label: t.ungroup,\n icon: UngroupIcon,\n shortcut: 'mod+shift+g',\n run: () => void ctx.ungroupNode(target.node.id),\n })\n // A group inside another can be ungrouped or taken out; the shortcut ungroups.\n if (tree.parentOf(target.node.id))\n items.push({\n key: 'leave-group',\n label: t.leaveGroup,\n icon: UngroupIcon,\n shortcut: ctx.isContainer(target.node) ? undefined : 'mod+shift+g',\n run: () => void ctx.leaveGroup(),\n })\n return items\n },\n})\n\n/**\n * The editor's built-in parts as extensions: the default node type, the\n * `bezier`, `step` and `straight` edge types, group nodes, stacking order,\n * the context menu and the toolbar over selected nodes. Pass it along with\n * your own extensions, e.g. `[flowKit(), aiNodes]`; without `extensions`\n * the editor uses it alone.\n */\nexport function flowKit(options: FlowKitOptions = {}): FlowExtension[] {\n const { menu = true, toolbar = true, group = true, layers: layered = true } = options\n const kit = [\n defineFlowExtension({ name: 'default-node', nodeTypes: [defaultNode] }),\n defineFlowExtension({ name: 'default-edges', edgeTypes: [bezierEdge, stepEdge, straightEdge] }),\n stacking,\n ]\n if (menu) kit.push(editMenu)\n if (toolbar) kit.push(editToolbar)\n if (group) kit.push(groups)\n if (layered) kit.push(layers)\n return kit\n}\n"],"mappings":"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"}
package/dist/layers.js ADDED
@@ -0,0 +1,150 @@
1
+ import { intersects } from "./core/geometry.js";
2
+ import { defineFlowExtension } from "./core/extension.js";
3
+ import { ChevronDownIcon, ChevronUpIcon, ChevronsDownIcon, ChevronsUpIcon } from "@dou-ui/icons";
4
+ // src/layers.ts
5
+ /** The nodes that stack, bottom first: what the editor draws in that order. */
6
+ function stack(ctx) {
7
+ const nodes = ctx.doc.value.nodes.filter((node) => !ctx.isContainer(node));
8
+ const index = new Map(nodes.map((node, i) => [node.id, i]));
9
+ return nodes.sort((a, b) => (a.z ?? 0) - (b.z ?? 0) || index.get(a.id) - index.get(b.id));
10
+ }
11
+ /**
12
+ * The selected nodes moved in the stack: to the top or bottom of everything,
13
+ * or one step past the nearest node each overlaps, so the step can be seen.
14
+ * Returns the `z` of every node whose place changed, numbering the stack
15
+ * from 0 at the bottom; nothing when nothing would change.
16
+ */
17
+ function layerChanges(ctx, move) {
18
+ const selected = new Set(ctx.selection.value.nodes);
19
+ const order = stack(ctx);
20
+ const moving = order.filter((node) => selected.has(node.id));
21
+ const others = order.filter((node) => !selected.has(node.id));
22
+ let next;
23
+ if (move === "front") next = [...others, ...moving];
24
+ else if (move === "back") next = [...moving, ...others];
25
+ else {
26
+ const up = move === "forward";
27
+ next = [...order];
28
+ const rect = (node) => ctx.getNodeRect(node.id);
29
+ for (let k = 0; k < moving.length; k++) {
30
+ const node = moving[up ? moving.length - 1 - k : k];
31
+ const at = next.indexOf(node);
32
+ const box = rect(node);
33
+ let past;
34
+ for (let i = up ? at + 1 : at - 1; i >= 0 && i < next.length; i += up ? 1 : -1) {
35
+ const other = next[i];
36
+ const r = rect(other);
37
+ if (!selected.has(other.id) && box && r && intersects(box, r)) {
38
+ past = other;
39
+ break;
40
+ }
41
+ }
42
+ if (!past) continue;
43
+ next.splice(at, 1);
44
+ next.splice(next.indexOf(past) + (up ? 1 : 0), 0, node);
45
+ }
46
+ }
47
+ const out = /* @__PURE__ */ new Map();
48
+ if (next.every((node, i) => node === order[i])) return out;
49
+ next.forEach((node, i) => {
50
+ if ((node.z ?? 0) !== i) out.set(node.id, i);
51
+ });
52
+ return out;
53
+ }
54
+ /**
55
+ * Moves the selected nodes in the stack, as one undo step, and says so to
56
+ * screen readers. Returns `false` when nothing moved, e.g. when they already
57
+ * are at the top; that is said too, unless `announce` is `false`.
58
+ */
59
+ function moveLayer(ctx, move, options = {}) {
60
+ const t = ctx.messages.value.layers;
61
+ const changes = layerChanges(ctx, move);
62
+ const say = (text) => options.announce !== false && ctx.announce(text);
63
+ if (!changes.size) {
64
+ if (ctx.selection.value.nodes.length) say({
65
+ front: t.top,
66
+ back: t.bottom,
67
+ forward: atEnd(ctx, "forward") ? t.top : t.noneAbove,
68
+ backward: atEnd(ctx, "backward") ? t.bottom : t.noneBelow
69
+ }[move]);
70
+ return false;
71
+ }
72
+ ctx.transact((tr) => {
73
+ for (const [id, z] of changes) tr.updateNode(id, { z });
74
+ });
75
+ say(t[move]);
76
+ return true;
77
+ }
78
+ /** Whether the selected nodes already are at the top (or bottom) of the whole stack. */
79
+ function atEnd(ctx, way) {
80
+ return !layerChanges(ctx, way === "forward" ? "front" : "back").size;
81
+ }
82
+ var LAYER_KEYS = [
83
+ [
84
+ "front",
85
+ "mod+shift+]",
86
+ ChevronsUpIcon
87
+ ],
88
+ [
89
+ "forward",
90
+ "mod+]",
91
+ ChevronUpIcon
92
+ ],
93
+ [
94
+ "backward",
95
+ "mod+[",
96
+ ChevronDownIcon
97
+ ],
98
+ [
99
+ "back",
100
+ "mod+shift+[",
101
+ ChevronsDownIcon
102
+ ]
103
+ ];
104
+ /**
105
+ * Stacking order: what is added lands on top, also once nodes have been
106
+ * moved in the stack.
107
+ */
108
+ var stacking = defineFlowExtension({
109
+ name: "stacking",
110
+ priority: 0,
111
+ transaction(tr) {
112
+ const ids = /* @__PURE__ */ new Set();
113
+ for (const step of tr.steps) if (step.type === "addNode" && step.node.z === void 0) ids.add(step.node.id);
114
+ if (!ids.size) return;
115
+ let top = 0;
116
+ for (const node of tr.doc.nodes) if (!ids.has(node.id)) top = Math.max(top, node.z ?? 0);
117
+ if (!top) return;
118
+ for (const id of ids) tr.updateNode(id, { z: ++top });
119
+ }
120
+ });
121
+ /** Moving nodes up and down the stack from the node menu and with Ctrl / ⌘ + [ and ]. */
122
+ var layers = defineFlowExtension({
123
+ name: "layers",
124
+ priority: 0,
125
+ contextMenu(ctx, target) {
126
+ if (target.kind !== "node" || ctx.readonly.value) return [];
127
+ const t = ctx.messages.value.layers;
128
+ return LAYER_KEYS.map(([move, shortcut, icon], i) => ({
129
+ key: `layer-${move}`,
130
+ label: t[move],
131
+ icon,
132
+ shortcut,
133
+ divided: i === 0,
134
+ disabled: !layerChanges(ctx, move).size,
135
+ run: () => void moveLayer(ctx, move)
136
+ }));
137
+ },
138
+ keymap(ctx) {
139
+ const keys = {};
140
+ const order = [...LAYER_KEYS.filter(([, key]) => key.includes("shift")), ...LAYER_KEYS];
141
+ for (const [move, key] of order) if (!keys[key]) keys[key] = () => {
142
+ if (ctx.readonly.value || !ctx.selection.value.nodes.length) return false;
143
+ moveLayer(ctx, move);
144
+ };
145
+ return keys;
146
+ }
147
+ });
148
+ export { layerChanges, layers, moveLayer, stacking };
149
+
150
+ //# sourceMappingURL=layers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layers.js","names":[],"sources":["../src/layers.ts"],"sourcesContent":["import type { ContextMenuItem } from 'dou-ui'\nimport { ChevronDownIcon, ChevronsDownIcon, ChevronsUpIcon, ChevronUpIcon } from '@dou-ui/icons'\nimport type { FlowEditorContext } from './context'\nimport { defineFlowExtension } from './core/extension'\nimport { intersects } from './core/geometry'\nimport type { FlowNode } from './core/model'\n\nexport type LayerMove = 'front' | 'forward' | 'backward' | 'back'\n\n/** The nodes that stack, bottom first: what the editor draws in that order. */\nfunction stack(ctx: FlowEditorContext): FlowNode[] {\n const nodes = ctx.doc.value.nodes.filter((node) => !ctx.isContainer(node))\n const index = new Map(nodes.map((node, i) => [node.id, i]))\n // oxlint-disable-next-line unicorn/no-array-sort -- sorts a fresh array\n return nodes.sort((a, b) => (a.z ?? 0) - (b.z ?? 0) || index.get(a.id)! - index.get(b.id)!)\n}\n\n/**\n * The selected nodes moved in the stack: to the top or bottom of everything,\n * or one step past the nearest node each overlaps, so the step can be seen.\n * Returns the `z` of every node whose place changed, numbering the stack\n * from 0 at the bottom; nothing when nothing would change.\n */\nexport function layerChanges(ctx: FlowEditorContext, move: LayerMove): Map<string, number> {\n const selected = new Set(ctx.selection.value.nodes)\n const order = stack(ctx)\n const moving = order.filter((node) => selected.has(node.id))\n const others = order.filter((node) => !selected.has(node.id))\n let next: FlowNode[]\n if (move === 'front') next = [...others, ...moving]\n else if (move === 'back') next = [...moving, ...others]\n else {\n const up = move === 'forward'\n next = [...order]\n const rect = (node: FlowNode) => ctx.getNodeRect(node.id)\n // from the end it moves towards, so the moved nodes don't pass each other\n for (let k = 0; k < moving.length; k++) {\n const node = moving[up ? moving.length - 1 - k : k]!\n const at = next.indexOf(node)\n const box = rect(node)\n // the nearest unselected node it overlaps, walking the way it moves\n let past: FlowNode | undefined\n for (let i = up ? at + 1 : at - 1; i >= 0 && i < next.length; i += up ? 1 : -1) {\n const other = next[i]!\n const r = rect(other)\n if (!selected.has(other.id) && box && r && intersects(box, r)) {\n past = other\n break\n }\n }\n if (!past) continue\n next.splice(at, 1)\n next.splice(next.indexOf(past) + (up ? 1 : 0), 0, node)\n }\n }\n const out = new Map<string, number>()\n if (next.every((node, i) => node === order[i])) return out\n next.forEach((node, i) => {\n if ((node.z ?? 0) !== i) out.set(node.id, i)\n })\n return out\n}\n\n/**\n * Moves the selected nodes in the stack, as one undo step, and says so to\n * screen readers. Returns `false` when nothing moved, e.g. when they already\n * are at the top; that is said too, unless `announce` is `false`.\n */\nexport function moveLayer(\n ctx: FlowEditorContext,\n move: LayerMove,\n options: { announce?: boolean } = {},\n): boolean {\n const t = ctx.messages.value.layers\n const changes = layerChanges(ctx, move)\n const say = (text: string) => options.announce !== false && ctx.announce(text)\n if (!changes.size) {\n if (ctx.selection.value.nodes.length)\n say(\n {\n front: t.top,\n back: t.bottom,\n forward: atEnd(ctx, 'forward') ? t.top : t.noneAbove,\n backward: atEnd(ctx, 'backward') ? t.bottom : t.noneBelow,\n }[move],\n )\n return false\n }\n ctx.transact((tr) => {\n for (const [id, z] of changes) tr.updateNode(id, { z })\n })\n say(t[move])\n return true\n}\n\n/** Whether the selected nodes already are at the top (or bottom) of the whole stack. */\nfunction atEnd(ctx: FlowEditorContext, way: 'forward' | 'backward') {\n return !layerChanges(ctx, way === 'forward' ? 'front' : 'back').size\n}\n\nconst LAYER_KEYS: [LayerMove, string, typeof ChevronsUpIcon][] = [\n ['front', 'mod+shift+]', ChevronsUpIcon],\n ['forward', 'mod+]', ChevronUpIcon],\n ['backward', 'mod+[', ChevronDownIcon],\n ['back', 'mod+shift+[', ChevronsDownIcon],\n]\n\n/**\n * Stacking order: what is added lands on top, also once nodes have been\n * moved in the stack.\n */\nexport const stacking = defineFlowExtension({\n name: 'stacking',\n priority: 0,\n transaction(tr) {\n const ids = new Set<string>()\n for (const step of tr.steps)\n if (step.type === 'addNode' && step.node.z === undefined) ids.add(step.node.id)\n if (!ids.size) return\n let top = 0\n for (const node of tr.doc.nodes) if (!ids.has(node.id)) top = Math.max(top, node.z ?? 0)\n if (!top) return\n for (const id of ids) tr.updateNode(id, { z: ++top })\n },\n})\n\n/** Moving nodes up and down the stack from the node menu and with Ctrl / ⌘ + [ and ]. */\nexport const layers = defineFlowExtension({\n name: 'layers',\n priority: 0,\n contextMenu(ctx, target) {\n if (target.kind !== 'node' || ctx.readonly.value) return []\n const t = ctx.messages.value.layers\n return LAYER_KEYS.map(([move, shortcut, icon], i): ContextMenuItem => ({\n key: `layer-${move}`,\n label: t[move],\n icon,\n shortcut,\n divided: i === 0,\n disabled: !layerChanges(ctx, move).size,\n run: () => void moveLayer(ctx, move),\n }))\n },\n keymap(ctx) {\n const keys: Record<string, () => boolean | void> = {}\n // with Shift first: without it, `mod+[` would match either\n const order = [...LAYER_KEYS.filter(([, key]) => key.includes('shift')), ...LAYER_KEYS]\n for (const [move, key] of order)\n if (!keys[key])\n keys[key] = () => {\n if (ctx.readonly.value || !ctx.selection.value.nodes.length) return false\n moveLayer(ctx, move)\n }\n return keys\n },\n})\n"],"mappings":"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"}