@idraw/core 0.4.0-beta.17 → 0.4.0-beta.19
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/esm/config.d.ts +1 -0
- package/dist/esm/config.js +1 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/middleware/info/draw-info.d.ts +31 -0
- package/dist/esm/middleware/info/draw-info.js +110 -0
- package/dist/esm/middleware/info/index.d.ts +3 -0
- package/dist/esm/middleware/info/index.js +110 -0
- package/dist/esm/middleware/info/types.d.ts +3 -0
- package/dist/esm/middleware/info/types.js +1 -0
- package/dist/esm/middleware/layout-selector/config.d.ts +6 -0
- package/dist/esm/middleware/layout-selector/config.js +6 -0
- package/dist/esm/middleware/layout-selector/index.d.ts +3 -0
- package/dist/esm/middleware/layout-selector/index.js +251 -0
- package/dist/esm/middleware/layout-selector/types.d.ts +12 -0
- package/dist/esm/middleware/layout-selector/types.js +2 -0
- package/dist/esm/middleware/layout-selector/util.d.ts +5 -0
- package/dist/esm/middleware/layout-selector/util.js +93 -0
- package/dist/esm/middleware/ruler/index.d.ts +2 -1
- package/dist/esm/middleware/ruler/index.js +3 -2
- package/dist/esm/middleware/ruler/types.d.ts +3 -0
- package/dist/esm/middleware/ruler/types.js +1 -0
- package/dist/esm/middleware/ruler/util.d.ts +6 -1
- package/dist/esm/middleware/ruler/util.js +55 -1
- package/dist/esm/middleware/scroller/index.d.ts +2 -1
- package/dist/esm/middleware/scroller/types.d.ts +9 -0
- package/dist/esm/middleware/scroller/types.js +1 -0
- package/dist/esm/middleware/scroller/util.js +1 -1
- package/dist/esm/middleware/selector/index.d.ts +4 -1
- package/dist/esm/middleware/selector/index.js +17 -9
- package/dist/index.global.js +825 -99
- package/dist/index.global.min.js +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { selectColor, disableColor } from './config';
|
|
2
|
+
function drawControllerBox(ctx, boxVertexes) {
|
|
3
|
+
ctx.setLineDash([]);
|
|
4
|
+
ctx.fillStyle = '#FFFFFF';
|
|
5
|
+
ctx.beginPath();
|
|
6
|
+
ctx.moveTo(boxVertexes[0].x, boxVertexes[0].y);
|
|
7
|
+
ctx.lineTo(boxVertexes[1].x, boxVertexes[1].y);
|
|
8
|
+
ctx.lineTo(boxVertexes[2].x, boxVertexes[2].y);
|
|
9
|
+
ctx.lineTo(boxVertexes[3].x, boxVertexes[3].y);
|
|
10
|
+
ctx.closePath();
|
|
11
|
+
ctx.fill();
|
|
12
|
+
ctx.strokeStyle = selectColor;
|
|
13
|
+
ctx.lineWidth = 2;
|
|
14
|
+
ctx.beginPath();
|
|
15
|
+
ctx.moveTo(boxVertexes[0].x, boxVertexes[0].y);
|
|
16
|
+
ctx.lineTo(boxVertexes[1].x, boxVertexes[1].y);
|
|
17
|
+
ctx.lineTo(boxVertexes[2].x, boxVertexes[2].y);
|
|
18
|
+
ctx.lineTo(boxVertexes[3].x, boxVertexes[3].y);
|
|
19
|
+
ctx.closePath();
|
|
20
|
+
ctx.stroke();
|
|
21
|
+
}
|
|
22
|
+
function drawControllerCross(ctx, opts) {
|
|
23
|
+
const { vertexes, strokeStyle, lineWidth } = opts;
|
|
24
|
+
ctx.setLineDash([]);
|
|
25
|
+
ctx.strokeStyle = strokeStyle;
|
|
26
|
+
ctx.lineWidth = lineWidth;
|
|
27
|
+
ctx.beginPath();
|
|
28
|
+
ctx.moveTo(vertexes[0].x, vertexes[0].y);
|
|
29
|
+
ctx.lineTo(vertexes[2].x, vertexes[2].y);
|
|
30
|
+
ctx.closePath();
|
|
31
|
+
ctx.stroke();
|
|
32
|
+
ctx.beginPath();
|
|
33
|
+
ctx.moveTo(vertexes[1].x, vertexes[1].y);
|
|
34
|
+
ctx.lineTo(vertexes[3].x, vertexes[3].y);
|
|
35
|
+
ctx.closePath();
|
|
36
|
+
ctx.stroke();
|
|
37
|
+
}
|
|
38
|
+
function drawControllerLine(ctx, opts) {
|
|
39
|
+
const { start, end, centerVertexes, disabled } = opts;
|
|
40
|
+
const lineWidth = disabled === true ? 1 : 2;
|
|
41
|
+
const strokeStyle = disabled === true ? disableColor : selectColor;
|
|
42
|
+
ctx.setLineDash([]);
|
|
43
|
+
ctx.strokeStyle = strokeStyle;
|
|
44
|
+
ctx.lineWidth = lineWidth;
|
|
45
|
+
ctx.beginPath();
|
|
46
|
+
ctx.moveTo(start.x, start.y);
|
|
47
|
+
ctx.lineTo(end.x, end.y);
|
|
48
|
+
ctx.closePath();
|
|
49
|
+
ctx.stroke();
|
|
50
|
+
if (disabled === true) {
|
|
51
|
+
drawControllerCross(ctx, {
|
|
52
|
+
vertexes: centerVertexes,
|
|
53
|
+
lineWidth,
|
|
54
|
+
strokeStyle
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function drawLayoutController(ctx, opts) {
|
|
59
|
+
const { controller, operations } = opts;
|
|
60
|
+
const { topLeft, topRight, bottomLeft, bottomRight, topMiddle, rightMiddle, bottomMiddle, leftMiddle } = controller;
|
|
61
|
+
drawControllerLine(ctx, { start: topLeft.center, end: topRight.center, centerVertexes: topMiddle.vertexes, disabled: !!(operations === null || operations === void 0 ? void 0 : operations.disableTop) });
|
|
62
|
+
drawControllerLine(ctx, { start: topRight.center, end: bottomRight.center, centerVertexes: rightMiddle.vertexes, disabled: !!(operations === null || operations === void 0 ? void 0 : operations.disableRight) });
|
|
63
|
+
drawControllerLine(ctx, { start: bottomRight.center, end: bottomLeft.center, centerVertexes: bottomMiddle.vertexes, disabled: !!(operations === null || operations === void 0 ? void 0 : operations.disableBottom) });
|
|
64
|
+
drawControllerLine(ctx, { start: bottomLeft.center, end: topLeft.center, centerVertexes: leftMiddle.vertexes, disabled: !!(operations === null || operations === void 0 ? void 0 : operations.disableLeft) });
|
|
65
|
+
const disabledOpts = {
|
|
66
|
+
lineWidth: 1,
|
|
67
|
+
strokeStyle: disableColor
|
|
68
|
+
};
|
|
69
|
+
if ((operations === null || operations === void 0 ? void 0 : operations.disableTopLeft) === true) {
|
|
70
|
+
drawControllerCross(ctx, Object.assign({ vertexes: topLeft.vertexes }, disabledOpts));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
drawControllerBox(ctx, topLeft.vertexes);
|
|
74
|
+
}
|
|
75
|
+
if ((operations === null || operations === void 0 ? void 0 : operations.disableTopRight) === true) {
|
|
76
|
+
drawControllerCross(ctx, Object.assign({ vertexes: topRight.vertexes }, disabledOpts));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
drawControllerBox(ctx, topRight.vertexes);
|
|
80
|
+
}
|
|
81
|
+
if ((operations === null || operations === void 0 ? void 0 : operations.disableBottomRight) === true) {
|
|
82
|
+
drawControllerCross(ctx, Object.assign({ vertexes: bottomRight.vertexes }, disabledOpts));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
drawControllerBox(ctx, bottomRight.vertexes);
|
|
86
|
+
}
|
|
87
|
+
if ((operations === null || operations === void 0 ? void 0 : operations.disableBottomLeft) === true) {
|
|
88
|
+
drawControllerCross(ctx, Object.assign({ vertexes: bottomLeft.vertexes }, disabledOpts));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
drawControllerBox(ctx, bottomLeft.vertexes);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { BoardMiddleware, CoreEventMap } from '@idraw/types';
|
|
2
|
+
import type { DeepRulerSharedStorage } from './types';
|
|
2
3
|
export declare const middlewareEventRuler = "@middleware/show-ruler";
|
|
3
|
-
export declare const MiddlewareRuler: BoardMiddleware<
|
|
4
|
+
export declare const MiddlewareRuler: BoardMiddleware<DeepRulerSharedStorage, CoreEventMap>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getViewScaleInfoFromSnapshot, getViewSizeInfoFromSnapshot } from '@idraw/util';
|
|
2
|
-
import { drawRulerBackground, drawXRuler, drawYRuler, calcXRulerScaleList, calcYRulerScaleList, drawUnderGrid } from './util';
|
|
2
|
+
import { drawRulerBackground, drawXRuler, drawYRuler, calcXRulerScaleList, calcYRulerScaleList, drawUnderGrid, drawScrollerSelectedArea } from './util';
|
|
3
3
|
export const middlewareEventRuler = '@middleware/show-ruler';
|
|
4
4
|
export const MiddlewareRuler = (opts) => {
|
|
5
|
-
const { boardContent, viewer, eventHub } = opts;
|
|
5
|
+
const { boardContent, viewer, eventHub, calculator } = opts;
|
|
6
6
|
const { helperContext, underContext } = boardContent;
|
|
7
7
|
let show = true;
|
|
8
8
|
let showGrid = true;
|
|
@@ -29,6 +29,7 @@ export const MiddlewareRuler = (opts) => {
|
|
|
29
29
|
if (show === true) {
|
|
30
30
|
const viewScaleInfo = getViewScaleInfoFromSnapshot(snapshot);
|
|
31
31
|
const viewSizeInfo = getViewSizeInfoFromSnapshot(snapshot);
|
|
32
|
+
drawScrollerSelectedArea(helperContext, { snapshot, calculator });
|
|
32
33
|
drawRulerBackground(helperContext, { viewScaleInfo, viewSizeInfo });
|
|
33
34
|
const xList = calcXRulerScaleList({ viewScaleInfo, viewSizeInfo });
|
|
34
35
|
drawXRuler(helperContext, { scaleList: xList });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ViewScaleInfo, ViewSizeInfo, ViewContext2D } from '@idraw/types';
|
|
1
|
+
import type { ViewScaleInfo, ViewSizeInfo, ViewContext2D, BoardViewerFrameSnapshot, ViewCalculator } from '@idraw/types';
|
|
2
|
+
import type { DeepRulerSharedStorage } from './types';
|
|
2
3
|
interface RulerScale {
|
|
3
4
|
num: number;
|
|
4
5
|
showNum: boolean;
|
|
@@ -30,4 +31,8 @@ export declare function drawUnderGrid(ctx: ViewContext2D, opts: {
|
|
|
30
31
|
viewScaleInfo: ViewScaleInfo;
|
|
31
32
|
viewSizeInfo: ViewSizeInfo;
|
|
32
33
|
}): void;
|
|
34
|
+
export declare function drawScrollerSelectedArea(ctx: ViewContext2D, opts: {
|
|
35
|
+
snapshot: BoardViewerFrameSnapshot<DeepRulerSharedStorage>;
|
|
36
|
+
calculator: ViewCalculator;
|
|
37
|
+
}): void;
|
|
33
38
|
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { formatNumber, rotateByCenter } from '@idraw/util';
|
|
1
|
+
import { formatNumber, rotateByCenter, getViewScaleInfoFromSnapshot, getViewSizeInfoFromSnapshot } from '@idraw/util';
|
|
2
|
+
import { keySelectedElementList, keyActionType } from '../selector';
|
|
2
3
|
const rulerSize = 16;
|
|
3
4
|
const background = '#FFFFFFA8';
|
|
4
5
|
const borderColor = '#00000080';
|
|
@@ -10,6 +11,7 @@ const fontWeight = 100;
|
|
|
10
11
|
const gridColor = '#AAAAAA20';
|
|
11
12
|
const gridKeyColor = '#AAAAAA40';
|
|
12
13
|
const lineSize = 1;
|
|
14
|
+
const selectedAreaColor = '#196097';
|
|
13
15
|
function calcRulerScaleList(opts) {
|
|
14
16
|
const { scale, viewLength, viewOffset } = opts;
|
|
15
17
|
const list = [];
|
|
@@ -185,3 +187,55 @@ export function drawUnderGrid(ctx, opts) {
|
|
|
185
187
|
ctx.stroke();
|
|
186
188
|
}
|
|
187
189
|
}
|
|
190
|
+
export function drawScrollerSelectedArea(ctx, opts) {
|
|
191
|
+
const { snapshot, calculator } = opts;
|
|
192
|
+
const { sharedStore } = snapshot;
|
|
193
|
+
const selectedElementList = sharedStore[keySelectedElementList];
|
|
194
|
+
const actionType = sharedStore[keyActionType];
|
|
195
|
+
if (['select', 'drag', 'drag-list', 'drag-list-end'].includes(actionType) && selectedElementList.length > 0) {
|
|
196
|
+
const viewScaleInfo = getViewScaleInfoFromSnapshot(snapshot);
|
|
197
|
+
const viewSizeInfo = getViewSizeInfoFromSnapshot(snapshot);
|
|
198
|
+
const rangeRectInfoList = [];
|
|
199
|
+
const xAreaStartList = [];
|
|
200
|
+
const xAreaEndList = [];
|
|
201
|
+
const yAreaStartList = [];
|
|
202
|
+
const yAreaEndList = [];
|
|
203
|
+
selectedElementList.forEach((elem) => {
|
|
204
|
+
const rectInfo = calculator.calcViewRectInfoFromRange(elem.uuid, {
|
|
205
|
+
viewScaleInfo,
|
|
206
|
+
viewSizeInfo
|
|
207
|
+
});
|
|
208
|
+
if (rectInfo) {
|
|
209
|
+
rangeRectInfoList.push(rectInfo);
|
|
210
|
+
xAreaStartList.push(rectInfo.left.x);
|
|
211
|
+
xAreaEndList.push(rectInfo.right.x);
|
|
212
|
+
yAreaStartList.push(rectInfo.top.y);
|
|
213
|
+
yAreaEndList.push(rectInfo.bottom.y);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
if (!(rangeRectInfoList.length > 0)) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const xAreaStart = Math.min(...xAreaStartList);
|
|
220
|
+
const xAreaEnd = Math.max(...xAreaEndList);
|
|
221
|
+
const yAreaStart = Math.min(...yAreaStartList);
|
|
222
|
+
const yAreaEnd = Math.max(...yAreaEndList);
|
|
223
|
+
ctx.globalAlpha = 1;
|
|
224
|
+
ctx.beginPath();
|
|
225
|
+
ctx.moveTo(xAreaStart, 0);
|
|
226
|
+
ctx.lineTo(xAreaEnd, 0);
|
|
227
|
+
ctx.lineTo(xAreaEnd, rulerSize);
|
|
228
|
+
ctx.lineTo(xAreaStart, rulerSize);
|
|
229
|
+
ctx.fillStyle = selectedAreaColor;
|
|
230
|
+
ctx.closePath();
|
|
231
|
+
ctx.fill();
|
|
232
|
+
ctx.beginPath();
|
|
233
|
+
ctx.moveTo(0, yAreaStart);
|
|
234
|
+
ctx.lineTo(rulerSize, yAreaStart);
|
|
235
|
+
ctx.lineTo(rulerSize, yAreaEnd);
|
|
236
|
+
ctx.lineTo(0, yAreaEnd);
|
|
237
|
+
ctx.fillStyle = selectedAreaColor;
|
|
238
|
+
ctx.closePath();
|
|
239
|
+
ctx.fill();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Point, ElementSize } from '@idraw/types';
|
|
2
|
+
import { keyXThumbRect, keyYThumbRect, keyPrevPoint, keyActivePoint, keyActiveThumbType } from './config';
|
|
3
|
+
export type DeepScrollerSharedStorage = {
|
|
4
|
+
[keyXThumbRect]: null | ElementSize;
|
|
5
|
+
[keyYThumbRect]: null | ElementSize;
|
|
6
|
+
[keyPrevPoint]: null | Point;
|
|
7
|
+
[keyActivePoint]: null | Point;
|
|
8
|
+
[keyActiveThumbType]: null | 'X' | 'Y';
|
|
9
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { keyXThumbRect, keyYThumbRect, keyPrevPoint, keyActivePoint, keyActiveThumbType } from './config';
|
|
@@ -2,7 +2,7 @@ import { getViewScaleInfoFromSnapshot, getViewSizeInfoFromSnapshot } from '@idra
|
|
|
2
2
|
import { keyActivePoint, keyActiveThumbType, keyPrevPoint, keyXThumbRect, keyYThumbRect } from './config';
|
|
3
3
|
const minScrollerWidth = 12;
|
|
4
4
|
const scrollerLineWidth = 16;
|
|
5
|
-
const scrollerThumbAlpha = 0.
|
|
5
|
+
const scrollerThumbAlpha = 0.3;
|
|
6
6
|
const scrollConfig = {
|
|
7
7
|
width: minScrollerWidth,
|
|
8
8
|
thumbColor: '#000000AA',
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { CoreEventMap } from '@idraw/types';
|
|
2
|
-
import type { BoardMiddleware, DeepSelectorSharedStorage } from './types';
|
|
2
|
+
import type { BoardMiddleware, ActionType, DeepSelectorSharedStorage } from './types';
|
|
3
|
+
import { keyActionType, keyResizeType, keyGroupQueue, keySelectedElementList } from './config';
|
|
4
|
+
export { keySelectedElementList, keyActionType, keyResizeType, keyGroupQueue };
|
|
5
|
+
export type { DeepSelectorSharedStorage, ActionType };
|
|
3
6
|
export declare const middlewareEventSelect: string;
|
|
4
7
|
export declare const middlewareEventSelectClear: string;
|
|
5
8
|
export declare const MiddlewareSelector: BoardMiddleware<DeepSelectorSharedStorage, CoreEventMap>;
|
|
@@ -5,6 +5,8 @@ import { getPointTarget, resizeElement, rotateElement, getSelectedListArea, calc
|
|
|
5
5
|
import { keyActionType, keyResizeType, keyAreaStart, keyAreaEnd, keyGroupQueue, keyGroupQueueVertexesList, keyHoverElement, keyHoverElementVertexes, keySelectedElementList, keySelectedElementListVertexes, keySelectedElementController, keySelectedElementPosition, keySelectedReferenceXLines, keySelectedReferenceYLines, keyIsMoving, controllerSize } from './config';
|
|
6
6
|
import { calcReferenceInfo } from './reference';
|
|
7
7
|
import { middlewareEventTextEdit } from '../text-editor';
|
|
8
|
+
import { eventChange } from '../../config';
|
|
9
|
+
export { keySelectedElementList, keyActionType, keyResizeType, keyGroupQueue };
|
|
8
10
|
export const middlewareEventSelect = '@middleware/select';
|
|
9
11
|
export const middlewareEventSelectClear = '@middleware/select-clear';
|
|
10
12
|
export const MiddlewareSelector = (opts) => {
|
|
@@ -200,6 +202,11 @@ export const MiddlewareSelector = (opts) => {
|
|
|
200
202
|
}) }));
|
|
201
203
|
triggerCursor(target);
|
|
202
204
|
if (target.type === null) {
|
|
205
|
+
if (sharer.getSharedStorage(keyHoverElement) || sharer.getSharedStorage(keyHoverElementVertexes)) {
|
|
206
|
+
sharer.setSharedStorage(keyHoverElement, null);
|
|
207
|
+
sharer.setSharedStorage(keyHoverElementVertexes, null);
|
|
208
|
+
viewer.drawFrame();
|
|
209
|
+
}
|
|
203
210
|
return;
|
|
204
211
|
}
|
|
205
212
|
if (target.type === 'over-element' &&
|
|
@@ -367,7 +374,7 @@ export const MiddlewareSelector = (opts) => {
|
|
|
367
374
|
type: 'updateElement',
|
|
368
375
|
content: {
|
|
369
376
|
element: elem,
|
|
370
|
-
position:
|
|
377
|
+
position: getElementPositionFromList(elem.uuid, data.elements) || []
|
|
371
378
|
}
|
|
372
379
|
},
|
|
373
380
|
viewSizeInfo,
|
|
@@ -417,21 +424,22 @@ export const MiddlewareSelector = (opts) => {
|
|
|
417
424
|
resizeType,
|
|
418
425
|
sharer
|
|
419
426
|
});
|
|
420
|
-
elems[0].angle = resizedElemSize.angle;
|
|
427
|
+
elems[0].angle = calculator.toGridNum(resizedElemSize.angle || 0);
|
|
421
428
|
}
|
|
422
429
|
else {
|
|
423
430
|
const resizedElemSize = resizeElement(elems[0], { scale, start: resizeStart, end: resizeEnd, resizeType, sharer });
|
|
424
|
-
elems[0].
|
|
425
|
-
elems[0].
|
|
431
|
+
const calcOpts = { ignore: !!elems[0].angle };
|
|
432
|
+
elems[0].x = calculator.toGridNum(resizedElemSize.x, calcOpts);
|
|
433
|
+
elems[0].y = calculator.toGridNum(resizedElemSize.y, calcOpts);
|
|
426
434
|
if (elems[0].type === 'group' && ((_c = elems[0].operations) === null || _c === void 0 ? void 0 : _c.deepResize) === true) {
|
|
427
435
|
deepResizeGroupElement(elems[0], {
|
|
428
|
-
w: calculator.toGridNum(resizedElemSize.w),
|
|
429
|
-
h: calculator.toGridNum(resizedElemSize.h)
|
|
436
|
+
w: calculator.toGridNum(resizedElemSize.w, calcOpts),
|
|
437
|
+
h: calculator.toGridNum(resizedElemSize.h, calcOpts)
|
|
430
438
|
});
|
|
431
439
|
}
|
|
432
440
|
else {
|
|
433
|
-
elems[0].w = calculator.toGridNum(resizedElemSize.w);
|
|
434
|
-
elems[0].h = calculator.toGridNum(resizedElemSize.h);
|
|
441
|
+
elems[0].w = calculator.toGridNum(resizedElemSize.w, calcOpts);
|
|
442
|
+
elems[0].h = calculator.toGridNum(resizedElemSize.h, calcOpts);
|
|
435
443
|
}
|
|
436
444
|
}
|
|
437
445
|
updateSelectedElementList([elems[0]]);
|
|
@@ -528,7 +536,7 @@ export const MiddlewareSelector = (opts) => {
|
|
|
528
536
|
if (type === 'resize') {
|
|
529
537
|
type = 'resizeElement';
|
|
530
538
|
}
|
|
531
|
-
eventHub.trigger(
|
|
539
|
+
eventHub.trigger(eventChange, { data, type });
|
|
532
540
|
}
|
|
533
541
|
viewer.drawFrame();
|
|
534
542
|
};
|