@design-core/core 0.0.7 → 51.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.github/workflows/DesignCoreQA.yml +3 -0
  2. package/core/designCore.js +1 -1
  3. package/core/dimensions/alignedDimension.js +7 -7
  4. package/core/dimensions/angularDimension.js +32 -32
  5. package/core/dimensions/{baseCircularDimension.js → circularDimensionBase.js} +19 -19
  6. package/core/dimensions/diametricDimension.js +10 -10
  7. package/core/dimensions/dimension.js +42 -42
  8. package/core/dimensions/{baseDimension.js → dimensionBase.js} +17 -17
  9. package/core/dimensions/{baseLinearDimension.js → linearDimensionBase.js} +9 -9
  10. package/core/dimensions/radialDimension.js +8 -8
  11. package/core/dimensions/rotatedDimension.js +8 -8
  12. package/core/entities/arc.js +22 -22
  13. package/core/entities/arctext.js +13 -13
  14. package/core/entities/circle.js +7 -7
  15. package/core/entities/hatch.js +210 -40
  16. package/core/entities/insert.js +11 -6
  17. package/core/entities/point.js +19 -19
  18. package/core/entities/polyline.js +3 -3
  19. package/core/entities/{basePolyline.js → polylineBase.js} +18 -18
  20. package/core/entities/text.js +4 -4
  21. package/core/lib/boundingBox.js +11 -11
  22. package/core/lib/canvas.js +13 -6
  23. package/core/lib/clipboard.js +2 -2
  24. package/core/lib/dxf/dxf.js +11 -11
  25. package/core/lib/dxf/dxfIterator.js +2 -2
  26. package/core/lib/entityManager.js +19 -19
  27. package/core/lib/inputManager.js +1 -1
  28. package/core/lib/matrix.js +1 -1
  29. package/core/lib/patterns.js +1 -1
  30. package/core/lib/polylineUtils.js +9 -9
  31. package/core/lib/renderers/cairoRenderer.js +5 -5
  32. package/core/lib/renderers/canvasRenderer.js +4 -4
  33. package/core/lib/renderers/pdfRenderer.js +7 -7
  34. package/core/lib/renderers/rendererBase.js +1 -1
  35. package/core/lib/scene.js +1 -1
  36. package/core/lib/selectionManager.js +18 -18
  37. package/core/lib/utils.js +5 -5
  38. package/core/properties/entityProperties.js +2 -1
  39. package/core/properties/flags.js +12 -0
  40. package/core/properties/property.js +8 -3
  41. package/core/properties/propertyManager.js +52 -37
  42. package/core/tables/block.js +50 -46
  43. package/core/tables/dimStyle.js +5 -5
  44. package/core/tables/ltypeManager.js +1 -1
  45. package/core/tables/vport.js +2 -2
  46. package/core/tools/chamfer.js +6 -6
  47. package/core/tools/chamferFilletBase.js +4 -4
  48. package/core/tools/copy.js +8 -8
  49. package/core/tools/copybase.js +3 -3
  50. package/core/tools/copyclip.js +3 -3
  51. package/core/tools/cornerEntity.js +2 -2
  52. package/core/tools/cutclip.js +3 -3
  53. package/core/tools/explode.js +6 -6
  54. package/core/tools/extend.js +13 -13
  55. package/core/tools/fillet.js +6 -6
  56. package/core/tools/matchProp.js +1 -1
  57. package/core/tools/mirror.js +11 -11
  58. package/core/tools/move.js +5 -5
  59. package/core/tools/offset.js +29 -29
  60. package/core/tools/purge.js +10 -10
  61. package/core/tools/rotate.js +16 -16
  62. package/core/tools/scale.js +6 -6
  63. package/core/tools/trim.js +15 -15
  64. package/cspell.json +323 -0
  65. package/package.json +1 -1
  66. package/test/dimensions/alignedDimension.test.js +3 -3
  67. package/test/dimensions/angularDimension.test.js +7 -7
  68. package/test/dimensions/diametricDimension.test.js +9 -9
  69. package/test/dimensions/dimension.test.js +12 -12
  70. package/test/dimensions/{baseDimension.test.js → dimensionBase.test.js} +12 -12
  71. package/test/dimensions/{baseLinearDimension.test.js → linearDimensionBase.test.js} +7 -7
  72. package/test/dimensions/radialDimension.test.js +9 -9
  73. package/test/dimensions/rotatedDimension.test.js +4 -4
  74. package/test/entities/arc.test.js +10 -10
  75. package/test/entities/arctext.test.js +6 -6
  76. package/test/entities/circle.test.js +18 -18
  77. package/test/entities/hatch.test.js +362 -39
  78. package/test/entities/insert.test.js +9 -9
  79. package/test/entities/point.test.js +3 -3
  80. package/test/entities/{basePolyline.test.js → polylineBase.test.js} +131 -62
  81. package/test/entities/text.test.js +19 -19
  82. package/test/integration/exportIntegration.test.js +3 -3
  83. package/test/integration/userInputIntegration.test.js +5 -5
  84. package/test/lib/boundingBox.test.js +3 -3
  85. package/test/lib/canvas.test.js +9 -9
  86. package/test/lib/clipboard.test.js +73 -0
  87. package/test/lib/inputManager.test.js +4 -4
  88. package/test/lib/scene.test.js +9 -9
  89. package/test/lib/selectionManager.test.js +3 -3
  90. package/test/lib/snapping.test.js +1 -1
  91. package/test/properties/flags.test.js +24 -0
  92. package/test/properties/propertyManager.test.js +93 -22
  93. package/test/renderers/pdfRenderer.test.js +2 -2
  94. package/test/tables/block.test.js +63 -14
  95. package/test/tables/layerManager.test.js +2 -2
  96. package/test/test-helpers/hatchGridRenderer.js +3 -3
  97. package/test/test-helpers/test-helpers.js +6 -6
  98. package/test/tools/chamfer.test.js +60 -60
  99. package/test/tools/chamferFilletBase.test.js +36 -36
  100. package/test/tools/copy.test.js +6 -6
  101. package/test/tools/copybase.test.js +2 -2
  102. package/test/tools/copyclip.test.js +2 -2
  103. package/test/tools/cornerEntity.test.js +8 -8
  104. package/test/tools/cutclip.test.js +2 -2
  105. package/test/tools/erase.test.js +6 -6
  106. package/test/tools/explode.test.js +2 -2
  107. package/test/tools/extend.test.js +84 -84
  108. package/test/tools/fillet.test.js +62 -62
  109. package/test/tools/matchProp.test.js +6 -6
  110. package/test/tools/mirror.test.js +26 -26
  111. package/test/tools/move.test.js +7 -7
  112. package/test/tools/offset.test.js +65 -65
  113. package/test/tools/purge.test.js +4 -4
  114. package/test/tools/rotate.test.js +10 -10
  115. package/test/tools/scale.test.js +28 -28
  116. package/test/tools/trim.test.js +109 -109
  117. package/test/tools/zoom.test.js +15 -17
@@ -24,9 +24,9 @@ test.each(inputScenarios)('Trim.execute handles $desc', async (scenario) => {
24
24
  // clear all scene entities
25
25
  core.scene.clear();
26
26
  // create line
27
- core.scene.addItem('Line', { points: [new Point(), new Point(10, 0)] });
27
+ core.scene.addEntity('Line', { points: [new Point(), new Point(10, 0)] });
28
28
  // create circle
29
- core.scene.addItem('Circle', { points: [new Point(), new Point(10, 0)] });
29
+ core.scene.addEntity('Circle', { points: [new Point(), new Point(10, 0)] });
30
30
  // select line
31
31
  core.scene.selectionManager.selectionSet.selectionSet.push(0);
32
32
 
@@ -35,7 +35,7 @@ test.each(inputScenarios)('Trim.execute handles $desc', async (scenario) => {
35
35
  await trim.execute();
36
36
 
37
37
  expect(trim.selectedBoundaryItems[0]).toEqual(core.scene.entities.get(0));
38
- expect(trim.selectedItem).toBe(core.scene.entities.get(1));
38
+ expect(trim.selectedEntity).toBe(core.scene.entities.get(1));
39
39
  expect(actionSpy).toHaveBeenCalled();
40
40
  }, { extraMethods: { actionCommand: () => actionSpy() } });
41
41
  });
@@ -60,12 +60,12 @@ test('Test Trim.action', () => {
60
60
  // clear all scene entities
61
61
  core.scene.clear();
62
62
  // Add items to scene
63
- core.scene.addItem('Line', { points: [lineOneStart, lineOneEnd] });
64
- core.scene.addItem('Line', { points: [lineTwoStart, lineTwoEnd] });
63
+ core.scene.addEntity('Line', { points: [lineOneStart, lineOneEnd] });
64
+ core.scene.addEntity('Line', { points: [lineTwoStart, lineTwoEnd] });
65
65
  // Select boundary item
66
66
  trim.selectedBoundaryItems = [core.scene.entities.get(0)];
67
67
  // select item to trim
68
- trim.selectedItem = core.scene.entities.get(1);
68
+ trim.selectedEntity = core.scene.entities.get(1);
69
69
  // set mouse location - required for trim
70
70
  core.mouse.setPosFromScenePoint(new Point(10, 50));
71
71
  // Perform trim
@@ -91,12 +91,12 @@ test('Test Trim.action', () => {
91
91
  // clear scene items
92
92
  core.scene.clear();
93
93
  // Add items to scene
94
- core.scene.addItem('Line', { points: [lineOneStart, lineOneEnd] });
95
- core.scene.addItem('Line', { points: [lineTwoStart, lineTwoEnd] });
94
+ core.scene.addEntity('Line', { points: [lineOneStart, lineOneEnd] });
95
+ core.scene.addEntity('Line', { points: [lineTwoStart, lineTwoEnd] });
96
96
  // Select boundary item
97
97
  trim.selectedBoundaryItems = [core.scene.entities.get(0)];
98
98
  // select item to trim
99
- trim.selectedItem = core.scene.entities.get(1);
99
+ trim.selectedEntity = core.scene.entities.get(1);
100
100
  // set mouse location - required for trim
101
101
  core.mouse.setPosFromScenePoint(new Point(-10, 50));
102
102
  // Perform trim
@@ -122,12 +122,12 @@ test('Test Trim.action', () => {
122
122
  // clear scene items
123
123
  core.scene.clear();
124
124
  // Add items to scene
125
- core.scene.addItem('Line', { points: [lineOneStart, lineOneEnd] });
126
- core.scene.addItem('Line', { points: [lineTwoStart, lineTwoEnd] });
125
+ core.scene.addEntity('Line', { points: [lineOneStart, lineOneEnd] });
126
+ core.scene.addEntity('Line', { points: [lineTwoStart, lineTwoEnd] });
127
127
  // Select boundary item
128
128
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
129
129
  // select item to trim
130
- trim.selectedItem = core.scene.entities.get(0);
130
+ trim.selectedEntity = core.scene.entities.get(0);
131
131
  // set mouse location - required for trim
132
132
  core.mouse.setPosFromScenePoint(new Point(0, 60));
133
133
  // Perform trim
@@ -155,12 +155,12 @@ test('Test Trim.action', () => {
155
155
  // clear scene items
156
156
  core.scene.clear();
157
157
  // Add items to scene
158
- core.scene.addItem('Line', { points: [lineOneStart, lineOneEnd] });
159
- core.scene.addItem('Line', { points: [lineTwoStart, lineTwoEnd] });
158
+ core.scene.addEntity('Line', { points: [lineOneStart, lineOneEnd] });
159
+ core.scene.addEntity('Line', { points: [lineTwoStart, lineTwoEnd] });
160
160
  // Select boundary item
161
161
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
162
162
  // select item to trim
163
- trim.selectedItem = core.scene.entities.get(0);
163
+ trim.selectedEntity = core.scene.entities.get(0);
164
164
  // set mouse location - required for trim
165
165
  core.mouse.setPosFromScenePoint(new Point(0, 30));
166
166
  // Perform trim
@@ -189,12 +189,12 @@ test('Test Trim.action', () => {
189
189
  // clear scene items
190
190
  core.scene.clear();
191
191
  // Add items to scene
192
- core.scene.addItem('Line', { points: [lineOneStart, lineOneEnd] });
193
- core.scene.addItem('Line', { points: [crossingLineStart, crossingLineEnd] });
192
+ core.scene.addEntity('Line', { points: [lineOneStart, lineOneEnd] });
193
+ core.scene.addEntity('Line', { points: [crossingLineStart, crossingLineEnd] });
194
194
  // Select boundary item
195
195
  trim.selectedBoundaryItems = [core.scene.entities.get(0)];
196
196
  // select item to trim
197
- trim.selectedItem = core.scene.entities.get(1);
197
+ trim.selectedEntity = core.scene.entities.get(1);
198
198
  // set mouse location - required for trim
199
199
  core.mouse.setPosFromScenePoint(new Point(25, 75));
200
200
  // Perform trim
@@ -220,12 +220,12 @@ test('Test Trim.action', () => {
220
220
  // clear scene items
221
221
  core.scene.clear();
222
222
  // Add items to scene
223
- core.scene.addItem('Line', { points: [lineOneStart, lineOneEnd] });
224
- core.scene.addItem('Line', { points: [crossingLineStart, crossingLineEnd] });
223
+ core.scene.addEntity('Line', { points: [lineOneStart, lineOneEnd] });
224
+ core.scene.addEntity('Line', { points: [crossingLineStart, crossingLineEnd] });
225
225
  // Select boundary item
226
226
  trim.selectedBoundaryItems = [core.scene.entities.get(0)];
227
227
  // select item to trim
228
- trim.selectedItem = core.scene.entities.get(1);
228
+ trim.selectedEntity = core.scene.entities.get(1);
229
229
  // set mouse location - required for trim
230
230
  core.mouse.setPosFromScenePoint(new Point(-25, 25));
231
231
  // Perform trim
@@ -253,11 +253,11 @@ test('Test Trim.action polyline - trim end segment', () => {
253
253
  const trim = new Trim();
254
254
  core.scene.clear();
255
255
 
256
- core.scene.addItem('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0), new Point(100, 0)] });
257
- core.scene.addItem('Line', { points: [new Point(75, -50), new Point(75, 50)] });
256
+ core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0), new Point(100, 0)] });
257
+ core.scene.addEntity('Line', { points: [new Point(75, -50), new Point(75, 50)] });
258
258
 
259
259
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
260
- trim.selectedItem = core.scene.entities.get(0);
260
+ trim.selectedEntity = core.scene.entities.get(0);
261
261
  core.mouse.setPosFromScenePoint(new Point(90, 0));
262
262
  trim.action();
263
263
 
@@ -296,11 +296,11 @@ test('Test Trim.action polyline - trim start segment', () => {
296
296
  const trim = new Trim();
297
297
  core.scene.clear();
298
298
 
299
- core.scene.addItem('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0), new Point(100, 0)] });
300
- core.scene.addItem('Line', { points: [new Point(25, -50), new Point(25, 50)] });
299
+ core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0), new Point(100, 0)] });
300
+ core.scene.addEntity('Line', { points: [new Point(25, -50), new Point(25, 50)] });
301
301
 
302
302
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
303
- trim.selectedItem = core.scene.entities.get(0);
303
+ trim.selectedEntity = core.scene.entities.get(0);
304
304
  core.mouse.setPosFromScenePoint(new Point(10, 0));
305
305
  trim.action();
306
306
 
@@ -334,12 +334,12 @@ test('Test Trim.action polyline - trim middle segment', () => {
334
334
  const trim = new Trim();
335
335
  core.scene.clear();
336
336
 
337
- core.scene.addItem('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0), new Point(100, 0), new Point(150, 0)] });
338
- core.scene.addItem('Line', { points: [new Point(25, -50), new Point(25, 50)] });
339
- core.scene.addItem('Line', { points: [new Point(75, -50), new Point(75, 50)] });
337
+ core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0), new Point(100, 0), new Point(150, 0)] });
338
+ core.scene.addEntity('Line', { points: [new Point(25, -50), new Point(25, 50)] });
339
+ core.scene.addEntity('Line', { points: [new Point(75, -50), new Point(75, 50)] });
340
340
 
341
341
  trim.selectedBoundaryItems = [core.scene.entities.get(1), core.scene.entities.get(2)];
342
- trim.selectedItem = core.scene.entities.get(0);
342
+ trim.selectedEntity = core.scene.entities.get(0);
343
343
  core.mouse.setPosFromScenePoint(new Point(50, 0));
344
344
  trim.action();
345
345
 
@@ -376,7 +376,7 @@ test('Test Trim.action polyline - trim middle segment', () => {
376
376
  test('Test Trim.action polyline - trim bulged arc segment', () => {
377
377
  // Polyline: (0,0) with bulge=1 -> arc -> (100,0) -> straight -> (200,0)
378
378
  // With bulge=1 (CCW) the semicircular arc goes through (50,-50)
379
- // Arc center: (50,0), radius: 50
379
+ // Arc centre: (50,0), radius: 50
380
380
  // Boundary: vertical line at x=50
381
381
  // Intersection at (50,-50) — bottom of semicircle
382
382
  // Mouse at (75,-40) — right of intersection on the arc
@@ -385,11 +385,11 @@ test('Test Trim.action polyline - trim bulged arc segment', () => {
385
385
  const trim = new Trim();
386
386
  core.scene.clear();
387
387
 
388
- core.scene.addItem('Lwpolyline', { points: [new Point(0, 0, 1), new Point(100, 0), new Point(200, 0)] });
389
- core.scene.addItem('Line', { points: [new Point(50, -100), new Point(50, 100)] });
388
+ core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0, 1), new Point(100, 0), new Point(200, 0)] });
389
+ core.scene.addEntity('Line', { points: [new Point(50, -100), new Point(50, 100)] });
390
390
 
391
391
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
392
- trim.selectedItem = core.scene.entities.get(0);
392
+ trim.selectedEntity = core.scene.entities.get(0);
393
393
  core.mouse.setPosFromScenePoint(new Point(75, -40));
394
394
  trim.action();
395
395
 
@@ -434,7 +434,7 @@ test('Trim.preview does not throw', () => {
434
434
 
435
435
  test('Trim.preview returns early when no boundary items set', () => {
436
436
  core.scene.clear();
437
- core.scene.addItem('Line', { points: [new Point(0, -10), new Point(0, 10)] });
437
+ core.scene.addEntity('Line', { points: [new Point(0, -10), new Point(0, 10)] });
438
438
  DesignCore.Scene.previewEntities.clear();
439
439
 
440
440
  const trim = new Trim();
@@ -446,8 +446,8 @@ test('Trim.preview returns early when no boundary items set', () => {
446
446
 
447
447
  test('Trim.preview returns early when findClosestItem returns undefined', () => {
448
448
  core.scene.clear();
449
- core.scene.addItem('Line', { points: [new Point(0, -10), new Point(0, 10)] });
450
- core.scene.addItem('Line', { points: [new Point(-10, 0), new Point(10, 0)] });
449
+ core.scene.addEntity('Line', { points: [new Point(0, -10), new Point(0, 10)] });
450
+ core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(10, 0)] });
451
451
  DesignCore.Scene.previewEntities.clear();
452
452
 
453
453
  const trim = new Trim();
@@ -463,8 +463,8 @@ test('Trim.preview returns early when findClosestItem returns undefined', () =>
463
463
  test('Trim.preview returns early when hovered entity does not implement trim', () => {
464
464
  // Text does not override Entity.trim() — preview must not emit a notification.
465
465
  core.scene.clear();
466
- core.scene.addItem('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary
467
- core.scene.addItem('Text', { points: [new Point(5, 0)], string: 'hello' }); // unsupported
466
+ core.scene.addEntity('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary
467
+ core.scene.addEntity('Text', { points: [new Point(5, 0)], string: 'hello' }); // unsupported
468
468
  DesignCore.Scene.previewEntities.clear();
469
469
 
470
470
  const notifySpy = jest.spyOn(core, 'notify');
@@ -486,12 +486,12 @@ test('Trim.preview returns early when hovered entity does not implement trim', (
486
486
  test('Trim.preview returns early when hovered entity has no intersections with boundary', () => {
487
487
  // Two parallel horizontal lines — no intersection with the vertical boundary
488
488
  core.scene.clear();
489
- core.scene.addItem('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary (vertical)
490
- core.scene.addItem('Line', { points: [new Point(-10, 5), new Point(10, 5)] }); // hovered (horizontal, no intersection with boundary)
489
+ core.scene.addEntity('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary (vertical)
490
+ core.scene.addEntity('Line', { points: [new Point(-10, 5), new Point(10, 5)] }); // hovered (horizontal, no intersection with boundary)
491
491
  DesignCore.Scene.previewEntities.clear();
492
492
 
493
493
  // Boundary is entity 0; hovered is entity 1 — they are parallel on the y-axis, so no intersection
494
- core.scene.addItem('Line', { points: [new Point(-10, 20), new Point(10, 20)] }); // extra line, no intersection
494
+ core.scene.addEntity('Line', { points: [new Point(-10, 20), new Point(10, 20)] }); // extra line, no intersection
495
495
 
496
496
  const trim = new Trim();
497
497
  trim.selectedBoundaryItems = [core.scene.entities.get(2)]; // horizontal boundary — parallel to hovered
@@ -510,8 +510,8 @@ test('Trim.preview populates previewEntities when entity can be trimmed', () =>
510
510
  // Vertical boundary at x=0; horizontal line from (-10,0) to (10,0) is the hovered entity.
511
511
  // Mouse at (5,0) → trims the right half, leaving the left half as a preview.
512
512
  core.scene.clear();
513
- core.scene.addItem('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary
514
- core.scene.addItem('Line', { points: [new Point(-10, 0), new Point(10, 0)] }); // hovered
513
+ core.scene.addEntity('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary
514
+ core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(10, 0)] }); // hovered
515
515
  DesignCore.Scene.previewEntities.clear();
516
516
 
517
517
  const trim = new Trim();
@@ -531,7 +531,7 @@ test('Trim.preview populates previewEntities when entity can be trimmed', () =>
531
531
  test('Trim.execute returns early when boundary input is undefined', async () => {
532
532
  core.scene.clear();
533
533
  core.scene.selectionManager.reset();
534
- core.scene.addItem('Line', { points: [new Point(), new Point(10, 0)] });
534
+ core.scene.addEntity('Line', { points: [new Point(), new Point(10, 0)] });
535
535
 
536
536
  await withMockInput(core.scene, [undefined], async () => {
537
537
  const trim = new Trim();
@@ -543,8 +543,8 @@ test('Trim.execute returns early when boundary input is undefined', async () =>
543
543
  test('Trim.execute exits selection loop when selection input is undefined', async () => {
544
544
  core.scene.clear();
545
545
  core.scene.selectionManager.reset();
546
- core.scene.addItem('Line', { points: [new Point(), new Point(10, 0)] });
547
- core.scene.addItem('Circle', { points: [new Point(), new Point(5, 0)] });
546
+ core.scene.addEntity('Line', { points: [new Point(), new Point(10, 0)] });
547
+ core.scene.addEntity('Circle', { points: [new Point(), new Point(5, 0)] });
548
548
  // preselect first item as boundary
549
549
  core.scene.selectionManager.selectionSet.selectionSet.push(0);
550
550
 
@@ -560,9 +560,9 @@ test('Trim.execute exits selection loop when selection input is undefined', asyn
560
560
  test('Trim.execute calls actionCommand once per trim selection', async () => {
561
561
  core.scene.clear();
562
562
  core.scene.selectionManager.reset();
563
- core.scene.addItem('Line', { points: [new Point(0, -10), new Point(0, 10)] });
564
- core.scene.addItem('Circle', { points: [new Point(-5, 0), new Point(0, 0)] });
565
- core.scene.addItem('Circle', { points: [new Point(-5, 0), new Point(0, 0)] });
563
+ core.scene.addEntity('Line', { points: [new Point(0, -10), new Point(0, 10)] });
564
+ core.scene.addEntity('Circle', { points: [new Point(-5, 0), new Point(0, 0)] });
565
+ core.scene.addEntity('Circle', { points: [new Point(-5, 0), new Point(0, 0)] });
566
566
  // preselect line as boundary
567
567
  core.scene.selectionManager.selectionSet.selectionSet.push(0);
568
568
 
@@ -579,11 +579,11 @@ test('Trim.execute calls actionCommand once per trim selection', async () => {
579
579
  );
580
580
  });
581
581
 
582
- test('Trim.action does nothing when selectedItem is null', () => {
582
+ test('Trim.action does nothing when selectedEntity is null', () => {
583
583
  core.scene.clear();
584
- core.scene.addItem('Line', { points: [new Point(), new Point(10, 0)] });
584
+ core.scene.addEntity('Line', { points: [new Point(), new Point(10, 0)] });
585
585
  const trim = new Trim();
586
- trim.selectedItem = null;
586
+ trim.selectedEntity = null;
587
587
  trim.selectedBoundaryItems = [core.scene.entities.get(0)];
588
588
 
589
589
  expect(() => trim.action()).not.toThrow();
@@ -591,24 +591,24 @@ test('Trim.action does nothing when selectedItem is null', () => {
591
591
 
592
592
  test('Trim.action does nothing when selectedBoundaryItems is empty', () => {
593
593
  core.scene.clear();
594
- core.scene.addItem('Line', { points: [new Point(), new Point(10, 0)] });
594
+ core.scene.addEntity('Line', { points: [new Point(), new Point(10, 0)] });
595
595
  const trim = new Trim();
596
- trim.selectedItem = core.scene.entities.get(0);
596
+ trim.selectedEntity = core.scene.entities.get(0);
597
597
  trim.selectedBoundaryItems = [];
598
598
 
599
599
  expect(() => trim.action()).not.toThrow();
600
- expect(trim.selectedItem).toBeNull();
600
+ expect(trim.selectedEntity).toBeNull();
601
601
  });
602
602
 
603
603
  test('Trim.action notifies NOTRIM when selected entity lacks fromPolylinePoints', () => {
604
604
  // Use a stub entity that has toPolylinePoints but no fromPolylinePoints.
605
605
  // action() must notify and not throw.
606
606
  core.scene.clear();
607
- core.scene.addItem('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary
607
+ core.scene.addEntity('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary
608
608
 
609
609
  const trim = new Trim();
610
610
  trim.selectedBoundaryItems = [core.scene.entities.get(0)];
611
- trim.selectedItem = {
611
+ trim.selectedEntity = {
612
612
  type: 'FakeEntity',
613
613
  toPolylinePoints: () => [new Point(-5, 0), new Point(5, 0)],
614
614
  // deliberately no fromPolylinePoints
@@ -618,7 +618,7 @@ test('Trim.action notifies NOTRIM when selected entity lacks fromPolylinePoints'
618
618
  trim.action();
619
619
 
620
620
  expect(notifySpy).toHaveBeenCalledWith(expect.stringContaining(Strings.Message.NOTRIM));
621
- expect(trim.selectedItem).toBeNull();
621
+ expect(trim.selectedEntity).toBeNull();
622
622
  notifySpy.mockRestore();
623
623
  });
624
624
 
@@ -626,7 +626,7 @@ test('Trim.preview silently skips entity that lacks fromPolylinePoints', () => {
626
626
  // Stub entity implements toPolylinePoints but not fromPolylinePoints.
627
627
  // preview() must return early without calling notify.
628
628
  core.scene.clear();
629
- core.scene.addItem('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary
629
+ core.scene.addEntity('Line', { points: [new Point(0, -10), new Point(0, 10)] }); // boundary
630
630
  DesignCore.Scene.previewEntities.clear();
631
631
 
632
632
  const stubEntity = {
@@ -655,29 +655,29 @@ test('Trim.preview silently skips entity that lacks fromPolylinePoints', () => {
655
655
  test('Trim.action notifies when no intersection found (parallel lines)', () => {
656
656
  core.scene.clear();
657
657
  // Two parallel vertical lines - no intersection
658
- core.scene.addItem('Line', { points: [new Point(0, 0), new Point(0, 100)] });
659
- core.scene.addItem('Line', { points: [new Point(10, 0), new Point(10, 100)] });
658
+ core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 100)] });
659
+ core.scene.addEntity('Line', { points: [new Point(10, 0), new Point(10, 100)] });
660
660
 
661
661
  const trim = new Trim();
662
662
  trim.selectedBoundaryItems = [core.scene.entities.get(0)];
663
- trim.selectedItem = core.scene.entities.get(1);
663
+ trim.selectedEntity = core.scene.entities.get(1);
664
664
 
665
665
  const notifySpy = jest.spyOn(core, 'notify').mockImplementation(() => {});
666
666
  trim.action();
667
667
 
668
668
  expect(notifySpy).toHaveBeenCalledWith(expect.stringContaining(Strings.Message.NOTRIM));
669
- expect(trim.selectedItem).toBeNull();
669
+ expect(trim.selectedEntity).toBeNull();
670
670
  notifySpy.mockRestore();
671
671
  });
672
672
 
673
673
  test('Trim.action notifies when boundary item equals selected item', () => {
674
674
  core.scene.clear();
675
- core.scene.addItem('Line', { points: [new Point(0, 0), new Point(100, 0)] });
675
+ core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(100, 0)] });
676
676
  const entity = core.scene.entities.get(0);
677
677
 
678
678
  const trim = new Trim();
679
679
  trim.selectedBoundaryItems = [entity];
680
- trim.selectedItem = entity;
680
+ trim.selectedEntity = entity;
681
681
 
682
682
  const notifySpy = jest.spyOn(core, 'notify').mockImplementation(() => {});
683
683
  trim.action();
@@ -687,7 +687,7 @@ test('Trim.action notifies when boundary item equals selected item', () => {
687
687
  });
688
688
 
689
689
  test('Trim.action trims an arc', () => {
690
- // Arc: center (0,0), start (10,0), end (-10,0) — CCW upper semicircle through (0,10)
690
+ // Arc: centre (0,0), start (10,0), end (-10,0) — CCW upper semicircle through (0,10)
691
691
  // Boundary: vertical line at x=0, intersects arc at (0,10)
692
692
  // Mouse at (7,7) — in the right half, selects (10,0)→(0,10) segment for removal
693
693
  // Expected: original arc removed, shorter arc from (0,10) to (-10,0) added
@@ -695,11 +695,11 @@ test('Trim.action trims an arc', () => {
695
695
  const trim = new Trim();
696
696
  core.scene.clear();
697
697
 
698
- core.scene.addItem('Arc', { points: [new Point(0, 0), new Point(10, 0), new Point(-10, 0)] });
699
- core.scene.addItem('Line', { points: [new Point(0, -20), new Point(0, 20)] });
698
+ core.scene.addEntity('Arc', { points: [new Point(0, 0), new Point(10, 0), new Point(-10, 0)] });
699
+ core.scene.addEntity('Line', { points: [new Point(0, -20), new Point(0, 20)] });
700
700
 
701
701
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
702
- trim.selectedItem = core.scene.entities.get(0);
702
+ trim.selectedEntity = core.scene.entities.get(0);
703
703
  core.mouse.setPosFromScenePoint(new Point(7, 7));
704
704
  trim.action();
705
705
 
@@ -718,7 +718,7 @@ test('Trim.action trims an arc', () => {
718
718
  });
719
719
 
720
720
  test('Trim.action trims a circle', () => {
721
- // Circle: center (0,0), radius 10
721
+ // Circle: centre (0,0), radius 10
722
722
  // Boundary: vertical line at x=0, intersects circle at (0,10) and (0,-10)
723
723
  // Mouse at (8,0) — on the right side
724
724
  // Expected: original circle removed, arc covering the right side added
@@ -726,11 +726,11 @@ test('Trim.action trims a circle', () => {
726
726
  const trim = new Trim();
727
727
  core.scene.clear();
728
728
 
729
- core.scene.addItem('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
730
- core.scene.addItem('Line', { points: [new Point(0, -20), new Point(0, 20)] });
729
+ core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
730
+ core.scene.addEntity('Line', { points: [new Point(0, -20), new Point(0, 20)] });
731
731
 
732
732
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
733
- trim.selectedItem = core.scene.entities.get(0);
733
+ trim.selectedEntity = core.scene.entities.get(0);
734
734
  core.mouse.setPosFromScenePoint(new Point(8, 0));
735
735
  trim.action();
736
736
 
@@ -742,7 +742,7 @@ test('Trim.action trims a circle', () => {
742
742
  if (core.scene.entities.get(i).type === 'Arc') arc = core.scene.entities.get(i);
743
743
  }
744
744
  expect(arc).toBeDefined();
745
- // Arc center should match the original circle center
745
+ // Arc centre should match the original circle centre
746
746
  expect(arc.points[0].x).toBeCloseTo(0, 10);
747
747
  expect(arc.points[0].y).toBeCloseTo(0, 10);
748
748
  });
@@ -757,16 +757,16 @@ test('Trim.action trims a closed polyline - produces open polyline with closed f
757
757
  core.scene.clear();
758
758
 
759
759
  // Five points where first === last → constructor pops last and sets flag=1
760
- core.scene.addItem('Lwpolyline', {
760
+ core.scene.addEntity('Lwpolyline', {
761
761
  points: [new Point(0, 0), new Point(100, 0), new Point(100, 100), new Point(0, 100), new Point(0, 0)],
762
762
  });
763
- core.scene.addItem('Line', { points: [new Point(50, -10), new Point(50, 110)] });
763
+ core.scene.addEntity('Line', { points: [new Point(50, -10), new Point(50, 110)] });
764
764
 
765
765
  const polyline = core.scene.entities.get(0);
766
766
  expect(polyline.flags.hasFlag(1)).toBe(true); // confirm closed before trim
767
767
 
768
768
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
769
- trim.selectedItem = polyline;
769
+ trim.selectedEntity = polyline;
770
770
  core.mouse.setPosFromScenePoint(new Point(75, 50));
771
771
  trim.action();
772
772
 
@@ -791,18 +791,18 @@ test('Trim.action trims middle of a line - circle boundary creates two intersect
791
791
  // segment index 1. The sort comparator falls through to the
792
792
  // positionAlongSegment comparison (line 179 of trim.js) because the segment
793
793
  // indices are equal.
794
- // Circle: center (50,0) radius 20 → intersects the x-axis at (30,0) and (70,0)
794
+ // Circle: centre (50,0) radius 20 → intersects the x-axis at (30,0) and (70,0)
795
795
  // Line: (0,0) → (100,0), mouse at (50,0) — inside the circle
796
796
  // Expected: original line removed, two shorter lines (0→30) and (70→100) added
797
797
 
798
798
  const trim = new Trim();
799
799
  core.scene.clear();
800
800
 
801
- core.scene.addItem('Line', { points: [new Point(0, 0), new Point(100, 0)] });
802
- core.scene.addItem('Circle', { points: [new Point(50, 0), new Point(70, 0)] }); // radius 20
801
+ core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(100, 0)] });
802
+ core.scene.addEntity('Circle', { points: [new Point(50, 0), new Point(70, 0)] }); // radius 20
803
803
 
804
804
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
805
- trim.selectedItem = core.scene.entities.get(0);
805
+ trim.selectedEntity = core.scene.entities.get(0);
806
806
  core.mouse.setPosFromScenePoint(new Point(50, 0));
807
807
  trim.action();
808
808
 
@@ -838,7 +838,7 @@ test('Trim.execute catches and logs errors thrown during input', async () => {
838
838
  });
839
839
 
840
840
  test('Trim.action trims a circle near the seam (right side, mouse at angle 0)', () => {
841
- // Circle: center (0,0), radius 10.
841
+ // Circle: centre (0,0), radius 10.
842
842
  // Circle.toPolylinePoints() always places the seam at angle 0 → vertex (10,0).
843
843
  // The old code failed when the mouse was near that seam because both intersections
844
844
  // appeared "after" the mouse in linear polyline order, leaving trimBefore=null.
@@ -851,11 +851,11 @@ test('Trim.action trims a circle near the seam (right side, mouse at angle 0)',
851
851
  const trim = new Trim();
852
852
  core.scene.clear();
853
853
 
854
- core.scene.addItem('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
855
- core.scene.addItem('Line', { points: [new Point(0, -20), new Point(0, 20)] });
854
+ core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
855
+ core.scene.addEntity('Line', { points: [new Point(0, -20), new Point(0, 20)] });
856
856
 
857
857
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
858
- trim.selectedItem = core.scene.entities.get(0);
858
+ trim.selectedEntity = core.scene.entities.get(0);
859
859
  core.mouse.setPosFromScenePoint(new Point(8, 0));
860
860
  trim.action();
861
861
 
@@ -867,7 +867,7 @@ test('Trim.action trims a circle near the seam (right side, mouse at angle 0)',
867
867
  }
868
868
  expect(arc).toBeDefined();
869
869
  // Remaining arc is the left half: from (0,10) CCW through (-10,0) to (0,-10)
870
- expect(arc.points[0].x).toBeCloseTo(0); // center
870
+ expect(arc.points[0].x).toBeCloseTo(0); // centre
871
871
  expect(arc.points[0].y).toBeCloseTo(0);
872
872
  expect(arc.points[1].x).toBeCloseTo(0); // start at (0,10)
873
873
  expect(arc.points[1].y).toBeCloseTo(10);
@@ -889,16 +889,16 @@ test('Trim.action trims a closed polyline near the seam vertex', () => {
889
889
  const trim = new Trim();
890
890
  core.scene.clear();
891
891
 
892
- core.scene.addItem('Lwpolyline', {
892
+ core.scene.addEntity('Lwpolyline', {
893
893
  points: [new Point(0, 0), new Point(100, 0), new Point(100, 100), new Point(0, 100), new Point(0, 0)],
894
894
  });
895
- core.scene.addItem('Line', { points: [new Point(-10, 50), new Point(110, 50)] });
895
+ core.scene.addEntity('Line', { points: [new Point(-10, 50), new Point(110, 50)] });
896
896
 
897
897
  const polyline = core.scene.entities.get(0);
898
898
  expect(polyline.flags.hasFlag(1)).toBe(true);
899
899
 
900
900
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
901
- trim.selectedItem = polyline;
901
+ trim.selectedEntity = polyline;
902
902
  // Mouse in the BOTTOM half — forward arc between the two intersections, crosses the seam
903
903
  core.mouse.setPosFromScenePoint(new Point(50, 25));
904
904
  trim.action();
@@ -922,8 +922,8 @@ test('Trim.action trims a closed polyline near the seam vertex', () => {
922
922
 
923
923
  test('Trim.action trims an open polyline with two consecutive arc segments', () => {
924
924
  // Polyline: (0,0,b=1) -> arc1 -> (100,0,b=1) -> arc2 -> (200,0)
925
- // arc1 center (50,0) radius 50, through (50,-50)
926
- // arc2 center (150,0) radius 50, through (150,-50)
925
+ // arc1 centre (50,0) radius 50, through (50,-50)
926
+ // arc2 centre (150,0) radius 50, through (150,-50)
927
927
  // Boundary: vertical line at x=150, intersection at (150,-50) on arc2.
928
928
  // Mouse at (120,-40): on arc2 BEFORE the intersection (in arc-travel order).
929
929
  // Expected: keep right portion = (150,-50) -> (200,0); discard left side.
@@ -931,11 +931,11 @@ test('Trim.action trims an open polyline with two consecutive arc segments', ()
931
931
  const trim = new Trim();
932
932
  core.scene.clear();
933
933
 
934
- core.scene.addItem('Lwpolyline', { points: [new Point(0, 0, 1), new Point(100, 0, 1), new Point(200, 0)] });
935
- core.scene.addItem('Line', { points: [new Point(150, -100), new Point(150, 100)] });
934
+ core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0, 1), new Point(100, 0, 1), new Point(200, 0)] });
935
+ core.scene.addEntity('Line', { points: [new Point(150, -100), new Point(150, 100)] });
936
936
 
937
937
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
938
- trim.selectedItem = core.scene.entities.get(0);
938
+ trim.selectedEntity = core.scene.entities.get(0);
939
939
  core.mouse.setPosFromScenePoint(new Point(120, -40));
940
940
  trim.action();
941
941
 
@@ -955,7 +955,7 @@ test('Trim.action trims an open polyline with two consecutive arc segments', ()
955
955
  });
956
956
 
957
957
  test('Trim.action trims an arc from the start (portionOne same-segment bulge)', () => {
958
- // Arc: center (0,0), start (10,0), end (-10,0) — CCW upper semicircle through (0,10).
958
+ // Arc: centre (0,0), start (10,0), end (-10,0) — CCW upper semicircle through (0,10).
959
959
  // Boundary: vertical line at x=0, intersection at (0,10).
960
960
  // Mouse at (-7,7) — LEFT of intersection, so trimBefore=(0,10), trimAfter=null.
961
961
  // portionOne = startLoc(seg1,(10,0)) → trimBefore(seg1,(0,10)) — same-segment arc split.
@@ -964,11 +964,11 @@ test('Trim.action trims an arc from the start (portionOne same-segment bulge)',
964
964
  const trim = new Trim();
965
965
  core.scene.clear();
966
966
 
967
- core.scene.addItem('Arc', { points: [new Point(0, 0), new Point(10, 0), new Point(-10, 0)] });
968
- core.scene.addItem('Line', { points: [new Point(0, -20), new Point(0, 20)] });
967
+ core.scene.addEntity('Arc', { points: [new Point(0, 0), new Point(10, 0), new Point(-10, 0)] });
968
+ core.scene.addEntity('Line', { points: [new Point(0, -20), new Point(0, 20)] });
969
969
 
970
970
  trim.selectedBoundaryItems = [core.scene.entities.get(1)];
971
- trim.selectedItem = core.scene.entities.get(0);
971
+ trim.selectedEntity = core.scene.entities.get(0);
972
972
  core.mouse.setPosFromScenePoint(new Point(-7, 7));
973
973
  trim.action();
974
974
 
@@ -987,7 +987,7 @@ test('Trim.action trims an arc from the start (portionOne same-segment bulge)',
987
987
  });
988
988
 
989
989
  test('Trim.action trims the middle of an arc (two intersections on same arc segment)', () => {
990
- // Arc: center (0,0), start (10,0), end (-10,0) — CCW upper semicircle through (0,10).
990
+ // Arc: centre (0,0), start (10,0), end (-10,0) — CCW upper semicircle through (0,10).
991
991
  // Two boundaries: vertical line at x=-5 and x=5.
992
992
  // Intersections at (5,√75)≈(5,8.66) and (-5,√75)≈(-5,8.66), both on segment 1.
993
993
  // Mouse at (0,9) — between both intersections at the top.
@@ -996,12 +996,12 @@ test('Trim.action trims the middle of an arc (two intersections on same arc segm
996
996
  const trim = new Trim();
997
997
  core.scene.clear();
998
998
 
999
- core.scene.addItem('Arc', { points: [new Point(0, 0), new Point(10, 0), new Point(-10, 0)] });
1000
- core.scene.addItem('Line', { points: [new Point(5, -20), new Point(5, 20)] });
1001
- core.scene.addItem('Line', { points: [new Point(-5, -20), new Point(-5, 20)] });
999
+ core.scene.addEntity('Arc', { points: [new Point(0, 0), new Point(10, 0), new Point(-10, 0)] });
1000
+ core.scene.addEntity('Line', { points: [new Point(5, -20), new Point(5, 20)] });
1001
+ core.scene.addEntity('Line', { points: [new Point(-5, -20), new Point(-5, 20)] });
1002
1002
 
1003
1003
  trim.selectedBoundaryItems = [core.scene.entities.get(1), core.scene.entities.get(2)];
1004
- trim.selectedItem = core.scene.entities.get(0);
1004
+ trim.selectedEntity = core.scene.entities.get(0);
1005
1005
  core.mouse.setPosFromScenePoint(new Point(0, 9));
1006
1006
  trim.action();
1007
1007
 
@@ -1036,12 +1036,12 @@ test('Trim.action trims with multiple boundary items', () => {
1036
1036
  const trim = new Trim();
1037
1037
  core.scene.clear();
1038
1038
 
1039
- core.scene.addItem('Line', { points: [new Point(0, 0), new Point(200, 0)] });
1040
- core.scene.addItem('Line', { points: [new Point(50, -20), new Point(50, 20)] });
1041
- core.scene.addItem('Line', { points: [new Point(150, -20), new Point(150, 20)] });
1039
+ core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(200, 0)] });
1040
+ core.scene.addEntity('Line', { points: [new Point(50, -20), new Point(50, 20)] });
1041
+ core.scene.addEntity('Line', { points: [new Point(150, -20), new Point(150, 20)] });
1042
1042
 
1043
1043
  trim.selectedBoundaryItems = [core.scene.entities.get(1), core.scene.entities.get(2)];
1044
- trim.selectedItem = core.scene.entities.get(0);
1044
+ trim.selectedEntity = core.scene.entities.get(0);
1045
1045
  core.mouse.setPosFromScenePoint(new Point(100, 0));
1046
1046
  trim.action();
1047
1047