@netless/telebox-insider 0.2.26 → 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/TeleBox/constants.d.ts +0 -3
  2. package/dist/TeleBox/index.d.ts +120 -91
  3. package/dist/TeleBox/typings.d.ts +40 -55
  4. package/dist/TeleBoxCollector/index.d.ts +25 -29
  5. package/dist/TeleBoxManager/MaxTitleBar/index.d.ts +13 -18
  6. package/dist/TeleBoxManager/constants.d.ts +0 -3
  7. package/dist/TeleBoxManager/index.d.ts +55 -18
  8. package/dist/TeleBoxManager/typings.d.ts +35 -28
  9. package/dist/TeleStage/index.d.ts +25 -0
  10. package/dist/TeleTitleBar/DefaultTitleBar/index.d.ts +6 -8
  11. package/dist/TeleTitleBar/typings.d.ts +3 -5
  12. package/dist/index.d.ts +0 -1
  13. package/dist/style.css +1 -1
  14. package/dist/telebox-insider.cjs.js +2 -2
  15. package/dist/telebox-insider.cjs.js.map +1 -1
  16. package/dist/telebox-insider.es.js +2 -2
  17. package/dist/telebox-insider.es.js.map +1 -1
  18. package/dist/utils.d.ts +0 -1
  19. package/package.json +6 -19
  20. package/src/TeleBox/constants.ts +0 -3
  21. package/src/TeleBox/index.ts +496 -678
  22. package/src/TeleBox/style.scss +1 -0
  23. package/src/TeleBox/typings.ts +40 -75
  24. package/src/TeleBoxCollector/index.ts +137 -159
  25. package/src/TeleBoxManager/MaxTitleBar/index.ts +82 -110
  26. package/src/TeleBoxManager/constants.ts +0 -3
  27. package/src/TeleBoxManager/index.ts +300 -326
  28. package/src/TeleBoxManager/typings.ts +42 -52
  29. package/src/TeleStage/index.ts +189 -0
  30. package/src/TeleStage/style.scss +49 -0
  31. package/src/TeleTitleBar/DefaultTitleBar/index.ts +48 -61
  32. package/src/TeleTitleBar/typings.ts +3 -9
  33. package/src/index.ts +0 -1
  34. package/src/utils.ts +0 -6
  35. package/dist/TeleBoxCollector/TeleBoxCollector.stories.d.ts +0 -5
  36. package/dist/TeleBoxManager/MaxTitleBar/MaxTitleBar.stories.d.ts +0 -7
  37. package/dist/TeleBoxManager/MaxTitleBar/MaxTitleBarReact.d.ts +0 -4
  38. package/dist/TeleBoxReact/TeleBox.stories.d.ts +0 -9
  39. package/dist/TeleBoxReact/index.d.ts +0 -17
  40. package/dist/TeleBoxReact/utils.d.ts +0 -2
  41. package/dist/TeleTitleBar/DefaultTitleBar/DefaultTitleBar.stories.d.ts +0 -4
  42. package/src/TeleBoxCollector/TeleBoxCollector.stories.tsx +0 -23
  43. package/src/TeleBoxManager/MaxTitleBar/MaxTitleBar.stories.tsx +0 -66
  44. package/src/TeleBoxManager/MaxTitleBar/MaxTitleBarReact.tsx +0 -34
  45. package/src/TeleBoxReact/TeleBox.stories.tsx +0 -74
  46. package/src/TeleBoxReact/index.tsx +0 -175
  47. package/src/TeleBoxReact/utils.ts +0 -14
  48. package/src/TeleTitleBar/DefaultTitleBar/DefaultTitleBar.stories.tsx +0 -15
@@ -1,49 +1,69 @@
1
- import EventEmitter from "eventemitter3";
2
1
  import shallowequal from "shallowequal";
2
+ import { ResizeObserver as ResizeObserverPolyfill } from "@juggle/resize-observer";
3
+ import { SideEffectManager } from "side-effect-manager";
4
+ import type {
5
+ ReadonlyVal,
6
+ ValEnhancedResult,
7
+ ReadonlyValEnhancedResult,
8
+ } from "value-enhancer";
9
+ import {
10
+ combine,
11
+ Val,
12
+ withValueEnhancer,
13
+ withReadonlyValueEnhancer,
14
+ } from "value-enhancer";
15
+ import Emittery from "emittery";
3
16
  import type {
4
- TeleBoxConfig,
17
+ ReadonlyTeleBox,
18
+ TeleBoxColorScheme,
5
19
  TeleBoxRect,
6
20
  TeleBoxState,
7
- } from "../TeleBox/typings";
21
+ } from "../TeleBox";
22
+ import {
23
+ TeleBox,
24
+ TELE_BOX_EVENT,
25
+ TELE_BOX_STATE,
26
+ TELE_BOX_COLOR_SCHEME,
27
+ TELE_BOX_DELEGATE_EVENT,
28
+ } from "../TeleBox";
8
29
  import { TeleBoxCollector } from "../TeleBoxCollector";
9
- import { ReadonlyTeleBox, TeleBox } from "../TeleBox";
10
- import { TELE_BOX_EVENT, TELE_BOX_STATE } from "../TeleBox/constants";
11
30
  import { TELE_BOX_MANAGER_EVENT } from "./constants";
12
31
  import type {
13
32
  TeleBoxManagerConfig,
14
33
  TeleBoxManagerCreateConfig,
15
- TeleBoxManagerEvents,
34
+ TeleBoxManagerEventConfig,
16
35
  TeleBoxManagerQueryConfig,
17
36
  TeleBoxManagerUpdateConfig,
18
37
  } from "./typings";
19
38
  import { MaxTitleBar } from "./MaxTitleBar";
20
- import {
21
- TeleBoxColorScheme,
22
- TELE_BOX_COLOR_SCHEME,
23
- TELE_BOX_DELEGATE_EVENT,
24
- } from "..";
25
- import { SideEffectManager } from "side-effect-manager";
26
- import {
27
- createSideEffectBinder,
28
- Val,
29
- ValEnhancedResult,
30
- withValueEnhancer,
31
- } from "value-enhancer";
39
+ import { TeleStage } from "../TeleStage";
32
40
 
33
41
  export * from "./typings";
34
42
  export * from "./constants";
35
43
 
44
+ const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
45
+
46
+ type ReadonlyValConfig = {
47
+ darkMode: ReadonlyVal<boolean, boolean>;
48
+ state: ReadonlyVal<TeleBoxState, boolean>;
49
+ rootRect: Val<TeleBoxRect>;
50
+ stageRect: ReadonlyVal<TeleBoxRect>;
51
+ };
52
+
36
53
  type ValConfig = {
37
54
  prefersColorScheme: Val<TeleBoxColorScheme, boolean>;
38
- containerRect: Val<TeleBoxRect, boolean>;
39
- collector: Val<TeleBoxCollector | null>;
40
- collectorRect: Val<TeleBoxRect | undefined>;
41
55
  readonly: Val<boolean, boolean>;
42
56
  minimized: Val<boolean, boolean>;
43
57
  maximized: Val<boolean, boolean>;
44
58
  fence: Val<boolean, boolean>;
59
+ stageRatio: Val<number, boolean>;
60
+ highlightStage: Val<boolean, boolean>;
45
61
  };
46
- export interface TeleBoxManager extends ValEnhancedResult<ValConfig> {}
62
+
63
+ type CombinedValEnhancedResult = ValEnhancedResult<ValConfig> &
64
+ ReadonlyValEnhancedResult<ReadonlyValConfig>;
65
+
66
+ export interface TeleBoxManager extends CombinedValEnhancedResult {}
47
67
 
48
68
  export class TeleBoxManager {
49
69
  public constructor({
@@ -51,91 +71,107 @@ export class TeleBoxManager {
51
71
  prefersColorScheme = TELE_BOX_COLOR_SCHEME.Light,
52
72
  minimized = false,
53
73
  maximized = false,
54
- fence = true,
55
- containerRect = {
56
- x: 0,
57
- y: 0,
58
- width: window.innerWidth,
59
- height: window.innerHeight,
60
- },
74
+ fence = false,
61
75
  collector,
62
76
  namespace = "telebox",
63
77
  readonly = false,
78
+ stageRatio = -1,
79
+ highlightStage = true,
64
80
  }: TeleBoxManagerConfig = {}) {
65
81
  this._sideEffect = new SideEffectManager();
66
- const { combine, createVal } = createSideEffectBinder(this._sideEffect);
67
82
 
68
83
  this.root = root;
69
84
  this.namespace = namespace;
70
85
 
71
- this.boxes$ = createVal<TeleBox[]>([]);
72
- this.topBox$ = this.boxes$.derive((boxes) => {
73
- if (boxes.length > 0) {
74
- const topBox = boxes.reduce((topBox, box) =>
75
- topBox.zIndex > box.zIndex ? topBox : box
86
+ const readonly$ = new Val(readonly);
87
+ const minimized$ = new Val(minimized);
88
+ const maximized$ = new Val(maximized);
89
+ const fence$ = new Val(fence);
90
+ const stageRatio$ = new Val(stageRatio);
91
+ const highlightStage$ = new Val(highlightStage);
92
+
93
+ const rootRect$ = new Val<TeleBoxRect>(
94
+ {
95
+ x: 0,
96
+ y: 0,
97
+ width: window.innerWidth,
98
+ height: window.innerHeight,
99
+ },
100
+ { compare: shallowequal }
101
+ );
102
+ this._sideEffect.add(() => {
103
+ const observer = new ResizeObserver((entries) => {
104
+ this._sideEffect.setTimeout(
105
+ // debounce
106
+ () => {
107
+ const rect = entries[0]?.contentRect;
108
+ if (rect) {
109
+ rootRect$.setValue({
110
+ x: rect.x,
111
+ y: rect.y,
112
+ width: rect.width,
113
+ height: rect.height,
114
+ });
115
+ }
116
+ },
117
+ 50,
118
+ "root-resize-observer"
76
119
  );
77
- return topBox;
78
- }
79
- return;
120
+ });
121
+ observer.observe(root);
122
+ return () => observer.disconnect();
80
123
  });
81
124
 
82
- const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
83
- const prefersDark$ = createVal(false);
125
+ this.boxes$ = new Val<TeleBox[]>([]);
126
+ this.topBox$ = new Val<TeleBox | undefined>(undefined);
127
+ this._sideEffect.addDisposer(
128
+ this.boxes$.subscribe((boxes) => {
129
+ if (boxes.length > 0) {
130
+ const topBox = boxes.reduce((topBox, box) =>
131
+ topBox.zIndex > box.zIndex ? topBox : box
132
+ );
133
+ this.topBox$.setValue(topBox);
134
+ } else {
135
+ this.topBox$.setValue(undefined);
136
+ }
137
+ })
138
+ );
84
139
 
85
- if (prefersDark) {
86
- prefersDark$.setValue(prefersDark.matches);
140
+ const prefersDarkMatch = window.matchMedia(
141
+ "(prefers-color-scheme: dark)"
142
+ );
143
+ const prefersDark$ = new Val(false);
144
+ if (prefersDarkMatch) {
145
+ prefersDark$.setValue(prefersDarkMatch.matches);
87
146
  this._sideEffect.add(() => {
88
147
  const handler = (evt: MediaQueryListEvent): void => {
89
148
  prefersDark$.setValue(evt.matches);
90
149
  };
91
- prefersDark.addListener(handler);
92
- return () => prefersDark.removeListener(handler);
150
+ prefersDarkMatch.addEventListener("change", handler);
151
+ return () =>
152
+ prefersDarkMatch.removeEventListener("change", handler);
93
153
  });
94
154
  }
95
155
 
96
- const prefersColorScheme$ = createVal(prefersColorScheme);
97
- prefersColorScheme$.reaction((prefersColorScheme, _, skipUpdate) => {
98
- this.boxes.forEach((box) =>
99
- box.setPrefersColorScheme(prefersColorScheme, skipUpdate)
100
- );
101
- if (!skipUpdate) {
102
- this.events.emit(
103
- TELE_BOX_MANAGER_EVENT.PrefersColorScheme,
104
- prefersColorScheme
105
- );
106
- }
107
- });
156
+ const prefersColorScheme$ = new Val(prefersColorScheme);
157
+ this._sideEffect.addDisposer(
158
+ prefersColorScheme$.reaction((prefersColorScheme, skipUpdate) => {
159
+ if (!skipUpdate) {
160
+ this.events.emit(
161
+ TELE_BOX_MANAGER_EVENT.PrefersColorScheme,
162
+ prefersColorScheme
163
+ );
164
+ }
165
+ })
166
+ );
108
167
 
109
- this._darkMode$ = combine(
168
+ const darkMode$ = combine(
110
169
  [prefersDark$, prefersColorScheme$],
111
170
  ([prefersDark, prefersColorScheme]) =>
112
171
  prefersColorScheme === "auto"
113
172
  ? prefersDark
114
173
  : prefersColorScheme === "dark"
115
174
  );
116
- this._darkMode$.reaction((darkMode, _, skipUpdate) => {
117
- this.boxes.forEach((box) => box.setDarkMode(darkMode, skipUpdate));
118
- if (!skipUpdate) {
119
- this.events.emit(TELE_BOX_MANAGER_EVENT.DarkMode, darkMode);
120
- }
121
- });
122
-
123
- const readonly$ = createVal(readonly);
124
- readonly$.reaction((readonly, _, skipUpdate) => {
125
- this.boxes.forEach((box) => box.setReadonly(readonly, skipUpdate));
126
- });
127
-
128
- const minimized$ = createVal(minimized);
129
-
130
- const maximized$ = createVal(maximized);
131
- maximized$.reaction((maximized, _, skipUpdate) => {
132
- this.boxes.forEach((box) =>
133
- box.setMaximized(maximized, skipUpdate)
134
- );
135
- if (!skipUpdate) {
136
- this.events.emit(TELE_BOX_MANAGER_EVENT.Maximized, maximized);
137
- }
138
- });
139
175
 
140
176
  const state$ = combine(
141
177
  [minimized$, maximized$],
@@ -146,101 +182,47 @@ export class TeleBoxManager {
146
182
  ? TELE_BOX_STATE.Maximized
147
183
  : TELE_BOX_STATE.Normal
148
184
  );
149
- state$.reaction((state, _, skipUpdate) => {
150
- this.maxTitleBar.setState(state);
151
- if (!skipUpdate) {
152
- this.events.emit(TELE_BOX_MANAGER_EVENT.State, state);
153
- }
154
- });
155
185
 
156
- const fence$ = createVal(fence);
157
- fence$.subscribe((fence, _, skipUpdate) => {
158
- this.boxes.forEach((box) => box.setFence(fence, skipUpdate));
159
- });
160
-
161
- const containerRect$ = createVal(containerRect, shallowequal);
162
- containerRect$.reaction((containerRect, _, skipUpdate) => {
163
- this.boxes.forEach((box) =>
164
- box.setContainerRect(containerRect, skipUpdate)
165
- );
166
- this.maxTitleBar.setContainerRect(containerRect);
167
- });
186
+ this.collector =
187
+ collector ??
188
+ new TeleBoxCollector({
189
+ minimized$: minimized$,
190
+ readonly$: readonly$,
191
+ darkMode$: darkMode$,
192
+ namespace,
193
+ root,
194
+ rootRect$,
195
+ });
168
196
 
169
- const collector$ = createVal(
170
- collector === null
171
- ? null
172
- : collector ||
173
- new TeleBoxCollector({
174
- visible: minimized,
175
- readonly: readonly,
176
- namespace,
177
- }).mount(root)
178
- );
179
- collector$.subscribe((collector) => {
180
- if (collector) {
181
- collector.setVisible(minimized$.value);
182
- collector.setReadonly(readonly$.value);
183
- collector.setDarkMode(this._darkMode$.value);
184
- this._sideEffect.add(() => {
185
- collector.onClick = () => {
186
- if (!readonly$.value) {
187
- minimized$.setValue(false);
188
- }
189
- };
190
- return () => collector.destroy();
191
- }, "collect-onClick");
192
- }
193
- });
194
- readonly$.subscribe((readonly) =>
195
- collector$.value?.setReadonly(readonly)
196
- );
197
- this._darkMode$.subscribe((darkMode) => {
198
- collector$.value?.setDarkMode(darkMode);
197
+ const teleStage = new TeleStage({
198
+ namespace,
199
+ rootRect$,
200
+ ratio$: stageRatio$,
201
+ root,
202
+ highlightStage$,
199
203
  });
204
+ this._sideEffect.addDisposer(() => teleStage.destroy());
200
205
 
201
- const calcCollectorRect = (): TeleBoxRect | undefined => {
202
- if (collector$.value?.$collector) {
203
- const { x, y, width, height } =
204
- collector$.value.$collector.getBoundingClientRect();
205
- const rootRect = this.root.getBoundingClientRect();
206
- return {
207
- x: x - rootRect.x,
208
- y: y - rootRect.y,
209
- width,
210
- height,
211
- };
212
- }
213
- return;
206
+ const readonlyValConfig: ReadonlyValConfig = {
207
+ darkMode: darkMode$,
208
+ state: state$,
209
+ rootRect: rootRect$,
210
+ stageRect: teleStage.stageRect$,
214
211
  };
215
212
 
216
- const collectorRect$ = createVal(
217
- minimized$.value ? calcCollectorRect() : void 0
218
- );
219
- collectorRect$.subscribe((collectorRect, _, skipUpdate) => {
220
- this.boxes.forEach((box) => {
221
- box.setCollectorRect(collectorRect, skipUpdate);
222
- });
223
- });
224
-
225
- minimized$.subscribe((minimized, _, skipUpdate) => {
226
- collector$.value?.setVisible(minimized);
227
-
228
- if (minimized) {
229
- if (collector$.value?.$collector) {
230
- collectorRect$.setValue(calcCollectorRect());
231
- } else if (import.meta.env.DEV) {
232
- console.warn("No collector for minimized boxes.");
233
- }
234
- }
213
+ withReadonlyValueEnhancer(this, readonlyValConfig);
235
214
 
236
- this.boxes.forEach((box) =>
237
- box.setMinimized(minimized, skipUpdate)
238
- );
215
+ const valConfig: ValConfig = {
216
+ prefersColorScheme: prefersColorScheme$,
217
+ readonly: readonly$,
218
+ fence: fence$,
219
+ minimized: minimized$,
220
+ maximized: maximized$,
221
+ stageRatio: stageRatio$,
222
+ highlightStage: highlightStage$,
223
+ };
239
224
 
240
- if (!skipUpdate) {
241
- this.events.emit(TELE_BOX_MANAGER_EVENT.Minimized, minimized);
242
- }
243
- });
225
+ withValueEnhancer(this, valConfig);
244
226
 
245
227
  const closeBtnClassName = this.wrapClassName("titlebar-icon-close");
246
228
 
@@ -287,13 +269,13 @@ export class TeleBoxManager {
287
269
  true
288
270
  );
289
271
 
290
- this.maxTitleBar = new MaxTitleBar({
291
- darkMode: this.darkMode,
292
- readonly: readonly$.value,
272
+ this.titleBar = new MaxTitleBar({
293
273
  namespace: this.namespace,
294
- state: state$.value,
295
- boxes: this.boxes$.value,
296
- containerRect: containerRect$.value,
274
+ boxes$: this.boxes$,
275
+ darkMode$: darkMode$,
276
+ readonly$: readonly$,
277
+ state$: state$,
278
+ rootRect$: rootRect$,
297
279
  onEvent: (event): void => {
298
280
  switch (event.type) {
299
281
  case TELE_BOX_DELEGATE_EVENT.Maximize: {
@@ -315,32 +297,37 @@ export class TeleBoxManager {
315
297
  }
316
298
  },
317
299
  });
318
- readonly$.subscribe((readonly) =>
319
- this.maxTitleBar.setReadonly(readonly)
320
- );
321
- this._darkMode$.subscribe((darkMode) => {
322
- this.maxTitleBar.setDarkMode(darkMode);
323
- });
324
- this.boxes$.reaction((boxes) => {
325
- this.maxTitleBar.setBoxes(boxes);
326
- });
327
-
328
- const valConfig: ValConfig = {
329
- prefersColorScheme: prefersColorScheme$,
330
- containerRect: containerRect$,
331
- collector: collector$,
332
- collectorRect: collectorRect$,
333
- readonly: readonly$,
334
- fence: fence$,
335
- minimized: minimized$,
336
- maximized: maximized$,
337
- };
338
300
 
339
- withValueEnhancer(this, valConfig);
340
-
341
- this._state$ = state$;
301
+ this.root.appendChild(this.titleBar.render());
342
302
 
343
- this.root.appendChild(this.maxTitleBar.render());
303
+ this._sideEffect.addDisposer([
304
+ state$.reaction((state, skipUpdate) => {
305
+ if (!skipUpdate) {
306
+ this.events.emit(TELE_BOX_MANAGER_EVENT.State, state);
307
+ }
308
+ }),
309
+ maximized$.reaction((maximized, skipUpdate) => {
310
+ if (!skipUpdate) {
311
+ this.events.emit(
312
+ TELE_BOX_MANAGER_EVENT.Maximized,
313
+ maximized
314
+ );
315
+ }
316
+ }),
317
+ minimized$.reaction((minimized, skipUpdate) => {
318
+ if (!skipUpdate) {
319
+ this.events.emit(
320
+ TELE_BOX_MANAGER_EVENT.Minimized,
321
+ minimized
322
+ );
323
+ }
324
+ }),
325
+ darkMode$.reaction((darkMode, skipUpdate) => {
326
+ if (!skipUpdate) {
327
+ this.events.emit(TELE_BOX_MANAGER_EVENT.DarkMode, darkMode);
328
+ }
329
+ }),
330
+ ]);
344
331
  }
345
332
 
346
333
  public get boxes(): ReadonlyArray<TeleBox> {
@@ -351,7 +338,10 @@ export class TeleBoxManager {
351
338
  return this.topBox$.value;
352
339
  }
353
340
 
354
- public readonly events = new EventEmitter() as TeleBoxManagerEvents;
341
+ public readonly events = new Emittery<
342
+ TeleBoxManagerEventConfig,
343
+ TeleBoxManagerEventConfig
344
+ >();
355
345
 
356
346
  protected _sideEffect: SideEffectManager;
357
347
 
@@ -359,18 +349,6 @@ export class TeleBoxManager {
359
349
 
360
350
  public readonly namespace: string;
361
351
 
362
- public _darkMode$: Val<boolean, boolean>;
363
-
364
- public get darkMode(): boolean {
365
- return this._darkMode$.value;
366
- }
367
-
368
- public _state$: Val<TeleBoxState, boolean>;
369
-
370
- public get state(): TeleBoxState {
371
- return this._state$.value;
372
- }
373
-
374
352
  /** @deprecated use setMaximized and setMinimized instead */
375
353
  public setState(state: TeleBoxState, skipUpdate = false): this {
376
354
  switch (state) {
@@ -399,16 +377,19 @@ export class TeleBoxManager {
399
377
  ): ReadonlyTeleBox {
400
378
  const box = new TeleBox({
401
379
  zIndex: this.topBox ? this.topBox.zIndex + 1 : 100,
402
- ...(smartPosition ? this.smartPosition(config) : config),
403
- darkMode: this.darkMode,
404
- prefersColorScheme: this.prefersColorScheme,
405
- maximized: this.maximized,
406
- minimized: this.minimized,
407
- fence: this.fence,
380
+ ...config,
381
+ ...(smartPosition ? this.smartPosition(config) : {}),
408
382
  namespace: this.namespace,
409
- containerRect: this.containerRect,
410
- readonly: this.readonly,
411
- collectorRect: this.collectorRect,
383
+ darkMode$: this._darkMode$,
384
+ maximized$: this._maximized$,
385
+ minimized$: this._minimized$,
386
+ fence$: this._fence$,
387
+ rootRect$: this._rootRect$,
388
+ managerStageRect$: this._stageRect$,
389
+ stageRatio$: this._stageRatio$,
390
+ readonly$: this._readonly$,
391
+ collectorRect$: this.collector._rect$,
392
+ managerHighlightStage$: this._highlightStage$,
412
393
  });
413
394
 
414
395
  box.mount(this.root);
@@ -422,52 +403,43 @@ export class TeleBoxManager {
422
403
 
423
404
  this.boxes$.setValue([...this.boxes, box]);
424
405
 
425
- box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Maximize, () => {
426
- this.setMaximized(!this.maximized);
427
- });
428
- box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Minimize, () => {
429
- this.setMinimized(true);
430
- });
431
- box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Close, () => {
432
- this.remove(box);
433
- this.focusTopBox();
434
- });
435
- box._coord$.reaction((_, __, skipUpdate) => {
436
- if (!skipUpdate) {
437
- this.events.emit(TELE_BOX_MANAGER_EVENT.Move, box);
438
- }
439
- });
440
- box._size$.reaction((_, __, skipUpdate) => {
441
- if (!skipUpdate) {
442
- this.events.emit(TELE_BOX_MANAGER_EVENT.Resize, box);
443
- }
444
- });
445
- box._intrinsicCoord$.reaction((_, __, skipUpdate) => {
446
- if (!skipUpdate) {
447
- this.events.emit(TELE_BOX_MANAGER_EVENT.IntrinsicMove, box);
448
- }
449
- });
450
- box._intrinsicSize$.reaction((_, __, skipUpdate) => {
451
- if (!skipUpdate) {
452
- this.events.emit(TELE_BOX_MANAGER_EVENT.IntrinsicResize, box);
453
- }
454
- });
455
- box._visualSize$.reaction((_, __, skipUpdate) => {
456
- if (!skipUpdate) {
457
- this.events.emit(TELE_BOX_MANAGER_EVENT.VisualResize, box);
458
- }
459
- });
460
- box._zIndex$.reaction((_, __, skipUpdate) => {
461
- if (this.boxes.length > 0) {
462
- const topBox = this.boxes.reduce((topBox, box) =>
463
- topBox.zIndex > box.zIndex ? topBox : box
464
- );
465
- this.topBox$.setValue(topBox);
466
- }
467
- if (!skipUpdate) {
468
- this.events.emit(TELE_BOX_MANAGER_EVENT.ZIndex, box);
469
- }
470
- });
406
+ this._sideEffect.addDisposer([
407
+ box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Maximize, () => {
408
+ this.setMaximized(!this.maximized);
409
+ }),
410
+ box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Minimize, () => {
411
+ this.setMinimized(true);
412
+ }),
413
+ box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Close, () => {
414
+ this.remove(box);
415
+ this.focusTopBox();
416
+ }),
417
+ box._intrinsicCoord$.reaction((_, skipUpdate) => {
418
+ if (!skipUpdate) {
419
+ this.events.emit(TELE_BOX_MANAGER_EVENT.IntrinsicMove, box);
420
+ }
421
+ }),
422
+ box._intrinsicSize$.reaction((_, skipUpdate) => {
423
+ if (!skipUpdate) {
424
+ this.events.emit(
425
+ TELE_BOX_MANAGER_EVENT.IntrinsicResize,
426
+ box
427
+ );
428
+ }
429
+ }),
430
+ box._zIndex$.reaction((_, skipUpdate) => {
431
+ if (this.boxes.length > 0) {
432
+ const topBox = this.boxes.reduce((topBox, box) =>
433
+ topBox.zIndex > box.zIndex ? topBox : box
434
+ );
435
+ this.topBox$.setValue(topBox);
436
+ }
437
+ if (!skipUpdate) {
438
+ this.events.emit(TELE_BOX_MANAGER_EVENT.ZIndex, box);
439
+ }
440
+ }),
441
+ ]);
442
+
471
443
  this.events.emit(TELE_BOX_MANAGER_EVENT.Created, box);
472
444
 
473
445
  return box;
@@ -551,16 +523,11 @@ export class TeleBoxManager {
551
523
  }
552
524
 
553
525
  public destroy(skipUpdate = false): void {
554
- this.events.removeAllListeners();
526
+ this.events.clearListeners();
555
527
  this._sideEffect.flushAll();
556
528
  this.removeAll(skipUpdate);
557
-
558
- Object.keys(this).forEach((key) => {
559
- const value = this[key as keyof this];
560
- if (value instanceof Val) {
561
- value.destroy();
562
- }
563
- });
529
+ this.collector.destroy();
530
+ this.titleBar.destroy();
564
531
  }
565
532
 
566
533
  public wrapClassName(className: string): string {
@@ -575,7 +542,7 @@ export class TeleBoxManager {
575
542
  let focusChanged = false;
576
543
  if (!targetBox.focus) {
577
544
  focusChanged = true;
578
- targetBox.setFocus(true, skipUpdate);
545
+ targetBox._focus$.setValue(true, skipUpdate);
579
546
  }
580
547
  if (focusChanged && !skipUpdate) {
581
548
  this.events.emit(
@@ -587,7 +554,7 @@ export class TeleBoxManager {
587
554
  this.blurBox(box, skipUpdate);
588
555
  }
589
556
  });
590
- this.maxTitleBar.focusBox(targetBox);
557
+ this.titleBar.focusBox(targetBox);
591
558
  }
592
559
  }
593
560
 
@@ -601,13 +568,13 @@ export class TeleBoxManager {
601
568
  const targetBox = this.getBox(boxOrID);
602
569
  if (targetBox) {
603
570
  if (targetBox.focus) {
604
- targetBox.setFocus(false, skipUpdate);
571
+ targetBox._focus$.setValue(false, skipUpdate);
605
572
  if (!skipUpdate) {
606
573
  this.events.emit(TELE_BOX_MANAGER_EVENT.Blurred, targetBox);
607
574
  }
608
575
  }
609
- if (this.maxTitleBar.focusedBox === targetBox) {
610
- this.maxTitleBar.focusBox();
576
+ if (this.titleBar.focusedBox === targetBox) {
577
+ this.titleBar.focusBox();
611
578
  }
612
579
  }
613
580
  }
@@ -615,18 +582,19 @@ export class TeleBoxManager {
615
582
  public blurAll(skipUpdate = false): void {
616
583
  this.boxes.forEach((box) => {
617
584
  if (box.focus) {
618
- box.setFocus(false, skipUpdate);
585
+ box._focus$.setValue(false, skipUpdate);
619
586
  if (!skipUpdate) {
620
587
  this.events.emit(TELE_BOX_MANAGER_EVENT.Blurred, box);
621
588
  }
622
589
  }
623
590
  });
624
- if (this.maxTitleBar.focusedBox) {
625
- this.maxTitleBar.focusBox();
591
+ if (this.titleBar.focusedBox) {
592
+ this.titleBar.focusBox();
626
593
  }
627
594
  }
628
595
 
629
- protected maxTitleBar: MaxTitleBar;
596
+ public collector: TeleBoxCollector;
597
+ public titleBar: MaxTitleBar;
630
598
 
631
599
  protected boxes$: Val<TeleBox[]>;
632
600
  protected topBox$: Val<TeleBox | undefined>;
@@ -647,43 +615,40 @@ export class TeleBoxManager {
647
615
  skipUpdate = false
648
616
  ): void {
649
617
  if (config.x != null || config.y != null) {
650
- box.move(
651
- config.x == null ? box.intrinsicX : config.x,
652
- config.y == null ? box.intrinsicY : config.y,
618
+ box._intrinsicCoord$.setValue(
619
+ {
620
+ x: config.x ?? box.intrinsicX,
621
+ y: config.y ?? box.intrinsicY,
622
+ },
653
623
  skipUpdate
654
624
  );
655
625
  }
656
626
  if (config.width != null || config.height != null) {
657
- box.resize(
658
- config.width == null ? box.intrinsicWidth : config.width,
659
- config.height == null ? box.intrinsicHeight : config.height,
627
+ box._intrinsicSize$.setValue(
628
+ {
629
+ width: config.width ?? box.intrinsicWidth,
630
+ height: config.height ?? box.intrinsicHeight,
631
+ },
660
632
  skipUpdate
661
633
  );
662
634
  }
663
635
  if (config.title != null) {
664
- box.setTitle(config.title);
665
- this.maxTitleBar.updateTitles();
636
+ box._title$.setValue(config.title);
666
637
  }
667
638
  if (config.visible != null) {
668
- box.setVisible(config.visible, skipUpdate);
669
- }
670
- if (config.minHeight != null) {
671
- box.setMinHeight(config.minHeight, skipUpdate);
672
- }
673
- if (config.minWidth != null) {
674
- box.setMinWidth(config.minWidth, skipUpdate);
639
+ box._visible$.setValue(config.visible, skipUpdate);
675
640
  }
676
641
  if (config.resizable != null) {
677
- box.setResizable(config.resizable, skipUpdate);
642
+ box._resizable$.setValue(config.resizable, skipUpdate);
678
643
  }
679
644
  if (config.draggable != null) {
680
- box.setDraggable(config.draggable, skipUpdate);
645
+ box._draggable$.setValue(config.draggable, skipUpdate);
681
646
  }
682
- if (config.fixRatio != null) {
683
- box.setFixRatio(config.fixRatio, skipUpdate);
647
+ if (config.ratio != null) {
648
+ box._ratio$.setValue(config.ratio, skipUpdate);
684
649
  }
685
650
  if (config.zIndex != null) {
686
- box.setZIndex(config.zIndex, skipUpdate);
651
+ box._zIndex$.setValue(config.zIndex, skipUpdate);
687
652
  }
688
653
  if (config.content != null) {
689
654
  box.mountContent(config.content);
@@ -691,52 +656,61 @@ export class TeleBoxManager {
691
656
  if (config.footer != null) {
692
657
  box.mountFooter(config.footer);
693
658
  }
659
+ if (config.minHeight != null || config.minWidth != null) {
660
+ box._minSize$.setValue(
661
+ {
662
+ width: config.minWidth ?? box.minWidth,
663
+ height: config.minHeight ?? box.minHeight,
664
+ },
665
+ skipUpdate
666
+ );
667
+ }
694
668
  }
695
669
 
696
- protected smartPosition(config: TeleBoxConfig = {}): TeleBoxConfig {
697
- let { x, y } = config;
698
- const { width = 0.5, height = 0.5 } = config;
670
+ /** Keep new boxes staggered inside stage area */
671
+ protected smartPosition(rect: Partial<TeleBoxRect>): TeleBoxRect {
672
+ let { x, y } = rect;
673
+ const { width = 0.5, height = 0.5 } = rect;
674
+ const stageRect = this.stageRect;
675
+ const topBox = this.topBox;
699
676
 
700
677
  if (x == null) {
701
- let vx = 20;
702
- if (this.topBox) {
703
- vx = this.topBox.intrinsicX * this.containerRect.width + 20;
704
-
678
+ let pxX = stageRect.x + 20;
679
+ if (topBox) {
680
+ const pxPreferredX = topBox.pxIntrinsicCoord.x + 20;
681
+ const pxIntrinsicWidth = width * stageRect.width;
705
682
  if (
706
- vx >
707
- this.containerRect.width - width * this.containerRect.width
683
+ pxPreferredX + pxIntrinsicWidth <=
684
+ stageRect.x + stageRect.width
708
685
  ) {
709
- vx = 20;
686
+ pxX = pxPreferredX;
710
687
  }
711
688
  }
712
- x = vx / this.containerRect.width;
689
+ x = (pxX - stageRect.x) / stageRect.width;
713
690
  }
714
691
 
715
692
  if (y == null) {
716
- let vy = 20;
717
-
718
- if (this.topBox) {
719
- vy = this.topBox.intrinsicY * this.containerRect.height + 20;
720
-
693
+ let pxY = stageRect.y + 20;
694
+ if (topBox) {
695
+ const pxPreferredY = topBox.pxIntrinsicCoord.y + 20;
696
+ const pxIntrinsicHeight = height * stageRect.height;
721
697
  if (
722
- vy >
723
- this.containerRect.height -
724
- height * this.containerRect.height
698
+ pxPreferredY + pxIntrinsicHeight <=
699
+ stageRect.y + stageRect.height
725
700
  ) {
726
- vy = 20;
701
+ pxY = pxPreferredY;
727
702
  }
728
703
  }
729
-
730
- y = vy / this.containerRect.height;
704
+ y = (pxY - stageRect.y) / stageRect.height;
731
705
  }
732
706
 
733
- return { ...config, x, y, width, height };
707
+ return { x, y, width, height };
734
708
  }
735
709
 
736
710
  protected makeBoxTop(box: TeleBox, skipUpdate = false): void {
737
711
  if (this.topBox) {
738
712
  if (box !== this.topBox) {
739
- box.setZIndex(this.topBox.zIndex + 1, skipUpdate);
713
+ box._zIndex$.setValue(this.topBox.zIndex + 1, skipUpdate);
740
714
  }
741
715
  }
742
716
  }