@foodmarketmaker/mapag 0.0.22 → 0.0.23

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.
@@ -228,6 +228,54 @@ async function pmtilesPixelInfo(url, map, e) {
228
228
  // const a = pixel[3];
229
229
  return pixel;
230
230
  }
231
+ function propertiesToTableHtml(properties) {
232
+ let html = '<table style="border-collapse: collapse; width: 100%; border: none; font-size: 9px;">';
233
+ for (const key in properties) {
234
+ if (properties.hasOwnProperty(key)) {
235
+ html += `<tr>
236
+ <td style="padding: 2px; font-weight: bold;">${key}</td>
237
+ <td style="padding: 2px;">${properties[key]}</td>
238
+ </tr>`;
239
+ }
240
+ }
241
+ html += '</table>';
242
+ return html;
243
+ }
244
+ class TableBuilder {
245
+ rows = [];
246
+ headerStyle = `style="padding: 2px; padding-top:6ps; font-size: 9px; font-weight: bold;"`;
247
+ rowStyle1 = `style="padding: 2px; font-size: 9px; font-weight: bold;"`;
248
+ rowStyle2 = `style="padding: 2px; font-size: 9px;`;
249
+ addHeader(...cells) {
250
+ this.rows.push(new TableRow(cells, true));
251
+ return this;
252
+ }
253
+ add(...cells) {
254
+ this.rows.push(new TableRow(cells));
255
+ return this;
256
+ }
257
+ toHtml() {
258
+ const rowHtml = this.rows.map(row => row.toHtml()).join('');
259
+ return `<table style="border-collapse: collapse; width: 100%; font-size: 9px;">${rowHtml}</table>`;
260
+ }
261
+ }
262
+ class TableRow {
263
+ isHeader;
264
+ cells;
265
+ headerStyle = `padding: 2px; padding-top:6px; font-size: 9px; font-weight: bold; text-align: left;`;
266
+ rowStyle1 = `padding: 2px; font-size: 9px; font-weight: bold;`;
267
+ rowStyle2 = `padding: 2px; font-size: 9px;`;
268
+ constructor(cells, isHeader = false) {
269
+ this.cells = cells;
270
+ this.isHeader = isHeader;
271
+ }
272
+ toHtml() {
273
+ if (this.isHeader) {
274
+ return `<tr>${this.cells.map(cell => `<th style="${this.headerStyle}">${cell}</th>`).join('\n')}</tr>`;
275
+ }
276
+ return `<tr>${this.cells.map((cell, index) => `<td style="${index == 0 ? this.rowStyle1 : this.rowStyle2}">${cell}</td>`).join('')}</tr>`;
277
+ }
278
+ }
231
279
 
232
280
  const DEFAULT_GLYPHS = "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/resources/fonts/{fontstack}/{range}.pbf";
233
281
  // export const DEFAULT_GLYPHS = "'https://geoserveis.icgc.cat/contextmaps/glyphs/{fontstack}/{range}.pbf';"
@@ -14625,168 +14673,6 @@ class CensusTractMapper {
14625
14673
  };
14626
14674
  }
14627
14675
 
14628
- class CropSequenceMapper {
14629
- static PMTILES = 'pmtiles://https://foodmarketmaker-upload-data.s3.us-west-2.amazonaws.com/tiles/NationalCSB_2017_2024_rev23.pmtiles';
14630
- FILL_LAYER_ID = 'cropsequence-layer';
14631
- LINE_LAYER_ID = 'cropsequence-layer-line';
14632
- LABEL_LAYER_ID = 'cropsequence-layer-label';
14633
- SOURCE_ID = 'cropsequence-source';
14634
- SOURCE_LAYER = 'NationalCSB_2017_2024_rev23';
14635
- settings = signal(new CropSequenceSettings(), ...(ngDevMode ? [{ debugName: "settings" }] : []));
14636
- current = null;
14637
- currentFeatureID = undefined;
14638
- over = signal(null, ...(ngDevMode ? [{ debugName: "over" }] : []));
14639
- constructor(settings) {
14640
- if (settings) {
14641
- this.settings.set({
14642
- ...this.settings(),
14643
- ...settings
14644
- });
14645
- }
14646
- const _ = effect(() => {
14647
- const settings = this.settings();
14648
- this._update(settings);
14649
- }, ...(ngDevMode ? [{ debugName: "_" }] : []));
14650
- }
14651
- update(settings) {
14652
- this.settings.set({ ...this.settings(), ...settings });
14653
- }
14654
- _update(settings) {
14655
- if (!this.map) {
14656
- return;
14657
- }
14658
- const map = this.map;
14659
- if (settings.visible) {
14660
- map.setLayoutProperty(this.FILL_LAYER_ID, 'visibility', 'visible');
14661
- map.setLayoutProperty(this.LINE_LAYER_ID, 'visibility', 'visible');
14662
- }
14663
- else {
14664
- map.setLayoutProperty(this.FILL_LAYER_ID, 'visibility', 'none');
14665
- map.setLayoutProperty(this.LINE_LAYER_ID, 'visibility', 'none');
14666
- }
14667
- map.setPaintProperty(this.FILL_LAYER_ID, 'fill-color', settings.fillColor);
14668
- map.setPaintProperty(this.FILL_LAYER_ID, 'fill-opacity', settings.fillOpacity);
14669
- map.setPaintProperty(this.LINE_LAYER_ID, 'line-color', settings.borderColor);
14670
- map.setPaintProperty(this.LINE_LAYER_ID, 'line-width', settings.borderWidth);
14671
- map.setPaintProperty(this.LINE_LAYER_ID, 'line-opacity', settings.borderOpacity);
14672
- const labelsVisible = settings.visible && settings.labelsVisible;
14673
- map.setLayoutProperty(this.LABEL_LAYER_ID, 'visibility', labelsVisible ? 'visible' : 'none');
14674
- map.setPaintProperty(this.LABEL_LAYER_ID, 'text-color', settings.labelsColor);
14675
- map.setPaintProperty(this.LABEL_LAYER_ID, 'text-halo-color', settings.labelsHaloColor);
14676
- map.setPaintProperty(this.LABEL_LAYER_ID, 'text-halo-width', settings.labelsHaloWidth);
14677
- map.setPaintProperty(this.LABEL_LAYER_ID, 'text-opacity', settings.labelsOpacity);
14678
- map.setLayoutProperty(this.LABEL_LAYER_ID, 'text-size', settings.labelsSize);
14679
- map.setLayoutProperty(this.LABEL_LAYER_ID, 'text-allow-overlap', settings.labelOverlap);
14680
- }
14681
- create() {
14682
- if (!this.map) {
14683
- return;
14684
- }
14685
- const map = this.map;
14686
- let PMTILES_URL = CropSequenceMapper.PMTILES;
14687
- AddSource(map, this.SOURCE_ID, {
14688
- type: 'vector',
14689
- url: PMTILES_URL,
14690
- });
14691
- const addedFill = AddLayer(map, {
14692
- id: this.FILL_LAYER_ID,
14693
- source: this.SOURCE_ID,
14694
- "source-layer": this.SOURCE_LAYER,
14695
- type: 'fill',
14696
- }, StandardLayersMapper.POLYGONS_BACKGROUND);
14697
- map.showTileBoundaries = true;
14698
- AddLayer(map, {
14699
- id: this.LINE_LAYER_ID,
14700
- source: this.SOURCE_ID,
14701
- "source-layer": this.SOURCE_LAYER,
14702
- type: 'line',
14703
- }, StandardLayersMapper.POLYGONS_BACKGROUND);
14704
- AddLayer(map, {
14705
- id: this.LABEL_LAYER_ID,
14706
- source: this.SOURCE_ID,
14707
- "source-layer": this.SOURCE_LAYER,
14708
- type: 'symbol',
14709
- layout: {
14710
- 'text-field': ['get', 'name'],
14711
- 'text-font': ['Open Sans Regular'],
14712
- 'text-size': this.settings().labelsSize,
14713
- 'text-allow-overlap': this.settings().labelOverlap,
14714
- },
14715
- paint: {
14716
- 'text-color': this.settings().labelsColor,
14717
- 'text-halo-color': this.settings().labelsHaloColor,
14718
- 'text-halo-width': this.settings().labelsHaloWidth,
14719
- },
14720
- }, StandardLayersMapper.POLYGONS_BACKGROUND);
14721
- this._update(this.settings());
14722
- if (!addedFill) {
14723
- return;
14724
- }
14725
- map.on('mousemove', this.FILL_LAYER_ID, (e) => {
14726
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
14727
- });
14728
- map.on('click', this.FILL_LAYER_ID, (e) => {
14729
- // Publish
14730
- this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
14731
- if (e.features && e.features.length > 0) {
14732
- const feature = e.features[0];
14733
- const coordinates = e.lngLat;
14734
- console.log('Feature properties:', feature.properties);
14735
- const name = feature.properties
14736
- ? feature.properties['name']
14737
- : 'Unknown';
14738
- // Ensure that if the popup is already open, we don't create a new one
14739
- if (this.popup) {
14740
- this.popup.remove();
14741
- }
14742
- const fields = feature.properties
14743
- ? Object.entries(feature.properties)
14744
- .map(([key, value]) => `<strong>${key}:</strong> ${value}`)
14745
- .join('<br/>')
14746
- : '';
14747
- this.currentFeatureID = feature?.properties?.['globalid'];
14748
- this.popup = new Popup({ maxWidth: '400px' })
14749
- .setLngLat(coordinates)
14750
- .setHTML(`<strong>Watershed:</strong> ${name}<hr /><br/>${fields}`)
14751
- .addTo(map);
14752
- }
14753
- });
14754
- }
14755
- async onReady(map, svc) {
14756
- this.map = map;
14757
- this.create();
14758
- }
14759
- reset() { }
14760
- clear() {
14761
- if (this.map) {
14762
- this.map.removeLayer(this.FILL_LAYER_ID);
14763
- this.map.removeLayer(this.LINE_LAYER_ID);
14764
- this.map.removeLayer(this.LABEL_LAYER_ID);
14765
- this.map.removeSource(this.SOURCE_ID);
14766
- }
14767
- }
14768
- legends;
14769
- count = 0;
14770
- total = 0;
14771
- map;
14772
- popup = null;
14773
- }
14774
- class CropSequenceSettings {
14775
- visible = true;
14776
- fillColor = '#0000ff';
14777
- fillOpacity = 0.1;
14778
- borderColor = '#01018b';
14779
- borderWidth = 1;
14780
- borderOpacity = 1.0;
14781
- labelsVisible = true;
14782
- labelsSize = 10;
14783
- labelsColor = '#000000';
14784
- labelsHaloColor = '#ffffff';
14785
- labelsHaloWidth = 1;
14786
- labelsOpacity = 1.0;
14787
- labelOverlap = false;
14788
- }
14789
-
14790
14676
  class CroplandDataLayerMapper {
14791
14677
  static PMTILES = 'pmtiles://https://foodmarketmaker-upload-data.s3.us-west-2.amazonaws.com/tiles/cdl_2024_30m.pmtiles';
14792
14678
  LAYER_ID = 'cropland-data-layer';
@@ -15320,6 +15206,163 @@ Dbl Crop Barley/Soybeans 254 433 47.5% 52.5% 0.47
15320
15206
 
15321
15207
  */
15322
15208
 
15209
+ class CropSequenceMapper {
15210
+ static PMTILES = 'pmtiles://https://foodmarketmaker-upload-data.s3.us-west-2.amazonaws.com/tiles/NationalCSB_2017_2024_rev23.pmtiles';
15211
+ FILL_LAYER_ID = 'cropsequence-layer';
15212
+ LINE_LAYER_ID = 'cropsequence-layer-line';
15213
+ SOURCE_ID = 'cropsequence-source';
15214
+ SOURCE_LAYER = 'NationalCSB_2017_2024_rev23';
15215
+ settings = signal(new CropSequenceSettings(), ...(ngDevMode ? [{ debugName: "settings" }] : []));
15216
+ current = null;
15217
+ currentFeatureID = undefined;
15218
+ over = signal(null, ...(ngDevMode ? [{ debugName: "over" }] : []));
15219
+ constructor(settings) {
15220
+ if (settings) {
15221
+ this.settings.set({
15222
+ ...this.settings(),
15223
+ ...settings
15224
+ });
15225
+ }
15226
+ const _ = effect(() => {
15227
+ const settings = this.settings();
15228
+ this._update(settings);
15229
+ }, ...(ngDevMode ? [{ debugName: "_" }] : []));
15230
+ }
15231
+ update(settings) {
15232
+ this.settings.set({ ...this.settings(), ...settings });
15233
+ }
15234
+ _update(settings) {
15235
+ if (!this.map) {
15236
+ return;
15237
+ }
15238
+ const map = this.map;
15239
+ if (settings.visible) {
15240
+ map.setLayoutProperty(this.FILL_LAYER_ID, 'visibility', 'visible');
15241
+ map.setLayoutProperty(this.LINE_LAYER_ID, 'visibility', 'visible');
15242
+ }
15243
+ else {
15244
+ map.setLayoutProperty(this.FILL_LAYER_ID, 'visibility', 'none');
15245
+ map.setLayoutProperty(this.LINE_LAYER_ID, 'visibility', 'none');
15246
+ }
15247
+ map.setPaintProperty(this.FILL_LAYER_ID, 'fill-color', settings.fillColor);
15248
+ map.setPaintProperty(this.FILL_LAYER_ID, 'fill-opacity', settings.fillOpacity);
15249
+ map.setPaintProperty(this.LINE_LAYER_ID, 'line-color', settings.borderColor);
15250
+ map.setPaintProperty(this.LINE_LAYER_ID, 'line-width', settings.borderWidth);
15251
+ map.setPaintProperty(this.LINE_LAYER_ID, 'line-opacity', settings.borderOpacity);
15252
+ }
15253
+ create() {
15254
+ if (!this.map) {
15255
+ return;
15256
+ }
15257
+ const map = this.map;
15258
+ let PMTILES_URL = CropSequenceMapper.PMTILES;
15259
+ AddSource(map, this.SOURCE_ID, {
15260
+ type: 'vector',
15261
+ url: PMTILES_URL,
15262
+ });
15263
+ const addedFill = AddLayer(map, {
15264
+ id: this.FILL_LAYER_ID,
15265
+ source: this.SOURCE_ID,
15266
+ "source-layer": this.SOURCE_LAYER,
15267
+ type: 'fill',
15268
+ }, StandardLayersMapper.POLYGONS_BACKGROUND);
15269
+ AddLayer(map, {
15270
+ id: this.LINE_LAYER_ID,
15271
+ source: this.SOURCE_ID,
15272
+ "source-layer": this.SOURCE_LAYER,
15273
+ type: 'line',
15274
+ }, StandardLayersMapper.POLYGONS_BACKGROUND);
15275
+ this._update(this.settings());
15276
+ if (!addedFill) {
15277
+ return;
15278
+ }
15279
+ map.on('mousemove', this.FILL_LAYER_ID, (e) => {
15280
+ this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
15281
+ });
15282
+ map.on('click', this.FILL_LAYER_ID, (e) => {
15283
+ // Publish
15284
+ this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
15285
+ if (e.features && e.features.length > 0) {
15286
+ const feature = e.features[0];
15287
+ const coordinates = e.lngLat;
15288
+ if (this.popup) {
15289
+ this.popup.remove();
15290
+ }
15291
+ const tb = new TableBuilder();
15292
+ const crop2017 = this.lookupClass(feature.properties ? feature.properties['CDL2017'] : null);
15293
+ const crop2018 = this.lookupClass(feature.properties ? feature.properties['CDL2018'] : null);
15294
+ const crop2019 = this.lookupClass(feature.properties ? feature.properties['CDL2019'] : null);
15295
+ const crop2020 = this.lookupClass(feature.properties ? feature.properties['CDL2020'] : null);
15296
+ const crop2021 = this.lookupClass(feature.properties ? feature.properties['CDL2021'] : null);
15297
+ const crop2022 = this.lookupClass(feature.properties ? feature.properties['CDL2022'] : null);
15298
+ const crop2023 = this.lookupClass(feature.properties ? feature.properties['CDL2023'] : null);
15299
+ const crop2024 = this.lookupClass(feature.properties ? feature.properties['CDL2024'] : null);
15300
+ tb.addHeader('Year', 'Crop Type');
15301
+ tb.add('2024', crop2024 ?? 'Unknown');
15302
+ tb.add('2023', crop2023 ?? 'Unknown');
15303
+ tb.add('2022', crop2022 ?? 'Unknown');
15304
+ tb.add('2021', crop2021 ?? 'Unknown');
15305
+ tb.add('2020', crop2020 ?? 'Unknown');
15306
+ tb.add('2019', crop2019 ?? 'Unknown');
15307
+ tb.add('2018', crop2018 ?? 'Unknown');
15308
+ tb.add('2017', crop2017 ?? 'Unknown');
15309
+ tb.addHeader('Location', "");
15310
+ tb.add('State FIPS', feature.properties ? feature.properties['STATEFIPS'] : 'Unknown');
15311
+ tb.add('County', feature.properties ? feature.properties['CNTY'] : 'Unknown');
15312
+ tb.add('County FIPS', feature.properties ? feature.properties['CNTYFIPS'] : 'Unknown');
15313
+ tb.add('ASD', feature.properties ? feature.properties['ASD'] : 'Unknown');
15314
+ tb.add('Area (M²)', feature.properties ? feature.properties['Shape_Area'] : 'Unknown');
15315
+ const fieldsHtml = tb.toHtml();
15316
+ this.currentFeatureID = feature?.properties?.['globalid'];
15317
+ this.popup = new Popup({ maxWidth: '400px' })
15318
+ .setLngLat(coordinates)
15319
+ .setHTML(`<strong>Crop Sequence</strong><br/>${fieldsHtml}`)
15320
+ .addTo(map);
15321
+ }
15322
+ });
15323
+ }
15324
+ lookupClass(code) {
15325
+ const found = CroplandLegend.find((item) => {
15326
+ return item.code == code;
15327
+ });
15328
+ if (found) {
15329
+ return found.class;
15330
+ }
15331
+ return undefined;
15332
+ }
15333
+ lookup(code) {
15334
+ const found = CroplandLegend.find((item) => {
15335
+ return item.code == code;
15336
+ });
15337
+ return found;
15338
+ }
15339
+ async onReady(map, svc) {
15340
+ this.map = map;
15341
+ this.create();
15342
+ }
15343
+ reset() { }
15344
+ clear() {
15345
+ if (this.map) {
15346
+ this.map.removeLayer(this.FILL_LAYER_ID);
15347
+ this.map.removeLayer(this.LINE_LAYER_ID);
15348
+ this.map.removeSource(this.SOURCE_ID);
15349
+ }
15350
+ }
15351
+ legends;
15352
+ count = 0;
15353
+ total = 0;
15354
+ map;
15355
+ popup = null;
15356
+ }
15357
+ class CropSequenceSettings {
15358
+ visible = true;
15359
+ fillColor = '#1aac39';
15360
+ fillOpacity = 0.2;
15361
+ borderColor = '#006e16';
15362
+ borderWidth = 1;
15363
+ borderOpacity = 0.5;
15364
+ }
15365
+
15323
15366
  class EsriMapper {
15324
15367
  jsonUrl = 'https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/resources/styles/root.json';
15325
15368
  SOURCE_ID = 'esri';
@@ -16735,5 +16778,5 @@ class HttpBoundaryLoader {
16735
16778
  * Generated bundle index. Do not edit.
16736
16779
  */
16737
16780
 
16738
- export { AddLayer, AddSource, AreaMapperMapper, BackgroundMaskMapper, BackgroundMaskSettings, BaseMapLight, BasemapSelect, BasemapSelectMenu, CensusTractMapper, Codes, CropSequenceMapper, CropSequenceSettings, CroplandDataLayerMapper, CroplandDataLayerSettings, CroplandLegend, DEFAULT_GLYPHS, DrawingMapper, EsriMapper, EsriSettings, HardinessMapper, HardinessSettings, HttpBoundaryLoader, MapAreaSelectComponent, MapComponent, MapSelectionService, MapService, MapStyles, MapboxMapperGroup, NAASMapper, NAASSettings, NaicsMapper, NaicsMapperSettings, NoOpMapper, RemoveLayer, RemoveSource, SaveMap, SelectMode, SimpleMapper, StandardLayersMapper, Styles, VectorTileServerMapper, WatershedMapper, WatershedSettings, discoverLayers, isGeoloader, isMultiPolygon, isNumber2DArray, isNumber3DArray, isPolygon, mapboxLoadImages, mapboxloadImage, pmtilesPixelInfo, sampleTilesForLayers, simpleClone, toMultiPolygon, trySync };
16781
+ export { AddLayer, AddSource, AreaMapperMapper, BackgroundMaskMapper, BackgroundMaskSettings, BaseMapLight, BasemapSelect, BasemapSelectMenu, CensusTractMapper, Codes, CropSequenceMapper, CropSequenceSettings, CroplandDataLayerMapper, CroplandDataLayerSettings, CroplandLegend, DEFAULT_GLYPHS, DrawingMapper, EsriMapper, EsriSettings, HardinessMapper, HardinessSettings, HttpBoundaryLoader, MapAreaSelectComponent, MapComponent, MapSelectionService, MapService, MapStyles, MapboxMapperGroup, NAASMapper, NAASSettings, NaicsMapper, NaicsMapperSettings, NoOpMapper, RemoveLayer, RemoveSource, SaveMap, SelectMode, SimpleMapper, StandardLayersMapper, Styles, TableBuilder, TableRow, VectorTileServerMapper, WatershedMapper, WatershedSettings, discoverLayers, isGeoloader, isMultiPolygon, isNumber2DArray, isNumber3DArray, isPolygon, mapboxLoadImages, mapboxloadImage, pmtilesPixelInfo, propertiesToTableHtml, sampleTilesForLayers, simpleClone, toMultiPolygon, trySync };
16739
16782
  //# sourceMappingURL=foodmarketmaker-mapag.mjs.map