@eclipse-glsp/client 2.2.0-next.332 → 2.2.0-next.334

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 (223) hide show
  1. package/css/change-bounds.css +36 -2
  2. package/css/glsp-sprotty.css +18 -2
  3. package/css/helper-lines.css +3 -3
  4. package/lib/base/default.module.d.ts.map +1 -1
  5. package/lib/base/default.module.js +3 -0
  6. package/lib/base/default.module.js.map +1 -1
  7. package/lib/base/feedback/css-feedback.d.ts +7 -2
  8. package/lib/base/feedback/css-feedback.d.ts.map +1 -1
  9. package/lib/base/feedback/css-feedback.js +10 -2
  10. package/lib/base/feedback/css-feedback.js.map +1 -1
  11. package/lib/base/feedback/feeback-emitter.d.ts +2 -2
  12. package/lib/base/feedback/feeback-emitter.d.ts.map +1 -1
  13. package/lib/base/feedback/feeback-emitter.js +5 -2
  14. package/lib/base/feedback/feeback-emitter.js.map +1 -1
  15. package/lib/base/index.d.ts +1 -0
  16. package/lib/base/index.d.ts.map +1 -1
  17. package/lib/base/index.js +1 -0
  18. package/lib/base/index.js.map +1 -1
  19. package/lib/base/model/diagram-loader.d.ts.map +1 -1
  20. package/lib/base/model/diagram-loader.js +6 -1
  21. package/lib/base/model/diagram-loader.js.map +1 -1
  22. package/lib/base/mouse-position-tracker.d.ts +22 -0
  23. package/lib/base/mouse-position-tracker.d.ts.map +1 -0
  24. package/lib/base/mouse-position-tracker.js +40 -0
  25. package/lib/base/mouse-position-tracker.js.map +1 -0
  26. package/lib/features/accessibility/view-key-tools/movement-key-tool.d.ts +2 -0
  27. package/lib/features/accessibility/view-key-tools/movement-key-tool.d.ts.map +1 -1
  28. package/lib/features/accessibility/view-key-tools/movement-key-tool.js +15 -7
  29. package/lib/features/accessibility/view-key-tools/movement-key-tool.js.map +1 -1
  30. package/lib/features/bounds/bounds-module.d.ts.map +1 -1
  31. package/lib/features/bounds/bounds-module.js +2 -0
  32. package/lib/features/bounds/bounds-module.js.map +1 -1
  33. package/lib/features/bounds/freeform-layout.d.ts +17 -1
  34. package/lib/features/bounds/freeform-layout.d.ts.map +1 -1
  35. package/lib/features/bounds/freeform-layout.js +14 -5
  36. package/lib/features/bounds/freeform-layout.js.map +1 -1
  37. package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts +5 -4
  38. package/lib/features/bounds/glsp-hidden-bounds-updater.d.ts.map +1 -1
  39. package/lib/features/bounds/glsp-hidden-bounds-updater.js +51 -39
  40. package/lib/features/bounds/glsp-hidden-bounds-updater.js.map +1 -1
  41. package/lib/features/bounds/hbox-layout.d.ts +18 -2
  42. package/lib/features/bounds/hbox-layout.d.ts.map +1 -1
  43. package/lib/features/bounds/hbox-layout.js +14 -5
  44. package/lib/features/bounds/hbox-layout.js.map +1 -1
  45. package/lib/features/bounds/index.d.ts +1 -0
  46. package/lib/features/bounds/index.d.ts.map +1 -1
  47. package/lib/features/bounds/index.js +1 -0
  48. package/lib/features/bounds/index.js.map +1 -1
  49. package/lib/features/bounds/layout-data.d.ts +27 -0
  50. package/lib/features/bounds/layout-data.d.ts.map +1 -0
  51. package/lib/features/bounds/layout-data.js +48 -0
  52. package/lib/features/bounds/layout-data.js.map +1 -0
  53. package/lib/features/bounds/local-bounds.d.ts +3 -1
  54. package/lib/features/bounds/local-bounds.d.ts.map +1 -1
  55. package/lib/features/bounds/local-bounds.js +14 -0
  56. package/lib/features/bounds/local-bounds.js.map +1 -1
  57. package/lib/features/bounds/vbox-layout.d.ts +18 -2
  58. package/lib/features/bounds/vbox-layout.d.ts.map +1 -1
  59. package/lib/features/bounds/vbox-layout.js +14 -5
  60. package/lib/features/bounds/vbox-layout.js.map +1 -1
  61. package/lib/features/change-bounds/index.d.ts +1 -0
  62. package/lib/features/change-bounds/index.d.ts.map +1 -1
  63. package/lib/features/change-bounds/index.js +1 -0
  64. package/lib/features/change-bounds/index.js.map +1 -1
  65. package/lib/features/change-bounds/model.d.ts +19 -3
  66. package/lib/features/change-bounds/model.d.ts.map +1 -1
  67. package/lib/features/change-bounds/model.js +92 -4
  68. package/lib/features/change-bounds/model.js.map +1 -1
  69. package/lib/features/change-bounds/movement-restrictor.d.ts +1 -0
  70. package/lib/features/change-bounds/movement-restrictor.d.ts.map +1 -1
  71. package/lib/features/change-bounds/movement-restrictor.js +7 -1
  72. package/lib/features/change-bounds/movement-restrictor.js.map +1 -1
  73. package/lib/features/change-bounds/point-position-updater.d.ts +3 -0
  74. package/lib/features/change-bounds/point-position-updater.d.ts.map +1 -1
  75. package/lib/features/change-bounds/point-position-updater.js +7 -2
  76. package/lib/features/change-bounds/point-position-updater.js.map +1 -1
  77. package/lib/features/change-bounds/position-snapper.d.ts +4 -0
  78. package/lib/features/change-bounds/position-snapper.d.ts.map +1 -1
  79. package/lib/features/change-bounds/position-snapper.js +4 -0
  80. package/lib/features/change-bounds/position-snapper.js.map +1 -1
  81. package/lib/features/change-bounds/snap.d.ts +6 -0
  82. package/lib/features/change-bounds/snap.d.ts.map +1 -1
  83. package/lib/features/change-bounds/snap.js +6 -0
  84. package/lib/features/change-bounds/snap.js.map +1 -1
  85. package/lib/features/change-bounds/tracker.d.ts +32 -0
  86. package/lib/features/change-bounds/tracker.d.ts.map +1 -0
  87. package/lib/features/change-bounds/tracker.js +60 -0
  88. package/lib/features/change-bounds/tracker.js.map +1 -0
  89. package/lib/features/debug/debug-bounds-decorator.d.ts +4 -1
  90. package/lib/features/debug/debug-bounds-decorator.d.ts.map +1 -1
  91. package/lib/features/debug/debug-bounds-decorator.js +14 -7
  92. package/lib/features/debug/debug-bounds-decorator.js.map +1 -1
  93. package/lib/features/element-template/mouse-tracking-element-position-listener.d.ts +9 -22
  94. package/lib/features/element-template/mouse-tracking-element-position-listener.d.ts.map +1 -1
  95. package/lib/features/element-template/mouse-tracking-element-position-listener.js +30 -46
  96. package/lib/features/element-template/mouse-tracking-element-position-listener.js.map +1 -1
  97. package/lib/features/helper-lines/helper-line-feedback.d.ts +2 -2
  98. package/lib/features/helper-lines/helper-line-feedback.d.ts.map +1 -1
  99. package/lib/features/helper-lines/helper-line-feedback.js +1 -1
  100. package/lib/features/helper-lines/helper-line-feedback.js.map +1 -1
  101. package/lib/features/helper-lines/helper-line-manager-default.d.ts +2 -1
  102. package/lib/features/helper-lines/helper-line-manager-default.d.ts.map +1 -1
  103. package/lib/features/helper-lines/helper-line-manager-default.js +23 -0
  104. package/lib/features/helper-lines/helper-line-manager-default.js.map +1 -1
  105. package/lib/features/helper-lines/helper-line-manager.d.ts +10 -2
  106. package/lib/features/helper-lines/helper-line-manager.d.ts.map +1 -1
  107. package/lib/features/routing/edge-router.d.ts +4 -0
  108. package/lib/features/routing/edge-router.d.ts.map +1 -1
  109. package/lib/features/routing/edge-router.js +37 -0
  110. package/lib/features/routing/edge-router.js.map +1 -1
  111. package/lib/features/select/select-mouse-listener.d.ts +3 -0
  112. package/lib/features/select/select-mouse-listener.d.ts.map +1 -1
  113. package/lib/features/select/select-mouse-listener.js +30 -2
  114. package/lib/features/select/select-mouse-listener.js.map +1 -1
  115. package/lib/features/tools/base-tools.d.ts +24 -15
  116. package/lib/features/tools/base-tools.d.ts.map +1 -1
  117. package/lib/features/tools/base-tools.js +0 -18
  118. package/lib/features/tools/base-tools.js.map +1 -1
  119. package/lib/features/tools/change-bounds/change-bounds-manager.d.ts +42 -0
  120. package/lib/features/tools/change-bounds/change-bounds-manager.d.ts.map +1 -0
  121. package/lib/features/tools/change-bounds/change-bounds-manager.js +136 -0
  122. package/lib/features/tools/change-bounds/change-bounds-manager.js.map +1 -0
  123. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.d.ts +6 -0
  124. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.d.ts.map +1 -1
  125. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js +14 -8
  126. package/lib/features/tools/change-bounds/change-bounds-tool-feedback.js.map +1 -1
  127. package/lib/features/tools/change-bounds/change-bounds-tool-module.d.ts.map +1 -1
  128. package/lib/features/tools/change-bounds/change-bounds-tool-module.js +2 -0
  129. package/lib/features/tools/change-bounds/change-bounds-tool-module.js.map +1 -1
  130. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.d.ts +6 -15
  131. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.d.ts.map +1 -1
  132. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js +24 -72
  133. package/lib/features/tools/change-bounds/change-bounds-tool-move-feedback.js.map +1 -1
  134. package/lib/features/tools/change-bounds/change-bounds-tool.d.ts +14 -25
  135. package/lib/features/tools/change-bounds/change-bounds-tool.d.ts.map +1 -1
  136. package/lib/features/tools/change-bounds/change-bounds-tool.js +63 -109
  137. package/lib/features/tools/change-bounds/change-bounds-tool.js.map +1 -1
  138. package/lib/features/tools/change-bounds/change-bounds-tracker.d.ts +136 -0
  139. package/lib/features/tools/change-bounds/change-bounds-tracker.d.ts.map +1 -0
  140. package/lib/features/tools/change-bounds/change-bounds-tracker.js +301 -0
  141. package/lib/features/tools/change-bounds/change-bounds-tracker.js.map +1 -0
  142. package/lib/features/tools/change-bounds/index.d.ts +2 -0
  143. package/lib/features/tools/change-bounds/index.d.ts.map +1 -1
  144. package/lib/features/tools/change-bounds/index.js +2 -0
  145. package/lib/features/tools/change-bounds/index.js.map +1 -1
  146. package/lib/features/tools/change-bounds/view.d.ts.map +1 -1
  147. package/lib/features/tools/change-bounds/view.js +1 -16
  148. package/lib/features/tools/change-bounds/view.js.map +1 -1
  149. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts +7 -9
  150. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.d.ts.map +1 -1
  151. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js +27 -47
  152. package/lib/features/tools/edge-edit/edge-edit-tool-feedback.js.map +1 -1
  153. package/lib/features/tools/edge-edit/edge-edit-tool.d.ts +2 -2
  154. package/lib/features/tools/edge-edit/edge-edit-tool.d.ts.map +1 -1
  155. package/lib/features/tools/edge-edit/edge-edit-tool.js +5 -5
  156. package/lib/features/tools/edge-edit/edge-edit-tool.js.map +1 -1
  157. package/lib/features/tools/marquee-selection/marquee-mouse-tool.d.ts +1 -0
  158. package/lib/features/tools/marquee-selection/marquee-mouse-tool.d.ts.map +1 -1
  159. package/lib/features/tools/marquee-selection/marquee-mouse-tool.js +3 -0
  160. package/lib/features/tools/marquee-selection/marquee-mouse-tool.js.map +1 -1
  161. package/lib/features/tools/node-creation/node-creation-tool.d.ts +2 -4
  162. package/lib/features/tools/node-creation/node-creation-tool.d.ts.map +1 -1
  163. package/lib/features/tools/node-creation/node-creation-tool.js +8 -11
  164. package/lib/features/tools/node-creation/node-creation-tool.js.map +1 -1
  165. package/lib/features/viewport/viewport-handler.d.ts +6 -4
  166. package/lib/features/viewport/viewport-handler.d.ts.map +1 -1
  167. package/lib/features/viewport/viewport-handler.js +13 -8
  168. package/lib/features/viewport/viewport-handler.js.map +1 -1
  169. package/lib/utils/gmodel-util.d.ts +20 -1
  170. package/lib/utils/gmodel-util.d.ts.map +1 -1
  171. package/lib/utils/gmodel-util.js +38 -16
  172. package/lib/utils/gmodel-util.js.map +1 -1
  173. package/lib/utils/layout-utils.d.ts +1 -0
  174. package/lib/utils/layout-utils.d.ts.map +1 -1
  175. package/lib/utils/layout-utils.js +5 -1
  176. package/lib/utils/layout-utils.js.map +1 -1
  177. package/package.json +3 -3
  178. package/src/base/default.module.ts +4 -1
  179. package/src/base/feedback/css-feedback.ts +10 -2
  180. package/src/base/feedback/feeback-emitter.ts +6 -3
  181. package/src/base/index.ts +1 -0
  182. package/src/base/model/diagram-loader.ts +5 -1
  183. package/src/base/mouse-position-tracker.ts +25 -0
  184. package/src/features/accessibility/view-key-tools/movement-key-tool.ts +12 -7
  185. package/src/features/bounds/bounds-module.ts +2 -0
  186. package/src/features/bounds/freeform-layout.ts +16 -6
  187. package/src/features/bounds/glsp-hidden-bounds-updater.ts +63 -46
  188. package/src/features/bounds/hbox-layout.ts +18 -9
  189. package/src/features/bounds/index.ts +1 -0
  190. package/src/features/bounds/layout-data.ts +48 -0
  191. package/src/features/bounds/local-bounds.ts +20 -4
  192. package/src/features/bounds/vbox-layout.ts +18 -10
  193. package/src/features/change-bounds/index.ts +1 -0
  194. package/src/features/change-bounds/model.ts +104 -4
  195. package/src/features/change-bounds/movement-restrictor.ts +10 -0
  196. package/src/features/change-bounds/point-position-updater.spec.ts +2 -0
  197. package/src/features/change-bounds/point-position-updater.ts +6 -0
  198. package/src/features/change-bounds/position-snapper.ts +4 -0
  199. package/src/features/change-bounds/snap.ts +6 -0
  200. package/src/features/change-bounds/tracker.ts +63 -0
  201. package/src/features/debug/debug-bounds-decorator.tsx +17 -7
  202. package/src/features/element-template/mouse-tracking-element-position-listener.ts +49 -71
  203. package/src/features/helper-lines/helper-line-feedback.ts +2 -1
  204. package/src/features/helper-lines/helper-line-manager-default.ts +37 -2
  205. package/src/features/helper-lines/helper-line-manager.ts +11 -2
  206. package/src/features/routing/edge-router.ts +42 -0
  207. package/src/features/select/select-mouse-listener.ts +15 -1
  208. package/src/features/tools/base-tools.ts +31 -19
  209. package/src/features/tools/change-bounds/change-bounds-manager.ts +145 -0
  210. package/src/features/tools/change-bounds/change-bounds-tool-feedback.ts +17 -6
  211. package/src/features/tools/change-bounds/change-bounds-tool-module.ts +2 -0
  212. package/src/features/tools/change-bounds/change-bounds-tool-move-feedback.ts +31 -81
  213. package/src/features/tools/change-bounds/change-bounds-tool.ts +89 -148
  214. package/src/features/tools/change-bounds/change-bounds-tracker.ts +455 -0
  215. package/src/features/tools/change-bounds/index.ts +2 -0
  216. package/src/features/tools/change-bounds/view.tsx +2 -14
  217. package/src/features/tools/edge-edit/edge-edit-tool-feedback.ts +34 -52
  218. package/src/features/tools/edge-edit/edge-edit-tool.ts +4 -3
  219. package/src/features/tools/marquee-selection/marquee-mouse-tool.ts +4 -0
  220. package/src/features/tools/node-creation/node-creation-tool.ts +7 -7
  221. package/src/features/viewport/viewport-handler.ts +13 -7
  222. package/src/utils/gmodel-util.ts +41 -5
  223. package/src/utils/layout-utils.ts +4 -0
@@ -31,6 +31,7 @@ import {
31
31
  } from '@eclipse-glsp/sprotty';
32
32
  import { inject, injectable } from 'inversify';
33
33
  import { ServerAction } from '../../base/model/glsp-model-source';
34
+ import { LayoutAware } from './layout-data';
34
35
 
35
36
  export interface LocalRequestBoundsAction extends RequestBoundsAction {
36
37
  elementIDs?: string[];
@@ -41,9 +42,11 @@ export namespace LocalRequestBoundsAction {
41
42
  return RequestBoundsAction.is(object) && !ServerAction.is(object) && hasArrayProp(object, 'elementIDs', true);
42
43
  }
43
44
 
44
- export function create(newRoot: GModelRootSchema, elementIDs?: string[]): LocalRequestBoundsAction {
45
+ export function create(newRoot: GModelRoot, elementIDs?: string[]): LocalRequestBoundsAction;
46
+ export function create(newRoot: GModelRootSchema, elementIDs?: string[]): LocalRequestBoundsAction;
47
+ export function create(newRoot: GModelRoot | GModelRootSchema, elementIDs?: string[]): LocalRequestBoundsAction {
45
48
  return {
46
- ...RequestBoundsAction.create(newRoot),
49
+ ...RequestBoundsAction.create(newRoot as unknown as GModelRootSchema),
47
50
  elementIDs
48
51
  };
49
52
  }
@@ -55,7 +58,7 @@ export namespace LocalRequestBoundsAction {
55
58
  elementIDs?: string[]
56
59
  ): CommandResult {
57
60
  // do not modify the main model (modelChanged = false) but request local bounds calculation on hidden model
58
- actionDispatcher.dispatch(LocalRequestBoundsAction.create(root as unknown as GModelRootSchema, elementIDs));
61
+ actionDispatcher.dispatch(LocalRequestBoundsAction.create(root, elementIDs));
59
62
  return {
60
63
  model: root,
61
64
  modelChanged: false,
@@ -65,7 +68,7 @@ export namespace LocalRequestBoundsAction {
65
68
  }
66
69
 
67
70
  export namespace LocalComputedBoundsAction {
68
- export function is(object: unknown): object is RequestBoundsAction {
71
+ export function is(object: unknown): object is ComputedBoundsAction & ServerAction {
69
72
  return ComputedBoundsAction.is(object) && ServerAction.is(object);
70
73
  }
71
74
 
@@ -94,9 +97,22 @@ export class LocalComputedBoundsCommand extends Command {
94
97
  }
95
98
  // apply computed bounds from the hidden model and return updated model to render new main model
96
99
  this.computedBoundsApplicator.apply(context.root as unknown as GModelRootSchema, this.action);
100
+ this.action.layoutData?.forEach(({ elementId, layoutData }) => {
101
+ const element = context.root.index.getById(elementId);
102
+ if (element !== undefined) {
103
+ LayoutAware.setLayoutData(element, layoutData);
104
+ }
105
+ });
97
106
  return context.root;
98
107
  }
99
108
 
109
+ this.action.layoutData?.forEach(({ elementId, layoutData }) => {
110
+ const element = context.root.index.getById(elementId);
111
+ if (element !== undefined) {
112
+ LayoutAware.setLayoutData(element, layoutData);
113
+ }
114
+ });
115
+
100
116
  // computed bounds action from server -> we do not care and do not trigger any update of the main model
101
117
  return {
102
118
  model: context.root,
@@ -13,22 +13,23 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
- import { injectable } from 'inversify';
17
16
  import {
18
17
  Bounds,
19
18
  BoundsData,
20
19
  Dimension,
21
20
  GChildElement,
22
- LayoutContainer,
23
- Point,
24
21
  GModelElement,
25
22
  GParentElement,
23
+ LayoutContainer,
24
+ Point,
26
25
  StatefulLayouter,
27
26
  VBoxLayoutOptions,
28
27
  VBoxLayouter,
29
28
  isBoundsAware,
30
29
  isLayoutableChild
31
30
  } from '@eclipse-glsp/sprotty';
31
+ import { injectable } from 'inversify';
32
+ import { LayoutAware } from './layout-data';
32
33
 
33
34
  export interface VBoxLayoutOptionsExt extends VBoxLayoutOptions {
34
35
  hGrab: boolean;
@@ -79,7 +80,9 @@ export class VBoxLayouterExt extends VBoxLayouter {
79
80
 
80
81
  if (maxWidth > 0 && maxHeight > 0) {
81
82
  const offset = this.layoutChildren(container, layouter, options, width, height, grabHeight, grabbingChildren);
82
- boundsData.bounds = this.getFinalContainerBounds(container, offset, options, childrenSize.width, childrenSize.height);
83
+ const computed = this.getComputedContainerDimensions(options, childrenSize.width, childrenSize.height);
84
+ LayoutAware.setComputedDimensions(boundsData, computed);
85
+ boundsData.bounds = this.getFinalContainerBounds(container, offset, options, computed.width, computed.height);
83
86
  boundsData.boundsChanged = true;
84
87
  }
85
88
  }
@@ -223,24 +226,29 @@ export class VBoxLayouterExt extends VBoxLayouter {
223
226
  return (element as any).layoutOptions;
224
227
  }
225
228
 
229
+ protected getComputedContainerDimensions(options: VBoxLayoutOptionsExt, maxWidth: number, maxHeight: number): Dimension {
230
+ return {
231
+ width: maxWidth + options.paddingLeft + options.paddingRight,
232
+ height: maxHeight + options.paddingTop + options.paddingBottom
233
+ };
234
+ }
235
+
226
236
  protected override getFinalContainerBounds(
227
237
  container: GParentElement & LayoutContainer,
228
238
  lastOffset: Point,
229
239
  options: VBoxLayoutOptionsExt,
230
- maxWidth: number,
231
- maxHeight: number
240
+ computedWidth: number,
241
+ computedHeight: number
232
242
  ): Bounds {
233
243
  const elementOptions = this.getElementLayoutOptions(container);
234
244
  const width = elementOptions?.prefWidth ?? options.minWidth;
235
245
  const height = elementOptions?.prefHeight ?? options.minHeight;
236
-
237
246
  const result = {
238
247
  x: container.bounds.x,
239
248
  y: container.bounds.y,
240
- width: Math.max(width, maxWidth + options.paddingLeft + options.paddingRight),
241
- height: Math.max(height, maxHeight + options.paddingTop + options.paddingBottom)
249
+ width: Math.max(width, computedWidth),
250
+ height: Math.max(height, computedHeight)
242
251
  };
243
-
244
252
  return result;
245
253
  }
246
254
 
@@ -18,3 +18,4 @@ export * from './movement-restrictor';
18
18
  export * from './point-position-updater';
19
19
  export * from './position-snapper';
20
20
  export * from './snap';
21
+ export * from './tracker';
@@ -14,15 +14,18 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
  import {
17
+ Bounds,
17
18
  GChildElement,
18
19
  GModelElement,
19
20
  GParentElement,
20
21
  Hoverable,
22
+ Point,
21
23
  hoverFeedbackFeature,
22
24
  isBoundsAware,
23
25
  isMoveable,
24
26
  isSelectable
25
27
  } from '@eclipse-glsp/sprotty';
28
+ import { CursorCSS } from '../../base';
26
29
  import { BoundsAwareModelElement, MoveableElement, ResizableModelElement } from '../../utils';
27
30
 
28
31
  export const resizeFeature = Symbol('resizeFeature');
@@ -34,9 +37,36 @@ export function isResizable(element: GModelElement): element is ResizableModelEl
34
37
  // eslint-disable-next-line no-shadow
35
38
  export enum ResizeHandleLocation {
36
39
  TopLeft = 'top-left',
40
+ Top = 'top',
37
41
  TopRight = 'top-right',
42
+ Right = 'right',
43
+ BottomRight = 'bottom-right',
44
+ Bottom = 'bottom',
38
45
  BottomLeft = 'bottom-left',
39
- BottomRight = 'bottom-right'
46
+ Left = 'left'
47
+ }
48
+
49
+ export namespace ResizeHandleLocation {
50
+ export function opposite(location: ResizeHandleLocation): ResizeHandleLocation {
51
+ switch (location) {
52
+ case ResizeHandleLocation.TopLeft:
53
+ return ResizeHandleLocation.BottomRight;
54
+ case ResizeHandleLocation.Top:
55
+ return ResizeHandleLocation.Bottom;
56
+ case ResizeHandleLocation.TopRight:
57
+ return ResizeHandleLocation.BottomLeft;
58
+ case ResizeHandleLocation.Right:
59
+ return ResizeHandleLocation.Left;
60
+ case ResizeHandleLocation.BottomRight:
61
+ return ResizeHandleLocation.TopLeft;
62
+ case ResizeHandleLocation.Bottom:
63
+ return ResizeHandleLocation.Top;
64
+ case ResizeHandleLocation.BottomLeft:
65
+ return ResizeHandleLocation.TopRight;
66
+ case ResizeHandleLocation.Left:
67
+ return ResizeHandleLocation.Right;
68
+ }
69
+ }
40
70
  }
41
71
 
42
72
  export function isBoundsAwareMoveable(element: GModelElement): element is BoundsAwareModelElement & MoveableElement {
@@ -64,18 +94,34 @@ export class SResizeHandle extends GChildElement implements Hoverable {
64
94
  return this.location === ResizeHandleLocation.TopLeft;
65
95
  }
66
96
 
67
- isSeResize(): boolean {
68
- return this.location === ResizeHandleLocation.BottomRight;
97
+ isNResize(): boolean {
98
+ return this.location === ResizeHandleLocation.Top;
69
99
  }
70
100
 
71
101
  isNeResize(): boolean {
72
102
  return this.location === ResizeHandleLocation.TopRight;
73
103
  }
74
104
 
105
+ isEResize(): boolean {
106
+ return this.location === ResizeHandleLocation.Right;
107
+ }
108
+
109
+ isSeResize(): boolean {
110
+ return this.location === ResizeHandleLocation.BottomRight;
111
+ }
112
+
113
+ isSResize(): boolean {
114
+ return this.location === ResizeHandleLocation.Bottom;
115
+ }
116
+
75
117
  isSwResize(): boolean {
76
118
  return this.location === ResizeHandleLocation.BottomLeft;
77
119
  }
78
120
 
121
+ isWResize(): boolean {
122
+ return this.location === ResizeHandleLocation.Left;
123
+ }
124
+
79
125
  isNwSeResize(): boolean {
80
126
  return this.isNwResize() || this.isSeResize();
81
127
  }
@@ -83,18 +129,72 @@ export class SResizeHandle extends GChildElement implements Hoverable {
83
129
  isNeSwResize(): boolean {
84
130
  return this.isNeResize() || this.isSwResize();
85
131
  }
132
+
133
+ static getHandlePosition(handle: SResizeHandle): Point;
134
+ static getHandlePosition(parent: ResizableModelElement, location: ResizeHandleLocation): Point;
135
+ static getHandlePosition(bounds: Bounds, location: ResizeHandleLocation): Point;
136
+ static getHandlePosition(first: ResizableModelElement | SResizeHandle | Bounds, second?: ResizeHandleLocation): Point {
137
+ const bounds = SResizeHandle.is(first) ? first.parent.bounds : first instanceof GModelElement ? first.bounds : first;
138
+ const location = SResizeHandle.is(first) ? first.location : second!;
139
+ switch (location) {
140
+ case ResizeHandleLocation.TopLeft:
141
+ return Bounds.topLeft(bounds);
142
+ case ResizeHandleLocation.Top:
143
+ return Bounds.topCenter(bounds);
144
+ case ResizeHandleLocation.TopRight:
145
+ return Bounds.topRight(bounds);
146
+ case ResizeHandleLocation.Right:
147
+ return Bounds.middleRight(bounds);
148
+ case ResizeHandleLocation.BottomRight:
149
+ return Bounds.bottomRight(bounds);
150
+ case ResizeHandleLocation.Bottom:
151
+ return Bounds.bottomCenter(bounds);
152
+ case ResizeHandleLocation.BottomLeft:
153
+ return Bounds.bottomLeft(bounds);
154
+ case ResizeHandleLocation.Left:
155
+ return Bounds.middleLeft(bounds);
156
+ }
157
+ }
158
+
159
+ static getCursorCss(handle: SResizeHandle): string {
160
+ switch (handle.location) {
161
+ case ResizeHandleLocation.TopLeft:
162
+ return CursorCSS.RESIZE_NW;
163
+ case ResizeHandleLocation.Top:
164
+ return CursorCSS.RESIZE_N;
165
+ case ResizeHandleLocation.TopRight:
166
+ return CursorCSS.RESIZE_NE;
167
+ case ResizeHandleLocation.Right:
168
+ return CursorCSS.RESIZE_E;
169
+ case ResizeHandleLocation.BottomRight:
170
+ return CursorCSS.RESIZE_SE;
171
+ case ResizeHandleLocation.Bottom:
172
+ return CursorCSS.RESIZE_S;
173
+ case ResizeHandleLocation.BottomLeft:
174
+ return CursorCSS.RESIZE_SW;
175
+ case ResizeHandleLocation.Left:
176
+ return CursorCSS.RESIZE_W;
177
+ }
178
+ }
179
+
180
+ static is(handle: unknown): handle is SResizeHandle {
181
+ return typeof handle === 'object' && !!handle && 'type' in handle && handle.type === SResizeHandle.TYPE;
182
+ }
86
183
  }
87
184
 
88
185
  export function addResizeHandles(
89
186
  element: ResizableModelElement,
90
187
  locations: ResizeHandleLocation[] = [
91
188
  ResizeHandleLocation.TopLeft,
92
- ResizeHandleLocation.TopRight,
189
+ ResizeHandleLocation.Top,
93
190
  ResizeHandleLocation.BottomLeft,
94
191
  ResizeHandleLocation.BottomRight
95
192
  ]
96
193
  ): void {
97
194
  for (const location of Object.values(ResizeHandleLocation)) {
195
+ if (typeof location === 'function') {
196
+ continue;
197
+ }
98
198
  const existing = element.children.find(child => child instanceof SResizeHandle && child.location === location);
99
199
  if (locations.includes(location) && !existing) {
100
200
  // add missing handle
@@ -108,3 +108,13 @@ export function removeMovementRestrictionFeedback(
108
108
 
109
109
  return ModifyCSSFeedbackAction.create({ elements, remove: movementRestrictor.cssClasses });
110
110
  }
111
+
112
+ export function movementRestrictionFeedback(
113
+ element: GModelElement,
114
+ movementRestrictor: IMovementRestrictor,
115
+ valid: boolean
116
+ ): ModifyCSSFeedbackAction {
117
+ return valid
118
+ ? removeMovementRestrictionFeedback(element, movementRestrictor)
119
+ : createMovementRestrictionFeedback(element, movementRestrictor);
120
+ }
@@ -13,6 +13,8 @@
13
13
  *
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
+ /* eslint-disable import/no-deprecated */
17
+ /* eslint-disable deprecation/deprecation */
16
18
 
17
19
  import { GModelElement } from '@eclipse-glsp/sprotty';
18
20
  import { expect } from 'chai';
@@ -14,6 +14,9 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
  /* eslint-disable @typescript-eslint/no-shadow */
17
+ /* eslint-disable import/no-deprecated */
18
+ /* eslint-disable deprecation/deprecation */
19
+
17
20
  import { GModelElement, ISnapper, Point, Writable } from '@eclipse-glsp/sprotty';
18
21
  import { calculateDeltaBetweenPoints } from '../../utils/gmodel-util';
19
22
  import { isMouseEvent } from '../../utils/html-utils';
@@ -29,6 +32,9 @@ import { useSnap } from './snap';
29
32
  *
30
33
  * You can initialize a this class with a optional {@link ISnapper}. If a
31
34
  * snapper is present, the positions will be snapped to the defined grid.
35
+ *
36
+ * @deprecated The use of this class is discouraged. Use the {@link ChangeBoundsManager.createTracker}
37
+ * instead which centralized a few aspects of the tracking.
32
38
  */
33
39
  export class PointPositionUpdater {
34
40
  protected positionSnapper: PositionSnapper;
@@ -18,6 +18,10 @@ import { inject, injectable, optional } from 'inversify';
18
18
  import { IHelperLineManager } from '../helper-lines/helper-line-manager';
19
19
  import { Direction, HelperLine, isHelperLine } from '../helper-lines/model';
20
20
 
21
+ /**
22
+ * @deprecated The use of this class is discouraged. Use the {@link ChangeBoundsManager.createTracker}
23
+ * instead which centralized a few aspects of the tracking.
24
+ */
21
25
  @injectable()
22
26
  export class PositionSnapper {
23
27
  constructor(
@@ -16,10 +16,16 @@
16
16
  /* eslint-disable @typescript-eslint/no-shadow */
17
17
  import { KeyboardModifier } from '@eclipse-glsp/sprotty';
18
18
 
19
+ /**
20
+ * @deprecated Use {@link ChangeBoundsManager.useSnap} instead which may be customized.
21
+ */
19
22
  export function useSnap(event: MouseEvent | KeyboardEvent): boolean {
20
23
  return !event.shiftKey;
21
24
  }
22
25
 
26
+ /**
27
+ * @deprecated Use {@link ChangeBoundsManager.unsnapModifier} instead which may be customized.
28
+ */
23
29
  export function unsnapModifier(): KeyboardModifier {
24
30
  return 'shift';
25
31
  }
@@ -0,0 +1,63 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2024 Axon Ivy AG and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+ import { Disposable, MousePositionTracker, Movement, Point, Vector } from '@eclipse-glsp/sprotty';
17
+
18
+ export class MovementCalculator implements Disposable {
19
+ protected position?: Point;
20
+
21
+ setPosition(position: Point): void {
22
+ this.position = { ...position };
23
+ }
24
+
25
+ updatePosition(param: Vector | Movement): void {
26
+ const vector = Vector.is(param) ? param : param.vector;
27
+ this.setPosition(Point.add(this.position ?? Point.ORIGIN, vector));
28
+ }
29
+
30
+ get hasPosition(): boolean {
31
+ return this.position !== undefined;
32
+ }
33
+
34
+ calculateMoveTo(targetPosition: Point): Movement {
35
+ return !this.position ? Movement.ZERO : Point.move(this.position, targetPosition);
36
+ }
37
+
38
+ dispose(): void {
39
+ this.position = undefined;
40
+ }
41
+ }
42
+
43
+ export class DiagramMovementCalculator extends MovementCalculator {
44
+ constructor(readonly positionTracker: MousePositionTracker) {
45
+ super();
46
+ }
47
+
48
+ init(): void {
49
+ const position = this.positionTracker.lastPositionOnDiagram;
50
+ if (position) {
51
+ this.setPosition(position);
52
+ }
53
+ }
54
+
55
+ calculateMoveToCurrent(): Movement {
56
+ const targetPosition = this.positionTracker.lastPositionOnDiagram;
57
+ return targetPosition ? this.calculateMoveTo(targetPosition) : Movement.ZERO;
58
+ }
59
+
60
+ reset(): void {
61
+ this.dispose();
62
+ }
63
+ }
@@ -15,7 +15,7 @@
15
15
  ********************************************************************************/
16
16
  /* eslint-disable max-len */
17
17
 
18
- import { Bounds, GModelElement, IVNodePostprocessor, Point, TYPES, isBoundsAware, setClass, svg } from '@eclipse-glsp/sprotty';
18
+ import { Bounds, GModelElement, IVNodePostprocessor, Point, TYPES, isDecoration, isSizeable, setClass, svg } from '@eclipse-glsp/sprotty';
19
19
  import { inject, injectable, optional } from 'inversify';
20
20
  import { VNode } from 'snabbdom';
21
21
  import { GGraph } from '../../model';
@@ -25,6 +25,8 @@ import { DebugManager } from './debug-manager';
25
25
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
26
  const JSX = { createElement: svg };
27
27
 
28
+ export const CSS_DEBUG_BOUNDS = 'debug-bounds';
29
+
28
30
  @injectable()
29
31
  export class DebugBoundsDecorator implements IVNodePostprocessor {
30
32
  @inject(TYPES.IDebugManager) @optional() protected debugManager?: DebugManager;
@@ -33,10 +35,10 @@ export class DebugBoundsDecorator implements IVNodePostprocessor {
33
35
  if (!this.debugManager?.isDebugEnabled) {
34
36
  return vnode;
35
37
  }
36
- if (isBoundsAware(element)) {
37
- this.decorateBoundsAware(vnode, element);
38
+ if (isSizeable(element) && this.shouldDecorateSizeable(element)) {
39
+ this.decorateSizeable(vnode, element);
38
40
  }
39
- if (element instanceof GGraph) {
41
+ if (element instanceof GGraph && this.shouldDecorateGraph(element)) {
40
42
  this.decorateGraph(vnode, element);
41
43
  }
42
44
  return vnode;
@@ -48,8 +50,12 @@ export class DebugBoundsDecorator implements IVNodePostprocessor {
48
50
  return 5;
49
51
  }
50
52
 
53
+ protected shouldDecorateGraph(graph: GGraph): boolean {
54
+ return true;
55
+ }
56
+
51
57
  protected decorateGraph(vnode: VNode, graph: GGraph): void {
52
- setClass(vnode, 'debug-bounds', true);
58
+ setClass(vnode, CSS_DEBUG_BOUNDS, true);
53
59
  const svgChild = vnode.children?.find(child => typeof child !== 'string' && child.sel === 'svg') as VNode | undefined;
54
60
  const group = svgChild?.children?.find(child => typeof child !== 'string' && child.sel === 'g') as VNode | undefined;
55
61
  group?.children?.push(this.renderOrigin(graph));
@@ -67,8 +73,12 @@ export class DebugBoundsDecorator implements IVNodePostprocessor {
67
73
  );
68
74
  }
69
75
 
70
- protected decorateBoundsAware(vnode: VNode, element: BoundsAwareModelElement): void {
71
- setClass(vnode, 'debug-bounds', true);
76
+ protected shouldDecorateSizeable(element: BoundsAwareModelElement): boolean {
77
+ return !isDecoration(element);
78
+ }
79
+
80
+ protected decorateSizeable(vnode: VNode, element: BoundsAwareModelElement): void {
81
+ setClass(vnode, CSS_DEBUG_BOUNDS, true);
72
82
  vnode.children?.push(this.renderTopLeftCorner(element));
73
83
  vnode.children?.push(this.renderTopRightCorner(element));
74
84
  vnode.children?.push(this.renderBottomLeftCorner(element));
@@ -14,55 +14,27 @@
14
14
  * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  ********************************************************************************/
16
16
 
17
- import {
18
- Action,
19
- Dimension,
20
- Disposable,
21
- ElementMove,
22
- GModelElement,
23
- MoveAction,
24
- Point,
25
- isBoundsAware,
26
- isMoveable
27
- } from '@eclipse-glsp/sprotty';
28
- import { injectable } from 'inversify';
17
+ import { Action, Dimension, GModelElement, MoveAction, Point, isBoundsAware, isMoveable } from '@eclipse-glsp/sprotty';
29
18
  import { DragAwareMouseListener } from '../../base/drag-aware-mouse-listener';
30
19
  import { CSS_HIDDEN, ModifyCSSFeedbackAction } from '../../base/feedback/css-feedback';
31
20
  import { FeedbackEmitter } from '../../base/feedback/feeback-emitter';
32
- import { IFeedbackEmitter } from '../../base/feedback/feedback-action-dispatcher';
33
- import { Tool } from '../../base/tool-manager/tool';
34
- import { MoveableElement } from '../../utils';
35
- import { getAbsolutePosition } from '../../utils/viewpoint-util';
21
+ import { MoveableElement, getAbsolutePosition } from '../../utils';
36
22
  import {
37
- IMovementRestrictor,
38
- createMovementRestrictionFeedback,
39
- removeMovementRestrictionFeedback
40
- } from '../change-bounds/movement-restrictor';
41
- import { PointPositionUpdater } from '../change-bounds/point-position-updater';
42
- import { PositionSnapper } from '../change-bounds/position-snapper';
43
- import { useSnap } from '../change-bounds/snap';
44
- import { MoveFinishedEventAction } from '../tools';
45
-
46
- export interface PositioningTool extends Tool {
47
- readonly positionSnapper: PositionSnapper;
48
- readonly movementRestrictor?: IMovementRestrictor;
23
+ CSS_RESIZE_MODE,
24
+ ChangeBoundsManager,
25
+ ChangeBoundsTracker,
26
+ FeedbackAwareTool,
27
+ MoveFinishedEventAction,
28
+ TrackedElementMove
29
+ } from '../tools';
49
30
 
50
- createFeedbackEmitter(): FeedbackEmitter;
51
- /**
52
- * @deprecated It is recommended to create a {@link createFeedbackEmitter dedicated emitter} per feedback instead of using the tool.
53
- */
54
- registerFeedback(feedbackActions: Action[], feedbackEmitter?: IFeedbackEmitter, cleanupActions?: Action[]): Disposable;
55
- /**
56
- * @deprecated It is recommended to create a {@link createFeedbackEmitter dedicated emitter} per feedback and dispose it like that.
57
- */
58
- deregisterFeedback(feedbackEmitter?: IFeedbackEmitter, cleanupActions?: Action[]): void;
31
+ export interface PositioningTool extends FeedbackAwareTool {
32
+ readonly changeBoundsManager: ChangeBoundsManager;
59
33
  }
60
34
 
61
- @injectable()
62
35
  export class MouseTrackingElementPositionListener extends DragAwareMouseListener {
63
- protected positionUpdater: PointPositionUpdater;
64
36
  protected moveGhostFeedback: FeedbackEmitter;
65
- protected currentPosition?: Point;
37
+ protected tracker: ChangeBoundsTracker;
66
38
 
67
39
  constructor(
68
40
  protected elementId: string,
@@ -70,54 +42,60 @@ export class MouseTrackingElementPositionListener extends DragAwareMouseListener
70
42
  protected cursorPosition: 'top-left' | 'middle' = 'top-left'
71
43
  ) {
72
44
  super();
73
- this.positionUpdater = new PointPositionUpdater(this.tool.positionSnapper);
45
+ this.tracker = this.tool.changeBoundsManager.createTracker();
74
46
  this.moveGhostFeedback = this.tool.createFeedbackEmitter();
75
47
  }
76
48
 
49
+ protected getTrackedElement(target: GModelElement, event: MouseEvent): MoveableElement | undefined {
50
+ const element = target.root.index.getById(this.elementId);
51
+ return !element || !isMoveable(element) ? undefined : element;
52
+ }
53
+
77
54
  override mouseMove(target: GModelElement, event: MouseEvent): Action[] {
78
55
  super.mouseMove(target, event);
79
- const element = target.root.index.getById(this.elementId);
80
- if (!element || !isMoveable(element)) {
56
+ const element = this.getTrackedElement(target, event);
57
+ if (!element) {
81
58
  return [];
82
59
  }
83
- if (this.positionUpdater.isLastDragPositionUndefined()) {
84
- this.positionUpdater.updateLastDragPosition(element.position);
60
+ if (!this.tracker.isTracking()) {
61
+ this.initialize(element, target, event);
85
62
  }
86
- const mousePosition = getAbsolutePosition(target, event);
87
- const delta = this.positionUpdater.updatePosition(element, mousePosition, useSnap(event));
88
- if (!delta) {
63
+ const move = this.tracker.moveElements([element], { snap: event, restrict: event, validate: true });
64
+ const elementMove = move.elementMoves[0];
65
+ if (!elementMove) {
89
66
  return [];
90
67
  }
91
- const toPosition = this.getElementTargetPosition(mousePosition, element, event);
92
- const elementMove = { elementId: element.id, toPosition: toPosition };
93
- this.addMoveFeeback(element, elementMove);
94
- this.currentPosition = toPosition;
95
68
  // since we are moving a ghost element that is feedback-only and will be removed anyway,
96
69
  // we just send a MoveFinishedEventAction instead of reseting the position with a MoveAction and the finished flag set to true.
97
- this.moveGhostFeedback.add(MoveAction.create([elementMove], { animate: false }), MoveFinishedEventAction.create()).submit();
70
+ this.moveGhostFeedback.add(
71
+ MoveAction.create([{ elementId: this.elementId, toPosition: elementMove.toPosition }], { animate: false }),
72
+ MoveFinishedEventAction.create()
73
+ );
74
+ this.addMoveFeeback(elementMove);
75
+ this.moveGhostFeedback.submit();
76
+ this.tracker.updateTrackingPosition(elementMove.moveVector);
98
77
  return [];
99
78
  }
100
79
 
101
- protected getElementTargetPosition(mousePosition: Point, element: MoveableElement, event: MouseEvent): Point {
102
- const unsnappedPosition =
103
- this.cursorPosition === 'middle' && isBoundsAware(element)
104
- ? Point.subtract(mousePosition, Dimension.center(element.bounds))
105
- : mousePosition;
106
- return this.tool.positionSnapper.snapPosition(unsnappedPosition, element, useSnap(event));
80
+ protected initialize(element: MoveableElement, target: GModelElement, event: MouseEvent): void {
81
+ this.tracker.startTracking();
82
+ element.position = this.initializeElementPosition(element, target, event);
107
83
  }
108
84
 
109
- protected addMoveFeeback(element: MoveableElement, elementMove: ElementMove): void {
110
- if (this.tool.movementRestrictor) {
111
- if (!this.tool.movementRestrictor.validate(element, elementMove.toPosition)) {
112
- this.moveGhostFeedback.add(
113
- createMovementRestrictionFeedback(element, this.tool.movementRestrictor),
114
- removeMovementRestrictionFeedback(element, this.tool.movementRestrictor)
115
- );
116
- } else {
117
- this.moveGhostFeedback.add(removeMovementRestrictionFeedback(element, this.tool.movementRestrictor));
118
- }
119
- }
120
- this.moveGhostFeedback.add(ModifyCSSFeedbackAction.create({ elements: [element.id], remove: [CSS_HIDDEN] }));
85
+ protected initializeElementPosition(element: MoveableElement, target: GModelElement, event: MouseEvent): Point {
86
+ const mousePosition = getAbsolutePosition(target, event);
87
+ return this.cursorPosition === 'middle' && isBoundsAware(element)
88
+ ? Point.subtract(mousePosition, Dimension.center(element.bounds))
89
+ : mousePosition;
90
+ }
91
+
92
+ protected addMoveFeeback(move: TrackedElementMove): void {
93
+ this.tool.changeBoundsManager.addRestrictionFeedback(this.moveGhostFeedback, move);
94
+ this.moveGhostFeedback.add(ModifyCSSFeedbackAction.create({ elements: [move.element.id], remove: [CSS_HIDDEN] }));
95
+ this.moveGhostFeedback.add(
96
+ ModifyCSSFeedbackAction.create({ add: [CSS_RESIZE_MODE] }),
97
+ ModifyCSSFeedbackAction.create({ remove: [CSS_RESIZE_MODE] })
98
+ );
121
99
  }
122
100
 
123
101
  override dispose(): void {