@netless/app-slide 0.3.0-canary.0 → 0.3.0-canary.3
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/SlideViewer.d.ts +4 -1
- package/dist/main.cjs.js +103 -103
- package/dist/main.cjs.js.map +1 -1
- package/dist/main.es.js +38 -17
- package/dist/main.es.js.map +1 -1
- package/dist/main.iife.js +94 -94
- package/dist/main.iife.js.map +1 -1
- package/package.json +1 -1
- package/src/SlideViewer.ts +23 -4
- package/src/fancy-scrollbar.scss +57 -0
- package/src/index.ts +26 -17
- package/src/style.scss +17 -11
package/package.json
CHANGED
package/src/SlideViewer.ts
CHANGED
|
@@ -105,7 +105,7 @@ function create_sidebar() {
|
|
|
105
105
|
|
|
106
106
|
const $preview = h("div");
|
|
107
107
|
set_class($preview, "preview");
|
|
108
|
-
$preview.classList.add("tele-fancy-scrollbar");
|
|
108
|
+
$preview.classList.add(wrap_class("tele-fancy-scrollbar"));
|
|
109
109
|
$preview.onclick = function on_click_preview(ev) {
|
|
110
110
|
if (readonly) return;
|
|
111
111
|
const page_index = (ev.target as HTMLElement).dataset?.pageIndex;
|
|
@@ -371,7 +371,10 @@ function on_visibility_change(callback: (visible: boolean) => void) {
|
|
|
371
371
|
return noop;
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
-
export type SlideViewerOptions = Omit<ISlideConfig, "anchor"> &
|
|
374
|
+
export type SlideViewerOptions = Omit<ISlideConfig, "anchor" | "mode" | "interactive"> & {
|
|
375
|
+
mode?: ISlideConfig["mode"];
|
|
376
|
+
interactive?: ISlideConfig["interactive"];
|
|
377
|
+
} & SlideAttributes;
|
|
375
378
|
|
|
376
379
|
export interface SlideViewerInfoResponse {
|
|
377
380
|
width: number;
|
|
@@ -402,7 +405,6 @@ export class SlideViewer {
|
|
|
402
405
|
this.$content = this.sidebar.$content;
|
|
403
406
|
this.$footer = this.footer.$footer;
|
|
404
407
|
append(this.$content, this.$slide);
|
|
405
|
-
append(this.$content, this.$footer);
|
|
406
408
|
|
|
407
409
|
let resolveReady: () => void;
|
|
408
410
|
this._readyPromise = new Promise(resolve => {
|
|
@@ -427,6 +429,11 @@ export class SlideViewer {
|
|
|
427
429
|
|
|
428
430
|
this.sideEffect.addDisposer(this.sidebar.destroy);
|
|
429
431
|
this.sideEffect.addDisposer(() => this.slide.destroy());
|
|
432
|
+
this.sideEffect.addDisposer(() => {
|
|
433
|
+
this.$content.parentElement && this.$content.remove();
|
|
434
|
+
this.$footer.parentElement && this.$footer.remove();
|
|
435
|
+
this.$slide.parentElement && this.$slide.remove();
|
|
436
|
+
});
|
|
430
437
|
|
|
431
438
|
let saved_is_frozen = false;
|
|
432
439
|
this.sideEffect.addDisposer(
|
|
@@ -441,7 +448,14 @@ export class SlideViewer {
|
|
|
441
448
|
})
|
|
442
449
|
);
|
|
443
450
|
|
|
444
|
-
this.slide = new Slide({
|
|
451
|
+
this.slide = new Slide({
|
|
452
|
+
anchor: this.$slide,
|
|
453
|
+
resize: true,
|
|
454
|
+
mode: "local",
|
|
455
|
+
interactive: true,
|
|
456
|
+
enableGlobalClick: true,
|
|
457
|
+
...options,
|
|
458
|
+
});
|
|
445
459
|
this.slide.setResource(options.taskId, options.url || DefaultUrl);
|
|
446
460
|
|
|
447
461
|
let resolveFetching: (response: SlideViewerInfoResponse) => void;
|
|
@@ -449,6 +463,11 @@ export class SlideViewer {
|
|
|
449
463
|
resolveFetching = resolve;
|
|
450
464
|
});
|
|
451
465
|
|
|
466
|
+
this.slide.on("slideChange", page => {
|
|
467
|
+
if (this._destroyed) return;
|
|
468
|
+
this.setPage(page);
|
|
469
|
+
});
|
|
470
|
+
|
|
452
471
|
this.slide.on("renderEnd", () => {
|
|
453
472
|
if (!this._ready)
|
|
454
473
|
setTimeout(() => {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
$namespace: "netless-app-slide";
|
|
2
|
+
|
|
3
|
+
$scrollbar-size: 8px;
|
|
4
|
+
$scrollbar-ff-width: auto; // FF-only accepts auto, thin, none
|
|
5
|
+
$scrollbar-minlength: 50px; // Minimum length of scrollbar thumb
|
|
6
|
+
$scrollbar-track-color: transparent;
|
|
7
|
+
$scrollbar-color: rgba(68, 78, 96, 0.1);
|
|
8
|
+
$scrollbar-color-hover: rgba(68, 78, 96, 0.2);
|
|
9
|
+
$scrollbar-color-active: rgba(68, 78, 96, 0.2);
|
|
10
|
+
|
|
11
|
+
.#{$namespace}-tele-fancy-scrollbar {
|
|
12
|
+
overscroll-behavior: contain;
|
|
13
|
+
overflow: auto;
|
|
14
|
+
overflow-y: scroll;
|
|
15
|
+
overflow-y: overlay; // for webkit
|
|
16
|
+
-webkit-overflow-scrolling: touch;
|
|
17
|
+
-ms-overflow-style: -ms-autohiding-scrollbar;
|
|
18
|
+
scrollbar-width: $scrollbar-ff-width;
|
|
19
|
+
// Firefox has incorrect track color
|
|
20
|
+
// scrollbar-color: $scrollbar-color $scrollbar-track-color;
|
|
21
|
+
|
|
22
|
+
&::-webkit-scrollbar {
|
|
23
|
+
height: $scrollbar-size;
|
|
24
|
+
width: $scrollbar-size;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&::-webkit-scrollbar-track {
|
|
28
|
+
background-color: $scrollbar-track-color;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&::-webkit-scrollbar-thumb {
|
|
32
|
+
background-color: $scrollbar-color;
|
|
33
|
+
background-color: $scrollbar-track-color;
|
|
34
|
+
border-radius: $scrollbar-size * 0.5;
|
|
35
|
+
transition: background-color 0.4s;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&:hover::-webkit-scrollbar-thumb {
|
|
39
|
+
background-color: $scrollbar-color;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
43
|
+
background-color: $scrollbar-color-hover;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&::-webkit-scrollbar-thumb:active {
|
|
47
|
+
background-color: $scrollbar-color-active;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&::-webkit-scrollbar-thumb:vertical {
|
|
51
|
+
min-height: $scrollbar-minlength;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&::-webkit-scrollbar-thumb:horizontal {
|
|
55
|
+
min-width: $scrollbar-minlength;
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -8,7 +8,6 @@ import ColorString from "color-string";
|
|
|
8
8
|
import { SideEffectManager } from "side-effect-manager";
|
|
9
9
|
import { SlideViewer } from "./SlideViewer";
|
|
10
10
|
import { refrigerator, addHooks } from "./Refrigerator";
|
|
11
|
-
import { noop } from "./utils";
|
|
12
11
|
|
|
13
12
|
export { SlideViewer, refrigerator, addHooks };
|
|
14
13
|
|
|
@@ -24,19 +23,19 @@ const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions, void> = {
|
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
const options = context.getAppOptions() || {};
|
|
27
|
-
const
|
|
26
|
+
const logger = make_logger(context);
|
|
27
|
+
logger.info("[Slide] setup @ " + __APP_VERSION__);
|
|
28
28
|
|
|
29
29
|
const sideEffect = new SideEffectManager();
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// Create UI
|
|
32
32
|
const viewer = new SlideViewer({
|
|
33
33
|
interactive: true,
|
|
34
34
|
mode: "interactive",
|
|
35
35
|
resize: true,
|
|
36
36
|
enableGlobalClick: true,
|
|
37
|
-
controller: debug,
|
|
38
37
|
timestamp: make_timestamp(context),
|
|
39
|
-
logger
|
|
38
|
+
logger,
|
|
40
39
|
renderOptions: {
|
|
41
40
|
minFPS: options.minFPS || 25,
|
|
42
41
|
maxFPS: options.maxFPS || 30,
|
|
@@ -61,18 +60,18 @@ const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions, void> = {
|
|
|
61
60
|
(window as any).slideViewer = viewer;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
//
|
|
63
|
+
// Mount UI
|
|
65
64
|
context.box.mountStyles(SlideViewer.styles);
|
|
66
65
|
context.box.mountStage(viewer.$slide);
|
|
67
66
|
context.box.mountFooter(viewer.$footer);
|
|
68
67
|
context.box.mountContent(viewer.$content);
|
|
69
68
|
sideEffect.addDisposer(() => viewer.destroy());
|
|
70
69
|
|
|
71
|
-
//
|
|
72
|
-
connect({ context, viewer, sideEffect,
|
|
70
|
+
// Connect UI with Netless App
|
|
71
|
+
connect({ context, viewer, sideEffect, logger });
|
|
73
72
|
|
|
74
73
|
onUnmount(context, () => {
|
|
75
|
-
|
|
74
|
+
logger.info("[Slide] destroy");
|
|
76
75
|
sideEffect.flushAll();
|
|
77
76
|
});
|
|
78
77
|
},
|
|
@@ -82,11 +81,20 @@ export default SlideApp;
|
|
|
82
81
|
|
|
83
82
|
export function previewSlide(options: SlideViewerOptions & { container: HTMLElement }) {
|
|
84
83
|
const { container } = options;
|
|
84
|
+
container.style.cssText = "display:flex;flex-direction:column";
|
|
85
85
|
const viewer = new SlideViewer(options);
|
|
86
|
+
container.appendChild(document.createElement("style")).textContent = SlideViewer.styles;
|
|
86
87
|
container.appendChild(viewer.$content);
|
|
88
|
+
container.appendChild(viewer.$footer);
|
|
89
|
+
viewer.prepare(() => viewer.slide.renderSlide(1));
|
|
87
90
|
return viewer;
|
|
88
91
|
}
|
|
89
92
|
|
|
93
|
+
if (import.meta.env.DEV) {
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
95
|
+
(window as any).previewSlide = previewSlide;
|
|
96
|
+
}
|
|
97
|
+
|
|
90
98
|
function make_timestamp(context: AppContext): () => number {
|
|
91
99
|
const room = context.room;
|
|
92
100
|
const player = context.displayer as Player;
|
|
@@ -99,7 +107,7 @@ function make_timestamp(context: AppContext): () => number {
|
|
|
99
107
|
}
|
|
100
108
|
}
|
|
101
109
|
|
|
102
|
-
function make_logger(context: AppContext) {
|
|
110
|
+
function make_logger(context: AppContext): { info: (msg: string) => void } {
|
|
103
111
|
if (import.meta.env.DEV) {
|
|
104
112
|
return { info: console.debug.bind(console) };
|
|
105
113
|
}
|
|
@@ -150,18 +158,18 @@ interface ConnectParams {
|
|
|
150
158
|
context: AppContext;
|
|
151
159
|
viewer: SlideViewer;
|
|
152
160
|
sideEffect: SideEffectManager;
|
|
153
|
-
|
|
161
|
+
logger: { info: (msg: string) => void };
|
|
154
162
|
}
|
|
155
163
|
|
|
156
|
-
function connect({ context, viewer, sideEffect,
|
|
157
|
-
const log =
|
|
164
|
+
function connect({ context, viewer, sideEffect, logger }: ConnectParams) {
|
|
165
|
+
const log = import.meta.env.DEV ? console.log.bind(console) : logger.info.bind(logger);
|
|
158
166
|
|
|
159
167
|
let whiteboard: WhiteBoardView | null = null;
|
|
160
168
|
|
|
161
169
|
viewer.prepare(({ width, height, slideCount }) => {
|
|
162
170
|
if (context.destroyed) return;
|
|
163
171
|
width && context.box.setStageRatio(height / width);
|
|
164
|
-
whiteboard = context.createWhiteBoardView(slideCount);
|
|
172
|
+
whiteboard = context.createWhiteBoardView({ size: slideCount });
|
|
165
173
|
kick_start();
|
|
166
174
|
});
|
|
167
175
|
|
|
@@ -224,9 +232,10 @@ function connect({ context, viewer, sideEffect, debug }: ConnectParams) {
|
|
|
224
232
|
|
|
225
233
|
// save state
|
|
226
234
|
slide.on("slideChange", page => {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
235
|
+
if (context.isWritable && whiteboard) {
|
|
236
|
+
log("[Slide] page to", page);
|
|
237
|
+
whiteboard.jumpPage(page - 1);
|
|
238
|
+
}
|
|
230
239
|
});
|
|
231
240
|
|
|
232
241
|
// handle ui events
|
package/src/style.scss
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@import "./fancy-scrollbar.scss";
|
|
2
|
+
|
|
1
3
|
$namespace: "netless-app-slide";
|
|
2
4
|
|
|
3
5
|
.#{$namespace}-content {
|
|
@@ -14,7 +16,7 @@ $namespace: "netless-app-slide";
|
|
|
14
16
|
.#{$namespace}-preview-mask {
|
|
15
17
|
display: none;
|
|
16
18
|
position: absolute;
|
|
17
|
-
z-index:
|
|
19
|
+
z-index: 10200;
|
|
18
20
|
top: 0;
|
|
19
21
|
left: 0;
|
|
20
22
|
width: 100%;
|
|
@@ -26,7 +28,7 @@ $namespace: "netless-app-slide";
|
|
|
26
28
|
flex-direction: column;
|
|
27
29
|
align-items: center;
|
|
28
30
|
position: absolute;
|
|
29
|
-
z-index:
|
|
31
|
+
z-index: 10300;
|
|
30
32
|
top: 0;
|
|
31
33
|
left: 0;
|
|
32
34
|
width: 33%;
|
|
@@ -85,7 +87,7 @@ $namespace: "netless-app-slide";
|
|
|
85
87
|
transform: translate(-100%);
|
|
86
88
|
text-align: right;
|
|
87
89
|
font-size: 12px;
|
|
88
|
-
color: #5f5f5f;
|
|
90
|
+
// color: #5f5f5f;
|
|
89
91
|
user-select: none;
|
|
90
92
|
}
|
|
91
93
|
|
|
@@ -96,7 +98,8 @@ $namespace: "netless-app-slide";
|
|
|
96
98
|
align-items: center;
|
|
97
99
|
padding: 0 16px;
|
|
98
100
|
border-top: 1px solid #eeeef7;
|
|
99
|
-
|
|
101
|
+
font-family: system-ui, -apple-system, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Noto Sans",
|
|
102
|
+
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
.#{$namespace}-float-footer {
|
|
@@ -169,11 +172,15 @@ $namespace: "netless-app-slide";
|
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
.#{$namespace}-page-number {
|
|
175
|
+
display: flex;
|
|
176
|
+
align-items: center;
|
|
177
|
+
height: 26px;
|
|
172
178
|
margin-left: auto;
|
|
173
179
|
font-size: 13px;
|
|
174
180
|
user-select: none;
|
|
175
181
|
white-space: nowrap;
|
|
176
182
|
word-break: keep-all;
|
|
183
|
+
font-variant-numeric: tabular-nums;
|
|
177
184
|
}
|
|
178
185
|
|
|
179
186
|
.#{$namespace}-page-number-input {
|
|
@@ -181,7 +188,7 @@ $namespace: "netless-app-slide";
|
|
|
181
188
|
outline: none;
|
|
182
189
|
width: 3em;
|
|
183
190
|
margin: 0;
|
|
184
|
-
padding: 0 2px;
|
|
191
|
+
padding: 0 0.5em 0 2px;
|
|
185
192
|
text-align: right;
|
|
186
193
|
font-size: 13px;
|
|
187
194
|
line-height: 1;
|
|
@@ -189,9 +196,12 @@ $namespace: "netless-app-slide";
|
|
|
189
196
|
font-family: inherit;
|
|
190
197
|
border-radius: 2px;
|
|
191
198
|
color: currentColor;
|
|
199
|
+
font-family: system-ui, -apple-system, "Segoe UI", "Roboto", "Ubuntu", "Cantarell", "Noto Sans",
|
|
200
|
+
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
192
201
|
background: transparent;
|
|
193
202
|
transition: background 0.4s;
|
|
194
203
|
user-select: text;
|
|
204
|
+
font-variant-numeric: tabular-nums;
|
|
195
205
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
|
196
206
|
|
|
197
207
|
&:hover,
|
|
@@ -232,17 +242,13 @@ $namespace: "netless-app-slide";
|
|
|
232
242
|
}
|
|
233
243
|
|
|
234
244
|
.telebox-color-scheme-dark {
|
|
235
|
-
.#{$namespace}-page-number-input {
|
|
236
|
-
color: #a6a6a8;
|
|
237
|
-
}
|
|
238
245
|
.#{$namespace}-page-number-input:active,
|
|
239
246
|
.#{$namespace}-page-number-input:focus,
|
|
240
247
|
.#{$namespace}-page-number-input:hover {
|
|
241
|
-
color:
|
|
248
|
+
color: currentColor;
|
|
249
|
+
background: #25282e;
|
|
242
250
|
}
|
|
243
251
|
.#{$namespace}-footer {
|
|
244
|
-
color: #a6a6a8;
|
|
245
|
-
background: #2d2d33;
|
|
246
252
|
border-top: none;
|
|
247
253
|
}
|
|
248
254
|
.#{$namespace}-footer-btn:hover {
|