@foodmarketmaker/mapag 0.0.44 → 0.0.46

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.
@@ -21,15 +21,15 @@ import bbox from '@turf/bbox';
21
21
  import bboxPolygon from '@turf/bbox-polygon';
22
22
  import buffer from '@turf/buffer';
23
23
  import difference from '@turf/difference';
24
- import { HttpClient } from '@angular/common/http';
24
+ import { HttpClient, httpResource } from '@angular/common/http';
25
25
  import { BinaryWriter, BinaryReader } from '@bufbuild/protobuf/wire';
26
+ import { featureFilter } from '@mapbox/mapbox-gl-style-spec';
26
27
  import { NgSelectComponent, NgLabelTemplateDirective, NgOptionTemplateDirective } from '@ng-select/ng-select';
28
+ import { CdkVirtualScrollViewport, CdkVirtualForOf, CdkFixedSizeVirtualScroll } from '@angular/cdk/scrolling';
27
29
 
28
30
  function SaveMap(map) {
29
31
  var mapCanvas = map.getCanvas();
30
- var image = mapCanvas
31
- .toDataURL('image/png')
32
- .replace('image/png', 'image/octet-stream');
32
+ var image = mapCanvas.toDataURL('image/png').replace('image/png', 'image/octet-stream');
33
33
  // here is the most important part because if you dont replace you will get a DOM 18 exception.
34
34
  window.location.href = image;
35
35
  }
@@ -187,37 +187,31 @@ async function pmtilesPixelInfo(url, map, e) {
187
187
  // Convert lat/lon to tile coordinates at a chosen zoom
188
188
  const zoom = 10; // pick a zoom level for sampling
189
189
  const x = Math.floor(((lngLat.lng + 180) / 360) * Math.pow(2, zoom));
190
- const y = Math.floor(((1 -
191
- Math.log(Math.tan((lngLat.lat * Math.PI) / 180) +
192
- 1 / Math.cos((lngLat.lat * Math.PI) / 180)) /
193
- Math.PI) /
190
+ const y = Math.floor(((1 - Math.log(Math.tan((lngLat.lat * Math.PI) / 180) + 1 / Math.cos((lngLat.lat * Math.PI) / 180)) / Math.PI) /
194
191
  2) *
195
192
  Math.pow(2, zoom));
196
193
  // 5. Fetch the tile from PMTiles
197
194
  const tile = await pmtiles.getZxy(zoom, x, y);
198
195
  if (!tile) {
199
- console.log("No tile found at this location");
196
+ console.log('No tile found at this location');
200
197
  return undefined;
201
198
  }
202
199
  // Decode the raster tile (PNG or WebP)
203
200
  const blob = new Blob([tile.data]);
204
201
  const bitmap = await createImageBitmap(blob);
205
202
  // Draw to canvas to read pixel
206
- const canvas = document.createElement("canvas");
203
+ const canvas = document.createElement('canvas');
207
204
  canvas.width = bitmap.width;
208
205
  canvas.height = bitmap.height;
209
- const ctx = canvas.getContext("2d");
206
+ const ctx = canvas.getContext('2d');
210
207
  if (!ctx) {
211
- console.error("Failed to get canvas context");
208
+ console.error('Failed to get canvas context');
212
209
  return undefined;
213
210
  }
214
211
  ctx.drawImage(bitmap, 0, 0);
215
212
  // Convert lat/lon to pixel coordinates inside the tile
216
213
  const px = Math.floor(((lngLat.lng + 180) / 360) * (256 * Math.pow(2, zoom))) % 256;
217
- const py = Math.floor(((1 -
218
- Math.log(Math.tan((lngLat.lat * Math.PI) / 180) +
219
- 1 / Math.cos((lngLat.lat * Math.PI) / 180)) /
220
- Math.PI) /
214
+ const py = Math.floor(((1 - Math.log(Math.tan((lngLat.lat * Math.PI) / 180) + 1 / Math.cos((lngLat.lat * Math.PI) / 180)) / Math.PI) /
221
215
  2) *
222
216
  (256 * Math.pow(2, zoom))) % 256;
223
217
  const pixel = ctx.getImageData(px, py, 1, 1).data;
@@ -255,7 +249,7 @@ class TableBuilder {
255
249
  return this;
256
250
  }
257
251
  toHtml() {
258
- const rowHtml = this.rows.map(row => row.toHtml()).join('');
252
+ const rowHtml = this.rows.map((row) => row.toHtml()).join('');
259
253
  return `<table style="border-collapse: collapse; width: 100%; font-size: 9px;">${rowHtml}</table>`;
260
254
  }
261
255
  }
@@ -271,7 +265,7 @@ class TableRow {
271
265
  }
272
266
  toHtml() {
273
267
  if (this.isHeader) {
274
- return `<tr>${this.cells.map(cell => `<th style="${this.headerStyle}">${cell}</th>`).join('\n')}</tr>`;
268
+ return `<tr>${this.cells.map((cell) => `<th style="${this.headerStyle}">${cell}</th>`).join('\n')}</tr>`;
275
269
  }
276
270
  return `<tr>${this.cells.map((cell, index) => `<td style="${index == 0 ? this.rowStyle1 : this.rowStyle2}">${cell}</td>`).join('')}</tr>`;
277
271
  }
@@ -279,7 +273,7 @@ class TableRow {
279
273
  function normalizeArray(values) {
280
274
  const min = Math.min(...values);
281
275
  const max = Math.max(...values);
282
- return values.map(v => normalize(v, min, max));
276
+ return values.map((v) => normalize(v, min, max));
283
277
  }
284
278
  function normalize(value, min, max) {
285
279
  if (max - min == 0) {
@@ -298,16 +292,60 @@ function prefixMatch(matchExpression, prefixes) {
298
292
  if (!prefixes || prefixes.length === 0) {
299
293
  return null;
300
294
  }
301
- const filter = [
302
- "any",
303
- ...prefixes.map(prefix => [
304
- "==",
305
- ["slice", matchExpression, 0, prefix.length],
306
- prefix
307
- ])
308
- ];
295
+ const filter = ['any', ...prefixes.map((prefix) => ['==', ['slice', matchExpression, 0, prefix.length], prefix])];
309
296
  return filter;
310
297
  }
298
+ class SourceLoadWatcher {
299
+ updated = signal(0, ...(ngDevMode ? [{ debugName: "updated" }] : []));
300
+ debounceTimer = null;
301
+ debounceMs;
302
+ sourceId;
303
+ map;
304
+ constructor(debounceMs = 30) {
305
+ this.debounceMs = debounceMs;
306
+ }
307
+ on(map, sourceId) {
308
+ this.map = map;
309
+ this.sourceId = sourceId;
310
+ this.map.on('sourcedata', this.handle);
311
+ }
312
+ off() {
313
+ if (!this.map)
314
+ return;
315
+ this.map.off('sourcedata', this.handle);
316
+ }
317
+ handle = (e) => {
318
+ if (!this.map)
319
+ return;
320
+ if (e.sourceId !== this.sourceId)
321
+ return;
322
+ // Ignore style/layout-only events (maplibre emits sourcedata for metadata/visibility changes)
323
+ if (e.dataType && e.dataType !== 'source')
324
+ return;
325
+ // Allow real data events; skip pure metadata/visibility
326
+ const sdt = e.sourceDataType;
327
+ const hasTile = Boolean(e.tile);
328
+ if (sdt === 'metadata')
329
+ return;
330
+ if (sdt && sdt !== 'content' && sdt !== 'tile')
331
+ return;
332
+ if (!sdt && !hasTile)
333
+ return; // unknown non-tile event (likely style/visibility)
334
+ // Only proceed when the map reports the source as fully loaded
335
+ if (!this.map.isSourceLoaded(e.sourceId))
336
+ return;
337
+ // Debounce to ensure we catch the *last* event
338
+ clearTimeout(this.debounceTimer);
339
+ this.debounceTimer = setTimeout(() => {
340
+ if (!this.map)
341
+ return;
342
+ // Wait for the map to finish rendering
343
+ this.map.once('idle', () => {
344
+ this.updated.update((n) => n + 1);
345
+ });
346
+ }, this.debounceMs);
347
+ };
348
+ }
311
349
 
312
350
  const DEFAULT_GLYPHS2 = "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/resources/fonts/{fontstack}/{range}.pbf";
313
351
  const DEFAULT_GLYPHS = "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf";
@@ -21769,6 +21807,15 @@ class NAASSettings {
21769
21807
  showLegend = false;
21770
21808
  }
21771
21809
 
21810
+ function Filter(features, filter) {
21811
+ if (!filter) {
21812
+ return features;
21813
+ }
21814
+ const fn = featureFilter(filter);
21815
+ const matched = features.filter((f) => fn.filter({ zoom: 12 }, f));
21816
+ return matched;
21817
+ }
21818
+
21772
21819
  const NaicsSalesOptions = [
21773
21820
  { key: 'Less Than $500,000'.toLowerCase(), value: 'Less Than $500,000' },
21774
21821
  { key: '$500,000 TO $1 Million'.toLowerCase(), value: '$500,000 TO $1 Million' },
@@ -21849,6 +21896,7 @@ class NaicsMapperSettings {
21849
21896
  filterState;
21850
21897
  filterStates = [];
21851
21898
  showLegend = false;
21899
+ externalLoad = true;
21852
21900
  }
21853
21901
  class NaicsMapper {
21854
21902
  legends = [];
@@ -21864,6 +21912,16 @@ class NaicsMapper {
21864
21912
  HEATMAP_LAYER_ID;
21865
21913
  settings = signal(new NaicsMapperSettings(), ...(ngDevMode ? [{ debugName: "settings" }] : []));
21866
21914
  current = null;
21915
+ watcher = new SourceLoadWatcher();
21916
+ http = inject(HttpClient);
21917
+ geoJsonUrl = computed(() => {
21918
+ const settings = this.settings();
21919
+ if (settings.externalLoad) {
21920
+ return this.buildSourceUrl(settings);
21921
+ }
21922
+ return null;
21923
+ }, ...(ngDevMode ? [{ debugName: "geoJsonUrl" }] : []));
21924
+ geoJsonResource = httpResource(() => this.geoJsonUrl() || undefined);
21867
21925
  constructor(settings, id = undefined) {
21868
21926
  if (id) {
21869
21927
  this.id = id;
@@ -21896,6 +21954,42 @@ class NaicsMapper {
21896
21954
  this._update(this.settings());
21897
21955
  }, ...(ngDevMode ? [{ debugName: "_updateGlobal" }] : []));
21898
21956
  }
21957
+ data = computed(() => {
21958
+ this.watcher.updated(); // depend on source data changes
21959
+ const settings = this.settings();
21960
+ if (!this.map) {
21961
+ return [];
21962
+ }
21963
+ const map = this.map;
21964
+ const filter = this.getFilter(settings);
21965
+ if (settings.externalLoad) {
21966
+ // Check if data is still loading or has an error
21967
+ if (this.geoJsonResource.isLoading()) {
21968
+ return [];
21969
+ }
21970
+ if (this.geoJsonResource.error()) {
21971
+ console.error('Failed to load GeoJSON:', this.geoJsonResource.error());
21972
+ return [];
21973
+ }
21974
+ // Check if we have loaded data
21975
+ if (!this.geoJsonResource.hasValue()) {
21976
+ return [];
21977
+ }
21978
+ const geoJsonData = this.geoJsonResource.value();
21979
+ const features = geoJsonData?.features || [];
21980
+ if (!features || features.length === 0) {
21981
+ return [];
21982
+ }
21983
+ const filtered = Filter(features, filter);
21984
+ return filtered || [];
21985
+ }
21986
+ else {
21987
+ const features = map.querySourceFeatures(this.id, {
21988
+ filter: filter ? filter : undefined,
21989
+ });
21990
+ return features || [];
21991
+ }
21992
+ }, ...(ngDevMode ? [{ debugName: "data" }] : []));
21899
21993
  update(settings) {
21900
21994
  this.settings.set({ ...this.settings(), ...settings });
21901
21995
  }
@@ -21919,7 +22013,7 @@ class NaicsMapper {
21919
22013
  break;
21920
22014
  case 'icon':
21921
22015
  if (map.getLayer(this.ICON_LAYER_ID)) {
21922
- await this.loadIcon();
22016
+ await this.loadIcon(settings);
21923
22017
  map.setLayoutProperty(this.ICON_LAYER_ID, 'visibility', settings.visible ? 'visible' : 'none');
21924
22018
  map.setLayoutProperty(this.ICON_LAYER_ID, 'icon-image', mapboxImageName(settings.iconUrl));
21925
22019
  map.setLayoutProperty(this.ICON_LAYER_ID, 'icon-size', settings.iconSize);
@@ -21945,6 +22039,7 @@ class NaicsMapper {
21945
22039
  onReady(map, svc) {
21946
22040
  this.map = map;
21947
22041
  this.svc.set(svc);
22042
+ this.watcher.on(map, this.id);
21948
22043
  this.create(this.settings());
21949
22044
  }
21950
22045
  reset() {
@@ -22004,18 +22099,7 @@ class NaicsMapper {
22004
22099
  svc.UpdateLegend(this.id, legend);
22005
22100
  }
22006
22101
  }
22007
- // Method to create layers
22008
- async create(settings) {
22009
- if (!this.map) {
22010
- return;
22011
- }
22012
- const map = this.map;
22013
- if (!settings.ID) {
22014
- return;
22015
- }
22016
- // Create the data source url based on source type
22017
- // 'https://foodmarketmaker-upload-data.s3.us-west-2.amazonaws.com/tiles/naics/geojson/NAICS_CODE_111320.geojson'
22018
- // let sourceURL = 'https://foodmarketmaker-upload-data.s3.us-west-2.amazonaws.com/tiles/naics/geojson/NAICS_CODE_311211.geojson
22102
+ buildSourceUrl(settings) {
22019
22103
  let sourceURL = 'https://foodmarketmaker-upload-data.s3.us-west-2.amazonaws.com/tiles/naics/';
22020
22104
  if (settings.source) {
22021
22105
  sourceURL += settings.source + '/';
@@ -22026,6 +22110,18 @@ class NaicsMapper {
22026
22110
  else {
22027
22111
  sourceURL += 'geojson/NAICS_CODE_' + settings?.ID + '.geojson';
22028
22112
  }
22113
+ return sourceURL;
22114
+ }
22115
+ // Method to create layers
22116
+ async create(settings) {
22117
+ if (!this.map) {
22118
+ return;
22119
+ }
22120
+ const map = this.map;
22121
+ if (!settings.ID) {
22122
+ return;
22123
+ }
22124
+ const sourceURL = this.buildSourceUrl(settings);
22029
22125
  // Update or add the source
22030
22126
  const currentSource = map.getSource(this.id);
22031
22127
  if (!currentSource) {
@@ -22034,15 +22130,16 @@ class NaicsMapper {
22034
22130
  data: sourceURL,
22035
22131
  });
22036
22132
  }
22037
- else if (currentSource._data !== sourceURL) {
22133
+ else {
22038
22134
  currentSource.setData(sourceURL);
22039
22135
  }
22040
22136
  // Add visualization layer based on type
22041
- await this.addVisualizationLayer(map);
22137
+ await this.addVisualizationLayer(map, settings);
22042
22138
  // Add cluster layers if clustering is enabled
22043
22139
  if (settings.sourceType === 'geojson') {
22044
22140
  // this.addClusterLayers(map);
22045
22141
  }
22142
+ console.log('NAICS Mapper created/updated:', this.id, settings);
22046
22143
  // Add popup on click
22047
22144
  this.map.off('click', this.CIRCLE_LAYER_ID, this.onClick);
22048
22145
  this.map.off('click', this.ICON_LAYER_ID, this.onClick);
@@ -22052,7 +22149,7 @@ class NaicsMapper {
22052
22149
  map.on('click', this.ICON_LAYER_ID, this.onClick);
22053
22150
  map.on('touchend', this.CIRCLE_LAYER_ID, this.onClick);
22054
22151
  map.on('touchend', this.ICON_LAYER_ID, this.onClick);
22055
- this.filter(map);
22152
+ this.filter(map, settings);
22056
22153
  untracked(() => this.updateLegend(settings));
22057
22154
  }
22058
22155
  getActiveLayerId() {
@@ -22068,12 +22165,11 @@ class NaicsMapper {
22068
22165
  return this.CIRCLE_LAYER_ID;
22069
22166
  }
22070
22167
  }
22071
- async loadIcon() {
22168
+ async loadIcon(settings) {
22072
22169
  if (!this.map) {
22073
22170
  return;
22074
22171
  }
22075
22172
  const map = this.map;
22076
- const settings = this.settings();
22077
22173
  const iconName = mapboxImageName(settings.iconUrl);
22078
22174
  if (settings.iconUrl && !map.hasImage(iconName)) {
22079
22175
  await mapboxloadImage(map, {
@@ -22083,15 +22179,11 @@ class NaicsMapper {
22083
22179
  });
22084
22180
  }
22085
22181
  }
22086
- async addVisualizationLayer(map) {
22087
- const settings = this.settings();
22182
+ async addVisualizationLayer(map, settings) {
22088
22183
  // Remove existing layers that ar not needed
22089
- if (settings.type !== 'circle')
22090
- RemoveLayer(map, this.CIRCLE_LAYER_ID);
22091
- if (settings.type !== 'icon')
22092
- RemoveLayer(map, this.ICON_LAYER_ID);
22093
- if (settings.type !== 'heatmap')
22094
- RemoveLayer(map, this.HEATMAP_LAYER_ID);
22184
+ // if (settings.type !== 'circle') RemoveLayer(map, this.CIRCLE_LAYER_ID);
22185
+ // if (settings.type !== 'icon') RemoveLayer(map, this.ICON_LAYER_ID);
22186
+ // if (settings.type !== 'heatmap') RemoveLayer(map, this.HEATMAP_LAYER_ID);
22095
22187
  // Add layer based on type
22096
22188
  switch (settings.type) {
22097
22189
  case 'circle':
@@ -22114,7 +22206,7 @@ class NaicsMapper {
22114
22206
  break;
22115
22207
  case 'icon':
22116
22208
  // Load icon image if URL is provided and not already loaded
22117
- await this.loadIcon();
22209
+ await this.loadIcon(settings);
22118
22210
  AddLayer(map, {
22119
22211
  id: this.ICON_LAYER_ID,
22120
22212
  type: 'symbol',
@@ -22155,8 +22247,7 @@ class NaicsMapper {
22155
22247
  break;
22156
22248
  }
22157
22249
  }
22158
- getFipsFilter() {
22159
- const settings = this.settings();
22250
+ getFipsFilter(settings) {
22160
22251
  if (settings.filterOverrideGlobal) {
22161
22252
  if (settings.filterStates && settings.filterStates.length > 0) {
22162
22253
  return settings.filterStates;
@@ -22167,8 +22258,51 @@ class NaicsMapper {
22167
22258
  }
22168
22259
  return this.svc()?.stateCountyFilter();
22169
22260
  }
22170
- filter(map) {
22171
- const settings = this.settings();
22261
+ getFilter(settings) {
22262
+ // Build filter conditions for each field
22263
+ const conditions = ['all'];
22264
+ const fipsFilter = this.getFipsFilter(settings);
22265
+ if (fipsFilter && fipsFilter.length > 0) {
22266
+ const filter = [
22267
+ "any",
22268
+ ...fipsFilter.map(prefix => [
22269
+ "==",
22270
+ ["slice", ["get", "FIPS"], 0, prefix.length],
22271
+ prefix
22272
+ ])
22273
+ ];
22274
+ // @ts-ignore
22275
+ conditions.push(filter);
22276
+ }
22277
+ // Filter by Employees (if array has values)
22278
+ if (settings.filterEmployees &&
22279
+ settings.filterEmployees.length > 0 &&
22280
+ settings.filterEmployees.length < Object.keys(NaicsEmployeesOptions).length) {
22281
+ const employeeConditions = [
22282
+ 'in',
22283
+ ['downcase', ['coalesce', ['get', 'NUMBER_OF_EMPLOYEES'], '']],
22284
+ ['literal', settings.filterEmployees],
22285
+ ];
22286
+ conditions.push(employeeConditions);
22287
+ }
22288
+ // Filter by Sales (if array has values)
22289
+ if (settings.filterSales &&
22290
+ settings.filterSales.length > 0 &&
22291
+ settings.filterSales.length < Object.keys(NaicsSalesOptions).length) {
22292
+ const salesConditions = [
22293
+ 'in',
22294
+ ['downcase', ['get', 'SALES_VOLUME']],
22295
+ ['literal', settings.filterSales],
22296
+ ];
22297
+ conditions.push(salesConditions);
22298
+ }
22299
+ // Apply filter if we have any conditions, otherwise clear filter
22300
+ if (conditions.length > 1) {
22301
+ return conditions;
22302
+ }
22303
+ return undefined;
22304
+ }
22305
+ filter(map, settings) {
22172
22306
  const layerId = this.getActiveLayerId();
22173
22307
  if (!map.getLayer(layerId)) {
22174
22308
  console.warn('Layer not found:', layerId);
@@ -22176,7 +22310,7 @@ class NaicsMapper {
22176
22310
  }
22177
22311
  // Build filter conditions for each field
22178
22312
  const conditions = ['all'];
22179
- const fipsFilter = this.getFipsFilter();
22313
+ const fipsFilter = this.getFipsFilter(settings);
22180
22314
  if (fipsFilter && fipsFilter.length > 0) {
22181
22315
  const filter = [
22182
22316
  "any",
@@ -22225,6 +22359,19 @@ class NaicsMapper {
22225
22359
  getSettings() {
22226
22360
  return { ...this.settings() };
22227
22361
  }
22362
+ flyToFeature(f) {
22363
+ if (!this.map) {
22364
+ return;
22365
+ }
22366
+ if (!f.geometry || f.geometry.type !== 'Point') {
22367
+ return;
22368
+ }
22369
+ const coords = f.geometry.coordinates;
22370
+ this.map.flyTo({
22371
+ center: [coords[0], coords[1]],
22372
+ zoom: 12,
22373
+ });
22374
+ }
22228
22375
  onClick = async (e) => {
22229
22376
  if (!this.map) {
22230
22377
  return;
@@ -22250,12 +22397,12 @@ class NaicsMapper {
22250
22397
  this.current.remove();
22251
22398
  this.current = null;
22252
22399
  }
22253
- const html = await this.renderPopup(features[0]);
22400
+ const html = this.renderPopup(features[0]);
22254
22401
  if (html) {
22255
22402
  this.current = new Popup().setLngLat(e.lngLat).setHTML(html).addTo(this.map);
22256
22403
  }
22257
22404
  };
22258
- async renderPopup(f) {
22405
+ renderPopup(f) {
22259
22406
  if (!f || !f.properties) {
22260
22407
  return undefined;
22261
22408
  }
@@ -22287,9 +22434,12 @@ class NaicsMapper {
22287
22434
  html += `<b>SIC: </b>${item?.['SIC_CODE1']} ${item?.['SIC1_DESCRIPTION']}`;
22288
22435
  }
22289
22436
  html += `FIPS: ${item?.['FIPS']}`;
22290
- if (f.geometry.type === 'Point') {
22437
+ if (f?.geometry?.type === 'Point') {
22291
22438
  html += `<br/><br/><small style="color: gray;">(${f.geometry.coordinates[1].toFixed(8)}, ${f.geometry.coordinates[0].toFixed(8)})</small>`;
22292
22439
  }
22440
+ else {
22441
+ console.warn('Feature geometry is not Point for popup coordinates display.', f);
22442
+ }
22293
22443
  html += `<br/><small style="color: gray;">${item?.['DSO_ID']}</small>`;
22294
22444
  return html;
22295
22445
  }
@@ -23742,6 +23892,11 @@ class PointDataMapper {
23742
23892
  settings = signal(new PointDataMapperSettings(), ...(ngDevMode ? [{ debugName: "settings" }] : []));
23743
23893
  svc = signal(null, ...(ngDevMode ? [{ debugName: "svc" }] : []));
23744
23894
  current = null;
23895
+ geoJsonUrl = computed(() => {
23896
+ const settings = this.settings();
23897
+ return settings.source;
23898
+ }, ...(ngDevMode ? [{ debugName: "geoJsonUrl" }] : []));
23899
+ geoJsonResource = httpResource(() => this.geoJsonUrl() || undefined);
23745
23900
  constructor(popupRenderer, settings) {
23746
23901
  this.id = 'points-' + Math.random().toString(36).substring(2, 15);
23747
23902
  this.popupRenderer = popupRenderer;
@@ -23777,6 +23932,34 @@ class PointDataMapper {
23777
23932
  this._update(this.settings());
23778
23933
  }, ...(ngDevMode ? [{ debugName: "_updateGlobal" }] : []));
23779
23934
  }
23935
+ data = computed(() => {
23936
+ // Check if data is still loading or has an error
23937
+ const settings = this.settings();
23938
+ if (this.geoJsonResource.isLoading()) {
23939
+ return [];
23940
+ }
23941
+ if (this.geoJsonResource.error()) {
23942
+ console.error('Failed to load GeoJSON:', this.geoJsonResource.error());
23943
+ return [];
23944
+ }
23945
+ // Check if we have loaded data
23946
+ if (!this.geoJsonResource.hasValue()) {
23947
+ return [];
23948
+ }
23949
+ const svc = this.svc();
23950
+ if (!svc) {
23951
+ return [];
23952
+ }
23953
+ svc.stateCountyFilter(); // depend
23954
+ const geoJsonData = this.geoJsonResource.value();
23955
+ const features = geoJsonData?.features || [];
23956
+ if (!features || features.length === 0) {
23957
+ return [];
23958
+ }
23959
+ const filter = this.getFilter(settings);
23960
+ const filtered = Filter(features, filter);
23961
+ return filtered || [];
23962
+ }, ...(ngDevMode ? [{ debugName: "data" }] : []));
23780
23963
  update(settings) {
23781
23964
  this.settings.set({ ...this.settings(), ...settings });
23782
23965
  }
@@ -23822,7 +24005,7 @@ class PointDataMapper {
23822
24005
  }
23823
24006
  break;
23824
24007
  }
23825
- this.filter(map);
24008
+ this.filter(map, settings);
23826
24009
  this.updateLegend(settings);
23827
24010
  }
23828
24011
  async loadIcon() {
@@ -23841,8 +24024,7 @@ class PointDataMapper {
23841
24024
  }
23842
24025
  }
23843
24026
  updateLegend(settings) { }
23844
- getActiveLayerId() {
23845
- const settings = this.settings();
24027
+ getActiveLayerId(settings) {
23846
24028
  switch (settings.type) {
23847
24029
  case 'circle':
23848
24030
  return this.POINT_LAYER_ID;
@@ -23854,13 +24036,7 @@ class PointDataMapper {
23854
24036
  return this.POINT_LAYER_ID;
23855
24037
  }
23856
24038
  }
23857
- filter(map) {
23858
- const settings = this.settings();
23859
- const layerId = this.getActiveLayerId();
23860
- if (!map.getLayer(layerId)) {
23861
- console.warn('Layer not found:', layerId);
23862
- return;
23863
- }
24039
+ getFilter(settings) {
23864
24040
  // Build filter conditions for each field
23865
24041
  const conditions = ['all'];
23866
24042
  const fipsFilter = this.getFipsFilter();
@@ -23875,14 +24051,21 @@ class PointDataMapper {
23875
24051
  // We can add any other filters here in the future
23876
24052
  // Apply filter if we have any conditions, otherwise clear filter
23877
24053
  if (conditions.length > 1) {
23878
- map.setFilter(layerId, conditions);
23879
- console.debug('Applied filter on layer:', layerId, 'filter:', JSON.stringify(conditions));
24054
+ return conditions;
23880
24055
  }
23881
24056
  else {
23882
- map.setFilter(layerId, null);
23883
- console.debug('Cleared filter on layer:', layerId);
24057
+ return null;
23884
24058
  }
23885
24059
  }
24060
+ filter(map, settings) {
24061
+ const layerId = this.getActiveLayerId(settings);
24062
+ if (!map.getLayer(layerId)) {
24063
+ console.warn('Layer not found:', layerId);
24064
+ return;
24065
+ }
24066
+ const filter = this.getFilter(settings);
24067
+ map.setFilter(layerId, filter);
24068
+ }
23886
24069
  onReady(map, svc) {
23887
24070
  this.map = map;
23888
24071
  this.svc.set(svc);
@@ -27158,6 +27341,92 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
27158
27341
  `, styles: ["dialog{font-size:14pt;width:100%;max-width:700px;border:none;border-radius:8px;box-shadow:0 2px 10px #0003;padding:16px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;flex-direction:column}dialog:open{display:flex}dialog .dlg-body{flex-grow:1;overflow-y:auto}dialog.legend{width:fit-content}dialog.legend h2{font-size:smaller}dialog select{max-width:90vw}dialog h2{color:#000}dialog h2:before{content:\"\\22ee\\22ee \";padding-right:4px}dialog h3{color:#000;border-bottom:2px solid gray;font-weight:500;font-size:.9em;margin-top:16px;margin-bottom:8px}dialog h4{color:#000;font-weight:500;margin-bottom:8px;margin-top:12px;font-size:.85em;border:none}dialog p{font-size:.8em}dialog a{text-decoration:none;color:#0a3773;font-weight:500;font-size:.8em;padding-left:4px}dialog a:hover{text-decoration:underline;cursor:pointer}dialog a:before{content:\"\\1f517\";padding-right:2px}.ctrl-group{display:flex;flex-direction:column}.ctrl-row{display:grid;grid-template-columns:auto 1fr auto 1fr;align-items:center;gap:4px;justify-items:start;padding-left:20px}.ctrl-first{grid-column:1}.ctrl-row label{font-size:.8em;margin:0;padding:0;font-weight:400}.ctrl.wide{grid-column:span 3}input[type=range]{grid-column:span 3;justify-self:stretch}input[type=color]{width:40px;height:24px;border-radius:4px;cursor:pointer}input[type=number]{width:6ch;font-size:.8em}.dlg-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button{background-color:#0a3773;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:.8em}button:hover{background-color:#083a5c}summary{font-size:1em;font-weight:600;color:#000;cursor:pointer;padding:8px 0;border-bottom:2px solid gray;list-style:none;-webkit-user-select:none;user-select:none;margin-bottom:8px}summary::-webkit-details-marker{display:none}summary:before{content:\"\\304f\";display:inline-block;margin-right:8px;transform:rotate(180deg);transition:transform .2s}details[open] summary:before{transform:rotate(270deg)}.radio-tabs{margin-bottom:12px;font-size:.8em;display:flex;flex-direction:row}.radio-tabs label{display:grid;grid-template-columns:auto 1fr;gap:4px;grid-template-rows:30px;align-items:center}.radio-tabs input[type=radio]{display:none}.radio-tabs label{padding:8px 12px;border:2px solid transparent;border-radius:6px;cursor:pointer;transition:all .2s ease}.radio-tabs label:has(input[type=radio]:checked){background-color:#fff;border-color:#333}.mgr-btn{justify-self:center;background-color:transparent;color:#4c4c4c;text-align:center;width:100%;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:4px 0;padding:6px;gap:4px;border:1px solid rgb(218,218,218)}.mgr-btn:hover{background-color:transparent;border-color:#4c4c4c}.legend-row{display:grid;grid-template-columns:auto 1fr;gap:8px;padding:4px 0;align-items:center}.legend-title{font-weight:700;text-align:center;margin-bottom:8px}.legend-item{height:15px;width:15px;border:1px solid #ccc}.maplibregl-popup-close-button{top:13px;right:15px}@media screen and (max-width: 600px){dialog{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:none;box-shadow:none;overflow:hidden}.dlg-buttons{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center}dialog h2:before{content:\"\";padding-right:0}}dialog{max-width:700px}.zone{display:flex;align-items:center;gap:8px;margin:0;padding:0;font-size:11pt}.zones{display:grid;grid-template-columns:1fr 1fr;column-gap:16px;row-gap:8px}@media (max-width: 600px){.zones{grid-template-columns:1fr}}\n"] }]
27159
27342
  }], ctorParameters: () => [], propDecorators: { map: [{ type: i0.Input, args: [{ isSignal: true, alias: "map", required: false }] }], customizeDialog: [{ type: i0.ViewChild, args: ['customizeDialog', { isSignal: true }] }], legendDialog: [{ type: i0.ViewChild, args: ['legendDialog', { isSignal: true }] }] } });
27160
27343
 
27344
+ class TileDialog {
27345
+ data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
27346
+ name = input('', ...(ngDevMode ? [{ debugName: "name" }] : []));
27347
+ contentTemplate = input(null, ...(ngDevMode ? [{ debugName: "contentTemplate" }] : []));
27348
+ selection = signal(null, ...(ngDevMode ? [{ debugName: "selection" }] : []));
27349
+ onSelect = output();
27350
+ dataDialog = viewChild('dataDialog', ...(ngDevMode ? [{ debugName: "dataDialog" }] : []));
27351
+ defaultTemplate = viewChild('defaultTemplate', ...(ngDevMode ? [{ debugName: "defaultTemplate" }] : []));
27352
+ toggle() {
27353
+ const dialog = this.dataDialog();
27354
+ if (!dialog) {
27355
+ return;
27356
+ }
27357
+ const dialogElement = dialog.nativeElement;
27358
+ if (dialogElement.open) {
27359
+ dialogElement.close();
27360
+ }
27361
+ else {
27362
+ dialogElement.show();
27363
+ }
27364
+ }
27365
+ onClick(feature) {
27366
+ this.selection.set(feature);
27367
+ this.onSelect.emit(feature);
27368
+ }
27369
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: TileDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
27370
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: TileDialog, isStandalone: true, selector: "mapag-tile-dialog", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, contentTemplate: { classPropertyName: "contentTemplate", publicName: "contentTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, viewQueries: [{ propertyName: "dataDialog", first: true, predicate: ["dataDialog"], descendants: true, isSignal: true }, { propertyName: "defaultTemplate", first: true, predicate: ["defaultTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: `
27371
+ <ng-template #defaultTemplate let-feature>
27372
+ <div>{{ feature }}</div>
27373
+ </ng-template>
27374
+ <dialog draggable mapagBringToFront onBody #dataDialog class="data-dialog">
27375
+ <h2>{{ name() }}</h2>
27376
+ <div class="dlg-body dlg-body-list ">
27377
+ {{ data()?.length }} records matching current filters.
27378
+ @if (data()?.length === 0) {
27379
+ <p>No data to display.</p>
27380
+ } @else {
27381
+ <cdk-virtual-scroll-viewport [itemSize]="10">
27382
+ <div *cdkVirtualFor="let feature of data()" (click)="onClick(feature)">
27383
+ <ng-container *ngTemplateOutlet="contentTemplate() || defaultTemplate; context: { $implicit: feature }"></ng-container>
27384
+ </div>
27385
+ </cdk-virtual-scroll-viewport>
27386
+ }
27387
+ </div>
27388
+ <div class="dlg-buttons">
27389
+ <button class="btn" (click)="toggle()">Close</button>
27390
+ </div>
27391
+ </dialog>
27392
+ `, isInline: true, styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: DraggableDialogDirective, selector: "dialog[draggable]" }, { kind: "directive", type: BringToFrontDirective, selector: "[mapagBringToFront]" }, { kind: "directive", type: OnBodyDirective, selector: "dialog[onBody]" }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27393
+ }
27394
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: TileDialog, decorators: [{
27395
+ type: Component,
27396
+ args: [{ selector: 'mapag-tile-dialog', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
27397
+ CommonModule,
27398
+ FormsModule,
27399
+ DraggableDialogDirective,
27400
+ BringToFrontDirective,
27401
+ OnBodyDirective,
27402
+ CdkVirtualScrollViewport,
27403
+ CdkVirtualForOf,
27404
+ CdkFixedSizeVirtualScroll,
27405
+ ], template: `
27406
+ <ng-template #defaultTemplate let-feature>
27407
+ <div>{{ feature }}</div>
27408
+ </ng-template>
27409
+ <dialog draggable mapagBringToFront onBody #dataDialog class="data-dialog">
27410
+ <h2>{{ name() }}</h2>
27411
+ <div class="dlg-body dlg-body-list ">
27412
+ {{ data()?.length }} records matching current filters.
27413
+ @if (data()?.length === 0) {
27414
+ <p>No data to display.</p>
27415
+ } @else {
27416
+ <cdk-virtual-scroll-viewport [itemSize]="10">
27417
+ <div *cdkVirtualFor="let feature of data()" (click)="onClick(feature)">
27418
+ <ng-container *ngTemplateOutlet="contentTemplate() || defaultTemplate; context: { $implicit: feature }"></ng-container>
27419
+ </div>
27420
+ </cdk-virtual-scroll-viewport>
27421
+ }
27422
+ </div>
27423
+ <div class="dlg-buttons">
27424
+ <button class="btn" (click)="toggle()">Close</button>
27425
+ </div>
27426
+ </dialog>
27427
+ ` }]
27428
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], contentTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentTemplate", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }], dataDialog: [{ type: i0.ViewChild, args: ['dataDialog', { isSignal: true }] }], defaultTemplate: [{ type: i0.ViewChild, args: ['defaultTemplate', { isSignal: true }] }] } });
27429
+
27161
27430
  class MMPanel {
27162
27431
  // Icons and static data
27163
27432
  faCircle = faCircle;
@@ -27222,6 +27491,9 @@ class MMPanel {
27222
27491
  'justify-self': 'center',
27223
27492
  };
27224
27493
  }, ...(ngDevMode ? [{ debugName: "heatMapStyle" }] : []));
27494
+ onSelect(f) {
27495
+ // Handle feature selection from dialog
27496
+ }
27225
27497
  constructor() {
27226
27498
  const _mapInit = effect(() => {
27227
27499
  const mapComp = this.map();
@@ -27283,6 +27555,9 @@ class MMPanel {
27283
27555
  ngOnDestroy() {
27284
27556
  this.mapper.clear();
27285
27557
  }
27558
+ toggleData() {
27559
+ // Implement dialog toggle logic here
27560
+ }
27286
27561
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MMPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
27287
27562
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: MMPanel, isStandalone: true, selector: "mapag-mm-panel", inputs: { map: { classPropertyName: "map", publicName: "map", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onRemove: "onRemove" }, viewQueries: [{ propertyName: "customizeDialog", first: true, predicate: ["customizeDialog"], descendants: true, isSignal: true }], ngImport: i0, template: `
27288
27563
  <hub-data-layer [visible]="mapper.settings().visible" [name]="mapper.settings().name"
@@ -27425,6 +27700,7 @@ class MMPanel {
27425
27700
  </div>
27426
27701
  <div class="dlg-buttons">
27427
27702
  <button class="btn" (click)="toggleLegend()">Legend</button>
27703
+ <button class="btn" (click)="dataDialog.toggle()">Data</button>
27428
27704
  <button class="btn" (click)="remove()">Remove</button>
27429
27705
  <button class="btn" (click)="reset()">Reset</button>
27430
27706
  <button class="btn" (click)="toggleShowHide()">
@@ -27434,11 +27710,22 @@ class MMPanel {
27434
27710
  <button class="btn" (click)="toggleDialog()">Close</button>
27435
27711
  </div>
27436
27712
  </dialog>
27437
- `, isInline: true, styles: ["dialog{font-size:14pt;width:100%;max-width:700px;border:none;border-radius:8px;box-shadow:0 2px 10px #0003;padding:16px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;flex-direction:column}dialog:open{display:flex}dialog .dlg-body{flex-grow:1;overflow-y:auto}dialog.legend{width:fit-content}dialog.legend h2{font-size:smaller}dialog select{max-width:90vw}dialog h2{color:#000}dialog h2:before{content:\"\\22ee\\22ee \";padding-right:4px}dialog h3{color:#000;border-bottom:2px solid gray;font-weight:500;font-size:.9em;margin-top:16px;margin-bottom:8px}dialog h4{color:#000;font-weight:500;margin-bottom:8px;margin-top:12px;font-size:.85em;border:none}dialog p{font-size:.8em}dialog a{text-decoration:none;color:#0a3773;font-weight:500;font-size:.8em;padding-left:4px}dialog a:hover{text-decoration:underline;cursor:pointer}dialog a:before{content:\"\\1f517\";padding-right:2px}.ctrl-group{display:flex;flex-direction:column}.ctrl-row{display:grid;grid-template-columns:auto 1fr auto 1fr;align-items:center;gap:4px;justify-items:start;padding-left:20px}.ctrl-first{grid-column:1}.ctrl-row label{font-size:.8em;margin:0;padding:0;font-weight:400}.ctrl.wide{grid-column:span 3}input[type=range]{grid-column:span 3;justify-self:stretch}input[type=color]{width:40px;height:24px;border-radius:4px;cursor:pointer}input[type=number]{width:6ch;font-size:.8em}.dlg-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button{background-color:#0a3773;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:.8em}button:hover{background-color:#083a5c}summary{font-size:1em;font-weight:600;color:#000;cursor:pointer;padding:8px 0;border-bottom:2px solid gray;list-style:none;-webkit-user-select:none;user-select:none;margin-bottom:8px}summary::-webkit-details-marker{display:none}summary:before{content:\"\\304f\";display:inline-block;margin-right:8px;transform:rotate(180deg);transition:transform .2s}details[open] summary:before{transform:rotate(270deg)}.radio-tabs{margin-bottom:12px;font-size:.8em;display:flex;flex-direction:row}.radio-tabs label{display:grid;grid-template-columns:auto 1fr;gap:4px;grid-template-rows:30px;align-items:center}.radio-tabs input[type=radio]{display:none}.radio-tabs label{padding:8px 12px;border:2px solid transparent;border-radius:6px;cursor:pointer;transition:all .2s ease}.radio-tabs label:has(input[type=radio]:checked){background-color:#fff;border-color:#333}.mgr-btn{justify-self:center;background-color:transparent;color:#4c4c4c;text-align:center;width:100%;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:4px 0;padding:6px;gap:4px;border:1px solid rgb(218,218,218)}.mgr-btn:hover{background-color:transparent;border-color:#4c4c4c}.legend-row{display:grid;grid-template-columns:auto 1fr;gap:8px;padding:4px 0;align-items:center}.legend-title{font-weight:700;text-align:center;margin-bottom:8px}.legend-item{height:15px;width:15px;border:1px solid #ccc}.maplibregl-popup-close-button{top:13px;right:15px}@media screen and (max-width: 600px){dialog{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:none;box-shadow:none;overflow:hidden}.dlg-buttons{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center}dialog h2:before{content:\"\";padding-right:0}}::deep .ng-select-container,::deep .ng-select{font-size:.8em}.filter-row{display:flex;flex-direction:column;margin-bottom:8px;font-size:.8em}.filter-row-cols{display:block;column-count:2}.zone{display:flex;align-items:center;gap:8px;margin:0;padding:0}.zones{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;row-gap:8px;overflow-y:auto;max-height:420px;font-size:.8em}.svgicon{height:30px;width:30px;-webkit-mask-size:contain;mask-size:contain}h4,label{display:flex;align-items:center;gap:4px}@media (max-width: 600px){.zones{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: HubDataLayer, selector: "hub-data-layer", inputs: ["visible", "name", "desc", "icon", "shape"], outputs: ["onCustomize", "onCheck"] }, { kind: "directive", type: DraggableDialogDirective, selector: "dialog[draggable]" }, { kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }, { kind: "directive", type: BringToFrontDirective, selector: "[mapagBringToFront]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27713
+
27714
+ <ng-template #dataTemplate let-feature>
27715
+ <div [innerHTML]="mapper.popupRenderer?.RenderPopup(feature) | async"></div>
27716
+ </ng-template>
27717
+ <mapag-tile-dialog
27718
+ #dataDialog
27719
+ [data]="mapper.data()"
27720
+ [name]="mapper.settings().name"
27721
+ [contentTemplate]="dataTemplate"
27722
+ (onSelect)="onSelect($event)">
27723
+ </mapag-tile-dialog>
27724
+ `, isInline: true, styles: ["dialog{font-size:14pt;width:100%;max-width:700px;border:none;border-radius:8px;box-shadow:0 2px 10px #0003;padding:16px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;flex-direction:column}dialog:open{display:flex}dialog .dlg-body{flex-grow:1;overflow-y:auto}dialog.legend{width:fit-content}dialog.legend h2{font-size:smaller}dialog select{max-width:90vw}dialog h2{color:#000}dialog h2:before{content:\"\\22ee\\22ee \";padding-right:4px}dialog h3{color:#000;border-bottom:2px solid gray;font-weight:500;font-size:.9em;margin-top:16px;margin-bottom:8px}dialog h4{color:#000;font-weight:500;margin-bottom:8px;margin-top:12px;font-size:.85em;border:none}dialog p{font-size:.8em}dialog a{text-decoration:none;color:#0a3773;font-weight:500;font-size:.8em;padding-left:4px}dialog a:hover{text-decoration:underline;cursor:pointer}dialog a:before{content:\"\\1f517\";padding-right:2px}.ctrl-group{display:flex;flex-direction:column}.ctrl-row{display:grid;grid-template-columns:auto 1fr auto 1fr;align-items:center;gap:4px;justify-items:start;padding-left:20px}.ctrl-first{grid-column:1}.ctrl-row label{font-size:.8em;margin:0;padding:0;font-weight:400}.ctrl.wide{grid-column:span 3}input[type=range]{grid-column:span 3;justify-self:stretch}input[type=color]{width:40px;height:24px;border-radius:4px;cursor:pointer}input[type=number]{width:6ch;font-size:.8em}.dlg-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button{background-color:#0a3773;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:.8em}button:hover{background-color:#083a5c}summary{font-size:1em;font-weight:600;color:#000;cursor:pointer;padding:8px 0;border-bottom:2px solid gray;list-style:none;-webkit-user-select:none;user-select:none;margin-bottom:8px}summary::-webkit-details-marker{display:none}summary:before{content:\"\\304f\";display:inline-block;margin-right:8px;transform:rotate(180deg);transition:transform .2s}details[open] summary:before{transform:rotate(270deg)}.radio-tabs{margin-bottom:12px;font-size:.8em;display:flex;flex-direction:row}.radio-tabs label{display:grid;grid-template-columns:auto 1fr;gap:4px;grid-template-rows:30px;align-items:center}.radio-tabs input[type=radio]{display:none}.radio-tabs label{padding:8px 12px;border:2px solid transparent;border-radius:6px;cursor:pointer;transition:all .2s ease}.radio-tabs label:has(input[type=radio]:checked){background-color:#fff;border-color:#333}.mgr-btn{justify-self:center;background-color:transparent;color:#4c4c4c;text-align:center;width:100%;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:4px 0;padding:6px;gap:4px;border:1px solid rgb(218,218,218)}.mgr-btn:hover{background-color:transparent;border-color:#4c4c4c}.legend-row{display:grid;grid-template-columns:auto 1fr;gap:8px;padding:4px 0;align-items:center}.legend-title{font-weight:700;text-align:center;margin-bottom:8px}.legend-item{height:15px;width:15px;border:1px solid #ccc}.maplibregl-popup-close-button{top:13px;right:15px}@media screen and (max-width: 600px){dialog{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:none;box-shadow:none;overflow:hidden}.dlg-buttons{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center}dialog h2:before{content:\"\";padding-right:0}}::deep .ng-select-container,::deep .ng-select{font-size:.8em}.filter-row{display:flex;flex-direction:column;margin-bottom:8px;font-size:.8em}.filter-row-cols{display:block;column-count:2}.zone{display:flex;align-items:center;gap:8px;margin:0;padding:0}.zones{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;row-gap:8px;overflow-y:auto;max-height:420px;font-size:.8em}.svgicon{height:30px;width:30px;-webkit-mask-size:contain;mask-size:contain}h4,label{display:flex;align-items:center;gap:4px}@media (max-width: 600px){.zones{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: HubDataLayer, selector: "hub-data-layer", inputs: ["visible", "name", "desc", "icon", "shape"], outputs: ["onCustomize", "onCheck"] }, { kind: "directive", type: DraggableDialogDirective, selector: "dialog[draggable]" }, { kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }, { kind: "directive", type: BringToFrontDirective, selector: "[mapagBringToFront]" }, { kind: "component", type: TileDialog, selector: "mapag-tile-dialog", inputs: ["data", "name", "contentTemplate"], outputs: ["onSelect"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27438
27725
  }
27439
27726
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MMPanel, decorators: [{
27440
27727
  type: Component,
27441
- args: [{ selector: 'mapag-mm-panel', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, HubDataLayer, DraggableDialogDirective, FaIconComponent, BringToFrontDirective], template: `
27728
+ args: [{ selector: 'mapag-mm-panel', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, HubDataLayer, DraggableDialogDirective, FaIconComponent, BringToFrontDirective, TileDialog], template: `
27442
27729
  <hub-data-layer [visible]="mapper.settings().visible" [name]="mapper.settings().name"
27443
27730
  [desc]="mapper.settings().description || 'MarketMaker Business'" shape="point" (onCheck)="setVisible($event)" (onCustomize)="toggleDialog()">
27444
27731
 
@@ -27579,6 +27866,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
27579
27866
  </div>
27580
27867
  <div class="dlg-buttons">
27581
27868
  <button class="btn" (click)="toggleLegend()">Legend</button>
27869
+ <button class="btn" (click)="dataDialog.toggle()">Data</button>
27582
27870
  <button class="btn" (click)="remove()">Remove</button>
27583
27871
  <button class="btn" (click)="reset()">Reset</button>
27584
27872
  <button class="btn" (click)="toggleShowHide()">
@@ -27588,6 +27876,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
27588
27876
  <button class="btn" (click)="toggleDialog()">Close</button>
27589
27877
  </div>
27590
27878
  </dialog>
27879
+
27880
+ <ng-template #dataTemplate let-feature>
27881
+ <div [innerHTML]="mapper.popupRenderer?.RenderPopup(feature) | async"></div>
27882
+ </ng-template>
27883
+ <mapag-tile-dialog
27884
+ #dataDialog
27885
+ [data]="mapper.data()"
27886
+ [name]="mapper.settings().name"
27887
+ [contentTemplate]="dataTemplate"
27888
+ (onSelect)="onSelect($event)">
27889
+ </mapag-tile-dialog>
27591
27890
  `, styles: ["dialog{font-size:14pt;width:100%;max-width:700px;border:none;border-radius:8px;box-shadow:0 2px 10px #0003;padding:16px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;flex-direction:column}dialog:open{display:flex}dialog .dlg-body{flex-grow:1;overflow-y:auto}dialog.legend{width:fit-content}dialog.legend h2{font-size:smaller}dialog select{max-width:90vw}dialog h2{color:#000}dialog h2:before{content:\"\\22ee\\22ee \";padding-right:4px}dialog h3{color:#000;border-bottom:2px solid gray;font-weight:500;font-size:.9em;margin-top:16px;margin-bottom:8px}dialog h4{color:#000;font-weight:500;margin-bottom:8px;margin-top:12px;font-size:.85em;border:none}dialog p{font-size:.8em}dialog a{text-decoration:none;color:#0a3773;font-weight:500;font-size:.8em;padding-left:4px}dialog a:hover{text-decoration:underline;cursor:pointer}dialog a:before{content:\"\\1f517\";padding-right:2px}.ctrl-group{display:flex;flex-direction:column}.ctrl-row{display:grid;grid-template-columns:auto 1fr auto 1fr;align-items:center;gap:4px;justify-items:start;padding-left:20px}.ctrl-first{grid-column:1}.ctrl-row label{font-size:.8em;margin:0;padding:0;font-weight:400}.ctrl.wide{grid-column:span 3}input[type=range]{grid-column:span 3;justify-self:stretch}input[type=color]{width:40px;height:24px;border-radius:4px;cursor:pointer}input[type=number]{width:6ch;font-size:.8em}.dlg-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button{background-color:#0a3773;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:.8em}button:hover{background-color:#083a5c}summary{font-size:1em;font-weight:600;color:#000;cursor:pointer;padding:8px 0;border-bottom:2px solid gray;list-style:none;-webkit-user-select:none;user-select:none;margin-bottom:8px}summary::-webkit-details-marker{display:none}summary:before{content:\"\\304f\";display:inline-block;margin-right:8px;transform:rotate(180deg);transition:transform .2s}details[open] summary:before{transform:rotate(270deg)}.radio-tabs{margin-bottom:12px;font-size:.8em;display:flex;flex-direction:row}.radio-tabs label{display:grid;grid-template-columns:auto 1fr;gap:4px;grid-template-rows:30px;align-items:center}.radio-tabs input[type=radio]{display:none}.radio-tabs label{padding:8px 12px;border:2px solid transparent;border-radius:6px;cursor:pointer;transition:all .2s ease}.radio-tabs label:has(input[type=radio]:checked){background-color:#fff;border-color:#333}.mgr-btn{justify-self:center;background-color:transparent;color:#4c4c4c;text-align:center;width:100%;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:4px 0;padding:6px;gap:4px;border:1px solid rgb(218,218,218)}.mgr-btn:hover{background-color:transparent;border-color:#4c4c4c}.legend-row{display:grid;grid-template-columns:auto 1fr;gap:8px;padding:4px 0;align-items:center}.legend-title{font-weight:700;text-align:center;margin-bottom:8px}.legend-item{height:15px;width:15px;border:1px solid #ccc}.maplibregl-popup-close-button{top:13px;right:15px}@media screen and (max-width: 600px){dialog{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:none;box-shadow:none;overflow:hidden}.dlg-buttons{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center}dialog h2:before{content:\"\";padding-right:0}}::deep .ng-select-container,::deep .ng-select{font-size:.8em}.filter-row{display:flex;flex-direction:column;margin-bottom:8px;font-size:.8em}.filter-row-cols{display:block;column-count:2}.zone{display:flex;align-items:center;gap:8px;margin:0;padding:0}.zones{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;row-gap:8px;overflow-y:auto;max-height:420px;font-size:.8em}.svgicon{height:30px;width:30px;-webkit-mask-size:contain;mask-size:contain}h4,label{display:flex;align-items:center;gap:4px}@media (max-width: 600px){.zones{grid-template-columns:1fr}}\n"] }]
27592
27891
  }], ctorParameters: () => [], propDecorators: { map: [{ type: i0.Input, args: [{ isSignal: true, alias: "map", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], customizeDialog: [{ type: i0.ViewChild, args: ['customizeDialog', { isSignal: true }] }], onRemove: [{ type: i0.Output, args: ["onRemove"] }] } });
27593
27892
  class MarketMakerPopupRenderer {
@@ -27677,6 +27976,7 @@ class HubNaicsPanel {
27677
27976
  map = input(...(ngDevMode ? [undefined, { debugName: "map" }] : []));
27678
27977
  mapper = new NaicsMapper();
27679
27978
  customizeDialog = viewChild('customizeDialog', ...(ngDevMode ? [{ debugName: "customizeDialog" }] : []));
27979
+ dataDialog = viewChild('dataDialog', ...(ngDevMode ? [{ debugName: "dataDialog" }] : []));
27680
27980
  onRemove = output();
27681
27981
  style = computed(() => {
27682
27982
  const sel = this.mapper.settings().type;
@@ -27750,6 +28050,20 @@ class HubNaicsPanel {
27750
28050
  }
27751
28051
  // Implement dialog toggle logic here
27752
28052
  }
28053
+ toggleData() {
28054
+ const dialog = this.dataDialog();
28055
+ if (!dialog) {
28056
+ return;
28057
+ }
28058
+ const dialogElement = dialog.nativeElement;
28059
+ if (dialogElement.open) {
28060
+ dialogElement.close();
28061
+ }
28062
+ else {
28063
+ dialogElement.show();
28064
+ }
28065
+ // Implement dialog toggle logic here
28066
+ }
27753
28067
  toggleLegend() {
27754
28068
  if (!this.parent) {
27755
28069
  return;
@@ -27772,6 +28086,7 @@ class HubNaicsPanel {
27772
28086
  ngOnDestroy() {
27773
28087
  this.mapper.clear();
27774
28088
  }
28089
+ trackById = (_, item) => item.id;
27775
28090
  updateFilter(filter, value, checked) {
27776
28091
  const settings = this.mapper.settings();
27777
28092
  let currentValues = [];
@@ -27798,8 +28113,12 @@ class HubNaicsPanel {
27798
28113
  this.update('filterEmployees', currentValues);
27799
28114
  }
27800
28115
  }
28116
+ // Open the "data" dialog in a new window and keep it in sync with the main window by using
28117
+ // broadcast channel
28118
+ newWindow() {
28119
+ }
27801
28120
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: HubNaicsPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
27802
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: HubNaicsPanel, isStandalone: true, selector: "hub-naics-panel", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, map: { classPropertyName: "map", publicName: "map", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onRemove: "onRemove" }, viewQueries: [{ propertyName: "customizeDialog", first: true, predicate: ["customizeDialog"], descendants: true, isSignal: true }], ngImport: i0, template: `
28121
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: HubNaicsPanel, isStandalone: true, selector: "hub-naics-panel", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, map: { classPropertyName: "map", publicName: "map", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onRemove: "onRemove" }, viewQueries: [{ propertyName: "customizeDialog", first: true, predicate: ["customizeDialog"], descendants: true, isSignal: true }, { propertyName: "dataDialog", first: true, predicate: ["dataDialog"], descendants: true, isSignal: true }], ngImport: i0, template: `
27803
28122
  <hub-data-layer [visible]="mapper.settings().visible" [name]="mapper.settings().Name||' '"
27804
28123
  [desc]="'NAICS Code ' + mapper.settings().ID" shape="point" (onCheck)="setVisible($event)" (onCustomize)="toggleDialog()">
27805
28124
 
@@ -27968,6 +28287,7 @@ class HubNaicsPanel {
27968
28287
  @if (parent) {
27969
28288
  <button class="btn" (click)="toggleLegend()">Legend</button>
27970
28289
  }
28290
+ <button class="btn" (click)="toggleData()">Data</button>
27971
28291
  <button class="btn" (click)="remove()">Remove</button>
27972
28292
  <button class="btn" (click)="reset()">Reset</button>
27973
28293
  <button class="btn" (click)="toggleShowHide()">
@@ -27977,11 +28297,28 @@ class HubNaicsPanel {
27977
28297
  <button class="btn" (click)="toggleDialog()">Close</button>
27978
28298
  </div>
27979
28299
  </dialog>
27980
- `, isInline: true, styles: ["dialog{font-size:14pt;width:100%;max-width:700px;border:none;border-radius:8px;box-shadow:0 2px 10px #0003;padding:16px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;flex-direction:column}dialog:open{display:flex}dialog .dlg-body{flex-grow:1;overflow-y:auto}dialog.legend{width:fit-content}dialog.legend h2{font-size:smaller}dialog select{max-width:90vw}dialog h2{color:#000}dialog h2:before{content:\"\\22ee\\22ee \";padding-right:4px}dialog h3{color:#000;border-bottom:2px solid gray;font-weight:500;font-size:.9em;margin-top:16px;margin-bottom:8px}dialog h4{color:#000;font-weight:500;margin-bottom:8px;margin-top:12px;font-size:.85em;border:none}dialog p{font-size:.8em}dialog a{text-decoration:none;color:#0a3773;font-weight:500;font-size:.8em;padding-left:4px}dialog a:hover{text-decoration:underline;cursor:pointer}dialog a:before{content:\"\\1f517\";padding-right:2px}.ctrl-group{display:flex;flex-direction:column}.ctrl-row{display:grid;grid-template-columns:auto 1fr auto 1fr;align-items:center;gap:4px;justify-items:start;padding-left:20px}.ctrl-first{grid-column:1}.ctrl-row label{font-size:.8em;margin:0;padding:0;font-weight:400}.ctrl.wide{grid-column:span 3}input[type=range]{grid-column:span 3;justify-self:stretch}input[type=color]{width:40px;height:24px;border-radius:4px;cursor:pointer}input[type=number]{width:6ch;font-size:.8em}.dlg-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button{background-color:#0a3773;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:.8em}button:hover{background-color:#083a5c}summary{font-size:1em;font-weight:600;color:#000;cursor:pointer;padding:8px 0;border-bottom:2px solid gray;list-style:none;-webkit-user-select:none;user-select:none;margin-bottom:8px}summary::-webkit-details-marker{display:none}summary:before{content:\"\\304f\";display:inline-block;margin-right:8px;transform:rotate(180deg);transition:transform .2s}details[open] summary:before{transform:rotate(270deg)}.radio-tabs{margin-bottom:12px;font-size:.8em;display:flex;flex-direction:row}.radio-tabs label{display:grid;grid-template-columns:auto 1fr;gap:4px;grid-template-rows:30px;align-items:center}.radio-tabs input[type=radio]{display:none}.radio-tabs label{padding:8px 12px;border:2px solid transparent;border-radius:6px;cursor:pointer;transition:all .2s ease}.radio-tabs label:has(input[type=radio]:checked){background-color:#fff;border-color:#333}.mgr-btn{justify-self:center;background-color:transparent;color:#4c4c4c;text-align:center;width:100%;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:4px 0;padding:6px;gap:4px;border:1px solid rgb(218,218,218)}.mgr-btn:hover{background-color:transparent;border-color:#4c4c4c}.legend-row{display:grid;grid-template-columns:auto 1fr;gap:8px;padding:4px 0;align-items:center}.legend-title{font-weight:700;text-align:center;margin-bottom:8px}.legend-item{height:15px;width:15px;border:1px solid #ccc}.maplibregl-popup-close-button{top:13px;right:15px}@media screen and (max-width: 600px){dialog{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:none;box-shadow:none;overflow:hidden}.dlg-buttons{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center}dialog h2:before{content:\"\";padding-right:0}}::deep .ng-select-container,::deep .ng-select{font-size:.8em}.filter-row{display:flex;flex-direction:column;margin-bottom:8px;font-size:.8em}.filter-row-cols{display:block;column-count:2}.zone{display:flex;align-items:center;gap:8px;margin:0;padding:0}.zones{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;row-gap:8px;overflow-y:auto;max-height:420px;font-size:.8em}.svgicon{height:30px;width:30px;-webkit-mask-size:contain;mask-size:contain}h4,label{display:flex;align-items:center;gap:4px}@media (max-width: 600px){.zones{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: HubDataLayer, selector: "hub-data-layer", inputs: ["visible", "name", "desc", "icon", "shape"], outputs: ["onCustomize", "onCheck"] }, { kind: "directive", type: DraggableDialogDirective, selector: "dialog[draggable]" }, { kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }, { kind: "directive", type: BringToFrontDirective, selector: "[mapagBringToFront]" }, { kind: "component", type: NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "appearance", "ariaLabelDropdown", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "tabFocusOnClearButton", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["bindLabelChange", "bindValueChange", "appearanceChange", "isOpenChange", "blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd", "itemsChange"] }, { kind: "directive", type: OnBodyDirective, selector: "dialog[onBody]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
28300
+
28301
+ <dialog draggable mapagBringToFront onBody #dataDialog class="data-dialog">
28302
+ <h2>{{mapper.settings().Name}}</h2>
28303
+ <div class="dlg-body dlg-body-list ">
28304
+ {{ mapper.data().length }} records matching current filters.
28305
+ <cdk-virtual-scroll-viewport [itemSize]="10">
28306
+ <div *cdkVirtualFor="let feature of mapper.data()" (click)="mapper.flyToFeature(feature)"
28307
+ class="data-tile" [innerHTML]="mapper.renderPopup(feature)">
28308
+ </div>
28309
+
28310
+ </cdk-virtual-scroll-viewport>
28311
+ </div>
28312
+ <div class="dlg-buttons">
28313
+ <button class="btn" (click)="toggleData()">Close</button>
28314
+ </div>
28315
+ </dialog>
28316
+ `, isInline: true, styles: ["dialog{font-size:14pt;width:100%;max-width:700px;border:none;border-radius:8px;box-shadow:0 2px 10px #0003;padding:16px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;flex-direction:column}dialog:open{display:flex}dialog .dlg-body{flex-grow:1;overflow-y:auto}dialog.legend{width:fit-content}dialog.legend h2{font-size:smaller}dialog select{max-width:90vw}dialog h2{color:#000}dialog h2:before{content:\"\\22ee\\22ee \";padding-right:4px}dialog h3{color:#000;border-bottom:2px solid gray;font-weight:500;font-size:.9em;margin-top:16px;margin-bottom:8px}dialog h4{color:#000;font-weight:500;margin-bottom:8px;margin-top:12px;font-size:.85em;border:none}dialog p{font-size:.8em}dialog a{text-decoration:none;color:#0a3773;font-weight:500;font-size:.8em;padding-left:4px}dialog a:hover{text-decoration:underline;cursor:pointer}dialog a:before{content:\"\\1f517\";padding-right:2px}.ctrl-group{display:flex;flex-direction:column}.ctrl-row{display:grid;grid-template-columns:auto 1fr auto 1fr;align-items:center;gap:4px;justify-items:start;padding-left:20px}.ctrl-first{grid-column:1}.ctrl-row label{font-size:.8em;margin:0;padding:0;font-weight:400}.ctrl.wide{grid-column:span 3}input[type=range]{grid-column:span 3;justify-self:stretch}input[type=color]{width:40px;height:24px;border-radius:4px;cursor:pointer}input[type=number]{width:6ch;font-size:.8em}.dlg-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button{background-color:#0a3773;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:.8em}button:hover{background-color:#083a5c}summary{font-size:1em;font-weight:600;color:#000;cursor:pointer;padding:8px 0;border-bottom:2px solid gray;list-style:none;-webkit-user-select:none;user-select:none;margin-bottom:8px}summary::-webkit-details-marker{display:none}summary:before{content:\"\\304f\";display:inline-block;margin-right:8px;transform:rotate(180deg);transition:transform .2s}details[open] summary:before{transform:rotate(270deg)}.radio-tabs{margin-bottom:12px;font-size:.8em;display:flex;flex-direction:row}.radio-tabs label{display:grid;grid-template-columns:auto 1fr;gap:4px;grid-template-rows:30px;align-items:center}.radio-tabs input[type=radio]{display:none}.radio-tabs label{padding:8px 12px;border:2px solid transparent;border-radius:6px;cursor:pointer;transition:all .2s ease}.radio-tabs label:has(input[type=radio]:checked){background-color:#fff;border-color:#333}.mgr-btn{justify-self:center;background-color:transparent;color:#4c4c4c;text-align:center;width:100%;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:4px 0;padding:6px;gap:4px;border:1px solid rgb(218,218,218)}.mgr-btn:hover{background-color:transparent;border-color:#4c4c4c}.legend-row{display:grid;grid-template-columns:auto 1fr;gap:8px;padding:4px 0;align-items:center}.legend-title{font-weight:700;text-align:center;margin-bottom:8px}.legend-item{height:15px;width:15px;border:1px solid #ccc}.maplibregl-popup-close-button{top:13px;right:15px}@media screen and (max-width: 600px){dialog{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:none;box-shadow:none;overflow:hidden}.dlg-buttons{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center}dialog h2:before{content:\"\";padding-right:0}}::deep .ng-select-container,::deep .ng-select{font-size:.8em}.dlg-body-list{display:grid;grid-template-rows:auto 1fr;row-gap:12px}.data-dialog{width:auto;max-width:min(450px,100vw);height:90dvh}.filter-row{display:flex;flex-direction:column;margin-bottom:8px;font-size:.8em}.filter-row-cols{display:block;column-count:2}.zone{display:flex;align-items:center;gap:8px;margin:0;padding:0}.zones{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;row-gap:8px;overflow-y:auto;max-height:420px;font-size:.8em}.data-viewport{height:360px;width:100%;border:1px solid #ccc;border-radius:6px;background:#fff}.data-tile{padding:6px;border:1px solid #ccc;margin:4px;font-size:10pt;box-shadow:0 2px 4px #0000001a}.data-tile:last-child{border-bottom:none}.tile-title{font-weight:600;color:#222}.tile-sub{color:#555;font-size:.85em}.svgicon{height:30px;width:30px;-webkit-mask-size:contain;mask-size:contain}h4,label{display:flex;align-items:center;gap:4px}@media (max-width: 600px){.zones{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: HubDataLayer, selector: "hub-data-layer", inputs: ["visible", "name", "desc", "icon", "shape"], outputs: ["onCustomize", "onCheck"] }, { kind: "directive", type: DraggableDialogDirective, selector: "dialog[draggable]" }, { kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }, { kind: "directive", type: BringToFrontDirective, selector: "[mapagBringToFront]" }, { kind: "component", type: NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "appearance", "ariaLabelDropdown", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "tabFocusOnClearButton", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick", "keyDownFn"], outputs: ["bindLabelChange", "bindValueChange", "appearanceChange", "isOpenChange", "blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd", "itemsChange"] }, { kind: "directive", type: OnBodyDirective, selector: "dialog[onBody]" }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
27981
28317
  }
27982
28318
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: HubNaicsPanel, decorators: [{
27983
28319
  type: Component,
27984
- args: [{ selector: 'hub-naics-panel', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, HubDataLayer, DraggableDialogDirective, FaIconComponent, BringToFrontDirective, NgSelectComponent, OnBodyDirective], template: `
28320
+ args: [{ selector: 'hub-naics-panel', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, HubDataLayer, DraggableDialogDirective, FaIconComponent,
28321
+ BringToFrontDirective, NgSelectComponent, OnBodyDirective, CdkVirtualScrollViewport, CdkVirtualForOf, CdkFixedSizeVirtualScroll], template: `
27985
28322
  <hub-data-layer [visible]="mapper.settings().visible" [name]="mapper.settings().Name||' '"
27986
28323
  [desc]="'NAICS Code ' + mapper.settings().ID" shape="point" (onCheck)="setVisible($event)" (onCustomize)="toggleDialog()">
27987
28324
 
@@ -28150,6 +28487,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
28150
28487
  @if (parent) {
28151
28488
  <button class="btn" (click)="toggleLegend()">Legend</button>
28152
28489
  }
28490
+ <button class="btn" (click)="toggleData()">Data</button>
28153
28491
  <button class="btn" (click)="remove()">Remove</button>
28154
28492
  <button class="btn" (click)="reset()">Reset</button>
28155
28493
  <button class="btn" (click)="toggleShowHide()">
@@ -28159,8 +28497,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
28159
28497
  <button class="btn" (click)="toggleDialog()">Close</button>
28160
28498
  </div>
28161
28499
  </dialog>
28162
- `, styles: ["dialog{font-size:14pt;width:100%;max-width:700px;border:none;border-radius:8px;box-shadow:0 2px 10px #0003;padding:16px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;flex-direction:column}dialog:open{display:flex}dialog .dlg-body{flex-grow:1;overflow-y:auto}dialog.legend{width:fit-content}dialog.legend h2{font-size:smaller}dialog select{max-width:90vw}dialog h2{color:#000}dialog h2:before{content:\"\\22ee\\22ee \";padding-right:4px}dialog h3{color:#000;border-bottom:2px solid gray;font-weight:500;font-size:.9em;margin-top:16px;margin-bottom:8px}dialog h4{color:#000;font-weight:500;margin-bottom:8px;margin-top:12px;font-size:.85em;border:none}dialog p{font-size:.8em}dialog a{text-decoration:none;color:#0a3773;font-weight:500;font-size:.8em;padding-left:4px}dialog a:hover{text-decoration:underline;cursor:pointer}dialog a:before{content:\"\\1f517\";padding-right:2px}.ctrl-group{display:flex;flex-direction:column}.ctrl-row{display:grid;grid-template-columns:auto 1fr auto 1fr;align-items:center;gap:4px;justify-items:start;padding-left:20px}.ctrl-first{grid-column:1}.ctrl-row label{font-size:.8em;margin:0;padding:0;font-weight:400}.ctrl.wide{grid-column:span 3}input[type=range]{grid-column:span 3;justify-self:stretch}input[type=color]{width:40px;height:24px;border-radius:4px;cursor:pointer}input[type=number]{width:6ch;font-size:.8em}.dlg-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button{background-color:#0a3773;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:.8em}button:hover{background-color:#083a5c}summary{font-size:1em;font-weight:600;color:#000;cursor:pointer;padding:8px 0;border-bottom:2px solid gray;list-style:none;-webkit-user-select:none;user-select:none;margin-bottom:8px}summary::-webkit-details-marker{display:none}summary:before{content:\"\\304f\";display:inline-block;margin-right:8px;transform:rotate(180deg);transition:transform .2s}details[open] summary:before{transform:rotate(270deg)}.radio-tabs{margin-bottom:12px;font-size:.8em;display:flex;flex-direction:row}.radio-tabs label{display:grid;grid-template-columns:auto 1fr;gap:4px;grid-template-rows:30px;align-items:center}.radio-tabs input[type=radio]{display:none}.radio-tabs label{padding:8px 12px;border:2px solid transparent;border-radius:6px;cursor:pointer;transition:all .2s ease}.radio-tabs label:has(input[type=radio]:checked){background-color:#fff;border-color:#333}.mgr-btn{justify-self:center;background-color:transparent;color:#4c4c4c;text-align:center;width:100%;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:4px 0;padding:6px;gap:4px;border:1px solid rgb(218,218,218)}.mgr-btn:hover{background-color:transparent;border-color:#4c4c4c}.legend-row{display:grid;grid-template-columns:auto 1fr;gap:8px;padding:4px 0;align-items:center}.legend-title{font-weight:700;text-align:center;margin-bottom:8px}.legend-item{height:15px;width:15px;border:1px solid #ccc}.maplibregl-popup-close-button{top:13px;right:15px}@media screen and (max-width: 600px){dialog{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:none;box-shadow:none;overflow:hidden}.dlg-buttons{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center}dialog h2:before{content:\"\";padding-right:0}}::deep .ng-select-container,::deep .ng-select{font-size:.8em}.filter-row{display:flex;flex-direction:column;margin-bottom:8px;font-size:.8em}.filter-row-cols{display:block;column-count:2}.zone{display:flex;align-items:center;gap:8px;margin:0;padding:0}.zones{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;row-gap:8px;overflow-y:auto;max-height:420px;font-size:.8em}.svgicon{height:30px;width:30px;-webkit-mask-size:contain;mask-size:contain}h4,label{display:flex;align-items:center;gap:4px}@media (max-width: 600px){.zones{grid-template-columns:1fr}}\n"] }]
28163
- }], ctorParameters: () => [], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], map: [{ type: i0.Input, args: [{ isSignal: true, alias: "map", required: false }] }], customizeDialog: [{ type: i0.ViewChild, args: ['customizeDialog', { isSignal: true }] }], onRemove: [{ type: i0.Output, args: ["onRemove"] }] } });
28500
+
28501
+ <dialog draggable mapagBringToFront onBody #dataDialog class="data-dialog">
28502
+ <h2>{{mapper.settings().Name}}</h2>
28503
+ <div class="dlg-body dlg-body-list ">
28504
+ {{ mapper.data().length }} records matching current filters.
28505
+ <cdk-virtual-scroll-viewport [itemSize]="10">
28506
+ <div *cdkVirtualFor="let feature of mapper.data()" (click)="mapper.flyToFeature(feature)"
28507
+ class="data-tile" [innerHTML]="mapper.renderPopup(feature)">
28508
+ </div>
28509
+
28510
+ </cdk-virtual-scroll-viewport>
28511
+ </div>
28512
+ <div class="dlg-buttons">
28513
+ <button class="btn" (click)="toggleData()">Close</button>
28514
+ </div>
28515
+ </dialog>
28516
+ `, styles: ["dialog{font-size:14pt;width:100%;max-width:700px;border:none;border-radius:8px;box-shadow:0 2px 10px #0003;padding:16px;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);margin:0;flex-direction:column}dialog:open{display:flex}dialog .dlg-body{flex-grow:1;overflow-y:auto}dialog.legend{width:fit-content}dialog.legend h2{font-size:smaller}dialog select{max-width:90vw}dialog h2{color:#000}dialog h2:before{content:\"\\22ee\\22ee \";padding-right:4px}dialog h3{color:#000;border-bottom:2px solid gray;font-weight:500;font-size:.9em;margin-top:16px;margin-bottom:8px}dialog h4{color:#000;font-weight:500;margin-bottom:8px;margin-top:12px;font-size:.85em;border:none}dialog p{font-size:.8em}dialog a{text-decoration:none;color:#0a3773;font-weight:500;font-size:.8em;padding-left:4px}dialog a:hover{text-decoration:underline;cursor:pointer}dialog a:before{content:\"\\1f517\";padding-right:2px}.ctrl-group{display:flex;flex-direction:column}.ctrl-row{display:grid;grid-template-columns:auto 1fr auto 1fr;align-items:center;gap:4px;justify-items:start;padding-left:20px}.ctrl-first{grid-column:1}.ctrl-row label{font-size:.8em;margin:0;padding:0;font-weight:400}.ctrl.wide{grid-column:span 3}input[type=range]{grid-column:span 3;justify-self:stretch}input[type=color]{width:40px;height:24px;border-radius:4px;cursor:pointer}input[type=number]{width:6ch;font-size:.8em}.dlg-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}button{background-color:#0a3773;color:#fff;border:none;border-radius:4px;padding:8px 16px;cursor:pointer;font-size:.8em}button:hover{background-color:#083a5c}summary{font-size:1em;font-weight:600;color:#000;cursor:pointer;padding:8px 0;border-bottom:2px solid gray;list-style:none;-webkit-user-select:none;user-select:none;margin-bottom:8px}summary::-webkit-details-marker{display:none}summary:before{content:\"\\304f\";display:inline-block;margin-right:8px;transform:rotate(180deg);transition:transform .2s}details[open] summary:before{transform:rotate(270deg)}.radio-tabs{margin-bottom:12px;font-size:.8em;display:flex;flex-direction:row}.radio-tabs label{display:grid;grid-template-columns:auto 1fr;gap:4px;grid-template-rows:30px;align-items:center}.radio-tabs input[type=radio]{display:none}.radio-tabs label{padding:8px 12px;border:2px solid transparent;border-radius:6px;cursor:pointer;transition:all .2s ease}.radio-tabs label:has(input[type=radio]:checked){background-color:#fff;border-color:#333}.mgr-btn{justify-self:center;background-color:transparent;color:#4c4c4c;text-align:center;width:100%;font-weight:600;cursor:pointer;display:flex;align-items:center;justify-content:center;margin:4px 0;padding:6px;gap:4px;border:1px solid rgb(218,218,218)}.mgr-btn:hover{background-color:transparent;border-color:#4c4c4c}.legend-row{display:grid;grid-template-columns:auto 1fr;gap:8px;padding:4px 0;align-items:center}.legend-title{font-weight:700;text-align:center;margin-bottom:8px}.legend-item{height:15px;width:15px;border:1px solid #ccc}.maplibregl-popup-close-button{top:13px;right:15px}@media screen and (max-width: 600px){dialog{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;border-radius:0;border:none;box-shadow:none;overflow:hidden}.dlg-buttons{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:center}dialog h2:before{content:\"\";padding-right:0}}::deep .ng-select-container,::deep .ng-select{font-size:.8em}.dlg-body-list{display:grid;grid-template-rows:auto 1fr;row-gap:12px}.data-dialog{width:auto;max-width:min(450px,100vw);height:90dvh}.filter-row{display:flex;flex-direction:column;margin-bottom:8px;font-size:.8em}.filter-row-cols{display:block;column-count:2}.zone{display:flex;align-items:center;gap:8px;margin:0;padding:0}.zones{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;row-gap:8px;overflow-y:auto;max-height:420px;font-size:.8em}.data-viewport{height:360px;width:100%;border:1px solid #ccc;border-radius:6px;background:#fff}.data-tile{padding:6px;border:1px solid #ccc;margin:4px;font-size:10pt;box-shadow:0 2px 4px #0000001a}.data-tile:last-child{border-bottom:none}.tile-title{font-weight:600;color:#222}.tile-sub{color:#555;font-size:.85em}.svgicon{height:30px;width:30px;-webkit-mask-size:contain;mask-size:contain}h4,label{display:flex;align-items:center;gap:4px}@media (max-width: 600px){.zones{grid-template-columns:1fr}}\n"] }]
28517
+ }], ctorParameters: () => [], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], map: [{ type: i0.Input, args: [{ isSignal: true, alias: "map", required: false }] }], customizeDialog: [{ type: i0.ViewChild, args: ['customizeDialog', { isSignal: true }] }], dataDialog: [{ type: i0.ViewChild, args: ['dataDialog', { isSignal: true }] }], onRemove: [{ type: i0.Output, args: ["onRemove"] }] } });
28164
28518
 
28165
28519
  class NaicsMgrPanel {
28166
28520
  faCircle = faCircle;
@@ -30492,6 +30846,12 @@ class WelcomePanel {
30492
30846
  be moved around the screen by dragging their title bars.
30493
30847
  </p>
30494
30848
 
30849
+ <h3>Feedback</h3>
30850
+ <p>
30851
+ We value your feedback to improve this tool. Please reach out to us with any comments, questions,
30852
+ or suggestions by using the <a href=" https://forms.gle/b8DHfcEe44XPChE18" target="_blank" class="btn">feedback form.</a>
30853
+ </p>
30854
+
30495
30855
  <h3>References</h3>
30496
30856
  <div style="display: flex; flex-direction: column;">
30497
30857
  <a href="https://foodmarketmaker.com" target="_blank">Food MarketMaker</a>
@@ -30551,6 +30911,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
30551
30911
  be moved around the screen by dragging their title bars.
30552
30912
  </p>
30553
30913
 
30914
+ <h3>Feedback</h3>
30915
+ <p>
30916
+ We value your feedback to improve this tool. Please reach out to us with any comments, questions,
30917
+ or suggestions by using the <a href=" https://forms.gle/b8DHfcEe44XPChE18" target="_blank" class="btn">feedback form.</a>
30918
+ </p>
30919
+
30554
30920
  <h3>References</h3>
30555
30921
  <div style="display: flex; flex-direction: column;">
30556
30922
  <a href="https://foodmarketmaker.com" target="_blank">Food MarketMaker</a>
@@ -30587,5 +30953,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
30587
30953
  * Generated bundle index. Do not edit.
30588
30954
  */
30589
30955
 
30590
- export { AddLayer, AddSource, AreaIcon, AreaMapperMapper, BackgroundMaskMapper, BackgroundMaskSettings, BaseMapLight, BasemapSelect, BasemapSelectMenu, BringToFrontDirective, BringToFrontService, CensusTractMapper, Codes, CropSequenceMapper, CropSequenceSettings, CroplandDataLayerMapper, CroplandDataLayerSettings, CroplandLegend, DEFAULT_GLYPHS, DEFAULT_GLYPHS2, DEFAULT_PIN_URL, DataSetFieldValue, DirectoryIndexPToTable, DirectoryIndexToTable, DraggableDialogDirective, DrawPolygon, DrawSquare, DrawingMapper, EsriMapper, EsriSettings, ExpandArrows, FilterPanel, FipsFromDataSet, FoodHubPanel, FoodhubMapper, FoodhubMapperSettings, HardinessMapper, HardinessSettings, HttpBoundaryLoader, HubCropSequencePanel, HubCroplandPanel, HubDataLayer, HubHardinessPanel, HubNaicsPanel, HubRailroadPanel, HubWatershedPanel, Icons, LineIcon, MMPanel, MapAreaSelectComponent, MapComponent, MapSelectionService, MapService, MapStyles, MapagDetails, MapboxMapperGroup, MarketMakerPopupRenderer, NAASMapper, NAASSettings, NASSInfo, NaicsEmployeesOptions, NaicsMapper, NaicsMapperSettings, NaicsMgrPanel, NaicsSalesOptions, NassIndex, NassInfoFromIndex, NassInfoFromIndexP, NassInfoFromPath, NassMgrPanel, NassPanel, NassService, NoOpMapper, PaletteDisplay, PaletteSelect, PointDataMapper, PointDataMapperSettings, PrintPanel, RailroadSettings, RailroadUsageSettings, RailroadsMapper, RasterIcon, ReferenceDataService, RemoveLayer, RemoveSource, SaveMap, SelectMode, SettingsPanel, SimpleMapper, StandardLayersMapper, StateCountySelectComponent, Styles, TableBuilder, TableRow, VectorTileServerMapper, WatershedMapper, WatershedSettings, WelcomePanel, discoverLayers, fixText, isGeoloader, isMultiPolygon, isNumber2DArray, isNumber3DArray, isPolygon, mapboxImageName, mapboxLoadImages, mapboxloadImage, normalize, normalizeArray, pmtilesPixelInfo, prefixMatch, propertiesToTableHtml, randomColor, sampleTilesForLayers, simpleClone, toMultiPolygon, trySync };
30956
+ export { AddLayer, AddSource, AreaIcon, AreaMapperMapper, BackgroundMaskMapper, BackgroundMaskSettings, BaseMapLight, BasemapSelect, BasemapSelectMenu, BringToFrontDirective, BringToFrontService, CensusTractMapper, Codes, CropSequenceMapper, CropSequenceSettings, CroplandDataLayerMapper, CroplandDataLayerSettings, CroplandLegend, DEFAULT_GLYPHS, DEFAULT_GLYPHS2, DEFAULT_PIN_URL, DataSetFieldValue, DirectoryIndexPToTable, DirectoryIndexToTable, DraggableDialogDirective, DrawPolygon, DrawSquare, DrawingMapper, EsriMapper, EsriSettings, ExpandArrows, FilterPanel, FipsFromDataSet, FoodHubPanel, FoodhubMapper, FoodhubMapperSettings, HardinessMapper, HardinessSettings, HttpBoundaryLoader, HubCropSequencePanel, HubCroplandPanel, HubDataLayer, HubHardinessPanel, HubNaicsPanel, HubRailroadPanel, HubWatershedPanel, Icons, LineIcon, MMPanel, MapAreaSelectComponent, MapComponent, MapSelectionService, MapService, MapStyles, MapagDetails, MapboxMapperGroup, MarketMakerPopupRenderer, NAASMapper, NAASSettings, NASSInfo, NaicsEmployeesOptions, NaicsMapper, NaicsMapperSettings, NaicsMgrPanel, NaicsSalesOptions, NassIndex, NassInfoFromIndex, NassInfoFromIndexP, NassInfoFromPath, NassMgrPanel, NassPanel, NassService, NoOpMapper, PaletteDisplay, PaletteSelect, PointDataMapper, PointDataMapperSettings, PrintPanel, RailroadSettings, RailroadUsageSettings, RailroadsMapper, RasterIcon, ReferenceDataService, RemoveLayer, RemoveSource, SaveMap, SelectMode, SettingsPanel, SimpleMapper, SourceLoadWatcher, StandardLayersMapper, StateCountySelectComponent, Styles, TableBuilder, TableRow, VectorTileServerMapper, WatershedMapper, WatershedSettings, WelcomePanel, discoverLayers, fixText, isGeoloader, isMultiPolygon, isNumber2DArray, isNumber3DArray, isPolygon, mapboxImageName, mapboxLoadImages, mapboxloadImage, normalize, normalizeArray, pmtilesPixelInfo, prefixMatch, propertiesToTableHtml, randomColor, sampleTilesForLayers, simpleClone, toMultiPolygon, trySync };
30591
30957
  //# sourceMappingURL=foodmarketmaker-mapag.mjs.map