@netless/fastboard-ui 1.0.3 → 1.0.5-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/fastboard-ui",
3
- "version": "1.0.3",
3
+ "version": "1.0.5-beta.0",
4
4
  "description": "The front-end of @netless/fastboard-core.",
5
5
  "main": "dist/index.js",
6
6
  "svelte": "dist/index.svelte.mjs",
@@ -12,15 +12,15 @@
12
12
  ],
13
13
  "repository": "netless-io/fastboard",
14
14
  "peerDependencies": {
15
- "@netless/fastboard-core": "1.0.3"
15
+ "@netless/fastboard-core": "1.0.5-beta.0"
16
16
  },
17
17
  "dependencies": {
18
18
  "tippy.js": "^6.3.7"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@netless/esbuild-plugin-inline-sass": "0.1.0",
22
- "@netless/fastboard-core": "1.0.3",
23
- "@netless/buildtool": "0.1.0"
22
+ "@netless/buildtool": "0.1.0",
23
+ "@netless/fastboard-core": "1.0.5-beta.0"
24
24
  },
25
25
  "scripts": {
26
26
  "cleanup": "rimraf dist",
@@ -0,0 +1,23 @@
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 width="24" height="24" viewBox="0 0 24 24" class="fastboard-icon {theme}" class:is-active={active}>
9
+ <g fill="none">
10
+ <path
11
+ fill="#5D6066"
12
+ d="m5.505 11.41l.53.53zM3 14.952h-.75zM9.048 21v.75zM11.41 5.505l-.53-.53zm1.831 12.34a.75.75 0 0 0 1.06-1.061zM7.216 9.697a.75.75 0 1 0-1.06 1.061zm10.749 2.362l-5.905 5.905l1.06 1.06l5.905-5.904zm-11.93-.12l5.905-5.905l-1.06-1.06l-5.905 5.904zm0 6.025c-.85-.85-1.433-1.436-1.812-1.933c-.367-.481-.473-.79-.473-1.08h-1.5c0 .749.312 1.375.78 1.99c.455.596 1.125 1.263 1.945 2.083zm-1.06-7.086c-.82.82-1.49 1.488-1.945 2.084c-.468.614-.78 1.24-.78 1.99h1.5c0-.29.106-.6.473-1.08c.38-.498.962-1.083 1.812-1.933zm7.085 7.086c-.85.85-1.435 1.433-1.933 1.813c-.48.366-.79.472-1.08.472v1.5c.75 0 1.376-.312 1.99-.78c.596-.455 1.264-1.125 2.084-1.945zm-7.085 1.06c.82.82 1.487 1.49 2.084 1.945c.614.468 1.24.78 1.989.78v-1.5c-.29 0-.599-.106-1.08-.473c-.497-.38-1.083-.962-1.933-1.812zm12.99-12.99c.85.85 1.433 1.436 1.813 1.933c.366.481.472.79.472 1.08h1.5c0-.749-.312-1.375-.78-1.99c-.455-.596-1.125-1.263-1.945-2.083zm1.06 7.086c.82-.82 1.49-1.488 1.945-2.084c.468-.614.78-1.24.78-1.99h-1.5c0 .29-.106.6-.473 1.08c-.38.498-.962 1.083-1.812 1.933zm0-8.146c-.82-.82-1.487-1.49-2.084-1.945c-.614-.468-1.24-.78-1.989-.78v1.5c.29 0 .599.106 1.08.473c.497.38 1.083.962 1.933 1.812zm-7.085 1.06c.85-.85 1.435-1.433 1.933-1.812c.48-.367.79-.473 1.08-.473v-1.5c-.75 0-1.376.312-1.99.78c-.596.455-1.264 1.125-2.084 1.945zm2.362 10.749L7.216 9.698l-1.06 1.061l7.085 7.085z"
13
+ class="fastboard-icon-fill-color"
14
+ />
15
+ <path
16
+ stroke="#5D6066"
17
+ stroke-linecap="round"
18
+ stroke-width="1.5"
19
+ d="M9 21h12"
20
+ class="fastboard-icon-stroke-color"
21
+ />
22
+ </g>
23
+ </svg>
@@ -0,0 +1,23 @@
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 width="24" height="24" viewBox="0 0 24 24" class="fastboard-icon {theme}" class:is-active={active}>
9
+ <g fill="none">
10
+ <path
11
+ fill="#5D6066"
12
+ d="m5.505 11.41l.53.53zM3 14.952h-.75zM9.048 21v.75zM11.41 5.505l-.53-.53zm1.831 12.34a.75.75 0 0 0 1.06-1.061zM7.216 9.697a.75.75 0 1 0-1.06 1.061zm10.749 2.362l-5.905 5.905l1.06 1.06l5.905-5.904zm-11.93-.12l5.905-5.905l-1.06-1.06l-5.905 5.904zm0 6.025c-.85-.85-1.433-1.436-1.812-1.933c-.367-.481-.473-.79-.473-1.08h-1.5c0 .749.312 1.375.78 1.99c.455.596 1.125 1.263 1.945 2.083zm-1.06-7.086c-.82.82-1.49 1.488-1.945 2.084c-.468.614-.78 1.24-.78 1.99h1.5c0-.29.106-.6.473-1.08c.38-.498.962-1.083 1.812-1.933zm7.085 7.086c-.85.85-1.435 1.433-1.933 1.813c-.48.366-.79.472-1.08.472v1.5c.75 0 1.376-.312 1.99-.78c.596-.455 1.264-1.125 2.084-1.945zm-7.085 1.06c.82.82 1.487 1.49 2.084 1.945c.614.468 1.24.78 1.989.78v-1.5c-.29 0-.599-.106-1.08-.473c-.497-.38-1.083-.962-1.933-1.812zm12.99-12.99c.85.85 1.433 1.436 1.813 1.933c.366.481.472.79.472 1.08h1.5c0-.749-.312-1.375-.78-1.99c-.455-.596-1.125-1.263-1.945-2.083zm1.06 7.086c.82-.82 1.49-1.488 1.945-2.084c.468-.614.78-1.24.78-1.99h-1.5c0 .29-.106.6-.473 1.08c-.38.498-.962 1.083-1.812 1.933zm0-8.146c-.82-.82-1.487-1.49-2.084-1.945c-.614-.468-1.24-.78-1.989-.78v1.5c.29 0 .599.106 1.08.473c.497.38 1.083.962 1.933 1.812zm-7.085 1.06c.85-.85 1.435-1.433 1.933-1.812c.48-.367.79-.473 1.08-.473v-1.5c-.75 0-1.376.312-1.99.78c-.596.455-1.264 1.125-2.084 1.945zm2.362 10.749L7.216 9.698l-1.06 1.061l7.085 7.085z"
13
+ class="fastboard-icon-fill-color"
14
+ />
15
+ <path
16
+ stroke="#5D6066"
17
+ stroke-linecap="round"
18
+ stroke-width="1.5"
19
+ d="M9 21h12"
20
+ class="fastboard-icon-stroke-color"
21
+ />
22
+ </g>
23
+ </svg>
@@ -49,6 +49,8 @@ import LaserPen from "./LaserPen.svelte";
49
49
  import LaserPenFilled from "./LaserPenFilled.svelte";
50
50
  import MarkPen from "./MarkPen.svelte";
51
51
  import MarkPenFilled from "./MarkPenFilled.svelte";
52
+ import EraserBitmap from "./EraserBitmap.svelte";
53
+ import EraserBitmapFilled from "./EraserBitmapFilled.svelte";
52
54
 
53
55
  const Icons = {
54
56
  Apps,
@@ -102,6 +104,8 @@ const Icons = {
102
104
  LaserPenFilled,
103
105
  MarkPen,
104
106
  MarkPenFilled,
107
+ EraserBitmap,
108
+ EraserBitmapFilled
105
109
  };
106
110
 
107
111
  export default Icons;
@@ -34,7 +34,7 @@
34
34
  $: if (app?.manager && app?.manager.room) {
35
35
  if (colors && !config.colors?.length) {
36
36
  const floatBarOptions = (app?.manager.room as any).floatBarOptions as { colors?: Color[] };
37
- if (floatBarOptions.colors) {
37
+ if (floatBarOptions?.colors) {
38
38
  colors = floatBarOptions.colors as Color[];
39
39
  }
40
40
  } else {
@@ -27,6 +27,7 @@
27
27
  import Clear from "../definitions/Clear.svelte";
28
28
  import Hand from "../definitions/Hand.svelte";
29
29
  import Laser from "../definitions/Laser.svelte";
30
+ import EraserSize from "./EraserSize.svelte";
30
31
 
31
32
  export let app: FastboardApp | null | undefined = null;
32
33
  export let theme: Theme = "light";
@@ -46,6 +47,7 @@
46
47
  let text_panel: HTMLDivElement;
47
48
  let shapes_panel: HTMLDivElement;
48
49
  let apps_panel: HTMLDivElement;
50
+ let eraser_panel: HTMLDivElement;
49
51
 
50
52
  let btn_props: Partial<ButtonProps>;
51
53
  $: btn_props = {
@@ -79,6 +81,8 @@
79
81
  $: hasUseMarkPen =
80
82
  (hasAppliancePlugin && ($memberState as ExtendMemberState)?.strokeOpacity === 0.5) || false;
81
83
  $: pencilType = hasUseLaserPen ? "laser" : hasUseMarkPen ? "mark" : "pencil";
84
+ $: hasUseEraserBitmap = hasAppliancePlugin && ($memberState as ExtendMemberState)?.isLine === false;
85
+ $: eraserType = hasUseEraserBitmap ? "pencilEraser" : "eraser";
82
86
 
83
87
  let top = writable(0);
84
88
 
@@ -114,7 +118,17 @@
114
118
  app?.setAppliance("text");
115
119
  }
116
120
  function eraser() {
117
- app?.setAppliance("eraser");
121
+ if (hasAppliancePlugin) {
122
+ if (appliance !== "eraser") {
123
+ if (eraserType === "pencilEraser") {
124
+ useEraserBitmap();
125
+ } else {
126
+ useEraser();
127
+ }
128
+ }
129
+ } else {
130
+ useEraser();
131
+ }
118
132
  }
119
133
  function hand() {
120
134
  app?.setAppliance("hand");
@@ -150,6 +164,22 @@
150
164
  strokeOpacity: 0.5,
151
165
  } as ExtendMemberState);
152
166
  }
167
+ function useEraser() {
168
+ if (hasAppliancePlugin) {
169
+ app?.appliancePlugin?.setMemberState({
170
+ currentApplianceName: "eraser",
171
+ isLine: true,
172
+ } as ExtendMemberState);
173
+ } else {
174
+ app?.setAppliance("eraser");
175
+ }
176
+ }
177
+ function useEraserBitmap() {
178
+ app?.appliancePlugin?.setMemberState({
179
+ currentApplianceName: "pencilEraser",
180
+ isLine: false,
181
+ } as ExtendMemberState);
182
+ }
153
183
  </script>
154
184
 
155
185
  {#if scrollable}
@@ -178,7 +208,15 @@
178
208
  {:else if item === "shapes"}
179
209
  <Shapes {app} {appliance} {theme} {btn_props} content={t.shapes} menu={shapes_panel} />
180
210
  {:else if item === "eraser"}
181
- <Eraser {appliance} {theme} {btn_props} on:click={eraser} content={c.eraser} />
211
+ <Eraser
212
+ {eraserType}
213
+ {appliance}
214
+ {theme}
215
+ {btn_props}
216
+ on:click={eraser}
217
+ content={c.eraser}
218
+ menu={hasAppliancePlugin ? eraser_panel : undefined}
219
+ />
182
220
  {:else if item === "clear"}
183
221
  <Clear {theme} {btn_props} on:click={clear} content={t.clear} />
184
222
  {:else if item === "hand"}
@@ -254,6 +292,32 @@
254
292
  <div class="{name}-panel-divider" />
255
293
  <StrokeColor {app} {theme} {disabled} {colors} />
256
294
  </div>
295
+ <div class="{name}-panel earser" bind:this={eraser_panel}>
296
+ <div class="{name}-panel-switch-earser">
297
+ {#if !!app?.appliancePlugin}
298
+ {#if eraserType !== "eraser"}
299
+ <Button class="{name}-panel-switch-btn" {...btn_props} on:click={useEraser}>
300
+ <Icons.Eraser {theme} />
301
+ </Button>
302
+ {:else if eraserType === "eraser"}
303
+ <Button class="{name}-panel-switch-btn" {...btn_props}>
304
+ <Icons.EraserFilled {theme} active />
305
+ </Button>
306
+ {/if}
307
+
308
+ {#if eraserType === "pencilEraser"}
309
+ <Button class="{name}-panel-switch-btn" {...btn_props}>
310
+ <Icons.EraserBitmap {theme} active />
311
+ </Button>
312
+ {:else if eraserType !== "pencilEraser"}
313
+ <Button class="{name}-panel-switch-btn" {...btn_props} on:click={useEraserBitmap}>
314
+ <Icons.EraserBitmapFilled {theme} />
315
+ </Button>
316
+ {/if}
317
+ {/if}
318
+ </div>
319
+ <EraserSize {app} {theme} {disabled} />
320
+ </div>
257
321
  <div class="{name}-panel apps" style="--n:{$apps.length}" bind:this={apps_panel}>
258
322
  {#each $apps as netless_app}
259
323
  {@const { icon, label, kind, onClick } = netless_app}
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import type { FastboardApp, ExtendMemberState } from "@netless/fastboard-core";
3
+ import type { Theme } from "../../../typings";
4
+ import Slider from "./Slider.svelte";
5
+
6
+ export let app: FastboardApp | null | undefined = null;
7
+ export let theme: Theme = "light";
8
+ export let disabled = false;
9
+
10
+ $: memberState = app?.memberState;
11
+ $: value = $memberState?.pencilEraserSize ?? 1;
12
+
13
+ $: props = { value, theme, disabled };
14
+
15
+ function set_eraser_size({ detail: value }: CustomEvent<number>) {
16
+ app?.appliancePlugin?.setMemberState({
17
+ pencilEraserSize: value,
18
+ } as ExtendMemberState);
19
+ }
20
+ </script>
21
+
22
+ <Slider class="fastboard-toolbar-slider" {...props} min={1} max={4} on:change={set_eraser_size} />
@@ -8,12 +8,22 @@
8
8
  export let content: ButtonProps["content"] | undefined;
9
9
  export let appliance: ApplianceNames | undefined;
10
10
  export let theme: Theme = "light";
11
+ export let menu: ButtonProps["menu"] | undefined;
12
+ export let eraserType: string = "eraser";
11
13
  </script>
12
14
 
13
- <Button class="eraser" {...btn_props} on:click {content}>
14
- {#if appliance === "eraser"}
15
- <Icons.EraserFilled {theme} active />
16
- {:else}
17
- <Icons.Eraser {theme} />
15
+ <Button class="eraser" {...btn_props} on:click {content} {menu}>
16
+ {#if eraserType === "eraser"}
17
+ {#if appliance === "eraser"}
18
+ <Icons.EraserFilled {theme} active />
19
+ {:else}
20
+ <Icons.Eraser {theme} />
21
+ {/if}
22
+ {:else if eraserType === "pencilEraser"}
23
+ {#if appliance === "pencilEraser"}
24
+ <Icons.EraserBitmapFilled {theme} active />
25
+ {:else}
26
+ <Icons.EraserBitmap {theme} />
27
+ {/if}
18
28
  {/if}
19
29
  </Button>
@@ -23,7 +23,7 @@ export function createUI(app?: FastboardApp | null, div?: Element): UI {
23
23
 
24
24
  if (app?.manager && app.manager.room) {
25
25
  const floatBarOptions = (app.manager.room as any).floatBarOptions as { colors?: Color[] };
26
- if (floatBarOptions.colors) {
26
+ if (floatBarOptions?.colors) {
27
27
  colors = floatBarOptions.colors as Color[];
28
28
  }
29
29
  }