@netless/fastboard-ui 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 (111) hide show
  1. package/LICENSE.txt +21 -0
  2. package/README.md +7 -0
  3. package/dist/index.d.ts +92 -0
  4. package/dist/index.js +10143 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +10114 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/dist/index.svelte.mjs +10368 -0
  9. package/dist/index.svelte.mjs.map +1 -0
  10. package/package.json +31 -0
  11. package/src/actions/height.ts +43 -0
  12. package/src/actions/scroll.ts +31 -0
  13. package/src/actions/tippy.ts +70 -0
  14. package/src/behaviors/icons/countdown.svg +1 -0
  15. package/src/behaviors/icons/geogebra.svg +1 -0
  16. package/src/behaviors/icons/visual-studio-code.svg +1 -0
  17. package/src/behaviors/index.ts +68 -0
  18. package/src/components/Button/Button.svelte +51 -0
  19. package/src/components/Button/Button.svelte.d.ts +26 -0
  20. package/src/components/Button/index.ts +2 -0
  21. package/src/components/Fastboard/Fastboard.scss +49 -0
  22. package/src/components/Fastboard/Fastboard.svelte +32 -0
  23. package/src/components/Fastboard/Fastboard.svelte.ts +12 -0
  24. package/src/components/Fastboard/ReplayFastboard.svelte +22 -0
  25. package/src/components/Fastboard/ReplayFastboard.svelte.ts +12 -0
  26. package/src/components/Fastboard/index.ts +5 -0
  27. package/src/components/Icon/Icon.svelte +11 -0
  28. package/src/components/Icon/Icon.svelte.d.ts +10 -0
  29. package/src/components/Icon/index.ts +2 -0
  30. package/src/components/Icons/Apps.svelte +49 -0
  31. package/src/components/Icons/Arrow.svelte +16 -0
  32. package/src/components/Icons/ArrowBolded.svelte +17 -0
  33. package/src/components/Icons/Balloon.svelte +16 -0
  34. package/src/components/Icons/BalloonBolded.svelte +16 -0
  35. package/src/components/Icons/Circle.svelte +20 -0
  36. package/src/components/Icons/CircleBolded.svelte +20 -0
  37. package/src/components/Icons/Clean.svelte +14 -0
  38. package/src/components/Icons/Clear.svelte +16 -0
  39. package/src/components/Icons/Click.svelte +16 -0
  40. package/src/components/Icons/ClickFilled.svelte +10 -0
  41. package/src/components/Icons/Diamond.svelte +16 -0
  42. package/src/components/Icons/Down.svelte +16 -0
  43. package/src/components/Icons/Eraser.svelte +16 -0
  44. package/src/components/Icons/EraserFilled.svelte +16 -0
  45. package/src/components/Icons/Icons.scss +20 -0
  46. package/src/components/Icons/Left.svelte +16 -0
  47. package/src/components/Icons/Line.svelte +16 -0
  48. package/src/components/Icons/LineBolded.svelte +16 -0
  49. package/src/components/Icons/Loading.svelte +10 -0
  50. package/src/components/Icons/Minus.svelte +16 -0
  51. package/src/components/Icons/Pause.svelte +10 -0
  52. package/src/components/Icons/Pencil.svelte +29 -0
  53. package/src/components/Icons/PencilFilled.svelte +16 -0
  54. package/src/components/Icons/Play.svelte +10 -0
  55. package/src/components/Icons/Plus.svelte +16 -0
  56. package/src/components/Icons/Rectangle.svelte +16 -0
  57. package/src/components/Icons/RectangleBolded.svelte +16 -0
  58. package/src/components/Icons/Redo.svelte +15 -0
  59. package/src/components/Icons/Reset.svelte +26 -0
  60. package/src/components/Icons/Rhombus.svelte +16 -0
  61. package/src/components/Icons/RhombusBolded.svelte +16 -0
  62. package/src/components/Icons/Right.svelte +16 -0
  63. package/src/components/Icons/Selector.svelte +24 -0
  64. package/src/components/Icons/SelectorFilled.svelte +18 -0
  65. package/src/components/Icons/SpeechBalloon.svelte +16 -0
  66. package/src/components/Icons/Star.svelte +16 -0
  67. package/src/components/Icons/StarBolded.svelte +16 -0
  68. package/src/components/Icons/Text.svelte +16 -0
  69. package/src/components/Icons/TextFilled.svelte +17 -0
  70. package/src/components/Icons/Triangle.svelte +16 -0
  71. package/src/components/Icons/TriangleBolded.svelte +16 -0
  72. package/src/components/Icons/Undo.svelte +15 -0
  73. package/src/components/Icons/Up.svelte +16 -0
  74. package/src/components/Icons/WhiteboardAdd.svelte +34 -0
  75. package/src/components/Icons/index.ts +93 -0
  76. package/src/components/PageControl/PageControl.scss +15 -0
  77. package/src/components/PageControl/PageControl.svelte +78 -0
  78. package/src/components/PageControl/PageControl.svelte.d.ts +13 -0
  79. package/src/components/PageControl/index.ts +2 -0
  80. package/src/components/PlayerControl/PlayerControl.scss +57 -0
  81. package/src/components/PlayerControl/PlayerControl.svelte +153 -0
  82. package/src/components/PlayerControl/PlayerControl.svelte.d.ts +13 -0
  83. package/src/components/PlayerControl/index.ts +2 -0
  84. package/src/components/RedoUndo/RedoUndo.scss +11 -0
  85. package/src/components/RedoUndo/RedoUndo.svelte +60 -0
  86. package/src/components/RedoUndo/RedoUndo.svelte.d.ts +13 -0
  87. package/src/components/RedoUndo/index.ts +2 -0
  88. package/src/components/Toolbar/README.md +57 -0
  89. package/src/components/Toolbar/Toolbar.scss +69 -0
  90. package/src/components/Toolbar/Toolbar.svelte +50 -0
  91. package/src/components/Toolbar/Toolbar.svelte.d.ts +12 -0
  92. package/src/components/Toolbar/components/Contents.scss +166 -0
  93. package/src/components/Toolbar/components/Contents.svelte +191 -0
  94. package/src/components/Toolbar/components/Shapes.svelte +85 -0
  95. package/src/components/Toolbar/components/Slider.scss +119 -0
  96. package/src/components/Toolbar/components/Slider.svelte +54 -0
  97. package/src/components/Toolbar/components/StrokeColor.svelte +39 -0
  98. package/src/components/Toolbar/components/StrokeWidth.svelte +20 -0
  99. package/src/components/Toolbar/components/constants.ts +80 -0
  100. package/src/components/Toolbar/components/helper.ts +24 -0
  101. package/src/components/Toolbar/index.ts +2 -0
  102. package/src/components/ZoomControl/ZoomControl.scss +15 -0
  103. package/src/components/ZoomControl/ZoomControl.svelte +99 -0
  104. package/src/components/ZoomControl/ZoomControl.svelte.d.ts +13 -0
  105. package/src/components/ZoomControl/index.ts +2 -0
  106. package/src/components/helpers.ts +3 -0
  107. package/src/components/theme.scss +91 -0
  108. package/src/components/variables.scss +69 -0
  109. package/src/index.ts +13 -0
  110. package/src/style.scss +36 -0
  111. package/src/typings.ts +17 -0
@@ -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.75"
13
+ d="m12 5 8 14H4l8-14Z"
14
+ class="fastboard-icon-stroke-color"
15
+ />
16
+ </svg>
@@ -0,0 +1,15 @@
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 fill="#5D6066" d="M10 5 4 9l6 4-2-4 2-4Z" class="fastboard-icon-fill-color" />
10
+ <path
11
+ fill="#5D6066"
12
+ d="M16 8.375H8v1.25h8v-1.25Zm0 8H4v1.25h12v-1.25ZM20.625 13A4.625 4.625 0 0 0 16 8.375v1.25A3.375 3.375 0 0 1 19.375 13h1.25Zm-1.25 0A3.375 3.375 0 0 1 16 16.375v1.25A4.625 4.625 0 0 0 20.625 13h-1.25Z"
13
+ class="fastboard-icon-fill-color"
14
+ />
15
+ </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
+ d="m16 14-2-2-2-2-2 2-2 2"
11
+ stroke="#5D6066"
12
+ stroke-linejoin="round"
13
+ stroke-width="1.25"
14
+ class="fastboard-icon-stroke-color"
15
+ />
16
+ </svg>
@@ -0,0 +1,34 @@
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
+ d="M4 20h16M4 6h16"
11
+ stroke="#5D6066"
12
+ stroke-linejoin="round"
13
+ stroke-width="1.25"
14
+ class="fastboard-icon-stroke-color"
15
+ />
16
+ <rect
17
+ height="10"
18
+ rx="1"
19
+ stroke="#5D6066"
20
+ stroke-linejoin="round"
21
+ stroke-width="1.25"
22
+ width="14"
23
+ x="5"
24
+ y="8"
25
+ class="fastboard-icon-stroke-color"
26
+ />
27
+ <path
28
+ d="M12 4v2m-3 7h6m-3-3v6"
29
+ stroke="#5D6066"
30
+ stroke-linejoin="round"
31
+ stroke-width="1.25"
32
+ class="fastboard-icon-stroke-color"
33
+ />
34
+ </svg>
@@ -0,0 +1,93 @@
1
+ import Apps from "./Apps.svelte";
2
+ import Arrow from "./Arrow.svelte";
3
+ import ArrowBolded from "./ArrowBolded.svelte";
4
+ import Balloon from "./Balloon.svelte";
5
+ import BalloonBolded from "./BalloonBolded.svelte";
6
+ import Circle from "./Circle.svelte";
7
+ import CircleBolded from "./CircleBolded.svelte";
8
+ import Clean from "./Clean.svelte";
9
+ import Clear from "./Clear.svelte";
10
+ import Click from "./Click.svelte";
11
+ import ClickFilled from "./ClickFilled.svelte";
12
+ import Diamond from "./Diamond.svelte";
13
+ import Down from "./Down.svelte";
14
+ import Eraser from "./Eraser.svelte";
15
+ import EraserFilled from "./EraserFilled.svelte";
16
+ import Left from "./Left.svelte";
17
+ import Line from "./Line.svelte";
18
+ import LineBolded from "./LineBolded.svelte";
19
+ import Minus from "./Minus.svelte";
20
+ import Pencil from "./Pencil.svelte";
21
+ import PencilFilled from "./PencilFilled.svelte";
22
+ import Plus from "./Plus.svelte";
23
+ import Rectangle from "./Rectangle.svelte";
24
+ import RectangleBolded from "./RectangleBolded.svelte";
25
+ import Redo from "./Redo.svelte";
26
+ import Reset from "./Reset.svelte";
27
+ import Rhombus from "./Rhombus.svelte";
28
+ import RhombusBolded from "./RhombusBolded.svelte";
29
+ import Right from "./Right.svelte";
30
+ import Selector from "./Selector.svelte";
31
+ import SelectorFilled from "./SelectorFilled.svelte";
32
+ import SpeechBalloon from "./SpeechBalloon.svelte";
33
+ import Star from "./Star.svelte";
34
+ import StarBolded from "./StarBolded.svelte";
35
+ import Text from "./Text.svelte";
36
+ import TextFilled from "./TextFilled.svelte";
37
+ import Triangle from "./Triangle.svelte";
38
+ import TriangleBolded from "./TriangleBolded.svelte";
39
+ import Undo from "./Undo.svelte";
40
+ import Up from "./Up.svelte";
41
+ import WhiteboardAdd from "./WhiteboardAdd.svelte";
42
+ import Play from "./Play.svelte";
43
+ import Pause from "./Pause.svelte";
44
+ import Loading from "./Loading.svelte";
45
+
46
+ const Icons = {
47
+ Apps,
48
+ Arrow,
49
+ ArrowBolded,
50
+ Balloon,
51
+ BalloonBolded,
52
+ Circle,
53
+ CircleBolded,
54
+ Clean,
55
+ Clear,
56
+ Click,
57
+ ClickFilled,
58
+ Diamond,
59
+ Down,
60
+ Eraser,
61
+ EraserFilled,
62
+ Left,
63
+ Line,
64
+ LineBolded,
65
+ Minus,
66
+ Pencil,
67
+ PencilFilled,
68
+ Plus,
69
+ Rectangle,
70
+ RectangleBolded,
71
+ Redo,
72
+ Reset,
73
+ Rhombus,
74
+ RhombusBolded,
75
+ Right,
76
+ Selector,
77
+ SelectorFilled,
78
+ SpeechBalloon,
79
+ Star,
80
+ StarBolded,
81
+ Text,
82
+ TextFilled,
83
+ Triangle,
84
+ TriangleBolded,
85
+ Undo,
86
+ Up,
87
+ WhiteboardAdd,
88
+ Play,
89
+ Pause,
90
+ Loading,
91
+ };
92
+
93
+ export default Icons;
@@ -0,0 +1,15 @@
1
+ @import "../theme.scss";
2
+
3
+ $name: "fastboard-page-control";
4
+
5
+ .#{$name} {
6
+ @include container;
7
+ }
8
+
9
+ .#{$name}-btn {
10
+ @include btn;
11
+ }
12
+
13
+ .#{$name}-text {
14
+ @include tabular-nums;
15
+ }
@@ -0,0 +1,78 @@
1
+ <script lang="ts" context="module">
2
+ import type { FastboardApp } from "@netless/fastboard-core";
3
+ import type { GenericIcon, I18nData, IconType, Language, Theme } from "../../typings";
4
+ const i18n: I18nData<"prev" | "next" | "add"> = {
5
+ en: {
6
+ prev: "Prev Page",
7
+ next: "Next Page",
8
+ add: "Add Page",
9
+ },
10
+ "zh-CN": {
11
+ prev: "上一页",
12
+ next: "下一页",
13
+ add: "添加页面",
14
+ },
15
+ };
16
+ </script>
17
+
18
+ <script lang="ts">
19
+ import Icon from "../Icon";
20
+ import Icons from "../Icons";
21
+ import Button from "../Button";
22
+
23
+ export let app: FastboardApp | null | undefined = null;
24
+ export let theme: Theme = "light";
25
+ export let language: Language = "en";
26
+ export let icons: GenericIcon<"prev" | "next" | "add"> | undefined = undefined;
27
+
28
+ const name = "fastboard-page-control";
29
+
30
+ $: writable = app?.writable;
31
+ $: disabled = !$writable;
32
+ $: t = i18n[language];
33
+
34
+ let type: IconType;
35
+ $: type = disabled ? "disable" : "normal";
36
+
37
+ $: index = app?.sceneIndex;
38
+ $: length = app?.sceneLength;
39
+ $: prev_disabled = disabled || !$index;
40
+ $: next_disabled = disabled || $length == null || $index === $length - 1;
41
+
42
+ function prevPage() {
43
+ app?.prevPage();
44
+ }
45
+
46
+ function nextPage() {
47
+ app?.nextPage();
48
+ }
49
+
50
+ function addPage() {
51
+ app?.addPage({ after: true });
52
+ }
53
+ </script>
54
+
55
+ <div class="{name} {theme}">
56
+ <Button class="prev" {name} {theme} disabled={prev_disabled} on:click={prevPage} content={t.prev}>
57
+ <Icon src={icons?.prev[type]} alt="[prev]">
58
+ <Icons.Left {theme} />
59
+ </Icon>
60
+ </Button>
61
+ <span class="{name}-text {theme}">
62
+ {#if $index == null || $length == null}
63
+ &hellip;
64
+ {:else}
65
+ {$index + 1}/{$length}
66
+ {/if}
67
+ </span>
68
+ <Button class="next" {name} {theme} disabled={next_disabled} on:click={nextPage} content={t.next}>
69
+ <Icon src={icons?.next[type]} alt="[next]">
70
+ <Icons.Right {theme} />
71
+ </Icon>
72
+ </Button>
73
+ <Button class="add" {name} {theme} {disabled} on:click={addPage} content={t.add}>
74
+ <Icon src={icons?.add[type]} alt="[add]">
75
+ <Icons.WhiteboardAdd {theme} />
76
+ </Icon>
77
+ </Button>
78
+ </div>
@@ -0,0 +1,13 @@
1
+ import type { FastboardApp } from "@netless/fastboard-core";
2
+ import type { Theme, Language, GenericIcon } from "../../typings";
3
+ import { SvelteComponentTyped } from "svelte";
4
+
5
+ export declare interface PageControlProps {
6
+ app?: FastboardApp | null;
7
+ theme?: Theme;
8
+ language?: Language;
9
+ icons?: GenericIcon<"prev" | "next" | "add">;
10
+ }
11
+
12
+ declare class PageControl extends SvelteComponentTyped<PageControlProps> {}
13
+ export default PageControl;
@@ -0,0 +1,2 @@
1
+ export { default } from "./PageControl.svelte";
2
+ export * from "./PageControl.svelte";
@@ -0,0 +1,57 @@
1
+ @import "../theme.scss";
2
+
3
+ $name: "fastboard-player-control";
4
+
5
+ .#{$name} {
6
+ @include container;
7
+ width: 100%;
8
+ }
9
+
10
+ .#{$name}-btn {
11
+ @include btn;
12
+ display: inline;
13
+
14
+ &.loading {
15
+ svg,
16
+ img {
17
+ animation: fastboard-player-control-rotate 0.5s linear infinite;
18
+ }
19
+ }
20
+
21
+ @keyframes fastboard-player-control-rotate {
22
+ 100% {
23
+ transform: rotate(360deg);
24
+ }
25
+ }
26
+
27
+ &.speed {
28
+ width: auto;
29
+ padding: 4px;
30
+ text-align: right;
31
+ font-size: 14px;
32
+ font-variant-numeric: tabular-nums;
33
+ }
34
+
35
+ @each $name, $theme in $themes {
36
+ &.is-active.#{$name} {
37
+ color: read($theme, "active-color");
38
+ }
39
+ }
40
+ }
41
+
42
+ .#{$name}-speed-text {
43
+ font-size: 14px;
44
+ font-variant-numeric: tabular-nums;
45
+ line-height: 16px;
46
+ }
47
+
48
+ .#{$name}-progress {
49
+ @extend .#{$name}-speed-text;
50
+ display: inline-flex;
51
+ align-items: center;
52
+ }
53
+
54
+ .#{$name}-panel.speed {
55
+ display: flex;
56
+ flex-direction: column;
57
+ }
@@ -0,0 +1,153 @@
1
+ <script lang="ts" context="module">
2
+ import type { FastboardPlayer } from "@netless/fastboard-core";
3
+ import type { GenericIcon, I18nData, IconType, Language, Theme } from "../../typings";
4
+
5
+ const speeds = [2.0, 1.5, 1.25, 1.0, 0.75, 0.5];
6
+
7
+ const i18n: I18nData<"play" | "pause" | "speed"> = {
8
+ en: {
9
+ play: "Play",
10
+ pause: "Pause",
11
+ speed: "Speed",
12
+ },
13
+ "zh-CN": {
14
+ play: "播放",
15
+ pause: "暂停",
16
+ speed: "速度",
17
+ },
18
+ };
19
+
20
+ function format(ms: number) {
21
+ const s = Math.floor(ms / 1000);
22
+ const m = Math.floor(s / 60);
23
+ return String(m).padStart(2, "0") + ":" + String(s % 60).padStart(2, "0");
24
+ }
25
+ </script>
26
+
27
+ <script lang="ts">
28
+ import Icon from "../Icon";
29
+ import Icons from "../Icons";
30
+ import Button from "../Button";
31
+ import Slider from "../Toolbar/components/Slider.svelte";
32
+
33
+ export let player: FastboardPlayer | null | undefined = null;
34
+ export let theme: Theme = "light";
35
+ export let language: Language = "en";
36
+ export let icons: GenericIcon<"play" | "pause" | "loading"> | undefined = undefined;
37
+
38
+ const name = "fastboard-player-control";
39
+
40
+ $: t = i18n[language];
41
+
42
+ let type: IconType;
43
+ $: type = disabled ? "disable" : "normal";
44
+
45
+ $: canPlay = player?.canplay;
46
+ $: disabled = !canPlay;
47
+ $: duration = player?.duration;
48
+ $: current = player?.currentTime;
49
+ $: speed = player?.speed;
50
+
51
+ $: phase = player?.phase;
52
+ $: loading = $phase === "waitingFirstFrame" || $phase === "buffering";
53
+ $: playing = $phase === "playing";
54
+ $: className = [loading ? "loading" : "", playing ? "pause" : "play"].filter(Boolean).join(" ");
55
+
56
+ let speed_panel: HTMLDivElement;
57
+
58
+ function toggle() {
59
+ if (!player) return;
60
+ switch (player.player.phase) {
61
+ case "waitingFirstFrame":
62
+ case "pause":
63
+ case "ended": {
64
+ player.play();
65
+ break;
66
+ }
67
+ case "playing": {
68
+ player.pause();
69
+ break;
70
+ }
71
+ }
72
+ }
73
+
74
+ function seek({ detail: seconds }: CustomEvent<number>) {
75
+ if (!player) return;
76
+ player.seek(seconds * 1000);
77
+ }
78
+
79
+ function setSpeed(speed: number) {
80
+ if (!player) return;
81
+ player.setSpeed(speed);
82
+ }
83
+ </script>
84
+
85
+ <div class="{name} {theme}">
86
+ <Button
87
+ class={className}
88
+ {name}
89
+ {theme}
90
+ {disabled}
91
+ on:click={toggle}
92
+ content={loading ? "" : playing ? t.pause : t.play}
93
+ >
94
+ {#if loading}
95
+ <Icon src={icons?.loading[type]} alt="[loading]">
96
+ <Icons.Loading {theme} />
97
+ </Icon>
98
+ {:else if playing}
99
+ <Icon src={icons?.pause[type]} alt="[pause]">
100
+ <Icons.Pause {theme} />
101
+ </Icon>
102
+ {:else}
103
+ <Icon src={icons?.play[type]} alt="[play]">
104
+ <Icons.Play {theme} />
105
+ </Icon>
106
+ {/if}
107
+ </Button>
108
+ {#if $current == null || $duration == null || $duration === 0}
109
+ <Slider class="{name}-slider" disabled />
110
+ <span class="{name}-progress loading">&hellip;/&hellip;</span>
111
+ {:else}
112
+ <Slider
113
+ class="{name}-slider"
114
+ {theme}
115
+ value={$current / 1000}
116
+ min={0}
117
+ max={$duration / 1000}
118
+ on:change={seek}
119
+ />
120
+ <span class="{name}-progress">
121
+ <span class="{name}-current">{format($current)}</span>
122
+ <span class="{name}-slash">/</span>
123
+ <span class="{name}-duration">{format($duration)}</span>
124
+ </span>
125
+ {/if}
126
+ <Button
127
+ class="speed"
128
+ {name}
129
+ {theme}
130
+ {disabled}
131
+ content={t.speed}
132
+ menu={speed_panel}
133
+ menu_placement="top-end"
134
+ >
135
+ <span class="{name}-speed-text">{$speed}x</span>
136
+ </Button>
137
+ </div>
138
+
139
+ <div style="display:none">
140
+ <div class="{name}-panel speed" bind:this={speed_panel}>
141
+ {#each speeds as s (s)}
142
+ <Button
143
+ class="speed {s === $speed ? 'is-active' : ''}"
144
+ {name}
145
+ {theme}
146
+ {disabled}
147
+ on:click={() => setSpeed(s)}
148
+ >
149
+ {s}x
150
+ </Button>
151
+ {/each}
152
+ </div>
153
+ </div>
@@ -0,0 +1,13 @@
1
+ import type { FastboardPlayer } from "@netless/fastboard-core";
2
+ import type { Theme, Language, GenericIcon } from "../../typings";
3
+ import { SvelteComponentTyped } from "svelte";
4
+
5
+ export declare interface PlayerControlProps {
6
+ player?: FastboardPlayer | null;
7
+ theme?: Theme;
8
+ language?: Language;
9
+ icons?: GenericIcon<"play" | "pause" | "loading">;
10
+ }
11
+
12
+ declare class PlayerControl extends SvelteComponentTyped<PlayerControlProps> {}
13
+ export default PlayerControl;
@@ -0,0 +1,2 @@
1
+ export { default } from "./PlayerControl.svelte";
2
+ export * from "./PlayerControl.svelte";
@@ -0,0 +1,11 @@
1
+ @import "../theme.scss";
2
+
3
+ $name: "fastboard-redo-undo";
4
+
5
+ .#{$name} {
6
+ @include container;
7
+ }
8
+
9
+ .#{$name}-btn {
10
+ @include btn;
11
+ }
@@ -0,0 +1,60 @@
1
+ <script lang="ts" context="module">
2
+ import type { FastboardApp } from "@netless/fastboard-core";
3
+ import type { GenericIcon, I18nData, IconType, Language, Theme } from "../../typings";
4
+ const i18n: I18nData<"redo" | "undo"> = {
5
+ en: {
6
+ redo: "Redo",
7
+ undo: "Undo",
8
+ },
9
+ "zh-CN": {
10
+ redo: "重做",
11
+ undo: "撤销",
12
+ },
13
+ };
14
+ </script>
15
+
16
+ <script lang="ts">
17
+ import Icon from "../Icon";
18
+ import Icons from "../Icons";
19
+ import Button from "../Button";
20
+
21
+ export let app: FastboardApp | null | undefined = null;
22
+ export let theme: Theme = "light";
23
+ export let language: Language = "en";
24
+ export let icons: GenericIcon<"undo" | "redo"> | undefined = undefined;
25
+
26
+ const name = "fastboard-redo-undo";
27
+
28
+ $: writable = app?.writable;
29
+ $: disabled = !$writable;
30
+ $: t = i18n[language];
31
+
32
+ let type: IconType;
33
+ $: type = disabled ? "disable" : "normal";
34
+
35
+ $: undoSteps = app?.canUndoSteps;
36
+ $: redoSteps = app?.canRedoSteps;
37
+ $: undo_disabled = disabled || !$undoSteps;
38
+ $: redo_disabled = disabled || !$redoSteps;
39
+
40
+ function undo() {
41
+ app?.undo();
42
+ }
43
+
44
+ function redo() {
45
+ app?.redo();
46
+ }
47
+ </script>
48
+
49
+ <div class="{name} {theme}">
50
+ <Button class="undo" {name} {theme} disabled={undo_disabled} on:click={undo} content={t.undo}>
51
+ <Icon src={icons?.undo[type]} alt="[undo]">
52
+ <Icons.Undo {theme} />
53
+ </Icon>
54
+ </Button>
55
+ <Button class="redo" {name} {theme} disabled={redo_disabled} on:click={redo} content={t.redo}>
56
+ <Icon src={icons?.redo[type]} alt="[redo]">
57
+ <Icons.Redo {theme} />
58
+ </Icon>
59
+ </Button>
60
+ </div>
@@ -0,0 +1,13 @@
1
+ import type { FastboardApp } from "@netless/fastboard-core";
2
+ import type { Theme, Language, GenericIcon } from "../../typings";
3
+ import { SvelteComponentTyped } from "svelte";
4
+
5
+ export declare interface RedoUndoProps {
6
+ app?: FastboardApp | null;
7
+ theme?: Theme;
8
+ language?: Language;
9
+ icons?: GenericIcon<"undo" | "redo">;
10
+ }
11
+
12
+ declare class RedoUndo extends SvelteComponentTyped<RedoUndoProps> {}
13
+ export default RedoUndo;
@@ -0,0 +1,2 @@
1
+ export { default } from "./RedoUndo.svelte";
2
+ export * from "./RedoUndo.svelte";
@@ -0,0 +1,57 @@
1
+ ## Fastboard Toolbar
2
+
3
+ ```
4
+ +---+ vertically center of the viewport
5
+ | ^ |-+ up/down button to do scroll
6
+ : / :<| collapse/expand button to toggle toolbar to the left
7
+ | v |-+
8
+ +---+ dynamic height according to the viewport
9
+ ```
10
+
11
+ This doc will give you an overview of how the toolbar structures, from top (outer) to bottom (inner).
12
+
13
+ ### The Outmost Container
14
+
15
+ <pre>--- content
16
+ &uarr;
17
+ : |&larr; handler
18
+ &darr;
19
+ ---</pre>
20
+
21
+ ```svelte
22
+ <container style="height: 100%; display: flex; align-items: center">
23
+ <content style="height: {computed_height}px" />
24
+ <handler style="position: absolute; left: 100%" />
25
+ </container>
26
+ ```
27
+
28
+ - Container has the full height for further calculations.
29
+ - Content is actually visible parts, it has background color.\
30
+ Its height will be calculated later.
31
+ - Handler is the button to collapse/expand the toolbar.
32
+
33
+ ### The Content
34
+
35
+ <pre>------- content
36
+ ^ up button
37
+ .---. scrollable area
38
+ : :
39
+ '---'
40
+ v down button
41
+ -------</pre>
42
+
43
+ ```svelte
44
+ <content style="height: {computed_height}px">
45
+ <up-button />
46
+ <scrollable-area style="overflow: hidden" />
47
+ <down-button />
48
+ </content>
49
+ ```
50
+
51
+ The `computed_height` is calculated by:
52
+
53
+ ```js
54
+ const max_height = button_height * 2 + scrollable_area_full_height;
55
+ let full_height = container.height;
56
+ computed_height = full_height < max_height ? full_height : max_height;
57
+ ```