@meltemi/diagrams-editor 1.9.0 → 1.10.17

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 (154) hide show
  1. package/dist/add-icons.d.ts +44 -0
  2. package/dist/add-icons.d.ts.map +1 -0
  3. package/dist/add-icons.js +178 -0
  4. package/dist/add-icons.js.map +1 -0
  5. package/dist/arrange.d.ts +54 -1
  6. package/dist/arrange.d.ts.map +1 -1
  7. package/dist/arrange.js +209 -8
  8. package/dist/arrange.js.map +1 -1
  9. package/dist/asset-files.d.ts +46 -0
  10. package/dist/asset-files.d.ts.map +1 -0
  11. package/dist/asset-files.js +79 -0
  12. package/dist/asset-files.js.map +1 -0
  13. package/dist/c4.d.ts +91 -1
  14. package/dist/c4.d.ts.map +1 -1
  15. package/dist/c4.js +358 -9
  16. package/dist/c4.js.map +1 -1
  17. package/dist/canvas/index.d.ts +1 -0
  18. package/dist/canvas/index.d.ts.map +1 -1
  19. package/dist/canvas/index.js +1 -0
  20. package/dist/canvas/index.js.map +1 -1
  21. package/dist/canvas/keyboard.d.ts +23 -2
  22. package/dist/canvas/keyboard.d.ts.map +1 -1
  23. package/dist/canvas/keyboard.js +23 -0
  24. package/dist/canvas/keyboard.js.map +1 -1
  25. package/dist/canvas/palette.d.ts +48 -6
  26. package/dist/canvas/palette.d.ts.map +1 -1
  27. package/dist/canvas/palette.js +55 -9
  28. package/dist/canvas/palette.js.map +1 -1
  29. package/dist/canvas/pens.d.ts +10 -0
  30. package/dist/canvas/pens.d.ts.map +1 -0
  31. package/dist/canvas/pens.js +29 -0
  32. package/dist/canvas/pens.js.map +1 -0
  33. package/dist/canvas/protocol.d.ts +580 -21
  34. package/dist/canvas/protocol.d.ts.map +1 -1
  35. package/dist/canvas/protocol.js +140 -3
  36. package/dist/canvas/protocol.js.map +1 -1
  37. package/dist/canvas/routes.d.ts +17 -0
  38. package/dist/canvas/routes.d.ts.map +1 -1
  39. package/dist/canvas/routes.js +37 -0
  40. package/dist/canvas/routes.js.map +1 -1
  41. package/dist/canvas/turning.d.ts +7 -0
  42. package/dist/canvas/turning.d.ts.map +1 -1
  43. package/dist/canvas/turning.js +17 -3
  44. package/dist/canvas/turning.js.map +1 -1
  45. package/dist/catalog.d.ts +5 -0
  46. package/dist/catalog.d.ts.map +1 -1
  47. package/dist/catalog.js +1 -1
  48. package/dist/catalog.js.map +1 -1
  49. package/dist/clipboard.d.ts.map +1 -1
  50. package/dist/clipboard.js +98 -9
  51. package/dist/clipboard.js.map +1 -1
  52. package/dist/effects.d.ts +5 -0
  53. package/dist/effects.d.ts.map +1 -1
  54. package/dist/effects.js +31 -22
  55. package/dist/effects.js.map +1 -1
  56. package/dist/exports.d.ts +25 -11
  57. package/dist/exports.d.ts.map +1 -1
  58. package/dist/exports.js +65 -28
  59. package/dist/exports.js.map +1 -1
  60. package/dist/fonts.d.ts +63 -0
  61. package/dist/fonts.d.ts.map +1 -0
  62. package/dist/fonts.js +175 -0
  63. package/dist/fonts.js.map +1 -0
  64. package/dist/icons.d.ts +2 -0
  65. package/dist/icons.d.ts.map +1 -1
  66. package/dist/icons.js +39 -6
  67. package/dist/icons.js.map +1 -1
  68. package/dist/index.d.ts +6 -3
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +4 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/inspector.d.ts.map +1 -1
  73. package/dist/inspector.js +545 -141
  74. package/dist/inspector.js.map +1 -1
  75. package/dist/layouts.d.ts +3 -2
  76. package/dist/layouts.d.ts.map +1 -1
  77. package/dist/layouts.js +4 -2
  78. package/dist/layouts.js.map +1 -1
  79. package/dist/messages/en.d.ts +106 -20
  80. package/dist/messages/en.d.ts.map +1 -1
  81. package/dist/messages/en.js +110 -26
  82. package/dist/messages/en.js.map +1 -1
  83. package/dist/messages/es.d.ts.map +1 -1
  84. package/dist/messages/es.js +80 -43
  85. package/dist/messages/es.js.map +1 -1
  86. package/dist/messages/index.d.ts +76 -17
  87. package/dist/messages/index.d.ts.map +1 -1
  88. package/dist/messages/keys.d.ts.map +1 -1
  89. package/dist/messages/keys.js +26 -0
  90. package/dist/messages/keys.js.map +1 -1
  91. package/dist/messages/services.d.ts +130 -1
  92. package/dist/messages/services.d.ts.map +1 -1
  93. package/dist/messages/services.js +150 -18
  94. package/dist/messages/services.js.map +1 -1
  95. package/dist/move-file.d.ts +32 -0
  96. package/dist/move-file.d.ts.map +1 -0
  97. package/dist/move-file.js +58 -0
  98. package/dist/move-file.js.map +1 -0
  99. package/dist/node.d.ts +1 -1
  100. package/dist/node.d.ts.map +1 -1
  101. package/dist/node.js.map +1 -1
  102. package/dist/projects.d.ts +65 -1
  103. package/dist/projects.d.ts.map +1 -1
  104. package/dist/projects.js +349 -1
  105. package/dist/projects.js.map +1 -1
  106. package/dist/render.d.ts +5 -0
  107. package/dist/render.d.ts.map +1 -1
  108. package/dist/render.js +4 -2
  109. package/dist/render.js.map +1 -1
  110. package/dist/sequence.d.ts +37 -8
  111. package/dist/sequence.d.ts.map +1 -1
  112. package/dist/sequence.js +409 -38
  113. package/dist/sequence.js.map +1 -1
  114. package/dist/services/actions.d.ts.map +1 -1
  115. package/dist/services/actions.js +65 -1
  116. package/dist/services/actions.js.map +1 -1
  117. package/dist/services/completion.d.ts.map +1 -1
  118. package/dist/services/completion.js +146 -16
  119. package/dist/services/completion.js.map +1 -1
  120. package/dist/services/docs.d.ts +5 -0
  121. package/dist/services/docs.d.ts.map +1 -1
  122. package/dist/services/docs.js +7 -0
  123. package/dist/services/docs.js.map +1 -1
  124. package/dist/services/hover.d.ts +5 -0
  125. package/dist/services/hover.d.ts.map +1 -1
  126. package/dist/services/hover.js +154 -21
  127. package/dist/services/hover.js.map +1 -1
  128. package/dist/services/navigation.d.ts +1 -1
  129. package/dist/services/navigation.d.ts.map +1 -1
  130. package/dist/services/navigation.js +8 -4
  131. package/dist/services/navigation.js.map +1 -1
  132. package/dist/services/stories.d.ts.map +1 -1
  133. package/dist/services/stories.js +31 -3
  134. package/dist/services/stories.js.map +1 -1
  135. package/dist/session.d.ts +121 -13
  136. package/dist/session.d.ts.map +1 -1
  137. package/dist/session.js +1349 -80
  138. package/dist/session.js.map +1 -1
  139. package/dist/syntax.d.ts.map +1 -1
  140. package/dist/syntax.js +3 -0
  141. package/dist/syntax.js.map +1 -1
  142. package/dist/targets.d.ts +25 -4
  143. package/dist/targets.d.ts.map +1 -1
  144. package/dist/targets.js +103 -7
  145. package/dist/targets.js.map +1 -1
  146. package/dist/text-places.d.ts +15 -3
  147. package/dist/text-places.d.ts.map +1 -1
  148. package/dist/text-places.js +187 -12
  149. package/dist/text-places.js.map +1 -1
  150. package/dist/themes.d.ts +0 -2
  151. package/dist/themes.d.ts.map +1 -1
  152. package/dist/themes.js +27 -13
  153. package/dist/themes.js.map +1 -1
  154. package/package.json +16 -16
@@ -0,0 +1,44 @@
1
+ import { type IconRegistry } from "@meltemi/diagrams-assets";
2
+ import type { FlowDiagram } from "@meltemi/diagrams-model";
3
+ import type { AddedIconInfo, IconFileCheck, IconFileInput, IconPrefixCheck } from "./canvas/protocol.js";
4
+ import type { AssetSteps, ProjectStep } from "./projects.js";
5
+ /** The prefix the Add icon dialog offers first. */
6
+ export declare const DEFAULT_ICON_PREFIX = "project";
7
+ /**
8
+ * What the Add icon dialog may do with a prefix: put the icons in a new pack, or in a pack of the
9
+ * project read from a folder; never in a built-in pack, a plugin's, an Iconify file of the
10
+ * project (the dialog writes SVG files) or an alias of `project.json`.
11
+ */
12
+ export declare function checkIconPrefix(registry: IconRegistry | undefined, prefix: string): IconPrefixCheck;
13
+ /**
14
+ * Each file of the Add icon dialog as the dialog shows it: the name it gets (the one asked for, or
15
+ * one made of the file's name and free in the pack), a preview through the sanitiser, and what
16
+ * keeps it from being added: an SVG the sanitiser refuses, a name a reference cannot write, a name
17
+ * the pack or an earlier file has.
18
+ */
19
+ export declare function checkIconFiles(registry: IconRegistry | undefined, prefix: string, files: readonly IconFileInput[]): IconFileCheck[];
20
+ /** What `addIcons` gives: the icons added, the files refused, and what to write. */
21
+ export interface AddedIcons {
22
+ readonly added: readonly AddedIconInfo[];
23
+ readonly refused: readonly {
24
+ readonly file: string;
25
+ readonly reason: string;
26
+ }[];
27
+ /** The files of the assets, and the statements that give the first icon to the targets. */
28
+ readonly assets: AssetSteps;
29
+ readonly steps: readonly ProjectStep[];
30
+ }
31
+ /**
32
+ * The files and statements that add icons to the project: one `assets/icons/<prefix>/<name>.svg`
33
+ * per file that can be added, the pack's licence in `assets/licenses.json` when it has none, an
34
+ * item per icon in the project's library (`assets/libraries/project.json`, a category per
35
+ * prefix), and `style <id> { icon }` of the first icon on the targets that take one. A prefix the
36
+ * icons cannot go into, or a licence missing or malformed, refuses every file.
37
+ */
38
+ export declare function addIcons(registry: IconRegistry | undefined, diagram: FlowDiagram | undefined, request: {
39
+ readonly prefix: string;
40
+ readonly licence?: string;
41
+ readonly files: readonly IconFileInput[];
42
+ readonly targets: readonly string[];
43
+ }): AddedIcons;
44
+ //# sourceMappingURL=add-icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-icons.d.ts","sourceRoot":"","sources":["../src/add-icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAQ3D,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,aAAa,EACb,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7D,mDAAmD;AACnD,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAU7C;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,YAAY,GAAG,SAAS,EAClC,MAAM,EAAE,MAAM,GACb,eAAe,CAoBjB;AAQD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,GAAG,SAAS,EAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,aAAa,EAAE,GAC9B,aAAa,EAAE,CAkCjB;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChF,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;CACxC;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,YAAY,GAAG,SAAS,EAClC,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,OAAO,EAAE;IACP,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,GACA,UAAU,CAyEZ"}
@@ -0,0 +1,178 @@
1
+ import { PACK_PREFIX, geometrySvg, humanise, isIconName, sanitizeSvg, slugifyIconName, } from "@meltemi/diagrams-assets";
2
+ import { ICONS_FOLDER, LICENSES_FILE, PROJECT_LIBRARY_FILE, iconFilePath, } from "@meltemi/diagrams-project";
3
+ import { libraryCategoryId } from "./asset-files.js";
4
+ import { takesIcon } from "./icons.js";
5
+ import { messages } from "./messages/index.js";
6
+ /** The prefix the Add icon dialog offers first. */
7
+ export const DEFAULT_ICON_PREFIX = "project";
8
+ /** What a licence may be written as: an SPDX identifier or a `LicenseRef-` name. */
9
+ const LICENCE = /^(?:LicenseRef-[A-Za-z0-9.-]+|[A-Za-z0-9][A-Za-z0-9.+-]*)$/;
10
+ /** Whether a pack is one of the project's own, read from a folder or a file under `assets/icons`. */
11
+ function projectPack(pack) {
12
+ return pack.metadata.source.startsWith(`${ICONS_FOLDER}/`);
13
+ }
14
+ /**
15
+ * What the Add icon dialog may do with a prefix: put the icons in a new pack, or in a pack of the
16
+ * project read from a folder; never in a built-in pack, a plugin's, an Iconify file of the
17
+ * project (the dialog writes SVG files) or an alias of `project.json`.
18
+ */
19
+ export function checkIconPrefix(registry, prefix) {
20
+ const words = messages().addIcons;
21
+ const fail = (problem) => ({
22
+ prefix,
23
+ problem,
24
+ existing: false,
25
+ licensed: false,
26
+ });
27
+ if (prefix === "")
28
+ return fail(words.prefixEmpty);
29
+ if (!PACK_PREFIX.test(prefix))
30
+ return fail(words.prefixInvalid(prefix));
31
+ const alias = registry?.aliasList()[prefix];
32
+ if (alias !== undefined)
33
+ return fail(words.prefixAlias(prefix, alias));
34
+ const pack = registry?.list().find((p) => p.prefix === prefix);
35
+ if (!pack)
36
+ return { prefix, existing: false, licensed: false };
37
+ if (pack.metadata.source === "built-in")
38
+ return fail(words.prefixBuiltIn(prefix));
39
+ if (!projectPack(pack))
40
+ return fail(words.prefixPlugin(prefix));
41
+ if (pack.metadata.source.endsWith(".json")) {
42
+ return fail(words.prefixIconify(prefix, pack.metadata.source));
43
+ }
44
+ return { prefix, existing: true, licensed: pack.metadata.license !== null };
45
+ }
46
+ /** The names a pack has, lower case: a file system may not tell `Logo.svg` from `logo.svg`. */
47
+ function takenNames(registry, prefix) {
48
+ const pack = registry?.list().find((p) => p.prefix === prefix);
49
+ return new Set((pack?.names() ?? []).map((n) => n.toLowerCase()));
50
+ }
51
+ /**
52
+ * Each file of the Add icon dialog as the dialog shows it: the name it gets (the one asked for, or
53
+ * one made of the file's name and free in the pack), a preview through the sanitiser, and what
54
+ * keeps it from being added: an SVG the sanitiser refuses, a name a reference cannot write, a name
55
+ * the pack or an earlier file has.
56
+ */
57
+ export function checkIconFiles(registry, prefix, files) {
58
+ const words = messages().addIcons;
59
+ const taken = takenNames(registry, prefix);
60
+ const used = new Set();
61
+ return files.map((file) => {
62
+ let name = file.name?.trim() ?? "";
63
+ let problem;
64
+ if (file.name === undefined) {
65
+ // A name is offered: the file's own, made writable, then `-2`, `-3`… while it is taken.
66
+ const slug = slugifyIconName(file.file);
67
+ name = slug;
68
+ for (let n = 2; slug !== "" && (taken.has(name.toLowerCase()) || used.has(name.toLowerCase())); n++) {
69
+ name = `${slug}-${n}`;
70
+ }
71
+ }
72
+ if (name === "")
73
+ problem = words.nameEmpty;
74
+ else if (!isIconName(name))
75
+ problem = words.nameInvalid(name);
76
+ else if (taken.has(name.toLowerCase()))
77
+ problem = words.nameTaken(`${prefix}:${name}`);
78
+ else if (used.has(name.toLowerCase()))
79
+ problem = words.nameTwice(name);
80
+ if (name !== "")
81
+ used.add(name.toLowerCase());
82
+ let svg = null;
83
+ if (!/<svg[\s>]/i.test(file.svg)) {
84
+ problem = words.notSvg;
85
+ }
86
+ else {
87
+ const result = sanitizeSvg(file.svg);
88
+ if (result.ok)
89
+ svg = geometrySvg(result.icon, 48, 48);
90
+ else
91
+ problem = words.unsafe(result.problem.message);
92
+ }
93
+ return { file: file.file, name, svg, ...(problem !== undefined ? { problem } : {}) };
94
+ });
95
+ }
96
+ /**
97
+ * The files and statements that add icons to the project: one `assets/icons/<prefix>/<name>.svg`
98
+ * per file that can be added, the pack's licence in `assets/licenses.json` when it has none, an
99
+ * item per icon in the project's library (`assets/libraries/project.json`, a category per
100
+ * prefix), and `style <id> { icon }` of the first icon on the targets that take one. A prefix the
101
+ * icons cannot go into, or a licence missing or malformed, refuses every file.
102
+ */
103
+ export function addIcons(registry, diagram, request) {
104
+ const words = messages().addIcons;
105
+ const none = { create: [], json: [] };
106
+ const refuseAll = (reason) => ({
107
+ added: [],
108
+ refused: request.files.map((f) => ({ file: f.file, reason })),
109
+ assets: none,
110
+ steps: [],
111
+ });
112
+ const prefix = checkIconPrefix(registry, request.prefix);
113
+ if (prefix.problem !== undefined)
114
+ return refuseAll(prefix.problem);
115
+ const licence = request.licence?.trim() ?? "";
116
+ if (!prefix.licensed) {
117
+ if (licence === "")
118
+ return refuseAll(words.licenceMissing);
119
+ if (!LICENCE.test(licence))
120
+ return refuseAll(words.licenceInvalid(licence));
121
+ }
122
+ const checks = checkIconFiles(registry, request.prefix, request.files.map((f) => ({ ...f, name: f.name ?? slugifyIconName(f.file) })));
123
+ const added = [];
124
+ const refused = [];
125
+ const create = [];
126
+ checks.forEach((check, i) => {
127
+ if (check.problem !== undefined) {
128
+ refused.push({ file: check.file, reason: check.problem });
129
+ return;
130
+ }
131
+ const reference = `${request.prefix}:${check.name}`;
132
+ create.push({ path: iconFilePath(request.prefix, check.name), text: request.files[i].svg });
133
+ const icon = sanitizeSvg(request.files[i].svg);
134
+ added.push({
135
+ file: check.file,
136
+ reference,
137
+ label: humanise(check.name),
138
+ svg: icon.ok ? geometrySvg(icon.icon, 24, 24) : null,
139
+ });
140
+ });
141
+ if (added.length === 0)
142
+ return { added, refused, assets: none, steps: [] };
143
+ const json = [];
144
+ if (!prefix.licensed) {
145
+ json.push({
146
+ path: LICENSES_FILE,
147
+ change: { kind: "licence", prefix: request.prefix, licence },
148
+ });
149
+ }
150
+ json.push({
151
+ path: PROJECT_LIBRARY_FILE,
152
+ change: {
153
+ kind: "libraryItems",
154
+ category: libraryCategoryId(request.prefix),
155
+ title: request.prefix,
156
+ items: added.map((icon) => ({ icon: icon.reference, label: icon.label })),
157
+ },
158
+ });
159
+ const steps = [];
160
+ if (diagram) {
161
+ for (const target of request.targets) {
162
+ const element = diagram.elementsById.get(target);
163
+ if (!element || !takesIcon(diagram, element))
164
+ continue;
165
+ const operation = {
166
+ kind: "setStyleProperty",
167
+ diagram: diagram.id,
168
+ target,
169
+ targetKind: "element",
170
+ property: "icon",
171
+ value: added[0].reference,
172
+ };
173
+ steps.push({ file: null, operation });
174
+ }
175
+ }
176
+ return { added, refused, assets: { create, json }, steps };
177
+ }
178
+ //# sourceMappingURL=add-icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-icons.js","sourceRoot":"","sources":["../src/add-icons.ts"],"names":[],"mappings":"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"}
package/dist/arrange.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { EditOperation } from "@meltemi/diagrams-edit";
2
- import { type Point } from "@meltemi/diagrams-model";
2
+ import { type Element, type FlowDiagram, type Point } from "@meltemi/diagrams-model";
3
3
  import { type DiagramView, type DocumentAnalysis } from "./analysis.js";
4
4
  /**
5
5
  * The interior origin of a group of a free diagram, which its children's places are measured
@@ -8,6 +8,20 @@ import { type DiagramView, type DocumentAnalysis } from "./analysis.js";
8
8
  * places are in diagram coordinates.
9
9
  */
10
10
  export declare function interiorOf(view: DiagramView, group: string | null): Point;
11
+ /** Whether an element keeps its points in its statement: a free line or a pen stroke. */
12
+ export declare function keepsPoints(element: Element): boolean;
13
+ /**
14
+ * The list group (`layout column` or `layout row`) that places an element of a free diagram: its
15
+ * group when that group is a list, which puts its children one after another and takes no
16
+ * `place` for them. Undefined for any other element, and for lines and pens, which keep their
17
+ * points in a list as in any group.
18
+ */
19
+ export declare function placingList(diagram: FlowDiagram, element: Element): string | undefined;
20
+ /**
21
+ * Whether alignment and distribution move an element: not a group, a line or a pen, which have no
22
+ * edges to line up, nor a child of a list, which its list places.
23
+ */
24
+ export declare function alignable(diagram: FlowDiagram, element: Element): boolean;
11
25
  /**
12
26
  * The `convertToContainer` operation for a flow node or a free box, with the elements drawn
13
27
  * stacked on it as its children: siblings declared after it on its layer whose box lies inside
@@ -39,6 +53,45 @@ export declare function stackedAfterMove(view: DiagramView, ids: readonly string
39
53
  * lands where it was dropped and the other children stay.
40
54
  */
41
55
  export declare function steadyGroups(view: DiagramView, leaving: readonly string[], target: string | null): EditOperation[];
56
+ /**
57
+ * The group a stroke through `points` (diagram coordinates) of `width` belongs to, from `start`
58
+ * (the innermost group under its first point, or the group it is in) outwards: the first that is
59
+ * not a list and whose drawn box holds the whole stroke, so that a stroke never grows a list nor
60
+ * moves the children it places; the top level (null) when none does. `start` as it is when it is
61
+ * no group of a drawn free diagram, which the edit judges.
62
+ */
63
+ export declare function strokeParent(view: DiagramView, start: string | null, points: readonly Point[], width: number): string | null;
64
+ /**
65
+ * The `setSize` that keeps a plain group of a free diagram drawn as it is while a stroke goes into
66
+ * it or moves in it: a group without `size` derives its size from what it holds and grows about
67
+ * its centre, which moves its interior and every child placed in it. The size is written as drawn,
68
+ * unrounded, so that the interior stays where it is to the hundredth. Nothing for the top level,
69
+ * a list (which grows with its children) or a group with a size.
70
+ */
71
+ export declare function steadySize(view: DiagramView, group: string | null): EditOperation[];
72
+ /**
73
+ * The operations that draw the pen `element` through `points`, in diagram coordinates, as a drag
74
+ * or a scale of its stroke leaves it: its points in its group's interior. A pen in a list, which
75
+ * would grow the list and move the children it places, goes out first to the nearest group around
76
+ * the list that is not a list and holds the stroke (`strokeParent`), or to the top level, so that
77
+ * it lands where it is dropped. `parent` is the group it ends in, which the caller keeps steady
78
+ * (`steadySize`).
79
+ */
80
+ export declare function penOperations(view: DiagramView, element: Element, points: readonly Point[]): {
81
+ readonly operations: EditOperation[];
82
+ readonly parent: string | null;
83
+ };
84
+ /**
85
+ * The operations that keep what the list group `list` holds drawn where it is once the list no
86
+ * longer places it, in the interior of `into`: the list itself when its layout goes, its parent
87
+ * when it is ungrouped (null: the top level). Each child the list places gets its `place` at its
88
+ * drawn centre, and the size it is drawn with when the list stretches it; when the list stays a
89
+ * group, a written size, which was its least size, becomes the size it is drawn with. Lines and
90
+ * pens that leave the list get their drawn points in the new interior. Into another list, which
91
+ * places them in order, the children get no place; nor in an `auto` diagram, whose engine places
92
+ * them, and which a place would make `assisted`.
93
+ */
94
+ export declare function unlistedOperations(view: DiagramView, list: string, into: string | null): EditOperation[];
42
95
  /**
43
96
  * The `arrange` operation that writes what ELK draws: the unplaced elements around the placed
44
97
  * ones (`unplaced`, laid out as `assisted`), or every element anew (`all`, laid out as `auto`),
@@ -1 +1 @@
1
- {"version":3,"file":"arrange.d.ts","sourceRoot":"","sources":["../src/arrange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAU5D,OAAO,EAA8C,KAAK,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,EAAe,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAErF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,CAczE;AAKD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,WAAW,EACjB,EAAE,EAAE,MAAM,GAER;IACE,QAAQ,CAAC,SAAS,EAAE,aAAa,GAAG;QAAE,IAAI,EAAE,oBAAoB,CAAA;KAAE,CAAC;IACnE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,GACD,SAAS,CA2CZ;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,SAAS,MAAM,EAAE,EACtB,KAAK,EAAE,KAAK,GACX;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAuBhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,aAAa,EAAE,CA4CjB;AAgCD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAAG,KAAK,GACxB,aAAa,GAAG,SAAS,CAE3B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAAG,KAAK,GACxB;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAkCnE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,aAAa,GAAG,SAAS,CAUjF;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAU9E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,MAAM,EACjB,EAAE,CAAC,EAAE,MAAM,GACV,CAAC,aAAa,GAAG;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CAiBrE"}
1
+ {"version":3,"file":"arrange.d.ts","sourceRoot":"","sources":["../src/arrange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAW5D,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,EAAe,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAErF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,KAAK,CAczE;AAKD,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAItF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAIzE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,WAAW,EACjB,EAAE,EAAE,MAAM,GAER;IACE,QAAQ,CAAC,SAAS,EAAE,aAAa,GAAG;QAAE,IAAI,EAAE,oBAAoB,CAAA;KAAE,CAAC;IACnE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,GACD,SAAS,CA6CZ;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,SAAS,MAAM,EAAE,EACtB,KAAK,EAAE,KAAK,GACX;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAyBhE;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,aAAa,EAAE,CA+CjB;AAkBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAWf;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,aAAa,EAAE,CAUnF;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,SAAS,KAAK,EAAE,GACvB;IAAE,QAAQ,CAAC,UAAU,EAAE,aAAa,EAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAoB1E;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,IAAI,GAClB,aAAa,EAAE,CAoEjB;AAoCD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAAG,KAAK,GACxB,aAAa,GAAG,SAAS,CAE3B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAAG,KAAK,GACxB;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAkCnE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,aAAa,GAAG,SAAS,CAUjF;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAU9E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,MAAM,EACjB,EAAE,CAAC,EAAE,MAAM,GACV,CAAC,aAAa,GAAG;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CAgBrE"}
package/dist/arrange.js CHANGED
@@ -1,4 +1,4 @@
1
- import { groupHeaderOf, layoutDiagram, stacked, StyleResolver, typeScale, } from "@meltemi/diagrams-layout";
1
+ import { DEFAULT_PEN_WIDTH, groupHeaderOf, layoutDiagram, stacked, StyleResolver, typeScale, } from "@meltemi/diagrams-layout";
2
2
  import { MAIN_LAYER } from "@meltemi/diagrams-model";
3
3
  import { diagramView } from "./analysis.js";
4
4
  /**
@@ -28,6 +28,29 @@ export function interiorOf(view, group) {
28
28
  }
29
29
  const parentId = (e) => e.groupPath[e.groupPath.length - 1] ?? null;
30
30
  const layerOf = (e) => e.layer ?? MAIN_LAYER;
31
+ /** Whether an element keeps its points in its statement: a free line or a pen stroke. */
32
+ export function keepsPoints(element) {
33
+ return element.kind === "line" || element.kind === "pen";
34
+ }
35
+ /**
36
+ * The list group (`layout column` or `layout row`) that places an element of a free diagram: its
37
+ * group when that group is a list, which puts its children one after another and takes no
38
+ * `place` for them. Undefined for any other element, and for lines and pens, which keep their
39
+ * points in a list as in any group.
40
+ */
41
+ export function placingList(diagram, element) {
42
+ if (diagram.type !== "free" || keepsPoints(element))
43
+ return undefined;
44
+ const parent = parentId(element);
45
+ return parent !== null && diagram.elementsById.get(parent)?.list ? parent : undefined;
46
+ }
47
+ /**
48
+ * Whether alignment and distribution move an element: not a group, a line or a pen, which have no
49
+ * edges to line up, nor a child of a list, which its list places.
50
+ */
51
+ export function alignable(diagram, element) {
52
+ return (element.kind !== "group" && !keepsPoints(element) && placingList(diagram, element) === undefined);
53
+ }
31
54
  /**
32
55
  * The `convertToContainer` operation for a flow node or a free box, with the elements drawn
33
56
  * stacked on it as its children: siblings declared after it on its layer whose box lies inside
@@ -46,7 +69,9 @@ export function containerOperation(view, id) {
46
69
  const after = diagram.elements.slice(diagram.elements.indexOf(element) + 1);
47
70
  const children = after.filter((e) => {
48
71
  const inner = boxes.get(e.id);
72
+ // Lines and pens keep their points where they are: they are drawings over the box.
49
73
  return (inner !== undefined &&
74
+ !keepsPoints(e) &&
50
75
  parentId(e) === parentId(element) &&
51
76
  layerOf(e) === layerOf(element) &&
52
77
  stacked(box, inner));
@@ -91,13 +116,16 @@ export function stackedAfterMove(view, ids, delta) {
91
116
  for (const id of ids) {
92
117
  const element = diagram.elementsById.get(id);
93
118
  const box = boxes.get(id);
94
- if (!element || !box)
119
+ // A stroke or a line over a box is a drawing on it, which no container carries.
120
+ if (!element || !box || keepsPoints(element))
95
121
  continue;
96
122
  const landed = { ...box, x: box.x + delta.x, y: box.y + delta.y };
97
123
  // The smallest box that holds it, which is the one it is seen on.
98
124
  let outer;
99
125
  for (const other of diagram.elements) {
100
- if (other.kind === "group" || moves(other) || layerOf(other) !== layerOf(element))
126
+ if (other.kind === "group" || keepsPoints(other) || moves(other))
127
+ continue;
128
+ if (layerOf(other) !== layerOf(element))
101
129
  continue;
102
130
  const holder = boxes.get(other.id);
103
131
  if (!holder || !stacked(holder, landed))
@@ -140,7 +168,10 @@ export function steadyGroups(view, leaving, target) {
140
168
  continue;
141
169
  const emptied = sources.has(group) &&
142
170
  diagram.elements.every((e) => e.groupPath[e.groupPath.length - 1] !== group || leaving.includes(e.id));
143
- if (!emptied && !(placed && diagram.type === "free"))
171
+ // A list grows and shrinks with its children, whose places it sets: it keeps no size of the
172
+ // moment unless it is left empty.
173
+ const list = Boolean(diagram.elementsById.get(group)?.list);
174
+ if (!emptied && (list || !(placed && diagram.type === "free")))
144
175
  continue;
145
176
  if (!placed) {
146
177
  // Relative to the interior of its own group in free diagrams.
@@ -163,10 +194,178 @@ export function steadyGroups(view, leaving, target) {
163
194
  }
164
195
  return ops;
165
196
  }
197
+ /**
198
+ * Whether a box holds a stroke through `points` of `width`: the box of its points grown by half
199
+ * its width on every side, as the layout bounds a pen.
200
+ */
201
+ function holdsStroke(box, points, width) {
202
+ const half = width / 2;
203
+ const slack = 1e-6;
204
+ return points.every((p) => p.x - half >= box.x - slack &&
205
+ p.x + half <= box.x + box.width + slack &&
206
+ p.y - half >= box.y - slack &&
207
+ p.y + half <= box.y + box.height + slack);
208
+ }
209
+ /**
210
+ * The group a stroke through `points` (diagram coordinates) of `width` belongs to, from `start`
211
+ * (the innermost group under its first point, or the group it is in) outwards: the first that is
212
+ * not a list and whose drawn box holds the whole stroke, so that a stroke never grows a list nor
213
+ * moves the children it places; the top level (null) when none does. `start` as it is when it is
214
+ * no group of a drawn free diagram, which the edit judges.
215
+ */
216
+ export function strokeParent(view, start, points, width) {
217
+ const diagram = view.diagram;
218
+ const group = start === null ? undefined : diagram.elementsById.get(start);
219
+ const boxes = view.layout?.boxes;
220
+ if (start === null || group?.kind !== "group" || diagram.type !== "free" || !boxes)
221
+ return start;
222
+ for (const id of [start, ...[...group.groupPath].reverse()]) {
223
+ const candidate = diagram.elementsById.get(id);
224
+ const box = boxes.get(id);
225
+ if (candidate && candidate.list === null && box && holdsStroke(box, points, width))
226
+ return id;
227
+ }
228
+ return null;
229
+ }
230
+ /**
231
+ * The `setSize` that keeps a plain group of a free diagram drawn as it is while a stroke goes into
232
+ * it or moves in it: a group without `size` derives its size from what it holds and grows about
233
+ * its centre, which moves its interior and every child placed in it. The size is written as drawn,
234
+ * unrounded, so that the interior stays where it is to the hundredth. Nothing for the top level,
235
+ * a list (which grows with its children) or a group with a size.
236
+ */
237
+ export function steadySize(view, group) {
238
+ const diagram = view.diagram;
239
+ if (group === null || diagram.type !== "free")
240
+ return [];
241
+ const element = diagram.elementsById.get(group);
242
+ const box = view.layout?.boxes?.get(group);
243
+ if (element?.kind !== "group" || element.list !== null || !box)
244
+ return [];
245
+ if (diagram.placement.some((p) => p.statement === "size" && p.target === group))
246
+ return [];
247
+ return [
248
+ { kind: "setSize", diagram: view.id, element: group, width: box.width, height: box.height },
249
+ ];
250
+ }
251
+ /**
252
+ * The operations that draw the pen `element` through `points`, in diagram coordinates, as a drag
253
+ * or a scale of its stroke leaves it: its points in its group's interior. A pen in a list, which
254
+ * would grow the list and move the children it places, goes out first to the nearest group around
255
+ * the list that is not a list and holds the stroke (`strokeParent`), or to the top level, so that
256
+ * it lands where it is dropped. `parent` is the group it ends in, which the caller keeps steady
257
+ * (`steadySize`).
258
+ */
259
+ export function penOperations(view, element, points) {
260
+ const diagram = view.diagram;
261
+ const current = parentId(element);
262
+ const width = view.layout?.pens?.get(element.id)?.width ?? DEFAULT_PEN_WIDTH;
263
+ const parent = current !== null && diagram.elementsById.get(current)?.list
264
+ ? strokeParent(view, current, points, width)
265
+ : current;
266
+ const operations = [];
267
+ if (parent !== current) {
268
+ operations.push({ kind: "moveElement", diagram: view.id, element: element.id, parent });
269
+ }
270
+ const origin = interiorOf(view, parent);
271
+ operations.push({
272
+ kind: "setPenPoints",
273
+ diagram: view.id,
274
+ element: element.id,
275
+ points: points.map((p) => ({ x: p.x - origin.x, y: p.y - origin.y })),
276
+ });
277
+ return { operations, parent };
278
+ }
279
+ /**
280
+ * The operations that keep what the list group `list` holds drawn where it is once the list no
281
+ * longer places it, in the interior of `into`: the list itself when its layout goes, its parent
282
+ * when it is ungrouped (null: the top level). Each child the list places gets its `place` at its
283
+ * drawn centre, and the size it is drawn with when the list stretches it; when the list stays a
284
+ * group, a written size, which was its least size, becomes the size it is drawn with. Lines and
285
+ * pens that leave the list get their drawn points in the new interior. Into another list, which
286
+ * places them in order, the children get no place; nor in an `auto` diagram, whose engine places
287
+ * them, and which a place would make `assisted`.
288
+ */
289
+ export function unlistedOperations(view, list, into) {
290
+ const diagram = view.diagram;
291
+ const layout = view.layout;
292
+ const geometry = layout?.lists?.get(list);
293
+ const boxes = layout?.boxes;
294
+ if (diagram.type !== "free" || !geometry || !boxes)
295
+ return [];
296
+ const d = view.id;
297
+ const sized = (id) => diagram.placement.some((p) => p.statement === "size" && p.target === id);
298
+ const size = (id, box) => ({
299
+ kind: "setSize",
300
+ diagram: d,
301
+ element: id,
302
+ width: Math.round(box.width),
303
+ height: Math.round(box.height),
304
+ });
305
+ const origin = into === list ? geometry.origin : interiorOf(view, into);
306
+ const ops = [];
307
+ const intoList = into !== null && into !== list && Boolean(diagram.elementsById.get(into)?.list);
308
+ if (!intoList) {
309
+ for (const id of geometry.children) {
310
+ const box = boxes.get(id);
311
+ if (!box)
312
+ continue;
313
+ if (view.mode !== "auto") {
314
+ ops.push({
315
+ kind: "setPosition",
316
+ diagram: d,
317
+ element: id,
318
+ x: Math.round(box.x + box.width / 2 - origin.x),
319
+ y: Math.round(box.y + box.height / 2 - origin.y),
320
+ });
321
+ }
322
+ if (geometry.align === "stretch" && !sized(id))
323
+ ops.push(size(id, box));
324
+ }
325
+ }
326
+ if (into === list) {
327
+ const box = boxes.get(list);
328
+ if (box && sized(list))
329
+ ops.push(size(list, box));
330
+ return ops;
331
+ }
332
+ for (const element of diagram.elements) {
333
+ if (parentId(element) !== list)
334
+ continue;
335
+ if (element.kind === "pen") {
336
+ const stroke = layout.pens?.get(element.id);
337
+ if (!stroke)
338
+ continue;
339
+ ops.push({
340
+ kind: "setPenPoints",
341
+ diagram: d,
342
+ element: element.id,
343
+ points: stroke.points.map((p) => ({ x: p.x - origin.x, y: p.y - origin.y })),
344
+ });
345
+ }
346
+ else if (element.kind === "line" && element.line) {
347
+ const at = layout.origins?.get(element.id) ?? { x: 0, y: 0 };
348
+ const moved = (p) => ({
349
+ x: Math.round(p.x + at.x - origin.x),
350
+ y: Math.round(p.y + at.y - origin.y),
351
+ });
352
+ ops.push({
353
+ kind: "setLinePoints",
354
+ diagram: d,
355
+ element: element.id,
356
+ from: moved(element.line.from),
357
+ to: moved(element.line.to),
358
+ via: element.line.via.map(moved),
359
+ });
360
+ }
361
+ }
362
+ return ops;
363
+ }
166
364
  /**
167
365
  * Centres of elements and sizes of groups from laid-out boxes. In free diagrams the centres of
168
366
  * group children are written relative to their group's interior (`origins`), and groups get a
169
- * place and a size.
367
+ * place and a size; lines and pens keep their points, the children of a list get no centre (the
368
+ * list places them) and a list no size (it grows with its children).
170
369
  */
171
370
  function fromBoxes(diagram, boxes, origins) {
172
371
  const positions = new Map();
@@ -174,15 +373,18 @@ function fromBoxes(diagram, boxes, origins) {
174
373
  const free = diagram.type === "free";
175
374
  for (const element of diagram.elements) {
176
375
  const box = boxes.get(element.id);
177
- if (!box)
376
+ if (!box || (free && keepsPoints(element)))
377
+ continue;
378
+ if (placingList(diagram, element) !== undefined)
178
379
  continue;
179
380
  const origin = free ? origins?.get(element.id) : undefined;
180
381
  positions.set(element.id, {
181
382
  x: box.x + box.width / 2 - (origin?.x ?? 0),
182
383
  y: box.y + box.height / 2 - (origin?.y ?? 0),
183
384
  });
184
- if (element.kind === "group")
385
+ if (element.kind === "group" && !element.list) {
185
386
  sizes.set(element.id, { width: box.width, height: box.height });
387
+ }
186
388
  }
187
389
  return free ? { positions, sizes, writeGroups: true } : { positions, sizes };
188
390
  }
@@ -278,7 +480,6 @@ export function convertOperation(analysis, diagramId, id) {
278
480
  metrics: {
279
481
  groupPadding: layout.theme.groupPadding,
280
482
  groupHeader: layout.theme.groupHeader,
281
- noteSize: scale.note,
282
483
  tagSize: scale.tag,
283
484
  },
284
485
  };