@netless/fastboard-ui 1.0.0-canary.0 → 1.0.0-canary.10
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.css +888 -0
- package/dist/index.d.ts +95 -69
- package/dist/index.js +7338 -2009
- package/dist/index.mjs +7342 -2011
- package/dist/index.svelte.mjs +10001 -3775
- package/package.json +6 -3
- package/src/actions/scroll.ts +1 -1
- package/src/actions/tippy.ts +9 -5
- package/src/behaviors/apps.ts +4 -38
- package/src/components/Button/Button.svelte +4 -1
- package/src/components/Button/Button.svelte.d.ts +2 -2
- package/src/components/Fastboard/Fastboard.scss +2 -3
- package/src/components/Fastboard/Fastboard.svelte +11 -4
- package/src/components/Fastboard/{Fastboard.svelte.ts → Fastboard.svelte.d.ts} +1 -1
- package/src/components/Fastboard/ReplayFastboard.svelte +13 -3
- package/src/components/Fastboard/{ReplayFastboard.svelte.ts → ReplayFastboard.svelte.d.ts} +2 -1
- package/src/components/Icons/Curve.svelte +10 -0
- package/src/components/Icons/CurveDashed.svelte +16 -0
- package/src/components/Icons/Eraser.svelte +35 -1
- package/src/components/Icons/EraserFilled.svelte +2 -2
- package/src/components/Icons/PencilEraser.svelte +16 -0
- package/src/components/Icons/PencilEraserFilled.svelte +16 -0
- package/src/components/Icons/index.ts +11 -0
- package/src/components/PageControl/PageControl.svelte +2 -2
- package/src/components/Toolbar/README.md +1 -1
- package/src/components/Toolbar/Toolbar.scss +5 -5
- package/src/components/Toolbar/Toolbar.svelte +24 -10
- package/src/components/Toolbar/Toolbar.svelte.d.ts +18 -1
- package/src/components/Toolbar/components/Contents.scss +14 -3
- package/src/components/Toolbar/components/Contents.svelte +191 -22
- package/src/components/Toolbar/components/PencilEraserSize.svelte +27 -0
- package/src/components/Toolbar/components/Shapes.svelte +1 -0
- package/src/components/Toolbar/components/Slider.svelte +0 -1
- package/src/components/Toolbar/components/StrokeColor.svelte +1 -0
- package/src/components/Toolbar/components/TextColor.svelte +1 -0
- package/src/components/Toolbar/components/constants.ts +32 -4
- package/src/components/Toolbar/components/helper.ts +1 -1
- package/src/components/ZoomControl/ZoomControl.svelte +5 -3
- package/src/components/theme.scss +11 -4
- package/src/helpers/index.ts +72 -48
- package/src/index.ts +8 -4
- package/src/style.scss +4 -0
- package/src/typings.ts +16 -6
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/index.svelte.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netless/fastboard-ui",
|
|
3
|
-
"version": "1.0.0-canary.
|
|
3
|
+
"version": "1.0.0-canary.10",
|
|
4
4
|
"description": "The front-end of @netless/fastboard-core.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"svelte": "dist/index.svelte.mjs",
|
|
@@ -8,16 +8,19 @@
|
|
|
8
8
|
"src",
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
|
+
"sideEffects": [
|
|
12
|
+
"dist/index.css"
|
|
13
|
+
],
|
|
11
14
|
"repository": "netless-io/fastboard",
|
|
12
15
|
"peerDependencies": {
|
|
13
|
-
"@netless/fastboard-core": "1.0.0-canary.
|
|
16
|
+
"@netless/fastboard-core": "1.0.0-canary.10"
|
|
14
17
|
},
|
|
15
18
|
"dependencies": {
|
|
16
19
|
"tippy.js": "^6.3.7"
|
|
17
20
|
},
|
|
18
21
|
"devDependencies": {
|
|
19
22
|
"@netless/esbuild-plugin-inline-sass": "0.1.0",
|
|
20
|
-
"@netless/fastboard-core": "1.0.0-canary.
|
|
23
|
+
"@netless/fastboard-core": "1.0.0-canary.10"
|
|
21
24
|
},
|
|
22
25
|
"scripts": {
|
|
23
26
|
"cleanup": "rimraf dist",
|
package/src/actions/scroll.ts
CHANGED
|
@@ -10,7 +10,7 @@ export const scrollTop: SvelteAction<Writable<number>> = function (node, value)
|
|
|
10
10
|
|
|
11
11
|
function on_scroll() {
|
|
12
12
|
clearTimeout(timer);
|
|
13
|
-
timer = setTimeout(() => value.set(node.scrollTop), 200);
|
|
13
|
+
timer = window.setTimeout(() => value.set(node.scrollTop), 200);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
node.addEventListener("scroll", on_scroll);
|
package/src/actions/tippy.ts
CHANGED
|
@@ -19,7 +19,7 @@ if (is_client) {
|
|
|
19
19
|
const el = instance.popper.firstElementChild;
|
|
20
20
|
if (el) {
|
|
21
21
|
el.classList.add("fastboard-tip");
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
const extra = ((instance.props as any).className || "").trim();
|
|
24
24
|
if (extra) {
|
|
25
25
|
el.classList.add(extra);
|
|
@@ -56,10 +56,14 @@ export const tippy: SvelteAction<Partial<Props & { className: string }>> = funct
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
export function tippy_hide_all() {
|
|
59
|
-
document.querySelectorAll("[data-tippy-root]").forEach(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
document.querySelectorAll("[data-tippy-root]").forEach(tippy_hide);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function tippy_hide(el: Element) {
|
|
63
|
+
const instance = (el as unknown as { _tippy: Instance })._tippy;
|
|
64
|
+
if (instance) {
|
|
65
|
+
instance.hide();
|
|
66
|
+
}
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
export const tippy_menu: Partial<Props> = {
|
package/src/behaviors/apps.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FastboardApp } from "@netless/fastboard-core";
|
|
2
|
-
import code_editor_svg from "./icons/visual-studio-code.svg";
|
|
3
|
-
import geogebra_svg from "./icons/geogebra.svg";
|
|
4
|
-
import countdown_svg from "./icons/countdown.svg";
|
|
2
|
+
// import code_editor_svg from "./icons/visual-studio-code.svg";
|
|
3
|
+
// import geogebra_svg from "./icons/geogebra.svg";
|
|
4
|
+
// import countdown_svg from "./icons/countdown.svg";
|
|
5
5
|
|
|
6
6
|
export interface AppInToolbar {
|
|
7
7
|
kind: string;
|
|
@@ -46,38 +46,4 @@ class AppsInToolbar {
|
|
|
46
46
|
|
|
47
47
|
export type { AppsInToolbar };
|
|
48
48
|
|
|
49
|
-
export const
|
|
50
|
-
{
|
|
51
|
-
kind: "Monaco",
|
|
52
|
-
icon: code_editor_svg,
|
|
53
|
-
label: "Code Editor",
|
|
54
|
-
onClick(app) {
|
|
55
|
-
app.manager.addApp({
|
|
56
|
-
kind: "Monaco",
|
|
57
|
-
options: { title: "Code Editor" },
|
|
58
|
-
});
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
kind: "GeoGebra",
|
|
63
|
-
icon: geogebra_svg,
|
|
64
|
-
label: "GeoGebra",
|
|
65
|
-
onClick(app) {
|
|
66
|
-
app.manager.addApp({
|
|
67
|
-
kind: "GeoGebra",
|
|
68
|
-
options: { title: "GeoGebra" },
|
|
69
|
-
});
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
kind: "Countdown",
|
|
74
|
-
icon: countdown_svg,
|
|
75
|
-
label: "Countdown",
|
|
76
|
-
onClick(app) {
|
|
77
|
-
app.manager.addApp({
|
|
78
|
-
kind: "Countdown",
|
|
79
|
-
options: { title: "Countdown" },
|
|
80
|
-
});
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
]);
|
|
49
|
+
export const stockedApps = new AppsInToolbar([]);
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
export { className as class };
|
|
8
8
|
export let name = "fastboard-ui";
|
|
9
9
|
export let theme: Theme = "light";
|
|
10
|
+
export let active = false;
|
|
10
11
|
export let disabled = false;
|
|
11
12
|
export let content: Content = "";
|
|
12
13
|
export let placement: Placement = "top";
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
<span class="{name}-btn-interactive {theme}" use:tippy={{ content, placement, className }}>
|
|
20
21
|
<button
|
|
21
22
|
class="{name}-btn {className} {theme}"
|
|
23
|
+
class:is-active={active}
|
|
22
24
|
{disabled}
|
|
23
25
|
on:click
|
|
24
26
|
use:tippy={{
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
{:else}
|
|
38
40
|
<button
|
|
39
41
|
class="{name}-btn {className} {theme}"
|
|
42
|
+
class:is-active={active}
|
|
40
43
|
{disabled}
|
|
41
44
|
on:click
|
|
42
45
|
use:tippy={{ content, placement, className }}
|
|
@@ -45,7 +48,7 @@
|
|
|
45
48
|
</button>
|
|
46
49
|
{/if}
|
|
47
50
|
{:else}
|
|
48
|
-
<button class="{name}-btn {className} {theme}" {disabled} on:click>
|
|
51
|
+
<button class="{name}-btn {className} {theme}" class:is-active={active} {disabled} on:click>
|
|
49
52
|
<slot />
|
|
50
53
|
</button>
|
|
51
54
|
{/if}
|
|
@@ -6,6 +6,7 @@ export declare interface ButtonProps {
|
|
|
6
6
|
class?: string;
|
|
7
7
|
name?: string;
|
|
8
8
|
theme?: Theme;
|
|
9
|
+
active?: boolean;
|
|
9
10
|
disabled?: boolean;
|
|
10
11
|
content?: Content;
|
|
11
12
|
placement?: Placement;
|
|
@@ -18,8 +19,7 @@ export declare interface ButtonEvents {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export declare interface ButtonSlots {
|
|
21
|
-
|
|
22
|
-
default: {};
|
|
22
|
+
default: any;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
declare class Button extends SvelteComponentTyped<ButtonProps, ButtonEvents, ButtonSlots> {}
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
display: flex;
|
|
18
18
|
align-items: center;
|
|
19
19
|
position: absolute;
|
|
20
|
-
bottom:
|
|
20
|
+
bottom: 50px;
|
|
21
21
|
top: 8px;
|
|
22
22
|
left: 0;
|
|
23
23
|
z-index: 200;
|
|
24
24
|
pointer-events: none;
|
|
25
25
|
|
|
26
26
|
.fastboard-toolbar {
|
|
27
|
-
padding-left:
|
|
27
|
+
padding-left: 8px;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
position: absolute;
|
|
35
35
|
bottom: 8px;
|
|
36
36
|
left: 8px;
|
|
37
|
-
padding: 8px;
|
|
38
37
|
z-index: 200;
|
|
39
38
|
pointer-events: none;
|
|
40
39
|
}
|
|
@@ -61,10 +61,17 @@
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
});
|
|
64
|
+
|
|
65
|
+
function focus_me() {
|
|
66
|
+
tippy_hide_all();
|
|
67
|
+
// workaround for some devices that enabled "windows ink"
|
|
68
|
+
let a = document.activeElement as HTMLElement | null;
|
|
69
|
+
a && a.blur && a.blur();
|
|
70
|
+
}
|
|
64
71
|
</script>
|
|
65
72
|
|
|
66
73
|
<div class="{name}-root" class:loading={!app}>
|
|
67
|
-
<div class="{name}-view" bind:this={container} on:touchstart|capture
|
|
74
|
+
<div class="{name}-view" bind:this={container} on:touchstart|capture={focus_me} />
|
|
68
75
|
<div class="{name}-left" class:hidden={!(layout === "visible" || layout === "toolbar-only")}>
|
|
69
76
|
{#if config.toolbar?.enable !== false}
|
|
70
77
|
<Toolbar {app} {theme} {language} config={config.toolbar} />
|
|
@@ -72,15 +79,15 @@
|
|
|
72
79
|
</div>
|
|
73
80
|
<div class="{name}-bottom-left" class:hidden={layout !== "visible"}>
|
|
74
81
|
{#if config.redo_undo?.enable !== false}
|
|
75
|
-
<RedoUndo {app} {theme} {language} />
|
|
82
|
+
<RedoUndo {app} {theme} {language} icons={config.redo_undo?.icons} />
|
|
76
83
|
{/if}
|
|
77
84
|
{#if config.zoom_control?.enable !== false}
|
|
78
|
-
<ZoomControl {app} {theme} {language} />
|
|
85
|
+
<ZoomControl {app} {theme} {language} icons={config.zoom_control?.icons} />
|
|
79
86
|
{/if}
|
|
80
87
|
</div>
|
|
81
88
|
<div class="{name}-bottom-right" class:hidden={layout !== "visible"}>
|
|
82
89
|
{#if config.page_control?.enable !== false}
|
|
83
|
-
<PageControl {app} {theme} {language} />
|
|
90
|
+
<PageControl {app} {theme} {language} icons={config.page_control?.icons} />
|
|
84
91
|
{/if}
|
|
85
92
|
</div>
|
|
86
93
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FastboardApp } from "@netless/fastboard-core";
|
|
2
|
-
import type {
|
|
2
|
+
import type { FastboardUIConfig, Language, Theme } from "../../typings";
|
|
3
3
|
import { SvelteComponentTyped } from "svelte";
|
|
4
4
|
|
|
5
5
|
export declare interface FastboardProps {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<script lang="ts">
|
|
4
4
|
import type { FastboardPlayer } from "@netless/fastboard-core";
|
|
5
|
-
import type { Language, Theme } from "../../typings";
|
|
5
|
+
import type { Language, ReplayFastboardUIConfig, Theme } from "../../typings";
|
|
6
6
|
import { onMount } from "svelte";
|
|
7
7
|
import { tippy_hide_all } from "../../actions/tippy";
|
|
8
8
|
import PlayerControl from "../PlayerControl";
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
export let player: FastboardPlayer | null | undefined = null;
|
|
11
11
|
export let theme: Theme = "light";
|
|
12
12
|
export let language: Language = "en";
|
|
13
|
+
export let config: ReplayFastboardUIConfig = {};
|
|
13
14
|
export let containerRef: ((element: HTMLDivElement | null) => void) | undefined = undefined;
|
|
14
15
|
|
|
15
16
|
const name = "fastboard";
|
|
@@ -39,11 +40,20 @@
|
|
|
39
40
|
};
|
|
40
41
|
}
|
|
41
42
|
});
|
|
43
|
+
|
|
44
|
+
function focus_me() {
|
|
45
|
+
tippy_hide_all();
|
|
46
|
+
// workaround for some devices that enabled "windows ink"
|
|
47
|
+
let a = document.activeElement as HTMLElement | null;
|
|
48
|
+
a && a.blur && a.blur();
|
|
49
|
+
}
|
|
42
50
|
</script>
|
|
43
51
|
|
|
44
52
|
<div class="{name}-root" class:loading={!player}>
|
|
45
|
-
<div class="{name}-view" bind:this={container} on:touchstart|capture
|
|
53
|
+
<div class="{name}-view" bind:this={container} on:touchstart|capture={focus_me} />
|
|
46
54
|
<div class="{name}-bottom">
|
|
47
|
-
|
|
55
|
+
{#if config.player_control?.enable !== false}
|
|
56
|
+
<PlayerControl {player} {theme} {language} icons={config.player_control?.icons} />
|
|
57
|
+
{/if}
|
|
48
58
|
</div>
|
|
49
59
|
</div>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { FastboardPlayer } from "@netless/fastboard-core";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Language, ReplayFastboardUIConfig, Theme } from "../../typings";
|
|
3
3
|
import { SvelteComponentTyped } from "svelte";
|
|
4
4
|
|
|
5
5
|
export declare interface ReplayFastboardProps {
|
|
6
6
|
player?: FastboardPlayer | null;
|
|
7
7
|
theme?: Theme;
|
|
8
8
|
language?: Language;
|
|
9
|
+
config?: ReplayFastboardUIConfig;
|
|
9
10
|
containerRef?: (container: HTMLDivElement | null) => void;
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Theme } from "../../typings";
|
|
3
|
+
|
|
4
|
+
export let theme: Theme = "light";
|
|
5
|
+
export let active = false;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<svg fill="none" viewBox="0 0 24 24" class="fastboard-icon {theme}" class:is-active={active}>
|
|
9
|
+
<path stroke="#5D6066" stroke-width="1.25" d="M4 4c16 0 0 16 16 16" class="fastboard-icon-stroke-color" />
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Theme } from "../../typings";
|
|
3
|
+
|
|
4
|
+
export let theme: Theme = "light";
|
|
5
|
+
export let active = false;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<svg fill="none" viewBox="0 0 24 24" class="fastboard-icon {theme}" class:is-active={active}>
|
|
9
|
+
<path
|
|
10
|
+
stroke="#5D6066"
|
|
11
|
+
stroke-dasharray="1.25 1.25"
|
|
12
|
+
stroke-width="1.25"
|
|
13
|
+
d="M4 4c16 0 0 16 16 16"
|
|
14
|
+
class="fastboard-icon-stroke-color"
|
|
15
|
+
/>
|
|
16
|
+
</svg>
|
|
@@ -7,10 +7,44 @@
|
|
|
7
7
|
|
|
8
8
|
<svg fill="none" viewBox="0 0 24 24" class="fastboard-icon {theme}" class:is-active={active}>
|
|
9
9
|
<path
|
|
10
|
+
d="M16 16L20 20M20 16L16 20"
|
|
10
11
|
stroke="#5D6066"
|
|
12
|
+
class="fastboard-icon-stroke-color"
|
|
13
|
+
stroke-width="1.25"
|
|
14
|
+
/>
|
|
15
|
+
<path
|
|
16
|
+
d="M13.4139 4.92898C14.195 4.14794 15.4613 4.14794 16.2423 4.92898L19.0708 7.75741C19.8518 8.53846 19.8518 9.80479 19.0708 10.5858L11.9997 17.6569C10.4376 19.219 7.90494 19.219 6.34284 17.6569L4.92863 16.2427C4.14758 15.4616 4.14758 14.1953 4.92863 13.4143L13.4139 4.92898Z"
|
|
17
|
+
stroke="#5D6066"
|
|
18
|
+
class="fastboard-icon-stroke-color"
|
|
19
|
+
stroke-width="1.25"
|
|
11
20
|
stroke-linejoin="round"
|
|
21
|
+
/>
|
|
22
|
+
<path
|
|
23
|
+
d="M12 6.34314L17.6569 12"
|
|
24
|
+
stroke="#5D6066"
|
|
25
|
+
class="fastboard-icon-stroke-color"
|
|
12
26
|
stroke-width="1.25"
|
|
13
|
-
|
|
27
|
+
stroke-linejoin="round"
|
|
28
|
+
/>
|
|
29
|
+
<path
|
|
30
|
+
d="M16.2422 4.92896L13.4138 7.75738"
|
|
31
|
+
stroke="#5D6066"
|
|
14
32
|
class="fastboard-icon-stroke-color"
|
|
33
|
+
stroke-width="1.25"
|
|
34
|
+
stroke-linejoin="round"
|
|
35
|
+
/>
|
|
36
|
+
<path
|
|
37
|
+
d="M17.6572 6.34314L14.8288 9.17157"
|
|
38
|
+
stroke="#5D6066"
|
|
39
|
+
class="fastboard-icon-stroke-color"
|
|
40
|
+
stroke-width="1.25"
|
|
41
|
+
stroke-linejoin="round"
|
|
42
|
+
/>
|
|
43
|
+
<path
|
|
44
|
+
d="M19.0713 7.75732L16.2429 10.5858"
|
|
45
|
+
stroke="#5D6066"
|
|
46
|
+
class="fastboard-icon-stroke-color"
|
|
47
|
+
stroke-width="1.25"
|
|
48
|
+
stroke-linejoin="round"
|
|
15
49
|
/>
|
|
16
50
|
</svg>
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
<svg fill="none" viewBox="0 0 24 24" class="fastboard-icon {theme}" class:is-active={active}>
|
|
9
9
|
<path
|
|
10
|
-
fill="#5D6066"
|
|
11
10
|
fill-rule="evenodd"
|
|
12
|
-
d="M16.242 4.929a2 2 0 0 0-2.828 0L4.93 13.414a2 2 0 0 0 0 2.829l1.414 1.414a4 4 0 0 0 5.657 0l5.215-5.215-5.657-5.657.884-.884 5.657 5.657.972-.972a2 2 0 0 0 0-2.829l-2.83-2.827Z"
|
|
13
11
|
clip-rule="evenodd"
|
|
12
|
+
d="M16.2423 4.92893C15.4612 4.14788 14.1949 4.14788 13.4138 4.92893L4.92856 13.4142C4.14751 14.1953 4.14751 15.4616 4.92856 16.2426L6.34277 17.6568C7.90487 19.2189 10.4375 19.2189 11.9996 17.6568L17.2146 12.4419L11.5577 6.78508L12.4416 5.9012L18.0985 11.558L19.0707 10.5858C19.8517 9.80473 19.8517 8.5384 19.0707 7.75735L16.2423 4.92893ZM17.1161 18L15.5581 16.4419L16.4419 15.5581L18 17.1161L19.5581 15.5581L20.4419 16.4419L18.8839 18L20.4419 19.5581L19.5581 20.4419L18 18.8839L16.4419 20.4419L15.5581 19.5581L17.1161 18Z"
|
|
13
|
+
fill="#3381FF"
|
|
14
14
|
class="fastboard-icon-fill-color"
|
|
15
15
|
/>
|
|
16
16
|
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Theme } from "../../typings";
|
|
3
|
+
|
|
4
|
+
export let theme: Theme = "light";
|
|
5
|
+
export let active = false;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<svg fill="none" viewBox="0 0 24 24" class="fastboard-icon {theme}" class:is-active={active}>
|
|
9
|
+
<path
|
|
10
|
+
stroke="#5D6066"
|
|
11
|
+
stroke-linejoin="round"
|
|
12
|
+
stroke-width="1.25"
|
|
13
|
+
d="M13.414 4.929a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L12 17.656a4 4 0 0 1-5.657 0L4.93 16.244a2 2 0 0 1 0-2.829l8.485-8.485ZM12 6.343 17.657 12m-1.414-7.071-2.829 2.828m4.243-1.414-2.829 2.829m4.243-1.415-2.828 2.829"
|
|
14
|
+
class="fastboard-icon-stroke-color"
|
|
15
|
+
/>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Theme } from "../../typings";
|
|
3
|
+
|
|
4
|
+
export let theme: Theme = "light";
|
|
5
|
+
export let active = false;
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<svg fill="none" viewBox="0 0 24 24" class="fastboard-icon {theme}" class:is-active={active}>
|
|
9
|
+
<path
|
|
10
|
+
fill="#5D6066"
|
|
11
|
+
fill-rule="evenodd"
|
|
12
|
+
d="M16.242 4.929a2 2 0 0 0-2.828 0L4.93 13.414a2 2 0 0 0 0 2.829l1.414 1.414a4 4 0 0 0 5.657 0l5.215-5.215-5.657-5.657.884-.884 5.657 5.657.972-.972a2 2 0 0 0 0-2.829l-2.83-2.827Z"
|
|
13
|
+
clip-rule="evenodd"
|
|
14
|
+
class="fastboard-icon-fill-color"
|
|
15
|
+
/>
|
|
16
|
+
</svg>
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
|
|
1
4
|
import Apps from "./Apps.svelte";
|
|
2
5
|
import Arrow from "./Arrow.svelte";
|
|
3
6
|
import ArrowBolded from "./ArrowBolded.svelte";
|
|
@@ -18,6 +21,8 @@ import LineBolded from "./LineBolded.svelte";
|
|
|
18
21
|
import Minus from "./Minus.svelte";
|
|
19
22
|
import Pencil from "./Pencil.svelte";
|
|
20
23
|
import PencilFilled from "./PencilFilled.svelte";
|
|
24
|
+
import PencilEraser from "./PencilEraser.svelte";
|
|
25
|
+
import PencilEraserFilled from "./PencilEraserFilled.svelte";
|
|
21
26
|
import Plus from "./Plus.svelte";
|
|
22
27
|
import Rectangle from "./Rectangle.svelte";
|
|
23
28
|
import RectangleBolded from "./RectangleBolded.svelte";
|
|
@@ -41,6 +46,8 @@ import WhiteboardAdd from "./WhiteboardAdd.svelte";
|
|
|
41
46
|
import Play from "./Play.svelte";
|
|
42
47
|
import Pause from "./Pause.svelte";
|
|
43
48
|
import Loading from "./Loading.svelte";
|
|
49
|
+
import Curve from "./Curve.svelte";
|
|
50
|
+
import CurveDashed from "./CurveDashed.svelte";
|
|
44
51
|
|
|
45
52
|
const Icons = {
|
|
46
53
|
Apps,
|
|
@@ -63,6 +70,8 @@ const Icons = {
|
|
|
63
70
|
Minus,
|
|
64
71
|
Pencil,
|
|
65
72
|
PencilFilled,
|
|
73
|
+
PencilEraser,
|
|
74
|
+
PencilEraserFilled,
|
|
66
75
|
Plus,
|
|
67
76
|
Rectangle,
|
|
68
77
|
RectangleBolded,
|
|
@@ -86,6 +95,8 @@ const Icons = {
|
|
|
86
95
|
Play,
|
|
87
96
|
Pause,
|
|
88
97
|
Loading,
|
|
98
|
+
Curve,
|
|
99
|
+
CurveDashed,
|
|
89
100
|
};
|
|
90
101
|
|
|
91
102
|
export default Icons;
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
let type: IconType;
|
|
35
35
|
$: type = disabled ? "disable" : "normal";
|
|
36
36
|
|
|
37
|
-
$: index = app?.
|
|
38
|
-
$: length = app?.
|
|
37
|
+
$: index = app?.pageIndex;
|
|
38
|
+
$: length = app?.pageLength;
|
|
39
39
|
$: prev_disabled = disabled || !$index;
|
|
40
40
|
$: next_disabled = disabled || $length == null || $index === $length - 1;
|
|
41
41
|
|
|
@@ -52,6 +52,6 @@ The `computed_height` is calculated by:
|
|
|
52
52
|
|
|
53
53
|
```js
|
|
54
54
|
const max_height = button_height * 2 + scrollable_area_full_height;
|
|
55
|
-
|
|
55
|
+
const full_height = container.height;
|
|
56
56
|
computed_height = full_height < max_height ? full_height : max_height;
|
|
57
57
|
```
|
|
@@ -7,12 +7,12 @@ $name: "fastboard-toolbar";
|
|
|
7
7
|
display: flex;
|
|
8
8
|
align-items: center;
|
|
9
9
|
position: relative;
|
|
10
|
-
|
|
11
|
-
transition:
|
|
10
|
+
left: 0px;
|
|
11
|
+
transition: left 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
12
12
|
pointer-events: none;
|
|
13
13
|
|
|
14
14
|
&.collapsed {
|
|
15
|
-
|
|
15
|
+
left: -100%;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -25,7 +25,7 @@ $name: "fastboard-toolbar";
|
|
|
25
25
|
cursor: pointer;
|
|
26
26
|
pointer-events: auto;
|
|
27
27
|
|
|
28
|
-
&:focus-
|
|
28
|
+
&:focus-visible {
|
|
29
29
|
outline: 2px solid -webkit-focus-ring-color;
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -71,7 +71,7 @@ $name: "fastboard-toolbar";
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
.#{$name}-btn {
|
|
74
|
-
@include btn(32px, 4px);
|
|
74
|
+
@include btn(32px, 4px, 8px);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
@import "./components/Slider.scss";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { FastboardApp } from "@netless/fastboard-core";
|
|
3
|
-
import type { Language, Theme
|
|
3
|
+
import type { Language, Theme } from "../../typings";
|
|
4
|
+
import type { ToolbarConfig } from ".";
|
|
4
5
|
import { writable as svelte_writable } from "svelte/store";
|
|
5
6
|
import { height } from "../../actions/height";
|
|
6
7
|
import { clamp } from "../helpers";
|
|
@@ -24,7 +25,9 @@
|
|
|
24
25
|
$: computed_height = clamp($container_height, extra_height, $scroll_height + extra_height);
|
|
25
26
|
$: scrollable = $scroll_height + extra_height > $container_height;
|
|
26
27
|
|
|
28
|
+
$: hide_dotted = config.pencil?.dotted === false;
|
|
27
29
|
$: hide_apps = config.apps?.enable === false;
|
|
30
|
+
$: eraser_type = config.eraser?.behavior || "both";
|
|
28
31
|
</script>
|
|
29
32
|
|
|
30
33
|
<div class="{name} {theme}" class:collapsed use:height={container_height}>
|
|
@@ -37,25 +40,36 @@
|
|
|
37
40
|
{scroll_height}
|
|
38
41
|
{computed_height}
|
|
39
42
|
{scrollable}
|
|
43
|
+
{hide_dotted}
|
|
40
44
|
{hide_apps}
|
|
45
|
+
{eraser_type}
|
|
41
46
|
/>
|
|
42
47
|
</div>
|
|
43
48
|
<label class="{name}-handler {theme}">
|
|
44
49
|
<input type="checkbox" bind:checked={collapsed} />
|
|
45
|
-
<svg
|
|
50
|
+
<svg width="17" height="42" viewBox="0 0 17 42" fill="none">
|
|
46
51
|
<path
|
|
52
|
+
d="M0 41H12C14.2091 41 16 39.2091 16 37V5C16 2.79086 14.2091 1 12 1H0"
|
|
53
|
+
stroke="#000"
|
|
47
54
|
fill="#fff"
|
|
48
|
-
|
|
49
|
-
d="m0 0 24 16q6 4 6 14v60q0 10-6 14L0 120"
|
|
50
|
-
class="{name}-handler-bg-color"
|
|
55
|
+
class="{name}-handler-border-color {name}-handler-bg-color"
|
|
51
56
|
/>
|
|
52
|
-
<path stroke="#000" d="m0 0 24 16q6 4 6 14v60q0 10-6 14L0 120" class="{name}-handler-border-color" />
|
|
53
57
|
{#if collapsed}
|
|
54
|
-
<path
|
|
55
|
-
|
|
58
|
+
<path
|
|
59
|
+
fill-rule="evenodd"
|
|
60
|
+
clip-rule="evenodd"
|
|
61
|
+
d="M8 19L6 17V25L8 23L10 21L8 19ZM4 17H5V25H4V17Z"
|
|
62
|
+
fill="#fff"
|
|
63
|
+
class="{name}-handler-image-fill-color"
|
|
64
|
+
/>
|
|
56
65
|
{:else}
|
|
57
|
-
<path
|
|
58
|
-
|
|
66
|
+
<path
|
|
67
|
+
fill-rule="evenodd"
|
|
68
|
+
clip-rule="evenodd"
|
|
69
|
+
d="M6 19L8 17V25L6 23L4 21L6 19ZM10 17H9V25H10V17Z"
|
|
70
|
+
fill="#fff"
|
|
71
|
+
class="{name}-handler-image-fill-color"
|
|
72
|
+
/>
|
|
59
73
|
{/if}
|
|
60
74
|
</svg>
|
|
61
75
|
</label>
|
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import type { FastboardApp } from "@netless/fastboard-core";
|
|
2
|
-
import type { Theme, Language
|
|
2
|
+
import type { Theme, Language } from "../../typings";
|
|
3
3
|
import { SvelteComponentTyped } from "svelte";
|
|
4
4
|
|
|
5
|
+
export declare interface ToolbarConfig {
|
|
6
|
+
pencil?: {
|
|
7
|
+
dotted?: boolean;
|
|
8
|
+
};
|
|
9
|
+
apps?: {
|
|
10
|
+
enable?: boolean;
|
|
11
|
+
};
|
|
12
|
+
eraser?: {
|
|
13
|
+
/**
|
|
14
|
+
* - delete: remove shapes under eraser
|
|
15
|
+
* - pencil: wipe out part of strokes under eraser, like a real eraser
|
|
16
|
+
* - both (default): will show a panel to choose different behavior
|
|
17
|
+
*/
|
|
18
|
+
behavior?: "delete" | "pencil" | "both";
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
5
22
|
export declare interface ToolbarProps {
|
|
6
23
|
app?: FastboardApp | null;
|
|
7
24
|
theme?: Theme;
|
|
@@ -20,8 +20,8 @@ $name: "fastboard-toolbar";
|
|
|
20
20
|
.#{$name}-triangle {
|
|
21
21
|
width: 0px;
|
|
22
22
|
height: 0px;
|
|
23
|
-
border-bottom:
|
|
24
|
-
border-left:
|
|
23
|
+
border-bottom: 3px solid;
|
|
24
|
+
border-left: 3px solid transparent;
|
|
25
25
|
position: absolute;
|
|
26
26
|
bottom: 0;
|
|
27
27
|
right: 0;
|
|
@@ -36,7 +36,7 @@ $name: "fastboard-toolbar";
|
|
|
36
36
|
overflow: hidden;
|
|
37
37
|
display: flex;
|
|
38
38
|
flex-direction: column;
|
|
39
|
-
gap:
|
|
39
|
+
gap: 0;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
.#{$name}-tooltip {
|
|
@@ -72,6 +72,17 @@ $name: "fastboard-toolbar";
|
|
|
72
72
|
background-color: rgba(#fff, 0.15);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
.#{$name}-slider.pencil-eraser-size {
|
|
76
|
+
width: 136px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// .#{$name}-panel-btns {
|
|
80
|
+
// // min-width: 108px;
|
|
81
|
+
|
|
82
|
+
// // .#{$name}-btn {
|
|
83
|
+
// // }
|
|
84
|
+
// }
|
|
85
|
+
|
|
75
86
|
.#{$name}-colors,
|
|
76
87
|
.#{$name}-shapes {
|
|
77
88
|
display: grid;
|