@threekit-tools/treble 0.0.90-next-06 → 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 } 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,8 @@ export declare class SpacesState {
15
15
  private _zoomLimits;
16
16
  private _translate;
17
17
  private _translateLimits;
18
+ private _unit;
19
+ private _validationConfig;
18
20
  private _state;
19
21
  constructor(config: ISpacesStateProps);
20
22
  get walls(): IWalls;
@@ -34,7 +36,7 @@ export declare class SpacesState {
34
36
  get verticesList(): Array<IVertex>;
35
37
  get verticesListToDraw(): Array<IVertex>;
36
38
  get features(): IFeatures;
37
- get featuresToDraw(): Record<string, IFeature[]>;
39
+ get featuresToDraw(): Record<string, IFeature[] | IFeatureDoor[]>;
38
40
  set features(features: IFeatures);
39
41
  get getHydratedFeatures(): undefined | IFeaturesHydrated;
40
42
  get featureCount(): number;
@@ -55,11 +57,15 @@ export declare class SpacesState {
55
57
  get zoomMin(): number;
56
58
  get zoomMax(): number;
57
59
  setZoom(delta: number): number | undefined;
60
+ get unit(): IUnits;
61
+ setUnit(unit: IUnits): IUnits;
58
62
  get translate(): ICoordinate2D;
59
63
  get translateMin(): ICoordinate2D;
60
64
  get translateMax(): ICoordinate2D;
61
65
  set translate(position: ICoordinate2D);
62
66
  get isDrawWallActive(): boolean;
67
+ get validationConfig(): IWallsValidationConfig;
68
+ set validationConfig(config: IWallsValidationConfig);
63
69
  transformLengthFromCanvas(length: number): number;
64
70
  transformLengthToCanvas(length: number): number;
65
71
  transformPointToCanvas(point: ICoordinate2D): ICoordinate2D;
@@ -73,7 +79,8 @@ export declare class SpacesState {
73
79
  private getWallConnectionCount;
74
80
  private getWallConnectionsHydrated;
75
81
  private getWallDimensions;
76
- private getWallDetailedDimensions;
82
+ private getWallDimensionsByIndex;
83
+ private getWallDetailedDimensionsByIndex;
77
84
  private getAllWallDimensionsToDraw;
78
85
  private shiftAllFeaturesOnWall;
79
86
  private addFeatureToWall;
@@ -97,7 +97,7 @@ var SpacesState = (function () {
97
97
  validators_1.areWallsIntersecting,
98
98
  validators_1.areWallsOrphaningFeatures,
99
99
  validators_1.areWallsDuplicated,
100
- ], validationData);
100
+ ], validationData, _this.validationConfig);
101
101
  var errorType = ((_b = _this._errorElement) === null || _b === void 0 ? void 0 : _b[0].type) || null;
102
102
  switch (errorType) {
103
103
  case types_1.IErrorTypes.HARD:
@@ -150,7 +150,7 @@ var SpacesState = (function () {
150
150
  wall: wall,
151
151
  features: _this.features,
152
152
  updatedFeature: featureUpdatesToValidate,
153
- });
153
+ }, _this.validationConfig);
154
154
  var errorType = ((_b = _this._errorElement) === null || _b === void 0 ? void 0 : _b[0].type) || null;
155
155
  switch (errorType) {
156
156
  case types_1.IErrorTypes.HARD:
@@ -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;
@@ -486,6 +497,16 @@ var SpacesState = (function () {
486
497
  enumerable: false,
487
498
  configurable: true
488
499
  });
500
+ Object.defineProperty(SpacesState.prototype, "validationConfig", {
501
+ get: function () {
502
+ return this._validationConfig;
503
+ },
504
+ set: function (config) {
505
+ this._validationConfig = config;
506
+ },
507
+ enumerable: false,
508
+ configurable: true
509
+ });
489
510
  SpacesState.prototype.transformLengthFromCanvas = function (length) {
490
511
  return length / this.zoomFactor;
491
512
  };
@@ -561,19 +582,22 @@ var SpacesState = (function () {
561
582
  return output;
562
583
  }, []);
563
584
  };
564
- SpacesState.prototype.getWallDimensions = function (index) {
565
- var _a;
566
- var line = (_a = this.getWall(index)) === null || _a === void 0 ? void 0 : _a.line;
567
- if (!line)
568
- return undefined;
585
+ SpacesState.prototype.getWallDimensions = function (line) {
569
586
  var lineLength = (0, geometry_1.getLengthOfLineSegment)(line) * this._config.config.scale;
570
- 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);
571
588
  return {
572
589
  line: line,
573
- label: (0, dataHandlers_1.prepLengthForUser)(convertedVal, this._config.config.unit),
590
+ label: (0, dataHandlers_1.prepLengthForUser)(convertedVal, this.unit),
574
591
  };
575
592
  };
576
- SpacesState.prototype.getWallDetailedDimensions = function (index) {
593
+ SpacesState.prototype.getWallDimensionsByIndex = function (index) {
594
+ var _a;
595
+ var line = (_a = this.getWall(index)) === null || _a === void 0 ? void 0 : _a.line;
596
+ if (!line)
597
+ return undefined;
598
+ return this.getWallDimensions(line);
599
+ };
600
+ SpacesState.prototype.getWallDetailedDimensionsByIndex = function (index) {
577
601
  var _this = this;
578
602
  var _a;
579
603
  var line = (_a = this.getWall(index)) === null || _a === void 0 ? void 0 : _a.line;
@@ -587,7 +611,7 @@ var SpacesState = (function () {
587
611
  var offset = _a.offset, length = _a.length;
588
612
  var featureLine = (0, geometry_1.getLineAtOffsetOnLineSegment)(line, offset, length);
589
613
  var featureLength = (0, geometry_1.getLengthOfLineSegment)(featureLine);
590
- var unit = constants_1.UNIT_LABELS[_this._config.config.unit];
614
+ var unit = constants_1.UNIT_LABELS[_this.unit];
591
615
  var scale = _this._config.config.scale;
592
616
  if (!i) {
593
617
  var startLine = [line[0], featureLine[0]];
@@ -630,8 +654,8 @@ var SpacesState = (function () {
630
654
  var indexes = new Set([detailedWallsIndexes].flat());
631
655
  var dimensionsList = this.walls.reduce(function (output, _, i) {
632
656
  var dimensions = indexes.has(i)
633
- ? _this.getWallDetailedDimensions(i)
634
- : _this.getWallDimensions(i);
657
+ ? _this.getWallDetailedDimensionsByIndex(i)
658
+ : _this.getWallDimensionsByIndex(i);
635
659
  if (!dimensions)
636
660
  return output;
637
661
  if (Array.isArray(dimensions))
@@ -750,20 +774,21 @@ var SpacesState = (function () {
750
774
  SpacesState.prototype.getFirstVacantLocation = function (length) {
751
775
  var _a;
752
776
  var walls = this.walls;
777
+ var padding = this.validationConfig.padding;
753
778
  var offset = undefined;
754
779
  for (var i = 0; i < walls.length; i++) {
755
780
  var wallLength = (0, geometry_1.getLengthOfLineSegment)(walls[i].line);
756
781
  var features = (_a = this.getWallConnectionsHydrated(i)) === null || _a === void 0 ? void 0 : _a.sort(function (a, b) { return a.offset - b.offset; });
757
782
  if (!(features === null || features === void 0 ? void 0 : features.length)) {
758
- if (length < wallLength - 2 * constants_1.WALL_PADDING_FOR_FEATURE)
759
- offset = (wallLength - 2 * constants_1.WALL_PADDING_FOR_FEATURE) / 2 - length / 2;
783
+ if (length < wallLength - 2 * padding)
784
+ offset = (wallLength - 2 * padding) / 2 - length / 2;
760
785
  }
761
786
  else {
762
787
  for (var j = 0; j < features.length && offset === undefined; j++) {
763
788
  var _b = features[j], currentOffset = _b.offset, currentLength = _b.length;
764
789
  if (!j) {
765
- if (constants_1.WALL_PADDING_FOR_FEATURE + length < currentOffset) {
766
- var slotStart = constants_1.WALL_PADDING_FOR_FEATURE;
790
+ if (padding + length < currentOffset) {
791
+ var slotStart = padding;
767
792
  var slotEnd = currentOffset;
768
793
  offset = slotStart + (slotEnd - slotStart) / 2 - length / 2;
769
794
  continue;
@@ -780,11 +805,9 @@ var SpacesState = (function () {
780
805
  }
781
806
  if (j === features.length - 1) {
782
807
  if (length <
783
- wallLength -
784
- constants_1.WALL_PADDING_FOR_FEATURE -
785
- (currentOffset + currentLength)) {
808
+ wallLength - padding - (currentOffset + currentLength)) {
786
809
  var slotStart = currentOffset + currentLength;
787
- var slotEnd = wallLength - constants_1.WALL_PADDING_FOR_FEATURE;
810
+ var slotEnd = wallLength - padding;
788
811
  offset = slotStart + (slotEnd - slotStart) / 2 - length / 2;
789
812
  }
790
813
  }
@@ -903,15 +926,18 @@ var SpacesState = (function () {
903
926
  if (index === undefined || offset === undefined)
904
927
  return;
905
928
  var newFeature = __assign(__assign({}, feature), { offset: offset, height: feature.height || 0, altitude: feature.altitude || 0, connectedTo: [types_2.IElements.WALL, index], restConfiguration: '{}' });
929
+ if (type === types_2.IElements.DOOR) {
930
+ newFeature.orientation = 'left';
931
+ newFeature.openingDirection = 'inside';
932
+ }
906
933
  var newFeatureIndex;
907
- if ((_a = this._state[types_2.IElements.FEATURE][type]) === null || _a === void 0 ? void 0 : _a.length) {
934
+ if ((_a = this._state[types_2.IElements.FEATURE][type]) === null || _a === void 0 ? void 0 : _a.length)
908
935
  newFeatureIndex = this._state[types_2.IElements.FEATURE][type].length;
909
- this._state[types_2.IElements.FEATURE][type].push(newFeature);
910
- }
911
936
  else {
912
- this._state[types_2.IElements.FEATURE][type] = [newFeature];
937
+ this._state[types_2.IElements.FEATURE][type] = [];
913
938
  newFeatureIndex = 0;
914
939
  }
940
+ this._state[types_2.IElements.FEATURE][type].push(newFeature);
915
941
  this.addFeatureToWall(index, [type, newFeatureIndex]);
916
942
  this.pushStateToConfigurator();
917
943
  };
@@ -1162,6 +1188,7 @@ var SpacesState = (function () {
1162
1188
  return;
1163
1189
  this._attributesState = attributes;
1164
1190
  var data = (0, dataHandlers_1.prepAttributesIncoming)(attributes, this._config);
1191
+ this.validationConfig = data.validationConfig;
1165
1192
  this.walls = data[types_2.IElements.WALL];
1166
1193
  this.vertices = data[types_2.IElements.VERTEX];
1167
1194
  this.features = data[types_2.IElements.FEATURE];
@@ -1235,7 +1262,7 @@ var SpacesState = (function () {
1235
1262
  validators_1.isWallTooShort,
1236
1263
  validators_1.isWallOverlappingExisitingWalls,
1237
1264
  validators_1.isWallIntersectingFeature,
1238
- ], validationData);
1265
+ ], validationData, this.validationConfig);
1239
1266
  var errorType = ((_d = this._errorElement) === null || _d === void 0 ? void 0 : _d[0].type) || null;
1240
1267
  switch (errorType) {
1241
1268
  case types_1.IErrorTypes.HARD:
@@ -1421,7 +1448,16 @@ var SpacesState = (function () {
1421
1448
  ? this.getAllWallDimensionsToDraw(activeWallIndex)
1422
1449
  : undefined, selection, this._config.config);
1423
1450
  if (((_f = this._newWall) === null || _f === void 0 ? void 0 : _f.start) && ((_g = this._newWall) === null || _g === void 0 ? void 0 : _g.end)) {
1424
- (0, draw_1.drawNewWall)(canvas, this.transformLineToCanvas([this._newWall.start, this._newWall.end]), this._config.config.styles, this._errorElement ? types_1.IElementStyleModes.ERROR : undefined);
1451
+ var newWallLine = [
1452
+ this._newWall.start,
1453
+ this._newWall.end,
1454
+ ];
1455
+ (0, draw_1.drawNewWall)(canvas, this.transformLineToCanvas(newWallLine), this._config.config.styles, this._errorElement ? types_1.IElementStyleModes.ERROR : undefined);
1456
+ if (this._showDimensions) {
1457
+ var preppedNewWallLine = this.transformLineToCanvas(newWallLine);
1458
+ var newWallDimensions = this.getWallDimensions(preppedNewWallLine);
1459
+ (0, draw_1.drawDimensions)(canvas, [newWallDimensions], this._config.config);
1460
+ }
1425
1461
  }
1426
1462
  };
1427
1463
  return SpacesState;
@@ -1,4 +1,16 @@
1
- import { ICoordinate2D, ISpacesAttributes } from './types';
1
+ import { ICoordinate2D, ISpacesAttributes, IWallsValidationConfig } from './types';
2
+ export declare enum WallMetadata {
3
+ MIN_LENGTH = "_tkSpace_minLength",
4
+ PADDING = "_tkSpace_padding"
5
+ }
6
+ export declare enum DoorOrientations {
7
+ LEFT = "Left",
8
+ RIGHT = "Right"
9
+ }
10
+ export declare enum DoorOpeningDirections {
11
+ INSIDE = "inside",
12
+ OUTSIDE = "outside"
13
+ }
2
14
  export declare const attributeNameDefaults: ISpacesAttributes;
3
15
  export declare const SCALE = 0.02;
4
16
  export declare const SNAP_PROXIMITY = 16;
@@ -9,8 +21,6 @@ export declare const ZOOM_SENSITIVITY = 0.8;
9
21
  export declare const TRANSLATE_MAX: ICoordinate2D;
10
22
  export declare const TRANSLATE_MIN: ICoordinate2D;
11
23
  export declare const TRANSLATE_DEFAULT: ICoordinate2D;
12
- export declare const MIN_WALL_LENGTH = 50;
13
- export declare const WALL_PADDING_FOR_FEATURE = 20;
14
24
  export declare const UNIT_LABELS: {
15
25
  feet: string;
16
26
  meter: string;
@@ -28,6 +38,7 @@ export declare const FEATURE_LABELS: {
28
38
  doors: string;
29
39
  openings: string;
30
40
  };
41
+ export declare const VALIDATION_CONFIG_DEFAULT: IWallsValidationConfig;
31
42
  export declare const FEATURE_LENGTH = 120;
32
43
  export declare const UI_ANCHOR_DISTANCE = -60;
33
44
  export declare const WALL_SNAP_DISTANCE = 12;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a, _b, _c, _d;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.WALL_SNAP_DISTANCE = exports.UI_ANCHOR_DISTANCE = exports.FEATURE_LENGTH = exports.FEATURE_LABELS = exports.UNIT_FACTORS = exports.UNIT_LABELS = exports.WALL_PADDING_FOR_FEATURE = exports.MIN_WALL_LENGTH = exports.TRANSLATE_DEFAULT = exports.TRANSLATE_MIN = exports.TRANSLATE_MAX = exports.ZOOM_SENSITIVITY = exports.ZOOM_DEFAULT = exports.ZOOM_MIN = exports.ZOOM_MAX = exports.SNAP_PROXIMITY = exports.SCALE = exports.attributeNameDefaults = void 0;
4
+ exports.WALL_SNAP_DISTANCE = exports.UI_ANCHOR_DISTANCE = exports.FEATURE_LENGTH = exports.VALIDATION_CONFIG_DEFAULT = exports.FEATURE_LABELS = exports.UNIT_FACTORS = exports.UNIT_LABELS = exports.TRANSLATE_DEFAULT = exports.TRANSLATE_MIN = exports.TRANSLATE_MAX = exports.ZOOM_SENSITIVITY = exports.ZOOM_DEFAULT = exports.ZOOM_MIN = exports.ZOOM_MAX = exports.SNAP_PROXIMITY = exports.SCALE = exports.attributeNameDefaults = exports.DoorOpeningDirections = exports.DoorOrientations = exports.WallMetadata = void 0;
5
5
  var types_1 = require("./types");
6
6
  var SpacesAttributes;
7
7
  (function (SpacesAttributes) {
@@ -22,24 +22,44 @@ var WallAttributes;
22
22
  WallAttributes["WALL_HEIGHT"] = "_tkSpace_wallHeight";
23
23
  WallAttributes["WALL_THICKNESS"] = "_tkSpace_wallThickness";
24
24
  })(WallAttributes || (WallAttributes = {}));
25
- var FeatureAttribute;
26
- (function (FeatureAttribute) {
27
- FeatureAttribute["POSITION_X"] = "_tkSpace_offsetX";
28
- FeatureAttribute["POSITION_Y"] = "_tkSpace_offsetY";
29
- FeatureAttribute["CONNECTED_TO"] = "_tkSpace_connectedTo";
30
- FeatureAttribute["FEATURE_HEIGHT"] = "_tkSpace_featureHeight";
31
- FeatureAttribute["FEATURE_LENGTH"] = "_tkSpace_featureWidth";
32
- })(FeatureAttribute || (FeatureAttribute = {}));
25
+ var WallMetadata;
26
+ (function (WallMetadata) {
27
+ WallMetadata["MIN_LENGTH"] = "_tkSpace_minLength";
28
+ WallMetadata["PADDING"] = "_tkSpace_padding";
29
+ })(WallMetadata = exports.WallMetadata || (exports.WallMetadata = {}));
30
+ var FeatureAttributes;
31
+ (function (FeatureAttributes) {
32
+ FeatureAttributes["POSITION_X"] = "_tkSpace_offsetX";
33
+ FeatureAttributes["POSITION_Y"] = "_tkSpace_offsetY";
34
+ FeatureAttributes["CONNECTED_TO"] = "_tkSpace_connectedTo";
35
+ FeatureAttributes["FEATURE_HEIGHT"] = "_tkSpace_featureHeight";
36
+ FeatureAttributes["FEATURE_LENGTH"] = "_tkSpace_featureWidth";
37
+ })(FeatureAttributes || (FeatureAttributes = {}));
38
+ var DoorAttributes;
39
+ (function (DoorAttributes) {
40
+ DoorAttributes["ORIENTATION"] = "_tkSpace_doorOrientation";
41
+ DoorAttributes["OPENING_DIRECTION"] = "_tkSpace_doorOpeningDirection";
42
+ })(DoorAttributes || (DoorAttributes = {}));
43
+ var DoorOrientations;
44
+ (function (DoorOrientations) {
45
+ DoorOrientations["LEFT"] = "Left";
46
+ DoorOrientations["RIGHT"] = "Right";
47
+ })(DoorOrientations = exports.DoorOrientations || (exports.DoorOrientations = {}));
48
+ var DoorOpeningDirections;
49
+ (function (DoorOpeningDirections) {
50
+ DoorOpeningDirections["INSIDE"] = "inside";
51
+ DoorOpeningDirections["OUTSIDE"] = "outside";
52
+ })(DoorOpeningDirections = exports.DoorOpeningDirections || (exports.DoorOpeningDirections = {}));
33
53
  exports.attributeNameDefaults = (_a = {},
34
54
  _a[types_1.IElements.WALL] = SpacesAttributes.WALLS,
35
55
  _a[types_1.IElements.WINDOW] = SpacesAttributes.WINDOWS,
36
56
  _a[types_1.IElements.OPENING] = SpacesAttributes.OPENINGS,
37
57
  _a[types_1.IElements.DOOR] = SpacesAttributes.DOORS,
38
- _a.featurePositionX = FeatureAttribute.POSITION_X,
39
- _a.featurePositionY = FeatureAttribute.POSITION_Y,
40
- _a.featureConnectedTo = FeatureAttribute.CONNECTED_TO,
41
- _a.featureHeight = FeatureAttribute.FEATURE_HEIGHT,
42
- _a.featureLength = FeatureAttribute.FEATURE_LENGTH,
58
+ _a.featurePositionX = FeatureAttributes.POSITION_X,
59
+ _a.featurePositionY = FeatureAttributes.POSITION_Y,
60
+ _a.featureConnectedTo = FeatureAttributes.CONNECTED_TO,
61
+ _a.featureHeight = FeatureAttributes.FEATURE_HEIGHT,
62
+ _a.featureLength = FeatureAttributes.FEATURE_LENGTH,
43
63
  _a.wallStartX = WallAttributes.START_X,
44
64
  _a.wallStartY = WallAttributes.START_Y,
45
65
  _a.wallStartZ = WallAttributes.START_Z,
@@ -47,6 +67,8 @@ exports.attributeNameDefaults = (_a = {},
47
67
  _a.wallEndY = WallAttributes.END_Y,
48
68
  _a.wallEndZ = WallAttributes.END_Z,
49
69
  _a.wallConnections = WallAttributes.CONNECTIONS,
70
+ _a.doorOrientation = DoorAttributes.ORIENTATION,
71
+ _a.doorOpeningDirection = DoorAttributes.OPENING_DIRECTION,
50
72
  _a);
51
73
  exports.SCALE = 0.02;
52
74
  exports.SNAP_PROXIMITY = 16;
@@ -57,8 +79,6 @@ exports.ZOOM_SENSITIVITY = 0.8;
57
79
  exports.TRANSLATE_MAX = [-400, -400];
58
80
  exports.TRANSLATE_MIN = [400, 400];
59
81
  exports.TRANSLATE_DEFAULT = [-200, -200];
60
- exports.MIN_WALL_LENGTH = 50;
61
- exports.WALL_PADDING_FOR_FEATURE = 20;
62
82
  exports.UNIT_LABELS = (_b = {},
63
83
  _b[types_1.IUnits.FEET] = 'ft',
64
84
  _b[types_1.IUnits.METER] = 'm',
@@ -76,6 +96,10 @@ exports.FEATURE_LABELS = (_d = {},
76
96
  _d[types_1.IElements.DOOR] = 'Door',
77
97
  _d[types_1.IElements.OPENING] = 'Opening',
78
98
  _d);
99
+ exports.VALIDATION_CONFIG_DEFAULT = {
100
+ padding: 20,
101
+ minLength: 50,
102
+ };
79
103
  exports.FEATURE_LENGTH = 120;
80
104
  exports.UI_ANCHOR_DISTANCE = -60;
81
105
  exports.WALL_SNAP_DISTANCE = 12;
@@ -1,7 +1,8 @@
1
- import type { IWalls, ISpacesStateProps, IVerticesState, IFeatures } from './types';
1
+ import type { IWalls, ISpacesStateProps, IVerticesState, IFeatures, IWallsValidationConfig } from './types';
2
2
  import { IUnits } from './types';
3
3
  import type { IConfiguration, IHydratedAttribute } from '../../types';
4
4
  export declare function prepAttributesIncoming(attributes: Record<string, IHydratedAttribute>, config: ISpacesStateProps): {
5
+ validationConfig: IWallsValidationConfig;
5
6
  features: {};
6
7
  walls: IWalls;
7
8
  vertex: IVerticesState;
@@ -69,50 +69,67 @@ function prepWallsAndVerticesIncoming(wallsAttribute, config) {
69
69
  });
70
70
  return _a = {}, _a[types_1.IElements.WALL] = walls, _a[types_1.IElements.VERTEX] = vertices, _a;
71
71
  }
72
- function prepFeatureIncoming(walls, featureAttribute, config) {
72
+ function getWallsVaidationConfig(wallsAttribute, config) {
73
+ var _a, _b;
74
+ var metadata = (wallsAttribute === null || wallsAttribute === void 0 ? void 0 : wallsAttribute.values[0].metadata) || {};
75
+ var validation = {
76
+ minLength: ((_a = metadata[constants_1.WallMetadata.MIN_LENGTH]) !== null && _a !== void 0 ? _a : constants_1.VALIDATION_CONFIG_DEFAULT.minLength) / config.config.scale,
77
+ padding: ((_b = metadata[constants_1.WallMetadata.PADDING]) !== null && _b !== void 0 ? _b : constants_1.VALIDATION_CONFIG_DEFAULT.padding) / config.config.scale,
78
+ };
79
+ return validation;
80
+ }
81
+ function prepFeatureIncoming(type, walls, featureAttribute, config) {
73
82
  var _a;
74
83
  var attributeName = config.attributes;
75
84
  var feature = [];
76
85
  (_a = featureAttribute === null || featureAttribute === void 0 ? void 0 : featureAttribute.value) === null || _a === void 0 ? void 0 : _a.forEach(function (_a) {
77
86
  var assetId = _a.assetId, configuration = _a.configuration;
78
87
  var offset = (configuration === null || configuration === void 0 ? void 0 : configuration[attributeName.featurePositionX]) / config.config.scale;
79
- var length = (configuration === null || configuration === void 0 ? void 0 : configuration[attributeName.featureLength]) / config.config.scale ||
80
- constants_1.FEATURE_LENGTH;
88
+ var length = (configuration === null || configuration === void 0 ? void 0 : configuration[attributeName.featureLength]) / config.config.scale;
81
89
  var height = (configuration === null || configuration === void 0 ? void 0 : configuration[attributeName.featureHeight]) / config.config.scale;
82
90
  var altitude = (configuration === null || configuration === void 0 ? void 0 : configuration[attributeName.featurePositionY]) / config.config.scale;
83
91
  var connectedTo = (configuration === null || configuration === void 0 ? void 0 : configuration[attributeName.featureConnectedTo]) || '';
84
92
  var wallIndex = prepConnectionIncoming(connectedTo)[1];
85
93
  var featureLine = (0, geometry_1.getLineAtOffsetOnLineSegment)(walls[wallIndex].line, offset, length);
86
- var path = (0, geometry_1.addThicknessToLine)(featureLine, config.config.styles.feature.thickness);
87
- feature.push({
94
+ var element = {
88
95
  assetId: assetId,
89
96
  offset: offset,
90
97
  length: length,
91
98
  height: height,
92
99
  altitude: altitude,
93
- path: path,
94
100
  connectedTo: [types_1.IElements.WALL, wallIndex],
101
+ path: (0, geometry_1.addThicknessToLine)(featureLine, config.config.styles.feature.thickness),
95
102
  restConfiguration: JSON.stringify(filterRestConfiguration(configuration, config.attributes)),
96
- });
103
+ };
104
+ if (type === types_1.IElements.DOOR) {
105
+ element.orientation =
106
+ (configuration === null || configuration === void 0 ? void 0 : configuration[attributeName.doorOrientation]) || constants_1.DoorOrientations.LEFT;
107
+ element.openingDirection =
108
+ (configuration === null || configuration === void 0 ? void 0 : configuration[attributeName.doorOpeningDirection]) ||
109
+ constants_1.DoorOpeningDirections.INSIDE;
110
+ }
111
+ feature.push(element);
97
112
  });
98
113
  return feature;
99
114
  }
100
115
  function prepAttributesIncoming(attributes, config) {
101
116
  var _a;
102
- var wallsAndVertices = prepWallsAndVerticesIncoming(attributes[config.attributes[types_1.IElements.WALL]], config);
117
+ var wallsAttribute = attributes[config.attributes[types_1.IElements.WALL]];
118
+ var wallsAndVertices = prepWallsAndVerticesIncoming(wallsAttribute, config);
119
+ var wallsValidation = getWallsVaidationConfig(wallsAttribute, config);
103
120
  var featuresList = [
104
121
  types_1.IElements.WINDOW,
105
122
  types_1.IElements.DOOR,
106
123
  types_1.IElements.OPENING,
107
124
  ];
108
125
  var featuresData = featuresList.reduce(function (output, type) {
109
- output[type] = prepFeatureIncoming(wallsAndVertices[types_1.IElements.WALL], attributes[config.attributes[type]], config);
126
+ output[type] = prepFeatureIncoming(type, wallsAndVertices[types_1.IElements.WALL], attributes[config.attributes[type]], config);
110
127
  return output;
111
128
  }, {});
112
- return __assign(__assign({}, wallsAndVertices), (_a = {}, _a[types_1.IElements.FEATURE] = featuresData, _a));
129
+ return __assign(__assign({}, wallsAndVertices), (_a = { validationConfig: wallsValidation }, _a[types_1.IElements.FEATURE] = featuresData, _a));
113
130
  }
114
131
  exports.prepAttributesIncoming = prepAttributesIncoming;
115
- function prepFeaturesOutgoing(features, config) {
132
+ function prepFeaturesOutgoing(type, features, config) {
116
133
  var attributeName = config.attributes;
117
134
  return features.map(function (feature) {
118
135
  var _a, _b;
@@ -136,6 +153,10 @@ function prepFeaturesOutgoing(features, config) {
136
153
  _b[key] = value ? value * config.config.scale : value,
137
154
  _b));
138
155
  }, __assign((_b = {}, _b[attributeName.featureConnectedTo] = connectedTo, _b), JSON.parse(restConfiguration)));
156
+ if (type === types_1.IElements.DOOR) {
157
+ configuration[attributeName.doorOrientation] = feature.orientation;
158
+ configuration[attributeName.doorOpeningDirection] = feature.openingDirection;
159
+ }
139
160
  return {
140
161
  assetId: assetId,
141
162
  configuration: configuration,
@@ -180,7 +201,7 @@ function prepAttributesOutgoing(walls, features, config) {
180
201
  var attributeName = config.attributes[type];
181
202
  if (!attributeName)
182
203
  return output;
183
- output[attributeName] = prepFeaturesOutgoing(features, config);
204
+ output[attributeName] = prepFeaturesOutgoing(type, features, config);
184
205
  return output;
185
206
  }, {});
186
207
  return __assign(__assign({}, featuresAttributes), (_a = {}, _a[config.attributes[types_1.IElements.WALL]] = wallsAttribute, _a));
@@ -1,4 +1,4 @@
1
- import { IWall, ICoordinate2D, ICoordinatesLine, IFeatures, IFeature, IElementAddress, ISpacesStyles, ISpacesConfigInternal, IStylesGrid, IStylesWall, IStylesVertex, ILineDimensions, IVertex, IElementStyleModes, IStylesFloor, IEnclosedSpace } from './types';
1
+ import { IWall, ICoordinate2D, ICoordinatesLine, IFeatures, IFeature, IElementAddress, ISpacesStyles, ISpacesConfigInternal, IStylesGrid, IStylesWall, IStylesVertex, IStylesDimension, ILineDimensions, IVertex, IElementStyleModes, IStylesFloor, IEnclosedSpace, IFeatureDoor } from './types';
2
2
  interface IWallToDraw extends Pick<IWall, 'line' | 'path'> {
3
3
  }
4
4
  interface IWallsToDraw extends Array<IWallToDraw> {
@@ -7,6 +7,7 @@ export declare function clearCanvas(canvas: HTMLCanvasElement): void;
7
7
  export declare function drawBackground(canvas: HTMLCanvasElement, color?: string): void;
8
8
  export declare function drawGrid(canvas: HTMLCanvasElement, styles: IStylesGrid): void;
9
9
  export declare function drawFloor(canvas: HTMLCanvasElement, enclosedSpaces: Array<IEnclosedSpace>, styles: IStylesFloor): void;
10
+ export declare function drawDimension(canvas: HTMLCanvasElement, line: ICoordinatesLine, styles: IStylesDimension, message: string): void;
10
11
  export declare function drawVertex(canvas: HTMLCanvasElement, point: ICoordinate2D, style: IStylesVertex, mode?: IElementStyleModes): void;
11
12
  export declare function drawNewWall(canvas: HTMLCanvasElement, line: ICoordinatesLine, styles: ISpacesStyles, mode?: IElementStyleModes.ERROR): void;
12
13
  export declare function drawWalls(canvas: HTMLCanvasElement, walls: IWallsToDraw, selections: {
@@ -28,7 +29,7 @@ export declare function drawWindows(canvas: HTMLCanvasElement, walls: IWallsToDr
28
29
  error: Array<number>;
29
30
  hidden: Array<number>;
30
31
  }, styles: ISpacesStyles): void;
31
- export declare function drawDoors(canvas: HTMLCanvasElement, walls: IWallsToDraw, doors: Array<IFeature>, selections: {
32
+ export declare function drawDoors(canvas: HTMLCanvasElement, walls: IWallsToDraw, doors: Array<IFeatureDoor>, selections: {
32
33
  active: Array<number>;
33
34
  highlighted: Array<number>;
34
35
  error: Array<number>;
@@ -9,10 +9,11 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
9
9
  return to.concat(ar || Array.prototype.slice.call(from));
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.drawSpaces = exports.drawElements = exports.drawOpenings = exports.drawDoors = exports.drawWindows = exports.drawDimensions = exports.drawVertices = exports.drawWalls = exports.drawNewWall = exports.drawVertex = exports.drawFloor = exports.drawGrid = exports.drawBackground = exports.clearCanvas = void 0;
12
+ exports.drawSpaces = exports.drawElements = exports.drawOpenings = exports.drawDoors = exports.drawWindows = exports.drawDimensions = exports.drawVertices = exports.drawWalls = exports.drawNewWall = exports.drawVertex = exports.drawDimension = exports.drawFloor = exports.drawGrid = exports.drawBackground = exports.clearCanvas = void 0;
13
13
  var types_1 = require("./types");
14
14
  var types_2 = require("./types");
15
15
  var geometry_1 = require("./geometry");
16
+ var constants_1 = require("./constants");
16
17
  var debug = false;
17
18
  function clearCanvas(canvas) {
18
19
  var ctx = canvas.getContext('2d');
@@ -161,6 +162,7 @@ function drawDimension(canvas, line, styles, message) {
161
162
  ctx.fillText(message, 0, 0);
162
163
  ctx.resetTransform();
163
164
  }
165
+ exports.drawDimension = drawDimension;
164
166
  function drawVertex(canvas, point, style, mode) {
165
167
  var ctx = canvas.getContext('2d');
166
168
  if (!ctx)
@@ -244,17 +246,42 @@ function drawWindow(canvas, wall, offset, length, style, mode) {
244
246
  ctx.arc(windowLine[1][0], windowLine[1][1], style.thickness / 2, angle + Math.PI / 2, angle - Math.PI / 2);
245
247
  ctx.fill();
246
248
  }
247
- function drawDoor(canvas, wall, offset, length, style, mode) {
249
+ function drawDoor(canvas, wall, offset, length, openingDirection, orientation, style, mode) {
248
250
  var ctx = canvas.getContext('2d');
249
251
  if (!ctx)
250
252
  return;
251
253
  var doorLine = (0, geometry_1.getLineAtOffsetOnLineSegment)(wall.line, offset, length);
252
254
  var points = (0, geometry_1.addThicknessToLine)(doorLine, style.thickness);
255
+ var angle = (0, geometry_1.getAngleOfLineSegment)(doorLine);
253
256
  var stroke = style.stroke, fill = style.fill, strokeWidth = style.strokeWidth;
254
257
  if (mode) {
255
258
  stroke = style[mode].stroke;
256
259
  fill = style[mode].fill;
257
260
  }
261
+ ctx.beginPath();
262
+ ctx.strokeStyle = stroke || fill;
263
+ ctx.lineWidth = 2;
264
+ if (openingDirection === constants_1.DoorOpeningDirections.INSIDE) {
265
+ if (orientation === constants_1.DoorOrientations.LEFT) {
266
+ ctx.moveTo.apply(ctx, points[0]);
267
+ ctx.arc.apply(ctx, __spreadArray(__spreadArray([], points[0], false), [length, angle - Math.PI / 2, angle], false));
268
+ }
269
+ else {
270
+ ctx.moveTo.apply(ctx, points[1]);
271
+ ctx.arc.apply(ctx, __spreadArray(__spreadArray([], points[1], false), [length, angle - Math.PI / 2, angle - Math.PI, true], false));
272
+ }
273
+ }
274
+ else {
275
+ if (orientation === constants_1.DoorOrientations.LEFT) {
276
+ ctx.moveTo.apply(ctx, points[2]);
277
+ ctx.arc.apply(ctx, __spreadArray(__spreadArray([], points[2], false), [length, angle + Math.PI / 2, angle + Math.PI], false));
278
+ }
279
+ else {
280
+ ctx.moveTo.apply(ctx, points[3]);
281
+ ctx.arc.apply(ctx, __spreadArray(__spreadArray([], points[3], false), [length, angle + Math.PI / 2, angle, true], false));
282
+ }
283
+ }
284
+ ctx.stroke();
258
285
  ctx.strokeStyle = stroke || fill;
259
286
  ctx.fillStyle = fill;
260
287
  ctx.lineWidth = strokeWidth || 1;
@@ -429,7 +456,7 @@ function drawDoors(canvas, walls, doors, selections, styles) {
429
456
  if (!(door === null || door === void 0 ? void 0 : door.connectedTo.length))
430
457
  return;
431
458
  var wallIndex = door.connectedTo[1];
432
- drawDoor(canvas, walls[wallIndex], door.offset, door.length, styles.feature, mode);
459
+ drawDoor(canvas, walls[wallIndex], door.offset, door.length, door.openingDirection, door.orientation, styles.feature, mode);
433
460
  });
434
461
  });
435
462
  }
@@ -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,22 +162,37 @@ 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
- var _a;
183
+ var _a, _b;
163
184
  if (!canvasRef.current)
164
185
  return;
165
186
  var zoomSensitivity = ((_a = props.config) === null || _a === void 0 ? void 0 : _a.zoomSensitivity) || constants_1.ZOOM_SENSITIVITY;
187
+ if ((_b = props.config) === null || _b === void 0 ? void 0 : _b.reverseZoom)
188
+ zoomSensitivity = -1 * zoomSensitivity;
166
189
  updateZoom(e.deltaY * zoomSensitivity);
167
190
  };
168
191
  var handleSelectModeHover = function (e) {
169
192
  if (!canvasRef.current)
170
193
  return;
194
+ if (!spacesRef.current)
195
+ return;
171
196
  if (modeValue !== types_1.IModes.SELECT)
172
197
  return;
173
198
  if (spacesRef.current.activeElement !== null)
@@ -181,16 +206,18 @@ var useSpaces = function (props) {
181
206
  var _a;
182
207
  if (!canvasRef.current)
183
208
  return;
209
+ if (!spacesRef.current)
210
+ return;
184
211
  if (modeValue !== types_1.IModes.SELECT)
185
212
  return;
186
213
  var cursorPoint = [e.offsetX, e.offsetY];
187
214
  spacesRef.current.selectElementIfInProximity(canvasRef.current, cursorPoint);
188
- if (!((_a = props.config) === null || _a === void 0 ? void 0 : _a.translateDisabled) && !spacesRef.current.activeElement)
189
- translationAnchorRef.current = cursorPoint;
190
215
  var element = spacesRef.current.getClickedElement(cursorPoint);
191
216
  if (!element) {
192
217
  if (selectedElement !== null)
193
218
  setSelectedElement(null);
219
+ if (!((_a = props.config) === null || _a === void 0 ? void 0 : _a.translateDisabled) && !spacesRef.current.activeElement)
220
+ translationAnchorRef.current = cursorPoint;
194
221
  return;
195
222
  }
196
223
  if (spacesRef.current.activeElement ||
@@ -200,6 +227,8 @@ var useSpaces = function (props) {
200
227
  selectElementPending.current = element;
201
228
  };
202
229
  var handleMoveSelectedElement = function (e) {
230
+ if (!spacesRef.current)
231
+ return;
203
232
  if (modeValue !== types_1.IModes.SELECT)
204
233
  return;
205
234
  if (!canvasRef.current)
@@ -213,6 +242,8 @@ var useSpaces = function (props) {
213
242
  return;
214
243
  if (!canvasRef.current)
215
244
  return;
245
+ if (!spacesRef.current)
246
+ return;
216
247
  if (spacesRef.current.selectedElement || !translationAnchorRef.current)
217
248
  return;
218
249
  var delta = [
@@ -228,6 +259,8 @@ var useSpaces = function (props) {
228
259
  return;
229
260
  if (!canvasRef.current)
230
261
  return;
262
+ if (!spacesRef.current)
263
+ return;
231
264
  if (!((_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
232
265
  spacesRef.current.cancelMoveActiveElement(canvasRef.current);
233
266
  return;
@@ -244,6 +277,8 @@ var useSpaces = function (props) {
244
277
  var handleDrawWallStart = function (e) {
245
278
  if (modeValue !== types_1.IModes.DRAW)
246
279
  return;
280
+ if (!spacesRef.current)
281
+ return;
247
282
  var cursorPoint = [e.offsetX, e.offsetY];
248
283
  spacesRef.current.startDrawNewWall(cursorPoint);
249
284
  };
@@ -252,6 +287,8 @@ var useSpaces = function (props) {
252
287
  return;
253
288
  if (!canvasRef.current)
254
289
  return;
290
+ if (!spacesRef.current)
291
+ return;
255
292
  var cursorPoint = [e.offsetX, e.offsetY];
256
293
  if (spacesRef.current.isDrawWallActive)
257
294
  spacesRef.current.drawNewWall(canvasRef.current, cursorPoint);
@@ -262,6 +299,8 @@ var useSpaces = function (props) {
262
299
  return;
263
300
  if (!canvasRef.current)
264
301
  return;
302
+ if (!spacesRef.current)
303
+ return;
265
304
  if (!selectedWallAsset)
266
305
  return;
267
306
  if (!((_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
@@ -274,13 +313,14 @@ var useSpaces = function (props) {
274
313
  if (!attribute)
275
314
  return undefined;
276
315
  var values = attribute.values.map(function (val) { return (__assign(__assign({}, val), { add: function (addToWallIndex, offset) {
277
- return spacesRef.current.addFeature(type, {
316
+ var _a;
317
+ return (_a = spacesRef.current) === null || _a === void 0 ? void 0 : _a.addFeature(type, {
278
318
  assetId: val.assetId,
279
319
  length: constants_1.FEATURE_LENGTH,
280
320
  offset: offset,
281
321
  }, addToWallIndex);
282
322
  } })); });
283
- 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); } })); });
284
324
  return __assign(__assign({}, attribute), { values: values, value: value });
285
325
  };
286
326
  var prepWallAttributeForOutput = function (attribute) {
@@ -305,7 +345,9 @@ var useSpaces = function (props) {
305
345
  var handleSetMode = function (mode) {
306
346
  if (mode === modeValue)
307
347
  return;
308
- drawSpaces();
348
+ if (!spacesRef.current)
349
+ return;
350
+ spacesRef.current.drawSpaces(canvasRef.current);
309
351
  dispatch((0, spaces_1.setMode)(mode));
310
352
  setSelectedElement(null);
311
353
  };
@@ -341,15 +383,17 @@ var useSpaces = function (props) {
341
383
  setSelectedElement(null);
342
384
  };
343
385
  var handleChangeTranslate = function (delta) {
386
+ if (!spacesRef.current)
387
+ return;
344
388
  spacesRef.current.translate = [
345
389
  spacesRef.current.translate[0] + delta[0],
346
390
  spacesRef.current.translate[1] + delta[1],
347
391
  ];
348
392
  dispatch((0, spaces_1.setTranslation)(spacesRef.current.translate));
349
- drawSpaces();
393
+ spacesRef.current.drawSpaces(canvasRef.current);
350
394
  };
351
395
  return {
352
- draw: drawSpaces,
396
+ draw: ((_b = spacesRef.current) === null || _b === void 0 ? void 0 : _b.drawSpaces(canvasRef.current)) || (function () { }),
353
397
  canvasRef: canvasRef,
354
398
  selectedElement: selectedElement === null
355
399
  ? selectedElement
@@ -376,11 +420,21 @@ var useSpaces = function (props) {
376
420
  handleToggle: handleToggleAngleSnapping,
377
421
  },
378
422
  zoom: {
379
- min: spacesRef.current.zoomMin,
380
- 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,
381
425
  value: zoom || constants_1.ZOOM_DEFAULT,
382
426
  handleChange: updateZoom,
383
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
+ },
384
438
  translate: {
385
439
  handleChange: handleChangeTranslate,
386
440
  },
@@ -62,17 +62,25 @@ export interface IFeature {
62
62
  connectedTo: [elementType: IElements.WALL, index: number];
63
63
  restConfiguration: string;
64
64
  }
65
- export interface IFeatureHydrated extends IFeature {
65
+ export interface IFeatureDoor extends IFeature {
66
+ orientation: string;
67
+ openingDirection: string;
68
+ }
69
+ interface IFeatureHydratedShared {
66
70
  line: ICoordinatesLine;
67
71
  }
68
- export interface IFeaturesShared<T> {
72
+ export interface IFeatureHydrated extends IFeature, IFeatureHydratedShared {
73
+ }
74
+ export interface IFeatureDoorHydrated extends IFeatureDoor, IFeatureHydratedShared {
75
+ }
76
+ export interface IFeaturesShared<T, D> {
69
77
  [IElements.WINDOW]?: Array<T>;
70
- [IElements.DOOR]?: Array<T>;
78
+ [IElements.DOOR]?: Array<D>;
71
79
  [IElements.OPENING]?: Array<T>;
72
80
  }
73
- export interface IFeatures extends IFeaturesShared<IFeature> {
81
+ export interface IFeatures extends IFeaturesShared<IFeature, IFeatureDoor> {
74
82
  }
75
- export interface IFeaturesHydrated extends IFeaturesShared<IFeatureHydrated> {
83
+ export interface IFeaturesHydrated extends IFeaturesShared<IFeatureHydrated, IFeatureDoorHydrated> {
76
84
  }
77
85
  export declare enum IElementStyleModes {
78
86
  HIGHLIGHT = "highlight",
@@ -159,6 +167,10 @@ export interface ISpacesThemePartial {
159
167
  vertex: Partial<IStylesVertex>;
160
168
  feature: Partial<IStylesFeature>;
161
169
  }
170
+ export interface IWallsValidationConfig {
171
+ minLength: number;
172
+ padding: number;
173
+ }
162
174
  export declare enum SNAPPING_TYPES {
163
175
  ANGLE = "angle"
164
176
  }
@@ -231,6 +243,7 @@ export interface ISpacesConfigUser extends ISpacesConfigShared<Partial<ISpacesSt
231
243
  zoomDisabled: boolean;
232
244
  translateDisabled: boolean;
233
245
  zoomSensitivity: number;
246
+ reverseZoom: boolean;
234
247
  }
235
248
  export interface ISpacesAttributes {
236
249
  [IElements.WALL]: string;
@@ -249,6 +262,8 @@ export interface ISpacesAttributes {
249
262
  wallEndY: string;
250
263
  wallEndZ: string;
251
264
  wallConnections: string;
265
+ doorOrientation: string;
266
+ doorOpeningDirection: string;
252
267
  }
253
268
  interface ISpacesPropsShared<T, U> {
254
269
  config: T;
@@ -1,4 +1,4 @@
1
- import { IWall, IFeatures, IElementAddress, IWalls, IErrorElement, IFeature, INewWall, ICoordinate2D, IVertex, ISnapPoint } from './types';
1
+ import { IWall, IFeatures, IElementAddress, IWalls, IErrorElement, IFeature, INewWall, ICoordinate2D, IVertex, ISnapPoint, IWallsValidationConfig } from './types';
2
2
  export interface IFeatureValidatorInput {
3
3
  updatedFeature: Pick<IFeature, 'length' | 'offset'> & {
4
4
  address: IElementAddress;
@@ -20,17 +20,17 @@ export interface IMoveVertexValidatorInput {
20
20
  vertex: IVertex;
21
21
  features: IFeatures;
22
22
  }
23
- declare type IValidatorFunction<T> = (input: T) => false | IErrorElement;
24
- export declare function isWallTooShort(input: IAddWallValidatorInput): false | IErrorElement;
23
+ declare type IValidatorFunction<T> = (input: T, validationConfig: IWallsValidationConfig) => false | IErrorElement;
24
+ export declare function isWallTooShort(input: IAddWallValidatorInput, validationConfig: IWallsValidationConfig): false | IErrorElement;
25
25
  export declare function isWallIntersectingFeature(input: IAddWallValidatorInput): false | IErrorElement;
26
26
  export declare function isWallOverlappingExisitingWalls(input: IAddWallValidatorInput): false | IErrorElement;
27
27
  export declare function isWallEndingOnFeature(input: IAddWallValidatorInput): false | IErrorElement;
28
- export declare function isFeatureOutsideWallBounds(input: IFeatureValidatorInput): false | IErrorElement;
28
+ export declare function isFeatureOutsideWallBounds(input: IFeatureValidatorInput, validationConfig: IWallsValidationConfig): false | IErrorElement;
29
29
  export declare function isFeatureCollidingWithExistingFeature(input: IFeatureValidatorInput): false | IErrorElement;
30
- export declare function areWallsTooShort(input: IMoveVertexValidatorInput): false | IErrorElement;
30
+ export declare function areWallsTooShort(input: IMoveVertexValidatorInput, validationConfig: IWallsValidationConfig): false | IErrorElement;
31
31
  export declare function areWallsIntersecting(input: IMoveVertexValidatorInput): false | IErrorElement;
32
- export declare function areWallsOrphaningFeatures(input: IMoveVertexValidatorInput): false | IErrorElement;
32
+ export declare function areWallsOrphaningFeatures(input: IMoveVertexValidatorInput, validationConfig: IWallsValidationConfig): false | IErrorElement;
33
33
  export declare function areWallsDuplicated(input: IMoveVertexValidatorInput): false | IErrorElement;
34
34
  export declare function isVertexLandingOnFeature(input: IMoveVertexValidatorInput): false | IErrorElement;
35
- export declare function runValidators<T>(validators: Array<IValidatorFunction<T>>, input: T): IErrorElement[] | null;
35
+ export declare function runValidators<T>(validators: Array<IValidatorFunction<T>>, input: T, validationConfig: IWallsValidationConfig): IErrorElement[] | null;
36
36
  export {};
@@ -13,9 +13,8 @@ exports.runValidators = exports.isVertexLandingOnFeature = exports.areWallsDupli
13
13
  var types_1 = require("./types");
14
14
  var geometry_1 = require("./geometry");
15
15
  var messaging_1 = require("./messaging");
16
- var constants_1 = require("./constants");
17
- function isLineTooShort(wallOrLine) {
18
- var minLength = constants_1.MIN_WALL_LENGTH;
16
+ function isLineTooShort(wallOrLine, validationConfig) {
17
+ var minLength = validationConfig.minLength;
19
18
  var line = Array.isArray(wallOrLine) ? wallOrLine : wallOrLine.line;
20
19
  var tooClose = geometry_1.arePointsWithinProximity.apply(void 0, __spreadArray(__spreadArray([], line, false), [minLength], false));
21
20
  if (tooClose)
@@ -25,8 +24,8 @@ function isLineTooShort(wallOrLine) {
25
24
  };
26
25
  return false;
27
26
  }
28
- function isWallTooShort(input) {
29
- return isLineTooShort(input.newWall.line);
27
+ function isWallTooShort(input, validationConfig) {
28
+ return isLineTooShort(input.newWall.line, validationConfig);
30
29
  }
31
30
  exports.isWallTooShort = isWallTooShort;
32
31
  function isWallIntersectingFeature(input) {
@@ -127,9 +126,9 @@ function isWallEndingOnFeature(input) {
127
126
  return false;
128
127
  }
129
128
  exports.isWallEndingOnFeature = isWallEndingOnFeature;
130
- function isFeatureOutsideWallBounds(input) {
129
+ function isFeatureOutsideWallBounds(input, validationConfig) {
131
130
  var wall = input.wall, updatedFeature = input.updatedFeature;
132
- var padding = constants_1.WALL_PADDING_FOR_FEATURE;
131
+ var padding = validationConfig.padding;
133
132
  var wallLength = (0, geometry_1.getLengthOfLineSegment)(wall.line);
134
133
  if (updatedFeature.offset < padding ||
135
134
  updatedFeature.offset + updatedFeature.length > wallLength - padding)
@@ -166,7 +165,7 @@ function isFeatureCollidingWithExistingFeature(input) {
166
165
  return false;
167
166
  }
168
167
  exports.isFeatureCollidingWithExistingFeature = isFeatureCollidingWithExistingFeature;
169
- function areWallsTooShort(input) {
168
+ function areWallsTooShort(input, validationConfig) {
170
169
  var walls = input.walls, vertex = input.vertex, updatedPosition = input.updatedPosition;
171
170
  var _a = vertex.connections.reduce(function (output, connection) {
172
171
  var _a;
@@ -184,7 +183,7 @@ function areWallsTooShort(input) {
184
183
  var index = wallIndexes_1[_i];
185
184
  var line = walls[index].line;
186
185
  line[updatedVerticesMap[index]] = updatedPosition.point;
187
- if (isLineTooShort(line))
186
+ if (isLineTooShort(line, validationConfig))
188
187
  return {
189
188
  address: { type: types_1.IElements.WALL, index: index },
190
189
  message: messaging_1.errorMessages.wallTooShort(),
@@ -230,9 +229,10 @@ function areWallsIntersecting(input) {
230
229
  return false;
231
230
  }
232
231
  exports.areWallsIntersecting = areWallsIntersecting;
233
- function areWallsOrphaningFeatures(input) {
232
+ function areWallsOrphaningFeatures(input, validationConfig) {
234
233
  var _a;
235
234
  var walls = input.walls, vertex = input.vertex, features = input.features, updatedPosition = input.updatedPosition;
235
+ var padding = validationConfig.padding;
236
236
  var _b = vertex.connections.reduce(function (output, connection) {
237
237
  var _a;
238
238
  var wallIndex = connection[0], vertexIndex = connection[1];
@@ -266,10 +266,9 @@ function areWallsOrphaningFeatures(input) {
266
266
  type: types_1.IErrorTypes.HARD,
267
267
  };
268
268
  if (updatedVerticesMap[wallIdx] === 0 &&
269
- feat.offset - wallLengthDelta < constants_1.WALL_PADDING_FOR_FEATURE)
269
+ feat.offset - wallLengthDelta < padding)
270
270
  return error;
271
- else if (feat.offset + feat.length >
272
- updatedWallLength - constants_1.WALL_PADDING_FOR_FEATURE) {
271
+ else if (feat.offset + feat.length > updatedWallLength - padding) {
273
272
  return error;
274
273
  }
275
274
  }
@@ -348,9 +347,9 @@ function isVertexLandingOnFeature(input) {
348
347
  return false;
349
348
  }
350
349
  exports.isVertexLandingOnFeature = isVertexLandingOnFeature;
351
- function runValidators(validators, input) {
350
+ function runValidators(validators, input, validationConfig) {
352
351
  var errors = validators.reduce(function (output, validate) {
353
- var error = validate(input);
352
+ var error = validate(input, validationConfig);
354
353
  if (error)
355
354
  output.push(error);
356
355
  return output;
@@ -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-06",
3
+ "version": "0.0.90-next-08",
4
4
  "author": "Amaan Saeed",
5
5
  "license": "MIT",
6
6
  "files": [