@dereekb/dbx-web 9.6.5 → 9.7.0

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.
@@ -2,11 +2,12 @@ import * as i0 from '@angular/core';
2
2
  import { Injectable, Optional, Inject, Directive, Host, Component, ElementRef, ViewChild, Input, ChangeDetectionStrategy, SkipSelf, Injector, NgModule } from '@angular/core';
3
3
  import * as i1$1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
- import { cleanup, filterMaybe, onTrueToFalse, SubscriptionObject } from '@dereekb/rxjs';
6
- import { latLngPointFunction, latLngBoundFunction, isSameLatLngPoint, isDefaultLatLngPoint, swMostLatLngPoint, neMostLatLngPoint, isSameLatLngBound, latLngBoundWrapsMap, isWithinLatLngBoundFunction, overlapsLatLngBoundFunction, diffLatLngBoundPoints, latLngBoundCenterPoint, addLatLngPoints, latLngPoint, DestroyFunctionObject, getValueFromGetter } from '@dereekb/util';
5
+ import { cleanup, filterMaybe, onTrueToFalse, SubscriptionObject, asObservable } from '@dereekb/rxjs';
6
+ import { latLngPointFunction, latLngBoundFunction, isSameLatLngPoint, isDefaultLatLngPoint, swMostLatLngPoint, neMostLatLngPoint, isSameLatLngBound, diffLatLngBoundPoints, latLngBoundWrapsMap, isWithinLatLngBoundFunction, overlapsLatLngBoundFunction, vectorsAreEqual, latLngBoundCenterPoint, addLatLngPoints, latLngPoint, DestroyFunctionObject, getValueFromGetter, LAT_LONG_10M_PRECISION, roundNumberToStepFunction } from '@dereekb/util';
7
7
  import { ComponentStore } from '@ngrx/component-store';
8
- import { switchMap, NEVER, defaultIfEmpty, map, tap, distinctUntilChanged, shareReplay, of, combineLatest, filter, first, startWith, interval, Subject, BehaviorSubject, throttleTime } from 'rxjs';
8
+ import { switchMap, NEVER, defaultIfEmpty, map, tap, distinctUntilChanged, shareReplay, of, combineLatest, filter, first, startWith, interval, Subject, BehaviorSubject, throttleTime, combineLatestWith } from 'rxjs';
9
9
  import * as MapboxGl from 'mapbox-gl';
10
+ import { bounds } from '@mapbox/geo-viewport';
10
11
  import * as i1 from 'ngx-mapbox-gl';
11
12
  import { NgxMapboxGLModule } from 'ngx-mapbox-gl';
12
13
  import * as i3$1 from '@dereekb/dbx-web';
@@ -20,7 +21,7 @@ import { MatIconModule } from '@angular/material/icon';
20
21
  import * as i6 from 'angular-resize-event';
21
22
  import { AngularResizeEventModule } from 'angular-resize-event';
22
23
  import * as i2 from '@dereekb/dbx-core';
23
- import { AbstractSubscriptionDirective, safeMarkForCheck, DbxInjectionComponentModule } from '@dereekb/dbx-core';
24
+ import { AbstractSubscriptionDirective, safeMarkForCheck, tapDetectChanges, DbxInjectionComponentModule } from '@dereekb/dbx-core';
24
25
  import * as i2$1 from '@angular/material/menu';
25
26
 
26
27
  class DbxMapboxConfig {
@@ -57,6 +58,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.2", ngImpor
57
58
  type: Optional
58
59
  }] }]; } });
59
60
 
61
+ function mapboxViewportBoundFunction(config) {
62
+ const { mapCanvasSize, tileSize = 512 } = config;
63
+ const dimensions = [mapCanvasSize.x, mapCanvasSize.y];
64
+ return ({ center, zoom }) => {
65
+ const boundingBox = bounds([center.lng, center.lat], zoom, dimensions, tileSize);
66
+ const [swLng, swLat, neLng, neLat] = boundingBox;
67
+ const result = {
68
+ sw: { lat: swLat, lng: swLng },
69
+ ne: { lat: neLat, lng: neLng }
70
+ };
71
+ return result;
72
+ };
73
+ }
74
+
60
75
  /**
61
76
  * Store used for retrieving information.
62
77
  */
@@ -70,8 +85,9 @@ class DbxMapboxMapStore extends ComponentStore {
70
85
  retainContent: true
71
86
  });
72
87
  this.dbxMapboxService = dbxMapboxService;
73
- this.latLngPoint = latLngPointFunction();
74
- this.latLngBound = latLngBoundFunction({ pointFunction: latLngPointFunction({ wrap: false, validate: false }) });
88
+ this.safeLatLngPoint = latLngPointFunction();
89
+ this.latLngPoint = latLngPointFunction({ wrap: false, validate: false });
90
+ this.latLngBound = latLngBoundFunction({ pointFunction: this.latLngPoint });
75
91
  // MARK: Effects
76
92
  this.setMapService = this.effect((input) => {
77
93
  return input.pipe(switchMap((service) => {
@@ -105,6 +121,12 @@ class DbxMapboxMapStore extends ComponentStore {
105
121
  addListener('click', (x) => this._setClickEvent(x));
106
122
  addListener('dblclick', (x) => this._setDoubleClickEvent(x));
107
123
  addListener('contextmenu', (x) => this._setRightClickEvent(x));
124
+ const refreshForResize = () => {
125
+ const { clientWidth: x, clientHeight: y } = map.getCanvas();
126
+ this._setMapCanvasSize({ x, y });
127
+ };
128
+ addListener('resize', refreshForResize);
129
+ refreshForResize();
108
130
  const subs = [];
109
131
  return {
110
132
  service,
@@ -137,7 +159,7 @@ class DbxMapboxMapStore extends ComponentStore {
137
159
  });
138
160
  this.setCenter = this.effect((input) => {
139
161
  return input.pipe(switchMap((center) => {
140
- const centerPoint = this.latLngPoint(center);
162
+ const centerPoint = this.safeLatLngPoint(center);
141
163
  return this.mapInstance$.pipe(tap((map) => map.setCenter(centerPoint)));
142
164
  }));
143
165
  });
@@ -256,21 +278,21 @@ class DbxMapboxMapStore extends ComponentStore {
256
278
  this.jumpTo = this.effect((input) => {
257
279
  return input.pipe(switchMap((x) => {
258
280
  const inputCenter = x.center ?? x.to?.center;
259
- const center = inputCenter ? this.latLngPoint(inputCenter) : undefined;
281
+ const center = inputCenter ? this.safeLatLngPoint(inputCenter) : undefined;
260
282
  return this.mapInstance$.pipe(tap((map) => map.jumpTo({ ...x.to, center }, x.eventData)));
261
283
  }));
262
284
  });
263
285
  this.easeTo = this.effect((input) => {
264
286
  return input.pipe(switchMap((x) => {
265
287
  const inputCenter = x.center ?? x.to?.center;
266
- const center = inputCenter ? this.latLngPoint(inputCenter) : undefined;
288
+ const center = inputCenter ? this.safeLatLngPoint(inputCenter) : undefined;
267
289
  return this.mapInstance$.pipe(tap((map) => map.easeTo({ ...x.to, center }, x.eventData)));
268
290
  }));
269
291
  });
270
292
  this.flyTo = this.effect((input) => {
271
293
  return input.pipe(switchMap((x) => {
272
294
  const inputCenter = x.center ?? x.to?.center;
273
- const center = inputCenter ? this.latLngPoint(inputCenter) : undefined;
295
+ const center = inputCenter ? this.safeLatLngPoint(inputCenter) : undefined;
274
296
  return this.mapInstance$.pipe(tap((map) => map.flyTo({ ...x.to, center }, x.eventData)));
275
297
  }));
276
298
  });
@@ -339,30 +361,34 @@ class DbxMapboxMapStore extends ComponentStore {
339
361
  const bound = x.getBounds();
340
362
  const boundSw = bound.getSouthWest();
341
363
  const boundNe = bound.getNorthEast();
342
- const sw = isDefaultLatLngPoint(boundSw) ? swMostLatLngPoint() : boundSw;
343
- const ne = isDefaultLatLngPoint(boundNe) ? neMostLatLngPoint() : boundNe;
364
+ const sw = isDefaultLatLngPoint(boundSw) ? swMostLatLngPoint() : { lat: boundSw.lat, lng: boundSw.lng };
365
+ const ne = isDefaultLatLngPoint(boundNe) ? neMostLatLngPoint() : { lat: boundNe.lat, lng: boundNe.lng };
344
366
  return this.latLngBound(sw, ne);
345
367
  }))), shareReplay(1))));
346
368
  this.bound$ = this.whenInitialized$.pipe(switchMap(() => {
347
369
  return this.isRendering$.pipe(onTrueToFalse(), startWith(undefined), switchMap((x) => this.boundNow$.pipe(first())), distinctUntilChanged(isSameLatLngBound), shareReplay(1));
348
370
  }));
371
+ this.boundSizing$ = this.bound$.pipe(map((x) => diffLatLngBoundPoints(x)), shareReplay(1));
349
372
  this.boundWrapsAroundWorld$ = this.bound$.pipe(map((x) => latLngBoundWrapsMap(x)), distinctUntilChanged(), shareReplay(1));
350
373
  this.isWithinBoundFunction$ = this.bound$.pipe(map((x) => isWithinLatLngBoundFunction(x)), shareReplay(1));
351
374
  this.overlapsBoundFunction$ = this.bound$.pipe(map((x) => overlapsLatLngBoundFunction(x)), shareReplay(1));
352
375
  this.zoomNow$ = this.whenInitialized$.pipe(switchMap(() => this.mapInstance$.pipe(switchMap((x) => this._renderingTimer.pipe(map(() => x.getZoom()))), shareReplay(1))));
353
376
  this.zoom$ = this.whenInitialized$.pipe(switchMap(() => {
354
- return this.isZooming$.pipe(onTrueToFalse(), startWith(undefined), switchMap((x) => this.zoomNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
377
+ return this.isZooming$.pipe(onTrueToFalse(), startWith(undefined), switchMap(() => this.zoomNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
355
378
  }));
356
379
  this.pitchNow$ = this.whenInitialized$.pipe(switchMap(() => this.mapInstance$.pipe(switchMap((x) => this._movingTimer.pipe(map(() => x.getPitch()))), shareReplay(1))));
357
380
  this.pitch$ = this.whenInitialized$.pipe(switchMap(() => {
358
- return this.isRotating$.pipe(onTrueToFalse(), startWith(undefined), switchMap((x) => this.pitchNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
381
+ return this.isRotating$.pipe(onTrueToFalse(), startWith(undefined), switchMap(() => this.pitchNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
359
382
  }));
360
383
  this.bearingNow$ = this.whenInitialized$.pipe(switchMap(() => this.mapInstance$.pipe(switchMap((x) => this._movingTimer.pipe(map(() => x.getBearing()))), shareReplay(1))));
361
384
  this.bearing$ = this.whenInitialized$.pipe(switchMap(() => {
362
- return this.isRotating$.pipe(onTrueToFalse(), startWith(undefined), switchMap((x) => this.bearingNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
385
+ return this.isRotating$.pipe(onTrueToFalse(), startWith(undefined), switchMap(() => this.bearingNow$.pipe(first())), distinctUntilChanged(), shareReplay(1));
363
386
  }));
364
387
  this.content$ = this.state$.pipe(map((x) => x.content), distinctUntilChanged(), shareReplay(1));
365
388
  this.hasContent$ = this.content$.pipe(map(Boolean));
389
+ this.currentMapCanvasSize$ = this.state$.pipe(map((x) => x.mapCanvasSize), distinctUntilChanged((a, b) => a != null && b != null && vectorsAreEqual(a, b)), shareReplay(1));
390
+ this.mapCanvasSize$ = this.currentMapCanvasSize$.pipe(filterMaybe());
391
+ this.viewportBoundFunction$ = this.mapCanvasSize$.pipe(map((x) => mapboxViewportBoundFunction({ mapCanvasSize: x })), shareReplay(1));
366
392
  this.clickEvent$ = this.state$.pipe(map((x) => x.clickEvent), distinctUntilChanged(), shareReplay(1));
367
393
  this.doubleClickEvent$ = this.state$.pipe(map((x) => x.doubleClickEvent), distinctUntilChanged(), shareReplay(1));
368
394
  this.rightClickEvent$ = this.state$.pipe(map((x) => x.rightClickEvent), distinctUntilChanged(), shareReplay(1));
@@ -373,6 +399,7 @@ class DbxMapboxMapStore extends ComponentStore {
373
399
  this._setMoveState = this.updater((state, moveState) => ({ ...state, moveState }));
374
400
  this._setZoomState = this.updater((state, zoomState) => ({ ...state, zoomState }));
375
401
  this._setRotateState = this.updater((state, rotateState) => ({ ...state, rotateState }));
402
+ this._setMapCanvasSize = this.updater((state, mapCanvasSize) => ({ ...state, mapCanvasSize }));
376
403
  this._setClickEvent = this.updater((state, clickEvent) => ({ ...state, clickEvent }));
377
404
  this._setDoubleClickEvent = this.updater((state, doubleClickEvent) => ({ ...state, doubleClickEvent }));
378
405
  this._setRightClickEvent = this.updater((state, rightClickEvent) => ({ ...state, rightClickEvent }));
@@ -419,7 +446,7 @@ class DbxMapboxMapStore extends ComponentStore {
419
446
  }
420
447
  calculateNextCenterOffsetWithScreenMarginChange(sizing) {
421
448
  return this.atNextIdle().pipe(switchMap(() => this.bound$.pipe(first(), map((bounds) => {
422
- const diff = diffLatLngBoundPoints(bounds);
449
+ const diff = diffLatLngBoundPoints(bounds, true);
423
450
  const center = latLngBoundCenterPoint(bounds);
424
451
  const offsetWidth = sizing.leftMargin + sizing.rightMargin; // 300 + 0
425
452
  const newWidth = sizing.fullWidth - offsetWidth; // 1000 - 300 - 0
@@ -889,7 +916,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.2", ngImpor
889
916
  * Component used to render a set of DbxMapboxMarker values from the input data and marker factory.
890
917
  */
891
918
  class DbxMapboxMarkersComponent {
892
- constructor() {
919
+ constructor(cdRef) {
920
+ this.cdRef = cdRef;
893
921
  this._data = new BehaviorSubject(undefined);
894
922
  this._markerFactory = new BehaviorSubject(undefined);
895
923
  this.markers$ = combineLatest([this._data.pipe(distinctUntilChanged()), this._markerFactory.pipe(distinctUntilChanged())]).pipe(map(([data, markerFactory]) => {
@@ -899,7 +927,7 @@ class DbxMapboxMarkersComponent {
899
927
  else {
900
928
  return [];
901
929
  }
902
- }), shareReplay(1));
930
+ }), tapDetectChanges(this.cdRef), shareReplay(1));
903
931
  }
904
932
  get data() {
905
933
  return this._data.value;
@@ -918,19 +946,20 @@ class DbxMapboxMarkersComponent {
918
946
  this._markerFactory.complete();
919
947
  }
920
948
  }
921
- DbxMapboxMarkersComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.2", ngImport: i0, type: DbxMapboxMarkersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
949
+ DbxMapboxMarkersComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.2", ngImport: i0, type: DbxMapboxMarkersComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
922
950
  DbxMapboxMarkersComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.2", type: DbxMapboxMarkersComponent, selector: "dbx-mapbox-markers", inputs: { data: "data", markerFactory: "markerFactory" }, ngImport: i0, template: `
923
951
  <dbx-mapbox-marker *ngFor="let marker of markers$ | async" [marker]="marker"></dbx-mapbox-marker>
924
- `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: DbxMapboxMarkerComponent, selector: "dbx-mapbox-marker", inputs: ["marker"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] });
952
+ `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: DbxMapboxMarkerComponent, selector: "dbx-mapbox-marker", inputs: ["marker"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
925
953
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.2", ngImport: i0, type: DbxMapboxMarkersComponent, decorators: [{
926
954
  type: Component,
927
955
  args: [{
928
956
  selector: 'dbx-mapbox-markers',
929
957
  template: `
930
958
  <dbx-mapbox-marker *ngFor="let marker of markers$ | async" [marker]="marker"></dbx-mapbox-marker>
931
- `
959
+ `,
960
+ changeDetection: ChangeDetectionStrategy.OnPush
932
961
  }]
933
- }], propDecorators: { data: [{
962
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { data: [{
934
963
  type: Input
935
964
  }], markerFactory: [{
936
965
  type: Input
@@ -1031,6 +1060,56 @@ function dbxMapboxColoredDotStyle(background, color) {
1031
1060
  };
1032
1061
  }
1033
1062
 
1063
+ /**
1064
+ * Filters the input objects based on their center and zoom values.
1065
+ *
1066
+ * This function caches the bounds computations for each of the input values.
1067
+ *
1068
+ * @param config
1069
+ * @returns
1070
+ */
1071
+ function filterByMapboxViewportBound(config) {
1072
+ const { boundDecisionObs: inputBoundDecisionObs, boundFunctionObs: inputBoundFunctionObs, defaultZoom: inputDefaultZoom = 17, readValue, zoomRounding, precision = LAT_LONG_10M_PRECISION } = config;
1073
+ const _latLngPoint = latLngPointFunction({ wrap: false, validate: false, precision });
1074
+ const _roundZoom = roundNumberToStepFunction(zoomRounding || { step: 0.5, round: 'floor' });
1075
+ const boundDecisionObs = asObservable(inputBoundDecisionObs);
1076
+ const boundFunctionObs = asObservable(inputBoundFunctionObs);
1077
+ return (input) => {
1078
+ return boundFunctionObs.pipe(distinctUntilChanged(), switchMap((viewportBoundFunction) => {
1079
+ const cache = new Map();
1080
+ return input.pipe(map((values) => {
1081
+ return values.map((value) => {
1082
+ const item = readValue(value);
1083
+ const centerLatLng = _latLngPoint(item.center);
1084
+ const zoomStep = _roundZoom(item.zoom || inputDefaultZoom);
1085
+ const cacheKey = `${zoomStep}_${centerLatLng.lat}_${centerLatLng.lng}`;
1086
+ const cachedValue = cache.get(cacheKey);
1087
+ let bound;
1088
+ if (!cachedValue) {
1089
+ bound = viewportBoundFunction({ center: centerLatLng, zoom: zoomStep });
1090
+ cache.set(cacheKey, bound);
1091
+ }
1092
+ else {
1093
+ bound = cachedValue;
1094
+ }
1095
+ return {
1096
+ value,
1097
+ bound
1098
+ };
1099
+ });
1100
+ }), combineLatestWith(boundDecisionObs), map(([items, boundFunction]) => {
1101
+ let valuesInBounds = [];
1102
+ items.forEach((item) => {
1103
+ if (boundFunction(item.bound)) {
1104
+ valuesInBounds.push(item.value);
1105
+ }
1106
+ });
1107
+ return valuesInBounds;
1108
+ }));
1109
+ }), shareReplay(1));
1110
+ };
1111
+ }
1112
+
1034
1113
  const KNOWN_MAPBOX_STYLES = [
1035
1114
  //
1036
1115
  'mapbox://styles/mapbox/streets-v11',
@@ -1052,5 +1131,5 @@ function mapboxZoomLevel(input) {
1052
1131
  * Generated bundle index. Do not edit.
1053
1132
  */
1054
1133
 
1055
- export { DEFAULT_MAPBOX_CENTER, DEFAULT_MAPBOX_MAP_STORE_TIMER_REFRESH_PERIOD, DEFAULT_MAPBOX_STYLE, DEFAULT_MAPBOX_ZOOM, DbxMapboxConfig, DbxMapboxLayoutComponent, DbxMapboxLayoutDrawerComponent, DbxMapboxMapDirective, DbxMapboxMapStore, DbxMapboxMapStoreInjectionBlockDirective, DbxMapboxMapStoreProviderBlock, DbxMapboxMarkerComponent, DbxMapboxMarkersComponent, DbxMapboxMenuComponent, DbxMapboxModule, DbxMapboxService, KNOWN_MAPBOX_STYLES, MAPBOX_MAX_ZOOM_LEVEL, MAPBOX_MIN_ZOOM_LEVEL, dbxMapboxColoredDotStyle, mapboxZoomLevel, provideMapboxStoreIfParentIsUnavailable };
1134
+ export { DEFAULT_MAPBOX_CENTER, DEFAULT_MAPBOX_MAP_STORE_TIMER_REFRESH_PERIOD, DEFAULT_MAPBOX_STYLE, DEFAULT_MAPBOX_ZOOM, DbxMapboxConfig, DbxMapboxLayoutComponent, DbxMapboxLayoutDrawerComponent, DbxMapboxMapDirective, DbxMapboxMapStore, DbxMapboxMapStoreInjectionBlockDirective, DbxMapboxMapStoreProviderBlock, DbxMapboxMarkerComponent, DbxMapboxMarkersComponent, DbxMapboxMenuComponent, DbxMapboxModule, DbxMapboxService, KNOWN_MAPBOX_STYLES, MAPBOX_MAX_ZOOM_LEVEL, MAPBOX_MIN_ZOOM_LEVEL, dbxMapboxColoredDotStyle, filterByMapboxViewportBound, mapboxViewportBoundFunction, mapboxZoomLevel, provideMapboxStoreIfParentIsUnavailable };
1056
1135
  //# sourceMappingURL=dereekb-dbx-web-mapbox.mjs.map