@foodmarketmaker/mapag 0.0.48 → 0.0.49

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.
@@ -12,11 +12,11 @@ import booleanContains from '@turf/boolean-contains';
12
12
  import booleanOverlap from '@turf/boolean-overlap';
13
13
  import { polygon, feature } from '@turf/helpers';
14
14
  import { Subject, firstValueFrom, map } from 'rxjs';
15
+ import maplibregl, { Popup } from 'maplibre-gl';
15
16
  import MapboxDraw from 'maplibre-gl-draw';
16
17
  import RectangleMode from 'mapbox-gl-draw-rectangle-mode';
17
18
  import { saveAs } from 'file-saver';
18
19
  import 'mapbox-gl-infobox/styles.css';
19
- import maplibregl, { Popup } from 'maplibre-gl';
20
20
  import bbox from '@turf/bbox';
21
21
  import bboxPolygon from '@turf/bbox-polygon';
22
22
  import buffer from '@turf/buffer';
@@ -208,9 +208,8 @@ async function sampleTilesForLayers(pmtiles) {
208
208
  return [];
209
209
  }
210
210
  }
211
- async function pmtilesPixelInfo(url, map, e) {
211
+ async function pmtilesPixelInfo(url, map, lngLat) {
212
212
  const pmtiles = new PMTiles(url.replace('pmtiles://', ''));
213
- const lngLat = e.lngLat; // {lng, lat}
214
213
  // Convert lat/lon to tile coordinates at a chosen zoom
215
214
  const zoom = 10; // pick a zoom level for sampling
216
215
  const x = Math.floor(((lngLat.lng + 180) / 360) * Math.pow(2, zoom));
@@ -13623,6 +13622,17 @@ class MapboxMapperGroup {
13623
13622
  clear() {
13624
13623
  this.mappers.forEach((mapper) => mapper.clear());
13625
13624
  }
13625
+ renderPopup(f) {
13626
+ for (const [name, mapper] of this.mappers) {
13627
+ if (mapper.renderPopup) {
13628
+ const result = mapper.renderPopup(f);
13629
+ if (result) {
13630
+ return result;
13631
+ }
13632
+ }
13633
+ }
13634
+ return undefined;
13635
+ }
13626
13636
  }
13627
13637
 
13628
13638
  class StandardLayersMapper {
@@ -13824,8 +13834,14 @@ class AreaMapperMapper {
13824
13834
  this.map.setZoom(src.minZoom);
13825
13835
  }
13826
13836
  }
13827
- renderPopup(item) {
13828
- return 'NO POPUP';
13837
+ renderPopup(feature) {
13838
+ if (!this.map) {
13839
+ return undefined;
13840
+ }
13841
+ if (feature.layer.id !== this.layer) {
13842
+ return undefined;
13843
+ }
13844
+ return undefined;
13829
13845
  }
13830
13846
  useStat(id, stats) {
13831
13847
  const i = stats.findIndex((a) => a.id == id);
@@ -14206,6 +14222,31 @@ class MapService {
14206
14222
  this.map.getCanvas().style.cursor = 'pointer';
14207
14223
  }
14208
14224
  }
14225
+ currentPopup = null;
14226
+ handleMapClick(point, lngLat) {
14227
+ if (!this.map)
14228
+ return;
14229
+ if (!this.mapper)
14230
+ return;
14231
+ // Get the features
14232
+ const features = this.map.queryRenderedFeatures(point);
14233
+ let html = undefined;
14234
+ for (const feature of features) {
14235
+ html = this.mapper.renderPopup(feature);
14236
+ if (html) {
14237
+ break;
14238
+ }
14239
+ }
14240
+ if (html) {
14241
+ if (this.currentPopup) {
14242
+ this.currentPopup.remove();
14243
+ }
14244
+ this.currentPopup = new Popup()
14245
+ .setLngLat(lngLat)
14246
+ .setHTML(html)
14247
+ .addTo(this.map);
14248
+ }
14249
+ }
14209
14250
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MapService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
14210
14251
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MapService, providedIn: 'root' });
14211
14252
  }
@@ -15119,6 +15160,15 @@ class MapComponent {
15119
15160
  this.mapper().onReady(map, this.svc);
15120
15161
  });
15121
15162
  });
15163
+ map.on('click', (e) => {
15164
+ this.svc.handleMapClick(e.point, e.lngLat);
15165
+ });
15166
+ map.on('touchend', (e) => {
15167
+ // Ignore multi-touch events
15168
+ if (e.points && e.points.length == 1) {
15169
+ this.svc.handleMapClick(e.point, e.lngLat);
15170
+ }
15171
+ });
15122
15172
  }
15123
15173
  });
15124
15174
  }
@@ -16110,7 +16160,7 @@ class CroplandDataLayerMapper {
16110
16160
  if (!this.settings().visible) {
16111
16161
  return;
16112
16162
  }
16113
- const pixel = await pmtilesPixelInfo(CroplandDataLayerMapper.PMTILES, map, e);
16163
+ const pixel = await pmtilesPixelInfo(CroplandDataLayerMapper.PMTILES, map, e.lngLat);
16114
16164
  if (!pixel) {
16115
16165
  console.error('No pixel data returned');
16116
16166
  return;
@@ -16641,53 +16691,40 @@ class CropSequenceMapper {
16641
16691
  type: 'line',
16642
16692
  }, StandardLayersMapper.POLYGONS_BACKGROUND);
16643
16693
  this._update(this.settings());
16644
- if (!addedFill) {
16645
- return;
16694
+ }
16695
+ renderPopup(feature) {
16696
+ if (!this.map) {
16697
+ return undefined;
16646
16698
  }
16647
- map.on('mousemove', this.FILL_LAYER_ID, (e) => {
16648
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
16649
- });
16650
- map.on('click', this.FILL_LAYER_ID, (e) => {
16651
- // Publish
16652
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
16653
- if (e.features && e.features.length > 0) {
16654
- const feature = e.features[0];
16655
- const coordinates = e.lngLat;
16656
- if (this.popup) {
16657
- this.popup.remove();
16658
- }
16659
- const tb = new TableBuilder();
16660
- const crop2017 = this.lookupClass(feature.properties ? feature.properties['CDL2017'] : null);
16661
- const crop2018 = this.lookupClass(feature.properties ? feature.properties['CDL2018'] : null);
16662
- const crop2019 = this.lookupClass(feature.properties ? feature.properties['CDL2019'] : null);
16663
- const crop2020 = this.lookupClass(feature.properties ? feature.properties['CDL2020'] : null);
16664
- const crop2021 = this.lookupClass(feature.properties ? feature.properties['CDL2021'] : null);
16665
- const crop2022 = this.lookupClass(feature.properties ? feature.properties['CDL2022'] : null);
16666
- const crop2023 = this.lookupClass(feature.properties ? feature.properties['CDL2023'] : null);
16667
- const crop2024 = this.lookupClass(feature.properties ? feature.properties['CDL2024'] : null);
16668
- tb.addHeader('Year', 'Crop Type');
16669
- tb.add('2024', crop2024 ?? 'Unknown');
16670
- tb.add('2023', crop2023 ?? 'Unknown');
16671
- tb.add('2022', crop2022 ?? 'Unknown');
16672
- tb.add('2021', crop2021 ?? 'Unknown');
16673
- tb.add('2020', crop2020 ?? 'Unknown');
16674
- tb.add('2019', crop2019 ?? 'Unknown');
16675
- tb.add('2018', crop2018 ?? 'Unknown');
16676
- tb.add('2017', crop2017 ?? 'Unknown');
16677
- tb.addHeader('Location', "");
16678
- tb.add('State FIPS', feature.properties ? feature.properties['STATEFIPS'] : 'Unknown');
16679
- tb.add('County', feature.properties ? feature.properties['CNTY'] : 'Unknown');
16680
- tb.add('County FIPS', feature.properties ? feature.properties['CNTYFIPS'] : 'Unknown');
16681
- tb.add('ASD', feature.properties ? feature.properties['ASD'] : 'Unknown');
16682
- tb.add('Area (M²)', feature.properties ? feature.properties['Shape_Area'] : 'Unknown');
16683
- const fieldsHtml = tb.toHtml();
16684
- this.currentFeatureID = feature?.properties?.['globalid'];
16685
- this.popup = new Popup({ maxWidth: '400px' })
16686
- .setLngLat(coordinates)
16687
- .setHTML(`<strong>Crop Sequence</strong><br/>${fieldsHtml}`)
16688
- .addTo(map);
16689
- }
16690
- });
16699
+ if (feature.layer.id !== this.FILL_LAYER_ID && feature.layer.id !== this.LINE_LAYER_ID) {
16700
+ return undefined;
16701
+ }
16702
+ const tb = new TableBuilder();
16703
+ const crop2017 = this.lookupClass(feature.properties ? feature.properties['CDL2017'] : null);
16704
+ const crop2018 = this.lookupClass(feature.properties ? feature.properties['CDL2018'] : null);
16705
+ const crop2019 = this.lookupClass(feature.properties ? feature.properties['CDL2019'] : null);
16706
+ const crop2020 = this.lookupClass(feature.properties ? feature.properties['CDL2020'] : null);
16707
+ const crop2021 = this.lookupClass(feature.properties ? feature.properties['CDL2021'] : null);
16708
+ const crop2022 = this.lookupClass(feature.properties ? feature.properties['CDL2022'] : null);
16709
+ const crop2023 = this.lookupClass(feature.properties ? feature.properties['CDL2023'] : null);
16710
+ const crop2024 = this.lookupClass(feature.properties ? feature.properties['CDL2024'] : null);
16711
+ tb.addHeader('Year', 'Crop Type');
16712
+ tb.add('2024', crop2024 ?? 'Unknown');
16713
+ tb.add('2023', crop2023 ?? 'Unknown');
16714
+ tb.add('2022', crop2022 ?? 'Unknown');
16715
+ tb.add('2021', crop2021 ?? 'Unknown');
16716
+ tb.add('2020', crop2020 ?? 'Unknown');
16717
+ tb.add('2019', crop2019 ?? 'Unknown');
16718
+ tb.add('2018', crop2018 ?? 'Unknown');
16719
+ tb.add('2017', crop2017 ?? 'Unknown');
16720
+ tb.addHeader('Location', "");
16721
+ tb.add('State FIPS', feature.properties ? feature.properties['STATEFIPS'] : 'Unknown');
16722
+ tb.add('County', feature.properties ? feature.properties['CNTY'] : 'Unknown');
16723
+ tb.add('County FIPS', feature.properties ? feature.properties['CNTYFIPS'] : 'Unknown');
16724
+ tb.add('ASD', feature.properties ? feature.properties['ASD'] : 'Unknown');
16725
+ tb.add('Area (M²)', feature.properties ? feature.properties['Shape_Area'] : 'Unknown');
16726
+ const fieldsHtml = tb.toHtml();
16727
+ return fieldsHtml;
16691
16728
  }
16692
16729
  lookupClass(code) {
16693
16730
  const found = CroplandLegend.find((item) => {
@@ -16720,7 +16757,6 @@ class CropSequenceMapper {
16720
16757
  count = 0;
16721
16758
  total = 0;
16722
16759
  map;
16723
- popup = null;
16724
16760
  }
16725
16761
  class CropSequenceSettings {
16726
16762
  visible = true;
@@ -16978,10 +17014,10 @@ class FoodhubMapper {
16978
17014
  RemoveLayer(this.map, this.CIRCLE_LAYER_ID);
16979
17015
  RemoveLayer(this.map, this.ICON_LAYER_ID);
16980
17016
  RemoveLayer(this.map, this.HEATMAP_LAYER_ID);
16981
- this.map.off('click', this.CIRCLE_LAYER_ID, this.onClick);
16982
- this.map.off('click', this.ICON_LAYER_ID, this.onClick);
16983
- this.map.off('touchend', this.CIRCLE_LAYER_ID, this.onClick);
16984
- this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
17017
+ // this.map.off('click', this.CIRCLE_LAYER_ID, this.onClick);
17018
+ // this.map.off('click', this.ICON_LAYER_ID, this.onClick);
17019
+ // this.map.off('touchend', this.CIRCLE_LAYER_ID, this.onClick);
17020
+ // this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
16985
17021
  this.count = 0;
16986
17022
  }
16987
17023
  updateLegend(settings) {
@@ -17020,14 +17056,14 @@ class FoodhubMapper {
17020
17056
  // this.addClusterLayers(map);
17021
17057
  }
17022
17058
  // Add popup on click
17023
- this.map.off('click', this.CIRCLE_LAYER_ID, this.onClick);
17024
- this.map.off('click', this.ICON_LAYER_ID, this.onClick);
17025
- this.map.off('touchend', this.CIRCLE_LAYER_ID, this.onClick);
17026
- this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
17027
- map.on('click', this.CIRCLE_LAYER_ID, this.onClick);
17028
- map.on('click', this.ICON_LAYER_ID, this.onClick);
17029
- map.on('touchend', this.CIRCLE_LAYER_ID, this.onClick);
17030
- map.on('touchend', this.ICON_LAYER_ID, this.onClick);
17059
+ // this.map.off('click', this.CIRCLE_LAYER_ID, this.onClick);
17060
+ // this.map.off('click', this.ICON_LAYER_ID, this.onClick);
17061
+ // this.map.off('touchend', this.CIRCLE_LAYER_ID, this.onClick);
17062
+ // this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
17063
+ // map.on('click', this.CIRCLE_LAYER_ID, this.onClick);
17064
+ // map.on('click', this.ICON_LAYER_ID, this.onClick);
17065
+ // map.on('touchend', this.CIRCLE_LAYER_ID, this.onClick);
17066
+ // map.on('touchend', this.ICON_LAYER_ID, this.onClick);
17031
17067
  this.filter(map);
17032
17068
  untracked(() => this.updateLegend(settings));
17033
17069
  }
@@ -17186,40 +17222,44 @@ class FoodhubMapper {
17186
17222
  getSettings() {
17187
17223
  return { ...this.settings() };
17188
17224
  }
17189
- onClick = (e) => {
17225
+ // onClick = (e: MapLayerMouseEvent | MapLayerTouchEvent) => {
17226
+ // if (!this.map) {
17227
+ // return;
17228
+ // }
17229
+ // const map = this.map;
17230
+ // let features;
17231
+ // const settings = this.settings();
17232
+ // if (settings.type == 'circle') {
17233
+ // features = this.map.queryRenderedFeatures(e.point, {
17234
+ // layers: [this.CIRCLE_LAYER_ID],
17235
+ // });
17236
+ // } else if (settings.type == 'icon') {
17237
+ // features = this.map.queryRenderedFeatures(e.point, {
17238
+ // layers: [this.ICON_LAYER_ID],
17239
+ // });
17240
+ // }
17241
+ // if (!features || features.length == 0) {
17242
+ // return;
17243
+ // }
17244
+ // if (features.length > 0) {
17245
+ // const item = features[0];
17246
+ // if (item) {
17247
+ // console.debug('Rendering Popup for ' + item.id + ' in ' + this.ICON_LAYER_ID);
17248
+ // const html = this.renderPopup(item);
17249
+ // if (!html) {
17250
+ // return;
17251
+ // }
17252
+ // new Popup().setLngLat(e.lngLat).setHTML(html).addTo(map);
17253
+ // }
17254
+ // }
17255
+ // };
17256
+ renderPopup(f) {
17190
17257
  if (!this.map) {
17191
- return;
17192
- }
17193
- const map = this.map;
17194
- let features;
17195
- const settings = this.settings();
17196
- if (settings.type == 'circle') {
17197
- features = this.map.queryRenderedFeatures(e.point, {
17198
- layers: [this.CIRCLE_LAYER_ID],
17199
- });
17200
- }
17201
- else if (settings.type == 'icon') {
17202
- features = this.map.queryRenderedFeatures(e.point, {
17203
- layers: [this.ICON_LAYER_ID],
17204
- });
17205
- }
17206
- if (!features || features.length == 0) {
17207
- return;
17258
+ return undefined;
17208
17259
  }
17209
- if (features.length > 0) {
17210
- const item = features[0];
17211
- if (item) {
17212
- console.debug('Rendering Popup for ' + item.id + ' in ' + this.ICON_LAYER_ID);
17213
- this.renderPopup(item).then((html) => {
17214
- if (!html) {
17215
- return;
17216
- }
17217
- new Popup().setLngLat(e.lngLat).setHTML(html).addTo(map);
17218
- });
17219
- }
17260
+ if (f.layer.id !== this.CIRCLE_LAYER_ID && f.layer.id !== this.ICON_LAYER_ID && f.layer.id !== this.HEATMAP_LAYER_ID) {
17261
+ return undefined;
17220
17262
  }
17221
- };
17222
- async renderPopup(f) {
17223
17263
  if (!f || !f.properties) {
17224
17264
  return undefined;
17225
17265
  }
@@ -17313,36 +17353,27 @@ class HardinessMapper {
17313
17353
  type: 'fill',
17314
17354
  }, StandardLayersMapper.POLYGONS_BACKGROUND);
17315
17355
  this._update(this.settings());
17316
- if (added) {
17317
- map.on('mousemove', this.LAYER_ID, (e) => {
17318
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
17319
- });
17320
- map.on('click', this.LAYER_ID, (e) => {
17321
- // Publish
17322
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
17323
- if (e.features && e.features.length > 0) {
17324
- const feature = e.features[0];
17325
- const coordinates = e.lngLat;
17326
- const name = feature.properties
17327
- ? feature.properties['zone']
17328
- : 'Unknown';
17329
- // Ensure that if the popup is already open, we don't create a new one
17330
- if (this.popup) {
17331
- this.popup.remove();
17332
- }
17333
- const fields = feature.properties
17334
- ? Object.entries(feature.properties)
17335
- .map(([key, value]) => `<strong>${key}:</strong> ${value}`)
17336
- .join('<br/>')
17337
- : '';
17338
- this.currentFeatureID = feature?.properties?.['globalid'];
17339
- this.popup = new Popup({ maxWidth: '400px' })
17340
- .setLngLat(coordinates)
17341
- .setHTML(`<strong>Hardiness:</strong> ${name}<hr /><br/>${fields}`)
17342
- .addTo(map);
17343
- }
17344
- });
17356
+ }
17357
+ renderPopup(feature) {
17358
+ if (!this.map) {
17359
+ return undefined;
17360
+ }
17361
+ if (feature.layer.id !== this.LAYER_ID) {
17362
+ return undefined;
17345
17363
  }
17364
+ const name = feature.properties
17365
+ ? feature.properties['zone']
17366
+ : 'Unknown';
17367
+ // Ensure that if the popup is already open, we don't create a new one
17368
+ if (this.popup) {
17369
+ this.popup.remove();
17370
+ }
17371
+ const fields = feature.properties
17372
+ ? Object.entries(feature.properties)
17373
+ .map(([key, value]) => `<strong>${key}:</strong> ${value}`)
17374
+ .join('<br/>')
17375
+ : '';
17376
+ return `<strong>Hardiness:</strong> ${name}<hr /><br/>${fields}`;
17346
17377
  }
17347
17378
  update(newSettings) {
17348
17379
  this.settings.set({ ...this.settings(), ...newSettings });
@@ -21568,8 +21599,6 @@ class NAASMapper {
21568
21599
  visibility: 'none',
21569
21600
  },
21570
21601
  }, StandardLayersMapper.POLYGONS_BACKGROUND);
21571
- map.off('click', this.LAYER_ID, this.onClick);
21572
- map.on('click', this.LAYER_ID, this.onClick);
21573
21602
  }
21574
21603
  setFeatureStates(settings, fs) {
21575
21604
  if (!this.map) {
@@ -21688,50 +21717,39 @@ class NAASMapper {
21688
21717
  }
21689
21718
  clear() {
21690
21719
  if (this.map) {
21691
- this.map.off('click', this.LAYER_ID, this.onClick);
21692
21720
  RemoveLayer(this.map, this.LAYER_ID);
21693
21721
  RemoveLayer(this.map, this.SOURCE_ID);
21694
21722
  }
21695
21723
  }
21696
- onClick = async (e) => {
21724
+ renderPopup(feature) {
21725
+ // Determine if this is mine
21697
21726
  if (!this.map) {
21698
- return;
21727
+ return undefined;
21728
+ }
21729
+ if (feature.layer.id !== this.LAYER_ID) {
21730
+ return undefined;
21699
21731
  }
21700
21732
  const settings = this.settings();
21701
21733
  const src = Layers.FindVector(settings.areaType);
21702
21734
  if (!src) {
21703
21735
  console.warn('ChoroplethMapper: No source found for area type ', settings.areaType);
21704
- return;
21736
+ return undefined;
21705
21737
  }
21706
- const features = this.map.queryRenderedFeatures(e.point, {
21707
- layers: [this.LAYER_ID],
21738
+ const state = this.map.getFeatureState({
21739
+ source: this.SOURCE_ID,
21740
+ sourceLayer: src.Source,
21741
+ id: feature.id
21708
21742
  });
21709
- if (features.length > 0) {
21710
- e.preventDefault();
21711
- if (this.current) {
21712
- this.current.remove();
21713
- this.current = null;
21714
- }
21715
- const f = features[0];
21716
- const state = this.map.getFeatureState({
21717
- source: this.SOURCE_ID,
21718
- sourceLayer: src.Source,
21719
- id: f.id
21720
- });
21721
- const html = await this.RenderPopup(f, state);
21722
- if (html) {
21723
- this.current = new Popup().setLngLat(e.lngLat).setHTML(html).addTo(this.map);
21724
- }
21725
- }
21726
- };
21743
+ return this.RenderPopup(feature, state);
21744
+ }
21727
21745
  RenderPopup(feature, state) {
21728
21746
  const nState = state;
21729
21747
  if (!nState) {
21730
- return Promise.resolve(undefined);
21748
+ return undefined;
21731
21749
  }
21732
21750
  const ds = nState.dataset;
21733
21751
  if (!ds) {
21734
- return Promise.resolve(undefined);
21752
+ return undefined;
21735
21753
  }
21736
21754
  const tab = new TableBuilder();
21737
21755
  tab.add("Source", DataSetFieldValue$1(ds, nState.row, "SOURCE_DESC") || "");
@@ -21742,14 +21760,21 @@ class NAASMapper {
21742
21760
  tab.add("Utilization", DataSetFieldValue$1(ds, nState.row, "UTIL_PRACTICE_DESC") || "");
21743
21761
  tab.add("Statistic", DataSetFieldValue$1(ds, nState.row, "STATISTICCAT_DESC") || "");
21744
21762
  tab.add("Unit", DataSetFieldValue$1(ds, nState.row, "UNIT_DESC") || "");
21745
- tab.add("State", DataSetFieldValue$1(ds, nState.row, "STATE_ABBR") || "");
21746
- tab.add("County", DataSetFieldValue$1(ds, nState.row, "COUNTY_CODE") || "");
21747
- tab.add("Year", DataSetFieldValue$1(ds, nState.row, "YEAR") || "");
21748
- tab.add("Value", nState?.value);
21749
- tab.add("RAW Value", nState?.raw);
21750
- tab.add("MIN Value", nState?.min || "");
21751
- tab.add("MAX Value", nState?.max || "");
21752
- return Promise.resolve(tab.toHtml());
21763
+ // tab.add("State", DataSetFieldValue(ds, nState.row, "STATE_ABBR") || "")
21764
+ // tab.add("County", DataSetFieldValue(ds, nState.row, "COUNTY_CODE") || "")
21765
+ // tab.add("Year", DataSetFieldValue(ds, nState.row, "YEAR") || "")
21766
+ // tab.add("Value", nState?.value)
21767
+ if (nState.raw !== undefined) {
21768
+ tab.add("Value", nState.raw.toLocaleString());
21769
+ }
21770
+ if (nState.min !== undefined) {
21771
+ tab.add("MIN Value", nState.min.toLocaleString());
21772
+ }
21773
+ if (nState.max !== undefined) {
21774
+ tab.add("MAX Value", nState.max.toLocaleString());
21775
+ }
21776
+ tab.add("GEOID", nState.id);
21777
+ return tab.toHtml();
21753
21778
  }
21754
21779
  }
21755
21780
  function FipsFromDataSet$1(ds, rowIndex) {
@@ -22086,10 +22111,6 @@ class NaicsMapper {
22086
22111
  RemoveLayer(this.map, this.CIRCLE_LAYER_ID);
22087
22112
  RemoveLayer(this.map, this.ICON_LAYER_ID);
22088
22113
  RemoveLayer(this.map, this.HEATMAP_LAYER_ID);
22089
- this.map.off('click', this.CIRCLE_LAYER_ID, this.onClick);
22090
- this.map.off('click', this.ICON_LAYER_ID, this.onClick);
22091
- this.map.off('touchend', this.CIRCLE_LAYER_ID, this.onClick);
22092
- this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
22093
22114
  const svc = this.svc();
22094
22115
  if (svc) {
22095
22116
  svc.UpdateLegend(this.id, undefined);
@@ -22167,15 +22188,6 @@ class NaicsMapper {
22167
22188
  // this.addClusterLayers(map);
22168
22189
  }
22169
22190
  console.log('NAICS Mapper created/updated:', this.id, settings);
22170
- // Add popup on click
22171
- this.map.off('click', this.CIRCLE_LAYER_ID, this.onClick);
22172
- this.map.off('click', this.ICON_LAYER_ID, this.onClick);
22173
- this.map.off('touchend', this.CIRCLE_LAYER_ID, this.onClick);
22174
- this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
22175
- map.on('click', this.CIRCLE_LAYER_ID, this.onClick);
22176
- map.on('click', this.ICON_LAYER_ID, this.onClick);
22177
- map.on('touchend', this.CIRCLE_LAYER_ID, this.onClick);
22178
- map.on('touchend', this.ICON_LAYER_ID, this.onClick);
22179
22191
  this.filter(map, settings);
22180
22192
  untracked(() => this.updateLegend(settings));
22181
22193
  }
@@ -22399,37 +22411,16 @@ class NaicsMapper {
22399
22411
  zoom: 12,
22400
22412
  });
22401
22413
  }
22402
- onClick = async (e) => {
22403
- if (!this.map) {
22404
- return;
22405
- }
22406
- const map = this.map;
22407
- let features;
22408
- const settings = this.settings();
22409
- if (settings.type == 'circle') {
22410
- features = this.map.queryRenderedFeatures(e.point, {
22411
- layers: [this.CIRCLE_LAYER_ID],
22412
- });
22413
- }
22414
- else if (settings.type == 'icon') {
22415
- features = this.map.queryRenderedFeatures(e.point, {
22416
- layers: [this.ICON_LAYER_ID],
22417
- });
22418
- }
22419
- if (!features || features.length == 0) {
22420
- return;
22421
- }
22422
- e.preventDefault();
22423
- if (this.current) {
22424
- this.current.remove();
22425
- this.current = null;
22414
+ renderPopup(f) {
22415
+ if (!this.map || !f || !f.layer) {
22416
+ return undefined;
22426
22417
  }
22427
- const html = this.renderPopup(features[0]);
22428
- if (html) {
22429
- this.current = new Popup().setLngLat(e.lngLat).setHTML(html).addTo(this.map);
22418
+ if (f.layer.id !== this.CIRCLE_LAYER_ID && f.layer.id !== this.ICON_LAYER_ID && f.layer.id !== this.HEATMAP_LAYER_ID) {
22419
+ return undefined;
22430
22420
  }
22431
- };
22432
- renderPopup(f) {
22421
+ return this.renderInfo(f);
22422
+ }
22423
+ renderInfo(f) {
22433
22424
  if (!f || !f.properties) {
22434
22425
  return undefined;
22435
22426
  }
@@ -24000,6 +23991,18 @@ class PointDataMapper {
24000
23991
  return features || [];
24001
23992
  }
24002
23993
  }, ...(ngDevMode ? [{ debugName: "data" }] : []));
23994
+ renderPopup(f) {
23995
+ if (!this.map) {
23996
+ return undefined;
23997
+ }
23998
+ if (f.layer.id !== this.HEAT_LAYER_ID && f.layer.id !== this.ICON_LAYER_ID && f.layer.id !== this.POINT_LAYER_ID) {
23999
+ return undefined;
24000
+ }
24001
+ if (this.popupRenderer) {
24002
+ return this.popupRenderer.RenderPopup(f);
24003
+ }
24004
+ return undefined;
24005
+ }
24003
24006
  update(settings) {
24004
24007
  this.settings.set({ ...this.settings(), ...settings });
24005
24008
  }
@@ -24135,10 +24138,10 @@ class PointDataMapper {
24135
24138
  RemoveLayer(this.map, c.iconLayer);
24136
24139
  }
24137
24140
  }
24138
- this.map.off('click', this.POINT_LAYER_ID, this.onClick);
24139
- this.map.off('touchend', this.POINT_LAYER_ID, this.onClick);
24140
- this.map.off('click', this.ICON_LAYER_ID, this.onClick);
24141
- this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
24141
+ // this.map.off('click', this.POINT_LAYER_ID, this.onClick);
24142
+ // this.map.off('touchend', this.POINT_LAYER_ID, this.onClick);
24143
+ // this.map.off('click', this.ICON_LAYER_ID, this.onClick);
24144
+ // this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
24142
24145
  RemoveSource(this.map, `${this.id}-source`);
24143
24146
  }
24144
24147
  loadSource() {
@@ -24158,10 +24161,10 @@ class PointDataMapper {
24158
24161
  type: 'geojson',
24159
24162
  data: sourceURL,
24160
24163
  });
24161
- map.on('click', this.POINT_LAYER_ID, this.onClick);
24162
- map.on('touchend', this.POINT_LAYER_ID, this.onClick);
24163
- map.on('click', this.ICON_LAYER_ID, this.onClick);
24164
- map.on('touchend', this.ICON_LAYER_ID, this.onClick);
24164
+ // map.on('click', this.POINT_LAYER_ID, this.onClick);
24165
+ // map.on('touchend', this.POINT_LAYER_ID, this.onClick);
24166
+ // map.on('click', this.ICON_LAYER_ID, this.onClick);
24167
+ // map.on('touchend', this.ICON_LAYER_ID, this.onClick);
24165
24168
  }
24166
24169
  else if (currentSource._data !== sourceURL) {
24167
24170
  currentSource.setData(sourceURL);
@@ -24352,32 +24355,31 @@ class PointDataMapper {
24352
24355
  }, StandardLayersMapper.POINTS);
24353
24356
  });
24354
24357
  }
24355
- onClick = async (e) => {
24356
- if (!this.map) {
24357
- return;
24358
- }
24359
- let features = [];
24360
- const settings = this.settings();
24361
- if (settings.type == 'circle') {
24362
- features = this.map.queryRenderedFeatures(e.point, { layers: [this.POINT_LAYER_ID] });
24363
- }
24364
- else if (settings.type == 'icon') {
24365
- features = this.map.queryRenderedFeatures(e.point, { layers: [this.ICON_LAYER_ID] });
24366
- }
24367
- if (!features || features.length == 0) {
24368
- return;
24369
- }
24370
- if (this.current) {
24371
- this.current.remove();
24372
- this.current = null;
24373
- }
24374
- if (this.popupRenderer) {
24375
- const html = await this.popupRenderer.RenderPopup(features[0]);
24376
- if (html) {
24377
- this.current = new Popup().setLngLat(e.lngLat).setHTML(html).addTo(this.map);
24378
- }
24379
- }
24380
- };
24358
+ // onClick = async (e: MapLayerMouseEvent | MapLayerTouchEvent) => {
24359
+ // if (!this.map) {
24360
+ // return;
24361
+ // }
24362
+ // let features: GeoJSON.Feature[] = [];
24363
+ // const settings = this.settings();
24364
+ // if (settings.type == 'circle') {
24365
+ // features = this.map.queryRenderedFeatures(e.point, { layers: [this.POINT_LAYER_ID] });
24366
+ // } else if (settings.type == 'icon') {
24367
+ // features = this.map.queryRenderedFeatures(e.point, { layers: [this.ICON_LAYER_ID] });
24368
+ // }
24369
+ // if (!features || features.length == 0) {
24370
+ // return;
24371
+ // }
24372
+ // if (this.current) {
24373
+ // this.current.remove();
24374
+ // this.current = null;
24375
+ // }
24376
+ // if (this.popupRenderer) {
24377
+ // const html = await this.popupRenderer.RenderPopup(features[0]);
24378
+ // if (html) {
24379
+ // this.current = new Popup().setLngLat(e.lngLat).setHTML(html).addTo(this.map);
24380
+ // }
24381
+ // }
24382
+ // };
24381
24383
  getSettings() {
24382
24384
  return { ...this.settings() };
24383
24385
  }
@@ -24482,40 +24484,30 @@ class RailroadsMapper {
24482
24484
  console.warn('RailroadsMapper: style has no `glyphs` URL — skipping labels layer to avoid PBF/glyph parse errors. Switch to a style with glyphs to enable labels.');
24483
24485
  }
24484
24486
  this._update(this.settings());
24485
- if (!added) {
24486
- return;
24487
+ }
24488
+ renderPopup(feature) {
24489
+ if (!this.map) {
24490
+ return undefined;
24487
24491
  }
24488
- map.on('click', this.LINE_LAYER_ID, (e) => {
24489
- // Publish
24490
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
24491
- if (e.features && e.features.length > 0) {
24492
- const feature = e.features[0];
24493
- const coordinates = e.lngLat;
24494
- if (this.popup) {
24495
- this.popup.remove();
24496
- }
24497
- const name = feature.properties['name'];
24498
- const tb = new TableBuilder();
24499
- tb.add('Length', this.fmtDistance(feature.properties['lengthkm']));
24500
- tb.add('Owner', feature.properties['railowner'] ?? '');
24501
- tb.add('Owner Code', feature.properties['railownercode'] ?? '');
24502
- tb.add('Usage', this.usageLabel(feature.properties['railusage'] ?? 0));
24503
- tb.add('Source', feature.properties['source_datadesc'] ?? '');
24504
- tb.add('Originator', feature.properties['source_originator'] ?? '');
24505
- tb.add('Load Date', feature.properties['loaddate'] ?? '');
24506
- const fieldsHtml = tb.toHtml();
24507
- let html = "";
24508
- if (name) {
24509
- html += `<strong>${name}</strong><br/>`;
24510
- }
24511
- html += fieldsHtml;
24512
- this.currentFeatureID = feature?.properties?.['globalid'];
24513
- this.popup = new Popup({ maxWidth: '400px' })
24514
- .setLngLat(coordinates)
24515
- .setHTML(html)
24516
- .addTo(map);
24517
- }
24518
- });
24492
+ if (feature.layer.id !== this.LINE_LAYER_ID && feature.layer.id !== this.LABEL_LAYER_ID) {
24493
+ return undefined;
24494
+ }
24495
+ const name = feature.properties['name'];
24496
+ const tb = new TableBuilder();
24497
+ tb.add('Length', this.fmtDistance(feature.properties['lengthkm']));
24498
+ tb.add('Owner', feature.properties['railowner'] ?? '');
24499
+ tb.add('Owner Code', feature.properties['railownercode'] ?? '');
24500
+ tb.add('Usage', this.usageLabel(feature.properties['railusage'] ?? 0));
24501
+ tb.add('Source', feature.properties['source_datadesc'] ?? '');
24502
+ tb.add('Originator', feature.properties['source_originator'] ?? '');
24503
+ tb.add('Load Date', feature.properties['loaddate'] ?? '');
24504
+ const fieldsHtml = tb.toHtml();
24505
+ let html = "";
24506
+ if (name) {
24507
+ html += `<strong>${name}</strong><br/>`;
24508
+ }
24509
+ html += fieldsHtml;
24510
+ return html;
24519
24511
  }
24520
24512
  fmtDistance(km) {
24521
24513
  if (!km) {
@@ -25063,35 +25055,27 @@ class WatershedMapper {
25063
25055
  }
25064
25056
  }
25065
25057
  });
25066
- map.on('mousemove', this.FILL_LAYER_ID, (e) => {
25067
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
25068
- });
25069
- map.on('click', this.FILL_LAYER_ID, (e) => {
25070
- // Publish
25071
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
25072
- if (e.features && e.features.length > 0) {
25073
- const feature = e.features[0];
25074
- const coordinates = e.lngLat;
25075
- console.log('Feature properties:', feature.properties);
25076
- const name = feature.properties
25077
- ? feature.properties['name']
25078
- : 'Unknown';
25079
- // Ensure that if the popup is already open, we don't create a new one
25080
- if (this.popup) {
25081
- this.popup.remove();
25082
- }
25083
- const fields = feature.properties
25084
- ? Object.entries(feature.properties)
25085
- .map(([key, value]) => `<strong>${key}:</strong> ${value}`)
25086
- .join('<br/>')
25087
- : '';
25088
- this.currentFeatureID = feature?.properties?.['globalid'];
25089
- this.popup = new Popup({ maxWidth: '400px' })
25090
- .setLngLat(coordinates)
25091
- .setHTML(`<strong>Watershed:</strong> ${name}<hr /><br/>${fields}`)
25092
- .addTo(map);
25093
- }
25094
- });
25058
+ }
25059
+ renderPopup(feature) {
25060
+ if (!this.map) {
25061
+ return undefined;
25062
+ }
25063
+ if (feature.layer.id !== this.FILL_LAYER_ID && feature.layer.id !== this.LINE_LAYER_ID && feature.layer.id !== this.LABEL_LAYER_ID) {
25064
+ return undefined;
25065
+ }
25066
+ const name = feature.properties
25067
+ ? feature.properties['name']
25068
+ : 'Unknown';
25069
+ // Ensure that if the popup is already open, we don't create a new one
25070
+ if (this.popup) {
25071
+ this.popup.remove();
25072
+ }
25073
+ const fields = feature.properties
25074
+ ? Object.entries(feature.properties)
25075
+ .map(([key, value]) => `<strong>${key}:</strong> ${value}`)
25076
+ .join('<br/>')
25077
+ : '';
25078
+ return `<strong>Watershed:</strong> ${name}<hr /><br/>${fields}`;
25095
25079
  }
25096
25080
  async onReady(map, svc) {
25097
25081
  this.map = map;
@@ -29345,7 +29329,7 @@ class MarketMakerPopupRenderer {
29345
29329
  return html;
29346
29330
  }
29347
29331
  RenderPopup(feature) {
29348
- return Promise.resolve(this.RenderPopupSync(feature));
29332
+ return this.RenderPopupSync(feature);
29349
29333
  }
29350
29334
  getArrayProperty(value) {
29351
29335
  const arr = this.parseArrayProperty(value) || [];
@@ -29724,7 +29708,7 @@ class HubNaicsPanel {
29724
29708
  {{ mapper.data().length }} records matching current filters.
29725
29709
  <cdk-virtual-scroll-viewport [itemSize]="10">
29726
29710
  <div *cdkVirtualFor="let feature of mapper.data()" (click)="mapper.flyToFeature(feature)"
29727
- class="data-tile" [innerHTML]="mapper.renderPopup(feature)">
29711
+ class="data-tile" [innerHTML]="mapper.renderInfo(feature)">
29728
29712
  </div>
29729
29713
 
29730
29714
  </cdk-virtual-scroll-viewport>
@@ -29924,7 +29908,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
29924
29908
  {{ mapper.data().length }} records matching current filters.
29925
29909
  <cdk-virtual-scroll-viewport [itemSize]="10">
29926
29910
  <div *cdkVirtualFor="let feature of mapper.data()" (click)="mapper.flyToFeature(feature)"
29927
- class="data-tile" [innerHTML]="mapper.renderPopup(feature)">
29911
+ class="data-tile" [innerHTML]="mapper.renderInfo(feature)">
29928
29912
  </div>
29929
29913
 
29930
29914
  </cdk-virtual-scroll-viewport>
@@ -32276,13 +32260,13 @@ class SettingsPanel {
32276
32260
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SettingsPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
32277
32261
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SettingsPanel, isStandalone: true, selector: "app-settings-panel", ngImport: i0, template: `
32278
32262
  <ng-content></ng-content>
32279
- `, isInline: true, styles: [":host{position:fixed;padding:16px;border:1px solid #ccc;border-radius:8px;background-color:#efe9e1;right:16px;top:16px;bottom:16px;width:300px;box-shadow:0 2px 8px #0000001a;overflow-y:auto}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
32263
+ `, isInline: true, styles: [":host{position:fixed;padding:16px;border:1px solid #ccc;border-radius:8px;background-color:#efe9e1;right:16px;top:16px;bottom:16px;width:320px;box-shadow:0 2px 8px #0000001a;overflow-y:auto}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
32280
32264
  }
32281
32265
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SettingsPanel, decorators: [{
32282
32266
  type: Component,
32283
32267
  args: [{ selector: 'app-settings-panel', changeDetection: ChangeDetectionStrategy.OnPush, imports: [], template: `
32284
32268
  <ng-content></ng-content>
32285
- `, styles: [":host{position:fixed;padding:16px;border:1px solid #ccc;border-radius:8px;background-color:#efe9e1;right:16px;top:16px;bottom:16px;width:300px;box-shadow:0 2px 8px #0000001a;overflow-y:auto}\n"] }]
32269
+ `, styles: [":host{position:fixed;padding:16px;border:1px solid #ccc;border-radius:8px;background-color:#efe9e1;right:16px;top:16px;bottom:16px;width:320px;box-shadow:0 2px 8px #0000001a;overflow-y:auto}\n"] }]
32286
32270
  }] });
32287
32271
 
32288
32272
  /*