@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
@@ -1,221 +0,0 @@
1
- import type { RoomState } from "white-web-sdk";
2
- import type { CommonProps, GenericIcon } from "../types";
3
-
4
- import clsx from "clsx";
5
- import React, { useCallback, useEffect, useState } from "react";
6
- import Tippy from "@tippyjs/react";
7
-
8
- import { clamp } from "../internal";
9
- import { TopOffset } from "../theme";
10
- import { Icon } from "../icons";
11
- import { Minus } from "../icons/Minus";
12
- import { Plus } from "../icons/Plus";
13
- import { Reset } from "../icons/Reset";
14
-
15
- export const name = "fastboard-zoom-control";
16
-
17
- export const ScalePoints: readonly number[] = [
18
- 0.10737418240000011, 0.13421772800000012, 0.16777216000000014,
19
- 0.20971520000000016, 0.26214400000000015, 0.3276800000000002,
20
- 0.4096000000000002, 0.5120000000000001, 0.6400000000000001, 0.8, 1, 1.26,
21
- 1.5876000000000001, 2.000376, 2.5204737600000002, 3.1757969376000004,
22
- 4.001504141376, 5.041895218133761, 6.352787974848539, 8.00451284830916, 10,
23
- ];
24
-
25
- function nextScale(scale: number, delta: 1 | -1) {
26
- const { length } = ScalePoints;
27
- const last = length - 1;
28
- if (scale < ScalePoints[0]) return ScalePoints[0];
29
- if (scale > ScalePoints[last]) return ScalePoints[last];
30
- for (let i = 0; i < length; ++i) {
31
- const curr = ScalePoints[i];
32
- const prev = i === 0 ? -Infinity : (ScalePoints[i - 1] + curr) / 2;
33
- const next = i === last ? Infinity : (ScalePoints[i + 1] + curr) / 2;
34
- if (prev <= scale && scale <= next)
35
- return ScalePoints[clamp(i + delta, 0, last)];
36
- }
37
- return 1;
38
- }
39
-
40
- export type ZoomControlProps = CommonProps &
41
- GenericIcon<"reset" | "minus" | "plus">;
42
-
43
- export function ZoomControl({
44
- room,
45
- manager,
46
- theme = "light",
47
- resetIcon,
48
- resetIconDisable,
49
- minusIcon,
50
- minusIconDisable,
51
- plusIcon,
52
- plusIconDisable,
53
- i18n,
54
- }: ZoomControlProps) {
55
- const [writable, setWritable] = useState(false);
56
- const [scale, setScale] = useState(1);
57
-
58
- const resetCamera = useCallback(() => {
59
- if (room?.isWritable) {
60
- if (manager) {
61
- manager.mainView.moveCamera({ scale: 1, centerX: 0, centerY: 0 });
62
- } else {
63
- const { scenes, index } = room.state.sceneState;
64
- if (scenes[index].ppt) {
65
- room.scalePptToFit();
66
- } else {
67
- room.moveCamera({ scale: 1, centerX: 0, centerY: 0 });
68
- }
69
- }
70
- }
71
- }, [room, manager]);
72
-
73
- const zoomIn = useCallback(() => {
74
- if (room?.isWritable) {
75
- if (manager) {
76
- manager.mainView.moveCamera({
77
- scale: nextScale(scale, 1),
78
- centerX: 0,
79
- centerY: 0,
80
- });
81
- } else {
82
- room.moveCamera({
83
- scale: nextScale(scale, 1),
84
- centerX: 0,
85
- centerY: 0,
86
- });
87
- }
88
- }
89
- }, [room, manager, scale]);
90
-
91
- const zoomOut = useCallback(() => {
92
- if (room?.isWritable) {
93
- if (manager) {
94
- manager.mainView.moveCamera({
95
- scale: nextScale(scale, -1),
96
- centerX: 0,
97
- centerY: 0,
98
- });
99
- } else {
100
- room.moveCamera({
101
- scale: nextScale(scale, -1),
102
- centerX: 0,
103
- centerY: 0,
104
- });
105
- }
106
- }
107
- }, [room, manager, scale]);
108
-
109
- useEffect(() => {
110
- if (room) {
111
- setWritable(room.isWritable);
112
- setScale(room.state.cameraState.scale);
113
- }
114
-
115
- if (manager) {
116
- setScale(manager.mainView.camera.scale);
117
- }
118
-
119
- const onRoomStateChanged = (modifyState: Partial<RoomState>) => {
120
- if (modifyState.cameraState) {
121
- setScale(modifyState.cameraState.scale);
122
- }
123
- };
124
-
125
- const onCameraUpdated = ({ scale }: { scale: number }) => setScale(scale);
126
-
127
- const updateWritable = () => setWritable(room?.isWritable || false);
128
-
129
- if (room) {
130
- room.callbacks.on("onEnableWriteNowChanged", updateWritable);
131
- if (manager) {
132
- manager.mainView.callbacks.on("onCameraUpdated", onCameraUpdated);
133
- } else {
134
- room.callbacks.on("onRoomStateChanged", onRoomStateChanged);
135
- }
136
- }
137
-
138
- return () => {
139
- if (room) {
140
- room.callbacks.off("onEnableWriteNowChanged", updateWritable);
141
- room.callbacks.off("onRoomStateChanged", onRoomStateChanged);
142
- manager?.mainView.callbacks.off("onCameraUpdated", onCameraUpdated);
143
- }
144
- };
145
- }, [room, manager]);
146
-
147
- const disabled = !writable;
148
-
149
- return (
150
- <div className={clsx(name, theme)}>
151
- {/* <span className={clsx(`${name}-cut-line`, theme)} /> */}
152
- <Tippy
153
- className="fastboard-tip"
154
- content={i18n?.t("zoomOut")}
155
- theme={theme}
156
- disabled={disabled}
157
- placement="top"
158
- duration={300}
159
- offset={TopOffset}
160
- >
161
- <button
162
- className={clsx(`${name}-btn`, "minus", theme)}
163
- disabled={disabled}
164
- onClick={zoomOut}
165
- >
166
- <Icon
167
- fallback={<Minus theme={theme} />}
168
- src={disabled ? minusIconDisable : minusIcon}
169
- alt="[minus]"
170
- />
171
- </button>
172
- </Tippy>
173
- <span className={clsx(`${name}-scale`, theme)}>
174
- {Math.ceil(scale * 100)}
175
- </span>
176
- <span className={clsx(`${name}-percent`, theme)}>%</span>
177
- <Tippy
178
- className="fastboard-tip"
179
- content={i18n?.t("zoomIn")}
180
- theme={theme}
181
- disabled={disabled}
182
- placement="top"
183
- duration={300}
184
- offset={TopOffset}
185
- >
186
- <button
187
- className={clsx(`${name}-btn`, "plus", theme)}
188
- disabled={disabled}
189
- onClick={zoomIn}
190
- >
191
- <Icon
192
- fallback={<Plus theme={theme} />}
193
- src={disabled ? plusIconDisable : plusIcon}
194
- alt="[plus]"
195
- />
196
- </button>
197
- </Tippy>
198
- <Tippy
199
- className="fastboard-tip"
200
- content={i18n?.t("reset")}
201
- theme={theme}
202
- disabled={disabled}
203
- placement="top"
204
- duration={300}
205
- offset={TopOffset}
206
- >
207
- <button
208
- className={clsx(`${name}-btn`, "reset", theme)}
209
- disabled={disabled}
210
- onClick={resetCamera}
211
- >
212
- <Icon
213
- fallback={<Reset theme={theme} />}
214
- src={disabled ? resetIconDisable : resetIcon}
215
- alt="[reset]"
216
- />
217
- </button>
218
- </Tippy>
219
- </div>
220
- );
221
- }
package/src/hooks.ts DELETED
@@ -1,53 +0,0 @@
1
- import type { WhiteboardApp, WhiteboardAppConfig } from "./WhiteboardApp";
2
-
3
- import { useEffect, useState } from "react";
4
- import { createWhiteboardApp } from "./index";
5
-
6
- export type FastBoardConfig = WhiteboardAppConfig;
7
-
8
- /**
9
- * @example
10
- * const [app, ref] = useFastboard({ sdkConfig, joinRoom })
11
- * if (app) {
12
- * app.insertDocs({...})
13
- * }
14
- * return <div style={{ width: '100%', height: '100%' }} ref={ref} />
15
- */
16
- export function useFastboard(config: FastBoardConfig): readonly [
17
- app: WhiteboardApp | null,
18
- ref: (div: HTMLDivElement | null) => void,
19
- collectorRef: (div: HTMLDivElement | null) => void
20
- ] & {
21
- readonly app: WhiteboardApp | null;
22
- readonly ref: (div: HTMLDivElement | null) => void;
23
- readonly collectorRef: (div: HTMLDivElement | null) => void;
24
- } {
25
- const [app, setApp] = useState<WhiteboardApp | null>(null);
26
- const [currentTarget, ref] = useState<HTMLDivElement | null>(null);
27
- const [collector, collectorRef] = useState<HTMLDivElement | null>(null);
28
-
29
- useEffect(() => {
30
- let isMounted = true;
31
- const promise = createWhiteboardApp(config).then(app => {
32
- if (isMounted) setApp(app);
33
- });
34
- return () => {
35
- isMounted = false;
36
- promise.then(() => app?.dispose());
37
- };
38
- // ignore config and app change
39
- // eslint-disable-next-line react-hooks/exhaustive-deps
40
- }, []);
41
-
42
- useEffect(() => {
43
- if (app) {
44
- app.bindElement(currentTarget, collector);
45
- }
46
- }, [app, collector, currentTarget]);
47
-
48
- return Object.assign([app, ref, collectorRef] as const, {
49
- app,
50
- ref,
51
- collectorRef,
52
- });
53
- }