@realsee/dnalogel 2.0.0-alpha.5 → 2.0.0-alpha.6
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/CHANGELOG.md +6 -0
- package/dist/dnalogel.cjs.js +2 -2
- package/dist/dnalogel.es.js +186 -59
- package/dist/dnalogel.umd.js +2 -2
- package/dist/style.css +1 -1
- package/docs/.nojekyll +1 -0
- package/docs/assets/highlight.css +29 -0
- package/docs/assets/icons.css +1043 -0
- package/docs/assets/icons.png +0 -0
- package/docs/assets/icons@2x.png +0 -0
- package/docs/assets/main.js +52 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1413 -0
- package/docs/assets/widgets.png +0 -0
- package/docs/assets/widgets@2x.png +0 -0
- package/docs/classes/ModelRoomLabelController.html +20 -0
- package/docs/enums/FLOOR_PLAN_ATTACHED_TO.html +1 -0
- package/docs/enums/ModelFloorplanErrorType.html +1 -0
- package/docs/index.html +10 -0
- package/docs/interfaces/ModelChassisCompassPluginData.html +1 -0
- package/docs/interfaces/ModelChassisCompassPluginExportType.html +1 -0
- package/docs/interfaces/ModelChassisCompassPluginParameterType.html +1 -0
- package/docs/interfaces/ModelEntryDoorGuidePluginData.html +1 -0
- package/docs/interfaces/ModelEntryDoorGuidePluginExportType.html +1 -0
- package/docs/interfaces/ModelFloorplanParameterType.html +1 -0
- package/docs/interfaces/ModelFloorplanViewEvent.html +5 -0
- package/docs/interfaces/ModelRoomLabelPluginData.html +1 -0
- package/docs/interfaces/PanoCompassPluginData.html +1 -0
- package/docs/interfaces/PanoCompassPluginParameterType.html +1 -0
- package/docs/interfaces/PanoCursorRaycasterPluginExportType.html +11 -0
- package/docs/interfaces/PanoRulerPluginExportType.html +1 -0
- package/docs/interfaces/PanoRulerPluginOptions.html +1 -0
- package/docs/interfaces/PanoRulerPluginParameterType.html +1 -0
- package/docs/interfaces/RoomLabel.html +13 -0
- package/docs/interfaces/TopviewFloorplanPluginParameterType.html +1 -0
- package/docs/modules.html +26 -0
- package/libs/CSS3DRenderPlugin/index.js +1 -1
- package/libs/PanoCompassPlugin/Assets/roomInfoIcon.d.ts +1 -0
- package/libs/PanoCompassPlugin/Assets/roomInfoIcon.js +1 -0
- package/libs/PanoCompassPlugin/getRoomInfoInstance.d.ts +8 -0
- package/libs/PanoCompassPlugin/getRoomInfoInstance.js +48 -0
- package/libs/PanoCompassPlugin/index.d.ts +29 -3
- package/libs/PanoCompassPlugin/index.js +106 -36
- package/libs/PanoRulerPlugin/index.js +1 -0
- package/libs/PanoRulerPlugin/style.d.ts +1 -1
- package/libs/PanoRulerPlugin/style.js +1 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/Camera.svelte +3 -3
- package/libs/floorplan/ModelFloorplanPlugin/Components/Camera.svelte.map +1 -1
- package/libs/floorplan/ModelFloorplanPlugin/Controller.d.ts +2 -0
- package/libs/floorplan/ModelFloorplanPlugin/Controller.js +3 -1
- package/libs/floorplan/TopviewFloorplanPlugin/Controller.d.ts +2 -0
- package/libs/floorplan/TopviewFloorplanPlugin/Controller.js +4 -3
- package/libs/floorplan/constant.d.ts +5 -0
- package/libs/floorplan/constant.js +6 -0
- package/libs/floorplan/typings/floorplanServerData.d.ts +4 -0
- package/libs/index.d.ts +1 -0
- package/libs/index.js +2 -0
- package/libs/shared-utils/getPxmm.d.ts +6 -1
- package/libs/shared-utils/getPxmm.js +26 -12
- package/package.json +2 -1
|
@@ -23,7 +23,10 @@ const domSizeStyle = `${size / 16}rem`;
|
|
|
23
23
|
class="floorplan__camera-rotate"
|
|
24
24
|
style:width="{domSizeStyle}"
|
|
25
25
|
style:height="{domSizeStyle}"
|
|
26
|
+
style:left="{'-' + domSizeStyle}"
|
|
27
|
+
style:top="{'-' + domSizeStyle}"
|
|
26
28
|
style:transform="{`rotate(${rotate}deg)`}"
|
|
29
|
+
style:transform-origin="{`${domSizeStyle} ${domSizeStyle}`}"
|
|
27
30
|
style="background-image: {`url(${cameraImageUrl || CAMERA_IMAGE})`}"
|
|
28
31
|
></div>
|
|
29
32
|
</div>
|
|
@@ -37,9 +40,6 @@ const domSizeStyle = `${size / 16}rem`;
|
|
|
37
40
|
|
|
38
41
|
.floorplan__camera-rotate {
|
|
39
42
|
position: absolute;
|
|
40
|
-
left: 15px;
|
|
41
|
-
top: 15px;
|
|
42
|
-
transform-origin: 15px 15px;
|
|
43
43
|
background-repeat: no-repeat;
|
|
44
44
|
background-size: 100%;
|
|
45
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":"AAAA,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;;;;;;;;;;;;;;;;;;AAuBjB,CAAC,CAAC,MAAM;;AAER,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AAC7F,EAAE,CAAC;AACH,IAAI,KAAK,CAAC,CAAC,iBAAiB,CAAC,MAAM;AACnC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;AAC/B,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;AAChC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,IAAI,KAAK,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACvE,EAAE,CAAC,CAAC,CAAC,GAAG;AACR,CAAC,CAAC,GAAG;;AAEL,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AACrB,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC;AAC9B,IAAI,QAAQ,CAAC,CAAC,QAAQ;AACtB,IAAI,KAAK,CAAC,CAAC,CAAC;AACZ,IAAI,MAAM,CAAC,CAAC,CAAC;AACb,EAAE;;AAEF,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC;AAC5B,IAAI,QAAQ,CAAC,CAAC,QAAQ;AACtB,IAAI,
|
|
1
|
+
{"version":3,"mappings":"AAAA,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;;;;;;;;;;;;;;;;;;AAuBjB,CAAC,CAAC,MAAM;;AAER,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AAC7F,EAAE,CAAC;AACH,IAAI,KAAK,CAAC,CAAC,iBAAiB,CAAC,MAAM;AACnC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;AAC/B,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;AAChC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;AACpC,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;AACnC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;AAC/D,IAAI,KAAK,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACvE,EAAE,CAAC,CAAC,CAAC,GAAG;AACR,CAAC,CAAC,GAAG;;AAEL,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AACrB,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC;AAC9B,IAAI,QAAQ,CAAC,CAAC,QAAQ;AACtB,IAAI,KAAK,CAAC,CAAC,CAAC;AACZ,IAAI,MAAM,CAAC,CAAC,CAAC;AACb,EAAE;;AAEF,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC;AAC5B,IAAI,QAAQ,CAAC,CAAC,QAAQ;AACtB,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,MAAM;AAChC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC;AACzB,EAAE;AACF,CAAC,CAAC,KAAK;","names":[],"sources":["Camera.svelte"]}
|
|
@@ -2,6 +2,7 @@ import { Five, Subscribe } from '@realsee/five';
|
|
|
2
2
|
import type { FloorplanEventHandlers } from './typings/events.type';
|
|
3
3
|
import type { FloorplanServerData } from '../typings/floorplanServerData';
|
|
4
4
|
import type { FloorplanRoomItem } from '../typings/floorplanData';
|
|
5
|
+
import { FLOOR_PLAN_ATTACHED_TO } from '../constant';
|
|
5
6
|
export interface ModelFloorplanParameterType {
|
|
6
7
|
selector?: string | Element;
|
|
7
8
|
scale?: number;
|
|
@@ -12,6 +13,7 @@ export interface ModelFloorplanParameterType {
|
|
|
12
13
|
ruleLabelsEnable?: boolean;
|
|
13
14
|
roomLabelsEnable?: boolean;
|
|
14
15
|
cameraImageUrl?: string;
|
|
16
|
+
attachedTo?: FLOOR_PLAN_ATTACHED_TO;
|
|
15
17
|
getLabelElement?: (room: FloorplanRoomItem) => Element | null;
|
|
16
18
|
}
|
|
17
19
|
export declare type ModelFloorplanPluginsConfigs = Omit<ModelFloorplanParameterType, 'selector' | 'scale'>;
|
|
@@ -98,7 +98,8 @@ export default class ModelFloorplanPluginController {
|
|
|
98
98
|
const width = max.x - min.x;
|
|
99
99
|
const height = max.y - min.y;
|
|
100
100
|
// 每毫米对应的 px 值
|
|
101
|
-
const
|
|
101
|
+
const options = this.configs.attachedTo ? { attachedTo: this.configs.attachedTo } : undefined;
|
|
102
|
+
const pxmm = getPxmm(this.five, this.wrapper, this.floorIndex, options);
|
|
102
103
|
const _width = Math.ceil(width * pxmm);
|
|
103
104
|
const _height = Math.ceil(height * pxmm);
|
|
104
105
|
if (this.size.width === _width && this.size.height === _height)
|
|
@@ -225,6 +226,7 @@ export default class ModelFloorplanPluginController {
|
|
|
225
226
|
if (shownFloor === null)
|
|
226
227
|
return;
|
|
227
228
|
this.floorIndex = shownFloor;
|
|
229
|
+
this.updateSize();
|
|
228
230
|
this.render();
|
|
229
231
|
};
|
|
230
232
|
handleModelLoaded = () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Five } from '@realsee/five';
|
|
2
2
|
import type { FloorplanServerData } from '../typings/floorplanServerData';
|
|
3
3
|
import type { FloorplanRoomItem } from '../typings/floorplanData';
|
|
4
|
+
import { FLOOR_PLAN_ATTACHED_TO } from '../constant';
|
|
4
5
|
export interface TopviewFloorplanPluginParameterType {
|
|
5
6
|
selector?: string | Element;
|
|
6
7
|
scale?: number;
|
|
@@ -12,6 +13,7 @@ export interface TopviewFloorplanPluginParameterType {
|
|
|
12
13
|
ruleLabelsEnable?: boolean;
|
|
13
14
|
roomLabelsEnable?: boolean;
|
|
14
15
|
preventRoomClick?: boolean;
|
|
16
|
+
attachedTo?: FLOOR_PLAN_ATTACHED_TO;
|
|
15
17
|
getLabelElement?: (room: FloorplanRoomItem) => Element | null;
|
|
16
18
|
}
|
|
17
19
|
export declare type TopviewFloorplanPluginReturnType = TopviewFloorplanPluginController;
|
|
@@ -62,6 +62,7 @@ export class TopviewFloorplanPluginController {
|
|
|
62
62
|
if (shownFloor === null)
|
|
63
63
|
return;
|
|
64
64
|
this.floorIndex = shownFloor;
|
|
65
|
+
this.updateSize();
|
|
65
66
|
this.render();
|
|
66
67
|
};
|
|
67
68
|
/** panoIndex 改变时,更新 floorIndex */
|
|
@@ -109,8 +110,8 @@ export class TopviewFloorplanPluginController {
|
|
|
109
110
|
};
|
|
110
111
|
show() {
|
|
111
112
|
this.visible = true;
|
|
112
|
-
this.updateSize();
|
|
113
113
|
this.five.model.show(this.floorIndex);
|
|
114
|
+
this.updateSize();
|
|
114
115
|
const renderDuration = 500;
|
|
115
116
|
const modelOpacity = this.configs.modelOpacity;
|
|
116
117
|
if (typeof modelOpacity === 'number') {
|
|
@@ -142,7 +143,8 @@ export class TopviewFloorplanPluginController {
|
|
|
142
143
|
const width = max.x - min.x;
|
|
143
144
|
const height = max.y - min.y;
|
|
144
145
|
// 每毫米对应的 px 值
|
|
145
|
-
const
|
|
146
|
+
const options = this.configs.attachedTo ? { attachedTo: this.configs.attachedTo } : undefined;
|
|
147
|
+
const pxmm = getPxmm(this.five, this.wrapper, this.floorIndex, options);
|
|
146
148
|
const _width = Math.ceil(width * pxmm);
|
|
147
149
|
const _height = Math.ceil(height * pxmm);
|
|
148
150
|
this.pxmm = pxmm;
|
|
@@ -157,7 +159,6 @@ export class TopviewFloorplanPluginController {
|
|
|
157
159
|
return;
|
|
158
160
|
const { getLabelElement, cameraImageUrl, preventRoomClick, hoverEnable, compassEnable, roomLabelsEnable, ruleLabelsEnable, } = this.configs;
|
|
159
161
|
const handleClick = preventRoomClick ? () => false : undefined;
|
|
160
|
-
console.log('🚀 ~ TopviewFloorplanPluginController ~ handleClick', handleClick);
|
|
161
162
|
const props = {
|
|
162
163
|
five: this.five,
|
|
163
164
|
pxmm: this.pxmm,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export var FLOOR_PLAN_ATTACHED_TO;
|
|
2
|
+
(function (FLOOR_PLAN_ATTACHED_TO) {
|
|
3
|
+
FLOOR_PLAN_ATTACHED_TO[FLOOR_PLAN_ATTACHED_TO["FLOOR"] = 1] = "FLOOR";
|
|
4
|
+
FLOOR_PLAN_ATTACHED_TO[FLOOR_PLAN_ATTACHED_TO["CEILING"] = 2] = "CEILING";
|
|
5
|
+
FLOOR_PLAN_ATTACHED_TO[FLOOR_PLAN_ATTACHED_TO["BOUNDING_CENTER"] = 3] = "BOUNDING_CENTER";
|
|
6
|
+
})(FLOOR_PLAN_ATTACHED_TO || (FLOOR_PLAN_ATTACHED_TO = {}));
|
package/libs/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type { PanoCursorRaycasterPluginExportType } from './PanoCursorRaycasterP
|
|
|
4
4
|
export { default as PanoCursorRaycasterPlugin } from './PanoCursorRaycasterPlugin';
|
|
5
5
|
export type { ModelRoomLabelController, ModelRoomLabelPluginData, RoomLabel, ModelRoomLabelPluginReturnType, ModelRoomLabelPluginParameters, } from './ModelRoomLabelPlugin';
|
|
6
6
|
export { default as ModelRoomLabelPlugin } from './ModelRoomLabelPlugin';
|
|
7
|
+
export * from './floorplan/constant';
|
|
7
8
|
export type { TopviewFloorplanPluginReturnType, TopviewFloorplanPluginParameterType, } from './floorplan/TopviewFloorplanPlugin';
|
|
8
9
|
export { default as TopviewFloorplanPlugin } from './floorplan/TopviewFloorplanPlugin';
|
|
9
10
|
export type { PanoFloorplanRadarPluginReturnType, PanoFloorplanRadarPluginParameterType, } from './floorplan/PanoFloorplanRadarPlugin';
|
package/libs/index.js
CHANGED
|
@@ -2,6 +2,8 @@ export { default as ModelViewPlugin } from './ModelViewPlugin';
|
|
|
2
2
|
export { default as CSS3DRenderPlugin } from './CSS3DRenderPlugin';
|
|
3
3
|
export { default as PanoCursorRaycasterPlugin } from './PanoCursorRaycasterPlugin';
|
|
4
4
|
export { default as ModelRoomLabelPlugin } from './ModelRoomLabelPlugin';
|
|
5
|
+
// floorplan
|
|
6
|
+
export * from './floorplan/constant';
|
|
5
7
|
export { default as TopviewFloorplanPlugin } from './floorplan/TopviewFloorplanPlugin';
|
|
6
8
|
export { default as PanoFloorplanRadarPlugin } from './floorplan/PanoFloorplanRadarPlugin';
|
|
7
9
|
export { default as ModelFloorplanPlugin } from './floorplan/ModelFloorplanPlugin';
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { Five } from '@realsee/five';
|
|
2
|
+
import { FLOOR_PLAN_ATTACHED_TO } from '../floorplan/constant';
|
|
3
|
+
interface GetPxmmOption {
|
|
4
|
+
attachedTo: FLOOR_PLAN_ATTACHED_TO;
|
|
5
|
+
}
|
|
2
6
|
/**
|
|
3
7
|
* 获取「在俯视图」状态下,模型 mm 与屏幕像素 px 的对应关系,即每 mm 对应多少 px
|
|
4
8
|
* @param five five
|
|
5
9
|
*/
|
|
6
|
-
export default function getPxmm(five: Five, container: Element): number;
|
|
10
|
+
export default function getPxmm(five: Five, container: Element, floorIndex: number, options?: GetPxmmOption): number;
|
|
11
|
+
export {};
|
|
@@ -1,20 +1,34 @@
|
|
|
1
|
+
import { FLOOR_PLAN_ATTACHED_TO } from '../floorplan/constant';
|
|
1
2
|
import * as THREE from 'three';
|
|
2
3
|
/**
|
|
3
4
|
* 获取「在俯视图」状态下,模型 mm 与屏幕像素 px 的对应关系,即每 mm 对应多少 px
|
|
4
5
|
* @param five five
|
|
5
6
|
*/
|
|
6
|
-
export default function getPxmm(five, container) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
export default function getPxmm(five, container, floorIndex, options) {
|
|
8
|
+
const maxFloorIndex = Math.max(...five.work.observers.map((ob) => ob.floorIndex));
|
|
9
|
+
function getFloorY(floorIndex) {
|
|
10
|
+
return floorIndex > maxFloorIndex
|
|
11
|
+
? five.model.bounding.max.y
|
|
12
|
+
: Math.max(...five.work.observers
|
|
13
|
+
.filter((ob) => ob.floorIndex === floorIndex)
|
|
14
|
+
.map((ob) => ob.standingPosition.y));
|
|
15
|
+
}
|
|
16
|
+
function getY() {
|
|
17
|
+
const currentFloorY = getFloorY(floorIndex);
|
|
18
|
+
const nextFloorY = getFloorY(floorIndex + 1);
|
|
19
|
+
const attachedTo = options?.attachedTo || FLOOR_PLAN_ATTACHED_TO.BOUNDING_CENTER;
|
|
20
|
+
if (attachedTo === FLOOR_PLAN_ATTACHED_TO.BOUNDING_CENTER)
|
|
21
|
+
return (five.model.bounding.max.y + five.model.bounding.min.y) / 2;
|
|
22
|
+
else if (attachedTo === FLOOR_PLAN_ATTACHED_TO.CEILING)
|
|
23
|
+
return nextFloorY;
|
|
24
|
+
else
|
|
25
|
+
return currentFloorY;
|
|
26
|
+
}
|
|
27
|
+
const y = getY();
|
|
28
|
+
const originPosition = new THREE.Vector3(0, y, 0);
|
|
29
|
+
const originPositionXUnit = new THREE.Vector3(1, y, 0);
|
|
30
|
+
const mouse = originPosition.clone().project(five.camera);
|
|
31
|
+
const xUnitMouse = originPositionXUnit.clone().project(five.camera);
|
|
18
32
|
const pxmm = Math.abs((xUnitMouse.x - mouse.x) / 1000) * (container.getBoundingClientRect().width / 2);
|
|
19
33
|
return pxmm;
|
|
20
34
|
}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"author": "REALSEE-DEVELOPER",
|
|
6
6
|
"repository": "https://github.com/realsee-developer/dnalogel.git",
|
|
7
7
|
"private": false,
|
|
8
|
-
"version": "2.0.0-alpha.
|
|
8
|
+
"version": "2.0.0-alpha.6",
|
|
9
9
|
"license": "SEE LICENSE IN TERMS.txt",
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build:dev": "yarn tsb && vite build --watch",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"files": [
|
|
20
20
|
"libs",
|
|
21
21
|
"dist",
|
|
22
|
+
"docs",
|
|
22
23
|
"TERMS.txt"
|
|
23
24
|
],
|
|
24
25
|
"devDependencies": {
|