@netless/telebox-insider 0.2.16 → 0.2.20

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.16",
3
+ "version": "0.2.20",
4
4
  "private": false,
5
5
  "description": "Window widget for Whiteboard",
6
6
  "license": "MIT",
@@ -935,7 +935,7 @@ export class TeleBox {
935
935
  }
936
936
  last$userStyles = $userStyles;
937
937
  if ($userStyles) {
938
- $content.appendChild($userStyles);
938
+ $contentWrap.appendChild($userStyles);
939
939
  }
940
940
  });
941
941
  });
@@ -105,6 +105,13 @@ export class MaxTitleBar extends DefaultTitleBar {
105
105
 
106
106
  public render(): HTMLElement {
107
107
  const $titleBar = super.render();
108
+ if ($titleBar.firstElementChild?.nextElementSibling) {
109
+ $titleBar.insertBefore(
110
+ this.$dragArea,
111
+ $titleBar.firstElementChild.nextElementSibling
112
+ );
113
+ }
114
+
108
115
  const { x, y, width } = this.containerRect;
109
116
  $titleBar.style.transform = `translate(${x}px, ${y}px)`;
110
117
  $titleBar.style.width = width + "px";
@@ -15,6 +15,15 @@ $scrollbar-color-active: rgba(238, 238, 247, 1);
15
15
  left: 0;
16
16
  z-index: $base-z-index * 500;
17
17
  user-select: none;
18
+
19
+ .#{$namespace}-drag-area {
20
+ height: 100%;
21
+ min-width: 16px;
22
+ position: static;
23
+ margin: 0;
24
+ flex-grow: 1;
25
+ flex-shrink: 0;
26
+ }
18
27
  }
19
28
 
20
29
  .#{$namespace}-max-titlebar-maximized {
@@ -36,9 +45,8 @@ $scrollbar-color-active: rgba(238, 238, 247, 1);
36
45
  }
37
46
 
38
47
  .#{$namespace}-titles {
39
- flex: 1;
40
48
  height: 100%;
41
- margin: 0 16px 0 -16px;
49
+ margin: 0;
42
50
  overflow-y: hidden;
43
51
  overflow-x: scroll;
44
52
  overflow-x: overlay; // for webkit
@@ -92,6 +100,7 @@ $scrollbar-color-active: rgba(238, 238, 247, 1);
92
100
  }
93
101
 
94
102
  .#{$namespace}-titles-tab {
103
+ height: 100%;
95
104
  overflow: hidden;
96
105
  max-width: 182px;
97
106
  min-width: 50px;
@@ -108,10 +117,7 @@ $scrollbar-color-active: rgba(238, 238, 247, 1);
108
117
  color: #7b88a0;
109
118
  background: transparent;
110
119
  cursor: pointer;
111
-
112
- & ~ & {
113
- margin-left: 2px;
114
- }
120
+ user-select: none;
115
121
  }
116
122
 
117
123
  .#{$namespace}-titles-tab-focus {
@@ -37,6 +37,7 @@ type ValConfig = {
37
37
  prefersColorScheme: Val<TeleBoxColorScheme, boolean>;
38
38
  containerRect: Val<TeleBoxRect, boolean>;
39
39
  collector: Val<TeleBoxCollector | null>;
40
+ collectorRect: Val<TeleBoxRect | undefined>;
40
41
  readonly: Val<boolean, boolean>;
41
42
  minimized: Val<boolean, boolean>;
42
43
  maximized: Val<boolean, boolean>;
@@ -197,25 +198,36 @@ export class TeleBoxManager {
197
198
  collector$.value?.setDarkMode(darkMode);
198
199
  });
199
200
 
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;
214
+ };
215
+
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
+
200
225
  minimized$.subscribe((minimized, _, skipUpdate) => {
201
226
  collector$.value?.setVisible(minimized);
202
227
 
203
228
  if (minimized) {
204
229
  if (collector$.value?.$collector) {
205
- const { x, y, width, height } =
206
- collector$.value.$collector.getBoundingClientRect();
207
- const rootRect = this.root.getBoundingClientRect();
208
- this.boxes.forEach((box) => {
209
- box.setCollectorRect(
210
- {
211
- x: x - rootRect.x,
212
- y: y - rootRect.y,
213
- width,
214
- height,
215
- },
216
- true
217
- );
218
- });
230
+ collectorRect$.setValue(calcCollectorRect());
219
231
  } else if (import.meta.env.DEV) {
220
232
  console.warn("No collector for minimized boxes.");
221
233
  }
@@ -255,6 +267,7 @@ export class TeleBoxManager {
255
267
  const box = this.getBox(id);
256
268
  if (box) {
257
269
  this.focusBox(box);
270
+ this.makeBoxTop(box);
258
271
  return;
259
272
  }
260
273
  }
@@ -293,6 +306,7 @@ export class TeleBoxManager {
293
306
  }
294
307
  case TELE_BOX_EVENT.Close: {
295
308
  this.removeTopBox();
309
+ this.focusTopBox();
296
310
  break;
297
311
  }
298
312
  default: {
@@ -315,6 +329,7 @@ export class TeleBoxManager {
315
329
  prefersColorScheme: prefersColorScheme$,
316
330
  containerRect: containerRect$,
317
331
  collector: collector$,
332
+ collectorRect: collectorRect$,
318
333
  readonly: readonly$,
319
334
  fence: fence$,
320
335
  minimized: minimized$,
@@ -393,12 +408,16 @@ export class TeleBoxManager {
393
408
  namespace: this.namespace,
394
409
  containerRect: this.containerRect,
395
410
  readonly: this.readonly,
411
+ collectorRect: this.collectorRect,
396
412
  });
397
413
 
398
414
  box.mount(this.root);
399
415
 
400
416
  if (box.focus) {
401
417
  this.focusBox(box);
418
+ if (smartPosition) {
419
+ this.makeBoxTop(box);
420
+ }
402
421
  }
403
422
 
404
423
  this.boxes$.setValue([...this.boxes, box]);
@@ -411,26 +430,40 @@ export class TeleBoxManager {
411
430
  });
412
431
  box._delegateEvents.on(TELE_BOX_DELEGATE_EVENT.Close, () => {
413
432
  this.remove(box);
433
+ this.focusTopBox();
414
434
  });
415
- box.events.on(TELE_BOX_EVENT.Move, () => {
416
- this.events.emit(TELE_BOX_MANAGER_EVENT.Move, box);
435
+ box._coord$.reaction((_, __, skipUpdate) => {
436
+ if (!skipUpdate) {
437
+ this.events.emit(TELE_BOX_MANAGER_EVENT.Move, box);
438
+ }
417
439
  });
418
- box.events.on(TELE_BOX_EVENT.Resize, () => {
419
- this.events.emit(TELE_BOX_MANAGER_EVENT.Resize, box);
440
+ box._size$.reaction((_, __, skipUpdate) => {
441
+ if (!skipUpdate) {
442
+ this.events.emit(TELE_BOX_MANAGER_EVENT.Resize, box);
443
+ }
420
444
  });
421
- box.events.on(TELE_BOX_EVENT.IntrinsicMove, () => {
422
- this.events.emit(TELE_BOX_MANAGER_EVENT.IntrinsicMove, box);
445
+ box._intrinsicCoord$.reaction((_, __, skipUpdate) => {
446
+ if (!skipUpdate) {
447
+ this.events.emit(TELE_BOX_MANAGER_EVENT.IntrinsicMove, box);
448
+ }
423
449
  });
424
- box.events.on(TELE_BOX_EVENT.IntrinsicResize, () => {
425
- this.events.emit(TELE_BOX_MANAGER_EVENT.IntrinsicResize, box);
450
+ box._intrinsicSize$.reaction((_, __, skipUpdate) => {
451
+ if (!skipUpdate) {
452
+ this.events.emit(TELE_BOX_MANAGER_EVENT.IntrinsicResize, box);
453
+ }
426
454
  });
427
- box.events.on(TELE_BOX_EVENT.VisualResize, () => {
428
- this.events.emit(TELE_BOX_MANAGER_EVENT.VisualResize, box);
455
+ box._visualSize$.reaction((_, __, skipUpdate) => {
456
+ if (!skipUpdate) {
457
+ this.events.emit(TELE_BOX_MANAGER_EVENT.VisualResize, box);
458
+ }
429
459
  });
430
- box.events.on(TELE_BOX_EVENT.ZIndex, () => {
460
+ box._zIndex$.reaction((_, __, skipUpdate) => {
431
461
  if (this.topBox && box.zIndex > this.topBox.zIndex) {
432
462
  this.topBox$.setValue(box);
433
463
  }
464
+ if (!skipUpdate) {
465
+ this.events.emit(TELE_BOX_MANAGER_EVENT.ZIndex, box);
466
+ }
434
467
  });
435
468
  this.events.emit(TELE_BOX_MANAGER_EVENT.Created, box);
436
469
 
@@ -480,7 +513,6 @@ export class TeleBoxManager {
480
513
  const boxes = this.boxes.slice();
481
514
  const deletedBoxes = boxes.splice(index, 1);
482
515
  this.boxes$.setValue(boxes);
483
- this.focusTopBox();
484
516
  deletedBoxes.forEach((box) => box.destroy());
485
517
  if (!skipUpdate) {
486
518
  if (this.boxes.length <= 0) {
@@ -542,7 +574,6 @@ export class TeleBoxManager {
542
574
  focusChanged = true;
543
575
  targetBox.setFocus(true, skipUpdate);
544
576
  }
545
- this.makeBoxTop(targetBox, skipUpdate);
546
577
  if (focusChanged && !skipUpdate) {
547
578
  this.events.emit(
548
579
  TELE_BOX_MANAGER_EVENT.Focused,
@@ -640,16 +671,16 @@ export class TeleBoxManager {
640
671
  box.setMinWidth(config.minWidth, skipUpdate);
641
672
  }
642
673
  if (config.resizable != null) {
643
- box.setResizable(config.resizable);
674
+ box.setResizable(config.resizable, skipUpdate);
644
675
  }
645
676
  if (config.draggable != null) {
646
- box.setDraggable(config.draggable);
677
+ box.setDraggable(config.draggable, skipUpdate);
647
678
  }
648
679
  if (config.fixRatio != null) {
649
680
  box.setFixRatio(config.fixRatio, skipUpdate);
650
681
  }
651
682
  if (config.zIndex != null) {
652
- box.setZIndex(config.zIndex);
683
+ box.setZIndex(config.zIndex, skipUpdate);
653
684
  }
654
685
  if (config.content != null) {
655
686
  box.mountContent(config.content);
@@ -704,9 +735,6 @@ export class TeleBoxManager {
704
735
  if (box !== this.topBox) {
705
736
  box.setZIndex(this.topBox.zIndex + 1, skipUpdate);
706
737
  this.topBox$.setValue(box);
707
- if (!skipUpdate) {
708
- this.events.emit(TELE_BOX_MANAGER_EVENT.ZIndex, box);
709
- }
710
738
  }
711
739
  }
712
740
  }
@@ -56,6 +56,8 @@ export class DefaultTitleBar implements TeleTitleBar {
56
56
  iconClassName: this.wrapClassName("titlebar-icon-close"),
57
57
  },
58
58
  ];
59
+
60
+ this.$dragArea = this.renderDragArea();
59
61
  }
60
62
 
61
63
  public readonly namespace: string;
@@ -64,6 +66,8 @@ export class DefaultTitleBar implements TeleTitleBar {
64
66
 
65
67
  public $title: HTMLElement | undefined;
66
68
 
69
+ public $dragArea: HTMLElement;
70
+
67
71
  public setTitle(title: string): void {
68
72
  this.title = title;
69
73
  if (this.$title) {
@@ -97,18 +101,10 @@ export class DefaultTitleBar implements TeleTitleBar {
97
101
  if (!this.$titleBar) {
98
102
  this.$titleBar = document.createElement("div");
99
103
  this.$titleBar.className = this.wrapClassName("titlebar");
100
- this.$titleBar.dataset.teleBoxHandle = TeleBoxDragHandleType;
101
- this.sideEffect.addEventListener(
102
- this.$titleBar,
103
- "mousedown",
104
- this.handleTitleBarClick
105
- );
106
- this.sideEffect.addEventListener(
107
- this.$titleBar,
108
- "touchstart",
109
- this.handleTitleBarClick,
110
- { passive: true }
111
- );
104
+
105
+ const $titleArea = document.createElement("div");
106
+ $titleArea.className = this.wrapClassName("title-area");
107
+ $titleArea.dataset.teleBoxHandle = TeleBoxDragHandleType;
112
108
 
113
109
  this.$title = document.createElement("h1");
114
110
  this.$title.className = this.wrapClassName("title");
@@ -118,6 +114,9 @@ export class DefaultTitleBar implements TeleTitleBar {
118
114
  this.$title.title = this.title;
119
115
  }
120
116
 
117
+ $titleArea.appendChild(this.$title);
118
+ $titleArea.appendChild(this.$dragArea);
119
+
121
120
  const $buttonsContainer = document.createElement("div");
122
121
  $buttonsContainer.className = this.wrapClassName("titlebar-btns");
123
122
 
@@ -167,13 +166,31 @@ export class DefaultTitleBar implements TeleTitleBar {
167
166
  }
168
167
  );
169
168
 
170
- this.$titleBar.appendChild(this.$title);
169
+ this.$titleBar.appendChild($titleArea);
171
170
  this.$titleBar.appendChild($buttonsContainer);
172
171
  }
173
172
 
174
173
  return this.$titleBar;
175
174
  }
176
175
 
176
+ public renderDragArea(): HTMLElement {
177
+ const $dragArea = document.createElement("div");
178
+ $dragArea.className = this.wrapClassName("drag-area");
179
+ $dragArea.dataset.teleBoxHandle = TeleBoxDragHandleType;
180
+ this.sideEffect.addEventListener(
181
+ $dragArea,
182
+ "mousedown",
183
+ this.handleTitleBarClick
184
+ );
185
+ this.sideEffect.addEventListener(
186
+ $dragArea,
187
+ "touchstart",
188
+ this.handleTitleBarTouch,
189
+ { passive: true }
190
+ );
191
+ return $dragArea;
192
+ }
193
+
177
194
  public dragHandle(): HTMLElement | undefined {
178
195
  return this.$titleBar;
179
196
  }
@@ -209,17 +226,18 @@ export class DefaultTitleBar implements TeleTitleBar {
209
226
 
210
227
  protected sideEffect = new SideEffectManager();
211
228
 
212
- protected lastTitleBarClick = 0;
229
+ protected lastTitleBarClick = {
230
+ timestamp: 0,
231
+ clientX: -100,
232
+ clientY: -100,
233
+ };
213
234
 
214
- protected handleTitleBarClick = (ev: MouseEvent | TouchEvent): void => {
235
+ protected handleTitleBarClick = (ev: MouseEvent): void => {
215
236
  if (this.readonly) {
216
237
  return;
217
238
  }
218
239
 
219
- if (
220
- (ev as MouseEvent).button != null &&
221
- (ev as MouseEvent).button !== 0
222
- ) {
240
+ if (ev.button !== 0) {
223
241
  return; // Not left mouse
224
242
  }
225
243
 
@@ -230,14 +248,62 @@ export class DefaultTitleBar implements TeleTitleBar {
230
248
  preventEvent(ev);
231
249
 
232
250
  const now = Date.now();
233
- if (now - this.lastTitleBarClick <= 500) {
234
- // double click
235
- if (this.onEvent) {
236
- this.onEvent({ type: TELE_BOX_DELEGATE_EVENT.Maximize });
251
+ if (now - this.lastTitleBarClick.timestamp <= 500) {
252
+ if (
253
+ Math.abs(ev.clientX - this.lastTitleBarClick.clientX) <= 3 &&
254
+ Math.abs(ev.clientY - this.lastTitleBarClick.clientY) <= 3
255
+ ) {
256
+ // double click
257
+ if (this.onEvent) {
258
+ this.onEvent({ type: TELE_BOX_DELEGATE_EVENT.Maximize });
259
+ }
260
+ }
261
+ } else if (this.onDragStart) {
262
+ this.onDragStart(ev);
263
+ }
264
+ this.lastTitleBarClick.timestamp = now;
265
+ this.lastTitleBarClick.clientX = ev.clientX;
266
+ this.lastTitleBarClick.clientY = ev.clientY;
267
+ };
268
+
269
+ protected lastTitleBarTouch = {
270
+ timestamp: 0,
271
+ clientX: -100,
272
+ clientY: -100,
273
+ };
274
+
275
+ protected handleTitleBarTouch = (ev: TouchEvent): void => {
276
+ if (this.readonly) {
277
+ return;
278
+ }
279
+
280
+ if ((ev.target as HTMLElement).dataset?.teleTitleBarNoDblClick) {
281
+ return; // btns
282
+ }
283
+
284
+ preventEvent(ev);
285
+
286
+ const now = Date.now();
287
+ const {
288
+ clientX = this.lastTitleBarTouch.clientX + 100,
289
+ clientY = this.lastTitleBarTouch.clientY + 100,
290
+ } = ev.touches[0] || {};
291
+
292
+ if (now - this.lastTitleBarTouch.timestamp <= 500) {
293
+ if (
294
+ Math.abs(clientX - this.lastTitleBarTouch.clientX) <= 3 &&
295
+ Math.abs(clientY - this.lastTitleBarTouch.clientY) <= 3
296
+ ) {
297
+ // double click
298
+ if (this.onEvent) {
299
+ this.onEvent({ type: TELE_BOX_DELEGATE_EVENT.Maximize });
300
+ }
237
301
  }
238
302
  } else if (this.onDragStart) {
239
303
  this.onDragStart(ev);
240
304
  }
241
- this.lastTitleBarClick = now;
305
+ this.lastTitleBarTouch.timestamp = now;
306
+ this.lastTitleBarTouch.clientX = clientX;
307
+ this.lastTitleBarTouch.clientY = clientY;
242
308
  };
243
309
  }
@@ -9,11 +9,21 @@
9
9
  background: #fff;
10
10
  user-select: none;
11
11
  border-bottom: 1px solid #eeeef7;
12
+ touch-action: manipulation;
13
+ }
14
+
15
+ .#{$namespace}-title-area {
16
+ overflow: hidden;
17
+ position: relative;
18
+ height: 100%;
19
+ flex: 1;
20
+ display: flex;
21
+ align-items: center;
12
22
  }
13
23
 
14
24
  .#{$namespace}-title {
15
25
  overflow: hidden;
16
- margin: 0 24px 0 0;
26
+ margin: 0;
17
27
  padding: 0;
18
28
  font-size: 14px;
19
29
  font-weight: 400;
@@ -24,6 +34,16 @@
24
34
  color: #191919;
25
35
  }
26
36
 
37
+ .#{$namespace}-drag-area {
38
+ position: absolute;
39
+ top: 0;
40
+ left: 0;
41
+ right: 0;
42
+ bottom: 0;
43
+ margin: auto;
44
+ z-index: 10;
45
+ }
46
+
27
47
  .#{$namespace}-titlebar-btns {
28
48
  white-space: nowrap;
29
49
  word-break: keep-all;