@netless/fastboard-react 0.2.13-canary.0 → 0.3.0-canary.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 (105) hide show
  1. package/README.md +49 -0
  2. package/dist/index.d.ts +11 -140
  3. package/dist/index.js +73 -2130
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +71 -2129
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +15 -23
  8. package/src/Fastboard.tsx +12 -0
  9. package/src/PageControl.tsx +11 -0
  10. package/src/RedoUndo.tsx +8 -0
  11. package/src/Toolbar.tsx +8 -0
  12. package/src/ZoomControl.tsx +11 -0
  13. package/src/hooks.tsx +53 -0
  14. package/src/index.tsx +19 -0
  15. package/src/style.scss +3 -26
  16. package/src/behaviors/style.ts +0 -4
  17. package/src/components/Fastboard.scss +0 -46
  18. package/src/components/Fastboard.tsx +0 -108
  19. package/src/components/PageControl/PageControl.scss +0 -84
  20. package/src/components/PageControl/PageControl.tsx +0 -101
  21. package/src/components/PageControl/hooks.ts +0 -24
  22. package/src/components/PageControl/index.ts +0 -2
  23. package/src/components/PlayerControl/PlayerControl.scss +0 -146
  24. package/src/components/PlayerControl/PlayerControl.tsx +0 -131
  25. package/src/components/PlayerControl/components/Button.tsx +0 -44
  26. package/src/components/PlayerControl/hooks.ts +0 -88
  27. package/src/components/PlayerControl/icons/Loading.tsx +0 -13
  28. package/src/components/PlayerControl/icons/Pause.tsx +0 -13
  29. package/src/components/PlayerControl/icons/Play.tsx +0 -13
  30. package/src/components/PlayerControl/icons/index.ts +0 -10
  31. package/src/components/PlayerControl/index.ts +0 -2
  32. package/src/components/RedoUndo/RedoUndo.scss +0 -56
  33. package/src/components/RedoUndo/RedoUndo.tsx +0 -76
  34. package/src/components/RedoUndo/hooks.ts +0 -18
  35. package/src/components/RedoUndo/index.ts +0 -2
  36. package/src/components/ReplayFastboard.tsx +0 -36
  37. package/src/components/Toolbar/Content.tsx +0 -89
  38. package/src/components/Toolbar/Toolbar.scss +0 -343
  39. package/src/components/Toolbar/Toolbar.tsx +0 -84
  40. package/src/components/Toolbar/components/ApplianceButtons.tsx +0 -108
  41. package/src/components/Toolbar/components/AppsButton.tsx +0 -134
  42. package/src/components/Toolbar/components/Button.tsx +0 -45
  43. package/src/components/Toolbar/components/ColorBox.tsx +0 -55
  44. package/src/components/Toolbar/components/CutLine.tsx +0 -8
  45. package/src/components/Toolbar/components/PencilButton.tsx +0 -66
  46. package/src/components/Toolbar/components/ShapesButton.tsx +0 -135
  47. package/src/components/Toolbar/components/Slider.tsx +0 -26
  48. package/src/components/Toolbar/components/TextButton.tsx +0 -62
  49. package/src/components/Toolbar/components/UpDownButtons.tsx +0 -49
  50. package/src/components/Toolbar/components/assets/cocos.png +0 -0
  51. package/src/components/Toolbar/components/assets/collapsed.png +0 -0
  52. package/src/components/Toolbar/components/assets/countdown.png +0 -0
  53. package/src/components/Toolbar/components/assets/expanded.png +0 -0
  54. package/src/components/Toolbar/components/assets/geogebra.png +0 -0
  55. package/src/components/Toolbar/components/assets/vscode.png +0 -0
  56. package/src/components/Toolbar/const.ts +0 -32
  57. package/src/components/Toolbar/hooks.ts +0 -89
  58. package/src/components/Toolbar/icons/Apps.tsx +0 -16
  59. package/src/components/Toolbar/icons/Arrow.tsx +0 -13
  60. package/src/components/Toolbar/icons/Circle.tsx +0 -13
  61. package/src/components/Toolbar/icons/Clean.tsx +0 -16
  62. package/src/components/Toolbar/icons/Clicker.tsx +0 -19
  63. package/src/components/Toolbar/icons/Collapse.tsx +0 -13
  64. package/src/components/Toolbar/icons/Diamond.tsx +0 -13
  65. package/src/components/Toolbar/icons/Down.tsx +0 -13
  66. package/src/components/Toolbar/icons/Eraser.tsx +0 -16
  67. package/src/components/Toolbar/icons/Expand.tsx +0 -13
  68. package/src/components/Toolbar/icons/Laser.tsx +0 -21
  69. package/src/components/Toolbar/icons/Line.tsx +0 -13
  70. package/src/components/Toolbar/icons/Loading.tsx +0 -13
  71. package/src/components/Toolbar/icons/Pencil.tsx +0 -16
  72. package/src/components/Toolbar/icons/Rectangle.tsx +0 -13
  73. package/src/components/Toolbar/icons/Selector.tsx +0 -13
  74. package/src/components/Toolbar/icons/SpeechBalloon.tsx +0 -17
  75. package/src/components/Toolbar/icons/Star.tsx +0 -17
  76. package/src/components/Toolbar/icons/Text.tsx +0 -13
  77. package/src/components/Toolbar/icons/Triangle.tsx +0 -13
  78. package/src/components/Toolbar/icons/Up.tsx +0 -13
  79. package/src/components/Toolbar/icons/index.ts +0 -42
  80. package/src/components/Toolbar/index.ts +0 -2
  81. package/src/components/ZoomControl/ZoomControl.scss +0 -84
  82. package/src/components/ZoomControl/ZoomControl.tsx +0 -96
  83. package/src/components/ZoomControl/hooks.ts +0 -50
  84. package/src/components/ZoomControl/index.ts +0 -2
  85. package/src/components/hooks.ts +0 -66
  86. package/src/components/tippy-util.ts +0 -8
  87. package/src/i18n/en.json +0 -31
  88. package/src/i18n/index.ts +0 -29
  89. package/src/i18n/zh-CN.json +0 -32
  90. package/src/icons/Left.tsx +0 -15
  91. package/src/icons/Minus.tsx +0 -15
  92. package/src/icons/Plus.tsx +0 -15
  93. package/src/icons/Redo.tsx +0 -19
  94. package/src/icons/Reset.tsx +0 -17
  95. package/src/icons/Right.tsx +0 -15
  96. package/src/icons/Undo.tsx +0 -19
  97. package/src/icons/WhiteboardAdd.tsx +0 -26
  98. package/src/icons/index.tsx +0 -11
  99. package/src/index.ts +0 -12
  100. package/src/internal/helpers.ts +0 -31
  101. package/src/internal/hooks.ts +0 -23
  102. package/src/internal/index.ts +0 -2
  103. package/src/theme.ts +0 -36
  104. package/src/typings.ts +0 -15
  105. package/src/vanilla/index.tsx +0 -28
@@ -1,88 +0,0 @@
1
- import type { DependencyList } from "react";
2
- import type { Player } from "white-web-sdk";
3
-
4
- import { useCallback, useEffect, useState } from "react";
5
- import { PlayerPhase } from "white-web-sdk";
6
- import { useLastValue } from "../../internal/hooks";
7
-
8
- const EMPTY_ARRAY: DependencyList = [];
9
-
10
- function useForceUpdate() {
11
- const [, forceUpdate_] = useState({});
12
- // eslint-disable-next-line react-hooks/exhaustive-deps
13
- return useCallback(() => forceUpdate_({}), EMPTY_ARRAY);
14
- }
15
-
16
- export function usePlayerControl(player?: Player | null) {
17
- const togglePlay = useCallback(() => {
18
- if (player) {
19
- switch (player.phase) {
20
- case PlayerPhase.WaitingFirstFrame:
21
- case PlayerPhase.Pause:
22
- case PlayerPhase.Ended: {
23
- player.play();
24
- break;
25
- }
26
- case PlayerPhase.Playing: {
27
- player.pause();
28
- break;
29
- }
30
- }
31
- }
32
- }, [player]);
33
-
34
- const seekToProgressTime = useCallback(
35
- (time: number) => {
36
- if (player) {
37
- player.seekToProgressTime(time);
38
- }
39
- },
40
- [player]
41
- );
42
-
43
- const lastPlayer = useLastValue(player);
44
-
45
- const forceUpdate = useForceUpdate();
46
-
47
- const setSpeed = useCallback(
48
- (speed: number) => {
49
- if (player) {
50
- player.playbackSpeed = speed;
51
- forceUpdate();
52
- }
53
- },
54
- [forceUpdate, player]
55
- );
56
-
57
- useEffect(() => {
58
- if (!lastPlayer && player) {
59
- forceUpdate();
60
- }
61
- }, [forceUpdate, lastPlayer, player]);
62
-
63
- useEffect(() => {
64
- if (player) {
65
- player.callbacks.on("onPhaseChanged", forceUpdate);
66
- player.callbacks.on("onProgressTimeChanged", forceUpdate);
67
- return () => {
68
- player.callbacks.off("onPhaseChanged", forceUpdate);
69
- player.callbacks.off("onProgressTimeChanged", forceUpdate);
70
- };
71
- }
72
- }, [forceUpdate, player]);
73
-
74
- const phase = player ? player.phase : PlayerPhase.WaitingFirstFrame;
75
- const currentTime = player ? player.progressTime : 0;
76
- const totalTime = player ? player.timeDuration : 0;
77
- const speed = player ? player.playbackSpeed : 1;
78
-
79
- return {
80
- phase,
81
- currentTime,
82
- totalTime,
83
- speed,
84
- setSpeed,
85
- togglePlay,
86
- seekToProgressTime,
87
- };
88
- }
@@ -1,13 +0,0 @@
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 d="M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8z" fill={stroke}></path>
11
- </svg>
12
- );
13
- };
@@ -1,13 +0,0 @@
1
- import type { IconProps } from "../../../typings";
2
-
3
- import React from "react";
4
- import { getStroke } from "../../../theme";
5
-
6
- export const Pause = (props: IconProps) => {
7
- const stroke = getStroke(props);
8
- return (
9
- <svg viewBox="0 0 24 24">
10
- <path d="M14 19h4V5h-4M6 19h4V5H6v14z" fill={stroke}></path>
11
- </svg>
12
- );
13
- };
@@ -1,13 +0,0 @@
1
- import type { IconProps } from "../../../typings";
2
-
3
- import React from "react";
4
- import { getStroke } from "../../../theme";
5
-
6
- export const Play = (props: IconProps) => {
7
- const stroke = getStroke(props);
8
- return (
9
- <svg viewBox="0 0 24 24">
10
- <path d="M8 5.14v14l11-7l-11-7z" fill={stroke}></path>
11
- </svg>
12
- );
13
- };
@@ -1,10 +0,0 @@
1
- import { memo } from "react";
2
- import { Loading } from "./Loading";
3
- import { Pause } from "./Pause";
4
- import { Play } from "./Play";
5
-
6
- export const Icons = {
7
- Play: memo(Play),
8
- Pause: memo(Pause),
9
- Loading: memo(Loading),
10
- };
@@ -1,2 +0,0 @@
1
- export * from "./hooks";
2
- export { PlayerControl, type PlayerControlProps } from "./PlayerControl";
@@ -1,56 +0,0 @@
1
- $name: "fastboard-redo-undo";
2
-
3
- .#{$name} {
4
- display: inline-flex;
5
- align-items: center;
6
- gap: 4px;
7
- padding: 4px;
8
- border-radius: 4px;
9
- backdrop-filter: blur(5px);
10
- -webkit-backdrop-filter: blur(5px);
11
-
12
- &.light {
13
- color: #333;
14
- background-color: rgba(255, 255, 255, 0.9);
15
- border: 1px solid #e5e8f0;
16
- }
17
-
18
- &.dark {
19
- color: #ddd;
20
- background-color: #14181e;
21
- border: 1px solid #383b42;
22
- }
23
- }
24
-
25
- .#{$name}-btn {
26
- appearance: none;
27
- cursor: pointer;
28
- margin: 0;
29
- border: 0;
30
- padding: 0;
31
- width: 24px;
32
- height: 24px;
33
- background-color: transparent;
34
- border-radius: 4px;
35
- font-size: 24px;
36
- line-height: 1;
37
-
38
- svg,
39
- img {
40
- width: 100%;
41
- height: 100%;
42
- }
43
-
44
- &:disabled {
45
- opacity: 0.5;
46
- cursor: not-allowed;
47
- }
48
-
49
- &.light:not(:disabled):hover {
50
- background-color: #ebf2ff;
51
- }
52
-
53
- &.dark:not(:disabled):hover {
54
- background-color: #383b42;
55
- }
56
- }
@@ -1,76 +0,0 @@
1
- import type { CommonProps, GenericIcon } from "../../typings";
2
-
3
- import Tippy from "@tippyjs/react";
4
- import clsx from "clsx";
5
- import React from "react";
6
-
7
- import { useTranslation } from "../../i18n";
8
- import { Icon } from "../../icons";
9
- import { Redo } from "../../icons/Redo";
10
- import { Undo } from "../../icons/Undo";
11
- import { TopOffset } from "../../theme";
12
- import { useTheme, useWritable } from "../hooks";
13
- import { useRedoUndo } from "./hooks";
14
-
15
- export const name = "fastboard-redo-undo";
16
-
17
- export type RedoUndoProps = CommonProps & GenericIcon<"undo" | "redo">;
18
-
19
- export function RedoUndo({ theme, undoIcon, undoIconDisable, redoIcon, redoIconDisable }: RedoUndoProps) {
20
- theme = useTheme(theme);
21
- const { t } = useTranslation();
22
-
23
- const writable = useWritable();
24
- const { redoSteps, undoSteps, redo, undo } = useRedoUndo();
25
-
26
- const disabled = !writable;
27
-
28
- return (
29
- <div className={clsx(name, theme)}>
30
- <Tippy
31
- className="fastboard-tip"
32
- content={t("undo")}
33
- theme={theme}
34
- disabled={disabled}
35
- placement="top"
36
- delay={[1000, 400]}
37
- duration={300}
38
- offset={TopOffset}
39
- >
40
- <button
41
- className={clsx(`${name}-btn`, "undo", theme)}
42
- disabled={disabled || undoSteps === 0}
43
- onClick={undo}
44
- >
45
- <Icon
46
- fallback={<Undo theme={theme} />}
47
- src={undoSteps === 0 ? undoIconDisable : undoIcon}
48
- alt="[undo]"
49
- />
50
- </button>
51
- </Tippy>
52
- <Tippy
53
- className="fastboard-tip"
54
- content={t("redo")}
55
- theme={theme}
56
- disabled={disabled}
57
- placement="top"
58
- delay={[1000, 400]}
59
- duration={300}
60
- offset={TopOffset}
61
- >
62
- <button
63
- className={clsx(`${name}-btn`, "redo", theme)}
64
- disabled={disabled || redoSteps === 0}
65
- onClick={redo}
66
- >
67
- <Icon
68
- fallback={<Redo theme={theme} />}
69
- src={redoSteps === 0 ? redoIconDisable : redoIcon}
70
- alt="[redo]"
71
- />
72
- </button>
73
- </Tippy>
74
- </div>
75
- );
76
- }
@@ -1,18 +0,0 @@
1
- import { useCallback } from "react";
2
- import { useFastboardApp, useFastboardValue } from "../hooks";
3
-
4
- export function useRedoUndo() {
5
- const app = useFastboardApp();
6
- const undoSteps = useFastboardValue(app.canUndoSteps);
7
- const redoSteps = useFastboardValue(app.canRedoSteps);
8
-
9
- const undo = useCallback(() => {
10
- app.undo();
11
- }, [app]);
12
-
13
- const redo = useCallback(() => {
14
- app.redo();
15
- }, [app]);
16
-
17
- return { redoSteps, undoSteps, redo, undo };
18
- }
@@ -1,2 +0,0 @@
1
- export * from "./hooks";
2
- export { RedoUndo, type RedoUndoProps } from "./RedoUndo";
@@ -1,36 +0,0 @@
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
- );
@@ -1,89 +0,0 @@
1
- import clsx from "clsx";
2
- import React, { useCallback, useContext, useEffect, useRef, useState } from "react";
3
- import { Icon } from "../../icons";
4
-
5
- import { clamp } from "../../internal";
6
- import { CleanButton, ClickerButton, EraserButton, SelectorButton } from "./components/ApplianceButtons";
7
- import { AppsButton } from "./components/AppsButton";
8
- import { PencilButton } from "./components/PencilButton";
9
- import { ShapesButton } from "./components/ShapesButton";
10
- import { TextButton } from "./components/TextButton";
11
- import { DownButton, UpButton } from "./components/UpDownButtons";
12
- import { ItemHeight, ItemsCount, MaxHeight, MinHeight } from "./const";
13
- import { name, ToolbarContext } from "./Toolbar";
14
-
15
- import collapsePNG from "./components/assets/collapsed.png";
16
-
17
- export interface ContextProps {
18
- onCollapse: () => void;
19
- }
20
-
21
- export function Content({ onCollapse }: ContextProps) {
22
- const { theme, icons, writable } = useContext(ToolbarContext);
23
- const ref = useRef<HTMLDivElement>(null);
24
- const [scrollTop, setScrollTop] = useState(0);
25
- const [parentHeight, setParentHeight] = useState(0);
26
- const disabled = !writable;
27
-
28
- const needScroll = parentHeight < ItemHeight * ItemsCount + 48;
29
- const sectionHeight = clamp(parentHeight - 48 * (needScroll ? 3 : 1), MinHeight, MaxHeight);
30
- const scrollBuffer = Math.max(parentHeight - sectionHeight - 1, 0);
31
- const disableScrollUp = scrollTop === 0;
32
- const disableScrollDown = scrollTop === scrollBuffer;
33
-
34
- const scrollTo = useCallback(
35
- (height: number) => {
36
- setScrollTop(clamp(scrollTop + height, 0, scrollBuffer));
37
- },
38
- [scrollBuffer, scrollTop]
39
- );
40
-
41
- useEffect(() => {
42
- if (ref.current) {
43
- ref.current.scrollTop = scrollTop;
44
- }
45
- }, [scrollTop]);
46
-
47
- useEffect(() => {
48
- const container = ref.current?.parentElement?.parentElement;
49
- if (container) {
50
- const { paddingTop, paddingBottom } = getComputedStyle(container);
51
- const padding = parseInt(paddingTop) + parseInt(paddingBottom) || 0;
52
- const resizeObserver = new ResizeObserver(() => {
53
- setParentHeight(container.getBoundingClientRect().height - padding);
54
- });
55
- resizeObserver.observe(container);
56
- return () => resizeObserver.disconnect();
57
- }
58
- }, []);
59
-
60
- return (
61
- <>
62
- {needScroll && <UpButton scrollTo={scrollTo} disabled={disableScrollUp} />}
63
- <div
64
- ref={ref}
65
- className={clsx(`${name}-section`)}
66
- style={{
67
- height: `${sectionHeight}px`,
68
- overflow: needScroll ? "hidden" : "visible",
69
- }}
70
- >
71
- <ClickerButton />
72
- <SelectorButton />
73
- <PencilButton />
74
- <TextButton />
75
- <ShapesButton />
76
- <EraserButton />
77
- <CleanButton />
78
- <AppsButton />
79
- </div>
80
- {needScroll && <DownButton scrollTo={scrollTo} disabled={disableScrollDown} />}
81
- <div className={clsx("fastboard-toolbar-mask", theme)} onClick={onCollapse}>
82
- <Icon
83
- fallback={<img draggable={false} className={clsx(`${name}-mask-btn`, theme)} src={collapsePNG} />}
84
- src={disabled ? icons?.expandIconDisable : icons?.expandIcon}
85
- />
86
- </div>
87
- </>
88
- );
89
- }