@netless/fastboard 0.0.8 → 0.1.0

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 (107) hide show
  1. package/LICENSE.txt +1 -1
  2. package/dist/index.js +426 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/index.mjs +393 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/package.json +16 -71
  7. package/src/base.ts +55 -0
  8. package/src/core.ts +307 -0
  9. package/src/emitter.ts +21 -0
  10. package/src/index.ts +70 -24
  11. package/src/{behaviors/register-apps.ts → register-apps.ts} +6 -14
  12. package/src/utils.ts +74 -0
  13. package/src/value.ts +74 -0
  14. package/README.md +0 -134
  15. package/dist/index.cjs.js +0 -14
  16. package/dist/index.cjs.js.map +0 -1
  17. package/dist/index.es.js +0 -2538
  18. package/dist/index.es.js.map +0 -1
  19. package/dist/svelte.cjs.js +0 -2
  20. package/dist/svelte.cjs.js.map +0 -1
  21. package/dist/svelte.es.js +0 -31
  22. package/dist/svelte.es.js.map +0 -1
  23. package/dist/vue.cjs.js +0 -2
  24. package/dist/vue.cjs.js.map +0 -1
  25. package/dist/vue.es.js +0 -42
  26. package/dist/vue.es.js.map +0 -1
  27. package/src/WhiteboardApp.ts +0 -80
  28. package/src/behaviors/style.ts +0 -17
  29. package/src/components/PageControl.scss +0 -80
  30. package/src/components/PageControl.tsx +0 -181
  31. package/src/components/PlayerControl/PlayerControl.scss +0 -145
  32. package/src/components/PlayerControl/PlayerControl.tsx +0 -158
  33. package/src/components/PlayerControl/components/Button.tsx +0 -55
  34. package/src/components/PlayerControl/hooks.ts +0 -95
  35. package/src/components/PlayerControl/icons/Loading.tsx +0 -13
  36. package/src/components/PlayerControl/icons/Pause.tsx +0 -13
  37. package/src/components/PlayerControl/icons/Play.tsx +0 -13
  38. package/src/components/PlayerControl/icons/index.ts +0 -10
  39. package/src/components/PlayerControl/index.ts +0 -1
  40. package/src/components/RedoUndo.scss +0 -56
  41. package/src/components/RedoUndo.tsx +0 -95
  42. package/src/components/Root.scss +0 -55
  43. package/src/components/Root.tsx +0 -61
  44. package/src/components/Toolbar/Content.tsx +0 -93
  45. package/src/components/Toolbar/Toolbar.scss +0 -247
  46. package/src/components/Toolbar/Toolbar.tsx +0 -82
  47. package/src/components/Toolbar/components/ApplianceButtons.tsx +0 -132
  48. package/src/components/Toolbar/components/AppsButton.tsx +0 -106
  49. package/src/components/Toolbar/components/Button.tsx +0 -54
  50. package/src/components/Toolbar/components/ColorBox.tsx +0 -56
  51. package/src/components/Toolbar/components/CutLine.tsx +0 -8
  52. package/src/components/Toolbar/components/PencilButton.tsx +0 -70
  53. package/src/components/Toolbar/components/ShapesButton.tsx +0 -143
  54. package/src/components/Toolbar/components/Slider.tsx +0 -27
  55. package/src/components/Toolbar/components/TextButton.tsx +0 -66
  56. package/src/components/Toolbar/components/UpDownButtons.tsx +0 -49
  57. package/src/components/Toolbar/components/assets/cocos.png +0 -0
  58. package/src/components/Toolbar/components/assets/countdown.png +0 -0
  59. package/src/components/Toolbar/components/assets/geogebra.png +0 -0
  60. package/src/components/Toolbar/components/assets/vscode.png +0 -0
  61. package/src/components/Toolbar/const.ts +0 -32
  62. package/src/components/Toolbar/hooks.ts +0 -113
  63. package/src/components/Toolbar/icons/Apps.tsx +0 -16
  64. package/src/components/Toolbar/icons/Arrow.tsx +0 -16
  65. package/src/components/Toolbar/icons/Circle.tsx +0 -21
  66. package/src/components/Toolbar/icons/Clean.tsx +0 -16
  67. package/src/components/Toolbar/icons/Clicker.tsx +0 -19
  68. package/src/components/Toolbar/icons/Collapse.tsx +0 -17
  69. package/src/components/Toolbar/icons/Diamond.tsx +0 -17
  70. package/src/components/Toolbar/icons/Down.tsx +0 -17
  71. package/src/components/Toolbar/icons/Eraser.tsx +0 -16
  72. package/src/components/Toolbar/icons/Expand.tsx +0 -17
  73. package/src/components/Toolbar/icons/Line.tsx +0 -13
  74. package/src/components/Toolbar/icons/Pencil.tsx +0 -16
  75. package/src/components/Toolbar/icons/Rectangle.tsx +0 -13
  76. package/src/components/Toolbar/icons/Selector.tsx +0 -16
  77. package/src/components/Toolbar/icons/SpeechBalloon.tsx +0 -17
  78. package/src/components/Toolbar/icons/Star.tsx +0 -17
  79. package/src/components/Toolbar/icons/Text.tsx +0 -16
  80. package/src/components/Toolbar/icons/Triangle.tsx +0 -17
  81. package/src/components/Toolbar/icons/Up.tsx +0 -17
  82. package/src/components/Toolbar/icons/index.ts +0 -42
  83. package/src/components/Toolbar/index.ts +0 -1
  84. package/src/components/ZoomControl.scss +0 -80
  85. package/src/components/ZoomControl.tsx +0 -221
  86. package/src/hooks.ts +0 -53
  87. package/src/i18n/en.json +0 -31
  88. package/src/i18n/index.ts +0 -22
  89. package/src/i18n/zh-CN.json +0 -32
  90. package/src/icons/ChevronLeft.tsx +0 -21
  91. package/src/icons/ChevronRight.tsx +0 -21
  92. package/src/icons/FilePlus.tsx +0 -18
  93. package/src/icons/Minus.tsx +0 -21
  94. package/src/icons/Plus.tsx +0 -21
  95. package/src/icons/Redo.tsx +0 -24
  96. package/src/icons/Reset.tsx +0 -23
  97. package/src/icons/Undo.tsx +0 -24
  98. package/src/icons/index.tsx +0 -11
  99. package/src/internal/Instance.tsx +0 -251
  100. package/src/internal/helpers.ts +0 -42
  101. package/src/internal/index.ts +0 -3
  102. package/src/internal/mount-whiteboard.ts +0 -90
  103. package/src/style.scss +0 -29
  104. package/src/svelte.ts +0 -45
  105. package/src/theme/index.ts +0 -36
  106. package/src/types/index.ts +0 -22
  107. package/src/vue.ts +0 -74
@@ -1,251 +0,0 @@
1
- import type { Mutable } from "type-fest";
2
- import type { WindowManager } from "@netless/window-manager";
3
- import type { Room, SceneDefinition, WhiteWebSdk } from "white-web-sdk";
4
- import type { JoinRoom, ManagerConfig, SdkConfig } from "./mount-whiteboard";
5
- import type { i18n } from "i18next";
6
-
7
- import React, { createContext, useContext } from "react";
8
- import ReactDOM from "react-dom";
9
-
10
- import { Root } from "../components/Root";
11
- import { mountWhiteboard } from "./mount-whiteboard";
12
- import { noop } from "./helpers";
13
-
14
- export interface AcceptParams {
15
- readonly sdk: WhiteWebSdk;
16
- readonly room: Room;
17
- readonly manager: WindowManager;
18
- readonly i18n: i18n;
19
- }
20
-
21
- export interface InsertDocsStatic {
22
- readonly fileType: "pdf" | "ppt";
23
- readonly scenePath: string;
24
- readonly scenes: SceneDefinition[];
25
- readonly title?: string;
26
- }
27
-
28
- export interface InsertDocsDynamic {
29
- readonly fileType: "pptx";
30
- readonly scenePath: string;
31
- readonly taskId: string;
32
- readonly title?: string;
33
- readonly url?: string;
34
- }
35
-
36
- export type InsertDocsParams = InsertDocsStatic | InsertDocsDynamic;
37
-
38
- export type Language = "zh-CN" | "en-US";
39
-
40
- export interface Layout {
41
- Toolbar?: boolean;
42
- PageControl?: boolean;
43
- RedoUndo?: boolean;
44
- ZoomControl?: boolean;
45
- }
46
-
47
- export interface WhiteboardAppConfig {
48
- readonly sdkConfig: SdkConfig;
49
- readonly joinRoom: JoinRoom;
50
- readonly managerConfig?: Omit<ManagerConfig, "container">;
51
- readonly layout?: Layout;
52
- readonly toolbar?: {
53
- apps?: {
54
- enable?: boolean;
55
- content?: React.ReactNode;
56
- onClick?: () => void;
57
- };
58
- };
59
- readonly language?: Language;
60
- }
61
-
62
- export interface Essentials {
63
- readonly sdk: WhiteWebSdk;
64
- readonly room: Room;
65
- readonly manager: WindowManager;
66
- readonly i18n: i18n;
67
- }
68
-
69
- export class Instance {
70
- static readonly Context = createContext<Instance | null>(null);
71
-
72
- config: Mutable<WhiteboardAppConfig>;
73
-
74
- sdk: WhiteWebSdk | null = null;
75
- room: Room | null = null;
76
- manager: WindowManager | null = null;
77
- i18n: i18n | null = null;
78
-
79
- ready = false;
80
- resolveReady!: () => void;
81
- readyPromise!: Promise<void>;
82
-
83
- refreshReadyPromise() {
84
- this.readyPromise = new Promise<void>(resolve => {
85
- this.resolveReady = () => {
86
- this.resolveReady = noop;
87
- this.ready = true;
88
- resolve();
89
- };
90
- });
91
- }
92
-
93
- constructor(config: WhiteboardAppConfig) {
94
- this.config = { ...config };
95
- this.refreshReadyPromise();
96
- this.initialize();
97
- }
98
-
99
- async initialize() {
100
- const essentials = await mountWhiteboard(
101
- this.config.sdkConfig,
102
- this.config.joinRoom,
103
- this.config.managerConfig || {},
104
- this.config.language || "en-US"
105
- );
106
- this.accept(essentials);
107
- this.resolveReady();
108
- }
109
-
110
- target: HTMLElement | null = null;
111
- collector: HTMLElement | null = null;
112
-
113
- bindElement(target: HTMLElement | null, collector: HTMLElement | null) {
114
- if (this.target && target) {
115
- ReactDOM.unmountComponentAtNode(this.target);
116
- }
117
- this.target = target;
118
- this.collector = collector;
119
- this.forceUpdate();
120
- }
121
-
122
- updateLayout(layout: Layout | undefined) {
123
- this.config.layout = layout;
124
- this.forceUpdate();
125
- }
126
-
127
- async forceUpdate() {
128
- await this.readyPromise;
129
- if (this.target) {
130
- ReactDOM.render(<Root instance={this} />, this.target);
131
- }
132
- }
133
-
134
- accept({ sdk, room, manager, i18n }: AcceptParams) {
135
- this.sdk = sdk;
136
- this.room = room;
137
- this.manager = manager;
138
- this.i18n = i18n;
139
- this.forceUpdate();
140
- }
141
-
142
- async dispose() {
143
- if (this.room) {
144
- await this.unmount();
145
- }
146
- if (this.target) {
147
- ReactDOM.unmountComponentAtNode(this.target);
148
- this.sdk = this.room = this.manager = this.target = null;
149
- }
150
- }
151
-
152
- async mount(node: HTMLElement) {
153
- await this.readyPromise;
154
- if (!this.manager) {
155
- throw new Error(`[WhiteboardApp] mounted, but not found window manager`);
156
- }
157
- if (this.collector) {
158
- this.manager.bindContainer(node, this.collector);
159
- } else {
160
- this.manager.bindContainer(node);
161
- }
162
- }
163
-
164
- async unmount() {
165
- if (this.manager) {
166
- this.manager.destroy();
167
- this.manager = null;
168
- }
169
- if (this.room) {
170
- try {
171
- await this.room.disconnect();
172
- } catch {
173
- // ignore any error on disconnecting
174
- }
175
- this.room = null;
176
- }
177
- this.refreshReadyPromise();
178
- }
179
-
180
- insertDocs(params: InsertDocsParams) {
181
- if (!this.manager) {
182
- throw new Error(`[WhiteboardApp] cannot insert doc before mounted`);
183
- }
184
- switch (params.fileType) {
185
- case "pdf":
186
- case "ppt":
187
- return this.manager.addApp({
188
- kind: "DocsViewer",
189
- options: {
190
- scenePath: params.scenePath,
191
- title: params.title,
192
- scenes: params.scenes,
193
- },
194
- });
195
- case "pptx":
196
- return this.manager.addApp({
197
- kind: "Slide",
198
- options: {
199
- scenePath: params.scenePath,
200
- title: params.title,
201
- },
202
- attributes: {
203
- taskId: params.taskId,
204
- url: params.url,
205
- },
206
- });
207
- }
208
- }
209
-
210
- insertCodeEditor() {
211
- if (!this.manager) {
212
- throw new Error(`[WhiteboardApp] cannot insert app before mounted`);
213
- }
214
- return this.manager.addApp({
215
- kind: "Monaco",
216
- options: { title: "Code Editor" },
217
- });
218
- }
219
-
220
- insertGeoGebra() {
221
- if (!this.manager) {
222
- throw new Error(`[WhiteboardApp] cannot insert app before mounted`);
223
- }
224
- return this.manager.addApp({
225
- kind: "GeoGebra",
226
- options: { title: "GeoGebra" },
227
- });
228
- }
229
-
230
- insertCountdown() {
231
- if (!this.manager) {
232
- throw new Error(`[WhiteboardApp] cannot insert app before mounted`);
233
- }
234
- return this.manager.addApp({
235
- kind: "Countdown",
236
- options: { title: "Countdown" },
237
- });
238
- }
239
-
240
- async changeLanguage(language: Language) {
241
- try {
242
- await this.i18n?.changeLanguage(language);
243
- } finally {
244
- await this.forceUpdate();
245
- }
246
- }
247
- }
248
-
249
- export function useInstance() {
250
- return useContext(Instance.Context);
251
- }
@@ -1,42 +0,0 @@
1
- export function noop() {
2
- return;
3
- }
4
-
5
- export function applyStyles(css: string) {
6
- const el = document.createElement("style");
7
- el.appendChild(document.createTextNode(css));
8
- document.head.appendChild(el);
9
- return el;
10
- }
11
-
12
- export function clamp(value: number, min: number, max: number) {
13
- return value < min ? min : value > max ? max : value;
14
- }
15
-
16
- export function isEqualArray<T>(a: T[], b: T[]) {
17
- return a.length === b.length && a.every((e, i) => e === b[i]);
18
- }
19
-
20
- export type TaskFn = () => Promise<void> | void;
21
-
22
- export class Lock {
23
- running = false;
24
- private nextFn: TaskFn | null = null;
25
- schedule(fn: TaskFn) {
26
- if (this.running) {
27
- this.nextFn = fn;
28
- } else {
29
- this.running = true;
30
- Promise.resolve(fn()).then(this.step);
31
- }
32
- }
33
- private step = () => {
34
- if (this.nextFn) {
35
- const fn = this.nextFn;
36
- this.nextFn = null;
37
- Promise.resolve(fn()).then(this.step);
38
- } else {
39
- this.running = false;
40
- }
41
- };
42
- }
@@ -1,3 +0,0 @@
1
- export * from "./helpers";
2
- export * from "./mount-whiteboard";
3
- export * from "./Instance";
@@ -1,90 +0,0 @@
1
- import type { MountParams } from "@netless/window-manager";
2
- import type {
3
- JoinRoomParams,
4
- RoomCallbacks,
5
- WhiteWebSdkConfiguration,
6
- } from "white-web-sdk";
7
- import type { Essentials, Language } from "./Instance";
8
-
9
- import { WindowManager } from "@netless/window-manager";
10
- import { DefaultHotKeys, WhiteWebSdk } from "white-web-sdk";
11
- import { createI18n } from "../i18n";
12
-
13
- export type SdkConfig = Omit<
14
- WhiteWebSdkConfiguration,
15
- "useMobXState" | "disableNewPencil" | "disableMagixEventDispatchLimit"
16
- >;
17
- export type JoinRoom = Omit<
18
- JoinRoomParams,
19
- "useMultiViews" | "disableMagixEventDispatchLimit"
20
- > & { callbacks?: Partial<RoomCallbacks> };
21
- export type ManagerConfig = Omit<MountParams, "room">;
22
-
23
- function ensureWindowManager(joinRoom: JoinRoom) {
24
- if (
25
- !joinRoom.invisiblePlugins ||
26
- !joinRoom.invisiblePlugins.includes(WindowManager)
27
- ) {
28
- joinRoom.invisiblePlugins = [
29
- ...(joinRoom.invisiblePlugins || []),
30
- WindowManager,
31
- ];
32
- }
33
- }
34
-
35
- export const defaultHotKeys = {
36
- changeToSelector: "s",
37
- changeToLaserPointer: "z",
38
- changeToPencil: "p",
39
- changeToRectangle: "r",
40
- changeToEllipse: "c",
41
- changeToEraser: "e",
42
- changeToText: "t",
43
- changeToStraight: "l",
44
- changeToArrow: "a",
45
- changeToHand: "h",
46
- };
47
-
48
- export async function mountWhiteboard(
49
- sdkConfig: SdkConfig,
50
- joinRoom: JoinRoom,
51
- managerConfig: ManagerConfig,
52
- language: Language
53
- ): Promise<Essentials> {
54
- const sdk = new WhiteWebSdk({
55
- ...sdkConfig,
56
- useMobXState: true,
57
- });
58
-
59
- ensureWindowManager(joinRoom);
60
- joinRoom = { ...joinRoom };
61
- const callbacks = joinRoom.callbacks;
62
- delete joinRoom.callbacks;
63
- const joinRoomParams: JoinRoomParams = {
64
- floatBar: true,
65
- hotKeys: {
66
- ...DefaultHotKeys,
67
- ...defaultHotKeys,
68
- },
69
- ...joinRoom,
70
- useMultiViews: true,
71
- disableNewPencil: false,
72
- disableMagixEventDispatchLimit: true,
73
- };
74
- const room = await sdk.joinRoom(joinRoomParams, callbacks);
75
-
76
- const manager = await WindowManager.mount({
77
- cursor: true,
78
- debug: import.meta.env.DEV,
79
- ...managerConfig,
80
- room,
81
- });
82
-
83
- const i18n = await createI18n({ language });
84
-
85
- if (import.meta.env.DEV) {
86
- Object.assign(window, { sdk, room, manager });
87
- }
88
-
89
- return { sdk, room, manager, i18n };
90
- }
package/src/style.scss DELETED
@@ -1,29 +0,0 @@
1
- @import "@netless/window-manager/dist/style.css";
2
- @import "tippy.js/dist/tippy.css";
3
- @import "tippy.js/themes/light.css";
4
- @import "rc-slider/assets/index.css";
5
- @import "./components/Root.scss";
6
- @import "./components/RedoUndo.scss";
7
- @import "./components/PageControl.scss";
8
- @import "./components/ZoomControl.scss";
9
- @import "./components/Toolbar/Toolbar.scss";
10
- @import "./components/PlayerControl/PlayerControl.scss";
11
-
12
- .tippy-box.fastboard-tip {
13
- color: #eee;
14
- background-color: rgba($color: #000000, $alpha: 0.95);
15
- backdrop-filter: blur(2px);
16
- -webkit-backdrop-filter: blur(2px);
17
- }
18
-
19
- .tippy-box.fastboard-tip[data-placement^="right"] > .tippy-arrow::before {
20
- top: 4px;
21
- border-width: 4px;
22
- border-right-color: #000;
23
- }
24
-
25
- .tippy-box.fastboard-tip[data-placement^="top"] > .tippy-arrow::before {
26
- left: 4px;
27
- border-width: 4px;
28
- border-top-color: #000;
29
- }
package/src/svelte.ts DELETED
@@ -1,45 +0,0 @@
1
- import { readable, type Readable } from "svelte/store";
2
- import { createWhiteboardApp } from "./index";
3
-
4
- import type { WhiteboardApp, WhiteboardAppConfig } from "./WhiteboardApp";
5
-
6
- export type FastBoardConfig = WhiteboardAppConfig;
7
-
8
- /**
9
- * @example
10
- * ```svelte
11
- * <script>
12
- * let ref = writable(null)
13
- * let app = useFastboard(ref, { sdkConfig, joinRoom })
14
- * if (app) {
15
- * app.insertDocs({...})
16
- * }
17
- * </script>
18
- * <div style="width: 100%; height: 100%" bind:this={$ref} />
19
- * ```
20
- */
21
- export function useFastboard(
22
- ref: Readable<HTMLElement | null>,
23
- config: FastBoardConfig
24
- ): Readable<WhiteboardApp | null> {
25
- return readable<WhiteboardApp | null>(null, set => {
26
- let app_: WhiteboardApp | null = null;
27
-
28
- createWhiteboardApp(config).then(app => {
29
- set((app_ = app));
30
- });
31
-
32
- const dispose = ref.subscribe(div => {
33
- if (div && app_) {
34
- app_.bindElement(div);
35
- }
36
- });
37
-
38
- return () => {
39
- dispose();
40
- if (app_) {
41
- app_.dispose();
42
- }
43
- };
44
- });
45
- }
@@ -1,36 +0,0 @@
1
- import type { IconProps } from "../types";
2
-
3
- export interface ThemeConfig {
4
- color: string;
5
- activeColor: string;
6
- backgroundColor: string;
7
- hoverBackgroundColor: string;
8
- }
9
-
10
- export const light: ThemeConfig = {
11
- color: "#5D5D5D",
12
- activeColor: "#3381FF",
13
- backgroundColor: "#fff",
14
- hoverBackgroundColor: "rgba(51, 129, 255, 0.1)",
15
- };
16
-
17
- export const dark: ThemeConfig = {
18
- ...light,
19
- color: "#eee",
20
- backgroundColor: "#111",
21
- };
22
-
23
- export const themes = { light, dark };
24
-
25
- export const getStroke = (props: IconProps) => {
26
- let config;
27
- if (props.theme) {
28
- config = themes[props.theme];
29
- } else {
30
- config = themes.light;
31
- }
32
- return props.active ? config.activeColor : config.color;
33
- };
34
-
35
- export const TopOffset = [0, 11] as [number, number];
36
- export const RightOffset = [0, 11] as [number, number];
@@ -1,22 +0,0 @@
1
- import type { Room } from "white-web-sdk";
2
- import type { WindowManager } from "@netless/window-manager";
3
- import type { i18n } from "i18next";
4
-
5
- export type Theme = "light" | "dark";
6
-
7
- export interface IconProps {
8
- theme?: Theme;
9
- active?: boolean;
10
- }
11
-
12
- export interface CommonProps {
13
- room?: Room | null;
14
- manager?: WindowManager | null;
15
- theme?: Theme;
16
- i18n?: i18n | null;
17
- }
18
-
19
- export type GenericIcon<
20
- K extends string,
21
- E extends string = "disable"
22
- > = Partial<Record<`${K}Icon${Capitalize<E | "">}`, string>>;
package/src/vue.ts DELETED
@@ -1,74 +0,0 @@
1
- import type { ComponentPublicInstance, Ref } from "vue-demi";
2
- import {
3
- computed,
4
- getCurrentScope,
5
- onScopeDispose,
6
- shallowRef,
7
- unref,
8
- watchEffect,
9
- } from "vue-demi";
10
- import { createWhiteboardApp } from "./index";
11
-
12
- import type { WhiteboardApp, WhiteboardAppConfig } from "./WhiteboardApp";
13
-
14
- export type FastBoardConfig = WhiteboardAppConfig;
15
-
16
- export type MaybeRef<T> = T | Ref<T>;
17
- export type VueInstance = ComponentPublicInstance;
18
- export type MaybeElementRef = MaybeRef<
19
- HTMLElement | SVGElement | VueInstance | undefined | null
20
- >;
21
-
22
- /**
23
- * Get the dom element of a ref of element or Vue component instance
24
- */
25
- export function unrefElement(elRef: MaybeElementRef) {
26
- const plain = unref(elRef);
27
- return (plain as VueInstance)?.$el ?? plain;
28
- }
29
-
30
- function tryOnScopeDispose(fn: () => void) {
31
- if (getCurrentScope()) {
32
- onScopeDispose(fn);
33
- return true;
34
- }
35
- return false;
36
- }
37
-
38
- /**
39
- * @example
40
- * ```vue
41
- * <script setup>
42
- * const el = ref(null)
43
- * const app = useFastboard(el, { sdkConfig, joinRoom })
44
- * if (app.value) {
45
- * app.value.insertDocs({...})
46
- * }
47
- * </script>
48
- * <template>
49
- * <div style="width: 100%; height: 100%" ref="el"></div>
50
- * </template>
51
- * ```
52
- */
53
- export function useFastboard(el: MaybeElementRef, config: FastBoardConfig) {
54
- const app = shallowRef<WhiteboardApp | null>(null);
55
- const target = computed(() => unrefElement(el));
56
-
57
- createWhiteboardApp(config).then(app_ => {
58
- app.value = app_;
59
- });
60
-
61
- watchEffect(() => {
62
- if (target.value && app.value) {
63
- app.value.bindElement(target.value);
64
- }
65
- });
66
-
67
- tryOnScopeDispose(() => {
68
- if (app.value) {
69
- app.value.dispose();
70
- }
71
- });
72
-
73
- return app;
74
- }