@netless/fastboard 0.0.7 → 0.0.11

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 (49) hide show
  1. package/README.md +21 -19
  2. package/dist/index.cjs.js +4 -4
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.es.js +678 -410
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/svelte.cjs.js +1 -1
  7. package/dist/svelte.cjs.js.map +1 -1
  8. package/dist/svelte.es.js +1 -0
  9. package/dist/svelte.es.js.map +1 -1
  10. package/dist/vue.cjs.js +1 -1
  11. package/dist/vue.cjs.js.map +1 -1
  12. package/dist/vue.es.js +1 -0
  13. package/dist/vue.es.js.map +1 -1
  14. package/package.json +11 -2
  15. package/src/WhiteboardApp.ts +91 -20
  16. package/src/components/{PageControl.scss → PageControl/PageControl.scss} +0 -0
  17. package/src/components/PageControl/PageControl.tsx +110 -0
  18. package/src/components/PageControl/hooks.ts +70 -0
  19. package/src/components/PageControl/index.ts +2 -0
  20. package/src/components/PlayerControl/PlayerControl.tsx +7 -8
  21. package/src/components/PlayerControl/hooks.ts +3 -10
  22. package/src/components/PlayerControl/index.ts +1 -0
  23. package/src/components/{RedoUndo.scss → RedoUndo/RedoUndo.scss} +0 -0
  24. package/src/components/{RedoUndo.tsx → RedoUndo/RedoUndo.tsx} +13 -29
  25. package/src/components/RedoUndo/hooks.ts +50 -0
  26. package/src/components/RedoUndo/index.ts +2 -0
  27. package/src/components/Root.tsx +10 -6
  28. package/src/components/Toolbar/Content.tsx +4 -3
  29. package/src/components/Toolbar/Toolbar.scss +35 -1
  30. package/src/components/Toolbar/Toolbar.tsx +78 -28
  31. package/src/components/Toolbar/components/Mask.tsx +44 -0
  32. package/src/components/Toolbar/components/assets/collapsed.png +0 -0
  33. package/src/components/Toolbar/components/assets/expanded.png +0 -0
  34. package/src/components/Toolbar/hooks.ts +28 -29
  35. package/src/components/Toolbar/index.ts +1 -0
  36. package/src/components/{ZoomControl.scss → ZoomControl/ZoomControl.scss} +0 -0
  37. package/src/components/ZoomControl/ZoomControl.tsx +109 -0
  38. package/src/components/ZoomControl/hooks.ts +111 -0
  39. package/src/components/ZoomControl/index.ts +2 -0
  40. package/src/components/hooks.ts +80 -0
  41. package/src/index.ts +20 -5
  42. package/src/internal/Instance.tsx +31 -7
  43. package/src/internal/helpers.ts +44 -0
  44. package/src/internal/hooks.ts +9 -0
  45. package/src/react.tsx +52 -0
  46. package/src/style.scss +9 -3
  47. package/src/components/PageControl.tsx +0 -181
  48. package/src/components/ZoomControl.tsx +0 -221
  49. package/src/hooks.ts +0 -53
package/dist/index.es.js CHANGED
@@ -33,11 +33,12 @@ var __publicField = (obj, key, value) => {
33
33
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
34
34
  return value;
35
35
  };
36
- import { WindowManager } from "@netless/window-manager";
36
+ import { WindowManager, BuiltinApps } from "@netless/window-manager";
37
37
  import { WhiteWebSdk, DefaultHotKeys, ApplianceNames, ShapeType, PlayerPhase } from "white-web-sdk";
38
38
  import i18next from "i18next";
39
- import require$$0, { memo, forwardRef, useContext, useCallback, useState, useEffect, useRef, createContext } from "react";
39
+ import React, { useState, useEffect, useCallback, memo, forwardRef, useContext, useRef, createContext } from "react";
40
40
  import ReactDOM from "react-dom";
41
+ import { AnimatePresence, motion } from "framer-motion";
41
42
  import clsx from "clsx";
42
43
  import Tippy from "@tippyjs/react";
43
44
  import RcSlider from "rc-slider";
@@ -117,6 +118,36 @@ class Lock {
117
118
  }
118
119
  }
119
120
  }
121
+ const SOUP = "!#%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
122
+ const SOUP_LEN = SOUP.length;
123
+ const ID_LEN = 20;
124
+ const reusedIdCarrier = Array(ID_LEN);
125
+ const genUID = () => {
126
+ for (let i = 0; i < ID_LEN; i++) {
127
+ reusedIdCarrier[i] = SOUP.charAt(Math.random() * SOUP_LEN);
128
+ }
129
+ return reusedIdCarrier.join("");
130
+ };
131
+ function makeSlideParams(scenes) {
132
+ const scenesWithoutPPT = [];
133
+ let taskId = "";
134
+ let url = "";
135
+ const pptSrcRE = /^pptx?(?<prefix>:\/\/\S+?dynamicConvert)\/(?<taskId>\w+)\//;
136
+ for (const { name: name2, ppt } of scenes) {
137
+ scenesWithoutPPT.push({ name: name2 });
138
+ if (!ppt || !ppt.src.startsWith("ppt")) {
139
+ continue;
140
+ }
141
+ const match = pptSrcRE.exec(ppt.src);
142
+ if (!match || !match.groups) {
143
+ continue;
144
+ }
145
+ taskId = match.groups.taskId;
146
+ url = "https" + match.groups.prefix;
147
+ break;
148
+ }
149
+ return { scenesWithoutPPT, taskId, url };
150
+ }
120
151
  const translation$1 = {
121
152
  clicker: "clicker",
122
153
  selector: "selector",
@@ -240,6 +271,129 @@ async function mountWhiteboard(sdkConfig, joinRoom, managerConfig, language) {
240
271
  const i18n = await createI18n({ language });
241
272
  return { sdk, room, manager, i18n };
242
273
  }
274
+ function useWritable(room) {
275
+ const [writable, setWritable] = useState(false);
276
+ useEffect(() => {
277
+ if (room) {
278
+ setWritable(room.isWritable);
279
+ room.isWritable && (room.disableSerialization = false);
280
+ const updateWritable = () => setWritable(room.isWritable);
281
+ room.callbacks.on("onEnableWriteNowChanged", updateWritable);
282
+ return () => {
283
+ room.callbacks.off("onEnableWriteNowChanged", updateWritable);
284
+ };
285
+ }
286
+ }, [room]);
287
+ return writable;
288
+ }
289
+ function useBoxState(manager) {
290
+ const [boxState, setBoxState] = useState();
291
+ useEffect(() => {
292
+ if (manager) {
293
+ setBoxState(manager.boxState);
294
+ manager.emitter.on("boxStateChange", setBoxState);
295
+ return () => {
296
+ manager.emitter.off("boxStateChange", setBoxState);
297
+ };
298
+ }
299
+ }, [manager]);
300
+ return boxState;
301
+ }
302
+ function useFocusedApp(manager) {
303
+ const [focused, setFocused] = useState();
304
+ useEffect(() => {
305
+ if (manager) {
306
+ setFocused(manager.focused);
307
+ manager.emitter.on("focusedChange", setFocused);
308
+ return () => {
309
+ manager.emitter.off("focusedChange", setFocused);
310
+ };
311
+ }
312
+ }, [manager]);
313
+ return focused;
314
+ }
315
+ function useMaximized(manager) {
316
+ return useBoxState(manager) === "maximized";
317
+ }
318
+ function useHideControls(manager) {
319
+ const maximized = useMaximized(manager);
320
+ const focusedApp = useFocusedApp(manager);
321
+ if (maximized) {
322
+ if (Object.values(BuiltinApps).some((kind) => focusedApp == null ? void 0 : focusedApp.includes(kind))) {
323
+ return "toolbar-only";
324
+ } else {
325
+ return true;
326
+ }
327
+ }
328
+ return false;
329
+ }
330
+ function useRoomState(room) {
331
+ const [memberState, setMemberState] = useState(void 0);
332
+ useEffect(() => {
333
+ if (room) {
334
+ setMemberState(room.state.memberState);
335
+ const onRoomStateChanged = (diff) => {
336
+ if (diff.memberState)
337
+ setMemberState(diff.memberState);
338
+ };
339
+ room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
340
+ return () => room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
341
+ }
342
+ }, [room]);
343
+ return { memberState };
344
+ }
345
+ function useToolbar(room, manager) {
346
+ const writable = useWritable(room);
347
+ const { memberState } = useRoomState(room);
348
+ const cleanCurrentScene = useCallback(() => {
349
+ if (manager) {
350
+ manager.mainView.cleanCurrentScene();
351
+ } else if (room) {
352
+ room.cleanCurrentScene();
353
+ }
354
+ }, [manager, room]);
355
+ const setAppliance = useCallback((appliance, shape) => {
356
+ const memberState2 = {
357
+ currentApplianceName: appliance,
358
+ shapeType: shape
359
+ };
360
+ if (manager) {
361
+ manager.mainView.setMemberState(memberState2);
362
+ } else if (room) {
363
+ room.setMemberState(memberState2);
364
+ }
365
+ }, [manager, room]);
366
+ const setStrokeWidth = useCallback((strokeWidth) => {
367
+ if (manager) {
368
+ manager.mainView.setMemberState({ strokeWidth });
369
+ } else if (room) {
370
+ room.setMemberState({ strokeWidth });
371
+ }
372
+ }, [manager, room]);
373
+ const setStrokeColor = useCallback((strokeColor) => {
374
+ if (manager) {
375
+ manager.mainView.setMemberState({ strokeColor });
376
+ } else if (room) {
377
+ room.setMemberState({ strokeColor });
378
+ }
379
+ }, [manager, room]);
380
+ return {
381
+ writable,
382
+ memberState,
383
+ cleanCurrentScene,
384
+ setAppliance,
385
+ setStrokeWidth,
386
+ setStrokeColor
387
+ };
388
+ }
389
+ const EmptyToolbarHook = {
390
+ writable: false,
391
+ memberState: void 0,
392
+ cleanCurrentScene: noop,
393
+ setAppliance: noop,
394
+ setStrokeWidth: noop,
395
+ setStrokeColor: noop
396
+ };
243
397
  var jsxRuntime = { exports: {} };
244
398
  var reactJsxRuntime_production_min = {};
245
399
  /*
@@ -318,7 +472,7 @@ shouldUseNative() ? Object.assign : function(target, source) {
318
472
  * This source code is licensed under the MIT license found in the
319
473
  * LICENSE file in the root directory of this source tree.
320
474
  */
321
- var f = require$$0, g = 60103;
475
+ var f = React, g = 60103;
322
476
  reactJsxRuntime_production_min.Fragment = 60107;
323
477
  if (typeof Symbol === "function" && Symbol.for) {
324
478
  var h = Symbol.for;
@@ -613,6 +767,32 @@ const Icons$1 = {
613
767
  Up: memo(Up),
614
768
  Down: memo(Down)
615
769
  };
770
+ const ShapesMap = {
771
+ [ApplianceNames.rectangle]: Icons$1.Rectangle,
772
+ [ApplianceNames.ellipse]: Icons$1.Circle,
773
+ [ApplianceNames.straight]: Icons$1.Line,
774
+ [ApplianceNames.arrow]: Icons$1.Arrow,
775
+ [ShapeType.Pentagram]: Icons$1.Star,
776
+ [ShapeType.Rhombus]: Icons$1.Diamond,
777
+ [ShapeType.Triangle]: Icons$1.Triangle,
778
+ [ShapeType.SpeechBalloon]: Icons$1.SpeechBalloon
779
+ };
780
+ const ApplianceShapes = [
781
+ ApplianceNames.rectangle,
782
+ ApplianceNames.ellipse,
783
+ ApplianceNames.straight,
784
+ ApplianceNames.arrow
785
+ ];
786
+ const Shapes = [
787
+ ShapeType.Pentagram,
788
+ ShapeType.Rhombus,
789
+ ShapeType.Triangle,
790
+ ShapeType.SpeechBalloon
791
+ ];
792
+ const ItemHeight = 32 + 4;
793
+ const ItemsCount = 8;
794
+ const MaxHeight = ItemHeight * ItemsCount - 4;
795
+ const MinHeight = ItemHeight * 2 - 4;
616
796
  const Button$1 = forwardRef((props, ref) => {
617
797
  const {
618
798
  content,
@@ -655,102 +835,6 @@ function CutLine() {
655
835
  className: clsx(`${name$4}-cut-line`, theme)
656
836
  });
657
837
  }
658
- function useWritable(room) {
659
- const [value, setValue] = useState(false);
660
- useEffect(() => {
661
- if (room) {
662
- const setWritable = () => setValue(room.isWritable);
663
- setWritable();
664
- room.callbacks.on("onEnableWriteNowChanged", setWritable);
665
- return () => room.callbacks.off("onEnableWriteNowChanged", setWritable);
666
- }
667
- }, [room]);
668
- return value;
669
- }
670
- function useRoomState(room) {
671
- const [memberState, setMemberState] = useState(void 0);
672
- useEffect(() => {
673
- if (room) {
674
- setMemberState(room.state.memberState);
675
- const onRoomStateChanged = (diff) => {
676
- if (diff.memberState)
677
- setMemberState(diff.memberState);
678
- };
679
- room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
680
- return () => room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
681
- }
682
- }, [room]);
683
- return { memberState };
684
- }
685
- function useToolbar(room) {
686
- const writable = useWritable(room);
687
- const { memberState } = useRoomState(room);
688
- const cleanCurrentScene = useCallback(() => {
689
- if (room == null ? void 0 : room.isWritable) {
690
- room.cleanCurrentScene();
691
- }
692
- }, [room]);
693
- const setAppliance = useCallback((appliance, shape) => {
694
- if (room == null ? void 0 : room.isWritable) {
695
- room.setMemberState({
696
- currentApplianceName: appliance,
697
- shapeType: shape
698
- });
699
- }
700
- }, [room]);
701
- const setStrokeWidth = useCallback((strokeWidth) => {
702
- if (room == null ? void 0 : room.isWritable) {
703
- room.setMemberState({ strokeWidth });
704
- }
705
- }, [room]);
706
- const setStrokeColor = useCallback((strokeColor) => {
707
- if (room == null ? void 0 : room.isWritable) {
708
- room.setMemberState({ strokeColor });
709
- }
710
- }, [room]);
711
- return {
712
- writable,
713
- memberState,
714
- cleanCurrentScene,
715
- setAppliance,
716
- setStrokeWidth,
717
- setStrokeColor
718
- };
719
- }
720
- const EmptyToolbarHook = {
721
- writable: false,
722
- memberState: void 0,
723
- cleanCurrentScene: noop,
724
- setAppliance: noop,
725
- setStrokeWidth: noop,
726
- setStrokeColor: noop
727
- };
728
- const ShapesMap = {
729
- [ApplianceNames.rectangle]: Icons$1.Rectangle,
730
- [ApplianceNames.ellipse]: Icons$1.Circle,
731
- [ApplianceNames.straight]: Icons$1.Line,
732
- [ApplianceNames.arrow]: Icons$1.Arrow,
733
- [ShapeType.Pentagram]: Icons$1.Star,
734
- [ShapeType.Rhombus]: Icons$1.Diamond,
735
- [ShapeType.Triangle]: Icons$1.Triangle,
736
- [ShapeType.SpeechBalloon]: Icons$1.SpeechBalloon
737
- };
738
- const ApplianceShapes = [
739
- ApplianceNames.rectangle,
740
- ApplianceNames.ellipse,
741
- ApplianceNames.straight,
742
- ApplianceNames.arrow
743
- ];
744
- const Shapes = [
745
- ShapeType.Pentagram,
746
- ShapeType.Rhombus,
747
- ShapeType.Triangle,
748
- ShapeType.SpeechBalloon
749
- ];
750
- const ItemHeight = 32 + 4;
751
- const ItemsCount = 8;
752
- const MaxHeight = ItemHeight * ItemsCount - 4;
753
- const MinHeight = ItemHeight * 2 - 4;
754
838
  function UpButton({
755
839
  disabled,
756
840
  scrollTo
@@ -1295,7 +1379,7 @@ function ShapeShapeButton({
1295
1379
  })
1296
1380
  });
1297
1381
  }
1298
- function Content() {
1382
+ const Content = React.memo(() => {
1299
1383
  var _a, _b, _c, _d, _e, _f, _g;
1300
1384
  const app = useInstance();
1301
1385
  const ref = useRef(null);
@@ -1337,7 +1421,7 @@ function Content() {
1337
1421
  disabled: disableScrollUp
1338
1422
  }), /* @__PURE__ */ jsxs("div", {
1339
1423
  ref,
1340
- className: `${name$4}-section`,
1424
+ className: clsx(`${name$4}-section`),
1341
1425
  style: {
1342
1426
  height: `${sectionHeight}px`,
1343
1427
  overflow: needScroll ? "hidden" : "visible"
@@ -1351,7 +1435,43 @@ function Content() {
1351
1435
  disabled: disableScrollDown
1352
1436
  })]
1353
1437
  });
1354
- }
1438
+ });
1439
+ var collapsePNG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAB8CAYAAAAMw2JFAAAAAXNSR0IArs4c6QAAA49JREFUeF7tnLFv00AUh5/TFVYkxIDEnKFjJ/gb2CIqpUPagYXNEV2LRGk7tAiRSA0bWcC0QzowwQKuVDnCLE2KTZCMSNLkHCLalCpBkdFVMTKh8TXO+c4S16XDSb0vv/vyfE3fqwQR+ZIA4AoAdADgJ08mSVXVV9ls9nE+nzcBAAFAnweQ1Gg06gihrmEYubm5OeX4+LgBAD9Yw0iO49S63S7U6/VYq9UyCoXC2tLS0kcAwEA9VkBnIO5m7XYbJwTVanVLluWcruvfAOA7ADhhA/0Fgjfr9/tweHgYs20baZq2sbCw8HaQTqgy/wPivvKTkxN8XFPNZvMdC5lHgmAgx3EAISQhhHqGYWyGKbMviJsOC5kvBOIjcxUAWjRkHgtkSGZb07R1WjKPDeIj82cAaAatzIFBhmU2TTOXTCZfBq3ME4HQlJkKCA2ZqYJMIjN1kKAyhwYyrsyhgpwns6IoyysrK/rgQfrnqc4ExCtzrVb7tbe39yCVSr0GAFyZz2CYguANT09PwbIsaWdn5146nX4zuO+wB8EwnU5HqlQqdiKRuHNwcFDC1Zh5Iu4xWZYVU1V1eXZ29jlOhRvI0dGRVC6XP8zMzNwFgK/cQHq9HpTLZXt6evo2AFS4geDbX6lUisXj8VsA8IkbCHZlf39/Kh6P3xQg7jtHJDL826JIRCRC+gRBOCIcEY6QEhCOkBISdUQ4IhwhJSAcISUk6kjojjxaXbt0Py3jP1DCtes3ruLvVetLnenRYIgnT7OX3Y25gLgQ3gSYg3ghuIEMQ3ABOQ+COcgoCKYgfhD/Jwh+1ZE4GrdKRkJWPxhulTUSBe28ZLglMgzDHcR9N3G/BpDuHH7r4qoY+lUx6PGIoxFHQ3JHOCIcEY6QEhCOkBISdUQ4IhwhJSAcISUk6ohwxM+RyLR/RaYhLjItgpFomoxEG2kkGmvxRBPXVmPPWIypKMpD5s3X3kEh0zSfJZPJF6NmK0JrI3VHpxBCaiaTWc/n877TJtRBPMNkdrFY3Jifn8ed3njUzneYjCqIZ7xue3FxMadpGh6vu9BEEhUQr4yFQmE1yMDhRCDjyEi6JAUGGVdG6iBBZaQK4pVRluVNXdfZjsfRkHGiRGjKGBjEI+P7TCazQaqMpI1I635jtmNVRtJGpPVRg8fbtGW8EAiL6VUiyGA4vUd6TJN+0KTr0u7u7hYLGUmg0fkHBiRSVuu/AWpfZNft9vFDAAAAAElFTkSuQmCC";
1440
+ var expandPNG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAB8CAYAAAAMw2JFAAAAAXNSR0IArs4c6QAAA5xJREFUeF7tnL9v00AUx5/TlRkJMSAxZ+jYCf4GtopK6dB2qBBsjshaJErboWVJpYaNLGDaIR2YYAFXqlxhlvzAJkhGJGlyDhVNSpWgyOiqBJnQ+urznW2Jy1JVVnKffv3x8yV9LxLE5CEBwFUA6ALAzyiZJFVVX21ubj7N5/MmACAAGEQBJDWbzQZCqGcYRm52dlbpdDpNAPgRNozkOE691+tBo9FItNtto1AorC0tLX0EAAzUDwvoDGS02NHREU4IarXatizLOV3XvwHAdwBweAP9BYIXGwwGcHh4mLBtG2matrGwsPB2mA5Xmf8BGf3lJycn+HRNtFqtd2HIfCEIBnIcBxBCEkKobxjGFk+ZPUFG6YQh86VAPGSuAUCbhcy+QMZktjVNW2cls28QD5k/A0CLtjJTg4zLbJpmLpVKvaStzIFAWMrMBISFzExBgsjMHIRWZm4gfmXmCnKezIqiLK+srOjDG+mfu3ooIG6Z6/X6r/39/Udzc3OvAQBX5jOYUEHwgqenp2BZlrS7u/sgnU6/Ge53wgfBMN1uV6pWq/b09PTdSqVSwtU49ERGp8myrISqqsszMzPPcSqRgRwfH0vlcvnD1NTUIgB8jQyk3+9DuVy2Jycn7wBANTIQvPsrlUqJZDJ5GwA+RQaCXSkWixPJZPKWABldOSKR8XeLIhGRCOkTBOGIcEQ4QkpAOEJKSNQR4YhwhJSAcISUkKgjTBy5fuPmNfxCNetLA/98srp25WFaxv+UpH5QnZpxEPz7/XuLnSAwzEBwFEFgmIIEgWEOQgvDBYQGhhuIXxiuIH5g/g8QP5czt0T8QFB/mHdeZXXXdr8QXEBoIJiD0EIwBQkCwQwksm0A9abD44lUl68A4ZEAkz0rDzDhiDg1JK+EI8IR4QgpAeEIKSFRR4QjwhFSAsIRUkKijsTSkdi0f8WmIS42LYKxaJqMRRtpLBpr8URTpK3GrrEYU1GUx6E3X7sHhUzTfJZKpV5cNFvBrY10NDqFEFKz2ex6Pp/3nDZhDuIaJrMPDg425ufncac3HrXzHCZjCuIar9vJZDI5TdPweN2lJpKYgLhlLBQKqzQDh4FA/MhI2ptQg/iVkTkIrYxMQdwyyrK8pet6uONxLGQMlAhLGalBXDK+z2azG6TKSFqIdNxrzNZXZSQtRDp+0eDxDmsZLwUSxvQqEWQ4nN4n3aZJLxT0uLS3t7cdhowk0Ph8gQGJNKzjvwGKWUjXcvHclAAAAABJRU5ErkJggg==";
1441
+ const Mask = React.memo(({
1442
+ toolbar,
1443
+ children
1444
+ }) => {
1445
+ const [rootElement] = useState(() => {
1446
+ const element = document.createElement("div");
1447
+ element.style.position = "absolute";
1448
+ return element;
1449
+ });
1450
+ useEffect(() => {
1451
+ if (toolbar && rootElement) {
1452
+ toolbar.appendChild(rootElement);
1453
+ }
1454
+ }, [rootElement, toolbar]);
1455
+ useEffect(() => {
1456
+ if (rootElement && toolbar) {
1457
+ toolbar.appendChild(rootElement);
1458
+ const toolbarRect = toolbar.getBoundingClientRect();
1459
+ const halfHeight = toolbarRect.height / 2 - 31;
1460
+ rootElement.style.top = halfHeight + "px";
1461
+ rootElement.style.left = "41px";
1462
+ rootElement.style.width = "17px";
1463
+ rootElement.style.height = "62px";
1464
+ return () => {
1465
+ toolbar.removeChild(rootElement);
1466
+ };
1467
+ }
1468
+ }, [rootElement, toolbar]);
1469
+ if (rootElement) {
1470
+ return ReactDOM.createPortal(children, rootElement);
1471
+ } else {
1472
+ return null;
1473
+ }
1474
+ });
1355
1475
  const ToolbarContext = createContext(__spreadValues({
1356
1476
  theme: "light"
1357
1477
  }, EmptyToolbarHook));
@@ -1360,12 +1480,18 @@ const Toolbar = ({
1360
1480
  theme = "light",
1361
1481
  icons,
1362
1482
  room,
1483
+ manager,
1363
1484
  i18n
1364
1485
  }) => {
1365
1486
  const [expanded, setExpanded] = useState(true);
1366
- const hook = useToolbar(room);
1367
- const toggle = useCallback(() => setExpanded((e) => !e), []);
1487
+ const hook = useToolbar(room, manager);
1488
+ const [toolbar, toolbarRef] = useState(null);
1489
+ const [onHover, setOnHover] = useState(false);
1490
+ const [pointEvents, setPointEvents] = useState(true);
1368
1491
  const disabled = !hook.writable;
1492
+ const toggle = useCallback(() => {
1493
+ setExpanded((e) => !e);
1494
+ }, []);
1369
1495
  return /* @__PURE__ */ jsx(ToolbarContext.Provider, {
1370
1496
  value: __spreadProps(__spreadValues({
1371
1497
  theme,
@@ -1373,32 +1499,108 @@ const Toolbar = ({
1373
1499
  }, hook), {
1374
1500
  i18n
1375
1501
  }),
1376
- children: /* @__PURE__ */ jsxs("div", {
1377
- className: clsx(name$4, theme),
1378
- children: [expanded ? /* @__PURE__ */ jsx(Button$1, {
1379
- content: i18n == null ? void 0 : i18n.t("collapse"),
1380
- onClick: toggle,
1381
- children: /* @__PURE__ */ jsx(Icon, {
1382
- fallback: /* @__PURE__ */ jsx(Icons$1.Collapse, {
1383
- theme
1384
- }),
1385
- src: disabled ? icons == null ? void 0 : icons.collapseIconDisable : icons == null ? void 0 : icons.collapseIcon
1386
- })
1387
- }) : /* @__PURE__ */ jsx(Button$1, {
1388
- content: i18n == null ? void 0 : i18n.t("expand"),
1502
+ children: /* @__PURE__ */ jsx(AnimatePresence, {
1503
+ children: expanded ? /* @__PURE__ */ jsxs(motion.div, {
1504
+ initial: {
1505
+ x: -100
1506
+ },
1507
+ animate: {
1508
+ x: 0,
1509
+ transition: {
1510
+ duration: 0.5
1511
+ }
1512
+ },
1513
+ ref: toolbarRef,
1514
+ className: clsx(name$4, theme),
1515
+ onPointerEnter: () => {
1516
+ if (expanded) {
1517
+ setOnHover(true);
1518
+ }
1519
+ },
1520
+ onMouseLeave: () => setOnHover(false),
1521
+ exit: {
1522
+ x: -100,
1523
+ transition: {
1524
+ duration: 0.5
1525
+ }
1526
+ },
1527
+ onAnimationStart: () => setPointEvents(false),
1528
+ onAnimationComplete: () => setPointEvents(true),
1529
+ style: {
1530
+ pointerEvents: pointEvents ? "auto" : "none"
1531
+ },
1532
+ children: [/* @__PURE__ */ jsx(Content, {}), expanded && onHover && /* @__PURE__ */ jsx(Mask, {
1533
+ toolbar,
1534
+ children: /* @__PURE__ */ jsx("div", {
1535
+ onClick: toggle,
1536
+ children: /* @__PURE__ */ jsx("img", {
1537
+ draggable: false,
1538
+ className: clsx(`${name$4}-mask-btn`, theme),
1539
+ src: collapsePNG
1540
+ })
1541
+ })
1542
+ })]
1543
+ }, "toolbar") : /* @__PURE__ */ jsx(motion.div, {
1544
+ className: clsx(`${name$4}-expand-btn`, theme),
1389
1545
  onClick: toggle,
1390
- children: /* @__PURE__ */ jsx(Icon, {
1391
- fallback: /* @__PURE__ */ jsx(Icons$1.Expand, {
1392
- theme
1546
+ initial: {
1547
+ x: -100
1548
+ },
1549
+ animate: {
1550
+ x: 0,
1551
+ transition: {
1552
+ duration: 0.5
1553
+ }
1554
+ },
1555
+ children: !expanded && /* @__PURE__ */ jsx(Icon, {
1556
+ fallback: /* @__PURE__ */ jsx("img", {
1557
+ draggable: false,
1558
+ src: expandPNG,
1559
+ className: clsx(`${name$4}-mask-btn`, theme)
1393
1560
  }),
1394
1561
  src: disabled ? icons == null ? void 0 : icons.expandIconDisable : icons == null ? void 0 : icons.expandIcon
1395
1562
  })
1396
- }), expanded && /* @__PURE__ */ jsxs(Fragment, {
1397
- children: [/* @__PURE__ */ jsx(CutLine, {}), /* @__PURE__ */ jsx(Content, {})]
1398
- })]
1563
+ }, "expand")
1399
1564
  })
1400
1565
  });
1401
1566
  };
1567
+ function useRedoUndo(room, manager) {
1568
+ const [undoSteps, setUndoSteps] = useState(0);
1569
+ const [redoSteps, setRedoSteps] = useState(0);
1570
+ useEffect(() => {
1571
+ if (manager) {
1572
+ manager.mainView.callbacks.on("onCanUndoStepsUpdate", setUndoSteps);
1573
+ manager.mainView.callbacks.on("onCanRedoStepsUpdate", setRedoSteps);
1574
+ return () => {
1575
+ manager.mainView.callbacks.off("onCanUndoStepsUpdate", setUndoSteps);
1576
+ manager.mainView.callbacks.off("onCanRedoStepsUpdate", setRedoSteps);
1577
+ };
1578
+ }
1579
+ if (room) {
1580
+ room.callbacks.on("onCanUndoStepsUpdate", setUndoSteps);
1581
+ room.callbacks.on("onCanRedoStepsUpdate", setRedoSteps);
1582
+ return () => {
1583
+ room.callbacks.off("onCanUndoStepsUpdate", setUndoSteps);
1584
+ room.callbacks.off("onCanRedoStepsUpdate", setRedoSteps);
1585
+ };
1586
+ }
1587
+ }, [room, manager]);
1588
+ const undo = useCallback(() => {
1589
+ if (manager) {
1590
+ manager.mainView.undo();
1591
+ } else if (room) {
1592
+ room.undo();
1593
+ }
1594
+ }, [manager, room]);
1595
+ const redo = useCallback(() => {
1596
+ if (manager) {
1597
+ manager.mainView.redo();
1598
+ } else if (room) {
1599
+ room.redo();
1600
+ }
1601
+ }, [manager, room]);
1602
+ return { redoSteps, undoSteps, redo, undo };
1603
+ }
1402
1604
  function Undo({
1403
1605
  theme = "light",
1404
1606
  active
@@ -1446,6 +1648,7 @@ function Redo({
1446
1648
  const name$3 = "fastboard-redo-undo";
1447
1649
  function RedoUndo({
1448
1650
  room,
1651
+ manager,
1449
1652
  theme = "light",
1450
1653
  undoIcon,
1451
1654
  undoIconDisable,
@@ -1453,24 +1656,13 @@ function RedoUndo({
1453
1656
  redoIconDisable,
1454
1657
  i18n
1455
1658
  }) {
1456
- const [writable, setWritable] = useState(false);
1457
- const [undoSteps, setUndoSteps] = useState(0);
1458
- const [redoSteps, setRedoSteps] = useState(0);
1459
- useEffect(() => {
1460
- if (room) {
1461
- setWritable(room.isWritable);
1462
- room.isWritable && (room.disableSerialization = false);
1463
- const updateWritable = () => setWritable((room == null ? void 0 : room.isWritable) || false);
1464
- room.callbacks.on("onEnableWriteNowChanged", updateWritable);
1465
- room.callbacks.on("onCanUndoStepsUpdate", setUndoSteps);
1466
- room.callbacks.on("onCanRedoStepsUpdate", setRedoSteps);
1467
- return () => {
1468
- room.callbacks.off("onEnableWriteNowChanged", updateWritable);
1469
- room.callbacks.off("onCanUndoStepsUpdate", setUndoSteps);
1470
- room.callbacks.off("onCanRedoStepsUpdate", setRedoSteps);
1471
- };
1472
- }
1473
- }, [room]);
1659
+ const writable = useWritable(room);
1660
+ const {
1661
+ redoSteps,
1662
+ undoSteps,
1663
+ redo,
1664
+ undo
1665
+ } = useRedoUndo(room, manager);
1474
1666
  const disabled = !writable;
1475
1667
  return /* @__PURE__ */ jsxs("div", {
1476
1668
  className: clsx(name$3, theme),
@@ -1485,7 +1677,7 @@ function RedoUndo({
1485
1677
  children: /* @__PURE__ */ jsx("button", {
1486
1678
  className: clsx(`${name$3}-btn`, "undo", theme),
1487
1679
  disabled: disabled || undoSteps === 0,
1488
- onClick: useCallback(() => room && room.undo(), [room]),
1680
+ onClick: undo,
1489
1681
  children: /* @__PURE__ */ jsx(Icon, {
1490
1682
  fallback: /* @__PURE__ */ jsx(Undo, {
1491
1683
  theme
@@ -1505,7 +1697,7 @@ function RedoUndo({
1505
1697
  children: /* @__PURE__ */ jsx("button", {
1506
1698
  className: clsx(`${name$3}-btn`, "redo", theme),
1507
1699
  disabled: disabled || redoSteps === 0,
1508
- onClick: useCallback(() => room && room.redo(), [room]),
1700
+ onClick: redo,
1509
1701
  children: /* @__PURE__ */ jsx(Icon, {
1510
1702
  fallback: /* @__PURE__ */ jsx(Redo, {
1511
1703
  theme
@@ -1517,6 +1709,113 @@ function RedoUndo({
1517
1709
  })]
1518
1710
  });
1519
1711
  }
1712
+ const ScalePoints = [
1713
+ 0.10737418240000011,
1714
+ 0.13421772800000012,
1715
+ 0.16777216000000014,
1716
+ 0.20971520000000016,
1717
+ 0.26214400000000015,
1718
+ 0.3276800000000002,
1719
+ 0.4096000000000002,
1720
+ 0.5120000000000001,
1721
+ 0.6400000000000001,
1722
+ 0.8,
1723
+ 1,
1724
+ 1.26,
1725
+ 1.5876000000000001,
1726
+ 2.000376,
1727
+ 2.5204737600000002,
1728
+ 3.1757969376000004,
1729
+ 4.001504141376,
1730
+ 5.041895218133761,
1731
+ 6.352787974848539,
1732
+ 8.00451284830916,
1733
+ 10
1734
+ ];
1735
+ function nextScale(scale, delta) {
1736
+ const { length } = ScalePoints;
1737
+ const last = length - 1;
1738
+ if (scale < ScalePoints[0])
1739
+ return ScalePoints[0];
1740
+ if (scale > ScalePoints[last])
1741
+ return ScalePoints[last];
1742
+ for (let i = 0; i < length; ++i) {
1743
+ const curr = ScalePoints[i];
1744
+ const prev = i === 0 ? -Infinity : (ScalePoints[i - 1] + curr) / 2;
1745
+ const next = i === last ? Infinity : (ScalePoints[i + 1] + curr) / 2;
1746
+ if (prev <= scale && scale <= next)
1747
+ return ScalePoints[clamp(i + delta, 0, last)];
1748
+ }
1749
+ return 1;
1750
+ }
1751
+ function useZoomControl(room, manager) {
1752
+ const [scale, setScale] = useState(1);
1753
+ const resetCamera = useCallback(() => {
1754
+ if (manager) {
1755
+ manager.mainView.moveCamera({ scale: 1, centerX: 0, centerY: 0 });
1756
+ } else if (room) {
1757
+ const { scenes, index } = room.state.sceneState;
1758
+ if (scenes[index].ppt) {
1759
+ room.scalePptToFit();
1760
+ } else {
1761
+ room.moveCamera({ scale: 1, centerX: 0, centerY: 0 });
1762
+ }
1763
+ }
1764
+ }, [room, manager]);
1765
+ const zoomIn = useCallback(() => {
1766
+ if (manager) {
1767
+ manager.mainView.moveCamera({
1768
+ scale: nextScale(scale, 1),
1769
+ centerX: 0,
1770
+ centerY: 0
1771
+ });
1772
+ } else if (room) {
1773
+ room.moveCamera({
1774
+ scale: nextScale(scale, 1),
1775
+ centerX: 0,
1776
+ centerY: 0
1777
+ });
1778
+ }
1779
+ }, [room, manager, scale]);
1780
+ const zoomOut = useCallback(() => {
1781
+ if (manager) {
1782
+ manager.mainView.moveCamera({
1783
+ scale: nextScale(scale, -1),
1784
+ centerX: 0,
1785
+ centerY: 0
1786
+ });
1787
+ } else if (room) {
1788
+ room.moveCamera({
1789
+ scale: nextScale(scale, -1),
1790
+ centerX: 0,
1791
+ centerY: 0
1792
+ });
1793
+ }
1794
+ }, [room, manager, scale]);
1795
+ useEffect(() => {
1796
+ if (manager) {
1797
+ setScale(manager.mainView.camera.scale);
1798
+ const onCameraUpdated = ({ scale: scale2 }) => setScale(scale2);
1799
+ manager.mainView.callbacks.on("onCameraUpdated", onCameraUpdated);
1800
+ return () => {
1801
+ manager.mainView.callbacks.off("onCameraUpdated", onCameraUpdated);
1802
+ };
1803
+ }
1804
+ if (room) {
1805
+ setScale(room.state.cameraState.scale);
1806
+ const onRoomStateChanged = (modifyState) => {
1807
+ if (modifyState.cameraState) {
1808
+ setScale(modifyState.cameraState.scale);
1809
+ }
1810
+ };
1811
+ room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
1812
+ return () => {
1813
+ room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
1814
+ };
1815
+ }
1816
+ }, [room, manager]);
1817
+ return { scale, resetCamera, zoomIn, zoomOut };
1818
+ }
1520
1819
  function Minus({
1521
1820
  theme = "light",
1522
1821
  active
@@ -1582,25 +1881,6 @@ function Reset({
1582
1881
  });
1583
1882
  }
1584
1883
  const name$2 = "fastboard-zoom-control";
1585
- const ScalePoints = [0.10737418240000011, 0.13421772800000012, 0.16777216000000014, 0.20971520000000016, 0.26214400000000015, 0.3276800000000002, 0.4096000000000002, 0.5120000000000001, 0.6400000000000001, 0.8, 1, 1.26, 1.5876000000000001, 2.000376, 2.5204737600000002, 3.1757969376000004, 4.001504141376, 5.041895218133761, 6.352787974848539, 8.00451284830916, 10];
1586
- function nextScale(scale, delta) {
1587
- const {
1588
- length
1589
- } = ScalePoints;
1590
- const last = length - 1;
1591
- if (scale < ScalePoints[0])
1592
- return ScalePoints[0];
1593
- if (scale > ScalePoints[last])
1594
- return ScalePoints[last];
1595
- for (let i = 0; i < length; ++i) {
1596
- const curr = ScalePoints[i];
1597
- const prev = i === 0 ? -Infinity : (ScalePoints[i - 1] + curr) / 2;
1598
- const next = i === last ? Infinity : (ScalePoints[i + 1] + curr) / 2;
1599
- if (prev <= scale && scale <= next)
1600
- return ScalePoints[clamp(i + delta, 0, last)];
1601
- }
1602
- return 1;
1603
- }
1604
1884
  function ZoomControl({
1605
1885
  room,
1606
1886
  manager,
@@ -1613,100 +1893,13 @@ function ZoomControl({
1613
1893
  plusIconDisable,
1614
1894
  i18n
1615
1895
  }) {
1616
- const [writable, setWritable] = useState(false);
1617
- const [scale, setScale] = useState(1);
1618
- const resetCamera = useCallback(() => {
1619
- if (room == null ? void 0 : room.isWritable) {
1620
- if (manager) {
1621
- manager.mainView.moveCamera({
1622
- scale: 1,
1623
- centerX: 0,
1624
- centerY: 0
1625
- });
1626
- } else {
1627
- const {
1628
- scenes,
1629
- index
1630
- } = room.state.sceneState;
1631
- if (scenes[index].ppt) {
1632
- room.scalePptToFit();
1633
- } else {
1634
- room.moveCamera({
1635
- scale: 1,
1636
- centerX: 0,
1637
- centerY: 0
1638
- });
1639
- }
1640
- }
1641
- }
1642
- }, [room, manager]);
1643
- const zoomIn = useCallback(() => {
1644
- if (room == null ? void 0 : room.isWritable) {
1645
- if (manager) {
1646
- manager.mainView.moveCamera({
1647
- scale: nextScale(scale, 1),
1648
- centerX: 0,
1649
- centerY: 0
1650
- });
1651
- } else {
1652
- room.moveCamera({
1653
- scale: nextScale(scale, 1),
1654
- centerX: 0,
1655
- centerY: 0
1656
- });
1657
- }
1658
- }
1659
- }, [room, manager, scale]);
1660
- const zoomOut = useCallback(() => {
1661
- if (room == null ? void 0 : room.isWritable) {
1662
- if (manager) {
1663
- manager.mainView.moveCamera({
1664
- scale: nextScale(scale, -1),
1665
- centerX: 0,
1666
- centerY: 0
1667
- });
1668
- } else {
1669
- room.moveCamera({
1670
- scale: nextScale(scale, -1),
1671
- centerX: 0,
1672
- centerY: 0
1673
- });
1674
- }
1675
- }
1676
- }, [room, manager, scale]);
1677
- useEffect(() => {
1678
- if (room) {
1679
- setWritable(room.isWritable);
1680
- setScale(room.state.cameraState.scale);
1681
- }
1682
- if (manager) {
1683
- setScale(manager.mainView.camera.scale);
1684
- }
1685
- const onRoomStateChanged = (modifyState) => {
1686
- if (modifyState.cameraState) {
1687
- setScale(modifyState.cameraState.scale);
1688
- }
1689
- };
1690
- const onCameraUpdated = ({
1691
- scale: scale2
1692
- }) => setScale(scale2);
1693
- const updateWritable = () => setWritable((room == null ? void 0 : room.isWritable) || false);
1694
- if (room) {
1695
- room.callbacks.on("onEnableWriteNowChanged", updateWritable);
1696
- if (manager) {
1697
- manager.mainView.callbacks.on("onCameraUpdated", onCameraUpdated);
1698
- } else {
1699
- room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
1700
- }
1701
- }
1702
- return () => {
1703
- if (room) {
1704
- room.callbacks.off("onEnableWriteNowChanged", updateWritable);
1705
- room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
1706
- manager == null ? void 0 : manager.mainView.callbacks.off("onCameraUpdated", onCameraUpdated);
1707
- }
1708
- };
1709
- }, [room, manager]);
1896
+ const writable = useWritable(room);
1897
+ const {
1898
+ scale,
1899
+ resetCamera,
1900
+ zoomIn,
1901
+ zoomOut
1902
+ } = useZoomControl(room, manager);
1710
1903
  const disabled = !writable;
1711
1904
  return /* @__PURE__ */ jsxs("div", {
1712
1905
  className: clsx(name$2, theme),
@@ -1779,6 +1972,60 @@ function ZoomControl({
1779
1972
  })]
1780
1973
  });
1781
1974
  }
1975
+ function usePageControl(room, manager) {
1976
+ const [pageIndex, setPageIndex] = useState(0);
1977
+ const [pageCount, setPageCount] = useState(0);
1978
+ const addPage = useCallback(async () => {
1979
+ if (manager && room) {
1980
+ await manager.switchMainViewToWriter();
1981
+ const path = room.state.sceneState.contextPath;
1982
+ room.putScenes(path, [{}], pageIndex + 1);
1983
+ await manager.setMainViewSceneIndex(pageIndex + 1);
1984
+ } else if (!manager && room) {
1985
+ const path = room.state.sceneState.contextPath;
1986
+ room.putScenes(path, [{}], pageIndex + 1);
1987
+ room.setSceneIndex(pageIndex + 1);
1988
+ }
1989
+ }, [room, manager, pageIndex]);
1990
+ const prevPage = useCallback(() => {
1991
+ if (manager) {
1992
+ manager.setMainViewSceneIndex(pageIndex - 1);
1993
+ } else if (room) {
1994
+ room.pptPreviousStep();
1995
+ }
1996
+ }, [room, manager, pageIndex]);
1997
+ const nextPage = useCallback(() => {
1998
+ if (manager) {
1999
+ manager.setMainViewSceneIndex(pageIndex + 1);
2000
+ } else if (room) {
2001
+ room.pptNextStep();
2002
+ }
2003
+ }, [room, manager, pageIndex]);
2004
+ useEffect(() => {
2005
+ if (room) {
2006
+ setPageIndex(room.state.sceneState.index);
2007
+ setPageCount(room.state.sceneState.scenes.length);
2008
+ if (manager) {
2009
+ manager.emitter.on("mainViewSceneIndexChange", setPageIndex);
2010
+ return () => {
2011
+ manager.emitter.off("mainViewSceneIndexChange", setPageIndex);
2012
+ };
2013
+ } else {
2014
+ const onRoomStateChanged = (modifyState) => {
2015
+ if (modifyState.sceneState) {
2016
+ setPageIndex(modifyState.sceneState.index);
2017
+ setPageCount(modifyState.sceneState.scenes.length);
2018
+ }
2019
+ };
2020
+ room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
2021
+ return () => {
2022
+ room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
2023
+ };
2024
+ }
2025
+ }
2026
+ }, [room, manager]);
2027
+ return { pageIndex, pageCount, prevPage, nextPage, addPage };
2028
+ }
1782
2029
  function FilePlus({
1783
2030
  theme = "light",
1784
2031
  active
@@ -1840,71 +2087,14 @@ function PageControl({
1840
2087
  nextIconDisable,
1841
2088
  i18n
1842
2089
  }) {
1843
- const [writable, setWritable] = useState(false);
1844
- const [pageIndex, setPageIndex] = useState(0);
1845
- const [pageCount, setPageCount] = useState(0);
1846
- const addPage = useCallback(async () => {
1847
- if (manager && room) {
1848
- await manager.switchMainViewToWriter();
1849
- const path = room.state.sceneState.contextPath;
1850
- room.putScenes(path, [{}], pageIndex + 1);
1851
- await manager.setMainViewSceneIndex(pageIndex + 1);
1852
- } else if (!manager && room) {
1853
- const path = room.state.sceneState.contextPath;
1854
- room.putScenes(path, [{}], pageIndex + 1);
1855
- room.setSceneIndex(pageIndex + 1);
1856
- }
1857
- }, [room, manager, pageIndex]);
1858
- const prevPage = useCallback(() => {
1859
- if (room == null ? void 0 : room.isWritable) {
1860
- if (manager) {
1861
- manager.setMainViewSceneIndex(pageIndex - 1);
1862
- } else {
1863
- room.pptPreviousStep();
1864
- }
1865
- }
1866
- }, [room, manager, pageIndex]);
1867
- const nextPage = useCallback(() => {
1868
- if (room == null ? void 0 : room.isWritable) {
1869
- if (manager) {
1870
- manager.setMainViewSceneIndex(pageIndex + 1);
1871
- } else {
1872
- room.pptNextStep();
1873
- }
1874
- }
1875
- }, [room, manager, pageIndex]);
1876
- useEffect(() => {
1877
- if (room) {
1878
- setWritable(room.isWritable);
1879
- setPageIndex(room.state.sceneState.index);
1880
- setPageCount(room.state.sceneState.scenes.length);
1881
- }
1882
- const onRoomStateChanged = (modifyState) => {
1883
- if (modifyState.sceneState) {
1884
- setPageIndex(modifyState.sceneState.index);
1885
- setPageCount(modifyState.sceneState.scenes.length);
1886
- }
1887
- };
1888
- const onMainViewModeChanged = (mode) => {
1889
- if (room && mode === 0) {
1890
- setPageIndex(room.state.sceneState.index);
1891
- setPageCount(room.state.sceneState.scenes.length);
1892
- }
1893
- };
1894
- const updateWritable = () => setWritable((room == null ? void 0 : room.isWritable) || false);
1895
- if (room) {
1896
- room.callbacks.on("onEnableWriteNowChanged", updateWritable);
1897
- room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
1898
- manager == null ? void 0 : manager.callbacks.on("mainViewModeChange", onMainViewModeChanged);
1899
- }
1900
- return () => {
1901
- if (room) {
1902
- room.callbacks.off("onEnableWriteNowChanged", updateWritable);
1903
- room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
1904
- manager == null ? void 0 : manager.callbacks.off("mainViewModeChange", onMainViewModeChanged);
1905
- }
1906
- };
1907
- }, [room, manager]);
2090
+ const writable = useWritable(room);
2091
+ const _a = usePageControl(room, manager), {
2092
+ pageIndex,
2093
+ pageCount
2094
+ } = _a, actions = __objRest(_a, [
2095
+ "pageIndex",
2096
+ "pageCount"
2097
+ ]);
1908
2098
  const disabled = !writable;
1909
2099
  return /* @__PURE__ */ jsxs("div", {
1910
2100
  className: clsx(name$1, theme),
@@ -1919,7 +2109,7 @@ function PageControl({
1919
2109
  children: /* @__PURE__ */ jsx("button", {
1920
2110
  className: clsx(`${name$1}-btn`, "prev", theme),
1921
2111
  disabled: disabled || pageIndex === 0,
1922
- onClick: prevPage,
2112
+ onClick: actions.prevPage,
1923
2113
  children: /* @__PURE__ */ jsx(Icon, {
1924
2114
  fallback: /* @__PURE__ */ jsx(ChevronLeft, {
1925
2115
  theme
@@ -1948,7 +2138,7 @@ function PageControl({
1948
2138
  children: /* @__PURE__ */ jsx("button", {
1949
2139
  className: clsx(`${name$1}-btn`, "next", theme),
1950
2140
  disabled: disabled || pageIndex === pageCount - 1,
1951
- onClick: nextPage,
2141
+ onClick: actions.nextPage,
1952
2142
  children: /* @__PURE__ */ jsx(Icon, {
1953
2143
  fallback: /* @__PURE__ */ jsx(ChevronRight, {
1954
2144
  theme
@@ -1968,7 +2158,7 @@ function PageControl({
1968
2158
  children: /* @__PURE__ */ jsx("button", {
1969
2159
  className: clsx(`${name$1}-btn`, "add", theme),
1970
2160
  disabled,
1971
- onClick: addPage,
2161
+ onClick: actions.addPage,
1972
2162
  children: /* @__PURE__ */ jsx(Icon, {
1973
2163
  fallback: /* @__PURE__ */ jsx(FilePlus, {
1974
2164
  theme
@@ -1985,17 +2175,19 @@ function Root({
1985
2175
  }) {
1986
2176
  const [mux] = useState(() => new Lock());
1987
2177
  const useWhiteboard = useCallback((container) => mux.schedule(container ? () => app.mount(container) : () => app.unmount()), [app, mux]);
1988
- const {
1989
- Toolbar: toolbar = true,
1990
- RedoUndo: redo_undo = true,
1991
- ZoomControl: zoom_control = true,
1992
- PageControl: page_control = true
1993
- } = app.config.layout || {};
2178
+ const hideControls = useHideControls(app.manager);
2179
+ const showControls = !hideControls;
1994
2180
  const props = {
1995
2181
  room: app.room,
1996
2182
  manager: app.manager,
1997
2183
  i18n: app.i18n
1998
2184
  };
2185
+ const {
2186
+ Toolbar: toolbar = showControls || hideControls === "toolbar-only",
2187
+ RedoUndo: redo_undo = showControls,
2188
+ ZoomControl: zoom_control = showControls,
2189
+ PageControl: page_control = showControls
2190
+ } = app.config.layout || {};
1999
2191
  return /* @__PURE__ */ jsx(Instance.Context.Provider, {
2000
2192
  value: app,
2001
2193
  children: /* @__PURE__ */ jsxs("div", {
@@ -2049,14 +2241,19 @@ class Instance {
2049
2241
  this.accept(essentials);
2050
2242
  this.resolveReady();
2051
2243
  }
2052
- bindElement(target, collector) {
2053
- if (this.target && target) {
2244
+ bindElement(target) {
2245
+ if (this.target && this.target !== target) {
2054
2246
  ReactDOM.unmountComponentAtNode(this.target);
2055
2247
  }
2056
2248
  this.target = target;
2057
- this.collector = collector;
2058
2249
  this.forceUpdate();
2059
2250
  }
2251
+ bindCollector(collector) {
2252
+ this.collector = collector;
2253
+ if (this.manager && collector) {
2254
+ this.manager.bindCollectorContainer(collector);
2255
+ }
2256
+ }
2060
2257
  updateLayout(layout) {
2061
2258
  this.config.layout = layout;
2062
2259
  this.forceUpdate();
@@ -2095,10 +2292,9 @@ class Instance {
2095
2292
  if (!this.manager) {
2096
2293
  throw new Error(`[WhiteboardApp] mounted, but not found window manager`);
2097
2294
  }
2295
+ this.manager.bindContainer(node);
2098
2296
  if (this.collector) {
2099
- this.manager.bindContainer(node, this.collector);
2100
- } else {
2101
- this.manager.bindContainer(node);
2297
+ this.manager.bindCollectorContainer(this.collector);
2102
2298
  }
2103
2299
  }
2104
2300
  async unmount() {
@@ -2135,7 +2331,8 @@ class Instance {
2135
2331
  kind: "Slide",
2136
2332
  options: {
2137
2333
  scenePath: params.scenePath,
2138
- title: params.title
2334
+ title: params.title,
2335
+ scenes: params.scenes
2139
2336
  },
2140
2337
  attributes: {
2141
2338
  taskId: params.taskId,
@@ -2177,6 +2374,23 @@ class Instance {
2177
2374
  }
2178
2375
  });
2179
2376
  }
2377
+ insertMedia({
2378
+ title,
2379
+ src
2380
+ }) {
2381
+ if (!this.manager) {
2382
+ throw new Error(`[WhiteboardApp] cannot insert app before mounted`);
2383
+ }
2384
+ return this.manager.addApp({
2385
+ kind: BuiltinApps.MediaPlayer,
2386
+ options: {
2387
+ title
2388
+ },
2389
+ attributes: {
2390
+ src
2391
+ }
2392
+ });
2393
+ }
2180
2394
  async changeLanguage(language) {
2181
2395
  var _a;
2182
2396
  try {
@@ -2190,13 +2404,11 @@ __publicField(Instance, "Context", createContext(null));
2190
2404
  function useInstance() {
2191
2405
  return useContext(Instance.Context);
2192
2406
  }
2193
- var style = '.netless-window-manager-playground{width:100%;height:100%;position:relative;z-index:1;overflow:hidden;user-select:none}.netless-window-manager-sizer{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;overflow:hidden;display:flex}.netless-window-manager-sizer-horizontal{flex-direction:column}.netless-window-manager-sizer:before,.netless-window-manager-sizer:after{flex:1;content:"";display:block}.netless-window-manager-chess-sizer:before,.netless-window-manager-chess-sizer:after{background-image:linear-gradient(45deg,#b0b0b0 25%,transparent 25%),linear-gradient(-45deg,#b0b0b0 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#b0b0b0 75%),linear-gradient(-45deg,transparent 75%,#b0b0b0 75%);background-color:#fff;background-size:20px 20px;background-position:0 0,0 10px,10px -10px,-10px 0px}.netless-window-manager-wrapper{position:relative;z-index:1;width:100%;height:100%;overflow:hidden}.netless-window-manager-main-view{width:100%;height:100%}.netless-window-manager-cursor-pencil-image,.netless-window-manager-cursor-eraser-image{width:26px;height:26px}.netless-window-manager-cursor-selector-image{width:24px;height:24px}.netless-window-manager-cursor-selector-avatar{border-radius:50%;border-style:solid;border-width:2px;border-color:#fff;margin-bottom:2px}.netless-window-manager-cursor-selector-avatar img{width:12px}.netless-window-manager-cursor-inner{border-radius:4px;display:flex;align-items:center;justify-content:center;flex-direction:row;padding-left:4px;padding-right:4px;font-size:12px}.netless-window-manager-cursor-inner-mellow{height:32px;border-radius:16px;display:flex;align-items:center;justify-content:center;flex-direction:row;padding-left:16px;padding-right:16px}.netless-window-manager-cursor-tag-name{font-size:12px;margin-left:4px;padding:2px 8px;border-radius:4px}.netless-window-manager-cursor-mid{display:flex;flex-direction:column;align-items:center;justify-content:center;position:absolute;width:26px;height:26px;z-index:2147483647;left:0;top:0;will-change:transform;transition:transform .05s;transform-origin:0 0;user-select:none}.netless-window-manager-cursor-pencil-offset{margin-left:-20px}.netless-window-manager-cursor-selector-offset{margin-left:-22px;margin-top:56px}.netless-window-manager-cursor-text-offset{margin-left:-30px;margin-top:18px}.netless-window-manager-cursor-shape-offset{display:flex;flex-direction:column;align-items:center;justify-content:center;position:absolute;width:180px;height:64px;margin-left:-30px;margin-top:12px}.netless-window-manager-cursor-name{width:100%;height:48px;display:flex;align-items:center;justify-content:center;position:absolute;top:-40px}.cursor-image-wrapper{display:flex;justify-content:center}.tele-fancy-scrollbar{overscroll-behavior:contain;overflow:auto;overflow-y:scroll;overflow-y:overlay;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;scrollbar-width:auto}.tele-fancy-scrollbar::-webkit-scrollbar{height:8px;width:8px}.tele-fancy-scrollbar::-webkit-scrollbar-track{background-color:transparent}.tele-fancy-scrollbar::-webkit-scrollbar-thumb{background-color:#444e601a;background-color:transparent;border-radius:4px;transition:background-color .4s}.tele-fancy-scrollbar:hover::-webkit-scrollbar-thumb{background-color:#444e601a}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:hover{background-color:#444e6033}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:active{background-color:#444e6033}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:vertical{min-height:50px}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:horizontal{min-width:50px}.telebox-box{position:absolute;top:0;left:0;z-index:100;will-change:transform;transition:width .4s cubic-bezier(.4,.9,.71,1.02),height .4s cubic-bezier(.55,.82,.63,.95),opacity .6s cubic-bezier(.7,0,.84,0),transform .4s ease}.telebox-box-main{position:relative;width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden;background:#f9f9fc;box-shadow:0 4px 10px #2f419226;border-radius:6px;border:1px solid #e3e3ec}.telebox-titlebar-wrap{flex-shrink:0;position:relative;z-index:1}.telebox-content-wrap{flex:1;width:100%;overflow:hidden;display:flex;justify-content:center;align-items:center}.telebox-content{width:100%;height:100%;position:relative}.telebox-footer-wrap{flex-shrink:0;display:flex;flex-direction:column}.telebox-footer-wrap:before{content:"";display:block;flex:1}.telebox-resize-handle{position:absolute;z-index:2147483647}.telebox-n{width:100%;height:5px;left:0;top:-5px;cursor:n-resize}.telebox-s{width:100%;height:5px;left:0;bottom:-5px;cursor:s-resize}.telebox-w{width:5px;height:100%;left:-5px;top:0;cursor:w-resize}.telebox-e{width:5px;height:100%;right:-5px;top:0;cursor:e-resize}.telebox-nw{width:15px;height:15px;top:-5px;left:-5px;cursor:nw-resize}.telebox-ne{width:15px;height:15px;top:-5px;right:-5px;cursor:ne-resize}.telebox-se{width:15px;height:15px;bottom:-5px;right:-5px;cursor:se-resize}.telebox-sw{width:15px;height:15px;bottom:-5px;left:-5px;cursor:sw-resize}.telebox-track-mask{position:fixed;top:0;left:0;z-index:2147483647;width:100%;height:100%;background:rgba(0,0,0,.0001);cursor:move}.telebox-cursor-n{cursor:n-resize}.telebox-cursor-s{cursor:s-resize}.telebox-cursor-w{cursor:w-resize}.telebox-cursor-e{cursor:e-resize}.telebox-cursor-nw{cursor:nw-resize}.telebox-cursor-ne{cursor:ne-resize}.telebox-cursor-se{cursor:se-resize}.telebox-cursor-sw{cursor:sw-resize}.telebox-maximized .telebox-resize-handles,.telebox-no-resize .telebox-resize-handles{display:none}.telebox-maximized{box-shadow:none;transition:none}.telebox-minimized{will-change:transform;transition:width 50ms cubic-bezier(.4,.9,.71,1.02),height 50ms cubic-bezier(.55,.82,.63,.95),opacity .6s cubic-bezier(.7,0,.84,0),transform .6s ease;opacity:0;pointer-events:none;user-select:none}.telebox-transforming{will-change:transform;transition:opacity .6s cubic-bezier(.7,0,.84,0)}.telebox-readonly .telebox-resize-handle{cursor:initial!important;pointer-events:none!important}.telebox-color-scheme-dark .telebox-box-main{color:#e9e9e9;background:#212126;border-color:#43434d}.telebox-titlebar{box-sizing:border-box;height:26px;display:flex;align-items:center;padding:0 16px;background:#fff;user-select:none;border-bottom:1px solid #eeeef7}.telebox-title{overflow:hidden;margin:0 24px 0 0;padding:0;font-size:14px;font-weight:400;font-family:PingFangSC-Regular,PingFang SC;white-space:nowrap;word-break:keep-all;text-overflow:ellipsis;color:#191919}.telebox-titlebar-btns{white-space:nowrap;word-break:keep-all;margin-left:auto;font-size:0}.telebox-titlebar-btn{width:22px;height:22px;padding:0;outline:0;border:none;background:0 0;cursor:pointer}.telebox-titlebar-btn~.telebox-titlebar-btn{margin-left:10px}.telebox-titlebar-btn-icon{width:22px;height:22px}.telebox-readonly .telebox-titlebar-btn{cursor:not-allowed}.telebox-titlebar-icon-minimize{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjh2MjhIMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj4KICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjYSIgLz4KICAgICAgICA8L21hc2s+CiAgICAgICAgPHBhdGggZmlsbD0iI0E3QTdDQSIgZmlsbC1ydWxlPSJub256ZXJvIiBkPSJNOSAxM2gxMHYxLjZIOXoiIG1hc2s9InVybCgjYikiIC8+CiAgICA8L2c+Cjwvc3ZnPgo=)}.telebox-titlebar-icon-maximize{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjh2MjhIMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj4KICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjYSIgLz4KICAgICAgICA8L21hc2s+CiAgICAgICAgPGcgZmlsbD0iI0E3QTdDQSIgZmlsbC1ydWxlPSJub256ZXJvIiBtYXNrPSJ1cmwoI2IpIj4KICAgICAgICAgICAgPHBhdGgKICAgICAgICAgICAgICAgIGQ9Ik0yMC40ODEgMTcuMWgxLjJ2NC41ODFIMTcuMXYtMS4yaDMuMzgxVjE3LjF6bS0xNC4xOTA1LS4wMDloMS4ydjMuMzgxaDMuMzgwOXYxLjJoLTQuNTgxdi00LjU4MXpNMTcuMSA2LjE5MDVoNC41ODF2NC41ODA5aC0xLjJ2LTMuMzgxSDE3LjF2LTEuMnptLTEwLjcwMDguMTA4N2g0Ljc5ODV2MS4ySDcuNTk5MnYzLjU5ODVoLTEuMlY2LjI5OTJ6IiAvPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+Cg==)}.telebox-titlebar-icon-maximize.is-active{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjZ2MjZIMHoiIC8+CiAgICAgICAgPHBhdGggaWQ9ImMiIGQ9Ik0yNi44NjkgMEwyOCAxLjEzMVYyNi44N0wyNi44NjkgMjhIMS4xM0wwIDI2Ljg3VjEuMTMxTDEuMTMgMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEgMSkiPgogICAgICAgICAgICA8bWFzayBpZD0iYiIgZmlsbD0iI2ZmZiI+CiAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNhIiAvPgogICAgICAgICAgICA8L21hc2s+CiAgICAgICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0tNC42NDI5LTQuNjQyOWgzNS4yODU4djM1LjI4NThILTQuNjQyOXoiIG1hc2s9InVybCgjYikiIC8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8bWFzayBpZD0iZCIgZmlsbD0iI2ZmZiI+CiAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNjIiAvPgogICAgICAgICAgICA8L21hc2s+CiAgICAgICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0tMTcuNTE2OCAxNEwxNC0xNy41MTY4IDQ1LjUxNjggMTQgMTQgNDUuNTE2OHoiIG1hc2s9InVybCgjZCkiIC8+CiAgICAgICAgPC9nPgogICAgICAgIDxwYXRoIHN0cm9rZT0iI0E3QTdDQSIgc3Ryb2tlLXdpZHRoPSIxLjIiCiAgICAgICAgICAgIGQ9Ik0xMC4wODg2IDIxLjQ4NjV2LTMuNjk2Nkg2LjM5Mk0yMS4zODU1IDEwLjE4OTVoLTMuNjk2NlY2LjQ5M00yMS40MDIgMTcuNzk4M2gtMy42OTY2djMuNjk2Nk0xMC4yNTAzIDYuMTQ5OHYzLjg5ODVINi4zNTE3IiAvPgogICAgPC9nPgo8L3N2Zz4K)}.telebox-titlebar-icon-close{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyOCAyOCI+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iI0E3QTdDQSIgc3Ryb2tlLXdpZHRoPSIxLjQiPgogICAgICAgIDxwYXRoIGQ9Ik04LjM1MyAyMC4zMzIxTDIwLjMzMiA4LjM1M00yMC4zMzIyIDIwLjMzMjFMOC4zNTMgOC4zNTMiIC8+CiAgICA8L2c+Cjwvc3ZnPgo=)}.telebox-color-scheme-dark .telebox-titlebar{color:#e9e9e9;background:#43434d;border-bottom:none}.telebox-collector{visibility:hidden;display:block;position:absolute;z-index:200;width:40px;height:40px;margin:0;padding:0;border:none;outline:0;font-size:0;border-radius:50%;background:#fff;box-shadow:0 2px 6px #2f419226;cursor:pointer;user-select:none;pointer-events:none;background-repeat:no-repeat;background-size:18px 16px;background-position:center}.telebox-collector-visible{visibility:visible;pointer-events:initial}.telebox-collector-readonly{cursor:not-allowed}.telebox-color-scheme-dark.telebox-collector{background-color:#43434d}.telebox-max-titlebar{display:none;position:absolute;top:0;left:0;z-index:50000;user-select:none}.telebox-max-titlebar-maximized{display:flex}.telebox-titles{flex:1;height:100%;margin:0 16px 0 -16px;overflow-y:hidden;overflow-x:scroll;overflow-x:overlay;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;scrollbar-width:auto}.telebox-titles::-webkit-scrollbar{height:8px;width:8px}.telebox-titles::-webkit-scrollbar-track{background-color:transparent}.telebox-titles::-webkit-scrollbar-thumb{background-color:#eeeef7cc;background-color:transparent;border-radius:4px;transition:background-color .4s}.telebox-titles:hover::-webkit-scrollbar-thumb{background-color:#eeeef7cc}.telebox-titles::-webkit-scrollbar-thumb:hover{background-color:#eeeef7}.telebox-titles::-webkit-scrollbar-thumb:active{background-color:#eeeef7}.telebox-titles::-webkit-scrollbar-thumb:vertical{min-height:50px}.telebox-titles::-webkit-scrollbar-thumb:horizontal{min-width:50px}.telebox-titles-content{height:100%;display:flex;flex-wrap:nowrap;align-items:center;padding:0}.telebox-titles-tab{overflow:hidden;max-width:182px;min-width:50px;padding:0 26px 0 16px;outline:0;font-size:13px;font-family:PingFangSC-Regular,PingFang SC;font-weight:400;text-overflow:ellipsis;white-space:nowrap;word-break:keep-all;border:none;border-right:1px solid #e5e5f0;color:#7b88a0;background:0 0;cursor:pointer}.telebox-titles-tab~.telebox-titles-tab{margin-left:2px}.telebox-titles-tab-focus{color:#357bf6}.telebox-readonly .telebox-titles-tab{cursor:not-allowed}.telebox-color-scheme-dark{color-scheme:dark}.telebox-color-scheme-dark.telebox-titlebar{color:#e9e9e9;background:#43434d;border-bottom:none}.telebox-color-scheme-dark .telebox-titles-tab{border-right-color:#7b88a0}.telebox-color-scheme-dark .telebox-title{color:#e9e9e9}.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}.tippy-box[data-theme~=light]{color:#26323d;box-shadow:0 0 20px 4px #9aa1b126,0 4px 80px -8px #24282f40,0 4px 4px -2px #5b5e6926;background-color:#fff}.tippy-box[data-theme~=light][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=light][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=light][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=light][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}.tippy-box[data-theme~=light]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=light]>.tippy-svg-arrow{fill:#fff}.rc-slider{position:relative;height:14px;padding:5px 0;width:100%;border-radius:6px;touch-action:none;box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.rc-slider *{box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.rc-slider-rail{position:absolute;width:100%;background-color:#e9e9e9;height:4px;border-radius:6px}.rc-slider-track{position:absolute;left:0;height:4px;border-radius:6px;background-color:#abe2fb}.rc-slider-handle{position:absolute;width:14px;height:14px;cursor:pointer;cursor:-webkit-grab;margin-top:-5px;cursor:grab;border-radius:50%;border:solid 2px #96dbfa;background-color:#fff;touch-action:pan-x}.rc-slider-handle-dragging.rc-slider-handle-dragging.rc-slider-handle-dragging{border-color:#57c5f7;box-shadow:0 0 0 5px #96dbfa}.rc-slider-handle:focus{outline:none}.rc-slider-handle-click-focused:focus{border-color:#96dbfa;box-shadow:unset}.rc-slider-handle:hover{border-color:#57c5f7}.rc-slider-handle:active{border-color:#57c5f7;box-shadow:0 0 5px #57c5f7;cursor:-webkit-grabbing;cursor:grabbing}.rc-slider-mark{position:absolute;top:18px;left:0;width:100%;font-size:12px}.rc-slider-mark-text{position:absolute;display:inline-block;vertical-align:middle;text-align:center;cursor:pointer;color:#999}.rc-slider-mark-text-active{color:#666}.rc-slider-step{position:absolute;width:100%;height:4px;background:transparent}.rc-slider-dot{position:absolute;bottom:-2px;margin-left:-4px;width:8px;height:8px;border:2px solid #e9e9e9;background-color:#fff;cursor:pointer;border-radius:50%;vertical-align:middle}.rc-slider-dot-active{border-color:#96dbfa}.rc-slider-dot-reverse{margin-right:-4px}.rc-slider-disabled{background-color:#e9e9e9}.rc-slider-disabled .rc-slider-track{background-color:#ccc}.rc-slider-disabled .rc-slider-handle,.rc-slider-disabled .rc-slider-dot{border-color:#ccc;box-shadow:none;background-color:#fff;cursor:not-allowed}.rc-slider-disabled .rc-slider-mark-text,.rc-slider-disabled .rc-slider-dot{cursor:not-allowed!important}.rc-slider-vertical{width:14px;height:100%;padding:0 5px}.rc-slider-vertical .rc-slider-rail{height:100%;width:4px}.rc-slider-vertical .rc-slider-track{left:5px;bottom:0;width:4px}.rc-slider-vertical .rc-slider-handle{margin-left:-5px;touch-action:pan-y}.rc-slider-vertical .rc-slider-mark{top:0;left:18px;height:100%}.rc-slider-vertical .rc-slider-step{height:100%;width:4px}.rc-slider-vertical .rc-slider-dot{left:2px;margin-bottom:-4px}.rc-slider-vertical .rc-slider-dot:first-child{margin-bottom:-4px}.rc-slider-vertical .rc-slider-dot:last-child{margin-bottom:-4px}.rc-slider-tooltip-zoom-down-enter,.rc-slider-tooltip-zoom-down-appear,.rc-slider-tooltip-zoom-down-leave{animation-duration:.3s;animation-fill-mode:both;display:block!important;animation-play-state:paused}.rc-slider-tooltip-zoom-down-enter.rc-slider-tooltip-zoom-down-enter-active,.rc-slider-tooltip-zoom-down-appear.rc-slider-tooltip-zoom-down-appear-active{animation-name:rcSliderTooltipZoomDownIn;animation-play-state:running}.rc-slider-tooltip-zoom-down-leave.rc-slider-tooltip-zoom-down-leave-active{animation-name:rcSliderTooltipZoomDownOut;animation-play-state:running}.rc-slider-tooltip-zoom-down-enter,.rc-slider-tooltip-zoom-down-appear{transform:scale(0);animation-timing-function:cubic-bezier(.23,1,.32,1)}.rc-slider-tooltip-zoom-down-leave{animation-timing-function:cubic-bezier(.755,.05,.855,.06)}@keyframes rcSliderTooltipZoomDownIn{0%{opacity:0;transform-origin:50% 100%;transform:scale(0)}to{transform-origin:50% 100%;transform:scale(1)}}@keyframes rcSliderTooltipZoomDownOut{0%{transform-origin:50% 100%;transform:scale(1)}to{opacity:0;transform-origin:50% 100%;transform:scale(0)}}.rc-slider-tooltip{position:absolute;left:-9999px;top:-9999px;visibility:visible;box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.rc-slider-tooltip *{box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.rc-slider-tooltip-hidden{display:none}.rc-slider-tooltip-placement-top{padding:4px 0 8px}.rc-slider-tooltip-inner{padding:6px 2px;min-width:24px;height:24px;font-size:12px;line-height:1;color:#fff;text-align:center;text-decoration:none;background-color:#6c6c6c;border-radius:6px;box-shadow:0 0 4px #d9d9d9}.rc-slider-tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.rc-slider-tooltip-placement-top .rc-slider-tooltip-arrow{bottom:4px;left:50%;margin-left:-4px;border-width:4px 4px 0;border-top-color:#6c6c6c}.fastboard-root{position:relative;width:100%;height:100%;overflow:hidden}.fastboard-loading{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;opacity:.6}.fastboard-view{position:absolute;top:0;left:0;width:100%;height:100%}.fastboard-left{position:absolute;top:0;left:0;height:calc(100% - 48px);padding:16px;z-index:201;display:flex;align-items:center}.fastboard-bottom-left,.fastboard-bottom-right{display:flex;gap:10px;position:absolute;bottom:8px;left:8px;padding:8px;z-index:200}.fastboard-bottom-right{left:initial;right:8px}.fastboard-redo-undo{display:inline-flex;align-items:center;gap:4px;padding:4px;border-radius:4px;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-redo-undo.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-redo-undo.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-redo-undo-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:0;width:24px;height:24px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1}.fastboard-redo-undo-btn svg,.fastboard-redo-undo-btn img{width:1em;height:1em}.fastboard-redo-undo-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-redo-undo-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-redo-undo-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-page-control{display:inline-flex;align-items:center;gap:4px;padding:4px;border-radius:4px;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-page-control.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-page-control.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-page-control-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:0;width:24px;height:24px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1}.fastboard-page-control-btn svg,.fastboard-page-control-btn img{width:1em;height:1em}.fastboard-page-control-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-page-control-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-page-control-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-page-control-cut-line{height:24px;width:.5px}.fastboard-page-control-cut-line.light{background-color:#e7e7e7}.fastboard-page-control-cut-line.dark{background-color:#ffffff26}.fastboard-page-control-slash{opacity:.6}.fastboard-page-control-page,.fastboard-page-control-slash,.fastboard-page-control-page-count{font-size:12px;font-variant-numeric:tabular-nums}.fastboard-zoom-control{position:relative;display:inline-flex;align-items:center;gap:4px;padding:4px;border-radius:4px;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-zoom-control.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-zoom-control.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-zoom-control-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:0;width:24px;height:24px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1}.fastboard-zoom-control-btn svg,.fastboard-zoom-control-btn img{width:1em;height:1em}.fastboard-zoom-control-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-zoom-control-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-zoom-control-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-zoom-control-cut-line{height:24px;width:.5px}.fastboard-zoom-control-cut-line.light{background-color:#e7e7e7}.fastboard-zoom-control-cut-line.dark{background-color:#ffffff26}.fastboard-zoom-control-percent{opacity:.6}.fastboard-zoom-control-scale,.fastboard-zoom-control-percent{font-size:12px;font-variant-numeric:tabular-nums}.fastboard-toolbar{display:flex;align-items:center;padding:4px;border-radius:4px;flex-direction:column;gap:4px;position:absolute;z-index:100;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-toolbar .rc-slider{padding:6px 0}.fastboard-toolbar .rc-slider-rail,.fastboard-toolbar .rc-slider-track{height:2px}.fastboard-toolbar .tippy-content{padding:8px}.fastboard-toolbar .tippy-box{border:1px solid rgba(0,0,0,.15);background-color:#333333f2;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-toolbar .tippy-box[data-theme~=light]{background-color:#fffffff2;box-shadow:0 5px 10px #00000040}.fastboard-toolbar.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-toolbar.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-toolbar-tooltip{display:inline-flex;align-items:center;gap:4px}.fastboard-toolbar-hotkey{margin-right:-4px;width:24px;height:24px;border-radius:4px;background-color:#ffffff1a;display:inline-flex;align-items:center;justify-content:center}.fastboard-toolbar-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:4px;width:32px;height:32px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1;position:relative}.fastboard-toolbar-btn-interactive{display:inline-block;width:32px;height:32px}.fastboard-toolbar-btn svg,.fastboard-toolbar-btn img{width:1em;height:1em}.fastboard-toolbar-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-toolbar-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-toolbar-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-toolbar-triangle{width:0px;height:0px;border-bottom:4px solid;border-left:4px solid transparent;position:absolute;bottom:0;right:0}.fastboard-toolbar-cut-line{display:inline-block;height:.5px;width:100%}.fastboard-toolbar-cut-line.light{background-color:#e7e7e7}.fastboard-toolbar-cut-line.dark{background-color:#ffffff26}.fastboard-toolbar-section{display:inline-flex;flex-flow:column nowrap;gap:4px;scroll-behavior:smooth}.fastboard-toolbar-panel{width:120px;padding:0;display:flex;flex-flow:column nowrap;align-items:center;gap:8px}.fastboard-toolbar-panel.apps{width:224px}.fastboard-toolbar-color-box,.fastboard-toolbar-shapes{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;align-items:center;justify-items:center}.fastboard-toolbar-color-box .fastboard-toolbar-btn,.fastboard-toolbar-shapes .fastboard-toolbar-btn{padding:0;width:24px;height:24px}.fastboard-toolbar-apps{width:100%;display:grid;grid-template-columns:repeat(3,1fr);gap:8px;align-items:center;justify-items:center}.fastboard-toolbar-apps .fastboard-toolbar-btn{width:40px;height:40px;font-size:40px}.fastboard-toolbar-app-icon{padding-top:4px;display:inline-flex;flex-flow:column nowrap;align-items:center;gap:4px}.fastboard-toolbar-app-icon .fastboard-toolbar-btn{padding:0}.fastboard-toolbar-app-icon-text{font-size:12px;color:#5d5d5d;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fastboard-toolbar-color-item{width:24px;height:24px;border-radius:4px;cursor:pointer}.fastboard-toolbar-color-item *.light:hover{background-color:#f5f5f5}.fastboard-toolbar-color-item *.dark:hover{background-color:#333}.fastboard-toolbar-color-border{width:24px;height:24px;border:1px solid transparent;border-radius:4px;display:inline-flex;align-items:center;justify-content:center}.fastboard-toolbar-color-border.active.light,.fastboard-toolbar-color-border.active.dark{border:1px solid rgba(51,129,255,.8)}.fastboard-toolbar-color-btn{margin:0;border:1px solid rgba(0,0,0,.24);padding:0;appearance:none;width:16px;height:16px;border-radius:4px;cursor:pointer}.fastboard-toolbar-color-btn:focus-visible{outline-offset:2px}.fastboard-player-control{width:100%;display:inline-flex;align-items:center;gap:4px;padding:4px;border-radius:4px;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-player-control.auto-hide{opacity:0;transition:opacity .2s}.fastboard-player-control.auto-hide:hover{opacity:1}.fastboard-player-control .rc-slider-disabled{background:transparent;opacity:.5}.fastboard-player-control .rc-slider-rail,.fastboard-player-control .rc-slider-track{height:2px}.fastboard-player-control .tippy-content{padding:8px}.fastboard-player-control .tippy-box{border:1px solid rgba(0,0,0,.15);background-color:#333333f2;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-player-control .tippy-box[data-theme~=light]{background-color:#fffffff2;box-shadow:0 5px 10px #00000040}.fastboard-player-control.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-player-control.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-player-control-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:0;min-width:24px;height:24px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.fastboard-player-control-btn svg,.fastboard-player-control-btn img{width:1em;height:1em}.fastboard-player-control-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-player-control-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-player-control-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-player-control-btn.loading{animation:fastboard-player-control-rotate .5s linear infinite}@keyframes fastboard-player-control-rotate{to{transform:rotate(360deg)}}.fastboard-player-control-panel{padding:0;display:flex;flex-flow:column nowrap;align-items:stretch;gap:4px}.fastboard-player-control-panel .fastboard-player-control-btn{width:initial;height:initial;user-select:none;font-size:12px;padding:4px;justify-content:flex-end}.fastboard-player-control-panel .fastboard-player-control-btn.active{color:#3381ff}.fastboard-player-control-slider{width:100%;padding:0 7px}.fastboard-player-control-slider.loading{cursor:not-allowed}.fastboard-player-control-slash{opacity:.6}.fastboard-player-control-current,.fastboard-player-control-slash,.fastboard-player-control-total,.fastboard-player-control-speed-text{font-size:12px;font-variant-numeric:tabular-nums}.tippy-box.fastboard-tip{color:#eee;background-color:#000000f2;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.tippy-box.fastboard-tip[data-placement^=right]>.tippy-arrow:before{top:4px;border-width:4px;border-right-color:#000}.tippy-box.fastboard-tip[data-placement^=top]>.tippy-arrow:before{left:4px;border-width:4px;border-top-color:#000}\n';
2407
+ var style = '.page-renderer-pages-container{position:relative;overflow:hidden}.page-renderer-page{position:absolute;top:0;left:0;will-change:transform;background-position:center;background-size:cover;background-repeat:no-repeat}.page-renderer-page-img{display:block;width:100%;height:auto;user-select:none}.netless-app-docs-viewer-static-scrollbar{position:absolute;top:0;right:0;z-index:2147483647;width:8px;min-height:30px;margin:0;padding:0;border:none;outline:none;border-radius:4px;background:rgba(68,78,96,.4);box-shadow:1px 1px 8px #ffffffb3;opacity:0;transition:background .4s,opacity .4s 3s,transform .2s;will-change:transform,height;user-select:none}.netless-app-docs-viewer-static-scrollbar.netless-app-docs-viewer-static-scrollbar-dragging{background:rgba(68,78,96,.6);opacity:1;transition:background .4s,opacity .4s 3s!important}.netless-app-docs-viewer-static-scrollbar:hover,.netless-app-docs-viewer-static-scrollbar:focus{background:rgba(68,78,96,.5)}.netless-app-docs-viewer-static-scrollbar:active{background:rgba(68,78,96,.6)}.netless-app-docs-viewer-content:hover .netless-app-docs-viewer-static-scrollbar{opacity:1;transition:background .4s,opacity .4s,transform .2s}.netless-app-docs-viewer-readonly .netless-app-docs-viewer-static-scrollbar{display:none}.netless-app-docs-viewer-static-pages:hover .netless-app-docs-viewer-static-scrollbar{opacity:1;transition:background .4s,opacity .4s,transform .2s}.netless-window-manager-playground{width:100%;height:100%;position:relative;z-index:1;overflow:hidden;user-select:none}.netless-window-manager-sizer{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;overflow:hidden;display:flex}.netless-window-manager-sizer-horizontal{flex-direction:column}.netless-window-manager-sizer:before,.netless-window-manager-sizer:after{flex:1;content:"";display:block}.netless-window-manager-chess-sizer:before,.netless-window-manager-chess-sizer:after{background-image:linear-gradient(45deg,#b0b0b0 25%,transparent 25%),linear-gradient(-45deg,#b0b0b0 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#b0b0b0 75%),linear-gradient(-45deg,transparent 75%,#b0b0b0 75%);background-color:#fff;background-size:20px 20px;background-position:0 0,0 10px,10px -10px,-10px 0px}.netless-window-manager-wrapper{position:relative;z-index:1;width:100%;height:100%;overflow:hidden}.netless-window-manager-main-view{width:100%;height:100%}.netless-window-manager-cursor-pencil-image,.netless-window-manager-cursor-eraser-image{width:26px;height:26px}.netless-window-manager-cursor-selector-image{width:24px;height:24px}.netless-window-manager-cursor-selector-avatar{border-radius:50%;border-style:solid;border-width:2px;border-color:#fff;margin-bottom:2px}.netless-window-manager-cursor-selector-avatar img{width:12px}.netless-window-manager-cursor-inner{border-radius:4px;display:flex;align-items:center;justify-content:center;flex-direction:row;padding-left:4px;padding-right:4px;font-size:12px}.netless-window-manager-cursor-inner-mellow{height:32px;border-radius:16px;display:flex;align-items:center;justify-content:center;flex-direction:row;padding-left:16px;padding-right:16px}.netless-window-manager-cursor-tag-name{font-size:12px;margin-left:4px;padding:2px 8px;border-radius:4px}.netless-window-manager-cursor-mid{display:flex;flex-direction:column;align-items:center;justify-content:center;position:absolute;width:26px;height:26px;z-index:2147483647;left:0;top:0;will-change:transform;transition:transform .05s;transform-origin:0 0;user-select:none}.netless-window-manager-cursor-pencil-offset{margin-left:-20px}.netless-window-manager-cursor-selector-offset{margin-left:-22px;margin-top:56px}.netless-window-manager-cursor-text-offset{margin-left:-30px;margin-top:18px}.netless-window-manager-cursor-shape-offset{display:flex;flex-direction:column;align-items:center;justify-content:center;position:absolute;width:180px;height:64px;margin-left:-30px;margin-top:12px}.netless-window-manager-cursor-name{width:100%;height:48px;display:flex;align-items:center;justify-content:center;position:absolute;top:-40px}.cursor-image-wrapper{display:flex;justify-content:center}.telebox-collector{position:absolute;right:10px;bottom:15px}.tele-fancy-scrollbar{overscroll-behavior:contain;overflow:auto;overflow-y:scroll;overflow-y:overlay;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;scrollbar-width:auto}.tele-fancy-scrollbar::-webkit-scrollbar{height:8px;width:8px}.tele-fancy-scrollbar::-webkit-scrollbar-track{background-color:transparent}.tele-fancy-scrollbar::-webkit-scrollbar-thumb{background-color:#444e601a;background-color:transparent;border-radius:4px;transition:background-color .4s}.tele-fancy-scrollbar:hover::-webkit-scrollbar-thumb{background-color:#444e601a}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:hover{background-color:#444e6033}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:active{background-color:#444e6033}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:vertical{min-height:50px}.tele-fancy-scrollbar::-webkit-scrollbar-thumb:horizontal{min-width:50px}.telebox-box{position:absolute;top:0;left:0;z-index:100;will-change:transform;transition:width .4s cubic-bezier(.4,.9,.71,1.02),height .4s cubic-bezier(.55,.82,.63,.95),opacity .6s cubic-bezier(.7,0,.84,0),transform .4s ease}.telebox-box-main{position:relative;width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden;background:#f9f9fc;box-shadow:0 4px 10px #2f419226;border-radius:6px;border:1px solid #e3e3ec}.telebox-titlebar-wrap{flex-shrink:0;position:relative;z-index:1}.telebox-content-wrap{flex:1;width:100%;overflow:hidden;display:flex;justify-content:center;align-items:center}.telebox-content{width:100%;height:100%;position:relative}.telebox-footer-wrap{flex-shrink:0;display:flex;flex-direction:column}.telebox-footer-wrap:before{content:"";display:block;flex:1}.telebox-resize-handle{position:absolute;z-index:2147483647}.telebox-n{width:100%;height:5px;left:0;top:-5px;cursor:n-resize}.telebox-s{width:100%;height:5px;left:0;bottom:-5px;cursor:s-resize}.telebox-w{width:5px;height:100%;left:-5px;top:0;cursor:w-resize}.telebox-e{width:5px;height:100%;right:-5px;top:0;cursor:e-resize}.telebox-nw{width:15px;height:15px;top:-5px;left:-5px;cursor:nw-resize}.telebox-ne{width:15px;height:15px;top:-5px;right:-5px;cursor:ne-resize}.telebox-se{width:15px;height:15px;bottom:-5px;right:-5px;cursor:se-resize}.telebox-sw{width:15px;height:15px;bottom:-5px;left:-5px;cursor:sw-resize}.telebox-track-mask{position:fixed;top:0;left:0;z-index:2147483647;width:100%;height:100%;background:rgba(0,0,0,.0001);cursor:move}.telebox-cursor-n{cursor:n-resize}.telebox-cursor-s{cursor:s-resize}.telebox-cursor-w{cursor:w-resize}.telebox-cursor-e{cursor:e-resize}.telebox-cursor-nw{cursor:nw-resize}.telebox-cursor-ne{cursor:ne-resize}.telebox-cursor-se{cursor:se-resize}.telebox-cursor-sw{cursor:sw-resize}.telebox-maximized .telebox-resize-handles,.telebox-no-resize .telebox-resize-handles{display:none}.telebox-maximized{box-shadow:none;transition:none}.telebox-minimized{will-change:transform;transition:width 50ms cubic-bezier(.4,.9,.71,1.02),height 50ms cubic-bezier(.55,.82,.63,.95),opacity .6s cubic-bezier(.7,0,.84,0),transform .6s ease;opacity:0;pointer-events:none;user-select:none}.telebox-transforming{will-change:transform;transition:opacity .6s cubic-bezier(.7,0,.84,0)}.telebox-readonly .telebox-resize-handle{cursor:initial!important;pointer-events:none!important}.telebox-color-scheme-dark .telebox-box-main{color:#e9e9e9;background:#212126;border-color:#43434d}.telebox-titlebar{box-sizing:border-box;height:26px;display:flex;align-items:center;padding:0 16px;background:#fff;user-select:none;border-bottom:1px solid #eeeef7}.telebox-title{overflow:hidden;margin:0 24px 0 0;padding:0;font-size:14px;font-weight:400;font-family:PingFangSC-Regular,PingFang SC;white-space:nowrap;word-break:keep-all;text-overflow:ellipsis;color:#191919}.telebox-titlebar-btns{white-space:nowrap;word-break:keep-all;margin-left:auto;font-size:0}.telebox-titlebar-btn{width:22px;height:22px;padding:0;outline:0;border:none;background:0 0;cursor:pointer}.telebox-titlebar-btn~.telebox-titlebar-btn{margin-left:10px}.telebox-titlebar-btn-icon{width:22px;height:22px}.telebox-readonly .telebox-titlebar-btn{cursor:not-allowed}.telebox-titlebar-icon-minimize{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjh2MjhIMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj4KICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjYSIgLz4KICAgICAgICA8L21hc2s+CiAgICAgICAgPHBhdGggZmlsbD0iI0E3QTdDQSIgZmlsbC1ydWxlPSJub256ZXJvIiBkPSJNOSAxM2gxMHYxLjZIOXoiIG1hc2s9InVybCgjYikiIC8+CiAgICA8L2c+Cjwvc3ZnPgo=)}.telebox-titlebar-icon-maximize{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjh2MjhIMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj4KICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjYSIgLz4KICAgICAgICA8L21hc2s+CiAgICAgICAgPGcgZmlsbD0iI0E3QTdDQSIgZmlsbC1ydWxlPSJub256ZXJvIiBtYXNrPSJ1cmwoI2IpIj4KICAgICAgICAgICAgPHBhdGgKICAgICAgICAgICAgICAgIGQ9Ik0yMC40ODEgMTcuMWgxLjJ2NC41ODFIMTcuMXYtMS4yaDMuMzgxVjE3LjF6bS0xNC4xOTA1LS4wMDloMS4ydjMuMzgxaDMuMzgwOXYxLjJoLTQuNTgxdi00LjU4MXpNMTcuMSA2LjE5MDVoNC41ODF2NC41ODA5aC0xLjJ2LTMuMzgxSDE3LjF2LTEuMnptLTEwLjcwMDguMTA4N2g0Ljc5ODV2MS4ySDcuNTk5MnYzLjU5ODVoLTEuMlY2LjI5OTJ6IiAvPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+Cg==)}.telebox-titlebar-icon-maximize.is-active{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjggMjgiPgogICAgPGRlZnM+CiAgICAgICAgPHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjZ2MjZIMHoiIC8+CiAgICAgICAgPHBhdGggaWQ9ImMiIGQ9Ik0yNi44NjkgMEwyOCAxLjEzMVYyNi44N0wyNi44NjkgMjhIMS4xM0wwIDI2Ljg3VjEuMTMxTDEuMTMgMHoiIC8+CiAgICA8L2RlZnM+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEgMSkiPgogICAgICAgICAgICA8bWFzayBpZD0iYiIgZmlsbD0iI2ZmZiI+CiAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNhIiAvPgogICAgICAgICAgICA8L21hc2s+CiAgICAgICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0tNC42NDI5LTQuNjQyOWgzNS4yODU4djM1LjI4NThILTQuNjQyOXoiIG1hc2s9InVybCgjYikiIC8+CiAgICAgICAgPC9nPgogICAgICAgIDxnPgogICAgICAgICAgICA8bWFzayBpZD0iZCIgZmlsbD0iI2ZmZiI+CiAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNjIiAvPgogICAgICAgICAgICA8L21hc2s+CiAgICAgICAgICAgIDxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0tMTcuNTE2OCAxNEwxNC0xNy41MTY4IDQ1LjUxNjggMTQgMTQgNDUuNTE2OHoiIG1hc2s9InVybCgjZCkiIC8+CiAgICAgICAgPC9nPgogICAgICAgIDxwYXRoIHN0cm9rZT0iI0E3QTdDQSIgc3Ryb2tlLXdpZHRoPSIxLjIiCiAgICAgICAgICAgIGQ9Ik0xMC4wODg2IDIxLjQ4NjV2LTMuNjk2Nkg2LjM5Mk0yMS4zODU1IDEwLjE4OTVoLTMuNjk2NlY2LjQ5M00yMS40MDIgMTcuNzk4M2gtMy42OTY2djMuNjk2Nk0xMC4yNTAzIDYuMTQ5OHYzLjg5ODVINi4zNTE3IiAvPgogICAgPC9nPgo8L3N2Zz4K)}.telebox-titlebar-icon-close{background:center/cover no-repeat url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyOCAyOCI+CiAgICA8ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZT0iI0E3QTdDQSIgc3Ryb2tlLXdpZHRoPSIxLjQiPgogICAgICAgIDxwYXRoIGQ9Ik04LjM1MyAyMC4zMzIxTDIwLjMzMiA4LjM1M00yMC4zMzIyIDIwLjMzMjFMOC4zNTMgOC4zNTMiIC8+CiAgICA8L2c+Cjwvc3ZnPgo=)}.telebox-color-scheme-dark .telebox-titlebar{color:#e9e9e9;background:#43434d;border-bottom:none}.telebox-collector{visibility:hidden;display:block;position:absolute;z-index:200;width:40px;height:40px;margin:0;padding:0;border:none;outline:0;font-size:0;border-radius:50%;background:#fff;box-shadow:0 2px 6px #2f419226;cursor:pointer;user-select:none;pointer-events:none;background-repeat:no-repeat;background-size:18px 16px;background-position:center}.telebox-collector-visible{visibility:visible;pointer-events:initial}.telebox-collector-readonly{cursor:not-allowed}.telebox-color-scheme-dark.telebox-collector{background-color:#43434d}.telebox-max-titlebar{display:none;position:absolute;top:0;left:0;z-index:50000;user-select:none}.telebox-max-titlebar-maximized{display:flex}.telebox-titles{flex:1;height:100%;margin:0 16px 0 -16px;overflow-y:hidden;overflow-x:scroll;overflow-x:overlay;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;scrollbar-width:auto}.telebox-titles::-webkit-scrollbar{height:8px;width:8px}.telebox-titles::-webkit-scrollbar-track{background-color:transparent}.telebox-titles::-webkit-scrollbar-thumb{background-color:#eeeef7cc;background-color:transparent;border-radius:4px;transition:background-color .4s}.telebox-titles:hover::-webkit-scrollbar-thumb{background-color:#eeeef7cc}.telebox-titles::-webkit-scrollbar-thumb:hover{background-color:#eeeef7}.telebox-titles::-webkit-scrollbar-thumb:active{background-color:#eeeef7}.telebox-titles::-webkit-scrollbar-thumb:vertical{min-height:50px}.telebox-titles::-webkit-scrollbar-thumb:horizontal{min-width:50px}.telebox-titles-content{height:100%;display:flex;flex-wrap:nowrap;align-items:center;padding:0}.telebox-titles-tab{overflow:hidden;max-width:182px;min-width:50px;padding:0 26px 0 16px;outline:0;font-size:13px;font-family:PingFangSC-Regular,PingFang SC;font-weight:400;text-overflow:ellipsis;white-space:nowrap;word-break:keep-all;border:none;border-right:1px solid #e5e5f0;color:#7b88a0;background:0 0;cursor:pointer}.telebox-titles-tab~.telebox-titles-tab{margin-left:2px}.telebox-titles-tab-focus{color:#357bf6}.telebox-readonly .telebox-titles-tab{cursor:not-allowed}.telebox-color-scheme-dark{color-scheme:dark}.telebox-color-scheme-dark.telebox-titlebar{color:#e9e9e9;background:#43434d;border-bottom:none}.telebox-color-scheme-dark .telebox-titles-tab{border-right-color:#7b88a0}.telebox-color-scheme-dark .telebox-title{color:#e9e9e9}.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}.tippy-box[data-theme~=light]{color:#26323d;box-shadow:0 0 20px 4px #9aa1b126,0 4px 80px -8px #24282f40,0 4px 4px -2px #5b5e6926;background-color:#fff}.tippy-box[data-theme~=light][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=light][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=light][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=light][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}.tippy-box[data-theme~=light]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=light]>.tippy-svg-arrow{fill:#fff}.rc-slider{position:relative;height:14px;padding:5px 0;width:100%;border-radius:6px;touch-action:none;box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.rc-slider *{box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.rc-slider-rail{position:absolute;width:100%;background-color:#e9e9e9;height:4px;border-radius:6px}.rc-slider-track{position:absolute;left:0;height:4px;border-radius:6px;background-color:#abe2fb}.rc-slider-handle{position:absolute;width:14px;height:14px;cursor:pointer;cursor:-webkit-grab;margin-top:-5px;cursor:grab;border-radius:50%;border:solid 2px #96dbfa;background-color:#fff;touch-action:pan-x}.rc-slider-handle-dragging.rc-slider-handle-dragging.rc-slider-handle-dragging{border-color:#57c5f7;box-shadow:0 0 0 5px #96dbfa}.rc-slider-handle:focus{outline:none}.rc-slider-handle-click-focused:focus{border-color:#96dbfa;box-shadow:unset}.rc-slider-handle:hover{border-color:#57c5f7}.rc-slider-handle:active{border-color:#57c5f7;box-shadow:0 0 5px #57c5f7;cursor:-webkit-grabbing;cursor:grabbing}.rc-slider-mark{position:absolute;top:18px;left:0;width:100%;font-size:12px}.rc-slider-mark-text{position:absolute;display:inline-block;vertical-align:middle;text-align:center;cursor:pointer;color:#999}.rc-slider-mark-text-active{color:#666}.rc-slider-step{position:absolute;width:100%;height:4px;background:transparent}.rc-slider-dot{position:absolute;bottom:-2px;margin-left:-4px;width:8px;height:8px;border:2px solid #e9e9e9;background-color:#fff;cursor:pointer;border-radius:50%;vertical-align:middle}.rc-slider-dot-active{border-color:#96dbfa}.rc-slider-dot-reverse{margin-right:-4px}.rc-slider-disabled{background-color:#e9e9e9}.rc-slider-disabled .rc-slider-track{background-color:#ccc}.rc-slider-disabled .rc-slider-handle,.rc-slider-disabled .rc-slider-dot{border-color:#ccc;box-shadow:none;background-color:#fff;cursor:not-allowed}.rc-slider-disabled .rc-slider-mark-text,.rc-slider-disabled .rc-slider-dot{cursor:not-allowed!important}.rc-slider-vertical{width:14px;height:100%;padding:0 5px}.rc-slider-vertical .rc-slider-rail{height:100%;width:4px}.rc-slider-vertical .rc-slider-track{left:5px;bottom:0;width:4px}.rc-slider-vertical .rc-slider-handle{margin-left:-5px;touch-action:pan-y}.rc-slider-vertical .rc-slider-mark{top:0;left:18px;height:100%}.rc-slider-vertical .rc-slider-step{height:100%;width:4px}.rc-slider-vertical .rc-slider-dot{left:2px;margin-bottom:-4px}.rc-slider-vertical .rc-slider-dot:first-child{margin-bottom:-4px}.rc-slider-vertical .rc-slider-dot:last-child{margin-bottom:-4px}.rc-slider-tooltip-zoom-down-enter,.rc-slider-tooltip-zoom-down-appear,.rc-slider-tooltip-zoom-down-leave{animation-duration:.3s;animation-fill-mode:both;display:block!important;animation-play-state:paused}.rc-slider-tooltip-zoom-down-enter.rc-slider-tooltip-zoom-down-enter-active,.rc-slider-tooltip-zoom-down-appear.rc-slider-tooltip-zoom-down-appear-active{animation-name:rcSliderTooltipZoomDownIn;animation-play-state:running}.rc-slider-tooltip-zoom-down-leave.rc-slider-tooltip-zoom-down-leave-active{animation-name:rcSliderTooltipZoomDownOut;animation-play-state:running}.rc-slider-tooltip-zoom-down-enter,.rc-slider-tooltip-zoom-down-appear{transform:scale(0);animation-timing-function:cubic-bezier(.23,1,.32,1)}.rc-slider-tooltip-zoom-down-leave{animation-timing-function:cubic-bezier(.755,.05,.855,.06)}@keyframes rcSliderTooltipZoomDownIn{0%{opacity:0;transform-origin:50% 100%;transform:scale(0)}to{transform-origin:50% 100%;transform:scale(1)}}@keyframes rcSliderTooltipZoomDownOut{0%{transform-origin:50% 100%;transform:scale(1)}to{opacity:0;transform-origin:50% 100%;transform:scale(0)}}.rc-slider-tooltip{position:absolute;left:-9999px;top:-9999px;visibility:visible;box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.rc-slider-tooltip *{box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.rc-slider-tooltip-hidden{display:none}.rc-slider-tooltip-placement-top{padding:4px 0 8px}.rc-slider-tooltip-inner{padding:6px 2px;min-width:24px;height:24px;font-size:12px;line-height:1;color:#fff;text-align:center;text-decoration:none;background-color:#6c6c6c;border-radius:6px;box-shadow:0 0 4px #d9d9d9}.rc-slider-tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.rc-slider-tooltip-placement-top .rc-slider-tooltip-arrow{bottom:4px;left:50%;margin-left:-4px;border-width:4px 4px 0;border-top-color:#6c6c6c}.fastboard-root{position:relative;width:100%;height:100%;overflow:hidden}.fastboard-loading{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;opacity:.6}.fastboard-view{position:absolute;top:0;left:0;width:100%;height:100%}.fastboard-left{position:absolute;top:0;left:0;height:calc(100% - 48px);padding:16px;z-index:201;display:flex;align-items:center}.fastboard-bottom-left,.fastboard-bottom-right{display:flex;gap:10px;position:absolute;bottom:8px;left:8px;padding:8px;z-index:200}.fastboard-bottom-right{left:initial;right:8px}.fastboard-redo-undo{display:inline-flex;align-items:center;gap:4px;padding:4px;border-radius:4px;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-redo-undo.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-redo-undo.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-redo-undo-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:0;width:24px;height:24px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1}.fastboard-redo-undo-btn svg,.fastboard-redo-undo-btn img{width:1em;height:1em}.fastboard-redo-undo-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-redo-undo-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-redo-undo-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-page-control{display:inline-flex;align-items:center;gap:4px;padding:4px;border-radius:4px;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-page-control.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-page-control.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-page-control-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:0;width:24px;height:24px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1}.fastboard-page-control-btn svg,.fastboard-page-control-btn img{width:1em;height:1em}.fastboard-page-control-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-page-control-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-page-control-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-page-control-cut-line{height:24px;width:.5px}.fastboard-page-control-cut-line.light{background-color:#e7e7e7}.fastboard-page-control-cut-line.dark{background-color:#ffffff26}.fastboard-page-control-slash{opacity:.6}.fastboard-page-control-page,.fastboard-page-control-slash,.fastboard-page-control-page-count{font-size:12px;font-variant-numeric:tabular-nums}.fastboard-zoom-control{position:relative;display:inline-flex;align-items:center;gap:4px;padding:4px;border-radius:4px;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-zoom-control.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-zoom-control.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-zoom-control-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:0;width:24px;height:24px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1}.fastboard-zoom-control-btn svg,.fastboard-zoom-control-btn img{width:1em;height:1em}.fastboard-zoom-control-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-zoom-control-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-zoom-control-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-zoom-control-cut-line{height:24px;width:.5px}.fastboard-zoom-control-cut-line.light{background-color:#e7e7e7}.fastboard-zoom-control-cut-line.dark{background-color:#ffffff26}.fastboard-zoom-control-percent{opacity:.6}.fastboard-zoom-control-scale,.fastboard-zoom-control-percent{font-size:12px;font-variant-numeric:tabular-nums}.fastboard-toolbar{display:flex;align-items:center;padding:4px;border-radius:4px;flex-direction:column;gap:4px;position:absolute;z-index:100;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-toolbar .rc-slider{padding:6px 0}.fastboard-toolbar .rc-slider-rail,.fastboard-toolbar .rc-slider-track{height:2px}.fastboard-toolbar .tippy-content{padding:8px}.fastboard-toolbar .tippy-box{border:1px solid rgba(0,0,0,.15);background-color:#333333f2;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-toolbar .tippy-box[data-theme~=light]{background-color:#fffffff2;box-shadow:0 5px 10px #00000040}.fastboard-toolbar.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-toolbar.expanded{border:1px solid rgba(0,0,0,.15)}.fastboard-toolbar.dark{color:#ddd;background-color:#333333d9}.fastboard-toolbar.expanded:hover{box-shadow:0 0 5px #00000040;transform:translate(0)}.fastboard-toolbar.collapsed{padding:0;background-color:transparent}.fastboard-toolbar-tooltip{display:inline-flex;align-items:center;gap:4px}.fastboard-toolbar-hotkey{margin-right:-4px;width:24px;height:24px;border-radius:4px;background-color:#ffffff1a;display:inline-flex;align-items:center;justify-content:center}.fastboard-toolbar-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:4px;width:32px;height:32px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1;position:relative}.fastboard-toolbar-btn-interactive{display:inline-block;width:32px;height:32px}.fastboard-toolbar-btn svg,.fastboard-toolbar-btn img{width:1em;height:1em}.fastboard-toolbar-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-toolbar-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-toolbar-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-toolbar-triangle{width:0px;height:0px;border-bottom:4px solid;border-left:4px solid transparent;position:absolute;bottom:0;right:0}.fastboard-toolbar-cut-line{display:inline-block;height:.5px;width:100%}.fastboard-toolbar-cut-line.light{background-color:#e7e7e7}.fastboard-toolbar-cut-line.dark{background-color:#ffffff26}.fastboard-toolbar-section{display:inline-flex;flex-flow:column nowrap;gap:4px;scroll-behavior:smooth}.fastboard-toolbar-section.collapsed{transform:translate(-100%);transition:1s transform}.fastboard-toolbar-panel{width:120px;padding:0;display:flex;flex-flow:column nowrap;align-items:center;gap:8px}.fastboard-toolbar-panel.apps{width:224px}.fastboard-toolbar-color-box,.fastboard-toolbar-shapes{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;align-items:center;justify-items:center}.fastboard-toolbar-color-box .fastboard-toolbar-btn,.fastboard-toolbar-shapes .fastboard-toolbar-btn{padding:0;width:24px;height:24px}.fastboard-toolbar-apps{width:100%;display:grid;grid-template-columns:repeat(3,1fr);gap:8px;align-items:center;justify-items:center}.fastboard-toolbar-apps .fastboard-toolbar-btn{width:40px;height:40px;font-size:40px}.fastboard-toolbar-app-icon{padding-top:4px;display:inline-flex;flex-flow:column nowrap;align-items:center;gap:4px}.fastboard-toolbar-app-icon .fastboard-toolbar-btn{padding:0}.fastboard-toolbar-app-icon-text{font-size:12px;color:#5d5d5d;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.fastboard-toolbar-color-item{width:24px;height:24px;border-radius:4px;cursor:pointer}.fastboard-toolbar-color-item *.light:hover{background-color:#f5f5f5}.fastboard-toolbar-color-item *.dark:hover{background-color:#333}.fastboard-toolbar-color-border{width:24px;height:24px;border:1px solid transparent;border-radius:4px;display:inline-flex;align-items:center;justify-content:center}.fastboard-toolbar-color-border.active.light,.fastboard-toolbar-color-border.active.dark{border:1px solid rgba(51,129,255,.8)}.fastboard-toolbar-color-btn{margin:0;border:1px solid rgba(0,0,0,.24);padding:0;appearance:none;width:16px;height:16px;border-radius:4px;cursor:pointer}.fastboard-toolbar-color-btn:focus-visible{outline-offset:2px}.fastboard-toolbar-mask-btn{width:17px;height:62px;cursor:pointer}.fastboard-toolbar-mask-btn.dark{filter:invert(.8)}.fastboard-toolbar-expand-btn{display:flex;align-items:center;position:absolute;left:0}.fastboard-player-control{width:100%;display:inline-flex;align-items:center;gap:4px;padding:4px;border-radius:4px;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-player-control.auto-hide{opacity:0;transition:opacity .2s}.fastboard-player-control.auto-hide:hover{opacity:1}.fastboard-player-control .rc-slider-disabled{background:transparent;opacity:.5}.fastboard-player-control .rc-slider-rail,.fastboard-player-control .rc-slider-track{height:2px}.fastboard-player-control .tippy-content{padding:8px}.fastboard-player-control .tippy-box{border:1px solid rgba(0,0,0,.15);background-color:#333333f2;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fastboard-player-control .tippy-box[data-theme~=light]{background-color:#fffffff2;box-shadow:0 5px 10px #00000040}.fastboard-player-control.light{color:#333;background-color:#ffffffd9;border:1px solid rgba(0,0,0,.15)}.fastboard-player-control.dark{color:#ddd;background-color:#333333d9;border:1px solid rgba(0,0,0,.45)}.fastboard-player-control-btn{appearance:none;cursor:pointer;margin:0;border:0;padding:0;min-width:24px;height:24px;background-color:transparent;border-radius:4px;font-size:24px;line-height:1;display:inline-flex;align-items:center;justify-content:center}.fastboard-player-control-btn svg,.fastboard-player-control-btn img{width:1em;height:1em}.fastboard-player-control-btn:disabled{opacity:.5;cursor:not-allowed}.fastboard-player-control-btn.light:not(:disabled):hover{background-color:#3381ff1a}.fastboard-player-control-btn.dark:not(:disabled):hover{background-color:#3381ff40}.fastboard-player-control-btn.loading{animation:fastboard-player-control-rotate .5s linear infinite}@keyframes fastboard-player-control-rotate{to{transform:rotate(360deg)}}.fastboard-player-control-panel{padding:0;display:flex;flex-flow:column nowrap;align-items:stretch;gap:4px}.fastboard-player-control-panel .fastboard-player-control-btn{width:initial;height:initial;user-select:none;font-size:12px;padding:4px;justify-content:flex-end}.fastboard-player-control-panel .fastboard-player-control-btn.active{color:#3381ff}.fastboard-player-control-slider{width:100%;padding:0 7px}.fastboard-player-control-slider.loading{cursor:not-allowed}.fastboard-player-control-slash{opacity:.6}.fastboard-player-control-current,.fastboard-player-control-slash,.fastboard-player-control-total,.fastboard-player-control-speed-text{font-size:12px;font-variant-numeric:tabular-nums}.fastboard{width:100%;height:100%;position:relative}.tippy-box.fastboard-tip{color:#eee;background-color:#000000f2;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.tippy-box.fastboard-tip[data-placement^=right]>.tippy-arrow:before{top:4px;border-width:4px;border-right-color:#000}.tippy-box.fastboard-tip[data-placement^=top]>.tippy-arrow:before{left:4px;border-width:4px;border-top-color:#000}\n';
2194
2408
  applyStyles(style);
2195
2409
  class WhiteboardApp {
2196
2410
  constructor(config) {
2197
2411
  __publicField(this, "_instance");
2198
- __publicField(this, "_target", null);
2199
- __publicField(this, "_collector", null);
2200
2412
  this.config = config;
2201
2413
  this._instance = new Instance(config);
2202
2414
  }
@@ -2213,18 +2425,62 @@ class WhiteboardApp {
2213
2425
  return this._instance.i18n;
2214
2426
  }
2215
2427
  get target() {
2216
- return this._target;
2428
+ return this._instance.target;
2217
2429
  }
2218
2430
  get collector() {
2219
- return this._collector;
2431
+ return this._instance.collector;
2220
2432
  }
2221
- bindElement(target, collector) {
2222
- this._target = target || null;
2223
- this._collector = collector || null;
2224
- this._instance.bindElement(this._target, this._collector);
2433
+ bindElement(target) {
2434
+ this._instance.bindElement(target || null);
2225
2435
  }
2226
- insertDocs(params) {
2227
- return this._instance.insertDocs(params);
2436
+ bindCollector(collector) {
2437
+ this._instance.bindCollector(collector || null);
2438
+ }
2439
+ get layout() {
2440
+ return this._instance.config.layout;
2441
+ }
2442
+ updateLayout(layout) {
2443
+ this._instance.updateLayout(layout);
2444
+ }
2445
+ insertMedia(params) {
2446
+ this._instance.insertMedia(params);
2447
+ }
2448
+ insertDocs(arg1, arg2) {
2449
+ if (typeof arg1 === "object" && "fileType" in arg1) {
2450
+ return this._instance.insertDocs(arg1);
2451
+ } else if (arg2 && arg2.status !== "Finished") {
2452
+ throw new Error("[WhiteboardApp] cannot insert a converting doc");
2453
+ } else if (arg2 && arg2.progress) {
2454
+ const scenes = arg2.progress.convertedFileList.map((f2, i) => ({
2455
+ name: String(i + 1),
2456
+ ppt: {
2457
+ src: f2.conversionFileUrl,
2458
+ width: f2.width,
2459
+ height: f2.height,
2460
+ previewURL: f2.preview
2461
+ }
2462
+ }));
2463
+ const uid = genUID();
2464
+ const scenePath = `/${arg2.uuid}/${uid}`;
2465
+ const { scenesWithoutPPT, taskId, url } = makeSlideParams(scenes);
2466
+ if (taskId && url) {
2467
+ return this._instance.insertDocs({
2468
+ fileType: "pptx",
2469
+ scenePath,
2470
+ taskId,
2471
+ title: arg1,
2472
+ url,
2473
+ scenes: scenesWithoutPPT
2474
+ });
2475
+ } else {
2476
+ return this._instance.insertDocs({
2477
+ fileType: "pdf",
2478
+ scenePath,
2479
+ scenes,
2480
+ title: arg1
2481
+ });
2482
+ }
2483
+ }
2228
2484
  }
2229
2485
  insertCodeEditor() {
2230
2486
  return this._instance.insertCodeEditor();
@@ -2242,12 +2498,7 @@ class WhiteboardApp {
2242
2498
  return this._instance.dispose();
2243
2499
  }
2244
2500
  }
2245
- const version = "0.0.7";
2246
- const EMPTY_ARRAY = [];
2247
- function useForceUpdate() {
2248
- const [, forceUpdate_] = useState({});
2249
- return useCallback(() => forceUpdate_({}), EMPTY_ARRAY);
2250
- }
2501
+ const version = "0.0.11";
2251
2502
  function useLastValue(value) {
2252
2503
  const ref = useRef(value);
2253
2504
  useEffect(() => {
@@ -2255,7 +2506,12 @@ function useLastValue(value) {
2255
2506
  }, [value]);
2256
2507
  return ref.current;
2257
2508
  }
2258
- function usePlayer(player) {
2509
+ const EMPTY_ARRAY = [];
2510
+ function useForceUpdate() {
2511
+ const [, forceUpdate_] = useState({});
2512
+ return useCallback(() => forceUpdate_({}), EMPTY_ARRAY);
2513
+ }
2514
+ function usePlayerControl(player) {
2259
2515
  const togglePlay = useCallback(() => {
2260
2516
  if (player) {
2261
2517
  switch (player.phase) {
@@ -2314,6 +2570,37 @@ function usePlayer(player) {
2314
2570
  seekToProgressTime
2315
2571
  };
2316
2572
  }
2573
+ const Button = forwardRef((props, ref) => {
2574
+ const {
2575
+ theme,
2576
+ content,
2577
+ disabled,
2578
+ active,
2579
+ onClick,
2580
+ interactive,
2581
+ placement = "top",
2582
+ children
2583
+ } = props;
2584
+ return /* @__PURE__ */ jsx(Tippy, {
2585
+ className: "fastboard-tip",
2586
+ content,
2587
+ interactive,
2588
+ theme,
2589
+ disabled,
2590
+ placement,
2591
+ offset: TopOffset,
2592
+ duration: 300,
2593
+ children: /* @__PURE__ */ jsx("button", {
2594
+ ref,
2595
+ className: clsx("fastboard-player-control-btn", theme, {
2596
+ active
2597
+ }),
2598
+ onClick,
2599
+ disabled,
2600
+ children
2601
+ })
2602
+ });
2603
+ });
2317
2604
  const Loading = (props) => {
2318
2605
  const stroke = getStroke(props);
2319
2606
  return /* @__PURE__ */ jsx("svg", {
@@ -2349,37 +2636,6 @@ const Icons = {
2349
2636
  Pause: memo(Pause),
2350
2637
  Loading: memo(Loading)
2351
2638
  };
2352
- const Button = forwardRef((props, ref) => {
2353
- const {
2354
- theme,
2355
- content,
2356
- disabled,
2357
- active,
2358
- onClick,
2359
- interactive,
2360
- placement = "top",
2361
- children
2362
- } = props;
2363
- return /* @__PURE__ */ jsx(Tippy, {
2364
- className: "fastboard-tip",
2365
- content,
2366
- interactive,
2367
- theme,
2368
- disabled,
2369
- placement,
2370
- offset: TopOffset,
2371
- duration: 300,
2372
- children: /* @__PURE__ */ jsx("button", {
2373
- ref,
2374
- className: clsx("fastboard-player-control-btn", theme, {
2375
- active
2376
- }),
2377
- onClick,
2378
- disabled,
2379
- children
2380
- })
2381
- });
2382
- });
2383
2639
  const name = "fastboard-player-control";
2384
2640
  function PlayerControl(_a) {
2385
2641
  var _b = _a, {
@@ -2394,7 +2650,7 @@ function PlayerControl(_a) {
2394
2650
  "i18n"
2395
2651
  ]);
2396
2652
  const [currentTime, setCurrentTime] = useState(0);
2397
- const player = usePlayer(player_);
2653
+ const player = usePlayerControl(player_);
2398
2654
  useEffect(() => {
2399
2655
  setCurrentTime(player.currentTime);
2400
2656
  }, [player.currentTime]);
@@ -2500,37 +2756,49 @@ function renderSpeeds({
2500
2756
  }, speed))
2501
2757
  });
2502
2758
  }
2503
- function useFastboard(config) {
2504
- const [app, setApp] = useState(null);
2505
- const [currentTarget, ref] = useState(null);
2506
- const [collector, collectorRef] = useState(null);
2759
+ function useCombinedRefs(...refs) {
2760
+ const targetRef = useRef(null);
2507
2761
  useEffect(() => {
2508
- let isMounted = true;
2509
- const promise = createWhiteboardApp(config).then((app2) => {
2510
- if (isMounted)
2511
- setApp(app2);
2512
- });
2513
- return () => {
2514
- isMounted = false;
2515
- promise.then(() => app == null ? void 0 : app.dispose());
2516
- };
2517
- }, []);
2762
+ for (const ref of refs) {
2763
+ if (!ref)
2764
+ continue;
2765
+ if (typeof ref === "function") {
2766
+ ref(targetRef.current);
2767
+ } else {
2768
+ ref.current = targetRef.current;
2769
+ }
2770
+ }
2771
+ }, [refs]);
2772
+ return targetRef;
2773
+ }
2774
+ const Fastboard = forwardRef((_c, outerRef) => {
2775
+ var _d = _c, {
2776
+ app
2777
+ } = _d, restProps = __objRest(_d, [
2778
+ "app"
2779
+ ]);
2780
+ const innerRef = useRef(null);
2781
+ const ref = useCombinedRefs(outerRef, innerRef);
2782
+ const previous = useLastValue(app);
2518
2783
  useEffect(() => {
2784
+ if (previous && previous !== app) {
2785
+ previous.bindElement(null);
2786
+ }
2519
2787
  if (app) {
2520
- app.bindElement(currentTarget, collector);
2788
+ app.bindElement(ref.current);
2521
2789
  }
2522
- }, [app, collector, currentTarget]);
2523
- return Object.assign([app, ref, collectorRef], {
2524
- app,
2525
- ref,
2526
- collectorRef
2527
- });
2528
- }
2790
+ }, [app, previous, ref]);
2791
+ return /* @__PURE__ */ jsx("div", __spreadProps(__spreadValues({
2792
+ className: "fastboard"
2793
+ }, restProps), {
2794
+ ref
2795
+ }));
2796
+ });
2529
2797
  const register = WindowManager.register.bind(WindowManager);
2530
2798
  async function createWhiteboardApp(config) {
2531
2799
  const app = new WhiteboardApp(config);
2532
2800
  await app._instance.readyPromise;
2533
2801
  return app;
2534
2802
  }
2535
- export { PageControl, PlayerControl, RedoUndo, Toolbar, WhiteboardApp, ZoomControl, createWhiteboardApp, register, useFastboard, version };
2803
+ export { Fastboard, PageControl, PlayerControl, RedoUndo, Toolbar, WhiteboardApp, ZoomControl, createWhiteboardApp, register, usePageControl, usePlayerControl, useRedoUndo, useToolbar, useZoomControl, version };
2536
2804
  //# sourceMappingURL=index.es.js.map