@babylonjs/shared-ui-components 7.25.2 → 7.26.1

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/historyStack.d.ts CHANGED
@@ -3,8 +3,9 @@ import type { IDisposable } from "@babylonjs/core/scene.js";
3
3
  * Class handling undo / redo operations
4
4
  */
5
5
  export declare class HistoryStack implements IDisposable {
6
- private _history;
6
+ private _historyStack;
7
7
  private _redoStack;
8
+ private _activeData;
8
9
  private readonly _maxHistoryLength;
9
10
  private _locked;
10
11
  private _dataProvider;
@@ -15,13 +16,19 @@ export declare class HistoryStack implements IDisposable {
15
16
  * @param applyUpdate defines the code to execute when undo/redo operation is required
16
17
  */
17
18
  constructor(dataProvider: () => any, applyUpdate: (data: any) => void);
19
+ /**
20
+ * Process key event to handle undo / redo
21
+ * @param evt defines the keyboard event to process
22
+ * @returns true if the event was processed
23
+ */
24
+ processKeyEvent(evt: KeyboardEvent): boolean;
18
25
  /**
19
26
  * Resets the stack
20
27
  */
21
28
  reset(): void;
22
29
  private _generateJSONDiff;
23
30
  private _applyJSONDiff;
24
- private _rebuildState;
31
+ private _copy;
25
32
  /**
26
33
  * Stores the current state
27
34
  */
package/historyStack.js CHANGED
@@ -8,19 +8,42 @@ export class HistoryStack {
8
8
  * @param applyUpdate defines the code to execute when undo/redo operation is required
9
9
  */
10
10
  constructor(dataProvider, applyUpdate) {
11
- this._history = [];
11
+ this._historyStack = [];
12
12
  this._redoStack = [];
13
- this._maxHistoryLength = 64;
13
+ this._maxHistoryLength = 256;
14
14
  this._locked = false;
15
15
  this._dataProvider = dataProvider;
16
16
  this._applyUpdate = applyUpdate;
17
17
  }
18
+ /**
19
+ * Process key event to handle undo / redo
20
+ * @param evt defines the keyboard event to process
21
+ * @returns true if the event was processed
22
+ */
23
+ processKeyEvent(evt) {
24
+ if (evt.ctrlKey || evt.metaKey) {
25
+ if (evt.key === "z" || evt.key === "Z") {
26
+ if (evt.shiftKey) {
27
+ this.redo();
28
+ return true;
29
+ }
30
+ this.undo();
31
+ return true;
32
+ }
33
+ if (evt.key === "y" || evt.key === "Y") {
34
+ this.redo();
35
+ return true;
36
+ }
37
+ }
38
+ return false;
39
+ }
18
40
  /**
19
41
  * Resets the stack
20
42
  */
21
43
  reset() {
22
- this._history = [];
44
+ this._historyStack = [];
23
45
  this._redoStack = [];
46
+ this._activeData = null;
24
47
  this.store();
25
48
  }
26
49
  _generateJSONDiff(obj1, obj2) {
@@ -105,12 +128,8 @@ export class HistoryStack {
105
128
  }
106
129
  return result;
107
130
  }
108
- _rebuildState() {
109
- let newState = JSON.parse(this._history[0]);
110
- for (let index = 1; index < this._history.length; index++) {
111
- newState = this._applyJSONDiff(newState, JSON.parse(this._history[index]));
112
- }
113
- return newState;
131
+ _copy(source) {
132
+ return JSON.parse(JSON.stringify(source));
114
133
  }
115
134
  /**
116
135
  * Stores the current state
@@ -119,25 +138,17 @@ export class HistoryStack {
119
138
  if (this._locked) {
120
139
  return;
121
140
  }
122
- const data = this._dataProvider();
123
- const dataString = JSON.stringify(data);
124
- if (this._history.length > 0) {
125
- const previousState = this._rebuildState();
126
- if (JSON.stringify(previousState) === dataString) {
141
+ const data = this._copy(this._dataProvider());
142
+ if (this._activeData) {
143
+ const diff = this._generateJSONDiff(data, this._activeData);
144
+ if (!diff) {
127
145
  return;
128
146
  }
129
- const diff = this._generateJSONDiff(previousState, data);
130
- if (diff) {
131
- this._history.push(JSON.stringify(diff));
132
- }
133
- }
134
- else {
135
- this._history.push(dataString);
147
+ this._historyStack.push(JSON.stringify(diff));
136
148
  }
137
- if (this._history.length > this._maxHistoryLength) {
138
- const base = this._history.splice(0, 1)[0];
139
- const diff = this._history[0];
140
- this._history[0] = JSON.stringify(this._applyJSONDiff(JSON.parse(base), JSON.parse(diff)));
149
+ this._activeData = data;
150
+ if (this._historyStack.length > this._maxHistoryLength) {
151
+ this._historyStack.shift();
141
152
  }
142
153
  this._redoStack.length = 0;
143
154
  }
@@ -145,35 +156,37 @@ export class HistoryStack {
145
156
  * Undo the latest operation
146
157
  */
147
158
  undo() {
148
- if (this._history.length < 2) {
159
+ if (!this._historyStack.length) {
149
160
  return;
150
161
  }
151
162
  this._locked = true;
152
- const current = this._history.pop();
153
- this._redoStack.push(current);
154
- const newState = this._rebuildState();
155
- this._applyUpdate(newState);
163
+ const diff = this._historyStack.pop();
164
+ const newState = this._applyJSONDiff(this._activeData, JSON.parse(diff));
165
+ this._redoStack.push(JSON.stringify(this._generateJSONDiff(newState, this._activeData)));
166
+ this._applyUpdate(this._copy(newState));
167
+ this._activeData = newState;
156
168
  this._locked = false;
157
169
  }
158
170
  /**
159
171
  * Redo the latest undo operation
160
172
  */
161
173
  redo() {
162
- if (this._redoStack.length < 1) {
174
+ if (!this._redoStack.length) {
163
175
  return;
164
176
  }
165
177
  this._locked = true;
166
- const current = this._redoStack.pop();
167
- this._history.push(current);
168
- const newState = this._rebuildState();
169
- this._applyUpdate(newState);
178
+ const diff = this._redoStack.pop();
179
+ const newState = this._applyJSONDiff(this._activeData, JSON.parse(diff));
180
+ this._historyStack.push(JSON.stringify(this._generateJSONDiff(newState, this._activeData)));
181
+ this._applyUpdate(this._copy(newState));
182
+ this._activeData = newState;
170
183
  this._locked = false;
171
184
  }
172
185
  /**
173
186
  * Disposes the stack
174
187
  */
175
188
  dispose() {
176
- this._history = [];
189
+ this._historyStack = [];
177
190
  this._redoStack = [];
178
191
  }
179
192
  }
@@ -1 +1 @@
1
- {"version":3,"file":"historyStack.js","sourceRoot":"","sources":["../../../dev/sharedUiComponents/src/historyStack.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,OAAO,YAAY;IAQrB;;;;OAIG;IACH,YAAY,YAAuB,EAAE,WAAgC;QAZ7D,aAAQ,GAAa,EAAE,CAAC;QACxB,eAAU,GAAa,EAAE,CAAC;QACjB,sBAAiB,GAAG,EAAE,CAAC;QAChC,YAAO,GAAG,KAAK,CAAC;QAUpB,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;IACpC,CAAC;IAED;;OAEG;IACI,KAAK;QACR,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAEO,iBAAiB,CAAC,IAAS,EAAE,IAAS;QAC1C,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,SAAS,CAAC;QACpC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;YACxF,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,EAAE;gBACrC,OAAO,KAAK,CAAC;aAChB;YACD,OAAO,IAAI,CAAC;SACf;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAC5C,MAAM,IAAI,GAAG,EAAE,CAAC;YAChB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YACrD,IAAI,UAAU,GAAG,KAAK,CAAC;YAEvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE;gBAChC,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3D,IAAI,SAAS,KAAK,SAAS,EAAE;oBACzB,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;oBACpB,UAAU,GAAG,IAAI,CAAC;iBACrB;aACJ;YAED,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;SACxC;QAED,MAAM,IAAI,GAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnE,IAAI,UAAU,GAAG,KAAK,CAAC;QAEvB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;YACpB,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE;gBAChB,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;gBACtB,UAAU,GAAG,IAAI,CAAC;aACrB;iBAAM,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE;gBACvB,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,oBAAoB;gBACvC,UAAU,GAAG,IAAI,CAAC;aACrB;iBAAM;gBACH,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChE,IAAI,UAAU,KAAK,SAAS,EAAE;oBAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;oBACvB,UAAU,GAAG,IAAI,CAAC;iBACrB;aACJ;SACJ;QAED,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACzC,CAAC;IAEO,cAAc,CAAC,IAAS,EAAE,IAAS;QACvC,IAAI,IAAI,KAAK,SAAS,EAAE;YACpB,OAAO,IAAI,CAAC;SACf;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;YAC3D,OAAO,IAAI,CAAC;SACf;QAED,MAAM,MAAM,GAAQ,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAElD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE;gBACzD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE;oBACrC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;iBACvB;qBAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE;oBAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;iBACrD;aACJ;SACJ;aAAM;YACH,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;gBACpB,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE;oBAChB,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;iBAC3B;aACJ;YACD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;gBACpB,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE;oBACrB,oCAAoC;iBACvC;qBAAM,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;oBAC5D,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;iBAC3D;qBAAM;oBACH,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;iBAC3B;aACJ;SACJ;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,aAAa;QACjB,IAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACvD,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC9E;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED;;OAEG;IACI,KAAK;QACR,IAAI,IAAI,CAAC,OAAO,EAAE;YACd,OAAO;SACV;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAExC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;YAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC3C,IAAI,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,UAAU,EAAE;gBAC9C,OAAO;aACV;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;YACzD,IAAI,IAAI,EAAE;gBACN,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;aAC5C;SACJ;aAAM;YACH,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SAClC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE;YAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAC9F;QAED,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACI,IAAI;QACP,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;YAC1B,OAAO;SACV;QAED,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAG,CAAC;QACrC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE9B,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAEtC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAE5B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,IAAI;QACP,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;YAC5B,OAAO;SACV;QAED,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,EAAG,CAAC;QACvC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE5B,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACtC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAE5B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,OAAO;QACV,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;IACzB,CAAC;CACJ","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 _history: string[] = [];\r\n private _redoStack: string[] = [];\r\n private readonly _maxHistoryLength = 64;\r\n private _locked = false;\r\n private _dataProvider: () => any;\r\n private _applyUpdate: (data: any) => void;\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 * Resets the stack\r\n */\r\n public reset() {\r\n this._history = [];\r\n this._redoStack = [];\r\n this.store();\r\n }\r\n\r\n private _generateJSONDiff(obj1: any, obj2: any): any {\r\n if (obj1 === obj2) return undefined;\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 _rebuildState() {\r\n let newState = JSON.parse(this._history[0]);\r\n for (let index = 1; index < this._history.length; index++) {\r\n newState = this._applyJSONDiff(newState, JSON.parse(this._history[index]));\r\n }\r\n\r\n return newState;\r\n }\r\n\r\n /**\r\n * Stores the current state\r\n */\r\n public store() {\r\n if (this._locked) {\r\n return;\r\n }\r\n\r\n const data = this._dataProvider();\r\n const dataString = JSON.stringify(data);\r\n\r\n if (this._history.length > 0) {\r\n const previousState = this._rebuildState();\r\n if (JSON.stringify(previousState) === dataString) {\r\n return;\r\n }\r\n const diff = this._generateJSONDiff(previousState, data);\r\n if (diff) {\r\n this._history.push(JSON.stringify(diff));\r\n }\r\n } else {\r\n this._history.push(dataString);\r\n }\r\n\r\n if (this._history.length > this._maxHistoryLength) {\r\n const base = this._history.splice(0, 1)[0];\r\n const diff = this._history[0];\r\n this._history[0] = JSON.stringify(this._applyJSONDiff(JSON.parse(base), JSON.parse(diff)));\r\n }\r\n\r\n this._redoStack.length = 0;\r\n }\r\n\r\n /**\r\n * Undo the latest operation\r\n */\r\n public undo() {\r\n if (this._history.length < 2) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n const current = this._history.pop()!;\r\n this._redoStack.push(current);\r\n\r\n const newState = this._rebuildState();\r\n\r\n this._applyUpdate(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 < 1) {\r\n return;\r\n }\r\n\r\n this._locked = true;\r\n const current = this._redoStack.pop()!;\r\n this._history.push(current);\r\n\r\n const newState = this._rebuildState();\r\n this._applyUpdate(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._history = [];\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 * 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 (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 this.store();\r\n }\r\n\r\n private _generateJSONDiff(obj1: any, obj2: any): any {\r\n if (obj1 === obj2) return undefined;\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 store() {\r\n if (this._locked) {\r\n return;\r\n }\r\n\r\n const data = this._copy(this._dataProvider());\r\n\r\n if (this._activeData) {\r\n const diff = this._generateJSONDiff(data, this._activeData);\r\n if (!diff) {\r\n return;\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 }\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 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"]}
@@ -28,6 +28,7 @@ export declare class GraphFrame {
28
28
  private _headerTextElement;
29
29
  private _headerCollapseElement;
30
30
  private _headerCloseElement;
31
+ private _headerFocusElement;
31
32
  private _commentsElement;
32
33
  private _portContainer;
33
34
  private _outputPortContainer;
@@ -57,6 +58,7 @@ export declare class GraphFrame {
57
58
  private readonly _closeSVG;
58
59
  private readonly _expandSVG;
59
60
  private readonly _collapseSVG;
61
+ private readonly _focusSVG;
60
62
  get id(): number;
61
63
  get isCollapsed(): boolean;
62
64
  private _createInputPort;
@@ -85,6 +87,11 @@ export declare class GraphFrame {
85
87
  get comments(): string;
86
88
  set comments(comments: string);
87
89
  constructor(candidate: Nullable<HTMLDivElement>, canvas: GraphCanvasComponent, doNotCaptureNodes?: boolean);
90
+ private _isFocused;
91
+ /**
92
+ * Enter/leave focus mode
93
+ */
94
+ switchFocusMode(): void;
88
95
  refresh(): void;
89
96
  addNode(node: GraphNode): void;
90
97
  removeNode(node: GraphNode): void;
@@ -425,6 +425,8 @@ export class GraphFrame {
425
425
  this._closeSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><g id="Layer_2" data-name="Layer 2"><path d="M16,15l5.85,5.84-1,1L15,15.93,9.15,21.78l-1-1L14,15,8.19,9.12l1-1L15,14l5.84-5.84,1,1Z"/></g></svg>`;
426
426
  this._expandSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><g id="Layer_2" data-name="Layer 2"><path d="M22.31,7.69V22.31H7.69V7.69ZM21.19,8.81H8.81V21.19H21.19Zm-6.75,6.75H11.06V14.44h3.38V11.06h1.12v3.38h3.38v1.12H15.56v3.38H14.44Z"/></g></svg>`;
427
427
  this._collapseSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30"><g id="Layer_2" data-name="Layer 2"><path d="M22.31,7.69V22.31H7.69V7.69ZM21.19,8.81H8.81V21.19H21.19Zm-2.25,6.75H11.06V14.44h7.88Z"/></g></svg>`;
428
+ this._focusSVG = `<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.24992 4.5C5.28344 4.5 4.49996 5.2835 4.49996 6.25V17.75C4.49996 18.7165 5.28344 19.5 6.24992 19.5H17.7496C18.7161 19.5 19.4996 18.7165 19.4996 17.75V13.75C19.4996 13.3358 19.8354 13 20.2496 13C20.6638 13 20.9995 13.3358 20.9995 13.75V17.75C20.9995 19.5449 19.5445 21 17.7496 21H6.24992C4.45504 21 3 19.5449 3 17.75V6.25C3 4.45507 4.45504 3 6.24992 3H10.2498C10.664 3 10.9998 3.33579 10.9998 3.75C10.9998 4.16421 10.664 4.5 10.2498 4.5H6.24992ZM12.9997 3.75C12.9997 3.33579 13.3355 3 13.7497 3H20.25C20.6642 3 21 3.33579 21 3.75V10.25C21 10.6642 20.6642 11 20.25 11C19.8358 11 19.5 10.6642 19.5 10.25V5.56074L14.28 10.7804C13.9871 11.0732 13.5123 11.0732 13.2194 10.7803C12.9265 10.4874 12.9265 10.0125 13.2194 9.71964L18.4395 4.5H13.7497C13.3355 4.5 12.9997 4.16421 12.9997 3.75Z" /></svg>`;
429
+ this._isFocused = false;
428
430
  this._initResizing = (evt) => {
429
431
  evt.stopPropagation();
430
432
  this._mouseStartPointX = evt.clientX;
@@ -867,6 +869,22 @@ export class GraphFrame {
867
869
  this._headerTextElement = root.ownerDocument.createElement("div");
868
870
  this._headerTextElement.classList.add(styles["frame-box-header-title"]);
869
871
  this._headerElement.appendChild(this._headerTextElement);
872
+ // Focus
873
+ this._headerFocusElement = root.ownerDocument.createElement("div");
874
+ this._headerFocusElement.classList.add(styles["frame-box-header-focus"]);
875
+ this._headerFocusElement.classList.add(styles["frame-box-header-button"]);
876
+ this._headerFocusElement.title = "Switch focus mode";
877
+ this._headerFocusElement.ondragstart = () => false;
878
+ this._headerFocusElement.addEventListener("pointerdown", (evt) => {
879
+ evt.stopPropagation();
880
+ });
881
+ this._headerFocusElement.addEventListener("pointerup", (evt) => {
882
+ evt.stopPropagation();
883
+ this.switchFocusMode();
884
+ });
885
+ this._headerFocusElement.innerHTML = this._focusSVG;
886
+ this._headerElement.appendChild(this._headerFocusElement);
887
+ // Collapse
870
888
  this._headerCollapseElement = root.ownerDocument.createElement("div");
871
889
  this._headerCollapseElement.classList.add(styles["frame-box-header-collapse"]);
872
890
  this._headerCollapseElement.classList.add(styles["frame-box-header-button"]);
@@ -883,6 +901,7 @@ export class GraphFrame {
883
901
  });
884
902
  this._headerCollapseElement.innerHTML = this._collapseSVG;
885
903
  this._headerElement.appendChild(this._headerCollapseElement);
904
+ // Close
886
905
  this._headerCloseElement = root.ownerDocument.createElement("div");
887
906
  this._headerCloseElement.classList.add(styles["frame-box-header-close"]);
888
907
  this._headerCloseElement.classList.add(styles["frame-box-header-button"]);
@@ -963,7 +982,65 @@ export class GraphFrame {
963
982
  this.refresh();
964
983
  }
965
984
  }
985
+ /**
986
+ * Enter/leave focus mode
987
+ */
988
+ switchFocusMode() {
989
+ if (this._isFocused) {
990
+ this._isFocused = false;
991
+ for (const node of this._ownerCanvas.nodes) {
992
+ if (this._nodes.indexOf(node) === -1) {
993
+ node.rootElement.style.transition = "";
994
+ node.rootElement.style.opacity = "";
995
+ node.rootElement.style.pointerEvents = "";
996
+ }
997
+ }
998
+ for (const link of this._ownerCanvas.links) {
999
+ link.path.style.transition = "";
1000
+ link.path.style.opacity = "";
1001
+ link.selectionPath.style.pointerEvents = "";
1002
+ }
1003
+ for (const frame of this._ownerCanvas.frames) {
1004
+ if (frame !== this) {
1005
+ frame.element.style.transition = "";
1006
+ frame.element.style.opacity = "";
1007
+ frame.element.style.pointerEvents = "";
1008
+ }
1009
+ }
1010
+ return;
1011
+ }
1012
+ this._isFocused = true;
1013
+ for (const node of this._ownerCanvas.nodes) {
1014
+ if (this._nodes.indexOf(node) === -1) {
1015
+ node.rootElement.style.transition = "opacity 0.5s";
1016
+ node.rootElement.style.opacity = "0.05";
1017
+ node.rootElement.style.pointerEvents = "none";
1018
+ }
1019
+ }
1020
+ for (const link of this._ownerCanvas.links) {
1021
+ if (this._nodes.indexOf(link.nodeA) === -1 || this._nodes.indexOf(link.nodeB) === -1) {
1022
+ link.path.style.transition = "opacity 0.5s";
1023
+ link.path.style.opacity = "0.3";
1024
+ link.selectionPath.style.pointerEvents = "none";
1025
+ }
1026
+ if (this._nodes.indexOf(link.nodeA) === -1 && this._nodes.indexOf(link.nodeB) === -1) {
1027
+ link.path.style.transition = "opacity 0.5s";
1028
+ link.path.style.opacity = "0.05";
1029
+ link.selectionPath.style.pointerEvents = "none";
1030
+ }
1031
+ }
1032
+ for (const frame of this._ownerCanvas.frames) {
1033
+ if (frame !== this) {
1034
+ frame.element.style.transition = "opacity 0.5s";
1035
+ frame.element.style.opacity = "0.05";
1036
+ frame.element.style.pointerEvents = "none";
1037
+ }
1038
+ }
1039
+ }
966
1040
  refresh() {
1041
+ if (this._isFocused) {
1042
+ return;
1043
+ }
967
1044
  this._nodes = [];
968
1045
  this._ownerCanvas.stateManager.onFrameCreatedObservable.notifyObservers(this);
969
1046
  }