@onerjs/shared-ui-components 8.44.7 → 8.44.8

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 (44) hide show
  1. package/components/bars/CommandButton.module.scss +2 -0
  2. package/historyStack.js +3 -0
  3. package/historyStack.js.map +1 -1
  4. package/nodeGraphSystem/common.module.scss +3 -0
  5. package/nodeGraphSystem/graphCanvas.d.ts +37 -0
  6. package/nodeGraphSystem/graphCanvas.js +139 -6
  7. package/nodeGraphSystem/graphCanvas.js.map +1 -1
  8. package/nodeGraphSystem/graphMinimap.d.ts +79 -0
  9. package/nodeGraphSystem/graphMinimap.js +319 -0
  10. package/nodeGraphSystem/graphMinimap.js.map +1 -0
  11. package/nodeGraphSystem/graphMinimap.module.scss +30 -0
  12. package/nodeGraphSystem/graphNode.d.ts +16 -0
  13. package/nodeGraphSystem/graphNode.js +76 -1
  14. package/nodeGraphSystem/graphNode.js.map +1 -1
  15. package/nodeGraphSystem/graphNode.module.scss +61 -0
  16. package/nodeGraphSystem/graphSearch.d.ts +54 -0
  17. package/nodeGraphSystem/graphSearch.js +181 -0
  18. package/nodeGraphSystem/graphSearch.js.map +1 -0
  19. package/nodeGraphSystem/graphSearch.module.scss +86 -0
  20. package/nodeGraphSystem/graphStickyNote.d.ts +94 -0
  21. package/nodeGraphSystem/graphStickyNote.js +310 -0
  22. package/nodeGraphSystem/graphStickyNote.js.map +1 -0
  23. package/nodeGraphSystem/graphStickyNote.module.scss +87 -0
  24. package/nodeGraphSystem/interfaces/nodeData.d.ts +2 -0
  25. package/nodeGraphSystem/interfaces/nodeData.js.map +1 -1
  26. package/nodeGraphSystem/interfaces/nodeLocationInfo.d.ts +10 -0
  27. package/nodeGraphSystem/interfaces/nodeLocationInfo.js.map +1 -1
  28. package/nodeGraphSystem/interfaces/portData.d.ts +2 -1
  29. package/nodeGraphSystem/interfaces/portData.js +1 -0
  30. package/nodeGraphSystem/interfaces/portData.js.map +1 -1
  31. package/nodeGraphSystem/interfaces/selectionChangedOptions.d.ts +2 -1
  32. package/nodeGraphSystem/interfaces/selectionChangedOptions.js.map +1 -1
  33. package/nodeGraphSystem/nodeLink.d.ts +12 -0
  34. package/nodeGraphSystem/nodeLink.js +77 -0
  35. package/nodeGraphSystem/nodeLink.js.map +1 -1
  36. package/nodeGraphSystem/nodePort.js +26 -1
  37. package/nodeGraphSystem/nodePort.js.map +1 -1
  38. package/nodeGraphSystem/nodePort.module.scss +37 -0
  39. package/nodeGraphSystem/stateManager.d.ts +6 -0
  40. package/nodeGraphSystem/stateManager.js +6 -0
  41. package/nodeGraphSystem/stateManager.js.map +1 -1
  42. package/package.json +1 -1
  43. package/split/splitContainer.js +2 -1
  44. package/split/splitContainer.js.map +1 -1
@@ -16,6 +16,7 @@
16
16
  .active {
17
17
  transform-origin: center;
18
18
  background-color: var(--selectionGrey);
19
+ box-shadow: 0 2px 0 0 white;
19
20
  }
20
21
 
21
22
  .commandButtonIcon {
@@ -30,4 +31,5 @@
30
31
  .disabled {
31
32
  pointer-events: none;
32
33
  color: black;
34
+ opacity: 0.35;
33
35
  }
package/historyStack.js CHANGED
@@ -165,6 +165,9 @@ export class HistoryStack {
165
165
  try {
166
166
  // _dataProvider can return T or Promise<T>; await handles both.
167
167
  const provided = await this._dataProvider();
168
+ if (provided == null) {
169
+ return;
170
+ }
168
171
  const data = this._copy(provided);
169
172
  if (this._activeData) {
170
173
  const diff = this._generateJSONDiff(data, this._activeData);
@@ -1 +1 @@
1
- {"version":3,"file":"historyStack.js","sourceRoot":"","sources":["../../../dev/sharedUiComponents/src/historyStack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IDisposable } from \"core/scene\";\r\n\r\n/**\r\n * Class handling undo / redo operations\r\n */\r\nexport class HistoryStack implements IDisposable {\r\n private _historyStack: string[] = [];\r\n private _redoStack: string[] = [];\r\n private _activeData: any;\r\n private readonly _maxHistoryLength = 256;\r\n private _locked = false;\r\n private _dataProvider: () => any;\r\n private _applyUpdate: (data: any) => void;\r\n\r\n /**\r\n * Gets or sets a boolean indicating if the stack is enabled\r\n */\r\n public isEnabled = true;\r\n\r\n /**\r\n * Constructor\r\n * @param dataProvider defines the data provider function\r\n * @param applyUpdate defines the code to execute when undo/redo operation is required\r\n */\r\n constructor(dataProvider: () => any, applyUpdate: (data: any) => void) {\r\n this._dataProvider = dataProvider;\r\n this._applyUpdate = applyUpdate;\r\n }\r\n\r\n /**\r\n * Process key event to handle undo / redo\r\n * @param evt defines the keyboard event to process\r\n * @returns true if the event was processed\r\n */\r\n processKeyEvent(evt: KeyboardEvent): boolean {\r\n if (!this.isEnabled) {\r\n return false;\r\n }\r\n\r\n if (evt.ctrlKey || evt.metaKey) {\r\n if (evt.key === \"z\" || evt.key === \"Z\") {\r\n if (evt.shiftKey) {\r\n this.redo();\r\n return true;\r\n }\r\n\r\n this.undo();\r\n return true;\r\n }\r\n if (evt.key === \"y\" || evt.key === \"Y\") {\r\n this.redo();\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Resets the stack\r\n */\r\n public reset() {\r\n this._historyStack = [];\r\n this._redoStack = [];\r\n this._activeData = null;\r\n void this.storeAsync();\r\n }\r\n\r\n /**\r\n * Remove the n-1 element of the stack\r\n */\r\n public collapseLastTwo() {\r\n if (this._historyStack.length < 2) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n const diff = this._historyStack.pop()!;\r\n const diff2 = this._historyStack.pop()!;\r\n\r\n let newState = this._applyJSONDiff(this._activeData, JSON.parse(diff));\r\n newState = this._applyJSONDiff(newState, JSON.parse(diff2));\r\n\r\n this._historyStack.push(JSON.stringify(this._generateJSONDiff(this._activeData, newState)));\r\n\r\n this._locked = false;\r\n }\r\n\r\n private _generateJSONDiff(obj1: any, obj2: any): any {\r\n if (obj1 === obj2) {\r\n return undefined;\r\n }\r\n if (obj1 === null || obj2 === null || typeof obj1 !== \"object\" || typeof obj2 !== \"object\") {\r\n if (obj1 !== obj2 && obj2 === undefined) {\r\n return \"@d@\";\r\n }\r\n return obj2;\r\n }\r\n\r\n if (Array.isArray(obj1) && Array.isArray(obj2)) {\r\n const diff = [];\r\n const maxLength = Math.max(obj1.length, obj2.length);\r\n let hasChanges = false;\r\n\r\n for (let i = 0; i < maxLength; i++) {\r\n const localDiff = this._generateJSONDiff(obj1[i], obj2[i]);\r\n if (localDiff !== undefined) {\r\n diff[i] = localDiff;\r\n hasChanges = true;\r\n }\r\n }\r\n\r\n return hasChanges ? diff : undefined;\r\n }\r\n\r\n const diff: any = {};\r\n const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);\r\n let hasChanges = false;\r\n\r\n for (const key of keys) {\r\n if (!(key in obj1)) {\r\n diff[key] = obj2[key];\r\n hasChanges = true;\r\n } else if (!(key in obj2)) {\r\n diff[key] = \"@d@\"; // Mark for deletion\r\n hasChanges = true;\r\n } else {\r\n const nestedDiff = this._generateJSONDiff(obj1[key], obj2[key]);\r\n if (nestedDiff !== undefined) {\r\n diff[key] = nestedDiff;\r\n hasChanges = true;\r\n }\r\n }\r\n }\r\n\r\n return hasChanges ? diff : undefined;\r\n }\r\n\r\n private _applyJSONDiff(obj1: any, diff: any) {\r\n if (diff === undefined) {\r\n return obj1;\r\n }\r\n if (typeof diff !== \"object\" || diff === null || obj1 == null) {\r\n return diff;\r\n }\r\n\r\n const result: any = Array.isArray(obj1) ? [] : {};\r\n\r\n if (Array.isArray(diff)) {\r\n for (let i = 0; i < Math.max(obj1.length, diff.length); i++) {\r\n if (diff[i] === null && i < obj1.length) {\r\n result[i] = obj1[i];\r\n } else if (diff[i] !== \"@d@\") {\r\n result[i] = this._applyJSONDiff(obj1[i], diff[i]);\r\n }\r\n }\r\n } else {\r\n for (const key in obj1) {\r\n if (!(key in diff)) {\r\n result[key] = obj1[key];\r\n }\r\n }\r\n for (const key in diff) {\r\n if (diff[key] === \"@d@\") {\r\n // Skip this key (it's been deleted)\r\n } else if (typeof diff[key] === \"object\" && diff[key] !== null) {\r\n result[key] = this._applyJSONDiff(obj1[key], diff[key]);\r\n } else {\r\n result[key] = diff[key];\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private _copy(source: any) {\r\n return JSON.parse(JSON.stringify(source));\r\n }\r\n\r\n /**\r\n * Stores the current state\r\n */\r\n public async storeAsync() {\r\n if (this._locked || !this.isEnabled) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n try {\r\n // _dataProvider can return T or Promise<T>; await handles both.\r\n const provided = await this._dataProvider();\r\n const data = this._copy(provided);\r\n\r\n if (this._activeData) {\r\n const diff = this._generateJSONDiff(data, this._activeData);\r\n if (!diff) {\r\n return; // finally will still run and release the lock\r\n }\r\n this._historyStack.push(JSON.stringify(diff));\r\n }\r\n\r\n this._activeData = data;\r\n\r\n if (this._historyStack.length > this._maxHistoryLength) {\r\n this._historyStack.shift();\r\n }\r\n\r\n this._redoStack.length = 0;\r\n } finally {\r\n this._locked = false;\r\n }\r\n }\r\n\r\n /**\r\n * Checks if there is any data in the history stack\r\n */\r\n public get hasData(): boolean {\r\n return this._historyStack.length > 0;\r\n }\r\n\r\n /**\r\n * Undo the latest operation\r\n */\r\n public undo() {\r\n if (!this._historyStack.length) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n const diff = this._historyStack.pop()!;\r\n\r\n const newState = this._applyJSONDiff(this._activeData, JSON.parse(diff));\r\n this._redoStack.push(JSON.stringify(this._generateJSONDiff(newState, this._activeData)));\r\n\r\n this._applyUpdate(this._copy(newState));\r\n\r\n this._activeData = newState;\r\n\r\n this._locked = false;\r\n }\r\n\r\n /**\r\n * Redo the latest undo operation\r\n */\r\n public redo() {\r\n if (!this._redoStack.length) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n const diff = this._redoStack.pop()!;\r\n\r\n const newState = this._applyJSONDiff(this._activeData, JSON.parse(diff));\r\n this._historyStack.push(JSON.stringify(this._generateJSONDiff(newState, this._activeData)));\r\n\r\n this._applyUpdate(this._copy(newState));\r\n this._activeData = newState;\r\n\r\n this._locked = false;\r\n }\r\n\r\n /**\r\n * Disposes the stack\r\n */\r\n public dispose() {\r\n this._historyStack = [];\r\n this._redoStack = [];\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"historyStack.js","sourceRoot":"","sources":["../../../dev/sharedUiComponents/src/historyStack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IDisposable } from \"core/scene\";\r\n\r\n/**\r\n * Class handling undo / redo operations\r\n */\r\nexport class HistoryStack implements IDisposable {\r\n private _historyStack: string[] = [];\r\n private _redoStack: string[] = [];\r\n private _activeData: any;\r\n private readonly _maxHistoryLength = 256;\r\n private _locked = false;\r\n private _dataProvider: () => any;\r\n private _applyUpdate: (data: any) => void;\r\n\r\n /**\r\n * Gets or sets a boolean indicating if the stack is enabled\r\n */\r\n public isEnabled = true;\r\n\r\n /**\r\n * Constructor\r\n * @param dataProvider defines the data provider function\r\n * @param applyUpdate defines the code to execute when undo/redo operation is required\r\n */\r\n constructor(dataProvider: () => any, applyUpdate: (data: any) => void) {\r\n this._dataProvider = dataProvider;\r\n this._applyUpdate = applyUpdate;\r\n }\r\n\r\n /**\r\n * Process key event to handle undo / redo\r\n * @param evt defines the keyboard event to process\r\n * @returns true if the event was processed\r\n */\r\n processKeyEvent(evt: KeyboardEvent): boolean {\r\n if (!this.isEnabled) {\r\n return false;\r\n }\r\n\r\n if (evt.ctrlKey || evt.metaKey) {\r\n if (evt.key === \"z\" || evt.key === \"Z\") {\r\n if (evt.shiftKey) {\r\n this.redo();\r\n return true;\r\n }\r\n\r\n this.undo();\r\n return true;\r\n }\r\n if (evt.key === \"y\" || evt.key === \"Y\") {\r\n this.redo();\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Resets the stack\r\n */\r\n public reset() {\r\n this._historyStack = [];\r\n this._redoStack = [];\r\n this._activeData = null;\r\n void this.storeAsync();\r\n }\r\n\r\n /**\r\n * Remove the n-1 element of the stack\r\n */\r\n public collapseLastTwo() {\r\n if (this._historyStack.length < 2) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n const diff = this._historyStack.pop()!;\r\n const diff2 = this._historyStack.pop()!;\r\n\r\n let newState = this._applyJSONDiff(this._activeData, JSON.parse(diff));\r\n newState = this._applyJSONDiff(newState, JSON.parse(diff2));\r\n\r\n this._historyStack.push(JSON.stringify(this._generateJSONDiff(this._activeData, newState)));\r\n\r\n this._locked = false;\r\n }\r\n\r\n private _generateJSONDiff(obj1: any, obj2: any): any {\r\n if (obj1 === obj2) {\r\n return undefined;\r\n }\r\n if (obj1 === null || obj2 === null || typeof obj1 !== \"object\" || typeof obj2 !== \"object\") {\r\n if (obj1 !== obj2 && obj2 === undefined) {\r\n return \"@d@\";\r\n }\r\n return obj2;\r\n }\r\n\r\n if (Array.isArray(obj1) && Array.isArray(obj2)) {\r\n const diff = [];\r\n const maxLength = Math.max(obj1.length, obj2.length);\r\n let hasChanges = false;\r\n\r\n for (let i = 0; i < maxLength; i++) {\r\n const localDiff = this._generateJSONDiff(obj1[i], obj2[i]);\r\n if (localDiff !== undefined) {\r\n diff[i] = localDiff;\r\n hasChanges = true;\r\n }\r\n }\r\n\r\n return hasChanges ? diff : undefined;\r\n }\r\n\r\n const diff: any = {};\r\n const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);\r\n let hasChanges = false;\r\n\r\n for (const key of keys) {\r\n if (!(key in obj1)) {\r\n diff[key] = obj2[key];\r\n hasChanges = true;\r\n } else if (!(key in obj2)) {\r\n diff[key] = \"@d@\"; // Mark for deletion\r\n hasChanges = true;\r\n } else {\r\n const nestedDiff = this._generateJSONDiff(obj1[key], obj2[key]);\r\n if (nestedDiff !== undefined) {\r\n diff[key] = nestedDiff;\r\n hasChanges = true;\r\n }\r\n }\r\n }\r\n\r\n return hasChanges ? diff : undefined;\r\n }\r\n\r\n private _applyJSONDiff(obj1: any, diff: any) {\r\n if (diff === undefined) {\r\n return obj1;\r\n }\r\n if (typeof diff !== \"object\" || diff === null || obj1 == null) {\r\n return diff;\r\n }\r\n\r\n const result: any = Array.isArray(obj1) ? [] : {};\r\n\r\n if (Array.isArray(diff)) {\r\n for (let i = 0; i < Math.max(obj1.length, diff.length); i++) {\r\n if (diff[i] === null && i < obj1.length) {\r\n result[i] = obj1[i];\r\n } else if (diff[i] !== \"@d@\") {\r\n result[i] = this._applyJSONDiff(obj1[i], diff[i]);\r\n }\r\n }\r\n } else {\r\n for (const key in obj1) {\r\n if (!(key in diff)) {\r\n result[key] = obj1[key];\r\n }\r\n }\r\n for (const key in diff) {\r\n if (diff[key] === \"@d@\") {\r\n // Skip this key (it's been deleted)\r\n } else if (typeof diff[key] === \"object\" && diff[key] !== null) {\r\n result[key] = this._applyJSONDiff(obj1[key], diff[key]);\r\n } else {\r\n result[key] = diff[key];\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n private _copy(source: any) {\r\n return JSON.parse(JSON.stringify(source));\r\n }\r\n\r\n /**\r\n * Stores the current state\r\n */\r\n public async storeAsync() {\r\n if (this._locked || !this.isEnabled) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n try {\r\n // _dataProvider can return T or Promise<T>; await handles both.\r\n const provided = await this._dataProvider();\r\n if (provided == null) {\r\n return;\r\n }\r\n const data = this._copy(provided);\r\n\r\n if (this._activeData) {\r\n const diff = this._generateJSONDiff(data, this._activeData);\r\n if (!diff) {\r\n return; // finally will still run and release the lock\r\n }\r\n this._historyStack.push(JSON.stringify(diff));\r\n }\r\n\r\n this._activeData = data;\r\n\r\n if (this._historyStack.length > this._maxHistoryLength) {\r\n this._historyStack.shift();\r\n }\r\n\r\n this._redoStack.length = 0;\r\n } finally {\r\n this._locked = false;\r\n }\r\n }\r\n\r\n /**\r\n * Checks if there is any data in the history stack\r\n */\r\n public get hasData(): boolean {\r\n return this._historyStack.length > 0;\r\n }\r\n\r\n /**\r\n * Undo the latest operation\r\n */\r\n public undo() {\r\n if (!this._historyStack.length) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n const diff = this._historyStack.pop()!;\r\n\r\n const newState = this._applyJSONDiff(this._activeData, JSON.parse(diff));\r\n this._redoStack.push(JSON.stringify(this._generateJSONDiff(newState, this._activeData)));\r\n\r\n this._applyUpdate(this._copy(newState));\r\n\r\n this._activeData = newState;\r\n\r\n this._locked = false;\r\n }\r\n\r\n /**\r\n * Redo the latest undo operation\r\n */\r\n public redo() {\r\n if (!this._redoStack.length) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n const diff = this._redoStack.pop()!;\r\n\r\n const newState = this._applyJSONDiff(this._activeData, JSON.parse(diff));\r\n this._historyStack.push(JSON.stringify(this._generateJSONDiff(newState, this._activeData)));\r\n\r\n this._applyUpdate(this._copy(newState));\r\n this._activeData = newState;\r\n\r\n this._locked = false;\r\n }\r\n\r\n /**\r\n * Disposes the stack\r\n */\r\n public dispose() {\r\n this._historyStack = [];\r\n this._redoStack = [];\r\n }\r\n}\r\n"]}
@@ -29,6 +29,9 @@
29
29
 
30
30
  .port-label {
31
31
  align-items: center;
32
+ white-space: nowrap;
33
+ overflow: hidden;
34
+ text-overflow: ellipsis;
32
35
  }
33
36
 
34
37
  .inputsContainer {
@@ -4,6 +4,7 @@ import type { Nullable } from "@onerjs/core/types.js";
4
4
  import { NodeLink } from "./nodeLink.js";
5
5
  import { NodePort } from "./nodePort.js";
6
6
  import { GraphFrame } from "./graphFrame.js";
7
+ import { GraphStickyNote } from "./graphStickyNote.js";
7
8
  import type { IEditorData, IFrameData } from "./interfaces/nodeLocationInfo.js";
8
9
  import type { StateManager } from "./stateManager.js";
9
10
  import type { INodeData } from "./interfaces/nodeData.js";
@@ -12,6 +13,16 @@ import type { INodeContainer } from "./interfaces/nodeContainer.js";
12
13
  export interface IGraphCanvasComponentProps {
13
14
  stateManager: StateManager;
14
15
  onEmitNewNode: (nodeData: INodeData) => GraphNode;
16
+ /** When true, a minimap overlay is shown during zoom/pan. Default false. */
17
+ enableMinimap?: boolean;
18
+ /** When true, sticky note annotations can be created and managed on the canvas. Default false. */
19
+ enableStickyNotes?: boolean;
20
+ /** When true, Ctrl+F opens a find-in-graph search bar. Default false. */
21
+ enableFindInGraph?: boolean;
22
+ /** When true, ports glow red during drag when hovering over an incompatible target. Default false. */
23
+ enablePortCompatibilityHighlight?: boolean;
24
+ /** When true, nodes can display validation and breakpoint badge overlays. Default false. */
25
+ enableNodeBadges?: boolean;
15
26
  }
16
27
  export declare class GraphCanvasComponent extends React.Component<IGraphCanvasComponentProps> implements INodeContainer {
17
28
  static readonly NodeWidth = 100;
@@ -53,17 +64,23 @@ export declare class GraphCanvasComponent extends React.Component<IGraphCanvasCo
53
64
  private _selectedFrames;
54
65
  private _frameCandidate;
55
66
  private _frames;
67
+ private _stickyNotes;
68
+ private _selectedStickyNotes;
56
69
  private _nodeDataContentList;
57
70
  private _altKeyIsPressed;
58
71
  private _shiftKeyIsPressed;
59
72
  private _multiKeyIsPressed;
60
73
  private _oldY;
74
+ private _keyUpHandler;
75
+ private _keyDownHandler;
76
+ private _blurHandler;
61
77
  _frameIsMoving: boolean;
62
78
  _isLoading: boolean;
63
79
  _targetLinkCandidate: Nullable<NodeLink>;
64
80
  private _isCopyingOrPasting;
65
81
  private _copiedNodes;
66
82
  private _copiedFrames;
83
+ private _searchRef;
67
84
  get gridSize(): number;
68
85
  set gridSize(value: number);
69
86
  get stateManager(): StateManager;
@@ -79,6 +96,8 @@ export declare class GraphCanvasComponent extends React.Component<IGraphCanvasCo
79
96
  get selectedNodes(): GraphNode[];
80
97
  get selectedLink(): Nullable<NodeLink>;
81
98
  get selectedFrames(): GraphFrame[];
99
+ get stickyNotes(): GraphStickyNote[];
100
+ get selectedStickyNotes(): GraphStickyNote[];
82
101
  get selectedPort(): Nullable<NodePort>;
83
102
  get canvasContainer(): HTMLDivElement;
84
103
  get hostCanvas(): HTMLDivElement;
@@ -86,6 +105,7 @@ export declare class GraphCanvasComponent extends React.Component<IGraphCanvasCo
86
105
  get selectionContainer(): HTMLDivElement;
87
106
  get frameContainer(): HTMLDivElement;
88
107
  private _selectedFrameAndNodesConflict;
108
+ private _deselectAllStickyNotes;
89
109
  constructor(props: IGraphCanvasComponentProps);
90
110
  populateConnectedEntriesBeforeRemoval(item: GraphNode, items: GraphNode[], inputs: Nullable<IPortData>[], outputs: Nullable<IPortData>[]): void;
91
111
  automaticRewire(inputs: Nullable<IPortData>[], outputs: Nullable<IPortData>[], firstOnly?: boolean): void;
@@ -109,16 +129,33 @@ export declare class GraphCanvasComponent extends React.Component<IGraphCanvasCo
109
129
  appendNode(nodeData: INodeData): GraphNode;
110
130
  distributeGraph(): void;
111
131
  componentDidMount(): void;
132
+ componentWillUnmount(): void;
112
133
  onMove(evt: React.PointerEvent): void;
113
134
  onDown(evt: React.PointerEvent<HTMLElement>): void;
114
135
  onUp(evt: React.PointerEvent): void;
115
136
  onWheel(evt: React.WheelEvent): void;
116
137
  zoomToFit(): void;
138
+ /**
139
+ * Pans the canvas so the given node is visible and roughly centered.
140
+ * @param node - the node to bring into view
141
+ */
142
+ zoomToNode(node: GraphNode): void;
117
143
  processCandidatePort(): void;
118
144
  connectNodes(nodeA: GraphNode, pointA: IPortData, nodeB: GraphNode, pointB: IPortData): void;
119
145
  drop(newNode: GraphNode, targetX: number, targetY: number, offsetX: number, offsetY: number): void;
120
146
  processEditorData(editorData: IEditorData): void;
121
147
  reOrganize(editorData?: Nullable<IEditorData>, isImportingAFrame?: boolean): void;
122
148
  addFrame(frameData: IFrameData): void;
149
+ /**
150
+ * Create a new sticky note at the given canvas-space position.
151
+ * @param x - x position in canvas space
152
+ * @param y - y position in canvas space
153
+ * @returns the created sticky note
154
+ */
155
+ addStickyNote(x: number, y: number): GraphStickyNote | null;
156
+ /**
157
+ * Open the find-in-graph search bar, if enabled.
158
+ */
159
+ showSearch(): void;
123
160
  render(): import("react/jsx-runtime").JSX.Element;
124
161
  }
@@ -7,6 +7,7 @@ import { NodePort } from "./nodePort.js";
7
7
  import { Vector2 } from "@onerjs/core/Maths/math.vector.js";
8
8
  import { DataStorage } from "@onerjs/core/Misc/dataStorage.js";
9
9
  import { GraphFrame } from "./graphFrame.js";
10
+ import { GraphStickyNote } from "./graphStickyNote.js";
10
11
  import { FrameNodePort } from "./frameNodePort.js";
11
12
  import { PortDataDirection } from "./interfaces/portData.js";
12
13
  import * as styles from "./graphCanvas.module.scss";
@@ -14,6 +15,8 @@ import * as commonStyles from "./common.module.scss";
14
15
  import { TypeLedger } from "./typeLedger.js";
15
16
  import { RefreshNode } from "./tools.js";
16
17
  import { SearchBoxComponent } from "./searchBox.js";
18
+ import { GraphMinimapComponent } from "./graphMinimap.js";
19
+ import { GraphSearchComponent } from "./graphSearch.js";
17
20
  export class GraphCanvasComponent extends React.Component {
18
21
  get gridSize() {
19
22
  return this._gridSize;
@@ -67,6 +70,12 @@ export class GraphCanvasComponent extends React.Component {
67
70
  get selectedFrames() {
68
71
  return this._selectedFrames;
69
72
  }
73
+ get stickyNotes() {
74
+ return this._stickyNotes;
75
+ }
76
+ get selectedStickyNotes() {
77
+ return this._selectedStickyNotes;
78
+ }
70
79
  get selectedPort() {
71
80
  return this._selectedPort;
72
81
  }
@@ -96,6 +105,12 @@ export class GraphCanvasComponent extends React.Component {
96
105
  }
97
106
  return false;
98
107
  }
108
+ _deselectAllStickyNotes() {
109
+ for (const note of this._selectedStickyNotes) {
110
+ note.setIsSelected(false);
111
+ }
112
+ this._selectedStickyNotes = [];
113
+ }
99
114
  constructor(props) {
100
115
  super(props);
101
116
  this._minZoom = 0.1;
@@ -130,17 +145,25 @@ export class GraphCanvasComponent extends React.Component {
130
145
  this._selectedFrames = [];
131
146
  this._frameCandidate = null;
132
147
  this._frames = [];
148
+ this._stickyNotes = [];
149
+ this._selectedStickyNotes = [];
133
150
  this._nodeDataContentList = new Array();
134
151
  this._altKeyIsPressed = false;
135
152
  this._shiftKeyIsPressed = false;
136
153
  this._multiKeyIsPressed = false;
137
154
  this._oldY = -1;
155
+ this._keyUpHandler = null;
156
+ this._keyDownHandler = null;
157
+ this._blurHandler = null;
138
158
  this._frameIsMoving = false;
139
159
  this._isLoading = false;
140
160
  this._targetLinkCandidate = null;
141
161
  this._isCopyingOrPasting = false;
142
162
  this._copiedNodes = [];
143
163
  this._copiedFrames = [];
164
+ this._searchRef = React.createRef();
165
+ props.stateManager.enablePortCompatibilityHighlight = !!props.enablePortCompatibilityHighlight;
166
+ props.stateManager.enableNodeBadges = !!props.enableNodeBadges;
144
167
  props.stateManager.onSelectionChangedObservable.add((options) => {
145
168
  const { selection, forceKeepSelection, marqueeSelection = false } = options || {};
146
169
  if (!selection) {
@@ -148,6 +171,10 @@ export class GraphCanvasComponent extends React.Component {
148
171
  this._selectedLink = null;
149
172
  this._selectedFrames = [];
150
173
  this._selectedPort = null;
174
+ for (const note of this._selectedStickyNotes) {
175
+ note.setIsSelected(false);
176
+ }
177
+ this._selectedStickyNotes = [];
151
178
  }
152
179
  else {
153
180
  if (selection instanceof NodeLink) {
@@ -155,18 +182,36 @@ export class GraphCanvasComponent extends React.Component {
155
182
  this._selectedFrames = [];
156
183
  this._selectedLink = selection;
157
184
  this._selectedPort = null;
185
+ this._deselectAllStickyNotes();
158
186
  }
159
187
  else if (selection instanceof NodePort) {
160
188
  this._selectedNodes = [];
161
189
  this._selectedFrames = [];
162
190
  this._selectedLink = null;
163
191
  this._selectedPort = selection;
192
+ this._deselectAllStickyNotes();
164
193
  }
165
194
  else if (selection instanceof FrameNodePort) {
166
195
  this._selectedNodes = [];
167
196
  this._selectedFrames = [];
168
197
  this._selectedLink = null;
169
198
  this._selectedPort = selection;
199
+ this._deselectAllStickyNotes();
200
+ }
201
+ else if (this.props.enableStickyNotes && selection instanceof GraphStickyNote) {
202
+ if (this._multiKeyIsPressed || this._shiftKeyIsPressed || forceKeepSelection) {
203
+ if (!this._selectedStickyNotes.includes(selection)) {
204
+ this._selectedStickyNotes.push(selection);
205
+ }
206
+ }
207
+ else {
208
+ this._selectedNodes = [];
209
+ this._selectedFrames = [];
210
+ this._selectedStickyNotes = [selection];
211
+ this._selectedLink = null;
212
+ this._selectedPort = null;
213
+ }
214
+ selection.setIsSelected(true);
170
215
  }
171
216
  else if (selection instanceof GraphNode || selection instanceof GraphFrame) {
172
217
  // If in marquee selection mode, always prioritize selecting nodes. Otherwise, always prioritize selecting the type of
@@ -202,6 +247,7 @@ export class GraphCanvasComponent extends React.Component {
202
247
  this._selectedNodes = [];
203
248
  this._selectedLink = null;
204
249
  this._selectedPort = null;
250
+ this._deselectAllStickyNotes();
205
251
  }
206
252
  }
207
253
  else if (selection instanceof GraphNode) {
@@ -215,6 +261,7 @@ export class GraphCanvasComponent extends React.Component {
215
261
  this._selectedNodes = [selection];
216
262
  this._selectedLink = null;
217
263
  this._selectedPort = null;
264
+ this._deselectAllStickyNotes();
218
265
  }
219
266
  }
220
267
  }
@@ -227,17 +274,20 @@ export class GraphCanvasComponent extends React.Component {
227
274
  props.stateManager.onGridSizeChanged.add(() => {
228
275
  this.gridSize = DataStorage.ReadNumber("GridSize", 20);
229
276
  });
230
- this.props.stateManager.hostDocument.addEventListener("keyup", () => this.onKeyUp(), false);
231
- this.props.stateManager.hostDocument.addEventListener("keydown", (evt) => {
277
+ this._keyUpHandler = () => this.onKeyUp();
278
+ this._keyDownHandler = (evt) => {
232
279
  this._altKeyIsPressed = evt.altKey;
233
280
  this._shiftKeyIsPressed = evt.shiftKey;
234
281
  this._multiKeyIsPressed = evt.ctrlKey || evt.metaKey;
235
- }, false);
236
- this.props.stateManager.hostDocument.defaultView.addEventListener("blur", () => {
282
+ };
283
+ this._blurHandler = () => {
237
284
  this._altKeyIsPressed = false;
238
285
  this._shiftKeyIsPressed = false;
239
286
  this._multiKeyIsPressed = false;
240
- }, false);
287
+ };
288
+ this.props.stateManager.hostDocument.addEventListener("keyup", this._keyUpHandler, false);
289
+ this.props.stateManager.hostDocument.addEventListener("keydown", this._keyDownHandler, false);
290
+ this.props.stateManager.hostDocument.defaultView.addEventListener("blur", this._blurHandler, false);
241
291
  // Store additional data to serialization object
242
292
  this.props.stateManager.storeEditorData = (editorData, graphFrame) => {
243
293
  editorData.frames = [];
@@ -251,6 +301,12 @@ export class GraphCanvasComponent extends React.Component {
251
301
  for (const frame of this._frames) {
252
302
  editorData.frames.push(frame.serialize(true));
253
303
  }
304
+ if (this.props.enableStickyNotes) {
305
+ editorData.stickyNotes = [];
306
+ for (const note of this._stickyNotes) {
307
+ editorData.stickyNotes.push(note.serialize());
308
+ }
309
+ }
254
310
  }
255
311
  };
256
312
  }
@@ -360,6 +416,13 @@ export class GraphCanvasComponent extends React.Component {
360
416
  frame.dispose();
361
417
  }
362
418
  }
419
+ if (this.props.enableStickyNotes && this._selectedStickyNotes.length) {
420
+ needRebuild = true;
421
+ for (const note of this._selectedStickyNotes) {
422
+ note.dispose();
423
+ }
424
+ this._selectedStickyNotes = [];
425
+ }
363
426
  if (!needRebuild) {
364
427
  return;
365
428
  }
@@ -627,8 +690,14 @@ export class GraphCanvasComponent extends React.Component {
627
690
  for (const frame of frames) {
628
691
  frame.dispose();
629
692
  }
693
+ const notes = this._stickyNotes.splice(0);
694
+ for (const note of notes) {
695
+ note.element.parentElement?.removeChild(note.element);
696
+ }
630
697
  this._nodes = [];
631
698
  this._frames = [];
699
+ this._stickyNotes = [];
700
+ this._selectedStickyNotes = [];
632
701
  this._links = [];
633
702
  this._graphCanvas.innerHTML = "";
634
703
  this._svgCanvas.innerHTML = "";
@@ -749,6 +818,18 @@ export class GraphCanvasComponent extends React.Component {
749
818
  this.gridSize = DataStorage.ReadNumber("GridSize", 20);
750
819
  this.updateTransform();
751
820
  }
821
+ componentWillUnmount() {
822
+ const doc = this.props.stateManager.hostDocument;
823
+ if (this._keyUpHandler) {
824
+ doc.removeEventListener("keyup", this._keyUpHandler);
825
+ }
826
+ if (this._keyDownHandler) {
827
+ doc.removeEventListener("keydown", this._keyDownHandler);
828
+ }
829
+ if (this._blurHandler) {
830
+ doc.defaultView?.removeEventListener("blur", this._blurHandler);
831
+ }
832
+ }
752
833
  onMove(evt) {
753
834
  if (this.stateManager.modalIsDisplayed) {
754
835
  return;
@@ -876,6 +957,9 @@ export class GraphCanvasComponent extends React.Component {
876
957
  this._candidateLink = new NodeLink(this, portElement, portElement.node);
877
958
  }
878
959
  this._candidateLinkedHasMoved = false;
960
+ if (this.stateManager.enablePortCompatibilityHighlight) {
961
+ this.stateManager.candidateSourcePortData = this._candidateLink.portA.portData;
962
+ }
879
963
  }
880
964
  return;
881
965
  }
@@ -947,6 +1031,7 @@ export class GraphCanvasComponent extends React.Component {
947
1031
  this._candidateLink.dispose();
948
1032
  this._candidateLink = null;
949
1033
  this._candidatePort = null;
1034
+ this.stateManager.candidateSourcePortData = null;
950
1035
  }
951
1036
  if (this._selectionBox) {
952
1037
  this._selectionBox.parentElement.removeChild(this._selectionBox);
@@ -1021,6 +1106,16 @@ export class GraphCanvasComponent extends React.Component {
1021
1106
  this.x = 0;
1022
1107
  this.y = 0;
1023
1108
  }
1109
+ /**
1110
+ * Pans the canvas so the given node is visible and roughly centered.
1111
+ * @param node - the node to bring into view
1112
+ */
1113
+ zoomToNode(node) {
1114
+ const containerWidth = this._rootContainer.clientWidth;
1115
+ const containerHeight = this._rootContainer.clientHeight;
1116
+ this.x = -node.x + containerWidth / (2 * this.zoom) - 100;
1117
+ this.y = -node.y + containerHeight / (2 * this.zoom) - 20;
1118
+ }
1024
1119
  processCandidatePort() {
1025
1120
  let pointB = this._candidateLink.portA.portData;
1026
1121
  let nodeB = this._candidateLink.portA.node;
@@ -1182,7 +1277,13 @@ export class GraphCanvasComponent extends React.Component {
1182
1277
  for (const frame of frames) {
1183
1278
  frame.dispose();
1184
1279
  }
1280
+ const notes = this._stickyNotes.splice(0);
1281
+ for (const note of notes) {
1282
+ note.element.parentElement?.removeChild(note.element);
1283
+ }
1185
1284
  this._frames = [];
1285
+ this._stickyNotes = [];
1286
+ this._selectedStickyNotes = [];
1186
1287
  this.x = editorData.x || 0;
1187
1288
  this.y = editorData.y || 0;
1188
1289
  this.zoom = editorData.zoom || 1;
@@ -1193,6 +1294,13 @@ export class GraphCanvasComponent extends React.Component {
1193
1294
  this._frames.push(frame);
1194
1295
  }
1195
1296
  }
1297
+ // Sticky notes
1298
+ if (this.props.enableStickyNotes && editorData.stickyNotes) {
1299
+ for (const noteData of editorData.stickyNotes) {
1300
+ const note = GraphStickyNote.Parse(noteData, this);
1301
+ this._stickyNotes.push(note);
1302
+ }
1303
+ }
1196
1304
  }
1197
1305
  reOrganize(editorData = null, isImportingAFrame = false) {
1198
1306
  if (!editorData || !editorData.locations) {
@@ -1228,8 +1336,33 @@ export class GraphCanvasComponent extends React.Component {
1228
1336
  this._frames.push(frame);
1229
1337
  this.stateManager.onSelectionChangedObservable.notifyObservers({ selection: frame });
1230
1338
  }
1339
+ /**
1340
+ * Create a new sticky note at the given canvas-space position.
1341
+ * @param x - x position in canvas space
1342
+ * @param y - y position in canvas space
1343
+ * @returns the created sticky note
1344
+ */
1345
+ addStickyNote(x, y) {
1346
+ if (!this.props.enableStickyNotes) {
1347
+ return null;
1348
+ }
1349
+ const note = new GraphStickyNote(this);
1350
+ note.x = x;
1351
+ note.y = y;
1352
+ this._stickyNotes.push(note);
1353
+ this.stateManager.onSelectionChangedObservable.notifyObservers({ selection: note });
1354
+ return note;
1355
+ }
1356
+ /**
1357
+ * Open the find-in-graph search bar, if enabled.
1358
+ */
1359
+ showSearch() {
1360
+ if (this.props.enableFindInGraph) {
1361
+ this._searchRef.current?.show();
1362
+ }
1363
+ }
1231
1364
  render() {
1232
- return (_jsxs("div", { ref: this._hostCanvasRef, id: "graph-canvas", className: styles["graph-canvas"], onWheel: (evt) => this.onWheel(evt), onPointerMove: (evt) => this.onMove(evt), onPointerDown: (evt) => this.onDown(evt), onPointerUp: (evt) => this.onUp(evt), children: [_jsxs("div", { id: "graph-container", className: styles["graph-container"], ref: this._rootContainerRef, children: [_jsx("div", { id: "graph-canvas-container", className: styles["graph-canvas-container"], ref: this._graphCanvasRef }), _jsx("div", { id: "frame-container", className: styles["frame-container"], ref: this._frameContainerRef }), _jsx("svg", { id: "graph-svg-container", className: styles["graph-svg-container"], ref: this._svgCanvasRef }), _jsx("div", { id: "selection-container", className: styles["selection-container"], ref: this._selectionContainerRef })] }), _jsx(SearchBoxComponent, { stateManager: this.stateManager })] }));
1365
+ return (_jsxs("div", { ref: this._hostCanvasRef, id: "graph-canvas", className: styles["graph-canvas"], onWheel: (evt) => this.onWheel(evt), onPointerMove: (evt) => this.onMove(evt), onPointerDown: (evt) => this.onDown(evt), onPointerUp: (evt) => this.onUp(evt), children: [_jsxs("div", { id: "graph-container", className: styles["graph-container"], ref: this._rootContainerRef, children: [_jsx("div", { id: "graph-canvas-container", className: styles["graph-canvas-container"], ref: this._graphCanvasRef }), _jsx("div", { id: "frame-container", className: styles["frame-container"], ref: this._frameContainerRef }), _jsx("svg", { id: "graph-svg-container", className: styles["graph-svg-container"], ref: this._svgCanvasRef }), _jsx("div", { id: "selection-container", className: styles["selection-container"], ref: this._selectionContainerRef })] }), _jsx(SearchBoxComponent, { stateManager: this.stateManager }), this.props.enableMinimap && _jsx(GraphMinimapComponent, { canvas: this }), this.props.enableFindInGraph && _jsx(GraphSearchComponent, { ref: this._searchRef, canvas: this })] }));
1233
1366
  }
1234
1367
  }
1235
1368
  GraphCanvasComponent.NodeWidth = 100;