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