@antv/infographic 0.2.13 → 0.2.15

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 (241) hide show
  1. package/README.md +12 -5
  2. package/README.zh-CN.md +12 -5
  3. package/dist/infographic.min.js +180 -171
  4. package/dist/infographic.min.js.map +1 -1
  5. package/esm/designs/structures/index.d.ts +1 -0
  6. package/esm/designs/structures/index.js +1 -0
  7. package/esm/designs/structures/relation-dagre-flow.js +4 -139
  8. package/esm/designs/structures/sequence-interaction.d.ts +54 -0
  9. package/esm/designs/structures/sequence-interaction.js +440 -0
  10. package/esm/designs/utils/geometry.d.ts +44 -0
  11. package/esm/designs/utils/geometry.js +244 -0
  12. package/esm/designs/utils/index.d.ts +1 -0
  13. package/esm/designs/utils/index.js +1 -0
  14. package/esm/editor/commands/UpdateOptions.d.ts +4 -4
  15. package/esm/editor/commands/UpdateOptions.js +6 -3
  16. package/esm/editor/editor.d.ts +5 -1
  17. package/esm/editor/editor.js +16 -5
  18. package/esm/editor/index.d.ts +1 -0
  19. package/esm/editor/index.js +1 -0
  20. package/esm/editor/interactions/brush-select.d.ts +0 -1
  21. package/esm/editor/interactions/brush-select.js +2 -10
  22. package/esm/editor/interactions/drag-canvas.d.ts +35 -0
  23. package/esm/editor/interactions/drag-canvas.js +161 -0
  24. package/esm/editor/interactions/drag-element.js +4 -3
  25. package/esm/editor/interactions/index.d.ts +1 -0
  26. package/esm/editor/interactions/index.js +1 -0
  27. package/esm/editor/interactions/zoom-wheel.d.ts +9 -0
  28. package/esm/editor/interactions/zoom-wheel.js +32 -15
  29. package/esm/editor/managers/index.d.ts +1 -0
  30. package/esm/editor/managers/index.js +1 -0
  31. package/esm/editor/managers/state.d.ts +4 -2
  32. package/esm/editor/managers/state.js +14 -13
  33. package/esm/editor/managers/sync-registry.d.ts +16 -0
  34. package/esm/editor/managers/sync-registry.js +51 -0
  35. package/esm/editor/plugins/{edit-bar/components → components}/button.js +1 -1
  36. package/esm/editor/plugins/{edit-bar/components → components}/color-picker.js +1 -1
  37. package/esm/editor/plugins/{edit-bar/components → components}/icons.d.ts +1 -0
  38. package/esm/editor/plugins/{edit-bar/components → components}/icons.js +1 -0
  39. package/esm/editor/plugins/{edit-bar/components → components}/popover.js +2 -2
  40. package/esm/editor/plugins/{edit-bar/components → components}/select.js +1 -1
  41. package/esm/editor/plugins/core-sync.d.ts +8 -0
  42. package/esm/editor/plugins/core-sync.js +30 -0
  43. package/esm/editor/plugins/edit-bar/edit-items/align-elements.js +1 -1
  44. package/esm/editor/plugins/edit-bar/edit-items/font-align.js +1 -1
  45. package/esm/editor/plugins/edit-bar/edit-items/font-color.js +1 -1
  46. package/esm/editor/plugins/edit-bar/edit-items/font-family.js +1 -1
  47. package/esm/editor/plugins/edit-bar/edit-items/font-size.js +1 -1
  48. package/esm/editor/plugins/edit-bar/edit-items/icon-color.js +1 -1
  49. package/esm/editor/plugins/edit-bar/index.d.ts +2 -2
  50. package/esm/editor/plugins/edit-bar/index.js +1 -1
  51. package/esm/editor/plugins/index.d.ts +2 -0
  52. package/esm/editor/plugins/index.js +2 -0
  53. package/esm/editor/plugins/reset-viewbox.d.ts +33 -0
  54. package/esm/editor/plugins/reset-viewbox.js +186 -0
  55. package/esm/editor/types/editor.d.ts +14 -0
  56. package/esm/editor/types/index.d.ts +1 -0
  57. package/esm/editor/types/interaction.d.ts +9 -0
  58. package/esm/editor/types/state.d.ts +4 -2
  59. package/esm/editor/types/sync.d.ts +27 -0
  60. package/esm/editor/types/sync.js +1 -0
  61. package/esm/editor/utils/data.js +3 -1
  62. package/esm/editor/utils/event.d.ts +1 -0
  63. package/esm/editor/utils/event.js +8 -0
  64. package/esm/editor/utils/index.d.ts +1 -0
  65. package/esm/editor/utils/index.js +1 -0
  66. package/esm/editor/utils/object.d.ts +15 -0
  67. package/esm/editor/utils/object.js +77 -0
  68. package/esm/index.d.ts +4 -3
  69. package/esm/index.js +3 -2
  70. package/esm/options/types.d.ts +7 -0
  71. package/esm/runtime/Infographic.js +20 -7
  72. package/esm/runtime/options.js +7 -2
  73. package/esm/syntax/index.js +40 -20
  74. package/esm/syntax/relations.js +26 -2
  75. package/esm/syntax/schema.js +1 -0
  76. package/esm/templates/built-in.js +27 -2
  77. package/esm/templates/sequence-interaction.d.ts +2 -0
  78. package/esm/templates/sequence-interaction.js +76 -0
  79. package/esm/types/data.d.ts +1 -0
  80. package/esm/utils/index.d.ts +1 -0
  81. package/esm/utils/index.js +1 -0
  82. package/esm/utils/measure-text.js +40 -9
  83. package/esm/utils/padding.d.ts +1 -0
  84. package/esm/utils/padding.js +6 -2
  85. package/esm/utils/types.d.ts +16 -0
  86. package/esm/utils/types.js +12 -0
  87. package/esm/version.d.ts +1 -1
  88. package/esm/version.js +1 -1
  89. package/lib/designs/structures/index.d.ts +1 -0
  90. package/lib/designs/structures/index.js +1 -0
  91. package/lib/designs/structures/relation-dagre-flow.js +5 -140
  92. package/lib/designs/structures/sequence-interaction.d.ts +54 -0
  93. package/lib/designs/structures/sequence-interaction.js +444 -0
  94. package/lib/designs/utils/geometry.d.ts +44 -0
  95. package/lib/designs/utils/geometry.js +256 -0
  96. package/lib/designs/utils/index.d.ts +1 -0
  97. package/lib/designs/utils/index.js +1 -0
  98. package/lib/editor/commands/UpdateOptions.d.ts +4 -4
  99. package/lib/editor/commands/UpdateOptions.js +6 -3
  100. package/lib/editor/editor.d.ts +5 -1
  101. package/lib/editor/editor.js +16 -5
  102. package/lib/editor/index.d.ts +1 -0
  103. package/lib/editor/index.js +1 -0
  104. package/lib/editor/interactions/brush-select.d.ts +0 -1
  105. package/lib/editor/interactions/brush-select.js +1 -9
  106. package/lib/editor/interactions/drag-canvas.d.ts +35 -0
  107. package/lib/editor/interactions/drag-canvas.js +165 -0
  108. package/lib/editor/interactions/drag-element.js +4 -3
  109. package/lib/editor/interactions/index.d.ts +1 -0
  110. package/lib/editor/interactions/index.js +3 -1
  111. package/lib/editor/interactions/zoom-wheel.d.ts +9 -0
  112. package/lib/editor/interactions/zoom-wheel.js +32 -15
  113. package/lib/editor/managers/index.d.ts +1 -0
  114. package/lib/editor/managers/index.js +1 -0
  115. package/lib/editor/managers/state.d.ts +4 -2
  116. package/lib/editor/managers/state.js +12 -11
  117. package/lib/editor/managers/sync-registry.d.ts +16 -0
  118. package/lib/editor/managers/sync-registry.js +55 -0
  119. package/lib/editor/plugins/{edit-bar/components → components}/button.js +1 -1
  120. package/lib/editor/plugins/{edit-bar/components → components}/color-picker.js +1 -1
  121. package/lib/editor/plugins/{edit-bar/components → components}/icons.d.ts +1 -0
  122. package/lib/editor/plugins/{edit-bar/components → components}/icons.js +2 -1
  123. package/lib/editor/plugins/{edit-bar/components → components}/popover.js +2 -2
  124. package/lib/editor/plugins/{edit-bar/components → components}/select.js +1 -1
  125. package/lib/editor/plugins/core-sync.d.ts +8 -0
  126. package/lib/editor/plugins/core-sync.js +34 -0
  127. package/lib/editor/plugins/edit-bar/edit-items/align-elements.js +1 -1
  128. package/lib/editor/plugins/edit-bar/edit-items/font-align.js +1 -1
  129. package/lib/editor/plugins/edit-bar/edit-items/font-color.js +1 -1
  130. package/lib/editor/plugins/edit-bar/edit-items/font-family.js +1 -1
  131. package/lib/editor/plugins/edit-bar/edit-items/font-size.js +1 -1
  132. package/lib/editor/plugins/edit-bar/edit-items/icon-color.js +1 -1
  133. package/lib/editor/plugins/edit-bar/index.d.ts +2 -2
  134. package/lib/editor/plugins/edit-bar/index.js +1 -1
  135. package/lib/editor/plugins/index.d.ts +2 -0
  136. package/lib/editor/plugins/index.js +5 -1
  137. package/lib/editor/plugins/reset-viewbox.d.ts +33 -0
  138. package/lib/editor/plugins/reset-viewbox.js +190 -0
  139. package/lib/editor/types/editor.d.ts +14 -0
  140. package/lib/editor/types/index.d.ts +1 -0
  141. package/lib/editor/types/interaction.d.ts +9 -0
  142. package/lib/editor/types/state.d.ts +4 -2
  143. package/lib/editor/types/sync.d.ts +27 -0
  144. package/lib/editor/types/sync.js +2 -0
  145. package/lib/editor/utils/data.js +3 -1
  146. package/lib/editor/utils/event.d.ts +1 -0
  147. package/lib/editor/utils/event.js +9 -0
  148. package/lib/editor/utils/index.d.ts +1 -0
  149. package/lib/editor/utils/index.js +1 -0
  150. package/lib/editor/utils/object.d.ts +15 -0
  151. package/lib/editor/utils/object.js +80 -0
  152. package/lib/index.d.ts +4 -3
  153. package/lib/index.js +9 -2
  154. package/lib/options/types.d.ts +7 -0
  155. package/lib/runtime/Infographic.js +19 -6
  156. package/lib/runtime/options.js +6 -1
  157. package/lib/syntax/index.js +40 -20
  158. package/lib/syntax/relations.js +26 -2
  159. package/lib/syntax/schema.js +1 -0
  160. package/lib/templates/built-in.js +27 -2
  161. package/lib/templates/sequence-interaction.d.ts +2 -0
  162. package/lib/templates/sequence-interaction.js +79 -0
  163. package/lib/types/data.d.ts +1 -0
  164. package/lib/utils/index.d.ts +1 -0
  165. package/lib/utils/index.js +1 -0
  166. package/lib/utils/measure-text.js +39 -8
  167. package/lib/utils/padding.d.ts +1 -0
  168. package/lib/utils/padding.js +7 -2
  169. package/lib/utils/types.d.ts +16 -0
  170. package/lib/utils/types.js +13 -0
  171. package/lib/version.d.ts +1 -1
  172. package/lib/version.js +1 -1
  173. package/package.json +1 -1
  174. package/src/designs/structures/index.ts +1 -0
  175. package/src/designs/structures/relation-dagre-flow.tsx +14 -178
  176. package/src/designs/structures/sequence-interaction.tsx +885 -0
  177. package/src/designs/utils/geometry.tsx +315 -0
  178. package/src/designs/utils/index.ts +1 -0
  179. package/src/editor/commands/UpdateOptions.ts +11 -6
  180. package/src/editor/editor.ts +26 -5
  181. package/src/editor/index.ts +1 -0
  182. package/src/editor/interactions/brush-select.ts +2 -8
  183. package/src/editor/interactions/drag-canvas.ts +203 -0
  184. package/src/editor/interactions/drag-element.ts +5 -4
  185. package/src/editor/interactions/index.ts +1 -0
  186. package/src/editor/interactions/zoom-wheel.ts +49 -13
  187. package/src/editor/managers/index.ts +1 -0
  188. package/src/editor/managers/state.ts +21 -21
  189. package/src/editor/managers/sync-registry.ts +66 -0
  190. package/src/editor/plugins/{edit-bar/components → components}/button.ts +1 -1
  191. package/src/editor/plugins/{edit-bar/components → components}/color-picker.ts +1 -1
  192. package/src/editor/plugins/{edit-bar/components → components}/icons.ts +4 -0
  193. package/src/editor/plugins/{edit-bar/components → components}/popover.ts +2 -2
  194. package/src/editor/plugins/{edit-bar/components → components}/select.ts +1 -1
  195. package/src/editor/plugins/core-sync.ts +44 -0
  196. package/src/editor/plugins/edit-bar/edit-items/align-elements.ts +2 -2
  197. package/src/editor/plugins/edit-bar/edit-items/font-align.ts +1 -1
  198. package/src/editor/plugins/edit-bar/edit-items/font-color.ts +1 -1
  199. package/src/editor/plugins/edit-bar/edit-items/font-family.ts +1 -1
  200. package/src/editor/plugins/edit-bar/edit-items/font-size.ts +3 -3
  201. package/src/editor/plugins/edit-bar/edit-items/icon-color.ts +1 -1
  202. package/src/editor/plugins/edit-bar/index.ts +2 -2
  203. package/src/editor/plugins/index.ts +2 -0
  204. package/src/editor/plugins/reset-viewbox.ts +258 -0
  205. package/src/editor/types/editor.ts +18 -0
  206. package/src/editor/types/index.ts +1 -0
  207. package/src/editor/types/interaction.ts +31 -0
  208. package/src/editor/types/state.ts +14 -2
  209. package/src/editor/types/sync.ts +33 -0
  210. package/src/editor/utils/data.ts +2 -1
  211. package/src/editor/utils/event.ts +7 -0
  212. package/src/editor/utils/index.ts +1 -0
  213. package/src/editor/utils/object.ts +116 -0
  214. package/src/index.ts +26 -2
  215. package/src/options/types.ts +11 -0
  216. package/src/runtime/Infographic.tsx +27 -17
  217. package/src/runtime/options.ts +8 -1
  218. package/src/syntax/index.ts +51 -18
  219. package/src/syntax/relations.ts +29 -2
  220. package/src/syntax/schema.ts +1 -0
  221. package/src/templates/built-in.ts +30 -0
  222. package/src/templates/sequence-interaction.ts +101 -0
  223. package/src/types/data.ts +1 -0
  224. package/src/utils/index.ts +1 -0
  225. package/src/utils/measure-text.ts +41 -9
  226. package/src/utils/padding.ts +10 -2
  227. package/src/utils/types.ts +61 -0
  228. package/src/version.ts +1 -1
  229. /package/esm/editor/plugins/{edit-bar/components → components}/button.d.ts +0 -0
  230. /package/esm/editor/plugins/{edit-bar/components → components}/color-picker.d.ts +0 -0
  231. /package/esm/editor/plugins/{edit-bar/components → components}/index.d.ts +0 -0
  232. /package/esm/editor/plugins/{edit-bar/components → components}/index.js +0 -0
  233. /package/esm/editor/plugins/{edit-bar/components → components}/popover.d.ts +0 -0
  234. /package/esm/editor/plugins/{edit-bar/components → components}/select.d.ts +0 -0
  235. /package/lib/editor/plugins/{edit-bar/components → components}/button.d.ts +0 -0
  236. /package/lib/editor/plugins/{edit-bar/components → components}/color-picker.d.ts +0 -0
  237. /package/lib/editor/plugins/{edit-bar/components → components}/index.d.ts +0 -0
  238. /package/lib/editor/plugins/{edit-bar/components → components}/index.js +0 -0
  239. /package/lib/editor/plugins/{edit-bar/components → components}/popover.d.ts +0 -0
  240. /package/lib/editor/plugins/{edit-bar/components → components}/select.d.ts +0 -0
  241. /package/src/editor/plugins/{edit-bar/components → components}/index.ts +0 -0
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEdgePathD = exports.getLabelPosition = exports.getPointAtT = exports.getTangentAngle = exports.getNodesAnchors = exports.createArrowElements = exports.createRoundedPath = exports.createStraightPath = exports.getMidPoint = void 0;
4
+ const jsx_runtime_1 = require("@antv/infographic/jsx-runtime");
5
+ const jsx_1 = require("../../jsx");
6
+ const getMidPoint = (points) => {
7
+ if (points.length === 0)
8
+ return null;
9
+ if (points.length === 1)
10
+ return points[0];
11
+ let total = 0;
12
+ const segments = [];
13
+ for (let i = 0; i < points.length - 1; i += 1) {
14
+ const start = points[i];
15
+ const end = points[i + 1];
16
+ const length = Math.hypot(end[0] - start[0], end[1] - start[1]);
17
+ segments.push({ length, start, end });
18
+ total += length;
19
+ }
20
+ if (total === 0)
21
+ return points[0];
22
+ let target = total / 2;
23
+ for (let i = 0; i < segments.length; i += 1) {
24
+ const segment = segments[i];
25
+ if (target <= segment.length || i === segments.length - 1) {
26
+ const ratio = segment.length === 0
27
+ ? 0
28
+ : Math.max(0, Math.min(1, target / segment.length));
29
+ return [
30
+ segment.start[0] + (segment.end[0] - segment.start[0]) * ratio,
31
+ segment.start[1] + (segment.end[1] - segment.start[1]) * ratio,
32
+ ];
33
+ }
34
+ target -= segment.length;
35
+ }
36
+ return points[Math.floor(points.length / 2)];
37
+ };
38
+ exports.getMidPoint = getMidPoint;
39
+ const createStraightPath = (points, dx, dy) => points
40
+ .map(([x, y], index) => {
41
+ const prefix = index === 0 ? 'M' : 'L';
42
+ return `${prefix} ${x + dx} ${y + dy}`;
43
+ })
44
+ .join(' ');
45
+ exports.createStraightPath = createStraightPath;
46
+ const createRoundedPath = (points, radius, dx, dy) => {
47
+ if (points.length < 2)
48
+ return '';
49
+ const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
50
+ const toPoint = ([x, y]) => ({
51
+ x: x + dx,
52
+ y: y + dy,
53
+ });
54
+ const output = [];
55
+ const first = toPoint(points[0]);
56
+ output.push(`M ${first.x} ${first.y}`);
57
+ if (points.length === 2) {
58
+ const last = toPoint(points[1]);
59
+ output.push(`L ${last.x} ${last.y}`);
60
+ return output.join(' ');
61
+ }
62
+ for (let i = 1; i < points.length - 1; i += 1) {
63
+ const prev = points[i - 1];
64
+ const curr = points[i];
65
+ const next = points[i + 1];
66
+ const v0x = curr[0] - prev[0];
67
+ const v0y = curr[1] - prev[1];
68
+ const v1x = next[0] - curr[0];
69
+ const v1y = next[1] - curr[1];
70
+ const d0 = Math.hypot(v0x, v0y);
71
+ const d1 = Math.hypot(v1x, v1y);
72
+ if (d0 === 0 || d1 === 0) {
73
+ const currPoint = toPoint(curr);
74
+ output.push(`L ${currPoint.x} ${currPoint.y}`);
75
+ continue;
76
+ }
77
+ const r = clamp(radius, 0, Math.min(d0, d1) / 2);
78
+ if (r === 0) {
79
+ const currPoint = toPoint(curr);
80
+ output.push(`L ${currPoint.x} ${currPoint.y}`);
81
+ continue;
82
+ }
83
+ const u0x = v0x / d0;
84
+ const u0y = v0y / d0;
85
+ const u1x = v1x / d1;
86
+ const u1y = v1y / d1;
87
+ const start = toPoint([curr[0] - u0x * r, curr[1] - u0y * r]);
88
+ const end = toPoint([curr[0] + u1x * r, curr[1] + u1y * r]);
89
+ output.push(`L ${start.x} ${start.y}`);
90
+ const currPoint = toPoint(curr);
91
+ output.push(`Q ${currPoint.x} ${currPoint.y} ${end.x} ${end.y}`);
92
+ }
93
+ const last = toPoint(points[points.length - 1]);
94
+ output.push(`L ${last.x} ${last.y}`);
95
+ return output.join(' ');
96
+ };
97
+ exports.createRoundedPath = createRoundedPath;
98
+ const createArrowElements = (x, y, angle, type, fillColor, edgeWidth, arrowSize) => {
99
+ const ux = Math.cos(angle);
100
+ const uy = Math.sin(angle);
101
+ const px = -uy;
102
+ const py = ux;
103
+ const length = arrowSize;
104
+ const halfWidth = arrowSize * 0.55;
105
+ if (type === 'arrow') {
106
+ const leftX = x - ux * length + px * halfWidth;
107
+ const leftY = y - uy * length + py * halfWidth;
108
+ const rightX = x - ux * length - px * halfWidth;
109
+ const rightY = y - uy * length - py * halfWidth;
110
+ return [
111
+ (0, jsx_runtime_1.jsx)(jsx_1.Path, { d: `M ${leftX} ${leftY} L ${x} ${y} L ${rightX} ${rightY}`, stroke: fillColor, strokeWidth: Math.max(1.5, edgeWidth), strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
112
+ ];
113
+ }
114
+ if (type === 'diamond') {
115
+ const diamondLength = length * 1.25;
116
+ const diamondWidth = halfWidth * 0.75;
117
+ const midX = x - ux * diamondLength * 0.5;
118
+ const midY = y - uy * diamondLength * 0.5;
119
+ const diamondPoints = [
120
+ { x, y },
121
+ { x: midX + px * diamondWidth, y: midY + py * diamondWidth },
122
+ { x: x - ux * diamondLength, y: y - uy * diamondLength },
123
+ { x: midX - px * diamondWidth, y: midY - py * diamondWidth },
124
+ ];
125
+ return [
126
+ (0, jsx_runtime_1.jsx)(jsx_1.Polygon, { points: diamondPoints, fill: fillColor, stroke: fillColor, strokeWidth: Math.max(1, edgeWidth * 0.8) }),
127
+ ];
128
+ }
129
+ const trianglePoints = [
130
+ { x, y },
131
+ {
132
+ x: x - ux * length + px * halfWidth,
133
+ y: y - uy * length + py * halfWidth,
134
+ },
135
+ {
136
+ x: x - ux * length - px * halfWidth,
137
+ y: y - uy * length - py * halfWidth,
138
+ },
139
+ ];
140
+ return [
141
+ (0, jsx_runtime_1.jsx)(jsx_1.Polygon, { points: trianglePoints, fill: fillColor, stroke: fillColor, strokeWidth: Math.max(1, edgeWidth * 0.8) }),
142
+ ];
143
+ };
144
+ exports.createArrowElements = createArrowElements;
145
+ // LT: Left Top (radio), LC: Left Center (1/2), LB: Left Bottom (1 - radio)
146
+ // RT: Right Top (radio), RC: Right Center (1/2), RB: Right Bottom (1 - radio)
147
+ const getNodesAnchors = (node) => {
148
+ const { x, y, width, height, radio = 0.25 } = node;
149
+ const q1H = height * radio;
150
+ const halfH = height * 0.5;
151
+ const q3H = height * (1 - radio);
152
+ return {
153
+ LT: { x, y: y + q1H },
154
+ LC: { x, y: y + halfH },
155
+ LB: { x, y: y + q3H },
156
+ RT: { x: x + width, y: y + q1H },
157
+ RC: { x: x + width, y: y + halfH },
158
+ RB: { x: x + width, y: y + q3H },
159
+ };
160
+ };
161
+ exports.getNodesAnchors = getNodesAnchors;
162
+ const getTangentAngle = (points, t) => {
163
+ const len = points.length;
164
+ // Cubic Bezier (Self loop)
165
+ if (len === 4) {
166
+ const p0 = points[0], p1 = points[1], p2 = points[2], p3 = points[3];
167
+ if (t === 0) {
168
+ return Math.atan2(p1[1] - p0[1], p1[0] - p0[0]);
169
+ }
170
+ else {
171
+ return Math.atan2(p3[1] - p2[1], p3[0] - p2[0]);
172
+ }
173
+ }
174
+ // Quad Bezier (Curved)
175
+ if (len === 3) {
176
+ const p0 = points[0], p1 = points[1], p2 = points[2];
177
+ if (t === 0) {
178
+ return Math.atan2(p1[1] - p0[1], p1[0] - p0[0]);
179
+ }
180
+ else {
181
+ return Math.atan2(p2[1] - p1[1], p2[0] - p1[0]);
182
+ }
183
+ }
184
+ // Line
185
+ if (len === 2) {
186
+ const p0 = points[0], p1 = points[1];
187
+ const angle = Math.atan2(p1[1] - p0[1], p1[0] - p0[0]);
188
+ return angle;
189
+ }
190
+ return 0;
191
+ };
192
+ exports.getTangentAngle = getTangentAngle;
193
+ /**
194
+ * 计算贝塞尔曲线上任意 t (0-1) 位置的点
195
+ */
196
+ const getPointAtT = (points, t = 0.5) => {
197
+ const len = points.length;
198
+ if (len === 4) {
199
+ const [p0, p1, p2, p3] = points;
200
+ const mt = 1 - t;
201
+ // B(t) = (1-t)^3*P0 + 3(1-t)^2*t*P1 + 3(1-t)*t^2*P2 + t^3*P3
202
+ return [
203
+ Math.pow(mt, 3) * p0[0] +
204
+ 3 * Math.pow(mt, 2) * t * p1[0] +
205
+ 3 * mt * Math.pow(t, 2) * p2[0] +
206
+ Math.pow(t, 3) * p3[0],
207
+ Math.pow(mt, 3) * p0[1] +
208
+ 3 * Math.pow(mt, 2) * t * p1[1] +
209
+ 3 * mt * Math.pow(t, 2) * p2[1] +
210
+ Math.pow(t, 3) * p3[1],
211
+ ];
212
+ }
213
+ if (len === 3) {
214
+ const [p0, p1, p2] = points;
215
+ const mt = 1 - t;
216
+ // B(t) = (1-t)^2*P0 + 2(1-t)*t*P1 + t^2*P2
217
+ return [
218
+ Math.pow(mt, 2) * p0[0] + 2 * mt * t * p1[0] + Math.pow(t, 2) * p2[0],
219
+ Math.pow(mt, 2) * p0[1] + 2 * mt * t * p1[1] + Math.pow(t, 2) * p2[1],
220
+ ];
221
+ }
222
+ if (len === 2) {
223
+ const [p0, p1] = points;
224
+ return [p0[0] + (p1[0] - p0[0]) * t, p0[1] + (p1[1] - p0[1]) * t];
225
+ }
226
+ return points[0] || [0, 0];
227
+ };
228
+ exports.getPointAtT = getPointAtT;
229
+ const getLabelPosition = (points, selfLoopOffset = 10) => {
230
+ const len = points.length;
231
+ // 默认取中点
232
+ const labelPoint = (0, exports.getPointAtT)(points);
233
+ if (len === 4) {
234
+ // 针对自连接(len=4)的特殊偏移处理
235
+ labelPoint[0] += selfLoopOffset;
236
+ }
237
+ return labelPoint;
238
+ };
239
+ exports.getLabelPosition = getLabelPosition;
240
+ const getEdgePathD = (points) => {
241
+ const len = points.length;
242
+ if (len === 4) {
243
+ const [p0, p1, p2, p3] = points;
244
+ return `M ${p0[0]} ${p0[1]} C ${p1[0]} ${p1[1]} ${p2[0]} ${p2[1]} ${p3[0]} ${p3[1]}`;
245
+ }
246
+ if (len === 3) {
247
+ const [p0, p1, p2] = points;
248
+ return `M ${p0[0]} ${p0[1]} Q ${p1[0]} ${p1[1]} ${p2[0]} ${p2[1]}`;
249
+ }
250
+ if (len === 2) {
251
+ const [p0, p1] = points;
252
+ return `M ${p0[0]} ${p0[1]} L ${p1[0]} ${p1[1]}`;
253
+ }
254
+ return '';
255
+ };
256
+ exports.getEdgePathD = getEdgePathD;
@@ -1,4 +1,5 @@
1
1
  export * from './color';
2
+ export * from './geometry';
2
3
  export * from './hierarchy-color';
3
4
  export * from './item';
4
5
  export * from './normalize-percent';
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./color"), exports);
18
+ __exportStar(require("./geometry"), exports);
18
19
  __exportStar(require("./hierarchy-color"), exports);
19
20
  __exportStar(require("./item"), exports);
20
21
  __exportStar(require("./normalize-percent"), exports);
@@ -1,14 +1,14 @@
1
- import type { ParsedInfographicOptions } from '../../options';
1
+ import type { UpdatableInfographicOptions } from '../../options';
2
2
  import type { ICommand, IStateManager } from '../types';
3
3
  export declare class UpdateOptionsCommand implements ICommand {
4
4
  private options;
5
5
  private original?;
6
- constructor(options: Partial<ParsedInfographicOptions>, original?: ParsedInfographicOptions | undefined);
6
+ constructor(options: UpdatableInfographicOptions, original?: UpdatableInfographicOptions | undefined);
7
7
  apply(state: IStateManager): Promise<void>;
8
8
  undo(state: IStateManager): Promise<void>;
9
9
  serialize(): {
10
10
  type: string;
11
- options: Partial<ParsedInfographicOptions>;
12
- original: ParsedInfographicOptions | undefined;
11
+ options: Partial<Omit<import("../../options").ParsedInfographicOptions, "container">>;
12
+ original: Partial<Omit<import("../../options").ParsedInfographicOptions, "container">> | undefined;
13
13
  };
14
14
  }
@@ -17,11 +17,14 @@ class UpdateOptionsCommand {
17
17
  }
18
18
  apply(state) {
19
19
  return __awaiter(this, void 0, void 0, function* () {
20
- const prev = state.getOptions();
21
20
  if (!this.original) {
22
- this.original = prev;
21
+ const prev = state.getOptions();
22
+ this.original = {};
23
+ Object.keys(this.options).forEach((key) => {
24
+ this.original[key] = prev[key];
25
+ });
23
26
  }
24
- state.updateOptions(Object.assign(Object.assign({}, prev), this.options));
27
+ state.updateOptions(this.options);
25
28
  });
26
29
  }
27
30
  undo(state) {
@@ -1,7 +1,7 @@
1
1
  import type { ParsedInfographicOptions } from '../options';
2
2
  import type { IEventEmitter } from '../types';
3
3
  import { InteractionManager } from './managers';
4
- import type { ICommandManager, IEditor, IPluginManager, IStateManager } from './types';
4
+ import type { ICommandManager, IEditor, IPluginManager, IStateManager, ISyncRegistry, SyncHandler } from './types';
5
5
  export declare class Editor implements IEditor {
6
6
  private emitter;
7
7
  private document;
@@ -10,7 +10,11 @@ export declare class Editor implements IEditor {
10
10
  commander: ICommandManager;
11
11
  plugin: IPluginManager;
12
12
  interaction: InteractionManager;
13
+ syncRegistry: ISyncRegistry;
13
14
  constructor(emitter: IEventEmitter, document: SVGSVGElement, options: ParsedInfographicOptions);
15
+ registerSync(path: string, handler: SyncHandler, options?: {
16
+ immediate?: boolean;
17
+ }): () => void;
14
18
  getDocument(): SVGSVGElement;
15
19
  destroy(): void;
16
20
  }
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Editor = void 0;
4
4
  const managers_1 = require("./managers");
5
+ const sync_registry_1 = require("./managers/sync-registry");
6
+ const plugins_1 = require("./plugins");
5
7
  class Editor {
6
8
  constructor(emitter, document, options) {
7
9
  this.emitter = emitter;
@@ -15,6 +17,12 @@ class Editor {
15
17
  const state = new managers_1.StateManager();
16
18
  const plugin = new managers_1.PluginManager();
17
19
  const interaction = new managers_1.InteractionManager();
20
+ const syncRegistry = new sync_registry_1.SyncRegistry(() => state.getOptions());
21
+ this.commander = commander;
22
+ this.state = state;
23
+ this.plugin = plugin;
24
+ this.interaction = interaction;
25
+ this.syncRegistry = syncRegistry;
18
26
  commander.init({ state, emitter });
19
27
  state.init({
20
28
  emitter,
@@ -22,12 +30,15 @@ class Editor {
22
30
  commander,
23
31
  options,
24
32
  });
33
+ // Load core plugin: CoreSyncPlugin (handles viewBox/padding sync)
34
+ const corePlugin = new plugins_1.CoreSyncPlugin();
35
+ const userPlugins = options.plugins || [];
25
36
  plugin.init({
26
37
  emitter,
27
38
  editor: this,
28
39
  commander,
29
40
  state,
30
- }, options.plugins);
41
+ }, [corePlugin, ...userPlugins]);
31
42
  interaction.init({
32
43
  emitter,
33
44
  editor: this,
@@ -35,10 +46,9 @@ class Editor {
35
46
  state,
36
47
  interactions: options.interactions,
37
48
  });
38
- this.commander = commander;
39
- this.state = state;
40
- this.plugin = plugin;
41
- this.interaction = interaction;
49
+ }
50
+ registerSync(path, handler, options) {
51
+ return this.syncRegistry.register(path, handler, options);
42
52
  }
43
53
  getDocument() {
44
54
  return this.document;
@@ -49,6 +59,7 @@ class Editor {
49
59
  this.plugin.destroy();
50
60
  this.commander.destroy();
51
61
  this.state.destroy();
62
+ this.syncRegistry.destroy();
52
63
  }
53
64
  }
54
65
  exports.Editor = Editor;
@@ -1,3 +1,4 @@
1
+ export * from './commands';
1
2
  export { Editor } from './editor';
2
3
  export * from './interactions';
3
4
  export * from './plugins';
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.Editor = void 0;
18
+ __exportStar(require("./commands"), exports);
18
19
  var editor_1 = require("./editor");
19
20
  Object.defineProperty(exports, "Editor", { enumerable: true, get: function () { return editor_1.Editor; } });
20
21
  __exportStar(require("./interactions"), exports);
@@ -19,5 +19,4 @@ export declare class BrushSelect extends Interaction implements IInteraction {
19
19
  private clearBrush;
20
20
  private collectSelection;
21
21
  private hasElementAtStart;
22
- private isTextSelectionTarget;
23
22
  }
@@ -25,7 +25,7 @@ class BrushSelect extends base_1.Interaction {
25
25
  return;
26
26
  if (event.button !== 0)
27
27
  return;
28
- if (this.isTextSelectionTarget(event.target))
28
+ if ((0, utils_2.isTextSelectionTarget)(event.target))
29
29
  return;
30
30
  if (this.hasElementAtStart(event.target))
31
31
  return;
@@ -173,13 +173,5 @@ class BrushSelect extends base_1.Interaction {
173
173
  return true;
174
174
  return Boolean((_a = target.closest) === null || _a === void 0 ? void 0 : _a.call(target, '[data-element-type]'));
175
175
  }
176
- isTextSelectionTarget(target) {
177
- if (!(target instanceof HTMLElement))
178
- return false;
179
- if (target.isContentEditable)
180
- return true;
181
- const tag = target.tagName.toLowerCase();
182
- return tag === 'input' || tag === 'textarea';
183
- }
184
176
  }
185
177
  exports.BrushSelect = BrushSelect;
@@ -0,0 +1,35 @@
1
+ import { IInteraction, InteractionInitOptions, KeyCode } from '../types';
2
+ import { Interaction } from './base';
3
+ export interface DragCanvasOptions {
4
+ trigger?: KeyCode[];
5
+ }
6
+ export declare class DragCanvas extends Interaction implements IInteraction {
7
+ name: string;
8
+ /**
9
+ * 触发交互的按键代码。
10
+ * 参考标准的 KeyboardEvent.code 值:
11
+ * https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
12
+ * @default ['Space']
13
+ */
14
+ trigger: KeyCode[];
15
+ constructor(options?: DragCanvasOptions);
16
+ private isTriggerPressed;
17
+ private pointerId?;
18
+ private startPoint?;
19
+ private document;
20
+ private startViewBoxString?;
21
+ private completeInteraction?;
22
+ private isHovering;
23
+ init(options: InteractionInitOptions): void;
24
+ destroy(): void;
25
+ private handleKeyDown;
26
+ private handlePointerDown;
27
+ private handlePointerMove;
28
+ private handlePointerUp;
29
+ private handleKeyUp;
30
+ private stopDrag;
31
+ private setCursor;
32
+ private handleBlur;
33
+ private onMouseEnter;
34
+ private onMouseLeave;
35
+ }
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DragCanvas = void 0;
13
+ const utils_1 = require("../../utils");
14
+ const commands_1 = require("../commands");
15
+ const utils_2 = require("../utils");
16
+ const base_1 = require("./base");
17
+ class DragCanvas extends base_1.Interaction {
18
+ constructor(options) {
19
+ super();
20
+ this.name = 'drag-canvas';
21
+ /**
22
+ * 触发交互的按键代码。
23
+ * 参考标准的 KeyboardEvent.code 值:
24
+ * https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
25
+ * @default ['Space']
26
+ */
27
+ this.trigger = ['Space'];
28
+ this.isTriggerPressed = false;
29
+ // 防止组件快捷键侵入性过强
30
+ this.isHovering = false;
31
+ this.handleKeyDown = (event) => {
32
+ if (!this.interaction.isActive())
33
+ return;
34
+ if ((0, utils_2.isTextSelectionTarget)(event.target))
35
+ return;
36
+ // 增加焦点的判断,防止对空格的preventDefault侵入性过强
37
+ const target = event.target;
38
+ const isBody = target === document.body || target === document.documentElement;
39
+ const isEditor = target === this.document || this.document.contains(target);
40
+ if (!isBody && !isEditor)
41
+ return;
42
+ if (!this.trigger.includes(event.code))
43
+ return;
44
+ if (!this.isHovering && !this.isTriggerPressed)
45
+ return;
46
+ event.preventDefault();
47
+ event.stopPropagation();
48
+ this.interaction.executeExclusiveInteraction(this, () => __awaiter(this, void 0, void 0, function* () {
49
+ return new Promise((resolve) => {
50
+ this.completeInteraction = resolve;
51
+ this.isTriggerPressed = true;
52
+ const viewBox = (0, utils_1.getViewBox)(this.document);
53
+ this.startViewBoxString = (0, utils_1.viewBoxToString)(viewBox);
54
+ this.setCursor('grab');
55
+ this.document.addEventListener('pointerdown', this.handlePointerDown);
56
+ window.addEventListener('keyup', this.handleKeyUp);
57
+ });
58
+ }));
59
+ };
60
+ this.handlePointerDown = (event) => {
61
+ if (event.button !== 0)
62
+ return;
63
+ event.preventDefault();
64
+ event.stopPropagation();
65
+ const svg = this.document;
66
+ this.startPoint = (0, utils_2.clientToViewport)(svg, event.clientX, event.clientY);
67
+ this.pointerId = event.pointerId;
68
+ this.setCursor('grabbing');
69
+ window.addEventListener('pointermove', this.handlePointerMove);
70
+ window.addEventListener('pointerup', this.handlePointerUp);
71
+ window.addEventListener('pointercancel', this.handlePointerUp);
72
+ };
73
+ this.handlePointerMove = (event) => {
74
+ if (event.pointerId !== this.pointerId || !this.startPoint)
75
+ return;
76
+ event.preventDefault();
77
+ event.stopPropagation();
78
+ const svg = this.document;
79
+ const current = (0, utils_2.clientToViewport)(svg, event.clientX, event.clientY);
80
+ const dx = current.x - this.startPoint.x;
81
+ const dy = current.y - this.startPoint.y;
82
+ const viewBox = (0, utils_1.getViewBox)(svg);
83
+ const { x, y, width, height } = viewBox;
84
+ const newX = x - dx;
85
+ const newY = y - dy;
86
+ this.state.updateOptions({
87
+ viewBox: (0, utils_1.viewBoxToString)({ x: newX, y: newY, width, height }),
88
+ });
89
+ };
90
+ this.handlePointerUp = (event) => {
91
+ if (event.pointerId !== this.pointerId)
92
+ return;
93
+ this.startPoint = undefined;
94
+ this.pointerId = undefined;
95
+ this.setCursor('grab');
96
+ window.removeEventListener('pointermove', this.handlePointerMove);
97
+ window.removeEventListener('pointerup', this.handlePointerUp);
98
+ window.removeEventListener('pointercancel', this.handlePointerUp);
99
+ };
100
+ this.handleKeyUp = (event) => {
101
+ if (!this.trigger.includes(event.code))
102
+ return;
103
+ this.stopDrag();
104
+ };
105
+ this.stopDrag = () => {
106
+ var _a;
107
+ if (this.startViewBoxString) {
108
+ const svg = this.document;
109
+ const viewBox = (0, utils_1.getViewBox)(svg);
110
+ const currentViewBoxString = (0, utils_1.viewBoxToString)(viewBox);
111
+ if (this.startViewBoxString !== currentViewBoxString) {
112
+ const command = new commands_1.UpdateOptionsCommand({ viewBox: currentViewBoxString }, { viewBox: this.startViewBoxString });
113
+ void this.commander.execute(command);
114
+ }
115
+ }
116
+ this.startViewBoxString = undefined;
117
+ this.isTriggerPressed = false;
118
+ this.setCursor('default');
119
+ this.startPoint = undefined;
120
+ this.pointerId = undefined;
121
+ window.removeEventListener('keyup', this.handleKeyUp);
122
+ this.document.removeEventListener('pointerdown', this.handlePointerDown);
123
+ window.removeEventListener('pointermove', this.handlePointerMove);
124
+ window.removeEventListener('pointerup', this.handlePointerUp);
125
+ window.removeEventListener('pointercancel', this.handlePointerUp);
126
+ (_a = this.completeInteraction) === null || _a === void 0 ? void 0 : _a.call(this);
127
+ this.completeInteraction = undefined;
128
+ };
129
+ this.setCursor = (behavior) => {
130
+ document.body.style.cursor = behavior;
131
+ };
132
+ this.handleBlur = () => {
133
+ this.stopDrag();
134
+ };
135
+ this.onMouseEnter = () => {
136
+ this.isHovering = true;
137
+ };
138
+ this.onMouseLeave = () => {
139
+ this.isHovering = false;
140
+ };
141
+ if (options === null || options === void 0 ? void 0 : options.trigger) {
142
+ this.trigger = options.trigger;
143
+ }
144
+ }
145
+ init(options) {
146
+ super.init(options);
147
+ this.document = this.editor.getDocument();
148
+ this.document.addEventListener('mouseenter', this.onMouseEnter);
149
+ this.document.addEventListener('mouseleave', this.onMouseLeave);
150
+ window.addEventListener('keydown', this.handleKeyDown);
151
+ window.addEventListener('blur', this.handleBlur);
152
+ }
153
+ destroy() {
154
+ window.removeEventListener('keydown', this.handleKeyDown);
155
+ window.removeEventListener('keyup', this.handleKeyUp);
156
+ this.document.removeEventListener('pointerdown', this.handlePointerDown);
157
+ window.removeEventListener('pointermove', this.handlePointerMove);
158
+ window.removeEventListener('pointerup', this.handlePointerUp);
159
+ window.removeEventListener('pointercancel', this.handlePointerUp);
160
+ window.removeEventListener('blur', this.handleBlur);
161
+ this.document.removeEventListener('mouseenter', this.onMouseEnter);
162
+ this.document.removeEventListener('mouseleave', this.onMouseLeave);
163
+ }
164
+ }
165
+ exports.DragCanvas = DragCanvas;
@@ -116,9 +116,6 @@ class DragElement extends base_1.Interaction {
116
116
  return true;
117
117
  if (!this.startTarget)
118
118
  return false;
119
- if (this.willReplaceSelection) {
120
- this.interaction.select([this.startTarget], 'replace');
121
- }
122
119
  this.dragItems = this.selectionForDrag
123
120
  .filter((element) => (0, utils_1.isEditableText)(element))
124
121
  .map((element) => this.createDragItem(element))
@@ -128,6 +125,10 @@ class DragElement extends base_1.Interaction {
128
125
  let started = false;
129
126
  this.interaction.executeExclusiveInteraction(this, () => __awaiter(this, void 0, void 0, function* () {
130
127
  return new Promise((resolve) => {
128
+ // 只有拿到锁之后,才真正执行选中逻辑
129
+ if (this.willReplaceSelection && this.startTarget) {
130
+ this.interaction.select([this.startTarget], 'replace');
131
+ }
131
132
  this.completeInteraction = resolve;
132
133
  started = true;
133
134
  });
@@ -2,6 +2,7 @@ export { Interaction } from './base';
2
2
  export { BrushSelect } from './brush-select';
3
3
  export { ClickSelect } from './click-select';
4
4
  export { DblClickEditText } from './dblclick-edit-text';
5
+ export { DragCanvas } from './drag-canvas';
5
6
  export { DragElement } from './drag-element';
6
7
  export { HotkeyHistory } from './hotkey-history';
7
8
  export { SelectHighlight } from './select-highlight';