From e4eac6e4256dc320f6c767ecbad54b83459c4331 Mon Sep 17 00:00:00 2001
From: zaultavangar <zaul_tavangar@brown.edu>
Date: Mon, 11 Dec 2023 14:46:58 -0500
Subject: updates to map feature

---
 .../views/nodes/MapBox/DirectionsAnchorMenu.tsx    | 137 +++++++++++++++++++++
 1 file changed, 137 insertions(+)
 create mode 100644 src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx

(limited to 'src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx')

diff --git a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
new file mode 100644
index 000000000..bf4028f01
--- /dev/null
+++ b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
@@ -0,0 +1,137 @@
+import React = require('react');
+import { observer } from "mobx-react";
+import { AntimodeMenu, AntimodeMenuProps } from "../../AntimodeMenu";
+import { IReactionDisposer, ObservableMap, reaction } from "mobx";
+import { Doc, Opt } from "../../../../fields/Doc";
+import { returnFalse, unimplementedFunction } from "../../../../Utils";
+import { NumCast, StrCast } from "../../../../fields/Types";
+import { SelectionManager } from "../../../util/SelectionManager";
+import { IconButton } from "browndash-components";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { SettingsManager } from "../../../util/SettingsManager";
+import { IconLookup, faAdd, faCalendarDays, faRoute } from "@fortawesome/free-solid-svg-icons";
+
+@observer
+export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
+    static Instance: DirectionsAnchorMenu;
+
+    private _disposer: IReactionDisposer | undefined;
+
+    public onMakeAnchor: () => Opt<Doc> = () => undefined; // Method to get anchor from text search
+
+    public Center: () => void = unimplementedFunction;
+    public OnClick: (e: PointerEvent) => void = unimplementedFunction;
+    // public OnAudio: (e: PointerEvent) => void = unimplementedFunction;
+    public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction;
+    public Highlight: (color: string, isTargetToggler: boolean, savedAnnotations?: ObservableMap<number, HTMLDivElement[]>, addAsAnnotation?: boolean) => Opt<Doc> = (color: string, isTargetToggler: boolean) => undefined;
+    public GetAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => undefined;
+    public Delete: () => void = unimplementedFunction;
+    // public MakeTargetToggle: () => void = unimplementedFunction;
+    // public ShowTargetTrail: () => void = unimplementedFunction;
+    public IsTargetToggler: () => boolean = returnFalse;
+
+    private title: string | undefined = undefined;
+
+    public setPinDoc(pinDoc: Doc){
+        this.title = StrCast(pinDoc.title ? pinDoc.title : `${NumCast(pinDoc.longitude)}, ${NumCast(pinDoc.latitude)}`) ;
+        console.log("Title: ", this.title)
+    }
+
+    public get Active() {
+        return this._left > 0;
+    }
+
+    constructor(props: Readonly<{}>) {
+        super(props);
+
+        DirectionsAnchorMenu.Instance = this;
+        DirectionsAnchorMenu.Instance._canFade = false;
+    }
+
+    componentWillUnmount() {
+        this._disposer?.();
+    }
+
+    componentDidMount() {
+        this._disposer = reaction(
+            () => SelectionManager.Views().slice(),
+            sel => DirectionsAnchorMenu.Instance.fadeOut(true)
+        );
+    }
+    // audioDown = (e: React.PointerEvent) => {
+    //     setupMoveUpEvents(this, e, returnFalse, returnFalse, e => this.OnAudio?.(e));
+    // };
+
+    // cropDown = (e: React.PointerEvent) => {
+    //     setupMoveUpEvents(
+    //         this,
+    //         e,
+    //         (e: PointerEvent) => {
+    //             this.StartCropDrag(e, this._commentCont.current!);
+    //             return true;
+    //         },
+    //         returnFalse,
+    //         e => this.OnCrop?.(e)
+    //     );
+    // };
+    // notePointerDown = (e: React.PointerEvent) => {
+    //     setupMoveUpEvent(
+    //         this,
+    //         e,
+    //         (e: PointerEvent) => {
+    //             this.StartDrag(e, this._commentRef.current!);
+    //             return true;
+    //         },
+    //         returnFalse,
+    //         e => this.OnClick(e)
+    //     );
+    // };
+
+    static top = React.createRef<HTMLDivElement>();
+
+    // public get Top(){
+    //     return this.top
+    // }
+
+    render() {
+        const buttons = (
+            <div className='directions-menu-buttons' style={{display: 'flex'}}>
+                <IconButton
+                    tooltip="Add route" //
+                    onPointerDown={this.Delete}
+                    icon={<FontAwesomeIcon icon={faAdd as IconLookup} />}
+                    color={SettingsManager.userColor}
+                />
+            
+            
+                <IconButton
+                    tooltip='Animate route'
+                    onPointerDown={this.Delete} /**TODO: fix */
+                    icon={<FontAwesomeIcon icon={faRoute as IconLookup}/>}
+                    color={SettingsManager.userColor}
+                />
+                <IconButton
+                    tooltip='Add to calendar'
+                    onPointerDown={this.Delete} /**TODO: fix */
+                    icon={<FontAwesomeIcon icon={faCalendarDays as IconLookup}/>}
+                    color={SettingsManager.userColor}
+                />
+            </div>
+        )
+
+        return this.getElement(
+            <div ref={DirectionsAnchorMenu.top} style={{ height: 'max-content' , width: '100%', display: 'flex', flexDirection: 'column' }}>
+                <div>{this.title}</div>
+                <div className='direction-inputs' style={{display: 'flex', flexDirection: 'column'}}>
+                    <input
+                        placeholder="Origin"
+                    />
+                    <input
+                        placeholder="Destination"
+                    />
+                </div>
+                {buttons}
+            </div>
+        )
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From adf56d455ab0e429b7eac3430890ba7677cce8d9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 15 Dec 2023 11:16:37 -0500
Subject: more fixes for mapbox and dataviz

---
 package-lock.json                                  | 2188 +++++++++++++++++++-
 package.json                                       |    3 +
 src/client/views/nodes/DataVizBox/DataVizBox.tsx   |   14 +-
 .../nodes/DataVizBox/components/Histogram.tsx      |  102 +-
 .../nodes/DataVizBox/components/LineChart.tsx      |   66 +-
 .../views/nodes/DataVizBox/components/PieChart.tsx |   88 +-
 .../views/nodes/DataVizBox/components/TableBox.tsx |   79 +-
 src/client/views/nodes/MapBox/AnimationUtility.ts  |  482 ++---
 .../views/nodes/MapBox/DirectionsAnchorMenu.tsx    |   69 +-
 .../views/nodes/MapboxMapBox/MapboxContainer.tsx   |   66 +-
 webpack.config.js                                  |    2 +-
 11 files changed, 2636 insertions(+), 523 deletions(-)

(limited to 'src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx')

diff --git a/package-lock.json b/package-lock.json
index 18c4f3d05..6496b4184 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,6 +25,7 @@
                 "@mui/material": "^5.14.19",
                 "@octokit/core": "^5.0.2",
                 "@react-google-maps/api": "^2.19.2",
+                "@turf/turf": "^6.5.0",
                 "@types/bezier-js": "^4.1.3",
                 "@types/cors": "^2.8.17",
                 "@types/d3-axis": "^3.0.6",
@@ -113,6 +114,7 @@
                 "jsonschema": "^1.4.1",
                 "jszip": "^3.10.1",
                 "lodash": "^4.17.21",
+                "mapbox-gl": "^3.0.1",
                 "mathquill": "^0.10.1-a",
                 "md5-file": "^5.0.0",
                 "memorystream": "^0.3.1",
@@ -163,6 +165,7 @@
                 "react-icons": "^4.12.0",
                 "react-jsx-parser": "^1.29.0",
                 "react-loading": "^2.0.3",
+                "react-map-gl": "^7.1.6",
                 "react-markdown": "^9.0.1",
                 "react-measure": "^2.5.2",
                 "react-resizable": "^3.0.5",
@@ -3126,6 +3129,42 @@
             "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
             "dev": true
         },
+        "node_modules/@mapbox/geojson-rewind": {
+            "version": "0.5.2",
+            "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz",
+            "integrity": "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==",
+            "dependencies": {
+                "get-stream": "^6.0.1",
+                "minimist": "^1.2.6"
+            },
+            "bin": {
+                "geojson-rewind": "geojson-rewind"
+            }
+        },
+        "node_modules/@mapbox/geojson-rewind/node_modules/get-stream": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+            "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/@mapbox/jsonlint-lines-primitives": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
+            "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==",
+            "engines": {
+                "node": ">= 0.6"
+            }
+        },
+        "node_modules/@mapbox/mapbox-gl-supported": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz",
+            "integrity": "sha512-HP6XvfNIzfoMVfyGjBckjiAOQK9WfX0ywdLubuPMPv+Vqf5fj0uCbgBQYpiqcWZT6cbyyRnTSXDheT1ugvF6UQ=="
+        },
         "node_modules/@mapbox/node-pre-gyp": {
             "version": "1.0.11",
             "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
@@ -3228,6 +3267,55 @@
             "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
             "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
         },
+        "node_modules/@mapbox/point-geometry": {
+            "version": "0.1.0",
+            "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
+            "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ=="
+        },
+        "node_modules/@mapbox/tiny-sdf": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz",
+            "integrity": "sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA=="
+        },
+        "node_modules/@mapbox/unitbezier": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz",
+            "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw=="
+        },
+        "node_modules/@mapbox/vector-tile": {
+            "version": "1.3.1",
+            "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz",
+            "integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==",
+            "dependencies": {
+                "@mapbox/point-geometry": "~0.1.0"
+            }
+        },
+        "node_modules/@mapbox/whoots-js": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz",
+            "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==",
+            "engines": {
+                "node": ">=6.0.0"
+            }
+        },
+        "node_modules/@maplibre/maplibre-gl-style-spec": {
+            "version": "19.3.3",
+            "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz",
+            "integrity": "sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==",
+            "dependencies": {
+                "@mapbox/jsonlint-lines-primitives": "~2.0.2",
+                "@mapbox/unitbezier": "^0.0.1",
+                "json-stringify-pretty-compact": "^3.0.0",
+                "minimist": "^1.2.8",
+                "rw": "^1.3.3",
+                "sort-object": "^3.0.3"
+            },
+            "bin": {
+                "gl-style-format": "dist/gl-style-format.mjs",
+                "gl-style-migrate": "dist/gl-style-migrate.mjs",
+                "gl-style-validate": "dist/gl-style-validate.mjs"
+            }
+        },
         "node_modules/@mongodb-js/saslprep": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.1.tgz",
@@ -3775,11 +3863,1588 @@
             "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
             "dev": true
         },
-        "node_modules/@tsconfig/node16": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
-            "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
-            "dev": true
+        "node_modules/@tsconfig/node16": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+            "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+            "dev": true
+        },
+        "node_modules/@turf/along": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/along/-/along-6.5.0.tgz",
+            "integrity": "sha512-LLyWQ0AARqJCmMcIEAXF4GEu8usmd4Kbz3qk1Oy5HoRNpZX47+i5exQtmIWKdqJ1MMhW26fCTXgpsEs5zgJ5gw==",
+            "dependencies": {
+                "@turf/bearing": "^6.5.0",
+                "@turf/destination": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/angle": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/angle/-/angle-6.5.0.tgz",
+            "integrity": "sha512-4pXMbWhFofJJAOvTMCns6N4C8CMd5Ih4O2jSAG9b3dDHakj3O4yN1+Zbm+NUei+eVEZ9gFeVp9svE3aMDenIkw==",
+            "dependencies": {
+                "@turf/bearing": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/rhumb-bearing": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/area": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/area/-/area-6.5.0.tgz",
+            "integrity": "sha512-xCZdiuojokLbQ+29qR6qoMD89hv+JAgWjLrwSEWL+3JV8IXKeNFl6XkEJz9HGkVpnXvQKJoRz4/liT+8ZZ5Jyg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/bbox": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-6.5.0.tgz",
+            "integrity": "sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/bbox-clip": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/bbox-clip/-/bbox-clip-6.5.0.tgz",
+            "integrity": "sha512-F6PaIRF8WMp8EmgU/Ke5B1Y6/pia14UAYB5TiBC668w5rVVjy5L8rTm/m2lEkkDMHlzoP9vNY4pxpNthE7rLcQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/bbox-polygon": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/bbox-polygon/-/bbox-polygon-6.5.0.tgz",
+            "integrity": "sha512-+/r0NyL1lOG3zKZmmf6L8ommU07HliP4dgYToMoTxqzsWzyLjaj/OzgQ8rBmv703WJX+aS6yCmLuIhYqyufyuw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/bearing": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/bearing/-/bearing-6.5.0.tgz",
+            "integrity": "sha512-dxINYhIEMzgDOztyMZc20I7ssYVNEpSv04VbMo5YPQsqa80KO3TFvbuCahMsCAW5z8Tncc8dwBlEFrmRjJG33A==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/bezier-spline": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/bezier-spline/-/bezier-spline-6.5.0.tgz",
+            "integrity": "sha512-vokPaurTd4PF96rRgGVm6zYYC5r1u98ZsG+wZEv9y3kJTuJRX/O3xIY2QnTGTdbVmAJN1ouOsD0RoZYaVoXORQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-clockwise": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-6.5.0.tgz",
+            "integrity": "sha512-45+C7LC5RMbRWrxh3Z0Eihsc8db1VGBO5d9BLTOAwU4jR6SgsunTfRWR16X7JUwIDYlCVEmnjcXJNi/kIU3VIw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-contains": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-contains/-/boolean-contains-6.5.0.tgz",
+            "integrity": "sha512-4m8cJpbw+YQcKVGi8y0cHhBUnYT+QRfx6wzM4GI1IdtYH3p4oh/DOBJKrepQyiDzFDaNIjxuWXBh0ai1zVwOQQ==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/boolean-point-on-line": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-crosses": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-crosses/-/boolean-crosses-6.5.0.tgz",
+            "integrity": "sha512-gvshbTPhAHporTlQwBJqyfW+2yV8q/mOTxG6PzRVl6ARsqNoqYQWkd4MLug7OmAqVyBzLK3201uAeBjxbGw0Ng==",
+            "dependencies": {
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/line-intersect": "^6.5.0",
+                "@turf/polygon-to-line": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-disjoint": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-disjoint/-/boolean-disjoint-6.5.0.tgz",
+            "integrity": "sha512-rZ2ozlrRLIAGo2bjQ/ZUu4oZ/+ZjGvLkN5CKXSKBcu6xFO6k2bgqeM8a1836tAW+Pqp/ZFsTA5fZHsJZvP2D5g==",
+            "dependencies": {
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/line-intersect": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/polygon-to-line": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-equal": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-equal/-/boolean-equal-6.5.0.tgz",
+            "integrity": "sha512-cY0M3yoLC26mhAnjv1gyYNQjn7wxIXmL2hBmI/qs8g5uKuC2hRWi13ydufE3k4x0aNRjFGlg41fjoYLwaVF+9Q==",
+            "dependencies": {
+                "@turf/clean-coords": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "geojson-equality": "0.1.6"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-intersects": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-intersects/-/boolean-intersects-6.5.0.tgz",
+            "integrity": "sha512-nIxkizjRdjKCYFQMnml6cjPsDOBCThrt+nkqtSEcxkKMhAQj5OO7o2CecioNTaX8EayqwMGVKcsz27oP4mKPTw==",
+            "dependencies": {
+                "@turf/boolean-disjoint": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-overlap": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-overlap/-/boolean-overlap-6.5.0.tgz",
+            "integrity": "sha512-8btMIdnbXVWUa1M7D4shyaSGxLRw6NjMcqKBcsTXcZdnaixl22k7ar7BvIzkaRYN3SFECk9VGXfLncNS3ckQUw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/line-intersect": "^6.5.0",
+                "@turf/line-overlap": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "geojson-equality": "0.1.6"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-parallel": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-parallel/-/boolean-parallel-6.5.0.tgz",
+            "integrity": "sha512-aSHJsr1nq9e5TthZGZ9CZYeXklJyRgR5kCLm5X4urz7+MotMOp/LsGOsvKvK9NeUl9+8OUmfMn8EFTT8LkcvIQ==",
+            "dependencies": {
+                "@turf/clean-coords": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/line-segment": "^6.5.0",
+                "@turf/rhumb-bearing": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-point-in-polygon": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-6.5.0.tgz",
+            "integrity": "sha512-DtSuVFB26SI+hj0SjrvXowGTUCHlgevPAIsukssW6BG5MlNSBQAo70wpICBNJL6RjukXg8d2eXaAWuD/CqL00A==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-point-on-line": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-point-on-line/-/boolean-point-on-line-6.5.0.tgz",
+            "integrity": "sha512-A1BbuQ0LceLHvq7F/P7w3QvfpmZqbmViIUPHdNLvZimFNLo4e6IQunmzbe+8aSStH9QRZm3VOflyvNeXvvpZEQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/boolean-within": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/boolean-within/-/boolean-within-6.5.0.tgz",
+            "integrity": "sha512-YQB3oU18Inx35C/LU930D36RAVe7LDXk1kWsQ8mLmuqYn9YdPsDQTMTkLJMhoQ8EbN7QTdy333xRQ4MYgToteQ==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/boolean-point-on-line": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/buffer": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/buffer/-/buffer-6.5.0.tgz",
+            "integrity": "sha512-qeX4N6+PPWbKqp1AVkBVWFerGjMYMUyencwfnkCesoznU6qvfugFHNAngNqIBVnJjZ5n8IFyOf+akcxnrt9sNg==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/center": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/projection": "^6.5.0",
+                "d3-geo": "1.7.1",
+                "turf-jsts": "*"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/buffer/node_modules/d3-array": {
+            "version": "1.2.4",
+            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
+            "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
+        },
+        "node_modules/@turf/buffer/node_modules/d3-geo": {
+            "version": "1.7.1",
+            "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.7.1.tgz",
+            "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==",
+            "dependencies": {
+                "d3-array": "1"
+            }
+        },
+        "node_modules/@turf/center": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/center/-/center-6.5.0.tgz",
+            "integrity": "sha512-T8KtMTfSATWcAX088rEDKjyvQCBkUsLnK/Txb6/8WUXIeOZyHu42G7MkdkHRoHtwieLdduDdmPLFyTdG5/e7ZQ==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/center-mean": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/center-mean/-/center-mean-6.5.0.tgz",
+            "integrity": "sha512-AAX6f4bVn12pTVrMUiB9KrnV94BgeBKpyg3YpfnEbBpkN/znfVhL8dG8IxMAxAoSZ61Zt9WLY34HfENveuOZ7Q==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/center-median": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/center-median/-/center-median-6.5.0.tgz",
+            "integrity": "sha512-dT8Ndu5CiZkPrj15PBvslpuf01ky41DEYEPxS01LOxp5HOUHXp1oJxsPxvc+i/wK4BwccPNzU1vzJ0S4emd1KQ==",
+            "dependencies": {
+                "@turf/center-mean": "^6.5.0",
+                "@turf/centroid": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/center-of-mass": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/center-of-mass/-/center-of-mass-6.5.0.tgz",
+            "integrity": "sha512-EWrriU6LraOfPN7m1jZi+1NLTKNkuIsGLZc2+Y8zbGruvUW+QV7K0nhf7iZWutlxHXTBqEXHbKue/o79IumAsQ==",
+            "dependencies": {
+                "@turf/centroid": "^6.5.0",
+                "@turf/convex": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/centroid": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-6.5.0.tgz",
+            "integrity": "sha512-MwE1oq5E3isewPprEClbfU5pXljIK/GUOMbn22UM3IFPDJX0KeoyLNwghszkdmFp/qMGL/M13MMWvU+GNLXP/A==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/circle": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/circle/-/circle-6.5.0.tgz",
+            "integrity": "sha512-oU1+Kq9DgRnoSbWFHKnnUdTmtcRUMmHoV9DjTXu9vOLNV5OWtAAh1VZ+mzsioGGzoDNT/V5igbFOkMfBQc0B6A==",
+            "dependencies": {
+                "@turf/destination": "^6.5.0",
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/clean-coords": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/clean-coords/-/clean-coords-6.5.0.tgz",
+            "integrity": "sha512-EMX7gyZz0WTH/ET7xV8MyrExywfm9qUi0/MY89yNffzGIEHuFfqwhcCqZ8O00rZIPZHUTxpmsxQSTfzJJA1CPw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/clone": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-6.5.0.tgz",
+            "integrity": "sha512-mzVtTFj/QycXOn6ig+annKrM6ZlimreKYz6f/GSERytOpgzodbQyOgkfwru100O1KQhhjSudKK4DsQ0oyi9cTw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/clusters": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/clusters/-/clusters-6.5.0.tgz",
+            "integrity": "sha512-Y6gfnTJzQ1hdLfCsyd5zApNbfLIxYEpmDibHUqR5z03Lpe02pa78JtgrgUNt1seeO/aJ4TG1NLN8V5gOrHk04g==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/clusters-dbscan": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/clusters-dbscan/-/clusters-dbscan-6.5.0.tgz",
+            "integrity": "sha512-SxZEE4kADU9DqLRiT53QZBBhu8EP9skviSyl+FGj08Y01xfICM/RR9ACUdM0aEQimhpu+ZpRVcUK+2jtiCGrYQ==",
+            "dependencies": {
+                "@turf/clone": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "density-clustering": "1.3.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/clusters-kmeans": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/clusters-kmeans/-/clusters-kmeans-6.5.0.tgz",
+            "integrity": "sha512-DwacD5+YO8kwDPKaXwT9DV46tMBVNsbi1IzdajZu1JDSWoN7yc7N9Qt88oi+p30583O0UPVkAK+A10WAQv4mUw==",
+            "dependencies": {
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "skmeans": "0.9.7"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/collect": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/collect/-/collect-6.5.0.tgz",
+            "integrity": "sha512-4dN/T6LNnRg099m97BJeOcTA5fSI8cu87Ydgfibewd2KQwBexO69AnjEFqfPX3Wj+Zvisj1uAVIZbPmSSrZkjg==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "rbush": "2.x"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/combine": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/combine/-/combine-6.5.0.tgz",
+            "integrity": "sha512-Q8EIC4OtAcHiJB3C4R+FpB4LANiT90t17uOd851qkM2/o6m39bfN5Mv0PWqMZIHWrrosZqRqoY9dJnzz/rJxYQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/concave": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/concave/-/concave-6.5.0.tgz",
+            "integrity": "sha512-I/sUmUC8TC5h/E2vPwxVht+nRt+TnXIPRoztDFvS8/Y0+cBDple9inLSo9nnPXMXidrBlGXZ9vQx/BjZUJgsRQ==",
+            "dependencies": {
+                "@turf/clone": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/tin": "^6.5.0",
+                "topojson-client": "3.x",
+                "topojson-server": "3.x"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/convex": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/convex/-/convex-6.5.0.tgz",
+            "integrity": "sha512-x7ZwC5z7PJB0SBwNh7JCeCNx7Iu+QSrH7fYgK0RhhNop13TqUlvHMirMLRgf2db1DqUetrAO2qHJeIuasquUWg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "concaveman": "*"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/destination": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/destination/-/destination-6.5.0.tgz",
+            "integrity": "sha512-4cnWQlNC8d1tItOz9B4pmJdWpXqS0vEvv65bI/Pj/genJnsL7evI0/Xw42RvEGROS481MPiU80xzvwxEvhQiMQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/difference": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/difference/-/difference-6.5.0.tgz",
+            "integrity": "sha512-l8iR5uJqvI+5Fs6leNbhPY5t/a3vipUF/3AeVLpwPQcgmedNXyheYuy07PcMGH5Jdpi5gItOiTqwiU/bUH4b3A==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "polygon-clipping": "^0.15.3"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/dissolve": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/dissolve/-/dissolve-6.5.0.tgz",
+            "integrity": "sha512-WBVbpm9zLTp0Bl9CE35NomTaOL1c4TQCtEoO43YaAhNEWJOOIhZMFJyr8mbvYruKl817KinT3x7aYjjCMjTAsQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "polygon-clipping": "^0.15.3"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/distance": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-6.5.0.tgz",
+            "integrity": "sha512-xzykSLfoURec5qvQJcfifw/1mJa+5UwByZZ5TZ8iaqjGYN0vomhV9aiSLeYdUGtYRESZ+DYC/OzY+4RclZYgMg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/distance-weight": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/distance-weight/-/distance-weight-6.5.0.tgz",
+            "integrity": "sha512-a8qBKkgVNvPKBfZfEJZnC3DV7dfIsC3UIdpRci/iap/wZLH41EmS90nM+BokAJflUHYy8PqE44wySGWHN1FXrQ==",
+            "dependencies": {
+                "@turf/centroid": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/ellipse": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/ellipse/-/ellipse-6.5.0.tgz",
+            "integrity": "sha512-kuXtwFviw/JqnyJXF1mrR/cb496zDTSbGKtSiolWMNImYzGGkbsAsFTjwJYgD7+4FixHjp0uQPzo70KDf3AIBw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/rhumb-destination": "^6.5.0",
+                "@turf/transform-rotate": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/envelope": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/envelope/-/envelope-6.5.0.tgz",
+            "integrity": "sha512-9Z+FnBWvOGOU4X+fMZxYFs1HjFlkKqsddLuMknRaqcJd6t+NIv5DWvPtDL8ATD2GEExYDiFLwMdckfr1yqJgHA==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/bbox-polygon": "^6.5.0",
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/explode": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/explode/-/explode-6.5.0.tgz",
+            "integrity": "sha512-6cSvMrnHm2qAsace6pw9cDmK2buAlw8+tjeJVXMfMyY+w7ZUi1rprWMsY92J7s2Dar63Bv09n56/1V7+tcj52Q==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/flatten": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/flatten/-/flatten-6.5.0.tgz",
+            "integrity": "sha512-IBZVwoNLVNT6U/bcUUllubgElzpMsNoCw8tLqBw6dfYg9ObGmpEjf9BIYLr7a2Yn5ZR4l7YIj2T7kD5uJjZADQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/flip": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/flip/-/flip-6.5.0.tgz",
+            "integrity": "sha512-oyikJFNjt2LmIXQqgOGLvt70RgE2lyzPMloYWM7OR5oIFGRiBvqVD2hA6MNw6JewIm30fWZ8DQJw1NHXJTJPbg==",
+            "dependencies": {
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/great-circle": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/great-circle/-/great-circle-6.5.0.tgz",
+            "integrity": "sha512-7ovyi3HaKOXdFyN7yy1yOMa8IyOvV46RC1QOQTT+RYUN8ke10eyqExwBpL9RFUPvlpoTzoYbM/+lWPogQlFncg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/helpers": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.5.0.tgz",
+            "integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==",
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/hex-grid": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/hex-grid/-/hex-grid-6.5.0.tgz",
+            "integrity": "sha512-Ln3tc2tgZT8etDOldgc6e741Smg1CsMKAz1/Mlel+MEL5Ynv2mhx3m0q4J9IB1F3a4MNjDeVvm8drAaf9SF33g==",
+            "dependencies": {
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/intersect": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/interpolate": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/interpolate/-/interpolate-6.5.0.tgz",
+            "integrity": "sha512-LSH5fMeiGyuDZ4WrDJNgh81d2DnNDUVJtuFryJFup8PV8jbs46lQGfI3r1DJ2p1IlEJIz3pmAZYeTfMMoeeohw==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/centroid": "^6.5.0",
+                "@turf/clone": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/hex-grid": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/point-grid": "^6.5.0",
+                "@turf/square-grid": "^6.5.0",
+                "@turf/triangle-grid": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/intersect": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/intersect/-/intersect-6.5.0.tgz",
+            "integrity": "sha512-2legGJeKrfFkzntcd4GouPugoqPUjexPZnOvfez+3SfIMrHvulw8qV8u7pfVyn2Yqs53yoVCEjS5sEpvQ5YRQg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "polygon-clipping": "^0.15.3"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/invariant": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-6.5.0.tgz",
+            "integrity": "sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/isobands": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/isobands/-/isobands-6.5.0.tgz",
+            "integrity": "sha512-4h6sjBPhRwMVuFaVBv70YB7eGz+iw0bhPRnp+8JBdX1UPJSXhoi/ZF2rACemRUr0HkdVB/a1r9gC32vn5IAEkw==",
+            "dependencies": {
+                "@turf/area": "^6.5.0",
+                "@turf/bbox": "^6.5.0",
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/explode": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "object-assign": "*"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/isolines": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/isolines/-/isolines-6.5.0.tgz",
+            "integrity": "sha512-6ElhiLCopxWlv4tPoxiCzASWt/jMRvmp6mRYrpzOm3EUl75OhHKa/Pu6Y9nWtCMmVC/RcWtiiweUocbPLZLm0A==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "object-assign": "*"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/kinks": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/kinks/-/kinks-6.5.0.tgz",
+            "integrity": "sha512-ViCngdPt1eEL7hYUHR2eHR662GvCgTc35ZJFaNR6kRtr6D8plLaDju0FILeFFWSc+o8e3fwxZEJKmFj9IzPiIQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/length": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/length/-/length-6.5.0.tgz",
+            "integrity": "sha512-5pL5/pnw52fck3oRsHDcSGrj9HibvtlrZ0QNy2OcW8qBFDNgZ4jtl6U7eATVoyWPKBHszW3dWETW+iLV7UARig==",
+            "dependencies": {
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-arc": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-arc/-/line-arc-6.5.0.tgz",
+            "integrity": "sha512-I6c+V6mIyEwbtg9P9zSFF89T7QPe1DPTG3MJJ6Cm1MrAY0MdejwQKOpsvNl8LDU2ekHOlz2kHpPVR7VJsoMllA==",
+            "dependencies": {
+                "@turf/circle": "^6.5.0",
+                "@turf/destination": "^6.5.0",
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-chunk": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-chunk/-/line-chunk-6.5.0.tgz",
+            "integrity": "sha512-i1FGE6YJaaYa+IJesTfyRRQZP31QouS+wh/pa6O3CC0q4T7LtHigyBSYjrbjSLfn2EVPYGlPCMFEqNWCOkC6zg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/length": "^6.5.0",
+                "@turf/line-slice-along": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-intersect": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-intersect/-/line-intersect-6.5.0.tgz",
+            "integrity": "sha512-CS6R1tZvVQD390G9Ea4pmpM6mJGPWoL82jD46y0q1KSor9s6HupMIo1kY4Ny+AEYQl9jd21V3Scz20eldpbTVA==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/line-segment": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "geojson-rbush": "3.x"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-offset": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-offset/-/line-offset-6.5.0.tgz",
+            "integrity": "sha512-CEXZbKgyz8r72qRvPchK0dxqsq8IQBdH275FE6o4MrBkzMcoZsfSjghtXzKaz9vvro+HfIXal0sTk2mqV1lQTw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-overlap": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-overlap/-/line-overlap-6.5.0.tgz",
+            "integrity": "sha512-xHOaWLd0hkaC/1OLcStCpfq55lPHpPNadZySDXYiYjEz5HXr1oKmtMYpn0wGizsLwrOixRdEp+j7bL8dPt4ojQ==",
+            "dependencies": {
+                "@turf/boolean-point-on-line": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/line-segment": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/nearest-point-on-line": "^6.5.0",
+                "deep-equal": "1.x",
+                "geojson-rbush": "3.x"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-segment": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-segment/-/line-segment-6.5.0.tgz",
+            "integrity": "sha512-jI625Ho4jSuJESNq66Mmi290ZJ5pPZiQZruPVpmHkUw257Pew0alMmb6YrqYNnLUuiVVONxAAKXUVeeUGtycfw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-slice": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-slice/-/line-slice-6.5.0.tgz",
+            "integrity": "sha512-vDqJxve9tBHhOaVVFXqVjF5qDzGtKWviyjbyi2QnSnxyFAmLlLnBfMX8TLQCAf2GxHibB95RO5FBE6I2KVPRuw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/nearest-point-on-line": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-slice-along": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-slice-along/-/line-slice-along-6.5.0.tgz",
+            "integrity": "sha512-KHJRU6KpHrAj+BTgTNqby6VCTnDzG6a1sJx/I3hNvqMBLvWVA2IrkR9L9DtsQsVY63IBwVdQDqiwCuZLDQh4Ng==",
+            "dependencies": {
+                "@turf/bearing": "^6.5.0",
+                "@turf/destination": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-split": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-split/-/line-split-6.5.0.tgz",
+            "integrity": "sha512-/rwUMVr9OI2ccJjw7/6eTN53URtGThNSD5I0GgxyFXMtxWiloRJ9MTff8jBbtPWrRka/Sh2GkwucVRAEakx9Sw==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/line-intersect": "^6.5.0",
+                "@turf/line-segment": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/nearest-point-on-line": "^6.5.0",
+                "@turf/square": "^6.5.0",
+                "@turf/truncate": "^6.5.0",
+                "geojson-rbush": "3.x"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/line-to-polygon": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/line-to-polygon/-/line-to-polygon-6.5.0.tgz",
+            "integrity": "sha512-qYBuRCJJL8Gx27OwCD1TMijM/9XjRgXH/m/TyuND4OXedBpIWlK5VbTIO2gJ8OCfznBBddpjiObLBrkuxTpN4Q==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/mask": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/mask/-/mask-6.5.0.tgz",
+            "integrity": "sha512-RQha4aU8LpBrmrkH8CPaaoAfk0Egj5OuXtv6HuCQnHeGNOQt3TQVibTA3Sh4iduq4EPxnZfDjgsOeKtrCA19lg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "polygon-clipping": "^0.15.3"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/meta": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.5.0.tgz",
+            "integrity": "sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/midpoint": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/midpoint/-/midpoint-6.5.0.tgz",
+            "integrity": "sha512-MyTzV44IwmVI6ec9fB2OgZ53JGNlgOpaYl9ArKoF49rXpL84F9rNATndbe0+MQIhdkw8IlzA6xVP4lZzfMNVCw==",
+            "dependencies": {
+                "@turf/bearing": "^6.5.0",
+                "@turf/destination": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/moran-index": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/moran-index/-/moran-index-6.5.0.tgz",
+            "integrity": "sha512-ItsnhrU2XYtTtTudrM8so4afBCYWNaB0Mfy28NZwLjB5jWuAsvyV+YW+J88+neK/ougKMTawkmjQqodNJaBeLQ==",
+            "dependencies": {
+                "@turf/distance-weight": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/nearest-point": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/nearest-point/-/nearest-point-6.5.0.tgz",
+            "integrity": "sha512-fguV09QxilZv/p94s8SMsXILIAMiaXI5PATq9d7YWijLxWUj6Q/r43kxyoi78Zmwwh1Zfqz9w+bCYUAxZ5+euA==",
+            "dependencies": {
+                "@turf/clone": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/nearest-point-on-line": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/nearest-point-on-line/-/nearest-point-on-line-6.5.0.tgz",
+            "integrity": "sha512-WthrvddddvmymnC+Vf7BrkHGbDOUu6Z3/6bFYUGv1kxw8tiZ6n83/VG6kHz4poHOfS0RaNflzXSkmCi64fLBlg==",
+            "dependencies": {
+                "@turf/bearing": "^6.5.0",
+                "@turf/destination": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/line-intersect": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/nearest-point-to-line": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/nearest-point-to-line/-/nearest-point-to-line-6.5.0.tgz",
+            "integrity": "sha512-PXV7cN0BVzUZdjj6oeb/ESnzXSfWmEMrsfZSDRgqyZ9ytdiIj/eRsnOXLR13LkTdXVOJYDBuf7xt1mLhM4p6+Q==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/point-to-line-distance": "^6.5.0",
+                "object-assign": "*"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/planepoint": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/planepoint/-/planepoint-6.5.0.tgz",
+            "integrity": "sha512-R3AahA6DUvtFbka1kcJHqZ7DMHmPXDEQpbU5WaglNn7NaCQg9HB0XM0ZfqWcd5u92YXV+Gg8QhC8x5XojfcM4Q==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/point-grid": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/point-grid/-/point-grid-6.5.0.tgz",
+            "integrity": "sha512-Iq38lFokNNtQJnOj/RBKmyt6dlof0yhaHEDELaWHuECm1lIZLY3ZbVMwbs+nXkwTAHjKfS/OtMheUBkw+ee49w==",
+            "dependencies": {
+                "@turf/boolean-within": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/point-on-feature": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/point-on-feature/-/point-on-feature-6.5.0.tgz",
+            "integrity": "sha512-bDpuIlvugJhfcF/0awAQ+QI6Om1Y1FFYE8Y/YdxGRongivix850dTeXCo0mDylFdWFPGDo7Mmh9Vo4VxNwW/TA==",
+            "dependencies": {
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/center": "^6.5.0",
+                "@turf/explode": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/nearest-point": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/point-to-line-distance": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/point-to-line-distance/-/point-to-line-distance-6.5.0.tgz",
+            "integrity": "sha512-opHVQ4vjUhNBly1bob6RWy+F+hsZDH9SA0UW36pIRzfpu27qipU18xup0XXEePfY6+wvhF6yL/WgCO2IbrLqEA==",
+            "dependencies": {
+                "@turf/bearing": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/projection": "^6.5.0",
+                "@turf/rhumb-bearing": "^6.5.0",
+                "@turf/rhumb-distance": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/points-within-polygon": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/points-within-polygon/-/points-within-polygon-6.5.0.tgz",
+            "integrity": "sha512-YyuheKqjliDsBDt3Ho73QVZk1VXX1+zIA2gwWvuz8bR1HXOkcuwk/1J76HuFMOQI3WK78wyAi+xbkx268PkQzQ==",
+            "dependencies": {
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/polygon-smooth": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/polygon-smooth/-/polygon-smooth-6.5.0.tgz",
+            "integrity": "sha512-LO/X/5hfh/Rk4EfkDBpLlVwt3i6IXdtQccDT9rMjXEP32tRgy0VMFmdkNaXoGlSSKf/1mGqLl4y4wHd86DqKbg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/polygon-tangents": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/polygon-tangents/-/polygon-tangents-6.5.0.tgz",
+            "integrity": "sha512-sB4/IUqJMYRQH9jVBwqS/XDitkEfbyqRy+EH/cMRJURTg78eHunvJ708x5r6umXsbiUyQU4eqgPzEylWEQiunw==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/boolean-within": "^6.5.0",
+                "@turf/explode": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/nearest-point": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/polygon-to-line": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/polygon-to-line/-/polygon-to-line-6.5.0.tgz",
+            "integrity": "sha512-5p4n/ij97EIttAq+ewSnKt0ruvuM+LIDzuczSzuHTpq4oS7Oq8yqg5TQ4nzMVuK41r/tALCk7nAoBuw3Su4Gcw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/polygonize": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/polygonize/-/polygonize-6.5.0.tgz",
+            "integrity": "sha512-a/3GzHRaCyzg7tVYHo43QUChCspa99oK4yPqooVIwTC61npFzdrmnywMv0S+WZjHZwK37BrFJGFrZGf6ocmY5w==",
+            "dependencies": {
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/envelope": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/projection": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/projection/-/projection-6.5.0.tgz",
+            "integrity": "sha512-/Pgh9mDvQWWu8HRxqpM+tKz8OzgauV+DiOcr3FCjD6ubDnrrmMJlsf6fFJmggw93mtVPrZRL6yyi9aYCQBOIvg==",
+            "dependencies": {
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/random": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/random/-/random-6.5.0.tgz",
+            "integrity": "sha512-8Q25gQ/XbA7HJAe+eXp4UhcXM9aOOJFaxZ02+XSNwMvY8gtWSCBLVqRcW4OhqilgZ8PeuQDWgBxeo+BIqqFWFQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/rectangle-grid": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/rectangle-grid/-/rectangle-grid-6.5.0.tgz",
+            "integrity": "sha512-yQZ/1vbW68O2KsSB3OZYK+72aWz/Adnf7m2CMKcC+aq6TwjxZjAvlbCOsNUnMAuldRUVN1ph6RXMG4e9KEvKvg==",
+            "dependencies": {
+                "@turf/boolean-intersects": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/rewind": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-6.5.0.tgz",
+            "integrity": "sha512-IoUAMcHWotBWYwSYuYypw/LlqZmO+wcBpn8ysrBNbazkFNkLf3btSDZMkKJO/bvOzl55imr/Xj4fi3DdsLsbzQ==",
+            "dependencies": {
+                "@turf/boolean-clockwise": "^6.5.0",
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/rhumb-bearing": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/rhumb-bearing/-/rhumb-bearing-6.5.0.tgz",
+            "integrity": "sha512-jMyqiMRK4hzREjQmnLXmkJ+VTNTx1ii8vuqRwJPcTlKbNWfjDz/5JqJlb5NaFDcdMpftWovkW5GevfnuzHnOYA==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/rhumb-destination": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/rhumb-destination/-/rhumb-destination-6.5.0.tgz",
+            "integrity": "sha512-RHNP1Oy+7xTTdRrTt375jOZeHceFbjwohPHlr9Hf68VdHHPMAWgAKqiX2YgSWDcvECVmiGaBKWus1Df+N7eE4Q==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/rhumb-distance": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/rhumb-distance/-/rhumb-distance-6.5.0.tgz",
+            "integrity": "sha512-oKp8KFE8E4huC2Z1a1KNcFwjVOqa99isxNOwfo4g3SUABQ6NezjKDDrnvC4yI5YZ3/huDjULLBvhed45xdCrzg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/sample": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/sample/-/sample-6.5.0.tgz",
+            "integrity": "sha512-kSdCwY7el15xQjnXYW520heKUrHwRvnzx8ka4eYxX9NFeOxaFITLW2G7UtXb6LJK8mmPXI8Aexv23F2ERqzGFg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/sector": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/sector/-/sector-6.5.0.tgz",
+            "integrity": "sha512-cYUOkgCTWqa23SOJBqxoFAc/yGCUsPRdn/ovbRTn1zNTm/Spmk6hVB84LCKOgHqvSF25i0d2kWqpZDzLDdAPbw==",
+            "dependencies": {
+                "@turf/circle": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/line-arc": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/shortest-path": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/shortest-path/-/shortest-path-6.5.0.tgz",
+            "integrity": "sha512-4de5+G7+P4hgSoPwn+SO9QSi9HY5NEV/xRJ+cmoFVRwv2CDsuOPDheHKeuIAhKyeKDvPvPt04XYWbac4insJMg==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/bbox-polygon": "^6.5.0",
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/clean-coords": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/transform-scale": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/simplify": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/simplify/-/simplify-6.5.0.tgz",
+            "integrity": "sha512-USas3QqffPHUY184dwQdP8qsvcVH/PWBYdXY5am7YTBACaQOMAlf6AKJs9FT8jiO6fQpxfgxuEtwmox+pBtlOg==",
+            "dependencies": {
+                "@turf/clean-coords": "^6.5.0",
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/square": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/square/-/square-6.5.0.tgz",
+            "integrity": "sha512-BM2UyWDmiuHCadVhHXKIx5CQQbNCpOxB6S/aCNOCLbhCeypKX5Q0Aosc5YcmCJgkwO5BERCC6Ee7NMbNB2vHmQ==",
+            "dependencies": {
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/square-grid": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/square-grid/-/square-grid-6.5.0.tgz",
+            "integrity": "sha512-mlR0ayUdA+L4c9h7p4k3pX6gPWHNGuZkt2c5II1TJRmhLkW2557d6b/Vjfd1z9OVaajb1HinIs1FMSAPXuuUrA==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/rectangle-grid": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/standard-deviational-ellipse": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/standard-deviational-ellipse/-/standard-deviational-ellipse-6.5.0.tgz",
+            "integrity": "sha512-02CAlz8POvGPFK2BKK8uHGUk/LXb0MK459JVjKxLC2yJYieOBTqEbjP0qaWhiBhGzIxSMaqe8WxZ0KvqdnstHA==",
+            "dependencies": {
+                "@turf/center-mean": "^6.5.0",
+                "@turf/ellipse": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/points-within-polygon": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/tag": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/tag/-/tag-6.5.0.tgz",
+            "integrity": "sha512-XwlBvrOV38CQsrNfrxvBaAPBQgXMljeU0DV8ExOyGM7/hvuGHJw3y8kKnQ4lmEQcmcrycjDQhP7JqoRv8vFssg==",
+            "dependencies": {
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/tesselate": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/tesselate/-/tesselate-6.5.0.tgz",
+            "integrity": "sha512-M1HXuyZFCfEIIKkglh/r5L9H3c5QTEsnMBoZOFQiRnGPGmJWcaBissGb7mTFX2+DKE7FNWXh4TDnZlaLABB0dQ==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "earcut": "^2.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/tin": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/tin/-/tin-6.5.0.tgz",
+            "integrity": "sha512-YLYikRzKisfwj7+F+Tmyy/LE3d2H7D4kajajIfc9mlik2+esG7IolsX/+oUz1biguDYsG0DUA8kVYXDkobukfg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/transform-rotate": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/transform-rotate/-/transform-rotate-6.5.0.tgz",
+            "integrity": "sha512-A2Ip1v4246ZmpssxpcL0hhiVBEf4L8lGnSPWTgSv5bWBEoya2fa/0SnFX9xJgP40rMP+ZzRaCN37vLHbv1Guag==",
+            "dependencies": {
+                "@turf/centroid": "^6.5.0",
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/rhumb-bearing": "^6.5.0",
+                "@turf/rhumb-destination": "^6.5.0",
+                "@turf/rhumb-distance": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/transform-scale": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/transform-scale/-/transform-scale-6.5.0.tgz",
+            "integrity": "sha512-VsATGXC9rYM8qTjbQJ/P7BswKWXHdnSJ35JlV4OsZyHBMxJQHftvmZJsFbOqVtQnIQIzf2OAly6rfzVV9QLr7g==",
+            "dependencies": {
+                "@turf/bbox": "^6.5.0",
+                "@turf/center": "^6.5.0",
+                "@turf/centroid": "^6.5.0",
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/rhumb-bearing": "^6.5.0",
+                "@turf/rhumb-destination": "^6.5.0",
+                "@turf/rhumb-distance": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/transform-translate": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/transform-translate/-/transform-translate-6.5.0.tgz",
+            "integrity": "sha512-NABLw5VdtJt/9vSstChp93pc6oel4qXEos56RBMsPlYB8hzNTEKYtC146XJvyF4twJeeYS8RVe1u7KhoFwEM5w==",
+            "dependencies": {
+                "@turf/clone": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/rhumb-destination": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/triangle-grid": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/triangle-grid/-/triangle-grid-6.5.0.tgz",
+            "integrity": "sha512-2jToUSAS1R1htq4TyLQYPTIsoy6wg3e3BQXjm2rANzw4wPQCXGOxrur1Fy9RtzwqwljlC7DF4tg0OnWr8RjmfA==",
+            "dependencies": {
+                "@turf/distance": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/intersect": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/truncate": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/truncate/-/truncate-6.5.0.tgz",
+            "integrity": "sha512-pFxg71pLk+eJj134Z9yUoRhIi8vqnnKvCYwdT4x/DQl/19RVdq1tV3yqOT3gcTQNfniteylL5qV1uTBDV5sgrg==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/turf": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/turf/-/turf-6.5.0.tgz",
+            "integrity": "sha512-ipMCPnhu59bh92MNt8+pr1VZQhHVuTMHklciQURo54heoxRzt1neNYZOBR6jdL+hNsbDGAECMuIpAutX+a3Y+w==",
+            "dependencies": {
+                "@turf/along": "^6.5.0",
+                "@turf/angle": "^6.5.0",
+                "@turf/area": "^6.5.0",
+                "@turf/bbox": "^6.5.0",
+                "@turf/bbox-clip": "^6.5.0",
+                "@turf/bbox-polygon": "^6.5.0",
+                "@turf/bearing": "^6.5.0",
+                "@turf/bezier-spline": "^6.5.0",
+                "@turf/boolean-clockwise": "^6.5.0",
+                "@turf/boolean-contains": "^6.5.0",
+                "@turf/boolean-crosses": "^6.5.0",
+                "@turf/boolean-disjoint": "^6.5.0",
+                "@turf/boolean-equal": "^6.5.0",
+                "@turf/boolean-intersects": "^6.5.0",
+                "@turf/boolean-overlap": "^6.5.0",
+                "@turf/boolean-parallel": "^6.5.0",
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/boolean-point-on-line": "^6.5.0",
+                "@turf/boolean-within": "^6.5.0",
+                "@turf/buffer": "^6.5.0",
+                "@turf/center": "^6.5.0",
+                "@turf/center-mean": "^6.5.0",
+                "@turf/center-median": "^6.5.0",
+                "@turf/center-of-mass": "^6.5.0",
+                "@turf/centroid": "^6.5.0",
+                "@turf/circle": "^6.5.0",
+                "@turf/clean-coords": "^6.5.0",
+                "@turf/clone": "^6.5.0",
+                "@turf/clusters": "^6.5.0",
+                "@turf/clusters-dbscan": "^6.5.0",
+                "@turf/clusters-kmeans": "^6.5.0",
+                "@turf/collect": "^6.5.0",
+                "@turf/combine": "^6.5.0",
+                "@turf/concave": "^6.5.0",
+                "@turf/convex": "^6.5.0",
+                "@turf/destination": "^6.5.0",
+                "@turf/difference": "^6.5.0",
+                "@turf/dissolve": "^6.5.0",
+                "@turf/distance": "^6.5.0",
+                "@turf/distance-weight": "^6.5.0",
+                "@turf/ellipse": "^6.5.0",
+                "@turf/envelope": "^6.5.0",
+                "@turf/explode": "^6.5.0",
+                "@turf/flatten": "^6.5.0",
+                "@turf/flip": "^6.5.0",
+                "@turf/great-circle": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/hex-grid": "^6.5.0",
+                "@turf/interpolate": "^6.5.0",
+                "@turf/intersect": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "@turf/isobands": "^6.5.0",
+                "@turf/isolines": "^6.5.0",
+                "@turf/kinks": "^6.5.0",
+                "@turf/length": "^6.5.0",
+                "@turf/line-arc": "^6.5.0",
+                "@turf/line-chunk": "^6.5.0",
+                "@turf/line-intersect": "^6.5.0",
+                "@turf/line-offset": "^6.5.0",
+                "@turf/line-overlap": "^6.5.0",
+                "@turf/line-segment": "^6.5.0",
+                "@turf/line-slice": "^6.5.0",
+                "@turf/line-slice-along": "^6.5.0",
+                "@turf/line-split": "^6.5.0",
+                "@turf/line-to-polygon": "^6.5.0",
+                "@turf/mask": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "@turf/midpoint": "^6.5.0",
+                "@turf/moran-index": "^6.5.0",
+                "@turf/nearest-point": "^6.5.0",
+                "@turf/nearest-point-on-line": "^6.5.0",
+                "@turf/nearest-point-to-line": "^6.5.0",
+                "@turf/planepoint": "^6.5.0",
+                "@turf/point-grid": "^6.5.0",
+                "@turf/point-on-feature": "^6.5.0",
+                "@turf/point-to-line-distance": "^6.5.0",
+                "@turf/points-within-polygon": "^6.5.0",
+                "@turf/polygon-smooth": "^6.5.0",
+                "@turf/polygon-tangents": "^6.5.0",
+                "@turf/polygon-to-line": "^6.5.0",
+                "@turf/polygonize": "^6.5.0",
+                "@turf/projection": "^6.5.0",
+                "@turf/random": "^6.5.0",
+                "@turf/rewind": "^6.5.0",
+                "@turf/rhumb-bearing": "^6.5.0",
+                "@turf/rhumb-destination": "^6.5.0",
+                "@turf/rhumb-distance": "^6.5.0",
+                "@turf/sample": "^6.5.0",
+                "@turf/sector": "^6.5.0",
+                "@turf/shortest-path": "^6.5.0",
+                "@turf/simplify": "^6.5.0",
+                "@turf/square": "^6.5.0",
+                "@turf/square-grid": "^6.5.0",
+                "@turf/standard-deviational-ellipse": "^6.5.0",
+                "@turf/tag": "^6.5.0",
+                "@turf/tesselate": "^6.5.0",
+                "@turf/tin": "^6.5.0",
+                "@turf/transform-rotate": "^6.5.0",
+                "@turf/transform-scale": "^6.5.0",
+                "@turf/transform-translate": "^6.5.0",
+                "@turf/triangle-grid": "^6.5.0",
+                "@turf/truncate": "^6.5.0",
+                "@turf/union": "^6.5.0",
+                "@turf/unkink-polygon": "^6.5.0",
+                "@turf/voronoi": "^6.5.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/union": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/union/-/union-6.5.0.tgz",
+            "integrity": "sha512-igYWCwP/f0RFHIlC2c0SKDuM/ObBaqSljI3IdV/x71805QbIvY/BYGcJdyNcgEA6cylIGl/0VSlIbpJHZ9ldhw==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "polygon-clipping": "^0.15.3"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/unkink-polygon": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/unkink-polygon/-/unkink-polygon-6.5.0.tgz",
+            "integrity": "sha512-8QswkzC0UqKmN1DT6HpA9upfa1HdAA5n6bbuzHy8NJOX8oVizVAqfEPY0wqqTgboDjmBR4yyImsdPGUl3gZ8JQ==",
+            "dependencies": {
+                "@turf/area": "^6.5.0",
+                "@turf/boolean-point-in-polygon": "^6.5.0",
+                "@turf/helpers": "^6.5.0",
+                "@turf/meta": "^6.5.0",
+                "rbush": "^2.0.1"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
+        },
+        "node_modules/@turf/voronoi": {
+            "version": "6.5.0",
+            "resolved": "https://registry.npmjs.org/@turf/voronoi/-/voronoi-6.5.0.tgz",
+            "integrity": "sha512-C/xUsywYX+7h1UyNqnydHXiun4UPjK88VDghtoRypR9cLlb7qozkiLRphQxxsCM0KxyxpVPHBVQXdAL3+Yurow==",
+            "dependencies": {
+                "@turf/helpers": "^6.5.0",
+                "@turf/invariant": "^6.5.0",
+                "d3-voronoi": "1.1.2"
+            },
+            "funding": {
+                "url": "https://opencollective.com/turf"
+            }
         },
         "node_modules/@types/adm-zip": {
             "version": "0.5.5",
@@ -4415,6 +6080,14 @@
             "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==",
             "dev": true
         },
+        "node_modules/@types/mapbox-gl": {
+            "version": "2.7.19",
+            "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-2.7.19.tgz",
+            "integrity": "sha512-pkRdlhQJNbtwcKJSVC4uuOA6M3OlOObIMhNecqHB991oeaDF5XkjSIRaTE0lh5p4KClptSCxW6MBiREVRHrl2A==",
+            "dependencies": {
+                "@types/geojson": "*"
+            }
+        },
         "node_modules/@types/mdast": {
             "version": "4.0.3",
             "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz",
@@ -5496,6 +7169,14 @@
                 "dequal": "^2.0.3"
             }
         },
+        "node_modules/arr-union": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+            "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/array-back": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz",
@@ -5703,6 +7384,14 @@
                 "node": "*"
             }
         },
+        "node_modules/assign-symbols": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+            "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/ast-types-flow": {
             "version": "0.0.8",
             "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
@@ -9255,6 +10944,23 @@
                 "node": ">= 0.8"
             }
         },
+        "node_modules/bytewise": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz",
+            "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==",
+            "dependencies": {
+                "bytewise-core": "^1.2.2",
+                "typewise": "^1.0.3"
+            }
+        },
+        "node_modules/bytewise-core": {
+            "version": "1.2.3",
+            "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz",
+            "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==",
+            "dependencies": {
+                "typewise-core": "^1.2"
+            }
+        },
         "node_modules/cacheable-lookup": {
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz",
@@ -9503,6 +11209,11 @@
                 "pnpm": ">=7"
             }
         },
+        "node_modules/cheap-ruler": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-3.0.2.tgz",
+            "integrity": "sha512-02T332h1/HTN6cDSufLP8x4JzDs2+VC+8qZ/N0kWIVPyc2xUkWwWh3B2fJxR7raXkL4Mq7k554mfuM9ofv/vGg=="
+        },
         "node_modules/check-error": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
@@ -9920,6 +11631,35 @@
             "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
             "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
         },
+        "node_modules/concaveman": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/concaveman/-/concaveman-1.2.1.tgz",
+            "integrity": "sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw==",
+            "dependencies": {
+                "point-in-polygon": "^1.1.0",
+                "rbush": "^3.0.1",
+                "robust-predicates": "^2.0.4",
+                "tinyqueue": "^2.0.3"
+            }
+        },
+        "node_modules/concaveman/node_modules/quickselect": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
+            "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
+        },
+        "node_modules/concaveman/node_modules/rbush": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz",
+            "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==",
+            "dependencies": {
+                "quickselect": "^2.0.0"
+            }
+        },
+        "node_modules/concaveman/node_modules/robust-predicates": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz",
+            "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg=="
+        },
         "node_modules/confusing-browser-globals": {
             "version": "1.0.11",
             "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz",
@@ -10344,6 +12084,11 @@
                 "url": "https://github.com/sponsors/fb55"
             }
         },
+        "node_modules/csscolorparser": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
+            "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w=="
+        },
         "node_modules/cssesc": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -10768,6 +12513,11 @@
                 "d3-selection": "2 - 3"
             }
         },
+        "node_modules/d3-voronoi": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz",
+            "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw=="
+        },
         "node_modules/d3-zoom": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
@@ -10932,6 +12682,25 @@
                 "node": ">=6"
             }
         },
+        "node_modules/deep-equal": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
+            "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
+            "dependencies": {
+                "is-arguments": "^1.1.1",
+                "is-date-object": "^1.0.5",
+                "is-regex": "^1.1.4",
+                "object-is": "^1.1.5",
+                "object-keys": "^1.1.1",
+                "regexp.prototype.flags": "^1.5.1"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
         "node_modules/deep-extend": {
             "version": "0.6.0",
             "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -11126,7 +12895,6 @@
             "version": "1.2.1",
             "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
             "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
-            "dev": true,
             "dependencies": {
                 "define-data-property": "^1.0.1",
                 "has-property-descriptors": "^1.0.0",
@@ -11160,6 +12928,11 @@
             "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
             "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
         },
+        "node_modules/density-clustering": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/density-clustering/-/density-clustering-1.3.0.tgz",
+            "integrity": "sha512-icpmBubVTwLnsaor9qH/4tG5+7+f61VcqMN3V3pm9sxxSCt2Jcs0zWOgwZW9ARJYaKD3FumIgHiMOcIMRRAzFQ=="
+        },
         "node_modules/depcheck": {
             "version": "1.4.7",
             "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-1.4.7.tgz",
@@ -11465,6 +13238,11 @@
                 "xtend": "^4.0.0"
             }
         },
+        "node_modules/earcut": {
+            "version": "2.2.4",
+            "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
+            "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
+        },
         "node_modules/eastasianwidth": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -13674,6 +15452,17 @@
             "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
             "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
         },
+        "node_modules/extend-shallow": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+            "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+            "dependencies": {
+                "is-extendable": "^0.1.0"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/external-editor": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
@@ -14601,7 +16390,6 @@
             "version": "1.2.3",
             "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
             "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
-            "dev": true,
             "funding": {
                 "url": "https://github.com/sponsors/ljharb"
             }
@@ -14701,6 +16489,49 @@
                 "node": ">=6.9.0"
             }
         },
+        "node_modules/geojson-equality": {
+            "version": "0.1.6",
+            "resolved": "https://registry.npmjs.org/geojson-equality/-/geojson-equality-0.1.6.tgz",
+            "integrity": "sha512-TqG8YbqizP3EfwP5Uw4aLu6pKkg6JQK9uq/XZ1lXQntvTHD1BBKJWhNpJ2M0ax6TuWMP3oyx6Oq7FCIfznrgpQ==",
+            "dependencies": {
+                "deep-equal": "^1.0.0"
+            }
+        },
+        "node_modules/geojson-rbush": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/geojson-rbush/-/geojson-rbush-3.2.0.tgz",
+            "integrity": "sha512-oVltQTXolxvsz1sZnutlSuLDEcQAKYC/uXt9zDzJJ6bu0W+baTI8LZBaTup5afzibEH4N3jlq2p+a152wlBJ7w==",
+            "dependencies": {
+                "@turf/bbox": "*",
+                "@turf/helpers": "6.x",
+                "@turf/meta": "6.x",
+                "@types/geojson": "7946.0.8",
+                "rbush": "^3.0.1"
+            }
+        },
+        "node_modules/geojson-rbush/node_modules/@types/geojson": {
+            "version": "7946.0.8",
+            "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz",
+            "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA=="
+        },
+        "node_modules/geojson-rbush/node_modules/quickselect": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
+            "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
+        },
+        "node_modules/geojson-rbush/node_modules/rbush": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz",
+            "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==",
+            "dependencies": {
+                "quickselect": "^2.0.0"
+            }
+        },
+        "node_modules/geojson-vt": {
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz",
+            "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg=="
+        },
         "node_modules/get-caller-file": {
             "version": "2.0.5",
             "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -14780,6 +16611,14 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/get-value": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+            "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/getpass": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -14797,6 +16636,11 @@
                 "omggif": "^1.0.10"
             }
         },
+        "node_modules/gl-matrix": {
+            "version": "3.4.3",
+            "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
+            "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
+        },
         "node_modules/glob": {
             "version": "8.1.0",
             "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
@@ -15034,6 +16878,11 @@
             "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
             "dev": true
         },
+        "node_modules/grid-index": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz",
+            "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA=="
+        },
         "node_modules/gtoken": {
             "version": "7.0.1",
             "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.0.1.tgz",
@@ -16501,7 +18350,6 @@
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
             "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
-            "dev": true,
             "dependencies": {
                 "has-tostringtag": "^1.0.0"
             },
@@ -16556,6 +18404,14 @@
                 "node": ">=0.4.0"
             }
         },
+        "node_modules/is-extendable": {
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+            "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/is-extglob": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -17235,6 +19091,11 @@
             "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
             "dev": true
         },
+        "node_modules/json-stringify-pretty-compact": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz",
+            "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA=="
+        },
         "node_modules/json-stringify-safe": {
             "version": "5.0.1",
             "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -17916,6 +19777,41 @@
             "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
             "dev": true
         },
+        "node_modules/mapbox-gl": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.0.1.tgz",
+            "integrity": "sha512-o7C6sAlj6Hkdd4xQVEgQflgJYNYyZOAtYahhIOb9m8chI8umtWcCp8Ie0iGLYJvce1WHRMa3WGzs69ggwuWlDA==",
+            "dependencies": {
+                "@mapbox/geojson-rewind": "^0.5.2",
+                "@mapbox/jsonlint-lines-primitives": "^2.0.2",
+                "@mapbox/mapbox-gl-supported": "^2.0.1",
+                "@mapbox/point-geometry": "^0.1.0",
+                "@mapbox/tiny-sdf": "^2.0.6",
+                "@mapbox/unitbezier": "^0.0.1",
+                "@mapbox/vector-tile": "^1.3.1",
+                "@mapbox/whoots-js": "^3.1.0",
+                "cheap-ruler": "^3.0.1",
+                "csscolorparser": "~1.0.3",
+                "earcut": "^2.2.4",
+                "geojson-vt": "^3.2.1",
+                "gl-matrix": "^3.4.3",
+                "grid-index": "^1.1.0",
+                "kdbush": "^4.0.1",
+                "murmurhash-js": "^1.0.0",
+                "pbf": "^3.2.1",
+                "potpack": "^2.0.0",
+                "quickselect": "^2.0.0",
+                "rw": "^1.3.3",
+                "supercluster": "^8.0.0",
+                "tinyqueue": "^2.0.3",
+                "vt-pbf": "^3.1.3"
+            }
+        },
+        "node_modules/mapbox-gl/node_modules/quickselect": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
+            "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
+        },
         "node_modules/markdown-table": {
             "version": "3.0.3",
             "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
@@ -19479,6 +21375,11 @@
                 "node": "*"
             }
         },
+        "node_modules/murmurhash-js": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz",
+            "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw=="
+        },
         "node_modules/mute-stream": {
             "version": "0.0.8",
             "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
@@ -22598,11 +24499,25 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/object-is": {
+            "version": "1.1.5",
+            "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
+            "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+            "dependencies": {
+                "call-bind": "^1.0.2",
+                "define-properties": "^1.1.3"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
         "node_modules/object-keys": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
             "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-            "dev": true,
             "engines": {
                 "node": ">= 0.4"
             }
@@ -23300,6 +25215,18 @@
             "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
             "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
         },
+        "node_modules/pbf": {
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz",
+            "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==",
+            "dependencies": {
+                "ieee754": "^1.1.12",
+                "resolve-protobuf-schema": "^2.1.0"
+            },
+            "bin": {
+                "pbf": "bin/pbf"
+            }
+        },
         "node_modules/pdf-parse": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-1.1.1.tgz",
@@ -23531,6 +25458,19 @@
                 "node": ">=12.13.0"
             }
         },
+        "node_modules/point-in-polygon": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/point-in-polygon/-/point-in-polygon-1.1.0.tgz",
+            "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw=="
+        },
+        "node_modules/polygon-clipping": {
+            "version": "0.15.3",
+            "resolved": "https://registry.npmjs.org/polygon-clipping/-/polygon-clipping-0.15.3.tgz",
+            "integrity": "sha512-ho0Xx5DLkgxRx/+n4O74XyJ67DcyN3Tu9bGYKsnTukGAW6ssnuak6Mwcyb1wHy9MZc9xsUWqIoiazkZB5weECg==",
+            "dependencies": {
+                "splaytree": "^3.1.0"
+            }
+        },
         "node_modules/postcss": {
             "version": "8.4.32",
             "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz",
@@ -23647,6 +25587,11 @@
                 "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
             }
         },
+        "node_modules/potpack": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.0.0.tgz",
+            "integrity": "sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw=="
+        },
         "node_modules/prelude-ls": {
             "version": "1.2.1",
             "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -23856,6 +25801,11 @@
                 "prosemirror-transform": "^1.1.0"
             }
         },
+        "node_modules/protocol-buffers-schema": {
+            "version": "3.6.0",
+            "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
+            "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="
+        },
         "node_modules/proxy-addr": {
             "version": "2.0.7",
             "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -24100,6 +26050,11 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/quickselect": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz",
+            "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ=="
+        },
         "node_modules/random-bytes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
@@ -24174,6 +26129,14 @@
                 "url": "https://opencollective.com/webpack"
             }
         },
+        "node_modules/rbush": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/rbush/-/rbush-2.0.2.tgz",
+            "integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==",
+            "dependencies": {
+                "quickselect": "^1.0.1"
+            }
+        },
         "node_modules/rc-switch": {
             "version": "4.1.0",
             "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz",
@@ -24410,6 +26373,29 @@
                 "react": ">=0.14.0"
             }
         },
+        "node_modules/react-map-gl": {
+            "version": "7.1.6",
+            "resolved": "https://registry.npmjs.org/react-map-gl/-/react-map-gl-7.1.6.tgz",
+            "integrity": "sha512-9XbrvpFF67Fyi+e6vRLJFnGpo3UF6ZHifIa8cS/wUYSsnv9sVyzGsN++FJy57zkz3Jh3kmf0xKZemR8K0FZLVw==",
+            "dependencies": {
+                "@maplibre/maplibre-gl-style-spec": "^19.2.1",
+                "@types/mapbox-gl": ">=1.0.0"
+            },
+            "peerDependencies": {
+                "mapbox-gl": ">=1.13.0",
+                "maplibre-gl": ">=1.13.0",
+                "react": ">=16.3.0",
+                "react-dom": ">=16.3.0"
+            },
+            "peerDependenciesMeta": {
+                "mapbox-gl": {
+                    "optional": true
+                },
+                "maplibre-gl": {
+                    "optional": true
+                }
+            }
+        },
         "node_modules/react-markdown": {
             "version": "9.0.1",
             "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz",
@@ -24775,7 +26761,6 @@
             "version": "1.5.1",
             "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
             "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
-            "dev": true,
             "dependencies": {
                 "call-bind": "^1.0.2",
                 "define-properties": "^1.2.0",
@@ -25197,6 +27182,14 @@
                 "node": ">=8"
             }
         },
+        "node_modules/resolve-protobuf-schema": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
+            "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
+            "dependencies": {
+                "protocol-buffers-schema": "^3.3.1"
+            }
+        },
         "node_modules/responselike": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
@@ -25913,7 +27906,6 @@
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
             "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
-            "dev": true,
             "dependencies": {
                 "define-data-property": "^1.0.1",
                 "functions-have-names": "^1.2.3",
@@ -25923,6 +27915,20 @@
                 "node": ">= 0.4"
             }
         },
+        "node_modules/set-value": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+            "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+            "dependencies": {
+                "extend-shallow": "^2.0.1",
+                "is-extendable": "^0.1.1",
+                "is-plain-object": "^2.0.3",
+                "split-string": "^3.0.1"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/setimmediate": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
@@ -26165,6 +28171,11 @@
             "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
             "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
         },
+        "node_modules/skmeans": {
+            "version": "0.9.7",
+            "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz",
+            "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg=="
+        },
         "node_modules/slice-ansi": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
@@ -26279,6 +28290,38 @@
                 "uuid": "dist/bin/uuid"
             }
         },
+        "node_modules/sort-asc": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz",
+            "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/sort-desc": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz",
+            "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/sort-object": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz",
+            "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==",
+            "dependencies": {
+                "bytewise": "^1.1.0",
+                "get-value": "^2.0.2",
+                "is-extendable": "^0.1.1",
+                "sort-asc": "^0.2.0",
+                "sort-desc": "^0.2.0",
+                "union-value": "^1.0.1"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/source-map": {
             "version": "0.5.7",
             "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -26359,6 +28402,11 @@
                 "wbuf": "^1.7.3"
             }
         },
+        "node_modules/splaytree": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/splaytree/-/splaytree-3.1.2.tgz",
+            "integrity": "sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A=="
+        },
         "node_modules/split-on-first": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
@@ -26372,6 +28420,40 @@
             "resolved": "https://registry.npmjs.org/split-skip/-/split-skip-0.0.2.tgz",
             "integrity": "sha512-weHOi8BolsDnGIwhhWHbA+wKSuSpvWwjRrdj8SdbIIis2vSwOE37CQP8x3EleuzxanUr3AK8BdUy4MkiOULPZg=="
         },
+        "node_modules/split-string": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+            "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+            "dependencies": {
+                "extend-shallow": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/split-string/node_modules/extend-shallow": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+            "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==",
+            "dependencies": {
+                "assign-symbols": "^1.0.0",
+                "is-extendable": "^1.0.1"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
+        "node_modules/split-string/node_modules/is-extendable": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+            "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+            "dependencies": {
+                "is-plain-object": "^2.0.4"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/sprintf-js": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -27034,7 +29116,8 @@
         "node_modules/text-table": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-            "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
+            "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+            "dev": true
         },
         "node_modules/textarea-caret": {
             "version": "3.1.0",
@@ -27073,6 +29156,11 @@
             "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
             "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
         },
+        "node_modules/tinyqueue": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz",
+            "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA=="
+        },
         "node_modules/titleize": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
@@ -27145,6 +29233,40 @@
                 "url": "https://github.com/sponsors/Borewit"
             }
         },
+        "node_modules/topojson-client": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz",
+            "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
+            "dependencies": {
+                "commander": "2"
+            },
+            "bin": {
+                "topo2geo": "bin/topo2geo",
+                "topomerge": "bin/topomerge",
+                "topoquantize": "bin/topoquantize"
+            }
+        },
+        "node_modules/topojson-client/node_modules/commander": {
+            "version": "2.20.3",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+        },
+        "node_modules/topojson-server": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/topojson-server/-/topojson-server-3.0.1.tgz",
+            "integrity": "sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==",
+            "dependencies": {
+                "commander": "2"
+            },
+            "bin": {
+                "geo2topo": "bin/geo2topo"
+            }
+        },
+        "node_modules/topojson-server/node_modules/commander": {
+            "version": "2.20.3",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+            "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+        },
         "node_modules/touch": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
@@ -27820,6 +29942,11 @@
                 "node": "*"
             }
         },
+        "node_modules/turf-jsts": {
+            "version": "1.2.3",
+            "resolved": "https://registry.npmjs.org/turf-jsts/-/turf-jsts-1.2.3.tgz",
+            "integrity": "sha512-Ja03QIJlPuHt4IQ2FfGex4F4JAr8m3jpaHbFbQrgwr7s7L6U8ocrHiF3J1+wf9jzhGKxvDeaCAnGDot8OjGFyA=="
+        },
         "node_modules/tweetnacl": {
             "version": "0.14.5",
             "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
@@ -27963,6 +30090,19 @@
                 "node": ">=18"
             }
         },
+        "node_modules/typewise": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz",
+            "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==",
+            "dependencies": {
+                "typewise-core": "^1.2.0"
+            }
+        },
+        "node_modules/typewise-core": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz",
+            "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg=="
+        },
         "node_modules/typical": {
             "version": "2.6.1",
             "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz",
@@ -28082,6 +30222,20 @@
             "resolved": "https://registry.npmjs.org/uninstall/-/uninstall-0.0.0.tgz",
             "integrity": "sha512-pjP/0+A4gsbDVa8XH/S2GZdT9NPJW8NFMy3GI7HnsWG+NAmFSSj3QidNosXBI9cPtxxNExEDdhKFO6sli8K3mA=="
         },
+        "node_modules/union-value": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+            "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+            "dependencies": {
+                "arr-union": "^3.1.0",
+                "get-value": "^2.0.6",
+                "is-extendable": "^0.1.1",
+                "set-value": "^2.0.1"
+            },
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/unist-util-is": {
             "version": "6.0.0",
             "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
@@ -28509,6 +30663,16 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/vt-pbf": {
+            "version": "3.1.3",
+            "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz",
+            "integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==",
+            "dependencies": {
+                "@mapbox/point-geometry": "0.1.0",
+                "@mapbox/vector-tile": "^1.3.1",
+                "pbf": "^3.2.1"
+            }
+        },
         "node_modules/w3c-keyname": {
             "version": "2.2.8",
             "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
diff --git a/package.json b/package.json
index fa0dc3ff5..98453a651 100644
--- a/package.json
+++ b/package.json
@@ -109,6 +109,7 @@
         "@mui/material": "^5.14.19",
         "@octokit/core": "^5.0.2",
         "@react-google-maps/api": "^2.19.2",
+        "@turf/turf": "^6.5.0",
         "@types/bezier-js": "^4.1.3",
         "@types/cors": "^2.8.17",
         "@types/d3-axis": "^3.0.6",
@@ -197,6 +198,7 @@
         "jsonschema": "^1.4.1",
         "jszip": "^3.10.1",
         "lodash": "^4.17.21",
+        "mapbox-gl": "^3.0.1",
         "mathquill": "^0.10.1-a",
         "md5-file": "^5.0.0",
         "memorystream": "^0.3.1",
@@ -247,6 +249,7 @@
         "react-icons": "^4.12.0",
         "react-jsx-parser": "^1.29.0",
         "react-loading": "^2.0.3",
+        "react-map-gl": "^7.1.6",
         "react-markdown": "^9.0.1",
         "react-measure": "^2.5.2",
         "react-resizable": "^3.0.5",
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index a626772e4..e31c04c40 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -98,7 +98,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     };
 
     componentDidMount() {
-        this.props.setContentView?.(this);
+        this._props.setContentView?.(this);
         if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData();
     }
 
@@ -110,19 +110,19 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
     // toggles for user to decide which chart type to view the data in
     @computed get renderVizView() {
-        const scale = this.props.NativeDimScaling?.() || 1;
+        const scale = this._props.NativeDimScaling?.() || 1;
         const sharedProps = {
             Document: this.Document,
             layoutDoc: this.layoutDoc,
             records: this.records,
             axes: this.axes,
-            height: (this.props.PanelHeight() / scale - 32) /* height of 'change view' button */ * 0.9,
-            width: (this.props.PanelWidth() / scale) * 0.9,
+            height: (this._props.PanelHeight() / scale - 32) /* height of 'change view' button */ * 0.9,
+            width: (this._props.PanelWidth() / scale) * 0.9,
             margin: { top: 10, right: 25, bottom: 75, left: 45 },
         };
         if (!this.records.length) return 'no data/visualization';
         switch (this.dataVizView) {
-            case DataVizView.TABLE:     return <TableBox  {...sharedProps} docView={this.props.DocumentView} selectAxes={this.selectAxes} />;
+            case DataVizView.TABLE:     return <TableBox  {...sharedProps} docView={this._props.DocumentView} selectAxes={this.selectAxes} />;
             case DataVizView.LINECHART: return <LineChart {...sharedProps} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => (this._vizRenderer = r ?? undefined)} />;
             case DataVizView.HISTOGRAM: return <Histogram {...sharedProps} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => (this._vizRenderer = r ?? undefined)} />;
             case DataVizView.PIECHART:  return <PieChart  {...sharedProps} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => (this._vizRenderer = r ?? undefined)} 
@@ -131,7 +131,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     }
 
     render() {
-        const scale = this.props.NativeDimScaling?.() || 1;
+        const scale = this._props.NativeDimScaling?.() || 1;
 
         return !this.records.length ? (
             // displays how to get data into the DataVizBox if its empty
@@ -140,7 +140,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             <div
                 className="dataViz"
                 style={{
-                    pointerEvents: this.props.isContentActive() === true ? 'all' : 'none',
+                    pointerEvents: this._props.isContentActive() === true ? 'all' : 'none',
                     width: `${100 / scale}%`,
                     height: `${100 / scale}%`,
                     transform: `scale(${scale})`,
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
index a1bd316f0..d786e84ad 100644
--- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx
+++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
@@ -1,7 +1,7 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { ColorPicker, EditableText, IconButton, Size, Type } from 'browndash-components';
 import * as d3 from 'd3';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { FaFillDrip } from 'react-icons/fa';
@@ -14,6 +14,7 @@ import { undoable } from '../../../../util/UndoManager';
 import { PinProps, PresBox } from '../../trails';
 import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils';
 import './Chart.scss';
+import { ObservableReactComponent } from '../../../ObservableReactComponent';
 
 export interface HistogramProps {
     Document: Doc;
@@ -33,7 +34,7 @@ export interface HistogramProps {
 }
 
 @observer
-export class Histogram extends React.Component<HistogramProps> {
+export class Histogram extends ObservableReactComponent<HistogramProps> {
     private _disposers: { [key: string]: IReactionDisposer } = {};
     private _histogramRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _histogramSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
@@ -45,46 +46,51 @@ export class Histogram extends React.Component<HistogramProps> {
     private selectedData: any = undefined; // Selection of selected bar
     private hoverOverData: any = undefined; // Selection of bar being hovered over
 
+    constructor(props: any) {
+        super(props);
+        makeObservable(this);
+    }
+
     @computed get _tableDataIds() {
-        return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
+        return !this.parentViz ? this._props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
     }
     // returns all the data records that will be rendered by only returning those records that have been selected by the parent visualization (or all records if there is no parent)
     @computed get _tableData() {
-        return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]);
+        return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
     }
     // filters all data to just display selected data if brushed (created from an incoming link)
     @computed get _histogramData() {
-        if (this.props.axes.length < 1) return [];
-        if (this.props.axes.length < 2) {
-            var ax0 = this.props.axes[0];
-            if (/\d/.test(this.props.records[0][ax0])) {
+        if (this._props.axes.length < 1) return [];
+        if (this._props.axes.length < 2) {
+            var ax0 = this._props.axes[0];
+            if (/\d/.test(this._props.records[0][ax0])) {
                 this.numericalXData = true;
             }
-            return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]] }));
+            return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] }));
         }
-        var ax0 = this.props.axes[0];
-        var ax1 = this.props.axes[1];
-        if (/\d/.test(this.props.records[0][ax0])) {
+        var ax0 = this._props.axes[0];
+        var ax1 = this._props.axes[1];
+        if (/\d/.test(this._props.records[0][ax0])) {
             this.numericalXData = true;
         }
-        if (/\d/.test(this.props.records[0][ax1])) {
+        if (/\d/.test(this._props.records[0][ax1])) {
             this.numericalYData = true;
         }
-        return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]], [ax1]: record[this.props.axes[1]] }));
+        return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]], [ax1]: record[this._props.axes[1]] }));
     }
 
     @computed get defaultGraphTitle() {
-        var ax0 = this.props.axes[0];
-        var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
-        if (this.props.axes.length < 2 || !ax1 || !/\d/.test(this.props.records[0][ax1]) || !this.numericalYData) {
+        var ax0 = this._props.axes[0];
+        var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined;
+        if (this._props.axes.length < 2 || !ax1 || !/\d/.test(this._props.records[0][ax1]) || !this.numericalYData) {
             return ax0 + ' Histogram';
         } else return ax0 + ' by ' + ax1 + ' Histogram';
     }
 
     @computed get parentViz() {
-        return DocCast(this.props.Document.dataViz_parentViz);
-        // return LinkManager.Instance.getAllRelatedLinks(this.props.Document) // out of all links
-        //     .filter(link => link.link_anchor_1 == this.props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
+        return DocCast(this._props.Document.dataViz_parentViz);
+        // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+        //     .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
         //     .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
     }
 
@@ -114,16 +120,16 @@ export class Histogram extends React.Component<HistogramProps> {
         const anchor = Docs.Create.ConfigDocument({
             title: 'histogram doc selection' + this._currSelected,
         });
-        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.Document);
+        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
         return anchor;
     };
 
     @computed get height() {
-        return this.props.height - this.props.margin.top - this.props.margin.bottom;
+        return this._props.height - this._props.margin.top - this._props.margin.bottom;
     }
 
     @computed get width() {
-        return this.props.width - this.props.margin.left - this.props.margin.right;
+        return this._props.width - this._props.margin.left - this._props.margin.right;
     }
 
     // cleans data by converting numerical data to numbers and taking out empty cells
@@ -211,10 +217,10 @@ export class Histogram extends React.Component<HistogramProps> {
             .select(this._histogramRef.current)
             .append('svg')
             .attr('class', 'graph')
-            .attr('width', width + this.props.margin.right + this.props.margin.left)
-            .attr('height', height + this.props.margin.top + this.props.margin.bottom)
+            .attr('width', width + this._props.margin.right + this._props.margin.left)
+            .attr('height', height + this._props.margin.top + this._props.margin.bottom)
             .append('g')
-            .attr('transform', 'translate(' + this.props.margin.left + ',' + this.props.margin.top + ')'));
+            .attr('transform', 'translate(' + this._props.margin.left + ',' + this._props.margin.top + ')'));
         var x = d3
             .scaleLinear()
             .domain(this.numericalXData ? [startingPoint!, endingPoint!] : [0, numBins])
@@ -382,7 +388,7 @@ export class Histogram extends React.Component<HistogramProps> {
             )
             .attr('fill', d => {
                 var barColor;
-                const barColors = StrListCast(this.props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
+                const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
                 barColors.forEach(each => {
                     if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1];
                     else {
@@ -390,24 +396,24 @@ export class Histogram extends React.Component<HistogramProps> {
                         if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1];
                     }
                 });
-                return barColor ? StrCast(barColor) : StrCast(this.props.layoutDoc.dataViz_histogram_defaultColor);
+                return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor);
             });
     };
 
     @action changeSelectedColor = (color: string) => {
         this.curBarSelected.attr('fill', color);
-        const barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
+        const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
 
-        const barColors = Cast(this.props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
+        const barColors = Cast(this._props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
         barColors.forEach(each => each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1));
         barColors.push(StrCast(barName + '::' + color));
     };
 
     @action eraseSelectedColor = () => {
-        this.curBarSelected.attr('fill', this.props.layoutDoc.dataViz_histogram_defaultColor);
-        const barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
+        this.curBarSelected.attr('fill', this._props.layoutDoc.dataViz_histogram_defaultColor);
+        const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
 
-        const barColors = Cast(this.props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
+        const barColors = Cast(this._props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
         barColors.forEach(each => each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1));
     };
 
@@ -416,7 +422,7 @@ export class Histogram extends React.Component<HistogramProps> {
         if (svg)
             svg.selectAll('rect').attr('fill', (d: any) => {
                 var barColor;
-                const barColors = StrListCast(this.props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
+                const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
                 barColors.forEach(each => {
                     if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1];
                     else {
@@ -424,7 +430,7 @@ export class Histogram extends React.Component<HistogramProps> {
                         if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1];
                     }
                 });
-                return barColor ? StrCast(barColor) : StrCast(this.props.layoutDoc.dataViz_histogram_defaultColor);
+                return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor);
             });
     };
 
@@ -433,14 +439,14 @@ export class Histogram extends React.Component<HistogramProps> {
         this._histogramData;
         var curSelectedBarName = '';
         var titleAccessor: any = '';
-        if (this.props.axes.length == 2) titleAccessor = 'dataViz_histogram_title' + this.props.axes[0] + '-' + this.props.axes[1];
-        else if (this.props.axes.length > 0) titleAccessor = 'dataViz_histogram_title' + this.props.axes[0];
-        if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
-        if (!this.props.layoutDoc.dataViz_histogram_defaultColor) this.props.layoutDoc.dataViz_histogram_defaultColor = '#69b3a2';
-        if (!this.props.layoutDoc.dataViz_histogram_barColors) this.props.layoutDoc.dataViz_histogram_barColors = new List<string>();
+        if (this._props.axes.length == 2) titleAccessor = 'dataViz_histogram_title' + this._props.axes[0] + '-' + this._props.axes[1];
+        else if (this._props.axes.length > 0) titleAccessor = 'dataViz_histogram_title' + this._props.axes[0];
+        if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
+        if (!this._props.layoutDoc.dataViz_histogram_defaultColor) this._props.layoutDoc.dataViz_histogram_defaultColor = '#69b3a2';
+        if (!this._props.layoutDoc.dataViz_histogram_barColors) this._props.layoutDoc.dataViz_histogram_barColors = new List<string>();
         var selected = 'none';
         if (this._currSelected) {
-            curSelectedBarName = StrCast(this._currSelected![this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
+            curSelectedBarName = StrCast(this._currSelected![this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
             selected = '{ ';
             Object.keys(this._currSelected).forEach(key =>
                 key //
@@ -450,17 +456,17 @@ export class Histogram extends React.Component<HistogramProps> {
             selected = selected.substring(0, selected.length - 2) + ' }';
         }
         var selectedBarColor;
-        var barColors = StrListCast(this.props.layoutDoc.histogramBarColors).map(each => each.split('::'));
+        var barColors = StrListCast(this._props.layoutDoc.histogramBarColors).map(each => each.split('::'));
         barColors.forEach(each => each[0] === curSelectedBarName && (selectedBarColor = each[1]));
 
         if (this._histogramData.length > 0 || !this.parentViz) {
-            return this.props.axes.length >= 1 ? (
+            return this._props.axes.length >= 1 ? (
                 <div className="chart-container">
                     <div className="graph-title">
                         <EditableText
-                            val={StrCast(this.props.layoutDoc[titleAccessor])}
+                            val={StrCast(this._props.layoutDoc[titleAccessor])}
                             setVal={undoable(
-                                action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+                                action(val => (this._props.layoutDoc[titleAccessor] = val as string)),
                                 'Change Graph Title'
                             )}
                             color={'black'}
@@ -472,9 +478,9 @@ export class Histogram extends React.Component<HistogramProps> {
                             tooltip={'Change Default Bar Color'}
                             type={Type.SEC}
                             icon={<FaFillDrip />}
-                            selectedColor={StrCast(this.props.layoutDoc.dataViz_histogram_defaultColor)}
-                            setFinalColor={undoable(color => (this.props.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')}
-                            setSelectedColor={undoable(color => (this.props.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')}
+                            selectedColor={StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor)}
+                            setFinalColor={undoable(color => (this._props.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')}
+                            setSelectedColor={undoable(color => (this._props.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')}
                             size={Size.XSMALL}
                         />
                     </div>
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index 7e0391879..abb95aa4c 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -1,6 +1,6 @@
 import { EditableText, Size } from 'browndash-components';
 import * as d3 from 'd3';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, NumListCast, StrListCast } from '../../../../../fields/Doc';
@@ -14,6 +14,7 @@ import { PinProps, PresBox } from '../../trails';
 import { DataVizBox } from '../DataVizBox';
 import { createLineGenerator, drawLine, minMaxRange, scaleCreatorNumerical, xAxisCreator, xGrid, yAxisCreator, yGrid } from '../utils/D3Utils';
 import './Chart.scss';
+import { ObservableReactComponent } from '../../../ObservableReactComponent';
 
 export interface DataPoint {
     x: number;
@@ -40,33 +41,38 @@ export interface LineChartProps {
 }
 
 @observer
-export class LineChart extends React.Component<LineChartProps> {
+export class LineChart extends ObservableReactComponent<LineChartProps> {
     private _disposers: { [key: string]: IReactionDisposer } = {};
     private _lineChartRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _lineChartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
     @observable _currSelected: SelectedDataPoint | undefined = undefined;
     // TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates
+    constructor(props:any) {
+        super(props);
+        makeObservable(this);
+    }
+
 
     @computed get _tableDataIds() {
-        return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
+        return !this.parentViz ? this._props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
     }
     // returns all the data records that will be rendered by only returning those records that have been selected by the parent visualization (or all records if there is no parent)
     @computed get _tableData() {
-        return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]);
+        return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
     }
     @computed get _lineChartData() {
-        var guids = StrListCast(this.props.layoutDoc.dataViz_rowIds);
-        if (this.props.axes.length <= 1) return [];
-        return this._tableData.map(record => ({ x: Number(record[this.props.axes[0]]), y: Number(record[this.props.axes[1]]) })).sort((a, b) => (a.x < b.x ? -1 : 1));
+        var guids = StrListCast(this._props.layoutDoc.dataViz_rowIds);
+        if (this._props.axes.length <= 1) return [];
+        return this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[1]]) })).sort((a, b) => (a.x < b.x ? -1 : 1));
     }
     @computed get graphTitle() {
-        return this.props.axes[1] + ' vs. ' + this.props.axes[0] + ' Line Chart';
+        return this._props.axes[1] + ' vs. ' + this._props.axes[0] + ' Line Chart';
     }
     @computed get parentViz() {
-        return DocCast(this.props.Document.dataViz_parentViz);
-        // return LinkManager.Instance.getAllRelatedLinks(this.props.Document) // out of all links
+        return DocCast(this._props.Document.dataViz_parentViz);
+        // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
         //     .filter(link => {
-        //         return link.link_anchor_1 == this.props.Document.dataViz_parentViz;
+        //         return link.link_anchor_1 == this._props.Document.dataViz_parentViz;
         //     }) // get links where this chart doc is the target of the link
         //     .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
     }
@@ -94,7 +100,7 @@ export class LineChart extends React.Component<LineChartProps> {
             { fireImmediately: true }
         );
         this._disposers.annos = reaction(
-            () => DocListCast(this.props.dataDoc[this.props.fieldKey + '_annotations']),
+            () => DocListCast(this._props.dataDoc[this._props.fieldKey + '_annotations']),
             annotations => {
                 // modify how d3 renders so that anything in this annotations list would be potentially highlighted in some way
                 // could be blue colored to make it look like anchor
@@ -114,7 +120,7 @@ export class LineChart extends React.Component<LineChartProps> {
                 // redraw annotations when the chart data has changed, or the local or inherited selection has changed
                 this.clearAnnotations();
                 selected && this.drawAnnotations(Number(selected.x), Number(selected.y), true);
-                incomingHighlited?.forEach((record: any) => this.drawAnnotations(Number(record[this.props.axes[0]]), Number(record[this.props.axes[1]])));
+                incomingHighlited?.forEach((record: any) => this.drawAnnotations(Number(record[this._props.axes[0]]), Number(record[this._props.axes[1]])));
             },
             { fireImmediately: true }
         );
@@ -170,23 +176,23 @@ export class LineChart extends React.Component<LineChartProps> {
             //
             title: 'line doc selection' + this._currSelected?.x,
         });
-        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.Document);
+        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
         anchor.config_dataVizSelection = this._currSelected ? new List<number>([this._currSelected.x, this._currSelected.y]) : undefined;
         return anchor;
     };
 
     @computed get height() {
-        return this.props.height - this.props.margin.top - this.props.margin.bottom;
+        return this._props.height - this._props.margin.top - this._props.margin.bottom;
     }
 
     @computed get width() {
-        return this.props.width - this.props.margin.left - this.props.margin.right;
+        return this._props.width - this._props.margin.left - this._props.margin.right;
     }
 
     @computed get defaultGraphTitle() {
-        var ax0 = this.props.axes[0];
-        var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
-        if (this.props.axes.length < 2 || !/\d/.test(this.props.records[0][ax0]) || !ax1) {
+        var ax0 = this._props.axes[0];
+        var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined;
+        if (this._props.axes.length < 2 || !/\d/.test(this._props.records[0][ax0]) || !ax1) {
             return ax0 + ' Line Chart';
         } else return ax1 + ' by ' + ax0 + ' Line Chart';
     }
@@ -210,7 +216,7 @@ export class LineChart extends React.Component<LineChartProps> {
         // TODO: nda - get rid of svg element in the list?
         if (this._currSelected && this._currSelected.x == x && this._currSelected.y == y) this._currSelected = undefined;
         else this._currSelected = x !== undefined && y !== undefined ? { x, y } : undefined;
-        this.props.records.forEach(record => record[this.props.axes[0]] === x && record[this.props.axes[1]] === y && (record.selected = true));
+        this._props.records.forEach(record => record[this._props.axes[0]] === x && record[this._props.axes[1]] === y && (record.selected = true));
     }
 
     drawDataPoints(data: DataPoint[], idx: number, xScale: d3.ScaleLinear<number, number, never>, yScale: d3.ScaleLinear<number, number, never>) {
@@ -245,7 +251,7 @@ export class LineChart extends React.Component<LineChartProps> {
         const yScale = scaleCreatorNumerical(0, yMax, height, 0);
 
         // adding svg
-        const margin = this.props.margin;
+        const margin = this._props.margin;
         const svg = (this._lineChartSvg = d3
             .select(this._lineChartRef.current)
             .append('svg')
@@ -317,7 +323,7 @@ export class LineChart extends React.Component<LineChartProps> {
         svg.append('text')
             .attr('transform', 'translate(' + width / 2 + ' ,' + (height + 40) + ')')
             .style('text-anchor', 'middle')
-            .text(this.props.axes[0]);
+            .text(this._props.axes[0]);
         svg.append('text')
             .attr('transform', 'rotate(-90)' + ' ' + 'translate( 0, ' + -10 + ')')
             .attr('x', -(height / 2))
@@ -325,7 +331,7 @@ export class LineChart extends React.Component<LineChartProps> {
             .attr('height', 20)
             .attr('width', 20)
             .style('text-anchor', 'middle')
-            .text(this.props.axes[1]);
+            .text(this._props.axes[1]);
     };
 
     private updateTooltip(
@@ -346,18 +352,18 @@ export class LineChart extends React.Component<LineChartProps> {
 
     render() {
         var titleAccessor: any = '';
-        if (this.props.axes.length == 2) titleAccessor = 'dataViz_lineChart_title' + this.props.axes[0] + '-' + this.props.axes[1];
-        else if (this.props.axes.length > 0) titleAccessor = 'dataViz_lineChart_title' + this.props.axes[0];
-        if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
-        const selectedPt = this._currSelected ? `{ ${this.props.axes[0]}: ${this._currSelected.x} ${this.props.axes[1]}: ${this._currSelected.y} }` : 'none';
+        if (this._props.axes.length == 2) titleAccessor = 'dataViz_lineChart_title' + this._props.axes[0] + '-' + this._props.axes[1];
+        else if (this._props.axes.length > 0) titleAccessor = 'dataViz_lineChart_title' + this._props.axes[0];
+        if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
+        const selectedPt = this._currSelected ? `{ ${this._props.axes[0]}: ${this._currSelected.x} ${this._props.axes[1]}: ${this._currSelected.y} }` : 'none';
         if (this._lineChartData.length > 0 || !this.parentViz || this.parentViz.length == 0) {
-            return this.props.axes.length >= 2 && /\d/.test(this.props.records[0][this.props.axes[0]]) && /\d/.test(this.props.records[0][this.props.axes[1]]) ? (
+            return this._props.axes.length >= 2 && /\d/.test(this._props.records[0][this._props.axes[0]]) && /\d/.test(this._props.records[0][this._props.axes[1]]) ? (
                 <div className="chart-container">
                     <div className="graph-title">
                         <EditableText
-                            val={StrCast(this.props.layoutDoc[titleAccessor])}
+                            val={StrCast(this._props.layoutDoc[titleAccessor])}
                             setVal={undoable(
-                                action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+                                action(val => (this._props.layoutDoc[titleAccessor] = val as string)),
                                 'Change Graph Title'
                             )}
                             color={'black'}
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
index c2e03744e..9e7265b26 100644
--- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
@@ -1,7 +1,7 @@
 import { Checkbox } from '@mui/material';
 import { ColorPicker, EditableText, Size, Type } from 'browndash-components';
 import * as d3 from 'd3';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { FaFillDrip } from 'react-icons/fa';
@@ -13,6 +13,7 @@ import { Docs } from '../../../../documents/Documents';
 import { undoable } from '../../../../util/UndoManager';
 import { PinProps, PresBox } from '../../trails';
 import './Chart.scss';
+import { ObservableReactComponent } from '../../../ObservableReactComponent';
 
 export interface PieChartProps {
     Document: Doc;
@@ -32,7 +33,7 @@ export interface PieChartProps {
 }
 
 @observer
-export class PieChart extends React.Component<PieChartProps> {
+export class PieChart extends ObservableReactComponent<PieChartProps> {
     private _disposers: { [key: string]: IReactionDisposer } = {};
     private _piechartRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _piechartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
@@ -41,44 +42,49 @@ export class PieChart extends React.Component<PieChartProps> {
     private hoverOverData: any = undefined; // Selection of slice being hovered over
     @observable _currSelected: any | undefined = undefined; // Object of selected slice
 
+    constructor(props: any) {
+        super(props);
+        makeObservable(this);
+    }
+
     @computed get _tableDataIds() {
-        return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
+        return !this.parentViz ? this._props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
     }
     // returns all the data records that will be rendered by only returning those records that have been selected by the parent visualization (or all records if there is no parent)
     @computed get _tableData() {
-        return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]);
+        return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
     }
 
     // organized by specified number percentages/ratios if one column is selected and it contains numbers
     // otherwise, assume data is organized by categories
     @computed get byCategory() {
-        return !/\d/.test(this.props.records[0][this.props.axes[0]]) || this.props.layoutDoc.dataViz_pie_asHistogram;
+        return !/\d/.test(this._props.records[0][this._props.axes[0]]) || this._props.layoutDoc.dataViz_pie_asHistogram;
     }
     // filters all data to just display selected data if brushed (created from an incoming link)
     @computed get _pieChartData() {
-        if (this.props.axes.length < 1) return [];
+        if (this._props.axes.length < 1) return [];
 
-        const ax0 = this.props.axes[0];
-        if (this.props.axes.length < 2) {
-            return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]] }));
+        const ax0 = this._props.axes[0];
+        if (this._props.axes.length < 2) {
+            return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] }));
         }
-        const ax1 = this.props.axes[1];
-        return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]], [ax1]: record[this.props.axes[1]] }));
+        const ax1 = this._props.axes[1];
+        return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]], [ax1]: record[this._props.axes[1]] }));
     }
 
     @computed get defaultGraphTitle() {
-        var ax0 = this.props.axes[0];
-        var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
-        if (this.props.axes.length < 2 || !/\d/.test(this.props.records[0][ax0]) || !ax1) {
+        var ax0 = this._props.axes[0];
+        var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined;
+        if (this._props.axes.length < 2 || !/\d/.test(this._props.records[0][ax0]) || !ax1) {
             return ax0 + ' Pie Chart';
         }
         return ax1 + ' by ' + ax0 + ' Pie Chart';
     }
 
     @computed get parentViz() {
-        return DocCast(this.props.Document.dataViz_parentViz);
-        // return LinkManager.Instance.getAllRelatedLinks(this.props.Document) // out of all links
-        //     .filter(link => link.link_anchor_1 == this.props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
+        return DocCast(this._props.Document.dataViz_parentViz);
+        // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+        //     .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
         //     .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
     }
 
@@ -101,16 +107,16 @@ export class PieChart extends React.Component<PieChartProps> {
             //
             title: 'piechart doc selection' + this._currSelected,
         });
-        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.Document);
+        PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
         return anchor;
     };
 
     @computed get height() {
-        return this.props.height - this.props.margin.top - this.props.margin.bottom;
+        return this._props.height - this._props.margin.top - this._props.margin.bottom;
     }
 
     @computed get width() {
-        return this.props.width - this.props.margin.left - this.props.margin.right;
+        return this._props.width - this._props.margin.left - this._props.margin.right;
     }
 
     // cleans data by converting numerical data to numbers and taking out empty cells
@@ -181,7 +187,7 @@ export class PieChart extends React.Component<PieChartProps> {
 
         var percentField = Object.keys(dataSet[0])[0];
         var descriptionField = Object.keys(dataSet[0])[1]!;
-        var radius = Math.min(width, height - this.props.margin.top - this.props.margin.bottom) / 2;
+        var radius = Math.min(width, height - this._props.margin.top - this._props.margin.bottom) / 2;
 
         // converts data into Objects
         var data = this.data(dataSet);
@@ -209,10 +215,10 @@ export class PieChart extends React.Component<PieChartProps> {
             .select(this._piechartRef.current)
             .append('svg')
             .attr('class', 'graph')
-            .attr('width', width + this.props.margin.right + this.props.margin.left)
-            .attr('height', height + this.props.margin.top + this.props.margin.bottom)
+            .attr('width', width + this._props.margin.right + this._props.margin.left)
+            .attr('height', height + this._props.margin.top + this._props.margin.bottom)
             .append('g'));
-        let g = svg.append('g').attr('transform', 'translate(' + (width / 2 + this.props.margin.left) + ',' + height / 2 + ')');
+        let g = svg.append('g').attr('transform', 'translate(' + (width / 2 + this._props.margin.left) + ',' + height / 2 + ')');
         var pie = d3.pie();
         var arc = d3.arc().innerRadius(0).outerRadius(radius);
 
@@ -249,7 +255,7 @@ export class PieChart extends React.Component<PieChartProps> {
             } catch (error) {}
             possibleDataPointVals.push(dataPointVal);
         });
-        const sliceColors = StrListCast(this.props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
+        const sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
         arcs.append('path')
             .attr('fill', (d, i) => {
                 var dataPoint;
@@ -261,7 +267,7 @@ export class PieChart extends React.Component<PieChartProps> {
                 }
                 var sliceColor;
                 if (dataPoint) {
-                    const sliceTitle = dataPoint[this.props.axes[0]];
+                    const sliceTitle = dataPoint[this._props.axes[0]];
                     const accessByName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle;
                     sliceColors.forEach(each => each[0] == accessByName && (sliceColor = each[1]));
                 }
@@ -309,10 +315,10 @@ export class PieChart extends React.Component<PieChartProps> {
 
     @action changeSelectedColor = (color: string) => {
         this.curSliceSelected.attr('fill', color);
-        const sliceTitle = this._currSelected[this.props.axes[0]];
+        const sliceTitle = this._currSelected[this._props.axes[0]];
         const sliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle;
 
-        const sliceColors = Cast(this.props.layoutDoc.dataViz_pie_sliceColors, listSpec('string'), null);
+        const sliceColors = Cast(this._props.layoutDoc.dataViz_pie_sliceColors, listSpec('string'), null);
         sliceColors.map(each => {
             if (each.split('::')[0] == sliceName) sliceColors.splice(sliceColors.indexOf(each), 1);
         });
@@ -320,20 +326,20 @@ export class PieChart extends React.Component<PieChartProps> {
     };
 
     @action changeHistogramCheckBox = () => {
-        this.props.layoutDoc.dataViz_pie_asHistogram = !this.props.layoutDoc.dataViz_pie_asHistogram;
+        this._props.layoutDoc.dataViz_pie_asHistogram = !this._props.layoutDoc.dataViz_pie_asHistogram;
         this.drawChart(this._pieChartData, this.width, this.height);
     };
 
     render() {
         var titleAccessor: any = '';
-        if (this.props.axes.length == 2) titleAccessor = 'dataViz_pie_title' + this.props.axes[0] + '-' + this.props.axes[1];
-        else if (this.props.axes.length > 0) titleAccessor = 'dataViz_pie_title' + this.props.axes[0];
-        if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
-        if (!this.props.layoutDoc.dataViz_pie_sliceColors) this.props.layoutDoc.dataViz_pie_sliceColors = new List<string>();
+        if (this._props.axes.length == 2) titleAccessor = 'dataViz_pie_title' + this._props.axes[0] + '-' + this._props.axes[1];
+        else if (this._props.axes.length > 0) titleAccessor = 'dataViz_pie_title' + this._props.axes[0];
+        if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
+        if (!this._props.layoutDoc.dataViz_pie_sliceColors) this._props.layoutDoc.dataViz_pie_sliceColors = new List<string>();
         var selected: string;
         var curSelectedSliceName = '';
         if (this._currSelected) {
-            const sliceTitle = this._currSelected[this.props.axes[0]];
+            const sliceTitle = this._currSelected[this._props.axes[0]];
             curSelectedSliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle;
             selected = '{ ';
             Object.keys(this._currSelected).map(key => {
@@ -343,19 +349,19 @@ export class PieChart extends React.Component<PieChartProps> {
             selected += ' }';
         } else selected = 'none';
         var selectedSliceColor;
-        var sliceColors = StrListCast(this.props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
+        var sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
         sliceColors.forEach(each => {
             if (each[0] == curSelectedSliceName!) selectedSliceColor = each[1];
         });
 
         if (this._pieChartData.length > 0 || !this.parentViz) {
-            return this.props.axes.length >= 1 ? (
+            return this._props.axes.length >= 1 ? (
                 <div className="chart-container">
                     <div className="graph-title">
                         <EditableText
-                            val={StrCast(this.props.layoutDoc[titleAccessor])}
+                            val={StrCast(this._props.layoutDoc[titleAccessor])}
                             setVal={undoable(
-                                action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+                                action(val => (this._props.layoutDoc[titleAccessor] = val as string)),
                                 'Change Graph Title'
                             )}
                             color={'black'}
@@ -363,9 +369,9 @@ export class PieChart extends React.Component<PieChartProps> {
                             fillWidth
                         />
                     </div>
-                    {this.props.axes.length === 1 && /\d/.test(this.props.records[0][this.props.axes[0]]) ? (
-                        <div className={'asHistogram-checkBox'} style={{ width: this.props.width }}>
-                            <Checkbox color="primary" onChange={this.changeHistogramCheckBox} checked={this.props.layoutDoc.dataViz_pie_asHistogram as boolean} />
+                    {this._props.axes.length === 1 && /\d/.test(this._props.records[0][this._props.axes[0]]) ? (
+                        <div className={'asHistogram-checkBox'} style={{ width: this._props.width }}>
+                            <Checkbox color="primary" onChange={this.changeHistogramCheckBox} checked={this._props.layoutDoc.dataViz_pie_asHistogram as boolean} />
                             Organize data as histogram
                         </div>
                     ) : null}
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 3e7d3af8c..f77c138df 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -1,5 +1,5 @@
 import { Button, Type } from 'browndash-components';
-import { action, computed, IReactionDisposer, observable, reaction, trace } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction, trace } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, Field, NumListCast } from '../../../../../fields/Doc';
@@ -11,6 +11,7 @@ import { DragManager } from '../../../../util/DragManager';
 import { DocumentView } from '../../DocumentView';
 import { DataVizView } from '../DataVizBox';
 import './Chart.scss';
+import { ObservableReactComponent } from '../../../ObservableReactComponent';
 const {  default: { DATA_VIZ_TABLE_ROW_HEIGHT } } = require('../../../global/globalCssVariables.module.scss'); // prettier-ignore
 interface TableBoxProps {
     Document: Doc;
@@ -30,13 +31,17 @@ interface TableBoxProps {
 }
 
 @observer
-export class TableBox extends React.Component<TableBoxProps> {
+export class TableBox extends ObservableReactComponent<TableBoxProps> {
     _inputChangedDisposer?: IReactionDisposer;
     _containerRef: HTMLDivElement | null = null;
 
     @observable _scrollTop = -1;
     @observable _tableHeight = 0;
     @observable _tableContainerHeight = 0;
+    constructor(props: any) {
+        super(props);
+        makeObservable(this);
+    }
 
     componentDidMount() {
         // if the tableData changes (ie., when records are selected by the parent (input) visulization),
@@ -48,17 +53,17 @@ export class TableBox extends React.Component<TableBoxProps> {
         this._inputChangedDisposer?.();
     }
     @computed get _tableDataIds() {
-        return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
+        return !this.parentViz ? this._props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
     }
     // returns all the data records that will be rendered by only returning those records that have been selected by the parent visualization (or all records if there is no parent)
     @computed get _tableData() {
-        return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]);
+        return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
     }
 
     @computed get parentViz() {
-        return DocCast(this.props.Document.dataViz_parentViz);
-        // return LinkManager.Instance.getAllRelatedLinks(this.props.Document) // out of all links
-        //     .filter(link => link.link_anchor_1 == this.props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
+        return DocCast(this._props.Document.dataViz_parentViz);
+        // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+        //     .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
         //     .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
     }
 
@@ -68,14 +73,14 @@ export class TableBox extends React.Component<TableBoxProps> {
 
     // updates the 'dataViz_selectedRows' and 'dataViz_highlightedRows' fields to no longer include rows that aren't in the table
     filterSelectedRowsDown = () => {
-        const selected = NumListCast(this.props.layoutDoc.dataViz_selectedRows);
-        this.props.layoutDoc.dataViz_selectedRows = new List<number>(selected.filter(rowId => this._tableDataIds.includes(rowId))); // filters through selected to remove guids that were removed in the incoming data
-        const highlighted = NumListCast(this.props.layoutDoc.dataViz_highlitedRows);
-        this.props.layoutDoc.dataViz_highlitedRows = new List<number>(highlighted.filter(rowId => this._tableDataIds.includes(rowId))); // filters through highlighted to remove guids that were removed in the incoming data
+        const selected = NumListCast(this._props.layoutDoc.dataViz_selectedRows);
+        this._props.layoutDoc.dataViz_selectedRows = new List<number>(selected.filter(rowId => this._tableDataIds.includes(rowId))); // filters through selected to remove guids that were removed in the incoming data
+        const highlighted = NumListCast(this._props.layoutDoc.dataViz_highlitedRows);
+        this._props.layoutDoc.dataViz_highlitedRows = new List<number>(highlighted.filter(rowId => this._tableDataIds.includes(rowId))); // filters through highlighted to remove guids that were removed in the incoming data
     };
 
     @computed get viewScale() {
-        return this.props.docView?.()?._props.ScreenToLocalTransform().Scale || 1;
+        return this._props.docView?.()?._props.ScreenToLocalTransform().Scale || 1;
     }
     @computed get rowHeight() {
         console.log('scale = ' + this.viewScale + '  table = ' + this._tableHeight + ' ids = ' + this._tableDataIds.length);
@@ -89,14 +94,14 @@ export class TableBox extends React.Component<TableBoxProps> {
         return Math.ceil(this.startID + (this._tableContainerHeight * this.viewScale) / (this.rowHeight || 1));
     }
     @action handleScroll = () => {
-        if (!this.props.docView?.()?.ContentDiv?.hidden) {
+        if (!this._props.docView?.()?.ContentDiv?.hidden) {
             this._scrollTop = this._containerRef?.scrollTop ?? 0;
         }
     };
     @action
     tableRowClick = (e: React.MouseEvent, rowId: number) => {
-        const highlited = Cast(this.props.layoutDoc.dataViz_highlitedRows, listSpec('number'), null);
-        const selected = Cast(this.props.layoutDoc.dataViz_selectedRows, listSpec('number'), null);
+        const highlited = Cast(this._props.layoutDoc.dataViz_highlitedRows, listSpec('number'), null);
+        const selected = Cast(this._props.layoutDoc.dataViz_selectedRows, listSpec('number'), null);
         if (e.metaKey) {
             // highlighting a row
             if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1);
@@ -120,26 +125,26 @@ export class TableBox extends React.Component<TableBoxProps> {
             e,
             e => {
                 // dragging off a column to create a brushed DataVizBox
-                const sourceAnchorCreator = () => this.props.docView?.()!.Document!;
+                const sourceAnchorCreator = () => this._props.docView?.()!.Document!;
                 const targetCreator = (annotationOn: Doc | undefined) => {
-                    const embedding = Doc.MakeEmbedding(this.props.docView?.()!.Document!);
+                    const embedding = Doc.MakeEmbedding(this._props.docView?.()!.Document!);
                     embedding._dataViz = DataVizView.TABLE;
                     embedding._dataViz_axes = new List<string>([col, col]);
-                    embedding._dataViz_parentViz = this.props.Document;
+                    embedding._dataViz_parentViz = this._props.Document;
                     embedding.annotationOn = annotationOn;
-                    embedding.histogramBarColors = Field.Copy(this.props.layoutDoc.histogramBarColors);
-                    embedding.defaultHistogramColor = this.props.layoutDoc.defaultHistogramColor;
-                    embedding.pieSliceColors = Field.Copy(this.props.layoutDoc.pieSliceColors);
+                    embedding.histogramBarColors = Field.Copy(this._props.layoutDoc.histogramBarColors);
+                    embedding.defaultHistogramColor = this._props.layoutDoc.defaultHistogramColor;
+                    embedding.pieSliceColors = Field.Copy(this._props.layoutDoc.pieSliceColors);
                     return embedding;
                 };
-                if (this.props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
-                    DragManager.StartAnchorAnnoDrag(e.target instanceof HTMLElement ? [e.target] : [], new DragManager.AnchorAnnoDragData(this.props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, {
+                if (this._props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
+                    DragManager.StartAnchorAnnoDrag(e.target instanceof HTMLElement ? [e.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, {
                         dragComplete: e => {
                             if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) {
                                 e.linkDocument.link_displayLine = true;
                                 e.linkDocument.link_matchEmbeddings = true;
                                 e.linkDocument.link_displayArrow = true;
-                                // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.Document;
+                                // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this._props.Document;
                                 // e.annoDragData.linkSourceDoc.followLinkZoom = false;
                             }
                         },
@@ -150,11 +155,11 @@ export class TableBox extends React.Component<TableBoxProps> {
             },
             emptyFunction,
             action(e => {
-                const newAxes = this.props.axes;
+                const newAxes = this._props.axes;
                 if (newAxes.includes(col)) newAxes.splice(newAxes.indexOf(col), 1);
                 else if (newAxes.length > 1) newAxes[1] = col;
                 else newAxes.push(col);
-                this.props.selectAxes(newAxes);
+                this._props.selectAxes(newAxes);
             })
         );
     };
@@ -166,14 +171,14 @@ export class TableBox extends React.Component<TableBoxProps> {
                     className="tableBox"
                     tabIndex={0}
                     onKeyDown={e => {
-                        if (this.props.layoutDoc && e.key === 'a' && (e.ctrlKey || e.metaKey)) {
+                        if (this._props.layoutDoc && e.key === 'a' && (e.ctrlKey || e.metaKey)) {
                             e.stopPropagation();
-                            this.props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds);
+                            this._props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds);
                         }
                     }}>
                     <div className="selectAll-buttons">
-                        <Button onClick={action(() => (this.props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds)))} text="Select All" type={Type.SEC} color={'black'} />
-                        <Button onClick={action(() => (this.props.layoutDoc.dataViz_selectedRows = new List<number>()))} text="Deselect All" type={Type.SEC} color={'black'} />
+                        <Button onClick={action(() => (this._props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds)))} text="Select All" type={Type.SEC} color={'black'} />
+                        <Button onClick={action(() => (this._props.layoutDoc.dataViz_selectedRows = new List<number>()))} text="Deselect All" type={Type.SEC} color={'black'} />
                     </div>
                     <div
                         className={`tableBox-container ${this.columns[0]}`}
@@ -181,7 +186,7 @@ export class TableBox extends React.Component<TableBoxProps> {
                         onScroll={this.handleScroll}
                         ref={action((r: HTMLDivElement | null) => {
                             this._containerRef = r;
-                            if (!this.props.docView?.()?.ContentDiv?.hidden && r) {
+                            if (!this._props.docView?.()?.ContentDiv?.hidden && r) {
                                 this._tableContainerHeight = r.getBoundingClientRect().height ?? 0;
                                 r.addEventListener(
                                     'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
@@ -196,7 +201,7 @@ export class TableBox extends React.Component<TableBoxProps> {
                         <table
                             className="tableBox-table"
                             ref={action((r: HTMLTableElement | null) => {
-                                if (!this.props.docView?.()?.ContentDiv?.hidden && r) {
+                                if (!this._props.docView?.()?.ContentDiv?.hidden && r) {
                                     this._tableHeight = r?.getBoundingClientRect().height ?? 0;
                                 }
                             })}>
@@ -207,8 +212,8 @@ export class TableBox extends React.Component<TableBoxProps> {
                                         <th
                                             key={this.columns.indexOf(col)}
                                             style={{
-                                                color: this.props.axes.slice().reverse().lastElement() === col ? 'darkgreen' : this.props.axes.lastElement() === col ? 'darkred' : undefined,
-                                                background: this.props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' : this.props.axes.lastElement() === col ? '#Fbdbdb' : undefined,
+                                                color: this._props.axes.slice().reverse().lastElement() === col ? 'darkgreen' : this._props.axes.lastElement() === col ? 'darkred' : undefined,
+                                                background: this._props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' : this._props.axes.lastElement() === col ? '#Fbdbdb' : undefined,
                                                 fontWeight: 'bolder',
                                                 border: '3px solid black',
                                             }}
@@ -227,13 +232,13 @@ export class TableBox extends React.Component<TableBoxProps> {
                                             className={`tableBox-row ${this.columns[0]}`}
                                             onClick={e => this.tableRowClick(e, rowId)}
                                             style={{
-                                                background: NumListCast(this.props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this.props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '',
+                                                background: NumListCast(this._props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '',
                                             }}>
                                             {this.columns.map(col => {
-                                                const colSelected = this.props.axes.length > 1 ? this.props.axes[0] == col || this.props.axes[1] == col : this.props.axes.length > 0 ? this.props.axes[0] == col : false;
+                                                const colSelected = this._props.axes.length > 1 ? this._props.axes[0] == col || this._props.axes[1] == col : this._props.axes.length > 0 ? this._props.axes[0] == col : false;
                                                 return (
                                                     <td key={this.columns.indexOf(col)} style={{ border: colSelected ? '3px solid black' : '1px solid black', fontWeight: colSelected ? 'bolder' : 'normal' }}>
-                                                        <div className="tableBox-cell">{this.props.records[rowId][col]}</div>
+                                                        <div className="tableBox-cell">{this._props.records[rowId][col]}</div>
                                                     </td>
                                                 );
                                             })}
diff --git a/src/client/views/nodes/MapBox/AnimationUtility.ts b/src/client/views/nodes/MapBox/AnimationUtility.ts
index 256acbf13..13ce5b7e2 100644
--- a/src/client/views/nodes/MapBox/AnimationUtility.ts
+++ b/src/client/views/nodes/MapBox/AnimationUtility.ts
@@ -1,13 +1,13 @@
-import mapboxgl from "mapbox-gl";
-import { MercatorCoordinate } from "mapbox-gl";
-import { MapRef } from "react-map-gl";
+import mapboxgl from 'mapbox-gl';
+import { MercatorCoordinate } from 'mapbox-gl';
+import { MapRef } from 'react-map-gl';
 import * as React from 'react';
-import * as d3 from "d3";
+import * as d3 from 'd3';
 import * as turf from '@turf/turf';
-import { Position } from "@turf/turf";
-import { Feature, FeatureCollection, GeoJsonProperties, Geometry } from "geojson";
-import { observer } from "mobx-react";
-import { action, computed, observable } from "mobx";
+import { Position } from '@turf/turf';
+import { Feature, FeatureCollection, GeoJsonProperties, Geometry } from 'geojson';
+import { observer } from 'mobx-react';
+import { action, computed, observable } from 'mobx';
 
 export enum AnimationStatus {
     START = 'start',
@@ -21,37 +21,35 @@ export enum AnimationSpeed {
     FAST = '3x',
 }
 
-@observer
 export class AnimationUtility {
-    private SMOOTH_FACTOR = 0.95
-    private ROUTE_COORDINATES: Position[] = []; 
+    private SMOOTH_FACTOR = 0.95;
+    private ROUTE_COORDINATES: Position[] = [];
     private PATH: turf.helpers.Feature<turf.helpers.LineString, turf.helpers.Properties>;
     private FLY_IN_START_PITCH = 40;
-    private FIRST_LNG_LAT: {lng: number, lat: number};
+    private FIRST_LNG_LAT: { lng: number; lat: number };
     private START_ALTITUDE = 3_000_000;
 
     @observable private isStreetViewAnimation: boolean;
     @observable private animationSpeed: AnimationSpeed;
 
-    
-    private previousLngLat: {lng: number, lat: number};
+    private previousLngLat: { lng: number; lat: number };
 
     private currentStreetViewBearing: number = 0;
 
     @computed get flyInEndBearing() {
-        return this.isStreetViewAnimation ? 
-            this.calculateBearing(
-                {
-                    lng: this.ROUTE_COORDINATES[0][0],
-                    lat: this.ROUTE_COORDINATES[0][1]
-                },
-                {
-                    lng: this.ROUTE_COORDINATES[1][0],
-                    lat: this.ROUTE_COORDINATES[1][1]
-                }
-            )
+        return this.isStreetViewAnimation
+            ? this.calculateBearing(
+                  {
+                      lng: this.ROUTE_COORDINATES[0][0],
+                      lat: this.ROUTE_COORDINATES[0][1],
+                  },
+                  {
+                      lng: this.ROUTE_COORDINATES[1][0],
+                      lat: this.ROUTE_COORDINATES[1][1],
+                  }
+              )
             : -20;
-        }
+    }
 
     @computed get flyInStartBearing() {
         return Math.max(0, Math.min(this.flyInEndBearing + 20, 360)); // between 0 and 360
@@ -80,8 +78,8 @@ export class AnimationUtility {
 
     @computed get animationDuration(): number {
         return 20_000;
-        // compute path distance for a standard speed 
-        // get animation speed 
+        // compute path distance for a standard speed
+        // get animation speed
         // get isStreetViewAnimation (should be slower if so)
     }
 
@@ -90,19 +88,13 @@ export class AnimationUtility {
         // calculate new flyToDuration and animationDuration
         this.animationSpeed = speed;
     }
-    
+
     @action
     public updateIsStreetViewAnimation(isStreetViewAnimation: boolean) {
         this.isStreetViewAnimation = isStreetViewAnimation;
     }
 
-
-    constructor(
-        firstLngLat: {lng: number, lat: number},
-        routeCoordinates: Position[],
-        isStreetViewAnimation: boolean,
-        animationSpeed: AnimationSpeed
-    ) {
+    constructor(firstLngLat: { lng: number; lat: number }, routeCoordinates: Position[], isStreetViewAnimation: boolean, animationSpeed: AnimationSpeed) {
         this.FIRST_LNG_LAT = firstLngLat;
         this.previousLngLat = firstLngLat;
         this.ROUTE_COORDINATES = routeCoordinates;
@@ -111,11 +103,11 @@ export class AnimationUtility {
         const bearing = this.calculateBearing(
             {
                 lng: routeCoordinates[0][0],
-                lat: routeCoordinates[0][1]
+                lat: routeCoordinates[0][1],
             },
             {
                 lng: routeCoordinates[1][0],
-                lat: routeCoordinates[1][1]
+                lat: routeCoordinates[1][1],
             }
         );
         this.currentStreetViewBearing = bearing;
@@ -137,293 +129,245 @@ export class AnimationUtility {
         currentAnimationPhase,
         updateAnimationPhase,
         updateFrameId,
-      }: {
-        map: MapRef,
+    }: {
+        map: MapRef;
         // path: turf.helpers.Feature<turf.helpers.LineString, turf.helpers.Properties>,
         // startBearing: number,
         // startAltitude: number,
         // pitch: number,
-        currentAnimationPhase: number,
-        updateAnimationPhase: ( 
-            newAnimationPhase: number,
-            ) => void,
+        currentAnimationPhase: number;
+        updateAnimationPhase: (newAnimationPhase: number) => void;
         updateFrameId: (newFrameId: number) => void;
+    }) => {
+        return new Promise<void>(async resolve => {
+            const pathDistance = turf.lineDistance(this.PATH);
+            console.log('PATH DISTANCE: ', pathDistance);
+            let startTime: number | null = null;
+
+            const frame = async (currentTime: number) => {
+                if (!startTime) startTime = currentTime;
+                const elapsedSinceLastFrame = currentTime - startTime;
+                const phaseIncrement = elapsedSinceLastFrame / this.animationDuration;
+                const animationPhase = currentAnimationPhase + phaseIncrement;
+
+                // when the duration is complete, resolve the promise and stop iterating
+                if (animationPhase > 1) {
+                    resolve();
+                    return;
+                }
 
-      }) => {
-        return new Promise<void>(async (resolve) => {
-          const pathDistance = turf.lineDistance(this.PATH);
-          console.log("PATH DISTANCE: ", pathDistance);
-          let startTime: number | null = null;
-      
-          const frame = async (currentTime: number) => {
-            if (!startTime) startTime = currentTime;
-            const elapsedSinceLastFrame = currentTime - startTime;
-            const phaseIncrement = elapsedSinceLastFrame / this.animationDuration;
-            const animationPhase = currentAnimationPhase + phaseIncrement;
-      
-            // when the duration is complete, resolve the promise and stop iterating
-            if (animationPhase > 1) {
-              resolve();
-              return;
-            }
+                // calculate the distance along the path based on the animationPhase
+                const alongPath = turf.along(this.PATH, pathDistance * animationPhase).geometry.coordinates;
+
+                const lngLat = {
+                    lng: alongPath[0],
+                    lat: alongPath[1],
+                };
+
+                let bearing: number;
+                if (this.isStreetViewAnimation) {
+                    bearing = this.lerp(
+                        this.currentStreetViewBearing,
+                        this.calculateBearing(this.previousLngLat, lngLat),
+                        0.028 // Adjust the transition speed as needed
+                    );
+                    this.currentStreetViewBearing = bearing;
+                    // bearing = this.calculateBearing(this.previousLngLat, lngLat); // TODO: Calculate actual bearing
+                } else {
+                    // slowly rotate the map at a constant rate
+                    bearing = this.flyInEndBearing - animationPhase * 200.0;
+                    // bearing = startBearing - animationPhase * 200.0;
+                }
+
+                this.previousLngLat = lngLat;
+
+                updateAnimationPhase(animationPhase);
+
+                // compute corrected camera ground position, so that he leading edge of the path is in view
+                var correctedPosition = this.computeCameraPosition(
+                    this.isStreetViewAnimation,
+                    this.flyInEndPitch,
+                    bearing,
+                    lngLat,
+                    this.flyInEndAltitude,
+                    true // smooth
+                );
+
+                // set the pitch and bearing of the camera
+                const camera = map.getFreeCameraOptions();
+                camera.setPitchBearing(this.flyInEndPitch, bearing);
+
+                console.log('Corrected pos: ', correctedPosition);
+                console.log('Start altitude: ', this.flyInEndAltitude);
+                // set the position and altitude of the camera
+                camera.position = MercatorCoordinate.fromLngLat(correctedPosition, this.flyInEndAltitude);
+
+                // apply the new camera options
+                map.setFreeCameraOptions(camera);
 
-      
-            // calculate the distance along the path based on the animationPhase
-            const alongPath = turf.along(this.PATH, pathDistance * animationPhase).geometry
-              .coordinates;
-      
-            const lngLat = {
-              lng: alongPath[0],
-              lat: alongPath[1],
+                // repeat!
+                const innerFrameId = await window.requestAnimationFrame(frame);
+                updateFrameId(innerFrameId);
             };
-      
-            let bearing: number;
-            if (this.isStreetViewAnimation){
-                bearing = this.lerp(
-                    this.currentStreetViewBearing,
-                    this.calculateBearing(this.previousLngLat, lngLat),
-                    0.028 // Adjust the transition speed as needed
-                  );
-                  this.currentStreetViewBearing = bearing;
-                // bearing = this.calculateBearing(this.previousLngLat, lngLat); // TODO: Calculate actual bearing
-            } else {
-                // slowly rotate the map at a constant rate
-                bearing = this.flyInEndBearing - animationPhase * 200.0;
-                // bearing = startBearing - animationPhase * 200.0;
-            }
 
-            this.previousLngLat = lngLat;
-            
-            updateAnimationPhase(animationPhase);
-      
-            // compute corrected camera ground position, so that he leading edge of the path is in view
-            var correctedPosition = this.computeCameraPosition(
-              this.isStreetViewAnimation,
-              this.flyInEndPitch,
-              bearing,
-              lngLat,
-              this.flyInEndAltitude,
-              true // smooth
-            );
-      
-            // set the pitch and bearing of the camera
-            const camera = map.getFreeCameraOptions();
-            camera.setPitchBearing(this.flyInEndPitch, bearing);
-      
-            console.log("Corrected pos: ", correctedPosition);
-            console.log("Start altitude: ", this.flyInEndAltitude);
-            // set the position and altitude of the camera
-            camera.position = MercatorCoordinate.fromLngLat(
-              correctedPosition,
-              this.flyInEndAltitude
-            );
-
-      
-            // apply the new camera options
-            map.setFreeCameraOptions(camera);
-      
-            // repeat!
-            const innerFrameId = await window.requestAnimationFrame(frame);
-            updateFrameId(innerFrameId);
-          };
-      
-          const outerFrameId = await window.requestAnimationFrame(frame);
-          updateFrameId(outerFrameId);
+            const outerFrameId = await window.requestAnimationFrame(frame);
+            updateFrameId(outerFrameId);
         });
-      };
+    };
 
-    public flyInAndRotate = async ({
-        map,
-        updateFrameId
-      }:
-      {
-        map: MapRef,
-        updateFrameId: (newFrameId: number) => void
-      }
-      ) => {
-        return new Promise<{bearing: number, altitude: number}>(async (resolve) => {
-          let start: number | null;
-      
-          var currentAltitude;
-          var currentBearing;
-          var currentPitch;
-      
-          // the animation frame will run as many times as necessary until the duration has been reached
-          const frame = async (time: number) => {
-            if (!start) {
-              start = time;
-            }
-      
-            // otherwise, use the current time to determine how far along in the duration we are
-            let animationPhase = (time - start) / this.flyToDuration;
-      
-            // because the phase calculation is imprecise, the final zoom can vary
-            // if it ended up greater than 1, set it to 1 so that we get the exact endAltitude that was requested
-            if (animationPhase > 1) {
-              animationPhase = 1;
-            }
-      
-            currentAltitude = this.START_ALTITUDE + (this.flyInEndAltitude - this.START_ALTITUDE) * d3.easeCubicOut(animationPhase)
-            // rotate the camera between startBearing and endBearing
-            currentBearing = this.flyInStartBearing + (this.flyInEndBearing - this.flyInStartBearing) * d3.easeCubicOut(animationPhase)
-      
-            currentPitch = this.FLY_IN_START_PITCH + (this.flyInEndPitch - this.FLY_IN_START_PITCH) * d3.easeCubicOut(animationPhase)
-      
-            // compute corrected camera ground position, so the start of the path is always in view
-            var correctedPosition = this.computeCameraPosition(
-              false,
-              currentPitch,
-              currentBearing,
-              this.FIRST_LNG_LAT,
-              currentAltitude
-            );
-      
-            // set the pitch and bearing of the camera
-            const camera = map.getFreeCameraOptions();
-            camera.setPitchBearing(currentPitch, currentBearing);
-      
-            // set the position and altitude of the camera
-            camera.position = MercatorCoordinate.fromLngLat(
-              correctedPosition,
-              currentAltitude
-            );
-      
-            // apply the new camera options
-            map.setFreeCameraOptions(camera);
-      
-            // when the animationPhase is done, resolve the promise so the parent function can move on to the next step in the sequence
-            if (animationPhase === 1) {
-              resolve({
-                bearing: currentBearing,
-                altitude: currentAltitude,
-              });
-      
-              // return so there are no further iterations of this frame
-              return;
-            }
-      
-            const innerFrameId = await window.requestAnimationFrame(frame);
-            updateFrameId(innerFrameId);
-            
-          };
-      
-         const outerFrameId = await window.requestAnimationFrame(frame);
-         updateFrameId(outerFrameId);
+    public flyInAndRotate = async ({ map, updateFrameId }: { map: MapRef; updateFrameId: (newFrameId: number) => void }) => {
+        return new Promise<{ bearing: number; altitude: number }>(async resolve => {
+            let start: number | null;
+
+            var currentAltitude;
+            var currentBearing;
+            var currentPitch;
+
+            // the animation frame will run as many times as necessary until the duration has been reached
+            const frame = async (time: number) => {
+                if (!start) {
+                    start = time;
+                }
+
+                // otherwise, use the current time to determine how far along in the duration we are
+                let animationPhase = (time - start) / this.flyToDuration;
+
+                // because the phase calculation is imprecise, the final zoom can vary
+                // if it ended up greater than 1, set it to 1 so that we get the exact endAltitude that was requested
+                if (animationPhase > 1) {
+                    animationPhase = 1;
+                }
+
+                currentAltitude = this.START_ALTITUDE + (this.flyInEndAltitude - this.START_ALTITUDE) * d3.easeCubicOut(animationPhase);
+                // rotate the camera between startBearing and endBearing
+                currentBearing = this.flyInStartBearing + (this.flyInEndBearing - this.flyInStartBearing) * d3.easeCubicOut(animationPhase);
+
+                currentPitch = this.FLY_IN_START_PITCH + (this.flyInEndPitch - this.FLY_IN_START_PITCH) * d3.easeCubicOut(animationPhase);
+
+                // compute corrected camera ground position, so the start of the path is always in view
+                var correctedPosition = this.computeCameraPosition(false, currentPitch, currentBearing, this.FIRST_LNG_LAT, currentAltitude);
+
+                // set the pitch and bearing of the camera
+                const camera = map.getFreeCameraOptions();
+                camera.setPitchBearing(currentPitch, currentBearing);
+
+                // set the position and altitude of the camera
+                camera.position = MercatorCoordinate.fromLngLat(correctedPosition, currentAltitude);
+
+                // apply the new camera options
+                map.setFreeCameraOptions(camera);
+
+                // when the animationPhase is done, resolve the promise so the parent function can move on to the next step in the sequence
+                if (animationPhase === 1) {
+                    resolve({
+                        bearing: currentBearing,
+                        altitude: currentAltitude,
+                    });
+
+                    // return so there are no further iterations of this frame
+                    return;
+                }
+
+                const innerFrameId = await window.requestAnimationFrame(frame);
+                updateFrameId(innerFrameId);
+            };
+
+            const outerFrameId = await window.requestAnimationFrame(frame);
+            updateFrameId(outerFrameId);
         });
-      };
+    };
 
-      previousCameraPosition: {lng: number, lat: number} | null = null;
+    previousCameraPosition: { lng: number; lat: number } | null = null;
 
-      lerp = (start: number, end: number, amt: number) => {
+    lerp = (start: number, end: number, amt: number) => {
         return (1 - amt) * start + amt * end;
-      }
-
-      computeCameraPosition = (
-        isStreetViewAnimation: boolean,
-        pitch: number,
-        bearing: number,
-        targetPosition: {lng: number, lat: number},
-        altitude: number,
-        smooth = false
-      ) => {
+    };
+
+    computeCameraPosition = (isStreetViewAnimation: boolean, pitch: number, bearing: number, targetPosition: { lng: number; lat: number }, altitude: number, smooth = false) => {
         const bearingInRadian = (bearing * Math.PI) / 180;
-        const pitchInRadian = ((90 - pitch)* Math.PI) / 180;
+        const pitchInRadian = ((90 - pitch) * Math.PI) / 180;
 
         let correctedLng = targetPosition.lng;
         let correctedLat = targetPosition.lat;
 
         if (!isStreetViewAnimation) {
-            const lngDiff =
-                ((altitude / Math.tan(pitchInRadian)) *
-                Math.sin(-bearingInRadian)) /
-                70000; // ~70km/degree longitude
-            const latDiff =
-                ((altitude / Math.tan(pitchInRadian)) *
-                Math.cos(-bearingInRadian)) /
-                110000 // 110km/degree latitude
+            const lngDiff = ((altitude / Math.tan(pitchInRadian)) * Math.sin(-bearingInRadian)) / 70000; // ~70km/degree longitude
+            const latDiff = ((altitude / Math.tan(pitchInRadian)) * Math.cos(-bearingInRadian)) / 110000; // 110km/degree latitude
 
             correctedLng = targetPosition.lng + lngDiff;
             correctedLat = targetPosition.lat - latDiff;
-
         }
-        
+
         const newCameraPosition = {
-          lng: correctedLng,
-          lat: correctedLat
+            lng: correctedLng,
+            lat: correctedLat,
         };
-      
+
         if (smooth) {
-          if (this.previousCameraPosition) {
-            newCameraPosition.lng = this.lerp(newCameraPosition.lng, this.previousCameraPosition.lng, this.SMOOTH_FACTOR);
-            newCameraPosition.lat = this.lerp(newCameraPosition.lat, this.previousCameraPosition.lat, this.SMOOTH_FACTOR);
-          }
+            if (this.previousCameraPosition) {
+                newCameraPosition.lng = this.lerp(newCameraPosition.lng, this.previousCameraPosition.lng, this.SMOOTH_FACTOR);
+                newCameraPosition.lat = this.lerp(newCameraPosition.lat, this.previousCameraPosition.lat, this.SMOOTH_FACTOR);
+            }
         }
-      
-        this.previousCameraPosition = newCameraPosition
-      
+
+        this.previousCameraPosition = newCameraPosition;
+
         return newCameraPosition;
-      };
-      
-      public static createGeoJSONCircle = (center: number[], radiusInKm: number, points = 64): Feature<Geometry, GeoJsonProperties>=> {
+    };
+
+    public static createGeoJSONCircle = (center: number[], radiusInKm: number, points = 64): Feature<Geometry, GeoJsonProperties> => {
         const coords = {
-          latitude: center[1],
-          longitude: center[0],
+            latitude: center[1],
+            longitude: center[0],
         };
         const km = radiusInKm;
         const ret = [];
-        const distanceX = km / (111.320 * Math.cos((coords.latitude * Math.PI) / 180));
+        const distanceX = km / (111.32 * Math.cos((coords.latitude * Math.PI) / 180));
         const distanceY = km / 110.574;
         let theta;
         let x;
         let y;
         for (let i = 0; i < points; i += 1) {
-          theta = (i / points) * (2 * Math.PI);
-          x = distanceX * Math.cos(theta);
-          y = distanceY * Math.sin(theta);
-          ret.push([coords.longitude + x, coords.latitude + y]);
+            theta = (i / points) * (2 * Math.PI);
+            x = distanceX * Math.cos(theta);
+            y = distanceY * Math.sin(theta);
+            ret.push([coords.longitude + x, coords.latitude + y]);
         }
         ret.push(ret[0]);
         return {
-          type: 'Feature',
-          geometry: {
-            type: 'Polygon',
-            coordinates: [ret],
-          },
-          properties: {}
+            type: 'Feature',
+            geometry: {
+                type: 'Polygon',
+                coordinates: [ret],
+            },
+            properties: {},
         };
-      }
+    };
 
-      private calculateBearing(
-        from: { lng: number; lat: number },
-        to: { lng: number; lat: number }
-      ): number {
+    private calculateBearing(from: { lng: number; lat: number }, to: { lng: number; lat: number }): number {
         const lon1 = from.lng;
         const lat1 = from.lat;
         const lon2 = to.lng;
         const lat2 = to.lat;
-      
+
         const lon1Rad = (lon1 * Math.PI) / 180;
         const lon2Rad = (lon2 * Math.PI) / 180;
         const lat1Rad = (lat1 * Math.PI) / 180;
         const lat2Rad = (lat2 * Math.PI) / 180;
-      
+
         const y = Math.sin(lon2Rad - lon1Rad) * Math.cos(lat2Rad);
-        const x =
-          Math.cos(lat1Rad) * Math.sin(lat2Rad) -
-          Math.sin(lat1Rad) * Math.cos(lat2Rad) * Math.cos(lon2Rad - lon1Rad);
-      
-        let bearing = Math.atan2(y,x);
-      
+        const x = Math.cos(lat1Rad) * Math.sin(lat2Rad) - Math.sin(lat1Rad) * Math.cos(lat2Rad) * Math.cos(lon2Rad - lon1Rad);
+
+        let bearing = Math.atan2(y, x);
+
         // Convert bearing from radians to degrees
         bearing = (bearing * 180) / Math.PI;
-      
+
         // Ensure the bearing is within [0, 360)
         if (bearing < 0) {
-          bearing += 360;
+            bearing += 360;
         }
-      
-        return bearing;
-      }
-
 
-}
\ No newline at end of file
+        return bearing;
+    }
+}
diff --git a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
index bf4028f01..f9607becf 100644
--- a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
+++ b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
@@ -1,15 +1,15 @@
-import React = require('react');
-import { observer } from "mobx-react";
-import { AntimodeMenu, AntimodeMenuProps } from "../../AntimodeMenu";
-import { IReactionDisposer, ObservableMap, reaction } from "mobx";
-import { Doc, Opt } from "../../../../fields/Doc";
-import { returnFalse, unimplementedFunction } from "../../../../Utils";
-import { NumCast, StrCast } from "../../../../fields/Types";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { IconButton } from "browndash-components";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { SettingsManager } from "../../../util/SettingsManager";
-import { IconLookup, faAdd, faCalendarDays, faRoute } from "@fortawesome/free-solid-svg-icons";
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
+import { IReactionDisposer, ObservableMap, reaction } from 'mobx';
+import { Doc, Opt } from '../../../../fields/Doc';
+import { returnFalse, unimplementedFunction } from '../../../../Utils';
+import { NumCast, StrCast } from '../../../../fields/Types';
+import { SelectionManager } from '../../../util/SelectionManager';
+import { IconButton } from 'browndash-components';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { SettingsManager } from '../../../util/SettingsManager';
+import { IconLookup, faAdd, faCalendarDays, faRoute } from '@fortawesome/free-solid-svg-icons';
 
 @observer
 export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -32,9 +32,9 @@ export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     private title: string | undefined = undefined;
 
-    public setPinDoc(pinDoc: Doc){
-        this.title = StrCast(pinDoc.title ? pinDoc.title : `${NumCast(pinDoc.longitude)}, ${NumCast(pinDoc.latitude)}`) ;
-        console.log("Title: ", this.title)
+    public setPinDoc(pinDoc: Doc) {
+        this.title = StrCast(pinDoc.title ? pinDoc.title : `${NumCast(pinDoc.longitude)}, ${NumCast(pinDoc.latitude)}`);
+        console.log('Title: ', this.title);
     }
 
     public get Active() {
@@ -54,7 +54,7 @@ export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     componentDidMount() {
         this._disposer = reaction(
-            () => SelectionManager.Views().slice(),
+            () => SelectionManager.Views.slice(),
             sel => DirectionsAnchorMenu.Instance.fadeOut(true)
         );
     }
@@ -95,43 +95,28 @@ export class DirectionsAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
 
     render() {
         const buttons = (
-            <div className='directions-menu-buttons' style={{display: 'flex'}}>
+            <div className="directions-menu-buttons" style={{ display: 'flex' }}>
                 <IconButton
                     tooltip="Add route" //
                     onPointerDown={this.Delete}
                     icon={<FontAwesomeIcon icon={faAdd as IconLookup} />}
                     color={SettingsManager.userColor}
                 />
-            
-            
-                <IconButton
-                    tooltip='Animate route'
-                    onPointerDown={this.Delete} /**TODO: fix */
-                    icon={<FontAwesomeIcon icon={faRoute as IconLookup}/>}
-                    color={SettingsManager.userColor}
-                />
-                <IconButton
-                    tooltip='Add to calendar'
-                    onPointerDown={this.Delete} /**TODO: fix */
-                    icon={<FontAwesomeIcon icon={faCalendarDays as IconLookup}/>}
-                    color={SettingsManager.userColor}
-                />
+
+                <IconButton tooltip="Animate route" onPointerDown={this.Delete} /**TODO: fix */ icon={<FontAwesomeIcon icon={faRoute as IconLookup} />} color={SettingsManager.userColor} />
+                <IconButton tooltip="Add to calendar" onPointerDown={this.Delete} /**TODO: fix */ icon={<FontAwesomeIcon icon={faCalendarDays as IconLookup} />} color={SettingsManager.userColor} />
             </div>
-        )
+        );
 
         return this.getElement(
-            <div ref={DirectionsAnchorMenu.top} style={{ height: 'max-content' , width: '100%', display: 'flex', flexDirection: 'column' }}>
+            <div ref={DirectionsAnchorMenu.top} style={{ height: 'max-content', width: '100%', display: 'flex', flexDirection: 'column' }}>
                 <div>{this.title}</div>
-                <div className='direction-inputs' style={{display: 'flex', flexDirection: 'column'}}>
-                    <input
-                        placeholder="Origin"
-                    />
-                    <input
-                        placeholder="Destination"
-                    />
+                <div className="direction-inputs" style={{ display: 'flex', flexDirection: 'column' }}>
+                    <input placeholder="Origin" />
+                    <input placeholder="Destination" />
                 </div>
                 {buttons}
             </div>
-        )
+        );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
index a6182991d..6a14427c0 100644
--- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
+++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
@@ -43,7 +43,7 @@ import { MapProvider, Map as MapboxMap } from 'react-map-gl';
  * A map marker is considered a document that contains a collection with stacking view of documents, it has a lat, lng location, which is passed to Maps API's custom marker (red pin) to be rendered on the google maps
  */
 
-const mapboxApiKey = "pk.eyJ1IjoiemF1bHRhdmFuZ2FyIiwiYSI6ImNsbnc2eHJpbTA1ZTUyam85aGx4Z2FhbGwifQ.2Kqw9mk-9wAAg9kmHmKzcg";
+const mapboxApiKey = 'pk.eyJ1IjoiemF1bHRhdmFuZ2FyIiwiYSI6ImNsbnc2eHJpbTA1ZTUyam85aGx4Z2FhbGwifQ.2Kqw9mk-9wAAg9kmHmKzcg';
 const bingApiKey = process.env.BING_MAPS; // if you're running local, get a Bing Maps api key here: https://www.bingmapsportal.com/  and then add it to the .env file in the Dash-Web root directory as: _CLIENT_BING_MAPS=<your apikey>
 
 /**
@@ -198,7 +198,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
                 title="Toggle Sidebar"
                 style={{
                     display: !this.props.isContentActive() ? 'none' : undefined,
-                    top: StrCast(this.rootDoc._layout_showTitle) === 'title' ? 20 : 5,
+                    top: StrCast(this.Document._layout_showTitle) === 'title' ? 20 : 5,
                     backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK,
                 }}
                 onPointerDown={this.sidebarBtnDown}>
@@ -230,8 +230,8 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
         });
 
         const targetCreator = (annotationOn: Doc | undefined) => {
-            const target = DocUtils.GetNewTextDoc('Note linked to ' + this.rootDoc.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow');
-            FormattedTextBox.SelectOnLoad = target[Id];
+            const target = DocUtils.GetNewTextDoc('Note linked to ' + this.Document.title, 0, 0, 100, 100, undefined, annotationOn, undefined, 'yellow');
+            FormattedTextBox.SetSelectOnLoad(target);
             return target;
         };
         const docView = this.props.DocumentView?.();
@@ -324,7 +324,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
     };
 
     @observable
-    bingSearchBarContents: any = this.rootDoc.map; // For Bing Maps: The contents of the Bing search bar (string)
+    bingSearchBarContents: any = this.Document.map; // For Bing Maps: The contents of the Bing search bar (string)
 
     geoDataRequestOptions = {
         entityType: 'PopulatedPlace',
@@ -357,9 +357,9 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
     deselectPin = () => {
         if (this.selectedPin) {
             // Removes filter
-            Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove');
-            Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove');
-            Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove');
+            Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'remove');
+            Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'remove');
+            Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove');
 
             const temp = this.selectedPin;
             if (!this._unmounting) {
@@ -372,7 +372,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
             }
             this.map_docToPinMap.set(temp, newpin);
             this.selectedPin = undefined;
-            this.bingSearchBarContents = this.rootDoc.map;
+            this.bingSearchBarContents = this.Document.map;
         }
     };
 
@@ -389,9 +389,9 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
         this.selectedPin = pinDoc;
         this.bingSearchBarContents = pinDoc.map;
 
-        // Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'match');
-        // Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'match');
-        Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPin)}`, 'check');
+        // Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'match');
+        // Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'match');
+        Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPin)}`, 'check');
 
         this.recolorPin(this.selectedPin, 'green');
 
@@ -460,8 +460,8 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
     getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps, existingPin?: Doc) => {
         /// this should use SELECTED pushpin for lat/long  if there is a selection, otherwise CENTER
         const anchor = Docs.Create.ConfigDocument({
-            title: 'MapAnchor:' + this.rootDoc.title,
-            text: StrCast(this.selectedPin?.map) || StrCast(this.rootDoc.map) || 'map location',
+            title: 'MapAnchor:' + this.Document.title,
+            text: StrCast(this.selectedPin?.map) || StrCast(this.Document.map) || 'map location',
             config_latitude: NumCast((existingPin ?? this.selectedPin)?.latitude ?? this.dataDoc.latitude),
             config_longitude: NumCast((existingPin ?? this.selectedPin)?.longitude ?? this.dataDoc.longitude),
             config_map_zoom: NumCast(this.dataDoc.map_zoom),
@@ -469,15 +469,15 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
             config_map: StrCast((existingPin ?? this.selectedPin)?.map) || StrCast(this.dataDoc.map),
             layout_unrendered: true,
             mapPin: existingPin ?? this.selectedPin,
-            annotationOn: this.rootDoc,
+            annotationOn: this.Document,
         });
         if (anchor) {
             if (!addAsAnnotation) anchor.backgroundColor = 'transparent';
             addAsAnnotation && this.addDocument(anchor);
-            PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.rootDoc);
+            PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), map: true } }, this.Document);
             return anchor;
         }
-        return this.rootDoc;
+        return this.Document;
     };
 
     map_docToPinMap = new Map<Doc, any>();
@@ -524,9 +524,9 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
     deleteSelectedPin = undoable(() => {
         if (this.selectedPin) {
             // Removes filter
-            Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove');
-            Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove');
-            Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove');
+            Doc.setDocFilter(this.Document, 'latitude', this.selectedPin.latitude, 'remove');
+            Doc.setDocFilter(this.Document, 'longitude', this.selectedPin.longitude, 'remove');
+            Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove');
 
             this.removePushpin(this.selectedPin);
         }
@@ -614,7 +614,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
         this.MicrosoftMaps.Events.addHandler(this._bingMap.current, 'maptypechanged', undoable(this.updateMapType, 'Map ViewType Change'));
 
         this._disposers.mapLocation = reaction(
-            () => this.rootDoc.map,
+            () => this.Document.map,
             mapLoc => (this.bingSearchBarContents = mapLoc),
             { fireImmediately: true }
         );
@@ -639,7 +639,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
         );
 
         this._disposers.location = reaction(
-            () => ({ lat: this.rootDoc.latitude, lng: this.rootDoc.longitude, zoom: this.rootDoc.map_zoom, mapType: this.rootDoc.map_type }),
+            () => ({ lat: this.Document.latitude, lng: this.Document.longitude, zoom: this.Document.map_zoom, mapType: this.Document.map_type }),
             locationObject => {
                 // if (this._bingMap.current)
                 try {
@@ -690,7 +690,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
                 }
             },
             e => {
-                const createPin = () => this.createPushpin(this.rootDoc.latitude, this.rootDoc.longitude, this.rootDoc.map);
+                const createPin = () => this.createPushpin(this.Document.latitude, this.Document.longitude, this.Document.map);
                 if (this.bingSearchBarContents) {
                     this.bingSearch().then(createPin);
                 } else createPin();
@@ -706,7 +706,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
     render() {
         // bcz:  no idea what's going on here, but bings maps have some kind of bug
         // such that we need to delay rendering a second map on startup until the first map is rendered.
-        this.rootDoc[DocCss];
+        this.Document[DocCss];
         if (MapBoxContainer._rerenderDelay) {
             // prettier-ignore
             this._rerenderTimeout = this._rerenderTimeout ??
@@ -715,7 +715,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
                         MapBoxContainer._rerenderDelay = 0;
                     }
                     this._rerenderTimeout = undefined;
-                    this.rootDoc[DocCss] = this.rootDoc[DocCss] + 1;
+                    this.Document[DocCss] = this.Document[DocCss] + 1;
                 }), MapBoxContainer._rerenderDelay);
             return null;
         }
@@ -732,7 +732,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
                     style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: this.pointerEvents() }}>
                     <div style={{ mixBlendMode: 'multiply' }}>{renderAnnotations(this.transparentFilter)}</div>
                     {renderAnnotations(this.opaqueFilter)}
-                    {SnappingManager.GetIsDragging() ? null : renderAnnotations()}
+                    {SnappingManager.IsDragging ? null : renderAnnotations()}
 
                     <div className="mapBox-searchbar">
                         <EditableText
@@ -758,15 +758,10 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
                         </div>
                     </div>
                     <MapProvider>
-                        <MapboxMap
-                            id="mabox-map"
-                            mapStyle={`mapbox://styles/mapbox/streets-v9`}
-                            mapboxAccessToken={mapboxApiKey}
-                        />
+                        <MapboxMap id="mabox-map" mapStyle={`mapbox://styles/mapbox/streets-v9`} mapboxAccessToken={mapboxApiKey} />
                     </MapProvider>
-                    
-  
-{/* 
+
+                    {/* 
                     <BingMapsReact
                         onMapReady={this.bingMapReady} //
                         bingMapsKey={bingApiKey}
@@ -786,7 +781,6 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
                                           {...this.props}
                                           renderDepth={this.props.renderDepth + 1}
                                           Document={pushpin}
-                                          DataDoc={undefined}
                                           PanelWidth={returnOne}
                                           PanelHeight={returnOne}
                                           NativeWidth={returnOne}
@@ -824,7 +818,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<ViewBoxAnnotata
                         ref={this._sidebarRef}
                         {...this.props}
                         fieldKey={this.fieldKey}
-                        rootDoc={this.rootDoc}
+                        Document={this.Document}
                         layoutDoc={this.layoutDoc}
                         dataDoc={this.dataDoc}
                         usePanelWidth={true}
diff --git a/webpack.config.js b/webpack.config.js
index a153616b8..d92086bc2 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -12,7 +12,7 @@ const plugins = [
     // new ForkTsCheckerWebpackPlugin({
     //     typescript: {
     //         // useTypescriptIncrementalApi: true,
-    //         eslint: true,
+    //         // eslint: true,
     //         memoryLimit: 8192,
     //     },
     //     // tslint: true,
-- 
cgit v1.2.3-70-g09d2

