From d235c79c47687653c6ef0581ee8ec48f80b77ba4 Mon Sep 17 00:00:00 2001
From: ndittren <36773036+ndittren@users.noreply.github.com>
Date: Mon, 2 Feb 2026 15:08:46 -0500
Subject: [PATCH] Update to React 18
---
media/src/activity.tsx | 13 +-
media/src/activity/activity-map.tsx | 55 ++++----
.../project-activity-components/common.tsx | 3 +-
media/src/project.tsx | 13 +-
media/src/project/project-map.tsx | 53 ++++----
media/src/utils.ts | 21 +++-
package-lock.json | 117 ++++++++----------
package.json | 8 +-
8 files changed, 152 insertions(+), 131 deletions(-)
diff --git a/media/src/activity.tsx b/media/src/activity.tsx
index 0486a2824..89ac6f8a1 100644
--- a/media/src/activity.tsx
+++ b/media/src/activity.tsx
@@ -1,10 +1,11 @@
import React from 'react';
-import ReactDOM from 'react-dom';
+import { createRoot } from 'react-dom/client';
import { ActivityMap } from './activity/activity-map';
-ReactDOM.render(
-
+const container = document.getElementById('activity-map-container');
+if (container) {
+ const root = createRoot(container);
+ root.render(
- ,
- document.getElementById('activity-map-container')
-);
+ );
+}
diff --git a/media/src/activity/activity-map.tsx b/media/src/activity/activity-map.tsx
index cf4dc491d..365f8bf0d 100644
--- a/media/src/activity/activity-map.tsx
+++ b/media/src/activity/activity-map.tsx
@@ -1,14 +1,21 @@
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useState, useEffect, useRef, useCallback } from 'react';
import {
_MapContext as MapContext, StaticMap, NavigationControl, Popup, MapRef
} from 'react-map-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
// Deck.gl
-import DeckGL, { Controller, FlyToInterpolator } from 'deck.gl';
+import DeckGL, { FlyToInterpolator } from 'deck.gl';
import { BitmapLayer, IconLayer, IconLayerProps } from '@deck.gl/layers';
import { TileLayer } from '@deck.gl/geo-layers';
-import { Position } from '@deck.gl/core/utils/positions';
-import { PickInfo } from '@deck.gl/core/lib/deck';
+// import { PickInfo } from 'deck.gl';
+type Position = [number, number] | [number, number, number];
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+type PickInfo = any;
import { ActivityMapPane } from './activity-map-pane';
import { LoadingModal } from '../project-activity-components/loading-modal';
@@ -59,7 +66,7 @@ export const ActivityMap: React.FC = () => {
const [projectData, setProjectData] = useState(null);
const [responseData, setResponseData] = useState([]);
- const deckglMap = useRef(null);
+ const deckglMap = useRef(null);
const mapPane = useRef(null);
const navControlStyle= {
@@ -189,7 +196,7 @@ export const ActivityMap: React.FC = () => {
const updateActivity = (instructions: string, pk: number): void => {
const data = {
- project: projectPk,
+ project: projectPk ? parseInt(projectPk, 10) : undefined,
instructions: instructions
};
void put(`/api/activity/${pk}/`, data)
@@ -574,7 +581,7 @@ export const ActivityMap: React.FC = () => {
//Close Popup if there is a click after search
setShowSearchPopup(false);
// Cast to provide type def for coordinate
- const infoPrime = info as PickInfo & {coordinate: [number, number]};
+ const infoPrime = info;
// Create on single click, make sure that new event
// is not created when user intends to pick an existing event
@@ -663,7 +670,7 @@ export const ActivityMap: React.FC = () => {
return activeEventDetail && d.pk == activeEventDetail.pk ?
ICON_SIZE_ACTIVE : ICON_SIZE; },
getColor: () => {
- return layer.color ? ICON_COLOR[layer.color] : ICON_COLOR_DEFAULT; },
+ return (layer.color ? ICON_COLOR[layer.color] : ICON_COLOR_DEFAULT) as any; },
visible: layerVisibility.get(layer.pk) || false
});
return acc.concat(MBLayer);
@@ -682,7 +689,7 @@ export const ActivityMap: React.FC = () => {
sizeScale: ICON_SCALE,
getPosition: (d) => d.lngLat,
getSize: ICON_SIZE,
- getColor: ICON_COLOR_ACTIVE,
+ getColor: ICON_COLOR_ACTIVE as any,
}));
}
const handleViewportChange = useCallback(
@@ -691,7 +698,7 @@ export const ActivityMap: React.FC = () => {
[]
);
const handleGeocoderViewportChange = useCallback(
- (newViewport) => {
+ (newViewport: any) => {
const geocoderDefaultOverrides = { transitionDuration: 1000 };
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
@@ -910,7 +917,8 @@ export const ActivityMap: React.FC = () => {
getPosition: (d) => d.location.lng_lat,
onClick: pickEventClickHandler,
getSize: ICON_SIZE,
- getColor: ICON_COLOR[layer.color],
+ getColor: (layer.color ?
+ ICON_COLOR[layer.color] : ICON_COLOR_DEFAULT) as any,
})
);
}
@@ -986,19 +994,19 @@ export const ActivityMap: React.FC = () => {
for (const layer of projData.raster_layers) {
rLayers.push(new TileLayer({
data: layer.url,
- renderSubLayers: (obj: TileSublayerProps) => {
+ renderSubLayers: ((obj: TileSublayerProps) => {
const {
bbox: {west, south, east, north}
} = obj.tile;
- return new BitmapLayer({
+ return new BitmapLayer(({
id: obj.id,
image: obj.data,
bounds: [west, south, east, north],
desaturate: 0,
transparentColor: [0, 0, 0, 0],
tintColor: [255, 255, 255]
- });
- }
+ }) as any);
+ }) as any
}));
}
setRasterLayers(rLayers);
@@ -1038,7 +1046,8 @@ export const ActivityMap: React.FC = () => {
getPosition: (d) => d.location.lng_lat,
onClick: pickEventClickHandler,
getSize: ICON_SIZE,
- getColor: ICON_COLOR[layer.color],
+ getColor: (layer.color ?
+ ICON_COLOR[layer.color] : ICON_COLOR_DEFAULT) as any,
})
);
}
@@ -1114,6 +1123,10 @@ export const ActivityMap: React.FC = () => {
void getData().finally(() => {setIsDataLoading(false);});
}, []);
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const DeckGLAny = DeckGL as any;
+
return (
<>
{(isMapLoading || isDataLoading) && }
@@ -1127,20 +1140,20 @@ export const ActivityMap: React.FC = () => {
ref={geocoderContainerRef}
style={{ position: 'absolute', top: 20, right: 20, zIndex: 1 }}
/>
- setViewportState(e.viewState)} // eslint-disable-line @typescript-eslint/no-unsafe-argument, max-len
+ onViewStateChange={(e: any) => setViewportState(e.viewState)} // eslint-disable-line @typescript-eslint/no-unsafe-argument, max-len
width={'100%'}
height={'100%'}
- controller={{doubleClickZoom: false} as {doubleClickZoom: boolean} & Controller} // eslint-disable-line max-len
- onClick={handleDeckGlClick}
+ controller={{doubleClickZoom: false} as any} // eslint-disable-line max-len
+ onClick={handleDeckGlClick as any}
pickingRadius={15}
- ContextProvider={MapContext.Provider}>
+ ContextProvider={MapContext.Provider as any}>
{
-
+
)}
{projectData && (
diff --git a/media/src/project-activity-components/common.tsx b/media/src/project-activity-components/common.tsx
index 35b81bd80..5fa72a725 100644
--- a/media/src/project-activity-components/common.tsx
+++ b/media/src/project-activity-components/common.tsx
@@ -1,6 +1,7 @@
/* A place to set shared settings */
import { FlyToInterpolator } from 'deck.gl';
-import { Position } from '@deck.gl/core/utils/positions';
+// import { Position } from '@deck.gl/core/utils/positions';
+export type Position = [number, number] | [number, number, number];
export const STATIC_URL = LocusTempus.staticUrl;
export const ICON_ATLAS = STATIC_URL + 'img/icon-map-marker.png';
diff --git a/media/src/project.tsx b/media/src/project.tsx
index 5a69e7c1c..733a6634d 100644
--- a/media/src/project.tsx
+++ b/media/src/project.tsx
@@ -1,10 +1,11 @@
import React from 'react';
-import ReactDOM from 'react-dom';
+import { createRoot } from 'react-dom/client';
import { ProjectMap } from './project/project-map';
-ReactDOM.render(
-
+const container = document.getElementById('project-map-container');
+if (container) {
+ const root = createRoot(container);
+ root.render(
- ,
- document.getElementById('project-map-container')
-);
+ );
+}
diff --git a/media/src/project/project-map.tsx b/media/src/project/project-map.tsx
index 713ef74bc..2f97a6364 100644
--- a/media/src/project/project-map.tsx
+++ b/media/src/project/project-map.tsx
@@ -1,14 +1,21 @@
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useState, useEffect, useRef, useCallback } from 'react';
import {
_MapContext as MapContext, StaticMap, NavigationControl, Popup, MapRef
} from 'react-map-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
// Deck.gl
-import DeckGL, { Controller, FlyToInterpolator } from 'deck.gl';
+import DeckGL, { FlyToInterpolator } from 'deck.gl';
import { BitmapLayer, IconLayer } from '@deck.gl/layers';
import { TileLayer } from '@deck.gl/geo-layers';
-import { Position } from '@deck.gl/core/utils/positions';
-import { PickInfo } from '@deck.gl/core/lib/deck';
+// import { PickInfo } from 'deck.gl';
+type Position = [number, number] | [number, number, number];
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+type PickInfo = any;
import { ProjectMapPane } from './project-map-pane';
import { LoadingModal } from '../project-activity-components/loading-modal';
@@ -40,7 +47,7 @@ export const ProjectMap: React.FC = () => {
const pathList = window.location.pathname.split('/');
const projectPk = pathList[pathList.length - 2];
const coursePk = pathList[pathList.length - 4];
- const deckglMap = useRef(null);
+ const deckglMap = useRef(null);
const mapPane = useRef(null);
const [isNewProject, setIsNewProject] = useState(newProjectFlag);
const [projectData, setProjectData] = useState(null);
@@ -329,7 +336,7 @@ export const ProjectMap: React.FC = () => {
return;
}
const data = {
- project: projectPk,
+ project: parseInt(projectPk, 10),
instructions: instructions
};
void post('/api/activity/', data)
@@ -341,7 +348,7 @@ export const ProjectMap: React.FC = () => {
const updateActivity = (instructions: string, pk: number): void => {
const data = {
- project: projectPk,
+ project: parseInt(projectPk, 10),
instructions: instructions
};
void put(`/api/activity/${pk}/`, data)
@@ -368,7 +375,7 @@ export const ProjectMap: React.FC = () => {
//Close Popup if there is a click after search
setShowSearchPopup(false);
// Cast to provide type def for coordinate
- const infoPrime = info as PickInfo & {coordinate: [number, number]};
+ const infoPrime = info;
// Create on single click, make sure that new event
// is not created when user intends to pick an existing event
@@ -445,7 +452,7 @@ export const ProjectMap: React.FC = () => {
return activeEventDetail && d.pk == activeEventDetail.pk ?
ICON_SIZE_ACTIVE : ICON_SIZE; },
getColor: () => {
- return layer.color ? ICON_COLOR[layer.color] : ICON_COLOR_DEFAULT; },
+ return (layer.color ? ICON_COLOR[layer.color] : ICON_COLOR_DEFAULT) as any; },
visible: layerVisibility.get(layer.pk) || false
});
return acc.concat(MBLayer);
@@ -464,17 +471,17 @@ export const ProjectMap: React.FC = () => {
sizeScale: ICON_SCALE,
getPosition: (d) => d.lngLat,
getSize: ICON_SIZE_ACTIVE,
- getColor: ICON_COLOR_ACTIVE,
+ getColor: ICON_COLOR_ACTIVE as any,
}));
}
const handleViewportChange = useCallback(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
- (newViewport: React.SetStateAction) => setViewportState(newViewport),
+ (newViewport: any) => setViewportState(newViewport),
[]
);
const handleGeocoderViewportChange = useCallback(
- (newViewport) => {
+ (newViewport: any) => {
const geocoderDefaultOverrides = { transitionDuration: 1000 };
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
@@ -533,19 +540,19 @@ export const ProjectMap: React.FC = () => {
for (const layer of projData.raster_layers) {
rLayers.push(new TileLayer({
data: layer.url,
- renderSubLayers: (obj: TileSublayerProps) => {
+ renderSubLayers: ((obj: TileSublayerProps) => {
const {
bbox: {west, south, east, north}
} = obj.tile;
- return new BitmapLayer({
+ return new BitmapLayer(({
id: obj.id,
image: obj.data,
bounds: [west, south, east, north],
desaturate: 0,
transparentColor: [0, 0, 0, 0],
tintColor: [255, 255, 255]
- });
- }
+ }) as any);
+ }) as any
}));
}
setRasterLayers(rLayers);
@@ -559,6 +566,10 @@ export const ProjectMap: React.FC = () => {
void getData().finally(() => {setIsDataLoading(false);});
}, []);
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const DeckGLAny = DeckGL as any;
+
return (
<>
{(isMapLoading || isDataLoading) && }
@@ -568,20 +579,20 @@ export const ProjectMap: React.FC = () => {
ref={geocoderContainerRef}
style={{ position: 'absolute', top: 20, right: 20, zIndex: 1 }}
/>
- setViewportState(e.viewState)} // eslint-disable-line @typescript-eslint/no-unsafe-argument, max-len
+ onViewStateChange={(e: any) => setViewportState(e.viewState)} // eslint-disable-line @typescript-eslint/no-unsafe-argument, max-len
width={'100%'}
height={'100%'}
- controller={{doubleClickZoom: false} as {doubleClickZoom: boolean} & Controller} // eslint-disable-line max-len
- onClick={handleDeckGlClick}
+ controller={{doubleClickZoom: false} as any} // eslint-disable-line max-len
+ onClick={handleDeckGlClick as any}
pickingRadius={15}
ref={deckglMap}
- ContextProvider={MapContext.Provider}>
+ ContextProvider={MapContext.Provider as any}>
{
-
+
)}
{projectData && (
diff --git a/media/src/utils.ts b/media/src/utils.ts
index 59da460cf..539d69bf6 100644
--- a/media/src/utils.ts
+++ b/media/src/utils.ts
@@ -1,7 +1,7 @@
-import DeckGL from 'deck.gl';
+// import DeckGL from 'deck.gl';
import { RefObject } from 'react';
import { WebMercatorViewport } from 'react-map-gl';
-import { LayerData } from './project-activity-components/common';
+import { LayerData, DEFAULT_VIEWPORT_STATE } from './project-activity-components/common';
import moment from 'moment';
type HTTPMethod = 'GET' | 'PUT' | 'POST' | 'DELETE'
@@ -66,7 +66,7 @@ export async function del(url: string): Promise {
export const getBoundedViewport = (
layers: LayerData[],
- deckGlRef: RefObject,
+ deckGlRef: RefObject<{ deck: { width: number, height: number } }>,
mapPaneRef: RefObject): WebMercatorViewport => {
// Returns a viewport object configured to include all event markers
@@ -92,13 +92,22 @@ export const getBoundedViewport = (
}
if (deckGlRef.current !== null) {
+ const width = deckGlRef.current.deck.width || 800; // Fallback to avoid crash
+ const height = deckGlRef.current.deck.height || 600;
+
const viewportOpt = {
- width: deckGlRef.current.deck.width,
- height: deckGlRef.current.deck.height
+ width,
+ height
};
+ if (width <= 0 || height <= 0) {
+ console.warn('Invalid dimensions for viewport, skipping fitBounds', width, height);
+ return new WebMercatorViewport({width: 800, height: 600, ...DEFAULT_VIEWPORT_STATE});
+ }
+
+
const padding = 50;
- // The left padding is contingent on if the map pane is visible or isn't.
+ // The left padding depends on whether the map pane is visible.
// First, assume that the map pane is visible. It doesn't get rendered until
// after this component is rendered.
let leftPaddingOffset = 512; // Trust me, the pane is 512px wide
diff --git a/package-lock.json b/package-lock.json
index c5aa001c6..68009829a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,8 +15,8 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@types/jest": "^30.0.0",
"@types/node": "^24.0.0",
- "@types/react": "^17.0.39",
- "@types/react-dom": "^18.0.0",
+ "@types/react": "^18.3.3",
+ "@types/react-dom": "^18.3.0",
"@types/react-map-gl": "^6.1.3",
"bootstrap": "^4.5.0",
"deck.gl": "^9.0.1",
@@ -28,8 +28,8 @@
"postcss": "^8.1.2",
"precss": "^4.0.0",
"quill-paste-smart": "^2.0.0",
- "react": "~17.0.2",
- "react-dom": "~17.0.2",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
"react-map-gl": "~6.1.19",
"react-map-gl-geocoder": "~2.2.0",
"react-quill": "^2.0.0",
@@ -4531,21 +4531,22 @@
}
},
"node_modules/@types/react": {
- "version": "17.0.55",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.55.tgz",
- "integrity": "sha512-kBcAhmT8RivFDYxHdy8QfPKu+WyfiiGjdPb9pIRtd6tj05j0zRHq5DBGW5Ogxv5cwSKd93BVgUk/HZ4I9p3zNg==",
+ "version": "18.3.27",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
+ "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
+ "license": "MIT",
"dependencies": {
"@types/prop-types": "*",
- "@types/scheduler": "*",
- "csstype": "^3.0.2"
+ "csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
- "version": "18.0.0",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.0.tgz",
- "integrity": "sha512-49897Y0UiCGmxZqpC8Blrf6meL8QUla6eb+BBhn69dTXlmuOlzkfr7HHY/O8J25e1lTUMs+YYxSlVDAaGHCOLg==",
- "dependencies": {
- "@types/react": "*"
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
}
},
"node_modules/@types/react-map-gl": {
@@ -4559,11 +4560,6 @@
"@types/viewport-mercator-project": "*"
}
},
- "node_modules/@types/scheduler": {
- "version": "0.16.2",
- "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
- "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
- },
"node_modules/@types/sinonjs__fake-timers": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz",
@@ -17829,28 +17825,28 @@
}
},
"node_modules/react": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
- "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1"
+ "loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
- "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
- "object-assign": "^4.1.1",
- "scheduler": "^0.20.2"
+ "scheduler": "^0.23.2"
},
"peerDependencies": {
- "react": "17.0.2"
+ "react": "^18.3.1"
}
},
"node_modules/react-is": {
@@ -18557,12 +18553,12 @@
}
},
"node_modules/scheduler": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
- "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1"
+ "loose-envify": "^1.1.0"
}
},
"node_modules/schema-utils": {
@@ -23864,22 +23860,19 @@
}
},
"@types/react": {
- "version": "17.0.55",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.55.tgz",
- "integrity": "sha512-kBcAhmT8RivFDYxHdy8QfPKu+WyfiiGjdPb9pIRtd6tj05j0zRHq5DBGW5Ogxv5cwSKd93BVgUk/HZ4I9p3zNg==",
+ "version": "18.3.27",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
+ "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
"requires": {
"@types/prop-types": "*",
- "@types/scheduler": "*",
- "csstype": "^3.0.2"
+ "csstype": "^3.2.2"
}
},
"@types/react-dom": {
- "version": "18.0.0",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.0.tgz",
- "integrity": "sha512-49897Y0UiCGmxZqpC8Blrf6meL8QUla6eb+BBhn69dTXlmuOlzkfr7HHY/O8J25e1lTUMs+YYxSlVDAaGHCOLg==",
- "requires": {
- "@types/react": "*"
- }
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "requires": {}
},
"@types/react-map-gl": {
"version": "6.1.3",
@@ -23892,11 +23885,6 @@
"@types/viewport-mercator-project": "*"
}
},
- "@types/scheduler": {
- "version": "0.16.2",
- "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
- "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew=="
- },
"@types/sinonjs__fake-timers": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz",
@@ -33598,22 +33586,20 @@
}
},
"react": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
- "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"requires": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1"
+ "loose-envify": "^1.1.0"
}
},
"react-dom": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz",
- "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"requires": {
"loose-envify": "^1.1.0",
- "object-assign": "^4.1.1",
- "scheduler": "^0.20.2"
+ "scheduler": "^0.23.2"
}
},
"react-is": {
@@ -34122,12 +34108,11 @@
"peer": true
},
"scheduler": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
- "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"requires": {
- "loose-envify": "^1.1.0",
- "object-assign": "^4.1.1"
+ "loose-envify": "^1.1.0"
}
},
"schema-utils": {
diff --git a/package.json b/package.json
index b5a97b214..150d3c73b 100644
--- a/package.json
+++ b/package.json
@@ -48,8 +48,8 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@types/jest": "^30.0.0",
"@types/node": "^24.0.0",
- "@types/react": "^17.0.39",
- "@types/react-dom": "^18.0.0",
+ "@types/react": "^18.3.3",
+ "@types/react-dom": "^18.3.0",
"@types/react-map-gl": "^6.1.3",
"bootstrap": "^4.5.0",
"deck.gl": "^9.0.1",
@@ -61,8 +61,8 @@
"postcss": "^8.1.2",
"precss": "^4.0.0",
"quill-paste-smart": "^2.0.0",
- "react": "~17.0.2",
- "react-dom": "~17.0.2",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
"react-map-gl": "~6.1.19",
"react-map-gl-geocoder": "~2.2.0",
"react-quill": "^2.0.0",