Skip to content

Commit d1b6b05

Browse files
dependabot[bot]freds-devmpfeilscheidtdav
authored
build(deps): bump react and @types/react (#488)
* build(deps): bump react and @types/react Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react). These dependencies needed to be updated together. Updates `react` from 18.3.1 to 19.0.0 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.0.0/packages/react) Updates `@types/react` from 18.3.18 to 19.0.7 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: react dependency-type: direct:production update-type: version-update:semver-major - dependency-name: "@types/react" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]> * resolve draggable component type error * fix new JSX namespace error * remove `use-between` library * feat: update package.lock after react update * fix: revert missing cast --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Fred <[email protected]> Co-authored-by: freds-dev <[email protected]> Co-authored-by: freds-dev <[email protected]> Co-authored-by: Matthias Pfeil <[email protected]> Co-authored-by: David Scheidt <[email protected]>
1 parent 59ae3ce commit d1b6b05

File tree

10 files changed

+488
-473
lines changed

10 files changed

+488
-473
lines changed

app/components/device-detail/device-detail-box.tsx

+5-12
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import {
2929
useSearchParams,
3030
Link,
3131
} from 'react-router'
32-
import { useBetween } from 'use-between'
3332
import SensorIcon from '../sensor-icon'
3433
import Spinner from '../spinner'
3534
import {
@@ -76,8 +75,9 @@ import { useToast } from '../ui/use-toast'
7675
import EntryLogs from './entry-logs'
7776
import ShareLink from './share-link'
7877
import { type loader } from '~/routes/explore.$deviceId'
79-
import { type SensorWithLatestMeasurement } from '~/schema'
78+
import { type SensorWithLatestMeasurement } from '~/schema'
8079
import { getArchiveLink } from '~/utils/device'
80+
import { useGlobalCompareMode } from './useGlobalCompareMode'
8181

8282
export interface MeasurementProps {
8383
sensorId: string
@@ -87,13 +87,6 @@ export interface MeasurementProps {
8787
max_value: string
8888
}
8989

90-
const useCompareMode = () => {
91-
const [compareMode, setCompareMode] = useState(false)
92-
return { compareMode, setCompareMode }
93-
}
94-
95-
export const useSharedCompareMode = () => useBetween(useCompareMode)
96-
9790
export default function DeviceDetailBox() {
9891
const navigation = useNavigation()
9992
const navigate = useNavigate()
@@ -103,12 +96,12 @@ export default function DeviceDetailBox() {
10396
const sensorIds = new Set()
10497

10598
const data = useLoaderData<typeof loader>()
106-
const nodeRef = useRef(null)
99+
const nodeRef = useRef<HTMLDivElement>(null)
107100
// state variables
108101
const [open, setOpen] = useState(true)
109102
const [offsetPositionX, setOffsetPositionX] = useState(0)
110103
const [offsetPositionY, setOffsetPositionY] = useState(0)
111-
const { compareMode, setCompareMode } = useSharedCompareMode()
104+
const [compareMode, setCompareMode] = useGlobalCompareMode()
112105
const [refreshOn] = useState(false)
113106
const [refreshSecond, setRefreshSecond] = useState(59)
114107

@@ -195,7 +188,7 @@ export default function DeviceDetailBox() {
195188
<>
196189
{open && (
197190
<Draggable
198-
nodeRef={nodeRef}
191+
nodeRef={nodeRef as React.RefObject<HTMLDivElement>}
199192
defaultPosition={{ x: offsetPositionX, y: offsetPositionY }}
200193
onDrag={handleDrag}
201194
bounds="#osem"

app/components/device-detail/graph.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
import 'chartjs-adapter-date-fns'
1414
// import { de, enGB } from "date-fns/locale";
1515
import { Download, RefreshCcw, X } from 'lucide-react'
16-
import { useMemo, useRef, useState, useEffect, useContext } from 'react'
16+
import { useMemo, useRef, useState, useEffect, useContext, RefObject } from 'react'
1717
import { Scatter } from 'react-chartjs-2'
1818
import { isBrowser, isTablet } from 'react-device-detect'
1919
import Draggable, { type DraggableData } from 'react-draggable'
@@ -97,7 +97,7 @@ export default function Graph({
9797
})
9898
const isAggregated = aggregation !== 'raw'
9999

100-
const nodeRef = useRef(null)
100+
const nodeRef = useRef<HTMLDivElement>(null)
101101
const chartRef = useRef<ChartJS<'scatter'>>(null)
102102

103103
useEffect(() => {
@@ -518,7 +518,7 @@ export default function Graph({
518518
return (
519519
<>
520520
<Draggable
521-
nodeRef={nodeRef}
521+
nodeRef={nodeRef as RefObject<HTMLDivElement>}
522522
bounds="#osem"
523523
handle="#graphTop"
524524
defaultPosition={{ x: offsetPositionX, y: offsetPositionY }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useEffect, useState } from 'react'
2+
3+
let globalValue = false // Shared global state
4+
let listeners: ((value: boolean) => void)[] = [] // Listeners for updates
5+
6+
export const useGlobalCompareMode = () => {
7+
const [compareMode, setCompareMode] = useState(globalValue)
8+
9+
// Function to update the global value and notify listeners
10+
const updateValue = (newValue: boolean) => {
11+
globalValue = newValue
12+
listeners.forEach((listener) => listener(newValue))
13+
}
14+
15+
// Subscribe to global state updates
16+
const subscribe = (listener: (value: boolean) => void) => {
17+
listeners.push(listener)
18+
return () => {
19+
listeners = listeners.filter((l) => l !== listener)
20+
}
21+
}
22+
23+
// Effect to keep the local state synced with the global state
24+
useEffect(() => {
25+
const unsubscribe = subscribe(setCompareMode)
26+
return unsubscribe // Clean up on unmount
27+
}, [])
28+
29+
return [compareMode, updateValue] as const
30+
}

app/components/error-boundary.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import React from "react";
12
import { isRouteErrorResponse, useParams, useRouteError, type ErrorResponse } from "react-router";
23
import { getErrorMessage } from "~/utils/misc";
34

45
type StatusHandler = (info: {
56
error: ErrorResponse;
67
params: Record<string, string | undefined>;
7-
}) => JSX.Element | null;
8+
}) => React.JSX.Element | null;
89

910
export function GeneralErrorBoundary({
1011
defaultStatusHandler = ({ error }) => (
@@ -17,7 +18,7 @@ export function GeneralErrorBoundary({
1718
}: {
1819
defaultStatusHandler?: StatusHandler;
1920
statusHandlers?: Record<number, StatusHandler>;
20-
unexpectedErrorHandler?: (error: unknown) => JSX.Element | null;
21+
unexpectedErrorHandler?: (error: unknown) => React.JSX.Element | null;
2122
}) {
2223
const error = useRouteError();
2324
const params = useParams();
+108-108
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,121 @@
1-
import { AnimatePresence, motion } from "framer-motion";
2-
import { Box, Rocket } from "lucide-react";
3-
import { useState } from "react";
4-
import { type MarkerProps, Marker, useMap } from "react-map-gl";
5-
import { useMatches, useNavigate, useSearchParams } from "react-router";
6-
import { useSharedCompareMode } from "~/components/device-detail/device-detail-box";
7-
import { cn } from "~/lib/utils";
8-
import { type Device } from "~/schema";
1+
import { AnimatePresence, motion } from 'framer-motion'
2+
import { Box, Rocket } from 'lucide-react'
3+
import { useState } from 'react'
4+
import { type MarkerProps, Marker, useMap } from 'react-map-gl'
5+
import { useMatches, useNavigate, useSearchParams } from 'react-router'
6+
import { useGlobalCompareMode } from '~/components/device-detail/useGlobalCompareMode'
7+
import { cn } from '~/lib/utils'
8+
import { type Device } from '~/schema'
99

1010
interface BoxMarkerProps extends MarkerProps {
11-
device: Device;
11+
device: Device
1212
}
1313

1414
const getStatusColor = (device: Device) => {
15-
if (device.status === "active") {
16-
if (device.exposure === "mobile") {
17-
return "bg-blue-100";
18-
}
19-
return "bg-green-300";
20-
} else if (device.status === "inactive") {
21-
return "bg-gray-100";
22-
} else {
23-
return "bg-gray-100 opacity-50";
24-
}
25-
};
15+
if (device.status === 'active') {
16+
if (device.exposure === 'mobile') {
17+
return 'bg-blue-100'
18+
}
19+
return 'bg-green-300'
20+
} else if (device.status === 'inactive') {
21+
return 'bg-gray-100'
22+
} else {
23+
return 'bg-gray-100 opacity-50'
24+
}
25+
}
2626

2727
export default function BoxMarker({ device, ...props }: BoxMarkerProps) {
28-
const navigate = useNavigate();
29-
const matches = useMatches();
30-
const { osem } = useMap();
31-
const { compareMode, setCompareMode } = useSharedCompareMode();
28+
const navigate = useNavigate()
29+
const matches = useMatches()
30+
const { osem } = useMap()
31+
const [compareMode, setCompareMode] = useGlobalCompareMode()
3232

33-
const isFullZoom = osem && osem?.getZoom() >= 14;
33+
const isFullZoom = osem && osem?.getZoom() >= 14
3434

35-
const [isHovered, setIsHovered] = useState(false);
36-
const [searchParams] = useSearchParams();
35+
const [isHovered, setIsHovered] = useState(false)
36+
const [searchParams] = useSearchParams()
3737

38-
// calculate zIndex based on device status and hover
39-
const getZIndex = () => {
40-
if (isHovered) {
41-
return 30;
42-
}
43-
// priority to active devices
44-
if (device.status === "active") {
45-
return 20;
46-
}
47-
if (device.status === "inactive") {
48-
return 10;
49-
}
38+
// calculate zIndex based on device status and hover
39+
const getZIndex = () => {
40+
if (isHovered) {
41+
return 30
42+
}
43+
// priority to active devices
44+
if (device.status === 'active') {
45+
return 20
46+
}
47+
if (device.status === 'inactive') {
48+
return 10
49+
}
5050

51-
return 0;
52-
};
51+
return 0
52+
}
5353

54-
return (
55-
<Marker
56-
{...props}
57-
style={{
58-
zIndex: getZIndex(),
59-
}}
60-
>
61-
<AnimatePresence mode="popLayout">
62-
<motion.div
63-
className={cn(
64-
"group absolute flex w-fit cursor-pointer items-center rounded-full bg-white p-1 text-sm shadow hover:z-10 hover:shadow-lg",
65-
isFullZoom ? "-left-4 -top-4" : "-left-[10px] -top-[10px]",
66-
)}
67-
onClick={() => {
68-
if (searchParams.has("sensor")) {
69-
searchParams.delete("sensor");
70-
}
71-
if (compareMode) {
72-
void navigate(
73-
`/explore/${matches[2].params.deviceId}/compare/${device.id}`,
74-
);
75-
setCompareMode(false);
76-
return;
77-
}
78-
void navigate({
79-
pathname: `${device.id}`,
80-
search: searchParams.toString(),
81-
});
82-
}}
83-
onHoverStart={() => setIsHovered(true)}
84-
onHoverEnd={() => setIsHovered(false)}
85-
>
86-
<span
87-
className={cn(
88-
"relative rounded-full transition-colors",
89-
`${getStatusColor(device)} p-1`,
90-
)}
91-
>
92-
{device.exposure === "mobile" ? (
93-
<Rocket className="text-black h-4 w-4" />
94-
) : (
95-
<Box className="text-black h-4 w-4" />
96-
)}
97-
{device.status === "active" ? (
98-
<div
99-
className={cn(
100-
"absolute left-0 top-0 h-full w-full animate-ping rounded-full opacity-50",
101-
getStatusColor(device),
102-
)}
103-
/>
104-
) : null}
105-
</span>
106-
{isFullZoom ? (
107-
<motion.span
108-
layoutId={device.id}
109-
className="text-black max-w-[100px] overflow-hidden overflow-ellipsis whitespace-nowrap px-1 group-hover:max-w-fit group-hover:overflow-auto"
110-
initial={{ opacity: 0, translateX: -20 }}
111-
animate={{ opacity: 1, translateX: 0 }}
112-
exit={{ opacity: 0, translateX: -20 }}
113-
>
114-
{device.name}
115-
</motion.span>
116-
) : null}
117-
</motion.div>
118-
</AnimatePresence>
119-
</Marker>
120-
);
54+
return (
55+
<Marker
56+
{...props}
57+
style={{
58+
zIndex: getZIndex(),
59+
}}
60+
>
61+
<AnimatePresence mode="popLayout">
62+
<motion.div
63+
className={cn(
64+
'group absolute flex w-fit cursor-pointer items-center rounded-full bg-white p-1 text-sm shadow hover:z-10 hover:shadow-lg',
65+
isFullZoom ? '-left-4 -top-4' : '-left-[10px] -top-[10px]',
66+
)}
67+
onClick={() => {
68+
if (searchParams.has('sensor')) {
69+
searchParams.delete('sensor')
70+
}
71+
if (compareMode) {
72+
void navigate(
73+
`/explore/${matches[2].params.deviceId}/compare/${device.id}`,
74+
)
75+
setCompareMode(false)
76+
return
77+
}
78+
void navigate({
79+
pathname: `${device.id}`,
80+
search: searchParams.toString(),
81+
})
82+
}}
83+
onHoverStart={() => setIsHovered(true)}
84+
onHoverEnd={() => setIsHovered(false)}
85+
>
86+
<span
87+
className={cn(
88+
'relative rounded-full transition-colors',
89+
`${getStatusColor(device)} p-1`,
90+
)}
91+
>
92+
{device.exposure === 'mobile' ? (
93+
<Rocket className="h-4 w-4 text-black" />
94+
) : (
95+
<Box className="h-4 w-4 text-black" />
96+
)}
97+
{device.status === 'active' ? (
98+
<div
99+
className={cn(
100+
'absolute left-0 top-0 h-full w-full animate-ping rounded-full opacity-50',
101+
getStatusColor(device),
102+
)}
103+
/>
104+
) : null}
105+
</span>
106+
{isFullZoom ? (
107+
<motion.span
108+
layoutId={device.id}
109+
className="max-w-[100px] overflow-hidden overflow-ellipsis whitespace-nowrap px-1 text-black group-hover:max-w-fit group-hover:overflow-auto"
110+
initial={{ opacity: 0, translateX: -20 }}
111+
animate={{ opacity: 1, translateX: 0 }}
112+
exit={{ opacity: 0, translateX: -20 }}
113+
>
114+
{device.name}
115+
</motion.span>
116+
) : null}
117+
</motion.div>
118+
</AnimatePresence>
119+
</Marker>
120+
)
121121
}

0 commit comments

Comments
 (0)