@netless/fastboard-react 0.2.8 → 0.2.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.
- package/dist/index.d.ts +146 -0
- package/dist/index.js +245 -188
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +193 -136
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
- package/src/components/Fastboard.scss +5 -0
- package/src/components/Fastboard.tsx +3 -10
- package/src/components/PlayerControl/PlayerControl.scss +1 -0
- package/src/components/PlayerControl/PlayerControl.tsx +3 -3
- package/src/components/PlayerControl/components/Button.tsx +1 -2
- package/src/components/ReplayFastboard.tsx +36 -0
- package/src/components/Toolbar/Toolbar.scss +33 -5
- package/src/components/Toolbar/components/AppsButton.tsx +20 -11
- package/src/components/Toolbar/components/Button.tsx +1 -2
- package/src/components/Toolbar/icons/Loading.tsx +13 -0
- package/src/components/tippy-util.ts +8 -0
- package/src/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netless/fastboard-react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "A UI kit built on top of @netless/fastboard.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"@tippyjs/react": "^4.2.6",
|
|
12
12
|
"clsx": "^1.1.1",
|
|
13
13
|
"framer-motion": "^6.2.8",
|
|
14
|
-
"i18next": "^21.6.
|
|
14
|
+
"i18next": "^21.6.13",
|
|
15
15
|
"rc-slider": "^9.7.5"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
"white-web-sdk": ">=2.16.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@netless/fastboard-core": "0.2.
|
|
26
|
-
"@netless/window-manager": "^0.4.
|
|
25
|
+
"@netless/fastboard-core": "0.2.11",
|
|
26
|
+
"@netless/window-manager": "^0.4.10",
|
|
27
27
|
"@types/react": "^17.0.39",
|
|
28
|
-
"@types/react-dom": "^17.0.
|
|
29
|
-
"sass": "^1.49.
|
|
28
|
+
"@types/react-dom": "^17.0.13",
|
|
29
|
+
"sass": "^1.49.9",
|
|
30
30
|
"tippy.js": "^6.3.7",
|
|
31
|
-
"tsup": "^5.
|
|
31
|
+
"tsup": "^5.12.0",
|
|
32
32
|
"white-web-sdk": "^2.16.10"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"check": "tsc --noEmit"
|
|
38
38
|
},
|
|
39
39
|
"module": "dist/index.mjs",
|
|
40
|
-
"types": "
|
|
40
|
+
"types": "dist/index.d.ts"
|
|
41
41
|
}
|
|
@@ -10,6 +10,7 @@ import { PageControl } from "./PageControl";
|
|
|
10
10
|
import { RedoUndo } from "./RedoUndo";
|
|
11
11
|
import { Toolbar } from "./Toolbar";
|
|
12
12
|
import { ZoomControl } from "./ZoomControl";
|
|
13
|
+
import { hideAll } from "./tippy-util";
|
|
13
14
|
|
|
14
15
|
export interface FastboardProps {
|
|
15
16
|
app?: FastboardApp | null;
|
|
@@ -58,7 +59,7 @@ function FastboardInternal({
|
|
|
58
59
|
|
|
59
60
|
const useWhiteboard = useCallback(
|
|
60
61
|
(container: HTMLDivElement | null) => {
|
|
61
|
-
if (container && app) app.
|
|
62
|
+
if (container && app) app.bindContainer(container);
|
|
62
63
|
},
|
|
63
64
|
[app]
|
|
64
65
|
);
|
|
@@ -77,11 +78,7 @@ function FastboardInternal({
|
|
|
77
78
|
<ThemeContext.Provider value={theme}>
|
|
78
79
|
<I18nContext.Provider value={i18n}>
|
|
79
80
|
<div {...restProps} className="fastboard-root" ref={forwardedRef}>
|
|
80
|
-
<div
|
|
81
|
-
className="fastboard-view"
|
|
82
|
-
ref={useWhiteboard}
|
|
83
|
-
onPointerDownCapture={focusThisElementImmediate}
|
|
84
|
-
/>
|
|
81
|
+
<div className="fastboard-view" ref={useWhiteboard} onTouchStartCapture={hideAll} />
|
|
85
82
|
{children ? (
|
|
86
83
|
children
|
|
87
84
|
) : (
|
|
@@ -109,7 +106,3 @@ function FastboardInternal({
|
|
|
109
106
|
</ThemeContext.Provider>
|
|
110
107
|
);
|
|
111
108
|
}
|
|
112
|
-
|
|
113
|
-
function focusThisElementImmediate(ev: React.PointerEvent<HTMLDivElement>) {
|
|
114
|
-
ev.currentTarget.focus();
|
|
115
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FastboardPlayer } from "@netless/fastboard-core";
|
|
2
2
|
import type { CommonProps, GenericIcon } from "../../typings";
|
|
3
3
|
|
|
4
4
|
import Tippy from "@tippyjs/react";
|
|
@@ -17,7 +17,7 @@ import { Icons } from "./icons";
|
|
|
17
17
|
|
|
18
18
|
export type PlayerControlProps = {
|
|
19
19
|
autoHide?: boolean;
|
|
20
|
-
player?:
|
|
20
|
+
player?: FastboardPlayer;
|
|
21
21
|
} & Omit<CommonProps, "room"> &
|
|
22
22
|
GenericIcon<"play" | "pause" | "loading">;
|
|
23
23
|
|
|
@@ -28,7 +28,7 @@ export function PlayerControl({ theme, autoHide = false, player: player_, ...ico
|
|
|
28
28
|
const { t } = useTranslation();
|
|
29
29
|
|
|
30
30
|
const [currentTime, setCurrentTime] = useState(0);
|
|
31
|
-
const player = usePlayerControl(player_);
|
|
31
|
+
const player = usePlayerControl(player_?.player);
|
|
32
32
|
|
|
33
33
|
useEffect(() => {
|
|
34
34
|
setCurrentTime(player.currentTime);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Placement } from "tippy.js";
|
|
2
1
|
import type { Theme } from "../../../typings";
|
|
3
2
|
|
|
4
3
|
import clsx from "clsx";
|
|
@@ -14,7 +13,7 @@ type ButtonProps = PropsWithChildren<{
|
|
|
14
13
|
active?: boolean;
|
|
15
14
|
onClick?: () => void;
|
|
16
15
|
interactive?: boolean;
|
|
17
|
-
placement?:
|
|
16
|
+
placement?: "top" | "right"; // not using tippy.js's placement to satisfy dts
|
|
18
17
|
}>;
|
|
19
18
|
|
|
20
19
|
export const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { FastboardPlayer } from "@netless/fastboard-core";
|
|
2
|
+
import type { DivProps } from "./Fastboard";
|
|
3
|
+
import type { Theme } from "../typings";
|
|
4
|
+
|
|
5
|
+
import React, { forwardRef, useCallback } from "react";
|
|
6
|
+
import { PlayerControl } from "./PlayerControl";
|
|
7
|
+
|
|
8
|
+
export interface ReplayFastboardProps {
|
|
9
|
+
player?: FastboardPlayer | null;
|
|
10
|
+
theme?: Theme;
|
|
11
|
+
autoHideControl?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const ReplayFastboard = /* @__PURE__ */ forwardRef<HTMLDivElement, ReplayFastboardProps & DivProps>(
|
|
15
|
+
function ReplayFastboard({ player, theme = "light", autoHideControl = false, ...restProps }, ref) {
|
|
16
|
+
const useWhiteboard = useCallback(
|
|
17
|
+
(container: HTMLDivElement | null) => {
|
|
18
|
+
if (container && player) player.bindContainer(container);
|
|
19
|
+
},
|
|
20
|
+
[player]
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
if (!player) {
|
|
24
|
+
return <div className="fastboard-root" ref={ref} {...restProps} />;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="fastboard-root" ref={ref} {...restProps}>
|
|
29
|
+
<div className="fastboard-view" ref={useWhiteboard} />
|
|
30
|
+
<div className="fastboard-bottom">
|
|
31
|
+
<PlayerControl player={player} theme={theme} autoHide={autoHideControl} />
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
);
|
|
@@ -153,12 +153,12 @@ $name: "fastboard-toolbar";
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
&-section
|
|
156
|
+
&-section ~ &-mask {
|
|
157
157
|
opacity: 0;
|
|
158
158
|
transition: 0.5s opacity 0.4s;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
&-section:hover
|
|
161
|
+
&-section:hover ~ &-mask,
|
|
162
162
|
&-mask:hover {
|
|
163
163
|
opacity: 1;
|
|
164
164
|
transition: 0.2s opacity;
|
|
@@ -173,7 +173,7 @@ $name: "fastboard-toolbar";
|
|
|
173
173
|
gap: 8px;
|
|
174
174
|
|
|
175
175
|
&.apps {
|
|
176
|
-
width: 240px
|
|
176
|
+
width: 240px + 8px * 2;
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -207,14 +207,33 @@ $name: "fastboard-toolbar";
|
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
&-app-icon-wrapper {
|
|
211
|
+
position: relative;
|
|
212
|
+
display: flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
justify-content: center;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
&-app-icon-mask {
|
|
218
|
+
position: absolute;
|
|
219
|
+
width: 36px;
|
|
220
|
+
height: 36px;
|
|
221
|
+
animation: fastboard-app-loading-rotate 0.5s linear infinite;
|
|
222
|
+
transform-origin: center;
|
|
223
|
+
}
|
|
224
|
+
|
|
210
225
|
&-app-is-loading {
|
|
211
|
-
opacity: 0.8;
|
|
212
226
|
cursor: wait;
|
|
227
|
+
button:disabled {
|
|
228
|
+
cursor: wait;
|
|
229
|
+
}
|
|
213
230
|
}
|
|
214
231
|
|
|
215
232
|
&-app-is-failed {
|
|
216
|
-
opacity: 0.5;
|
|
217
233
|
cursor: not-allowed;
|
|
234
|
+
button:disabled {
|
|
235
|
+
cursor: not-allowed;
|
|
236
|
+
}
|
|
218
237
|
}
|
|
219
238
|
|
|
220
239
|
&-app-icon {
|
|
@@ -313,3 +332,12 @@ $name: "fastboard-toolbar";
|
|
|
313
332
|
left: 0;
|
|
314
333
|
}
|
|
315
334
|
}
|
|
335
|
+
|
|
336
|
+
@keyframes fastboard-app-loading-rotate {
|
|
337
|
+
from {
|
|
338
|
+
transform: rotate(0deg);
|
|
339
|
+
}
|
|
340
|
+
to {
|
|
341
|
+
transform: rotate(360deg);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -12,6 +12,7 @@ import { Icons } from "../icons";
|
|
|
12
12
|
import { ToolbarContext } from "../Toolbar";
|
|
13
13
|
import { Button } from "./Button";
|
|
14
14
|
import { useFastboardApp } from "../../hooks";
|
|
15
|
+
import { Loading } from "../icons/Loading";
|
|
15
16
|
|
|
16
17
|
export interface AppsButtonProps {
|
|
17
18
|
content?: React.ReactNode;
|
|
@@ -104,22 +105,30 @@ interface AppIconProps {
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
function AppIcon({ title, src, alt, appStatus, onClick }: AppIconProps) {
|
|
108
|
+
const { theme } = useContext(ToolbarContext);
|
|
107
109
|
const { status = "idle", reason } = appStatus || {};
|
|
108
110
|
const loading = status === "loading";
|
|
109
111
|
const failed = status === "failed";
|
|
110
112
|
const unifiedTitle = loading ? "loading" : failed ? reason : title;
|
|
111
113
|
|
|
112
114
|
return (
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
"fastboard-toolbar-app-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
<div className="fastboard-toolbar-app-icon-wrapper">
|
|
116
|
+
<span
|
|
117
|
+
className={clsx("fastboard-toolbar-app-icon", {
|
|
118
|
+
"fastboard-toolbar-app-is-loading": loading,
|
|
119
|
+
"fastboard-toolbar-app-is-failed": failed,
|
|
120
|
+
})}
|
|
121
|
+
>
|
|
122
|
+
<Button disabled={failed || loading} placement="top" content={unifiedTitle} onClick={onClick}>
|
|
123
|
+
<img src={src} alt={alt} title={unifiedTitle} />
|
|
124
|
+
</Button>
|
|
125
|
+
<span className="fastboard-toolbar-app-icon-text">{title}</span>
|
|
126
|
+
</span>
|
|
127
|
+
{loading && (
|
|
128
|
+
<span className="fastboard-toolbar-app-icon-mask">
|
|
129
|
+
<Loading theme={theme} />
|
|
130
|
+
</span>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
124
133
|
);
|
|
125
134
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Placement } from "tippy.js";
|
|
2
1
|
import type { PropsWithChildren } from "react";
|
|
3
2
|
|
|
4
3
|
import clsx from "clsx";
|
|
@@ -14,7 +13,7 @@ type ButtonProps = PropsWithChildren<{
|
|
|
14
13
|
active?: boolean;
|
|
15
14
|
onClick?: () => void;
|
|
16
15
|
interactive?: boolean;
|
|
17
|
-
placement?:
|
|
16
|
+
placement?: "top" | "right"; // not using tippy.js's placement to satisfy dts
|
|
18
17
|
}>;
|
|
19
18
|
|
|
20
19
|
export const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IconProps } from "../../../typings";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { getStroke } from "../../../theme";
|
|
5
|
+
|
|
6
|
+
export const Loading = (props: IconProps) => {
|
|
7
|
+
const stroke = getStroke(props);
|
|
8
|
+
return (
|
|
9
|
+
<svg viewBox="0 0 24 24">
|
|
10
|
+
<path fill={stroke} d="M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8Z"></path>
|
|
11
|
+
</svg>
|
|
12
|
+
);
|
|
13
|
+
};
|
package/src/index.ts
CHANGED