@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.
- package/components/bars/CommandButton.module.scss +2 -0
- package/historyStack.js +3 -0
- package/historyStack.js.map +1 -1
- package/nodeGraphSystem/common.module.scss +3 -0
- package/nodeGraphSystem/graphCanvas.d.ts +37 -0
- package/nodeGraphSystem/graphCanvas.js +139 -6
- package/nodeGraphSystem/graphCanvas.js.map +1 -1
- package/nodeGraphSystem/graphMinimap.d.ts +79 -0
- package/nodeGraphSystem/graphMinimap.js +319 -0
- package/nodeGraphSystem/graphMinimap.js.map +1 -0
- package/nodeGraphSystem/graphMinimap.module.scss +30 -0
- package/nodeGraphSystem/graphNode.d.ts +16 -0
- package/nodeGraphSystem/graphNode.js +76 -1
- package/nodeGraphSystem/graphNode.js.map +1 -1
- package/nodeGraphSystem/graphNode.module.scss +61 -0
- package/nodeGraphSystem/graphSearch.d.ts +54 -0
- package/nodeGraphSystem/graphSearch.js +181 -0
- package/nodeGraphSystem/graphSearch.js.map +1 -0
- package/nodeGraphSystem/graphSearch.module.scss +86 -0
- package/nodeGraphSystem/graphStickyNote.d.ts +94 -0
- package/nodeGraphSystem/graphStickyNote.js +310 -0
- package/nodeGraphSystem/graphStickyNote.js.map +1 -0
- package/nodeGraphSystem/graphStickyNote.module.scss +87 -0
- package/nodeGraphSystem/interfaces/nodeData.d.ts +2 -0
- package/nodeGraphSystem/interfaces/nodeData.js.map +1 -1
- package/nodeGraphSystem/interfaces/nodeLocationInfo.d.ts +10 -0
- package/nodeGraphSystem/interfaces/nodeLocationInfo.js.map +1 -1
- package/nodeGraphSystem/interfaces/portData.d.ts +2 -1
- package/nodeGraphSystem/interfaces/portData.js +1 -0
- package/nodeGraphSystem/interfaces/portData.js.map +1 -1
- package/nodeGraphSystem/interfaces/selectionChangedOptions.d.ts +2 -1
- package/nodeGraphSystem/interfaces/selectionChangedOptions.js.map +1 -1
- package/nodeGraphSystem/nodeLink.d.ts +12 -0
- package/nodeGraphSystem/nodeLink.js +77 -0
- package/nodeGraphSystem/nodeLink.js.map +1 -1
- package/nodeGraphSystem/nodePort.js +26 -1
- package/nodeGraphSystem/nodePort.js.map +1 -1
- package/nodeGraphSystem/nodePort.module.scss +37 -0
- package/nodeGraphSystem/stateManager.d.ts +6 -0
- package/nodeGraphSystem/stateManager.js +6 -0
- package/nodeGraphSystem/stateManager.js.map +1 -1
- package/package.json +1 -1
- package/split/splitContainer.js +2 -1
- package/split/splitContainer.js.map +1 -1
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);
|
package/historyStack.js.map
CHANGED
|
@@ -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"]}
|
|
@@ -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.
|
|
231
|
-
this.
|
|
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
|
-
}
|
|
236
|
-
this.
|
|
282
|
+
};
|
|
283
|
+
this._blurHandler = () => {
|
|
237
284
|
this._altKeyIsPressed = false;
|
|
238
285
|
this._shiftKeyIsPressed = false;
|
|
239
286
|
this._multiKeyIsPressed = false;
|
|
240
|
-
}
|
|
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;
|