@focusbc/bbs-lib 0.0.9 → 0.0.11

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.
@@ -63676,7 +63676,7 @@ function rewindPolygon(coords, reverse) {
63676
63676
  var lodash = __toESM(require_lodash(), 1);
63677
63677
  var import_lodash = __toESM(require_lodash(), 1);
63678
63678
 
63679
- // node_modules/polylabel/node_modules/tinyqueue/index.js
63679
+ // node_modules/@focusbc/map-rendering/node_modules/tinyqueue/index.js
63680
63680
  var TinyQueue2 = class {
63681
63681
  constructor(data = [], compare = (a2, b2) => a2 < b2 ? -1 : a2 > b2 ? 1 : 0) {
63682
63682
  this.data = data;
@@ -63733,7 +63733,7 @@ var TinyQueue2 = class {
63733
63733
  }
63734
63734
  };
63735
63735
 
63736
- // node_modules/polylabel/polylabel.js
63736
+ // node_modules/@focusbc/map-rendering/node_modules/polylabel/polylabel.js
63737
63737
  function polylabel(polygon3, precision = 1, debug2 = false) {
63738
63738
  let minX = Infinity;
63739
63739
  let minY = Infinity;
@@ -78338,6 +78338,30 @@ var FbcEditableDynamicLayer = class extends FbcEditableLayer {
78338
78338
  };
78339
78339
  FbcEditableDynamicLayer.layerName = "FbcEditableDynamicLayer";
78340
78340
 
78341
+ // src/utils/color.utils.ts
78342
+ var ColorUtils = class {
78343
+ /**
78344
+ * Converts a hex color string to an rgba color.
78345
+ * @param hex - The hex color string to convert to rgba.
78346
+ * @param opacity - The opacity of the color.
78347
+ * @returns
78348
+ */
78349
+ static hexToRgba(hex, opacity) {
78350
+ if (!hex) {
78351
+ return [0, 0, 0, 0];
78352
+ }
78353
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{0,2})$/i.exec(hex);
78354
+ if (!result?.length || result.length < 3) {
78355
+ return [0, 0, 0, 0];
78356
+ }
78357
+ let alpha = result[4] ? parseInt(result[4], 16) : 255;
78358
+ if (opacity !== null && opacity !== void 0) {
78359
+ alpha = Math.round(opacity / 100 * 255);
78360
+ }
78361
+ return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16), alpha];
78362
+ }
78363
+ };
78364
+
78341
78365
  // src/overlay/overlay-dynamic-layer.builder.ts
78342
78366
  var SHAPES_LAYER_ID = "bbs-shapes";
78343
78367
  var OverlayDynamicLayerBuilder = class {
@@ -78350,6 +78374,7 @@ var OverlayDynamicLayerBuilder = class {
78350
78374
  this._onEdit = () => {
78351
78375
  };
78352
78376
  }
78377
+ // #region Setters
78353
78378
  setSelectedShapeId(shapeId) {
78354
78379
  this._selectedShapeId = shapeId;
78355
78380
  return this;
@@ -78366,23 +78391,21 @@ var OverlayDynamicLayerBuilder = class {
78366
78391
  this._onEdit = onEdit;
78367
78392
  return this;
78368
78393
  }
78394
+ // #endregion
78395
+ // #region Build
78369
78396
  build() {
78370
- const mapPolygon = (polygon3) => {
78371
- return [...polygon3.map((point3) => [point3[0], point3[1]]), [polygon3[0][0], polygon3[0][1]]];
78372
- };
78373
78397
  const objects = [];
78398
+ const labelObjects = [];
78374
78399
  for (const shape of this._shapes) {
78375
78400
  const segments = ShapeInstanceToShapeSegmentsMapper.map(shape);
78376
78401
  for (const segment of segments) {
78377
- objects.push({
78378
- id: segment.shapeId + Math.random(),
78402
+ const object = {
78403
+ id: `${segment.shapeId}-${segment.segmentIndex}`,
78379
78404
  groupId: segment.shapeId,
78380
78405
  geometry: {
78381
78406
  type: "MultiPolygon",
78382
- coordinates: [[mapPolygon(segment.polygon)]],
78383
- style: segment.style
78407
+ coordinates: segment.geometry.coordinates
78384
78408
  },
78385
- label: segment.style?.text,
78386
78409
  type: ObjectType.POLYGON,
78387
78410
  visible: true,
78388
78411
  selectable: true,
@@ -78394,13 +78417,6 @@ var OverlayDynamicLayerBuilder = class {
78394
78417
  editable: true,
78395
78418
  style: {
78396
78419
  pattern: LayerObjectPolygonPattern.NONE,
78397
- label: {
78398
- size: 10,
78399
- color: segment.style?.textColorHex ?? "#000000",
78400
- family: LayerObjectLabelFamily.ARIAL,
78401
- weight: 400,
78402
- opacity: 100
78403
- },
78404
78420
  borderFormat: {
78405
78421
  gap: 0,
78406
78422
  width: 1
@@ -78411,13 +78427,21 @@ var OverlayDynamicLayerBuilder = class {
78411
78427
  borderOpacity: 100,
78412
78428
  borderSize: segment.style?.borderWidth ?? 1
78413
78429
  }
78430
+ };
78431
+ const rotationAngle = shape.rotationRadians ? RotationUtils.radiansToDegrees(shape.rotationRadians) : void 0;
78432
+ labelObjects.push({
78433
+ segment,
78434
+ rotationAngle,
78435
+ initialRotationAngle: rotationAngle
78414
78436
  });
78437
+ objects.push(object);
78415
78438
  }
78416
78439
  }
78417
- return new FbcEditableDynamicLayer({
78440
+ return new BbsDynamicLayer({
78418
78441
  selectedIndexes: this._selectedShapeId ? objects.flatMap((object, index) => object.groupId === this._selectedShapeId ? [index] : []) : void 0,
78419
78442
  id: SHAPES_LAYER_ID,
78420
78443
  data: objects,
78444
+ labelObjects,
78421
78445
  mode: this._edit ? ModeType.TRANSFORM : ModeType.VIEW,
78422
78446
  pickable: true,
78423
78447
  modeConfig: {
@@ -78430,6 +78454,7 @@ var OverlayDynamicLayerBuilder = class {
78430
78454
  }
78431
78455
  });
78432
78456
  }
78457
+ // #endregion
78433
78458
  };
78434
78459
  var DEFAULT_WIDTH_METERS = 6;
78435
78460
  var ShapeInstanceToShapeSegmentsMapper = class {
@@ -78447,25 +78472,37 @@ var ShapeInstanceToShapeSegmentsMapper = class {
78447
78472
  const rotationRadians = shape.rotationRadians ?? 0;
78448
78473
  const rows = shape.type.rows ?? [];
78449
78474
  const hasGrid = rows.length > 0 && rows.some((row) => row.columns.length > 0);
78450
- const toSegment = (minEast, maxEast, minNorth, maxNorth, segmentIndex2) => ({
78475
+ const mapPolygon = (polygon3) => {
78476
+ return [...polygon3.map((point3) => [point3[0], point3[1]]), [polygon3[0][0], polygon3[0][1]]];
78477
+ };
78478
+ const toSegment = (minEast, maxEast, minNorth, maxNorth, segmentIndex2, size2) => ({
78451
78479
  shapeId: shape.id,
78452
78480
  segmentIndex: segmentIndex2,
78453
- polygon: this.localPointsToPolygon(
78454
- [
78455
- { east: minEast, north: minNorth },
78456
- { east: maxEast, north: minNorth },
78457
- { east: maxEast, north: maxNorth },
78458
- { east: minEast, north: maxNorth }
78459
- ],
78460
- shape.center,
78461
- rotationRadians
78462
- ),
78481
+ geometry: {
78482
+ type: "MultiPolygon",
78483
+ coordinates: [
78484
+ [
78485
+ mapPolygon(
78486
+ this.localPointsToPolygon(
78487
+ [
78488
+ { east: minEast, north: minNorth },
78489
+ { east: maxEast, north: minNorth },
78490
+ { east: maxEast, north: maxNorth },
78491
+ { east: minEast, north: maxNorth }
78492
+ ],
78493
+ shape.center,
78494
+ rotationRadians
78495
+ )
78496
+ )
78497
+ ]
78498
+ ]
78499
+ },
78463
78500
  style: shape.styling?.[segmentIndex2],
78464
78501
  shape,
78465
- size
78502
+ size: size2
78466
78503
  });
78467
78504
  if (!hasGrid) {
78468
- return [toSegment(-halfWidth, halfWidth, -halfHeight, halfHeight, 0)];
78505
+ return [toSegment(-halfWidth, halfWidth, -halfHeight, halfHeight, 0, size)];
78469
78506
  }
78470
78507
  const rowWeights = this.normalizeWeights(rows.map((row) => row.height));
78471
78508
  const segments = [];
@@ -78488,12 +78525,14 @@ var ShapeInstanceToShapeSegmentsMapper = class {
78488
78525
  const colMinEast = east;
78489
78526
  const colMaxEast = east + columnWidth;
78490
78527
  east = colMaxEast;
78491
- segments.push(toSegment(colMinEast, colMaxEast, rowMinNorth, rowMaxNorth, segmentIndex));
78528
+ segments.push(
78529
+ toSegment(colMinEast, colMaxEast, rowMinNorth, rowMaxNorth, segmentIndex, { widthMeters: columnWidth, heightMeters: rowHeight })
78530
+ );
78492
78531
  segmentIndex++;
78493
78532
  }
78494
78533
  }
78495
78534
  if (segments.length === 0) {
78496
- return [toSegment(-halfWidth, halfWidth, -halfHeight, halfHeight, 0)];
78535
+ return [toSegment(-halfWidth, halfWidth, -halfHeight, halfHeight, 0, size)];
78497
78536
  }
78498
78537
  return segments;
78499
78538
  }
@@ -78538,6 +78577,152 @@ var ShapeInstanceToShapeSegmentsMapper = class {
78538
78577
  return rotatedRing.slice(0, -1);
78539
78578
  }
78540
78579
  };
78580
+ var BaseLayer = FbcEditableDynamicLayer;
78581
+ var BbsDynamicLayer = class extends BaseLayer {
78582
+ initializeState(context) {
78583
+ super.initializeState(context);
78584
+ this.setState({
78585
+ labelObjects: this.props.labelObjects ?? [],
78586
+ changedLabelRanges: null
78587
+ });
78588
+ }
78589
+ updateState(params) {
78590
+ super.updateState(params);
78591
+ const { props, oldProps, changeFlags } = params;
78592
+ if (changeFlags.dataChanged || props.labelObjects !== oldProps.labelObjects) {
78593
+ this.setState({
78594
+ labelObjects: props.labelObjects ?? [],
78595
+ changedLabelRanges: null
78596
+ });
78597
+ }
78598
+ }
78599
+ getModeProps(props) {
78600
+ const modeProps = super.getModeProps(props);
78601
+ const baseOnEdit = modeProps.onEdit;
78602
+ modeProps.onEdit = (action) => {
78603
+ baseOnEdit(action);
78604
+ if (action.phase === "live") {
78605
+ this.patchLabels(action);
78606
+ }
78607
+ };
78608
+ return modeProps;
78609
+ }
78610
+ renderLayers() {
78611
+ const layers = super.renderLayers() ?? [];
78612
+ return [...layers, this.buildLabelLayer()];
78613
+ }
78614
+ patchLabels(action) {
78615
+ const objects = action.updatedData;
78616
+ const indexes = action.editContext?.objectInstanceIndexes;
78617
+ if (!objects || !indexes?.length) {
78618
+ return;
78619
+ }
78620
+ const labelObjects = [...this.state.labelObjects ?? []];
78621
+ let changed = false;
78622
+ for (const index of indexes) {
78623
+ const object = objects[index];
78624
+ const label = labelObjects[index];
78625
+ if (!object || !label) {
78626
+ continue;
78627
+ }
78628
+ labelObjects[index] = {
78629
+ ...label,
78630
+ segment: { ...label.segment, geometry: object.geometry },
78631
+ rotationAngle: (label.initialRotationAngle ?? 0) + (object.config?.rotation ?? 0)
78632
+ };
78633
+ changed = true;
78634
+ }
78635
+ if (!changed) {
78636
+ return;
78637
+ }
78638
+ this.setState({
78639
+ labelObjects,
78640
+ changedLabelRanges: [...new Set(indexes)].sort((a2, b2) => a2 - b2).map((index) => ({
78641
+ startRow: index,
78642
+ endRow: index + 1
78643
+ }))
78644
+ });
78645
+ }
78646
+ buildLabelLayer() {
78647
+ const labelObjects = this.state.labelObjects ?? [];
78648
+ const changedLabelRanges = this.state.changedLabelRanges;
78649
+ return new text_layer_default(
78650
+ this.getSubLayerProps({
78651
+ id: "labels",
78652
+ data: labelObjects,
78653
+ // Empty ranges would suppress attribute updates (truthy []); use undefined for full rebuild.
78654
+ _dataDiff: changedLabelRanges?.length ? () => changedLabelRanges : void 0,
78655
+ pickable: false,
78656
+ fontFamily: "Open Sans",
78657
+ sizeUnits: "meters",
78658
+ billboard: false,
78659
+ getAlignmentBaseline: () => "center",
78660
+ getText: (d2) => d2.segment.style?.text ?? "",
78661
+ getTextAnchor: (d2) => {
78662
+ const angle3 = d2.rotationAngle ?? 0;
78663
+ switch (d2.segment.style?.textPosition) {
78664
+ case "left":
78665
+ return angle3 > 90 && angle3 < 270 ? "start" : "end";
78666
+ case "right":
78667
+ return angle3 > 90 && angle3 < 270 ? "end" : "start";
78668
+ default:
78669
+ return "middle";
78670
+ }
78671
+ },
78672
+ getPosition: (d2) => {
78673
+ const feature3 = feature(d2.segment.geometry);
78674
+ const centroid3 = centroid(feature3);
78675
+ const offsetX = Number(d2.segment.style?.textPosition);
78676
+ if (isNaN(offsetX)) {
78677
+ return centroid3.geometry.coordinates;
78678
+ }
78679
+ const angle3 = d2.rotationAngle ?? 0;
78680
+ const offsetPoint = destination(point(centroid3.geometry.coordinates), offsetX, angle3 + 90, {
78681
+ units: "meters"
78682
+ });
78683
+ return offsetPoint.geometry.coordinates;
78684
+ },
78685
+ getSize: (d2) => {
78686
+ if (!d2.segment.style?.text?.length) {
78687
+ return 0;
78688
+ }
78689
+ const ring = d2.segment.geometry.coordinates[0][0];
78690
+ const measuredWidth = distance5(ring[0], ring[1], { units: "meters" });
78691
+ const style = d2.segment.style;
78692
+ const size = measuredWidth / style.text.length * 1.5;
78693
+ switch (style.textSize) {
78694
+ case "medium":
78695
+ return size * 0.75;
78696
+ case "small":
78697
+ return size * 0.5;
78698
+ case "large":
78699
+ return size;
78700
+ default:
78701
+ const textSizeNumber = Number(style.textSize);
78702
+ if (!isNaN(textSizeNumber)) {
78703
+ return size / textSizeNumber;
78704
+ }
78705
+ return size;
78706
+ }
78707
+ },
78708
+ getColor: (d2) => {
78709
+ if (d2.segment.style?.textColorHex) {
78710
+ return ColorUtils.hexToRgba(d2.segment.style.textColorHex);
78711
+ }
78712
+ return [0, 0, 0, 255];
78713
+ },
78714
+ getFontFamily: (_2) => LayerObjectLabelFamily.ARIAL,
78715
+ getAngle: (d2) => {
78716
+ if (d2.rotationAngle) {
78717
+ return -d2.rotationAngle;
78718
+ }
78719
+ return 0;
78720
+ }
78721
+ })
78722
+ );
78723
+ }
78724
+ };
78725
+ BbsDynamicLayer.layerName = "BbsDynamicLayer";
78541
78726
 
78542
78727
  // src/overlay/overlay-static-layer.builder.ts
78543
78728
  var OverlayStaticLayerBuilder = class {
@@ -78565,17 +78750,6 @@ var OverlayStaticLayerBuilder = class {
78565
78750
  return this.createRasterTileLayer(layer, index);
78566
78751
  });
78567
78752
  }
78568
- hexToRgba(hex, opacity) {
78569
- var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{0,2})$/i.exec(hex);
78570
- if (!result?.length || result.length < 3) {
78571
- return [0, 0, 0, 0];
78572
- }
78573
- let alpha = result[4] ? parseInt(result[4], 16) : 255;
78574
- if (opacity !== null && opacity !== void 0) {
78575
- alpha = Math.round(opacity / 100 * 255);
78576
- }
78577
- return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16), alpha];
78578
- }
78579
78753
  createVectorTileLayer(layer, index) {
78580
78754
  const id = layer.id;
78581
78755
  const version2 = layer.version;
@@ -78583,7 +78757,7 @@ var OverlayStaticLayerBuilder = class {
78583
78757
  const maxZoom = layer.maxZoom;
78584
78758
  const tileUrl = `${this._apiUrl}/bbs/map/get-map-vector-tile/?layerId=${id}&x={x}&y={y}&z={z}&version=${version2}`;
78585
78759
  const hexColor = layer.lineColor ?? "#000000";
78586
- const lineColor = this.hexToRgba(hexColor);
78760
+ const lineColor = ColorUtils.hexToRgba(hexColor);
78587
78761
  return new mvt_layer_default({
78588
78762
  id,
78589
78763
  index,
@@ -78704,8 +78878,9 @@ var MapOverlay = class _MapOverlay {
78704
78878
  dataTransfer: event.dataTransfer
78705
78879
  });
78706
78880
  };
78707
- const { zoom, heading, tilt } = options;
78708
- const { center: center3, defaultLevelId, rotation } = context;
78881
+ const { zoom, heading: optionsHeading, tilt } = options;
78882
+ const { center: center3, defaultLevelId, heading: contextHeading } = context;
78883
+ const heading = _MapOverlay.convertHeading(optionsHeading ?? contextHeading);
78709
78884
  this._context = context;
78710
78885
  this._htmlElement = htmlElement;
78711
78886
  this._levelId = defaultLevelId;
@@ -78713,7 +78888,7 @@ var MapOverlay = class _MapOverlay {
78713
78888
  zoom: zoom ?? DEFAULT_ZOOM,
78714
78889
  latitude: center3?.lat ?? 0,
78715
78890
  longitude: center3?.lng ?? 0,
78716
- bearing: (heading || rotation) ?? 0,
78891
+ bearing: heading,
78717
78892
  pitch: tilt ?? 0,
78718
78893
  maxZoom: MAX_ZOOM
78719
78894
  };
@@ -78757,7 +78932,7 @@ var MapOverlay = class _MapOverlay {
78757
78932
  if (this._blueprint) {
78758
78933
  staticLayers = new OverlayStaticLayerBuilder(this._context.apiUrl, this._context.apiKey, this._levelId).setLayers(this._context.staticLayers).setSurroundings(this._surroundings).build();
78759
78934
  }
78760
- return [dynamicLayer, ...staticLayers];
78935
+ return [...staticLayers, dynamicLayer];
78761
78936
  }
78762
78937
  rebuildLayers() {
78763
78938
  this._deck.setProps({ layers: this.createLayers() });
@@ -78835,7 +79010,7 @@ var MapOverlay = class _MapOverlay {
78835
79010
  this.rebuildLayers();
78836
79011
  }
78837
79012
  }
78838
- normalizeShapeInstance(shape) {
79013
+ static normalizeShapeInstance(shape) {
78839
79014
  const DEFAULT_WIDTH_METERS2 = 6;
78840
79015
  const type = shape.type;
78841
79016
  const widthMeters = type.widthInMeters != null && type.widthInMeters > 0 ? type.widthInMeters : DEFAULT_WIDTH_METERS2;
@@ -78855,6 +79030,10 @@ var MapOverlay = class _MapOverlay {
78855
79030
  rotationRadians: RotationUtils.normalizeRadians(shape.rotationRadians ?? 0)
78856
79031
  };
78857
79032
  }
79033
+ static convertHeading(heading) {
79034
+ heading = heading % 360;
79035
+ return (360 - heading) % 360;
79036
+ }
78858
79037
  //#endregion
78859
79038
  //#region Public methods
78860
79039
  /**
@@ -78875,14 +79054,14 @@ var MapOverlay = class _MapOverlay {
78875
79054
  }
78876
79055
  //#region Getters and Setters
78877
79056
  setContext(context) {
78878
- const { center: center3, defaultLevelId, rotation } = context;
79057
+ const { center: center3, defaultLevelId, heading } = context;
78879
79058
  this._context = context;
78880
79059
  this._levelId = defaultLevelId;
78881
79060
  this._viewState = {
78882
79061
  ...this._viewState,
78883
79062
  latitude: center3.lat ?? 0,
78884
79063
  longitude: center3.lng ?? 0,
78885
- bearing: rotation ?? this._viewState.bearing ?? 0
79064
+ bearing: _MapOverlay.convertHeading(heading)
78886
79065
  };
78887
79066
  this._deck.setProps({ viewState: this._viewState });
78888
79067
  this.rebuildLayers();
@@ -78944,17 +79123,17 @@ var MapOverlay = class _MapOverlay {
78944
79123
  this._centerChangedEvent.emit(center3);
78945
79124
  }
78946
79125
  getHeading() {
78947
- return this._viewState.bearing ?? 0;
79126
+ return _MapOverlay.convertHeading(this._viewState.bearing ?? 0);
78948
79127
  }
78949
79128
  setHeading(heading) {
78950
- this.applyViewState({ ...this._viewState, bearing: heading });
79129
+ this.applyViewState({ ...this._viewState, bearing: _MapOverlay.convertHeading(heading) });
78951
79130
  this._headingChangedEvent.emit(heading);
78952
79131
  }
78953
79132
  getShapes() {
78954
79133
  return this._shapes;
78955
79134
  }
78956
79135
  setShapes(shapes) {
78957
- this._shapes = shapes.map((shape) => this.normalizeShapeInstance(shape));
79136
+ this._shapes = shapes.map((shape) => _MapOverlay.normalizeShapeInstance(shape));
78958
79137
  if (this._selectedShapeId && !this._shapes.some((s2) => s2.id === this._selectedShapeId)) {
78959
79138
  this._selectedShapeId = null;
78960
79139
  }