@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.
- package/LICENSE.txt +1 -1
- package/dist/index.js +426 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +393 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +16 -71
- package/src/base.ts +55 -0
- package/src/core.ts +307 -0
- package/src/emitter.ts +21 -0
- package/src/index.ts +70 -24
- package/src/{behaviors/register-apps.ts → register-apps.ts} +6 -14
- package/src/utils.ts +74 -0
- package/src/value.ts +74 -0
- package/README.md +0 -134
- package/dist/index.cjs.js +0 -14
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.es.js +0 -2538
- package/dist/index.es.js.map +0 -1
- package/dist/svelte.cjs.js +0 -2
- package/dist/svelte.cjs.js.map +0 -1
- package/dist/svelte.es.js +0 -31
- package/dist/svelte.es.js.map +0 -1
- package/dist/vue.cjs.js +0 -2
- package/dist/vue.cjs.js.map +0 -1
- package/dist/vue.es.js +0 -42
- package/dist/vue.es.js.map +0 -1
- package/src/WhiteboardApp.ts +0 -80
- package/src/behaviors/style.ts +0 -17
- package/src/components/PageControl.scss +0 -80
- package/src/components/PageControl.tsx +0 -181
- package/src/components/PlayerControl/PlayerControl.scss +0 -145
- package/src/components/PlayerControl/PlayerControl.tsx +0 -158
- package/src/components/PlayerControl/components/Button.tsx +0 -55
- package/src/components/PlayerControl/hooks.ts +0 -95
- package/src/components/PlayerControl/icons/Loading.tsx +0 -13
- package/src/components/PlayerControl/icons/Pause.tsx +0 -13
- package/src/components/PlayerControl/icons/Play.tsx +0 -13
- package/src/components/PlayerControl/icons/index.ts +0 -10
- package/src/components/PlayerControl/index.ts +0 -1
- package/src/components/RedoUndo.scss +0 -56
- package/src/components/RedoUndo.tsx +0 -95
- package/src/components/Root.scss +0 -55
- package/src/components/Root.tsx +0 -61
- package/src/components/Toolbar/Content.tsx +0 -93
- package/src/components/Toolbar/Toolbar.scss +0 -247
- package/src/components/Toolbar/Toolbar.tsx +0 -82
- package/src/components/Toolbar/components/ApplianceButtons.tsx +0 -132
- package/src/components/Toolbar/components/AppsButton.tsx +0 -106
- package/src/components/Toolbar/components/Button.tsx +0 -54
- package/src/components/Toolbar/components/ColorBox.tsx +0 -56
- package/src/components/Toolbar/components/CutLine.tsx +0 -8
- package/src/components/Toolbar/components/PencilButton.tsx +0 -70
- package/src/components/Toolbar/components/ShapesButton.tsx +0 -143
- package/src/components/Toolbar/components/Slider.tsx +0 -27
- package/src/components/Toolbar/components/TextButton.tsx +0 -66
- package/src/components/Toolbar/components/UpDownButtons.tsx +0 -49
- package/src/components/Toolbar/components/assets/cocos.png +0 -0
- package/src/components/Toolbar/components/assets/countdown.png +0 -0
- package/src/components/Toolbar/components/assets/geogebra.png +0 -0
- package/src/components/Toolbar/components/assets/vscode.png +0 -0
- package/src/components/Toolbar/const.ts +0 -32
- package/src/components/Toolbar/hooks.ts +0 -113
- package/src/components/Toolbar/icons/Apps.tsx +0 -16
- package/src/components/Toolbar/icons/Arrow.tsx +0 -16
- package/src/components/Toolbar/icons/Circle.tsx +0 -21
- package/src/components/Toolbar/icons/Clean.tsx +0 -16
- package/src/components/Toolbar/icons/Clicker.tsx +0 -19
- package/src/components/Toolbar/icons/Collapse.tsx +0 -17
- package/src/components/Toolbar/icons/Diamond.tsx +0 -17
- package/src/components/Toolbar/icons/Down.tsx +0 -17
- package/src/components/Toolbar/icons/Eraser.tsx +0 -16
- package/src/components/Toolbar/icons/Expand.tsx +0 -17
- package/src/components/Toolbar/icons/Line.tsx +0 -13
- package/src/components/Toolbar/icons/Pencil.tsx +0 -16
- package/src/components/Toolbar/icons/Rectangle.tsx +0 -13
- package/src/components/Toolbar/icons/Selector.tsx +0 -16
- package/src/components/Toolbar/icons/SpeechBalloon.tsx +0 -17
- package/src/components/Toolbar/icons/Star.tsx +0 -17
- package/src/components/Toolbar/icons/Text.tsx +0 -16
- package/src/components/Toolbar/icons/Triangle.tsx +0 -17
- package/src/components/Toolbar/icons/Up.tsx +0 -17
- package/src/components/Toolbar/icons/index.ts +0 -42
- package/src/components/Toolbar/index.ts +0 -1
- package/src/components/ZoomControl.scss +0 -80
- package/src/components/ZoomControl.tsx +0 -221
- package/src/hooks.ts +0 -53
- package/src/i18n/en.json +0 -31
- package/src/i18n/index.ts +0 -22
- package/src/i18n/zh-CN.json +0 -32
- package/src/icons/ChevronLeft.tsx +0 -21
- package/src/icons/ChevronRight.tsx +0 -21
- package/src/icons/FilePlus.tsx +0 -18
- package/src/icons/Minus.tsx +0 -21
- package/src/icons/Plus.tsx +0 -21
- package/src/icons/Redo.tsx +0 -24
- package/src/icons/Reset.tsx +0 -23
- package/src/icons/Undo.tsx +0 -24
- package/src/icons/index.tsx +0 -11
- package/src/internal/Instance.tsx +0 -251
- package/src/internal/helpers.ts +0 -42
- package/src/internal/index.ts +0 -3
- package/src/internal/mount-whiteboard.ts +0 -90
- package/src/style.scss +0 -29
- package/src/svelte.ts +0 -45
- package/src/theme/index.ts +0 -36
- package/src/types/index.ts +0 -22
- package/src/vue.ts +0 -74
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import type { CommonProps, GenericIcon, Theme } from "../../types";
|
|
2
|
-
import type { i18n } from "i18next";
|
|
3
|
-
|
|
4
|
-
import clsx from "clsx";
|
|
5
|
-
import React, { createContext, useCallback, useState } from "react";
|
|
6
|
-
|
|
7
|
-
import { Icon } from "../../icons";
|
|
8
|
-
import { Icons } from "./icons";
|
|
9
|
-
import { Button } from "./components/Button";
|
|
10
|
-
import { CutLine } from "./components/CutLine";
|
|
11
|
-
import { EmptyToolbarHook, useToolbar, type ToolbarHook } from "./hooks";
|
|
12
|
-
import { Content } from "./Content";
|
|
13
|
-
|
|
14
|
-
export type ToolbarProps = CommonProps & {
|
|
15
|
-
icons?: GenericIcon<
|
|
16
|
-
| "clicker"
|
|
17
|
-
| "selector"
|
|
18
|
-
| "pencil"
|
|
19
|
-
| "eraser"
|
|
20
|
-
| "clean"
|
|
21
|
-
| "expand"
|
|
22
|
-
| "collapse"
|
|
23
|
-
| "up"
|
|
24
|
-
| "down"
|
|
25
|
-
| "text"
|
|
26
|
-
| "apps"
|
|
27
|
-
>;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
type ToolbarContextType = ToolbarHook & {
|
|
31
|
-
theme: Theme;
|
|
32
|
-
icons?: ToolbarProps["icons"];
|
|
33
|
-
i18n?: i18n | null;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export const ToolbarContext = createContext<ToolbarContextType>({
|
|
37
|
-
theme: "light",
|
|
38
|
-
...EmptyToolbarHook,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
export const name = "fastboard-toolbar";
|
|
42
|
-
|
|
43
|
-
export const Toolbar = ({
|
|
44
|
-
theme = "light",
|
|
45
|
-
icons,
|
|
46
|
-
room,
|
|
47
|
-
i18n,
|
|
48
|
-
}: ToolbarProps) => {
|
|
49
|
-
const [expanded, setExpanded] = useState(true);
|
|
50
|
-
const hook = useToolbar(room);
|
|
51
|
-
const toggle = useCallback(() => setExpanded(e => !e), []);
|
|
52
|
-
|
|
53
|
-
const disabled = !hook.writable;
|
|
54
|
-
|
|
55
|
-
return (
|
|
56
|
-
<ToolbarContext.Provider value={{ theme, icons, ...hook, i18n }}>
|
|
57
|
-
<div className={clsx(name, theme)}>
|
|
58
|
-
{expanded ? (
|
|
59
|
-
<Button content={i18n?.t("collapse")} onClick={toggle}>
|
|
60
|
-
<Icon
|
|
61
|
-
fallback={<Icons.Collapse theme={theme} />}
|
|
62
|
-
src={disabled ? icons?.collapseIconDisable : icons?.collapseIcon}
|
|
63
|
-
/>
|
|
64
|
-
</Button>
|
|
65
|
-
) : (
|
|
66
|
-
<Button content={i18n?.t("expand")} onClick={toggle}>
|
|
67
|
-
<Icon
|
|
68
|
-
fallback={<Icons.Expand theme={theme} />}
|
|
69
|
-
src={disabled ? icons?.expandIconDisable : icons?.expandIcon}
|
|
70
|
-
/>
|
|
71
|
-
</Button>
|
|
72
|
-
)}
|
|
73
|
-
{expanded && (
|
|
74
|
-
<>
|
|
75
|
-
<CutLine />
|
|
76
|
-
<Content />
|
|
77
|
-
</>
|
|
78
|
-
)}
|
|
79
|
-
</div>
|
|
80
|
-
</ToolbarContext.Provider>
|
|
81
|
-
);
|
|
82
|
-
};
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import type { HotKey } from "white-web-sdk";
|
|
2
|
-
|
|
3
|
-
import React, { useCallback, useContext } from "react";
|
|
4
|
-
import { ApplianceNames } from "white-web-sdk";
|
|
5
|
-
|
|
6
|
-
import { defaultHotKeys, useInstance } from "../../../internal";
|
|
7
|
-
import { Icon } from "../../../icons";
|
|
8
|
-
import { Icons } from "../icons";
|
|
9
|
-
import { ToolbarContext } from "../Toolbar";
|
|
10
|
-
import { Button } from "./Button";
|
|
11
|
-
|
|
12
|
-
export function renderToolTip(text: string | undefined, hotkey?: HotKey) {
|
|
13
|
-
if (!(typeof hotkey === "string")) return text;
|
|
14
|
-
return (
|
|
15
|
-
<span className="fastboard-toolbar-tooltip">
|
|
16
|
-
<span>{text}</span>
|
|
17
|
-
<span className="fastboard-toolbar-hotkey">{hotkey.toUpperCase()}</span>
|
|
18
|
-
</span>
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function ClickerButton() {
|
|
23
|
-
const app = useInstance();
|
|
24
|
-
|
|
25
|
-
const { theme, icons, writable, setAppliance, memberState, i18n } =
|
|
26
|
-
useContext(ToolbarContext);
|
|
27
|
-
|
|
28
|
-
const changeAppliance = useCallback(
|
|
29
|
-
() => setAppliance(ApplianceNames.clicker),
|
|
30
|
-
[setAppliance]
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
const shortcut = app?.config.joinRoom.hotKeys?.changeToClick;
|
|
34
|
-
const appliance = memberState?.currentApplianceName;
|
|
35
|
-
const active = appliance === ApplianceNames.clicker;
|
|
36
|
-
const disabled = !writable;
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<Button
|
|
40
|
-
content={renderToolTip(i18n?.t("clicker"), shortcut)}
|
|
41
|
-
onClick={changeAppliance}
|
|
42
|
-
active={active}
|
|
43
|
-
>
|
|
44
|
-
<Icon
|
|
45
|
-
fallback={<Icons.Clicker theme={theme} active={active} />}
|
|
46
|
-
src={disabled ? icons?.clickerIconDisable : icons?.clickerIcon}
|
|
47
|
-
alt="[clicker]"
|
|
48
|
-
/>
|
|
49
|
-
</Button>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function SelectorButton() {
|
|
54
|
-
const app = useInstance();
|
|
55
|
-
|
|
56
|
-
const { theme, icons, writable, setAppliance, memberState, i18n } =
|
|
57
|
-
useContext(ToolbarContext);
|
|
58
|
-
|
|
59
|
-
const changeAppliance = useCallback(
|
|
60
|
-
() => setAppliance(ApplianceNames.selector),
|
|
61
|
-
[setAppliance]
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const appliance = memberState?.currentApplianceName;
|
|
65
|
-
const active = appliance === ApplianceNames.selector;
|
|
66
|
-
const disabled = !writable;
|
|
67
|
-
const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)
|
|
68
|
-
.changeToSelector;
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<Button
|
|
72
|
-
content={renderToolTip(i18n?.t("selector"), shortcut)}
|
|
73
|
-
onClick={changeAppliance}
|
|
74
|
-
active={active}
|
|
75
|
-
>
|
|
76
|
-
<Icon
|
|
77
|
-
fallback={<Icons.Selector theme={theme} active={active} />}
|
|
78
|
-
src={disabled ? icons?.selectorIconDisable : icons?.selectorIcon}
|
|
79
|
-
alt="[selector]"
|
|
80
|
-
/>
|
|
81
|
-
</Button>
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function EraserButton() {
|
|
86
|
-
const app = useInstance();
|
|
87
|
-
|
|
88
|
-
const { theme, icons, writable, setAppliance, memberState, i18n } =
|
|
89
|
-
useContext(ToolbarContext);
|
|
90
|
-
|
|
91
|
-
const changeAppliance = useCallback(
|
|
92
|
-
() => setAppliance(ApplianceNames.eraser),
|
|
93
|
-
[setAppliance]
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
const appliance = memberState?.currentApplianceName;
|
|
97
|
-
const active = appliance === ApplianceNames.eraser;
|
|
98
|
-
const disabled = !writable;
|
|
99
|
-
const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)
|
|
100
|
-
.changeToEraser;
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<Button
|
|
104
|
-
content={renderToolTip(i18n?.t("eraser"), shortcut)}
|
|
105
|
-
onClick={changeAppliance}
|
|
106
|
-
active={active}
|
|
107
|
-
>
|
|
108
|
-
<Icon
|
|
109
|
-
fallback={<Icons.Eraser theme={theme} active={active} />}
|
|
110
|
-
src={disabled ? icons?.eraserIconDisable : icons?.eraserIcon}
|
|
111
|
-
alt="[eraser]"
|
|
112
|
-
/>
|
|
113
|
-
</Button>
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function CleanButton() {
|
|
118
|
-
const { theme, icons, writable, cleanCurrentScene, i18n } =
|
|
119
|
-
useContext(ToolbarContext);
|
|
120
|
-
|
|
121
|
-
const disabled = !writable;
|
|
122
|
-
|
|
123
|
-
return (
|
|
124
|
-
<Button content={i18n?.t("clean")} onClick={cleanCurrentScene}>
|
|
125
|
-
<Icon
|
|
126
|
-
fallback={<Icons.Clean theme={theme} />}
|
|
127
|
-
src={disabled ? icons?.cleanIconDisable : icons?.cleanIcon}
|
|
128
|
-
alt="[clean]"
|
|
129
|
-
/>
|
|
130
|
-
</Button>
|
|
131
|
-
);
|
|
132
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import Tippy from "@tippyjs/react";
|
|
2
|
-
import React, { useContext } from "react";
|
|
3
|
-
|
|
4
|
-
import vscodePNG from "./assets/vscode.png";
|
|
5
|
-
import geogebraPNG from "./assets/geogebra.png";
|
|
6
|
-
import countdownPNG from "./assets/countdown.png";
|
|
7
|
-
|
|
8
|
-
import { useInstance } from "../../../internal";
|
|
9
|
-
import { Icon } from "../../../icons";
|
|
10
|
-
import { RightOffset } from "../../../theme";
|
|
11
|
-
import { Icons } from "../icons";
|
|
12
|
-
import { ToolbarContext } from "../Toolbar";
|
|
13
|
-
import { Button } from "./Button";
|
|
14
|
-
|
|
15
|
-
export interface AppsButtonProps {
|
|
16
|
-
content?: React.ReactNode;
|
|
17
|
-
onClick?: () => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function AppsButton({ content, onClick }: AppsButtonProps) {
|
|
21
|
-
const { theme, icons, writable } = useContext(ToolbarContext);
|
|
22
|
-
|
|
23
|
-
const disabled = !writable;
|
|
24
|
-
|
|
25
|
-
const button = (
|
|
26
|
-
<Button content="Apps" onClick={onClick}>
|
|
27
|
-
<Icon
|
|
28
|
-
fallback={<Icons.Apps theme={theme} />}
|
|
29
|
-
src={disabled ? icons?.appsIconDisable : icons?.appsIcon}
|
|
30
|
-
alt="[apps]"
|
|
31
|
-
/>
|
|
32
|
-
</Button>
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
return content === false ? (
|
|
36
|
-
button
|
|
37
|
-
) : (
|
|
38
|
-
<span className="fastboard-toolbar-btn-interactive">
|
|
39
|
-
<Tippy
|
|
40
|
-
className="fastboard-tip"
|
|
41
|
-
content={renderAppsButtonContent(content)}
|
|
42
|
-
theme={theme}
|
|
43
|
-
placement="right-end"
|
|
44
|
-
trigger="click"
|
|
45
|
-
offset={RightOffset}
|
|
46
|
-
arrow={false}
|
|
47
|
-
interactive
|
|
48
|
-
>
|
|
49
|
-
{button}
|
|
50
|
-
</Tippy>
|
|
51
|
-
</span>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function renderAppsButtonContent(content?: React.ReactNode) {
|
|
56
|
-
return (
|
|
57
|
-
<div className="fastboard-toolbar-panel apps">
|
|
58
|
-
<div className="fastboard-toolbar-apps">{content || <DefaultApps />}</div>
|
|
59
|
-
</div>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function DefaultApps() {
|
|
64
|
-
const app = useInstance();
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<>
|
|
68
|
-
<AppIcon
|
|
69
|
-
title="Code Editor"
|
|
70
|
-
src={vscodePNG}
|
|
71
|
-
alt="[code editor]"
|
|
72
|
-
onClick={app?.insertCodeEditor.bind(app)}
|
|
73
|
-
/>
|
|
74
|
-
<AppIcon
|
|
75
|
-
title="GeoGebra"
|
|
76
|
-
src={geogebraPNG}
|
|
77
|
-
alt="[geogebra]"
|
|
78
|
-
onClick={app?.insertGeoGebra.bind(app)}
|
|
79
|
-
/>
|
|
80
|
-
<AppIcon
|
|
81
|
-
title="Countdown"
|
|
82
|
-
src={countdownPNG}
|
|
83
|
-
alt="[countdown]"
|
|
84
|
-
onClick={app?.insertCountdown.bind(app)}
|
|
85
|
-
/>
|
|
86
|
-
</>
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
interface AppIconProps {
|
|
91
|
-
title: string;
|
|
92
|
-
src: string;
|
|
93
|
-
alt: string;
|
|
94
|
-
onClick?: () => void;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function AppIcon({ title, src, alt, onClick }: AppIconProps) {
|
|
98
|
-
return (
|
|
99
|
-
<span className="fastboard-toolbar-app-icon">
|
|
100
|
-
<Button placement="top" content={title} onClick={onClick}>
|
|
101
|
-
<img src={src} alt={alt} title={title} />
|
|
102
|
-
</Button>
|
|
103
|
-
<span className="fastboard-toolbar-app-icon-text">{title}</span>
|
|
104
|
-
</span>
|
|
105
|
-
);
|
|
106
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { Placement } from "tippy.js";
|
|
2
|
-
|
|
3
|
-
import clsx from "clsx";
|
|
4
|
-
import React, { forwardRef, useContext, type PropsWithChildren } from "react";
|
|
5
|
-
import Tippy from "@tippyjs/react";
|
|
6
|
-
|
|
7
|
-
import { RightOffset } from "../../../theme";
|
|
8
|
-
import { ToolbarContext } from "../Toolbar";
|
|
9
|
-
|
|
10
|
-
type ButtonProps = PropsWithChildren<{
|
|
11
|
-
content: React.ReactNode;
|
|
12
|
-
disabled?: boolean;
|
|
13
|
-
active?: boolean;
|
|
14
|
-
onClick?: () => void;
|
|
15
|
-
interactive?: boolean;
|
|
16
|
-
placement?: Placement;
|
|
17
|
-
}>;
|
|
18
|
-
|
|
19
|
-
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
20
|
-
(props, ref) => {
|
|
21
|
-
const {
|
|
22
|
-
content,
|
|
23
|
-
disabled,
|
|
24
|
-
active,
|
|
25
|
-
onClick,
|
|
26
|
-
interactive,
|
|
27
|
-
placement = "right",
|
|
28
|
-
children,
|
|
29
|
-
} = props;
|
|
30
|
-
const { writable, theme } = useContext(ToolbarContext);
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<Tippy
|
|
34
|
-
className="fastboard-tip"
|
|
35
|
-
content={content}
|
|
36
|
-
interactive={interactive}
|
|
37
|
-
theme={theme}
|
|
38
|
-
disabled={disabled || !writable}
|
|
39
|
-
placement={placement}
|
|
40
|
-
offset={placement.includes("right") ? RightOffset : undefined}
|
|
41
|
-
duration={300}
|
|
42
|
-
>
|
|
43
|
-
<button
|
|
44
|
-
ref={ref}
|
|
45
|
-
className={clsx("fastboard-toolbar-btn", theme, { active })}
|
|
46
|
-
onClick={onClick}
|
|
47
|
-
disabled={disabled || !writable}
|
|
48
|
-
>
|
|
49
|
-
{children}
|
|
50
|
-
</button>
|
|
51
|
-
</Tippy>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
);
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import type { Color } from "white-web-sdk";
|
|
2
|
-
|
|
3
|
-
import clsx from "clsx";
|
|
4
|
-
import React, { useContext } from "react";
|
|
5
|
-
|
|
6
|
-
import { isEqualArray } from "../../../internal";
|
|
7
|
-
import { ToolbarContext } from "../Toolbar";
|
|
8
|
-
|
|
9
|
-
const colors: Record<string, Color> = {
|
|
10
|
-
"#E02020": [224, 32, 32],
|
|
11
|
-
"#F7B500": [247, 181, 0],
|
|
12
|
-
"#6DD400": [109, 212, 0],
|
|
13
|
-
"#32C5FF": [50, 197, 255],
|
|
14
|
-
"#0091FF": [0, 145, 255],
|
|
15
|
-
"#6236FF": [98, 54, 255],
|
|
16
|
-
"#B620E0": [182, 32, 224],
|
|
17
|
-
"#6D7278": [109, 114, 120],
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const colorKeys = Object.keys(colors);
|
|
21
|
-
|
|
22
|
-
export function ColorBox() {
|
|
23
|
-
const { theme, memberState, setStrokeColor, writable } =
|
|
24
|
-
useContext(ToolbarContext);
|
|
25
|
-
|
|
26
|
-
const strokeColor = memberState?.strokeColor;
|
|
27
|
-
const disabled = !writable;
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div className={clsx("fastboard-toolbar-color-box", theme)}>
|
|
31
|
-
{colorKeys.map((key: string) => (
|
|
32
|
-
<div
|
|
33
|
-
key={key}
|
|
34
|
-
className={clsx("fastboard-toolbar-color-item", theme)}
|
|
35
|
-
onClick={() => setStrokeColor(colors[key])}
|
|
36
|
-
>
|
|
37
|
-
<div
|
|
38
|
-
className={clsx("fastboard-toolbar-color-border", theme, {
|
|
39
|
-
active: strokeColor && isEqualArray(strokeColor, colors[key]),
|
|
40
|
-
})}
|
|
41
|
-
>
|
|
42
|
-
<button
|
|
43
|
-
className={clsx("fastboard-toolbar-color-btn")}
|
|
44
|
-
style={{ background: key }}
|
|
45
|
-
disabled={disabled}
|
|
46
|
-
onClick={ev => {
|
|
47
|
-
ev.stopPropagation();
|
|
48
|
-
setStrokeColor(colors[key]);
|
|
49
|
-
}}
|
|
50
|
-
/>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
))}
|
|
54
|
-
</div>
|
|
55
|
-
);
|
|
56
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import clsx from "clsx";
|
|
2
|
-
import React, { useContext } from "react";
|
|
3
|
-
import { ToolbarContext, name } from "../Toolbar";
|
|
4
|
-
|
|
5
|
-
export function CutLine() {
|
|
6
|
-
const { theme } = useContext(ToolbarContext);
|
|
7
|
-
return <span className={clsx(`${name}-cut-line`, theme)} />;
|
|
8
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import Tippy from "@tippyjs/react";
|
|
2
|
-
import React, { useCallback } from "react";
|
|
3
|
-
import { useContext } from "react";
|
|
4
|
-
import { ApplianceNames } from "white-web-sdk";
|
|
5
|
-
|
|
6
|
-
import { defaultHotKeys, useInstance } from "../../../internal";
|
|
7
|
-
import { Icon } from "../../../icons";
|
|
8
|
-
import { RightOffset } from "../../../theme";
|
|
9
|
-
import { Icons } from "../icons";
|
|
10
|
-
import { ToolbarContext } from "../Toolbar";
|
|
11
|
-
import { Button } from "./Button";
|
|
12
|
-
import { ColorBox } from "./ColorBox";
|
|
13
|
-
import { CutLine } from "./CutLine";
|
|
14
|
-
import { Slider } from "./Slider";
|
|
15
|
-
import { renderToolTip } from "./ApplianceButtons";
|
|
16
|
-
|
|
17
|
-
export function PencilButton() {
|
|
18
|
-
const app = useInstance();
|
|
19
|
-
|
|
20
|
-
const { theme, icons, writable, setAppliance, memberState, i18n } =
|
|
21
|
-
useContext(ToolbarContext);
|
|
22
|
-
|
|
23
|
-
const changeAppliance = useCallback(() => {
|
|
24
|
-
setAppliance(ApplianceNames.pencil);
|
|
25
|
-
}, [setAppliance]);
|
|
26
|
-
|
|
27
|
-
const appliance = memberState?.currentApplianceName;
|
|
28
|
-
const active = appliance === ApplianceNames.pencil;
|
|
29
|
-
const disabled = !writable;
|
|
30
|
-
const shortcut = (app?.config.joinRoom.hotKeys || defaultHotKeys)
|
|
31
|
-
.changeToPencil;
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<span className="fastboard-toolbar-btn-interactive">
|
|
35
|
-
<Tippy
|
|
36
|
-
className="fastboard-tip"
|
|
37
|
-
content={renderPencilButtonContent()}
|
|
38
|
-
theme={theme}
|
|
39
|
-
placement="right-start"
|
|
40
|
-
trigger="click"
|
|
41
|
-
offset={RightOffset}
|
|
42
|
-
arrow={false}
|
|
43
|
-
interactive
|
|
44
|
-
>
|
|
45
|
-
<Button
|
|
46
|
-
content={renderToolTip(i18n?.t("pencil"), shortcut)}
|
|
47
|
-
active={active}
|
|
48
|
-
onClick={changeAppliance}
|
|
49
|
-
>
|
|
50
|
-
<Icon
|
|
51
|
-
fallback={<Icons.Pencil theme={theme} active={active} />}
|
|
52
|
-
src={disabled ? icons?.pencilIconDisable : icons?.pencilIcon}
|
|
53
|
-
alt="[pencil]"
|
|
54
|
-
/>
|
|
55
|
-
<span className="fastboard-toolbar-triangle" />
|
|
56
|
-
</Button>
|
|
57
|
-
</Tippy>
|
|
58
|
-
</span>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function renderPencilButtonContent() {
|
|
63
|
-
return (
|
|
64
|
-
<div className="fastboard-toolbar-panel pencil">
|
|
65
|
-
<Slider />
|
|
66
|
-
<CutLine />
|
|
67
|
-
<ColorBox />
|
|
68
|
-
</div>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import type { IconProps } from "../../../types";
|
|
2
|
-
|
|
3
|
-
import Tippy from "@tippyjs/react";
|
|
4
|
-
import React, { useContext } from "react";
|
|
5
|
-
import type { ShapeType } from "white-web-sdk";
|
|
6
|
-
import { ApplianceNames } from "white-web-sdk";
|
|
7
|
-
|
|
8
|
-
import { RightOffset } from "../../../theme";
|
|
9
|
-
import { ApplianceShapes, Shapes, ShapesMap } from "../const";
|
|
10
|
-
import { Icons } from "../icons";
|
|
11
|
-
import { ToolbarContext } from "../Toolbar";
|
|
12
|
-
import { Button } from "./Button";
|
|
13
|
-
import { CutLine } from "./CutLine";
|
|
14
|
-
import { Slider } from "./Slider";
|
|
15
|
-
import { ColorBox } from "./ColorBox";
|
|
16
|
-
|
|
17
|
-
const ShapeTypes = new Set([...ApplianceShapes, ...Shapes]);
|
|
18
|
-
|
|
19
|
-
export function ShapesButton() {
|
|
20
|
-
const { theme, memberState, i18n } = useContext(ToolbarContext);
|
|
21
|
-
|
|
22
|
-
const appliance = memberState?.currentApplianceName;
|
|
23
|
-
const shape = memberState?.shapeType;
|
|
24
|
-
|
|
25
|
-
const key = (
|
|
26
|
-
appliance === ApplianceNames.shape ? shape : appliance
|
|
27
|
-
) as keyof typeof ShapesMap;
|
|
28
|
-
|
|
29
|
-
const active = ShapeTypes.has(key);
|
|
30
|
-
|
|
31
|
-
const CurrentIcon = ShapesMap[key] || Icons.Rectangle;
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<span className="fastboard-toolbar-btn-interactive">
|
|
35
|
-
<Tippy
|
|
36
|
-
className="fastboard-tip"
|
|
37
|
-
content={renderShapesButtonContent()}
|
|
38
|
-
theme={theme}
|
|
39
|
-
placement="right-start"
|
|
40
|
-
trigger="click"
|
|
41
|
-
offset={RightOffset}
|
|
42
|
-
arrow={false}
|
|
43
|
-
interactive
|
|
44
|
-
>
|
|
45
|
-
<Button content={i18n?.t("shape")} active={active}>
|
|
46
|
-
<CurrentIcon theme={theme} active={active} />
|
|
47
|
-
<span className="fastboard-toolbar-triangle" />
|
|
48
|
-
</Button>
|
|
49
|
-
</Tippy>
|
|
50
|
-
</span>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function renderShapesButtonContent() {
|
|
55
|
-
return (
|
|
56
|
-
<div className="fastboard-toolbar-panel shapes">
|
|
57
|
-
<ShapesBox />
|
|
58
|
-
<CutLine />
|
|
59
|
-
<Slider />
|
|
60
|
-
<CutLine />
|
|
61
|
-
<ColorBox />
|
|
62
|
-
</div>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function ShapesBox() {
|
|
67
|
-
const { i18n } = useContext(ToolbarContext);
|
|
68
|
-
return (
|
|
69
|
-
<div className="fastboard-toolbar-shapes">
|
|
70
|
-
{ApplianceShapes.map(Appliance => (
|
|
71
|
-
<ApplianceShapeButton
|
|
72
|
-
key={Appliance}
|
|
73
|
-
content={i18n?.t(Appliance)}
|
|
74
|
-
Appliance={Appliance}
|
|
75
|
-
Icon={ShapesMap[Appliance]}
|
|
76
|
-
/>
|
|
77
|
-
))}
|
|
78
|
-
{Shapes.map(shape => (
|
|
79
|
-
<ShapeShapeButton
|
|
80
|
-
key={shape}
|
|
81
|
-
content={i18n?.t(shape)}
|
|
82
|
-
shape={shape}
|
|
83
|
-
Icon={ShapesMap[shape]}
|
|
84
|
-
/>
|
|
85
|
-
))}
|
|
86
|
-
</div>
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
interface ApplianceShapeButtonProps {
|
|
91
|
-
content?: string;
|
|
92
|
-
Appliance: ApplianceNames;
|
|
93
|
-
Icon: React.ComponentType<IconProps>;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function ApplianceShapeButton({
|
|
97
|
-
content,
|
|
98
|
-
Appliance,
|
|
99
|
-
Icon,
|
|
100
|
-
}: ApplianceShapeButtonProps) {
|
|
101
|
-
const { theme, writable, setAppliance, memberState } =
|
|
102
|
-
useContext(ToolbarContext);
|
|
103
|
-
|
|
104
|
-
const current = memberState?.currentApplianceName;
|
|
105
|
-
const disabled = !writable;
|
|
106
|
-
|
|
107
|
-
return (
|
|
108
|
-
<Button
|
|
109
|
-
content={content}
|
|
110
|
-
disabled={disabled}
|
|
111
|
-
placement="top"
|
|
112
|
-
onClick={() => setAppliance(Appliance)}
|
|
113
|
-
>
|
|
114
|
-
<Icon theme={theme} active={current === Appliance} />
|
|
115
|
-
</Button>
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
interface ShapeShapeButtonProps {
|
|
120
|
-
content?: string;
|
|
121
|
-
shape: ShapeType;
|
|
122
|
-
Icon: React.ComponentType<IconProps>;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function ShapeShapeButton({ content, shape, Icon }: ShapeShapeButtonProps) {
|
|
126
|
-
const { theme, writable, setAppliance, memberState } =
|
|
127
|
-
useContext(ToolbarContext);
|
|
128
|
-
|
|
129
|
-
const appliance = memberState?.currentApplianceName;
|
|
130
|
-
const current = appliance === ApplianceNames.shape && memberState?.shapeType;
|
|
131
|
-
const disabled = !writable;
|
|
132
|
-
|
|
133
|
-
return (
|
|
134
|
-
<Button
|
|
135
|
-
content={content}
|
|
136
|
-
disabled={disabled}
|
|
137
|
-
placement="top"
|
|
138
|
-
onClick={() => setAppliance(ApplianceNames.shape, shape)}
|
|
139
|
-
>
|
|
140
|
-
<Icon theme={theme} active={current === shape} />
|
|
141
|
-
</Button>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import clsx from "clsx";
|
|
2
|
-
import RcSlider from "rc-slider";
|
|
3
|
-
import React, { useContext } from "react";
|
|
4
|
-
|
|
5
|
-
import { themes } from "../../../theme";
|
|
6
|
-
import { ToolbarContext } from "../Toolbar";
|
|
7
|
-
|
|
8
|
-
export function Slider() {
|
|
9
|
-
const { theme, writable, memberState, setStrokeWidth } =
|
|
10
|
-
useContext(ToolbarContext);
|
|
11
|
-
const { activeColor } = themes[theme];
|
|
12
|
-
|
|
13
|
-
const strokeWidth = memberState?.strokeWidth || 0;
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<RcSlider
|
|
17
|
-
disabled={!writable}
|
|
18
|
-
className={clsx("fastboard-toolbar-slider", theme)}
|
|
19
|
-
trackStyle={{ background: activeColor }}
|
|
20
|
-
handleStyle={{ border: `1px solid ${activeColor}` }}
|
|
21
|
-
value={strokeWidth}
|
|
22
|
-
onChange={setStrokeWidth}
|
|
23
|
-
min={1}
|
|
24
|
-
max={32}
|
|
25
|
-
/>
|
|
26
|
-
);
|
|
27
|
-
}
|