@netless/forge-slide 0.1.1-alpha.0 → 0.1.1-alpha.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/package.json CHANGED
@@ -1,26 +1,26 @@
1
1
  {
2
2
  "name": "@netless/forge-slide",
3
- "version": "0.1.1-alpha.0",
3
+ "version": "0.1.1-alpha.10",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "dependencies": {
9
- "@netless/slide": "^1.4.15",
10
- "uuid": "^11.0.5",
11
- "@netless/forge-room": "0.1.8",
12
- "@netless/forge-whiteboard": "0.1.14"
9
+ "@netless/slide": "^1.4.21"
13
10
  },
14
11
  "peerDependencies": {
15
12
  "eventemitter3": "^5.0.1",
16
13
  "yjs": "^13.6.18",
17
- "@netless/forge-room": "0.1.8"
14
+ "uuid": "^11.0.5",
15
+ "@netless/forge-room": "0.1.12-alpha.0",
16
+ "@netless/forge-whiteboard": "0.1.15"
18
17
  },
19
18
  "keywords": [],
20
19
  "author": "",
21
20
  "license": "ISC",
22
21
  "scripts": {
23
22
  "dev": "onChange 'src/**/*' -- npm run build",
24
- "build": "tsc --emitDeclarationOnly && node build.mjs"
23
+ "build": "pnpm lint && tsc --emitDeclarationOnly && node build.mjs",
24
+ "lint": "eslint src"
25
25
  }
26
26
  }
@@ -0,0 +1,132 @@
1
+ import EventEmitter from 'eventemitter3';
2
+ import { Icons } from './icons';
3
+
4
+ interface FooterViewEvents {
5
+ prevPage: () => void;
6
+ nextPage: () => void;
7
+ prevStep: () => void;
8
+ nextStep: () => void;
9
+ sideBarToggle: () => void;
10
+ }
11
+
12
+ const EM_COLOR = '#8C8C8C';
13
+
14
+ export class FooterView extends EventEmitter<FooterViewEvents> {
15
+
16
+ public readonly root: HTMLDivElement;
17
+
18
+ private prevStep: HTMLDivElement;
19
+ private nextStep: HTMLDivElement;
20
+
21
+ private prevPage: HTMLDivElement;
22
+ private nextPage: HTMLDivElement;
23
+
24
+ private sideBarToggle: HTMLDivElement;
25
+
26
+ private eventMap: Map<HTMLDivElement, (() => void)[]> = new Map();
27
+
28
+ public constructor() {
29
+ super();
30
+ this.root = document.createElement('div');
31
+ this.root.classList.add('forge-slide-footer');
32
+ this.root.style.height = '24px';
33
+ this.root.style.zIndex = '6';
34
+ this.root.style.display = 'flex';
35
+ this.root.style.alignItems = 'center';
36
+ this.root.style.justifyContent = 'center';
37
+ this.root.style.backgroundColor = '#fff';
38
+
39
+ this.prevStep = this.createIcon(Icons.prevStep(EM_COLOR), () => {
40
+ this.emit('prevStep');
41
+ });
42
+
43
+ this.nextStep = this.createIcon(Icons.nextStep(EM_COLOR), () => {
44
+ this.emit('nextStep');
45
+ });
46
+
47
+ this.prevPage = this.createIcon(Icons.prevPage(EM_COLOR), () => {
48
+ this.emit('prevPage');
49
+ });
50
+
51
+ this.nextPage = this.createIcon(Icons.nextPage(EM_COLOR), () => {
52
+ this.emit('nextPage');
53
+ });
54
+
55
+ this.sideBarToggle = this.createIcon(Icons.sideBar(EM_COLOR), () => {
56
+ this.emit('sideBarToggle');
57
+ });
58
+
59
+ this.root.appendChild(this.sideBarToggle);
60
+ this.root.appendChild(this.createSpacer());
61
+ this.root.appendChild(this.prevPage);
62
+ this.root.appendChild(this.prevStep);
63
+ this.root.appendChild(this.nextStep);
64
+ this.root.appendChild(this.nextPage);
65
+ this.root.appendChild(this.createSpacer());
66
+ }
67
+
68
+ public prevPageState(enable: boolean): void {
69
+ if (enable) {
70
+ this.prevPage.style.pointerEvents = 'all';
71
+ this.prevPage.style.opacity = '1';
72
+ } else {
73
+ this.prevPage.style.pointerEvents = 'none';
74
+ this.prevPage.style.opacity = '0.5';
75
+ }
76
+ }
77
+
78
+ public nextPageState(enable: boolean): void {
79
+ if (enable) {
80
+ this.nextPage.style.pointerEvents = 'all';
81
+ this.nextPage.style.opacity = '1';
82
+ } else {
83
+ this.nextPage.style.pointerEvents = 'none';
84
+ this.nextPage.style.opacity = '0.5';
85
+ }
86
+ }
87
+
88
+ private createSpacer(): HTMLDivElement {
89
+ const div = document.createElement('div');
90
+ div.style.flex = '1 1 auto';
91
+ return div;
92
+ }
93
+
94
+ private createIcon(svgContent: string, action: () => void): HTMLDivElement {
95
+ const icon = document.createElement('div');
96
+ icon.style.width = '18px';
97
+ icon.style.height = '18px';
98
+ icon.style.borderRadius = '2px';
99
+ icon.style.margin = '6px';
100
+ icon.innerHTML = svgContent;
101
+ const onClickHandle = () => {
102
+ action();
103
+ };
104
+ const onMouseOverHandle = () => {
105
+ icon.style.backgroundColor = '#f0f0f0';
106
+ };
107
+ const onMouseOutHandle = () => {
108
+ icon.style.backgroundColor = 'transparent';
109
+ };
110
+ icon.addEventListener('click', onClickHandle);
111
+ icon.addEventListener('mouseover', onMouseOverHandle);
112
+ icon.addEventListener('mouseout', onMouseOutHandle);
113
+ this.eventMap.set(icon, [onClickHandle, onMouseOutHandle, onMouseOverHandle]);
114
+ return icon;
115
+ }
116
+
117
+ private clearHTMLEventListeners() {
118
+ this.eventMap.forEach((value, key) => {
119
+ if (key) {
120
+ const [clickEvent, mouseOutEvent, mouseOverEvent] = value;
121
+ key.removeEventListener('click', clickEvent);
122
+ key.removeEventListener('mouseover', mouseOverEvent);
123
+ key.removeEventListener('mouseout', mouseOutEvent);
124
+ }
125
+ });
126
+ }
127
+
128
+ dispose() {
129
+ this.removeAllListeners();
130
+ this.clearHTMLEventListeners();
131
+ }
132
+ }
@@ -1,6 +1,4 @@
1
- import { type RoomUser, type UserManager } from "@netless/forge-room";
2
- import EventEmitter from "eventemitter3";
3
- import * as Y from "yjs";
1
+ import { AbstractApplicationPermissions, ApplicationPermissionEvents } from '@netless/forge-room';
4
2
 
5
3
  export enum ForgeSlidePermissionFlag {
6
4
  /**
@@ -27,7 +25,7 @@ export enum ForgeSlidePermissionFlag {
27
25
  ForgeSlidePermissionFlag.clickAnim
28
26
  }
29
27
 
30
- export interface ForgeSlidePermissionEvents {
28
+ export interface ForgeSlidePermissionEvents extends ApplicationPermissionEvents {
31
29
  /**
32
30
  * 当用户权限变更时触发
33
31
  * @param { string } userId 对应 userId
@@ -37,123 +35,18 @@ export interface ForgeSlidePermissionEvents {
37
35
  change: (userId: string, flags: ForgeSlidePermissionFlag[], value: number) => void;
38
36
  }
39
37
 
40
- export class ForgeSlidePermissions extends EventEmitter<ForgeSlidePermissionEvents> {
41
-
42
- private requestUserMap: (userId: string) => Y.Map<any>;
43
- private userManager: UserManager;
44
- private observers: Map<string, any> = new Map();
45
-
46
- public constructor(
47
- userManager: UserManager,
48
- requestUserMap: (userId: string) => Y.Map<any>,
49
- ) {
50
- super();
51
- this.userManager = userManager;
52
- this.requestUserMap = requestUserMap;
53
- this.createModel(this.userManager.selfId);
54
- this.userManager.userIdList().forEach((userId) => {
55
- this.addObserve(userId);
56
- });
57
-
58
- this.userManager.on("join", this.handleUserJoin);
59
- this.userManager.on("leave", this.handleUserLeave);
60
- }
61
-
62
- private handleUserLeave = (user: RoomUser) => {
63
- const cb = this.observers.get(user.id);
64
- if (cb) {
65
- this.requestUserMap(user.id).unobserve(cb);
66
- }
67
- };
68
-
69
- private handleUserJoin = (user: RoomUser) => {
70
- this.addObserve(user.id);
71
- };
72
-
73
- private addObserve(userId: string) {
74
- const observer = (evt: Y.YMapEvent<any>) => {
75
- this.handleUserPermissionChange(userId, evt);
76
- };
77
- this.observers.set(userId, observer);
78
- this.requestUserMap(userId).observe(observer)
79
- }
80
-
81
- private createModel(userId: string) {
82
- const userMap = this.requestUserMap(userId);
83
- if (!userMap.has("permission")) {
84
- userMap.set("permission", 0);
85
- }
86
- }
87
-
88
- private handleUserPermissionChange(userId: string, evt: Y.YMapEvent<any>) {
89
- for (const [key, value] of evt.changes.keys.entries()) {
90
- if (key === "permission") {
91
- if (value.action === "add" || value.action === "update") {
92
- const newValue = this.requestUserMap(userId).get("permission");
93
- this.emit("change", userId, this.resolveFlags(newValue), newValue);
94
- }
95
- }
96
- }
97
- }
98
-
99
- /**
38
+ export class ForgeSlidePermissions extends AbstractApplicationPermissions<ForgeSlidePermissionFlag, ForgeSlidePermissionEvents> {
39
+ /**
100
40
  * 解析权限列表组合
101
41
  * @param {number} value - 权限数字值
102
42
  * @return {WhiteboardPermissionFlag[]} - 权限列表
103
43
  */
104
- public resolveFlags(value: number): ForgeSlidePermissionFlag[] {
105
- return [
106
- ForgeSlidePermissionFlag.changePage,
107
- ForgeSlidePermissionFlag.changeStep,
108
- ForgeSlidePermissionFlag.clickAnim
109
- ].filter(v => (v & value) !== 0)
110
- }
111
-
112
- /**
113
- * 获取权限列表组合对应的数值
114
- * @param { string } userId 不传表示获取自己
115
- */
116
- public getPermissionValue(userId?: string): number {
117
- return this.requestUserMap(userId ?? this.userManager.selfId).get("permission") ?? 0;
118
- }
119
-
120
- /**
121
- * 获取权限列表
122
- * @param {string=} userId 可选, 不传表示获取自己
123
- */
124
- public getPermissionFlags(userId?: string): ForgeSlidePermissionFlag[] {
125
- const value = this.requestUserMap(userId ?? this.userManager.selfId).get("permission") ?? 0;
126
- return this.resolveFlags(value);
127
- }
128
-
129
- /**
130
- * 返回对应 userId 是否有相应权限
131
- * @param {string=} userId 可选, 不传表示返回自己是否有相应权限
132
- * @param {WhiteboardPermissionFlag} flag
133
- */
134
- public hasPermission(flag: ForgeSlidePermissionFlag, userId?: string): boolean {
135
- return ((this.requestUserMap(userId ?? this.userManager.selfId).get("permission") ?? 0) & flag) !== 0;
136
- }
137
-
138
- /**
139
- * 添加权限
140
- * @param {WhiteboardPermissionFlag} flag 权限标记
141
- * @param {string=} userId 可选, 为 userId 添加权限, 不传表示为自己添加权限
142
- */
143
- public addPermission(flag: ForgeSlidePermissionFlag, userId?: string) {
144
- const userMap = this.requestUserMap(userId ?? this.userManager.selfId);
145
- const oldValue = userMap.get("permission") ?? 0;
146
- this.requestUserMap(userId ?? this.userManager.selfId).set("permission", oldValue | flag);
147
- }
148
-
149
- /**
150
- * 移除权限
151
- * @param {WhiteboardPermissionFlag} flag 权限标记
152
- * @param {string=} userId 可选, 为 userId 移除权限, 不传表示为自己移除权限
153
- */
154
- public removePermission(flag: ForgeSlidePermissionFlag, userId?: string) {
155
- const userMap = this.requestUserMap(userId ?? this.userManager.selfId);
156
- const oldValue = userMap.get("permission") ?? 0;
157
- this.requestUserMap(userId ?? this.userManager.selfId).set("permission", oldValue & (~flag));
158
- }
159
- }
44
+ public resolveFlags(value: number): ForgeSlidePermissionFlag[] {
45
+ return [
46
+ ForgeSlidePermissionFlag.changePage,
47
+ ForgeSlidePermissionFlag.changeStep,
48
+ ForgeSlidePermissionFlag.clickAnim,
49
+ ].filter(v => (v & value) !== 0);
50
+ }
51
+
52
+ }
@@ -1,91 +1,113 @@
1
- import {SlideApplicationOption} from "./SlideApplication";
2
- import EventEmitter from "eventemitter3";
1
+ import { SlideApplicationOption } from './SlideApplication';
2
+ import EventEmitter from 'eventemitter3';
3
3
 
4
4
  interface SideBarViewEvents {
5
5
  pageChange: (index: number) => void;
6
6
  }
7
7
 
8
8
  export class SideBarView extends EventEmitter<SideBarViewEvents> {
9
- public readonly root: HTMLDivElement = document.createElement("div");
10
- private itemList: HTMLDivElement[] = [];
9
+ public readonly root: HTMLDivElement = document.createElement('div');
10
+ private isShow: boolean = false;
11
+ private eventsMap: Map<HTMLDivElement, (() => void)[]> = new Map();
11
12
 
12
- public constructor() {
13
- super();
14
- this.root.style.backgroundColor = '#eee';
15
- this.root.className = "slide-sidebar";
16
- this.root.style.width = "240px";
17
- this.root.style.height = "100%";
18
- this.root.style.position = "absolute";
19
- this.root.style.left = "-240px";
20
- this.root.style.top = "0";
21
- this.root.style.zIndex = "5";
22
- this.root.style.transition = "left 0.3s ease-in-out";
23
- this.root.style.overflow = "auto";
24
- this.root.style.border = "1px solid #ccc";
25
- this.root.style.boxShadow = "0 0 10px rgba(0, 0, 0, 0.1)";
26
- this.root.style.display = "flex";
27
- this.root.style.flexDirection = "column";
28
- this.root.style.justifyContent = "flex-start";
29
- this.root.style.alignItems = "center";
13
+ public constructor() {
14
+ super();
15
+ this.root.style.backgroundColor = '#eee';
16
+ this.root.className = 'forge-slide-sidebar';
17
+ this.root.style.width = '240px';
18
+ this.root.style.height = '100%';
19
+ this.root.style.position = 'absolute';
20
+ this.root.style.left = '-240px';
21
+ this.root.style.top = '0';
22
+ this.root.style.zIndex = '5';
23
+ this.root.style.transition = 'left 0.3s ease-in-out';
24
+ this.root.style.overflow = 'auto';
25
+ this.root.style.display = 'flex';
26
+ this.root.style.flexDirection = 'column';
27
+ this.root.style.justifyContent = 'flex-start';
28
+ this.root.style.alignItems = 'center';
29
+ }
30
30
 
31
- }
32
-
33
- private onMouseOver = (itemContainer: HTMLDivElement) => {
34
- itemContainer.style.borderColor = "#ccc";
35
- }
36
-
37
- private onMouseOut = (itemContainer: HTMLDivElement) => {
38
- itemContainer.style.borderColor = "transparent";
39
- }
31
+ get isShowSideBar(): boolean {
32
+ return this.isShow;
33
+ }
40
34
 
41
- private onClickHandle = (index: number) => {
42
- this.emit("pageChange", index);
43
- }
35
+ public initialize(slideCount: number, option: SlideApplicationOption): void {
36
+ for (let i = 1; i <= slideCount; i++) {
37
+ const itemContainer = document.createElement('div');
38
+ itemContainer.style.width = '60%';
39
+ itemContainer.style.display = 'flex';
40
+ itemContainer.style.justifyContent = 'center';
41
+ itemContainer.style.alignItems = 'flex-start';
42
+ itemContainer.style.position = 'relative';
43
+ itemContainer.style.borderRadius = '4px';
44
+ itemContainer.style.transition = 'border-color .3s';
45
+ itemContainer.style.marginBottom = '10px';
46
+
47
+ const onMouseOverHandle = () => {
48
+ itemContainer.style.borderColor = '#ccc';
49
+ };
50
+ const onMouseOutHandle = () => {
51
+ itemContainer.style.borderColor = 'transparent';
52
+ };
53
+ const onClickHandle = () => {
54
+ this.emit('pageChange', i);
55
+ };
44
56
 
45
- public initialize(slideCount: number, option: SlideApplicationOption): void {
46
- for (let i = 1; i <= slideCount; i++) {
47
- const itemContainer = document.createElement("div");
48
- this.itemList.push(itemContainer);
49
- itemContainer.style.width = "60%";
50
- itemContainer.style.display = "flex";
51
- itemContainer.style.justifyContent = "center";
52
- itemContainer.style.alignItems = "flex-start";
53
- itemContainer.style.border = "7px solid transparent";
54
- itemContainer.style.position = "relative";
55
- itemContainer.style.borderRadius = "4px"
56
- itemContainer.style.transition = "border-color .3s";
57
- itemContainer.style.marginBottom = "10px";
57
+ itemContainer.addEventListener('click', onClickHandle);
58
+ itemContainer.addEventListener('mouseover', onMouseOverHandle);
59
+ itemContainer.addEventListener('mouseout', onMouseOutHandle);
60
+ this.eventsMap.set(itemContainer, [onClickHandle, onMouseOverHandle, onMouseOutHandle]);
58
61
 
59
- itemContainer.addEventListener("mouseover", () => this.onMouseOver(itemContainer))
60
- itemContainer.addEventListener("mouseout", () => this.onMouseOut(itemContainer))
61
- itemContainer.addEventListener("click", () => this.onClickHandle(i))
62
+ const pageIndex = document.createElement('span');
63
+ pageIndex.textContent = `${i}`;
64
+ pageIndex.style.position = 'absolute';
65
+ pageIndex.style.top = '1px';
66
+ pageIndex.style.left = '-10px';
67
+ pageIndex.style.transform = 'translate(-100%)';
68
+ pageIndex.style.fontSize = '12px';
69
+ pageIndex.style.color = '#5f5f5f';
62
70
 
63
- const pageIndex = document.createElement("span");
64
- pageIndex.textContent = `${i}`;
65
- pageIndex.style.position = "absolute";
66
- pageIndex.style.top = "1px";
67
- pageIndex.style.left = "-10px";
68
- pageIndex.style.transform = "translate(-100%)";
69
- pageIndex.style.fontSize = "12px";
70
- pageIndex.style.color = "#5f5f5f";
71
+ const preview = document.createElement('img');
72
+ preview.style.width = '100%';
73
+ preview.style.display = 'inline-block';
74
+ preview.src = `${option.prefix}/${option.taskId}/preview/${i}.png`;
71
75
 
72
- const preview = document.createElement("img");
73
- preview.style.width = "100%";
74
- preview.style.display = "inline-block";
75
- preview.src = `${option.prefix}/${option.taskId}/preview/${i}.png`;
76
+ itemContainer.appendChild(preview);
77
+ itemContainer.appendChild(pageIndex);
76
78
 
77
- itemContainer.appendChild(preview);
78
- itemContainer.appendChild(pageIndex);
79
+ this.root.appendChild(itemContainer);
80
+ }
81
+ }
79
82
 
80
- this.root.appendChild(itemContainer);
81
- }
83
+ public hidden() {
84
+ if (!this.root) {
85
+ return;
82
86
  }
87
+ this.root.style.left = '-240px';
88
+ this.root.style.border = 'none';
89
+ this.root.style.boxShadow = 'none';
90
+ this.isShow = false;
91
+ }
83
92
 
84
- public dispose() {
85
- this.itemList.forEach(item => {
86
- item.removeEventListener("mouseover", () => this.onMouseOver(item))
87
- item.removeEventListener("mouseout", () => this.onMouseOut(item))
88
- })
93
+ public show() {
94
+ if (!this.root) {
95
+ return;
89
96
  }
97
+ this.root.style.left = '0';
98
+ this.root.style.border = '1px solid #ccc';
99
+ this.root.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
100
+ this.isShow = true;
101
+ }
102
+
103
+ public dispose() {
104
+ this.removeAllListeners();
105
+ this.eventsMap.forEach((handlers, element) => {
106
+ const [clickEvent, mouseOverEvent, mouseOutEvent] = handlers;
107
+ element.removeEventListener('click', clickEvent);
108
+ element.removeEventListener('mouseover', mouseOverEvent);
109
+ element.removeEventListener('mouseout', mouseOutEvent);
110
+ });
111
+ }
90
112
 
91
113
  }
package/src/Slide.ts CHANGED
@@ -1,6 +1,6 @@
1
- import EventEmitter from "eventemitter3";
2
- import { ApplicationInstanceType } from "@netless/forge-room";
3
- import { ForgeSlidePermissionFlag, ForgeSlidePermissions } from "./ForgeSlidePermession";
1
+ import EventEmitter from 'eventemitter3';
2
+ import { ApplicationInstanceType } from '@netless/forge-room';
3
+ import { ForgeSlidePermissionFlag, ForgeSlidePermissions } from './ForgeSlidePermession';
4
4
 
5
5
  export interface SlideEvents {
6
6
  /**
@@ -39,56 +39,57 @@ export interface SlideEvents {
39
39
 
40
40
  export class SlideForge extends EventEmitter<SlideEvents> implements ApplicationInstanceType {
41
41
 
42
- public readonly view!: HTMLDivElement;
43
- public readonly permissions!: ForgeSlidePermissions;
44
- public readonly footView!: HTMLDivElement;
45
- /**
42
+ public readonly view!: HTMLDivElement;
43
+ public readonly permissions!: ForgeSlidePermissions;
44
+ public readonly footView!: HTMLDivElement;
45
+ public readonly sideBarView!: HTMLDivElement;
46
+ /**
46
47
  * 当前页面索引, 从 0 开始
47
48
  */
48
- public readonly pageIndex!: number;
49
- /**
49
+ public readonly pageIndex!: number;
50
+ /**
50
51
  * 总页数
51
52
  */
52
- public readonly pageCount!: number;
53
- /**
53
+ public readonly pageCount!: number;
54
+ /**
54
55
  * 切换到参数指定页面, index 从 0 开始
55
56
  * @param {number} index 页面索引
56
57
  */
57
- public goto!: (index: number) => void
58
- /**
58
+ public goto!: (index: number) => void;
59
+ /**
59
60
  * 下一步, 如果已经是本页的最后一步, 则切换到下一页
60
61
  */
61
- public nextStep!: () => void
62
- /**
62
+ public nextStep!: () => void;
63
+ /**
63
64
  * 上一步, 如果已经是本页的第一步, 则切换到上一页
64
65
  */
65
- public prevStep!: () => void
66
- /**
66
+ public prevStep!: () => void;
67
+ /**
67
68
  * 下一页, 如果是最后一页, 则不执行任何操作
68
69
  */
69
- public nextPage!: () => void
70
- /**
70
+ public nextPage!: () => void;
71
+ /**
71
72
  * 上一页, 如果是第一页, 则不执行任何操作
72
73
  */
73
- public prevPage!: () => void
74
- /**
74
+ public prevPage!: () => void;
75
+ /**
75
76
  * 切换侧栏显示状态
76
77
  */
77
- public sideBarToggle!: () => void
78
+ public sideBarToggle!: () => void;
78
79
 
79
- /**
80
+ /**
80
81
  * 获取预览图图片内容, base64 编码
81
82
  * @param {number} index 页面索引
82
83
  */
83
- public imgContent!: (index: number) => Promise<string>;
84
- /**
84
+ public imgContent!: (index: number) => Promise<string>;
85
+ /**
85
86
  * 获取预览图图片链接
86
87
  * @param {number} index 页面索引
87
88
  */
88
- public imgUrl!: (index: number) => Promise<string>;
89
- /**
89
+ public imgUrl!: (index: number) => Promise<string>;
90
+ /**
90
91
  * 获取预览图图片尺寸
91
92
  * @param {number} index 页面索引
92
93
  */
93
- public imgSize!: (index: number) => Promise<{width: number, height: number}>;
94
+ public imgSize!: (index: number) => Promise<{width: number, height: number}>;
94
95
  }