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

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.
@@ -6,11 +6,13 @@ import type {
6
6
  ValEnhancedResult,
7
7
  ReadonlyValEnhancedResult,
8
8
  } from "value-enhancer";
9
+ import { derive } from "value-enhancer";
9
10
  import {
10
11
  combine,
11
12
  Val,
12
13
  withValueEnhancer,
13
14
  withReadonlyValueEnhancer,
15
+ ValManager,
14
16
  } from "value-enhancer";
15
17
  import Emittery from "emittery";
16
18
  import type {
@@ -46,6 +48,7 @@ const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill;
46
48
  type ReadonlyValConfig = {
47
49
  darkMode: ReadonlyVal<boolean, boolean>;
48
50
  state: ReadonlyVal<TeleBoxState, boolean>;
51
+ root: Val<HTMLElement | null>;
49
52
  rootRect: Val<TeleBoxRect>;
50
53
  stageRect: ReadonlyVal<TeleBoxRect>;
51
54
  };
@@ -67,7 +70,7 @@ export interface TeleBoxManager extends CombinedValEnhancedResult {}
67
70
 
68
71
  export class TeleBoxManager {
69
72
  public constructor({
70
- root = document.body,
73
+ root = null,
71
74
  prefersColorScheme = TELE_BOX_COLOR_SCHEME.Light,
72
75
  minimized = false,
73
76
  maximized = false,
@@ -80,9 +83,12 @@ export class TeleBoxManager {
80
83
  }: TeleBoxManagerConfig = {}) {
81
84
  this._sideEffect = new SideEffectManager();
82
85
 
83
- this.root = root;
84
86
  this.namespace = namespace;
85
87
 
88
+ const valManager = new ValManager();
89
+ this._sideEffect.addDisposer(() => valManager.destroy());
90
+
91
+ const root$ = new Val(root);
86
92
  const readonly$ = new Val(readonly);
87
93
  const minimized$ = new Val(minimized);
88
94
  const maximized$ = new Val(maximized);
@@ -99,28 +105,26 @@ export class TeleBoxManager {
99
105
  },
100
106
  { compare: shallowequal }
101
107
  );
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"
119
- );
120
- });
121
- observer.observe(root);
122
- return () => observer.disconnect();
123
- });
108
+ this._sideEffect.addDisposer(
109
+ root$.subscribe((root) => {
110
+ this._sideEffect.add(() => {
111
+ if (!root) {
112
+ return () => void 0;
113
+ }
114
+ const observer = new ResizeObserver(() => {
115
+ const rect = root.getBoundingClientRect();
116
+ rootRect$.setValue({
117
+ x: rect.x,
118
+ y: rect.y,
119
+ width: rect.width,
120
+ height: rect.height,
121
+ });
122
+ });
123
+ observer.observe(root);
124
+ return () => observer.disconnect();
125
+ }, "calc-root-rect");
126
+ })
127
+ );
124
128
 
125
129
  this.boxes$ = new Val<TeleBox[]>([]);
126
130
  this.topBox$ = new Val<TeleBox | undefined>(undefined);
@@ -190,7 +194,7 @@ export class TeleBoxManager {
190
194
  readonly$: readonly$,
191
195
  darkMode$: darkMode$,
192
196
  namespace,
193
- root,
197
+ root$,
194
198
  rootRect$,
195
199
  });
196
200
 
@@ -198,19 +202,24 @@ export class TeleBoxManager {
198
202
  namespace,
199
203
  rootRect$,
200
204
  ratio$: stageRatio$,
201
- root,
202
- highlightStage$,
205
+ root$,
206
+ highlightStage$: combine(
207
+ [highlightStage$, maximized$, minimized$],
208
+ ([highlightStage, maximized, minimized]) =>
209
+ highlightStage && (minimized || !maximized)
210
+ ),
203
211
  });
204
212
  this._sideEffect.addDisposer(() => teleStage.destroy());
205
213
 
206
214
  const readonlyValConfig: ReadonlyValConfig = {
207
215
  darkMode: darkMode$,
208
216
  state: state$,
217
+ root: root$,
209
218
  rootRect: rootRect$,
210
219
  stageRect: teleStage.stageRect$,
211
220
  };
212
221
 
213
- withReadonlyValueEnhancer(this, readonlyValConfig);
222
+ withReadonlyValueEnhancer(this, readonlyValConfig, valManager);
214
223
 
215
224
  const valConfig: ValConfig = {
216
225
  prefersColorScheme: prefersColorScheme$,
@@ -222,7 +231,7 @@ export class TeleBoxManager {
222
231
  highlightStage: highlightStage$,
223
232
  };
224
233
 
225
- withValueEnhancer(this, valConfig);
234
+ withValueEnhancer(this, valConfig, valManager);
226
235
 
227
236
  const closeBtnClassName = this.wrapClassName("titlebar-icon-close");
228
237
 
@@ -271,10 +280,12 @@ export class TeleBoxManager {
271
280
 
272
281
  this.titleBar = new MaxTitleBar({
273
282
  namespace: this.namespace,
283
+ title$: derive(this.topBox$, (topBox) => topBox?.title || ""),
274
284
  boxes$: this.boxes$,
275
285
  darkMode$: darkMode$,
276
286
  readonly$: readonly$,
277
287
  state$: state$,
288
+ root$,
278
289
  rootRect$: rootRect$,
279
290
  onEvent: (event): void => {
280
291
  switch (event.type) {
@@ -298,8 +309,6 @@ export class TeleBoxManager {
298
309
  },
299
310
  });
300
311
 
301
- this.root.appendChild(this.titleBar.render());
302
-
303
312
  this._sideEffect.addDisposer([
304
313
  state$.reaction((state, skipUpdate) => {
305
314
  if (!skipUpdate) {
@@ -345,8 +354,6 @@ export class TeleBoxManager {
345
354
 
346
355
  protected _sideEffect: SideEffectManager;
347
356
 
348
- protected root: HTMLElement;
349
-
350
357
  public readonly namespace: string;
351
358
 
352
359
  /** @deprecated use setMaximized and setMinimized instead */
@@ -380,20 +387,19 @@ export class TeleBoxManager {
380
387
  ...config,
381
388
  ...(smartPosition ? this.smartPosition(config) : {}),
382
389
  namespace: this.namespace,
390
+ root$: this._root$,
383
391
  darkMode$: this._darkMode$,
384
392
  maximized$: this._maximized$,
385
393
  minimized$: this._minimized$,
386
394
  fence$: this._fence$,
387
395
  rootRect$: this._rootRect$,
388
396
  managerStageRect$: this._stageRect$,
389
- stageRatio$: this._stageRatio$,
397
+ managerStageRatio$: this._stageRatio$,
390
398
  readonly$: this._readonly$,
391
399
  collectorRect$: this.collector._rect$,
392
400
  managerHighlightStage$: this._highlightStage$,
393
401
  });
394
402
 
395
- box.mount(this.root);
396
-
397
403
  if (box.focus) {
398
404
  this.focusBox(box);
399
405
  if (smartPosition) {
@@ -522,6 +528,20 @@ export class TeleBoxManager {
522
528
  return deletedBoxes;
523
529
  }
524
530
 
531
+ /**
532
+ * Mount manager to a container element.
533
+ */
534
+ public mount(root: HTMLElement): void {
535
+ this._root$.setValue(root);
536
+ }
537
+
538
+ /**
539
+ * Unmount manager from the container element.
540
+ */
541
+ public unmount(): void {
542
+ this._root$.setValue(null);
543
+ }
544
+
525
545
  public destroy(skipUpdate = false): void {
526
546
  this.events.clearListeners();
527
547
  this._sideEffect.flushAll();
@@ -650,6 +670,9 @@ export class TeleBoxManager {
650
670
  if (config.zIndex != null) {
651
671
  box._zIndex$.setValue(config.zIndex, skipUpdate);
652
672
  }
673
+ if (config.stageRatio !== undefined) {
674
+ box.setStageRatio(config.stageRatio, skipUpdate);
675
+ }
653
676
  if (config.content != null) {
654
677
  box.mountContent(config.content);
655
678
  }
@@ -6,7 +6,7 @@ import type { TELE_BOX_MANAGER_EVENT } from "./constants";
6
6
 
7
7
  export interface TeleBoxManagerConfig extends Pick<TeleBoxConfig, "namespace"> {
8
8
  /** Element to mount boxes. */
9
- readonly root?: HTMLElement;
9
+ readonly root?: HTMLElement | null;
10
10
  /** Stage area height/with ratio. No ratio if <= 0. Default -1. */
11
11
  readonly stageRatio?: number;
12
12
  /** Where the minimized boxes go. */
@@ -37,11 +37,17 @@ type TeleBoxManagerBoxConfigBaseProps =
37
37
  | "resizable"
38
38
  | "draggable"
39
39
  | "ratio"
40
- | "zIndex";
40
+ | "zIndex"
41
+ | "stageRatio";
41
42
 
42
43
  export type TeleBoxManagerCreateConfig = Pick<
43
44
  TeleBoxConfig,
44
- TeleBoxManagerBoxConfigBaseProps | "content" | "footer" | "id" | "focus"
45
+ | TeleBoxManagerBoxConfigBaseProps
46
+ | "content"
47
+ | "stage"
48
+ | "footer"
49
+ | "id"
50
+ | "focus"
45
51
  >;
46
52
 
47
53
  export type TeleBoxManagerQueryConfig = Pick<
@@ -51,6 +57,7 @@ export type TeleBoxManagerQueryConfig = Pick<
51
57
  | "resizable"
52
58
  | "draggable"
53
59
  | "ratio"
60
+ | "stageRatio"
54
61
  | "zIndex"
55
62
  | "id"
56
63
  | "focus"
@@ -58,7 +65,7 @@ export type TeleBoxManagerQueryConfig = Pick<
58
65
 
59
66
  export type TeleBoxManagerUpdateConfig = Pick<
60
67
  TeleBoxConfig,
61
- TeleBoxManagerBoxConfigBaseProps | "content" | "footer"
68
+ TeleBoxManagerBoxConfigBaseProps | "content" | "stage" | "footer"
62
69
  >;
63
70
 
64
71
  type CheckTeleBoxManagerConfig<
@@ -3,13 +3,12 @@ import "./style.scss";
3
3
  import shallowequal from "shallowequal";
4
4
  import { SideEffectManager } from "side-effect-manager";
5
5
  import type { ReadonlyVal } from "value-enhancer";
6
- import { Val } from "value-enhancer";
7
6
  import { combine } from "value-enhancer";
8
7
  import type { TeleBoxRect } from "../TeleBox/typings";
9
8
 
10
9
  export interface TeleStageConfig {
11
10
  namespace: string;
12
- root?: HTMLElement | null;
11
+ root$: ReadonlyVal<HTMLElement | null>;
13
12
  rootRect$: ReadonlyVal<TeleBoxRect>;
14
13
  ratio$: ReadonlyVal<number>;
15
14
  highlightStage$: ReadonlyVal<boolean>;
@@ -21,7 +20,6 @@ export class TeleStage {
21
20
  public readonly namespace: string;
22
21
  public readonly stageRect$: ReadonlyVal<TeleBoxRect>;
23
22
  public readonly highlightStage$: ReadonlyVal<boolean>;
24
- public readonly root$: Val<HTMLElement | null>;
25
23
 
26
24
  public $boxStage?: HTMLDivElement;
27
25
 
@@ -30,19 +28,14 @@ export class TeleStage {
30
28
  rootRect$,
31
29
  ratio$,
32
30
  highlightStage$,
33
- root = null,
31
+ root$,
34
32
  }: TeleStageConfig) {
35
33
  this.namespace = namespace;
36
34
  this.highlightStage$ = highlightStage$;
37
- this.root$ = new Val<HTMLElement | null>(root);
38
35
 
39
36
  this.stageRect$ = combine(
40
- [rootRect$, highlightStage$, ratio$],
41
- ([rootRect, highlightStage, ratio]) => {
42
- if (!highlightStage) {
43
- return rootRect;
44
- }
45
-
37
+ [rootRect$, ratio$],
38
+ ([rootRect, ratio]) => {
46
39
  if (ratio <= 0 || rootRect.width <= 0 || rootRect.height <= 0) {
47
40
  return rootRect;
48
41
  }
@@ -73,7 +66,7 @@ export class TeleStage {
73
66
  );
74
67
 
75
68
  this._sideEffect.addDisposer(
76
- combine([this.root$, highlightStage$]).subscribe(
69
+ combine([root$, highlightStage$]).subscribe(
77
70
  ([root, highlightStage]) => {
78
71
  if (root && highlightStage) {
79
72
  root.appendChild(this.render());
@@ -171,14 +164,6 @@ export class TeleStage {
171
164
  return $boxStage;
172
165
  }
173
166
 
174
- public mount($root: HTMLElement): void {
175
- this.root$.setValue($root);
176
- }
177
-
178
- public unmount(): void {
179
- this.root$.setValue(null);
180
- }
181
-
182
167
  public destroy(): void {
183
168
  this._sideEffect.flushAll();
184
169
  }
@@ -3,7 +3,7 @@
3
3
  .#{$namespace}-box-stage-container {
4
4
  display: none;
5
5
  position: absolute;
6
- z-index: $base-z-index - 1;
6
+ z-index: $stage-z-index;
7
7
  top: 0;
8
8
  left: 0;
9
9
  width: 100%;
@@ -14,7 +14,7 @@ import type {
14
14
  TeleTitleBarEvent,
15
15
  } from "../typings";
16
16
  import { preventEvent } from "../../utils";
17
- import { Val } from "value-enhancer";
17
+ import type { ReadonlyVal } from "value-enhancer";
18
18
 
19
19
  export type DefaultTitleBarButton = TeleTitleBarEvent & {
20
20
  readonly iconClassName: string;
@@ -29,7 +29,7 @@ export class DefaultTitleBar implements TeleTitleBar {
29
29
  public constructor({
30
30
  readonly$,
31
31
  state$,
32
- title = "",
32
+ title$,
33
33
  buttons,
34
34
  onEvent,
35
35
  onDragStart,
@@ -37,7 +37,7 @@ export class DefaultTitleBar implements TeleTitleBar {
37
37
  }: DefaultTitleBarConfig) {
38
38
  this.readonly$ = readonly$;
39
39
  this.state$ = state$;
40
- this.title$ = new Val(title);
40
+ this.title$ = title$;
41
41
  this.onEvent = onEvent;
42
42
  this.onDragStart = onDragStart;
43
43
  this.namespace = namespace;
@@ -67,14 +67,6 @@ export class DefaultTitleBar implements TeleTitleBar {
67
67
 
68
68
  public $dragArea: HTMLElement;
69
69
 
70
- public get title(): string {
71
- return this.title$.value;
72
- }
73
-
74
- public setTitle(title: string): void {
75
- this.title$.setValue(title);
76
- }
77
-
78
70
  public render(): HTMLElement {
79
71
  if (!this.$titleBar) {
80
72
  this.$titleBar = document.createElement("div");
@@ -205,7 +197,7 @@ export class DefaultTitleBar implements TeleTitleBar {
205
197
 
206
198
  protected readonly$: TeleTitleBarConfig["readonly$"];
207
199
 
208
- protected title$: Val<string>;
200
+ protected title$: ReadonlyVal<string>;
209
201
 
210
202
  protected buttons: ReadonlyArray<DefaultTitleBarButton>;
211
203
 
@@ -10,7 +10,7 @@ export type TeleTitleBarEvent<U = keyof TeleBoxDelegateEventConfig> =
10
10
 
11
11
  export interface TeleTitleBarConfig {
12
12
  readonly$: ReadonlyVal<boolean, boolean>;
13
- title?: string;
13
+ title$: ReadonlyVal<string, boolean>;
14
14
  state$: ReadonlyVal<TeleBoxState, boolean>;
15
15
  namespace?: string;
16
16
  onEvent?: (event: TeleTitleBarEvent) => void;
@@ -1,2 +1,5 @@
1
1
  $namespace: "telebox";
2
2
  $base-z-index: 100;
3
+ $max-titlebar-z-index: $base-z-index + 5000;
4
+ $stage-z-index: $max-titlebar-z-index + 10;
5
+ $collector-z-index: $stage-z-index + 10;