@esri/solutions-components 0.6.32 → 0.6.33

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. package/dist/cjs/basemap-gallery_7.cjs.entry.js +14 -2
  2. package/dist/cjs/calcite-combobox_6.cjs.entry.js +1 -1
  3. package/dist/cjs/card-manager_3.cjs.entry.js +19 -11
  4. package/dist/cjs/crowdsource-manager.cjs.entry.js +7 -7
  5. package/dist/cjs/{downloadUtils-84024878.js → downloadUtils-b37689dd.js} +22 -2
  6. package/dist/cjs/{index.es-eb7cf427.js → index.es-83e253dc.js} +2 -2
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/cjs/map-select-tools_3.cjs.entry.js +2 -2
  9. package/dist/cjs/{mapViewUtils-786a219b.js → mapViewUtils-303bf42d.js} +1 -1
  10. package/dist/cjs/public-notification.cjs.entry.js +2 -2
  11. package/dist/cjs/solutions-components.cjs.js +1 -1
  12. package/dist/collection/components/crowdsource-manager/crowdsource-manager.css +8 -0
  13. package/dist/collection/components/crowdsource-manager/crowdsource-manager.js +6 -6
  14. package/dist/collection/components/floor-filter/floor-filter.js +2 -1
  15. package/dist/collection/components/layer-table/layer-table.js +13 -7
  16. package/dist/collection/components/map-card/map-card.css +5 -1
  17. package/dist/collection/components/map-card/map-card.js +20 -1
  18. package/dist/collection/components/map-tools/map-tools.js +15 -1
  19. package/dist/collection/utils/downloadUtils.js +20 -0
  20. package/dist/collection/utils/downloadUtils.ts +20 -0
  21. package/dist/collection/utils/queryUtils.js +1 -1
  22. package/dist/collection/utils/queryUtils.ts +1 -1
  23. package/dist/collection/utils/test/downloadUtils.spec.js +79 -5
  24. package/dist/collection/utils/test/downloadUtils.spec.tsx +84 -5
  25. package/dist/components/crowdsource-manager.js +7 -7
  26. package/dist/components/downloadUtils.js +20 -0
  27. package/dist/components/floor-filter2.js +2 -1
  28. package/dist/components/layer-table2.js +13 -7
  29. package/dist/components/map-card2.js +5 -2
  30. package/dist/components/map-tools2.js +14 -1
  31. package/dist/components/queryUtils.js +1 -1
  32. package/dist/esm/basemap-gallery_7.entry.js +14 -2
  33. package/dist/esm/calcite-combobox_6.entry.js +1 -1
  34. package/dist/esm/card-manager_3.entry.js +19 -11
  35. package/dist/esm/crowdsource-manager.entry.js +7 -7
  36. package/dist/esm/{downloadUtils-fa2b3718.js → downloadUtils-ddd7eeb7.js} +22 -2
  37. package/dist/esm/{index.es-cc671fd2.js → index.es-a53707d1.js} +2 -2
  38. package/dist/esm/loader.js +1 -1
  39. package/dist/esm/map-select-tools_3.entry.js +2 -2
  40. package/dist/esm/{mapViewUtils-8bfabd80.js → mapViewUtils-43c930f1.js} +1 -1
  41. package/dist/esm/public-notification.entry.js +2 -2
  42. package/dist/esm/solutions-components.js +1 -1
  43. package/dist/solutions-components/{p-e94c7cf2.js → p-05ba41f9.js} +1 -1
  44. package/dist/solutions-components/{p-ce3b40ca.entry.js → p-4792005c.entry.js} +1 -1
  45. package/dist/solutions-components/{p-86893d46.entry.js → p-50a3a887.entry.js} +1 -1
  46. package/dist/solutions-components/p-65ade5af.entry.js +6 -0
  47. package/dist/solutions-components/p-7b61f856.entry.js +6 -0
  48. package/dist/solutions-components/{p-190c83b9.entry.js → p-978a26b3.entry.js} +1 -1
  49. package/dist/solutions-components/p-a5342c42.entry.js +6 -0
  50. package/dist/solutions-components/{p-37a58e04.js → p-b745143d.js} +3 -3
  51. package/dist/solutions-components/{p-53bc5fc1.js → p-f2194390.js} +1 -1
  52. package/dist/solutions-components/solutions-components.esm.js +1 -1
  53. package/dist/solutions-components/utils/downloadUtils.ts +20 -0
  54. package/dist/solutions-components/utils/queryUtils.ts +1 -1
  55. package/dist/solutions-components/utils/test/downloadUtils.spec.tsx +84 -5
  56. package/dist/types/components/map-card/map-card.d.ts +4 -0
  57. package/dist/types/components/map-tools/map-tools.d.ts +8 -0
  58. package/dist/types/components.d.ts +8 -0
  59. package/package.json +1 -1
  60. package/dist/solutions-components/p-792e171f.entry.js +0 -6
  61. package/dist/solutions-components/p-d44ad6c4.entry.js +0 -6
  62. package/dist/solutions-components/p-f2dcb05a.entry.js +0 -6
@@ -331,26 +331,26 @@ export class LayerTable {
331
331
  func: () => this._selectAll(),
332
332
  label: this._translations.selectAll,
333
333
  disabled: false,
334
- isOverflow: true
334
+ isOverflow: false
335
335
  }, {
336
336
  icon: "compare",
337
337
  func: () => this._switchSelected(),
338
338
  label: this._translations.switchSelected,
339
339
  disabled: false,
340
- isOverflow: true
340
+ isOverflow: false
341
341
  }, {
342
342
  icon: "refresh",
343
343
  func: () => this._refresh(),
344
344
  label: this._translations.refresh,
345
345
  disabled: false,
346
- isOverflow: true
346
+ isOverflow: false
347
347
  },
348
348
  this.enableCSV ? {
349
349
  icon: "export",
350
350
  func: () => void this._exportToCSV(),
351
351
  label: this._translations.exportCSV,
352
352
  disabled: false,
353
- isOverflow: true
353
+ isOverflow: false
354
354
  } : undefined];
355
355
  this._defaultVisibleToolSizeInfos = undefined;
356
356
  }
@@ -394,14 +394,20 @@ export class LayerTable {
394
394
  prev.push(cur.id);
395
395
  return prev;
396
396
  }, []);
397
+ let forceFinish = false;
397
398
  const controlsThatFit = [...this._defaultVisibleToolSizeInfos].reduce((prev, cur) => {
398
- if (skipControls.indexOf(cur.id) < 0 &&
399
+ if (!forceFinish && skipControls.indexOf(cur.id) < 0 &&
399
400
  (currentTools.indexOf(cur.id) > -1 || (controlsWidth + cur.width) <= toolbarWidth)) {
400
401
  if (currentTools.indexOf(cur.id) < 0) {
401
402
  controlsWidth += cur.width;
402
403
  }
403
404
  prev.push(cur);
404
405
  }
406
+ else if (skipControls.indexOf(cur.id) < 0 && (controlsWidth + cur.width) > toolbarWidth) {
407
+ // exit the first time we evalute this as true...otherwise it will add the next control that will fit
408
+ // and not preserve the overall order of controls
409
+ forceFinish = true;
410
+ }
405
411
  return prev;
406
412
  }, []);
407
413
  this._setControlsThatFit(controlsThatFit, skipControls);
@@ -480,9 +486,9 @@ export class LayerTable {
480
486
  */
481
487
  _getDropdown(id) {
482
488
  const dropdownItems = this._getDropdownItems();
483
- return (h("calcite-dropdown", { disabled: this._layer === undefined, id: "solutions-more" }, h("calcite-action", { appearance: "solid", id: id, label: "", slot: "trigger", text: "" }, h("calcite-button", { appearance: "transparent", iconEnd: "chevron-down", kind: "neutral" }, this._translations.more)), h("calcite-dropdown-group", { "selection-mode": "none" }, dropdownItems.map(item => {
489
+ return dropdownItems.length > 0 ? (h("calcite-dropdown", { disabled: this._layer === undefined, id: "solutions-more" }, h("calcite-action", { appearance: "solid", id: id, label: "", slot: "trigger", text: "" }, h("calcite-button", { appearance: "transparent", iconEnd: "chevron-down", kind: "neutral" }, this._translations.more)), h("calcite-dropdown-group", { "selection-mode": "none" }, dropdownItems.map(item => {
484
490
  return (h("calcite-dropdown-item", { iconStart: item.icon, onClick: item.func }, item.label));
485
- }))));
491
+ })))) : undefined;
486
492
  }
487
493
  /**
488
494
  * Get a list of toolInfos that should display in the dropdown
@@ -21,9 +21,13 @@
21
21
  }
22
22
 
23
23
  .map-height {
24
- height: calc(100% - 58px);
24
+ height: calc(100% - 51px);
25
25
  }
26
26
 
27
27
  .box-shadow {
28
28
  box-shadow: none !important;
29
29
  }
30
+
31
+ .visibility-hidden {
32
+ visibility: hidden;
33
+ }
@@ -38,6 +38,7 @@ export class MapCard {
38
38
  this.enableSearch = undefined;
39
39
  this.enableBasemap = undefined;
40
40
  this.basemapConfig = undefined;
41
+ this.hidden = undefined;
41
42
  this.mapInfos = [];
42
43
  this.mapView = undefined;
43
44
  this._searchConfiguration = undefined;
@@ -64,7 +65,8 @@ export class MapCard {
64
65
  * Renders the component.
65
66
  */
66
67
  render() {
67
- return (h(Host, null, h("map-picker", { mapInfos: this.mapInfos }), h("div", { class: "map-height", ref: (el) => (this._mapDiv = el) }), h("map-tools", { basemapConfig: this.basemapConfig, class: "box-shadow", enableBasemap: this.enableBasemap, enableFloorFilter: this.enableFloorFilter, enableFullscreen: this.enableFullscreen, enableLegend: this.enableLegend, enableSearch: this.enableSearch, mapView: this.mapView, ref: (el) => this._mapTools = el, searchConfiguration: this._searchConfiguration })));
68
+ const mapClass = this.hidden ? "visibility-hidden" : "";
69
+ return (h(Host, null, h("map-picker", { mapInfos: this.mapInfos }), h("div", { class: `map-height ${mapClass}`, ref: (el) => (this._mapDiv = el) }), h("map-tools", { basemapConfig: this.basemapConfig, class: "box-shadow", enableBasemap: this.enableBasemap, enableFloorFilter: this.enableFloorFilter, enableFullscreen: this.enableFullscreen, enableLegend: this.enableLegend, enableSearch: this.enableSearch, mapView: this.mapView, ref: (el) => this._mapTools = el, searchConfiguration: this._searchConfiguration })));
68
70
  }
69
71
  //--------------------------------------------------------------------------
70
72
  //
@@ -247,6 +249,23 @@ export class MapCard {
247
249
  "text": "IBasemapConfig: List of any basemaps to filter out from the basemap widget"
248
250
  }
249
251
  },
252
+ "hidden": {
253
+ "type": "boolean",
254
+ "mutable": false,
255
+ "complexType": {
256
+ "original": "boolean",
257
+ "resolved": "boolean",
258
+ "references": {}
259
+ },
260
+ "required": false,
261
+ "optional": false,
262
+ "docs": {
263
+ "tags": [],
264
+ "text": "boolean: When true the map display will be hidden"
265
+ },
266
+ "attribute": "hidden",
267
+ "reflect": false
268
+ },
250
269
  "mapInfos": {
251
270
  "type": "unknown",
252
271
  "mutable": false,
@@ -31,6 +31,7 @@ export class MapTools {
31
31
  this.layout = "vertical";
32
32
  this.mapView = undefined;
33
33
  this.searchConfiguration = undefined;
34
+ this._hasFloorInfo = false;
34
35
  this._translations = undefined;
35
36
  this._showTools = true;
36
37
  this._showBasemapWidget = false;
@@ -44,6 +45,15 @@ export class MapTools {
44
45
  // Watch handlers
45
46
  //
46
47
  //--------------------------------------------------------------------------
48
+ /**
49
+ * When the mapView loads check if it supports floor awareness
50
+ */
51
+ async mapViewWatchHandler() {
52
+ await this.mapView.when(() => {
53
+ var _a, _b;
54
+ this._hasFloorInfo = (_b = (_a = this.mapView) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.floorInfo;
55
+ });
56
+ }
47
57
  /**
48
58
  * When the _showBasemapWidget property is true display the basemap gallery
49
59
  */
@@ -157,7 +167,7 @@ export class MapTools {
157
167
  this._getActionGroup(fullscreenIcon, false, fullscreenTip, () => this._expand()) :
158
168
  undefined, this.enableBasemap ?
159
169
  this._getActionGroup("basemap", false, this._translations.basemap, () => this._toggleBasemapPicker()) :
160
- undefined, this.enableFloorFilter ?
170
+ undefined, this.enableFloorFilter && this._hasFloorInfo ?
161
171
  this._getActionGroup("urban-model", false, this._translations.floorFilter, () => this._toggleFloorFilter()) :
162
172
  undefined)), h("basemap-gallery", { basemapConfig: this.basemapConfig, class: basemapClass, mapView: this.mapView, ref: (el) => { this._basemapElement = el; } }), h("map-search", { class: searchClass, mapView: this.mapView, ref: (el) => { this._searchElement = el; }, resultGraphicEnabled: true, searchConfiguration: this.searchConfiguration }), h("map-legend", { class: legendClass, mapView: this.mapView, ref: (el) => { this._legendElement = el; } }), h("map-fullscreen", { class: fullscreenClass, mapView: this.mapView, ref: (el) => { this._fullscreenElement = el; } }), h("floor-filter", { class: floorFilterClass, enabled: this.enableFloorFilter, mapView: this.mapView, ref: (el) => { this._floorFilterElement = el; } })));
163
173
  }
@@ -432,6 +442,7 @@ export class MapTools {
432
442
  }
433
443
  static get states() {
434
444
  return {
445
+ "_hasFloorInfo": {},
435
446
  "_translations": {},
436
447
  "_showTools": {},
437
448
  "_showBasemapWidget": {},
@@ -444,6 +455,9 @@ export class MapTools {
444
455
  static get elementRef() { return "el"; }
445
456
  static get watchers() {
446
457
  return [{
458
+ "propName": "mapView",
459
+ "methodName": "mapViewWatchHandler"
460
+ }, {
447
461
  "propName": "_showBasemapWidget",
448
462
  "methodName": "_showBasemapWidgetWatchHandler"
449
463
  }, {
@@ -514,6 +514,26 @@ export function _prepareAttributeValue(attributeValue, attributeType, attributeD
514
514
  // e.g., "12/31/1969, 4:00 PM"
515
515
  value = value.replace(/\xe2\x80\xaf/g, "");
516
516
  break;
517
+ case "date-only":
518
+ // Value is a string, e.g., "2020-12-08"
519
+ if (attributeFormat === null || attributeFormat === void 0 ? void 0 : attributeFormat.dateFormat) {
520
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat);
521
+ value = intl.formatDateOnly(value, dateFormatIntlOptions);
522
+ }
523
+ else {
524
+ value = intl.formatDateOnly(value);
525
+ }
526
+ break;
527
+ case "time-only":
528
+ // Value is a string, e.g., "14:51:44.2533333"
529
+ if (attributeFormat === null || attributeFormat === void 0 ? void 0 : attributeFormat.dateFormat) {
530
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat);
531
+ value = intl.formatTimeOnly(value, dateFormatIntlOptions);
532
+ }
533
+ else {
534
+ value = intl.formatTimeOnly(value);
535
+ }
536
+ break;
517
537
  case "double":
518
538
  case "integer":
519
539
  case "long":
@@ -688,6 +688,26 @@ export function _prepareAttributeValue(
688
688
  value = value.replace(/\xe2\x80\xaf/g, "");
689
689
  break;
690
690
 
691
+ case "date-only":
692
+ // Value is a string, e.g., "2020-12-08"
693
+ if (attributeFormat?.dateFormat) {
694
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat as any);
695
+ value = intl.formatDateOnly(value, dateFormatIntlOptions);
696
+ } else {
697
+ value = intl.formatDateOnly(value);
698
+ }
699
+ break;
700
+
701
+ case "time-only":
702
+ // Value is a string, e.g., "14:51:44.2533333"
703
+ if (attributeFormat?.dateFormat) {
704
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat as any);
705
+ value = intl.formatTimeOnly(value, dateFormatIntlOptions);
706
+ } else {
707
+ value = intl.formatTimeOnly(value);
708
+ }
709
+ break;
710
+
691
711
  case "double":
692
712
  case "integer":
693
713
  case "long":
@@ -49,7 +49,7 @@ export async function queryAllFeatures(start, layer, graphics) {
49
49
  */
50
50
  export async function queryAllIds(layer) {
51
51
  const query = layer.createQuery();
52
- query.where = "1=1";
52
+ query.where = layer.definitionExpression || "1=1";
53
53
  return await layer.queryObjectIds(query);
54
54
  }
55
55
  /**
@@ -59,7 +59,7 @@ export async function queryAllIds(
59
59
  layer: __esri.FeatureLayer
60
60
  ): Promise<number[]> {
61
61
  const query = layer.createQuery();
62
- query.where = "1=1";
62
+ query.where = layer.definitionExpression || "1=1";
63
63
  return await layer.queryObjectIds(query);
64
64
  }
65
65
 
@@ -803,21 +803,95 @@ describe("downloadUtils", () => {
803
803
  });
804
804
  });
805
805
  describe('_prepareAttributeValue', () => {
806
+ it('should format date attributes', () => {
807
+ const attributeValue = new Date('2022-02-01T00:00:00.000Z');
808
+ const attributeType = 'date';
809
+ const attributeDomain = null;
810
+ const attributeFormat = null;
811
+ const intl = {
812
+ formatDate: jest.fn().mockReturnValue('02/01/2022'),
813
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
814
+ };
815
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
816
+ expect(result).toEqual('02/01/2022');
817
+ expect(intl.formatDate).toHaveBeenCalledWith(attributeValue);
818
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
819
+ });
820
+ it('should format date-only attributes', () => {
821
+ const attributeValue = '2020-02-01';
822
+ const attributeType = 'date-only';
823
+ const attributeDomain = null;
824
+ const attributeFormat = null;
825
+ const intl = {
826
+ formatDateOnly: jest.fn().mockReturnValue('02/01/2022'),
827
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
828
+ };
829
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
830
+ expect(result).toEqual('02/01/2022');
831
+ expect(intl.formatDateOnly).toHaveBeenCalledWith(attributeValue);
832
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
833
+ });
834
+ it('should format time-only attributes', () => {
835
+ const attributeValue = '14:51:44.2533333';
836
+ const attributeType = 'time-only';
837
+ const attributeDomain = null;
838
+ const attributeFormat = null;
839
+ const intl = {
840
+ formatTimeOnly: jest.fn().mockReturnValue('14:41'),
841
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
842
+ };
843
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
844
+ expect(result).toEqual('14:41');
845
+ expect(intl.formatTimeOnly).toHaveBeenCalledWith(attributeValue);
846
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
847
+ });
806
848
  it('should format date attributes using the specified date format', () => {
807
- const attributeValue = new Date('2022-01-01T00:00:00.000Z');
849
+ const attributeValue = new Date('2022-02-01T00:00:00.000Z');
808
850
  const attributeType = 'date';
809
851
  const attributeDomain = null;
810
852
  const attributeFormat = {
811
- dateFormat: 'short-date'
853
+ dateFormat: 'shortdate'
812
854
  };
813
855
  const intl = {
814
- formatDate: jest.fn().mockReturnValue('01/01/2022'),
856
+ formatDate: jest.fn().mockReturnValue('02/01/2022'),
815
857
  convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
816
858
  };
817
859
  const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
818
- expect(result).toEqual('01/01/2022');
860
+ expect(result).toEqual('02/01/2022');
819
861
  expect(intl.formatDate).toHaveBeenCalledWith(attributeValue, {});
820
- expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('short-date');
862
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
863
+ });
864
+ it('should format date-only attributes using the specified date format', () => {
865
+ const attributeValue = '2020-02-01';
866
+ const attributeType = 'date-only';
867
+ const attributeDomain = null;
868
+ const attributeFormat = {
869
+ dateFormat: 'shortdate'
870
+ };
871
+ const intl = {
872
+ formatDateOnly: jest.fn().mockReturnValue('02/01/2022'),
873
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
874
+ };
875
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
876
+ expect(result).toEqual('02/01/2022');
877
+ expect(intl.formatDateOnly).toHaveBeenCalledWith(attributeValue, {});
878
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
879
+ });
880
+ it('should format time-only attributes using the specified date format', () => {
881
+ const attributeValue = '14:51:44.2533333';
882
+ const attributeType = 'time-only';
883
+ const attributeDomain = null;
884
+ const attributeFormat = {
885
+ dateFormat: 'shortdate'
886
+ };
887
+ const intl = {
888
+ formatTimeOnly: jest.fn().mockReturnValue('14:41'),
889
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
890
+ };
891
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat, intl);
892
+ expect(result).toEqual('14:41');
893
+ expect(intl.formatTimeOnly).toHaveBeenCalledWith(attributeValue, {});
894
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
821
895
  });
822
896
  it('should format number attributes using the specified number format', () => {
823
897
  const attributeValue = 1234.5678;
@@ -924,21 +924,100 @@ describe("downloadUtils", () => {
924
924
 
925
925
  describe('_prepareAttributeValue', () => {
926
926
 
927
+ it('should format date attributes', () => {
928
+ const attributeValue = new Date('2022-02-01T00:00:00.000Z');
929
+ const attributeType = 'date';
930
+ const attributeDomain = null;
931
+ const attributeFormat = null;
932
+ const intl = {
933
+ formatDate: jest.fn().mockReturnValue('02/01/2022'),
934
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
935
+ };
936
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
937
+ expect(result).toEqual('02/01/2022');
938
+ expect(intl.formatDate).toHaveBeenCalledWith(attributeValue);
939
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
940
+ });
941
+
942
+ it('should format date-only attributes', () => {
943
+ const attributeValue = '2020-02-01';
944
+ const attributeType = 'date-only';
945
+ const attributeDomain = null;
946
+ const attributeFormat = null;
947
+ const intl = {
948
+ formatDateOnly: jest.fn().mockReturnValue('02/01/2022'),
949
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
950
+ };
951
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
952
+ expect(result).toEqual('02/01/2022');
953
+ expect(intl.formatDateOnly).toHaveBeenCalledWith(attributeValue);
954
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
955
+ });
956
+
957
+ it('should format time-only attributes', () => {
958
+ const attributeValue = '14:51:44.2533333';
959
+ const attributeType = 'time-only';
960
+ const attributeDomain = null;
961
+ const attributeFormat = null;
962
+ const intl = {
963
+ formatTimeOnly: jest.fn().mockReturnValue('14:41'),
964
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
965
+ };
966
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
967
+ expect(result).toEqual('14:41');
968
+ expect(intl.formatTimeOnly).toHaveBeenCalledWith(attributeValue);
969
+ expect(intl.convertDateFormatToIntlOptions).not.toHaveBeenCalled();
970
+ });
971
+
927
972
  it('should format date attributes using the specified date format', () => {
928
- const attributeValue = new Date('2022-01-01T00:00:00.000Z');
973
+ const attributeValue = new Date('2022-02-01T00:00:00.000Z');
929
974
  const attributeType = 'date';
930
975
  const attributeDomain = null;
931
976
  const attributeFormat = {
932
- dateFormat: 'short-date'
977
+ dateFormat: 'shortdate'
933
978
  };
934
979
  const intl = {
935
- formatDate: jest.fn().mockReturnValue('01/01/2022'),
980
+ formatDate: jest.fn().mockReturnValue('02/01/2022'),
936
981
  convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
937
982
  };
938
983
  const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
939
- expect(result).toEqual('01/01/2022');
984
+ expect(result).toEqual('02/01/2022');
940
985
  expect(intl.formatDate).toHaveBeenCalledWith(attributeValue, {});
941
- expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('short-date');
986
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
987
+ });
988
+
989
+ it('should format date-only attributes using the specified date format', () => {
990
+ const attributeValue = '2020-02-01';
991
+ const attributeType = 'date-only';
992
+ const attributeDomain = null;
993
+ const attributeFormat = {
994
+ dateFormat: 'shortdate'
995
+ };
996
+ const intl = {
997
+ formatDateOnly: jest.fn().mockReturnValue('02/01/2022'),
998
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
999
+ };
1000
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
1001
+ expect(result).toEqual('02/01/2022');
1002
+ expect(intl.formatDateOnly).toHaveBeenCalledWith(attributeValue, {});
1003
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
1004
+ });
1005
+
1006
+ it('should format time-only attributes using the specified date format', () => {
1007
+ const attributeValue = '14:51:44.2533333';
1008
+ const attributeType = 'time-only';
1009
+ const attributeDomain = null;
1010
+ const attributeFormat = {
1011
+ dateFormat: 'shortdate'
1012
+ };
1013
+ const intl = {
1014
+ formatTimeOnly: jest.fn().mockReturnValue('14:41'),
1015
+ convertDateFormatToIntlOptions: jest.fn().mockReturnValue({})
1016
+ };
1017
+ const result = downloadUtils._prepareAttributeValue(attributeValue, attributeType, attributeDomain, attributeFormat as any, intl);
1018
+ expect(result).toEqual('14:41');
1019
+ expect(intl.formatTimeOnly).toHaveBeenCalledWith(attributeValue, {});
1020
+ expect(intl.convertDateFormatToIntlOptions).toHaveBeenCalledWith('shortdate');
942
1021
  });
943
1022
 
944
1023
  it('should format number attributes using the specified number format', () => {
@@ -50,7 +50,7 @@ import { d as defineCustomElement$4 } from './map-picker2.js';
50
50
  import { d as defineCustomElement$3 } from './map-search2.js';
51
51
  import { d as defineCustomElement$2 } from './map-tools2.js';
52
52
 
53
- const crowdsourceManagerCss = ":host{display:block;--calcite-label-margin-bottom:0px;--solutions-theme-foreground-color:var(--calcite-ui-foreground-1)}.padding-1-2{padding:0.5rem}.display-flex{display:flex}.width-full{width:100%}.width-1-2{position:relative;width:50%}.width-1-3{position:relative;width:33.33%}.width-2-3{position:relative;width:66.66%}.width-0{width:0}.height-full{height:100%}.height-1-2{position:relative;height:50%}.height-0{height:0}.toggle-node{width:51px;height:51px}.overflow-hidden{overflow:hidden}.flex-column{flex-direction:column}.border{border:1px solid var(--calcite-ui-border-3)}.border-bottom{border-bottom:1px solid var(--calcite-ui-border-3)}.border-sides{border-left:1px solid var(--calcite-ui-border-3);border-right:1px solid var(--calcite-ui-border-3)}.position-relative{position:relative}.height-50{height:50%}.adjusted-height-50{height:calc(50% - 25px)}.adjusted-height-100{height:calc(100% - 50px)}.adjusted-height-100-50{height:calc(100% - 50px)}.display-none{display:none}.height-53{height:53px}.position-absolute-53{position:absolute;top:53px}.display-grid{display:grid}.height-50-px{height:50px}.padding-inline-start-75{padding-inline-start:0.75rem}.align-items-center{align-items:center}.esri-floor-filter__close-levels-button{width:40px !important;height:40px !important}.esri-floor-filter__level-button{width:40px !important;height:40px !important}.esri-floor-filter__browse-button{width:40px !important;height:40px !important}";
53
+ const crowdsourceManagerCss = ":host{display:block;--calcite-label-margin-bottom:0px;--solutions-theme-foreground-color:var(--calcite-ui-foreground-1)}.padding-1-2{padding:0.5rem}.display-flex{display:flex}.width-full{width:100%}.width-1-2{position:relative;width:50%}.width-1-3{position:relative;width:33.33%}.width-2-3{position:relative;width:66.66%}.width-0{width:0}.height-full{height:100%}.height-1-2{position:relative;height:50%}.height-0{height:0}.toggle-node{width:51px;height:51px}.overflow-hidden{overflow:hidden}.flex-column{flex-direction:column}.border{border:1px solid var(--calcite-ui-border-3)}.border-bottom{border-bottom:1px solid var(--calcite-ui-border-3)}.border-sides{border-left:1px solid var(--calcite-ui-border-3);border-right:1px solid var(--calcite-ui-border-3)}.position-relative{position:relative}.height-50{height:50%}.adjusted-height-50{height:calc(50% - 25px)}.adjusted-height-100{height:calc(100% - 50px)}.adjusted-height-100-50{height:calc(100% - 50px)}.display-none{display:none}.height-53{height:53px}.position-absolute-53{position:absolute;top:53px}.display-grid{display:grid}.height-50-px{height:50px}.padding-inline-start-75{padding-inline-start:0.75rem}.align-items-center{align-items:center}.esri-floor-filter__close-levels-button{width:40px !important;height:40px !important}.esri-floor-filter__level-button{width:40px !important;height:40px !important}.esri-floor-filter__browse-button{width:40px !important;height:40px !important}.position-absolute-50{position:absolute;top:50px;bottom:0px;left:0px;right:0px}";
54
54
 
55
55
  const CrowdsourceManager$1 = /*@__PURE__*/ proxyCustomElement(class CrowdsourceManager extends HTMLElement {
56
56
  constructor() {
@@ -279,11 +279,11 @@ const CrowdsourceManager$1 = /*@__PURE__*/ proxyCustomElement(class CrowdsourceM
279
279
  * @protected
280
280
  */
281
281
  _getMapNode(layoutMode, hideMap) {
282
- var _a, _b, _c;
282
+ var _a;
283
283
  const mapDisplayClass = this.classicGrid && layoutMode === ELayoutMode.GRID ? "display-flex height-full width-1-2" :
284
284
  layoutMode === ELayoutMode.GRID && !hideMap ? "" : "display-none";
285
- const mapContainerClass = this.classicGrid && layoutMode === ELayoutMode.GRID ? "width-full" : this._expandPopup ? "height-50-px" : "adjusted-height-50";
286
- return (h("div", { class: `${mapContainerClass} overflow-hidden ${mapDisplayClass}` }, h("map-card", { basemapConfig: this.basemapConfig, class: "width-full", enableBasemap: this.enableBasemap, enableFloorFilter: this.enableFloorFilter && ((_b = (_a = this._mapView) === null || _a === void 0 ? void 0 : _a.map) === null || _b === void 0 ? void 0 : _b.floorInfo), enableFullscreen: this.enableFullscreen, enableLegend: this.enableLegend, enableSearch: this.enableSearch, mapInfos: (_c = this.mapInfos) === null || _c === void 0 ? void 0 : _c.filter(mapInfo => mapInfo.visible !== false) })));
285
+ const mapContainerClass = this.classicGrid && layoutMode === ELayoutMode.GRID ? "width-full" : "adjusted-height-50";
286
+ return (h("div", { class: `${mapContainerClass} overflow-hidden ${mapDisplayClass}` }, h("map-card", { basemapConfig: this.basemapConfig, class: "width-full", enableBasemap: this.enableBasemap, enableFloorFilter: this.enableFloorFilter, enableFullscreen: this.enableFullscreen, enableLegend: this.enableLegend, enableSearch: this.enableSearch, hidden: this._expandPopup, mapInfos: (_a = this.mapInfos) === null || _a === void 0 ? void 0 : _a.filter(mapInfo => mapInfo.visible !== false) })));
287
287
  }
288
288
  /**
289
289
  * Get the expand node for the popup information
@@ -296,7 +296,8 @@ const CrowdsourceManager$1 = /*@__PURE__*/ proxyCustomElement(class CrowdsourceM
296
296
  const id = "expand-popup";
297
297
  const tooltip = this._expandPopup ? this._translations.collapsePopup : this._translations.expandPopup;
298
298
  const themeClass = this.theme === "dark" ? "calcite-mode-dark" : "calcite-mode-light";
299
- return (h("div", { class: "calcite-mode-dark height-full" }, h("calcite-panel", null, h("div", { class: "display-flex align-items-center", slot: "header-content" }, h("calcite-icon", { icon: "information", scale: "s" }), h("div", { class: "padding-inline-start-75" }, this._translations.information)), h("calcite-action", { icon: icon, id: id, onClick: () => this._togglePopup(), slot: "header-actions-end" }), h("calcite-tooltip", { class: themeClass, label: "", placement: "bottom", "reference-element": id }, h("span", null, tooltip)), this._getCardNode())));
299
+ const popupNodeClass = !this._expandPopup ? "height-full" : "position-absolute-50";
300
+ return (h("div", { class: "calcite-mode-dark " + popupNodeClass }, h("calcite-panel", null, h("div", { class: "display-flex align-items-center", slot: "header-content" }, h("calcite-icon", { icon: "information", scale: "s" }), h("div", { class: "padding-inline-start-75" }, this._translations.information)), h("calcite-action", { icon: icon, id: id, onClick: () => this._togglePopup(), slot: "header-actions-end" }), h("calcite-tooltip", { class: themeClass, label: "", placement: "bottom", "reference-element": id }, h("span", null, tooltip)), this._getCardNode())));
300
301
  }
301
302
  /**
302
303
  * Toggle the popup information
@@ -317,9 +318,8 @@ const CrowdsourceManager$1 = /*@__PURE__*/ proxyCustomElement(class CrowdsourceM
317
318
  */
318
319
  _getCardNode() {
319
320
  const cardManagerHeight = !this._expandPopup ? "height-50" : "height-full";
320
- const cardManagerContainer = this._expandPopup ? "width-50 adjusted-height-100-50" : "width-50 height-full";
321
321
  const themeClass = this.theme === "dark" ? "calcite-mode-dark" : "calcite-mode-light";
322
- return (h("div", { class: `${cardManagerContainer} ${themeClass}` }, h("card-manager", { class: `${cardManagerHeight} width-full`, mapView: this === null || this === void 0 ? void 0 : this._mapView, zoomAndScrollToSelected: this.zoomAndScrollToSelected })));
322
+ return (h("div", { class: `width-50 height-full ${themeClass}` }, h("card-manager", { class: `${cardManagerHeight} width-full`, mapView: this === null || this === void 0 ? void 0 : this._mapView, zoomAndScrollToSelected: this.zoomAndScrollToSelected })));
323
323
  }
324
324
  /**
325
325
  * Get the table node based for the current layout
@@ -2829,6 +2829,26 @@ function _prepareAttributeValue(attributeValue, attributeType, attributeDomain,
2829
2829
  // e.g., "12/31/1969, 4:00 PM"
2830
2830
  value = value.replace(/\xe2\x80\xaf/g, "");
2831
2831
  break;
2832
+ case "date-only":
2833
+ // Value is a string, e.g., "2020-12-08"
2834
+ if (attributeFormat === null || attributeFormat === void 0 ? void 0 : attributeFormat.dateFormat) {
2835
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat);
2836
+ value = intl.formatDateOnly(value, dateFormatIntlOptions);
2837
+ }
2838
+ else {
2839
+ value = intl.formatDateOnly(value);
2840
+ }
2841
+ break;
2842
+ case "time-only":
2843
+ // Value is a string, e.g., "14:51:44.2533333"
2844
+ if (attributeFormat === null || attributeFormat === void 0 ? void 0 : attributeFormat.dateFormat) {
2845
+ const dateFormatIntlOptions = intl.convertDateFormatToIntlOptions(attributeFormat.dateFormat);
2846
+ value = intl.formatTimeOnly(value, dateFormatIntlOptions);
2847
+ }
2848
+ else {
2849
+ value = intl.formatTimeOnly(value);
2850
+ }
2851
+ break;
2832
2852
  case "double":
2833
2853
  case "integer":
2834
2854
  case "long":
@@ -77,7 +77,8 @@ const FloorFilter = /*@__PURE__*/ proxyCustomElement(class FloorFilter extends H
77
77
  * @protected
78
78
  */
79
79
  _initFloorFilter(view) {
80
- if (view && this.enabled && this.FloorFilter) {
80
+ var _a;
81
+ if (view && this.enabled && this.FloorFilter && ((_a = view === null || view === void 0 ? void 0 : view.map) === null || _a === void 0 ? void 0 : _a.floorInfo)) {
81
82
  if (!this.floorFilterWidget) {
82
83
  this.floorFilterWidget = new this.FloorFilter({
83
84
  container: this._floorFilterElement,
@@ -346,26 +346,26 @@ const LayerTable = /*@__PURE__*/ proxyCustomElement(class LayerTable extends HTM
346
346
  func: () => this._selectAll(),
347
347
  label: this._translations.selectAll,
348
348
  disabled: false,
349
- isOverflow: true
349
+ isOverflow: false
350
350
  }, {
351
351
  icon: "compare",
352
352
  func: () => this._switchSelected(),
353
353
  label: this._translations.switchSelected,
354
354
  disabled: false,
355
- isOverflow: true
355
+ isOverflow: false
356
356
  }, {
357
357
  icon: "refresh",
358
358
  func: () => this._refresh(),
359
359
  label: this._translations.refresh,
360
360
  disabled: false,
361
- isOverflow: true
361
+ isOverflow: false
362
362
  },
363
363
  this.enableCSV ? {
364
364
  icon: "export",
365
365
  func: () => void this._exportToCSV(),
366
366
  label: this._translations.exportCSV,
367
367
  disabled: false,
368
- isOverflow: true
368
+ isOverflow: false
369
369
  } : undefined];
370
370
  this._defaultVisibleToolSizeInfos = undefined;
371
371
  }
@@ -409,14 +409,20 @@ const LayerTable = /*@__PURE__*/ proxyCustomElement(class LayerTable extends HTM
409
409
  prev.push(cur.id);
410
410
  return prev;
411
411
  }, []);
412
+ let forceFinish = false;
412
413
  const controlsThatFit = [...this._defaultVisibleToolSizeInfos].reduce((prev, cur) => {
413
- if (skipControls.indexOf(cur.id) < 0 &&
414
+ if (!forceFinish && skipControls.indexOf(cur.id) < 0 &&
414
415
  (currentTools.indexOf(cur.id) > -1 || (controlsWidth + cur.width) <= toolbarWidth)) {
415
416
  if (currentTools.indexOf(cur.id) < 0) {
416
417
  controlsWidth += cur.width;
417
418
  }
418
419
  prev.push(cur);
419
420
  }
421
+ else if (skipControls.indexOf(cur.id) < 0 && (controlsWidth + cur.width) > toolbarWidth) {
422
+ // exit the first time we evalute this as true...otherwise it will add the next control that will fit
423
+ // and not preserve the overall order of controls
424
+ forceFinish = true;
425
+ }
420
426
  return prev;
421
427
  }, []);
422
428
  this._setControlsThatFit(controlsThatFit, skipControls);
@@ -495,9 +501,9 @@ const LayerTable = /*@__PURE__*/ proxyCustomElement(class LayerTable extends HTM
495
501
  */
496
502
  _getDropdown(id) {
497
503
  const dropdownItems = this._getDropdownItems();
498
- return (h("calcite-dropdown", { disabled: this._layer === undefined, id: "solutions-more" }, h("calcite-action", { appearance: "solid", id: id, label: "", slot: "trigger", text: "" }, h("calcite-button", { appearance: "transparent", iconEnd: "chevron-down", kind: "neutral" }, this._translations.more)), h("calcite-dropdown-group", { "selection-mode": "none" }, dropdownItems.map(item => {
504
+ return dropdownItems.length > 0 ? (h("calcite-dropdown", { disabled: this._layer === undefined, id: "solutions-more" }, h("calcite-action", { appearance: "solid", id: id, label: "", slot: "trigger", text: "" }, h("calcite-button", { appearance: "transparent", iconEnd: "chevron-down", kind: "neutral" }, this._translations.more)), h("calcite-dropdown-group", { "selection-mode": "none" }, dropdownItems.map(item => {
499
505
  return (h("calcite-dropdown-item", { iconStart: item.icon, onClick: item.func }, item.label));
500
- }))));
506
+ })))) : undefined;
501
507
  }
502
508
  /**
503
509
  * Get a list of toolInfos that should display in the dropdown