@foodmarketmaker/mapag 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, effect, input, Input, Component, ChangeDetectionStrategy, inject, NgZone, Injectable, output, viewChild } from '@angular/core';
2
+ import { signal, effect, input, Input, Component, viewChild, ChangeDetectionStrategy, inject, NgZone, Injectable, output } from '@angular/core';
3
3
  import { PMTiles, Protocol } from 'pmtiles';
4
4
  import * as i1 from '@angular/common';
5
5
  import { CommonModule } from '@angular/common';
@@ -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';"
@@ -602,89 +650,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
602
650
 
603
651
  class BasemapSelectMenu {
604
652
  map = input.required(...(ngDevMode ? [{ debugName: "map" }] : []));
605
- isPopoverVisible = false;
653
+ styleDialog = viewChild.required('styleDialog');
606
654
  mapStylesArray = Object.values(MapStyles);
607
- popoverTimeout;
608
- constructor() {
609
- }
610
655
  get currentStyle() {
611
656
  return this.map().styles.style();
612
657
  }
613
658
  getBackgroundImage() {
614
659
  const currentStyle = this.map().styles.style();
615
- // Try different path approaches for debugging
616
660
  const originalPath = currentStyle.image;
617
- // Return the original path first to test
618
661
  return `url(${originalPath})`;
619
662
  }
620
- showPopover() {
621
- if (this.popoverTimeout) {
622
- clearTimeout(this.popoverTimeout);
623
- }
624
- this.isPopoverVisible = true;
625
- }
626
- hidePopover() {
627
- this.popoverTimeout = window.setTimeout(() => {
628
- this.isPopoverVisible = false;
629
- }, 200); // Small delay to allow moving to popover
663
+ openDialog(event) {
664
+ event.stopPropagation();
665
+ const dialog = this.styleDialog().nativeElement;
666
+ dialog.showModal();
630
667
  }
631
- keepPopoverOpen() {
632
- if (this.popoverTimeout) {
633
- clearTimeout(this.popoverTimeout);
634
- this.popoverTimeout = undefined;
635
- }
668
+ closeDialog() {
669
+ const dialog = this.styleDialog().nativeElement;
670
+ dialog.close();
636
671
  }
637
672
  selectStyle(style) {
638
673
  const s = this.map().styles;
639
674
  if (s) {
640
675
  s.style.set(style);
641
676
  }
642
- this.isPopoverVisible = false;
643
- }
644
- onClick() {
645
- // Keep the original cycling behavior as fallback
646
- const s = this.map().styles;
647
- const current = this.map().styles.style();
648
- const next = this.nextStyle(current);
649
- s.style.set(next);
650
- }
651
- nextStyle(current) {
652
- const s = this.map().styles;
653
- if (!current) {
654
- // If no current style, return the first one
655
- const firstKey = Object.keys(MapStyles)[0];
656
- return MapStyles[firstKey];
657
- }
658
- // Get all the keys from MapStyles
659
- const styleKeys = Object.keys(MapStyles);
660
- // Find the current style's index
661
- const currentIndex = styleKeys.findIndex(key => MapStyles[key].code === current.code);
662
- // If current style not found, return the first one
663
- if (currentIndex === -1) {
664
- return MapStyles[styleKeys[0]];
665
- }
666
- // Get the next index, wrapping around to 0 if we're at the end
667
- const nextIndex = (currentIndex + 1) % styleKeys.length;
668
- // Return the next style
669
- return MapStyles[styleKeys[nextIndex]];
677
+ this.closeDialog();
670
678
  }
671
679
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BasemapSelectMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
672
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.10", type: BasemapSelectMenu, isStandalone: true, selector: "mapag-basemap-select-menu", inputs: { map: { classPropertyName: "map", publicName: "map", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
680
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.10", type: BasemapSelectMenu, isStandalone: true, selector: "mapag-basemap-select-menu", inputs: { map: { classPropertyName: "map", publicName: "map", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "styleDialog", first: true, predicate: ["styleDialog"], descendants: true, isSignal: true }], ngImport: i0, template: `
673
681
  <div class="basemap-container"
674
- (mouseenter)="showPopover()"
675
- (mouseleave)="hidePopover()"
676
- (click)="onClick()"
677
682
  [style.background-image]="getBackgroundImage()">
678
683
  <div class="basemap-title" [style.color]="currentStyle?.nameColor || '#ffffff'">
679
684
  {{ currentStyle?.name || 'No Style Selected' }}
680
685
  </div>
681
- <!-- <div class="basemap-overlay"></div> -->
686
+ <button class="dialog-button"
687
+ (click)="openDialog($event)"
688
+ title="Choose basemap style">
689
+ ...
690
+ </button>
682
691
  </div>
683
692
 
684
- <div class="style-popover"
685
- [class.show]="isPopoverVisible"
686
- (mouseenter)="keepPopoverOpen()"
687
- (mouseleave)="hidePopover()">
693
+ <dialog #styleDialog class="style-dialog">
694
+ <div class="dialog-header">
695
+ <h3>Select Basemap Style</h3>
696
+ <button class="close-button" (click)="closeDialog()">✕</button>
697
+ </div>
688
698
  <div class="style-grid">
689
699
  <div *ngFor="let style of mapStylesArray"
690
700
  class="style-item"
@@ -692,27 +702,29 @@ class BasemapSelectMenu {
692
702
  <mapag-basemap-select [styleData]="style" [styles]="map().styles"></mapag-basemap-select>
693
703
  </div>
694
704
  </div>
695
- </div>
696
- `, isInline: true, styles: [":host{display:block;width:200px;height:80px;position:relative}.basemap-container{position:relative;width:100%;height:100%;border-radius:12px;background-size:cover;background-position:center;background-repeat:no-repeat;background-color:#f5f5f5;overflow:hidden;cursor:pointer;transition:transform .2s ease,box-shadow .2s ease;box-shadow:0 2px 8px #00000026;display:flex;align-items:center;justify-content:center}.basemap-container:hover{box-shadow:0 4px 16px #0003}.basemap-overlay{position:absolute;inset:0;background:linear-gradient(135deg,#0000001a,#0000004d);border-radius:12px;pointer-events:none}.basemap-title{position:relative;z-index:2;color:#fff;font-size:19px;font-weight:600;text-align:center;padding:8px 16px;background:#0000;border-radius:8px;-webkit-user-select:none;user-select:none;text-shadow:0 2px 4px rgba(0,0,0,.8);max-width:90%;word-wrap:break-word;line-height:1.2}.basemap-container:not([style*=\"background-image: url\"]){background:linear-gradient(135deg,#667eea,#764ba2)}.basemap-container:not([style*=\"background-image: url\"]) .basemap-overlay{background:#0000001a}.style-popover{padding:16px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #00000026;border:1px solid rgba(0,0,0,.1);opacity:0;visibility:hidden;transform:translateY(-10px);transition:opacity .2s ease,transform .2s ease,visibility .2s ease;position:absolute;top:calc(100% + 8px);left:0;z-index:1000;max-width:90vw;max-height:80vh;overflow-y:auto;min-width:100%}.style-popover.show{opacity:1;visibility:visible;transform:translateY(0)}.style-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;min-width:380px;max-width:600px}.style-item{cursor:pointer;transition:transform .2s ease}.style-item:hover{transform:scale(1.05)}@media (max-width: 768px){.style-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr));min-width:300px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: BasemapSelect, selector: "mapag-basemap-select", inputs: ["styleData", "styles"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
705
+ </dialog>
706
+ `, isInline: true, styles: [":host{display:block;width:200px;height:60px;position:relative}.basemap-container{position:relative;width:100%;height:100%;border-radius:12px;background-size:cover;background-position:center;background-repeat:no-repeat;background-color:#f5f5f5;overflow:hidden;box-shadow:0 2px 8px #00000026;display:flex;align-items:center;justify-content:center}.basemap-title{position:relative;z-index:1;color:#fff;font-size:19px;font-weight:600;text-align:center;padding:8px 16px;background:#0000;border-radius:8px;-webkit-user-select:none;user-select:none;text-shadow:0 2px 4px rgba(0,0,0,.8);max-width:90%;word-wrap:break-word;line-height:1.2}.dialog-button{position:absolute;top:50%;transform:translateY(-50%);right:8px;background:#ffffffe6;border:none;border-radius:6px;padding:4px 10px;font-size:18px;font-weight:700;cursor:pointer;z-index:2;transition:background-color .2s ease,transform .2s ease;box-shadow:0 2px 4px #0003;letter-spacing:1px}.dialog-button:hover{background:#fff;transform:translateY(-50%) scale(1.1)}.dialog-button:active{transform:translateY(-50%) scale(.95)}.basemap-container:not([style*=\"background-image: url\"]){background:linear-gradient(135deg,#667eea,#764ba2)}.style-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;border:none;border-radius:12px;padding:0;max-width:90vw;max-height:80vh;box-shadow:0 8px 32px #00000040;background:#fff}.style-dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.dialog-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid rgba(0,0,0,.1)}.dialog-header h3{margin:0;font-size:18px;font-weight:600;color:#333}.close-button{background:transparent;border:none;font-size:24px;cursor:pointer;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:6px;color:#666;transition:background-color .2s ease,color .2s ease}.close-button:hover{background-color:#0000000d;color:#333}.style-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;padding:20px;min-width:380px;max-width:600px;overflow-y:auto}.style-item{cursor:pointer;transition:transform .2s ease}.style-item:hover{transform:scale(1.05)}@media (max-width: 768px){.style-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr));min-width:300px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: BasemapSelect, selector: "mapag-basemap-select", inputs: ["styleData", "styles"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
697
707
  }
698
708
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: BasemapSelectMenu, decorators: [{
699
709
  type: Component,
700
710
  args: [{ selector: 'mapag-basemap-select-menu', imports: [CommonModule, BasemapSelect], changeDetection: ChangeDetectionStrategy.OnPush, template: `
701
711
  <div class="basemap-container"
702
- (mouseenter)="showPopover()"
703
- (mouseleave)="hidePopover()"
704
- (click)="onClick()"
705
712
  [style.background-image]="getBackgroundImage()">
706
713
  <div class="basemap-title" [style.color]="currentStyle?.nameColor || '#ffffff'">
707
714
  {{ currentStyle?.name || 'No Style Selected' }}
708
715
  </div>
709
- <!-- <div class="basemap-overlay"></div> -->
716
+ <button class="dialog-button"
717
+ (click)="openDialog($event)"
718
+ title="Choose basemap style">
719
+ ...
720
+ </button>
710
721
  </div>
711
722
 
712
- <div class="style-popover"
713
- [class.show]="isPopoverVisible"
714
- (mouseenter)="keepPopoverOpen()"
715
- (mouseleave)="hidePopover()">
723
+ <dialog #styleDialog class="style-dialog">
724
+ <div class="dialog-header">
725
+ <h3>Select Basemap Style</h3>
726
+ <button class="close-button" (click)="closeDialog()">✕</button>
727
+ </div>
716
728
  <div class="style-grid">
717
729
  <div *ngFor="let style of mapStylesArray"
718
730
  class="style-item"
@@ -720,9 +732,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
720
732
  <mapag-basemap-select [styleData]="style" [styles]="map().styles"></mapag-basemap-select>
721
733
  </div>
722
734
  </div>
723
- </div>
724
- `, styles: [":host{display:block;width:200px;height:80px;position:relative}.basemap-container{position:relative;width:100%;height:100%;border-radius:12px;background-size:cover;background-position:center;background-repeat:no-repeat;background-color:#f5f5f5;overflow:hidden;cursor:pointer;transition:transform .2s ease,box-shadow .2s ease;box-shadow:0 2px 8px #00000026;display:flex;align-items:center;justify-content:center}.basemap-container:hover{box-shadow:0 4px 16px #0003}.basemap-overlay{position:absolute;inset:0;background:linear-gradient(135deg,#0000001a,#0000004d);border-radius:12px;pointer-events:none}.basemap-title{position:relative;z-index:2;color:#fff;font-size:19px;font-weight:600;text-align:center;padding:8px 16px;background:#0000;border-radius:8px;-webkit-user-select:none;user-select:none;text-shadow:0 2px 4px rgba(0,0,0,.8);max-width:90%;word-wrap:break-word;line-height:1.2}.basemap-container:not([style*=\"background-image: url\"]){background:linear-gradient(135deg,#667eea,#764ba2)}.basemap-container:not([style*=\"background-image: url\"]) .basemap-overlay{background:#0000001a}.style-popover{padding:16px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #00000026;border:1px solid rgba(0,0,0,.1);opacity:0;visibility:hidden;transform:translateY(-10px);transition:opacity .2s ease,transform .2s ease,visibility .2s ease;position:absolute;top:calc(100% + 8px);left:0;z-index:1000;max-width:90vw;max-height:80vh;overflow-y:auto;min-width:100%}.style-popover.show{opacity:1;visibility:visible;transform:translateY(0)}.style-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;min-width:380px;max-width:600px}.style-item{cursor:pointer;transition:transform .2s ease}.style-item:hover{transform:scale(1.05)}@media (max-width: 768px){.style-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr));min-width:300px}}\n"] }]
725
- }], ctorParameters: () => [], propDecorators: { map: [{ type: i0.Input, args: [{ isSignal: true, alias: "map", required: true }] }] } });
735
+ </dialog>
736
+ `, styles: [":host{display:block;width:200px;height:60px;position:relative}.basemap-container{position:relative;width:100%;height:100%;border-radius:12px;background-size:cover;background-position:center;background-repeat:no-repeat;background-color:#f5f5f5;overflow:hidden;box-shadow:0 2px 8px #00000026;display:flex;align-items:center;justify-content:center}.basemap-title{position:relative;z-index:1;color:#fff;font-size:19px;font-weight:600;text-align:center;padding:8px 16px;background:#0000;border-radius:8px;-webkit-user-select:none;user-select:none;text-shadow:0 2px 4px rgba(0,0,0,.8);max-width:90%;word-wrap:break-word;line-height:1.2}.dialog-button{position:absolute;top:50%;transform:translateY(-50%);right:8px;background:#ffffffe6;border:none;border-radius:6px;padding:4px 10px;font-size:18px;font-weight:700;cursor:pointer;z-index:2;transition:background-color .2s ease,transform .2s ease;box-shadow:0 2px 4px #0003;letter-spacing:1px}.dialog-button:hover{background:#fff;transform:translateY(-50%) scale(1.1)}.dialog-button:active{transform:translateY(-50%) scale(.95)}.basemap-container:not([style*=\"background-image: url\"]){background:linear-gradient(135deg,#667eea,#764ba2)}.style-dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;border:none;border-radius:12px;padding:0;max-width:90vw;max-height:80vh;box-shadow:0 8px 32px #00000040;background:#fff}.style-dialog::backdrop{background:#00000080;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.dialog-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid rgba(0,0,0,.1)}.dialog-header h3{margin:0;font-size:18px;font-weight:600;color:#333}.close-button{background:transparent;border:none;font-size:24px;cursor:pointer;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:6px;color:#666;transition:background-color .2s ease,color .2s ease}.close-button:hover{background-color:#0000000d;color:#333}.style-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;padding:20px;min-width:380px;max-width:600px;overflow-y:auto}.style-item{cursor:pointer;transition:transform .2s ease}.style-item:hover{transform:scale(1.05)}@media (max-width: 768px){.style-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr));min-width:300px}}\n"] }]
737
+ }], propDecorators: { map: [{ type: i0.Input, args: [{ isSignal: true, alias: "map", required: true }] }], styleDialog: [{ type: i0.ViewChild, args: ['styleDialog', { isSignal: true }] }] } });
726
738
 
727
739
  const BaseMapLight = {
728
740
  "version": 8,
@@ -14625,168 +14637,6 @@ class CensusTractMapper {
14625
14637
  };
14626
14638
  }
14627
14639
 
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
14640
  class CroplandDataLayerMapper {
14791
14641
  static PMTILES = 'pmtiles://https://foodmarketmaker-upload-data.s3.us-west-2.amazonaws.com/tiles/cdl_2024_30m.pmtiles';
14792
14642
  LAYER_ID = 'cropland-data-layer';
@@ -15320,6 +15170,163 @@ Dbl Crop Barley/Soybeans 254 433 47.5% 52.5% 0.47
15320
15170
 
15321
15171
  */
15322
15172
 
15173
+ class CropSequenceMapper {
15174
+ static PMTILES = 'pmtiles://https://foodmarketmaker-upload-data.s3.us-west-2.amazonaws.com/tiles/NationalCSB_2017_2024_rev23.pmtiles';
15175
+ FILL_LAYER_ID = 'cropsequence-layer';
15176
+ LINE_LAYER_ID = 'cropsequence-layer-line';
15177
+ SOURCE_ID = 'cropsequence-source';
15178
+ SOURCE_LAYER = 'NationalCSB_2017_2024_rev23';
15179
+ settings = signal(new CropSequenceSettings(), ...(ngDevMode ? [{ debugName: "settings" }] : []));
15180
+ current = null;
15181
+ currentFeatureID = undefined;
15182
+ over = signal(null, ...(ngDevMode ? [{ debugName: "over" }] : []));
15183
+ constructor(settings) {
15184
+ if (settings) {
15185
+ this.settings.set({
15186
+ ...this.settings(),
15187
+ ...settings
15188
+ });
15189
+ }
15190
+ const _ = effect(() => {
15191
+ const settings = this.settings();
15192
+ this._update(settings);
15193
+ }, ...(ngDevMode ? [{ debugName: "_" }] : []));
15194
+ }
15195
+ update(settings) {
15196
+ this.settings.set({ ...this.settings(), ...settings });
15197
+ }
15198
+ _update(settings) {
15199
+ if (!this.map) {
15200
+ return;
15201
+ }
15202
+ const map = this.map;
15203
+ if (settings.visible) {
15204
+ map.setLayoutProperty(this.FILL_LAYER_ID, 'visibility', 'visible');
15205
+ map.setLayoutProperty(this.LINE_LAYER_ID, 'visibility', 'visible');
15206
+ }
15207
+ else {
15208
+ map.setLayoutProperty(this.FILL_LAYER_ID, 'visibility', 'none');
15209
+ map.setLayoutProperty(this.LINE_LAYER_ID, 'visibility', 'none');
15210
+ }
15211
+ map.setPaintProperty(this.FILL_LAYER_ID, 'fill-color', settings.fillColor);
15212
+ map.setPaintProperty(this.FILL_LAYER_ID, 'fill-opacity', settings.fillOpacity);
15213
+ map.setPaintProperty(this.LINE_LAYER_ID, 'line-color', settings.borderColor);
15214
+ map.setPaintProperty(this.LINE_LAYER_ID, 'line-width', settings.borderWidth);
15215
+ map.setPaintProperty(this.LINE_LAYER_ID, 'line-opacity', settings.borderOpacity);
15216
+ }
15217
+ create() {
15218
+ if (!this.map) {
15219
+ return;
15220
+ }
15221
+ const map = this.map;
15222
+ let PMTILES_URL = CropSequenceMapper.PMTILES;
15223
+ AddSource(map, this.SOURCE_ID, {
15224
+ type: 'vector',
15225
+ url: PMTILES_URL,
15226
+ });
15227
+ const addedFill = AddLayer(map, {
15228
+ id: this.FILL_LAYER_ID,
15229
+ source: this.SOURCE_ID,
15230
+ "source-layer": this.SOURCE_LAYER,
15231
+ type: 'fill',
15232
+ }, StandardLayersMapper.POLYGONS_BACKGROUND);
15233
+ AddLayer(map, {
15234
+ id: this.LINE_LAYER_ID,
15235
+ source: this.SOURCE_ID,
15236
+ "source-layer": this.SOURCE_LAYER,
15237
+ type: 'line',
15238
+ }, StandardLayersMapper.POLYGONS_BACKGROUND);
15239
+ this._update(this.settings());
15240
+ if (!addedFill) {
15241
+ return;
15242
+ }
15243
+ map.on('mousemove', this.FILL_LAYER_ID, (e) => {
15244
+ this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
15245
+ });
15246
+ map.on('click', this.FILL_LAYER_ID, (e) => {
15247
+ // Publish
15248
+ this.over.set(e.features && e.features.length > 0 ? e.features[0] : null);
15249
+ if (e.features && e.features.length > 0) {
15250
+ const feature = e.features[0];
15251
+ const coordinates = e.lngLat;
15252
+ if (this.popup) {
15253
+ this.popup.remove();
15254
+ }
15255
+ const tb = new TableBuilder();
15256
+ const crop2017 = this.lookupClass(feature.properties ? feature.properties['CDL2017'] : null);
15257
+ const crop2018 = this.lookupClass(feature.properties ? feature.properties['CDL2018'] : null);
15258
+ const crop2019 = this.lookupClass(feature.properties ? feature.properties['CDL2019'] : null);
15259
+ const crop2020 = this.lookupClass(feature.properties ? feature.properties['CDL2020'] : null);
15260
+ const crop2021 = this.lookupClass(feature.properties ? feature.properties['CDL2021'] : null);
15261
+ const crop2022 = this.lookupClass(feature.properties ? feature.properties['CDL2022'] : null);
15262
+ const crop2023 = this.lookupClass(feature.properties ? feature.properties['CDL2023'] : null);
15263
+ const crop2024 = this.lookupClass(feature.properties ? feature.properties['CDL2024'] : null);
15264
+ tb.addHeader('Year', 'Crop Type');
15265
+ tb.add('2024', crop2024 ?? 'Unknown');
15266
+ tb.add('2023', crop2023 ?? 'Unknown');
15267
+ tb.add('2022', crop2022 ?? 'Unknown');
15268
+ tb.add('2021', crop2021 ?? 'Unknown');
15269
+ tb.add('2020', crop2020 ?? 'Unknown');
15270
+ tb.add('2019', crop2019 ?? 'Unknown');
15271
+ tb.add('2018', crop2018 ?? 'Unknown');
15272
+ tb.add('2017', crop2017 ?? 'Unknown');
15273
+ tb.addHeader('Location', "");
15274
+ tb.add('State FIPS', feature.properties ? feature.properties['STATEFIPS'] : 'Unknown');
15275
+ tb.add('County', feature.properties ? feature.properties['CNTY'] : 'Unknown');
15276
+ tb.add('County FIPS', feature.properties ? feature.properties['CNTYFIPS'] : 'Unknown');
15277
+ tb.add('ASD', feature.properties ? feature.properties['ASD'] : 'Unknown');
15278
+ tb.add('Area (M²)', feature.properties ? feature.properties['Shape_Area'] : 'Unknown');
15279
+ const fieldsHtml = tb.toHtml();
15280
+ this.currentFeatureID = feature?.properties?.['globalid'];
15281
+ this.popup = new Popup({ maxWidth: '400px' })
15282
+ .setLngLat(coordinates)
15283
+ .setHTML(`<strong>Crop Sequence</strong><br/>${fieldsHtml}`)
15284
+ .addTo(map);
15285
+ }
15286
+ });
15287
+ }
15288
+ lookupClass(code) {
15289
+ const found = CroplandLegend.find((item) => {
15290
+ return item.code == code;
15291
+ });
15292
+ if (found) {
15293
+ return found.class;
15294
+ }
15295
+ return undefined;
15296
+ }
15297
+ lookup(code) {
15298
+ const found = CroplandLegend.find((item) => {
15299
+ return item.code == code;
15300
+ });
15301
+ return found;
15302
+ }
15303
+ async onReady(map, svc) {
15304
+ this.map = map;
15305
+ this.create();
15306
+ }
15307
+ reset() { }
15308
+ clear() {
15309
+ if (this.map) {
15310
+ this.map.removeLayer(this.FILL_LAYER_ID);
15311
+ this.map.removeLayer(this.LINE_LAYER_ID);
15312
+ this.map.removeSource(this.SOURCE_ID);
15313
+ }
15314
+ }
15315
+ legends;
15316
+ count = 0;
15317
+ total = 0;
15318
+ map;
15319
+ popup = null;
15320
+ }
15321
+ class CropSequenceSettings {
15322
+ visible = true;
15323
+ fillColor = '#1aac39';
15324
+ fillOpacity = 0.2;
15325
+ borderColor = '#006e16';
15326
+ borderWidth = 1;
15327
+ borderOpacity = 0.5;
15328
+ }
15329
+
15323
15330
  class EsriMapper {
15324
15331
  jsonUrl = 'https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/resources/styles/root.json';
15325
15332
  SOURCE_ID = 'esri';
@@ -16735,5 +16742,5 @@ class HttpBoundaryLoader {
16735
16742
  * Generated bundle index. Do not edit.
16736
16743
  */
16737
16744
 
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 };
16745
+ 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
16746
  //# sourceMappingURL=foodmarketmaker-mapag.mjs.map