Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build(deps): bump react and @types/react #488

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions app/components/device-detail/device-detail-box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
useSearchParams,
Link,
} from 'react-router'
import { useBetween } from 'use-between'
import SensorIcon from '../sensor-icon'
import Spinner from '../spinner'
import {
Expand Down Expand Up @@ -76,8 +75,9 @@
import EntryLogs from './entry-logs'
import ShareLink from './share-link'
import { type loader } from '~/routes/explore.$deviceId'
import { type SensorWithLatestMeasurement } from '~/schema'
import { type SensorWithLatestMeasurement } from '~/schema'
import { getArchiveLink } from '~/utils/device'
import { useGlobalCompareMode } from './useGlobalCompareMode'

Check warning on line 80 in app/components/device-detail/device-detail-box.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

`./useGlobalCompareMode` import should occur before import of `~/routes/explore.$deviceId`

export interface MeasurementProps {
sensorId: string
Expand All @@ -87,13 +87,6 @@
max_value: string
}

const useCompareMode = () => {
const [compareMode, setCompareMode] = useState(false)
return { compareMode, setCompareMode }
}

export const useSharedCompareMode = () => useBetween(useCompareMode)

export default function DeviceDetailBox() {
const navigation = useNavigation()
const navigate = useNavigate()
Expand All @@ -103,12 +96,12 @@
const sensorIds = new Set()

const data = useLoaderData<typeof loader>()
const nodeRef = useRef(null)
const nodeRef = useRef<HTMLDivElement>(null)
// state variables
const [open, setOpen] = useState(true)
const [offsetPositionX, setOffsetPositionX] = useState(0)
const [offsetPositionY, setOffsetPositionY] = useState(0)
const { compareMode, setCompareMode } = useSharedCompareMode()
const [compareMode, setCompareMode] = useGlobalCompareMode()
const [refreshOn] = useState(false)
const [refreshSecond, setRefreshSecond] = useState(59)

Expand Down Expand Up @@ -195,7 +188,7 @@
<>
{open && (
<Draggable
nodeRef={nodeRef}
nodeRef={nodeRef as React.RefObject<HTMLDivElement>}
defaultPosition={{ x: offsetPositionX, y: offsetPositionY }}
onDrag={handleDrag}
bounds="#osem"
Expand Down
4 changes: 2 additions & 2 deletions app/components/device-detail/graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default function Graph({
})
const isAggregated = aggregation !== 'raw'

const nodeRef = useRef(null)
const nodeRef = useRef<HTMLDivElement>(null)
const chartRef = useRef<ChartJS<'line'>>(null)

useEffect(() => {
Expand Down Expand Up @@ -518,7 +518,7 @@ export default function Graph({
return (
<>
<Draggable
nodeRef={nodeRef}
nodeRef={nodeRef as React.RefObject<HTMLDivElement>}
bounds="#osem"
handle="#graphTop"
defaultPosition={{ x: offsetPositionX, y: offsetPositionY }}
Expand Down
30 changes: 30 additions & 0 deletions app/components/device-detail/useGlobalCompareMode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useEffect, useState } from 'react'

let globalValue = false // Shared global state
let listeners: ((value: boolean) => void)[] = [] // Listeners for updates

export const useGlobalCompareMode = () => {
const [compareMode, setCompareMode] = useState(globalValue)

// Function to update the global value and notify listeners
const updateValue = (newValue: boolean) => {
globalValue = newValue
listeners.forEach((listener) => listener(newValue))
}

// Subscribe to global state updates
const subscribe = (listener: (value: boolean) => void) => {
listeners.push(listener)
return () => {
listeners = listeners.filter((l) => l !== listener)
}
}

// Effect to keep the local state synced with the global state
useEffect(() => {
const unsubscribe = subscribe(setCompareMode)
return unsubscribe // Clean up on unmount
}, [])

return [compareMode, updateValue] as const
}
5 changes: 3 additions & 2 deletions app/components/error-boundary.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from "react";
import { isRouteErrorResponse, useParams, useRouteError, type ErrorResponse } from "react-router";
import { getErrorMessage } from "~/utils/misc";

type StatusHandler = (info: {
error: ErrorResponse;
params: Record<string, string | undefined>;
}) => JSX.Element | null;
}) => React.JSX.Element | null;

export function GeneralErrorBoundary({
defaultStatusHandler = ({ error }) => (
Expand All @@ -17,7 +18,7 @@ export function GeneralErrorBoundary({
}: {
defaultStatusHandler?: StatusHandler;
statusHandlers?: Record<number, StatusHandler>;
unexpectedErrorHandler?: (error: unknown) => JSX.Element | null;
unexpectedErrorHandler?: (error: unknown) => React.JSX.Element | null;
}) {
const error = useRouteError();
const params = useParams();
Expand Down
216 changes: 108 additions & 108 deletions app/components/map/layers/cluster/box-marker.tsx
Original file line number Diff line number Diff line change
@@ -1,121 +1,121 @@
import { AnimatePresence, motion } from "framer-motion";
import { Box, Rocket } from "lucide-react";
import { useState } from "react";
import { type MarkerProps, Marker, useMap } from "react-map-gl";
import { useMatches, useNavigate, useSearchParams } from "react-router";
import { useSharedCompareMode } from "~/components/device-detail/device-detail-box";
import { cn } from "~/lib/utils";
import { type Device } from "~/schema";
import { AnimatePresence, motion } from 'framer-motion'
import { Box, Rocket } from 'lucide-react'
import { useState } from 'react'
import { type MarkerProps, Marker, useMap } from 'react-map-gl'
import { useMatches, useNavigate, useSearchParams } from 'react-router'
import { useGlobalCompareMode } from '~/components/device-detail/useGlobalCompareMode'
import { cn } from '~/lib/utils'
import { type Device } from '~/schema'

interface BoxMarkerProps extends MarkerProps {
device: Device;
device: Device
}

const getStatusColor = (device: Device) => {
if (device.status === "active") {
if (device.exposure === "mobile") {
return "bg-blue-100";
}
return "bg-green-300";
} else if (device.status === "inactive") {
return "bg-gray-100";
} else {
return "bg-gray-100 opacity-50";
}
};
if (device.status === 'active') {
if (device.exposure === 'mobile') {
return 'bg-blue-100'
}
return 'bg-green-300'
} else if (device.status === 'inactive') {
return 'bg-gray-100'
} else {
return 'bg-gray-100 opacity-50'
}
}

export default function BoxMarker({ device, ...props }: BoxMarkerProps) {
const navigate = useNavigate();
const matches = useMatches();
const { osem } = useMap();
const { compareMode, setCompareMode } = useSharedCompareMode();
const navigate = useNavigate()
const matches = useMatches()
const { osem } = useMap()
const [compareMode, setCompareMode] = useGlobalCompareMode()

const isFullZoom = osem && osem?.getZoom() >= 14;
const isFullZoom = osem && osem?.getZoom() >= 14

const [isHovered, setIsHovered] = useState(false);
const [searchParams] = useSearchParams();
const [isHovered, setIsHovered] = useState(false)
const [searchParams] = useSearchParams()

// calculate zIndex based on device status and hover
const getZIndex = () => {
if (isHovered) {
return 30;
}
// priority to active devices
if (device.status === "active") {
return 20;
}
if (device.status === "inactive") {
return 10;
}
// calculate zIndex based on device status and hover
const getZIndex = () => {
if (isHovered) {
return 30
}
// priority to active devices
if (device.status === 'active') {
return 20
}
if (device.status === 'inactive') {
return 10
}

return 0;
};
return 0
}

return (
<Marker
{...props}
style={{
zIndex: getZIndex(),
}}
>
<AnimatePresence mode="popLayout">
<motion.div
className={cn(
"group absolute flex w-fit cursor-pointer items-center rounded-full bg-white p-1 text-sm shadow hover:z-10 hover:shadow-lg",
isFullZoom ? "-left-4 -top-4" : "-left-[10px] -top-[10px]",
)}
onClick={() => {
if (searchParams.has("sensor")) {
searchParams.delete("sensor");
}
if (compareMode) {
void navigate(
`/explore/${matches[2].params.deviceId}/compare/${device.id}`,
);
setCompareMode(false);
return;
}
void navigate({
pathname: `${device.id}`,
search: searchParams.toString(),
});
}}
onHoverStart={() => setIsHovered(true)}
onHoverEnd={() => setIsHovered(false)}
>
<span
className={cn(
"relative rounded-full transition-colors",
`${getStatusColor(device)} p-1`,
)}
>
{device.exposure === "mobile" ? (
<Rocket className="text-black h-4 w-4" />
) : (
<Box className="text-black h-4 w-4" />
)}
{device.status === "active" ? (
<div
className={cn(
"absolute left-0 top-0 h-full w-full animate-ping rounded-full opacity-50",
getStatusColor(device),
)}
/>
) : null}
</span>
{isFullZoom ? (
<motion.span
layoutId={device.id}
className="text-black max-w-[100px] overflow-hidden overflow-ellipsis whitespace-nowrap px-1 group-hover:max-w-fit group-hover:overflow-auto"
initial={{ opacity: 0, translateX: -20 }}
animate={{ opacity: 1, translateX: 0 }}
exit={{ opacity: 0, translateX: -20 }}
>
{device.name}
</motion.span>
) : null}
</motion.div>
</AnimatePresence>
</Marker>
);
return (
<Marker
{...props}
style={{
zIndex: getZIndex(),
}}
>
<AnimatePresence mode="popLayout">
<motion.div
className={cn(
'group absolute flex w-fit cursor-pointer items-center rounded-full bg-white p-1 text-sm shadow hover:z-10 hover:shadow-lg',
isFullZoom ? '-left-4 -top-4' : '-left-[10px] -top-[10px]',
)}
onClick={() => {
if (searchParams.has('sensor')) {
searchParams.delete('sensor')
}
if (compareMode) {
void navigate(
`/explore/${matches[2].params.deviceId}/compare/${device.id}`,
)
setCompareMode(false)
return
}
void navigate({
pathname: `${device.id}`,
search: searchParams.toString(),
})
}}
onHoverStart={() => setIsHovered(true)}
onHoverEnd={() => setIsHovered(false)}
>
<span
className={cn(
'relative rounded-full transition-colors',
`${getStatusColor(device)} p-1`,
)}
>
{device.exposure === 'mobile' ? (
<Rocket className="h-4 w-4 text-black" />
) : (
<Box className="h-4 w-4 text-black" />
)}
{device.status === 'active' ? (
<div
className={cn(
'absolute left-0 top-0 h-full w-full animate-ping rounded-full opacity-50',
getStatusColor(device),
)}
/>
) : null}
</span>
{isFullZoom ? (
<motion.span
layoutId={device.id}
className="max-w-[100px] overflow-hidden overflow-ellipsis whitespace-nowrap px-1 text-black group-hover:max-w-fit group-hover:overflow-auto"
initial={{ opacity: 0, translateX: -20 }}
animate={{ opacity: 1, translateX: 0 }}
exit={{ opacity: 0, translateX: -20 }}
>
{device.name}
</motion.span>
) : null}
</motion.div>
</AnimatePresence>
</Marker>
)
}
Loading
Loading