@netless/telebox-insider 0.2.4 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/telebox-insider",
3
- "version": "0.2.4",
3
+ "version": "0.2.8",
4
4
  "private": false,
5
5
  "description": "Window widget for Whiteboard",
6
6
  "license": "MIT",
@@ -75,6 +75,6 @@
75
75
  "shallowequal": "^1.1.0",
76
76
  "side-effect-manager": "^0.1.5",
77
77
  "stylefire": "^7.0.3",
78
- "value-enhancer": "^0.0.7"
78
+ "value-enhancer": "^0.0.8"
79
79
  }
80
80
  }
@@ -1,3 +1,9 @@
1
+ export enum TELE_BOX_COLOR_SCHEME {
2
+ Light = "light",
3
+ Dark = "dark",
4
+ Auto = "auto",
5
+ }
6
+
1
7
  export enum TELE_BOX_STATE {
2
8
  Normal = "normal",
3
9
  Minimized = "minimized",
@@ -5,6 +11,8 @@ export enum TELE_BOX_STATE {
5
11
  }
6
12
 
7
13
  export enum TELE_BOX_EVENT {
14
+ DarkMode = "dark_mode",
15
+ PrefersColorScheme = "prefers_color_scheme",
8
16
  Close = "close",
9
17
  Focus = "focus",
10
18
  Blur = "blur",
@@ -26,6 +26,7 @@ import {
26
26
  TELE_BOX_STATE,
27
27
  TELE_BOX_RESIZE_HANDLE,
28
28
  TELE_BOX_DELEGATE_EVENT,
29
+ TELE_BOX_COLOR_SCHEME,
29
30
  } from "./constants";
30
31
  import type {
31
32
  TeleBoxConfig,
@@ -36,12 +37,15 @@ import type {
36
37
  TeleBoxDelegateEvents,
37
38
  TeleBoxCoord,
38
39
  TeleBoxSize,
40
+ TeleBoxColorScheme,
39
41
  } from "./typings";
40
42
 
41
43
  export * from "./constants";
42
44
  export * from "./typings";
43
45
 
44
46
  type ValConfig = {
47
+ prefersColorScheme: Val<TeleBoxColorScheme, boolean>;
48
+ darkMode: Val<boolean, boolean>;
45
49
  containerRect: Val<TeleBoxRect, boolean>;
46
50
  collectorRect: Val<TeleBoxRect | undefined, boolean>;
47
51
  /** Box title. Default empty. */
@@ -74,6 +78,8 @@ export class TeleBox {
74
78
  public constructor({
75
79
  id = genUniqueKey(),
76
80
  title = getBoxDefaultName(),
81
+ prefersColorScheme = TELE_BOX_COLOR_SCHEME.Light,
82
+ darkMode,
77
83
  visible = true,
78
84
  width = 0.5,
79
85
  height = 0.5,
@@ -112,6 +118,58 @@ export class TeleBox {
112
118
  this.events = new EventEmitter();
113
119
  this._delegateEvents = new EventEmitter();
114
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
+ darkMode$.setValue(prefersDark.matches, skipUpdate);
144
+ const handler = (
145
+ evt: MediaQueryListEvent
146
+ ): void => {
147
+ darkMode$.setValue(evt.matches, skipUpdate);
148
+ };
149
+ prefersDark.addEventListener("change", handler);
150
+ return () =>
151
+ prefersDark.removeEventListener(
152
+ "change",
153
+ handler
154
+ );
155
+ } else {
156
+ darkMode$.setValue(
157
+ prefersColorScheme === "dark",
158
+ skipUpdate
159
+ );
160
+ return () => {};
161
+ }
162
+ }, "prefers-color-scheme");
163
+ }
164
+ );
165
+ }
166
+
167
+ darkMode$.reaction((darkMode, _, skipUpdate) => {
168
+ if (!skipUpdate) {
169
+ this.events.emit(TELE_BOX_EVENT.DarkMode, darkMode);
170
+ }
171
+ });
172
+
115
173
  const containerRect$ = createVal(containerRect, shallowequal);
116
174
  const collectorRect$ = createVal(collectorRect, shallowequal);
117
175
 
@@ -354,6 +412,8 @@ export class TeleBox {
354
412
  const $userStyles$ = createVal(styles);
355
413
 
356
414
  const valConfig: ValConfig = {
415
+ prefersColorScheme: prefersColorScheme$,
416
+ darkMode: darkMode$,
357
417
  containerRect: containerRect$,
358
418
  collectorRect: collectorRect$,
359
419
  title: title$,
@@ -417,6 +477,10 @@ export class TeleBox {
417
477
  public _coord$: Val<TeleBoxCoord, boolean>;
418
478
  public _intrinsicCoord$: Val<TeleBoxCoord, boolean>;
419
479
 
480
+ public get darkMode(): boolean {
481
+ return this._darkMode$.value;
482
+ }
483
+
420
484
  public _state$: Val<TeleBoxState, boolean>;
421
485
 
422
486
  public get state(): TeleBoxState {
@@ -690,6 +754,9 @@ export class TeleBox {
690
754
  /** DOM of the box content */
691
755
  public $content!: HTMLElement;
692
756
 
757
+ /** DOM of the box title bar */
758
+ public $titleBar!: HTMLElement;
759
+
693
760
  /** DOM of the box footer */
694
761
  public $footer!: HTMLElement;
695
762
 
@@ -732,6 +799,13 @@ export class TeleBox {
732
799
  bindClassName(this.$box, this._draggable$, "no-drag", isFalsy);
733
800
  bindClassName(this.$box, this._resizable$, "no-resize", isFalsy);
734
801
  bindClassName(this.$box, this._focus$, "blur", isFalsy);
802
+ bindClassName(this.$box, this._darkMode$, "color-scheme-dark");
803
+ bindClassName(
804
+ this.$box,
805
+ this._darkMode$,
806
+ "color-scheme-light",
807
+ isFalsy
808
+ );
735
809
 
736
810
  this._renderSideEffect.add(() => {
737
811
  const minimizedClassName = this.wrapClassName("minimized");
@@ -833,6 +907,7 @@ export class TeleBox {
833
907
  const $titleBar = document.createElement("div");
834
908
  $titleBar.className = this.wrapClassName("titlebar-wrap");
835
909
  $titleBar.appendChild(this.titleBar.render());
910
+ this.$titleBar = $titleBar;
836
911
 
837
912
  const $contentWrap = document.createElement("div");
838
913
  $contentWrap.className = this.wrapClassName("content-wrap");
@@ -202,3 +202,11 @@
202
202
  pointer-events: none !important;
203
203
  }
204
204
  }
205
+
206
+ .#{$namespace}-color-scheme-dark {
207
+ .#{$namespace}-box-main {
208
+ color: #e9e9e9;
209
+ background: #212126;
210
+ border-color: #43434d;
211
+ }
212
+ }
@@ -6,8 +6,11 @@ import type {
6
6
  TELE_BOX_DELEGATE_EVENT,
7
7
  TELE_BOX_RESIZE_HANDLE,
8
8
  TELE_BOX_STATE,
9
+ TELE_BOX_COLOR_SCHEME,
9
10
  } from "./constants";
10
11
 
12
+ export type TeleBoxColorScheme = `${TELE_BOX_COLOR_SCHEME}`;
13
+
11
14
  export type TeleBoxCoord = { x: number; y: number };
12
15
 
13
16
  export type TeleBoxSize = { width: number; height: number };
@@ -26,6 +29,10 @@ export interface TeleBoxConfig {
26
29
  readonly id?: string;
27
30
  /** Box title. Default empty. */
28
31
  readonly title?: string;
32
+ /** Prefers Box color scheme. Default light. */
33
+ readonly prefersColorScheme?: TeleBoxColorScheme;
34
+ /** Actual Box Dark Mode */
35
+ readonly darkMode?: boolean;
29
36
  /** Box visible. Default true. */
30
37
  readonly visible?: boolean;
31
38
  /** Box width relative to root element. 0~1. Default 0.5. */
@@ -79,6 +86,8 @@ export interface TeleBoxConfig {
79
86
  type CheckTeleBoxConfig<T extends Record<`${TELE_BOX_EVENT}`, any>> = T;
80
87
 
81
88
  export type TeleBoxEventConfig = CheckTeleBoxConfig<{
89
+ dark_mode: boolean;
90
+ prefers_color_scheme: TeleBoxColorScheme;
82
91
  close: void;
83
92
  focus: void;
84
93
  blur: void;
@@ -10,4 +10,6 @@ export enum TELE_BOX_MANAGER_EVENT {
10
10
  IntrinsicMove = "intrinsic_move",
11
11
  IntrinsicResize = "intrinsic_resize",
12
12
  VisualResize = "visual_resize",
13
+ PrefersColorScheme = "prefers_color_scheme",
14
+ DarkMode = "dark_mode",
13
15
  }
@@ -17,7 +17,11 @@ import type {
17
17
  TeleBoxManagerUpdateConfig,
18
18
  } from "./typings";
19
19
  import { MaxTitleBar } from "./MaxTitleBar";
20
- import { TELE_BOX_DELEGATE_EVENT } from "..";
20
+ import {
21
+ TeleBoxColorScheme,
22
+ TELE_BOX_COLOR_SCHEME,
23
+ TELE_BOX_DELEGATE_EVENT,
24
+ } from "..";
21
25
  import { SideEffectManager } from "side-effect-manager";
22
26
  import {
23
27
  createSideEffectBinder,
@@ -30,6 +34,7 @@ export * from "./typings";
30
34
  export * from "./constants";
31
35
 
32
36
  type ValConfig = {
37
+ prefersColorScheme: Val<TeleBoxColorScheme, boolean>;
33
38
  containerRect: Val<TeleBoxRect, boolean>;
34
39
  collector: Val<TeleBoxCollector | null>;
35
40
  readonly: Val<boolean, boolean>;
@@ -42,6 +47,7 @@ export interface TeleBoxManager extends ValEnhancedResult<ValConfig> {}
42
47
  export class TeleBoxManager {
43
48
  public constructor({
44
49
  root = document.body,
50
+ prefersColorScheme = TELE_BOX_COLOR_SCHEME.Light,
45
51
  minimized = false,
46
52
  maximized = false,
47
53
  fence = true,
@@ -63,6 +69,43 @@ export class TeleBoxManager {
63
69
  this.namespace = namespace;
64
70
  this.zIndex = zIndex;
65
71
 
72
+ const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
73
+ const prefersDark$ = createVal(prefersDark.matches);
74
+ this._sideEffect.add(() => {
75
+ const handler = (evt: MediaQueryListEvent): void => {
76
+ prefersDark$.setValue(evt.matches);
77
+ };
78
+ prefersDark.addEventListener("change", handler);
79
+ return () => prefersDark.removeEventListener("change", handler);
80
+ });
81
+
82
+ const prefersColorScheme$ = createVal(prefersColorScheme);
83
+ prefersColorScheme$.reaction((prefersColorScheme, _, skipUpdate) => {
84
+ this.boxes.forEach((box) =>
85
+ box.setPrefersColorScheme(prefersColorScheme, skipUpdate)
86
+ );
87
+ if (!skipUpdate) {
88
+ this.events.emit(
89
+ TELE_BOX_MANAGER_EVENT.PrefersColorScheme,
90
+ prefersColorScheme
91
+ );
92
+ }
93
+ });
94
+
95
+ this._darkMode$ = combine(
96
+ [prefersDark$, prefersColorScheme$],
97
+ ([prefersDark, prefersColorScheme]) =>
98
+ prefersColorScheme === "auto"
99
+ ? prefersDark
100
+ : prefersColorScheme === "dark"
101
+ );
102
+ this._darkMode$.reaction((darkMode, _, skipUpdate) => {
103
+ this.boxes.forEach((box) => box.setDarkMode(darkMode, skipUpdate));
104
+ if (!skipUpdate) {
105
+ this.events.emit(TELE_BOX_MANAGER_EVENT.DarkMode, darkMode);
106
+ }
107
+ });
108
+
66
109
  const readonly$ = createVal(readonly);
67
110
  readonly$.reaction((readonly, _, skipUpdate) => {
68
111
  this.boxes.forEach((box) => box.setReadonly(readonly, skipUpdate));
@@ -246,6 +289,7 @@ export class TeleBoxManager {
246
289
  );
247
290
 
248
291
  const valConfig: ValConfig = {
292
+ prefersColorScheme: prefersColorScheme$,
249
293
  containerRect: containerRect$,
250
294
  collector: collector$,
251
295
  readonly: readonly$,
@@ -271,6 +315,12 @@ export class TeleBoxManager {
271
315
 
272
316
  public zIndex: number;
273
317
 
318
+ public _darkMode$: Val<boolean, boolean>;
319
+
320
+ public get darkMode(): boolean {
321
+ return this._darkMode$.value;
322
+ }
323
+
274
324
  public _state$: Val<TeleBoxState, boolean>;
275
325
 
276
326
  public get state(): TeleBoxState {
@@ -385,11 +435,11 @@ export class TeleBoxManager {
385
435
  const box = boxes[0];
386
436
  this.focusBox({ focus: false, box });
387
437
  box.destroy();
388
- if (this.boxes.length <= 0) {
389
- this.setMaximized(false);
390
- this.setMinimized(false);
391
- }
392
438
  if (!skipUpdate) {
439
+ if (this.boxes.length <= 0) {
440
+ this.setMaximized(false);
441
+ this.setMinimized(false);
442
+ }
393
443
  this.events.emit(TELE_BOX_MANAGER_EVENT.Removed, boxes);
394
444
  }
395
445
  return box;
@@ -412,11 +462,11 @@ export class TeleBoxManager {
412
462
  const boxes = this.boxes.splice(0, this.boxes.length);
413
463
  this.maxTitleBar.setBoxes(this.boxes);
414
464
  boxes.forEach((box) => box.destroy());
415
- if (this.boxes.length <= 0) {
416
- this.setMaximized(false);
417
- this.setMinimized(false);
418
- }
419
465
  if (!skipUpdate) {
466
+ if (this.boxes.length <= 0) {
467
+ this.setMaximized(false);
468
+ this.setMinimized(false);
469
+ }
420
470
  this.events.emit(TELE_BOX_MANAGER_EVENT.Removed, boxes);
421
471
  }
422
472
  return boxes;
@@ -614,6 +664,8 @@ export class TeleBoxManager {
614
664
  y,
615
665
  width,
616
666
  height,
667
+ darkMode: this.darkMode,
668
+ prefersColorScheme: this.prefersColorScheme,
617
669
  maximized: this.maximized,
618
670
  minimized: this.minimized,
619
671
  fence: this.fence,
@@ -1,4 +1,5 @@
1
1
  import type EventEmitter from "eventemitter3";
2
+ import { TeleBoxColorScheme } from "..";
2
3
  import type { ReadonlyTeleBox, TeleBoxState } from "../TeleBox";
3
4
  import type { TeleBoxConfig } from "../TeleBox/typings";
4
5
  import type { TeleBoxCollector } from "../TeleBoxCollector";
@@ -7,6 +8,7 @@ import type { TELE_BOX_MANAGER_EVENT } from "./constants";
7
8
  export interface TeleBoxManagerConfig
8
9
  extends Pick<
9
10
  TeleBoxConfig,
11
+ | "prefersColorScheme"
10
12
  | "fence"
11
13
  | "containerRect"
12
14
  | "maximized"
@@ -67,6 +69,8 @@ export type TeleBoxManagerEventConfig = CheckTeleBoxManagerConfig<{
67
69
  intrinsic_move: [ReadonlyTeleBox];
68
70
  intrinsic_resize: [ReadonlyTeleBox];
69
71
  visual_resize: [ReadonlyTeleBox];
72
+ prefers_color_scheme: [TeleBoxColorScheme];
73
+ dark_mode: [boolean];
70
74
  }>;
71
75
 
72
76
  export type TeleBoxManagerEvent = keyof TeleBoxManagerEventConfig;
@@ -16,6 +16,12 @@ export type TeleBoxReactProps = TeleBoxConfig & {
16
16
  export const TeleBoxReact: FC<TeleBoxReactProps> = (props) => {
17
17
  const [teleBox] = useState(() => new TeleBox(props));
18
18
 
19
+ useUpdateEffect(() => {
20
+ if (props.prefersColorScheme != null) {
21
+ teleBox.setPrefersColorScheme(props.prefersColorScheme);
22
+ }
23
+ }, [teleBox, props.prefersColorScheme]);
24
+
19
25
  useUpdateEffect(() => {
20
26
  if (props.minWidth != null) {
21
27
  teleBox.setMinWidth(props.minWidth);
@@ -52,6 +58,18 @@ export const TeleBoxReact: FC<TeleBoxReactProps> = (props) => {
52
58
  }
53
59
  }, [teleBox, props.visible]);
54
60
 
61
+ useUpdateEffect(() => {
62
+ if (props.minimized != null) {
63
+ teleBox.setMinimized(props.minimized, true);
64
+ }
65
+ }, [teleBox, props.minimized]);
66
+
67
+ useUpdateEffect(() => {
68
+ if (props.maximized != null) {
69
+ teleBox.setMaximized(props.maximized, true);
70
+ }
71
+ }, [teleBox, props.maximized]);
72
+
55
73
  useUpdateEffect(() => {
56
74
  if (props.state != null) {
57
75
  teleBox.setState(props.state, true);
@@ -71,3 +71,15 @@
71
71
  .#{$namespace}-titlebar-icon-close {
72
72
  background: center / cover no-repeat url("./icons/close.svg");
73
73
  }
74
+
75
+ .#{$namespace}-color-scheme-dark {
76
+ .#{$namespace}-title {
77
+ color: #e9e9e9;
78
+ }
79
+
80
+ .#{$namespace}-titlebar {
81
+ color: #e9e9e9;
82
+ background: #43434d;
83
+ border-bottom: none;
84
+ }
85
+ }