squarified 0.3.5 → 0.3.7

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/dist/index.js CHANGED
@@ -1,1697 +1,1976 @@
1
1
  'use strict';
2
2
 
3
- var __defProp$c = Object.defineProperty;
4
- var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
- var __publicField$c = (obj, key, value) => __defNormalProp$c(obj, typeof key !== "symbol" ? key + "" : key, value);
6
3
  const DEG_TO_RAD = Math.PI / 180;
7
4
  class Matrix2D {
8
- constructor(loc = {}) {
9
- __publicField$c(this, "a");
10
- __publicField$c(this, "b");
11
- __publicField$c(this, "c");
12
- __publicField$c(this, "d");
13
- __publicField$c(this, "e");
14
- __publicField$c(this, "f");
15
- this.a = loc.a || 1;
16
- this.b = loc.b || 0;
17
- this.c = loc.c || 0;
18
- this.d = loc.d || 1;
19
- this.e = loc.e || 0;
20
- this.f = loc.f || 0;
21
- }
22
- create(loc) {
23
- Object.assign(this, loc);
24
- return this;
25
- }
26
- transform(x, y, scaleX, scaleY, rotation, skewX, skewY) {
27
- this.scale(scaleX, scaleY).translation(x, y);
28
- if (skewX || skewY) {
29
- this.skew(skewX, skewY);
30
- } else {
31
- this.roate(rotation);
32
- }
33
- return this;
34
- }
35
- translation(x, y) {
36
- this.e += x;
37
- this.f += y;
38
- return this;
39
- }
40
- scale(a, d) {
41
- this.a *= a;
42
- this.d *= d;
43
- return this;
44
- }
45
- skew(x, y) {
46
- const tanX = Math.tan(x * DEG_TO_RAD);
47
- const tanY = Math.tan(y * DEG_TO_RAD);
48
- const a = this.a + this.b * tanX;
49
- const b = this.b + this.a * tanY;
50
- const c = this.c + this.d * tanX;
51
- const d = this.d + this.c * tanY;
52
- this.a = a;
53
- this.b = b;
54
- this.c = c;
55
- this.d = d;
56
- return this;
57
- }
58
- roate(rotation) {
59
- if (rotation > 0) {
60
- const rad = rotation * DEG_TO_RAD;
61
- const cosTheta = Math.cos(rad);
62
- const sinTheta = Math.sin(rad);
63
- const a = this.a * cosTheta - this.b * sinTheta;
64
- const b = this.a * sinTheta + this.b * cosTheta;
65
- const c = this.c * cosTheta - this.d * sinTheta;
66
- const d = this.c * sinTheta + this.d * cosTheta;
67
- this.a = a;
68
- this.b = b;
69
- this.c = c;
70
- this.d = d;
71
- }
72
- return this;
73
- }
5
+ a;
6
+ b;
7
+ c;
8
+ d;
9
+ e;
10
+ f;
11
+ constructor(loc = {}){
12
+ this.a = loc.a || 1;
13
+ this.b = loc.b || 0;
14
+ this.c = loc.c || 0;
15
+ this.d = loc.d || 1;
16
+ this.e = loc.e || 0;
17
+ this.f = loc.f || 0;
18
+ }
19
+ create(loc) {
20
+ Object.assign(this, loc);
21
+ return this;
22
+ }
23
+ transform(x, y, scaleX, scaleY, rotation, skewX, skewY) {
24
+ this.scale(scaleX, scaleY).translation(x, y);
25
+ if (skewX || skewY) {
26
+ this.skew(skewX, skewY);
27
+ } else {
28
+ this.roate(rotation);
29
+ }
30
+ return this;
31
+ }
32
+ translation(x, y) {
33
+ this.e += x;
34
+ this.f += y;
35
+ return this;
36
+ }
37
+ scale(a, d) {
38
+ this.a *= a;
39
+ this.d *= d;
40
+ return this;
41
+ }
42
+ skew(x, y) {
43
+ const tanX = Math.tan(x * DEG_TO_RAD);
44
+ const tanY = Math.tan(y * DEG_TO_RAD);
45
+ const a = this.a + this.b * tanX;
46
+ const b = this.b + this.a * tanY;
47
+ const c = this.c + this.d * tanX;
48
+ const d = this.d + this.c * tanY;
49
+ this.a = a;
50
+ this.b = b;
51
+ this.c = c;
52
+ this.d = d;
53
+ return this;
54
+ }
55
+ roate(rotation) {
56
+ if (rotation > 0) {
57
+ const rad = rotation * DEG_TO_RAD;
58
+ const cosTheta = Math.cos(rad);
59
+ const sinTheta = Math.sin(rad);
60
+ const a = this.a * cosTheta - this.b * sinTheta;
61
+ const b = this.a * sinTheta + this.b * cosTheta;
62
+ const c = this.c * cosTheta - this.d * sinTheta;
63
+ const d = this.c * sinTheta + this.d * cosTheta;
64
+ this.a = a;
65
+ this.b = b;
66
+ this.c = c;
67
+ this.d = d;
68
+ }
69
+ return this;
70
+ }
74
71
  }
75
72
 
76
- var __defProp$b = Object.defineProperty;
77
- var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
78
- var __publicField$b = (obj, key, value) => __defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value);
79
73
  const SELF_ID = {
80
- id: 0,
81
- get() {
82
- return this.id++;
83
- }
74
+ id: 0,
75
+ get () {
76
+ return this.id++;
77
+ }
84
78
  };
85
- var DisplayType = /* @__PURE__ */ ((DisplayType2) => {
86
- DisplayType2["Graph"] = "Graph";
87
- DisplayType2["Box"] = "Box";
88
- DisplayType2["Text"] = "Text";
89
- DisplayType2["RoundRect"] = "RoundRect";
90
- DisplayType2["Bitmap"] = "Bitmap";
91
- return DisplayType2;
92
- })(DisplayType || {});
79
+ var DisplayType = /*#__PURE__*/ function(DisplayType) {
80
+ DisplayType["Graph"] = "Graph";
81
+ DisplayType["Box"] = "Box";
82
+ DisplayType["Text"] = "Text";
83
+ DisplayType["RoundRect"] = "RoundRect";
84
+ DisplayType["Bitmap"] = "Bitmap";
85
+ return DisplayType;
86
+ }({});
93
87
  class Display {
94
- constructor() {
95
- __publicField$b(this, "parent");
96
- __publicField$b(this, "id");
97
- __publicField$b(this, "matrix");
98
- this.parent = null;
99
- this.id = SELF_ID.get();
100
- this.matrix = new Matrix2D();
101
- }
102
- destory() {
103
- }
88
+ parent;
89
+ id;
90
+ matrix;
91
+ constructor(){
92
+ this.parent = null;
93
+ this.id = SELF_ID.get();
94
+ this.matrix = new Matrix2D();
95
+ }
96
+ destory() {
97
+ //
98
+ }
104
99
  }
105
100
  const ASSIGN_MAPPINGS = {
106
- fillStyle: 1,
107
- strokeStyle: 2,
108
- font: 4,
109
- lineWidth: 8,
110
- textAlign: 16,
111
- textBaseline: 32
101
+ fillStyle: 0o1,
102
+ strokeStyle: 0o2,
103
+ font: 0o4,
104
+ lineWidth: 0o10,
105
+ textAlign: 0o20,
106
+ textBaseline: 0o40
112
107
  };
113
108
  const ASSIGN_MAPPINGS_MODE = ASSIGN_MAPPINGS.fillStyle | ASSIGN_MAPPINGS.strokeStyle | ASSIGN_MAPPINGS.font | ASSIGN_MAPPINGS.lineWidth | ASSIGN_MAPPINGS.textAlign | ASSIGN_MAPPINGS.textBaseline;
114
- const CALL_MAPPINGS_MODE = 0;
109
+ const CALL_MAPPINGS_MODE = 0o0;
115
110
  function createInstruction() {
116
- return {
117
- mods: [],
118
- fillStyle(...args) {
119
- this.mods.push({ mod: ["fillStyle", args], type: ASSIGN_MAPPINGS.fillStyle });
120
- },
121
- fillRect(...args) {
122
- this.mods.push({ mod: ["fillRect", args], type: CALL_MAPPINGS_MODE });
123
- },
124
- strokeStyle(...args) {
125
- this.mods.push({ mod: ["strokeStyle", args], type: ASSIGN_MAPPINGS.strokeStyle });
126
- },
127
- lineWidth(...args) {
128
- this.mods.push({ mod: ["lineWidth", args], type: ASSIGN_MAPPINGS.lineWidth });
129
- },
130
- strokeRect(...args) {
131
- this.mods.push({ mod: ["strokeRect", args], type: CALL_MAPPINGS_MODE });
132
- },
133
- fillText(...args) {
134
- this.mods.push({ mod: ["fillText", args], type: CALL_MAPPINGS_MODE });
135
- },
136
- font(...args) {
137
- this.mods.push({ mod: ["font", args], type: ASSIGN_MAPPINGS.font });
138
- },
139
- textBaseline(...args) {
140
- this.mods.push({ mod: ["textBaseline", args], type: ASSIGN_MAPPINGS.textBaseline });
141
- },
142
- textAlign(...args) {
143
- this.mods.push({ mod: ["textAlign", args], type: ASSIGN_MAPPINGS.textAlign });
144
- },
145
- beginPath() {
146
- this.mods.push({ mod: ["beginPath", []], type: CALL_MAPPINGS_MODE });
147
- },
148
- moveTo(...args) {
149
- this.mods.push({ mod: ["moveTo", args], type: CALL_MAPPINGS_MODE });
150
- },
151
- arcTo(...args) {
152
- this.mods.push({ mod: ["arcTo", args], type: CALL_MAPPINGS_MODE });
153
- },
154
- closePath() {
155
- this.mods.push({ mod: ["closePath", []], type: CALL_MAPPINGS_MODE });
156
- },
157
- fill() {
158
- this.mods.push({ mod: ["fill", []], type: CALL_MAPPINGS_MODE });
159
- },
160
- stroke() {
161
- this.mods.push({ mod: ["stroke", []], type: CALL_MAPPINGS_MODE });
162
- },
163
- drawImage(...args) {
164
- this.mods.push({ mod: ["drawImage", args], type: CALL_MAPPINGS_MODE });
165
- }
166
- };
111
+ return {
112
+ mods: [],
113
+ fillStyle (...args) {
114
+ this.mods.push({
115
+ mod: [
116
+ 'fillStyle',
117
+ args
118
+ ],
119
+ type: ASSIGN_MAPPINGS.fillStyle
120
+ });
121
+ },
122
+ fillRect (...args) {
123
+ this.mods.push({
124
+ mod: [
125
+ 'fillRect',
126
+ args
127
+ ],
128
+ type: CALL_MAPPINGS_MODE
129
+ });
130
+ },
131
+ strokeStyle (...args) {
132
+ this.mods.push({
133
+ mod: [
134
+ 'strokeStyle',
135
+ args
136
+ ],
137
+ type: ASSIGN_MAPPINGS.strokeStyle
138
+ });
139
+ },
140
+ lineWidth (...args) {
141
+ this.mods.push({
142
+ mod: [
143
+ 'lineWidth',
144
+ args
145
+ ],
146
+ type: ASSIGN_MAPPINGS.lineWidth
147
+ });
148
+ },
149
+ strokeRect (...args) {
150
+ this.mods.push({
151
+ mod: [
152
+ 'strokeRect',
153
+ args
154
+ ],
155
+ type: CALL_MAPPINGS_MODE
156
+ });
157
+ },
158
+ fillText (...args) {
159
+ this.mods.push({
160
+ mod: [
161
+ 'fillText',
162
+ args
163
+ ],
164
+ type: CALL_MAPPINGS_MODE
165
+ });
166
+ },
167
+ font (...args) {
168
+ this.mods.push({
169
+ mod: [
170
+ 'font',
171
+ args
172
+ ],
173
+ type: ASSIGN_MAPPINGS.font
174
+ });
175
+ },
176
+ textBaseline (...args) {
177
+ this.mods.push({
178
+ mod: [
179
+ 'textBaseline',
180
+ args
181
+ ],
182
+ type: ASSIGN_MAPPINGS.textBaseline
183
+ });
184
+ },
185
+ textAlign (...args) {
186
+ this.mods.push({
187
+ mod: [
188
+ 'textAlign',
189
+ args
190
+ ],
191
+ type: ASSIGN_MAPPINGS.textAlign
192
+ });
193
+ },
194
+ beginPath () {
195
+ this.mods.push({
196
+ mod: [
197
+ 'beginPath',
198
+ []
199
+ ],
200
+ type: CALL_MAPPINGS_MODE
201
+ });
202
+ },
203
+ moveTo (...args) {
204
+ this.mods.push({
205
+ mod: [
206
+ 'moveTo',
207
+ args
208
+ ],
209
+ type: CALL_MAPPINGS_MODE
210
+ });
211
+ },
212
+ arcTo (...args) {
213
+ this.mods.push({
214
+ mod: [
215
+ 'arcTo',
216
+ args
217
+ ],
218
+ type: CALL_MAPPINGS_MODE
219
+ });
220
+ },
221
+ closePath () {
222
+ this.mods.push({
223
+ mod: [
224
+ 'closePath',
225
+ []
226
+ ],
227
+ type: CALL_MAPPINGS_MODE
228
+ });
229
+ },
230
+ fill () {
231
+ this.mods.push({
232
+ mod: [
233
+ 'fill',
234
+ []
235
+ ],
236
+ type: CALL_MAPPINGS_MODE
237
+ });
238
+ },
239
+ stroke () {
240
+ this.mods.push({
241
+ mod: [
242
+ 'stroke',
243
+ []
244
+ ],
245
+ type: CALL_MAPPINGS_MODE
246
+ });
247
+ },
248
+ drawImage (...args) {
249
+ // @ts-expect-error safe
250
+ this.mods.push({
251
+ mod: [
252
+ 'drawImage',
253
+ args
254
+ ],
255
+ type: CALL_MAPPINGS_MODE
256
+ });
257
+ }
258
+ };
167
259
  }
168
260
  class S extends Display {
169
- constructor(options = {}) {
170
- super();
171
- __publicField$b(this, "width");
172
- __publicField$b(this, "height");
173
- __publicField$b(this, "x");
174
- __publicField$b(this, "y");
175
- __publicField$b(this, "scaleX");
176
- __publicField$b(this, "scaleY");
177
- __publicField$b(this, "rotation");
178
- __publicField$b(this, "skewX");
179
- __publicField$b(this, "skewY");
180
- this.width = options.width || 0;
181
- this.height = options.height || 0;
182
- this.x = options.x || 0;
183
- this.y = options.y || 0;
184
- this.scaleX = options.scaleX || 1;
185
- this.scaleY = options.scaleY || 1;
186
- this.rotation = options.rotation || 0;
187
- this.skewX = options.skewX || 0;
188
- this.skewY = options.skewY || 0;
189
- }
190
- }
261
+ width;
262
+ height;
263
+ x;
264
+ y;
265
+ scaleX;
266
+ scaleY;
267
+ rotation;
268
+ skewX;
269
+ skewY;
270
+ constructor(options = {}){
271
+ super();
272
+ this.width = options.width || 0;
273
+ this.height = options.height || 0;
274
+ this.x = options.x || 0;
275
+ this.y = options.y || 0;
276
+ this.scaleX = options.scaleX || 1;
277
+ this.scaleY = options.scaleY || 1;
278
+ this.rotation = options.rotation || 0;
279
+ this.skewX = options.skewX || 0;
280
+ this.skewY = options.skewY || 0;
281
+ }
282
+ }
283
+ // For performance. we need impl AABB Check for render.
191
284
  class Graph extends S {
192
- constructor(options = {}) {
193
- super(options);
194
- __publicField$b(this, "instruction");
195
- __publicField$b(this, "__options__");
196
- __publicField$b(this, "__widget__");
197
- this.instruction = createInstruction();
198
- this.__options__ = options;
199
- this.__widget__ = null;
200
- }
201
- render(ctx) {
202
- this.create();
203
- const cap = this.instruction.mods.length;
204
- for (let i = 0; i < cap; i++) {
205
- const { mod, type } = this.instruction.mods[i];
206
- const [direct, ...args] = mod;
207
- if (type & ASSIGN_MAPPINGS_MODE) {
208
- ctx[direct] = args[0];
209
- continue;
210
- }
211
- ctx[direct].apply(ctx, ...args);
212
- }
213
- }
214
- get __instanceOf__() {
215
- return "Graph" /* Graph */;
216
- }
285
+ instruction;
286
+ __options__;
287
+ __widget__;
288
+ constructor(options = {}){
289
+ super(options);
290
+ this.instruction = createInstruction();
291
+ this.__options__ = options;
292
+ this.__widget__ = null;
293
+ }
294
+ render(ctx) {
295
+ this.create();
296
+ const cap = this.instruction.mods.length;
297
+ for(let i = 0; i < cap; i++){
298
+ const { mod, type } = this.instruction.mods[i];
299
+ const [direct, ...args] = mod;
300
+ if (type & ASSIGN_MAPPINGS_MODE) {
301
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
302
+ // @ts-expect-error
303
+ ctx[direct] = args[0];
304
+ continue;
305
+ }
306
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
307
+ // @ts-expect-error
308
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
309
+ ctx[direct].apply(ctx, ...args);
310
+ }
311
+ }
312
+ get __instanceOf__() {
313
+ return "Graph";
314
+ }
217
315
  }
218
316
 
219
317
  function isGraph(display) {
220
- return display.__instanceOf__ === DisplayType.Graph;
318
+ return display.__instanceOf__ === DisplayType.Graph;
221
319
  }
222
320
  function isBox(display) {
223
- return display.__instanceOf__ === DisplayType.Box;
321
+ return display.__instanceOf__ === DisplayType.Box;
224
322
  }
225
323
  function isRoundRect(display) {
226
- return isGraph(display) && display.__shape__ === DisplayType.RoundRect;
324
+ return isGraph(display) && display.__shape__ === DisplayType.RoundRect;
227
325
  }
228
326
  function isText(display) {
229
- return isGraph(display) && display.__shape__ === DisplayType.Text;
327
+ return isGraph(display) && display.__shape__ === DisplayType.Text;
230
328
  }
231
329
  function isBitmap(display) {
232
- return isGraph(display) && display.__shape__ === DisplayType.Bitmap;
330
+ return isGraph(display) && display.__shape__ === DisplayType.Bitmap;
233
331
  }
234
332
  const asserts = {
235
- isGraph,
236
- isBox,
237
- isText,
238
- isRoundRect,
239
- isBitmap
333
+ isGraph,
334
+ isBox,
335
+ isText,
336
+ isRoundRect,
337
+ isBitmap
240
338
  };
241
339
 
242
- var __defProp$a = Object.defineProperty;
243
- var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
244
- var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
245
340
  class C extends Display {
246
- constructor() {
247
- super();
248
- __publicField$a(this, "elements");
249
- this.elements = [];
250
- }
251
- add(...elements) {
252
- const cap = elements.length;
253
- for (let i = 0; i < cap; i++) {
254
- const element = elements[i];
255
- if (element.parent) ;
256
- this.elements.push(element);
257
- element.parent = this;
258
- }
259
- }
260
- remove(...elements) {
261
- const cap = elements.length;
262
- for (let i = 0; i < cap; i++) {
263
- for (let j = this.elements.length - 1; j >= 0; j--) {
264
- const element = this.elements[j];
265
- if (element.id === elements[i].id) {
266
- this.elements.splice(j, 1);
267
- element.parent = null;
268
- }
269
- }
270
- }
271
- }
272
- destory() {
273
- this.elements.forEach((element) => element.parent = null);
274
- this.elements.length = 0;
275
- }
341
+ elements;
342
+ constructor(){
343
+ super();
344
+ this.elements = [];
345
+ }
346
+ add(...elements) {
347
+ const cap = elements.length;
348
+ for(let i = 0; i < cap; i++){
349
+ const element = elements[i];
350
+ if (element.parent) ;
351
+ this.elements.push(element);
352
+ element.parent = this;
353
+ }
354
+ }
355
+ remove(...elements) {
356
+ const cap = elements.length;
357
+ for(let i = 0; i < cap; i++){
358
+ for(let j = this.elements.length - 1; j >= 0; j--){
359
+ const element = this.elements[j];
360
+ if (element.id === elements[i].id) {
361
+ this.elements.splice(j, 1);
362
+ element.parent = null;
363
+ }
364
+ }
365
+ }
366
+ }
367
+ destory() {
368
+ this.elements.forEach((element)=>element.parent = null);
369
+ this.elements.length = 0;
370
+ }
276
371
  }
277
372
  class Box extends C {
278
- constructor() {
279
- super();
280
- __publicField$a(this, "elements");
281
- this.elements = [];
282
- }
283
- add(...elements) {
284
- const cap = elements.length;
285
- for (let i = 0; i < cap; i++) {
286
- const element = elements[i];
287
- if (element.parent) ;
288
- this.elements.push(element);
289
- element.parent = this;
290
- }
291
- }
292
- remove(...elements) {
293
- const cap = elements.length;
294
- for (let i = 0; i < cap; i++) {
295
- for (let j = this.elements.length - 1; j >= 0; j--) {
296
- const element = this.elements[j];
297
- if (element.id === elements[i].id) {
298
- this.elements.splice(j, 1);
299
- element.parent = null;
300
- }
301
- }
302
- }
303
- }
304
- destory() {
305
- this.elements.forEach((element) => element.parent = null);
306
- this.elements.length = 0;
307
- }
308
- get __instanceOf__() {
309
- return DisplayType.Box;
310
- }
311
- clone() {
312
- const box = new Box();
313
- if (this.elements.length) {
314
- const stack = [{ elements: this.elements, parent: box }];
315
- while (stack.length > 0) {
316
- const { elements, parent } = stack.pop();
373
+ elements;
374
+ constructor(){
375
+ super();
376
+ this.elements = [];
377
+ }
378
+ add(...elements) {
317
379
  const cap = elements.length;
318
- for (let i = 0; i < cap; i++) {
319
- const element = elements[i];
320
- if (asserts.isBox(element)) {
321
- const newBox = new Box();
322
- newBox.parent = parent;
323
- parent.add(newBox);
324
- stack.push({ elements: element.elements, parent: newBox });
325
- } else if (asserts.isGraph(element)) {
326
- const el = element.clone();
327
- el.parent = parent;
328
- parent.add(el);
329
- }
330
- }
331
- }
332
- }
333
- return box;
334
- }
380
+ for(let i = 0; i < cap; i++){
381
+ const element = elements[i];
382
+ if (element.parent) ;
383
+ this.elements.push(element);
384
+ element.parent = this;
385
+ }
386
+ }
387
+ remove(...elements) {
388
+ const cap = elements.length;
389
+ for(let i = 0; i < cap; i++){
390
+ for(let j = this.elements.length - 1; j >= 0; j--){
391
+ const element = this.elements[j];
392
+ if (element.id === elements[i].id) {
393
+ this.elements.splice(j, 1);
394
+ element.parent = null;
395
+ }
396
+ }
397
+ }
398
+ }
399
+ destory() {
400
+ this.elements.forEach((element)=>element.parent = null);
401
+ this.elements.length = 0;
402
+ }
403
+ get __instanceOf__() {
404
+ return DisplayType.Box;
405
+ }
406
+ clone() {
407
+ const box = new Box();
408
+ if (this.elements.length) {
409
+ const stack = [
410
+ {
411
+ elements: this.elements,
412
+ parent: box
413
+ }
414
+ ];
415
+ while(stack.length > 0){
416
+ const { elements, parent } = stack.pop();
417
+ const cap = elements.length;
418
+ for(let i = 0; i < cap; i++){
419
+ const element = elements[i];
420
+ if (asserts.isBox(element)) {
421
+ const newBox = new Box();
422
+ newBox.parent = parent;
423
+ parent.add(newBox);
424
+ stack.push({
425
+ elements: element.elements,
426
+ parent: newBox
427
+ });
428
+ } else if (asserts.isGraph(element)) {
429
+ const el = element.clone();
430
+ el.parent = parent;
431
+ parent.add(el);
432
+ }
433
+ }
434
+ }
435
+ }
436
+ return box;
437
+ }
335
438
  }
336
439
 
337
- var __defProp$9 = Object.defineProperty;
338
- var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
339
- var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
340
440
  class Bitmap extends Graph {
341
- constructor(options = {}) {
342
- super(options);
343
- __publicField$9(this, "bitmap");
344
- __publicField$9(this, "style");
345
- __publicField$9(this, "dpi");
346
- this.bitmap = options.bitmap || null;
347
- this.style = options.style || /* @__PURE__ */ Object.create(null);
348
- this.dpi = options.dpi || 1;
349
- }
350
- create() {
351
- if (this.bitmap) {
352
- this.instruction.drawImage(this.bitmap, 0, 0, this.bitmap.width / this.dpi, this.bitmap.height / this.dpi);
353
- }
354
- }
355
- clone() {
356
- return new Bitmap({ ...this.style, ...this.__options__ });
357
- }
358
- get __shape__() {
359
- return DisplayType.Bitmap;
360
- }
441
+ bitmap;
442
+ style;
443
+ dpi;
444
+ constructor(options = {}){
445
+ super(options);
446
+ this.bitmap = options.bitmap || null;
447
+ this.style = options.style || Object.create(null);
448
+ this.dpi = options.dpi || 1;
449
+ }
450
+ create() {
451
+ if (this.bitmap) {
452
+ this.instruction.drawImage(this.bitmap, 0, 0, this.bitmap.width / this.dpi, this.bitmap.height / this.dpi);
453
+ }
454
+ }
455
+ clone() {
456
+ return new Bitmap({
457
+ ...this.style,
458
+ ...this.__options__
459
+ });
460
+ }
461
+ get __shape__() {
462
+ return DisplayType.Bitmap;
463
+ }
361
464
  }
362
465
 
466
+ // Runtime is designed for graph element
363
467
  function decodeHLS(meta) {
364
- const { h, l, s, a } = meta;
365
- if ("a" in meta) {
366
- return `hsla(${h}deg, ${s}%, ${l}%, ${a})`;
367
- }
368
- return `hsl(${h}deg, ${s}%, ${l}%)`;
468
+ const { h, l, s, a } = meta;
469
+ if ('a' in meta) {
470
+ return `hsla(${h}deg, ${s}%, ${l}%, ${a})`;
471
+ }
472
+ return `hsl(${h}deg, ${s}%, ${l}%)`;
369
473
  }
370
474
  function decodeRGB(meta) {
371
- const { r, g, b, a } = meta;
372
- if ("a" in meta) {
373
- return `rgba(${r}, ${g}, ${b}, ${a})`;
374
- }
375
- return `rgb(${r}, ${g}, ${b})`;
475
+ const { r, g, b, a } = meta;
476
+ if ('a' in meta) {
477
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
478
+ }
479
+ return `rgb(${r}, ${g}, ${b})`;
376
480
  }
377
481
  function decodeColor(meta) {
378
- return meta.mode === "rgb" ? decodeRGB(meta.desc) : decodeHLS(meta.desc);
482
+ return meta.mode === 'rgb' ? decodeRGB(meta.desc) : decodeHLS(meta.desc);
379
483
  }
380
484
  function evaluateFillStyle(primitive, opacity = 1) {
381
- const descibe = { mode: primitive.mode, desc: { ...primitive.desc, a: opacity } };
382
- return decodeColor(descibe);
485
+ const descibe = {
486
+ mode: primitive.mode,
487
+ desc: {
488
+ ...primitive.desc,
489
+ a: opacity
490
+ }
491
+ };
492
+ return decodeColor(descibe);
383
493
  }
384
494
  const runtime = {
385
- evaluateFillStyle
495
+ evaluateFillStyle
386
496
  };
387
497
 
388
- var __defProp$8 = Object.defineProperty;
389
- var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
390
- var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
391
498
  class RoundRect extends Graph {
392
- constructor(options = {}) {
393
- super(options);
394
- __publicField$8(this, "style");
395
- this.style = options.style || /* @__PURE__ */ Object.create(null);
396
- }
397
- get __shape__() {
398
- return DisplayType.RoundRect;
399
- }
400
- create() {
401
- const padding = this.style.padding;
402
- const x = 0;
403
- const y = 0;
404
- const width = this.width - padding * 2;
405
- const height = this.height - padding * 2;
406
- const radius = this.style.radius || 0;
407
- this.instruction.beginPath();
408
- this.instruction.moveTo(x + radius, y);
409
- this.instruction.arcTo(x + width, y, x + width, y + height, radius);
410
- this.instruction.arcTo(x + width, y + height, x, y + height, radius);
411
- this.instruction.arcTo(x, y + height, x, y, radius);
412
- this.instruction.arcTo(x, y, x + width, y, radius);
413
- this.instruction.closePath();
414
- if (this.style.fill) {
415
- this.instruction.closePath();
416
- this.instruction.fillStyle(runtime.evaluateFillStyle(this.style.fill, this.style.opacity));
417
- this.instruction.fill();
418
- }
419
- if (this.style.stroke) {
420
- if (typeof this.style.lineWidth === "number") {
421
- this.instruction.lineWidth(this.style.lineWidth);
422
- }
423
- this.instruction.strokeStyle(this.style.stroke);
424
- this.instruction.stroke();
425
- }
426
- }
427
- clone() {
428
- return new RoundRect({ ...this.style, ...this.__options__ });
429
- }
499
+ style;
500
+ constructor(options = {}){
501
+ super(options);
502
+ this.style = options.style || Object.create(null);
503
+ }
504
+ get __shape__() {
505
+ return DisplayType.RoundRect;
506
+ }
507
+ create() {
508
+ const padding = this.style.padding;
509
+ const x = 0;
510
+ const y = 0;
511
+ const width = this.width - padding * 2;
512
+ const height = this.height - padding * 2;
513
+ const radius = this.style.radius || 0;
514
+ this.instruction.beginPath();
515
+ this.instruction.moveTo(x + radius, y);
516
+ this.instruction.arcTo(x + width, y, x + width, y + height, radius);
517
+ this.instruction.arcTo(x + width, y + height, x, y + height, radius);
518
+ this.instruction.arcTo(x, y + height, x, y, radius);
519
+ this.instruction.arcTo(x, y, x + width, y, radius);
520
+ this.instruction.closePath();
521
+ if (this.style.fill) {
522
+ this.instruction.closePath();
523
+ this.instruction.fillStyle(runtime.evaluateFillStyle(this.style.fill, this.style.opacity));
524
+ this.instruction.fill();
525
+ }
526
+ if (this.style.stroke) {
527
+ if (typeof this.style.lineWidth === 'number') {
528
+ this.instruction.lineWidth(this.style.lineWidth);
529
+ }
530
+ this.instruction.strokeStyle(this.style.stroke);
531
+ this.instruction.stroke();
532
+ }
533
+ }
534
+ clone() {
535
+ return new RoundRect({
536
+ ...this.style,
537
+ ...this.__options__
538
+ });
539
+ }
430
540
  }
431
541
 
432
- var __defProp$7 = Object.defineProperty;
433
- var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
434
- var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
435
542
  class Text extends Graph {
436
- constructor(options = {}) {
437
- super(options);
438
- __publicField$7(this, "text");
439
- __publicField$7(this, "style");
440
- this.text = options.text || "";
441
- this.style = options.style || /* @__PURE__ */ Object.create(null);
442
- }
443
- create() {
444
- if (this.style.fill) {
445
- this.instruction.font(this.style.font);
446
- this.instruction.lineWidth(this.style.lineWidth);
447
- this.instruction.textBaseline(this.style.baseline);
448
- this.instruction.fillStyle(this.style.fill);
449
- this.instruction.fillText(this.text, 0, 0);
450
- }
451
- }
452
- clone() {
453
- return new Text({ ...this.style, ...this.__options__ });
454
- }
455
- get __shape__() {
456
- return DisplayType.Text;
457
- }
543
+ text;
544
+ style;
545
+ constructor(options = {}){
546
+ super(options);
547
+ this.text = options.text || '';
548
+ this.style = options.style || Object.create(null);
549
+ }
550
+ create() {
551
+ if (this.style.fill) {
552
+ this.instruction.font(this.style.font);
553
+ this.instruction.lineWidth(this.style.lineWidth);
554
+ this.instruction.textBaseline(this.style.baseline);
555
+ this.instruction.fillStyle(this.style.fill);
556
+ this.instruction.fillText(this.text, 0, 0);
557
+ }
558
+ }
559
+ clone() {
560
+ return new Text({
561
+ ...this.style,
562
+ ...this.__options__
563
+ });
564
+ }
565
+ get __shape__() {
566
+ return DisplayType.Text;
567
+ }
458
568
  }
459
569
 
460
570
  function traverse(graphs, handler) {
461
- const len = graphs.length;
462
- for (let i = 0; i < len; i++) {
463
- const graph = graphs[i];
464
- if (asserts.isGraph(graph)) {
465
- handler(graph);
466
- } else if (asserts.isBox(graph)) {
467
- traverse(graph.elements, handler);
571
+ const len = graphs.length;
572
+ for(let i = 0; i < len; i++){
573
+ const graph = graphs[i];
574
+ if (asserts.isGraph(graph)) {
575
+ handler(graph);
576
+ } else if (asserts.isBox(graph)) {
577
+ traverse(graph.elements, handler);
578
+ }
468
579
  }
469
- }
470
580
  }
581
+ // https://jhildenbiddle.github.io/canvas-size/#/?id=maxheight
471
582
  function getCanvasBoundarySize() {
472
- const ua = navigator.userAgent;
473
- let size = 16384;
474
- if (/Firefox\/(\d+)/.test(ua)) {
475
- const version = parseInt(RegExp.$1, 10);
476
- if (version >= 122) {
477
- size = 23168;
478
- } else {
479
- size = 11180;
583
+ const ua = navigator.userAgent;
584
+ let size = 16384;
585
+ if (/Firefox\/(\d+)/.test(ua)) {
586
+ const version = parseInt(RegExp.$1, 10);
587
+ if (version >= 122) {
588
+ size = 23168;
589
+ } else {
590
+ size = 11180;
591
+ }
480
592
  }
481
- }
482
- return { size };
593
+ return {
594
+ size
595
+ };
483
596
  }
484
597
  const canvasBoundarySize = getCanvasBoundarySize();
485
598
 
599
+ // Currently, etoile is an internal module, so we won't need too much easing functions.
600
+ // And the animation logic is implemented by user code.
486
601
  const easing = {
487
- linear: (k) => k,
488
- quadraticIn: (k) => k * k,
489
- quadraticOut: (k) => k * (2 - k),
490
- quadraticInOut: (k) => {
491
- if ((k *= 2) < 1) {
492
- return 0.5 * k * k;
493
- }
494
- return -0.5 * (--k * (k - 2) - 1);
495
- },
496
- cubicIn: (k) => k * k * k,
497
- cubicOut: (k) => {
498
- if ((k *= 2) < 1) {
499
- return 0.5 * k * k * k;
500
- }
501
- return 0.5 * ((k -= 2) * k * k + 2);
502
- },
503
- cubicInOut: (k) => {
504
- if ((k *= 2) < 1) {
505
- return 0.5 * k * k * k;
506
- }
507
- return 0.5 * ((k -= 2) * k * k + 2);
508
- }
602
+ linear: (k)=>k,
603
+ quadraticIn: (k)=>k * k,
604
+ quadraticOut: (k)=>k * (2 - k),
605
+ quadraticInOut: (k)=>{
606
+ if ((k *= 2) < 1) {
607
+ return 0.5 * k * k;
608
+ }
609
+ return -0.5 * (--k * (k - 2) - 1);
610
+ },
611
+ cubicIn: (k)=>k * k * k,
612
+ cubicOut: (k)=>{
613
+ if ((k *= 2) < 1) {
614
+ return 0.5 * k * k * k;
615
+ }
616
+ return 0.5 * ((k -= 2) * k * k + 2);
617
+ },
618
+ cubicInOut: (k)=>{
619
+ if ((k *= 2) < 1) {
620
+ return 0.5 * k * k * k;
621
+ }
622
+ return 0.5 * ((k -= 2) * k * k + 2);
623
+ }
509
624
  };
510
625
 
511
- var __defProp$6 = Object.defineProperty;
512
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
513
- var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
514
626
  class Event {
515
- constructor() {
516
- __publicField$6(this, "eventCollections");
517
- this.eventCollections = /* @__PURE__ */ Object.create(null);
518
- }
519
- on(evt, handler, c) {
520
- if (!(evt in this.eventCollections)) {
521
- this.eventCollections[evt] = [];
522
- }
523
- const data = {
524
- name: evt,
525
- handler,
526
- ctx: c || this,
527
- silent: false
528
- };
529
- this.eventCollections[evt].push(data);
530
- }
531
- off(evt, handler) {
532
- if (evt in this.eventCollections) {
533
- if (!handler) {
534
- this.eventCollections[evt] = [];
535
- return;
536
- }
537
- this.eventCollections[evt] = this.eventCollections[evt].filter((d) => d.handler !== handler);
538
- }
539
- }
540
- silent(evt, handler) {
541
- if (!(evt in this.eventCollections)) {
542
- return;
543
- }
544
- this.eventCollections[evt].forEach((d) => {
545
- if (!handler || d.handler === handler) {
546
- d.silent = true;
547
- }
548
- });
549
- }
550
- active(evt, handler) {
551
- if (!(evt in this.eventCollections)) {
552
- return;
553
- }
554
- this.eventCollections[evt].forEach((d) => {
555
- if (!handler || d.handler === handler) {
556
- d.silent = false;
557
- }
558
- });
559
- }
560
- emit(evt, ...args) {
561
- if (!this.eventCollections[evt]) {
562
- return;
627
+ eventCollections;
628
+ constructor(){
629
+ this.eventCollections = Object.create(null);
563
630
  }
564
- const handlers = this.eventCollections[evt];
565
- if (handlers.length) {
566
- handlers.forEach((d) => {
567
- if (d.silent) {
568
- return;
631
+ on(evt, handler, c) {
632
+ if (!(evt in this.eventCollections)) {
633
+ this.eventCollections[evt] = [];
634
+ }
635
+ const data = {
636
+ name: evt,
637
+ handler,
638
+ ctx: c || this,
639
+ silent: false
640
+ };
641
+ this.eventCollections[evt].push(data);
642
+ }
643
+ off(evt, handler) {
644
+ if (evt in this.eventCollections) {
645
+ if (!handler) {
646
+ this.eventCollections[evt] = [];
647
+ return;
648
+ }
649
+ this.eventCollections[evt] = this.eventCollections[evt].filter((d)=>d.handler !== handler);
569
650
  }
570
- d.handler.call(d.ctx, ...args);
571
- });
572
651
  }
573
- }
574
- bindWithContext(c) {
575
- return (evt, handler) => this.on(evt, handler, c);
576
- }
652
+ silent(evt, handler) {
653
+ if (!(evt in this.eventCollections)) {
654
+ return;
655
+ }
656
+ this.eventCollections[evt].forEach((d)=>{
657
+ if (!handler || d.handler === handler) {
658
+ d.silent = true;
659
+ }
660
+ });
661
+ }
662
+ active(evt, handler) {
663
+ if (!(evt in this.eventCollections)) {
664
+ return;
665
+ }
666
+ this.eventCollections[evt].forEach((d)=>{
667
+ if (!handler || d.handler === handler) {
668
+ d.silent = false;
669
+ }
670
+ });
671
+ }
672
+ emit(evt, ...args) {
673
+ if (!this.eventCollections[evt]) {
674
+ return;
675
+ }
676
+ const handlers = this.eventCollections[evt];
677
+ if (handlers.length) {
678
+ handlers.forEach((d)=>{
679
+ if (d.silent) {
680
+ return;
681
+ }
682
+ d.handler.call(d.ctx, ...args);
683
+ });
684
+ }
685
+ }
686
+ bindWithContext(c) {
687
+ return (evt, handler)=>this.on(evt, handler, c);
688
+ }
577
689
  }
578
690
 
579
691
  function hashCode(str) {
580
- let hash = 0;
581
- for (let i = 0; i < str.length; i++) {
582
- const code = str.charCodeAt(i);
583
- hash = (hash << 5) - hash + code;
584
- hash = hash & hash;
585
- }
586
- return hash;
692
+ let hash = 0;
693
+ for(let i = 0; i < str.length; i++){
694
+ const code = str.charCodeAt(i);
695
+ hash = (hash << 5) - hash + code;
696
+ hash = hash & hash;
697
+ }
698
+ return hash;
587
699
  }
700
+ // For strings we only check the first character to determine if it's a number (I think it's enough)
588
701
  function perferNumeric(s) {
589
- if (typeof s === "number") {
590
- return true;
591
- }
592
- return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
702
+ if (typeof s === 'number') {
703
+ return true;
704
+ }
705
+ return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
593
706
  }
594
707
  function createRoundBlock(x, y, width, height, style) {
595
- return new RoundRect({ width, height, x, y, style: { ...style } });
708
+ return new RoundRect({
709
+ width,
710
+ height,
711
+ x,
712
+ y,
713
+ style: {
714
+ ...style
715
+ }
716
+ });
596
717
  }
597
718
  function createTitleText(text, x, y, font, color) {
598
- return new Text({
599
- text,
600
- x,
601
- y,
602
- style: { fill: color, textAlign: "center", baseline: "middle", font, lineWidth: 1 }
603
- });
719
+ return new Text({
720
+ text,
721
+ x,
722
+ y,
723
+ style: {
724
+ fill: color,
725
+ textAlign: 'center',
726
+ baseline: 'middle',
727
+ font,
728
+ lineWidth: 1
729
+ }
730
+ });
604
731
  }
605
732
  const raf = window.requestAnimationFrame;
606
733
  function createCanvasElement() {
607
- return document.createElement("canvas");
734
+ return document.createElement('canvas');
608
735
  }
609
736
  function applyCanvasTransform(ctx, matrix, dpr) {
610
- ctx.setTransform(matrix.a * dpr, matrix.b * dpr, matrix.c * dpr, matrix.d * dpr, matrix.e * dpr, matrix.f * dpr);
737
+ ctx.setTransform(matrix.a * dpr, matrix.b * dpr, matrix.c * dpr, matrix.d * dpr, matrix.e * dpr, matrix.f * dpr);
611
738
  }
612
739
  function mixin(app, methods) {
613
- methods.forEach(({ name, fn }) => {
614
- Object.defineProperty(app, name, {
615
- value: fn(app),
616
- writable: false
740
+ methods.forEach(({ name, fn })=>{
741
+ Object.defineProperty(app, name, {
742
+ value: fn(app),
743
+ writable: false
744
+ });
617
745
  });
618
- });
619
746
  }
620
747
  function prettyStrJoin(...s) {
621
- return s.join("");
748
+ return s.join('');
622
749
  }
623
750
 
624
- const NAME_SPACE = "etoile";
751
+ const NAME_SPACE = 'etoile';
625
752
  const log = {
626
- error: (message) => {
627
- return `[${NAME_SPACE}] ${message}`;
628
- }
753
+ error: (message)=>{
754
+ return `[${NAME_SPACE}] ${message}`;
755
+ }
629
756
  };
630
757
 
631
- var __defProp$5 = Object.defineProperty;
632
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
633
- var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
634
758
  function writeBoundingRectForCanvas(c, w, h, dpr) {
635
- c.width = w * dpr;
636
- c.height = h * dpr;
637
- c.style.cssText = `width: ${w}px; height: ${h}px`;
759
+ c.width = w * dpr;
760
+ c.height = h * dpr;
761
+ c.style.cssText = `width: ${w}px; height: ${h}px`;
638
762
  }
639
763
  class Canvas {
640
- constructor(options) {
641
- __publicField$5(this, "canvas");
642
- __publicField$5(this, "ctx");
643
- this.canvas = createCanvasElement();
644
- this.setOptions(options);
645
- this.ctx = this.canvas.getContext("2d");
646
- }
647
- setOptions(options) {
648
- writeBoundingRectForCanvas(this.canvas, options.width, options.height, options.devicePixelRatio);
649
- }
764
+ canvas;
765
+ ctx;
766
+ constructor(options){
767
+ this.canvas = createCanvasElement();
768
+ this.setOptions(options);
769
+ this.ctx = this.canvas.getContext('2d');
770
+ }
771
+ setOptions(options) {
772
+ writeBoundingRectForCanvas(this.canvas, options.width, options.height, options.devicePixelRatio);
773
+ }
650
774
  }
651
775
  class Render {
652
- constructor(to, options) {
653
- __publicField$5(this, "options");
654
- __publicField$5(this, "container");
655
- this.container = new Canvas(options);
656
- this.options = options;
657
- this.initOptions(options);
658
- if (!options.shaow) {
659
- to.appendChild(this.container.canvas);
660
- }
661
- }
662
- clear(width, height) {
663
- this.ctx.clearRect(0, 0, width, height);
664
- }
665
- get canvas() {
666
- return this.container.canvas;
667
- }
668
- get ctx() {
669
- return this.container.ctx;
670
- }
671
- initOptions(userOptions = {}) {
672
- Object.assign(this.options, userOptions);
673
- this.container.setOptions(this.options);
674
- }
675
- destory() {
676
- }
776
+ options;
777
+ container;
778
+ constructor(to, options){
779
+ this.container = new Canvas(options);
780
+ this.options = options;
781
+ this.initOptions(options);
782
+ if (!options.shaow) {
783
+ to.appendChild(this.container.canvas);
784
+ }
785
+ }
786
+ clear(width, height) {
787
+ this.ctx.clearRect(0, 0, width, height);
788
+ }
789
+ get canvas() {
790
+ return this.container.canvas;
791
+ }
792
+ get ctx() {
793
+ return this.container.ctx;
794
+ }
795
+ initOptions(userOptions = {}) {
796
+ Object.assign(this.options, userOptions);
797
+ this.container.setOptions(this.options);
798
+ }
799
+ destory() {}
677
800
  }
678
801
 
679
- var __defProp$4 = Object.defineProperty;
680
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
681
- var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
802
+ // First cleanup canvas
682
803
  function drawGraphIntoCanvas(graph, opts) {
683
- const { ctx, dpr } = opts;
684
- ctx.save();
685
- if (asserts.isBox(graph)) {
686
- const elements = graph.elements;
687
- const cap = elements.length;
688
- for (let i = 0; i < cap; i++) {
689
- const element = elements[i];
690
- drawGraphIntoCanvas(element, opts);
691
- }
692
- }
693
- if (asserts.isGraph(graph)) {
694
- const matrix = graph.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
695
- matrix.transform(graph.x, graph.y, graph.scaleX, graph.scaleY, graph.rotation, graph.skewX, graph.skewY);
696
- if (asserts.isRoundRect(graph)) {
697
- const effectiveWidth = graph.width - graph.style.padding * 2;
698
- const effectiveHeight = graph.height - graph.style.padding * 2;
699
- if (effectiveWidth <= 0 || effectiveHeight <= 0) {
700
- ctx.restore();
701
- return;
702
- }
703
- if (graph.style.radius >= effectiveHeight / 2 || graph.style.radius >= effectiveWidth / 2) {
704
- ctx.restore();
705
- return;
706
- }
707
- }
708
- applyCanvasTransform(ctx, matrix, dpr);
709
- graph.render(ctx);
710
- }
711
- ctx.restore();
804
+ const { ctx, dpr } = opts;
805
+ ctx.save();
806
+ if (asserts.isBox(graph)) {
807
+ const elements = graph.elements;
808
+ const cap = elements.length;
809
+ for(let i = 0; i < cap; i++){
810
+ const element = elements[i];
811
+ drawGraphIntoCanvas(element, opts);
812
+ }
813
+ }
814
+ if (asserts.isGraph(graph)) {
815
+ const matrix = graph.matrix.create({
816
+ a: 1,
817
+ b: 0,
818
+ c: 0,
819
+ d: 1,
820
+ e: 0,
821
+ f: 0
822
+ });
823
+ matrix.transform(graph.x, graph.y, graph.scaleX, graph.scaleY, graph.rotation, graph.skewX, graph.skewY);
824
+ if (asserts.isRoundRect(graph)) {
825
+ const effectiveWidth = graph.width - graph.style.padding * 2;
826
+ const effectiveHeight = graph.height - graph.style.padding * 2;
827
+ if (effectiveWidth <= 0 || effectiveHeight <= 0) {
828
+ ctx.restore();
829
+ return;
830
+ }
831
+ if (graph.style.radius >= effectiveHeight / 2 || graph.style.radius >= effectiveWidth / 2) {
832
+ ctx.restore();
833
+ return;
834
+ }
835
+ }
836
+ applyCanvasTransform(ctx, matrix, dpr);
837
+ graph.render(ctx);
838
+ }
839
+ ctx.restore();
712
840
  }
713
841
  class Schedule extends Box {
714
- constructor(to, renderOptions = {}) {
715
- super();
716
- __publicField$4(this, "render");
717
- __publicField$4(this, "to");
718
- __publicField$4(this, "event");
719
- this.to = typeof to === "string" ? document.querySelector(to) : to;
720
- if (!this.to) {
721
- throw new Error(log.error("The element to bind is not found."));
722
- }
723
- const { width, height } = this.to.getBoundingClientRect();
724
- Object.assign(renderOptions, { width, height }, { devicePixelRatio: window.devicePixelRatio || 1 });
725
- this.event = new Event();
726
- this.render = new Render(this.to, renderOptions);
727
- }
728
- update() {
729
- this.render.clear(this.render.options.width, this.render.options.height);
730
- this.execute(this.render, this);
731
- const matrix = this.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
732
- applyCanvasTransform(this.render.ctx, matrix, this.render.options.devicePixelRatio);
733
- }
734
- // execute all graph elements
735
- execute(render, graph = this) {
736
- drawGraphIntoCanvas(graph, { c: render.canvas, ctx: render.ctx, dpr: render.options.devicePixelRatio });
737
- }
842
+ render;
843
+ to;
844
+ event;
845
+ constructor(to, renderOptions = {}){
846
+ super();
847
+ this.to = typeof to === 'string' ? document.querySelector(to) : to;
848
+ if (!this.to) {
849
+ throw new Error(log.error('The element to bind is not found.'));
850
+ }
851
+ const { width, height } = this.to.getBoundingClientRect();
852
+ Object.assign(renderOptions, {
853
+ width,
854
+ height
855
+ }, {
856
+ devicePixelRatio: window.devicePixelRatio || 1
857
+ });
858
+ this.event = new Event();
859
+ this.render = new Render(this.to, renderOptions);
860
+ }
861
+ update() {
862
+ this.render.clear(this.render.options.width, this.render.options.height);
863
+ this.execute(this.render, this);
864
+ const matrix = this.matrix.create({
865
+ a: 1,
866
+ b: 0,
867
+ c: 0,
868
+ d: 1,
869
+ e: 0,
870
+ f: 0
871
+ });
872
+ applyCanvasTransform(this.render.ctx, matrix, this.render.options.devicePixelRatio);
873
+ }
874
+ // execute all graph elements
875
+ execute(render, graph = this) {
876
+ drawGraphIntoCanvas(graph, {
877
+ c: render.canvas,
878
+ ctx: render.ctx,
879
+ dpr: render.options.devicePixelRatio
880
+ });
881
+ }
738
882
  }
739
883
 
740
- var __defProp$3 = Object.defineProperty;
741
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
742
- var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
743
884
  class RenderCache extends Canvas {
744
- constructor(opts) {
745
- super(opts);
746
- __publicField$3(this, "key");
747
- __publicField$3(this, "$memory");
748
- this.key = "render-cache";
749
- this.$memory = false;
750
- }
751
- get state() {
752
- return this.$memory;
753
- }
754
- flush(treemap, matrix = new Matrix2D()) {
755
- const { devicePixelRatio, width, height } = treemap.render.options;
756
- const { a, d } = matrix;
757
- const { size } = canvasBoundarySize;
758
- if (width * a >= size || height * d >= size) {
759
- return;
760
- }
761
- if (width * a * height * d >= size * size) {
762
- return;
763
- }
764
- this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
765
- this.setOptions({ width: width * a, height: height * d, devicePixelRatio });
766
- resetLayout(treemap, width * a, height * d);
767
- drawGraphIntoCanvas(treemap, { c: this.canvas, ctx: this.ctx, dpr: devicePixelRatio });
768
- this.$memory = true;
769
- }
770
- destroy() {
771
- this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
772
- this.$memory = false;
773
- }
885
+ key;
886
+ $memory;
887
+ constructor(opts){
888
+ super(opts);
889
+ this.key = 'render-cache';
890
+ this.$memory = false;
891
+ }
892
+ get state() {
893
+ return this.$memory;
894
+ }
895
+ flush(treemap, matrix = new Matrix2D()) {
896
+ const { devicePixelRatio, width, height } = treemap.render.options;
897
+ const { a, d } = matrix;
898
+ const { size } = canvasBoundarySize;
899
+ // Check outof boundary
900
+ if (width * a >= size || height * d >= size) {
901
+ return;
902
+ }
903
+ if (width * a * height * d >= size * size) {
904
+ return;
905
+ }
906
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
907
+ this.setOptions({
908
+ width: width * a,
909
+ height: height * d,
910
+ devicePixelRatio
911
+ });
912
+ resetLayout(treemap, width * a, height * d);
913
+ drawGraphIntoCanvas(treemap, {
914
+ c: this.canvas,
915
+ ctx: this.ctx,
916
+ dpr: devicePixelRatio
917
+ });
918
+ this.$memory = true;
919
+ }
920
+ destroy() {
921
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
922
+ this.$memory = false;
923
+ }
774
924
  }
775
925
  class FontCache {
776
- constructor() {
777
- __publicField$3(this, "key");
778
- __publicField$3(this, "fonts");
779
- __publicField$3(this, "ellispsis");
780
- this.key = "font-cache";
781
- this.fonts = {};
782
- this.ellispsis = {};
783
- }
784
- get state() {
785
- return true;
786
- }
787
- flush(treemap, matrix = new Matrix2D()) {
788
- const { width, height } = treemap.render.options;
789
- const { a, d } = matrix;
790
- const zoomedWidth = width * a;
791
- const zoomedHeight = height * d;
792
- if (zoomedWidth <= width || zoomedHeight <= height) {
793
- return;
794
- }
795
- traverse([treemap.elements[0]], (graph) => {
796
- if (asserts.isRoundRect(graph)) {
797
- const { x, y, height: graphHeight, width: graphWidth } = graph;
798
- if (!graphHeight || !graphWidth) {
799
- return;
800
- }
801
- if (x >= 0 && y >= 0 && x + graphWidth <= width && y + graphHeight <= height) {
802
- if (graph.__widget__) {
803
- const node = graph.__widget__.node;
804
- delete this.fonts[node.id];
805
- delete this.ellispsis[node.label];
806
- }
807
- }
808
- }
809
- });
810
- }
811
- destroy() {
812
- this.fonts = {};
813
- this.ellispsis = {};
814
- }
815
- queryFontById(id, byDefault) {
816
- if (!(id in this.fonts)) {
817
- this.fonts[id] = byDefault();
818
- }
819
- return this.fonts[id];
820
- }
926
+ key;
927
+ fonts;
928
+ ellispsis;
929
+ constructor(){
930
+ this.key = 'font-cache';
931
+ this.fonts = {};
932
+ this.ellispsis = {};
933
+ }
934
+ get state() {
935
+ return true;
936
+ }
937
+ flush(treemap, matrix = new Matrix2D()) {
938
+ const { width, height } = treemap.render.options;
939
+ const { a, d } = matrix;
940
+ const zoomedWidth = width * a;
941
+ const zoomedHeight = height * d;
942
+ if (zoomedWidth <= width || zoomedHeight <= height) {
943
+ return;
944
+ }
945
+ traverse([
946
+ treemap.elements[0]
947
+ ], (graph)=>{
948
+ if (asserts.isRoundRect(graph)) {
949
+ const { x, y, height: graphHeight, width: graphWidth } = graph;
950
+ if (!graphHeight || !graphWidth) {
951
+ return;
952
+ }
953
+ if (x >= 0 && y >= 0 && x + graphWidth <= width && y + graphHeight <= height) {
954
+ if (graph.__widget__) {
955
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
956
+ const node = graph.__widget__.node;
957
+ delete this.fonts[node.id];
958
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
959
+ delete this.ellispsis[node.label];
960
+ }
961
+ }
962
+ }
963
+ });
964
+ }
965
+ destroy() {
966
+ this.fonts = {};
967
+ this.ellispsis = {};
968
+ }
969
+ queryFontById(id, byDefault) {
970
+ if (!(id in this.fonts)) {
971
+ this.fonts[id] = byDefault();
972
+ }
973
+ return this.fonts[id];
974
+ }
821
975
  }
822
976
 
823
- var __defProp$2 = Object.defineProperty;
824
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
825
- var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
826
- const DOM_EVENTS = ["click", "mousedown", "mousemove", "mouseup", "mouseover", "mouseout", "wheel"];
977
+ // primitive types
978
+ const DOM_EVENTS = [
979
+ 'click',
980
+ 'mousedown',
981
+ 'mousemove',
982
+ 'mouseup',
983
+ 'mouseover',
984
+ 'mouseout',
985
+ 'wheel'
986
+ ];
827
987
  function getOffset(el) {
828
- let e = 0;
829
- let f = 0;
830
- if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
831
- const { top, left } = el.getBoundingClientRect();
832
- e = top;
833
- f = left;
834
- } else {
835
- for (let elt = el; elt; elt = el.offsetParent) {
836
- e += el.offsetLeft;
837
- f += el.offsetTop;
838
- }
839
- }
840
- return [
841
- e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
842
- f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
843
- ];
988
+ let e = 0;
989
+ let f = 0;
990
+ if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
991
+ const { top, left } = el.getBoundingClientRect();
992
+ e = top;
993
+ f = left;
994
+ } else {
995
+ for(let elt = el; elt; elt = el.offsetParent){
996
+ e += el.offsetLeft;
997
+ f += el.offsetTop;
998
+ }
999
+ }
1000
+ return [
1001
+ e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
1002
+ f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
1003
+ ];
844
1004
  }
845
1005
  function captureBoxXY(c, evt, a, d, translateX, translateY) {
846
- const boundingClientRect = c.getBoundingClientRect();
847
- if (evt instanceof MouseEvent) {
848
- const [e, f] = getOffset(c);
1006
+ const boundingClientRect = c.getBoundingClientRect();
1007
+ if (evt instanceof MouseEvent) {
1008
+ const [e, f] = getOffset(c);
1009
+ return {
1010
+ x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
1011
+ y: (evt.clientY - boundingClientRect.top - f - translateY) / d
1012
+ };
1013
+ }
849
1014
  return {
850
- x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
851
- y: (evt.clientY - boundingClientRect.top - f - translateY) / d
1015
+ x: 0,
1016
+ y: 0
852
1017
  };
853
- }
854
- return { x: 0, y: 0 };
855
1018
  }
856
1019
  function createEffectRun(c) {
857
- return (fn) => {
858
- const effect = () => {
859
- const done = fn();
860
- if (!done) {
861
- c.animationFrameID = raf(effect);
862
- }
1020
+ return (fn)=>{
1021
+ const effect = ()=>{
1022
+ const done = fn();
1023
+ if (!done) {
1024
+ c.animationFrameID = raf(effect);
1025
+ }
1026
+ };
1027
+ if (!c.animationFrameID) {
1028
+ c.animationFrameID = raf(effect);
1029
+ }
863
1030
  };
864
- if (!c.animationFrameID) {
865
- c.animationFrameID = raf(effect);
866
- }
867
- };
868
1031
  }
869
1032
  function createEffectStop(c) {
870
- return () => {
871
- if (c.animationFrameID) {
872
- window.cancelAnimationFrame(c.animationFrameID);
873
- c.animationFrameID = null;
874
- }
875
- };
1033
+ return ()=>{
1034
+ if (c.animationFrameID) {
1035
+ window.cancelAnimationFrame(c.animationFrameID);
1036
+ c.animationFrameID = null;
1037
+ }
1038
+ };
876
1039
  }
877
1040
  function createSmoothFrame() {
878
- const c = {
879
- animationFrameID: null
880
- };
881
- const run = createEffectRun(c);
882
- const stop = createEffectStop(c);
883
- return { run, stop };
1041
+ const c = {
1042
+ animationFrameID: null
1043
+ };
1044
+ const run = createEffectRun(c);
1045
+ const stop = createEffectStop(c);
1046
+ return {
1047
+ run,
1048
+ stop
1049
+ };
884
1050
  }
1051
+ // Some thoughts DOMEvent was designed this way intentionally. I don't have any idea of splitting the general libray yet.
1052
+ // The follow captureBoxXy matrix a and d be 1 is because of the scaled canvas (without zoomed) is with a new layout.
885
1053
  function bindDOMEvent(el, evt, dom) {
886
- const handler = (e) => {
887
- const { x, y } = captureBoxXY(el, e, 1, 1, dom.matrix.e, dom.matrix.f);
888
- dom.emit(evt, { native: e, loc: { x, y } });
889
- };
890
- el.addEventListener(evt, handler);
891
- return handler;
1054
+ const handler = (e)=>{
1055
+ const { x, y } = captureBoxXY(el, e, 1, 1, dom.matrix.e, dom.matrix.f);
1056
+ // @ts-expect-error safe
1057
+ dom.emit(evt, {
1058
+ native: e,
1059
+ loc: {
1060
+ x,
1061
+ y
1062
+ }
1063
+ });
1064
+ };
1065
+ el.addEventListener(evt, handler);
1066
+ return handler;
892
1067
  }
893
1068
  class DOMEvent extends Event {
894
- constructor(el) {
895
- super();
896
- __publicField$2(this, "el");
897
- __publicField$2(this, "events");
898
- __publicField$2(this, "matrix");
899
- this.el = el;
900
- this.matrix = new Matrix2D();
901
- this.events = DOM_EVENTS.map((evt) => bindDOMEvent(this.el, evt, this));
902
- }
1069
+ el;
1070
+ events;
1071
+ matrix;
1072
+ constructor(el){
1073
+ super();
1074
+ this.el = el;
1075
+ this.matrix = new Matrix2D();
1076
+ this.events = DOM_EVENTS.map((evt)=>bindDOMEvent(this.el, evt, this));
1077
+ }
903
1078
  }
904
1079
 
1080
+ // Note: I won't decide to support mobile devices.
1081
+ // So don't create any reporting issues about mobile devices.
1082
+ // Notte: this only work at wheel event.
905
1083
  function useMagicTrackPad(event) {
906
- if (event.cancelable !== false) {
907
- event.preventDefault();
908
- }
909
- !event.ctrlKey;
1084
+ if (event.cancelable !== false) {
1085
+ event.preventDefault();
1086
+ }
1087
+ !event.ctrlKey;
910
1088
  }
911
1089
 
912
1090
  function sortChildrenByKey(data, ...keys) {
913
- return data.sort((a, b) => {
914
- for (const key of keys) {
915
- const v = a[key];
916
- const v2 = b[key];
917
- if (perferNumeric(v) && perferNumeric(v2)) {
918
- if (v2 > v) {
919
- return 1;
920
- }
921
- if (v2 < v) {
922
- return -1;
923
- }
924
- continue;
925
- }
926
- const comparison = ("" + v).localeCompare("" + v2);
927
- if (comparison !== 0) {
928
- return comparison;
929
- }
930
- }
931
- return 0;
932
- });
1091
+ return data.sort((a, b)=>{
1092
+ for (const key of keys){
1093
+ const v = a[key];
1094
+ const v2 = b[key];
1095
+ if (perferNumeric(v) && perferNumeric(v2)) {
1096
+ if (v2 > v) {
1097
+ return 1;
1098
+ }
1099
+ if (v2 < v) {
1100
+ return -1;
1101
+ }
1102
+ continue;
1103
+ }
1104
+ // Not numeric, compare as string
1105
+ const comparison = ('' + v).localeCompare('' + v2);
1106
+ if (comparison !== 0) {
1107
+ return comparison;
1108
+ }
1109
+ }
1110
+ return 0;
1111
+ });
933
1112
  }
934
1113
  function c2m(data, key, modifier) {
935
- if (Array.isArray(data.groups)) {
936
- data.groups = sortChildrenByKey(data.groups.map((d) => c2m(d, key, modifier)), "weight");
937
- }
938
- const obj = { ...data, weight: data[key] };
939
- if (modifier) {
940
- return modifier(obj);
941
- }
942
- return obj;
1114
+ if (Array.isArray(data.groups)) {
1115
+ data.groups = sortChildrenByKey(data.groups.map((d)=>c2m(d, key, modifier)), 'weight');
1116
+ }
1117
+ const obj = {
1118
+ ...data,
1119
+ weight: data[key]
1120
+ };
1121
+ if (modifier) {
1122
+ return modifier(obj);
1123
+ }
1124
+ return obj;
943
1125
  }
944
1126
  function flatten(data) {
945
- const result = [];
946
- for (let i = 0; i < data.length; i++) {
947
- const { groups, ...rest } = data[i];
948
- result.push(rest);
949
- if (groups) {
950
- result.push(...flatten(groups));
1127
+ const result = [];
1128
+ for(let i = 0; i < data.length; i++){
1129
+ const { groups, ...rest } = data[i];
1130
+ result.push(rest);
1131
+ if (groups) {
1132
+ result.push(...flatten(groups));
1133
+ }
951
1134
  }
952
- }
953
- return result;
1135
+ return result;
954
1136
  }
955
1137
  function bindParentForModule(modules, parent) {
956
- return modules.map((module) => {
957
- const next = { ...module };
958
- next.parent = parent;
959
- if (next.groups && Array.isArray(next.groups)) {
960
- next.groups = bindParentForModule(next.groups, next);
961
- }
962
- return next;
963
- });
1138
+ return modules.map((module)=>{
1139
+ const next = {
1140
+ ...module
1141
+ };
1142
+ next.parent = parent;
1143
+ if (next.groups && Array.isArray(next.groups)) {
1144
+ next.groups = bindParentForModule(next.groups, next);
1145
+ }
1146
+ return next;
1147
+ });
964
1148
  }
965
1149
  function getNodeDepth(node) {
966
- let depth = 0;
967
- while (node.parent) {
968
- node = node.parent;
969
- depth++;
970
- }
971
- return depth;
1150
+ let depth = 0;
1151
+ while(node.parent){
1152
+ node = node.parent;
1153
+ depth++;
1154
+ }
1155
+ return depth;
972
1156
  }
973
1157
  function visit(data, fn) {
974
- if (!data) {
975
- return null;
976
- }
977
- for (const d of data) {
978
- if (d.children) {
979
- const result = visit(d.children, fn);
980
- if (result) {
981
- return result;
982
- }
983
- }
984
- const stop = fn(d);
985
- if (stop) {
986
- return d;
1158
+ if (!data) {
1159
+ return null;
1160
+ }
1161
+ for (const d of data){
1162
+ if (d.children) {
1163
+ const result = visit(d.children, fn);
1164
+ if (result) {
1165
+ return result;
1166
+ }
1167
+ }
1168
+ const stop = fn(d);
1169
+ if (stop) {
1170
+ return d;
1171
+ }
987
1172
  }
988
- }
989
- return null;
1173
+ return null;
990
1174
  }
991
1175
  function findRelativeNode(p, layoutNodes) {
992
- return visit(layoutNodes, (node) => {
993
- const [x, y, w, h] = node.layout;
994
- if (p.x >= x && p.y >= y && p.x < x + w && p.y < y + h) {
995
- return true;
996
- }
997
- });
1176
+ return visit(layoutNodes, (node)=>{
1177
+ const [x, y, w, h] = node.layout;
1178
+ if (p.x >= x && p.y >= y && p.x < x + w && p.y < y + h) {
1179
+ return true;
1180
+ }
1181
+ });
998
1182
  }
999
1183
  function findRelativeNodeById(id, layoutNodes) {
1000
- return visit(layoutNodes, (node) => {
1001
- if (node.node.id === id) {
1002
- return true;
1003
- }
1004
- });
1184
+ return visit(layoutNodes, (node)=>{
1185
+ if (node.node.id === id) {
1186
+ return true;
1187
+ }
1188
+ });
1005
1189
  }
1006
1190
 
1007
- var __defProp$1 = Object.defineProperty;
1008
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1009
- var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1191
+ // Because of the cache system. scale factor is not needed to apply.
1192
+ // Eg. Only use scale factor when the layout is changed.
1010
1193
  function createTreemapEventState() {
1011
- return {
1012
- isDragging: false,
1013
- isWheeling: false,
1014
- isZooming: false,
1015
- currentNode: null,
1016
- forceDestroy: false,
1017
- dragX: 0,
1018
- dragY: 0
1019
- };
1194
+ return {
1195
+ isDragging: false,
1196
+ isWheeling: false,
1197
+ isZooming: false,
1198
+ currentNode: null,
1199
+ forceDestroy: false,
1200
+ dragX: 0,
1201
+ dragY: 0
1202
+ };
1020
1203
  }
1021
1204
  const INTERNAL_EVENT_MAPPINGS = {
1022
- ON_ZOOM: 1,
1023
- ON_CLEANUP: 3
1205
+ ON_ZOOM: 0o1,
1206
+ ON_CLEANUP: 0o3
1024
1207
  };
1025
1208
  const ANIMATION_DURATION = 300;
1026
- const fill = { desc: { r: 255, g: 255, b: 255 }, mode: "rgb" };
1209
+ const fill = {
1210
+ desc: {
1211
+ r: 255,
1212
+ g: 255,
1213
+ b: 255
1214
+ },
1215
+ mode: 'rgb'
1216
+ };
1027
1217
  function smoothFrame(callback, opts) {
1028
- const frame = createSmoothFrame();
1029
- const startTime = Date.now();
1030
- const condtion = (process) => {
1031
- if (Array.isArray(opts.deps)) {
1032
- return opts.deps.some((dep) => dep());
1033
- }
1034
- return process >= 1;
1035
- };
1036
- frame.run(() => {
1037
- const elapsed = Date.now() - startTime;
1038
- const progress = Math.min(elapsed / opts.duration, 1);
1039
- if (condtion(progress)) {
1040
- frame.stop();
1041
- if (opts.onStop) {
1042
- opts.onStop();
1043
- }
1044
- return true;
1045
- }
1046
- return callback(progress, frame.stop);
1047
- });
1218
+ const frame = createSmoothFrame();
1219
+ const startTime = Date.now();
1220
+ const condtion = (process)=>{
1221
+ if (Array.isArray(opts.deps)) {
1222
+ return opts.deps.some((dep)=>dep());
1223
+ }
1224
+ return process >= 1;
1225
+ };
1226
+ frame.run(()=>{
1227
+ const elapsed = Date.now() - startTime;
1228
+ const progress = Math.min(elapsed / opts.duration, 1);
1229
+ if (condtion(progress)) {
1230
+ frame.stop();
1231
+ if (opts.onStop) {
1232
+ opts.onStop();
1233
+ }
1234
+ return true;
1235
+ }
1236
+ return callback(progress, frame.stop);
1237
+ });
1048
1238
  }
1049
1239
  const HIGH_LIGHT_OPACITY = 0.3;
1050
1240
  function drawHighlight(treemap, evt) {
1051
- const { highlight } = treemap;
1052
- const { currentNode } = evt.state;
1053
- if (currentNode) {
1054
- const [x, y, w, h] = currentNode.layout;
1055
- smoothFrame((_, cleanup) => {
1056
- cleanup();
1057
- highlight.reset();
1058
- const mask = createRoundBlock(x, y, w, h, { fill, opacity: HIGH_LIGHT_OPACITY, radius: 4, padding: 2 });
1059
- highlight.add(mask);
1060
- highlight.setZIndexForHighlight("1");
1061
- stackMatrixTransform(mask, evt.matrix.e, evt.matrix.f, 1);
1062
- highlight.update();
1063
- if (!evt.state.currentNode) {
1064
- return true;
1065
- }
1066
- }, {
1067
- duration: ANIMATION_DURATION,
1068
- deps: [() => evt.state.isDragging, () => evt.state.isWheeling, () => evt.state.isZooming]
1069
- });
1070
- } else {
1071
- highlight.reset();
1072
- highlight.setZIndexForHighlight();
1073
- }
1241
+ const { highlight } = treemap;
1242
+ const { currentNode } = evt.state;
1243
+ if (currentNode) {
1244
+ const [x, y, w, h] = currentNode.layout;
1245
+ smoothFrame((_, cleanup)=>{
1246
+ cleanup();
1247
+ highlight.reset();
1248
+ const mask = createRoundBlock(x, y, w, h, {
1249
+ fill,
1250
+ opacity: HIGH_LIGHT_OPACITY,
1251
+ radius: 4,
1252
+ padding: 2
1253
+ });
1254
+ highlight.add(mask);
1255
+ highlight.setZIndexForHighlight('1');
1256
+ stackMatrixTransform(mask, evt.matrix.e, evt.matrix.f, 1);
1257
+ highlight.update();
1258
+ if (!evt.state.currentNode) {
1259
+ return true;
1260
+ }
1261
+ }, {
1262
+ duration: ANIMATION_DURATION,
1263
+ deps: [
1264
+ ()=>evt.state.isDragging,
1265
+ ()=>evt.state.isWheeling,
1266
+ ()=>evt.state.isZooming
1267
+ ]
1268
+ });
1269
+ } else {
1270
+ highlight.reset();
1271
+ highlight.setZIndexForHighlight();
1272
+ }
1074
1273
  }
1274
+ // TODO: Do we need turn off internal events?
1075
1275
  class TreemapEvent extends DOMEvent {
1076
- constructor(app, treemap) {
1077
- super(treemap.render.canvas);
1078
- __publicField$1(this, "exposedEvent");
1079
- __publicField$1(this, "state");
1080
- __publicField$1(this, "zoom");
1081
- this.exposedEvent = new Event();
1082
- this.state = createTreemapEventState();
1083
- const exposedMethods = [
1084
- { name: "on", fn: () => this.exposedEvent.bindWithContext(treemap.api) },
1085
- { name: "off", fn: () => this.exposedEvent.off.bind(this.exposedEvent) }
1086
- ];
1087
- DOM_EVENTS.forEach((evt) => {
1088
- this.on(evt, (metadata) => {
1089
- this.dispatch({ type: evt, treemap }, metadata);
1090
- });
1091
- });
1092
- mixin(app, exposedMethods);
1093
- treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP, () => {
1094
- this.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
1095
- this.state = createTreemapEventState();
1096
- });
1097
- this.zoom = createOnZoom(treemap, this);
1098
- treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, this.zoom);
1099
- }
1100
- dispatch(ctx, metadata) {
1101
- const node = findRelativeNode(metadata.loc, ctx.treemap.layoutNodes);
1102
- const fn = prettyStrJoin("on", ctx.type);
1103
- if (typeof this[fn] === "function") {
1104
- this[fn](ctx, metadata, node);
1105
- }
1106
- if (ctx.type === "mousemove") {
1107
- if (this.state.isDragging) {
1108
- this.exposedEvent.silent("click");
1109
- } else {
1110
- this.exposedEvent.active("click");
1111
- }
1112
- }
1113
- this.exposedEvent.emit(ctx.type === "macOSWheel" ? "wheel" : ctx.type, { native: metadata.native, module: node });
1114
- }
1115
- onmousemove(ctx, metadata, node) {
1116
- if (!this.state.isDragging) {
1117
- if (this.state.currentNode !== node || !node) {
1118
- this.state.currentNode = node;
1119
- }
1120
- drawHighlight(ctx.treemap, this);
1121
- } else {
1122
- const { treemap } = ctx;
1123
- smoothFrame((_, cleanup) => {
1124
- cleanup();
1125
- const { offsetX: x, offsetY: y } = metadata.native;
1126
- const { dragX: lastX, dragY: lastY } = this.state;
1127
- const drawX = x - lastX;
1128
- const drawY = y - lastY;
1276
+ exposedEvent;
1277
+ state;
1278
+ zoom;
1279
+ constructor(app, treemap){
1280
+ super(treemap.render.canvas);
1281
+ this.exposedEvent = new Event();
1282
+ this.state = createTreemapEventState();
1283
+ const exposedMethods = [
1284
+ {
1285
+ name: 'on',
1286
+ fn: ()=>this.exposedEvent.bindWithContext(treemap.api)
1287
+ },
1288
+ {
1289
+ name: 'off',
1290
+ fn: ()=>this.exposedEvent.off.bind(this.exposedEvent)
1291
+ }
1292
+ ];
1293
+ DOM_EVENTS.forEach((evt)=>{
1294
+ this.on(evt, (metadata)=>{
1295
+ // if (evt === 'wheel' && macOS) {
1296
+ // this.dispatch({ type: 'macOSWheel', treemap }, metadata)
1297
+ // return
1298
+ // }
1299
+ this.dispatch({
1300
+ type: evt,
1301
+ treemap
1302
+ }, metadata);
1303
+ });
1304
+ });
1305
+ mixin(app, exposedMethods);
1306
+ treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP, ()=>{
1307
+ this.matrix.create({
1308
+ a: 1,
1309
+ b: 0,
1310
+ c: 0,
1311
+ d: 1,
1312
+ e: 0,
1313
+ f: 0
1314
+ });
1315
+ this.state = createTreemapEventState();
1316
+ });
1317
+ this.zoom = createOnZoom(treemap, this);
1318
+ treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, this.zoom);
1319
+ }
1320
+ dispatch(ctx, metadata) {
1321
+ const node = findRelativeNode(metadata.loc, ctx.treemap.layoutNodes);
1322
+ const fn = prettyStrJoin('on', ctx.type);
1323
+ // @ts-expect-error safe
1324
+ if (typeof this[fn] === 'function') {
1325
+ // @ts-expect-error safe
1326
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
1327
+ this[fn](ctx, metadata, node);
1328
+ }
1329
+ // note: onmouseup event will trigger click event together
1330
+ if (ctx.type === 'mousemove') {
1331
+ if (this.state.isDragging) {
1332
+ this.exposedEvent.silent('click');
1333
+ } else {
1334
+ this.exposedEvent.active('click');
1335
+ }
1336
+ }
1337
+ // For macOS
1338
+ this.exposedEvent.emit(ctx.type === 'macOSWheel' ? 'wheel' : ctx.type, {
1339
+ native: metadata.native,
1340
+ module: node
1341
+ });
1342
+ }
1343
+ onmousemove(ctx, metadata, node) {
1344
+ if (!this.state.isDragging) {
1345
+ if (this.state.currentNode !== node || !node) {
1346
+ this.state.currentNode = node;
1347
+ }
1348
+ drawHighlight(ctx.treemap, this);
1349
+ } else {
1350
+ // for drag
1351
+ const { treemap } = ctx;
1352
+ smoothFrame((_, cleanup)=>{
1353
+ cleanup();
1354
+ const { offsetX: x, offsetY: y } = metadata.native;
1355
+ const { dragX: lastX, dragY: lastY } = this.state;
1356
+ const drawX = x - lastX;
1357
+ const drawY = y - lastY;
1358
+ treemap.highlight.reset();
1359
+ treemap.highlight.setZIndexForHighlight();
1360
+ treemap.reset();
1361
+ this.matrix.translation(drawX, drawY);
1362
+ Object.assign(this.state, {
1363
+ isDragging: true,
1364
+ dragX: x,
1365
+ dragY: y
1366
+ });
1367
+ stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
1368
+ treemap.update();
1369
+ return true;
1370
+ }, {
1371
+ duration: ANIMATION_DURATION,
1372
+ deps: [
1373
+ ()=>this.state.forceDestroy
1374
+ ],
1375
+ onStop: ()=>{
1376
+ this.state.isDragging = false;
1377
+ }
1378
+ });
1379
+ }
1380
+ }
1381
+ onmouseout(ctx) {
1382
+ this.state.currentNode = null;
1383
+ drawHighlight(ctx.treemap, this);
1384
+ }
1385
+ onmousedown(ctx, metadata) {
1386
+ if (isScrollWheelOrRightButtonOnMouseupAndDown(metadata.native)) {
1387
+ return;
1388
+ }
1389
+ this.state.isDragging = true;
1390
+ this.state.dragX = metadata.native.offsetX;
1391
+ this.state.dragY = metadata.native.offsetY;
1392
+ this.state.forceDestroy = false;
1393
+ if (!ctx.treemap.renderCache.state) {
1394
+ this.exposedEvent.silent('mousemove');
1395
+ this.silent('mousemove');
1396
+ ctx.treemap.renderCache.flush(ctx.treemap, this.matrix);
1397
+ this.active('mousemove');
1398
+ this.exposedEvent.active('mousemove');
1399
+ }
1400
+ }
1401
+ onmouseup(ctx) {
1402
+ if (!this.state.isDragging) {
1403
+ return;
1404
+ }
1405
+ this.state.forceDestroy = true;
1406
+ this.state.isDragging = false;
1407
+ const { treemap } = ctx;
1129
1408
  treemap.highlight.reset();
1130
1409
  treemap.highlight.setZIndexForHighlight();
1131
- treemap.reset();
1132
- this.matrix.translation(drawX, drawY);
1133
- Object.assign(this.state, { isDragging: true, dragX: x, dragY: y });
1134
- stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
1135
- treemap.update();
1136
- return true;
1137
- }, {
1138
- duration: ANIMATION_DURATION,
1139
- deps: [() => this.state.forceDestroy],
1140
- onStop: () => {
1141
- this.state.isDragging = false;
1142
- }
1143
- });
1144
- }
1145
- }
1146
- onmouseout(ctx) {
1147
- this.state.currentNode = null;
1148
- drawHighlight(ctx.treemap, this);
1149
- }
1150
- onmousedown(ctx, metadata) {
1151
- if (isScrollWheelOrRightButtonOnMouseupAndDown(metadata.native)) {
1152
- return;
1153
- }
1154
- this.state.isDragging = true;
1155
- this.state.dragX = metadata.native.offsetX;
1156
- this.state.dragY = metadata.native.offsetY;
1157
- this.state.forceDestroy = false;
1158
- if (!ctx.treemap.renderCache.state) {
1159
- this.exposedEvent.silent("mousemove");
1160
- this.silent("mousemove");
1161
- ctx.treemap.renderCache.flush(ctx.treemap, this.matrix);
1162
- this.active("mousemove");
1163
- this.exposedEvent.active("mousemove");
1164
- }
1165
- }
1166
- onmouseup(ctx) {
1167
- if (!this.state.isDragging) {
1168
- return;
1169
- }
1170
- this.state.forceDestroy = true;
1171
- this.state.isDragging = false;
1172
- const { treemap } = ctx;
1173
- treemap.highlight.reset();
1174
- treemap.highlight.setZIndexForHighlight();
1175
- }
1176
- onwheel(ctx, metadata) {
1177
- ctx.treemap.renderCache.destroy();
1178
- ctx.treemap.event.silent(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
1179
- const { native } = metadata;
1180
- const { treemap } = ctx;
1181
- const wheelDelta = native.wheelDelta;
1182
- const absWheelDelta = Math.abs(wheelDelta);
1183
- const offsetX = native.offsetX;
1184
- const offsetY = native.offsetY;
1185
- if (wheelDelta === 0) {
1186
- return;
1187
- }
1188
- this.state.forceDestroy = true;
1189
- const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
1190
- const delta = wheelDelta > 0 ? factor : 1 / factor;
1191
- const targetScaleRatio = this.matrix.a * delta;
1192
- const translateX = offsetX - (offsetX - this.matrix.e) * delta;
1193
- const translateY = offsetY - (offsetY - this.matrix.f) * delta;
1194
- smoothFrame((progress, cleanup) => {
1195
- this.exposedEvent.silent("mousemove");
1196
- this.silent("mousemove");
1197
- this.silent("click");
1198
- this.exposedEvent.silent("click");
1199
- treemap.highlight.reset();
1200
- treemap.highlight.setZIndexForHighlight();
1201
- treemap.fontCache.flush(treemap, this.matrix);
1202
- this.state.isWheeling = true;
1203
- const easedProgress = easing.cubicInOut(progress);
1204
- const scale = (targetScaleRatio - this.matrix.a) * easedProgress;
1205
- this.matrix.a += scale;
1206
- this.matrix.d += scale;
1207
- this.matrix.translation((translateX - this.matrix.e) * easedProgress, (translateY - this.matrix.f) * easedProgress);
1208
- resetLayout(
1209
- treemap,
1210
- treemap.render.canvas.width * this.matrix.a / treemap.render.options.devicePixelRatio,
1211
- treemap.render.canvas.height * this.matrix.d / treemap.render.options.devicePixelRatio
1212
- );
1213
- stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
1214
- treemap.update();
1215
- cleanup();
1216
- }, {
1217
- duration: ANIMATION_DURATION,
1218
- onStop: () => {
1219
- this.state.forceDestroy = false;
1220
- this.state.isWheeling = false;
1221
- this.active("mousemove");
1222
- this.exposedEvent.active("mousemove");
1223
- this.active("click");
1224
- this.exposedEvent.active("click");
1225
- treemap.event.active(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
1226
- }
1227
- });
1228
- }
1229
- onmacOSWheel(ctx, metadata) {
1230
- useMagicTrackPad(metadata.native);
1231
- }
1410
+ }
1411
+ onwheel(ctx, metadata) {
1412
+ ctx.treemap.renderCache.destroy();
1413
+ ctx.treemap.event.silent(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
1414
+ const { native } = metadata;
1415
+ const { treemap } = ctx;
1416
+ // @ts-expect-error safe
1417
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1418
+ const wheelDelta = native.wheelDelta;
1419
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
1420
+ const absWheelDelta = Math.abs(wheelDelta);
1421
+ const offsetX = native.offsetX;
1422
+ const offsetY = native.offsetY;
1423
+ if (wheelDelta === 0) {
1424
+ return;
1425
+ }
1426
+ this.state.forceDestroy = true;
1427
+ const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
1428
+ const delta = wheelDelta > 0 ? factor : 1 / factor;
1429
+ const targetScaleRatio = this.matrix.a * delta;
1430
+ const translateX = offsetX - (offsetX - this.matrix.e) * delta;
1431
+ const translateY = offsetY - (offsetY - this.matrix.f) * delta;
1432
+ smoothFrame((progress, cleanup)=>{
1433
+ this.exposedEvent.silent('mousemove');
1434
+ this.silent('mousemove');
1435
+ this.silent('click');
1436
+ this.exposedEvent.silent('click');
1437
+ treemap.highlight.reset();
1438
+ treemap.highlight.setZIndexForHighlight();
1439
+ treemap.fontCache.flush(treemap, this.matrix);
1440
+ this.state.isWheeling = true;
1441
+ const easedProgress = easing.cubicInOut(progress);
1442
+ const scale = (targetScaleRatio - this.matrix.a) * easedProgress;
1443
+ this.matrix.a += scale;
1444
+ this.matrix.d += scale;
1445
+ this.matrix.translation((translateX - this.matrix.e) * easedProgress, (translateY - this.matrix.f) * easedProgress);
1446
+ // Each shape will scale by schedule phase. (According the dpi)
1447
+ // So that if the DPI is more than 1. we need to shrink first. ( w / dpi , h / dpi )
1448
+ // Schedule will scale it back to the original size.
1449
+ resetLayout(treemap, treemap.render.canvas.width * this.matrix.a / treemap.render.options.devicePixelRatio, treemap.render.canvas.height * this.matrix.d / treemap.render.options.devicePixelRatio);
1450
+ stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
1451
+ treemap.update();
1452
+ cleanup();
1453
+ }, {
1454
+ duration: ANIMATION_DURATION,
1455
+ onStop: ()=>{
1456
+ this.state.forceDestroy = false;
1457
+ this.state.isWheeling = false;
1458
+ // this.active('mousedown')
1459
+ this.active('mousemove');
1460
+ this.exposedEvent.active('mousemove');
1461
+ this.active('click');
1462
+ this.exposedEvent.active('click');
1463
+ treemap.event.active(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
1464
+ }
1465
+ });
1466
+ }
1467
+ onmacOSWheel(ctx, metadata) {
1468
+ useMagicTrackPad(metadata.native);
1469
+ }
1232
1470
  }
1233
1471
  function stackMatrixTransform(graph, e, f, scale) {
1234
- graph.x = graph.x * scale + e;
1235
- graph.y = graph.y * scale + f;
1236
- graph.scaleX = scale;
1237
- graph.scaleY = scale;
1472
+ graph.x = graph.x * scale + e;
1473
+ graph.y = graph.y * scale + f;
1474
+ graph.scaleX = scale;
1475
+ graph.scaleY = scale;
1238
1476
  }
1239
1477
  function stackMatrixTransformWithGraphAndLayer(graphs, e, f, scale) {
1240
- traverse(graphs, (graph) => stackMatrixTransform(graph, e, f, scale));
1478
+ traverse(graphs, (graph)=>stackMatrixTransform(graph, e, f, scale));
1241
1479
  }
1480
+ // Only works for mouseup and mousedown events
1242
1481
  function isScrollWheelOrRightButtonOnMouseupAndDown(e) {
1243
- return e.which === 2 || e.which === 3;
1482
+ return e.which === 2 || e.which === 3;
1244
1483
  }
1245
1484
  function createOnZoom(treemap, evt) {
1246
- return (node) => {
1247
- treemap.renderCache.destroy();
1248
- evt.state.isZooming = true;
1249
- const c = treemap.render.canvas;
1250
- const boundingClientRect = c.getBoundingClientRect();
1251
- if (node) {
1252
- const [mx, my, mw, mh] = node.layout;
1253
- const factor = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
1254
- const targetScale = factor * evt.matrix.a;
1255
- const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * factor;
1256
- const translateY = boundingClientRect.height / 2 - (my + mh / 2) * factor;
1257
- smoothFrame((progress, cleanup) => {
1258
- cleanup();
1259
- evt.silent("mousemove");
1260
- evt.exposedEvent.silent("mousemove");
1261
- treemap.fontCache.flush(treemap, evt.matrix);
1262
- const easedProgress = easing.cubicInOut(progress);
1263
- const scale = (targetScale - evt.matrix.a) * easedProgress;
1264
- evt.matrix.a += scale;
1265
- evt.matrix.d += scale;
1266
- evt.matrix.translation((translateX - evt.matrix.e) * easedProgress, (translateY - evt.matrix.f) * easedProgress);
1267
- resetLayout(
1268
- treemap,
1269
- treemap.render.canvas.width * evt.matrix.a / treemap.render.options.devicePixelRatio,
1270
- treemap.render.canvas.height * evt.matrix.d / treemap.render.options.devicePixelRatio
1271
- );
1272
- stackMatrixTransformWithGraphAndLayer(treemap.elements, evt.matrix.e, evt.matrix.f, 1);
1273
- treemap.update();
1274
- }, {
1275
- duration: ANIMATION_DURATION,
1276
- onStop: () => {
1277
- evt.state.isZooming = false;
1278
- evt.active("mousemove");
1279
- evt.exposedEvent.active("mousemove");
1485
+ return (node)=>{
1486
+ treemap.renderCache.destroy();
1487
+ evt.state.isZooming = true;
1488
+ const c = treemap.render.canvas;
1489
+ const boundingClientRect = c.getBoundingClientRect();
1490
+ if (node) {
1491
+ const [mx, my, mw, mh] = node.layout;
1492
+ const factor = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
1493
+ const targetScale = factor * evt.matrix.a;
1494
+ const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * factor;
1495
+ const translateY = boundingClientRect.height / 2 - (my + mh / 2) * factor;
1496
+ smoothFrame((progress, cleanup)=>{
1497
+ cleanup();
1498
+ evt.silent('mousemove');
1499
+ evt.exposedEvent.silent('mousemove');
1500
+ treemap.fontCache.flush(treemap, evt.matrix);
1501
+ const easedProgress = easing.cubicInOut(progress);
1502
+ const scale = (targetScale - evt.matrix.a) * easedProgress;
1503
+ evt.matrix.a += scale;
1504
+ evt.matrix.d += scale;
1505
+ evt.matrix.translation((translateX - evt.matrix.e) * easedProgress, (translateY - evt.matrix.f) * easedProgress);
1506
+ resetLayout(treemap, treemap.render.canvas.width * evt.matrix.a / treemap.render.options.devicePixelRatio, treemap.render.canvas.height * evt.matrix.d / treemap.render.options.devicePixelRatio);
1507
+ stackMatrixTransformWithGraphAndLayer(treemap.elements, evt.matrix.e, evt.matrix.f, 1);
1508
+ treemap.update();
1509
+ }, {
1510
+ duration: ANIMATION_DURATION,
1511
+ onStop: ()=>{
1512
+ evt.state.isZooming = false;
1513
+ evt.active('mousemove');
1514
+ evt.exposedEvent.active('mousemove');
1515
+ }
1516
+ });
1280
1517
  }
1281
- });
1282
- }
1283
- };
1518
+ };
1284
1519
  }
1285
1520
 
1286
1521
  function register(Mod) {
1287
- return (app, treemap) => {
1288
- new Mod(app, treemap);
1289
- };
1522
+ return (app, treemap)=>{
1523
+ new Mod(app, treemap);
1524
+ };
1290
1525
  }
1291
1526
 
1292
1527
  function squarify(data, rect, layoutDecorator) {
1293
- const result = [];
1294
- if (!data.length) {
1528
+ const result = [];
1529
+ if (!data.length) {
1530
+ return result;
1531
+ }
1532
+ const worst = (start, end, shortestSide, totalWeight, aspectRatio)=>{
1533
+ const max = data[start].weight * aspectRatio;
1534
+ const min = data[end].weight * aspectRatio;
1535
+ return Math.max(shortestSide * shortestSide * max / (totalWeight * totalWeight), totalWeight * totalWeight / (shortestSide * shortestSide * min));
1536
+ };
1537
+ const recursion = (start, rect)=>{
1538
+ while(start < data.length){
1539
+ let totalWeight = 0;
1540
+ for(let i = start; i < data.length; i++){
1541
+ totalWeight += data[i].weight;
1542
+ }
1543
+ const shortestSide = Math.min(rect.w, rect.h);
1544
+ const aspectRatio = rect.w * rect.h / totalWeight;
1545
+ let end = start;
1546
+ let areaInRun = 0;
1547
+ let oldWorst = 0;
1548
+ // find the best split
1549
+ while(end < data.length){
1550
+ const area = data[end].weight * aspectRatio;
1551
+ const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
1552
+ if (end > start && oldWorst < newWorst) {
1553
+ break;
1554
+ }
1555
+ areaInRun += area;
1556
+ oldWorst = newWorst;
1557
+ end++;
1558
+ }
1559
+ const splited = Math.round(areaInRun / shortestSide);
1560
+ let areaInLayout = 0;
1561
+ for(let i = start; i < end; i++){
1562
+ const children = data[i];
1563
+ const area = children.weight * aspectRatio;
1564
+ const lower = Math.round(shortestSide * areaInLayout / areaInRun);
1565
+ const upper = Math.round(shortestSide * (areaInLayout + area) / areaInRun);
1566
+ const [x, y, w, h] = rect.w >= rect.h ? [
1567
+ rect.x,
1568
+ rect.y + lower,
1569
+ splited,
1570
+ upper - lower
1571
+ ] : [
1572
+ rect.x + lower,
1573
+ rect.y,
1574
+ upper - lower,
1575
+ splited
1576
+ ];
1577
+ const depth = getNodeDepth(children) || 1;
1578
+ const { titleAreaHeight, rectGap } = layoutDecorator;
1579
+ const diff = titleAreaHeight.max / depth;
1580
+ const hh = diff < titleAreaHeight.min ? titleAreaHeight.min : diff;
1581
+ result.push({
1582
+ layout: [
1583
+ x,
1584
+ y,
1585
+ w,
1586
+ h
1587
+ ],
1588
+ node: children,
1589
+ decorator: {
1590
+ ...layoutDecorator,
1591
+ titleHeight: hh
1592
+ },
1593
+ children: w > rectGap * 2 && h > hh + rectGap ? squarify(children.groups || [], {
1594
+ x: x + rectGap,
1595
+ y: y + hh,
1596
+ w: w - rectGap * 2,
1597
+ h: h - hh - rectGap
1598
+ }, layoutDecorator) : []
1599
+ });
1600
+ areaInLayout += area;
1601
+ }
1602
+ start = end;
1603
+ if (rect.w >= rect.h) {
1604
+ rect.x += splited;
1605
+ rect.w -= splited;
1606
+ } else {
1607
+ rect.y += splited;
1608
+ rect.h -= splited;
1609
+ }
1610
+ }
1611
+ };
1612
+ recursion(0, rect);
1295
1613
  return result;
1296
- }
1297
- const worst = (start, end, shortestSide, totalWeight, aspectRatio) => {
1298
- const max = data[start].weight * aspectRatio;
1299
- const min = data[end].weight * aspectRatio;
1300
- return Math.max(
1301
- shortestSide * shortestSide * max / (totalWeight * totalWeight),
1302
- totalWeight * totalWeight / (shortestSide * shortestSide * min)
1303
- );
1304
- };
1305
- const recursion = (start, rect2) => {
1306
- while (start < data.length) {
1307
- let totalWeight = 0;
1308
- for (let i = start; i < data.length; i++) {
1309
- totalWeight += data[i].weight;
1310
- }
1311
- const shortestSide = Math.min(rect2.w, rect2.h);
1312
- const aspectRatio = rect2.w * rect2.h / totalWeight;
1313
- let end = start;
1314
- let areaInRun = 0;
1315
- let oldWorst = 0;
1316
- while (end < data.length) {
1317
- const area = data[end].weight * aspectRatio;
1318
- const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
1319
- if (end > start && oldWorst < newWorst) {
1320
- break;
1321
- }
1322
- areaInRun += area;
1323
- oldWorst = newWorst;
1324
- end++;
1325
- }
1326
- const splited = Math.round(areaInRun / shortestSide);
1327
- let areaInLayout = 0;
1328
- for (let i = start; i < end; i++) {
1329
- const children = data[i];
1330
- const area = children.weight * aspectRatio;
1331
- const lower = Math.round(shortestSide * areaInLayout / areaInRun);
1332
- const upper = Math.round(shortestSide * (areaInLayout + area) / areaInRun);
1333
- const [x, y, w, h] = rect2.w >= rect2.h ? [rect2.x, rect2.y + lower, splited, upper - lower] : [rect2.x + lower, rect2.y, upper - lower, splited];
1334
- const depth = getNodeDepth(children) || 1;
1335
- const { titleAreaHeight, rectGap } = layoutDecorator;
1336
- const diff = titleAreaHeight.max / depth;
1337
- const hh = diff < titleAreaHeight.min ? titleAreaHeight.min : diff;
1338
- result.push({
1339
- layout: [x, y, w, h],
1340
- node: children,
1341
- decorator: {
1342
- ...layoutDecorator,
1343
- titleHeight: hh
1344
- },
1345
- children: w > rectGap * 2 && h > hh + rectGap ? squarify(children.groups || [], {
1346
- x: x + rectGap,
1347
- y: y + hh,
1348
- w: w - rectGap * 2,
1349
- h: h - hh - rectGap
1350
- }, layoutDecorator) : []
1351
- });
1352
- areaInLayout += area;
1353
- }
1354
- start = end;
1355
- if (rect2.w >= rect2.h) {
1356
- rect2.x += splited;
1357
- rect2.w -= splited;
1358
- } else {
1359
- rect2.y += splited;
1360
- rect2.h -= splited;
1361
- }
1362
- }
1363
- };
1364
- recursion(0, rect);
1365
- return result;
1366
1614
  }
1367
1615
 
1368
- var __defProp = Object.defineProperty;
1369
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1370
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1371
1616
  function measureTextWidth(c, text) {
1372
- return c.measureText(text).width;
1617
+ return c.measureText(text).width;
1373
1618
  }
1374
1619
  function evaluateOptimalFontSize(c, text, font, desiredW, desiredH) {
1375
- desiredW = Math.floor(desiredW);
1376
- desiredH = Math.floor(desiredH);
1377
- const { range, family } = font;
1378
- let min = range.min;
1379
- let max = range.max;
1380
- const cache = /* @__PURE__ */ new Map();
1381
- while (max - min >= 1) {
1382
- const current = min + (max - min) / 2;
1383
- if (!cache.has(current)) {
1384
- c.font = `${current}px ${family}`;
1385
- const metrics = c.measureText(text);
1386
- const width2 = metrics.width;
1387
- const height2 = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
1388
- cache.set(current, { width: width2, height: height2 });
1389
- }
1390
- const { width, height } = cache.get(current);
1391
- if (width > desiredW || height > desiredH) {
1392
- max = current;
1393
- } else {
1394
- min = current;
1620
+ desiredW = Math.floor(desiredW);
1621
+ desiredH = Math.floor(desiredH);
1622
+ const { range, family } = font;
1623
+ let min = range.min;
1624
+ let max = range.max;
1625
+ const cache = new Map();
1626
+ while(max - min >= 1){
1627
+ const current = min + (max - min) / 2;
1628
+ if (!cache.has(current)) {
1629
+ c.font = `${current}px ${family}`;
1630
+ const metrics = c.measureText(text);
1631
+ const width = metrics.width;
1632
+ const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
1633
+ cache.set(current, {
1634
+ width,
1635
+ height
1636
+ });
1637
+ }
1638
+ const { width, height } = cache.get(current);
1639
+ if (width > desiredW || height > desiredH) {
1640
+ max = current;
1641
+ } else {
1642
+ min = current;
1643
+ }
1395
1644
  }
1396
- }
1397
- return Math.floor(min);
1645
+ return Math.floor(min);
1398
1646
  }
1399
1647
  function getSafeText(c, text, width, cache) {
1400
- let ellipsisWidth = 0;
1401
- if (text in cache) {
1402
- ellipsisWidth = cache[text];
1403
- } else {
1404
- ellipsisWidth = measureTextWidth(c, "...");
1405
- cache[text] = ellipsisWidth;
1406
- }
1407
- if (width < ellipsisWidth) {
1408
- return false;
1409
- }
1410
- const textWidth = measureTextWidth(c, text);
1411
- if (textWidth < width) {
1412
- return { text, width: textWidth };
1413
- }
1414
- return { text: "...", width: ellipsisWidth };
1648
+ let ellipsisWidth = 0;
1649
+ if (text in cache) {
1650
+ ellipsisWidth = cache[text];
1651
+ } else {
1652
+ ellipsisWidth = measureTextWidth(c, '...');
1653
+ cache[text] = ellipsisWidth;
1654
+ }
1655
+ if (width < ellipsisWidth) {
1656
+ return false;
1657
+ }
1658
+ const textWidth = measureTextWidth(c, text);
1659
+ if (textWidth < width) {
1660
+ return {
1661
+ text,
1662
+ width: textWidth
1663
+ };
1664
+ }
1665
+ return {
1666
+ text: '...',
1667
+ width: ellipsisWidth
1668
+ };
1415
1669
  }
1416
1670
  function resetLayout(treemap, w, h) {
1417
- treemap.layoutNodes = squarify(treemap.data, { w, h, x: 0, y: 0 }, treemap.decorator.layout);
1418
- treemap.reset(true);
1671
+ treemap.layoutNodes = squarify(treemap.data, {
1672
+ w,
1673
+ h,
1674
+ x: 0,
1675
+ y: 0
1676
+ }, treemap.decorator.layout);
1677
+ treemap.reset(true);
1419
1678
  }
1420
1679
  class Highlight extends Schedule {
1421
- reset() {
1422
- this.destory();
1423
- this.update();
1424
- }
1425
- get canvas() {
1426
- return this.render.canvas;
1427
- }
1428
- setZIndexForHighlight(zIndex = "-1") {
1429
- this.canvas.style.zIndex = zIndex;
1430
- }
1431
- init() {
1432
- this.setZIndexForHighlight();
1433
- this.canvas.style.position = "absolute";
1434
- this.canvas.style.pointerEvents = "none";
1435
- }
1680
+ reset() {
1681
+ this.destory();
1682
+ this.update();
1683
+ }
1684
+ get canvas() {
1685
+ return this.render.canvas;
1686
+ }
1687
+ setZIndexForHighlight(zIndex = '-1') {
1688
+ this.canvas.style.zIndex = zIndex;
1689
+ }
1690
+ init() {
1691
+ this.setZIndexForHighlight();
1692
+ this.canvas.style.position = 'absolute';
1693
+ this.canvas.style.pointerEvents = 'none';
1694
+ }
1436
1695
  }
1437
1696
  class TreemapLayout extends Schedule {
1438
- constructor(...args) {
1439
- super(...args);
1440
- __publicField(this, "data");
1441
- __publicField(this, "layoutNodes");
1442
- __publicField(this, "decorator");
1443
- __publicField(this, "bgBox");
1444
- __publicField(this, "fgBox");
1445
- __publicField(this, "highlight");
1446
- __publicField(this, "renderCache");
1447
- __publicField(this, "fontCache");
1448
- this.data = [];
1449
- this.layoutNodes = [];
1450
- this.bgBox = new Box();
1451
- this.fgBox = new Box();
1452
- this.decorator = /* @__PURE__ */ Object.create(null);
1453
- this.highlight = new Highlight(this.to, { width: this.render.options.width, height: this.render.options.height });
1454
- this.renderCache = new RenderCache(this.render.options);
1455
- this.fontCache = new FontCache();
1456
- }
1457
- drawBackgroundNode(node) {
1458
- const [x, y, w, h] = node.layout;
1459
- const padding = 2;
1460
- if (w - padding * 2 <= 0 || h - padding * 2 <= 0) {
1461
- return;
1462
- }
1463
- const fill = this.decorator.color.mappings[node.node.id];
1464
- const rect = createRoundBlock(x, y, w, h, { fill, padding, radius: 4 });
1465
- rect.__widget__ = node;
1466
- this.bgBox.add(rect);
1467
- for (const child of node.children) {
1468
- this.drawBackgroundNode(child);
1469
- }
1470
- }
1471
- drawForegroundNode(node) {
1472
- const [x, y, w, h] = node.layout;
1473
- if (!w || !h) {
1474
- return;
1475
- }
1476
- const { titleHeight, rectGap } = node.decorator;
1477
- const { fontSize, fontFamily, color } = this.decorator.font;
1478
- const optimalFontSize = this.fontCache.queryFontById(node.node.id, () => evaluateOptimalFontSize(
1479
- this.render.ctx,
1480
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
1481
- node.node.label,
1482
- {
1483
- range: fontSize,
1484
- family: fontFamily
1485
- },
1486
- w - rectGap * 2,
1487
- node.children.length ? Math.round(titleHeight / 2) + rectGap : h
1488
- ));
1489
- this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
1490
- const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.fontCache.ellispsis);
1491
- if (!result) {
1492
- return;
1493
- }
1494
- if (result.width >= w || optimalFontSize >= h) {
1495
- return;
1496
- }
1497
- const { text, width } = result;
1498
- const textX = x + Math.round((w - width) / 2);
1499
- const textY = y + (node.children.length ? Math.round(titleHeight / 2) : Math.round(h / 2));
1500
- this.fgBox.add(createTitleText(text, textX, textY, `${optimalFontSize}px ${fontFamily}`, color));
1501
- for (const child of node.children) {
1502
- this.drawForegroundNode(child);
1503
- }
1504
- }
1505
- reset(refresh = false) {
1506
- this.remove(this.bgBox, this.fgBox);
1507
- this.bgBox.destory();
1508
- if (this.renderCache.state) {
1509
- this.fgBox.destory();
1510
- this.bgBox.add(new Bitmap({ bitmap: this.renderCache.canvas, dpi: this.render.options.devicePixelRatio }));
1511
- } else {
1512
- for (const node of this.layoutNodes) {
1513
- this.drawBackgroundNode(node);
1514
- }
1515
- if (!this.fgBox.elements.length || refresh) {
1516
- this.render.ctx.textBaseline = "middle";
1517
- this.fgBox.destory();
1518
- for (const node of this.layoutNodes) {
1519
- this.drawForegroundNode(node);
1520
- }
1521
- } else {
1522
- this.fgBox = this.fgBox.clone();
1523
- }
1524
- }
1525
- this.add(this.bgBox, this.fgBox);
1526
- }
1527
- get api() {
1528
- return {
1529
- zoom: (node) => {
1530
- if (!node) {
1531
- return;
1697
+ data;
1698
+ layoutNodes;
1699
+ decorator;
1700
+ bgBox;
1701
+ fgBox;
1702
+ highlight;
1703
+ renderCache;
1704
+ fontCache;
1705
+ constructor(...args){
1706
+ super(...args);
1707
+ this.data = [];
1708
+ this.layoutNodes = [];
1709
+ this.bgBox = new Box();
1710
+ this.fgBox = new Box();
1711
+ this.decorator = Object.create(null);
1712
+ this.highlight = new Highlight(this.to, {
1713
+ width: this.render.options.width,
1714
+ height: this.render.options.height
1715
+ });
1716
+ this.renderCache = new RenderCache(this.render.options);
1717
+ this.fontCache = new FontCache();
1718
+ }
1719
+ drawBackgroundNode(node) {
1720
+ const [x, y, w, h] = node.layout;
1721
+ const padding = 2;
1722
+ if (w - padding * 2 <= 0 || h - padding * 2 <= 0) {
1723
+ return;
1532
1724
  }
1533
- this.event.emit(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, node);
1534
- }
1535
- };
1536
- }
1725
+ const fill = this.decorator.color.mappings[node.node.id];
1726
+ const rect = createRoundBlock(x, y, w, h, {
1727
+ fill,
1728
+ padding,
1729
+ radius: 4
1730
+ });
1731
+ rect.__widget__ = node;
1732
+ this.bgBox.add(rect);
1733
+ for (const child of node.children){
1734
+ this.drawBackgroundNode(child);
1735
+ }
1736
+ }
1737
+ drawForegroundNode(node) {
1738
+ const [x, y, w, h] = node.layout;
1739
+ if (!w || !h) {
1740
+ return;
1741
+ }
1742
+ const { titleHeight, rectGap } = node.decorator;
1743
+ const { fontSize, fontFamily, color } = this.decorator.font;
1744
+ const optimalFontSize = this.fontCache.queryFontById(node.node.id, ()=>evaluateOptimalFontSize(this.render.ctx, // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
1745
+ node.node.label, {
1746
+ range: fontSize,
1747
+ family: fontFamily
1748
+ }, w - rectGap * 2, node.children.length ? Math.round(titleHeight / 2) + rectGap : h));
1749
+ this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
1750
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
1751
+ const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.fontCache.ellispsis);
1752
+ if (!result) {
1753
+ return;
1754
+ }
1755
+ if (result.width >= w || optimalFontSize >= h) {
1756
+ return;
1757
+ }
1758
+ const { text, width } = result;
1759
+ const textX = x + Math.round((w - width) / 2);
1760
+ const textY = y + (node.children.length ? Math.round(titleHeight / 2) : Math.round(h / 2));
1761
+ this.fgBox.add(createTitleText(text, textX, textY, `${optimalFontSize}px ${fontFamily}`, color));
1762
+ for (const child of node.children){
1763
+ this.drawForegroundNode(child);
1764
+ }
1765
+ }
1766
+ reset(refresh = false) {
1767
+ this.remove(this.bgBox, this.fgBox);
1768
+ this.bgBox.destory();
1769
+ if (this.renderCache.state) {
1770
+ this.fgBox.destory();
1771
+ this.bgBox.add(new Bitmap({
1772
+ bitmap: this.renderCache.canvas,
1773
+ dpi: this.render.options.devicePixelRatio
1774
+ }));
1775
+ } else {
1776
+ for (const node of this.layoutNodes){
1777
+ this.drawBackgroundNode(node);
1778
+ }
1779
+ if (!this.fgBox.elements.length || refresh) {
1780
+ this.render.ctx.textBaseline = 'middle';
1781
+ this.fgBox.destory();
1782
+ for (const node of this.layoutNodes){
1783
+ this.drawForegroundNode(node);
1784
+ }
1785
+ } else {
1786
+ this.fgBox = this.fgBox.clone();
1787
+ }
1788
+ }
1789
+ this.add(this.bgBox, this.fgBox);
1790
+ }
1791
+ get api() {
1792
+ return {
1793
+ zoom: (node)=>{
1794
+ if (!node) {
1795
+ return;
1796
+ }
1797
+ this.event.emit(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, node);
1798
+ }
1799
+ };
1800
+ }
1537
1801
  }
1538
1802
  function createTreemap() {
1539
- let treemap = null;
1540
- let root = null;
1541
- let installed = false;
1542
- const uses = [];
1543
- const context = {
1544
- init,
1545
- dispose,
1546
- setOptions,
1547
- resize,
1548
- use,
1549
- zoom
1550
- };
1551
- function init(el) {
1552
- treemap = new TreemapLayout(el);
1553
- root = el;
1554
- root.style.position = "relative";
1555
- if (!installed) {
1556
- register(TreemapEvent)(context, treemap);
1557
- installed = true;
1558
- }
1559
- }
1560
- function dispose() {
1561
- if (root && treemap) {
1562
- treemap.destory();
1563
- root.removeChild(root.firstChild);
1564
- root = null;
1565
- treemap = null;
1566
- }
1567
- }
1568
- function resize() {
1569
- if (!treemap || !root) {
1570
- return;
1571
- }
1572
- treemap.renderCache.destroy();
1573
- treemap.fontCache.destroy();
1574
- const { width, height } = root.getBoundingClientRect();
1575
- treemap.render.initOptions({ height, width, devicePixelRatio: window.devicePixelRatio });
1576
- treemap.render.canvas.style.position = "absolute";
1577
- treemap.event.emit(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP);
1578
- treemap.highlight.render.initOptions({ height, width, devicePixelRatio: window.devicePixelRatio });
1579
- treemap.highlight.reset();
1580
- treemap.highlight.init();
1581
- resetLayout(treemap, width, height);
1582
- treemap.update();
1583
- treemap.renderCache.flush(treemap, treemap.matrix);
1584
- }
1585
- function setOptions(options) {
1586
- if (!treemap) {
1587
- throw new Error(log.error("Treemap not initialized"));
1588
- }
1589
- treemap.data = bindParentForModule(options.data || []);
1590
- for (const use2 of uses) {
1591
- use2(treemap);
1592
- }
1593
- resize();
1594
- }
1595
- function use(key, register2) {
1596
- switch (key) {
1597
- case "decorator":
1598
- uses.push((treemap2) => register2(treemap2));
1599
- break;
1600
- }
1601
- }
1602
- function zoom(id) {
1603
- if (!treemap) {
1604
- throw new Error(log.error("treemap don't init."));
1605
- }
1606
- const node = findRelativeNodeById(id, treemap.layoutNodes);
1607
- if (node) {
1608
- treemap.api.zoom(node);
1609
- }
1610
- }
1611
- return context;
1803
+ let treemap = null;
1804
+ let root = null;
1805
+ let installed = false;
1806
+ const uses = [];
1807
+ const context = {
1808
+ init,
1809
+ dispose,
1810
+ setOptions,
1811
+ resize,
1812
+ use,
1813
+ zoom
1814
+ };
1815
+ function init(el) {
1816
+ treemap = new TreemapLayout(el);
1817
+ root = el;
1818
+ root.style.position = 'relative';
1819
+ if (!installed) {
1820
+ register(TreemapEvent)(context, treemap);
1821
+ installed = true;
1822
+ }
1823
+ }
1824
+ function dispose() {
1825
+ if (root && treemap) {
1826
+ treemap.destory();
1827
+ root.removeChild(root.firstChild);
1828
+ root = null;
1829
+ treemap = null;
1830
+ }
1831
+ }
1832
+ function resize() {
1833
+ if (!treemap || !root) {
1834
+ return;
1835
+ }
1836
+ treemap.renderCache.destroy();
1837
+ treemap.fontCache.destroy();
1838
+ const { width, height } = root.getBoundingClientRect();
1839
+ treemap.render.initOptions({
1840
+ height,
1841
+ width,
1842
+ devicePixelRatio: window.devicePixelRatio
1843
+ });
1844
+ treemap.render.canvas.style.position = 'absolute';
1845
+ treemap.event.emit(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP);
1846
+ treemap.highlight.render.initOptions({
1847
+ height,
1848
+ width,
1849
+ devicePixelRatio: window.devicePixelRatio
1850
+ });
1851
+ treemap.highlight.reset();
1852
+ treemap.highlight.init();
1853
+ resetLayout(treemap, width, height);
1854
+ treemap.update();
1855
+ treemap.renderCache.flush(treemap, treemap.matrix);
1856
+ }
1857
+ function setOptions(options) {
1858
+ if (!treemap) {
1859
+ throw new Error(log.error('Treemap not initialized'));
1860
+ }
1861
+ treemap.data = bindParentForModule(options.data || []);
1862
+ for (const use of uses){
1863
+ use(treemap);
1864
+ }
1865
+ resize();
1866
+ }
1867
+ function use(key, register) {
1868
+ switch(key){
1869
+ case 'decorator':
1870
+ uses.push((treemap)=>register(treemap));
1871
+ break;
1872
+ }
1873
+ }
1874
+ function zoom(id) {
1875
+ if (!treemap) {
1876
+ throw new Error(log.error("treemap don't init."));
1877
+ }
1878
+ const node = findRelativeNodeById(id, treemap.layoutNodes);
1879
+ if (node) {
1880
+ treemap.api.zoom(node);
1881
+ }
1882
+ }
1883
+ return context;
1612
1884
  }
1613
1885
 
1614
1886
  const defaultLayoutOptions = {
1615
- titleAreaHeight: {
1616
- max: 60,
1617
- min: 30
1618
- },
1619
- rectGap: 5,
1620
- rectBorderRadius: 0.5,
1621
- rectBorderWidth: 1.5
1887
+ titleAreaHeight: {
1888
+ max: 60,
1889
+ min: 30
1890
+ },
1891
+ rectGap: 5,
1892
+ rectBorderRadius: 0.5,
1893
+ rectBorderWidth: 1.5
1622
1894
  };
1623
1895
  const defaultFontOptions = {
1624
- color: "#000",
1625
- fontSize: {
1626
- max: 70,
1627
- min: 0
1628
- },
1629
- fontFamily: "sans-serif"
1896
+ color: '#000',
1897
+ fontSize: {
1898
+ max: 70,
1899
+ min: 0
1900
+ },
1901
+ fontFamily: 'sans-serif'
1630
1902
  };
1631
1903
  function presetDecorator(app) {
1632
- Object.assign(app.decorator, {
1633
- layout: defaultLayoutOptions,
1634
- font: defaultFontOptions,
1635
- color: { mappings: evaluateColorMappings(app.data) }
1636
- });
1904
+ Object.assign(app.decorator, {
1905
+ layout: defaultLayoutOptions,
1906
+ font: defaultFontOptions,
1907
+ color: {
1908
+ mappings: evaluateColorMappings(app.data)
1909
+ }
1910
+ });
1637
1911
  }
1638
1912
  function evaluateColorMappings(data) {
1639
- const colorMappings = {};
1640
- const hashToHue = (id) => {
1641
- const hash = Math.abs(hashCode(id));
1642
- return hash % 360;
1643
- };
1644
- const lightScale = (depth) => 50 - depth * 5;
1645
- const baseSaturation = 80;
1646
- const siblingHueShift = 30;
1647
- const rc = 0.2126;
1648
- const gc = 0.7152;
1649
- const bc = 0.0722;
1650
- const hslToRgb = (h, s, l) => {
1651
- const a = s * Math.min(l, 1 - l);
1652
- const f = (n) => {
1653
- const k = (n + h / 30) % 12;
1654
- return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
1913
+ const colorMappings = {};
1914
+ const hashToHue = (id)=>{
1915
+ const hash = Math.abs(hashCode(id));
1916
+ return hash % 360;
1655
1917
  };
1656
- return { r: f(0), g: f(8), b: f(4) };
1657
- };
1658
- const calculateLuminance = (r, g, b) => {
1659
- return rc * r + gc * g + bc * b;
1660
- };
1661
- const calculateColor = (module, depth, parentHue, siblingIndex, totalSiblings) => {
1662
- const nodeHue = hashToHue(module.id);
1663
- const hue = parentHue !== null ? (parentHue + siblingHueShift * siblingIndex / totalSiblings) % 360 : nodeHue;
1664
- const lightness = lightScale(depth);
1665
- const hslColor = {
1666
- h: hue,
1667
- s: baseSaturation,
1668
- l: lightness / 100
1918
+ const lightScale = (depth)=>50 - depth * 5;
1919
+ const baseSaturation = 80;
1920
+ const siblingHueShift = 30;
1921
+ const rc = 0.2126;
1922
+ const gc = 0.7152;
1923
+ const bc = 0.0722;
1924
+ const hslToRgb = (h, s, l)=>{
1925
+ const a = s * Math.min(l, 1 - l);
1926
+ const f = (n)=>{
1927
+ const k = (n + h / 30) % 12;
1928
+ return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
1929
+ };
1930
+ return {
1931
+ r: f(0),
1932
+ g: f(8),
1933
+ b: f(4)
1934
+ };
1669
1935
  };
1670
- const { r, g, b } = hslToRgb(hslColor.h, hslColor.s / 100, hslColor.l);
1671
- const luminance = calculateLuminance(r, g, b);
1672
- if (luminance < 0.6) {
1673
- hslColor.l += 0.2;
1674
- } else if (luminance > 0.8) {
1675
- hslColor.l -= 0.1;
1676
- }
1677
- hslColor.l *= 100;
1678
- colorMappings[module.id] = {
1679
- mode: "hsl",
1680
- desc: hslColor
1936
+ const calculateLuminance = (r, g, b)=>{
1937
+ return rc * r + gc * g + bc * b;
1681
1938
  };
1682
- if (module.groups && Array.isArray(module.groups)) {
1683
- const totalChildren = module.groups.length;
1684
- for (let i = 0; i < totalChildren; i++) {
1685
- const child = module.groups[i];
1686
- calculateColor(child, depth + 1, hue, i, totalChildren);
1687
- }
1688
- }
1689
- };
1690
- for (let i = 0; i < data.length; i++) {
1691
- const module = data[i];
1692
- calculateColor(module, 0, null, i, data.length);
1693
- }
1694
- return colorMappings;
1939
+ const calculateColor = (module, depth, parentHue, siblingIndex, totalSiblings)=>{
1940
+ const nodeHue = hashToHue(module.id);
1941
+ const hue = parentHue !== null ? (parentHue + siblingHueShift * siblingIndex / totalSiblings) % 360 : nodeHue;
1942
+ const lightness = lightScale(depth);
1943
+ const hslColor = {
1944
+ h: hue,
1945
+ s: baseSaturation,
1946
+ l: lightness / 100
1947
+ };
1948
+ const { r, g, b } = hslToRgb(hslColor.h, hslColor.s / 100, hslColor.l);
1949
+ const luminance = calculateLuminance(r, g, b);
1950
+ if (luminance < 0.6) {
1951
+ hslColor.l += 0.2;
1952
+ } else if (luminance > 0.8) {
1953
+ hslColor.l -= 0.1;
1954
+ }
1955
+ hslColor.l *= 100;
1956
+ colorMappings[module.id] = {
1957
+ mode: 'hsl',
1958
+ desc: hslColor
1959
+ };
1960
+ if (module.groups && Array.isArray(module.groups)) {
1961
+ const totalChildren = module.groups.length;
1962
+ for(let i = 0; i < totalChildren; i++){
1963
+ const child = module.groups[i];
1964
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
1965
+ calculateColor(child, depth + 1, hue, i, totalChildren);
1966
+ }
1967
+ }
1968
+ };
1969
+ for(let i = 0; i < data.length; i++){
1970
+ const module = data[i];
1971
+ calculateColor(module, 0, null, i, data.length);
1972
+ }
1973
+ return colorMappings;
1695
1974
  }
1696
1975
 
1697
1976
  exports.TreemapLayout = TreemapLayout;