orcasvn-react-diagrams 0.2.12 → 0.2.13

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 (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +15 -11
  3. package/ai/api-contract.json +47 -0
  4. package/ai/invariants.json +6 -2
  5. package/ai/manifest.json +1 -1
  6. package/dist/cjs/examples.js +427 -48
  7. package/dist/cjs/index.js +226 -36
  8. package/dist/cjs/types/api/createDiagramEditor.d.ts +2 -1
  9. package/dist/cjs/types/api/types.d.ts +50 -0
  10. package/dist/cjs/types/displaybox/demos/deletionEventsDemo.d.ts +2 -0
  11. package/dist/cjs/types/displaybox/demos/focusElementDemo.d.ts +4 -0
  12. package/dist/cjs/types/engine/DiagramEngine.d.ts +9 -0
  13. package/dist/esm/examples.js +427 -48
  14. package/dist/esm/examples.js.map +1 -1
  15. package/dist/esm/index.js +226 -36
  16. package/dist/esm/index.js.map +1 -1
  17. package/dist/esm/types/api/createDiagramEditor.d.ts +2 -1
  18. package/dist/esm/types/api/types.d.ts +50 -0
  19. package/dist/esm/types/displaybox/demos/deletionEventsDemo.d.ts +2 -0
  20. package/dist/esm/types/displaybox/demos/focusElementDemo.d.ts +4 -0
  21. package/dist/esm/types/engine/DiagramEngine.d.ts +9 -0
  22. package/dist/examples.d.ts +51 -0
  23. package/dist/index.d.ts +52 -1
  24. package/docs/API_CONTRACT.md +48 -1
  25. package/docs/ARCHITECTURE.md +9 -7
  26. package/docs/CAPABILITIES.md +3 -0
  27. package/docs/COMMANDS_EVENTS.md +15 -6
  28. package/docs/DOCUMENTATION_WORKFLOW.md +3 -1
  29. package/docs/INTEGRATION_PLAYBOOK.md +4 -0
  30. package/docs/PORTING_CHECKLIST.md +4 -1
  31. package/package.json +1 -1
  32. package/src/displaybox/demos/DeletionEventsDemoTab.tsx +167 -9
  33. package/src/displaybox/demos/deletionEventsDemo.ts +2 -2
  34. package/src/displaybox/demos/focusElementDemo.ts +91 -0
  35. package/src/displaybox/demos/index.tsx +2 -0
@@ -1,4 +1,4 @@
1
- import { DiagramEngineHandle, Point, DiagramState, ElementShapeHoverControlActivationEvent, ElementShapeHoverControlInteractionEvent, ElementShapeHoverControls, EngineChangeEvent, EngineSelectionEvent, LinkTargetPortCreationHandler, LinkColorPoolPolicy, LinkRouteRefreshPolicy, ViewportFitOptions } from './types';
1
+ import { DiagramEngineHandle, Point, DiagramState, ElementShapeHoverControlActivationEvent, ElementShapeHoverControlInteractionEvent, ElementShapeHoverControls, EngineChangeEvent, EngineSelectionEvent, LinkTargetPortCreationHandler, LinkColorPoolPolicy, LinkRouteRefreshPolicy, FocusElementOptions, ViewportFitOptions } from './types';
2
2
  import { type BuiltInShapeKind } from '../shapes';
3
3
  export type SimpleShape = {
4
4
  id: string;
@@ -41,6 +41,7 @@ export type DiagramEditorHandle = DiagramEngineHandle & {
41
41
  completeLinkToElement: (targetElementId: string, pointer: Point) => void;
42
42
  cancelLink: () => void;
43
43
  zoomToFitElements: (options?: ViewportFitOptions) => void;
44
+ focusElement: (elementId: string, options?: FocusElementOptions) => void;
44
45
  exportImage: (options?: DiagramImageExportOptions) => string;
45
46
  resize: (width: number, height: number) => void;
46
47
  setElementShapeHoverControls: (controls?: ElementShapeHoverControls) => void;
@@ -24,6 +24,9 @@ export type ViewportFitOptions = {
24
24
  minZoom?: number;
25
25
  maxZoom?: number;
26
26
  };
27
+ export type FocusElementOptions = {
28
+ zoom?: number;
29
+ };
27
30
  export type MoveConstraint = 'free' | 'inside' | 'border';
28
31
  export type TextInteractionPolicy = {
29
32
  movable?: boolean;
@@ -394,6 +397,11 @@ export type ElementPointerEvent = {
394
397
  pointer: EnginePointerInfo;
395
398
  isMulti: boolean;
396
399
  };
400
+ export type ElementDoubleClickEvent = {
401
+ elementId: string;
402
+ pointer: EnginePointerInfo;
403
+ isMulti: boolean;
404
+ };
397
405
  export type ElementMovedEvent = {
398
406
  elementId: string;
399
407
  oldWorld: Point;
@@ -418,18 +426,55 @@ export type GridLayoutChangedEvent = {
418
426
  beforeGridTemplate?: ElementLayoutGridRowTemplate[];
419
427
  afterGridTemplate: ElementLayoutGridRowTemplate[];
420
428
  };
429
+ export type DeletionTrigger = 'direct' | 'selection' | 'cascade';
430
+ export type DeletionRootRef = {
431
+ entity: 'element' | 'port' | 'link' | 'text';
432
+ id: string;
433
+ };
434
+ export type ElementDeletingEvent = {
435
+ elementId: string;
436
+ trigger: DeletionTrigger;
437
+ root: DeletionRootRef;
438
+ cancel: () => void;
439
+ cancelled: boolean;
440
+ };
421
441
  export type ElementDeletedEvent = {
422
442
  elementId: string;
423
443
  };
444
+ export type PortDeletingEvent = {
445
+ portId: string;
446
+ elementId: string;
447
+ trigger: DeletionTrigger;
448
+ root: DeletionRootRef;
449
+ cancel: () => void;
450
+ cancelled: boolean;
451
+ };
424
452
  export type PortDeletedEvent = {
425
453
  portId: string;
426
454
  elementId: string;
427
455
  };
456
+ export type LinkDeletingEvent = {
457
+ linkId: string;
458
+ sourcePortId: string;
459
+ targetPortId: string;
460
+ trigger: DeletionTrigger;
461
+ root: DeletionRootRef;
462
+ cancel: () => void;
463
+ cancelled: boolean;
464
+ };
428
465
  export type LinkDeletedEvent = {
429
466
  linkId: string;
430
467
  sourcePortId: string;
431
468
  targetPortId: string;
432
469
  };
470
+ export type TextDeletingEvent = {
471
+ textId: string;
472
+ ownerId?: string | null;
473
+ trigger: DeletionTrigger;
474
+ root: DeletionRootRef;
475
+ cancel: () => void;
476
+ cancelled: boolean;
477
+ };
433
478
  export type TextDeletedEvent = {
434
479
  textId: string;
435
480
  ownerId?: string | null;
@@ -483,13 +528,18 @@ export type EngineEventMap = {
483
528
  portMoved: PortMovedEvent;
484
529
  portSelected: PortSelectedEvent;
485
530
  elementClick: ElementPointerEvent;
531
+ elementDoubleClick: ElementDoubleClickEvent;
486
532
  elementDragged: ElementDropEvent;
487
533
  elementMoved: ElementMovedEvent;
488
534
  elementResized: ElementResizedEvent;
489
535
  gridLayoutChanged: GridLayoutChangedEvent;
536
+ elementDeleting: ElementDeletingEvent;
490
537
  elementDeleted: ElementDeletedEvent;
538
+ portDeleting: PortDeletingEvent;
491
539
  portDeleted: PortDeletedEvent;
540
+ linkDeleting: LinkDeletingEvent;
492
541
  linkDeleted: LinkDeletedEvent;
542
+ textDeleting: TextDeletingEvent;
493
543
  textDeleted: TextDeletedEvent;
494
544
  textUpdated: TextUpdatedEvent;
495
545
  elementSelected: ElementSelectedEvent;
@@ -1,2 +1,4 @@
1
+ import type { DiagramState } from '../../api';
1
2
  import type { DemoConfig } from '../types';
3
+ export declare const createDeletionEventsState: () => DiagramState;
2
4
  export declare const deletionEventsDemoConfig: DemoConfig;
@@ -0,0 +1,4 @@
1
+ import type { DiagramState } from '../../api';
2
+ import type { DemoConfig } from '../types';
3
+ export declare const createFocusElementState: () => DiagramState;
4
+ export declare const focusElementDemoConfig: DemoConfig;
@@ -120,6 +120,7 @@ export default class DiagramEngine {
120
120
  emitPortMouseDown(event: PortMouseEvent): void;
121
121
  emitPortMouseUp(event: PortMouseEvent): void;
122
122
  emitElementClick(elementId: string, pointer: EnginePointerInfo, isMulti: boolean): void;
123
+ emitElementDoubleClick(elementId: string, pointer: EnginePointerInfo, isMulti: boolean): void;
123
124
  emitElementLinkStarted(event: {
124
125
  sourcePortId: string;
125
126
  sourceElementId: string;
@@ -172,6 +173,14 @@ export default class DiagramEngine {
172
173
  private refreshLinksForRenderCycle;
173
174
  private normalizePortsForHostPolicies;
174
175
  private computeRemovalDiff;
176
+ private resolveDeletionRoot;
177
+ private applyRemovalCommand;
178
+ private planRemoval;
179
+ private emitDeletionLifecycleEvents;
180
+ private emitElementDeleting;
181
+ private emitPortDeleting;
182
+ private emitLinkDeleting;
183
+ private emitTextDeleting;
175
184
  private emitEntityDeletionEvents;
176
185
  }
177
186
  export declare const createDiagramEngine: (config: DiagramEngineConfig) => DiagramEngineHandle;
@@ -26,6 +26,9 @@ type ViewportFitOptions = {
26
26
  minZoom?: number;
27
27
  maxZoom?: number;
28
28
  };
29
+ type FocusElementOptions = {
30
+ zoom?: number;
31
+ };
29
32
  type MoveConstraint = 'free' | 'inside' | 'border';
30
33
  type TextInteractionPolicy = {
31
34
  movable?: boolean;
@@ -353,6 +356,11 @@ type ElementPointerEvent = {
353
356
  pointer: EnginePointerInfo;
354
357
  isMulti: boolean;
355
358
  };
359
+ type ElementDoubleClickEvent = {
360
+ elementId: string;
361
+ pointer: EnginePointerInfo;
362
+ isMulti: boolean;
363
+ };
356
364
  type ElementMovedEvent = {
357
365
  elementId: string;
358
366
  oldWorld: Point;
@@ -377,18 +385,55 @@ type GridLayoutChangedEvent = {
377
385
  beforeGridTemplate?: ElementLayoutGridRowTemplate[];
378
386
  afterGridTemplate: ElementLayoutGridRowTemplate[];
379
387
  };
388
+ type DeletionTrigger = 'direct' | 'selection' | 'cascade';
389
+ type DeletionRootRef = {
390
+ entity: 'element' | 'port' | 'link' | 'text';
391
+ id: string;
392
+ };
393
+ type ElementDeletingEvent = {
394
+ elementId: string;
395
+ trigger: DeletionTrigger;
396
+ root: DeletionRootRef;
397
+ cancel: () => void;
398
+ cancelled: boolean;
399
+ };
380
400
  type ElementDeletedEvent = {
381
401
  elementId: string;
382
402
  };
403
+ type PortDeletingEvent = {
404
+ portId: string;
405
+ elementId: string;
406
+ trigger: DeletionTrigger;
407
+ root: DeletionRootRef;
408
+ cancel: () => void;
409
+ cancelled: boolean;
410
+ };
383
411
  type PortDeletedEvent = {
384
412
  portId: string;
385
413
  elementId: string;
386
414
  };
415
+ type LinkDeletingEvent = {
416
+ linkId: string;
417
+ sourcePortId: string;
418
+ targetPortId: string;
419
+ trigger: DeletionTrigger;
420
+ root: DeletionRootRef;
421
+ cancel: () => void;
422
+ cancelled: boolean;
423
+ };
387
424
  type LinkDeletedEvent = {
388
425
  linkId: string;
389
426
  sourcePortId: string;
390
427
  targetPortId: string;
391
428
  };
429
+ type TextDeletingEvent = {
430
+ textId: string;
431
+ ownerId?: string | null;
432
+ trigger: DeletionTrigger;
433
+ root: DeletionRootRef;
434
+ cancel: () => void;
435
+ cancelled: boolean;
436
+ };
392
437
  type TextDeletedEvent = {
393
438
  textId: string;
394
439
  ownerId?: string | null;
@@ -442,13 +487,18 @@ type EngineEventMap = {
442
487
  portMoved: PortMovedEvent;
443
488
  portSelected: PortSelectedEvent;
444
489
  elementClick: ElementPointerEvent;
490
+ elementDoubleClick: ElementDoubleClickEvent;
445
491
  elementDragged: ElementDropEvent;
446
492
  elementMoved: ElementMovedEvent;
447
493
  elementResized: ElementResizedEvent;
448
494
  gridLayoutChanged: GridLayoutChangedEvent;
495
+ elementDeleting: ElementDeletingEvent;
449
496
  elementDeleted: ElementDeletedEvent;
497
+ portDeleting: PortDeletingEvent;
450
498
  portDeleted: PortDeletedEvent;
499
+ linkDeleting: LinkDeletingEvent;
451
500
  linkDeleted: LinkDeletedEvent;
501
+ textDeleting: TextDeletingEvent;
452
502
  textDeleted: TextDeletedEvent;
453
503
  textUpdated: TextUpdatedEvent;
454
504
  elementSelected: ElementSelectedEvent;
@@ -569,6 +619,7 @@ type DiagramEditorHandle = DiagramEngineHandle & {
569
619
  completeLinkToElement: (targetElementId: string, pointer: Point) => void;
570
620
  cancelLink: () => void;
571
621
  zoomToFitElements: (options?: ViewportFitOptions) => void;
622
+ focusElement: (elementId: string, options?: FocusElementOptions) => void;
572
623
  exportImage: (options?: DiagramImageExportOptions) => string;
573
624
  resize: (width: number, height: number) => void;
574
625
  setElementShapeHoverControls: (controls?: ElementShapeHoverControls) => void;
package/dist/index.d.ts CHANGED
@@ -24,6 +24,9 @@ type ViewportFitOptions = {
24
24
  minZoom?: number;
25
25
  maxZoom?: number;
26
26
  };
27
+ type FocusElementOptions = {
28
+ zoom?: number;
29
+ };
27
30
  type MoveConstraint = 'free' | 'inside' | 'border';
28
31
  type TextInteractionPolicy = {
29
32
  movable?: boolean;
@@ -394,6 +397,11 @@ type ElementPointerEvent = {
394
397
  pointer: EnginePointerInfo;
395
398
  isMulti: boolean;
396
399
  };
400
+ type ElementDoubleClickEvent = {
401
+ elementId: string;
402
+ pointer: EnginePointerInfo;
403
+ isMulti: boolean;
404
+ };
397
405
  type ElementMovedEvent = {
398
406
  elementId: string;
399
407
  oldWorld: Point;
@@ -418,18 +426,55 @@ type GridLayoutChangedEvent = {
418
426
  beforeGridTemplate?: ElementLayoutGridRowTemplate[];
419
427
  afterGridTemplate: ElementLayoutGridRowTemplate[];
420
428
  };
429
+ type DeletionTrigger = 'direct' | 'selection' | 'cascade';
430
+ type DeletionRootRef = {
431
+ entity: 'element' | 'port' | 'link' | 'text';
432
+ id: string;
433
+ };
434
+ type ElementDeletingEvent = {
435
+ elementId: string;
436
+ trigger: DeletionTrigger;
437
+ root: DeletionRootRef;
438
+ cancel: () => void;
439
+ cancelled: boolean;
440
+ };
421
441
  type ElementDeletedEvent = {
422
442
  elementId: string;
423
443
  };
444
+ type PortDeletingEvent = {
445
+ portId: string;
446
+ elementId: string;
447
+ trigger: DeletionTrigger;
448
+ root: DeletionRootRef;
449
+ cancel: () => void;
450
+ cancelled: boolean;
451
+ };
424
452
  type PortDeletedEvent = {
425
453
  portId: string;
426
454
  elementId: string;
427
455
  };
456
+ type LinkDeletingEvent = {
457
+ linkId: string;
458
+ sourcePortId: string;
459
+ targetPortId: string;
460
+ trigger: DeletionTrigger;
461
+ root: DeletionRootRef;
462
+ cancel: () => void;
463
+ cancelled: boolean;
464
+ };
428
465
  type LinkDeletedEvent = {
429
466
  linkId: string;
430
467
  sourcePortId: string;
431
468
  targetPortId: string;
432
469
  };
470
+ type TextDeletingEvent = {
471
+ textId: string;
472
+ ownerId?: string | null;
473
+ trigger: DeletionTrigger;
474
+ root: DeletionRootRef;
475
+ cancel: () => void;
476
+ cancelled: boolean;
477
+ };
433
478
  type TextDeletedEvent = {
434
479
  textId: string;
435
480
  ownerId?: string | null;
@@ -483,13 +528,18 @@ type EngineEventMap = {
483
528
  portMoved: PortMovedEvent;
484
529
  portSelected: PortSelectedEvent;
485
530
  elementClick: ElementPointerEvent;
531
+ elementDoubleClick: ElementDoubleClickEvent;
486
532
  elementDragged: ElementDropEvent;
487
533
  elementMoved: ElementMovedEvent;
488
534
  elementResized: ElementResizedEvent;
489
535
  gridLayoutChanged: GridLayoutChangedEvent;
536
+ elementDeleting: ElementDeletingEvent;
490
537
  elementDeleted: ElementDeletedEvent;
538
+ portDeleting: PortDeletingEvent;
491
539
  portDeleted: PortDeletedEvent;
540
+ linkDeleting: LinkDeletingEvent;
492
541
  linkDeleted: LinkDeletedEvent;
542
+ textDeleting: TextDeletingEvent;
493
543
  textDeleted: TextDeletedEvent;
494
544
  textUpdated: TextUpdatedEvent;
495
545
  elementSelected: ElementSelectedEvent;
@@ -857,6 +907,7 @@ type DiagramEditorHandle = DiagramEngineHandle & {
857
907
  completeLinkToElement: (targetElementId: string, pointer: Point) => void;
858
908
  cancelLink: () => void;
859
909
  zoomToFitElements: (options?: ViewportFitOptions) => void;
910
+ focusElement: (elementId: string, options?: FocusElementOptions) => void;
860
911
  exportImage: (options?: DiagramImageExportOptions) => string;
861
912
  resize: (width: number, height: number) => void;
862
913
  setElementShapeHoverControls: (controls?: ElementShapeHoverControls) => void;
@@ -864,4 +915,4 @@ type DiagramEditorHandle = DiagramEngineHandle & {
864
915
  };
865
916
  declare const createDiagramEditor: (config: DiagramEditorConfig) => DiagramEditorHandle;
866
917
 
867
- export { type AnchorReference, type BorderSide$1 as BorderSide, type ClientRectLike, type DiagramContainer, type DiagramEditorConfig, type DiagramEditorHandle, type DiagramEngineHandle, type DiagramImageExportOptions, type DiagramPatch, type DiagramState, type EdgeHoverControl, type ElementChildInteractionPolicy, type ElementData, type ElementDeletedEvent, type ElementDropEvent, type ElementLayout, type ElementLayoutAlign, type ElementLayoutAutoResizeMode, type ElementLayoutChildFitCrossAxis, type ElementLayoutChildFitMainAxis, type ElementLayoutGridRowTemplate, type ElementLayoutLabelReservedSpace, type ElementLayoutLabelReservedSpaceMode, type ElementLayoutLabelReservedSpacePlacement, type ElementLayoutMode, type ElementLinkConnectingEvent, type ElementLinkEndedEvent, type ElementLinkStartedEvent, type ElementMovedEvent, type ElementPointerEvent, type ElementPortMovementPolicy, type ElementResizedEvent, type ElementSelectedEvent, type ElementShapeControlDragEvent, type ElementShapeControlEventType, type ElementShapeHoverControlActivationEvent, type ElementShapeHoverControlInteractionEvent, type ElementShapeHoverControls, EllipseMidPoint, type EngineChangeEvent, type EngineConfigEvent, type EngineEventMap, type EnginePointerInfo, type EngineSelectionEvent, type GridLayoutChangedEvent, type GridLayoutChangedReason, type GridRowSnapshot, type HostAnchorPreset, type HoverControlIcon, type LinkColorPoolPolicy, type LinkData, type LinkDeletedEvent, type LinkRouteRefreshMode, type LinkRouteRefreshPolicy, type LinkRoutingMode, type LinkTargetPortCreationContext, type LinkTargetPortCreationHandler, type LinkTargetPortCreationPhase, type LinkTargetPortCreationResult, type LinkTargetPortDraft, type MoveConstraint, type OverlayShapeConfig, type OverlayShapeHandle, type PaperClickEvent, type Point, type PortAnchor, type PortAnchorConstraint, type PortBorderTransformContext, type PortBorderTransformResult, type PortData, type PortDeletedEvent, type PortLinkAttachMode, type PortMouseEvent, type PortMovedEvent, type PortPositionLimits, type PortSelectedEvent, type PositionAxisLimit, type Rect, type RerouteLinksOptions, type ResolvePortAnchorsOptions, type ShapeControlDefinition, type ShapeControlTargetKind, type ShapeControlVisibilityTrigger, type ShapeDrawContext, type ShapeEdgeTarget, type ShapeEllipseMidPointTarget, type ShapeHoverGeometry, type ShapeVertexTarget, type SimpleShape, type Size, type TextData, type TextDeletedEvent, type TextInteractionPolicy, type TextLayout, type TextLayoutBoundsMode, type TextLayoutOverflowMode, type TextLayoutWrapMode, type TextSelectedEvent, type TextUpdatedEvent, type VertexHoverControl, type ViewportFitOptions, createDiagramEditor, createDiagramEngine };
918
+ export { type AnchorReference, type BorderSide$1 as BorderSide, type ClientRectLike, type DeletionRootRef, type DeletionTrigger, type DiagramContainer, type DiagramEditorConfig, type DiagramEditorHandle, type DiagramEngineHandle, type DiagramImageExportOptions, type DiagramPatch, type DiagramState, type EdgeHoverControl, type ElementChildInteractionPolicy, type ElementData, type ElementDeletedEvent, type ElementDeletingEvent, type ElementDoubleClickEvent, type ElementDropEvent, type ElementLayout, type ElementLayoutAlign, type ElementLayoutAutoResizeMode, type ElementLayoutChildFitCrossAxis, type ElementLayoutChildFitMainAxis, type ElementLayoutGridRowTemplate, type ElementLayoutLabelReservedSpace, type ElementLayoutLabelReservedSpaceMode, type ElementLayoutLabelReservedSpacePlacement, type ElementLayoutMode, type ElementLinkConnectingEvent, type ElementLinkEndedEvent, type ElementLinkStartedEvent, type ElementMovedEvent, type ElementPointerEvent, type ElementPortMovementPolicy, type ElementResizedEvent, type ElementSelectedEvent, type ElementShapeControlDragEvent, type ElementShapeControlEventType, type ElementShapeHoverControlActivationEvent, type ElementShapeHoverControlInteractionEvent, type ElementShapeHoverControls, EllipseMidPoint, type EngineChangeEvent, type EngineConfigEvent, type EngineEventMap, type EnginePointerInfo, type EngineSelectionEvent, type FocusElementOptions, type GridLayoutChangedEvent, type GridLayoutChangedReason, type GridRowSnapshot, type HostAnchorPreset, type HoverControlIcon, type LinkColorPoolPolicy, type LinkData, type LinkDeletedEvent, type LinkDeletingEvent, type LinkRouteRefreshMode, type LinkRouteRefreshPolicy, type LinkRoutingMode, type LinkTargetPortCreationContext, type LinkTargetPortCreationHandler, type LinkTargetPortCreationPhase, type LinkTargetPortCreationResult, type LinkTargetPortDraft, type MoveConstraint, type OverlayShapeConfig, type OverlayShapeHandle, type PaperClickEvent, type Point, type PortAnchor, type PortAnchorConstraint, type PortBorderTransformContext, type PortBorderTransformResult, type PortData, type PortDeletedEvent, type PortDeletingEvent, type PortLinkAttachMode, type PortMouseEvent, type PortMovedEvent, type PortPositionLimits, type PortSelectedEvent, type PositionAxisLimit, type Rect, type RerouteLinksOptions, type ResolvePortAnchorsOptions, type ShapeControlDefinition, type ShapeControlTargetKind, type ShapeControlVisibilityTrigger, type ShapeDrawContext, type ShapeEdgeTarget, type ShapeEllipseMidPointTarget, type ShapeHoverGeometry, type ShapeVertexTarget, type SimpleShape, type Size, type TextData, type TextDeletedEvent, type TextDeletingEvent, type TextInteractionPolicy, type TextLayout, type TextLayoutBoundsMode, type TextLayoutOverflowMode, type TextLayoutWrapMode, type TextSelectedEvent, type TextUpdatedEvent, type VertexHoverControl, type ViewportFitOptions, createDiagramEditor, createDiagramEngine };
@@ -105,6 +105,12 @@ Defaults:
105
105
  - non-finite values fall back to defaults
106
106
  - `minZoom`/`maxZoom` are clamped to positive values and normalized into ascending order
107
107
 
108
+ ### `FocusElementOptions`
109
+ - Optional `zoom?: number`
110
+ - Semantics:
111
+ - omitted `zoom` preserves the current viewport zoom
112
+ - provided `zoom` is clamped to the same normalized min/max range used by viewport fit helpers
113
+
108
114
  ### `TextInteractionPolicy`
109
115
  - Optional `movable?: boolean` (default behavior: `true`)
110
116
  - Optional `editable?: boolean` (default behavior: `true`)
@@ -197,6 +203,36 @@ Defaults:
197
203
  - `beforeRows` / `afterRows`: arrays of `{ childIds: string[] }` snapshots describing derived row membership before and after the topology change
198
204
  - Emitted only when enabled grid-child width resizing causes a real row-topology change
199
205
 
206
+ ### `ElementDoubleClickEvent`
207
+ - Required: `elementId`, `pointer`, `isMulti`
208
+ - Emitted for eligible element-body double click / double tap
209
+ - Observational only; does not cancel or replace the normal click-selection flow
210
+
211
+ ### `DeletionTrigger`
212
+ - `'direct' | 'selection' | 'cascade'`
213
+
214
+ ### `DeletionRootRef`
215
+ - Required: `entity`, `id`
216
+ - `entity`: `'element' | 'port' | 'link' | 'text'`
217
+ - `id` is the original requested delete root for the active delete pass
218
+
219
+ ### `ElementDeletingEvent`
220
+ - Required: `elementId`, `trigger`, `root`, `cancel`, `cancelled`
221
+ - Emitted before an element deletion commits, including descendant element cascades
222
+
223
+ ### `PortDeletingEvent`
224
+ - Required: `portId`, `elementId`, `trigger`, `root`, `cancel`, `cancelled`
225
+ - Emitted before a port deletion commits, including cascades caused by parent element removal
226
+
227
+ ### `LinkDeletingEvent`
228
+ - Required: `linkId`, `sourcePortId`, `targetPortId`, `trigger`, `root`, `cancel`, `cancelled`
229
+ - Emitted before a link deletion commits, including cascades caused by element or port removal
230
+
231
+ ### `TextDeletingEvent`
232
+ - Required: `textId`, `trigger`, `root`, `cancel`, `cancelled`
233
+ - Optional: `ownerId?: string | null`
234
+ - Emitted before a text deletion commits, including cascades caused by owner deletion
235
+
200
236
  ### `TextData`
201
237
  - Required: `id`, `content`, `position`
202
238
  - Optional: `size`, `style`, `ownerId`, `layout`, `interaction`, `displayContent`, `displayOffset`, `displayClipSize`
@@ -251,6 +287,7 @@ Defaults:
251
287
  - `completeLinkToElement(targetElementId, pointer)`
252
288
  - `cancelLink()`
253
289
  - `zoomToFitElements(options?)`
290
+ - `focusElement(elementId, options?)`
254
291
  - `exportImage(options?)`
255
292
  - `resize(width, height)`
256
293
  - `setElementShapeHoverControls(controls?)`
@@ -290,13 +327,18 @@ Defaults:
290
327
  - `portMoved: PortMovedEvent`
291
328
  - `portSelected: PortSelectedEvent`
292
329
  - `elementClick: ElementPointerEvent`
330
+ - `elementDoubleClick: ElementDoubleClickEvent`
293
331
  - `elementDragged: ElementDropEvent`
294
332
  - `elementMoved: ElementMovedEvent`
295
333
  - `elementResized: ElementResizedEvent`
296
334
  - `gridLayoutChanged: GridLayoutChangedEvent`
335
+ - `elementDeleting: ElementDeletingEvent`
297
336
  - `elementDeleted: ElementDeletedEvent`
337
+ - `portDeleting: PortDeletingEvent`
298
338
  - `portDeleted: PortDeletedEvent`
339
+ - `linkDeleting: LinkDeletingEvent`
299
340
  - `linkDeleted: LinkDeletedEvent`
341
+ - `textDeleting: TextDeletingEvent`
300
342
  - `textDeleted: TextDeletedEvent`
301
343
  - `textUpdated: TextUpdatedEvent`
302
344
  - `elementSelected: ElementSelectedEvent`
@@ -312,8 +354,11 @@ Defaults:
312
354
  - `zoomToFitElements` computes bounds from `elements[]` only, ignores ports/links/texts for fit expansion, and no-ops when no elements exist.
313
355
  - `zoomToFitElements` ignores hidden elements when computing fit bounds.
314
356
  - `zoomToFitElements` applies its result through `setViewport`, so hosts observe the standard viewport patch/change path.
357
+ - `focusElement(elementId, options?)` centers the target element bounds in the current editor viewport and preserves the current zoom unless `options.zoom` is provided.
358
+ - `focusElement(...)` no-ops when the target id does not resolve to an element world position.
315
359
  - `exportImage({ fitToContent })` derives crop bounds from visible scene entities only.
316
360
  - Built-in empty-paper panning now starts from plain primary-button drag and no longer requires `panKey`; marquee selection uses `Shift + primary drag`.
361
+ - `elementDoubleClick` is observational; normal click selection still runs, and text double click keeps built-in text-edit precedence instead of also emitting `elementDoubleClick`.
317
362
  - `clientToWorld` uses: `world = (client - containerRect - pan) / zoom`, with zoom fallback to `1` when zoom is `0`.
318
363
  - `rerouteLinks(ids)` skips manual links unless `options.includeManual === true`.
319
364
  - `linkRouteRefreshPolicy.mode` defaults to `'mutation-only'`; `'redraw-two-endpoint-change'` enables redraw-cycle reroute checks for links whose two endpoints changed.
@@ -326,6 +371,8 @@ Defaults:
326
371
  - Link labels use the existing text lifecycle and event surface: `addText(...)`, `moveTextTo(...)`, `updateText(...)`, `removeText(...)`, `textUpdated`, and `textDeleted`.
327
372
  - Link-owned text defaults to unconstrained layout unless `TextLayout.boundsMode` is explicitly set; element-only owner-width defaults do not apply to link labels.
328
373
  - `gridLayoutChanged` is additive and does not replace standard `change` / `elementResized` flows.
374
+ - Deletion mutators emit cancellable `elementDeleting` / `portDeleting` / `linkDeleting` / `textDeleting` before commit and matching `...Deleted` events after successful removal.
375
+ - Canceling any dependent `...Deleting` event aborts the current root deletion request; `deleteSelection()` still continues evaluating unrelated selected roots.
329
376
  - `ElementData.visible = false` hides only the element body from built-in renderer sync, hit testing, marquee selection, persisted selection, and fit/export helpers.
330
377
  - Descendant element visibility is not suppressed by hidden ancestors; direct-owned parent ports/texts still follow the hidden parent, and links remain visible whenever both endpoint ports are visible.
331
378
  - `ElementData.selectable = false` blocks built-in element-body selection while still allowing visible owned ports to participate in their normal interaction flows.
@@ -334,7 +381,7 @@ Defaults:
334
381
  - `TextData.interaction.movable = false` blocks built-in drag only; selection still works and programmatic movement remains allowed.
335
382
  - `TextData.interaction.editable = false` blocks built-in textarea editing only; selection still works and programmatic text updates remain allowed.
336
383
  - Text layout/overflow resolution updates `displayContent` and emits `textUpdated` when `updateText` is called.
337
- - Deletion mutators emit cascading `portDeleted`/`linkDeleted`/`textDeleted` for removed dependent entities.
384
+ - Successful cascade removal still emits the matching dependent `...Deleted` events for removed entities.
338
385
 
339
386
  ## Verification References
340
387
  - `src/api/__tests__/createDiagramEditor.test.ts`
@@ -3,8 +3,8 @@
3
3
  > Sections: [Module Boundaries](#module-boundaries) | [Runtime Flow](#runtime-flow) | [Integration Boundary](#integration-boundary) | [Key Sources](#key-sources)
4
4
 
5
5
  ## Module Boundaries
6
- - `src/api/`: public entry points and type contracts.
7
- - `src/engine/`: command execution, event bus, selection, viewport, routing/snap integration.
6
+ - `src/api/`: public entry points, type contracts, and editor-only helpers such as `zoomToFitElements(...)` and `focusElement(...)`.
7
+ - `src/engine/`: command execution, event bus, selection, viewport, routing/snap integration, and delete-lifecycle orchestration.
8
8
  - `src/engine/`: `DiagramEngine` orchestration plus extracted services (`TextLayoutService`, `AutoLayoutService`, `LinkRoutingService`, `MutationPipeline`).
9
9
  - `src/models/`: in-memory state graph for elements/ports/links/texts.
10
10
  - `src/renderer/`: renderer interface and shape registry contracts.
@@ -14,15 +14,17 @@
14
14
  - `src/utils/`: geometry, patch helpers, guards, ids.
15
15
 
16
16
  ## Runtime Flow
17
- 1. Host calls API mutator.
18
- 2. Engine executes command(s) against model.
19
- 3. Engine emits patches + latest state via `change`.
20
- 4. Scheduler requests render.
21
- 5. Renderer syncs model to view nodes.
17
+ 1. Host calls API mutator or editor helper.
18
+ 2. Interaction or API helper resolves target intent and any required lifecycle hooks.
19
+ 3. Engine executes command(s) against model or applies viewport state updates.
20
+ 4. Engine emits patches + latest state via `change`.
21
+ 5. Scheduler requests render.
22
+ 6. Renderer syncs model to view nodes.
22
23
 
23
24
  ## Integration Boundary
24
25
  - Engine core does not require Konva if you use `createDiagramEngine` with a custom `Renderer`.
25
26
  - `createDiagramEditor` wires Konva stage, hit testing, and interaction defaults.
27
+ - The Konva-backed editor surface also owns editor-only navigation helpers such as `focusElement(...)`.
26
28
 
27
29
  ## Key Sources
28
30
  - `src/api/createDiagramEditor.ts`
@@ -18,7 +18,10 @@
18
18
  - Optional grid-child width topology editing with `gridLayoutChanged` host events.
19
19
  - Parent-owned direct-child drag suppression through `ElementData.childElementInteraction`.
20
20
  - Element-level visibility/selectability policy through `ElementData.visible` and `ElementData.selectable`, with element-body-only hiding, direct-owned port/text suppression, and visible descendants that keep their own links/rendering behavior.
21
+ - Host-callable viewport focus through `focusElement(elementId, options?)`.
21
22
  - Element shape hover controls with edge/vertex/midpoint targets and interaction callbacks.
23
+ - Observational `elementDoubleClick` event for element-body double click / double tap.
24
+ - Cancellable delete lifecycle events (`elementDeleting`, `portDeleting`, `linkDeleting`, `textDeleting`) before direct, selection, and cascade removals commit.
22
25
  - Link labels through link-owned `TextData`, including midpoint-relative attachment that follows reroute and endpoint movement.
23
26
  - Optional host callback for shaping auto-created destination ports during link-to-element preview and commit.
24
27
  - Optional random link color assignment from configurable pools during link creation, plus opt-in load-time fill for links missing `style.stroke`.
@@ -6,7 +6,7 @@
6
6
  - Engine mutators route through command factories in `src/engine/EngineCommands.ts`.
7
7
  - Each command applies model mutation and returns one or more patches.
8
8
  - `emitChange` publishes `{ patches, state }` on `change`.
9
- - Editor helpers such as `zoomToFitElements(options?)` compose existing engine commands rather than introducing a separate patch type.
9
+ - Editor helpers such as `zoomToFitElements(options?)` and `focusElement(elementId, options?)` compose existing viewport updates rather than introducing separate patch types.
10
10
 
11
11
  ## Patch Entities
12
12
  - `element`
@@ -20,7 +20,7 @@
20
20
  ## Mutation To Events Mapping
21
21
  - `add/move/resize/remove element`
22
22
  - Always `change`
23
- - Plus `elementMoved`, `elementResized`, or `elementDeleted` when applicable
23
+ - Plus `elementMoved`, `elementResized`, `elementDeleting`, or `elementDeleted` when applicable
24
24
  - `resize element` with enabled grid-child width topology editing
25
25
  - Standard `change`
26
26
  - Standard `elementResized` when size changes
@@ -28,22 +28,26 @@
28
28
  - `add/move/remove port`
29
29
  - Always `change`
30
30
  - Plus `portMoved` on effective movement
31
- - Plus `portDeleted` on removal (including cascade removal)
31
+ - Plus `portDeleting` before removal and `portDeleted` on successful removal (including cascade removal)
32
32
  - `add/update/remove link`
33
33
  - Always `change`
34
- - Plus `linkDeleted` on removal (including cascade removal)
34
+ - Plus `linkDeleting` before removal and `linkDeleted` on successful removal (including cascade removal)
35
35
  - `add/update/move/remove text`
36
36
  - Always `change`
37
37
  - Plus `textUpdated` when `updateText` resolves display layout
38
- - Plus `textDeleted` on removal (including cascade removal)
38
+ - Plus `textDeleting` before removal and `textDeleted` on successful removal (including cascade removal)
39
39
  - `setSelection/toggleSelection/deleteSelection`
40
40
  - `selection` plus derived selected entity events
41
+ - `deleteSelection` evaluates each selected root independently, so a vetoed root can be skipped while unrelated roots still delete
41
42
  - hidden element bodies, direct-owned hidden artifacts, and `selectable:false` element IDs are filtered out before selection persists/emits
42
43
  - `setViewport`
43
44
  - `change` with viewport patch (`render: false`)
44
45
  - `zoomToFitElements`
45
46
  - delegates to `setViewport` when at least one visible element exists
46
47
  - emits the same viewport `change` patch path
48
+ - `focusElement`
49
+ - delegates to `setViewport` when the target element resolves
50
+ - preserves the current zoom unless `options.zoom` is supplied
47
51
  - `setRouting/setSnapping/registerShape`
48
52
  - `config` events
49
53
 
@@ -53,6 +57,8 @@
53
57
  - legacy `element-drop`
54
58
  - `elementDragged`
55
59
  - Click paper: `paperClick`
60
+ - Double click/tap element body:
61
+ - `elementDoubleClick`
56
62
  - Linking:
57
63
  - `elementLinkStarted`
58
64
  - optional `onCreateLinkTargetPort(...)` preview/commit shaping for link-to-element completion
@@ -60,13 +66,16 @@
60
66
  - `elementLinkEnded`
61
67
 
62
68
  ## Preconditions
63
- - Events are emitted only after engine state transition logic.
69
+ - Events are emitted only after engine state transition logic resolves a valid action.
70
+ - Cancellable `...Deleting` events emit before the corresponding mutation commits.
64
71
  - Derived events require selected IDs to resolve to known entity types.
65
72
 
66
73
  ## Failure Modes
67
74
  - Unknown IDs do not emit entity-specific movement/selection events.
68
75
  - Canceled link creation emits `elementLinkEnded` with `cancelled=true` and no link creation.
76
+ - `focusElement(...)` emits no viewport change when the target element id does not resolve.
69
77
  - Built-in element-body selection emits no persisted element selection when the target element is hidden or sets `selectable = false`.
78
+ - Text double click continues text editing precedence and does not also emit `elementDoubleClick`.
70
79
  - Built-in drag on a direct child element emits no move/drop mutation when its parent sets `childElementInteraction.movable = false`.
71
80
  - `textUpdated` emits only when target text exists; missing IDs remain no-op.
72
81
 
@@ -59,7 +59,7 @@ When resuming later:
59
59
  5. Re-run packaging verification.
60
60
 
61
61
  ## 6. Current Status
62
- - Last updated: 2026-06-26
62
+ - Last updated: 2026-07-07
63
63
  - Last completed step: 10
64
64
  - Next step: 7 (optional additional fixture coverage for deeper nested/manual-route scenarios)
65
65
  - Owner: Codex (with repository maintainers)
@@ -93,3 +93,5 @@ When resuming later:
93
93
  - 2026-06-20: Ran release validations: `npm run typecheck`, `npm test -- --watchAll=false`, `npm run build`, `npm run rollup-build-lib`, and `npm pack --dry-run`.
94
94
  - 2026-06-26: Completed release-doc pass for `v0.2.12`; refreshed release highlights, link-created target-port callback contract text, integration guidance, and machine-readable contract metadata.
95
95
  - 2026-06-26: Ran release validations: `npm run typecheck`, `npm test -- --watchAll=false`, `npm run build`, `npm run rollup-build-lib`, and `npm pack --dry-run`.
96
+ - 2026-07-07: Completed release-doc pass for `v0.2.13`; refreshed release highlights, focus/navigation and delete-lifecycle API/event docs, and machine-readable contract metadata.
97
+ - 2026-07-07: Ran release validations: `npm run typecheck`, `npm test -- --watchAll=false`, `npm run build`, `npm run rollup-build-lib`, and `npm pack --dry-run`.
@@ -23,6 +23,8 @@ Embed this library into another diagram host while preserving deterministic stat
23
23
  10. Set `linkColorPoolPolicy` when hosts want random link colors on creation and optional load-time backfill for loaded links whose `style.stroke` is missing or blank.
24
24
  11. Create link labels with ordinary `TextData` by setting `ownerId` to the target link id; the stored `position` is midpoint-relative for link-owned text rather than a free world-space coordinate.
25
25
  12. Set `onCreateLinkTargetPort` when hosts need to customize the auto-created destination port for link-to-element drops; keep using `elementLinkConnecting` when the host needs to cancel the drop entirely.
26
+ 13. Use `focusElement(elementId, options?)` when the host needs to center one editor element in response to navigation, search, or external selection.
27
+ 14. Subscribe to `elementDoubleClick` and cancellable `...Deleting` events when the host needs double-click intent or pre-delete confirmation/guard logic.
26
28
 
27
29
  ## Path B: Engine-Only Adapter
28
30
  1. Implement `Renderer`:
@@ -42,9 +44,11 @@ Embed this library into another diagram host while preserving deterministic stat
42
44
  - host edge label -> `TextData` with `ownerId = link.id`
43
45
  - Event mapping:
44
46
  - host click -> `setSelection` / `emitElementClick`-equivalent behavior
47
+ - host double click / double tap -> `elementDoubleClick`
45
48
  - host drag end -> `emitElementDrop`-equivalent payload
46
49
  - host link gesture -> `elementLinkStarted/Connecting/Ended` lifecycle
47
50
  - optional host target-port shaping -> `onCreateLinkTargetPort(...)` for link-to-element preview/commit only
51
+ - host delete confirmation / veto surface -> cancellable `elementDeleting` / `portDeleting` / `linkDeleting` / `textDeleting`
48
52
 
49
53
  ## Behavioral Checklist Per Integration Step
50
54
  - Preconditions
@@ -32,14 +32,17 @@
32
32
  - Ensure host can emulate:
33
33
  - `elementDrop` + legacy `element-drop`
34
34
  - `paperClick`
35
+ - `elementDoubleClick`
35
36
  - `elementLinkStarted/Connecting/Ended`
36
37
  - `portMouseDown/portMouseUp`
37
- - deletion and text lifecycle events (`portDeleted`, `linkDeleted`, `textDeleted`, `textUpdated`)
38
+ - cancellable delete lifecycle events (`elementDeleting`, `portDeleting`, `linkDeleting`, `textDeleting`)
39
+ - post-delete and text lifecycle events (`elementDeleted`, `portDeleted`, `linkDeleted`, `textDeleted`, `textUpdated`)
38
40
 
39
41
  ## 6. Verify Cascading Deletes
40
42
  - Deleting element should remove descendant ports, connected links, owned texts.
41
43
  - Deleting port should remove connected links and owned texts.
42
44
  - Deleting link should remove owned texts.
45
+ - A veto from any `...Deleting` handler should abort that root delete request before mutation commit.
43
46
 
44
47
  ## 7. Run Fixture-Based Validation
45
48
  - Load fixtures from `fixtures/*.json`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orcasvn-react-diagrams",
3
- "version": "0.2.12",
3
+ "version": "0.2.13",
4
4
  "dependencies": {
5
5
  "eventemitter3": "^5.0.1",
6
6
  "flatten-js": "^0.6.9",