@threekit-tools/treble 0.0.90-next-07 → 0.0.90-next-08

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.
@@ -1,4 +1,4 @@
1
- import { IWalls, IVerticesState, ICoordinate2D, IFeature, IFeatures, ICoordinatesLine, ISpacesStateProps, IElementAddress, IFeatureName, IVertex, IFeaturesHydrated, IElementUi, IElementName, IActiveElement, IEnclosedSpace, IFeatureDoor, IWallsValidationConfig } from './types';
1
+ import { IWalls, IVerticesState, ICoordinate2D, IFeature, IFeatures, ICoordinatesLine, ISpacesStateProps, IElementAddress, IFeatureName, IVertex, IFeaturesHydrated, IElementUi, IElementName, IActiveElement, IUnits, IEnclosedSpace, IFeatureDoor, IWallsValidationConfig } from './types';
2
2
  import type { IHydratedAttribute } from '../../types';
3
3
  export declare class SpacesState {
4
4
  private _config;
@@ -15,6 +15,7 @@ export declare class SpacesState {
15
15
  private _zoomLimits;
16
16
  private _translate;
17
17
  private _translateLimits;
18
+ private _unit;
18
19
  private _validationConfig;
19
20
  private _state;
20
21
  constructor(config: ISpacesStateProps);
@@ -56,6 +57,8 @@ export declare class SpacesState {
56
57
  get zoomMin(): number;
57
58
  get zoomMax(): number;
58
59
  setZoom(delta: number): number | undefined;
60
+ get unit(): IUnits;
61
+ setUnit(unit: IUnits): IUnits;
59
62
  get translate(): ICoordinate2D;
60
63
  get translateMin(): ICoordinate2D;
61
64
  get translateMax(): ICoordinate2D;
@@ -365,10 +365,10 @@ var SpacesState = (function () {
365
365
  return loops.reduce(function (output, loop) {
366
366
  var screenSpaceArea = Math.round((0, geometry_1.getPolygonArea)(loop));
367
367
  var area = screenSpaceArea * Math.pow(_this._config.config.scale, 2);
368
- var convertedArea = (0, dataHandlers_1.convertAreaUnit)(area, types_1.IUnits.METER, _this._config.config.unit);
368
+ var convertedArea = (0, dataHandlers_1.convertAreaUnit)(area, types_1.IUnits.METER, _this.unit);
369
369
  var enclosedSpace = {
370
370
  loop: loop.map(function (point) { return _this.transformPointToCanvas(point); }),
371
- area: (0, dataHandlers_1.prepAreaForUser)(convertedArea, _this._config.config.unit),
371
+ area: (0, dataHandlers_1.prepAreaForUser)(convertedArea, _this.unit),
372
372
  center: loop.reduce(function (centerPoint, point) {
373
373
  centerPoint[0] += point[0] / loop.length;
374
374
  centerPoint[1] += point[1] / loop.length;
@@ -447,6 +447,17 @@ var SpacesState = (function () {
447
447
  this._zoom = preppedZoom;
448
448
  return this.zoom;
449
449
  };
450
+ Object.defineProperty(SpacesState.prototype, "unit", {
451
+ get: function () {
452
+ return this._unit;
453
+ },
454
+ enumerable: false,
455
+ configurable: true
456
+ });
457
+ SpacesState.prototype.setUnit = function (unit) {
458
+ this._unit = unit;
459
+ return this._unit;
460
+ };
450
461
  Object.defineProperty(SpacesState.prototype, "translate", {
451
462
  get: function () {
452
463
  return this._translate;
@@ -573,10 +584,10 @@ var SpacesState = (function () {
573
584
  };
574
585
  SpacesState.prototype.getWallDimensions = function (line) {
575
586
  var lineLength = (0, geometry_1.getLengthOfLineSegment)(line) * this._config.config.scale;
576
- var convertedVal = (0, dataHandlers_1.convertLengthUnit)(lineLength, types_1.IUnits.METER, this._config.config.unit);
587
+ var convertedVal = (0, dataHandlers_1.convertLengthUnit)(lineLength, types_1.IUnits.METER, this.unit);
577
588
  return {
578
589
  line: line,
579
- label: (0, dataHandlers_1.prepLengthForUser)(convertedVal, this._config.config.unit),
590
+ label: (0, dataHandlers_1.prepLengthForUser)(convertedVal, this.unit),
580
591
  };
581
592
  };
582
593
  SpacesState.prototype.getWallDimensionsByIndex = function (index) {
@@ -600,7 +611,7 @@ var SpacesState = (function () {
600
611
  var offset = _a.offset, length = _a.length;
601
612
  var featureLine = (0, geometry_1.getLineAtOffsetOnLineSegment)(line, offset, length);
602
613
  var featureLength = (0, geometry_1.getLengthOfLineSegment)(featureLine);
603
- var unit = constants_1.UNIT_LABELS[_this._config.config.unit];
614
+ var unit = constants_1.UNIT_LABELS[_this.unit];
604
615
  var scale = _this._config.config.scale;
605
616
  if (!i) {
606
617
  var startLine = [line[0], featureLine[0]];
@@ -28,6 +28,16 @@ interface IUseSpaces {
28
28
  value: number;
29
29
  handleChange: (value: number) => void;
30
30
  };
31
+ unit: {
32
+ value: IUnits;
33
+ options: Array<{
34
+ label: string;
35
+ value: IUnits;
36
+ selected: boolean;
37
+ handleSelect: () => void;
38
+ }>;
39
+ handleChange: (unit: IUnits) => void;
40
+ };
31
41
  translate: {
32
42
  handleChange: (delta: ICoordinate2D) => void;
33
43
  };
@@ -48,18 +48,19 @@ var store_1 = require("../../store");
48
48
  var spaces_1 = require("../../store/spaces");
49
49
  var useThreekitInitStatus_1 = __importDefault(require("../useThreekitInitStatus"));
50
50
  var useSpaces = function (props) {
51
- var _a;
51
+ var _a, _b, _c, _d;
52
52
  var attributesState = (0, useConfigurator_1.default)()[0];
53
53
  var hasLoaded = (0, useThreekitInitStatus_1.default)();
54
54
  var dispatch = (0, store_1.useThreekitDispatch)();
55
55
  var layouts = (0, store_1.useThreekitSelector)(spaces_1.getLayouts);
56
56
  var zoom = (0, store_1.useThreekitSelector)(spaces_1.getZoom);
57
+ var unit = (0, store_1.useThreekitSelector)(spaces_1.getUnit);
57
58
  var translation = (0, store_1.useThreekitSelector)(spaces_1.getTranslation);
58
59
  var modeValue = (0, store_1.useThreekitSelector)(spaces_1.getMode);
59
60
  var showDimensions = (0, store_1.useThreekitSelector)(spaces_1.getShowDimensions);
60
61
  var angleSnappingEnabled = (0, store_1.useThreekitSelector)(spaces_1.getAngleSnappingEnabled);
61
- var _b = (0, react_1.useState)(null), selectedElement = _b[0], setSelectedElement = _b[1];
62
- var _c = (0, react_1.useState)(null), selectedWallAsset = _c[0], setSelectedWallAsset = _c[1];
62
+ var _e = (0, react_1.useState)(null), selectedElement = _e[0], setSelectedElement = _e[1];
63
+ var _f = (0, react_1.useState)(null), selectedWallAsset = _f[0], setSelectedWallAsset = _f[1];
63
64
  var canvasRef = (0, react_1.useRef)(null);
64
65
  var selectElementPending = (0, react_1.useRef)(null);
65
66
  var translationAnchorRef = (0, react_1.useRef)(null);
@@ -74,26 +75,33 @@ var useSpaces = function (props) {
74
75
  : themes_1.default[themes_1.IThemes.DEFAULT],
75
76
  }, props.config);
76
77
  var attributeNames = Object.assign(constants_1.attributeNameDefaults, props.attributes);
77
- var spacesRef = (0, react_1.useRef)(new SpacesState_1.default(__assign(__assign({}, props), { config: preppedConfig, attributes: attributeNames })));
78
- var drawSpaces = function () { return spacesRef.current.drawSpaces(canvasRef.current); };
78
+ var spacesRef = (0, react_1.useRef)();
79
79
  (0, react_1.useEffect)(function () {
80
- var _a;
80
+ spacesRef.current = new SpacesState_1.default(__assign(__assign({}, props), { config: preppedConfig, attributes: attributeNames }));
81
+ }, []);
82
+ (0, react_1.useEffect)(function () {
83
+ var _a, _b, _c;
81
84
  if (!selectedWallAsset && (attributesState === null || attributesState === void 0 ? void 0 : attributesState[attributeNames[types_1.IElements.WALL]]))
82
85
  setSelectedWallAsset(((_a = attributesState === null || attributesState === void 0 ? void 0 : attributesState[attributeNames[types_1.IElements.WALL]]) === null || _a === void 0 ? void 0 : _a.values[0].assetId) || null);
83
86
  var attributesDelinked = JSON.parse(JSON.stringify(attributesState));
84
- spacesRef.current.setAttributesToState(attributesDelinked);
85
- drawSpaces();
87
+ (_b = spacesRef.current) === null || _b === void 0 ? void 0 : _b.setAttributesToState(attributesDelinked);
88
+ (_c = spacesRef.current) === null || _c === void 0 ? void 0 : _c.drawSpaces(canvasRef.current);
86
89
  }, [attributesState]);
87
90
  (0, react_1.useEffect)(function () {
88
91
  var _a;
92
+ if (!spacesRef.current)
93
+ return;
89
94
  if (zoom &&
90
95
  ((_a = props.config) === null || _a === void 0 ? void 0 : _a.zoomDefault) &&
91
96
  props.config.zoomDefault >= spacesRef.current.zoomMin &&
92
97
  spacesRef.current.zoomMax >= props.config.zoomDefault)
93
98
  updateZoom(props.config.zoomDefault);
99
+ updateUnit(preppedConfig.unit);
94
100
  }, []);
95
101
  (0, react_1.useEffect)(function () {
96
102
  var _a, _b;
103
+ if (!spacesRef.current)
104
+ return;
97
105
  if (canvasRef === null || canvasRef === void 0 ? void 0 : canvasRef.current) {
98
106
  spacesRef.current.canvasDimensions = [
99
107
  canvasRef.current.width,
@@ -129,6 +137,8 @@ var useSpaces = function (props) {
129
137
  };
130
138
  });
131
139
  (0, react_1.useEffect)(function () {
140
+ if (!spacesRef.current)
141
+ return;
132
142
  spacesRef.current.showDimensions = showDimensions;
133
143
  spacesRef.current.angleSnappingEnabled = angleSnappingEnabled;
134
144
  spacesRef.current.selectedElement = selectedElement
@@ -137,7 +147,7 @@ var useSpaces = function (props) {
137
147
  index: selectedElement.path[1],
138
148
  }
139
149
  : null;
140
- drawSpaces();
150
+ spacesRef.current.drawSpaces(canvasRef.current);
141
151
  }, [selectedElement, showDimensions, angleSnappingEnabled]);
142
152
  (0, react_1.useEffect)(function () {
143
153
  if (!hasLoaded)
@@ -152,11 +162,22 @@ var useSpaces = function (props) {
152
162
  }));
153
163
  }, [hasLoaded, JSON.stringify(props.layouts)]);
154
164
  var updateZoom = function (value) {
165
+ if (!spacesRef.current)
166
+ return;
155
167
  var newZoom = spacesRef.current.setZoom(value);
156
168
  if (!newZoom)
157
169
  return;
158
170
  dispatch((0, spaces_1.setZoom)(newZoom));
159
- drawSpaces();
171
+ spacesRef.current.drawSpaces(canvasRef.current);
172
+ };
173
+ var updateUnit = function (unit) {
174
+ if (!spacesRef.current)
175
+ return;
176
+ var newUnit = spacesRef.current.setUnit(unit);
177
+ if (!newUnit)
178
+ return;
179
+ dispatch((0, spaces_1.setUnit)(newUnit));
180
+ spacesRef.current.drawSpaces(canvasRef.current);
160
181
  };
161
182
  var handleScrollToZoom = function (e) {
162
183
  var _a, _b;
@@ -170,6 +191,8 @@ var useSpaces = function (props) {
170
191
  var handleSelectModeHover = function (e) {
171
192
  if (!canvasRef.current)
172
193
  return;
194
+ if (!spacesRef.current)
195
+ return;
173
196
  if (modeValue !== types_1.IModes.SELECT)
174
197
  return;
175
198
  if (spacesRef.current.activeElement !== null)
@@ -183,6 +206,8 @@ var useSpaces = function (props) {
183
206
  var _a;
184
207
  if (!canvasRef.current)
185
208
  return;
209
+ if (!spacesRef.current)
210
+ return;
186
211
  if (modeValue !== types_1.IModes.SELECT)
187
212
  return;
188
213
  var cursorPoint = [e.offsetX, e.offsetY];
@@ -202,6 +227,8 @@ var useSpaces = function (props) {
202
227
  selectElementPending.current = element;
203
228
  };
204
229
  var handleMoveSelectedElement = function (e) {
230
+ if (!spacesRef.current)
231
+ return;
205
232
  if (modeValue !== types_1.IModes.SELECT)
206
233
  return;
207
234
  if (!canvasRef.current)
@@ -215,6 +242,8 @@ var useSpaces = function (props) {
215
242
  return;
216
243
  if (!canvasRef.current)
217
244
  return;
245
+ if (!spacesRef.current)
246
+ return;
218
247
  if (spacesRef.current.selectedElement || !translationAnchorRef.current)
219
248
  return;
220
249
  var delta = [
@@ -230,6 +259,8 @@ var useSpaces = function (props) {
230
259
  return;
231
260
  if (!canvasRef.current)
232
261
  return;
262
+ if (!spacesRef.current)
263
+ return;
233
264
  if (!((_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
234
265
  spacesRef.current.cancelMoveActiveElement(canvasRef.current);
235
266
  return;
@@ -246,6 +277,8 @@ var useSpaces = function (props) {
246
277
  var handleDrawWallStart = function (e) {
247
278
  if (modeValue !== types_1.IModes.DRAW)
248
279
  return;
280
+ if (!spacesRef.current)
281
+ return;
249
282
  var cursorPoint = [e.offsetX, e.offsetY];
250
283
  spacesRef.current.startDrawNewWall(cursorPoint);
251
284
  };
@@ -254,6 +287,8 @@ var useSpaces = function (props) {
254
287
  return;
255
288
  if (!canvasRef.current)
256
289
  return;
290
+ if (!spacesRef.current)
291
+ return;
257
292
  var cursorPoint = [e.offsetX, e.offsetY];
258
293
  if (spacesRef.current.isDrawWallActive)
259
294
  spacesRef.current.drawNewWall(canvasRef.current, cursorPoint);
@@ -264,6 +299,8 @@ var useSpaces = function (props) {
264
299
  return;
265
300
  if (!canvasRef.current)
266
301
  return;
302
+ if (!spacesRef.current)
303
+ return;
267
304
  if (!selectedWallAsset)
268
305
  return;
269
306
  if (!((_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
@@ -276,13 +313,14 @@ var useSpaces = function (props) {
276
313
  if (!attribute)
277
314
  return undefined;
278
315
  var values = attribute.values.map(function (val) { return (__assign(__assign({}, val), { add: function (addToWallIndex, offset) {
279
- return spacesRef.current.addFeature(type, {
316
+ var _a;
317
+ return (_a = spacesRef.current) === null || _a === void 0 ? void 0 : _a.addFeature(type, {
280
318
  assetId: val.assetId,
281
319
  length: constants_1.FEATURE_LENGTH,
282
320
  offset: offset,
283
321
  }, addToWallIndex);
284
322
  } })); });
285
- var value = attribute.value.map(function (val, i) { return (__assign(__assign({}, val), { delete: function () { return spacesRef.current.deleteFeature(type, i); } })); });
323
+ var value = attribute.value.map(function (val, i) { return (__assign(__assign({}, val), { delete: function () { var _a; return (_a = spacesRef.current) === null || _a === void 0 ? void 0 : _a.deleteFeature(type, i); } })); });
286
324
  return __assign(__assign({}, attribute), { values: values, value: value });
287
325
  };
288
326
  var prepWallAttributeForOutput = function (attribute) {
@@ -307,7 +345,9 @@ var useSpaces = function (props) {
307
345
  var handleSetMode = function (mode) {
308
346
  if (mode === modeValue)
309
347
  return;
310
- drawSpaces();
348
+ if (!spacesRef.current)
349
+ return;
350
+ spacesRef.current.drawSpaces(canvasRef.current);
311
351
  dispatch((0, spaces_1.setMode)(mode));
312
352
  setSelectedElement(null);
313
353
  };
@@ -343,15 +383,17 @@ var useSpaces = function (props) {
343
383
  setSelectedElement(null);
344
384
  };
345
385
  var handleChangeTranslate = function (delta) {
386
+ if (!spacesRef.current)
387
+ return;
346
388
  spacesRef.current.translate = [
347
389
  spacesRef.current.translate[0] + delta[0],
348
390
  spacesRef.current.translate[1] + delta[1],
349
391
  ];
350
392
  dispatch((0, spaces_1.setTranslation)(spacesRef.current.translate));
351
- drawSpaces();
393
+ spacesRef.current.drawSpaces(canvasRef.current);
352
394
  };
353
395
  return {
354
- draw: drawSpaces,
396
+ draw: ((_b = spacesRef.current) === null || _b === void 0 ? void 0 : _b.drawSpaces(canvasRef.current)) || (function () { }),
355
397
  canvasRef: canvasRef,
356
398
  selectedElement: selectedElement === null
357
399
  ? selectedElement
@@ -378,11 +420,21 @@ var useSpaces = function (props) {
378
420
  handleToggle: handleToggleAngleSnapping,
379
421
  },
380
422
  zoom: {
381
- min: spacesRef.current.zoomMin,
382
- max: spacesRef.current.zoomMax,
423
+ min: ((_c = spacesRef.current) === null || _c === void 0 ? void 0 : _c.zoomMin) || 1,
424
+ max: ((_d = spacesRef.current) === null || _d === void 0 ? void 0 : _d.zoomMax) || 1,
383
425
  value: zoom || constants_1.ZOOM_DEFAULT,
384
426
  handleChange: updateZoom,
385
427
  },
428
+ unit: {
429
+ value: unit,
430
+ options: [types_1.IUnits.FEET, types_1.IUnits.METER, types_1.IUnits.INCH, types_1.IUnits.CM].map(function (el) { return ({
431
+ value: el,
432
+ label: el,
433
+ selected: unit === el,
434
+ handleSelect: function () { return updateUnit(el); },
435
+ }); }),
436
+ handleChange: updateUnit,
437
+ },
386
438
  translate: {
387
439
  handleChange: handleChangeTranslate,
388
440
  },
@@ -1,6 +1,6 @@
1
1
  import { RootState, ThreekitDispatch } from './index';
2
2
  import { IConfiguration } from '../types';
3
- import { ICoordinate2D, IModes } from '../hooks/useSpaces/types';
3
+ import { ICoordinate2D, IModes, IUnits } from '../hooks/useSpaces/types';
4
4
  interface ILayout {
5
5
  label: string;
6
6
  configuration: IConfiguration;
@@ -16,6 +16,7 @@ interface IAttributeMap {
16
16
  export interface SpacesState {
17
17
  mode: IModes;
18
18
  layouts: Array<ILayout>;
19
+ unit: IUnits;
19
20
  zoom: null | number;
20
21
  translation: null | ICoordinate2D;
21
22
  showDimensions: boolean;
@@ -23,6 +24,7 @@ export interface SpacesState {
23
24
  }
24
25
  export declare const setLayouts: import("@reduxjs/toolkit").ActionCreatorWithPayload<ILayout[], string>;
25
26
  export declare const setZoom: import("@reduxjs/toolkit").ActionCreatorWithPayload<number, string>;
27
+ export declare const setUnit: import("@reduxjs/toolkit").ActionCreatorWithPayload<IUnits, string>;
26
28
  export declare const setTranslation: import("@reduxjs/toolkit").ActionCreatorWithPayload<ICoordinate2D, string>;
27
29
  export declare const setMode: import("@reduxjs/toolkit").ActionCreatorWithPayload<IModes, string>;
28
30
  export declare const setShowDimensions: import("@reduxjs/toolkit").ActionCreatorWithPayload<boolean, string>;
@@ -30,6 +32,7 @@ export declare const setAngleSnappingEnabled: import("@reduxjs/toolkit").ActionC
30
32
  declare const reducer: import("redux").Reducer<SpacesState, import("redux").AnyAction>;
31
33
  export declare const getMode: (state: RootState) => IModes;
32
34
  export declare const getLayouts: (state: RootState) => Array<ILayout>;
35
+ export declare const getUnit: (state: RootState) => IUnits;
33
36
  export declare const getZoom: (state: RootState) => number | null;
34
37
  export declare const getTranslation: (state: RootState) => ICoordinate2D | null;
35
38
  export declare const getShowDimensions: (state: RootState) => boolean;
@@ -59,13 +59,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
59
59
  return (mod && mod.__esModule) ? mod : { "default": mod };
60
60
  };
61
61
  Object.defineProperty(exports, "__esModule", { value: true });
62
- exports.hydrateLayouts = exports.getAngleSnappingEnabled = exports.getShowDimensions = exports.getTranslation = exports.getZoom = exports.getLayouts = exports.getMode = exports.setAngleSnappingEnabled = exports.setShowDimensions = exports.setMode = exports.setTranslation = exports.setZoom = exports.setLayouts = void 0;
62
+ exports.hydrateLayouts = exports.getAngleSnappingEnabled = exports.getShowDimensions = exports.getTranslation = exports.getZoom = exports.getUnit = exports.getLayouts = exports.getMode = exports.setAngleSnappingEnabled = exports.setShowDimensions = exports.setMode = exports.setTranslation = exports.setUnit = exports.setZoom = exports.setLayouts = void 0;
63
63
  var toolkit_1 = require("@reduxjs/toolkit");
64
64
  var api_1 = __importDefault(require("../api"));
65
65
  var types_1 = require("../hooks/useSpaces/types");
66
66
  var findLoops_1 = require("../hooks/useSpaces/findLoops");
67
67
  exports.setLayouts = (0, toolkit_1.createAction)('treble/spaces/set-layouts');
68
68
  exports.setZoom = (0, toolkit_1.createAction)('treble/spaces/set-zoom');
69
+ exports.setUnit = (0, toolkit_1.createAction)('treble/spaces/set-unit');
69
70
  exports.setTranslation = (0, toolkit_1.createAction)('treble/spaces/set-translation');
70
71
  exports.setMode = (0, toolkit_1.createAction)('treble/spaces/set-mode');
71
72
  exports.setShowDimensions = (0, toolkit_1.createAction)('treble/spaces/set-show-dimensions');
@@ -73,6 +74,7 @@ exports.setAngleSnappingEnabled = (0, toolkit_1.createAction)('treble/spaces/set
73
74
  var initialState = {
74
75
  mode: types_1.IModes.SELECT,
75
76
  layouts: [],
77
+ unit: types_1.IUnits.FEET,
76
78
  zoom: null,
77
79
  translation: null,
78
80
  showDimensions: true,
@@ -88,6 +90,9 @@ var reducer = (0, toolkit_1.createSlice)({
88
90
  builder.addCase(exports.setLayouts, function (state, action) {
89
91
  return __assign(__assign({}, state), { layouts: action.payload });
90
92
  });
93
+ builder.addCase(exports.setUnit, function (state, action) {
94
+ return __assign(__assign({}, state), { unit: action.payload });
95
+ });
91
96
  builder.addCase(exports.setZoom, function (state, action) {
92
97
  return __assign(__assign({}, state), { zoom: action.payload });
93
98
  });
@@ -109,6 +114,8 @@ var getLayouts = function (state) {
109
114
  return state.spaces.layouts;
110
115
  };
111
116
  exports.getLayouts = getLayouts;
117
+ var getUnit = function (state) { return state.spaces.unit; };
118
+ exports.getUnit = getUnit;
112
119
  var getZoom = function (state) { return state.spaces.zoom; };
113
120
  exports.getZoom = getZoom;
114
121
  var getTranslation = function (state) { return state.spaces.translation; };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threekit-tools/treble",
3
- "version": "0.0.90-next-07",
3
+ "version": "0.0.90-next-08",
4
4
  "author": "Amaan Saeed",
5
5
  "license": "MIT",
6
6
  "files": [