squarified 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,1438 +1,1405 @@
1
1
  'use strict';
2
2
 
3
- var _computedKey;
4
- _computedKey = Symbol.iterator;
5
- class Iter {
6
- keys;
7
- data;
8
- constructor(data){
9
- this.data = data;
10
- this.keys = Object.keys(data);
11
- }
12
- // dprint-ignore
13
- *[_computedKey]() {
14
- for(let i = 0; i < this.keys.length; i++){
15
- yield {
16
- key: this.keys[i],
17
- value: this.data[this.keys[i]],
18
- index: i,
19
- peek: ()=>this.keys[i + 1]
20
- };
21
- }
22
- }
23
- }
24
- // For strings we only check the first character to determine if it's a number (I think it's enough)
25
- function perferNumeric(s) {
26
- if (typeof s === 'number') return true;
27
- return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
28
- }
29
-
3
+ var __defProp$a = Object.defineProperty;
4
+ var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
+ var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
30
6
  const DEG_TO_RAD = Math.PI / 180;
31
7
  class Matrix2D {
32
- a;
33
- b;
34
- c;
35
- d;
36
- e;
37
- f;
38
- constructor(loc = {}){
39
- this.a = loc.a || 1;
40
- this.b = loc.b || 0;
41
- this.c = loc.c || 0;
42
- this.d = loc.d || 1;
43
- this.e = loc.e || 0;
44
- this.f = loc.f || 0;
45
- }
46
- create(loc) {
47
- for (const { key, value } of new Iter(loc)){
48
- if (Object.hasOwnProperty.call(this, key)) {
49
- this[key] = value;
50
- }
51
- }
52
- return this;
53
- }
54
- transform(x, y, scaleX, scaleY, rotation, skewX, skewY) {
55
- this.scale(scaleX, scaleY).translation(x, y);
56
- if (skewX || skewY) {
57
- this.skew(skewX, skewY);
58
- } else {
59
- this.roate(rotation);
60
- }
61
- return this;
62
- }
63
- translation(x, y) {
64
- this.e += x;
65
- this.f += y;
66
- return this;
67
- }
68
- scale(a, d) {
69
- this.a *= a;
70
- this.d *= d;
71
- return this;
72
- }
73
- skew(x, y) {
74
- const tanX = Math.tan(x * DEG_TO_RAD);
75
- const tanY = Math.tan(y * DEG_TO_RAD);
76
- const a = this.a + this.b * tanX;
77
- const b = this.b + this.a * tanY;
78
- const c = this.c + this.d * tanX;
79
- const d = this.d + this.c * tanY;
80
- this.a = a;
81
- this.b = b;
82
- this.c = c;
83
- this.d = d;
84
- return this;
85
- }
86
- roate(rotation) {
87
- if (rotation > 0) {
88
- const rad = rotation * DEG_TO_RAD;
89
- const cosTheta = Math.cos(rad);
90
- const sinTheta = Math.sin(rad);
91
- const a = this.a * cosTheta - this.b * sinTheta;
92
- const b = this.a * sinTheta + this.b * cosTheta;
93
- const c = this.c * cosTheta - this.d * sinTheta;
94
- const d = this.c * sinTheta + this.d * cosTheta;
95
- this.a = a;
96
- this.b = b;
97
- this.c = c;
98
- this.d = d;
99
- }
100
- return this;
101
- }
8
+ constructor(loc = {}) {
9
+ __publicField$a(this, "a");
10
+ __publicField$a(this, "b");
11
+ __publicField$a(this, "c");
12
+ __publicField$a(this, "d");
13
+ __publicField$a(this, "e");
14
+ __publicField$a(this, "f");
15
+ this.a = loc.a || 1;
16
+ this.b = loc.b || 0;
17
+ this.c = loc.c || 0;
18
+ this.d = loc.d || 1;
19
+ this.e = loc.e || 0;
20
+ this.f = loc.f || 0;
21
+ }
22
+ create(loc) {
23
+ for (const { key, value } of new Iter(loc)) {
24
+ if (Object.hasOwnProperty.call(this, key)) {
25
+ this[key] = value;
26
+ }
27
+ }
28
+ return this;
29
+ }
30
+ transform(x, y, scaleX, scaleY, rotation, skewX, skewY) {
31
+ this.scale(scaleX, scaleY).translation(x, y);
32
+ if (skewX || skewY) {
33
+ this.skew(skewX, skewY);
34
+ } else {
35
+ this.roate(rotation);
36
+ }
37
+ return this;
38
+ }
39
+ translation(x, y) {
40
+ this.e += x;
41
+ this.f += y;
42
+ return this;
43
+ }
44
+ scale(a, d) {
45
+ this.a *= a;
46
+ this.d *= d;
47
+ return this;
48
+ }
49
+ skew(x, y) {
50
+ const tanX = Math.tan(x * DEG_TO_RAD);
51
+ const tanY = Math.tan(y * DEG_TO_RAD);
52
+ const a = this.a + this.b * tanX;
53
+ const b = this.b + this.a * tanY;
54
+ const c = this.c + this.d * tanX;
55
+ const d = this.d + this.c * tanY;
56
+ this.a = a;
57
+ this.b = b;
58
+ this.c = c;
59
+ this.d = d;
60
+ return this;
61
+ }
62
+ roate(rotation) {
63
+ if (rotation > 0) {
64
+ const rad = rotation * DEG_TO_RAD;
65
+ const cosTheta = Math.cos(rad);
66
+ const sinTheta = Math.sin(rad);
67
+ const a = this.a * cosTheta - this.b * sinTheta;
68
+ const b = this.a * sinTheta + this.b * cosTheta;
69
+ const c = this.c * cosTheta - this.d * sinTheta;
70
+ const d = this.c * sinTheta + this.d * cosTheta;
71
+ this.a = a;
72
+ this.b = b;
73
+ this.c = c;
74
+ this.d = d;
75
+ }
76
+ return this;
77
+ }
102
78
  }
103
79
 
80
+ var __defProp$9 = Object.defineProperty;
81
+ var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
82
+ var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
104
83
  const SELF_ID = {
105
- id: 0,
106
- get () {
107
- return this.id++;
108
- }
84
+ id: 0,
85
+ get() {
86
+ return this.id++;
87
+ }
109
88
  };
89
+ var DisplayType = /* @__PURE__ */ ((DisplayType2) => {
90
+ DisplayType2["Graph"] = "Graph";
91
+ DisplayType2["Box"] = "Box";
92
+ DisplayType2["Rect"] = "Rect";
93
+ DisplayType2["Text"] = "Text";
94
+ return DisplayType2;
95
+ })(DisplayType || {});
110
96
  class Display {
111
- parent;
112
- id;
113
- matrix;
114
- constructor(){
115
- this.parent = null;
116
- this.id = SELF_ID.get();
117
- this.matrix = new Matrix2D();
118
- }
119
- destory() {
120
- //
121
- }
97
+ constructor() {
98
+ __publicField$9(this, "parent");
99
+ __publicField$9(this, "id");
100
+ __publicField$9(this, "matrix");
101
+ this.parent = null;
102
+ this.id = SELF_ID.get();
103
+ this.matrix = new Matrix2D();
104
+ }
105
+ destory() {
106
+ }
122
107
  }
123
108
  const ASSIGN_MAPPINGS = {
124
- fillStyle: !0,
125
- strokeStyle: !0,
126
- font: !0,
127
- lineWidth: !0,
128
- textAlign: !0,
129
- textBaseline: !0
109
+ fillStyle: true,
110
+ strokeStyle: true,
111
+ font: true,
112
+ lineWidth: true,
113
+ textAlign: true,
114
+ textBaseline: true
130
115
  };
131
116
  function createInstruction() {
132
- return {
133
- mods: [],
134
- fillStyle (...args) {
135
- this.mods.push([
136
- 'fillStyle',
137
- args
138
- ]);
139
- },
140
- fillRect (...args) {
141
- this.mods.push([
142
- 'fillRect',
143
- args
144
- ]);
145
- },
146
- strokeStyle (...args) {
147
- this.mods.push([
148
- 'strokeStyle',
149
- args
150
- ]);
151
- },
152
- lineWidth (...args) {
153
- this.mods.push([
154
- 'lineWidth',
155
- args
156
- ]);
157
- },
158
- strokeRect (...args) {
159
- this.mods.push([
160
- 'strokeRect',
161
- args
162
- ]);
163
- },
164
- fillText (...args) {
165
- this.mods.push([
166
- 'fillText',
167
- args
168
- ]);
169
- },
170
- font (...args) {
171
- this.mods.push([
172
- 'font',
173
- args
174
- ]);
175
- },
176
- textBaseline (...args) {
177
- this.mods.push([
178
- 'textBaseline',
179
- args
180
- ]);
181
- },
182
- textAlign (...args) {
183
- this.mods.push([
184
- 'textAlign',
185
- args
186
- ]);
187
- }
188
- };
117
+ return {
118
+ mods: [],
119
+ fillStyle(...args) {
120
+ this.mods.push(["fillStyle", args]);
121
+ },
122
+ fillRect(...args) {
123
+ this.mods.push(["fillRect", args]);
124
+ },
125
+ strokeStyle(...args) {
126
+ this.mods.push(["strokeStyle", args]);
127
+ },
128
+ lineWidth(...args) {
129
+ this.mods.push(["lineWidth", args]);
130
+ },
131
+ strokeRect(...args) {
132
+ this.mods.push(["strokeRect", args]);
133
+ },
134
+ fillText(...args) {
135
+ this.mods.push(["fillText", args]);
136
+ },
137
+ font(...args) {
138
+ this.mods.push(["font", args]);
139
+ },
140
+ textBaseline(...args) {
141
+ this.mods.push(["textBaseline", args]);
142
+ },
143
+ textAlign(...args) {
144
+ this.mods.push(["textAlign", args]);
145
+ }
146
+ };
189
147
  }
190
148
  class S extends Display {
191
- width;
192
- height;
193
- x;
194
- y;
195
- scaleX;
196
- scaleY;
197
- rotation;
198
- skewX;
199
- skewY;
200
- constructor(options = {}){
201
- super();
202
- this.width = options.width || 0;
203
- this.height = options.height || 0;
204
- this.x = options.x || 0;
205
- this.y = options.y || 0;
206
- this.scaleX = options.scaleX || 1;
207
- this.scaleY = options.scaleY || 1;
208
- this.rotation = options.rotation || 0;
209
- this.skewX = options.skewX || 0;
210
- this.skewY = options.skewY || 0;
211
- }
149
+ constructor(options = {}) {
150
+ super();
151
+ __publicField$9(this, "width");
152
+ __publicField$9(this, "height");
153
+ __publicField$9(this, "x");
154
+ __publicField$9(this, "y");
155
+ __publicField$9(this, "scaleX");
156
+ __publicField$9(this, "scaleY");
157
+ __publicField$9(this, "rotation");
158
+ __publicField$9(this, "skewX");
159
+ __publicField$9(this, "skewY");
160
+ this.width = options.width || 0;
161
+ this.height = options.height || 0;
162
+ this.x = options.x || 0;
163
+ this.y = options.y || 0;
164
+ this.scaleX = options.scaleX || 1;
165
+ this.scaleY = options.scaleY || 1;
166
+ this.rotation = options.rotation || 0;
167
+ this.skewX = options.skewX || 0;
168
+ this.skewY = options.skewY || 0;
169
+ }
212
170
  }
213
171
  class Graph extends S {
214
- instruction;
215
- constructor(options = {}){
216
- super(options);
217
- this.instruction = createInstruction();
218
- }
219
- render(ctx) {
220
- this.create();
221
- this.instruction.mods.forEach((mod)=>{
222
- const direct = mod[0];
223
- if (direct in ASSIGN_MAPPINGS) {
224
- // @ts-expect-error
225
- ctx[direct] = mod[1];
226
- return;
227
- }
228
- // @ts-expect-error
229
- ctx[direct].apply(ctx, ...mod.slice(1));
230
- });
231
- }
172
+ constructor(options = {}) {
173
+ super(options);
174
+ __publicField$9(this, "instruction");
175
+ __publicField$9(this, "__refresh__");
176
+ __publicField$9(this, "__options__");
177
+ this.instruction = createInstruction();
178
+ this.__refresh__ = true;
179
+ this.__options__ = options;
180
+ }
181
+ render(ctx) {
182
+ this.create();
183
+ const cap = this.instruction.mods.length;
184
+ for (let i = 0; i < cap; i++) {
185
+ const mod = this.instruction.mods[i];
186
+ const [direct, ...args] = mod;
187
+ if (direct in ASSIGN_MAPPINGS) {
188
+ ctx[direct] = args[0];
189
+ continue;
190
+ }
191
+ ctx[direct].apply(ctx, ...args);
192
+ }
193
+ }
194
+ get __instanceOf__() {
195
+ return "Graph" /* Graph */;
196
+ }
197
+ }
198
+
199
+ function isGraph(display) {
200
+ return display.__instanceOf__ === DisplayType.Graph;
201
+ }
202
+ function isBox(display) {
203
+ return display.__instanceOf__ === DisplayType.Box;
232
204
  }
205
+ function isRect(display) {
206
+ return isGraph(display) && display.__shape__ === DisplayType.Rect;
207
+ }
208
+ function isText(display) {
209
+ return isGraph(display) && display.__shape__ === DisplayType.Text;
210
+ }
211
+ const asserts = {
212
+ isGraph,
213
+ isBox,
214
+ isRect,
215
+ isText
216
+ };
233
217
 
218
+ var __defProp$8 = Object.defineProperty;
219
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
220
+ var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, key + "" , value);
234
221
  class Box extends Display {
235
- elements;
236
- constructor(){
237
- super();
238
- this.elements = [];
239
- }
240
- add(...elements) {
241
- const cap = elements.length;
242
- for(let i = 0; i < cap; i++){
243
- const element = elements[i];
244
- if (element.parent) ;
245
- this.elements.push(element);
246
- element.parent = this;
222
+ constructor() {
223
+ super();
224
+ __publicField$8(this, "elements");
225
+ this.elements = [];
226
+ }
227
+ add(...elements) {
228
+ const cap = elements.length;
229
+ for (let i = 0; i < cap; i++) {
230
+ const element = elements[i];
231
+ if (element.parent) ;
232
+ this.elements.push(element);
233
+ element.parent = this;
234
+ }
235
+ }
236
+ remove(...elements) {
237
+ const cap = elements.length;
238
+ for (let i = 0; i < cap; i++) {
239
+ for (let j = this.elements.length - 1; j >= 0; j--) {
240
+ const element = this.elements[j];
241
+ if (element.id === elements[i].id) {
242
+ this.elements.splice(j, 1);
243
+ element.parent = null;
247
244
  }
248
- }
249
- remove(...elements) {
245
+ }
246
+ }
247
+ }
248
+ destory() {
249
+ this.elements.forEach((element) => element.parent = null);
250
+ this.elements.length = 0;
251
+ }
252
+ get __instanceOf__() {
253
+ return DisplayType.Box;
254
+ }
255
+ clone() {
256
+ const box = new Box();
257
+ if (this.elements.length) {
258
+ const traverse = (elements, parent) => {
259
+ const els = [];
250
260
  const cap = elements.length;
251
- for(let i = 0; i < cap; i++){
252
- for(let j = this.elements.length - 1; j >= 0; j--){
253
- const element = this.elements[j];
254
- if (element.id === elements[i].id) {
255
- this.elements.splice(j, 1);
256
- element.parent = null;
257
- }
258
- }
261
+ for (let i = 0; i < cap; i++) {
262
+ const element = elements[i];
263
+ if (asserts.isBox(element)) {
264
+ const box2 = new Box();
265
+ box2.parent = parent;
266
+ box2.add(...traverse(element.elements, box2));
267
+ els.push(box2);
268
+ } else if (asserts.isGraph(element)) {
269
+ const el = element.clone();
270
+ el.parent = parent;
271
+ els.push(el);
272
+ }
259
273
  }
274
+ return els;
275
+ };
276
+ box.add(...traverse(this.elements, box));
260
277
  }
261
- destory() {
262
- this.elements.forEach((element)=>element.parent = null);
263
- this.elements.length = 0;
264
- }
278
+ return box;
279
+ }
265
280
  }
266
281
 
267
- // Runtime is designed for graph element
268
282
  function decodeHLS(meta) {
269
- const { h, l, s, a } = meta;
270
- if ('a' in meta) {
271
- return `hsla(${h}deg, ${s}%, ${l}%, ${a})`;
272
- }
273
- return `hsl(${h}deg, ${s}%, ${l}%)`;
283
+ const { h, l, s, a } = meta;
284
+ if ("a" in meta) {
285
+ return `hsla(${h}deg, ${s}%, ${l}%, ${a})`;
286
+ }
287
+ return `hsl(${h}deg, ${s}%, ${l}%)`;
274
288
  }
275
289
  function decodeRGB(meta) {
276
- const { r, g, b, a } = meta;
277
- if ('a' in meta) {
278
- return `rgba(${r}, ${g}, ${b}, ${a})`;
279
- }
280
- return `rgb(${r}, ${g}, ${b})`;
290
+ const { r, g, b, a } = meta;
291
+ if ("a" in meta) {
292
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
293
+ }
294
+ return `rgb(${r}, ${g}, ${b})`;
281
295
  }
282
296
  function decodeColor(meta) {
283
- return meta.mode === 'rgb' ? decodeRGB(meta.desc) : decodeHLS(meta.desc);
297
+ return meta.mode === "rgb" ? decodeRGB(meta.desc) : decodeHLS(meta.desc);
284
298
  }
285
299
  function evaluateFillStyle(primitive, opacity = 1) {
286
- const descibe = {
287
- mode: primitive.mode,
288
- desc: {
289
- ...primitive.desc,
290
- a: opacity
291
- }
292
- };
293
- return decodeColor(descibe);
300
+ const descibe = { mode: primitive.mode, desc: { ...primitive.desc, a: opacity } };
301
+ return decodeColor(descibe);
294
302
  }
295
303
  const runtime = {
296
- evaluateFillStyle
304
+ evaluateFillStyle
297
305
  };
298
306
 
307
+ var __defProp$7 = Object.defineProperty;
308
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
309
+ var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, key + "" , value);
299
310
  class Rect extends Graph {
300
- style;
301
- constructor(options = {}){
302
- super(options);
303
- this.style = options.style || Object.create(null);
304
- }
305
- create() {
306
- if (this.style.fill) {
307
- this.instruction.fillStyle(runtime.evaluateFillStyle(this.style.fill, this.style.opacity));
308
- this.instruction.fillRect(0, 0, this.width, this.height);
309
- }
310
- if (this.style.stroke) {
311
- this.instruction.strokeStyle(this.style.stroke);
312
- if (typeof this.style.lineWidth === 'number') {
313
- this.instruction.lineWidth(this.style.lineWidth);
314
- }
315
- this.instruction.strokeRect(0, 0, this.width, this.height);
316
- }
317
- }
311
+ constructor(options = {}) {
312
+ super(options);
313
+ __publicField$7(this, "style");
314
+ this.style = options.style || /* @__PURE__ */ Object.create(null);
315
+ }
316
+ get __shape__() {
317
+ return DisplayType.Rect;
318
+ }
319
+ create() {
320
+ if (this.style.fill) {
321
+ this.instruction.fillStyle(runtime.evaluateFillStyle(this.style.fill, this.style.opacity));
322
+ this.instruction.fillRect(0, 0, this.width, this.height);
323
+ }
324
+ if (this.style.stroke) {
325
+ this.instruction.strokeStyle(this.style.stroke);
326
+ if (typeof this.style.lineWidth === "number") {
327
+ this.instruction.lineWidth(this.style.lineWidth);
328
+ }
329
+ this.instruction.strokeRect(0, 0, this.width, this.height);
330
+ }
331
+ }
332
+ clone() {
333
+ return new Rect({ ...this.style, ...this.__options__ });
334
+ }
318
335
  }
319
336
 
337
+ var __defProp$6 = Object.defineProperty;
338
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
339
+ var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
320
340
  class Text extends Graph {
321
- text;
322
- style;
323
- constructor(options = {}){
324
- super(options);
325
- this.text = options.text || '';
326
- this.style = options.style || Object.create(null);
327
- }
328
- create() {
329
- if (this.style.fill) {
330
- this.instruction.font(this.style.font);
331
- this.instruction.lineWidth(this.style.lineWidth);
332
- this.instruction.textBaseline(this.style.baseline);
333
- this.instruction.fillStyle(this.style.fill);
334
- this.instruction.fillText(this.text, 0, 0);
335
- }
336
- }
341
+ constructor(options = {}) {
342
+ super(options);
343
+ __publicField$6(this, "text");
344
+ __publicField$6(this, "style");
345
+ this.text = options.text || "";
346
+ this.style = options.style || /* @__PURE__ */ Object.create(null);
347
+ }
348
+ create() {
349
+ if (this.style.fill) {
350
+ this.instruction.font(this.style.font);
351
+ this.instruction.lineWidth(this.style.lineWidth);
352
+ this.instruction.textBaseline(this.style.baseline);
353
+ this.instruction.fillStyle(this.style.fill);
354
+ this.instruction.fillText(this.text, 0, 0);
355
+ }
356
+ }
357
+ clone() {
358
+ return new Text({ ...this.style, ...this.__options__ });
359
+ }
360
+ get __shape__() {
361
+ return DisplayType.Text;
362
+ }
337
363
  }
338
364
 
365
+ var __defProp$5 = Object.defineProperty;
366
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
367
+ var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, key + "" , value);
339
368
  class Event {
340
- eventCollections;
341
- constructor(){
342
- this.eventCollections = Object.create(null);
343
- }
344
- on(evt, handler, c) {
345
- if (!(evt in this.eventCollections)) {
346
- this.eventCollections[evt] = [];
347
- }
348
- const data = {
349
- name: evt,
350
- handler,
351
- ctx: c || this
352
- };
353
- this.eventCollections[evt].push(data);
354
- }
355
- off(evt, handler) {
356
- if (evt in this.eventCollections) {
357
- if (!handler) {
358
- this.eventCollections[evt] = [];
359
- return;
360
- }
361
- this.eventCollections[evt] = this.eventCollections[evt].filter((d)=>d.handler !== handler);
362
- }
363
- }
364
- emit(evt, ...args) {
365
- if (!this.eventCollections[evt]) return;
366
- const handlers = this.eventCollections[evt];
367
- if (handlers.length) {
368
- handlers.forEach((d)=>{
369
- d.handler.call(d.ctx, ...args);
370
- });
371
- }
372
- }
373
- bindWithContext(c) {
374
- return (evt, handler)=>this.on(evt, handler, c);
375
- }
369
+ constructor() {
370
+ __publicField$5(this, "eventCollections");
371
+ this.eventCollections = /* @__PURE__ */ Object.create(null);
372
+ }
373
+ on(evt, handler, c) {
374
+ if (!(evt in this.eventCollections)) {
375
+ this.eventCollections[evt] = [];
376
+ }
377
+ const data = {
378
+ name: evt,
379
+ handler,
380
+ ctx: c || this
381
+ };
382
+ this.eventCollections[evt].push(data);
383
+ }
384
+ off(evt, handler) {
385
+ if (evt in this.eventCollections) {
386
+ if (!handler) {
387
+ this.eventCollections[evt] = [];
388
+ return;
389
+ }
390
+ this.eventCollections[evt] = this.eventCollections[evt].filter((d) => d.handler !== handler);
391
+ }
392
+ }
393
+ emit(evt, ...args) {
394
+ if (!this.eventCollections[evt]) return;
395
+ const handlers = this.eventCollections[evt];
396
+ if (handlers.length) {
397
+ handlers.forEach((d) => {
398
+ d.handler.call(d.ctx, ...args);
399
+ });
400
+ }
401
+ }
402
+ bindWithContext(c) {
403
+ return (evt, handler) => this.on(evt, handler, c);
404
+ }
376
405
  }
377
406
 
378
- const NAME_SPACE = 'etoile';
407
+ const NAME_SPACE = "etoile";
379
408
  const log = {
380
- error: (message)=>{
381
- return `[${NAME_SPACE}] ${message}`;
382
- }
409
+ error: (message) => {
410
+ return `[${NAME_SPACE}] ${message}`;
411
+ }
383
412
  };
384
413
 
414
+ var __defProp$4 = Object.defineProperty;
415
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
416
+ var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
385
417
  class Render {
386
- canvas;
387
- ctx;
388
- options;
389
- constructor(to, options){
390
- this.canvas = document.createElement('canvas');
391
- this.ctx = this.canvas.getContext('2d');
392
- this.options = options;
393
- this.initOptions(options);
394
- to.appendChild(this.canvas);
395
- }
396
- clear(width, height) {
397
- this.ctx.clearRect(0, 0, width, height);
398
- }
399
- initOptions(userOptions = {}) {
400
- Object.assign(this.options, userOptions);
401
- const { options } = this;
402
- this.canvas.width = options.width * options.devicePixelRatio;
403
- this.canvas.height = options.height * options.devicePixelRatio;
404
- this.canvas.style.cssText = `width: ${options.width}px; height: ${options.height}px`;
405
- }
406
- update(schedule) {
407
- this.clear(this.options.width, this.options.height);
408
- schedule.execute(this);
409
- }
410
- destory() {}
418
+ constructor(to, options) {
419
+ __publicField$4(this, "canvas");
420
+ __publicField$4(this, "ctx");
421
+ __publicField$4(this, "options");
422
+ this.canvas = document.createElement("canvas");
423
+ this.ctx = this.canvas.getContext("2d");
424
+ this.options = options;
425
+ this.initOptions(options);
426
+ to.appendChild(this.canvas);
427
+ }
428
+ clear(width, height) {
429
+ this.ctx.clearRect(0, 0, width, height);
430
+ }
431
+ initOptions(userOptions = {}) {
432
+ Object.assign(this.options, userOptions);
433
+ const { options } = this;
434
+ this.canvas.width = options.width * options.devicePixelRatio;
435
+ this.canvas.height = options.height * options.devicePixelRatio;
436
+ this.canvas.style.cssText = `width: ${options.width}px; height: ${options.height}px`;
437
+ }
438
+ update(schedule) {
439
+ this.clear(this.options.width, this.options.height);
440
+ schedule.execute(this);
441
+ }
442
+ destory() {
443
+ }
411
444
  }
412
445
 
446
+ var __defProp$3 = Object.defineProperty;
447
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
448
+ var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
413
449
  let Schedule$1 = class Schedule extends Box {
414
- render;
415
- to;
416
- event;
417
- constructor(to, renderOptions = {}){
418
- super();
419
- this.to = typeof to === 'string' ? document.querySelector(to) : to;
420
- if (!this.to) {
421
- throw new Error(log.error('The element to bind is not found.'));
450
+ constructor(to, renderOptions = {}) {
451
+ super();
452
+ __publicField$3(this, "render");
453
+ __publicField$3(this, "to");
454
+ __publicField$3(this, "event");
455
+ this.to = typeof to === "string" ? document.querySelector(to) : to;
456
+ if (!this.to) {
457
+ throw new Error(log.error("The element to bind is not found."));
458
+ }
459
+ const { width, height } = this.to.getBoundingClientRect();
460
+ Object.assign(renderOptions, { width, height }, { devicePixelRatio: window.devicePixelRatio || 1 });
461
+ this.event = new Event();
462
+ this.render = new Render(this.to, renderOptions);
463
+ }
464
+ applyTransform(matrix) {
465
+ const pixel = this.render.options.devicePixelRatio;
466
+ this.render.ctx.setTransform(
467
+ matrix.a * pixel,
468
+ matrix.b * pixel,
469
+ matrix.c * pixel,
470
+ matrix.d * pixel,
471
+ matrix.e * pixel,
472
+ matrix.f * pixel
473
+ );
474
+ }
475
+ update() {
476
+ this.render.update(this);
477
+ const matrix = this.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
478
+ this.applyTransform(matrix);
479
+ }
480
+ // execute all graph elements
481
+ execute(render, graph = this) {
482
+ render.ctx.save();
483
+ if (asserts.isBox(graph)) {
484
+ const elements = graph.elements;
485
+ const cap = elements.length;
486
+ const matrices = new Array(cap);
487
+ for (let i = 0; i < cap; i++) {
488
+ const element = elements[i];
489
+ if (asserts.isGraph(element)) {
490
+ matrices[i] = element.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
491
+ matrices[i].transform(element.x, element.y, element.scaleX, element.scaleY, element.rotation, element.skewX, element.skewY);
422
492
  }
423
- const { width, height } = this.to.getBoundingClientRect();
424
- Object.assign(renderOptions, {
425
- width,
426
- height
427
- }, {
428
- devicePixelRatio: window.devicePixelRatio || 1
429
- });
430
- this.event = new Event();
431
- this.render = new Render(this.to, renderOptions);
432
- }
433
- applyTransform(matrix) {
434
- const pixel = this.render.options.devicePixelRatio;
435
- this.render.ctx.setTransform(matrix.a * pixel, matrix.b * pixel, matrix.c * pixel, matrix.d * pixel, matrix.e * pixel, matrix.f * pixel);
436
- }
437
- update() {
438
- this.render.update(this);
439
- const matrix = this.matrix.create({
440
- a: 1,
441
- b: 0,
442
- c: 0,
443
- d: 1,
444
- e: 0,
445
- f: 0
446
- });
447
- this.applyTransform(matrix);
448
- }
449
- // execute all graph elements
450
- execute(render, graph = this) {
451
- render.ctx.save();
452
- let matrix = graph.matrix;
453
- this.applyTransform(matrix);
454
- if (graph instanceof Box) {
455
- const cap = graph.elements.length;
456
- for(let i = 0; i < cap; i++){
457
- const element = graph.elements[i];
458
- matrix = element.matrix.create({
459
- a: 1,
460
- b: 0,
461
- c: 0,
462
- d: 1,
463
- e: 0,
464
- f: 0
465
- });
466
- if (element instanceof Graph) {
467
- matrix.transform(element.x, element.y, element.scaleX, element.scaleY, element.rotation, element.skewX, element.skewY);
468
- }
469
- this.execute(render, element);
470
- }
471
- }
472
- if (graph instanceof Graph) {
473
- graph.render(render.ctx);
474
- }
475
- render.ctx.restore();
476
- }
493
+ }
494
+ for (let i = 0; i < cap; i++) {
495
+ const element = elements[i];
496
+ this.execute(render, element);
497
+ }
498
+ }
499
+ if (asserts.isGraph(graph)) {
500
+ const matrix = graph.matrix;
501
+ this.applyTransform(matrix);
502
+ graph.render(render.ctx);
503
+ }
504
+ render.ctx.restore();
505
+ }
477
506
  };
478
507
 
479
508
  function traverse(graphs, handler) {
480
- graphs.forEach((graph)=>{
481
- if (graph instanceof Box) {
482
- traverse(graph.elements, handler);
483
- } else if (graph instanceof Graph) {
484
- handler(graph);
485
- }
486
- });
509
+ const len = graphs.length;
510
+ for (let i = 0; i < len; i++) {
511
+ const graph = graphs[i];
512
+ if (asserts.isBox(graph)) {
513
+ traverse(graph.elements, handler);
514
+ } else if (asserts.isGraph(graph)) {
515
+ handler(graph);
516
+ }
517
+ }
487
518
  }
488
519
  const etoile = {
489
- Schedule: Schedule$1,
490
- traverse
520
+ Schedule: Schedule$1,
521
+ traverse
491
522
  };
492
523
 
493
- // Currently, etoile is an internal module, so we won't need too much easing functions.
494
- // And the animation logic is implemented by user code.
495
524
  const easing = {
496
- linear: (k)=>k,
497
- quadraticIn: (k)=>k * k,
498
- quadraticOut: (k)=>k * (2 - k),
499
- quadraticInOut: (k)=>{
500
- if ((k *= 2) < 1) {
501
- return 0.5 * k * k;
502
- }
503
- return -0.5 * (--k * (k - 2) - 1);
504
- },
505
- cubicIn: (k)=>k * k * k,
506
- cubicOut: (k)=>{
507
- if ((k *= 2) < 1) {
508
- return 0.5 * k * k * k;
509
- }
510
- return 0.5 * ((k -= 2) * k * k + 2);
511
- },
512
- cubicInOut: (k)=>{
513
- if ((k *= 2) < 1) {
514
- return 0.5 * k * k * k;
515
- }
516
- return 0.5 * ((k -= 2) * k * k + 2);
517
- }
525
+ linear: (k) => k,
526
+ quadraticIn: (k) => k * k,
527
+ quadraticOut: (k) => k * (2 - k),
528
+ quadraticInOut: (k) => {
529
+ if ((k *= 2) < 1) {
530
+ return 0.5 * k * k;
531
+ }
532
+ return -0.5 * (--k * (k - 2) - 1);
533
+ },
534
+ cubicIn: (k) => k * k * k,
535
+ cubicOut: (k) => {
536
+ if ((k *= 2) < 1) {
537
+ return 0.5 * k * k * k;
538
+ }
539
+ return 0.5 * ((k -= 2) * k * k + 2);
540
+ },
541
+ cubicInOut: (k) => {
542
+ if ((k *= 2) < 1) {
543
+ return 0.5 * k * k * k;
544
+ }
545
+ return 0.5 * ((k -= 2) * k * k + 2);
546
+ }
518
547
  };
519
548
 
549
+ var __defProp$2 = Object.defineProperty;
550
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
551
+ var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
552
+ class Iter {
553
+ constructor(data) {
554
+ __publicField$2(this, "keys");
555
+ __publicField$2(this, "data");
556
+ this.data = data;
557
+ this.keys = Object.keys(data);
558
+ }
559
+ // dprint-ignore
560
+ *[Symbol.iterator]() {
561
+ for (let i = 0; i < this.keys.length; i++) {
562
+ yield {
563
+ key: this.keys[i],
564
+ value: this.data[this.keys[i]],
565
+ index: i,
566
+ peek: () => this.keys[i + 1]
567
+ };
568
+ }
569
+ }
570
+ }
571
+ function perferNumeric(s) {
572
+ if (typeof s === "number") return true;
573
+ return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
574
+ }
575
+ function createFillBlock(x, y, width, height, style) {
576
+ return new Rect({ width, height, x, y, style });
577
+ }
578
+ function createTitleText(text, x, y, font, color) {
579
+ return new Text({
580
+ text,
581
+ x,
582
+ y,
583
+ style: { fill: color, textAlign: "center", baseline: "middle", font, lineWidth: 1 }
584
+ });
585
+ }
586
+ const raf = window.requestAnimationFrame;
587
+
520
588
  function sortChildrenByKey(data, ...keys) {
521
- return data.sort((a, b)=>{
522
- for (const key of keys){
523
- const v = a[key];
524
- const v2 = b[key];
525
- if (perferNumeric(v) && perferNumeric(v2)) {
526
- if (v2 > v) return 1;
527
- if (v2 < v) return -1;
528
- continue;
529
- }
530
- // Not numeric, compare as string
531
- const comparison = ('' + v).localeCompare('' + v2);
532
- if (comparison !== 0) return comparison;
533
- }
534
- return 0;
535
- });
589
+ return data.sort((a, b) => {
590
+ for (const key of keys) {
591
+ const v = a[key];
592
+ const v2 = b[key];
593
+ if (perferNumeric(v) && perferNumeric(v2)) {
594
+ if (v2 > v) return 1;
595
+ if (v2 < v) return -1;
596
+ continue;
597
+ }
598
+ const comparison = ("" + v).localeCompare("" + v2);
599
+ if (comparison !== 0) return comparison;
600
+ }
601
+ return 0;
602
+ });
536
603
  }
537
604
  function c2m(data, key, modifier) {
538
- if (Array.isArray(data.groups)) {
539
- data.groups = sortChildrenByKey(data.groups.map((d)=>c2m(d, key, modifier)), 'weight');
540
- }
541
- const obj = {
542
- ...data,
543
- weight: data[key]
544
- };
545
- if (modifier) return modifier(obj);
546
- return obj;
605
+ if (Array.isArray(data.groups)) {
606
+ data.groups = sortChildrenByKey(data.groups.map((d) => c2m(d, key, modifier)), "weight");
607
+ }
608
+ const obj = { ...data, weight: data[key] };
609
+ if (modifier) return modifier(obj);
610
+ return obj;
547
611
  }
548
612
  function flatten(data) {
549
- const result = [];
550
- for(let i = 0; i < data.length; i++){
551
- const { groups, ...rest } = data[i];
552
- result.push(rest);
553
- if (groups) {
554
- result.push(...flatten(groups));
555
- }
556
- }
557
- return result;
613
+ const result = [];
614
+ for (let i = 0; i < data.length; i++) {
615
+ const { groups, ...rest } = data[i];
616
+ result.push(rest);
617
+ if (groups) {
618
+ result.push(...flatten(groups));
619
+ }
620
+ }
621
+ return result;
558
622
  }
559
623
  function bindParentForModule(modules, parent) {
560
- return modules.map((module)=>{
561
- const next = {
562
- ...module
563
- };
564
- next.parent = parent;
565
- if (next.groups && Array.isArray(next.groups)) {
566
- next.groups = bindParentForModule(next.groups, next);
567
- }
568
- return next;
569
- });
624
+ return modules.map((module) => {
625
+ const next = { ...module };
626
+ next.parent = parent;
627
+ if (next.groups && Array.isArray(next.groups)) {
628
+ next.groups = bindParentForModule(next.groups, next);
629
+ }
630
+ return next;
631
+ });
570
632
  }
571
633
  function getNodeDepth(node) {
572
- let depth = 0;
573
- while(node.parent){
574
- node = node.parent;
575
- depth++;
576
- }
577
- return depth;
634
+ let depth = 0;
635
+ while (node.parent) {
636
+ node = node.parent;
637
+ depth++;
638
+ }
639
+ return depth;
578
640
  }
579
641
  function visit(data, fn) {
580
- if (!data) return null;
581
- for (const d of data){
582
- if (d.children) {
583
- const result = visit(d.children, fn);
584
- if (result) return result;
585
- }
586
- const stop = fn(d);
587
- if (stop) return d;
588
- }
589
- return null;
642
+ if (!data) return null;
643
+ for (const d of data) {
644
+ if (d.children) {
645
+ const result = visit(d.children, fn);
646
+ if (result) return result;
647
+ }
648
+ const stop = fn(d);
649
+ if (stop) return d;
650
+ }
651
+ return null;
590
652
  }
591
653
  function findRelativeNode(c, p, layoutNodes) {
592
- return visit(layoutNodes, (node)=>{
593
- const [x, y, w, h] = node.layout;
594
- if (p.x >= x && p.y >= y && p.x < x + w && p.y < y + h) {
595
- return true;
596
- }
597
- });
654
+ return visit(layoutNodes, (node) => {
655
+ const [x, y, w, h] = node.layout;
656
+ if (p.x >= x && p.y >= y && p.x < x + w && p.y < y + h) {
657
+ return true;
658
+ }
659
+ });
598
660
  }
599
661
  function findRelativeNodeById(id, layoutNodes) {
600
- return visit(layoutNodes, (node)=>{
601
- if (node.node.id === id) {
602
- return true;
603
- }
604
- });
662
+ return visit(layoutNodes, (node) => {
663
+ if (node.node.id === id) {
664
+ return true;
665
+ }
666
+ });
605
667
  }
606
668
 
607
669
  function squarify(data, rect, layoutDecorator) {
608
- const result = [];
609
- if (!data.length) return result;
610
- const worst = (start, end, shortestSide, totalWeight, aspectRatio)=>{
611
- const max = data[start].weight * aspectRatio;
612
- const min = data[end].weight * aspectRatio;
613
- return Math.max(shortestSide * shortestSide * max / (totalWeight * totalWeight), totalWeight * totalWeight / (shortestSide * shortestSide * min));
614
- };
615
- const recursion = (start, rect)=>{
616
- while(start < data.length){
617
- let totalWeight = 0;
618
- for(let i = start; i < data.length; i++){
619
- totalWeight += data[i].weight;
620
- }
621
- const shortestSide = Math.min(rect.w, rect.h);
622
- const aspectRatio = rect.w * rect.h / totalWeight;
623
- let end = start;
624
- let areaInRun = 0;
625
- let oldWorst = 0;
626
- // find the best split
627
- while(end < data.length){
628
- const area = data[end].weight * aspectRatio;
629
- const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
630
- if (end > start && oldWorst < newWorst) break;
631
- areaInRun += area;
632
- oldWorst = newWorst;
633
- end++;
634
- }
635
- const splited = Math.round(areaInRun / shortestSide);
636
- let areaInLayout = 0;
637
- for(let i = start; i < end; i++){
638
- const children = data[i];
639
- const area = children.weight * aspectRatio;
640
- const lower = Math.round(shortestSide * areaInLayout / areaInRun);
641
- const upper = Math.round(shortestSide * (areaInLayout + area) / areaInRun);
642
- const [x, y, w, h] = rect.w >= rect.h ? [
643
- rect.x,
644
- rect.y + lower,
645
- splited,
646
- upper - lower
647
- ] : [
648
- rect.x + lower,
649
- rect.y,
650
- upper - lower,
651
- splited
652
- ];
653
- const depth = getNodeDepth(children) || 1;
654
- const { titleAreaHeight, rectGap } = layoutDecorator;
655
- const diff = titleAreaHeight.max / depth;
656
- const hh = diff < titleAreaHeight.min ? titleAreaHeight.min : diff;
657
- result.push({
658
- layout: [
659
- x,
660
- y,
661
- w,
662
- h
663
- ],
664
- node: children,
665
- decorator: {
666
- ...layoutDecorator,
667
- titleHeight: hh
668
- },
669
- children: w > rectGap * 2 && h > hh + rectGap ? squarify(children.groups || [], {
670
- x: x + rectGap,
671
- y: y + hh,
672
- w: w - rectGap * 2,
673
- h: h - hh - rectGap
674
- }, layoutDecorator) : []
675
- });
676
- areaInLayout += area;
677
- }
678
- start = end;
679
- if (rect.w >= rect.h) {
680
- rect.x += splited;
681
- rect.w -= splited;
682
- } else {
683
- rect.y += splited;
684
- rect.h -= splited;
685
- }
686
- }
687
- };
688
- recursion(0, rect);
689
- return result;
670
+ const result = [];
671
+ if (!data.length) return result;
672
+ const worst = (start, end, shortestSide, totalWeight, aspectRatio) => {
673
+ const max = data[start].weight * aspectRatio;
674
+ const min = data[end].weight * aspectRatio;
675
+ return Math.max(
676
+ shortestSide * shortestSide * max / (totalWeight * totalWeight),
677
+ totalWeight * totalWeight / (shortestSide * shortestSide * min)
678
+ );
679
+ };
680
+ const recursion = (start, rect2) => {
681
+ while (start < data.length) {
682
+ let totalWeight = 0;
683
+ for (let i = start; i < data.length; i++) {
684
+ totalWeight += data[i].weight;
685
+ }
686
+ const shortestSide = Math.min(rect2.w, rect2.h);
687
+ const aspectRatio = rect2.w * rect2.h / totalWeight;
688
+ let end = start;
689
+ let areaInRun = 0;
690
+ let oldWorst = 0;
691
+ while (end < data.length) {
692
+ const area = data[end].weight * aspectRatio;
693
+ const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
694
+ if (end > start && oldWorst < newWorst) break;
695
+ areaInRun += area;
696
+ oldWorst = newWorst;
697
+ end++;
698
+ }
699
+ const splited = Math.round(areaInRun / shortestSide);
700
+ let areaInLayout = 0;
701
+ for (let i = start; i < end; i++) {
702
+ const children = data[i];
703
+ const area = children.weight * aspectRatio;
704
+ const lower = Math.round(shortestSide * areaInLayout / areaInRun);
705
+ const upper = Math.round(shortestSide * (areaInLayout + area) / areaInRun);
706
+ 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];
707
+ const depth = getNodeDepth(children) || 1;
708
+ const { titleAreaHeight, rectGap } = layoutDecorator;
709
+ const diff = titleAreaHeight.max / depth;
710
+ const hh = diff < titleAreaHeight.min ? titleAreaHeight.min : diff;
711
+ result.push({
712
+ layout: [x, y, w, h],
713
+ node: children,
714
+ decorator: {
715
+ ...layoutDecorator,
716
+ titleHeight: hh
717
+ },
718
+ children: w > rectGap * 2 && h > hh + rectGap ? squarify(children.groups || [], {
719
+ x: x + rectGap,
720
+ y: y + hh,
721
+ w: w - rectGap * 2,
722
+ h: h - hh - rectGap
723
+ }, layoutDecorator) : []
724
+ });
725
+ areaInLayout += area;
726
+ }
727
+ start = end;
728
+ if (rect2.w >= rect2.h) {
729
+ rect2.x += splited;
730
+ rect2.w -= splited;
731
+ } else {
732
+ rect2.y += splited;
733
+ rect2.h -= splited;
734
+ }
735
+ }
736
+ };
737
+ recursion(0, rect);
738
+ return result;
690
739
  }
691
740
 
692
741
  function applyForOpacity(graph, lastState, nextState, easedProgress) {
693
- const alpha = lastState + (nextState - lastState) * easedProgress;
694
- if (graph instanceof Rect) {
695
- graph.style.opacity = alpha;
742
+ const alpha = lastState + (nextState - lastState) * easedProgress;
743
+ if (asserts.isRect(graph)) {
744
+ graph.style.opacity = alpha;
745
+ }
746
+ }
747
+ function createEffectRun(c) {
748
+ return (fn) => {
749
+ const effect = () => {
750
+ const done = fn();
751
+ if (done) {
752
+ c.animationFrameID = null;
753
+ } else {
754
+ c.animationFrameID = raf(effect);
755
+ }
756
+ };
757
+ if (!c.animationFrameID) {
758
+ c.animationFrameID = raf(effect);
759
+ }
760
+ };
761
+ }
762
+ function createEffectStop(c) {
763
+ return () => {
764
+ if (c.animationFrameID) {
765
+ window.cancelAnimationFrame(c.animationFrameID);
766
+ c.animationFrameID = null;
696
767
  }
768
+ };
769
+ }
770
+ function createEffectScope() {
771
+ const c = {
772
+ animationFrameID: null
773
+ };
774
+ const run = createEffectRun(c);
775
+ const stop = createEffectStop(c);
776
+ return { run, stop };
697
777
  }
698
778
 
699
779
  class RegisterModule {
700
- static mixin(app, methods) {
701
- methods.forEach(({ name, fn })=>{
702
- Object.defineProperty(app, name, {
703
- value: fn(app),
704
- writable: false
705
- });
706
- });
707
- }
780
+ static mixin(app, methods) {
781
+ methods.forEach(({ name, fn }) => {
782
+ Object.defineProperty(app, name, {
783
+ value: fn(app),
784
+ writable: false
785
+ });
786
+ });
787
+ }
708
788
  }
709
789
  function registerModuleForSchedule(mod) {
710
- if (mod instanceof RegisterModule) {
711
- return (app, treemap, render)=>mod.init(app, treemap, render);
712
- }
713
- throw new Error(log.error('The module is not a valid RegisterScheduleModule.'));
790
+ if (mod instanceof RegisterModule) {
791
+ return (app, treemap, render) => mod.init(app, treemap, render);
792
+ }
793
+ throw new Error(log.error("The module is not a valid RegisterScheduleModule."));
714
794
  }
715
795
 
716
- // etoile is a simple 2D render engine for web and it don't take complex rendering into account.
717
- // So it's no need to implement a complex event algorithm or hit mode.
718
- // If one day etoile need to build as a useful library. Pls rewrite it!
719
- // All of implementation don't want to consider the compatibility of the browser.
720
- const primitiveEvents = [
721
- 'click',
722
- 'mousedown',
723
- 'mousemove',
724
- 'mouseup',
725
- 'mouseover',
726
- 'mouseout'
727
- ];
796
+ var __defProp$1 = Object.defineProperty;
797
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
798
+ var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
799
+ const primitiveEvents = ["click", "mousedown", "mousemove", "mouseup", "mouseover", "mouseout"];
800
+ const fill = { desc: { r: 255, g: 255, b: 255 }, mode: "rgb" };
728
801
  function smoothDrawing(c) {
729
- const { self, treemap } = c;
730
- const currentNode = self.currentNode;
731
- if (currentNode) {
732
- const lloc = new Set();
733
- visit([
734
- currentNode
735
- ], (node)=>{
736
- const [x, y, w, h] = node.layout;
737
- const { rectGap, titleHeight } = node.decorator;
738
- lloc.add(x + '-' + y);
739
- lloc.add(x + '-' + (y + h - rectGap));
740
- lloc.add(x + '-' + (y + titleHeight));
741
- lloc.add(x + w - rectGap + '-' + (y + titleHeight));
742
- });
743
- const startTime = Date.now();
744
- const animationDuration = 300;
745
- const draw = ()=>{
746
- if (self.forceDestroy) {
747
- return;
748
- }
749
- const elapsed = Date.now() - startTime;
750
- const progress = Math.min(elapsed / animationDuration, 1);
751
- const easedProgress = easing.cubicIn(progress) || 0.1;
752
- let allTasksCompleted = true;
753
- treemap.reset();
754
- etoile.traverse([
755
- treemap.elements[0]
756
- ], (graph)=>{
757
- const key = `${graph.x}-${graph.y}`;
758
- if (lloc.has(key)) {
759
- applyForOpacity(graph, 1, 0.7, easedProgress);
760
- if (progress < 1) {
761
- allTasksCompleted = false;
762
- }
763
- }
764
- });
765
- applyGraphTransform(treemap.elements, self.translateX, self.translateY, self.scaleRatio);
766
- treemap.update();
767
- if (!allTasksCompleted) {
768
- window.requestAnimationFrame(draw);
769
- }
770
- };
771
- if (!self.isAnimating) {
772
- self.isAnimating = true;
773
- window.requestAnimationFrame(draw);
774
- }
775
- } else {
776
- treemap.reset();
777
- applyGraphTransform(treemap.elements, self.translateX, self.translateY, self.scaleRatio);
778
- treemap.update();
779
- }
802
+ const { self, treemap } = c;
803
+ const currentNode = self.currentNode;
804
+ if (currentNode) {
805
+ const { run, stop } = createEffectScope();
806
+ const startTime = Date.now();
807
+ const animationDuration = 300;
808
+ const [x, y, w, h] = currentNode.layout;
809
+ run(() => {
810
+ if (self.forceDestroy) {
811
+ stop();
812
+ return true;
813
+ }
814
+ const elapsed = Date.now() - startTime;
815
+ const progress = Math.min(elapsed / animationDuration, 1);
816
+ const easedProgress = easing.cubicInOut(progress);
817
+ const mask = createFillBlock(x, y, w, h, { fill, opacity: 0.4 });
818
+ treemap.reset();
819
+ applyForOpacity(mask, 0.4, 0.4, easedProgress);
820
+ treemap.bgBox.add(mask);
821
+ applyGraphTransform(treemap.elements, self.translateX, self.translateY, self.scaleRatio);
822
+ treemap.update();
823
+ return progress >= 1;
824
+ });
825
+ } else {
826
+ treemap.reset();
827
+ applyGraphTransform(treemap.elements, self.translateX, self.translateY, self.scaleRatio);
828
+ treemap.update();
829
+ }
780
830
  }
781
831
  function applyZoomEvent(ctx) {
782
- ctx.treemap.event.on('zoom', (node)=>{
783
- const root = null;
784
- if (ctx.self.isDragging) return;
785
- onZoom(ctx, node, root);
786
- });
832
+ ctx.treemap.event.on("zoom", (node) => {
833
+ const root = null;
834
+ if (ctx.self.isDragging) return;
835
+ onZoom(ctx, node, root);
836
+ });
787
837
  }
788
838
  function getOffset(el) {
789
- let e = 0;
790
- let f = 0;
791
- if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
792
- const { top, left } = el.getBoundingClientRect();
793
- e = top;
794
- f = left;
795
- } else {
796
- for(let elt = el; elt; elt = el.offsetParent){
797
- e += el.offsetLeft;
798
- f += el.offsetTop;
799
- }
800
- }
801
- return [
802
- e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
803
- f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
804
- ];
839
+ let e = 0;
840
+ let f = 0;
841
+ if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
842
+ const { top, left } = el.getBoundingClientRect();
843
+ e = top;
844
+ f = left;
845
+ } else {
846
+ for (let elt = el; elt; elt = el.offsetParent) {
847
+ e += el.offsetLeft;
848
+ f += el.offsetTop;
849
+ }
850
+ }
851
+ return [
852
+ e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
853
+ f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
854
+ ];
805
855
  }
806
856
  function captureBoxXY(c, evt, a, d, translateX, translateY) {
807
- const boundingClientRect = c.getBoundingClientRect();
808
- if (evt instanceof MouseEvent) {
809
- const [e, f] = getOffset(c);
810
- return {
811
- x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
812
- y: (evt.clientY - boundingClientRect.top - f - translateY) / d
813
- };
814
- }
857
+ const boundingClientRect = c.getBoundingClientRect();
858
+ if (evt instanceof MouseEvent) {
859
+ const [e, f] = getOffset(c);
815
860
  return {
816
- x: 0,
817
- y: 0
861
+ x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
862
+ y: (evt.clientY - boundingClientRect.top - f - translateY) / d
818
863
  };
864
+ }
865
+ return { x: 0, y: 0 };
819
866
  }
820
867
  function bindPrimitiveEvent(ctx, evt, bus) {
821
- const { treemap, self } = ctx;
822
- const c = treemap.render.canvas;
823
- const handler = (e)=>{
824
- const { x, y } = captureBoxXY(c, e, self.scaleRatio, self.scaleRatio, self.translateX, self.translateY);
825
- const event = {
826
- native: e,
827
- module: findRelativeNode(c, {
828
- x,
829
- y
830
- }, treemap.layoutNodes)
831
- };
832
- // @ts-expect-error
833
- bus.emit(evt, event);
868
+ const { treemap, self } = ctx;
869
+ const c = treemap.render.canvas;
870
+ const handler = (e) => {
871
+ const { x, y } = captureBoxXY(
872
+ c,
873
+ e,
874
+ self.scaleRatio,
875
+ self.scaleRatio,
876
+ self.translateX,
877
+ self.translateY
878
+ );
879
+ const event = {
880
+ native: e,
881
+ module: findRelativeNode(c, { x, y }, treemap.layoutNodes)
834
882
  };
835
- c.addEventListener(evt, handler);
836
- return handler;
883
+ bus.emit(evt, event);
884
+ };
885
+ c.addEventListener(evt, handler);
886
+ return handler;
837
887
  }
838
888
  class SelfEvent extends RegisterModule {
839
- currentNode;
840
- isAnimating;
841
- forceDestroy;
842
- scaleRatio;
843
- translateX;
844
- translateY;
845
- layoutWidth;
846
- layoutHeight;
847
- isDragging;
848
- draggingState;
849
- event;
850
- constructor(){
851
- super();
852
- this.currentNode = null;
853
- this.isAnimating = false;
854
- this.forceDestroy = false;
855
- this.isDragging = false;
856
- this.scaleRatio = 1;
857
- this.translateX = 0;
858
- this.translateY = 0;
859
- this.layoutWidth = 0;
860
- this.layoutHeight = 0;
861
- this.draggingState = {
862
- x: 0,
863
- y: 0
864
- };
865
- this.event = new Event();
866
- }
867
- ondragstart(metadata) {
868
- const { native } = metadata;
869
- if (isScrollWheelOrRightButtonOnMouseupAndDown(native)) {
870
- return;
871
- }
872
- const x = native.offsetX;
873
- const y = native.offsetY;
874
- this.self.isDragging = true;
875
- this.self.draggingState = {
876
- x,
877
- y
878
- };
879
- }
880
- ondragmove(metadata) {
881
- if (!this.self.isDragging) {
882
- if ('zoom' in this.treemap.event.eventCollections) {
883
- const condit = this.treemap.event.eventCollections.zoom.length > 0;
884
- if (!condit) {
885
- applyZoomEvent(this);
886
- }
887
- }
888
- return;
889
- }
890
- // @ts-expect-error
891
- this.self.event.off('mousemove', this.self.onmousemove);
892
- this.treemap.event.off('zoom');
893
- this.self.forceDestroy = true;
894
- const { native } = metadata;
895
- const x = native.offsetX;
896
- const y = native.offsetY;
897
- const { x: lastX, y: lastY } = this.self.draggingState;
898
- const drawX = x - lastX;
899
- const drawY = y - lastY;
900
- this.self.translateX += drawX;
901
- this.self.translateY += drawY;
902
- this.self.draggingState = {
903
- x,
904
- y
905
- };
906
- this.treemap.reset();
907
- applyGraphTransform(this.treemap.elements, this.self.translateX, this.self.translateY, this.self.scaleRatio);
908
- this.treemap.update();
909
- }
910
- ondragend(metadata) {
911
- if (!this.self.isDragging) {
912
- return;
913
- }
914
- this.self.isDragging = false;
915
- this.self.draggingState = {
916
- x: 0,
917
- y: 0
918
- };
919
- this.self.event.bindWithContext(this)('mousemove', this.self.onmousemove);
920
- }
921
- onmousemove(metadata) {
922
- const { self } = this;
923
- if (self.isDragging) {
924
- return;
925
- }
926
- const { module: node } = metadata;
927
- self.forceDestroy = false;
928
- if (self.currentNode !== node) {
929
- self.currentNode = node;
930
- self.isAnimating = false;
889
+ constructor() {
890
+ super();
891
+ __publicField$1(this, "currentNode");
892
+ __publicField$1(this, "forceDestroy");
893
+ __publicField$1(this, "scaleRatio");
894
+ __publicField$1(this, "translateX");
895
+ __publicField$1(this, "translateY");
896
+ __publicField$1(this, "layoutWidth");
897
+ __publicField$1(this, "layoutHeight");
898
+ __publicField$1(this, "isDragging");
899
+ __publicField$1(this, "draggingState");
900
+ __publicField$1(this, "event");
901
+ this.currentNode = null;
902
+ this.forceDestroy = false;
903
+ this.isDragging = false;
904
+ this.scaleRatio = 1;
905
+ this.translateX = 0;
906
+ this.translateY = 0;
907
+ this.layoutWidth = 0;
908
+ this.layoutHeight = 0;
909
+ this.draggingState = { x: 0, y: 0 };
910
+ this.event = new Event();
911
+ }
912
+ ondragstart(metadata) {
913
+ const { native } = metadata;
914
+ if (isScrollWheelOrRightButtonOnMouseupAndDown(native)) {
915
+ return;
916
+ }
917
+ const x = native.offsetX;
918
+ const y = native.offsetY;
919
+ this.self.isDragging = true;
920
+ this.self.draggingState = { x, y };
921
+ }
922
+ ondragmove(metadata) {
923
+ if (!this.self.isDragging) {
924
+ if ("zoom" in this.treemap.event.eventCollections) {
925
+ const condit = this.treemap.event.eventCollections.zoom.length > 0;
926
+ if (!condit) {
927
+ applyZoomEvent(this);
931
928
  }
932
- smoothDrawing(this);
933
- }
934
- onmouseout() {
935
- const { self } = this;
936
- self.currentNode = null;
937
- self.forceDestroy = true;
938
- self.isDragging = false;
939
- smoothDrawing(this);
940
- }
941
- onwheel(metadata) {
942
- const { self, treemap } = this;
943
- // @ts-expect-error
944
- const wheelDelta = metadata.native.wheelDelta;
945
- const absWheelDelta = Math.abs(wheelDelta);
946
- const offsetX = metadata.native.offsetX;
947
- const offsetY = metadata.native.offsetY;
948
- if (wheelDelta === 0) {
949
- return;
950
- }
951
- self.forceDestroy = true;
952
- self.isAnimating = true;
953
- treemap.reset();
954
- const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
955
- const delta = wheelDelta > 0 ? factor : 1 / factor;
956
- self.scaleRatio *= delta;
957
- const translateX = offsetX - (offsetX - self.translateX) * delta;
958
- const translateY = offsetY - (offsetY - self.translateY) * delta;
959
- self.translateX = translateX;
960
- self.translateY = translateY;
961
- applyGraphTransform(treemap.elements, self.translateX, self.translateY, self.scaleRatio);
962
- treemap.update();
963
- self.forceDestroy = false;
964
- self.isAnimating = false;
965
- }
966
- init(app, treemap, render) {
967
- const event = this.event;
968
- const nativeEvents = [];
969
- const methods = [
970
- {
971
- name: 'on',
972
- fn: ()=>event.bindWithContext(treemap.api).bind(event)
973
- },
974
- {
975
- name: 'off',
976
- fn: ()=>event.off.bind(event)
977
- },
978
- {
979
- name: 'emit',
980
- fn: ()=>event.emit.bind(event)
981
- }
982
- ];
983
- RegisterModule.mixin(app, methods);
984
- const selfEvents = [
985
- ...primitiveEvents,
986
- 'wheel'
987
- ];
988
- selfEvents.forEach((evt)=>{
989
- nativeEvents.push(bindPrimitiveEvent({
990
- treemap,
991
- self: this
992
- }, evt, event));
993
- });
994
- const selfEvt = event.bindWithContext({
995
- treemap,
996
- self: this
997
- });
998
- selfEvt('mousedown', this.ondragstart);
999
- selfEvt('mousemove', this.ondragmove);
1000
- selfEvt('mouseup', this.ondragend);
1001
- // highlight
1002
- selfEvt('mousemove', this.onmousemove);
1003
- selfEvt('mouseout', this.onmouseout);
1004
- // wheel
1005
- selfEvt('wheel', this.onwheel);
1006
- applyZoomEvent({
1007
- treemap,
1008
- self: this
1009
- });
1010
- treemap.event.on('cleanup:selfevent', ()=>{
1011
- this.currentNode = null;
1012
- this.isAnimating = false;
1013
- this.scaleRatio = 1;
1014
- this.translateX = 0;
1015
- this.translateY = 0;
1016
- this.layoutWidth = treemap.render.canvas.width;
1017
- this.layoutHeight = treemap.render.canvas.height;
1018
- this.isDragging = false;
1019
- this.draggingState = {
1020
- x: 0,
1021
- y: 0
1022
- };
1023
- });
1024
- }
929
+ }
930
+ return;
931
+ }
932
+ this.self.event.off("mousemove", this.self.onmousemove);
933
+ this.treemap.event.off("zoom");
934
+ this.self.forceDestroy = true;
935
+ const { native } = metadata;
936
+ const x = native.offsetX;
937
+ const y = native.offsetY;
938
+ const { x: lastX, y: lastY } = this.self.draggingState;
939
+ const drawX = x - lastX;
940
+ const drawY = y - lastY;
941
+ this.self.translateX += drawX;
942
+ this.self.translateY += drawY;
943
+ this.self.draggingState = { x, y };
944
+ this.treemap.reset();
945
+ applyGraphTransform(this.treemap.elements, this.self.translateX, this.self.translateY, this.self.scaleRatio);
946
+ this.treemap.update();
947
+ }
948
+ ondragend(metadata) {
949
+ if (!this.self.isDragging) {
950
+ return;
951
+ }
952
+ this.self.isDragging = false;
953
+ this.self.draggingState = { x: 0, y: 0 };
954
+ this.self.event.bindWithContext(this)("mousemove", this.self.onmousemove);
955
+ }
956
+ onmousemove(metadata) {
957
+ const { self } = this;
958
+ if (self.isDragging) {
959
+ return;
960
+ }
961
+ const { module: node } = metadata;
962
+ self.forceDestroy = false;
963
+ if (self.currentNode !== node) {
964
+ self.currentNode = node;
965
+ }
966
+ smoothDrawing(this);
967
+ }
968
+ onmouseout() {
969
+ const { self } = this;
970
+ self.currentNode = null;
971
+ self.forceDestroy = true;
972
+ self.isDragging = false;
973
+ smoothDrawing(this);
974
+ }
975
+ onwheel(metadata) {
976
+ const { self, treemap } = this;
977
+ const wheelDelta = metadata.native.wheelDelta;
978
+ const absWheelDelta = Math.abs(wheelDelta);
979
+ const offsetX = metadata.native.offsetX;
980
+ const offsetY = metadata.native.offsetY;
981
+ if (wheelDelta === 0) {
982
+ return;
983
+ }
984
+ self.forceDestroy = true;
985
+ treemap.reset();
986
+ const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
987
+ const delta = wheelDelta > 0 ? factor : 1 / factor;
988
+ self.scaleRatio *= delta;
989
+ const translateX = offsetX - (offsetX - self.translateX) * delta;
990
+ const translateY = offsetY - (offsetY - self.translateY) * delta;
991
+ self.translateX = translateX;
992
+ self.translateY = translateY;
993
+ applyGraphTransform(treemap.elements, self.translateX, self.translateY, self.scaleRatio);
994
+ treemap.update();
995
+ self.forceDestroy = false;
996
+ }
997
+ init(app, treemap, render) {
998
+ const event = this.event;
999
+ const nativeEvents = [];
1000
+ const methods = [
1001
+ {
1002
+ name: "on",
1003
+ fn: () => event.bindWithContext(treemap.api).bind(event)
1004
+ },
1005
+ {
1006
+ name: "off",
1007
+ fn: () => event.off.bind(event)
1008
+ },
1009
+ {
1010
+ name: "emit",
1011
+ fn: () => event.emit.bind(event)
1012
+ }
1013
+ ];
1014
+ RegisterModule.mixin(app, methods);
1015
+ const selfEvents = [...primitiveEvents, "wheel"];
1016
+ selfEvents.forEach((evt) => {
1017
+ nativeEvents.push(bindPrimitiveEvent({ treemap, self: this }, evt, event));
1018
+ });
1019
+ const selfEvt = event.bindWithContext({ treemap, self: this });
1020
+ selfEvt("mousedown", this.ondragstart);
1021
+ selfEvt("mousemove", this.ondragmove);
1022
+ selfEvt("mouseup", this.ondragend);
1023
+ selfEvt("mousemove", this.onmousemove);
1024
+ selfEvt("mouseout", this.onmouseout);
1025
+ selfEvt("wheel", this.onwheel);
1026
+ applyZoomEvent({ treemap, self: this });
1027
+ treemap.event.on("cleanup:selfevent", () => {
1028
+ this.currentNode = null;
1029
+ this.scaleRatio = 1;
1030
+ this.translateX = 0;
1031
+ this.translateY = 0;
1032
+ this.layoutWidth = treemap.render.canvas.width;
1033
+ this.layoutHeight = treemap.render.canvas.height;
1034
+ this.isDragging = false;
1035
+ this.draggingState = { x: 0, y: 0 };
1036
+ });
1037
+ }
1025
1038
  }
1026
1039
  function estimateZoomingArea(node, root, w, h) {
1027
- const defaultSizes = [
1028
- w,
1029
- h,
1030
- 1
1031
- ];
1032
- if (root === node) {
1033
- return defaultSizes;
1034
- }
1035
- const viewArea = w * h;
1036
- let area = viewArea;
1037
- let parent = node.node.parent;
1038
- let totalWeight = node.node.weight;
1039
- while(parent){
1040
- const siblings = parent.groups || [];
1041
- let siblingWeightSum = 0;
1042
- for (const sibling of siblings){
1043
- siblingWeightSum += sibling.weight;
1044
- }
1045
- area *= siblingWeightSum / totalWeight;
1046
- totalWeight = parent.weight;
1047
- parent = parent.parent;
1048
- }
1049
- const maxScaleFactor = 2.5;
1050
- const minScaleFactor = 0.3;
1051
- const scaleFactor = Math.max(minScaleFactor, Math.min(maxScaleFactor, Math.sqrt(area / viewArea)));
1052
- return [
1053
- w * scaleFactor,
1054
- h * scaleFactor
1055
- ];
1040
+ const defaultSizes = [w, h, 1];
1041
+ if (root === node) {
1042
+ return defaultSizes;
1043
+ }
1044
+ const viewArea = w * h;
1045
+ let area = viewArea;
1046
+ let parent = node.node.parent;
1047
+ let totalWeight = node.node.weight;
1048
+ while (parent) {
1049
+ const siblings = parent.groups || [];
1050
+ let siblingWeightSum = 0;
1051
+ for (const sibling of siblings) {
1052
+ siblingWeightSum += sibling.weight;
1053
+ }
1054
+ area *= siblingWeightSum / totalWeight;
1055
+ totalWeight = parent.weight;
1056
+ parent = parent.parent;
1057
+ }
1058
+ const maxScaleFactor = 2.5;
1059
+ const minScaleFactor = 0.3;
1060
+ const scaleFactor = Math.max(minScaleFactor, Math.min(maxScaleFactor, Math.sqrt(area / viewArea)));
1061
+ return [w * scaleFactor, h * scaleFactor];
1056
1062
  }
1057
1063
  function applyGraphTransform(graphs, translateX, translateY, scale) {
1058
- etoile.traverse(graphs, (graph)=>{
1059
- graph.x = graph.x * scale + translateX;
1060
- graph.y = graph.y * scale + translateY;
1061
- graph.scaleX = scale;
1062
- graph.scaleY = scale;
1063
- });
1064
+ etoile.traverse(graphs, (graph) => {
1065
+ graph.x = graph.x * scale + translateX;
1066
+ graph.y = graph.y * scale + translateY;
1067
+ graph.scaleX = scale;
1068
+ graph.scaleY = scale;
1069
+ });
1064
1070
  }
1065
1071
  function onZoom(ctx, node, root) {
1066
- if (!node) return;
1067
- const { treemap, self } = ctx;
1068
- let isAnimating = false;
1069
- const c = treemap.render.canvas;
1070
- const boundingClientRect = c.getBoundingClientRect();
1071
- const [w, h] = estimateZoomingArea(node, root, boundingClientRect.width, boundingClientRect.height);
1072
- resetLayout(treemap, w, h);
1073
- const module = findRelativeNodeById(node.node.id, treemap.layoutNodes);
1074
- if (module) {
1075
- const [mx, my, mw, mh] = module.layout;
1076
- const scale = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
1077
- const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * scale;
1078
- const translateY = boundingClientRect.height / 2 - (my + mh / 2) * scale;
1079
- const initialScale = self.scaleRatio;
1080
- const initialTranslateX = self.translateX;
1081
- const initialTranslateY = self.translateY;
1082
- const startTime = Date.now();
1083
- const animationDuration = 300;
1084
- const draw = ()=>{
1085
- if (self.forceDestroy) {
1086
- return;
1087
- }
1088
- const elapsed = Date.now() - startTime;
1089
- const progress = Math.min(elapsed / animationDuration, 1);
1090
- const easedProgress = easing.cubicInOut(progress);
1091
- const scaleRatio = initialScale + (scale - initialScale) * easedProgress;
1092
- self.translateX = initialTranslateX + (translateX - initialTranslateX) * easedProgress;
1093
- self.translateY = initialTranslateY + (translateY - initialTranslateY) * easedProgress;
1094
- self.scaleRatio = scaleRatio;
1095
- treemap.reset();
1096
- applyGraphTransform(treemap.elements, self.translateX, self.translateY, scaleRatio);
1097
- treemap.update();
1098
- if (progress < 1) {
1099
- window.requestAnimationFrame(draw);
1100
- } else {
1101
- self.layoutWidth = w;
1102
- self.layoutHeight = h;
1103
- isAnimating = false;
1104
- }
1105
- };
1106
- if (!isAnimating) {
1107
- isAnimating = true;
1108
- window.requestAnimationFrame(draw);
1109
- }
1110
- }
1111
- root = node;
1072
+ if (!node) return;
1073
+ const { treemap, self } = ctx;
1074
+ const c = treemap.render.canvas;
1075
+ const boundingClientRect = c.getBoundingClientRect();
1076
+ const [w, h] = estimateZoomingArea(node, root, boundingClientRect.width, boundingClientRect.height);
1077
+ resetLayout(treemap, w, h);
1078
+ const module = findRelativeNodeById(node.node.id, treemap.layoutNodes);
1079
+ if (module) {
1080
+ const [mx, my, mw, mh] = module.layout;
1081
+ const scale = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
1082
+ const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * scale;
1083
+ const translateY = boundingClientRect.height / 2 - (my + mh / 2) * scale;
1084
+ const initialScale = self.scaleRatio;
1085
+ const initialTranslateX = self.translateX;
1086
+ const initialTranslateY = self.translateY;
1087
+ const startTime = Date.now();
1088
+ const animationDuration = 300;
1089
+ if (self.layoutHeight !== w || self.layoutHeight !== h) {
1090
+ delete treemap.fontsCaches[module.node.id];
1091
+ delete treemap.ellispsisWidthCache[module.node.id];
1092
+ }
1093
+ const { run, stop } = createEffectScope();
1094
+ run(() => {
1095
+ const elapsed = Date.now() - startTime;
1096
+ const progress = Math.min(elapsed / animationDuration, 1);
1097
+ if (progress >= 1) {
1098
+ stop();
1099
+ self.layoutWidth = w;
1100
+ self.layoutHeight = h;
1101
+ }
1102
+ const easedProgress = easing.cubicInOut(progress);
1103
+ const scaleRatio = initialScale + (scale - initialScale) * easedProgress;
1104
+ self.translateX = initialTranslateX + (translateX - initialTranslateX) * easedProgress;
1105
+ self.translateY = initialTranslateY + (translateY - initialTranslateY) * easedProgress;
1106
+ self.scaleRatio = scaleRatio;
1107
+ treemap.reset();
1108
+ applyGraphTransform(treemap.elements, self.translateX, self.translateY, scaleRatio);
1109
+ treemap.update();
1110
+ return progress >= 1;
1111
+ });
1112
+ }
1113
+ root = node;
1112
1114
  }
1113
- // Only works for mouseup and mousedown events
1114
1115
  function isScrollWheelOrRightButtonOnMouseupAndDown(e) {
1115
- return e.which === 2 || e.which === 3;
1116
+ return e.which === 2 || e.which === 3;
1116
1117
  }
1117
1118
 
1119
+ var __defProp = Object.defineProperty;
1120
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1121
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1118
1122
  const defaultRegistries = [
1119
- registerModuleForSchedule(new SelfEvent())
1123
+ registerModuleForSchedule(new SelfEvent())
1120
1124
  ];
1121
- function charCodeWidth(c, ch) {
1122
- return c.measureText(String.fromCharCode(ch)).width;
1123
- }
1124
- function evaluateOptimalFontSize(c, text, width, fontRange, fontFamily, height) {
1125
- height = Math.floor(height);
1126
- let optimalFontSize = fontRange.min;
1127
- for(let fontSize = fontRange.min; fontSize <= fontRange.max; fontSize++){
1128
- c.font = `${fontSize}px ${fontFamily}`;
1129
- let textWidth = 0;
1130
- const textHeight = fontSize;
1131
- let i = 0;
1132
- while(i < text.length){
1133
- const codePointWidth = charCodeWidth(c, text.charCodeAt(i));
1134
- textWidth += codePointWidth;
1135
- i++;
1136
- }
1137
- if (textWidth >= width) {
1138
- const overflow = textWidth - width;
1139
- const ratio = overflow / textWidth;
1140
- const newFontSize = Math.abs(Math.floor(fontSize - fontSize * ratio));
1141
- optimalFontSize = newFontSize || fontRange.min;
1142
- break;
1143
- }
1144
- if (textHeight >= height) {
1145
- const overflow = textHeight - height;
1146
- const ratio = overflow / textHeight;
1147
- const newFontSize = Math.abs(Math.floor(fontSize - fontSize * ratio));
1148
- optimalFontSize = newFontSize || fontRange.min;
1149
- break;
1150
- }
1151
- optimalFontSize = fontSize;
1152
- }
1153
- return optimalFontSize;
1125
+ function measureTextWidth(c, text) {
1126
+ return c.measureText(text).width;
1154
1127
  }
1155
- function getSafeText(c, text, width) {
1156
- const ellipsisWidth = c.measureText('...').width;
1157
- if (width < ellipsisWidth) {
1158
- return false;
1159
- }
1160
- let textWidth = 0;
1161
- let i = 0;
1162
- while(i < text.length){
1163
- const codePointWidth = charCodeWidth(c, text.charCodeAt(i));
1164
- textWidth += codePointWidth;
1165
- i++;
1166
- }
1167
- if (textWidth < width) {
1168
- return {
1169
- text,
1170
- width: textWidth
1171
- };
1128
+ function evaluateOptimalFontSize(c, text, font, desiredW, desiredH) {
1129
+ desiredW = Math.floor(desiredW);
1130
+ desiredH = Math.floor(desiredH);
1131
+ const { range, family } = font;
1132
+ let min = range.min;
1133
+ let max = range.max;
1134
+ const cache = /* @__PURE__ */ new Map();
1135
+ while (max - min >= 1) {
1136
+ const current = min + (max - min) / 2;
1137
+ if (!cache.has(current)) {
1138
+ c.font = `${current}px ${family}`;
1139
+ const metrics = c.measureText(text);
1140
+ const width2 = metrics.width;
1141
+ const height2 = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
1142
+ cache.set(current, { width: width2, height: height2 });
1143
+ }
1144
+ const { width, height } = cache.get(current);
1145
+ if (width > desiredW || height > desiredH) {
1146
+ max = current;
1147
+ } else {
1148
+ min = current;
1172
1149
  }
1173
- return {
1174
- text: '...',
1175
- width: ellipsisWidth
1176
- };
1150
+ }
1151
+ return Math.floor(min);
1177
1152
  }
1178
- function createFillBlock(color, x, y, width, height) {
1179
- return new Rect({
1180
- width,
1181
- height,
1182
- x,
1183
- y,
1184
- style: {
1185
- fill: color,
1186
- opacity: 1
1187
- }
1188
- });
1189
- }
1190
- function createTitleText(text, x, y, font, color) {
1191
- return new Text({
1192
- text,
1193
- x,
1194
- y,
1195
- style: {
1196
- fill: color,
1197
- textAlign: 'center',
1198
- baseline: 'middle',
1199
- font,
1200
- lineWidth: 1
1201
- }
1202
- });
1153
+ function getSafeText(c, text, width, cache) {
1154
+ let ellipsisWidth = 0;
1155
+ if (text in cache) {
1156
+ ellipsisWidth = cache[text];
1157
+ } else {
1158
+ ellipsisWidth = measureTextWidth(c, "...");
1159
+ cache[text] = ellipsisWidth;
1160
+ }
1161
+ if (width < ellipsisWidth) {
1162
+ return false;
1163
+ }
1164
+ const textWidth = measureTextWidth(c, text);
1165
+ if (textWidth < width) {
1166
+ return { text, width: textWidth };
1167
+ }
1168
+ return { text: "...", width: ellipsisWidth };
1203
1169
  }
1204
1170
  function resetLayout(treemap, w, h) {
1205
- treemap.layoutNodes = squarify(treemap.data, {
1206
- w,
1207
- h,
1208
- x: 0,
1209
- y: 0
1210
- }, treemap.decorator.layout);
1211
- treemap.reset();
1171
+ treemap.layoutNodes = squarify(treemap.data, { w, h, x: 0, y: 0 }, treemap.decorator.layout);
1172
+ treemap.reset();
1212
1173
  }
1213
- // https://www.typescriptlang.org/docs/handbook/mixins.html
1214
1174
  class Schedule extends etoile.Schedule {
1215
1175
  }
1216
1176
  class TreemapLayout extends Schedule {
1217
- data;
1218
- layoutNodes;
1219
- decorator;
1220
- bgBox;
1221
- fgBox;
1222
- constructor(...args){
1223
- super(...args);
1224
- this.data = [];
1225
- this.layoutNodes = [];
1226
- this.bgBox = new Box();
1227
- this.fgBox = new Box();
1228
- this.decorator = Object.create(null);
1229
- }
1230
- drawBackgroundNode(node) {
1231
- for (const child of node.children){
1232
- this.drawBackgroundNode(child);
1233
- }
1234
- const [x, y, w, h] = node.layout;
1235
- const { rectGap, titleHeight } = node.decorator;
1236
- const fill = this.decorator.color.mappings[node.node.id];
1237
- if (node.children.length) {
1238
- const box = new Box();
1239
- box.add(createFillBlock(fill, x, y, w, titleHeight), createFillBlock(fill, x, y + h - rectGap, w, rectGap), createFillBlock(fill, x, y + titleHeight, rectGap, h - titleHeight - rectGap), createFillBlock(fill, x + w - rectGap, y + titleHeight, rectGap, h - titleHeight - rectGap));
1240
- this.bgBox.add(box);
1241
- } else {
1242
- this.bgBox.add(createFillBlock(fill, x, y, w, h));
1243
- }
1244
- }
1245
- drawForegroundNode(node) {
1246
- for (const child of node.children){
1247
- this.drawForegroundNode(child);
1248
- }
1249
- const [x, y, w, h] = node.layout;
1250
- const { rectBorderWidth, titleHeight, rectGap } = node.decorator;
1251
- const { fontSize, fontFamily, color } = this.decorator.font;
1252
- const rect = new Rect({
1253
- x: x + 0.5,
1254
- y: y + 0.5,
1255
- width: w,
1256
- height: h,
1257
- style: {
1258
- stroke: '#222',
1259
- lineWidth: rectBorderWidth
1260
- }
1261
- });
1262
- this.fgBox.add(rect);
1263
- this.render.ctx.textBaseline = 'middle';
1264
- const optimalFontSize = evaluateOptimalFontSize(this.render.ctx, node.node.label, w - rectGap * 2, fontSize, fontFamily, node.children.length ? Math.round(titleHeight / 2) + rectGap : h);
1265
- this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
1266
- if (h > titleHeight) {
1267
- const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2);
1268
- if (!result) return;
1269
- const { text, width } = result;
1270
- const textX = x + Math.round((w - width) / 2);
1271
- let textY = y + Math.round(h / 2);
1272
- if (node.children.length) {
1273
- textY = y + Math.round(titleHeight / 2);
1274
- }
1275
- this.fgBox.add(createTitleText(text, textX, textY, `${optimalFontSize}px ${fontFamily}`, color));
1276
- } else {
1277
- const ellipsisWidth = 3 * charCodeWidth(this.render.ctx, 46);
1278
- const textX = x + Math.round((w - ellipsisWidth) / 2);
1279
- const textY = y + Math.round(h / 2);
1280
- this.fgBox.add(createTitleText('...', textX, textY, `${optimalFontSize}px ${fontFamily}`, color));
1281
- }
1282
- }
1283
- reset() {
1284
- this.bgBox.destory();
1285
- this.fgBox.destory();
1286
- this.remove(this.bgBox, this.fgBox);
1287
- for (const node of this.layoutNodes){
1288
- this.drawBackgroundNode(node);
1289
- this.drawForegroundNode(node);
1290
- }
1291
- this.add(this.bgBox, this.fgBox);
1292
- }
1293
- get api() {
1294
- return {
1295
- zoom: (node)=>{
1296
- this.event.emit('zoom', node);
1297
- }
1298
- };
1299
- }
1177
+ constructor(...args) {
1178
+ super(...args);
1179
+ __publicField(this, "data");
1180
+ __publicField(this, "layoutNodes");
1181
+ __publicField(this, "decorator");
1182
+ __publicField(this, "bgBox");
1183
+ __publicField(this, "fgBox");
1184
+ __publicField(this, "fontsCaches");
1185
+ __publicField(this, "ellispsisWidthCache");
1186
+ this.data = [];
1187
+ this.layoutNodes = [];
1188
+ this.bgBox = new Box();
1189
+ this.fgBox = new Box();
1190
+ this.decorator = /* @__PURE__ */ Object.create(null);
1191
+ this.fontsCaches = /* @__PURE__ */ Object.create(null);
1192
+ this.ellispsisWidthCache = /* @__PURE__ */ Object.create(null);
1193
+ }
1194
+ drawBackgroundNode(node) {
1195
+ const [x, y, w, h] = node.layout;
1196
+ const fill = this.decorator.color.mappings[node.node.id];
1197
+ const s = createFillBlock(x, y, w, h, { fill });
1198
+ this.bgBox.add(s);
1199
+ for (const child of node.children) {
1200
+ this.drawBackgroundNode(child);
1201
+ }
1202
+ }
1203
+ drawForegroundNode(node) {
1204
+ const [x, y, w, h] = node.layout;
1205
+ if (!w || !h) return;
1206
+ const { rectBorderWidth, titleHeight, rectGap } = node.decorator;
1207
+ const { fontSize, fontFamily, color } = this.decorator.font;
1208
+ this.fgBox.add(createFillBlock(x + 0.5, y + 0.5, w, h, { stroke: "#222", lineWidth: rectBorderWidth }));
1209
+ let optimalFontSize;
1210
+ if (node.node.id in this.fontsCaches) {
1211
+ optimalFontSize = this.fontsCaches[node.node.id];
1212
+ } else {
1213
+ optimalFontSize = evaluateOptimalFontSize(
1214
+ this.render.ctx,
1215
+ node.node.id,
1216
+ {
1217
+ range: fontSize,
1218
+ family: fontFamily
1219
+ },
1220
+ w - rectGap * 2,
1221
+ node.children.length ? Math.round(titleHeight / 2) + rectGap : h
1222
+ );
1223
+ this.fontsCaches[node.node.id] = optimalFontSize;
1224
+ }
1225
+ this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
1226
+ const result = getSafeText(this.render.ctx, node.node.id, w - rectGap * 2, this.ellispsisWidthCache);
1227
+ if (!result) return;
1228
+ if (result.width >= w || optimalFontSize >= h) return;
1229
+ const { text, width } = result;
1230
+ const textX = x + Math.round((w - width) / 2);
1231
+ const textY = y + (node.children.length ? Math.round(titleHeight / 2) : Math.round(h / 2));
1232
+ this.fgBox.add(createTitleText(text, textX, textY, `${optimalFontSize}px ${fontFamily}`, color));
1233
+ for (const child of node.children) {
1234
+ this.drawForegroundNode(child);
1235
+ }
1236
+ }
1237
+ reset() {
1238
+ this.bgBox.destory();
1239
+ this.fgBox.destory();
1240
+ this.remove(this.bgBox, this.fgBox);
1241
+ this.render.ctx.textBaseline = "middle";
1242
+ for (const node of this.layoutNodes) {
1243
+ this.drawBackgroundNode(node);
1244
+ this.drawForegroundNode(node);
1245
+ }
1246
+ this.add(this.bgBox, this.fgBox);
1247
+ }
1248
+ get api() {
1249
+ return {
1250
+ zoom: (node) => {
1251
+ this.event.emit("zoom", node);
1252
+ }
1253
+ };
1254
+ }
1300
1255
  }
1301
1256
  function createTreemap() {
1302
- let treemap = null;
1303
- let root = null;
1304
- const uses = [];
1305
- const context = {
1306
- init,
1307
- dispose,
1308
- setOptions,
1309
- resize,
1310
- use
1311
- };
1312
- function init(el) {
1313
- treemap = new TreemapLayout(el);
1314
- root = el;
1315
- }
1316
- function dispose() {
1317
- if (root && treemap) {
1318
- treemap.destory();
1319
- root.removeChild(root.firstChild);
1320
- root = null;
1321
- treemap = null;
1322
- }
1323
- }
1324
- function resize() {
1325
- if (!treemap || !root) return;
1326
- const { width, height } = root.getBoundingClientRect();
1327
- treemap.render.initOptions({
1328
- height,
1329
- width,
1330
- devicePixelRatio: window.devicePixelRatio
1331
- });
1332
- treemap.event.emit('cleanup:selfevent');
1333
- resetLayout(treemap, width, height);
1334
- treemap.update();
1335
- }
1336
- function setOptions(options) {
1337
- if (!treemap) {
1338
- throw new Error('Treemap not initialized');
1339
- }
1340
- treemap.data = bindParentForModule(options.data || []);
1341
- for (const registry of defaultRegistries){
1342
- registry(context, treemap, treemap.render);
1343
- }
1344
- for (const use of uses){
1345
- use(treemap);
1346
- }
1347
- resize();
1348
- }
1349
- function use(key, register) {
1350
- switch(key){
1351
- case 'decorator':
1352
- uses.push((treemap)=>register(treemap));
1353
- break;
1354
- }
1355
- }
1356
- return context;
1257
+ let treemap = null;
1258
+ let root = null;
1259
+ let installed = false;
1260
+ const uses = [];
1261
+ const context = {
1262
+ init,
1263
+ dispose,
1264
+ setOptions,
1265
+ resize,
1266
+ use,
1267
+ zoom
1268
+ };
1269
+ function init(el) {
1270
+ treemap = new TreemapLayout(el);
1271
+ root = el;
1272
+ }
1273
+ function dispose() {
1274
+ if (root && treemap) {
1275
+ treemap.destory();
1276
+ root.removeChild(root.firstChild);
1277
+ root = null;
1278
+ treemap = null;
1279
+ }
1280
+ }
1281
+ function resize() {
1282
+ if (!treemap || !root) return;
1283
+ const { width, height } = root.getBoundingClientRect();
1284
+ treemap.render.initOptions({ height, width, devicePixelRatio: window.devicePixelRatio });
1285
+ treemap.fontsCaches = /* @__PURE__ */ Object.create(null);
1286
+ treemap.event.emit("cleanup:selfevent");
1287
+ resetLayout(treemap, width, height);
1288
+ treemap.update();
1289
+ }
1290
+ function setOptions(options) {
1291
+ if (!treemap) {
1292
+ throw new Error("Treemap not initialized");
1293
+ }
1294
+ treemap.data = bindParentForModule(options.data || []);
1295
+ if (!installed) {
1296
+ for (const registry of defaultRegistries) {
1297
+ registry(context, treemap, treemap.render);
1298
+ }
1299
+ installed = true;
1300
+ }
1301
+ for (const use2 of uses) {
1302
+ use2(treemap);
1303
+ }
1304
+ resize();
1305
+ }
1306
+ function use(key, register) {
1307
+ switch (key) {
1308
+ case "decorator":
1309
+ uses.push((treemap2) => register(treemap2));
1310
+ break;
1311
+ }
1312
+ }
1313
+ function zoom(id) {
1314
+ if (!treemap) {
1315
+ throw new Error("treemap don't init.");
1316
+ }
1317
+ const node = findRelativeNodeById(id, treemap.layoutNodes);
1318
+ node && treemap.api.zoom(node);
1319
+ }
1320
+ return context;
1357
1321
  }
1358
1322
 
1359
1323
  const defaultLayoutOptions = {
1360
- titleAreaHeight: {
1361
- max: 80,
1362
- min: 20
1363
- },
1364
- rectGap: 5,
1365
- rectBorderRadius: 0.5,
1366
- rectBorderWidth: 1.5
1324
+ titleAreaHeight: {
1325
+ max: 80,
1326
+ min: 20
1327
+ },
1328
+ rectGap: 5,
1329
+ rectBorderRadius: 0.5,
1330
+ rectBorderWidth: 1.5
1367
1331
  };
1368
1332
  const defaultFontOptions = {
1369
- color: '#000',
1370
- fontSize: {
1371
- max: 38,
1372
- min: 7
1373
- },
1374
- fontFamily: 'sans-serif'
1333
+ color: "#000",
1334
+ fontSize: {
1335
+ max: 38,
1336
+ min: 7
1337
+ },
1338
+ fontFamily: "sans-serif"
1375
1339
  };
1376
1340
  function presetDecorator(app) {
1377
- Object.assign(app.decorator, {
1378
- layout: defaultLayoutOptions,
1379
- font: defaultFontOptions,
1380
- color: colorMappings(app)
1381
- });
1341
+ Object.assign(app.decorator, {
1342
+ layout: defaultLayoutOptions,
1343
+ font: defaultFontOptions,
1344
+ color: colorMappings(app)
1345
+ });
1382
1346
  }
1383
1347
  function colorDecorator(node, state) {
1384
- const depth = getNodeDepth(node);
1385
- let baseHue = 0;
1386
- let sweepAngle = Math.PI * 2;
1387
- const totalHueRange = Math.PI;
1388
- if (node.parent) {
1389
- sweepAngle = node.weight / node.parent.weight * sweepAngle;
1390
- baseHue = state.hue + sweepAngle / Math.PI * 180;
1391
- }
1392
- baseHue += sweepAngle;
1393
- const depthHueOffset = depth + totalHueRange / 10;
1394
- const finalHue = baseHue + depthHueOffset / 2;
1395
- const saturation = 0.6 + 0.4 * Math.max(0, Math.cos(finalHue));
1396
- const lightness = 0.5 + 0.2 * Math.max(0, Math.cos(finalHue + Math.PI * 2 / 3));
1397
- state.hue = baseHue;
1398
- return {
1399
- mode: 'hsl',
1400
- desc: {
1401
- h: finalHue,
1402
- s: Math.round(saturation * 100),
1403
- l: Math.round(lightness * 100)
1404
- }
1405
- };
1348
+ const depth = getNodeDepth(node);
1349
+ let baseHue = 0;
1350
+ let sweepAngle = Math.PI * 2;
1351
+ const totalHueRange = Math.PI;
1352
+ if (node.parent) {
1353
+ sweepAngle = node.weight / node.parent.weight * sweepAngle;
1354
+ baseHue = state.hue + sweepAngle / Math.PI * 180;
1355
+ }
1356
+ baseHue += sweepAngle;
1357
+ const depthHueOffset = depth + totalHueRange / 10;
1358
+ const finalHue = baseHue + depthHueOffset / 2;
1359
+ const saturation = 0.6 + 0.4 * Math.max(0, Math.cos(finalHue));
1360
+ const lightness = 0.5 + 0.2 * Math.max(0, Math.cos(finalHue + Math.PI * 2 / 3));
1361
+ state.hue = baseHue;
1362
+ return {
1363
+ mode: "hsl",
1364
+ desc: {
1365
+ h: finalHue,
1366
+ s: Math.round(saturation * 100),
1367
+ l: Math.round(lightness * 100)
1368
+ }
1369
+ };
1406
1370
  }
1407
1371
  function evaluateColorMappingByNode(node, state) {
1408
- const colorMappings = {};
1409
- if (node.groups && Array.isArray(node.groups)) {
1410
- for (const child of node.groups){
1411
- Object.assign(colorMappings, evaluateColorMappingByNode(child, state));
1412
- }
1413
- }
1414
- if (node.id) {
1415
- colorMappings[node.id] = colorDecorator(node, state);
1416
- }
1417
- return colorMappings;
1372
+ const colorMappings2 = {};
1373
+ if (node.groups && Array.isArray(node.groups)) {
1374
+ for (const child of node.groups) {
1375
+ Object.assign(colorMappings2, evaluateColorMappingByNode(child, state));
1376
+ }
1377
+ }
1378
+ if (node.id) {
1379
+ colorMappings2[node.id] = colorDecorator(node, state);
1380
+ }
1381
+ return colorMappings2;
1418
1382
  }
1419
1383
  function colorMappings(app) {
1420
- const colorMappings = {};
1421
- const state = {
1422
- hue: 0
1423
- };
1424
- for (const node of app.data){
1425
- Object.assign(colorMappings, evaluateColorMappingByNode(node, state));
1426
- }
1427
- return {
1428
- mappings: colorMappings
1429
- };
1384
+ const colorMappings2 = {};
1385
+ const state = {
1386
+ hue: 0
1387
+ };
1388
+ for (const node of app.data) {
1389
+ Object.assign(colorMappings2, evaluateColorMappingByNode(node, state));
1390
+ }
1391
+ return { mappings: colorMappings2 };
1430
1392
  }
1431
1393
 
1394
+ exports.TreemapLayout = TreemapLayout;
1432
1395
  exports.c2m = c2m;
1433
1396
  exports.createTreemap = createTreemap;
1434
1397
  exports.defaultFontOptions = defaultFontOptions;
1435
1398
  exports.defaultLayoutOptions = defaultLayoutOptions;
1399
+ exports.findRelativeNode = findRelativeNode;
1400
+ exports.findRelativeNodeById = findRelativeNodeById;
1436
1401
  exports.flattenModule = flatten;
1402
+ exports.getNodeDepth = getNodeDepth;
1437
1403
  exports.presetDecorator = presetDecorator;
1438
1404
  exports.sortChildrenByKey = sortChildrenByKey;
1405
+ exports.visit = visit;