@theseam/ui-common 0.3.1 → 0.3.2

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.
Files changed (82) hide show
  1. package/breadcrumbs/_breadcrumbs-theme.scss +3 -3
  2. package/breadcrumbs/breadcrumbs/breadcrumbs.component.scss +10 -10
  3. package/bundles/theseam-ui-common-form-field.umd.js +1 -1
  4. package/bundles/theseam-ui-common-form-field.umd.js.map +1 -1
  5. package/bundles/theseam-ui-common-google-maps.umd.js +2202 -0
  6. package/bundles/theseam-ui-common-google-maps.umd.js.map +1 -0
  7. package/bundles/theseam-ui-common-menu.umd.js +1 -0
  8. package/bundles/theseam-ui-common-menu.umd.js.map +1 -1
  9. package/bundles/theseam-ui-common-utils.umd.js +610 -136
  10. package/bundles/theseam-ui-common-utils.umd.js.map +1 -1
  11. package/esm2015/form-field/input.directive.js +2 -2
  12. package/esm2015/google-maps/google-maps/google-maps.component.js +261 -0
  13. package/esm2015/google-maps/google-maps-contextmenu.js +113 -0
  14. package/esm2015/google-maps/google-maps-controls.service.js +70 -0
  15. package/esm2015/google-maps/google-maps-feature-helpers.js +177 -0
  16. package/esm2015/google-maps/google-maps-places-autocomplete/google-maps-places-autocomplete.component.js +195 -0
  17. package/esm2015/google-maps/google-maps-places-autocomplete/google-maps-places-autocomplete.directive.js +163 -0
  18. package/esm2015/google-maps/google-maps-recenter-button-control/google-maps-recenter-button-control.component.js +57 -0
  19. package/esm2015/google-maps/google-maps-upload-button-control/google-maps-upload-button-control.component.js +119 -0
  20. package/esm2015/google-maps/google-maps.module.js +45 -0
  21. package/esm2015/google-maps/google-maps.service.js +344 -0
  22. package/esm2015/google-maps/map-control.component.js +65 -0
  23. package/esm2015/google-maps/map-controls-service.js +4 -0
  24. package/esm2015/google-maps/map-file-drop/map-file-drop.component.js +135 -0
  25. package/esm2015/google-maps/map-value-manager.service.js +46 -0
  26. package/esm2015/google-maps/public-api.js +14 -0
  27. package/esm2015/google-maps/theseam-ui-common-google-maps.js +6 -0
  28. package/esm2015/menu/menu-toggle.directive.js +2 -1
  29. package/esm2015/utils/geo-json/coerce-feature-collection.js +44 -0
  30. package/esm2015/utils/geo-json/geo-json-to-area.js +11 -0
  31. package/esm2015/utils/geo-json/is-feature-collection.validator.js +21 -0
  32. package/esm2015/utils/geo-json/is-only-geometry-types.js +23 -0
  33. package/esm2015/utils/geo-json/is-only-geometry-types.validator.js +32 -0
  34. package/esm2015/utils/geo-json/merge-polygons.js +35 -0
  35. package/esm2015/utils/geo-json/no-inner-rings.validator.js +63 -0
  36. package/esm2015/utils/geo-json/no-kinks.validator.js +39 -0
  37. package/esm2015/utils/geo-json/read-geo-file.js +99 -0
  38. package/esm2015/utils/geo-json/split-multi-polygons.js +29 -0
  39. package/esm2015/utils/is-null-or-undefined.js +1 -1
  40. package/esm2015/utils/public-api.js +11 -1
  41. package/fesm2015/theseam-ui-common-form-field.js +1 -1
  42. package/fesm2015/theseam-ui-common-form-field.js.map +1 -1
  43. package/fesm2015/theseam-ui-common-google-maps.js +1729 -0
  44. package/fesm2015/theseam-ui-common-google-maps.js.map +1 -0
  45. package/fesm2015/theseam-ui-common-menu.js +1 -0
  46. package/fesm2015/theseam-ui-common-menu.js.map +1 -1
  47. package/fesm2015/theseam-ui-common-utils.js +477 -94
  48. package/fesm2015/theseam-ui-common-utils.js.map +1 -1
  49. package/form-field/theseam-ui-common-form-field.metadata.json +1 -1
  50. package/framework/top-bar/_top-bar-theme.scss +5 -5
  51. package/google-maps/google-maps/google-maps.component.d.ts +89 -0
  52. package/google-maps/google-maps-contextmenu.d.ts +15 -0
  53. package/google-maps/google-maps-controls.service.d.ts +23 -0
  54. package/google-maps/google-maps-feature-helpers.d.ts +37 -0
  55. package/google-maps/google-maps-places-autocomplete/google-maps-places-autocomplete.component.d.ts +104 -0
  56. package/google-maps/google-maps-places-autocomplete/google-maps-places-autocomplete.directive.d.ts +80 -0
  57. package/google-maps/google-maps-recenter-button-control/google-maps-recenter-button-control.component.d.ts +21 -0
  58. package/google-maps/google-maps-upload-button-control/google-maps-upload-button-control.component.d.ts +34 -0
  59. package/google-maps/google-maps.module.d.ts +2 -0
  60. package/google-maps/google-maps.service.d.ts +53 -0
  61. package/google-maps/map-control.component.d.ts +20 -0
  62. package/google-maps/map-controls-service.d.ts +13 -0
  63. package/google-maps/map-file-drop/map-file-drop.component.d.ts +34 -0
  64. package/google-maps/map-value-manager.service.d.ts +18 -0
  65. package/google-maps/package.json +11 -0
  66. package/google-maps/public-api.d.ts +13 -0
  67. package/google-maps/theseam-ui-common-google-maps.d.ts +5 -0
  68. package/google-maps/theseam-ui-common-google-maps.metadata.json +1 -0
  69. package/package.json +17 -10
  70. package/utils/geo-json/coerce-feature-collection.d.ts +2 -0
  71. package/utils/geo-json/geo-json-to-area.d.ts +6 -0
  72. package/utils/geo-json/is-feature-collection.validator.d.ts +3 -0
  73. package/utils/geo-json/is-only-geometry-types.d.ts +5 -0
  74. package/utils/geo-json/is-only-geometry-types.validator.d.ts +4 -0
  75. package/utils/geo-json/merge-polygons.d.ts +9 -0
  76. package/utils/geo-json/no-inner-rings.validator.d.ts +10 -0
  77. package/utils/geo-json/no-kinks.validator.d.ts +3 -0
  78. package/utils/geo-json/read-geo-file.d.ts +7 -0
  79. package/utils/geo-json/split-multi-polygons.d.ts +8 -0
  80. package/utils/is-null-or-undefined.d.ts +1 -1
  81. package/utils/public-api.d.ts +10 -0
  82. package/utils/theseam-ui-common-utils.metadata.json +1 -1
@@ -1,7 +1,12 @@
1
1
  import { switchMap, startWith, map, distinctUntilChanged, mapTo, filter, take, pairwise, toArray, tap, shareReplay, publishReplay, refCount, skip } from 'rxjs/operators';
2
2
  import { of, merge, interval, from, combineLatest, Observable, isObservable, BehaviorSubject, Subject } from 'rxjs';
3
- import { __rest, __awaiter } from 'tslib';
3
+ import area from '@turf/area';
4
+ import { convertArea } from '@turf/helpers';
5
+ import kinks from '@turf/kinks';
6
+ import { __awaiter, __rest } from 'tslib';
7
+ import { isDevMode } from '@angular/core';
4
8
  import fileType from '@marklb/file-type';
9
+ import shp from 'shpjs';
5
10
 
6
11
  /**
7
12
  *
@@ -307,6 +312,476 @@ function isEmptyUrlRoute(activatedRoute) {
307
312
  return activatedRoute.snapshot.url.length === 0;
308
313
  }
309
314
 
315
+ // TODO: Make this more thorough and maybe error on unrecognized.
316
+ function coerceFeatureCollection(value) {
317
+ return parseValue(value);
318
+ }
319
+ /**
320
+ * Parses the value to a FeatureCollection object or null if it is not a
321
+ * FeatureCollection.
322
+ */
323
+ function parseValue(value) {
324
+ const _value = parseStringValue(value);
325
+ if (isFeatureCollectionValue(_value)) {
326
+ return _value;
327
+ }
328
+ return null;
329
+ }
330
+ /**
331
+ * Tries to parse the value to an object, in case the value is a stringified
332
+ * json.
333
+ */
334
+ function parseStringValue(value) {
335
+ if (typeof value === 'string') {
336
+ try {
337
+ return JSON.parse(value);
338
+ }
339
+ catch (_a) {
340
+ return null;
341
+ }
342
+ }
343
+ return value;
344
+ }
345
+ /**
346
+ * Checks if the value is a FeatureCollection.
347
+ *
348
+ * NOTE: This is not a thorough FeatureCollection check. It only checks that the
349
+ * value is an object resembling a GeoJSON.FeatureCollection, enough for the
350
+ * validator.
351
+ */
352
+ function isFeatureCollectionValue(value) {
353
+ if (value === undefined || value === null) {
354
+ return false;
355
+ }
356
+ return value.type === 'FeatureCollection' && Array.isArray(value.features);
357
+ }
358
+
359
+ /**
360
+ *
361
+ */
362
+ function geoJsonToArea(geoJson, units = 'acres') {
363
+ const area_mSqr = area(geoJson);
364
+ const acres = convertArea(area_mSqr, 'meters', units);
365
+ return acres;
366
+ }
367
+
368
+ const IS_FEATURE_COLLECTION_VALIDATOR_NAME = 'is-feature-collection';
369
+ function isFeatureCollectionValidator() {
370
+ return (control) => {
371
+ // Don't need to validate if there isn't a value. Use `Validators.required` for that.
372
+ if (isEmptyInputValue(control.value)) {
373
+ return null; // don't validate empty values to allow optional controls
374
+ }
375
+ const value = coerceFeatureCollection(control.value);
376
+ if (value === null) {
377
+ return {
378
+ [IS_FEATURE_COLLECTION_VALIDATOR_NAME]: {
379
+ reason: `Must be a FeatureCollection.`,
380
+ }
381
+ };
382
+ }
383
+ return null;
384
+ };
385
+ }
386
+
387
+ /**
388
+ * Returns true if the GeoJSON is only specifies geometries.
389
+ */
390
+ function isOnlyGeometryTypes(featureCollection, types) {
391
+ if (types.length === 0) {
392
+ if (featureCollection.features.length > 0) {
393
+ // If no types are specified then there can't be any specified types found.
394
+ return false;
395
+ }
396
+ else {
397
+ // If no types are specified and there are no features then there is
398
+ // nothing to say a specified type isn't found.
399
+ return true;
400
+ }
401
+ }
402
+ for (const f of featureCollection.features) {
403
+ if (types.indexOf(f.geometry.type) === -1) {
404
+ return false;
405
+ }
406
+ }
407
+ return true;
408
+ }
409
+
410
+ const IS_ONLY_GEOMETRY_TYPES_VALIDATOR_NAME = 'is-only-geometry-types';
411
+ function isOnlyGeometryTypesValidator(types) {
412
+ return (control) => {
413
+ // Don't need to validate if there isn't a value. Use `Validators.required` for that.
414
+ if (isEmptyInputValue(control.value)) {
415
+ return null; // don't validate empty values to allow optional controls
416
+ }
417
+ const value = coerceFeatureCollection(control.value);
418
+ if (value === null) {
419
+ // If there isn't a FeatureCollection then there is nothing to validate.
420
+ // Use 'isFeatureCollection' to validate the value is a FeatureCollection.
421
+ return null;
422
+ }
423
+ if (!isOnlyGeometryTypes(value, types)) {
424
+ const typesNotAllowed = value.features
425
+ .map(f => f.geometry.type)
426
+ .filter(t => types.indexOf(t) === -1);
427
+ const distinctTypesNotAllowed = Array.from(new Set(typesNotAllowed));
428
+ return {
429
+ [IS_ONLY_GEOMETRY_TYPES_VALIDATOR_NAME]: {
430
+ reason: `Only geometry type${(types.length === 1 ? '' : 's')} ${types.join(', ')} allowed.`,
431
+ notAllowedGeometryTypesFound: distinctTypesNotAllowed,
432
+ }
433
+ };
434
+ }
435
+ return null;
436
+ };
437
+ }
438
+
439
+ /**
440
+ * Merge Polygon and MultiPolygon geometries into a single MultiPolygon. Any
441
+ * properties, other than 'coordinates', of the Polygons and MultiPolygons will
442
+ * be lost.
443
+ *
444
+ * NOTE: Polygons and MultPolygons in a GeometryCollection will not be merged.
445
+ */
446
+ function mergePolygons(featureCollection) {
447
+ const multiPolygon = {
448
+ type: 'MultiPolygon',
449
+ coordinates: [],
450
+ };
451
+ for (let i = 0; i < featureCollection.features.length; i++) {
452
+ const f = featureCollection.features[i];
453
+ if (f.geometry.type === 'Polygon') {
454
+ multiPolygon.coordinates.push(f.geometry.coordinates);
455
+ featureCollection.features.splice(i, 1);
456
+ i--;
457
+ }
458
+ else if (f.geometry.type === 'MultiPolygon') {
459
+ multiPolygon.coordinates.push(...f.geometry.coordinates);
460
+ featureCollection.features.splice(i, 1);
461
+ i--;
462
+ }
463
+ }
464
+ if (multiPolygon.coordinates.length > 0) {
465
+ const feature = {
466
+ type: 'Feature',
467
+ geometry: multiPolygon,
468
+ properties: {},
469
+ };
470
+ featureCollection.features.push(feature);
471
+ }
472
+ }
473
+
474
+ const NO_INNER_RINGS_VALIDATOR_NAME = 'no-inner-rings';
475
+ /**
476
+ * Validates that a FeatureCollection does not contain any Polygon with inner
477
+ * rings("holes").
478
+ *
479
+ * NOTE: Only considers Polygon and MultiPolygon. Does not consider
480
+ * GeometryCollection.
481
+ */
482
+ function noInnerRingsValidator() {
483
+ return (control) => {
484
+ // Don't need to validate if there isn't a value. Use `Validators.required` for that.
485
+ if (isEmptyInputValue(control.value)) {
486
+ return null; // don't validate empty values to allow optional controls
487
+ }
488
+ const value = coerceFeatureCollection(control.value);
489
+ if (value === null) {
490
+ // If there isn't a FeatureCollection then there is nothing to validate.
491
+ // Use 'isFeatureCollection' to validate the value is a FeatureCollection.
492
+ return null;
493
+ }
494
+ if (hasInnerRing(value)) {
495
+ return {
496
+ [NO_INNER_RINGS_VALIDATOR_NAME]: {
497
+ reason: `A shape cannot have an inner ring.`
498
+ }
499
+ };
500
+ }
501
+ return null;
502
+ };
503
+ }
504
+ /**
505
+ * Checks if a FeatureCollection contains any geometries with an inner
506
+ * ring("hole").
507
+ *
508
+ * NOTE: Does not consider GeometryCollection.
509
+ */
510
+ function hasInnerRing(featureCollection) {
511
+ for (const f of featureCollection.features) {
512
+ // The spec says the right-hand rule must be followed, but also specifies
513
+ // that tools should not reject polygons that do not follow the right-hand
514
+ // rule. It does specify that the first ring must be the exterior ring and
515
+ // the others must be the interior. So, this should be safe to just check
516
+ // if there are multiple rings, instead of checking their winding orders.
517
+ //
518
+ // Polygon spec: https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.6
519
+ if (f.geometry.type === 'Polygon') {
520
+ if (f.geometry.coordinates.length > 1) {
521
+ return true;
522
+ }
523
+ }
524
+ else if (f.geometry.type === 'MultiPolygon') {
525
+ for (const coords of f.geometry.coordinates) {
526
+ if (coords.length > 1) {
527
+ return true;
528
+ }
529
+ }
530
+ }
531
+ }
532
+ return false;
533
+ }
534
+
535
+ const kinkableGeometryTypes = ['LineString', 'MultiLineString', 'MultiPolygon', 'Polygon'];
536
+ const NO_KINKS_VALIDATOR_NAME = 'no-kinks';
537
+ function noKinksValidator() {
538
+ return (control) => {
539
+ // Don't need to validate if there isn't a value. Use `Validators.required` for that.
540
+ if (isEmptyInputValue(control.value)) {
541
+ return null; // don't validate empty values to allow optional controls
542
+ }
543
+ const value = coerceFeatureCollection(control.value);
544
+ if (value === null) {
545
+ return null;
546
+ }
547
+ const kinksFound = [];
548
+ for (const f of value.features) {
549
+ if (kinkableGeometryTypes.indexOf(f.geometry.type) !== -1) {
550
+ const _kinks = kinks(f);
551
+ if (_kinks.features.length > 0) {
552
+ kinksFound.push({
553
+ feature: f,
554
+ kinks: _kinks,
555
+ });
556
+ }
557
+ }
558
+ }
559
+ if (kinksFound.length > 0) {
560
+ return {
561
+ [NO_KINKS_VALIDATOR_NAME]: {
562
+ reason: 'Paths should not intersect themself.',
563
+ featuresWithKink: kinksFound,
564
+ }
565
+ };
566
+ }
567
+ return null;
568
+ };
569
+ }
570
+
571
+ // import { Buffer } from 'buffer/'
572
+ const Buffer$1 = require('buffer/').Buffer;
573
+ function readFileAsync(file) {
574
+ return new Promise((resolve, reject) => {
575
+ const reader = new FileReader();
576
+ reader.onload = () => {
577
+ resolve(reader.result);
578
+ };
579
+ reader.readAsArrayBuffer(file);
580
+ });
581
+ }
582
+ function readFileAsDataUrlAsync(file) {
583
+ return __awaiter(this, void 0, void 0, function* () {
584
+ return new Promise((resolve, reject) => {
585
+ const reader = new FileReader();
586
+ reader.onload = () => {
587
+ resolve(reader.result);
588
+ };
589
+ reader.readAsDataURL(file);
590
+ });
591
+ });
592
+ }
593
+ function fileBufferToBlob(fileBuffer, defaultMime = 'application/octet-stream') {
594
+ return __awaiter(this, void 0, void 0, function* () {
595
+ const fType = fileType(fileBuffer);
596
+ const mime = (fType) ? fType.mime : defaultMime;
597
+ const blob = new Blob([fileBuffer], { type: mime });
598
+ return blob;
599
+ });
600
+ }
601
+ function fileBufferToObjectUrl(fileBuffer, defaultMime = 'application/octet-stream') {
602
+ return __awaiter(this, void 0, void 0, function* () {
603
+ const file = yield fileBufferToBlob(fileBuffer, defaultMime);
604
+ const fileURL = URL.createObjectURL(file);
605
+ return fileURL;
606
+ });
607
+ }
608
+ function fileDataFromBuffer(fileBuffer, defaultMime = 'application/octet-stream') {
609
+ return __awaiter(this, void 0, void 0, function* () {
610
+ const _fileBuffer = Buffer$1.from(fileBuffer);
611
+ const fType = fileType(_fileBuffer);
612
+ const ext = fType && fType.ext || undefined;
613
+ const mime = fType ? fType.mime : defaultMime;
614
+ const blob = new Blob([_fileBuffer], { type: mime });
615
+ const fileData = { ext, mime, blob };
616
+ return fileData;
617
+ });
618
+ }
619
+ function openBlob(blob, target, filename) {
620
+ // NOTE: IE and MSEdge do not allow Blob resources as a source for
621
+ // tabs or iframes. msSaveOrOpenBlob is used as a workaround. I
622
+ // haven't been able to find a way to just open the Blob file in
623
+ // another tab yet for IE or MSEdge.
624
+ if (window.navigator.msSaveOrOpenBlob) {
625
+ window.navigator.msSaveOrOpenBlob(blob, filename);
626
+ }
627
+ else {
628
+ const url = URL.createObjectURL(blob);
629
+ const win = window.open(url, target);
630
+ // TODO: Consider if always setting opener to null is to restrictive
631
+ // if (win && target && target.toLowerCase() === '_blank') {
632
+ // win.opener = null
633
+ // }
634
+ }
635
+ }
636
+
637
+ /** Returns object without property */
638
+ function withoutProperty(obj, propName) {
639
+ const _a = obj, _b = propName, _ = _a[_b], without = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
640
+ return without;
641
+ }
642
+ /** Returns object without properties */
643
+ function withoutProperties(obj, propNames) {
644
+ let without = obj;
645
+ for (const propName of propNames) {
646
+ without = withoutProperty(without, propName);
647
+ }
648
+ return without;
649
+ }
650
+ /** Delete property of object */
651
+ function deleteProperty(obj, propName) {
652
+ if (obj.hasOwnProperty(propName)) {
653
+ delete obj[propName];
654
+ }
655
+ }
656
+ /** Delete properties of object */
657
+ function deleteProperties(obj, propNames) {
658
+ for (const propName of propNames) {
659
+ deleteProperty(obj, propName);
660
+ }
661
+ }
662
+
663
+ const Buffer = require('buffer/').Buffer;
664
+ /**
665
+ * Reads a File, or buffer of file content, in GeoJSON or ESRI Shapefile format
666
+ * and returns a GeoJSON `FeatureCollection`.
667
+ */
668
+ function readGeoFile(fileOrBuffer) {
669
+ var _a;
670
+ return __awaiter(this, void 0, void 0, function* () {
671
+ const buffer = yield coerceFileOrBufferToBuffer(fileOrBuffer);
672
+ if (isShpFile(buffer)) {
673
+ return yield parseShpFile(buffer);
674
+ }
675
+ else if (((_a = fileType(buffer)) === null || _a === void 0 ? void 0 : _a.mime) === 'application/zip') {
676
+ try {
677
+ return yield parseShpZip(buffer);
678
+ }
679
+ catch (e) {
680
+ // NOTE: If 'shpjs' updates or we switch to a fork, where it doesn't use
681
+ // node buffers, then we can remove this rethrow.
682
+ if (isDevMode()) {
683
+ if (e.message === 'nodebuffer is not supported by this platform') {
684
+ console.warn('Try adding Buffer polyfill.\n' +
685
+ 'Install: npm install buffer\n' +
686
+ 'Add `global.Buffer = global.Buffer || require(\'buffer\').Buffer` to "src/polyfills.ts"');
687
+ }
688
+ }
689
+ throw e;
690
+ }
691
+ }
692
+ return parseGeoJson(buffer);
693
+ });
694
+ }
695
+ function coerceFileOrBufferToBuffer(fileOrBuffer) {
696
+ return __awaiter(this, void 0, void 0, function* () {
697
+ if (fileOrBuffer instanceof File) {
698
+ const arrBuf = yield readFileAsync(fileOrBuffer);
699
+ return Buffer.from(arrBuf);
700
+ }
701
+ return Buffer.from(fileOrBuffer);
702
+ });
703
+ }
704
+ // NOTE: Our current version of file-type does not detect shp files. We can
705
+ // remove this function when file-types is upgraded.
706
+ function isShpFile(buffer) {
707
+ const header = [0x27, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
708
+ const offset = 2;
709
+ if (buffer.length < (header.length + offset)) {
710
+ return false;
711
+ }
712
+ for (let i = 0; i < header.length; i++) {
713
+ if (header[i] !== buffer[i + offset]) {
714
+ return false;
715
+ }
716
+ }
717
+ return true;
718
+ }
719
+ function parseShpFile(buffer) {
720
+ return __awaiter(this, void 0, void 0, function* () {
721
+ const geometries = yield shp.parseShp(buffer, undefined);
722
+ const featCollection = {
723
+ type: 'FeatureCollection',
724
+ features: geometries.map(geom => ({
725
+ type: 'Feature',
726
+ geometry: geom,
727
+ properties: {}
728
+ }))
729
+ };
730
+ return featCollection;
731
+ });
732
+ }
733
+ function parseShpZip(buffer) {
734
+ return __awaiter(this, void 0, void 0, function* () {
735
+ let featCollection = yield shp.parseZip(buffer, undefined);
736
+ if (Array.isArray(featCollection)) {
737
+ if (featCollection.length === 0) {
738
+ throw Error(`Shape data not found.`);
739
+ }
740
+ else if (featCollection.length > 1) {
741
+ throw Error(`Multiple shape files not supported.`);
742
+ }
743
+ featCollection = featCollection[0];
744
+ }
745
+ return withoutProperty(featCollection, 'fileName');
746
+ });
747
+ }
748
+ function parseGeoJson(buffer) {
749
+ const json = JSON.parse(buffer.toString());
750
+ if ((json === null || json === void 0 ? void 0 : json.type) === 'FeatureCollection' && Array.isArray(json === null || json === void 0 ? void 0 : json.features)) {
751
+ return json;
752
+ }
753
+ throw Error(`Unable to parse as GeoJSON.`);
754
+ }
755
+
756
+ /**
757
+ * Split all MultiPolygon into Polygon. Any properties, other than
758
+ * 'coordinates', of the MultiPolygons will be lost.
759
+ *
760
+ * NOTE: MultiPolygons in a GeometryCollection will not be split.
761
+ */
762
+ function splitMultiPolygons(featureCollection) {
763
+ for (let i = 0; i < featureCollection.features.length; i++) {
764
+ if (featureCollection.features[i]) {
765
+ const geometry = featureCollection.features[i].geometry;
766
+ if (geometry.type === 'MultiPolygon') {
767
+ const features = splitMultPolygon(geometry).map(p => ({
768
+ type: 'Feature',
769
+ geometry: p,
770
+ properties: {},
771
+ }));
772
+ featureCollection.features.splice(i, 1, ...features);
773
+ i += Math.max(features.length - 1, 0);
774
+ }
775
+ }
776
+ }
777
+ }
778
+ function splitMultPolygon(multiPolygon) {
779
+ return multiPolygon.coordinates.map(c => ({
780
+ type: 'Polygon',
781
+ coordinates: c,
782
+ }));
783
+ }
784
+
310
785
  // Based on source: https://github.com/sindresorhus/array-move/blob/main/index.js
311
786
  /**
312
787
  Moves the item to the new position in the input array. Useful for huge arrays
@@ -441,98 +916,6 @@ function loadStyleSheet(path) {
441
916
  });
442
917
  }
443
918
 
444
- /** Returns object without property */
445
- function withoutProperty(obj, propName) {
446
- const _a = obj, _b = propName, _ = _a[_b], without = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
447
- return without;
448
- }
449
- /** Returns object without properties */
450
- function withoutProperties(obj, propNames) {
451
- let without = obj;
452
- for (const propName of propNames) {
453
- without = withoutProperty(without, propName);
454
- }
455
- return without;
456
- }
457
- /** Delete property of object */
458
- function deleteProperty(obj, propName) {
459
- if (obj.hasOwnProperty(propName)) {
460
- delete obj[propName];
461
- }
462
- }
463
- /** Delete properties of object */
464
- function deleteProperties(obj, propNames) {
465
- for (const propName of propNames) {
466
- deleteProperty(obj, propName);
467
- }
468
- }
469
-
470
- // import { Buffer } from 'buffer/'
471
- const Buffer = require('buffer/').Buffer;
472
- function readFileAsync(file) {
473
- return new Promise((resolve, reject) => {
474
- const reader = new FileReader();
475
- reader.onload = () => {
476
- resolve(reader.result);
477
- };
478
- reader.readAsArrayBuffer(file);
479
- });
480
- }
481
- function readFileAsDataUrlAsync(file) {
482
- return __awaiter(this, void 0, void 0, function* () {
483
- return new Promise((resolve, reject) => {
484
- const reader = new FileReader();
485
- reader.onload = () => {
486
- resolve(reader.result);
487
- };
488
- reader.readAsDataURL(file);
489
- });
490
- });
491
- }
492
- function fileBufferToBlob(fileBuffer, defaultMime = 'application/octet-stream') {
493
- return __awaiter(this, void 0, void 0, function* () {
494
- const fType = fileType(fileBuffer);
495
- const mime = (fType) ? fType.mime : defaultMime;
496
- const blob = new Blob([fileBuffer], { type: mime });
497
- return blob;
498
- });
499
- }
500
- function fileBufferToObjectUrl(fileBuffer, defaultMime = 'application/octet-stream') {
501
- return __awaiter(this, void 0, void 0, function* () {
502
- const file = yield fileBufferToBlob(fileBuffer, defaultMime);
503
- const fileURL = URL.createObjectURL(file);
504
- return fileURL;
505
- });
506
- }
507
- function fileDataFromBuffer(fileBuffer, defaultMime = 'application/octet-stream') {
508
- return __awaiter(this, void 0, void 0, function* () {
509
- const _fileBuffer = Buffer.from(fileBuffer);
510
- const fType = fileType(_fileBuffer);
511
- const ext = fType && fType.ext || undefined;
512
- const mime = fType ? fType.mime : defaultMime;
513
- const blob = new Blob([_fileBuffer], { type: mime });
514
- const fileData = { ext, mime, blob };
515
- return fileData;
516
- });
517
- }
518
- function openBlob(blob, target, filename) {
519
- // NOTE: IE and MSEdge do not allow Blob resources as a source for
520
- // tabs or iframes. msSaveOrOpenBlob is used as a workaround. I
521
- // haven't been able to find a way to just open the Blob file in
522
- // another tab yet for IE or MSEdge.
523
- if (window.navigator.msSaveOrOpenBlob) {
524
- window.navigator.msSaveOrOpenBlob(blob, filename);
525
- }
526
- else {
527
- const url = URL.createObjectURL(blob);
528
- const win = window.open(url, target);
529
- // TODO: Consider if always setting opener to null is to restrictive
530
- // if (win && target && target.toLowerCase() === '_blank') {
531
- // win.opener = null
532
- // }
533
- }
534
- }
535
-
536
919
  function notNullOrUndefined(value) {
537
920
  return value !== null && value !== undefined;
538
921
  }
@@ -881,5 +1264,5 @@ function fractionalDigitsCount(value) {
881
1264
  * Generated bundle index. Do not edit.
882
1265
  */
883
1266
 
884
- export { PollingTickerOptions, Refreshable, activatedRoutesWithDataProperty, arrayMoveImmutable, arrayMoveMutable, calcPercentage, createPadding, deleteProperties, deleteProperty, fileBufferToBlob, fileBufferToObjectUrl, fileDataFromBuffer, fractionalDigitsCount, getAttribute, getClosestWidgetCdkDrag, getControlName, getControlPath, hasAttribute, hasProperty, hasRequiredControl, isAbsoluteUrl, isEmptyInputValue, isEmptyUrlRoute, isNullOrUndefined, isNumeric, leafChildRoute, loadStyle, loadStyleSheet, mapEach, notNullOrUndefined, observeControlIsDifferent, observeControlStatus, observeControlValid, observeControlValue, observeControlValueChange, observeQueryList, openBlob, padEnd, padStart, phoneNumberMask, pollingTicker, readFileAsDataUrlAsync, readFileAsync, routeSnapshotPathFull, routeSnapshotPathRelative, subscriberCount, tapFirst, toggleAttribute, waitOnConditionAsync, waitOnNonPendingStatus, willHaveDataProp, withoutProperties, withoutProperty, wrapIntoObservable, ɵ0 };
1267
+ export { IS_FEATURE_COLLECTION_VALIDATOR_NAME, IS_ONLY_GEOMETRY_TYPES_VALIDATOR_NAME, NO_INNER_RINGS_VALIDATOR_NAME, NO_KINKS_VALIDATOR_NAME, PollingTickerOptions, Refreshable, activatedRoutesWithDataProperty, arrayMoveImmutable, arrayMoveMutable, calcPercentage, coerceFeatureCollection, createPadding, deleteProperties, deleteProperty, fileBufferToBlob, fileBufferToObjectUrl, fileDataFromBuffer, fractionalDigitsCount, geoJsonToArea, getAttribute, getClosestWidgetCdkDrag, getControlName, getControlPath, hasAttribute, hasProperty, hasRequiredControl, isAbsoluteUrl, isEmptyInputValue, isEmptyUrlRoute, isFeatureCollectionValidator, isNullOrUndefined, isNumeric, isOnlyGeometryTypes, isOnlyGeometryTypesValidator, leafChildRoute, loadStyle, loadStyleSheet, mapEach, mergePolygons, noInnerRingsValidator, noKinksValidator, notNullOrUndefined, observeControlIsDifferent, observeControlStatus, observeControlValid, observeControlValue, observeControlValueChange, observeQueryList, openBlob, padEnd, padStart, phoneNumberMask, pollingTicker, readFileAsDataUrlAsync, readFileAsync, readGeoFile, routeSnapshotPathFull, routeSnapshotPathRelative, splitMultiPolygons, subscriberCount, tapFirst, toggleAttribute, waitOnConditionAsync, waitOnNonPendingStatus, willHaveDataProp, withoutProperties, withoutProperty, wrapIntoObservable, ɵ0 };
885
1268
  //# sourceMappingURL=theseam-ui-common-utils.js.map