@netless/telebox-insider 0.2.25 → 1.0.0-alpha.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.
Files changed (52) hide show
  1. package/dist/TeleBox/constants.d.ts +0 -3
  2. package/dist/TeleBox/index.d.ts +118 -97
  3. package/dist/TeleBox/typings.d.ts +42 -55
  4. package/dist/TeleBoxCollector/index.d.ts +25 -29
  5. package/dist/TeleBoxManager/MaxTitleBar/index.d.ts +14 -18
  6. package/dist/TeleBoxManager/constants.d.ts +0 -3
  7. package/dist/TeleBoxManager/index.d.ts +64 -19
  8. package/dist/TeleBoxManager/typings.d.ts +35 -28
  9. package/dist/TeleStage/index.d.ts +21 -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 +1 -15
  15. package/dist/telebox-insider.cjs.js.map +1 -1
  16. package/dist/telebox-insider.es.js +1 -15
  17. package/dist/telebox-insider.es.js.map +1 -1
  18. package/dist/utils.d.ts +0 -1
  19. package/package.json +7 -19
  20. package/src/TeleBox/constants.ts +0 -3
  21. package/src/TeleBox/index.ts +500 -690
  22. package/src/TeleBox/style.scss +6 -0
  23. package/src/TeleBox/typings.ts +42 -75
  24. package/src/TeleBoxCollector/index.ts +136 -159
  25. package/src/TeleBoxCollector/style.scss +3 -0
  26. package/src/TeleBoxManager/MaxTitleBar/index.ts +95 -108
  27. package/src/TeleBoxManager/MaxTitleBar/style.scss +3 -1
  28. package/src/TeleBoxManager/constants.ts +0 -3
  29. package/src/TeleBoxManager/index.ts +329 -336
  30. package/src/TeleBoxManager/typings.ts +42 -52
  31. package/src/TeleStage/index.ts +178 -0
  32. package/src/TeleStage/style.scss +49 -0
  33. package/src/TeleTitleBar/DefaultTitleBar/index.ts +48 -61
  34. package/src/TeleTitleBar/DefaultTitleBar/style.scss +7 -0
  35. package/src/TeleTitleBar/typings.ts +3 -9
  36. package/src/index.ts +0 -1
  37. package/src/scss/mixins.scss +7 -0
  38. package/src/utils.ts +0 -6
  39. package/dist/TeleBoxCollector/TeleBoxCollector.stories.d.ts +0 -5
  40. package/dist/TeleBoxManager/MaxTitleBar/MaxTitleBar.stories.d.ts +0 -7
  41. package/dist/TeleBoxManager/MaxTitleBar/MaxTitleBarReact.d.ts +0 -4
  42. package/dist/TeleBoxReact/TeleBox.stories.d.ts +0 -9
  43. package/dist/TeleBoxReact/index.d.ts +0 -17
  44. package/dist/TeleBoxReact/utils.d.ts +0 -2
  45. package/dist/TeleTitleBar/DefaultTitleBar/DefaultTitleBar.stories.d.ts +0 -4
  46. package/src/TeleBoxCollector/TeleBoxCollector.stories.tsx +0 -23
  47. package/src/TeleBoxManager/MaxTitleBar/MaxTitleBar.stories.tsx +0 -66
  48. package/src/TeleBoxManager/MaxTitleBar/MaxTitleBarReact.tsx +0 -34
  49. package/src/TeleBoxReact/TeleBox.stories.tsx +0 -74
  50. package/src/TeleBoxReact/index.tsx +0 -175
  51. package/src/TeleBoxReact/utils.ts +0 -14
  52. package/src/TeleTitleBar/DefaultTitleBar/DefaultTitleBar.stories.tsx +0 -15
@@ -1,21 +1,22 @@
1
1
  import "./style.scss";
2
2
 
3
- import EventEmitter from "eventemitter3";
3
+ import Emittery from "emittery";
4
4
  import styler from "stylefire";
5
5
  import shallowequal from "shallowequal";
6
- import { SideEffectManager } from "side-effect-manager";
7
- import {
8
- createSideEffectBinder,
9
- Val,
6
+ import { genUID, SideEffectManager } from "side-effect-manager";
7
+ import type {
8
+ ReadonlyVal,
9
+ ReadonlyValEnhancedResult,
10
10
  ValEnhancedResult,
11
- ValSideEffectBinder,
12
- withValueEnhancer,
13
11
  } from "value-enhancer";
14
- import { DefaultTitleBar, TeleTitleBar } from "../TeleTitleBar";
12
+ import { withValueEnhancer } from "value-enhancer";
13
+ import { combine, Val, withReadonlyValueEnhancer } from "value-enhancer";
14
+ import type { TeleTitleBar } from "../TeleTitleBar";
15
+ import { DefaultTitleBar } from "../TeleTitleBar";
16
+ import { ResizeObserver as ResizeObserverPolyfill } from "@juggle/resize-observer";
15
17
  import {
16
18
  clamp,
17
19
  flattenEvent,
18
- genUniqueKey,
19
20
  getBoxDefaultName,
20
21
  isFalsy,
21
22
  isTruthy,
@@ -25,61 +26,75 @@ import {
25
26
  TELE_BOX_EVENT,
26
27
  TELE_BOX_STATE,
27
28
  TELE_BOX_RESIZE_HANDLE,
28
- TELE_BOX_DELEGATE_EVENT,
29
- TELE_BOX_COLOR_SCHEME,
30
29
  } from "./constants";
31
30
  import type {
32
31
  TeleBoxConfig,
33
- TeleBoxRect,
34
- TeleBoxEvents,
35
32
  TeleBoxHandleType,
36
33
  TeleBoxState,
37
- TeleBoxDelegateEvents,
38
34
  TeleBoxCoord,
39
35
  TeleBoxSize,
40
- TeleBoxColorScheme,
36
+ TeleBoxEventConfig,
37
+ TeleBoxEvent,
38
+ TeleBoxDelegateEventConfig,
39
+ TeleBoxRect,
41
40
  } from "./typings";
41
+ import { TeleStage } from "../TeleStage";
42
42
 
43
43
  export * from "./constants";
44
44
  export * from "./typings";
45
45
 
46
+ const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
47
+
48
+ type RequiredTeleBoxConfig = Required<TeleBoxConfig>;
49
+
46
50
  type ValConfig = {
47
- prefersColorScheme: Val<TeleBoxColorScheme, boolean>;
48
- darkMode: Val<boolean, boolean>;
49
- containerRect: Val<TeleBoxRect, boolean>;
50
- collectorRect: Val<TeleBoxRect | undefined, boolean>;
51
- /** Box title. Default empty. */
52
- title: Val<string, boolean>;
53
- /** Is box visible */
54
- visible: Val<boolean, boolean>;
55
- /** Is box readonly */
56
- readonly: Val<boolean, boolean>;
57
- /** Able to resize box window */
58
- resizable: Val<boolean, boolean>;
59
- /** Able to drag box window */
60
- draggable: Val<boolean, boolean>;
61
- /** Restrict box to always be within the containing area. */
62
- fence: Val<boolean, boolean>;
63
- /** Fixed width/height ratio for box window. */
64
- fixRatio: Val<boolean, boolean>;
65
- focus: Val<boolean, boolean>;
66
- zIndex: Val<number, boolean>;
67
- /** Is box minimized. Default false. */
68
- minimized: Val<boolean, boolean>;
69
- /** Is box maximized. Default false. */
70
- maximized: Val<boolean, boolean>;
71
- $userContent: Val<HTMLElement | undefined>;
72
- $userFooter: Val<HTMLElement | undefined>;
73
- $userStyles: Val<HTMLStyleElement | undefined>;
51
+ title: Val<RequiredTeleBoxConfig["title"], boolean>;
52
+ visible: Val<RequiredTeleBoxConfig["visible"], boolean>;
53
+ resizable: Val<RequiredTeleBoxConfig["resizable"], boolean>;
54
+ draggable: Val<RequiredTeleBoxConfig["draggable"], boolean>;
55
+ ratio: Val<RequiredTeleBoxConfig["ratio"], boolean>;
56
+ };
57
+
58
+ type ReadonlyValConfig = {
59
+ darkMode: RequiredTeleBoxConfig["darkMode$"];
60
+ fence: RequiredTeleBoxConfig["fence$"];
61
+ minimized: RequiredTeleBoxConfig["minimized$"];
62
+ maximized: RequiredTeleBoxConfig["maximized$"];
63
+ readonly: RequiredTeleBoxConfig["readonly$"];
64
+ rootRect: RequiredTeleBoxConfig["rootRect$"];
65
+ managerStageRect: RequiredTeleBoxConfig["managerStageRect$"];
66
+ collectorRect: RequiredTeleBoxConfig["collectorRect$"];
67
+
68
+ zIndex: Val<RequiredTeleBoxConfig["zIndex"], boolean>;
69
+ focus: Val<RequiredTeleBoxConfig["focus"], boolean>;
70
+
71
+ $userContent: Val<TeleBoxConfig["content"], boolean>;
72
+ $userFooter: Val<TeleBoxConfig["footer"], boolean>;
73
+ $userStyles: Val<TeleBoxConfig["styles"], boolean>;
74
+
75
+ minSize: Val<TeleBoxSize, boolean>;
76
+ intrinsicSize: Val<TeleBoxSize, boolean>;
77
+ intrinsicCoord: Val<TeleBoxCoord, boolean>;
78
+ pxMinSize: ReadonlyVal<TeleBoxSize, boolean>;
79
+ pxIntrinsicSize: ReadonlyVal<TeleBoxSize, boolean>;
80
+ pxIntrinsicCoord: ReadonlyVal<TeleBoxCoord, boolean>;
81
+ state: ReadonlyVal<TeleBoxState, boolean>;
82
+ highlightStage: ReadonlyVal<boolean, boolean>;
83
+ boxHighlightStage: Val<boolean | null, boolean>;
84
+ contentRect: Val<TeleBoxRect>;
85
+ contentStageRect: ReadonlyVal<TeleBoxRect | null>;
74
86
  };
75
- export interface TeleBox extends ValEnhancedResult<ValConfig> {}
87
+
88
+ type CombinedValEnhancedResult = ReadonlyValEnhancedResult<ReadonlyValConfig> &
89
+ ValEnhancedResult<ValConfig>;
90
+
91
+ export interface TeleBox extends CombinedValEnhancedResult {}
76
92
 
77
93
  export class TeleBox {
78
94
  public constructor({
79
- id = genUniqueKey(),
95
+ id = genUID(),
80
96
  title = getBoxDefaultName(),
81
- prefersColorScheme = TELE_BOX_COLOR_SCHEME.Light,
82
- darkMode,
97
+ namespace = "telebox",
83
98
  visible = true,
84
99
  width = 0.5,
85
100
  height = 0.5,
@@ -87,146 +102,43 @@ export class TeleBox {
87
102
  minHeight = 0,
88
103
  x = 0.1,
89
104
  y = 0.1,
90
- minimized = false,
91
- maximized = false,
92
- readonly = false,
93
105
  resizable = true,
94
106
  draggable = true,
95
- fence = true,
96
- fixRatio = false,
107
+ ratio = -1,
97
108
  focus = false,
98
109
  zIndex = 100,
99
- namespace = "telebox",
100
110
  titleBar,
101
111
  content,
102
112
  footer,
103
113
  styles,
104
- containerRect = {
105
- x: 0,
106
- y: 0,
107
- width: window.innerWidth,
108
- height: window.innerHeight,
109
- },
110
- collectorRect,
111
- }: TeleBoxConfig = {}) {
114
+ highlightStage = null,
115
+ darkMode$,
116
+ fence$,
117
+ minimized$,
118
+ maximized$,
119
+ readonly$,
120
+ root$,
121
+ rootRect$,
122
+ managerStageRect$,
123
+ stageRatio$,
124
+ collectorRect$,
125
+ managerHighlightStage$,
126
+ }: TeleBoxConfig) {
112
127
  this._sideEffect = new SideEffectManager();
113
- this._valSideEffectBinder = createSideEffectBinder(this._sideEffect);
114
- const { combine, createVal } = this._valSideEffectBinder;
115
128
 
116
129
  this.id = id;
117
130
  this.namespace = namespace;
118
- this.events = new EventEmitter();
119
- this._delegateEvents = new EventEmitter();
120
-
121
- const prefersColorScheme$ = createVal<TeleBoxColorScheme, boolean>(
122
- prefersColorScheme
123
- );
124
- prefersColorScheme$.reaction((prefersColorScheme, _, skipUpdate) => {
125
- if (!skipUpdate) {
126
- this.events.emit(
127
- TELE_BOX_EVENT.PrefersColorScheme,
128
- prefersColorScheme
129
- );
130
- }
131
- });
132
-
133
- const darkMode$ = createVal(Boolean(darkMode));
134
-
135
- if (darkMode == null) {
136
- prefersColorScheme$.subscribe(
137
- (prefersColorScheme, _, skipUpdate) => {
138
- this._sideEffect.add(() => {
139
- if (prefersColorScheme === "auto") {
140
- const prefersDark = window.matchMedia(
141
- "(prefers-color-scheme: dark)"
142
- );
143
- if (prefersDark) {
144
- darkMode$.setValue(
145
- prefersDark.matches,
146
- skipUpdate
147
- );
148
- const handler = (
149
- evt: MediaQueryListEvent
150
- ): void => {
151
- darkMode$.setValue(evt.matches, skipUpdate);
152
- };
153
- prefersDark.addListener(handler);
154
- return () =>
155
- prefersDark.removeListener(handler);
156
- } else {
157
- return noop;
158
- }
159
- } else {
160
- darkMode$.setValue(
161
- prefersColorScheme === "dark",
162
- skipUpdate
163
- );
164
- return noop;
165
- }
166
- }, "prefers-color-scheme");
167
- }
168
- );
169
- }
170
-
171
- darkMode$.reaction((darkMode, _, skipUpdate) => {
172
- if (!skipUpdate) {
173
- this.events.emit(TELE_BOX_EVENT.DarkMode, darkMode);
174
- }
175
- });
176
-
177
- const containerRect$ = createVal(containerRect, shallowequal);
178
- const collectorRect$ = createVal(collectorRect, shallowequal);
179
-
180
- const title$ = createVal(title);
181
-
182
- const visible$ = createVal(visible);
183
- visible$.reaction((visible, _, skipUpdate) => {
184
- if (!skipUpdate && !visible) {
185
- this.events.emit(TELE_BOX_EVENT.Close);
186
- }
187
- });
188
-
189
- const readonly$ = createVal(readonly);
190
- readonly$.reaction((readonly, _, skipUpdate) => {
191
- if (!skipUpdate) {
192
- this.events.emit(TELE_BOX_EVENT.Readonly, readonly);
193
- }
194
- });
195
-
196
- const resizable$ = createVal(resizable);
197
- const draggable$ = createVal(draggable);
198
- const fence$ = createVal(fence);
199
- const fixRatio$ = createVal(fixRatio);
200
-
201
- const zIndex$ = createVal(zIndex);
202
- zIndex$.reaction((zIndex, _, skipUpdate) => {
203
- if (!skipUpdate) {
204
- this.events.emit(TELE_BOX_EVENT.ZIndex, zIndex);
205
- }
206
- });
207
-
208
- const focus$ = createVal(focus);
209
- focus$.reaction((focus, _, skipUpdate) => {
210
- if (!skipUpdate) {
211
- this.events.emit(
212
- focus ? TELE_BOX_EVENT.Focus : TELE_BOX_EVENT.Blur
213
- );
214
- }
215
- });
216
131
 
217
- const minimized$ = createVal(minimized);
218
- minimized$.reaction((minimized, _, skipUpdate) => {
219
- if (!skipUpdate) {
220
- this.events.emit(TELE_BOX_EVENT.Minimized, minimized);
221
- }
222
- });
223
-
224
- const maximized$ = createVal(maximized);
225
- maximized$.reaction((maximized, _, skipUpdate) => {
226
- if (!skipUpdate) {
227
- this.events.emit(TELE_BOX_EVENT.Maximized, maximized);
228
- }
229
- });
132
+ const title$ = new Val(title);
133
+ const visible$ = new Val(visible);
134
+ const resizable$ = new Val(resizable);
135
+ const draggable$ = new Val(draggable);
136
+ const ratio$ = new Val(ratio);
137
+ const zIndex$ = new Val(zIndex);
138
+ const focus$ = new Val(focus);
139
+ const $userContent$ = new Val(content);
140
+ const $userFooter$ = new Val(footer);
141
+ const $userStyles$ = new Val(styles);
230
142
 
231
143
  const state$ = combine(
232
144
  [minimized$, maximized$],
@@ -237,232 +149,218 @@ export class TeleBox {
237
149
  ? TELE_BOX_STATE.Maximized
238
150
  : TELE_BOX_STATE.Normal
239
151
  );
240
- state$.reaction((state, _, skipUpdate) => {
241
- if (!skipUpdate) {
242
- this.events.emit(TELE_BOX_EVENT.State, state);
243
- }
244
- });
245
152
 
246
- const minSize$ = createVal(
153
+ const minSize$ = new Val(
247
154
  {
248
155
  width: clamp(minWidth, 0, 1),
249
156
  height: clamp(minHeight, 0, 1),
250
157
  },
251
- shallowequal
158
+ { compare: shallowequal }
252
159
  );
253
160
 
254
- const intrinsicSize$ = createVal(
255
- {
256
- width: clamp(width, minSize$.value.width, 1),
257
- height: clamp(height, minSize$.value.height, 1),
258
- },
259
- shallowequal
161
+ const pxMinSize$ = combine(
162
+ [minSize$, managerStageRect$],
163
+ ([minSize, managerStageRect]) => ({
164
+ width: minSize.width * managerStageRect.width,
165
+ height: minSize.height * managerStageRect.height,
166
+ }),
167
+ { compare: shallowequal }
260
168
  );
261
- minSize$.reaction((minSize, _, skipUpdate) => {
262
- intrinsicSize$.setValue(
263
- {
264
- width: clamp(width, minSize.width, 1),
265
- height: clamp(height, minSize.height, 1),
266
- },
267
- skipUpdate
268
- );
269
- });
270
- intrinsicSize$.reaction((size, _, skipUpdate) => {
271
- if (!skipUpdate) {
272
- this.events.emit(TELE_BOX_EVENT.IntrinsicResize, size);
273
- }
274
- });
275
169
 
276
- const size$ = combine(
277
- [intrinsicSize$, maximized$],
278
- ([intrinsicSize, maximized]) => {
279
- if (maximized) {
280
- return { width: 1, height: 1 };
281
- }
282
- return intrinsicSize;
283
- },
284
- shallowequal
170
+ const intrinsicSize$ = new Val(
171
+ { width, height },
172
+ { compare: shallowequal }
285
173
  );
286
- size$.reaction((size, _, skipUpdate) => {
287
- if (!skipUpdate) {
288
- this.events.emit(TELE_BOX_EVENT.Resize, size);
289
- }
290
- });
291
174
 
292
- const visualSize$ = combine(
293
- [size$, minimized$, containerRect$, collectorRect$],
294
- ([size, minimized, containerRect, collectorRect]) => {
295
- if (minimized && collectorRect) {
296
- return {
297
- width:
298
- collectorRect.width /
299
- size.width /
300
- containerRect.width,
301
- height:
302
- collectorRect.height /
303
- size.height /
304
- containerRect.height,
305
- };
306
- }
307
- return size;
308
- },
309
- shallowequal
175
+ this._sideEffect.addDisposer(
176
+ // check intrinsicSize overflow
177
+ minSize$.reaction((minSize, skipUpdate) => {
178
+ intrinsicSize$.setValue(
179
+ {
180
+ width: Math.max(width, minSize.width),
181
+ height: Math.max(height, minSize.height),
182
+ },
183
+ skipUpdate
184
+ );
185
+ })
310
186
  );
311
- visualSize$.reaction((size, _, skipUpdate) => {
312
- if (!skipUpdate) {
313
- this.events.emit(TELE_BOX_EVENT.VisualResize, size);
314
- }
315
- });
316
187
 
317
- const intrinsicCoord$ = createVal(
318
- { x: clamp(x, 0, 1), y: clamp(y, 0, 1) },
319
- shallowequal
188
+ const intrinsicCoord$ = new Val({ x, y }, { compare: shallowequal });
189
+
190
+ const pxIntrinsicSize$ = combine(
191
+ [intrinsicSize$, managerStageRect$],
192
+ ([size, managerStageRect]) => ({
193
+ width: managerStageRect.width * size.width,
194
+ height: managerStageRect.height * size.height,
195
+ }),
196
+ { compare: shallowequal }
320
197
  );
321
- intrinsicCoord$.reaction((coord, _, skipUpdate) => {
322
- if (!skipUpdate) {
323
- this.events.emit(TELE_BOX_EVENT.IntrinsicMove, coord);
324
- }
325
- });
326
198
 
327
- const coord$ = combine(
328
- [
329
- intrinsicCoord$,
330
- intrinsicSize$,
331
- containerRect$,
332
- collectorRect$,
333
- minimized$,
334
- maximized$,
335
- ],
336
- ([
337
- intrinsicCoord,
338
- intrinsicSize,
339
- containerRect,
340
- collectorRect,
341
- minimized,
342
- maximized,
343
- ]) => {
344
- if (minimized && collectorRect) {
345
- if (maximized) {
346
- return {
347
- x:
348
- (collectorRect.x + collectorRect.width / 2) /
349
- containerRect.width -
350
- 1 / 2,
351
- y:
352
- (collectorRect.y + collectorRect.height / 2) /
353
- containerRect.height -
354
- 1 / 2,
355
- };
356
- }
357
- return {
358
- x:
359
- (collectorRect.x + collectorRect.width / 2) /
360
- containerRect.width -
361
- intrinsicSize.width / 2,
362
- y:
363
- (collectorRect.y + collectorRect.height / 2) /
364
- containerRect.height -
365
- intrinsicSize.height / 2,
366
- };
367
- }
368
- if (maximized) {
369
- return { x: 0, y: 0 };
370
- }
371
- return intrinsicCoord;
372
- },
373
- shallowequal
199
+ const pxIntrinsicCoord$ = combine(
200
+ [intrinsicCoord$, managerStageRect$],
201
+ ([intrinsicCoord, managerStageRect]) => ({
202
+ x:
203
+ intrinsicCoord.x * managerStageRect.width +
204
+ managerStageRect.x,
205
+ y:
206
+ intrinsicCoord.y * managerStageRect.height +
207
+ managerStageRect.y,
208
+ }),
209
+ { compare: shallowequal }
374
210
  );
375
- coord$.reaction((coord, _, skipUpdate) => {
376
- if (!skipUpdate) {
377
- this.events.emit(TELE_BOX_EVENT.Move, coord);
378
- }
379
- });
380
211
 
381
- this.titleBar =
382
- titleBar ||
383
- new DefaultTitleBar({
384
- readonly: readonly$.value,
385
- title: title$.value,
386
- namespace: this.namespace,
387
- onDragStart: (event) => this._handleTrackStart?.(event),
388
- onEvent: (event): void => {
389
- if (this._delegateEvents.listeners.length > 0) {
390
- this._delegateEvents.emit(event.type);
391
- } else {
392
- switch (event.type) {
393
- case TELE_BOX_DELEGATE_EVENT.Maximize: {
394
- maximized$.setValue(!maximized$.value);
395
- break;
396
- }
397
- case TELE_BOX_DELEGATE_EVENT.Minimize: {
398
- minimized$.setValue(true);
399
- break;
400
- }
401
- case TELE_BOX_DELEGATE_EVENT.Close: {
402
- visible$.setValue(false);
403
- break;
404
- }
405
- default: {
406
- console.error(
407
- "Unsupported titleBar event:",
408
- event
409
- );
410
- break;
411
- }
412
- }
413
- }
414
- },
415
- });
416
- readonly$.reaction((readonly) => {
417
- this.titleBar.setReadonly(readonly);
212
+ const boxHighlightStage$ = new Val<boolean | null, boolean>(
213
+ highlightStage
214
+ );
215
+
216
+ const highlightStage$ = combine(
217
+ [maximized$, boxHighlightStage$, managerHighlightStage$],
218
+ ([maximized, boxHighlightStage, managerHighlightStage]) =>
219
+ boxHighlightStage === null
220
+ ? managerHighlightStage && maximized
221
+ : boxHighlightStage
222
+ );
223
+
224
+ const contentRoot$ = new Val<HTMLElement | null>(null);
225
+
226
+ const contentRect$ = new Val<TeleBoxRect>(rootRect$.value, {
227
+ compare: shallowequal,
418
228
  });
419
229
 
420
- const $userContent$ = createVal(content);
421
- const $userFooter$ = createVal(footer);
422
- const $userStyles$ = createVal(styles);
230
+ const teleStage = new TeleStage({
231
+ namespace,
232
+ root$: contentRoot$,
233
+ rootRect$: contentRect$,
234
+ ratio$: stageRatio$,
235
+ highlightStage$,
236
+ });
237
+ this._sideEffect.addDisposer(() => teleStage.destroy());
423
238
 
424
- const valConfig: ValConfig = {
425
- prefersColorScheme: prefersColorScheme$,
239
+ const readonlyValConfig: ReadonlyValConfig = {
426
240
  darkMode: darkMode$,
427
- containerRect: containerRect$,
428
- collectorRect: collectorRect$,
429
- title: title$,
430
- visible: visible$,
431
- readonly: readonly$,
432
- resizable: resizable$,
433
- draggable: draggable$,
434
241
  fence: fence$,
435
- fixRatio: fixRatio$,
436
- focus: focus$,
437
- zIndex: zIndex$,
438
242
  minimized: minimized$,
439
243
  maximized: maximized$,
244
+ readonly: readonly$,
245
+ rootRect: rootRect$,
246
+ managerStageRect: managerStageRect$,
247
+ collectorRect: collectorRect$,
248
+
249
+ zIndex: zIndex$,
250
+ focus: focus$,
251
+
440
252
  $userContent: $userContent$,
441
253
  $userFooter: $userFooter$,
442
254
  $userStyles: $userStyles$,
255
+
256
+ state: state$,
257
+ minSize: minSize$,
258
+ pxMinSize: pxMinSize$,
259
+ intrinsicSize: intrinsicSize$,
260
+ intrinsicCoord: intrinsicCoord$,
261
+ pxIntrinsicSize: pxIntrinsicSize$,
262
+ pxIntrinsicCoord: pxIntrinsicCoord$,
263
+ highlightStage: highlightStage$,
264
+ boxHighlightStage: boxHighlightStage$,
265
+ contentRect: contentRect$,
266
+ contentStageRect: teleStage.stageRect$,
267
+ };
268
+
269
+ withReadonlyValueEnhancer(this, readonlyValConfig);
270
+
271
+ const valConfig: ValConfig = {
272
+ title: title$,
273
+ visible: visible$,
274
+ resizable: resizable$,
275
+ draggable: draggable$,
276
+ ratio: ratio$,
443
277
  };
444
278
 
445
279
  withValueEnhancer(this, valConfig);
446
280
 
447
- this._state$ = state$;
448
- this._minSize$ = minSize$;
449
- this._size$ = size$;
450
- this._intrinsicSize$ = intrinsicSize$;
451
- this._visualSize$ = visualSize$;
452
- this._coord$ = coord$;
453
- this._intrinsicCoord$ = intrinsicCoord$;
454
-
455
- if (this.fixRatio) {
456
- this.transform(
457
- coord$.value.x,
458
- coord$.value.y,
459
- size$.value.width,
460
- size$.value.height,
461
- true
462
- );
463
- }
281
+ this.titleBar =
282
+ titleBar ||
283
+ new DefaultTitleBar({
284
+ readonly$: readonly$,
285
+ state$: state$,
286
+ title: title$.value,
287
+ namespace: this.namespace,
288
+ onDragStart: (event) => this._handleTrackStart?.(event),
289
+ onEvent: (event) => this._delegateEvents.emit(event.type),
290
+ });
291
+
292
+ this._sideEffect.addDisposer(
293
+ ratio$.subscribe((ratio) => {
294
+ if (ratio > 0) {
295
+ this.transform(
296
+ pxIntrinsicCoord$.value.x,
297
+ pxIntrinsicCoord$.value.y,
298
+ pxIntrinsicSize$.value.width,
299
+ pxIntrinsicSize$.value.height,
300
+ true
301
+ );
302
+ }
303
+ })
304
+ );
305
+
306
+ this._sideEffect.addDisposer(
307
+ fence$.subscribe((fence) => {
308
+ if (fence) {
309
+ this.move(
310
+ pxIntrinsicCoord$.value.x,
311
+ pxIntrinsicCoord$.value.y,
312
+ true
313
+ );
314
+ }
315
+ })
316
+ );
464
317
 
465
318
  this.$box = this.render();
319
+ contentRoot$.setValue(this.$content.parentElement);
320
+
321
+ const watchValEvent = <E extends TeleBoxEvent>(
322
+ val: ReadonlyVal<TeleBoxEventConfig[E], boolean>,
323
+ event: E
324
+ ) => {
325
+ this._sideEffect.addDisposer(
326
+ val.reaction((v, skipUpdate) => {
327
+ if (!skipUpdate) {
328
+ this.events.emit<any>(event, v);
329
+ }
330
+ })
331
+ );
332
+ };
333
+
334
+ watchValEvent(darkMode$, TELE_BOX_EVENT.DarkMode);
335
+ watchValEvent(readonly$, TELE_BOX_EVENT.Readonly);
336
+ watchValEvent(zIndex$, TELE_BOX_EVENT.ZIndex);
337
+ watchValEvent(minimized$, TELE_BOX_EVENT.Minimized);
338
+ watchValEvent(maximized$, TELE_BOX_EVENT.Maximized);
339
+ watchValEvent(state$, TELE_BOX_EVENT.State);
340
+ watchValEvent(intrinsicSize$, TELE_BOX_EVENT.IntrinsicResize);
341
+ watchValEvent(intrinsicCoord$, TELE_BOX_EVENT.IntrinsicMove);
342
+
343
+ this._sideEffect.addDisposer([
344
+ visible$.reaction((visible, skipUpdate) => {
345
+ if (!skipUpdate && !visible) {
346
+ this.events.emit(TELE_BOX_EVENT.Close);
347
+ }
348
+ }),
349
+ focus$.reaction((focus, skipUpdate) => {
350
+ if (!skipUpdate) {
351
+ this.events.emit(
352
+ focus ? TELE_BOX_EVENT.Focus : TELE_BOX_EVENT.Blur
353
+ );
354
+ }
355
+ }),
356
+ root$.subscribe((root) => {
357
+ if (root) {
358
+ root.appendChild(this.$box);
359
+ } else if (this.$box.parentNode) {
360
+ this.$box.remove();
361
+ }
362
+ }),
363
+ ]);
466
364
  }
467
365
 
468
366
  public readonly id: string;
@@ -470,97 +368,50 @@ export class TeleBox {
470
368
  /** ClassName Prefix. For CSS styling. Default "telebox" */
471
369
  public readonly namespace: string;
472
370
 
473
- public readonly events: TeleBoxEvents;
371
+ public readonly events = new Emittery<
372
+ TeleBoxEventConfig,
373
+ TeleBoxEventConfig
374
+ >();
474
375
 
475
- public readonly _delegateEvents: TeleBoxDelegateEvents;
376
+ public readonly _delegateEvents = new Emittery<
377
+ TeleBoxDelegateEventConfig,
378
+ TeleBoxDelegateEventConfig
379
+ >();
476
380
 
477
381
  protected _sideEffect: SideEffectManager;
478
382
 
479
- protected _valSideEffectBinder: ValSideEffectBinder;
480
-
481
383
  public titleBar: TeleTitleBar;
482
384
 
483
- public _minSize$: Val<TeleBoxSize, boolean>;
484
- public _size$: Val<TeleBoxSize, boolean>;
485
- public _intrinsicSize$: Val<TeleBoxSize, boolean>;
486
- public _visualSize$: Val<TeleBoxSize, boolean>;
487
- public _coord$: Val<TeleBoxCoord, boolean>;
488
- public _intrinsicCoord$: Val<TeleBoxCoord, boolean>;
489
-
490
- public get darkMode(): boolean {
491
- return this._darkMode$.value;
492
- }
493
-
494
- public _state$: Val<TeleBoxState, boolean>;
495
-
496
- public get state(): TeleBoxState {
497
- return this._state$.value;
498
- }
499
-
500
- /** @deprecated use setMaximized and setMinimized instead */
501
- public setState(state: TeleBoxState, skipUpdate = false): this {
502
- switch (state) {
503
- case TELE_BOX_STATE.Maximized: {
504
- this.setMinimized(false, skipUpdate);
505
- this.setMaximized(true, skipUpdate);
506
- break;
507
- }
508
- case TELE_BOX_STATE.Minimized: {
509
- this.setMinimized(true, skipUpdate);
510
- this.setMaximized(false, skipUpdate);
511
- break;
512
- }
513
- default: {
514
- this.setMinimized(false, skipUpdate);
515
- this.setMaximized(false, skipUpdate);
516
- break;
517
- }
518
- }
519
- return this;
520
- }
521
-
522
- /** Minimum box width relative to container element. 0~1. Default 0. */
385
+ /** Minimum box width relative to stage area. 0~1. Default 0. */
523
386
  public get minWidth(): number {
524
387
  return this._minSize$.value.width;
525
388
  }
526
389
 
527
- /** Minimum box height relative to container element. 0~1. Default 0. */
390
+ /** Minimum box height relative to stage area. 0~1. Default 0. */
528
391
  public get minHeight(): number {
529
392
  return this._minSize$.value.height;
530
393
  }
531
394
 
532
395
  /**
533
- * @param minWidth Minimum box width relative to container element. 0~1.
396
+ * @param minWidth Minimum box width relative to stage area. 0~1.
534
397
  * @returns this
535
398
  */
536
- public setMinWidth(minWidth: number, skipUpdate = false): this {
399
+ public setMinWidth(minWidth: number, skipUpdate = false): void {
537
400
  this._minSize$.setValue(
538
401
  { width: minWidth, height: this.minHeight },
539
402
  skipUpdate
540
403
  );
541
- return this;
542
404
  }
543
405
 
544
406
  /**
545
407
  * @param minHeight Minimum box height relative to container element. 0~1.
546
408
  * @returns this
547
409
  */
548
- public setMinHeight(minHeight: number, skipUpdate = false): this {
410
+ public setMinHeight(minHeight: number, skipUpdate = false): void {
549
411
  this._minSize$.setValue(
550
412
  { width: this.minWidth, height: minHeight },
551
413
  skipUpdate
552
414
  );
553
- return this;
554
- }
555
-
556
- /** Intrinsic box width relative to container element(without counting the effect of maximization or minimization). 0~1. Default 0.5. */
557
- public get intrinsicWidth(): number {
558
- return this._intrinsicSize$.value.width;
559
- }
560
-
561
- /** Intrinsic box height relative to container element(without counting the effect of maximization or minimization). 0~1. Default 0.5. */
562
- public get intrinsicHeight(): number {
563
- return this._intrinsicSize$.value.height;
564
415
  }
565
416
 
566
417
  /**
@@ -570,39 +421,14 @@ export class TeleBox {
570
421
  * @param skipUpdate Skip emitting event.
571
422
  * @returns this
572
423
  */
573
- public resize(width: number, height: number, skipUpdate = false): this {
574
- this._intrinsicSize$.setValue({ width, height }, skipUpdate);
575
- return this;
576
- }
577
-
578
- /** Box width relative to container element. 0~1. Default 0.5. */
579
- public get width(): number {
580
- return this._size$.value.width;
581
- }
582
-
583
- /** Box height relative to container element. 0~1. Default 0.5. */
584
- public get height(): number {
585
- return this._size$.value.height;
586
- }
587
-
588
- /** Box width in pixels. */
589
- public get absoluteWidth(): number {
590
- return this.width * this.containerRect.width;
591
- }
592
-
593
- /** Box height in pixels. */
594
- public get absoluteHeight(): number {
595
- return this.height * this.containerRect.height;
596
- }
597
-
598
- /** Actual rendered box width relative to container element. 0~1. Default 0.5. */
599
- public get visualWidth(): number {
600
- return this._visualSize$.value.width;
601
- }
602
-
603
- /** Actual rendered box height relative to container element. 0~1. Default 0.5. */
604
- public get visualHeight(): number {
605
- return this._visualSize$.value.height;
424
+ public resize(width: number, height: number, skipUpdate = false): void {
425
+ this._intrinsicSize$.setValue(
426
+ {
427
+ width: Math.max(width, this.minWidth),
428
+ height: Math.max(height, this.minHeight),
429
+ },
430
+ skipUpdate
431
+ );
606
432
  }
607
433
 
608
434
  /** Intrinsic box x position relative to container element(without counting the effect of maximization or minimization). 0~1. Default 0.1. */
@@ -615,133 +441,141 @@ export class TeleBox {
615
441
  return this._intrinsicCoord$.value.y;
616
442
  }
617
443
 
444
+ /** Intrinsic box width relative to container element(without counting the effect of maximization or minimization). 0~1. Default 0.1. */
445
+ public get intrinsicWidth(): number {
446
+ return this._intrinsicSize$.value.width;
447
+ }
448
+
449
+ /** Intrinsic box height relative to container element(without counting the effect of maximization or minimization). 0~1. Default 0.1. */
450
+ public get intrinsicHeight(): number {
451
+ return this._intrinsicSize$.value.height;
452
+ }
453
+
618
454
  /**
619
455
  * Move box position.
620
- * @param x x position relative to container element. 0~1.
621
- * @param y y position relative to container element. 0~1.
456
+ * @param x x position in px.
457
+ * @param y y position in px.
622
458
  * @param skipUpdate Skip emitting event.
623
459
  * @returns this
624
460
  */
625
- public move(x: number, y: number, skipUpdate = false): this {
626
- this._intrinsicCoord$.setValue({ x, y }, skipUpdate);
627
- return this;
628
- }
629
-
630
- /** Box x position relative to container element. 0~1. Default 0.1. */
631
- public get x(): number {
632
- return this._coord$.value.x;
633
- }
461
+ protected move(x: number, y: number, skipUpdate = false): void {
462
+ let safeX: number;
463
+ let safeY: number;
464
+ const managerStageRect = this.managerStageRect;
465
+ const pxIntrinsicSize = this.pxIntrinsicSize;
466
+
467
+ if (this.fence) {
468
+ safeX = clamp(
469
+ x,
470
+ managerStageRect.x,
471
+ managerStageRect.x +
472
+ managerStageRect.width -
473
+ pxIntrinsicSize.width
474
+ );
475
+ safeY = clamp(
476
+ y,
477
+ managerStageRect.y,
478
+ managerStageRect.y +
479
+ managerStageRect.height -
480
+ pxIntrinsicSize.height
481
+ );
482
+ } else {
483
+ const rootRect = this.rootRect;
484
+ safeX = clamp(
485
+ x,
486
+ rootRect.x - pxIntrinsicSize.width + 20,
487
+ rootRect.x + rootRect.width - 20
488
+ );
489
+ safeY = clamp(y, rootRect.y, rootRect.y + rootRect.height - 20);
490
+ }
634
491
 
635
- /** Box y position relative to container element. 0~1. Default 0.1. */
636
- public get y(): number {
637
- return this._coord$.value.y;
492
+ this._intrinsicCoord$.setValue(
493
+ {
494
+ x: (safeX - managerStageRect.x) / managerStageRect.width,
495
+ y: (safeY - managerStageRect.y) / managerStageRect.height,
496
+ },
497
+ skipUpdate
498
+ );
638
499
  }
639
500
 
640
501
  /**
641
502
  * Resize + Move, with respect to fixed ratio.
642
- * @param x x position relative to container element. 0~1.
643
- * @param y y position relative to container element. 0~1.
644
- * @param width Box width relative to container element. 0~1.
645
- * @param height Box height relative to container element. 0~1.
503
+ * @param x x position in px.
504
+ * @param y y position in px.
505
+ * @param width Box width in px.
506
+ * @param height Box height in px.
646
507
  * @param skipUpdate Skip emitting event.
647
508
  * @returns this
648
509
  */
649
- public transform(
510
+ protected transform(
650
511
  x: number,
651
512
  y: number,
652
513
  width: number,
653
514
  height: number,
654
515
  skipUpdate = false
655
- ): this {
656
- if (this.fixRatio) {
657
- const newHeight =
658
- (this.intrinsicHeight / this.intrinsicWidth) * width;
659
- if (y !== this.intrinsicY) {
516
+ ): void {
517
+ const managerStageRect = this.managerStageRect;
518
+ const rootRect = this.rootRect;
519
+
520
+ width = Math.max(width, this.pxMinSize.width);
521
+ height = Math.max(height, this.pxMinSize.height);
522
+
523
+ if (this.ratio > 0) {
524
+ const newHeight = this.ratio * width;
525
+ if (y !== this.pxIntrinsicCoord.y) {
660
526
  y -= newHeight - height;
661
527
  }
662
528
  height = newHeight;
663
529
  }
664
530
 
665
- if (y < 0) {
666
- y = 0;
667
- if (height > this.intrinsicHeight) {
668
- height = this.intrinsicHeight;
669
- }
531
+ if (y < rootRect.y) {
532
+ y = rootRect.y;
533
+ height = this.pxIntrinsicSize.height;
670
534
  }
671
535
 
672
- this._intrinsicCoord$.setValue(
673
- {
674
- x: width >= this.minWidth ? x : this.intrinsicX,
675
- y: height >= this.minHeight ? y : this.intrinsicY,
676
- },
677
- skipUpdate
678
- );
536
+ this.move(x, y, skipUpdate);
679
537
  this._intrinsicSize$.setValue(
680
538
  {
681
- width: clamp(width, this.minWidth, 1),
682
- height: clamp(height, this.minHeight, 1),
539
+ width: width / managerStageRect.width,
540
+ height: height / managerStageRect.height,
683
541
  },
684
542
  skipUpdate
685
543
  );
686
-
687
- return this;
688
- }
689
-
690
- /**
691
- * Mount box to a container element.
692
- */
693
- public mount(container: HTMLElement): this {
694
- container.appendChild(this.render());
695
- return this;
696
- }
697
-
698
- /**
699
- * Unmount box from the container element.
700
- */
701
- public unmount(): this {
702
- if (this.$box) {
703
- this.$box.remove();
704
- }
705
- return this;
706
544
  }
707
545
 
708
546
  /**
709
547
  * Mount dom to box content.
710
548
  */
711
- public mountContent(content: HTMLElement): this {
712
- this.set$userContent(content);
713
- return this;
549
+ public mountContent(content: HTMLElement): void {
550
+ this._$userContent$.setValue(content);
714
551
  }
715
552
 
716
553
  /**
717
554
  * Unmount content from the box.
718
555
  */
719
- public unmountContent(): this {
720
- this.set$userContent(undefined);
721
- return this;
556
+ public unmountContent(): void {
557
+ this._$userContent$.setValue(undefined);
722
558
  }
723
559
 
724
560
  /**
725
561
  * Mount dom to box Footer.
726
562
  */
727
- public mountFooter(footer: HTMLElement): this {
728
- this.set$userFooter(footer);
729
- return this;
563
+ public mountFooter(footer: HTMLElement): void {
564
+ this._$userFooter$.setValue(footer);
730
565
  }
731
566
 
732
567
  /**
733
568
  * Unmount Footer from the box.
734
569
  */
735
- public unmountFooter(): this {
736
- this.set$userFooter(undefined);
737
- return this;
570
+ public unmountFooter(): void {
571
+ this._$userFooter$.setValue(undefined);
738
572
  }
739
573
 
740
574
  public getUserStyles(): HTMLStyleElement | undefined {
741
575
  return this.$userStyles;
742
576
  }
743
577
 
744
- public mountStyles(styles: string | HTMLStyleElement): this {
578
+ public mountStyles(styles: string | HTMLStyleElement): void {
745
579
  let $styles: HTMLStyleElement;
746
580
  if (typeof styles === "string") {
747
581
  $styles = document.createElement("style");
@@ -749,13 +583,16 @@ export class TeleBox {
749
583
  } else {
750
584
  $styles = styles;
751
585
  }
752
- this.set$userStyles($styles);
753
- return this;
586
+ this._$userStyles$.setValue($styles);
754
587
  }
755
588
 
756
- public unmountStyles(): this {
757
- this.set$userStyles(undefined);
758
- return this;
589
+ public unmountStyles(): void {
590
+ this._$userStyles$.setValue(undefined);
591
+ }
592
+
593
+ /** Show stage frame and grey-out the non-stage area. Inherit setting from manager if null. */
594
+ setHighlightStage(highlightStage: boolean | null): void {
595
+ this._boxHighlightStage$.setValue(highlightStage);
759
596
  }
760
597
 
761
598
  /** DOM of the box */
@@ -770,34 +607,22 @@ export class TeleBox {
770
607
  /** DOM of the box footer */
771
608
  public $footer!: HTMLElement;
772
609
 
773
- protected _renderSideEffect = new SideEffectManager();
774
-
775
- public render(root?: HTMLElement): HTMLElement {
776
- if (root) {
777
- if (root === this.$box) {
778
- return this.$box;
779
- } else {
780
- this.$box = root;
781
- }
782
- } else {
783
- if (this.$box) {
784
- return this.$box;
785
- } else {
786
- this.$box = document.createElement("div");
787
- }
610
+ protected render(): HTMLElement {
611
+ if (this.$box) {
612
+ return this.$box;
788
613
  }
789
614
 
790
- this._renderSideEffect.flushAll();
615
+ this.$box = document.createElement("div");
791
616
 
792
617
  this.$box.classList.add(this.wrapClassName("box"));
793
618
 
794
619
  const bindClassName = <TValue>(
795
620
  el: Element,
796
- val: Val<TValue, boolean>,
621
+ val: ReadonlyVal<TValue, boolean>,
797
622
  className: string,
798
623
  predicate: (value: TValue) => boolean = isTruthy
799
624
  ): string => {
800
- return this._renderSideEffect.add(() => {
625
+ return this._sideEffect.add(() => {
801
626
  const wrappedClassName = this.wrapClassName(className);
802
627
  return val.subscribe((value) => {
803
628
  el.classList.toggle(wrappedClassName, predicate(value));
@@ -817,7 +642,7 @@ export class TeleBox {
817
642
  isFalsy
818
643
  );
819
644
 
820
- this._renderSideEffect.add(() => {
645
+ this._sideEffect.add(() => {
821
646
  const minimizedClassName = this.wrapClassName("minimized");
822
647
  const maximizedClassName = this.wrapClassName("maximized");
823
648
  const MAXIMIZED_TIMER_ID = "box-maximized-timer";
@@ -829,11 +654,11 @@ export class TeleBox {
829
654
  );
830
655
 
831
656
  if (state === TELE_BOX_STATE.Maximized) {
832
- this._renderSideEffect.flush(MAXIMIZED_TIMER_ID);
657
+ this._sideEffect.flush(MAXIMIZED_TIMER_ID);
833
658
  this.$box.classList.toggle(maximizedClassName, true);
834
659
  } else {
835
660
  // delay so that transition won't be triggered
836
- this._renderSideEffect.setTimeout(
661
+ this._sideEffect.setTimeout(
837
662
  () => {
838
663
  this.$box.classList.toggle(
839
664
  maximizedClassName,
@@ -847,68 +672,83 @@ export class TeleBox {
847
672
  });
848
673
  });
849
674
 
850
- this._renderSideEffect.add(() =>
675
+ this._sideEffect.addDisposer(
851
676
  this._visible$.subscribe((visible) => {
852
677
  this.$box.style.display = visible ? "block" : "none";
853
678
  })
854
679
  );
855
680
 
856
- this._renderSideEffect.add(() =>
681
+ this._sideEffect.addDisposer(
857
682
  this._zIndex$.subscribe((zIndex) => {
858
683
  this.$box.style.zIndex = String(zIndex);
859
684
  })
860
685
  );
861
686
 
687
+ this.$box.dataset.teleBoxID = this.id;
688
+
862
689
  const boxStyler = styler(this.$box);
863
690
 
864
- this.$box.dataset.teleBoxID = this.id;
691
+ const boxStyles$ = combine(
692
+ [
693
+ this._maximized$,
694
+ this._minimized$,
695
+ this._pxIntrinsicSize$,
696
+ this._pxIntrinsicCoord$,
697
+ this._collectorRect$,
698
+ ],
699
+ ([
700
+ maximized,
701
+ minimized,
702
+ pxIntrinsicSize,
703
+ pxIntrinsicCoord,
704
+ collectorRect,
705
+ ]) => {
706
+ if (minimized && collectorRect) {
707
+ return {
708
+ x: collectorRect.x + collectorRect.width / 2,
709
+ y: collectorRect.y + collectorRect.height / 2,
710
+ width: pxIntrinsicSize.width + "px",
711
+ height: pxIntrinsicSize.height + "px",
712
+ scaleX: collectorRect.width / pxIntrinsicSize.width,
713
+ scaleY: collectorRect.height / pxIntrinsicSize.height,
714
+ };
715
+ }
716
+ if (maximized) {
717
+ return {
718
+ x: 0,
719
+ y: 0,
720
+ width: "100%",
721
+ height: "100%",
722
+ scaleX: 1,
723
+ scaleY: 1,
724
+ };
725
+ }
726
+ return {
727
+ x: pxIntrinsicCoord.x,
728
+ y: pxIntrinsicCoord.y,
729
+ width: pxIntrinsicSize.width + "px",
730
+ height: pxIntrinsicSize.height + "px",
731
+ scaleX: 1,
732
+ scaleY: 1,
733
+ };
734
+ },
735
+ { compare: shallowequal }
736
+ );
865
737
 
866
- this.$box.style.width = this.absoluteWidth + "px";
867
- this.$box.style.height = this.absoluteHeight + "px";
738
+ const boxStyles = boxStyles$.value;
739
+ this.$box.style.width = boxStyles.width;
740
+ this.$box.style.height = boxStyles.height;
868
741
  // Add 10px offset on first frame
869
742
  // which creates a subtle moving effect
870
- const translateX =
871
- this.x * this.containerRect.width + this.containerRect.x;
872
- const translateY =
873
- this.y * this.containerRect.height + this.containerRect.y;
874
- this.$box.style.transform = `translate(${translateX - 10}px,${
875
- translateY - 10
743
+ this.$box.style.transform = `translate(${boxStyles.x - 10}px,${
744
+ boxStyles.y - 10
876
745
  }px)`;
877
746
 
878
- this._valSideEffectBinder
879
- .combine(
880
- [
881
- this._coord$,
882
- this._size$,
883
- this._minimized$,
884
- this._containerRect$,
885
- this._collectorRect$,
886
- ],
887
- ([coord, size, minimized, containerRect, collectorRect]) => {
888
- const absoluteWidth = size.width * containerRect.width;
889
- const absoluteHeight = size.height * containerRect.height;
890
- return {
891
- width: absoluteWidth,
892
- height: absoluteHeight,
893
- x: coord.x * containerRect.width,
894
- y: coord.y * containerRect.height,
895
- scaleX:
896
- minimized && collectorRect
897
- ? collectorRect.width / absoluteWidth
898
- : 1,
899
- scaleY:
900
- minimized && collectorRect
901
- ? collectorRect.height / absoluteHeight
902
- : 1,
903
- };
904
- },
905
- shallowequal
906
- )
907
- .subscribe((styles) => {
747
+ this._sideEffect.addDisposer(
748
+ boxStyles$.subscribe((styles) => {
908
749
  boxStyler.set(styles);
909
- });
910
-
911
- boxStyler.set({ x: translateX, y: translateY });
750
+ })
751
+ );
912
752
 
913
753
  const $boxMain = document.createElement("div");
914
754
  $boxMain.className = this.wrapClassName("box-main");
@@ -927,7 +767,23 @@ export class TeleBox {
927
767
  this.wrapClassName("content") + " tele-fancy-scrollbar";
928
768
  this.$content = $content;
929
769
 
930
- this._renderSideEffect.add(() => {
770
+ this._sideEffect.add(() => {
771
+ const observer = new ResizeObserver((entries) => {
772
+ const rect = entries[0]?.contentRect;
773
+ if (rect) {
774
+ this._contentRect$.setValue({
775
+ x: rect.x,
776
+ y: rect.y,
777
+ width: rect.width,
778
+ height: rect.height,
779
+ });
780
+ }
781
+ });
782
+ observer.observe($content);
783
+ return () => observer.disconnect();
784
+ });
785
+
786
+ this._sideEffect.add(() => {
931
787
  let last$userStyles: HTMLStyleElement | undefined;
932
788
  return this._$userStyles$.subscribe(($userStyles) => {
933
789
  if (last$userStyles) {
@@ -940,7 +796,7 @@ export class TeleBox {
940
796
  });
941
797
  });
942
798
 
943
- this._renderSideEffect.add(() => {
799
+ this._sideEffect.add(() => {
944
800
  let last$userContent: HTMLElement | undefined;
945
801
  return this._$userContent$.subscribe(($userContent) => {
946
802
  if (last$userContent) {
@@ -959,7 +815,7 @@ export class TeleBox {
959
815
  $footer.className = this.wrapClassName("footer-wrap");
960
816
  this.$footer = $footer;
961
817
 
962
- this._renderSideEffect.add(() => {
818
+ this._sideEffect.add(() => {
963
819
  let last$userFooter: HTMLElement | undefined;
964
820
  return this._$userFooter$.subscribe(($userFooter) => {
965
821
  if (last$userFooter) {
@@ -1028,109 +884,67 @@ export class TeleBox {
1028
884
  preventEvent(ev);
1029
885
 
1030
886
  let { pageX, pageY } = flattenEvent(ev);
1031
- if (pageY < 0) {
1032
- pageY = 0;
887
+ if (pageY < this.rootRect.y) {
888
+ pageY = this.rootRect.y;
1033
889
  }
1034
890
 
1035
- const offsetX =
1036
- (pageX - trackStartPageX) / this.containerRect.width;
1037
- const offsetY =
1038
- (pageY - trackStartPageY) / this.containerRect.height;
891
+ const offsetX = pageX - trackStartPageX;
892
+ const offsetY = pageY - trackStartPageY;
893
+
894
+ let { x: newX, y: newY } = this.pxIntrinsicCoord;
895
+ let { width: newWidth, height: newHeight } = this.pxIntrinsicSize;
1039
896
 
1040
897
  switch (trackingHandle) {
1041
898
  case TELE_BOX_RESIZE_HANDLE.North: {
1042
- this.transform(
1043
- this.x,
1044
- trackStartY + offsetY,
1045
- this.width,
1046
- trackStartHeight - offsetY
1047
- );
899
+ newY = trackStartY + offsetY;
900
+ newHeight = trackStartHeight - offsetY;
1048
901
  break;
1049
902
  }
903
+ // eslint-disable-next-line no-fallthrough
1050
904
  case TELE_BOX_RESIZE_HANDLE.South: {
1051
- this.transform(
1052
- this.x,
1053
- this.y,
1054
- this.width,
1055
- trackStartHeight + offsetY
1056
- );
905
+ newHeight = trackStartHeight + offsetY;
1057
906
  break;
1058
907
  }
1059
908
  case TELE_BOX_RESIZE_HANDLE.West: {
1060
- this.transform(
1061
- trackStartX + offsetX,
1062
- this.y,
1063
- trackStartWidth - offsetX,
1064
- this.height
1065
- );
909
+ newX = trackStartX + offsetX;
910
+ newWidth = trackStartWidth - offsetX;
1066
911
  break;
1067
912
  }
1068
913
  case TELE_BOX_RESIZE_HANDLE.East: {
1069
- this.transform(
1070
- this.x,
1071
- this.y,
1072
- trackStartWidth + offsetX,
1073
- this.height
1074
- );
914
+ newWidth = trackStartWidth + offsetX;
1075
915
  break;
1076
916
  }
1077
917
  case TELE_BOX_RESIZE_HANDLE.NorthWest: {
1078
- this.transform(
1079
- trackStartX + offsetX,
1080
- trackStartY + offsetY,
1081
- trackStartWidth - offsetX,
1082
- trackStartHeight - offsetY
1083
- );
918
+ newX = trackStartX + offsetX;
919
+ newY = trackStartY + offsetY;
920
+ newWidth = trackStartWidth - offsetX;
921
+ newHeight = trackStartHeight - offsetY;
1084
922
  break;
1085
923
  }
1086
924
  case TELE_BOX_RESIZE_HANDLE.NorthEast: {
1087
- this.transform(
1088
- this.x,
1089
- trackStartY + offsetY,
1090
- trackStartWidth + offsetX,
1091
- trackStartHeight - offsetY
1092
- );
925
+ newY = trackStartY + offsetY;
926
+ newWidth = trackStartWidth + offsetX;
927
+ newHeight = trackStartHeight - offsetY;
1093
928
  break;
1094
929
  }
1095
930
  case TELE_BOX_RESIZE_HANDLE.SouthEast: {
1096
- this.transform(
1097
- this.x,
1098
- this.y,
1099
- trackStartWidth + offsetX,
1100
- trackStartHeight + offsetY
1101
- );
931
+ newWidth = trackStartWidth + offsetX;
932
+ newHeight = trackStartHeight + offsetY;
1102
933
  break;
1103
934
  }
1104
935
  case TELE_BOX_RESIZE_HANDLE.SouthWest: {
1105
- this.transform(
1106
- trackStartX + offsetX,
1107
- this.y,
1108
- trackStartWidth - offsetX,
1109
- trackStartHeight + offsetY
1110
- );
936
+ newX = trackStartX + offsetX;
937
+ newWidth = trackStartWidth - offsetX;
938
+ newHeight = trackStartHeight + offsetY;
1111
939
  break;
1112
940
  }
1113
941
  default: {
1114
- if (this.fence) {
1115
- this.move(
1116
- clamp(trackStartX + offsetX, 0, 1 - this.width),
1117
- clamp(trackStartY + offsetY, 0, 1 - this.height)
1118
- );
1119
- } else {
1120
- const xOverflowOffset = 20 / this.containerRect.width;
1121
- const yOverflowOffset = 20 / this.containerRect.height;
1122
- this.move(
1123
- clamp(
1124
- trackStartX + offsetX,
1125
- xOverflowOffset - this.width,
1126
- 1 - xOverflowOffset
1127
- ),
1128
- clamp(trackStartY + offsetY, 0, 1 - yOverflowOffset)
1129
- );
1130
- }
1131
- break;
942
+ this.move(trackStartX + offsetX, trackStartY + offsetY);
943
+ return;
1132
944
  }
1133
945
  }
946
+
947
+ this.transform(newX, newY, newWidth, newHeight);
1134
948
  };
1135
949
 
1136
950
  const handleTrackEnd = (ev: MouseEvent | TouchEvent): void => {
@@ -1174,10 +988,9 @@ export class TeleBox {
1174
988
  if (target.dataset?.teleBoxHandle) {
1175
989
  preventEvent(ev);
1176
990
 
1177
- trackStartX = this.x;
1178
- trackStartY = this.y;
1179
- trackStartWidth = this.width;
1180
- trackStartHeight = this.height;
991
+ ({ x: trackStartX, y: trackStartY } = this.pxIntrinsicCoord);
992
+ ({ width: trackStartWidth, height: trackStartHeight } =
993
+ this.pxIntrinsicSize);
1181
994
 
1182
995
  ({ pageX: trackStartPageX, pageY: trackStartPageY } =
1183
996
  flattenEvent(ev));
@@ -1247,14 +1060,14 @@ export class TeleBox {
1247
1060
  );
1248
1061
  }
1249
1062
 
1250
- public destroy(): void {
1063
+ public async destroy(): Promise<void> {
1251
1064
  this.$box.remove();
1252
- this.events.emit(TELE_BOX_EVENT.Destroyed);
1253
-
1254
1065
  this._sideEffect.flushAll();
1255
- this._renderSideEffect.flushAll();
1256
- this.events.removeAllListeners();
1257
- this._delegateEvents.removeAllListeners();
1066
+ this._sideEffect.flushAll();
1067
+
1068
+ await this.events.emit(TELE_BOX_EVENT.Destroyed);
1069
+ this.events.clearListeners();
1070
+ this._delegateEvents.clearListeners();
1258
1071
  }
1259
1072
 
1260
1073
  /**
@@ -1265,12 +1078,9 @@ export class TeleBox {
1265
1078
  }
1266
1079
  }
1267
1080
 
1268
- function noop(): void {
1269
- return;
1270
- }
1271
-
1272
1081
  type PropKeys<K = keyof TeleBox> = K extends keyof TeleBox
1273
- ? TeleBox[K] extends Function
1082
+ ? // eslint-disable-next-line @typescript-eslint/ban-types
1083
+ TeleBox[K] extends Function
1274
1084
  ? never
1275
1085
  : K
1276
1086
  : never;