From 6e145421efa281a2e150911ba84c7cff3a275886 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 26 May 2024 15:37:17 +0800 Subject: [PATCH 001/181] Add button to Message page to send a traceroute to a node. As noted in meshtastic/web#179, it would be great to be able to send traceroutes from the web application. This patch adds a button to the messages page that sends a traceroute to the selected node. --- src/pages/Messages.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 82325107..2a179208 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -7,11 +7,11 @@ import { useDevice } from "@core/stores/deviceStore.js"; import { Hashicon } from "@emeraldpay/hashicon-react"; import { Protobuf, Types } from "@meshtastic/js"; import { getChannelName } from "@pages/Channels.js"; -import { HashIcon } from "lucide-react"; +import { HashIcon, WaypointsIcon } from "lucide-react"; import { useState } from "react"; export const MessagesPage = (): JSX.Element => { - const { channels, nodes, hardware, messages } = useDevice(); + const { channels, nodes, hardware, messages, connection } = useDevice(); const [chatType, setChatType] = useState("broadcast"); const [activeChat, setActiveChat] = useState( @@ -72,6 +72,18 @@ export const MessagesPage = (): JSX.Element => { ? nodes.get(activeChat)?.user?.longName ?? "Unknown" : "Loading..." }`} + actions={[ + { + icon: WaypointsIcon, + async onClick() { + await connection?.traceRoute(nodes.get(activeChat)?.num).then(() => + toast({ + title: `Traceroute sent.`, + }), + ); + }, + }, + ]} > {allChannels.map( (channel) => From a7237bcb2bcf7bc19dc0602541c079292021ec0c Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 26 May 2024 15:40:55 +0800 Subject: [PATCH 002/181] Revert "Support floats in number fields" This reverts commit 5fdd07ee68b14c687c71e785b517bdde18f2f910. --- src/components/Form/FormInput.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Form/FormInput.tsx b/src/components/Form/FormInput.tsx index 74cea240..af69d882 100644 --- a/src/components/Form/FormInput.tsx +++ b/src/components/Form/FormInput.tsx @@ -32,11 +32,11 @@ export function GenericInput({ onChange( field.type === "number" - ? Number.parseFloat(e.target.value) + ? Number.parseInt(e.target.value) : e.target.value, ) } From 82c1d3e3f102726407f3fd12dbf506f75b459800 Mon Sep 17 00:00:00 2001 From: Chris Drackett Date: Tue, 30 Apr 2024 10:35:09 -0700 Subject: [PATCH 003/181] Support floats in number fields --- src/components/Form/FormInput.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Form/FormInput.tsx b/src/components/Form/FormInput.tsx index af69d882..74cea240 100644 --- a/src/components/Form/FormInput.tsx +++ b/src/components/Form/FormInput.tsx @@ -32,11 +32,11 @@ export function GenericInput({ onChange( field.type === "number" - ? Number.parseInt(e.target.value) + ? Number.parseFloat(e.target.value) : e.target.value, ) } From 97b9570196853b2e3f224a251eaeba0754d59f86 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 26 May 2024 15:41:37 +0800 Subject: [PATCH 004/181] Revert "Add button to Message page to send a traceroute to a node." This reverts commit 6e145421efa281a2e150911ba84c7cff3a275886. --- src/pages/Messages.tsx | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 2a179208..82325107 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -7,11 +7,11 @@ import { useDevice } from "@core/stores/deviceStore.js"; import { Hashicon } from "@emeraldpay/hashicon-react"; import { Protobuf, Types } from "@meshtastic/js"; import { getChannelName } from "@pages/Channels.js"; -import { HashIcon, WaypointsIcon } from "lucide-react"; +import { HashIcon } from "lucide-react"; import { useState } from "react"; export const MessagesPage = (): JSX.Element => { - const { channels, nodes, hardware, messages, connection } = useDevice(); + const { channels, nodes, hardware, messages } = useDevice(); const [chatType, setChatType] = useState("broadcast"); const [activeChat, setActiveChat] = useState( @@ -72,18 +72,6 @@ export const MessagesPage = (): JSX.Element => { ? nodes.get(activeChat)?.user?.longName ?? "Unknown" : "Loading..." }`} - actions={[ - { - icon: WaypointsIcon, - async onClick() { - await connection?.traceRoute(nodes.get(activeChat)?.num).then(() => - toast({ - title: `Traceroute sent.`, - }), - ); - }, - }, - ]} > {allChannels.map( (channel) => From 1458497fc3459cd3658a4729b5eddb549e26173b Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 26 May 2024 15:42:50 +0800 Subject: [PATCH 005/181] Add button to Message page to send a traceroute to a node. As noted in meshtastic/web#179, it would be great to be able to send traceroutes from the web application. This patch adds a button to the messages page that sends a traceroute to the selected node. --- src/pages/Messages.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 82325107..2a179208 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -7,11 +7,11 @@ import { useDevice } from "@core/stores/deviceStore.js"; import { Hashicon } from "@emeraldpay/hashicon-react"; import { Protobuf, Types } from "@meshtastic/js"; import { getChannelName } from "@pages/Channels.js"; -import { HashIcon } from "lucide-react"; +import { HashIcon, WaypointsIcon } from "lucide-react"; import { useState } from "react"; export const MessagesPage = (): JSX.Element => { - const { channels, nodes, hardware, messages } = useDevice(); + const { channels, nodes, hardware, messages, connection } = useDevice(); const [chatType, setChatType] = useState("broadcast"); const [activeChat, setActiveChat] = useState( @@ -72,6 +72,18 @@ export const MessagesPage = (): JSX.Element => { ? nodes.get(activeChat)?.user?.longName ?? "Unknown" : "Loading..." }`} + actions={[ + { + icon: WaypointsIcon, + async onClick() { + await connection?.traceRoute(nodes.get(activeChat)?.num).then(() => + toast({ + title: `Traceroute sent.`, + }), + ); + }, + }, + ]} > {allChannels.map( (channel) => From 390b16812ab5a47523997f701d4d32c40e80a18b Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 26 May 2024 18:41:13 +0800 Subject: [PATCH 006/181] Subscribe to and store traceroutePackets --- src/core/stores/deviceStore.ts | 24 ++++++++++++++++++++++++ src/core/subscriptions.ts | 6 ++++++ 2 files changed, 30 insertions(+) diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index fee9fb8f..d350c154 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -73,6 +73,7 @@ export interface Device { addPosition: (position: Types.PacketMetadata) => void; addConnection: (connection: Types.ConnectionType) => void; addMessage: (message: MessageWithState) => void; + addTraceRoute: (traceroute: Protobuf.Mesh.RouteDiscovery) => void; addMetadata: (from: number, metadata: Protobuf.Mesh.DeviceMetadata) => void; setMessageState: ( type: "direct" | "broadcast", @@ -119,6 +120,7 @@ export const useDeviceStore = create((set, get) => ({ direct: new Map(), broadcast: new Map(), }, + traceroutes: new Map(), connection: undefined, activePage: "messages", activeNode: 0, @@ -483,6 +485,7 @@ export const useDeviceStore = create((set, get) => ({ }), ); }, + addMetadata: (from, metadata) => { set( produce((draft) => { @@ -494,6 +497,27 @@ export const useDeviceStore = create((set, get) => ({ }), ); }, + addTraceRoute: (traceroute) => { + set( + produce((draft) => { + console.log("addTraceRoute called"); + console.log(traceroute); + const device = draft.devices.get(id); + if (!device) { + return; + } + + const nodetraceroutes = device.traceroutes.get(traceroute.from) + if (nodetraceroutes) { + nodetraceroutes.push(traceroute); + device.traceroutes.set(traceroute.from, nodetraceroutes); + } else { + device.traceroutes.set(traceroute.from, [traceroute]); + } + console.log(device.traceroutes); + }), + ); + }, setMessageState: ( type: "direct" | "broadcast", channelIndex: Types.ChannelNumber, diff --git a/src/core/subscriptions.ts b/src/core/subscriptions.ts index cdbaa892..40febae9 100644 --- a/src/core/subscriptions.ts +++ b/src/core/subscriptions.ts @@ -86,6 +86,12 @@ export const subscribeAll = ( }); }); + connection.events.onTraceRoutePacket.subscribe((traceRoutePacket) => { + device.addTraceRoute({ + ...traceRoutePacket, + }); + }); + connection.events.onPendingSettingsChange.subscribe((state) => { device.setPendingSettingsChanges(state); }); From 86263990e606146a2b45095dfb5629eebb0714c2 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 26 May 2024 18:41:48 +0800 Subject: [PATCH 007/181] Add Toast lib to Messages page --- src/pages/Messages.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 2a179208..29a5e9fa 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -9,6 +9,8 @@ import { Protobuf, Types } from "@meshtastic/js"; import { getChannelName } from "@pages/Channels.js"; import { HashIcon, WaypointsIcon } from "lucide-react"; import { useState } from "react"; +import { useToast } from "@core/hooks/useToast.js"; + export const MessagesPage = (): JSX.Element => { const { channels, nodes, hardware, messages, connection } = useDevice(); @@ -25,6 +27,8 @@ export const MessagesPage = (): JSX.Element => { (ch) => ch.role !== Protobuf.Channel.Channel_Role.DISABLED, ); const currentChannel = channels.get(activeChat); + const { toast } = useToast(); + return ( <> From be3117651caf11de3bee7f89d858ee2ecec3f02c Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Sun, 26 May 2024 21:00:30 +0800 Subject: [PATCH 008/181] Add basic traceroute display This patch adds basic traceroute display functionality on the Messages page for an individual node. --- .../PageComponents/Messages/ChannelChat.tsx | 18 ++++++++++ .../PageComponents/Messages/TraceRoute.tsx | 33 +++++++++++++++++++ src/core/stores/deviceStore.ts | 2 +- src/pages/Messages.tsx | 3 +- 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 src/components/PageComponents/Messages/TraceRoute.tsx diff --git a/src/components/PageComponents/Messages/ChannelChat.tsx b/src/components/PageComponents/Messages/ChannelChat.tsx index e43ae196..438591c7 100644 --- a/src/components/PageComponents/Messages/ChannelChat.tsx +++ b/src/components/PageComponents/Messages/ChannelChat.tsx @@ -1,6 +1,7 @@ import { Subtle } from "@app/components/UI/Typography/Subtle.js"; import { MessageWithState, useDevice } from "@app/core/stores/deviceStore.js"; import { Message } from "@components/PageComponents/Messages/Message.js"; +import { TraceRoute } from "@components/PageComponents/Messages/TraceRoute.js"; import { MessageInput } from "@components/PageComponents/Messages/MessageInput.js"; import type { Types } from "@meshtastic/js"; import { InboxIcon } from "lucide-react"; @@ -9,12 +10,14 @@ export interface ChannelChatProps { messages?: MessageWithState[]; channel: Types.ChannelNumber; to: Types.Destination; + traceroutes?: Types.PacketMetadata[]; } export const ChannelChat = ({ messages, channel, to, + traceroutes, }: ChannelChatProps): JSX.Element => { const { nodes } = useDevice(); @@ -38,6 +41,21 @@ export const ChannelChat = ({ No Messages )} + {traceroutes ? ( + traceroutes.map((traceroute, index) => ( + + )) + ) : ( +
+ + No Traceroutes +
+ )}
diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx new file mode 100644 index 00000000..86c4c8bb --- /dev/null +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -0,0 +1,33 @@ +import type { MessageWithState } from "@app/core/stores/deviceStore.js"; +import type { Protobuf } from "@meshtastic/js"; +import { + WaypointsIcon, + ArrowRightLeft, +} from "lucide-react"; + +export interface TraceRouteProps { + from?: Protobuf.Mesh.NodeInfo; + to?: Protobuf.Mesh.NodeInfo; + route?: Protobuf.Mesh.RouteDiscovery; +} + +export const TraceRoute = ({ + from, + to, + route, +}: TraceRouteProps): JSX.Element => { + return route.length == 0 ? ( +
+ + {from?.user?.longName}↔{to?.user?.longName} + +
+ ) : ( +
+ + {route} + +
+ + ); +}; diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index d350c154..a792fb4c 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -512,7 +512,7 @@ export const useDeviceStore = create((set, get) => ({ nodetraceroutes.push(traceroute); device.traceroutes.set(traceroute.from, nodetraceroutes); } else { - device.traceroutes.set(traceroute.from, [traceroute]); + device.traceroutes.set(traceroute.from, [traceroute]); } console.log(device.traceroutes); }), diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 29a5e9fa..4ac7ec64 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -13,7 +13,7 @@ import { useToast } from "@core/hooks/useToast.js"; export const MessagesPage = (): JSX.Element => { - const { channels, nodes, hardware, messages, connection } = useDevice(); + const { channels, nodes, hardware, messages, traceroutes, connection } = useDevice(); const [chatType, setChatType] = useState("broadcast"); const [activeChat, setActiveChat] = useState( @@ -108,6 +108,7 @@ export const MessagesPage = (): JSX.Element => { to={activeChat} messages={messages.direct.get(node.num)} channel={Types.ChannelNumber.Primary} + traceroutes={traceroutes.get(node.num)} /> ), )} From 056a194ede338657300514da5732b27359edd35c Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 09:53:20 +0800 Subject: [PATCH 009/181] Add formatting logic for multi-hop traceroutes --- .../PageComponents/Messages/TraceRoute.tsx | 16 +++++++++------- src/core/stores/deviceStore.ts | 1 - 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index 86c4c8bb..e1857b79 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -1,9 +1,5 @@ -import type { MessageWithState } from "@app/core/stores/deviceStore.js"; +import { useDevice } from "@app/core/stores/deviceStore.js"; import type { Protobuf } from "@meshtastic/js"; -import { - WaypointsIcon, - ArrowRightLeft, -} from "lucide-react"; export interface TraceRouteProps { from?: Protobuf.Mesh.NodeInfo; @@ -11,11 +7,14 @@ export interface TraceRouteProps { route?: Protobuf.Mesh.RouteDiscovery; } + export const TraceRoute = ({ from, to, route, }: TraceRouteProps): JSX.Element => { + const { nodes } = useDevice(); + return route.length == 0 ? (
@@ -25,9 +24,12 @@ export const TraceRoute = ({ ) : (
- {route} + {from?.user?.longName}↔ + {route.map((hop) => ( + nodes.get(hop).user?.longName + "↔" + ))} + {to?.user?.longName}
- ); }; diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index a792fb4c..dc82e1cb 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -514,7 +514,6 @@ export const useDeviceStore = create((set, get) => ({ } else { device.traceroutes.set(traceroute.from, [traceroute]); } - console.log(device.traceroutes); }), ); }, From f16cce90c892d562f8c93073de20bb74bd727103 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 10:09:59 +0800 Subject: [PATCH 010/181] Fix case where intermediary node in traceroute is unknown. --- src/components/PageComponents/Messages/TraceRoute.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index e1857b79..9911e6cd 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -26,7 +26,7 @@ export const TraceRoute = ({ {from?.user?.longName}↔ {route.map((hop) => ( - nodes.get(hop).user?.longName + "↔" + nodes.get(hop)?.user?.longName ?? "Unknown" + "↔" ))} {to?.user?.longName} From a728b848e120d448043e4524e8e1af7647adaf7a Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 10:39:45 +0800 Subject: [PATCH 011/181] Don't show traceroute button on Channels It doesn't work, it's only for nodes! --- src/pages/Messages.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 4ac7ec64..f1d58173 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -76,7 +76,9 @@ export const MessagesPage = (): JSX.Element => { ? nodes.get(activeChat)?.user?.longName ?? "Unknown" : "Loading..." }`} - actions={[ + actions={ + chatType === "direct" + ? [ { icon: WaypointsIcon, async onClick() { @@ -87,7 +89,9 @@ export const MessagesPage = (): JSX.Element => { ); }, }, - ]} + ] + : [] + } > {allChannels.map( (channel) => From 0f89e04bb05c0f1273797419aa6fee622a4552d6 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 10:56:34 +0800 Subject: [PATCH 012/181] Only show traceroutes on node direct message pageso --- src/components/PageComponents/Messages/ChannelChat.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PageComponents/Messages/ChannelChat.tsx b/src/components/PageComponents/Messages/ChannelChat.tsx index 438591c7..d1945832 100644 --- a/src/components/PageComponents/Messages/ChannelChat.tsx +++ b/src/components/PageComponents/Messages/ChannelChat.tsx @@ -41,7 +41,7 @@ export const ChannelChat = ({ No Messages
)} - {traceroutes ? ( + { to === "broadcast" ? null : traceroutes ? ( traceroutes.map((traceroute, index) => ( Date: Mon, 27 May 2024 11:40:59 +0800 Subject: [PATCH 013/181] Fix build errors Several types were wrong. --- src/components/PageComponents/Messages/ChannelChat.tsx | 4 ++-- src/components/PageComponents/Messages/TraceRoute.tsx | 6 +++--- src/core/stores/deviceStore.ts | 3 ++- src/pages/Nodes.tsx | 8 ++++++++ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/components/PageComponents/Messages/ChannelChat.tsx b/src/components/PageComponents/Messages/ChannelChat.tsx index d1945832..650ee678 100644 --- a/src/components/PageComponents/Messages/ChannelChat.tsx +++ b/src/components/PageComponents/Messages/ChannelChat.tsx @@ -3,14 +3,14 @@ import { MessageWithState, useDevice } from "@app/core/stores/deviceStore.js"; import { Message } from "@components/PageComponents/Messages/Message.js"; import { TraceRoute } from "@components/PageComponents/Messages/TraceRoute.js"; import { MessageInput } from "@components/PageComponents/Messages/MessageInput.js"; -import type { Types } from "@meshtastic/js"; +import type { Protobuf, Types } from "@meshtastic/js"; import { InboxIcon } from "lucide-react"; export interface ChannelChatProps { messages?: MessageWithState[]; channel: Types.ChannelNumber; to: Types.Destination; - traceroutes?: Types.PacketMetadata[]; + traceroutes?: Types.PacketMetadata[]; } export const ChannelChat = ({ diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index 9911e6cd..26f08bd4 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -2,9 +2,9 @@ import { useDevice } from "@app/core/stores/deviceStore.js"; import type { Protobuf } from "@meshtastic/js"; export interface TraceRouteProps { - from?: Protobuf.Mesh.NodeInfo; - to?: Protobuf.Mesh.NodeInfo; - route?: Protobuf.Mesh.RouteDiscovery; + from: Protobuf.Mesh.NodeInfo; + to: Protobuf.Mesh.NodeInfo; + route: Array; } diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index dc82e1cb..ecd1f7f0 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -41,6 +41,7 @@ export interface Device { direct: Map; broadcast: Map; }; + traceroutes: Map[]>; connection?: Types.ConnectionType; activePage: Page; activeNode: number; @@ -73,7 +74,7 @@ export interface Device { addPosition: (position: Types.PacketMetadata) => void; addConnection: (connection: Types.ConnectionType) => void; addMessage: (message: MessageWithState) => void; - addTraceRoute: (traceroute: Protobuf.Mesh.RouteDiscovery) => void; + addTraceRoute: (traceroute: Types.PacketMetadata) => void; addMetadata: (from: number, metadata: Protobuf.Mesh.DeviceMetadata) => void; setMessageState: ( type: "direct" | "broadcast", diff --git a/src/pages/Nodes.tsx b/src/pages/Nodes.tsx index 8b1c03a6..1ece9be5 100644 --- a/src/pages/Nodes.tsx +++ b/src/pages/Nodes.tsx @@ -26,6 +26,7 @@ export const NodesPage = (): JSX.Element => { { title: "MAC Address", type: "normal", sortable: true }, { title: "Last Heard", type: "normal", sortable: true }, { title: "SNR", type: "normal", sortable: true }, + { title: "Connection", type: "normal", sortable: true }, ]} rows={filteredNodes.map((node) => [ , @@ -55,6 +56,13 @@ export const NodesPage = (): JSX.Element => { {Math.min(Math.max((node.snr + 10) * 5, 0), 100)}%/ {(node.snr + 10) * 5}raw , + + {node.lastHeard != 0 ? + (node.viaMqtt === false && node.hopsAway === 0 + ? "Direct": node.hopsAway.toString() + " hops away") + : "-"} + {node.viaMqtt === true? ", via MQTT": ""} + ])} />
From 54c983439cab1e27b906ebf47ba414c626510820 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 11:52:33 +0800 Subject: [PATCH 014/181] Fix type Number - number --- src/components/PageComponents/Messages/TraceRoute.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index 26f08bd4..4f160991 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -4,7 +4,7 @@ import type { Protobuf } from "@meshtastic/js"; export interface TraceRouteProps { from: Protobuf.Mesh.NodeInfo; to: Protobuf.Mesh.NodeInfo; - route: Array; + route: Array; } From e825a737b0dd9b82bdb41e5be0a2dc9bcd40df23 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 12:08:32 +0800 Subject: [PATCH 015/181] Fix build errors --- src/components/PageComponents/Messages/TraceRoute.tsx | 4 ++-- src/pages/Messages.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index 4f160991..513810dc 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -2,8 +2,8 @@ import { useDevice } from "@app/core/stores/deviceStore.js"; import type { Protobuf } from "@meshtastic/js"; export interface TraceRouteProps { - from: Protobuf.Mesh.NodeInfo; - to: Protobuf.Mesh.NodeInfo; + from?: Protobuf.Mesh.NodeInfo; + to?: Protobuf.Mesh.NodeInfo; route: Array; } diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index f1d58173..81d0cd15 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -82,7 +82,8 @@ export const MessagesPage = (): JSX.Element => { { icon: WaypointsIcon, async onClick() { - await connection?.traceRoute(nodes.get(activeChat)?.num).then(() => + if (nodes.get(activeChat)?.num === undefined) return; + await connection?.traceRoute(nodes.get(activeChat)?.num!).then(() => toast({ title: `Traceroute sent.`, }), From 569c2daa0950841a416c98d3067510a04da1c376 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 20:57:09 +0800 Subject: [PATCH 016/181] Fix traceroute ordering for multi-hop traceroutes --- src/components/PageComponents/Messages/TraceRoute.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index 513810dc..593f8a58 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -18,17 +18,17 @@ export const TraceRoute = ({ return route.length == 0 ? (
- {from?.user?.longName}↔{to?.user?.longName} + {to?.user?.longName}↔{from?.user?.longName}
) : (
- {from?.user?.longName}↔ + {to?.user?.longName}↔ {route.map((hop) => ( - nodes.get(hop)?.user?.longName ?? "Unknown" + "↔" + nodes.get(hop)?.user?.longName + "↔" ?? "Unknown↔" ))} - {to?.user?.longName} + {from?.user?.longName}
); From 452f2581e239a93eef17798a82024344ace06cea Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 21:02:42 +0800 Subject: [PATCH 017/181] Fix incorrect use of operator build error. --- src/components/PageComponents/Messages/TraceRoute.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index 593f8a58..9053d0d6 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -26,7 +26,7 @@ export const TraceRoute = ({ {to?.user?.longName}↔ {route.map((hop) => ( - nodes.get(hop)?.user?.longName + "↔" ?? "Unknown↔" + (nodes.get(hop)?.user?.longName ?? "Unknown↔") + "↔" ))} {from?.user?.longName} From daff97a5e0d2cf6257749a58116feed1c8316425 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Mon, 27 May 2024 21:04:12 +0800 Subject: [PATCH 018/181] Fix double double arrow on unknown nodes in multi-hop traceroutes --- src/components/PageComponents/Messages/TraceRoute.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PageComponents/Messages/TraceRoute.tsx b/src/components/PageComponents/Messages/TraceRoute.tsx index 9053d0d6..6bc0a1e5 100644 --- a/src/components/PageComponents/Messages/TraceRoute.tsx +++ b/src/components/PageComponents/Messages/TraceRoute.tsx @@ -26,7 +26,7 @@ export const TraceRoute = ({ {to?.user?.longName}↔ {route.map((hop) => ( - (nodes.get(hop)?.user?.longName ?? "Unknown↔") + "↔" + (nodes.get(hop)?.user?.longName ?? "Unknown") + "↔" ))} {from?.user?.longName} From e9a681ab211c97ebbfdd764d9e35b3decbdb5594 Mon Sep 17 00:00:00 2001 From: Hunter Thornsberry Date: Sun, 16 Jun 2024 11:01:39 -0400 Subject: [PATCH 019/181] Add tr column and Toast when starting tr --- src/components/PageComponents/Messages/ChannelChat.tsx | 6 +++++- src/pages/Messages.tsx | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/PageComponents/Messages/ChannelChat.tsx b/src/components/PageComponents/Messages/ChannelChat.tsx index 650ee678..dd2959e1 100644 --- a/src/components/PageComponents/Messages/ChannelChat.tsx +++ b/src/components/PageComponents/Messages/ChannelChat.tsx @@ -23,7 +23,8 @@ export const ChannelChat = ({ return (
-
+
+
{messages ? ( messages.map((message, index) => ( No Messages
)} +
+
{ to === "broadcast" ? null : traceroutes ? ( traceroutes.map((traceroute, index) => ( )}
+
diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 81d0cd15..f8d51cd9 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -83,6 +83,9 @@ export const MessagesPage = (): JSX.Element => { icon: WaypointsIcon, async onClick() { if (nodes.get(activeChat)?.num === undefined) return; + toast({ + title: "Sending Traceroute, please wait..." + }) await connection?.traceRoute(nodes.get(activeChat)?.num!).then(() => toast({ title: `Traceroute sent.`, From 93b139c268a6494f37dce81de4634aea160f3682 Mon Sep 17 00:00:00 2001 From: Brandon Vandegrift Date: Mon, 27 May 2024 16:21:56 -0400 Subject: [PATCH 020/181] Update biome, fix and enforce recommended rules --- .vscode/settings.json | 9 ++- biome.json | 4 +- package.json | 5 +- pnpm-lock.yaml | 2 +- postcss.config.cjs | 4 +- src/components/CommandPalette.tsx | 4 +- src/components/DeviceSelector.tsx | 2 +- src/components/Dialog/DialogManager.tsx | 2 +- src/components/Dialog/QRDialog.tsx | 36 +++++++---- src/components/Dialog/RebootDialog.tsx | 2 +- src/components/Dialog/RemoveNodeDialog.tsx | 4 +- src/components/Dialog/ShutdownDialog.tsx | 2 +- src/components/Form/DynamicForm.tsx | 21 ++++--- src/components/Form/DynamicFormField.tsx | 15 ++++- src/components/Form/FormInput.tsx | 2 +- src/components/Form/FormSelect.tsx | 4 +- src/components/Form/FormToggle.tsx | 4 +- src/components/PageComponents/Channel.tsx | 52 +++++++++++++--- src/components/PageComponents/Config/LoRa.tsx | 2 +- src/components/PageComponents/Connect/BLE.tsx | 2 +- .../PageComponents/Connect/HTTP.tsx | 14 +++-- .../PageComponents/Connect/Serial.tsx | 31 +++++----- .../PageComponents/Messages/ChannelChat.tsx | 5 +- .../ModuleConfig/DetectionSensor.tsx | 6 +- .../PageComponents/ModuleConfig/MQTT.tsx | 32 ++++++++-- .../ModuleConfig/NeighborInfo.tsx | 2 +- .../ModuleConfig/Paxcounter.tsx | 3 +- src/components/PageLayout.tsx | 2 +- src/components/Sidebar.tsx | 14 +++-- src/components/Toaster.tsx | 10 +++- src/components/UI/Button.tsx | 2 +- src/components/UI/Toast.tsx | 2 +- src/components/generic/Table/index.tsx | 19 +++++- src/core/hooks/useToast.ts | 36 ++++++----- src/core/stores/appStore.ts | 9 ++- src/core/stores/deviceStore.ts | 4 +- src/core/subscriptions.ts | 2 +- src/core/utils/cn.ts | 2 +- src/pages/Config/DeviceConfig.tsx | 5 +- src/pages/Config/ModuleConfig.tsx | 2 +- src/pages/Map.tsx | 36 +++++------ src/pages/Nodes.tsx | 60 +++++++++++-------- src/validation/config/position.ts | 8 ++- src/validation/moduleConfig/mqtt.ts | 2 +- vite.config.ts | 4 +- 45 files changed, 314 insertions(+), 176 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a71cfe36..f9d98cd9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ { - "editor.defaultFormatter": "biomejs.biome", - "editor.formatOnSave": true -} \ No newline at end of file + "editor.defaultFormatter": "biomejs.biome", + "editor.codeActionsOnSave": { + "quickfix.biome": "explicit" + }, + "editor.formatOnSave": true +} diff --git a/biome.json b/biome.json index d7ab186b..c0f18797 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.6.3/schema.json", + "$schema": "https://biomejs.dev/schemas/1.7.3/schema.json", "organizeImports": { "enabled": true }, @@ -20,7 +20,7 @@ "linter": { "enabled": true, "rules": { - "all": true + "recommended": true } } } diff --git a/package.json b/package.json index bf87eb02..392d8cd6 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,9 @@ "license": "GPL-3.0-only", "scripts": { "dev": "vite --host", - "build": "tsc && vite build", + "build": "tsc && pnpm check && vite build ", "check": "biome check .", + "check:fix": "pnpm check --write", "preview": "vite preview", "package": "gzipper c -i html,js,css,png,ico,svg,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ $(ls ./dist/output/)" }, @@ -60,7 +61,7 @@ "zustand": "4.5.2" }, "devDependencies": { - "@biomejs/biome": "^1.6.3", + "@biomejs/biome": "^1.8.1", "@buf/meshtastic_protobufs.bufbuild_es": "1.8.0-20240325205556-b11811405eea.2", "@types/chrome": "^0.0.263", "@types/node": "^20.11.30", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be303f7a..0ea3d560 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -122,7 +122,7 @@ dependencies: devDependencies: '@biomejs/biome': - specifier: ^1.6.3 + specifier: ^1.8.1 version: 1.8.1 '@buf/meshtastic_protobufs.bufbuild_es': specifier: 1.8.0-20240325205556-b11811405eea.2 diff --git a/postcss.config.cjs b/postcss.config.cjs index 5cbc2c7d..12a703d9 100644 --- a/postcss.config.cjs +++ b/postcss.config.cjs @@ -1,6 +1,6 @@ module.exports = { plugins: { tailwindcss: {}, - autoprefixer: {} - } + autoprefixer: {}, + }, }; diff --git a/src/components/CommandPalette.tsx b/src/components/CommandPalette.tsx index 5e37816d..07f456e1 100644 --- a/src/components/CommandPalette.tsx +++ b/src/components/CommandPalette.tsx @@ -19,7 +19,7 @@ import { LayersIcon, LayoutIcon, LinkIcon, - LucideIcon, + type LucideIcon, MapIcon, MessageSquareIcon, MoonIcon, @@ -350,7 +350,7 @@ export const CommandPalette = (): JSX.Element => { window.addEventListener("keydown", handleKeydown); return () => window.removeEventListener("keydown", handleKeydown); - }, []); + }, [setCommandPaletteOpen]); return ( { diff --git a/src/components/Dialog/DialogManager.tsx b/src/components/Dialog/DialogManager.tsx index 877eec4e..53e2509b 100644 --- a/src/components/Dialog/DialogManager.tsx +++ b/src/components/Dialog/DialogManager.tsx @@ -1,9 +1,9 @@ +import { RemoveNodeDialog } from "@app/components/Dialog/RemoveNodeDialog.js"; import { DeviceNameDialog } from "@components/Dialog/DeviceNameDialog.js"; import { ImportDialog } from "@components/Dialog/ImportDialog.js"; import { QRDialog } from "@components/Dialog/QRDialog.js"; import { RebootDialog } from "@components/Dialog/RebootDialog.js"; import { ShutdownDialog } from "@components/Dialog/ShutdownDialog.js"; -import { RemoveNodeDialog } from "@app/components/Dialog/RemoveNodeDialog.js" import { useDevice } from "@core/stores/deviceStore.js"; export const DialogManager = (): JSX.Element => { diff --git a/src/components/Dialog/QRDialog.tsx b/src/components/Dialog/QRDialog.tsx index e58455b3..27a57a1d 100644 --- a/src/components/Dialog/QRDialog.tsx +++ b/src/components/Dialog/QRDialog.tsx @@ -9,10 +9,10 @@ import { } from "@components/UI/Dialog.js"; import { Input } from "@components/UI/Input.js"; import { Label } from "@components/UI/Label.js"; -import { Protobuf, Types } from "@meshtastic/js"; +import { Protobuf, type Types } from "@meshtastic/js"; import { fromByteArray } from "base64-js"; import { ClipboardIcon } from "lucide-react"; -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { QRCode } from "react-qrcode-logo"; export interface QRDialogProps { @@ -32,7 +32,7 @@ export const QRDialog = ({ const [qrCodeUrl, setQrCodeUrl] = useState(""); const [qrCodeAdd, setQrCodeAdd] = useState(); - const allChannels = Array.from(channels.values()); + const allChannels = useMemo(() => Array.from(channels.values()), [channels]); useEffect(() => { const channelsToEncode = allChannels @@ -50,8 +50,10 @@ export const QRDialog = ({ .replace(/\+/g, "-") .replace(/\//g, "_"); - setQrCodeUrl(`https://meshtastic.org/e/#${base64}${qrCodeAdd ? "?add=true" : ""}`); - }, [channels, selectedChannels, qrCodeAdd, loraConfig]); + setQrCodeUrl( + `https://meshtastic.org/e/#${base64}${qrCodeAdd ? "?add=true" : ""}`, + ); + }, [allChannels, selectedChannels, qrCodeAdd, loraConfig]); return ( @@ -97,18 +99,26 @@ export const QRDialog = ({
diff --git a/src/components/Dialog/RebootDialog.tsx b/src/components/Dialog/RebootDialog.tsx index f4a591bf..79ff86bd 100644 --- a/src/components/Dialog/RebootDialog.tsx +++ b/src/components/Dialog/RebootDialog.tsx @@ -37,7 +37,7 @@ export const RebootDialog = ({ setTime(parseInt(e.target.value))} + onChange={(e) => setTime(Number.parseInt(e.target.value))} action={{ icon: ClockIcon, onClick() { diff --git a/src/components/Dialog/RemoveNodeDialog.tsx b/src/components/Dialog/RemoveNodeDialog.tsx index 789388db..b2db5d56 100644 --- a/src/components/Dialog/RemoveNodeDialog.tsx +++ b/src/components/Dialog/RemoveNodeDialog.tsx @@ -44,7 +44,9 @@ export const RemoveNodeDialog = ({ - + diff --git a/src/components/Dialog/ShutdownDialog.tsx b/src/components/Dialog/ShutdownDialog.tsx index ea1ac487..cf34fee5 100644 --- a/src/components/Dialog/ShutdownDialog.tsx +++ b/src/components/Dialog/ShutdownDialog.tsx @@ -38,7 +38,7 @@ export const ShutdownDialog = ({ setTime(parseInt(e.target.value))} + onChange={(e) => setTime(Number.parseInt(e.target.value))} suffix="Minutes" /> + + ); + }, +); +Generator.displayName = "Button"; + +export { Generator, generatorVariants }; From 38b7e600b107e953fde342ad42cf2636f96f915e Mon Sep 17 00:00:00 2001 From: Hunter Thornsberry Date: Sun, 28 Jul 2024 15:57:17 -0400 Subject: [PATCH 039/181] key generation --- package.json | 1 + pnpm-lock.yaml | 17 +++++++++++++++++ src/components/UI/Generator.tsx | 7 ++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b1b7326f..e56bdaed 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cmdk": "^1.0.0", + "crypto-random-string": "^5.0.0", "immer": "^10.1.1", "lucide-react": "^0.363.0", "mapbox-gl": "npm:empty-npm-package@^1.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b94369f4..938ea82e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -80,6 +80,9 @@ importers: cmdk: specifier: ^1.0.0 version: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + crypto-random-string: + specifier: ^5.0.0 + version: 5.0.0 immer: specifier: ^10.1.1 version: 10.1.1 @@ -1901,6 +1904,10 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + crypto-random-string@5.0.0: + resolution: {integrity: sha512-KWjTXWwxFd6a94m5CdRGW/t82Tr8DoBc9dNnPCAbFI1EBweN6v1tv8y4Y1m7ndkp/nkIBRxUxAzpaBnR2k3bcQ==} + engines: {node: '>=14.16'} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -2929,6 +2936,10 @@ packages: turf-jsts@1.2.3: resolution: {integrity: sha512-Ja03QIJlPuHt4IQ2FfGex4F4JAr8m3jpaHbFbQrgwr7s7L6U8ocrHiF3J1+wf9jzhGKxvDeaCAnGDot8OjGFyA==} + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + typescript@5.5.2: resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==} engines: {node: '>=14.17'} @@ -5293,6 +5304,10 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypto-random-string@5.0.0: + dependencies: + type-fest: 2.19.0 + cssesc@3.0.0: {} csstype@3.1.3: {} @@ -6365,6 +6380,8 @@ snapshots: turf-jsts@1.2.3: {} + type-fest@2.19.0: {} + typescript@5.5.2: {} typewise-core@1.2.0: {} diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index 64b78bee..857ec51d 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -12,6 +12,7 @@ import { SelectValue, } from "@components/UI/Select.js"; import { useState } from "react"; +import cryptoRandomString from 'crypto-random-string'; const generatorVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2", @@ -61,13 +62,13 @@ const Generator = React.forwardRef( const generate = () => { let generated = "thisisapass"; if (bitCount == "bit8") { - generated = "8bitpassword" + generated = btoa(cryptoRandomString({length: 1, type: 'alphanumeric'})); } if (bitCount == "bit128") { - generated = "128bitpassword" + generated = btoa(cryptoRandomString({length: 16, type: 'alphanumeric'})); } if (bitCount == "bit256") { - generated = "256bitpassword" + generated = btoa(cryptoRandomString({length: 32, type: 'alphanumeric'})); } return generated; }; From 9c6aff534a83f223c5ea96a87f823506f721ba1c Mon Sep 17 00:00:00 2001 From: Hunter Thornsberry Date: Sun, 28 Jul 2024 16:43:41 -0400 Subject: [PATCH 040/181] a bit of cleanup --- src/components/Form/FormPasswordGenerator.tsx | 7 ----- src/components/PageComponents/Channel.tsx | 3 +- src/components/UI/Generator.tsx | 29 +++++-------------- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/src/components/Form/FormPasswordGenerator.tsx b/src/components/Form/FormPasswordGenerator.tsx index eb30dc1a..a53e7d96 100644 --- a/src/components/Form/FormPasswordGenerator.tsx +++ b/src/components/Form/FormPasswordGenerator.tsx @@ -14,13 +14,6 @@ import type { control, field, }: GenericFormElementProps>) { - const [password, createPassword] = useState(""); - - const generate = () => { - let generatedPass = "VHl1OTVpY7TAly0jGF0X2A=="; - return generatedPass - } - return ( { label: "pre-Shared Key", description: "256, 128, or 8 bit PSKs allowed", properties: { - // act + passwordValue: fromByteArray(channel?.settings?.psk ?? new Uint8Array(0)), + devicePSKBitCount: channel?.settings?.psk.length }, }, { diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index 857ec51d..ae42ed3f 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -50,28 +50,15 @@ export interface GeneratorProps extends React.BaseHTMLAttributes, VariantProps { + devicePSKBitCount?: number; passwordValue?: string; textValue?: string; } const Generator = React.forwardRef( - ({ passwordValue, textValue, className, variant, size, ...props }, ref) => { - const [pass, setPass] = useState(""); - const [bitCount, setBits] = useState("bit256"); - - const generate = () => { - let generated = "thisisapass"; - if (bitCount == "bit8") { - generated = btoa(cryptoRandomString({length: 1, type: 'alphanumeric'})); - } - if (bitCount == "bit128") { - generated = btoa(cryptoRandomString({length: 16, type: 'alphanumeric'})); - } - if (bitCount == "bit256") { - generated = btoa(cryptoRandomString({length: 32, type: 'alphanumeric'})); - } - return generated; - }; + ({ devicePSKBitCount, passwordValue, textValue, className, variant, size, ...props }, ref) => { + const [pass, setPass] = useState(passwordValue ?? ""); + const [bitCount, setBits] = useState(devicePSKBitCount?.toString() ?? ""); return ( <> @@ -87,9 +74,9 @@ const Generator = React.forwardRef( - 256 bit - 128 bit - 8 bit + 256 bit + 128 bit + 8 bit + + + ); }, From 5771e1b7333fa0e706de5192cb53bf0fab852229 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Mon, 5 Aug 2024 16:33:57 +0200 Subject: [PATCH 042/181] Fixed hops singular form --- src/pages/Nodes.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/Nodes.tsx b/src/pages/Nodes.tsx index a97dc543..73ba6e46 100644 --- a/src/pages/Nodes.tsx +++ b/src/pages/Nodes.tsx @@ -75,7 +75,9 @@ export const NodesPage = (): JSX.Element => { {node.lastHeard !== 0 ? node.viaMqtt === false && node.hopsAway === 0 ? "Direct" - : `${node.hopsAway.toString()} hops away` + : `${node.hopsAway.toString()} ${ + node.hopsAway > 1 ? "hops" : "hop" + } away` : "-"} {node.viaMqtt === true ? ", via MQTT" : ""} , From cd0fcbbf900012d67742bf92f9180a44a9357fc7 Mon Sep 17 00:00:00 2001 From: Hunter Thornsberry Date: Tue, 6 Aug 2024 00:50:17 -0400 Subject: [PATCH 043/181] initial working version --- src/components/Form/FormPasswordGenerator.tsx | 10 ++-- src/components/PageComponents/Channel.tsx | 29 ++++++++--- src/components/UI/Generator.tsx | 52 ++++++++----------- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/src/components/Form/FormPasswordGenerator.tsx b/src/components/Form/FormPasswordGenerator.tsx index 762be7b0..7dc7281f 100644 --- a/src/components/Form/FormPasswordGenerator.tsx +++ b/src/components/Form/FormPasswordGenerator.tsx @@ -3,11 +3,11 @@ import type { GenericFormElementProps, } from "@components/Form/DynamicForm.js"; import { Generator } from "@components/UI/Generator.js"; -import { useState } from "react"; import { Controller, type FieldValues } from "react-hook-form"; export interface PasswordGeneratorProps extends BaseFormBuilderProps { type: "passwordGenerator"; + devicePSKBitCount: number; } export function PasswordGenerator({ @@ -20,11 +20,13 @@ export function PasswordGenerator({ control={control} render={({ field: { value, onChange, ...rest } }) => ( + {...rest} /> )} /> ); diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index b9c76612..942b6666 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -4,6 +4,8 @@ import { useToast } from "@core/hooks/useToast.js"; import { useDevice } from "@core/stores/deviceStore.js"; import { Protobuf } from "@meshtastic/js"; import { fromByteArray, toByteArray } from "base64-js"; +import cryptoRandomString from "crypto-random-string"; +import { useState } from "react"; export interface SettingsPanelProps { channel: Protobuf.Channel.Channel; @@ -13,12 +15,15 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { const { config, connection, addChannel } = useDevice(); const { toast } = useToast(); + const [pass, setPass] = useState(fromByteArray(channel?.settings?.psk ?? new Uint8Array(0))); + const [bitCount, setBits] = useState(channel?.settings?.psk.length ?? 16); + const onSubmit = (data: ChannelValidation) => { const channel = new Protobuf.Channel.Channel({ ...data, settings: { ...data.settings, - psk: toByteArray(data.settings.psk ?? ""), + psk: toByteArray(pass), moduleSettings: { positionPrecision: data.settings.positionEnabled ? data.settings.preciseLocation @@ -36,6 +41,18 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }); }; + + const clickEventCb = (e) => { + setPass( + btoa( + cryptoRandomString({ + length: bitCount ?? 0, + type: "alphanumeric", + }), + ), + ); + } + return ( onSubmit={onSubmit} @@ -46,7 +63,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { ...{ settings: { ...channel?.settings, - psk: fromByteArray(channel?.settings?.psk ?? new Uint8Array(0)), + psk: pass, positionEnabled: channel?.settings?.moduleSettings?.positionPrecision !== undefined && @@ -80,11 +97,11 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { name: "settings.psk", label: "pre-Shared Key", description: "256, 128, or 8 bit PSKs allowed", + devicePSKBitCount: bitCount ?? 0, properties: { - passwordValue: fromByteArray( - channel?.settings?.psk ?? new Uint8Array(0), - ), - devicePSKBitCount: channel?.settings?.psk.length, + value: pass, + onClick: clickEventCb, + changeEvent: (e: string) => setBits(parseInt(e)), }, }, { diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index bcc78c59..dc057336 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -10,9 +10,9 @@ import { SelectTrigger, SelectValue, } from "@components/UI/Select.js"; -import { cn } from "@core/utils/cn.js"; import cryptoRandomString from "crypto-random-string"; import { useState } from "react"; +import { fromByteArray, toByteArray } from "base64-js"; const generatorVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2", @@ -49,36 +49,41 @@ export interface GeneratorProps extends React.BaseHTMLAttributes, VariantProps { devicePSKBitCount?: number; - passwordValue?: string; - textValue?: string; + value: string; + buttonText?: string; + changeEvent: Function; + } -const Generator = React.forwardRef( +const getBitString = (bitcount?: number) => { + if (bitcount == 32) { + return "32" + } + if (bitcount == 1) { + return "1" + } + return "16" +} + +const Generator = React.forwardRef( ( { devicePSKBitCount, - passwordValue, - textValue, - className, + value, + buttonText, variant, - size, + changeEvent, ...props }, ref, ) => { - const [pass, setPass] = useState(passwordValue ?? ""); - const [bitCount, setBits] = useState( - devicePSKBitCount?.toString() ?? "", - ); return ( <> - + @@ -100,11 +91,7 @@ const Generator = React.forwardRef( - From faf094084cdddf99e435746b8ebb59fce41d5fee Mon Sep 17 00:00:00 2001 From: Hunter Thornsberry Date: Tue, 6 Aug 2024 01:04:44 -0400 Subject: [PATCH 045/181] remove used imports and rename clickEventCb --- src/components/PageComponents/Channel.tsx | 4 ++-- src/components/UI/Generator.tsx | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index ddb4813c..3c79a543 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -45,7 +45,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }); }; - const clickEventCb = (e) => { + const clickEvent = () => { setPass( btoa( cryptoRandomString({ @@ -103,7 +103,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { devicePSKBitCount: bitCount ?? 0, properties: { value: pass, - onClick: clickEventCb, + onClick: clickEvent, changeEvent: (e: string) => setBits(Number.parseInt(e)), }, }, diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index 1e12d498..5b3dd44f 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -10,9 +10,6 @@ import { SelectTrigger, SelectValue, } from "@components/UI/Select.js"; -import { fromByteArray, toByteArray } from "base64-js"; -import cryptoRandomString from "crypto-random-string"; -import { useState } from "react"; const generatorVariants = cva( "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2", From 1eedb6d97b33d8cb07c311c42d1d08b10aa2fdef Mon Sep 17 00:00:00 2001 From: Hunter Thornsberry Date: Sat, 10 Aug 2024 18:50:47 -0400 Subject: [PATCH 046/181] validation --- src/components/Form/DynamicForm.tsx | 5 ++ src/components/Form/FormPasswordGenerator.tsx | 12 +++- src/components/Form/FormWrapper.tsx | 5 ++ src/components/PageComponents/Channel.tsx | 54 ++++++++++++++- src/components/UI/Generator.tsx | 67 +++++-------------- src/components/UI/Input.tsx | 31 ++++++--- 6 files changed, 110 insertions(+), 64 deletions(-) diff --git a/src/components/Form/DynamicForm.tsx b/src/components/Form/DynamicForm.tsx index 4c9b551b..d70a0ee5 100644 --- a/src/components/Form/DynamicForm.tsx +++ b/src/components/Form/DynamicForm.tsx @@ -26,6 +26,7 @@ export interface BaseFormBuilderProps { disabledBy?: DisabledBy[]; label: string; description?: string; + validationText?: string; properties?: Record; } @@ -44,6 +45,8 @@ export interface DynamicFormProps { fieldGroups: { label: string; description: string; + valid?: boolean; + validationText?: string; fields: FieldProps[]; }[]; } @@ -98,6 +101,8 @@ export function DynamicForm({ key={field.label} label={field.label} description={field.description} + valid={field.validationText == undefined || field.validationText == ""} + validationText={field.validationText} > extends BaseFormBuilderProps { type: "passwordGenerator"; devicePSKBitCount: number; + inputChange: ChangeEventHandler; + selectChange: (event: string) => void; + buttonClick: MouseEventHandler; } export function PasswordGenerator({ @@ -18,12 +22,14 @@ export function PasswordGenerator({ ( + render={({ field: { value,...rest } }) => ( (
@@ -19,6 +23,7 @@ export const FieldWrapper = ({

{description}

+
{children}
diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index 3c79a543..85a6866c 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -21,6 +21,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { const [bitCount, setBits] = useState( channel?.settings?.psk.length ?? 16, ); + const [validationText, setValidationText] = useState(); const onSubmit = (data: ChannelValidation) => { const channel = new Protobuf.Channel.Channel({ @@ -54,8 +55,53 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }), ), ); + setValidationText(undefined); }; + const validatePass = (input: string, count: number) => { + if (count == 32) { + if (input.length != 44) { + setValidationText("Please enter a valid 256 bit PSK."); + } + else { + setValidationText(undefined); + } + } + else if (count == 16) + { + if (input.length != 24) { + setValidationText("Please enter a valid 128 bit PSK."); + } + else { + setValidationText(undefined); + } + } + else if (count == 1) + { + if (input.length != 4) { + setValidationText("Please enter a valid 1 bit PSK"); + } + else { + setValidationText(undefined); + } + } + else { + setValidationText("Unkown PSK length."); + } + } + + const inputChangeEvent = (e) => { + let psk = e.currentTarget?.value; + setPass(psk); + validatePass(psk, bitCount); + }; + + const selectChangeEvent = (e: string) => { + let count = Number.parseInt(e); + setBits(count); + validatePass(pass, count); + } + return ( onSubmit={onSubmit} @@ -100,11 +146,13 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { name: "settings.psk", label: "pre-Shared Key", description: "256, 128, or 8 bit PSKs allowed", + validationText: validationText, devicePSKBitCount: bitCount ?? 0, + inputChange: inputChangeEvent, + selectChange: selectChangeEvent, + buttonClick: clickEvent, properties: { - value: pass, - onClick: clickEvent, - changeEvent: (e: string) => setBits(Number.parseInt(e)), + value: pass }, }, { diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index 5b3dd44f..bdf0c3b8 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -1,4 +1,3 @@ -import { type VariantProps, cva } from "class-variance-authority"; import * as React from "react"; import { Button } from "@components/UI/Button.js"; @@ -11,67 +10,35 @@ import { SelectValue, } from "@components/UI/Select.js"; -const generatorVariants = cva( - "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2", - { - variants: { - variant: { - default: "", - destructive: - "bg-red-500 text-white hover:bg-red-600 dark:hover:bg-red-600", - success: - "bg-green-500 text-white hover:bg-green-600 dark:hover:bg-green-600", - outline: - "bg-transparent border border-slate-200 hover:bg-slate-100 dark:border-slate-700 dark:text-slate-100", - subtle: - "bg-slate-100 text-slate-900 hover:bg-slate-200 dark:bg-slate-700 dark:text-slate-100", - ghost: - "bg-transparent hover:bg-slate-100 dark:hover:bg-slate-800 dark:text-slate-100 dark:hover:text-slate-100 data-[state=open]:bg-transparent dark:data-[state=open]:bg-transparent", - link: "bg-transparent underline-offset-4 hover:underline text-slate-900 dark:text-slate-100 hover:bg-transparent dark:hover:bg-transparent", - }, - size: { - default: "h-10 py-2 px-4", - sm: "h-9 px-2 rounded-md", - lg: "h-11 px-8 rounded-md", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - }, -); - export interface GeneratorProps - extends React.BaseHTMLAttributes, - VariantProps { + extends React.BaseHTMLAttributes { devicePSKBitCount?: number; value: string; + variant: "default" | "invalid"; buttonText?: string; - changeEvent: (event: string) => void; + selectChange: (event: string) => void; + inputChange: (event: React.ChangeEvent) => void; + buttonClick: React.MouseEventHandler; } -const getBitString = (bitcount?: number) => { - if (bitcount === 32) { - return "32"; - } - if (bitcount === 1) { - return "1"; - } - return "16"; -}; const Generator = React.forwardRef( ( - { devicePSKBitCount, value, buttonText, variant, changeEvent, ...props }, + { devicePSKBitCount, variant, value, buttonText, selectChange, inputChange, buttonClick, ...props }, ref, ) => { return ( <> - + - @@ -97,4 +64,4 @@ const Generator = React.forwardRef( ); Generator.displayName = "Button"; -export { Generator, generatorVariants }; +export { Generator }; diff --git a/src/components/UI/Input.tsx b/src/components/UI/Input.tsx index e13f25f4..c7ac3217 100644 --- a/src/components/UI/Input.tsx +++ b/src/components/UI/Input.tsx @@ -2,9 +2,28 @@ import * as React from "react"; import { cn } from "@core/utils/cn.js"; import type { LucideIcon } from "lucide-react"; +import { cva, VariantProps } from "class-variance-authority"; + +const inputVariants = cva( + "flex h-10 w-full rounded-md border bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900", + { + variants: { + variant: { + default: + "border-slate-300 dark:border-slate-700", + invalid: + "border-red-500 dark:border-red-500", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); export interface InputProps - extends React.InputHTMLAttributes { + extends React.InputHTMLAttributes, + VariantProps { prefix?: string; suffix?: string; action?: { @@ -14,7 +33,7 @@ export interface InputProps } const Input = React.forwardRef( - ({ className, prefix, suffix, action, ...props }, ref) => { + ({ className, variant, prefix, suffix, action, ...props }, ref) => { return (
{prefix && ( @@ -23,11 +42,7 @@ const Input = React.forwardRef( )} @@ -51,4 +66,4 @@ const Input = React.forwardRef( ); Input.displayName = "Input"; -export { Input }; +export { Input, inputVariants }; From e7892fd6a04dbe8e17cab291d563602f836a852d Mon Sep 17 00:00:00 2001 From: Hunter Thornsberry Date: Sat, 10 Aug 2024 19:07:02 -0400 Subject: [PATCH 047/181] biome --- src/components/Form/DynamicForm.tsx | 5 ++- src/components/Form/FormPasswordGenerator.tsx | 4 +- src/components/Form/FormWrapper.tsx | 4 +- src/components/PageComponents/Channel.tsx | 38 ++++++++----------- src/components/UI/Generator.tsx | 28 ++++++++++---- src/components/UI/Input.tsx | 14 ++++--- 6 files changed, 52 insertions(+), 41 deletions(-) diff --git a/src/components/Form/DynamicForm.tsx b/src/components/Form/DynamicForm.tsx index d70a0ee5..470f36e7 100644 --- a/src/components/Form/DynamicForm.tsx +++ b/src/components/Form/DynamicForm.tsx @@ -101,7 +101,10 @@ export function DynamicForm({ key={field.label} label={field.label} description={field.description} - valid={field.validationText == undefined || field.validationText == ""} + valid={ + field.validationText === undefined || + field.validationText === "" + } validationText={field.validationText} > extends BaseFormBuilderProps { @@ -22,7 +22,7 @@ export function PasswordGenerator({ ( + render={({ field: { value, ...rest } }) => (

{description}

- +
{children}
diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index 85a6866c..fd425995 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -59,48 +59,40 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }; const validatePass = (input: string, count: number) => { - if (count == 32) { - if (input.length != 44) { + if (count === 32) { + if (input.length !== 44) { setValidationText("Please enter a valid 256 bit PSK."); - } - else { + } else { setValidationText(undefined); } - } - else if (count == 16) - { - if (input.length != 24) { + } else if (count === 16) { + if (input.length !== 24) { setValidationText("Please enter a valid 128 bit PSK."); - } - else { + } else { setValidationText(undefined); } - } - else if (count == 1) - { - if (input.length != 4) { + } else if (count === 1) { + if (input.length !== 4) { setValidationText("Please enter a valid 1 bit PSK"); - } - else { + } else { setValidationText(undefined); } - } - else { + } else { setValidationText("Unkown PSK length."); } - } + }; const inputChangeEvent = (e) => { - let psk = e.currentTarget?.value; + const psk = e.currentTarget?.value; setPass(psk); validatePass(psk, bitCount); }; const selectChangeEvent = (e: string) => { - let count = Number.parseInt(e); + const count = Number.parseInt(e); setBits(count); validatePass(pass, count); - } + }; return ( @@ -152,7 +144,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { selectChange: selectChangeEvent, buttonClick: clickEvent, properties: { - value: pass + value: pass, }, }, { diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index bdf0c3b8..344e89bb 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -10,8 +10,7 @@ import { SelectValue, } from "@components/UI/Select.js"; -export interface GeneratorProps - extends React.BaseHTMLAttributes { +export interface GeneratorProps extends React.BaseHTMLAttributes { devicePSKBitCount?: number; value: string; variant: "default" | "invalid"; @@ -21,17 +20,25 @@ export interface GeneratorProps buttonClick: React.MouseEventHandler; } - const Generator = React.forwardRef( ( - { devicePSKBitCount, variant, value, buttonText, selectChange, inputChange, buttonClick, ...props }, + { + devicePSKBitCount, + variant, + value, + buttonText, + selectChange, + inputChange, + buttonClick, + ...props + }, ref, ) => { return ( <> - ( - diff --git a/src/components/UI/Input.tsx b/src/components/UI/Input.tsx index c7ac3217..2c3080fb 100644 --- a/src/components/UI/Input.tsx +++ b/src/components/UI/Input.tsx @@ -1,18 +1,16 @@ import * as React from "react"; import { cn } from "@core/utils/cn.js"; +import { type VariantProps, cva } from "class-variance-authority"; import type { LucideIcon } from "lucide-react"; -import { cva, VariantProps } from "class-variance-authority"; const inputVariants = cva( "flex h-10 w-full rounded-md border bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900", { variants: { variant: { - default: - "border-slate-300 dark:border-slate-700", - invalid: - "border-red-500 dark:border-red-500", + default: "border-slate-300 dark:border-slate-700", + invalid: "border-red-500 dark:border-red-500", }, }, defaultVariants: { @@ -42,7 +40,11 @@ const Input = React.forwardRef( )} From 54a7b88146c26ee4cfabf4c2740ce3de35ee1c56 Mon Sep 17 00:00:00 2001 From: Hunter Thornsberry Date: Sat, 10 Aug 2024 19:50:21 -0400 Subject: [PATCH 048/181] rewrite PSK validation --- src/components/Form/DynamicForm.tsx | 1 - src/components/PageComponents/Channel.tsx | 24 ++++------------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/components/Form/DynamicForm.tsx b/src/components/Form/DynamicForm.tsx index 470f36e7..61c4c0e7 100644 --- a/src/components/Form/DynamicForm.tsx +++ b/src/components/Form/DynamicForm.tsx @@ -40,7 +40,6 @@ export interface DynamicFormProps { onSubmit: SubmitHandler; submitType?: "onChange" | "onSubmit"; hasSubmitButton?: boolean; - // defaultValues?: DeepPartial; defaultValues?: DefaultValues; fieldGroups: { label: string; diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index fd425995..d90e950b 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -59,30 +59,14 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }; const validatePass = (input: string, count: number) => { - if (count === 32) { - if (input.length !== 44) { - setValidationText("Please enter a valid 256 bit PSK."); - } else { - setValidationText(undefined); - } - } else if (count === 16) { - if (input.length !== 24) { - setValidationText("Please enter a valid 128 bit PSK."); - } else { - setValidationText(undefined); - } - } else if (count === 1) { - if (input.length !== 4) { - setValidationText("Please enter a valid 1 bit PSK"); - } else { - setValidationText(undefined); - } + if (input.length % 4 !== 0 || toByteArray(input).length !== count) { + setValidationText(`Please enter a valid ${count * 8} bit PSK.`); } else { - setValidationText("Unkown PSK length."); + setValidationText(undefined); } }; - const inputChangeEvent = (e) => { + const inputChangeEvent = (e: React.ChangeEvent) => { const psk = e.currentTarget?.value; setPass(psk); validatePass(psk, bitCount); From 4c4be2e18fffbcb63dfc8e57388a7d648a64f1cb Mon Sep 17 00:00:00 2001 From: rcarteraz Date: Mon, 19 Aug 2024 13:20:56 -0700 Subject: [PATCH 049/181] temp solution --- src/App.tsx | 2 ++ src/components/UI/Footer.tsx | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/components/UI/Footer.tsx diff --git a/src/App.tsx b/src/App.tsx index 1a014eb5..8b77213f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,7 @@ import { DeviceSelector } from "@components/DeviceSelector.js"; import { DialogManager } from "@components/Dialog/DialogManager.js"; import { NewDeviceDialog } from "@components/Dialog/NewDeviceDialog.js"; import { Toaster } from "@components/Toaster.js"; +import Footer from "@components/UI/Footer.js"; import { ThemeController } from "@components/generic/ThemeController.js"; import { useAppStore } from "@core/stores/appStore.js"; import { useDeviceStore } from "@core/stores/deviceStore.js"; @@ -44,6 +45,7 @@ export const App = (): JSX.Element => { )}
+
diff --git a/src/components/UI/Footer.tsx b/src/components/UI/Footer.tsx new file mode 100644 index 00000000..5d02c4dd --- /dev/null +++ b/src/components/UI/Footer.tsx @@ -0,0 +1,35 @@ +import React from "react"; + +const Footer = () => { + return ( + + ); +}; + +export default Footer; From 6c1f140ad16402668e05ed5e7e2a806cf663296b Mon Sep 17 00:00:00 2001 From: rcarteraz Date: Mon, 19 Aug 2024 13:31:22 -0700 Subject: [PATCH 050/181] oops -- helps if you use the full link --- src/components/UI/Footer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/UI/Footer.tsx b/src/components/UI/Footer.tsx index 5d02c4dd..ece49077 100644 --- a/src/components/UI/Footer.tsx +++ b/src/components/UI/Footer.tsx @@ -19,7 +19,7 @@ const Footer = () => { {" "} | Meshtastic® is a registered trademark of Meshtastic LLC. | From 049f3de919d79e71fefd4da077d6b9b58d083c1a Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Mon, 19 Aug 2024 23:50:10 +0200 Subject: [PATCH 051/181] Added security tab --- src/components/PageComponents/Config/Security.tsx | 5 +++++ src/pages/Config/DeviceConfig.tsx | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 src/components/PageComponents/Config/Security.tsx diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx new file mode 100644 index 00000000..71346d1a --- /dev/null +++ b/src/components/PageComponents/Config/Security.tsx @@ -0,0 +1,5 @@ +export const Security = (): JSX.Element => { + return ( +

Security

+ ) +}; \ No newline at end of file diff --git a/src/pages/Config/DeviceConfig.tsx b/src/pages/Config/DeviceConfig.tsx index 66b8559d..45973e60 100644 --- a/src/pages/Config/DeviceConfig.tsx +++ b/src/pages/Config/DeviceConfig.tsx @@ -5,6 +5,7 @@ import { LoRa } from "@components/PageComponents/Config/LoRa.js"; import { Network } from "@components/PageComponents/Config/Network.js"; import { Position } from "@components/PageComponents/Config/Position.js"; import { Power } from "@components/PageComponents/Config/Power.js"; +import { Security } from "@components/PageComponents/Config/Security.js"; import { Tabs, TabsContent, @@ -47,6 +48,10 @@ export const DeviceConfig = (): JSX.Element => { label: "Bluetooth", element: Bluetooth, }, + { + label: "Security", + element: Security, + }, ]; return ( From a8dcab0844cde6f3a8a3467b0980cb195ce3f787 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 00:07:32 +0200 Subject: [PATCH 052/181] Added security input fields --- .../PageComponents/Config/Security.tsx | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index 71346d1a..4adb899e 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -1,5 +1,38 @@ +import { DynamicForm } from "@app/components/Form/DynamicForm"; + export const Security = (): JSX.Element => { + const onSubmit = (data: any) => { + console.log(data); + }; return ( -

Security

+ ) }; \ No newline at end of file From f6be57224e2e11704a222420185a00acd96f159f Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 15:04:10 +0200 Subject: [PATCH 053/181] Updated inputs --- .../PageComponents/Config/Security.tsx | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index 4adb899e..b2f7d5f5 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -1,4 +1,4 @@ -import { DynamicForm } from "@app/components/Form/DynamicForm"; +import { DynamicForm } from "@app/components/Form/DynamicForm.js"; export const Security = (): JSX.Element => { const onSubmit = (data: any) => { @@ -9,26 +9,68 @@ export const Security = (): JSX.Element => { onSubmit={onSubmit} fieldGroups={[ { - label: "Security", - description: "Admin and direct messages keys", + label: "Security Settings", + description: "Settings for the Security module", fields: [ { type: "text", name: "publicKey", label: "Public Key", - description: "Sent out to other nodes on the mesh to allow them to compute a shared secret key.", + description: "Sent out to other nodes on the mesh to allow them to compute a shared secret key", }, { type: "text", name: "privateKey", label: "Private Key", - description: "Used to create a shared key with a remote device." + description: "Used to create a shared key with a remote device", + }, + ], + }, + { + label: "Admin Settings", + description: "Settings for Admin ", + fields: [ + { + type: "toggle", + name: "adminChannelEnabled", + label: "Admin Channel", + description: "Enable 'admin' channel", + }, + { + type: "toggle", + name: "isManaged", + label: "Is Managed", + description: "Enable if you want to manage this node from other nodes", }, { type: "text", name: "adminKey", label: "Admin Key", - description: "The public key authorized to send admin messages to this node." + description: "The public key authorized to send admin messages to this node", + } + ], + }, + { + label: "Logging Settings", + description: "Settings for Logging", + fields: [ + { + type: "toggle", + name: "bluetoothLoggingEnabled", + label: "Bluetooth Logging", + description: "Enable Bluetooth Logging", + }, + { + type: "toggle", + name: "debugLogApiEnabled", + label: "Debug Log API", + description: "Enable Log API", + }, + { + type: "toggle", + name: "serialEnabled", + label: "Serial", + description: "Enable Serial" } ], }, From be9169f56f0f370d12ebdade5ab980f7046841d2 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 15:08:13 +0200 Subject: [PATCH 054/181] Use protobuf pki branch, tmp for dev --- package.json | 2 +- pnpm-lock.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index e56bdaed..b49b2041 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ }, "devDependencies": { "@biomejs/biome": "^1.8.2", - "@buf/meshtastic_protobufs.bufbuild_es": "1.10.0-20240613143006-244927bc441a.1", + "@buf/meshtastic_protobufs.bufbuild_es": "2.0.0-00000000000000-aaea594f36a5.2", "@types/chrome": "^0.0.263", "@types/node": "^20.14.9", "@types/react": "^18.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 938ea82e..6bb4dad7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -130,8 +130,8 @@ importers: specifier: ^1.8.2 version: 1.8.2 '@buf/meshtastic_protobufs.bufbuild_es': - specifier: 1.10.0-20240613143006-244927bc441a.1 - version: 1.10.0-20240613143006-244927bc441a.1(@bufbuild/protobuf@1.10.0) + specifier: 2.0.0-00000000000000-aaea594f36a5.2 + version: 2.0.0-00000000000000-aaea594f36a5.2(@bufbuild/protobuf@1.10.0) '@types/chrome': specifier: ^0.0.263 version: 0.0.263 @@ -354,10 +354,10 @@ packages: cpu: [x64] os: [win32] - '@buf/meshtastic_protobufs.bufbuild_es@1.10.0-20240613143006-244927bc441a.1': - resolution: {tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/-/meshtastic_protobufs.bufbuild_es-1.10.0-20240613143006-244927bc441a.1.tgz} + '@buf/meshtastic_protobufs.bufbuild_es@2.0.0-00000000000000-aaea594f36a5.2': + resolution: {tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/-/meshtastic_protobufs.bufbuild_es-2.0.0-00000000000000-aaea594f36a5.2.tgz} peerDependencies: - '@bufbuild/protobuf': ^1.10.0 + '@bufbuild/protobuf': ^2.0.0 '@bufbuild/protobuf@1.10.0': resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} @@ -3306,7 +3306,7 @@ snapshots: '@biomejs/cli-win32-x64@1.8.2': optional: true - '@buf/meshtastic_protobufs.bufbuild_es@1.10.0-20240613143006-244927bc441a.1(@bufbuild/protobuf@1.10.0)': + '@buf/meshtastic_protobufs.bufbuild_es@2.0.0-00000000000000-aaea594f36a5.2(@bufbuild/protobuf@1.10.0)': dependencies: '@bufbuild/protobuf': 1.10.0 From f64b96527e0806d9dce99f7d3bf7c1872117a6c8 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 17:18:55 +0200 Subject: [PATCH 055/181] Add security to device config store --- src/core/stores/deviceStore.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index 29ac6ee0..a716a85b 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -191,6 +191,9 @@ export const useDeviceStore = create((set, get) => ({ device.config.bluetooth = config.payloadVariant.value; break; } + case "security": { + device.config.security = config.payloadVariant.value; + } } } }), From d3836a7250ffc909bbf005b65dc975678b2518b5 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 17:19:36 +0200 Subject: [PATCH 056/181] Add class SecurityValidation --- src/validation/config/security.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/validation/config/security.ts diff --git a/src/validation/config/security.ts b/src/validation/config/security.ts new file mode 100644 index 00000000..4d501537 --- /dev/null +++ b/src/validation/config/security.ts @@ -0,0 +1,31 @@ +import type { Message } from "@bufbuild/protobuf"; +import type { Protobuf } from "@meshtastic/js"; +import { IsBoolean, IsString } from "class-validator"; + +export class SecurityValidation + implements Omit +{ + @IsBoolean() + adminChannelEnabled: boolean; + + @IsString() + adminKey: string; + + @IsBoolean() + bluetoothLoggingEnabled: boolean; + + @IsBoolean() + debugLogApiEnabled: boolean; + + @IsBoolean() + isManaged: boolean; + + @IsString() + privateKey: string; + + @IsString() + publicKey: string; + + @IsBoolean() + serialEnabled: boolean; +} \ No newline at end of file From 7d5950d6cc127237a637bd550c1ba3b1589d9615 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 17:23:42 +0200 Subject: [PATCH 057/181] Add SecurityValidation to security channel --- .../PageComponents/Config/Security.tsx | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index b2f7d5f5..8553cf33 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -1,12 +1,47 @@ +import type { SecurityValidation } from "@app/validation/config/security.js" import { DynamicForm } from "@app/components/Form/DynamicForm.js"; +import { useDevice } from "@core/stores/deviceStore.js"; +import { Protobuf } from "@meshtastic/js"; +import { fromByteArray, toByteArray } from "base64-js"; +import { useState } from "react"; export const Security = (): JSX.Element => { - const onSubmit = (data: any) => { - console.log(data); + const { config, nodes, hardware, setWorkingConfig } = useDevice(); + + const [adminKey, setAdminKey] = useState( + fromByteArray(config.security?.adminKey ?? new Uint8Array(0)) + ); + const [privateKey, setPrivateKey] = useState( + fromByteArray(config.security?.privateKey ?? new Uint8Array(0)) + ); + const [publicKey, setPublicKey] = useState( + fromByteArray(config.security?.publicKey ?? new Uint8Array(0)) + ); + + const onSubmit = (data: SecurityValidation) => { + setWorkingConfig( + new Protobuf.Config.Config({ + payloadVariant: { + case: "security", + value: { + ...data, + adminKey: toByteArray(adminKey), + privateKey: toByteArray(privateKey), + publicKey: toByteArray(publicKey), + } + }, + }) + ) }; return ( - onSubmit={onSubmit} + defaultValues={{ + ...config.security, + adminKey: adminKey, + privateKey: privateKey, + publicKey: publicKey + }} fieldGroups={[ { label: "Security Settings", @@ -77,4 +112,4 @@ export const Security = (): JSX.Element => { ]} /> ) -}; \ No newline at end of file +}; From 6d3bf39b76542e61edad4f6e9c650f1e99016baa Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 18:06:27 +0200 Subject: [PATCH 058/181] Updated @buf/meshtastic_protobufs.bufbuild_es to lastest --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b49b2041..5c260975 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ }, "devDependencies": { "@biomejs/biome": "^1.8.2", - "@buf/meshtastic_protobufs.bufbuild_es": "2.0.0-00000000000000-aaea594f36a5.2", + "@buf/meshtastic_protobufs.bufbuild_es": "2.0.0-20240820152623-fac6975bbc78.2", "@types/chrome": "^0.0.263", "@types/node": "^20.14.9", "@types/react": "^18.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6bb4dad7..605247d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -130,8 +130,8 @@ importers: specifier: ^1.8.2 version: 1.8.2 '@buf/meshtastic_protobufs.bufbuild_es': - specifier: 2.0.0-00000000000000-aaea594f36a5.2 - version: 2.0.0-00000000000000-aaea594f36a5.2(@bufbuild/protobuf@1.10.0) + specifier: 2.0.0-20240820152623-fac6975bbc78.2 + version: 2.0.0-20240820152623-fac6975bbc78.2(@bufbuild/protobuf@1.10.0) '@types/chrome': specifier: ^0.0.263 version: 0.0.263 @@ -354,8 +354,8 @@ packages: cpu: [x64] os: [win32] - '@buf/meshtastic_protobufs.bufbuild_es@2.0.0-00000000000000-aaea594f36a5.2': - resolution: {tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/-/meshtastic_protobufs.bufbuild_es-2.0.0-00000000000000-aaea594f36a5.2.tgz} + '@buf/meshtastic_protobufs.bufbuild_es@2.0.0-20240820152623-fac6975bbc78.2': + resolution: {tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/-/meshtastic_protobufs.bufbuild_es-2.0.0-20240820152623-fac6975bbc78.2.tgz} peerDependencies: '@bufbuild/protobuf': ^2.0.0 @@ -3306,7 +3306,7 @@ snapshots: '@biomejs/cli-win32-x64@1.8.2': optional: true - '@buf/meshtastic_protobufs.bufbuild_es@2.0.0-00000000000000-aaea594f36a5.2(@bufbuild/protobuf@1.10.0)': + '@buf/meshtastic_protobufs.bufbuild_es@2.0.0-20240820152623-fac6975bbc78.2(@bufbuild/protobuf@1.10.0)': dependencies: '@bufbuild/protobuf': 1.10.0 From f0eae444c7ca2391c3b291cd12b496729276c0c6 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 18:10:39 +0200 Subject: [PATCH 059/181] Update descriptions in Security --- src/components/PageComponents/Config/Security.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index 8553cf33..17ec99fa 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -45,7 +45,7 @@ export const Security = (): JSX.Element => { fieldGroups={[ { label: "Security Settings", - description: "Settings for the Security module", + description: "Settings for the Security configuration", fields: [ { type: "text", @@ -69,13 +69,13 @@ export const Security = (): JSX.Element => { type: "toggle", name: "adminChannelEnabled", label: "Admin Channel", - description: "Enable 'admin' channel", + description: "Allow incoming device control over the insecure legacy admin channel", }, { type: "toggle", name: "isManaged", label: "Is Managed", - description: "Enable if you want to manage this node from other nodes", + description: 'If true, device is considered to be "managed" by a mesh administrator via admin messages', }, { type: "text", @@ -93,19 +93,19 @@ export const Security = (): JSX.Element => { type: "toggle", name: "bluetoothLoggingEnabled", label: "Bluetooth Logging", - description: "Enable Bluetooth Logging", + description: "Enables device (serial style logs) over Bluetooth", }, { type: "toggle", name: "debugLogApiEnabled", label: "Debug Log API", - description: "Enable Log API", + description: "Output live debug logging over serial", }, { type: "toggle", name: "serialEnabled", label: "Serial", - description: "Enable Serial" + description: "Serial Console over the Stream API" } ], }, From af51659e71b6ce43856db93e7fcbc906289b7abe Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 18:50:19 +0200 Subject: [PATCH 060/181] Add always to disabled by in dynamics form --- src/components/Form/DynamicForm.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Form/DynamicForm.tsx b/src/components/Form/DynamicForm.tsx index 61c4c0e7..9affc0c7 100644 --- a/src/components/Form/DynamicForm.tsx +++ b/src/components/Form/DynamicForm.tsx @@ -16,7 +16,7 @@ import { } from "react-hook-form"; interface DisabledBy { - fieldName: Path; + fieldName: Path | "always"; selector?: number; invert?: boolean; } @@ -66,7 +66,9 @@ export function DynamicForm({ if (!disabledBy) return false; return disabledBy.some((field) => { + if (field.fieldName === "always") return true const value = getValues(field.fieldName); + if (value === "always") return true; if (typeof value === "boolean") return field.invert ? value : !value; if (typeof value === "number") return field.invert From 65247c4f351bb7f41268298d8b3ac5b84acef0ec Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Tue, 20 Aug 2024 18:51:02 +0200 Subject: [PATCH 061/181] Update Security tab --- src/components/PageComponents/Config/Security.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index 17ec99fa..ea3b2f17 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -47,18 +47,19 @@ export const Security = (): JSX.Element => { label: "Security Settings", description: "Settings for the Security configuration", fields: [ - { - type: "text", - name: "publicKey", - label: "Public Key", - description: "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - }, { type: "text", name: "privateKey", label: "Private Key", description: "Used to create a shared key with a remote device", }, + { + type: "text", + name: "publicKey", + label: "Public Key", + description: "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + disabledBy: [ { fieldName: "always" } ] + }, ], }, { From 8bb0a9674479b9dda9d023fca416f1c547d11007 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Wed, 21 Aug 2024 13:13:42 +0200 Subject: [PATCH 062/181] Downgraded @buf/meshtastic_protobufs.bufbuild_es from 2.0 to 1.10 --- package.json | 2 +- pnpm-lock.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 5c260975..b65359d9 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ }, "devDependencies": { "@biomejs/biome": "^1.8.2", - "@buf/meshtastic_protobufs.bufbuild_es": "2.0.0-20240820152623-fac6975bbc78.2", + "@buf/meshtastic_protobufs.bufbuild_es": "1.10.0-20240820152623-fac6975bbc78.1", "@types/chrome": "^0.0.263", "@types/node": "^20.14.9", "@types/react": "^18.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 605247d7..62578557 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -130,8 +130,8 @@ importers: specifier: ^1.8.2 version: 1.8.2 '@buf/meshtastic_protobufs.bufbuild_es': - specifier: 2.0.0-20240820152623-fac6975bbc78.2 - version: 2.0.0-20240820152623-fac6975bbc78.2(@bufbuild/protobuf@1.10.0) + specifier: 1.10.0-20240820152623-fac6975bbc78.1 + version: 1.10.0-20240820152623-fac6975bbc78.1(@bufbuild/protobuf@1.10.0) '@types/chrome': specifier: ^0.0.263 version: 0.0.263 @@ -354,10 +354,10 @@ packages: cpu: [x64] os: [win32] - '@buf/meshtastic_protobufs.bufbuild_es@2.0.0-20240820152623-fac6975bbc78.2': - resolution: {tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/-/meshtastic_protobufs.bufbuild_es-2.0.0-20240820152623-fac6975bbc78.2.tgz} + '@buf/meshtastic_protobufs.bufbuild_es@1.10.0-20240820152623-fac6975bbc78.1': + resolution: {tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/-/meshtastic_protobufs.bufbuild_es-1.10.0-20240820152623-fac6975bbc78.1.tgz} peerDependencies: - '@bufbuild/protobuf': ^2.0.0 + '@bufbuild/protobuf': ^1.10.0 '@bufbuild/protobuf@1.10.0': resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} @@ -3306,7 +3306,7 @@ snapshots: '@biomejs/cli-win32-x64@1.8.2': optional: true - '@buf/meshtastic_protobufs.bufbuild_es@2.0.0-20240820152623-fac6975bbc78.2(@bufbuild/protobuf@1.10.0)': + '@buf/meshtastic_protobufs.bufbuild_es@1.10.0-20240820152623-fac6975bbc78.1(@bufbuild/protobuf@1.10.0)': dependencies: '@bufbuild/protobuf': 1.10.0 From cf423620c4e7a8da32d1b1484f8122fc07593172 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Wed, 21 Aug 2024 17:41:24 +0200 Subject: [PATCH 063/181] Error & formating fixes --- src/components/Form/DynamicForm.tsx | 2 +- .../PageComponents/Config/Security.tsx | 40 ++++++++++--------- src/components/Sidebar.tsx | 2 +- src/pages/Map.tsx | 8 ++-- src/validation/config/bluetooth.ts | 6 ++- src/validation/config/lora.ts | 3 +- src/validation/config/power.ts | 3 +- src/validation/config/security.ts | 8 +++- src/validation/moduleConfig/storeForward.ts | 5 ++- 9 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/components/Form/DynamicForm.tsx b/src/components/Form/DynamicForm.tsx index 9affc0c7..58bf241e 100644 --- a/src/components/Form/DynamicForm.tsx +++ b/src/components/Form/DynamicForm.tsx @@ -66,7 +66,7 @@ export function DynamicForm({ if (!disabledBy) return false; return disabledBy.some((field) => { - if (field.fieldName === "always") return true + if (field.fieldName === "always") return true; const value = getValues(field.fieldName); if (value === "always") return true; if (typeof value === "boolean") return field.invert ? value : !value; diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index ea3b2f17..2834574c 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -1,5 +1,5 @@ -import type { SecurityValidation } from "@app/validation/config/security.js" import { DynamicForm } from "@app/components/Form/DynamicForm.js"; +import type { SecurityValidation } from "@app/validation/config/security.js"; import { useDevice } from "@core/stores/deviceStore.js"; import { Protobuf } from "@meshtastic/js"; import { fromByteArray, toByteArray } from "base64-js"; @@ -9,13 +9,13 @@ export const Security = (): JSX.Element => { const { config, nodes, hardware, setWorkingConfig } = useDevice(); const [adminKey, setAdminKey] = useState( - fromByteArray(config.security?.adminKey ?? new Uint8Array(0)) + fromByteArray(config.security?.adminKey ?? new Uint8Array(0)), ); const [privateKey, setPrivateKey] = useState( - fromByteArray(config.security?.privateKey ?? new Uint8Array(0)) + fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), ); const [publicKey, setPublicKey] = useState( - fromByteArray(config.security?.publicKey ?? new Uint8Array(0)) + fromByteArray(config.security?.publicKey ?? new Uint8Array(0)), ); const onSubmit = (data: SecurityValidation) => { @@ -28,10 +28,10 @@ export const Security = (): JSX.Element => { adminKey: toByteArray(adminKey), privateKey: toByteArray(privateKey), publicKey: toByteArray(publicKey), - } + }, }, - }) - ) + }), + ); }; return ( @@ -40,7 +40,7 @@ export const Security = (): JSX.Element => { ...config.security, adminKey: adminKey, privateKey: privateKey, - publicKey: publicKey + publicKey: publicKey, }} fieldGroups={[ { @@ -57,8 +57,9 @@ export const Security = (): JSX.Element => { type: "text", name: "publicKey", label: "Public Key", - description: "Sent out to other nodes on the mesh to allow them to compute a shared secret key", - disabledBy: [ { fieldName: "always" } ] + description: + "Sent out to other nodes on the mesh to allow them to compute a shared secret key", + disabledBy: [{ fieldName: "always" }], }, ], }, @@ -70,20 +71,23 @@ export const Security = (): JSX.Element => { type: "toggle", name: "adminChannelEnabled", label: "Admin Channel", - description: "Allow incoming device control over the insecure legacy admin channel", + description: + "Allow incoming device control over the insecure legacy admin channel", }, { type: "toggle", name: "isManaged", label: "Is Managed", - description: 'If true, device is considered to be "managed" by a mesh administrator via admin messages', + description: + 'If true, device is considered to be "managed" by a mesh administrator via admin messages', }, { type: "text", name: "adminKey", label: "Admin Key", - description: "The public key authorized to send admin messages to this node", - } + description: + "The public key authorized to send admin messages to this node", + }, ], }, { @@ -106,11 +110,11 @@ export const Security = (): JSX.Element => { type: "toggle", name: "serialEnabled", label: "Serial", - description: "Serial Console over the Stream API" - } + description: "Serial Console over the Stream API", + }, ], }, ]} - /> - ) + /> + ); }; diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 96d820bb..116b6647 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -85,7 +85,7 @@ export const Sidebar = ({ children }: SidebarProps): JSX.Element => {
- {myNode?.deviceMetrics?.voltage.toPrecision(3) ?? "UNK"} volts + {myNode?.deviceMetrics?.voltage?.toPrecision(3) ?? "UNK"} volts
diff --git a/src/pages/Map.tsx b/src/pages/Map.tsx index 8c86480e..53df0cd4 100644 --- a/src/pages/Map.tsx +++ b/src/pages/Map.tsx @@ -144,8 +144,8 @@ export const MapPage = (): JSX.Element => { {waypoints.map((wp) => (
@@ -163,8 +163,8 @@ export const MapPage = (): JSX.Element => { return ( { diff --git a/src/validation/config/bluetooth.ts b/src/validation/config/bluetooth.ts index 65a0d0be..efaca6e9 100644 --- a/src/validation/config/bluetooth.ts +++ b/src/validation/config/bluetooth.ts @@ -3,7 +3,11 @@ import { Protobuf } from "@meshtastic/js"; import { IsBoolean, IsEnum, IsInt } from "class-validator"; export class BluetoothValidation - implements Omit + implements + Omit< + Protobuf.Config.Config_BluetoothConfig, + keyof Message | "deviceLoggingEnabled" + > { @IsBoolean() enabled: boolean; diff --git a/src/validation/config/lora.ts b/src/validation/config/lora.ts index 291a42d0..f5ef49d6 100644 --- a/src/validation/config/lora.ts +++ b/src/validation/config/lora.ts @@ -3,7 +3,8 @@ import { Protobuf } from "@meshtastic/js"; import { IsArray, IsBoolean, IsEnum, IsInt, Max, Min } from "class-validator"; export class LoRaValidation - implements Omit + implements + Omit { @IsBoolean() usePreset: boolean; diff --git a/src/validation/config/power.ts b/src/validation/config/power.ts index 3f3d097a..67bd1cd0 100644 --- a/src/validation/config/power.ts +++ b/src/validation/config/power.ts @@ -3,7 +3,8 @@ import type { Protobuf } from "@meshtastic/js"; import { IsBoolean, IsInt, IsNumber, Max, Min } from "class-validator"; export class PowerValidation - implements Omit + implements + Omit { @IsBoolean() isPowerSaving: boolean; diff --git a/src/validation/config/security.ts b/src/validation/config/security.ts index 4d501537..d1a35808 100644 --- a/src/validation/config/security.ts +++ b/src/validation/config/security.ts @@ -3,7 +3,11 @@ import type { Protobuf } from "@meshtastic/js"; import { IsBoolean, IsString } from "class-validator"; export class SecurityValidation - implements Omit + implements + Omit< + Protobuf.Config.Config_SecurityConfig, + keyof Message | "adminKey" | "privateKey" | "publicKey" + > { @IsBoolean() adminChannelEnabled: boolean; @@ -28,4 +32,4 @@ export class SecurityValidation @IsBoolean() serialEnabled: boolean; -} \ No newline at end of file +} diff --git a/src/validation/moduleConfig/storeForward.ts b/src/validation/moduleConfig/storeForward.ts index 82d9f4c2..773a2539 100644 --- a/src/validation/moduleConfig/storeForward.ts +++ b/src/validation/moduleConfig/storeForward.ts @@ -4,7 +4,10 @@ import { IsBoolean, IsInt } from "class-validator"; export class StoreForwardValidation implements - Omit + Omit< + Protobuf.ModuleConfig.ModuleConfig_StoreForwardConfig, + keyof Message | "isServer" + > { @IsBoolean() enabled: boolean; From 66fb3005758f565c89c5e9477da9f176d08b9ba1 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Wed, 21 Aug 2024 18:52:03 +0200 Subject: [PATCH 064/181] Moved prop. from Device to Security & Hide PKI Eye --- .../PageComponents/Config/Device.tsx | 19 --------- .../PageComponents/Config/Security.tsx | 42 ++++++++++++++----- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/components/PageComponents/Config/Device.tsx b/src/components/PageComponents/Config/Device.tsx index c0f3bfc4..ce2b5ce1 100644 --- a/src/components/PageComponents/Config/Device.tsx +++ b/src/components/PageComponents/Config/Device.tsx @@ -36,19 +36,6 @@ export const Device = (): JSX.Element => { formatEnumName: true, }, }, - { - type: "toggle", - name: "serialEnabled", - label: "Serial Output Enabled", - description: "Enable the device's serial console", - }, - { - type: "toggle", - name: "debugLogEnabled", - label: "Enabled Debug Log", - description: - "Output debugging information to the device's serial port (auto disables when serial client is connected)", - }, { type: "number", name: "buttonGpio", @@ -86,12 +73,6 @@ export const Device = (): JSX.Element => { label: "Double Tap as Button Press", description: "Treat double tap as button press", }, - { - type: "toggle", - name: "isManaged", - label: "Managed", - description: "Is this device managed by a mesh administator", - }, { type: "toggle", name: "disableTripleClick", diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index 2834574c..c9e1175c 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -3,20 +3,23 @@ import type { SecurityValidation } from "@app/validation/config/security.js"; import { useDevice } from "@core/stores/deviceStore.js"; import { Protobuf } from "@meshtastic/js"; import { fromByteArray, toByteArray } from "base64-js"; +import { Eye, EyeOff } from "lucide-react"; import { useState } from "react"; export const Security = (): JSX.Element => { const { config, nodes, hardware, setWorkingConfig } = useDevice(); - const [adminKey, setAdminKey] = useState( - fromByteArray(config.security?.adminKey ?? new Uint8Array(0)), - ); const [privateKey, setPrivateKey] = useState( fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), ); + const [privateKeyVisible, setPrivateKeyVisible] = useState(false); const [publicKey, setPublicKey] = useState( fromByteArray(config.security?.publicKey ?? new Uint8Array(0)), ); + const [adminKey, setAdminKey] = useState( + fromByteArray(config.security?.adminKey ?? new Uint8Array(0)), + ); + const [adminKeyVisible, setAdminKeyVisible] = useState(false); const onSubmit = (data: SecurityValidation) => { setWorkingConfig( @@ -48,10 +51,22 @@ export const Security = (): JSX.Element => { description: "Settings for the Security configuration", fields: [ { - type: "text", + type: privateKeyVisible ? "text" : "password", name: "privateKey", label: "Private Key", description: "Used to create a shared key with a remote device", + disabledBy: [ + { + fieldName: "adminChannelEnabled", + invert: true, + }, + ], + properties: { + action: { + icon: privateKeyVisible ? EyeOff : Eye, + onClick: () => setPrivateKeyVisible(!privateKeyVisible), + }, + }, }, { type: "text", @@ -70,21 +85,28 @@ export const Security = (): JSX.Element => { { type: "toggle", name: "adminChannelEnabled", - label: "Admin Channel", + label: "Allow Legacy Admin", description: "Allow incoming device control over the insecure legacy admin channel", }, { type: "toggle", name: "isManaged", - label: "Is Managed", + label: "Managed", description: 'If true, device is considered to be "managed" by a mesh administrator via admin messages', }, { - type: "text", + type: adminKeyVisible ? "text" : "password", name: "adminKey", label: "Admin Key", + disabledBy: [{ fieldName: "adminChannelEnabled" }], + properties: { + action: { + icon: adminKeyVisible ? EyeOff : Eye, + onClick: () => setAdminKeyVisible(!adminKeyVisible), + }, + }, description: "The public key authorized to send admin messages to this node", }, @@ -97,19 +119,19 @@ export const Security = (): JSX.Element => { { type: "toggle", name: "bluetoothLoggingEnabled", - label: "Bluetooth Logging", + label: "Allow Bluetooth Logging", description: "Enables device (serial style logs) over Bluetooth", }, { type: "toggle", name: "debugLogApiEnabled", - label: "Debug Log API", + label: "Enable Debug Log API", description: "Output live debug logging over serial", }, { type: "toggle", name: "serialEnabled", - label: "Serial", + label: "Serial Output Enabled", description: "Serial Console over the Stream API", }, ], From 1cdf18747db4fa5e0e20c351896545dff31ea103 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Wed, 7 Aug 2024 08:35:16 +0200 Subject: [PATCH 065/181] Added ip utils --- src/core/utils/ip.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/core/utils/ip.ts diff --git a/src/core/utils/ip.ts b/src/core/utils/ip.ts new file mode 100644 index 00000000..09f7c935 --- /dev/null +++ b/src/core/utils/ip.ts @@ -0,0 +1,13 @@ +export function convertIntToIpAddress(int: number): string { + return `${int & 0xff}.${(int >> 8) & 0xff}.${(int >> 16) & 0xff}.${(int >> 24) & 0xff}`; +} + +export function convertIpAddressToInt(ip: string): number | null { + const parts = ip.split('.').map(Number).reverse(); // little-endian byte order + + if (parts.some(Number.isNaN)) { + return null; + } + + return parts.reduce((total, part) => (total << 8) | part, 0); +} \ No newline at end of file From ebd5a3d3a6a82fdc8c92f5840793beccf5240cad Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Wed, 7 Aug 2024 08:36:32 +0200 Subject: [PATCH 066/181] Implemented IP utils --- .../PageComponents/Config/Network.tsx | 26 +++++++++++++++++-- src/validation/config/network.ts | 8 +++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/components/PageComponents/Config/Network.tsx b/src/components/PageComponents/Config/Network.tsx index 1b31db59..df6bd78e 100644 --- a/src/components/PageComponents/Config/Network.tsx +++ b/src/components/PageComponents/Config/Network.tsx @@ -2,10 +2,27 @@ import type { NetworkValidation } from "@app/validation/config/network.js"; import { DynamicForm } from "@components/Form/DynamicForm.js"; import { useDevice } from "@core/stores/deviceStore.js"; import { Protobuf } from "@meshtastic/js"; +import { convertIntToIpAddress, convertIpAddressToInt } from "@core/utils/ip.js"; export const Network = (): JSX.Element => { const { config, setWorkingConfig } = useDevice(); + const netConfig = { + wifiEnabled: config.network?.wifiEnabled, + wifiSsid: config.network?.wifiSsid, + wifiPsk: config.network?.wifiPsk, + ethEnabled: config.network?.ethEnabled, + addressMode: config.network?.addressMode, + ipv4Config: { + ip: convertIntToIpAddress(config.network?.ipv4Config?.ip ?? 0), + gateway: convertIntToIpAddress(config.network?.ipv4Config?.gateway ?? 0), + subnet: convertIntToIpAddress(config.network?.ipv4Config?.subnet ?? 0), + dns: convertIntToIpAddress(config.network?.ipv4Config?.dns ?? 0), + }, + ntpServer: config.network?.ntpServer, + rsyslogServer: config.network?.rsyslogServer, + } + const onSubmit = (data: NetworkValidation) => { setWorkingConfig( new Protobuf.Config.Config({ @@ -14,7 +31,12 @@ export const Network = (): JSX.Element => { value: { ...data, ipv4Config: new Protobuf.Config.Config_NetworkConfig_IpV4Config( - data.ipv4Config, + { + ip: convertIpAddressToInt(data.ipv4Config.ip) ?? 0, + gateway: convertIpAddressToInt(data.ipv4Config.gateway) ?? 0, + subnet: convertIpAddressToInt(data.ipv4Config.subnet) ?? 0, + dns: convertIpAddressToInt(data.ipv4Config.dns) ?? 0, + }, ), }, }, @@ -25,7 +47,7 @@ export const Network = (): JSX.Element => { return ( onSubmit={onSubmit} - defaultValues={config.network} + defaultValues={netConfig} fieldGroups={[ { label: "WiFi Config", diff --git a/src/validation/config/network.ts b/src/validation/config/network.ts index 8f851d69..65953aae 100644 --- a/src/validation/config/network.ts +++ b/src/validation/config/network.ts @@ -45,17 +45,17 @@ export class NetworkValidationIpV4Config { @IsIP() @IsOptional() - ip: number; + ip: string; @IsIP() @IsOptional() - gateway: number; + gateway: string; @IsIP() @IsOptional() - subnet: number; + subnet: string; @IsIP() @IsOptional() - dns: number; + dns: string; } From 8ed3ce820342eed5fab7f70b35f10d72a489447a Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Wed, 21 Aug 2024 23:13:35 +0200 Subject: [PATCH 067/181] Error & Format fixing --- .../PageComponents/Config/Network.tsx | 21 ++++++++++--------- src/core/utils/ip.ts | 6 +++--- src/validation/config/network.ts | 5 ++++- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/components/PageComponents/Config/Network.tsx b/src/components/PageComponents/Config/Network.tsx index df6bd78e..564f22a3 100644 --- a/src/components/PageComponents/Config/Network.tsx +++ b/src/components/PageComponents/Config/Network.tsx @@ -1,8 +1,11 @@ import type { NetworkValidation } from "@app/validation/config/network.js"; import { DynamicForm } from "@components/Form/DynamicForm.js"; import { useDevice } from "@core/stores/deviceStore.js"; +import { + convertIntToIpAddress, + convertIpAddressToInt, +} from "@core/utils/ip.js"; import { Protobuf } from "@meshtastic/js"; -import { convertIntToIpAddress, convertIpAddressToInt } from "@core/utils/ip.js"; export const Network = (): JSX.Element => { const { config, setWorkingConfig } = useDevice(); @@ -21,7 +24,7 @@ export const Network = (): JSX.Element => { }, ntpServer: config.network?.ntpServer, rsyslogServer: config.network?.rsyslogServer, - } + }; const onSubmit = (data: NetworkValidation) => { setWorkingConfig( @@ -30,14 +33,12 @@ export const Network = (): JSX.Element => { case: "network", value: { ...data, - ipv4Config: new Protobuf.Config.Config_NetworkConfig_IpV4Config( - { - ip: convertIpAddressToInt(data.ipv4Config.ip) ?? 0, - gateway: convertIpAddressToInt(data.ipv4Config.gateway) ?? 0, - subnet: convertIpAddressToInt(data.ipv4Config.subnet) ?? 0, - dns: convertIpAddressToInt(data.ipv4Config.dns) ?? 0, - }, - ), + ipv4Config: new Protobuf.Config.Config_NetworkConfig_IpV4Config({ + ip: convertIpAddressToInt(data.ipv4Config.ip) ?? 0, + gateway: convertIpAddressToInt(data.ipv4Config.gateway) ?? 0, + subnet: convertIpAddressToInt(data.ipv4Config.subnet) ?? 0, + dns: convertIpAddressToInt(data.ipv4Config.dns) ?? 0, + }), }, }, }), diff --git a/src/core/utils/ip.ts b/src/core/utils/ip.ts index 09f7c935..3fcc9686 100644 --- a/src/core/utils/ip.ts +++ b/src/core/utils/ip.ts @@ -3,11 +3,11 @@ export function convertIntToIpAddress(int: number): string { } export function convertIpAddressToInt(ip: string): number | null { - const parts = ip.split('.').map(Number).reverse(); // little-endian byte order + const parts = ip.split(".").map(Number).reverse(); // little-endian byte order if (parts.some(Number.isNaN)) { - return null; + return null; } return parts.reduce((total, part) => (total << 8) | part, 0); -} \ No newline at end of file +} diff --git a/src/validation/config/network.ts b/src/validation/config/network.ts index 65953aae..41db88d7 100644 --- a/src/validation/config/network.ts +++ b/src/validation/config/network.ts @@ -41,7 +41,10 @@ export class NetworkValidation export class NetworkValidationIpV4Config implements - Omit + Omit< + Protobuf.Config.Config_NetworkConfig_IpV4Config, + keyof Message | "ip" | "gateway" | "subnet" | "dns" + > { @IsIP() @IsOptional() From 02a63c213eba55e835da16057e75ada4cdd0e5a4 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Thu, 22 Aug 2024 14:08:17 +0200 Subject: [PATCH 068/181] Add key verification & generation --- .../PageComponents/Config/Security.tsx | 110 ++++++++++++++++-- 1 file changed, 103 insertions(+), 7 deletions(-) diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index c9e1175c..c1739aba 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -3,6 +3,7 @@ import type { SecurityValidation } from "@app/validation/config/security.js"; import { useDevice } from "@core/stores/deviceStore.js"; import { Protobuf } from "@meshtastic/js"; import { fromByteArray, toByteArray } from "base64-js"; +import cryptoRandomString from "crypto-random-string"; import { Eye, EyeOff } from "lucide-react"; import { useState } from "react"; @@ -13,6 +14,11 @@ export const Security = (): JSX.Element => { fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), ); const [privateKeyVisible, setPrivateKeyVisible] = useState(false); + const [privateKeyBitCount, setPrivateKeyBitCount] = useState( + config.security?.privateKey.length ?? 16, + ); + const [privateKeyValidationText, setPrivateKeyValidationText] = + useState(); const [publicKey, setPublicKey] = useState( fromByteArray(config.security?.publicKey ?? new Uint8Array(0)), ); @@ -20,8 +26,15 @@ export const Security = (): JSX.Element => { fromByteArray(config.security?.adminKey ?? new Uint8Array(0)), ); const [adminKeyVisible, setAdminKeyVisible] = useState(false); + const [adminKeyBitCount, setAdminKeyBitCount] = useState( + config.security?.adminKey.length ?? 16, + ); + const [adminKeyValidationText, setAdminKeyValidationText] = + useState(); const onSubmit = (data: SecurityValidation) => { + if (privateKeyValidationText || adminKeyValidationText) return; + setWorkingConfig( new Protobuf.Config.Config({ payloadVariant: { @@ -36,14 +49,75 @@ export const Security = (): JSX.Element => { }), ); }; + + const clickEvent = ( + setKey: (value: React.SetStateAction) => void, + bitCount: number, + setValidationText: ( + value: React.SetStateAction, + ) => void, + ) => { + setKey( + btoa( + cryptoRandomString({ + length: bitCount ?? 0, + type: "alphanumeric", + }), + ), + ); + setValidationText(undefined); + }; + + const validatePass = ( + input: string, + count: number, + setValidationText: ( + value: React.SetStateAction, + ) => void, + ) => { + if (input.length % 4 !== 0 || toByteArray(input).length !== count) { + setValidationText(`Please enter a valid ${count * 8} bit PSK.`); + } else { + setValidationText(undefined); + } + }; + + const privateKeyInputChangeEvent = ( + e: React.ChangeEvent, + ) => { + const psk = e.currentTarget?.value; + setPrivateKey(psk); + validatePass(psk, privateKeyBitCount, setPrivateKeyValidationText); + }; + + const adminKeyInputChangeEvent = (e: React.ChangeEvent) => { + const psk = e.currentTarget?.value; + setAdminKey(psk); + validatePass(psk, privateKeyBitCount, setAdminKeyValidationText); + }; + + const privateKeySelectChangeEvent = (e: string) => { + const count = Number.parseInt(e); + setPrivateKeyBitCount(count); + validatePass(privateKey, count, setPrivateKeyValidationText); + }; + + const adminKeySelectChangeEvent = (e: string) => { + const count = Number.parseInt(e); + setAdminKeyBitCount(count); + validatePass(privateKey, count, setAdminKeyValidationText); + }; + return ( onSubmit={onSubmit} defaultValues={{ ...config.security, - adminKey: adminKey, - privateKey: privateKey, - publicKey: publicKey, + ...{ + adminKey: adminKey, + privateKey: privateKey, + publicKey: publicKey, + }, }} fieldGroups={[ { @@ -51,10 +125,20 @@ export const Security = (): JSX.Element => { description: "Settings for the Security configuration", fields: [ { - type: privateKeyVisible ? "text" : "password", + type: "passwordGenerator", name: "privateKey", label: "Private Key", description: "Used to create a shared key with a remote device", + validationText: privateKeyValidationText, + devicePSKBitCount: privateKeyBitCount, + inputChange: privateKeyInputChangeEvent, + selectChange: privateKeySelectChangeEvent, + buttonClick: () => + clickEvent( + setPrivateKey, + privateKeyBitCount, + setPrivateKeyValidationText, + ), disabledBy: [ { fieldName: "adminChannelEnabled", @@ -62,6 +146,7 @@ export const Security = (): JSX.Element => { }, ], properties: { + value: privateKey, action: { icon: privateKeyVisible ? EyeOff : Eye, onClick: () => setPrivateKeyVisible(!privateKeyVisible), @@ -97,18 +182,29 @@ export const Security = (): JSX.Element => { 'If true, device is considered to be "managed" by a mesh administrator via admin messages', }, { - type: adminKeyVisible ? "text" : "password", + type: "passwordGenerator", name: "adminKey", label: "Admin Key", + description: + "The public key authorized to send admin messages to this node", + validationText: adminKeyValidationText, + devicePSKBitCount: adminKeyBitCount, + inputChange: adminKeyInputChangeEvent, + selectChange: adminKeySelectChangeEvent, + buttonClick: () => + clickEvent( + setAdminKey, + adminKeyBitCount, + setAdminKeyValidationText, + ), disabledBy: [{ fieldName: "adminChannelEnabled" }], properties: { + value: adminKey, action: { icon: adminKeyVisible ? EyeOff : Eye, onClick: () => setAdminKeyVisible(!adminKeyVisible), }, }, - description: - "The public key authorized to send admin messages to this node", }, ], }, From e3fad3015fa489a1dbe169de12aa95e367aee324 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Thu, 22 Aug 2024 15:45:11 +0200 Subject: [PATCH 069/181] Add hide toggle to password generator --- src/components/Form/FormPasswordGenerator.tsx | 4 ++++ .../PageComponents/Config/Security.tsx | 2 ++ src/components/UI/Generator.tsx | 16 ++++++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/components/Form/FormPasswordGenerator.tsx b/src/components/Form/FormPasswordGenerator.tsx index d015d3af..a94b0215 100644 --- a/src/components/Form/FormPasswordGenerator.tsx +++ b/src/components/Form/FormPasswordGenerator.tsx @@ -8,6 +8,7 @@ import { Controller, type FieldValues } from "react-hook-form"; export interface PasswordGeneratorProps extends BaseFormBuilderProps { type: "passwordGenerator"; + hide?: boolean; devicePSKBitCount: number; inputChange: ChangeEventHandler; selectChange: (event: string) => void; @@ -17,6 +18,7 @@ export interface PasswordGeneratorProps extends BaseFormBuilderProps { export function PasswordGenerator({ control, field, + disabled, }: GenericFormElementProps>) { return ( ({ control={control} render={({ field: { value, ...rest } }) => ( ({ buttonText="Generate" {...field.properties} {...rest} + disabled={disabled} /> )} /> diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index c1739aba..a82ed980 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -133,6 +133,7 @@ export const Security = (): JSX.Element => { devicePSKBitCount: privateKeyBitCount, inputChange: privateKeyInputChangeEvent, selectChange: privateKeySelectChangeEvent, + hide: !privateKeyVisible, buttonClick: () => clickEvent( setPrivateKey, @@ -191,6 +192,7 @@ export const Security = (): JSX.Element => { devicePSKBitCount: adminKeyBitCount, inputChange: adminKeyInputChangeEvent, selectChange: adminKeySelectChangeEvent, + hide: !adminKeyVisible, buttonClick: () => clickEvent( setAdminKey, diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index 344e89bb..0e8b1e0d 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -9,8 +9,10 @@ import { SelectTrigger, SelectValue, } from "@components/UI/Select.js"; +import type { LucideIcon } from "lucide-react"; export interface GeneratorProps extends React.BaseHTMLAttributes { + hide?: boolean; devicePSKBitCount?: number; value: string; variant: "default" | "invalid"; @@ -18,11 +20,17 @@ export interface GeneratorProps extends React.BaseHTMLAttributes { selectChange: (event: string) => void; inputChange: (event: React.ChangeEvent) => void; buttonClick: React.MouseEventHandler; + action?: { + icon: LucideIcon; + onClick: () => void; + }; + disabled?: boolean; } const Generator = React.forwardRef( ( { + hide = true, devicePSKBitCount, variant, value, @@ -30,6 +38,8 @@ const Generator = React.forwardRef( selectChange, inputChange, buttonClick, + action, + disabled, ...props }, ref, @@ -37,17 +47,19 @@ const Generator = React.forwardRef( return ( <> + + + + + ); +}; diff --git a/src/components/Form/FormPasswordGenerator.tsx b/src/components/Form/FormPasswordGenerator.tsx index 09e97ff5..784086fb 100644 --- a/src/components/Form/FormPasswordGenerator.tsx +++ b/src/components/Form/FormPasswordGenerator.tsx @@ -7,6 +7,7 @@ import { Eye, EyeOff } from "lucide-react"; import type { ChangeEventHandler, MouseEventHandler } from "react"; import { useState } from "react"; import { Controller, type FieldValues } from "react-hook-form"; +import type { ButtonVariant } from "@components/UI/Button"; export interface PasswordGeneratorProps extends BaseFormBuilderProps { type: "passwordGenerator"; @@ -15,7 +16,12 @@ export interface PasswordGeneratorProps extends BaseFormBuilderProps { devicePSKBitCount: number; inputChange: ChangeEventHandler; selectChange: (event: string) => void; - buttonClick: MouseEventHandler; + actionButtons: { + text: string; + onClick: React.MouseEventHandler; + variant: ButtonVariant; + className?: string; + }[]; } export function PasswordGenerator({ @@ -38,19 +44,18 @@ export function PasswordGenerator({ action={ field.hide ? { - icon: passwordShown ? EyeOff : Eye, - onClick: togglePasswordVisiblity, - } + icon: passwordShown ? EyeOff : Eye, + onClick: togglePasswordVisiblity, + } : undefined } devicePSKBitCount={field.devicePSKBitCount} bits={field.bits} inputChange={field.inputChange} selectChange={field.selectChange} - buttonClick={field.buttonClick} value={value} variant={field.validationText ? "invalid" : "default"} - buttonText="Generate" + actionButtons={field.actionButtons} {...field.properties} {...rest} disabled={disabled} diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index 3655e5f8..7b581d72 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -6,6 +6,7 @@ import { Protobuf } from "@meshtastic/js"; import { fromByteArray, toByteArray } from "base64-js"; import cryptoRandomString from "crypto-random-string"; import { useState } from "react"; +import { PkiRegenerateDialog } from "../Dialog/PkiRegenerateDialog"; export interface SettingsPanelProps { channel: Protobuf.Channel.Channel; @@ -22,6 +23,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { channel?.settings?.psk.length ?? 16, ); const [validationText, setValidationText] = useState(); + const [preSharedDialogOpen, setPreSharedDialogOpen] = useState(false); const onSubmit = (data: ChannelValidation) => { const channel = new Protobuf.Channel.Channel({ @@ -46,7 +48,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }); }; - const clickEvent = () => { + const preSharedKeyRegenerate = () => { setPass( btoa( cryptoRandomString({ @@ -56,6 +58,11 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { ), ); setValidationText(undefined); + setPreSharedDialogOpen(false); + }; + + const preSharedClickEvent = () => { + setPreSharedDialogOpen(true); }; const validatePass = (input: string, count: number) => { @@ -79,104 +86,105 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }; return ( - - onSubmit={onSubmit} - submitType="onSubmit" - hasSubmitButton={true} - defaultValues={{ - ...channel, - ...{ - settings: { - ...channel?.settings, - psk: pass, - positionEnabled: - channel?.settings?.moduleSettings?.positionPrecision !== + <> + + onSubmit={onSubmit} + submitType="onSubmit" + hasSubmitButton={true} + defaultValues={{ + ...channel, + ...{ + settings: { + ...channel?.settings, + psk: pass, + positionEnabled: + channel?.settings?.moduleSettings?.positionPrecision !== undefined && - channel?.settings?.moduleSettings?.positionPrecision > 0, - preciseLocation: - channel?.settings?.moduleSettings?.positionPrecision === 32, - positionPrecision: - channel?.settings?.moduleSettings?.positionPrecision === undefined - ? 10 - : channel?.settings?.moduleSettings?.positionPrecision, + channel?.settings?.moduleSettings?.positionPrecision > 0, + preciseLocation: + channel?.settings?.moduleSettings?.positionPrecision === 32, + positionPrecision: + channel?.settings?.moduleSettings?.positionPrecision === undefined + ? 10 + : channel?.settings?.moduleSettings?.positionPrecision, + }, }, - }, - }} - fieldGroups={[ - { - label: "Channel Settings", - description: "Crypto, MQTT & misc settings", - fields: [ - { - type: "select", - name: "role", - label: "Role", - disabled: channel.index === 0, - description: - "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - properties: { - enumValue: - channel.index === 0 - ? { PRIMARY: 1 } - : { DISABLED: 0, SECONDARY: 2 }, + }} + fieldGroups={[ + { + label: "Channel Settings", + description: "Crypto, MQTT & misc settings", + fields: [ + { + type: "select", + name: "role", + label: "Role", + disabled: channel.index === 0, + description: + "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + properties: { + enumValue: + channel.index === 0 + ? { PRIMARY: 1 } + : { DISABLED: 0, SECONDARY: 2 }, + }, }, - }, - { - type: "passwordGenerator", - name: "settings.psk", - label: "pre-Shared Key", - description: "256, 128, or 8 bit PSKs allowed", - validationText: validationText, - devicePSKBitCount: bitCount ?? 0, - inputChange: inputChangeEvent, - selectChange: selectChangeEvent, - buttonClick: clickEvent, - hide: true, - properties: { - value: pass, + { + type: "passwordGenerator", + name: "settings.psk", + label: "Pre-Shared Key", + description: "256, 128, or 8 bit PSKs allowed", + validationText: validationText, + devicePSKBitCount: bitCount ?? 0, + inputChange: inputChangeEvent, + selectChange: selectChangeEvent, + actionButtons: [{ text: 'Generate', variant: 'success', onClick: preSharedClickEvent }], + hide: true, + properties: { + value: pass, + }, }, - }, - { - type: "text", - name: "settings.name", - label: "Name", - description: - "A unique name for the channel <12 bytes, leave blank for default", - }, - { - type: "toggle", - name: "settings.uplinkEnabled", - label: "Uplink Enabled", - description: "Send messages from the local mesh to MQTT", - }, - { - type: "toggle", - name: "settings.downlinkEnabled", - label: "Downlink Enabled", - description: "Send messages from MQTT to the local mesh", - }, - { - type: "toggle", - name: "settings.positionEnabled", - label: "Allow Position Requests", - description: "Send position to channel", - }, - { - type: "toggle", - name: "settings.preciseLocation", - label: "Precise Location", - description: "Send precise location to channel", - }, - { - type: "select", - name: "settings.positionPrecision", - label: "Approximate Location", - description: - "If not sharing precise location, position shared on channel will be accurate within this distance", - properties: { - enumValue: - config.display?.units === 0 - ? { + { + type: "text", + name: "settings.name", + label: "Name", + description: + "A unique name for the channel <12 bytes, leave blank for default", + }, + { + type: "toggle", + name: "settings.uplinkEnabled", + label: "Uplink Enabled", + description: "Send messages from the local mesh to MQTT", + }, + { + type: "toggle", + name: "settings.downlinkEnabled", + label: "Downlink Enabled", + description: "Send messages from MQTT to the local mesh", + }, + { + type: "toggle", + name: "settings.positionEnabled", + label: "Allow Position Requests", + description: "Send position to channel", + }, + { + type: "toggle", + name: "settings.preciseLocation", + label: "Precise Location", + description: "Send precise location to channel", + }, + { + type: "select", + name: "settings.positionPrecision", + label: "Approximate Location", + description: + "If not sharing precise location, position shared on channel will be accurate within this distance", + properties: { + enumValue: + config.display?.units === 0 + ? { "Within 23 km": 10, "Within 12 km": 11, "Within 5.8 km": 12, @@ -188,7 +196,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { "Within 90 m": 18, "Within 50 m": 19, } - : { + : { "Within 15 miles": 10, "Within 7.3 miles": 11, "Within 3.6 miles": 12, @@ -200,11 +208,17 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { "Within 300 feet": 18, "Within 150 feet": 19, }, + }, }, - }, - ], - }, - ]} - /> + ], + }, + ]} + /> + setPreSharedDialogOpen(false)} + onSubmit={() => preSharedKeyRegenerate()} + /> + ); }; diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index cf675751..d6e76cc9 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -12,7 +12,7 @@ import { Eye, EyeOff } from "lucide-react"; import { useState } from "react"; export const Security = (): JSX.Element => { - const { config, nodes, hardware, setWorkingConfig } = useDevice(); + const { config, nodes, hardware, setWorkingConfig, setDialogOpen } = useDevice(); const [privateKey, setPrivateKey] = useState( fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), @@ -31,7 +31,7 @@ export const Security = (): JSX.Element => { ); const [adminKeyValidationText, setAdminKeyValidationText] = useState(); - const [dialogOpen, setDialogOpen] = useState(false); + const [privateKeyDialogOpen, setPrivateKeyDialogOpen] = useState(false); const onSubmit = (data: SecurityValidation) => { if (privateKeyValidationText || adminKeyValidationText) return; @@ -71,9 +71,13 @@ export const Security = (): JSX.Element => { }; const privateKeyClickEvent = () => { - setDialogOpen(true); + setPrivateKeyDialogOpen(true); }; + const pkiBackupClickEvent = () => { + setDialogOpen("pkiBackup", true); + } + const pkiRegenerate = () => { const privateKey = getX25519PrivateKey(); const publicKey = getX25519PublicKey(privateKey); @@ -86,7 +90,7 @@ export const Security = (): JSX.Element => { setPrivateKeyValidationText, ); - setDialogOpen(false); + setPrivateKeyDialogOpen(false); }; const privateKeyInputChangeEvent = ( @@ -149,7 +153,18 @@ export const Security = (): JSX.Element => { inputChange: privateKeyInputChangeEvent, selectChange: privateKeySelectChangeEvent, hide: !privateKeyVisible, - buttonClick: privateKeyClickEvent, + actionButtons: [ + { + text: "Generate", + onClick: privateKeyClickEvent, + variant: "success", + }, + { + text: "Backup Key", + onClick: pkiBackupClickEvent, + variant: "subtle", + }, + ], properties: { value: privateKey, action: { @@ -228,8 +243,8 @@ export const Security = (): JSX.Element => { ]} /> setDialogOpen(false)} + open={privateKeyDialogOpen} + onOpenChange={() => setPrivateKeyDialogOpen(false)} onSubmit={() => pkiRegenerate()} /> diff --git a/src/components/UI/Button.tsx b/src/components/UI/Button.tsx index 39418551..e1b2d704 100644 --- a/src/components/UI/Button.tsx +++ b/src/components/UI/Button.tsx @@ -35,9 +35,11 @@ const buttonVariants = cva( }, ); +export type ButtonVariant = VariantProps["variant"]; + export interface ButtonProps extends React.ButtonHTMLAttributes, - VariantProps {} + VariantProps { } const Button = React.forwardRef( ({ className, variant, size, ...props }, ref) => { diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index cb8fea26..c983b8ef 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -1,6 +1,6 @@ import * as React from "react"; -import { Button } from "@components/UI/Button.tsx"; +import { Button, type ButtonVariant } from "@components/UI/Button.tsx"; import { Input } from "@components/UI/Input.tsx"; import { Select, @@ -16,11 +16,15 @@ export interface GeneratorProps extends React.BaseHTMLAttributes { devicePSKBitCount?: number; value: string; variant: "default" | "invalid"; - buttonText?: string; + actionButtons: { + text: string; + onClick: React.MouseEventHandler; + variant: ButtonVariant; + className?: string; + }[]; bits?: { text: string; value: string; key: string }[]; selectChange: (event: string) => void; inputChange: (event: React.ChangeEvent) => void; - buttonClick: React.MouseEventHandler; action?: { icon: LucideIcon; onClick: () => void; @@ -35,7 +39,7 @@ const Generator = React.forwardRef( devicePSKBitCount, variant, value, - buttonText, + actionButtons, bits = [ { text: "256 bit", value: "32", key: "bit256" }, { text: "128 bit", value: "16", key: "bit128" }, @@ -43,7 +47,6 @@ const Generator = React.forwardRef( ], selectChange, inputChange, - buttonClick, action, disabled, ...props @@ -93,15 +96,21 @@ const Generator = React.forwardRef( ))} - +
+ {actionButtons?.map(({ text, onClick, variant, className }) => ( + + ))} +
); }, diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index a716a85b..bd407611 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -25,7 +25,8 @@ export type DialogVariant = | "shutdown" | "reboot" | "deviceName" - | "nodeRemoval"; + | "nodeRemoval" + | "pkiBackup"; export interface Device { id: number; @@ -60,6 +61,7 @@ export interface Device { reboot: boolean; deviceName: boolean; nodeRemoval: boolean; + pkiBackup: boolean; }; setStatus: (status: Types.DeviceStatusEnum) => void; @@ -142,6 +144,7 @@ export const useDeviceStore = create((set, get) => ({ reboot: false, deviceName: false, nodeRemoval: false, + pkiBackup: false, }, pendingSettingsChanges: false, messageDraft: "", From 7cd03c6a527140912a6dfc05815feaf9fa16a687 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Fri, 3 Jan 2025 21:40:56 -0500 Subject: [PATCH 150/181] feat: Add key backup reminder. Refactor Toast component to handle dark mode better --- package.json | 2 + pnpm-lock.yaml | 214 +++++++++++++--------- src/App.tsx | 4 +- src/components/Dialog/DialogManager.tsx | 2 +- src/components/Dialog/PKIBackupDialog.tsx | 13 +- src/components/KeyBackupReminder.tsx | 21 +++ src/components/Toaster.tsx | 17 +- src/components/UI/Toast.tsx | 70 +++---- src/core/hooks/useCookie.ts | 35 ++++ src/core/hooks/useKeyBackupReminder.tsx | 85 +++++++++ 10 files changed, 326 insertions(+), 137 deletions(-) create mode 100644 src/components/KeyBackupReminder.tsx create mode 100644 src/core/hooks/useCookie.ts create mode 100644 src/core/hooks/useKeyBackupReminder.tsx diff --git a/package.json b/package.json index 05221d9b..84a49432 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "cmdk": "^1.0.0", "crypto-random-string": "^5.0.0", "immer": "^10.1.1", + "js-cookie": "^3.0.5", "lucide-react": "^0.363.0", "mapbox-gl": "^3.6.0", "maplibre-gl": "4.1.2", @@ -70,6 +71,7 @@ "@rsbuild/core": "^1.0.10", "@rsbuild/plugin-react": "^1.0.3", "@types/chrome": "^0.0.263", + "@types/js-cookie": "^3.0.6", "@types/node": "^20.14.9", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9edbfd5..79d6d5ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,6 +89,9 @@ importers: immer: specifier: ^10.1.1 version: 10.1.1 + js-cookie: + specifier: ^3.0.5 + version: 3.0.5 lucide-react: specifier: ^0.363.0 version: 0.363.0(react@18.3.1) @@ -127,7 +130,7 @@ importers: version: 3.0.6(react@18.3.1) vite-plugin-node-polyfills: specifier: ^0.22.0 - version: 0.22.0(rollup@4.24.0)(vite@5.3.6(@types/node@20.14.9)) + version: 0.22.0(rollup@4.29.1)(vite@5.3.6(@types/node@20.14.9)) zustand: specifier: 4.5.2 version: 4.5.2(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1) @@ -147,6 +150,9 @@ importers: '@types/chrome': specifier: ^0.0.263 version: 0.0.263 + '@types/js-cookie': + specifier: ^3.0.6 + version: 3.0.6 '@types/node': specifier: ^20.14.9 version: 20.14.9 @@ -173,7 +179,7 @@ importers: version: 8.4.38 rollup-plugin-visualizer: specifier: ^5.12.0 - version: 5.12.0(rollup@4.24.0) + version: 5.12.0(rollup@4.29.1) tailwindcss: specifier: ^3.4.4 version: 3.4.4 @@ -1165,83 +1171,98 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.24.0': - resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} + '@rollup/rollup-android-arm-eabi@4.29.1': + resolution: {integrity: sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.24.0': - resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} + '@rollup/rollup-android-arm64@4.29.1': + resolution: {integrity: sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.24.0': - resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} + '@rollup/rollup-darwin-arm64@4.29.1': + resolution: {integrity: sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.24.0': - resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} + '@rollup/rollup-darwin-x64@4.29.1': + resolution: {integrity: sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.24.0': - resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} + '@rollup/rollup-freebsd-arm64@4.29.1': + resolution: {integrity: sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.29.1': + resolution: {integrity: sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.29.1': + resolution: {integrity: sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.24.0': - resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} + '@rollup/rollup-linux-arm-musleabihf@4.29.1': + resolution: {integrity: sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.24.0': - resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} + '@rollup/rollup-linux-arm64-gnu@4.29.1': + resolution: {integrity: sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.24.0': - resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} + '@rollup/rollup-linux-arm64-musl@4.29.1': + resolution: {integrity: sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': - resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} + '@rollup/rollup-linux-loongarch64-gnu@4.29.1': + resolution: {integrity: sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.29.1': + resolution: {integrity: sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.24.0': - resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} + '@rollup/rollup-linux-riscv64-gnu@4.29.1': + resolution: {integrity: sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.24.0': - resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} + '@rollup/rollup-linux-s390x-gnu@4.29.1': + resolution: {integrity: sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.24.0': - resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} + '@rollup/rollup-linux-x64-gnu@4.29.1': + resolution: {integrity: sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.24.0': - resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} + '@rollup/rollup-linux-x64-musl@4.29.1': + resolution: {integrity: sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.24.0': - resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} + '@rollup/rollup-win32-arm64-msvc@4.29.1': + resolution: {integrity: sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.24.0': - resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} + '@rollup/rollup-win32-ia32-msvc@4.29.1': + resolution: {integrity: sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.24.0': - resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} + '@rollup/rollup-win32-x64-msvc@4.29.1': + resolution: {integrity: sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==} cpu: [x64] os: [win32] @@ -1690,6 +1711,9 @@ packages: '@types/har-format@1.2.15': resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==} + '@types/js-cookie@3.0.6': + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + '@types/mapbox-gl@3.1.0': resolution: {integrity: sha512-hI6cQDjw1bkJw7MC/eHMqq5TWUamLwsujnUUeiIX2KDRjxRNSYMjnHz07+LATz9I9XIsKumOtUz4gRYnZOJ/FA==} @@ -1864,8 +1888,8 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - caniuse-lite@1.0.30001638: - resolution: {integrity: sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ==} + caniuse-lite@1.0.30001690: + resolution: {integrity: sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==} cheap-ruler@4.0.0: resolution: {integrity: sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==} @@ -2417,6 +2441,10 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + js-sha3@0.8.0: resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} @@ -2923,8 +2951,8 @@ packages: rollup: optional: true - rollup@4.24.0: - resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} + rollup@4.29.1: + resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -4258,68 +4286,77 @@ snapshots: '@radix-ui/rect@1.1.0': {} - '@rollup/plugin-inject@5.0.5(rollup@4.24.0)': + '@rollup/plugin-inject@5.0.5(rollup@4.29.1)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.24.0) + '@rollup/pluginutils': 5.1.0(rollup@4.29.1) estree-walker: 2.0.2 magic-string: 0.30.11 optionalDependencies: - rollup: 4.24.0 + rollup: 4.29.1 - '@rollup/pluginutils@5.1.0(rollup@4.24.0)': + '@rollup/pluginutils@5.1.0(rollup@4.29.1)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.24.0 + rollup: 4.29.1 - '@rollup/rollup-android-arm-eabi@4.24.0': + '@rollup/rollup-android-arm-eabi@4.29.1': optional: true - '@rollup/rollup-android-arm64@4.24.0': + '@rollup/rollup-android-arm64@4.29.1': optional: true - '@rollup/rollup-darwin-arm64@4.24.0': + '@rollup/rollup-darwin-arm64@4.29.1': optional: true - '@rollup/rollup-darwin-x64@4.24.0': + '@rollup/rollup-darwin-x64@4.29.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + '@rollup/rollup-freebsd-arm64@4.29.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.24.0': + '@rollup/rollup-freebsd-x64@4.29.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.24.0': + '@rollup/rollup-linux-arm-gnueabihf@4.29.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.24.0': + '@rollup/rollup-linux-arm-musleabihf@4.29.1': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + '@rollup/rollup-linux-arm64-gnu@4.29.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.24.0': + '@rollup/rollup-linux-arm64-musl@4.29.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.24.0': + '@rollup/rollup-linux-loongarch64-gnu@4.29.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.24.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.29.1': optional: true - '@rollup/rollup-linux-x64-musl@4.24.0': + '@rollup/rollup-linux-riscv64-gnu@4.29.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.24.0': + '@rollup/rollup-linux-s390x-gnu@4.29.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.24.0': + '@rollup/rollup-linux-x64-gnu@4.29.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.24.0': + '@rollup/rollup-linux-x64-musl@4.29.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.29.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.29.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.29.1': optional: true '@rsbuild/core@1.0.10': @@ -4381,7 +4418,7 @@ snapshots: '@module-federation/runtime-tools': 0.5.1 '@rspack/binding': 1.0.8 '@rspack/lite-tapable': 1.0.1 - caniuse-lite: 1.0.30001638 + caniuse-lite: 1.0.30001690 optionalDependencies: '@swc/helpers': 0.5.13 @@ -5255,6 +5292,8 @@ snapshots: '@types/har-format@1.2.15': {} + '@types/js-cookie@3.0.6': {} + '@types/mapbox-gl@3.1.0': dependencies: '@types/geojson': 7946.0.14 @@ -5343,7 +5382,7 @@ snapshots: autoprefixer@10.4.19(postcss@8.4.38): dependencies: browserslist: 4.23.1 - caniuse-lite: 1.0.30001638 + caniuse-lite: 1.0.30001690 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 @@ -5424,7 +5463,7 @@ snapshots: browserslist@4.23.1: dependencies: - caniuse-lite: 1.0.30001638 + caniuse-lite: 1.0.30001690 electron-to-chromium: 1.4.812 node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.1) @@ -5459,7 +5498,7 @@ snapshots: camelcase-css@2.0.1: {} - caniuse-lite@1.0.30001638: {} + caniuse-lite@1.0.30001690: {} cheap-ruler@4.0.0: {} @@ -6075,6 +6114,8 @@ snapshots: jiti@1.21.6: {} + js-cookie@3.0.5: {} + js-sha3@0.8.0: {} js-tokens@4.0.0: {} @@ -6620,35 +6661,38 @@ snapshots: robust-predicates@3.0.2: {} - rollup-plugin-visualizer@5.12.0(rollup@4.24.0): + rollup-plugin-visualizer@5.12.0(rollup@4.29.1): dependencies: open: 8.4.2 picomatch: 2.3.1 source-map: 0.7.4 yargs: 17.7.2 optionalDependencies: - rollup: 4.24.0 + rollup: 4.29.1 - rollup@4.24.0: + rollup@4.29.1: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.24.0 - '@rollup/rollup-android-arm64': 4.24.0 - '@rollup/rollup-darwin-arm64': 4.24.0 - '@rollup/rollup-darwin-x64': 4.24.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 - '@rollup/rollup-linux-arm-musleabihf': 4.24.0 - '@rollup/rollup-linux-arm64-gnu': 4.24.0 - '@rollup/rollup-linux-arm64-musl': 4.24.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 - '@rollup/rollup-linux-riscv64-gnu': 4.24.0 - '@rollup/rollup-linux-s390x-gnu': 4.24.0 - '@rollup/rollup-linux-x64-gnu': 4.24.0 - '@rollup/rollup-linux-x64-musl': 4.24.0 - '@rollup/rollup-win32-arm64-msvc': 4.24.0 - '@rollup/rollup-win32-ia32-msvc': 4.24.0 - '@rollup/rollup-win32-x64-msvc': 4.24.0 + '@rollup/rollup-android-arm-eabi': 4.29.1 + '@rollup/rollup-android-arm64': 4.29.1 + '@rollup/rollup-darwin-arm64': 4.29.1 + '@rollup/rollup-darwin-x64': 4.29.1 + '@rollup/rollup-freebsd-arm64': 4.29.1 + '@rollup/rollup-freebsd-x64': 4.29.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.29.1 + '@rollup/rollup-linux-arm-musleabihf': 4.29.1 + '@rollup/rollup-linux-arm64-gnu': 4.29.1 + '@rollup/rollup-linux-arm64-musl': 4.29.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.29.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.29.1 + '@rollup/rollup-linux-riscv64-gnu': 4.29.1 + '@rollup/rollup-linux-s390x-gnu': 4.29.1 + '@rollup/rollup-linux-x64-gnu': 4.29.1 + '@rollup/rollup-linux-x64-musl': 4.29.1 + '@rollup/rollup-win32-arm64-msvc': 4.29.1 + '@rollup/rollup-win32-ia32-msvc': 4.29.1 + '@rollup/rollup-win32-x64-msvc': 4.29.1 fsevents: 2.3.3 run-parallel@1.2.0: @@ -6986,9 +7030,9 @@ snapshots: validator@13.12.0: {} - vite-plugin-node-polyfills@0.22.0(rollup@4.24.0)(vite@5.3.6(@types/node@20.14.9)): + vite-plugin-node-polyfills@0.22.0(rollup@4.29.1)(vite@5.3.6(@types/node@20.14.9)): dependencies: - '@rollup/plugin-inject': 5.0.5(rollup@4.24.0) + '@rollup/plugin-inject': 5.0.5(rollup@4.29.1) node-stdlib-browser: 1.2.0 vite: 5.3.6(@types/node@20.14.9) transitivePeerDependencies: @@ -6998,7 +7042,7 @@ snapshots: dependencies: esbuild: 0.21.5 postcss: 8.4.49 - rollup: 4.24.0 + rollup: 4.29.1 optionalDependencies: '@types/node': 20.14.9 fsevents: 2.3.3 diff --git a/src/App.tsx b/src/App.tsx index c936bc9c..8c15dc97 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,7 +2,7 @@ import { DeviceWrapper } from "@app/DeviceWrapper.tsx"; import { PageRouter } from "@app/PageRouter.tsx"; import { CommandPalette } from "@components/CommandPalette.tsx"; import { DeviceSelector } from "@components/DeviceSelector.tsx"; -import { DialogManager } from "@components/Dialog/DialogManager.tsx"; +import { DialogManager } from "@components/Dialog/DialogManager"; import { NewDeviceDialog } from "@components/Dialog/NewDeviceDialog.tsx"; import { Toaster } from "@components/Toaster.tsx"; import Footer from "@components/UI/Footer.tsx"; @@ -11,6 +11,7 @@ import { useAppStore } from "@core/stores/appStore.ts"; import { useDeviceStore } from "@core/stores/deviceStore.ts"; import { Dashboard } from "@pages/Dashboard/index.tsx"; import { MapProvider } from "react-map-gl"; +import { KeyBackupReminder } from "@components/KeyBackupReminder"; export const App = (): JSX.Element => { const { getDevice } = useDeviceStore(); @@ -37,6 +38,7 @@ export const App = (): JSX.Element => { {device ? (
+
diff --git a/src/components/Dialog/DialogManager.tsx b/src/components/Dialog/DialogManager.tsx index 762bd5a7..afebdf5d 100644 --- a/src/components/Dialog/DialogManager.tsx +++ b/src/components/Dialog/DialogManager.tsx @@ -5,7 +5,7 @@ import { QRDialog } from "@components/Dialog/QRDialog.tsx"; import { RebootDialog } from "@components/Dialog/RebootDialog.tsx"; import { ShutdownDialog } from "@components/Dialog/ShutdownDialog.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; -import { PkiBackupDialog } from "./PKIBackupDialog"; +import { PkiBackupDialog } from "@components/Dialog/PKIBackupDialog"; export const DialogManager = (): JSX.Element => { const { channels, config, dialog, setDialogOpen } = useDevice(); diff --git a/src/components/Dialog/PKIBackupDialog.tsx b/src/components/Dialog/PKIBackupDialog.tsx index 3737236a..4b482bf7 100644 --- a/src/components/Dialog/PKIBackupDialog.tsx +++ b/src/components/Dialog/PKIBackupDialog.tsx @@ -21,7 +21,7 @@ export const PkiBackupDialog = ({ open, onOpenChange, }: PkiBackupDialogProps) => { - const { config } = useDevice(); + const { config, setDialogOpen } = useDevice(); const privateKeyData = config.security?.privateKey // If the private data doesn't exist return null @@ -31,6 +31,10 @@ export const PkiBackupDialog = ({ const getPrivateKey = React.useMemo(() => fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), [config.security?.privateKey]); + const closeDialog = React.useCallback(() => { + setDialogOpen("pkiBackup", false) + }, [setDialogOpen]) + const renderPrintWindow = React.useCallback(() => { const printWindow = window.open("", "_blank"); if (printWindow) { @@ -52,8 +56,10 @@ export const PkiBackupDialog = ({ `); printWindow.document.close(); printWindow.print(); + closeDialog() + } - }, [getPrivateKey]); + }, [getPrivateKey, closeDialog]); const createDownloadKeyFile = React.useCallback(() => { const blob = new Blob([getPrivateKey], { type: "text/plain" }); @@ -65,8 +71,9 @@ export const PkiBackupDialog = ({ document.body.appendChild(link); link.click(); document.body.removeChild(link); + closeDialog() URL.revokeObjectURL(url); - }, [getPrivateKey]); + }, [getPrivateKey, closeDialog]); return ( diff --git a/src/components/KeyBackupReminder.tsx b/src/components/KeyBackupReminder.tsx new file mode 100644 index 00000000..45819bd7 --- /dev/null +++ b/src/components/KeyBackupReminder.tsx @@ -0,0 +1,21 @@ +import { useBackupReminder } from "@app/core/hooks/useKeyBackupReminder"; +import { useDevice } from "@app/core/stores/deviceStore"; + +export const KeyBackupReminder = (): JSX.Element => { + const { setDialogOpen } = useDevice(); + + useBackupReminder({ + suppressDays: 7, + message: "We recommend backing up your key data regularly. Would you like to back up now?", + onAccept: () => setDialogOpen("pkiBackup", true), + cookieOptions: { + secure: true, + sameSite: 'strict' + } + }); + + return ( + <> + + ); +}; diff --git a/src/components/Toaster.tsx b/src/components/Toaster.tsx index cfe13a9d..cf322758 100644 --- a/src/components/Toaster.tsx +++ b/src/components/Toaster.tsx @@ -1,5 +1,3 @@ -import { useToast } from "@core/hooks/useToast.ts"; - import { Toast, ToastClose, @@ -7,7 +5,8 @@ import { ToastProvider, ToastTitle, ToastViewport, -} from "@components/UI/Toast.tsx"; +} from "@components/UI/Toast"; +import { useToast } from "@core/hooks/useToast"; export function Toaster() { const { toasts } = useToast(); @@ -15,16 +14,10 @@ export function Toaster() { return ( {toasts.map(({ id, title, description, action, ...props }) => ( - +
- {title && ( - {title} - )} - {description && ( - - {description} - - )} + {title && {title}} + {description && {description}}
{action} diff --git a/src/components/UI/Toast.tsx b/src/components/UI/Toast.tsx index ca8dfc90..d40b294a 100644 --- a/src/components/UI/Toast.tsx +++ b/src/components/UI/Toast.tsx @@ -1,11 +1,11 @@ -import * as ToastPrimitives from "@radix-ui/react-toast"; -import { type VariantProps, cva } from "class-variance-authority"; -import { X } from "lucide-react"; -import * as React from "react"; +import * as React from "react" +import * as ToastPrimitives from "@radix-ui/react-toast" +import { cva, type VariantProps } from "class-variance-authority" +import { X } from 'lucide-react' -import { cn } from "@core/utils/cn.ts"; +import { cn } from "@core/utils/cn" -const ToastProvider = ToastPrimitives.Provider; +const ToastProvider = ToastPrimitives.Provider const ToastViewport = React.forwardRef< React.ElementRef, @@ -14,35 +14,34 @@ const ToastViewport = React.forwardRef< -)); -ToastViewport.displayName = ToastPrimitives.Viewport.displayName; +)) +ToastViewport.displayName = ToastPrimitives.Viewport.displayName const toastVariants = cva( - "data-[swipe=move]:transition-none grow-1 group relative pointer-events-auto flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full mt-4 data-[state=closed]:slide-out-to-right-full dark:border-slate-700 last:mt-0 sm:last:mt-4", + "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", { variants: { variant: { - default: - "bg-white border-slate-200 dark:bg-slate-800 dark:border-slate-700", + default: "border bg-background text-foreground dark:bg-slate-700 dark:border-slate-600 dark:text-slate-50", destructive: - "group destructive bg-red-600 text-white border-red-600 dark:border-red-600", + "group destructive bg-red-600 text-white dark:border-red-900 dark:bg-red-900 dark:text-red-50" }, }, defaultVariants: { variant: "default", }, - }, -); + } +) const Toast = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef & - VariantProps + VariantProps >(({ className, variant, ...props }, ref) => { return ( - ); -}); -Toast.displayName = ToastPrimitives.Root.displayName; + ) +}) +Toast.displayName = ToastPrimitives.Root.displayName const ToastAction = React.forwardRef< React.ElementRef, @@ -61,13 +60,13 @@ const ToastAction = React.forwardRef< -)); -ToastAction.displayName = ToastPrimitives.Action.displayName; +)) +ToastAction.displayName = ToastPrimitives.Action.displayName const ToastClose = React.forwardRef< React.ElementRef, @@ -76,16 +75,16 @@ const ToastClose = React.forwardRef< -)); -ToastClose.displayName = ToastPrimitives.Close.displayName; +)) +ToastClose.displayName = ToastPrimitives.Close.displayName const ToastTitle = React.forwardRef< React.ElementRef, @@ -96,8 +95,8 @@ const ToastTitle = React.forwardRef< className={cn("text-sm font-semibold", className)} {...props} /> -)); -ToastTitle.displayName = ToastPrimitives.Title.displayName; +)) +ToastTitle.displayName = ToastPrimitives.Title.displayName const ToastDescription = React.forwardRef< React.ElementRef, @@ -108,12 +107,12 @@ const ToastDescription = React.forwardRef< className={cn("text-sm opacity-90", className)} {...props} /> -)); -ToastDescription.displayName = ToastPrimitives.Description.displayName; +)) +ToastDescription.displayName = ToastPrimitives.Description.displayName -type ToastProps = React.ComponentPropsWithoutRef; +type ToastProps = React.ComponentPropsWithoutRef -type ToastActionElement = React.ReactElement; +type ToastActionElement = React.ReactElement export { type ToastProps, @@ -125,4 +124,5 @@ export { ToastDescription, ToastClose, ToastAction, -}; +} + diff --git a/src/core/hooks/useCookie.ts b/src/core/hooks/useCookie.ts new file mode 100644 index 00000000..6a1eb311 --- /dev/null +++ b/src/core/hooks/useCookie.ts @@ -0,0 +1,35 @@ +import React from "react"; +import Cookies, { type CookieAttributes } from "js-cookie"; + +type Cookie = [ + T | undefined, + (value: T, options?: CookieAttributes) => void, + () => void, +]; + +const useCookie = ( + cookieName: string, + initialValue?: T, +): Cookie => { + const [cookieValue, setCookieValue] = React.useState(() => { + const cookie = Cookies.get(cookieName); + return cookie ? (JSON.parse(cookie) as T) : initialValue; + }); + + const setCookie = React.useCallback( + (value: T, options?: CookieAttributes) => { + Cookies.set(cookieName, JSON.stringify(value), options); + setCookieValue(value); + }, + [cookieName], + ); + + const removeCookie = React.useCallback(() => { + Cookies.remove(cookieName); + setCookieValue(undefined); + }, [cookieName]); + + return [cookieValue, setCookie, removeCookie]; +}; + +export default useCookie; diff --git a/src/core/hooks/useKeyBackupReminder.tsx b/src/core/hooks/useKeyBackupReminder.tsx new file mode 100644 index 00000000..8ce9e1d8 --- /dev/null +++ b/src/core/hooks/useKeyBackupReminder.tsx @@ -0,0 +1,85 @@ +import { useEffect, useCallback } from 'react'; +import { useToast } from './useToast'; +import useCookie from './useCookie'; +import type { CookieAttributes } from 'js-cookie'; +import { Button } from '@app/components/UI/Button'; + +interface UseBackupReminderOptions { + suppressDays?: number; + message?: string; + onAccept?: () => void | Promise; + cookieName?: string; + cookieOptions?: CookieAttributes; +} + +interface ReminderState { + suppressed: boolean; + lastShown: string; +} + +export function useBackupReminder({ + suppressDays = 365, + message = "It's time to back up your key data. Would you like to do this now?", + onAccept = () => { }, + cookieName = "backup_reminder_state", + cookieOptions = {}, +}: UseBackupReminderOptions = {}) { + const { toast } = useToast(); + + const [reminderState, setReminderState, resetReminderState] = useCookie(cookieName); + + const suppressReminder = useCallback(() => { + const expiryDate = new Date(); + expiryDate.setDate(expiryDate.getDate() + suppressDays); + + setReminderState( + { + suppressed: true, + lastShown: new Date().toISOString(), + }, + { + ...cookieOptions, + expires: expiryDate, + } + ); + + }, [setReminderState, suppressDays, cookieOptions]); + + useEffect(() => { + if (!reminderState) { + const { dismiss: dimissToast } = toast({ + title: "Backup Reminder", + description: message, + action: ( +
+ + +
+ ), + }); + } + }, [reminderState]); + + return { + resetReminder: resetReminderState + }; +} \ No newline at end of file From 1c8476df534c6a9f2d2395895c56ec5523992409 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 6 Jan 2025 11:43:36 -0500 Subject: [PATCH 151/181] refactor: consolidate browser feature detection into typed hook. Update connect dialog messaging to describe requirement for https when conneecting --- src/components/Dialog/NewDeviceDialog.tsx | 73 +++++++++++++------- src/core/hooks/useBrowserFeatureDetection.ts | 32 +++++++++ 2 files changed, 80 insertions(+), 25 deletions(-) create mode 100644 src/core/hooks/useBrowserFeatureDetection.ts diff --git a/src/components/Dialog/NewDeviceDialog.tsx b/src/components/Dialog/NewDeviceDialog.tsx index 6062d69c..92d4c75a 100644 --- a/src/components/Dialog/NewDeviceDialog.tsx +++ b/src/components/Dialog/NewDeviceDialog.tsx @@ -1,3 +1,4 @@ +import { useBrowserFeatureDetection } from "@app/core/hooks/useBrowserFeatureDetection"; import { BLE } from "@components/PageComponents/Connect/BLE.tsx"; import { HTTP } from "@components/PageComponents/Connect/HTTP.tsx"; import { Serial } from "@components/PageComponents/Connect/Serial.tsx"; @@ -28,30 +29,8 @@ export interface TabManifest { disabledLink?: string; } -const tabs: TabManifest[] = [ - { - label: "HTTP", - element: HTTP, - disabled: false, - disabledMessage: "Unsuported connection method", - }, - { - label: "Bluetooth", - element: BLE, - disabled: !navigator.bluetooth, - disabledMessage: - "Web Bluetooth is currently only supported by Chromium-based browsers", - disabledLink: - "https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility", - }, - { - label: "Serial", - element: Serial, - disabled: !navigator.serial, - disabledMessage: - "WebSerial is currently only supported by Chromium based browsers: https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility", - }, -]; + + export interface NewDeviceProps { open: boolean; onOpenChange: (open: boolean) => void; @@ -61,6 +40,36 @@ export const NewDeviceDialog = ({ open, onOpenChange, }: NewDeviceProps): JSX.Element => { + const { hasRequiredFeatures, isSecureContext, missingFeatures } = useBrowserFeatureDetection(); + console.log(missingFeatures); + + const tabs: TabManifest[] = [ + { + label: "HTTP", + element: HTTP, + disabled: false, + disabledMessage: "Unsuported connection method", + }, + { + label: "Bluetooth", + element: BLE, + disabled: missingFeatures.includes("Web Bluetooth"), + disabledMessage: + "Web Bluetooth is currently only supported by Chromium-based browsers", + disabledLink: + "https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility" + }, + { + label: "Serial", + element: Serial, + disabled: missingFeatures.includes("Web Serial"), + disabledMessage: + "Web Serial is currently only supported by Chromium based browsers", + disabledLink: "https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility", + }, + ]; + + return ( @@ -92,7 +101,21 @@ export const NewDeviceDialog = ({ ))} - {(!navigator.bluetooth || !navigator.serial) && ( + {!isSecureContext && ( + <> + + Web Bluetooth and Web Serial require using a HTTPS connection or to localhost. + + + Read more:  + + Secure Contexts + + + + )} + + {!hasRequiredFeatures && ( <> Web Bluetooth and Web Serial are currently only supported by diff --git a/src/core/hooks/useBrowserFeatureDetection.ts b/src/core/hooks/useBrowserFeatureDetection.ts new file mode 100644 index 00000000..df103b2c --- /dev/null +++ b/src/core/hooks/useBrowserFeatureDetection.ts @@ -0,0 +1,32 @@ +type Feature = 'Web Bluetooth' | 'Web Serial'; +type FeatureKey = 'bluetooth' | 'serial'; + +interface BrowserFeatureDetection { + hasRequiredFeatures: boolean; + missingFeatures: Feature[]; + isSecureContext: boolean; +} + +const featureLabels: Record = { + bluetooth: 'Web Bluetooth', + serial: 'Web Serial' +}; + +export function useBrowserFeatureDetection(): BrowserFeatureDetection { + const { bluetooth, serial } = navigator; + const isSecureContext = window.location.protocol === 'https:' || + window.location.hostname === 'localhost'; + + const features = { + bluetooth, + serial + }; + + return { + hasRequiredFeatures: Object.values(features).every(Boolean), + missingFeatures: Object.entries(features) + .filter(([_, supported]) => !supported) + .map(([feature]) => featureLabels[feature as FeatureKey]), + isSecureContext + }; +} \ No newline at end of file From 63be65a4871e9e391a4d6653e684e612b9c4e211 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 6 Jan 2025 13:45:45 -0500 Subject: [PATCH 152/181] feat: added empty value to pre-shared key size. --- src/components/PageComponents/Channel.tsx | 50 +++++++++++------------ src/components/UI/Generator.tsx | 1 + 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index 3655e5f8..e281b242 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -91,7 +91,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { psk: pass, positionEnabled: channel?.settings?.moduleSettings?.positionPrecision !== - undefined && + undefined && channel?.settings?.moduleSettings?.positionPrecision > 0, preciseLocation: channel?.settings?.moduleSettings?.positionPrecision === 32, @@ -124,8 +124,8 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { { type: "passwordGenerator", name: "settings.psk", - label: "pre-Shared Key", - description: "256, 128, or 8 bit PSKs allowed", + label: "Pre-Shared Key", + description: "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", validationText: validationText, devicePSKBitCount: bitCount ?? 0, inputChange: inputChangeEvent, @@ -177,29 +177,29 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { enumValue: config.display?.units === 0 ? { - "Within 23 km": 10, - "Within 12 km": 11, - "Within 5.8 km": 12, - "Within 2.9 km": 13, - "Within 1.5 km": 14, - "Within 700 m": 15, - "Within 350 m": 16, - "Within 200 m": 17, - "Within 90 m": 18, - "Within 50 m": 19, - } + "Within 23 km": 10, + "Within 12 km": 11, + "Within 5.8 km": 12, + "Within 2.9 km": 13, + "Within 1.5 km": 14, + "Within 700 m": 15, + "Within 350 m": 16, + "Within 200 m": 17, + "Within 90 m": 18, + "Within 50 m": 19, + } : { - "Within 15 miles": 10, - "Within 7.3 miles": 11, - "Within 3.6 miles": 12, - "Within 1.8 miles": 13, - "Within 0.9 miles": 14, - "Within 0.5 miles": 15, - "Within 0.2 miles": 16, - "Within 600 feet": 17, - "Within 300 feet": 18, - "Within 150 feet": 19, - }, + "Within 15 miles": 10, + "Within 7.3 miles": 11, + "Within 3.6 miles": 12, + "Within 1.8 miles": 13, + "Within 0.9 miles": 14, + "Within 0.5 miles": 15, + "Within 0.2 miles": 16, + "Within 600 feet": 17, + "Within 300 feet": 18, + "Within 150 feet": 19, + }, }, }, ], diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index cb8fea26..5e29ef49 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -40,6 +40,7 @@ const Generator = React.forwardRef( { text: "256 bit", value: "32", key: "bit256" }, { text: "128 bit", value: "16", key: "bit128" }, { text: "8 bit", value: "1", key: "bit8" }, + { text: "Empty", value: "0", key: "empty" }, ], selectChange, inputChange, From cbabcd4782c3097ce1113008dca8eed4ebc34ce2 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 6 Jan 2025 16:00:13 -0500 Subject: [PATCH 153/181] feat: added delay to toast appearing to avoid conflicting with messages/node loading. --- src/core/hooks/useKeyBackupReminder.tsx | 62 +++++++++++++------------ 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/core/hooks/useKeyBackupReminder.tsx b/src/core/hooks/useKeyBackupReminder.tsx index 8ce9e1d8..9af1ec70 100644 --- a/src/core/hooks/useKeyBackupReminder.tsx +++ b/src/core/hooks/useKeyBackupReminder.tsx @@ -17,6 +17,8 @@ interface ReminderState { lastShown: string; } +const TOAST_DELAY = 10000; + export function useBackupReminder({ suppressDays = 365, message = "It's time to back up your key data. Would you like to do this now?", @@ -47,35 +49,37 @@ export function useBackupReminder({ useEffect(() => { if (!reminderState) { - const { dismiss: dimissToast } = toast({ - title: "Backup Reminder", - description: message, - action: ( -
- - -
- ), - }); + setTimeout(() => { + const { dismiss: dimissToast } = toast({ + title: "Backup Reminder", + description: message, + action: ( +
+ + +
+ ), + }); + }, TOAST_DELAY); } }, [reminderState]); From 74e33d09b1133cd7b4f2e4f96f2e4ee33c9d5780 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Fri, 3 Jan 2025 12:05:29 -0500 Subject: [PATCH 154/181] feat: Add pki backup dialog, refactor Channels pre-shared key to support regenerate dialog --- src/components/Dialog/DialogManager.tsx | 7 + src/components/Dialog/PKIBackupDialog.tsx | 104 +++++++ src/components/Form/FormPasswordGenerator.tsx | 17 +- src/components/PageComponents/Channel.tsx | 262 +++++++++--------- .../PageComponents/Config/Security.tsx | 29 +- src/components/UI/Button.tsx | 4 +- src/components/UI/Generator.tsx | 37 ++- src/core/stores/deviceStore.ts | 5 +- 8 files changed, 312 insertions(+), 153 deletions(-) create mode 100644 src/components/Dialog/PKIBackupDialog.tsx diff --git a/src/components/Dialog/DialogManager.tsx b/src/components/Dialog/DialogManager.tsx index 16e60120..762bd5a7 100644 --- a/src/components/Dialog/DialogManager.tsx +++ b/src/components/Dialog/DialogManager.tsx @@ -5,6 +5,7 @@ import { QRDialog } from "@components/Dialog/QRDialog.tsx"; import { RebootDialog } from "@components/Dialog/RebootDialog.tsx"; import { ShutdownDialog } from "@components/Dialog/ShutdownDialog.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; +import { PkiBackupDialog } from "./PKIBackupDialog"; export const DialogManager = (): JSX.Element => { const { channels, config, dialog, setDialogOpen } = useDevice(); @@ -49,6 +50,12 @@ export const DialogManager = (): JSX.Element => { setDialogOpen("nodeRemoval", open); }} /> + { + setDialogOpen("pkiBackup", open); + }} + /> ); }; diff --git a/src/components/Dialog/PKIBackupDialog.tsx b/src/components/Dialog/PKIBackupDialog.tsx new file mode 100644 index 00000000..3737236a --- /dev/null +++ b/src/components/Dialog/PKIBackupDialog.tsx @@ -0,0 +1,104 @@ +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@components/UI/Dialog.tsx"; +import { Button } from "@components/UI/Button"; +import { DownloadIcon, PrinterIcon } from "lucide-react"; +import React from "react"; +import { useDevice } from "@app/core/stores/deviceStore"; +import { fromByteArray } from "base64-js"; + +export interface PkiBackupDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export const PkiBackupDialog = ({ + open, + onOpenChange, +}: PkiBackupDialogProps) => { + const { config } = useDevice(); + const privateKeyData = config.security?.privateKey + + // If the private data doesn't exist return null + if (!privateKeyData) { + return null + } + + const getPrivateKey = React.useMemo(() => fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), [config.security?.privateKey]); + + const renderPrintWindow = React.useCallback(() => { + const printWindow = window.open("", "_blank"); + if (printWindow) { + printWindow.document.write(` + + + Your Private Key + + + +

Your Private Key

+

${getPrivateKey}

+ + + `); + printWindow.document.close(); + printWindow.print(); + } + }, [getPrivateKey]); + + const createDownloadKeyFile = React.useCallback(() => { + const blob = new Blob([getPrivateKey], { type: "text/plain" }); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = "meshtastic_private_key.txt"; + link.style.display = "none"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); + }, [getPrivateKey]); + + + return ( + + + + Backup Key + + Its important to backup your private key and store your backup securely! + + + If you lose your private key, you will need to reset your device. + + + + + + + + + ); +}; diff --git a/src/components/Form/FormPasswordGenerator.tsx b/src/components/Form/FormPasswordGenerator.tsx index 09e97ff5..784086fb 100644 --- a/src/components/Form/FormPasswordGenerator.tsx +++ b/src/components/Form/FormPasswordGenerator.tsx @@ -7,6 +7,7 @@ import { Eye, EyeOff } from "lucide-react"; import type { ChangeEventHandler, MouseEventHandler } from "react"; import { useState } from "react"; import { Controller, type FieldValues } from "react-hook-form"; +import type { ButtonVariant } from "@components/UI/Button"; export interface PasswordGeneratorProps extends BaseFormBuilderProps { type: "passwordGenerator"; @@ -15,7 +16,12 @@ export interface PasswordGeneratorProps extends BaseFormBuilderProps { devicePSKBitCount: number; inputChange: ChangeEventHandler; selectChange: (event: string) => void; - buttonClick: MouseEventHandler; + actionButtons: { + text: string; + onClick: React.MouseEventHandler; + variant: ButtonVariant; + className?: string; + }[]; } export function PasswordGenerator({ @@ -38,19 +44,18 @@ export function PasswordGenerator({ action={ field.hide ? { - icon: passwordShown ? EyeOff : Eye, - onClick: togglePasswordVisiblity, - } + icon: passwordShown ? EyeOff : Eye, + onClick: togglePasswordVisiblity, + } : undefined } devicePSKBitCount={field.devicePSKBitCount} bits={field.bits} inputChange={field.inputChange} selectChange={field.selectChange} - buttonClick={field.buttonClick} value={value} variant={field.validationText ? "invalid" : "default"} - buttonText="Generate" + actionButtons={field.actionButtons} {...field.properties} {...rest} disabled={disabled} diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index e281b242..ef316c91 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -6,6 +6,7 @@ import { Protobuf } from "@meshtastic/js"; import { fromByteArray, toByteArray } from "base64-js"; import cryptoRandomString from "crypto-random-string"; import { useState } from "react"; +import { PkiRegenerateDialog } from "../Dialog/PkiRegenerateDialog"; export interface SettingsPanelProps { channel: Protobuf.Channel.Channel; @@ -22,6 +23,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { channel?.settings?.psk.length ?? 16, ); const [validationText, setValidationText] = useState(); + const [preSharedDialogOpen, setPreSharedDialogOpen] = useState(false); const onSubmit = (data: ChannelValidation) => { const channel = new Protobuf.Channel.Channel({ @@ -46,7 +48,7 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }); }; - const clickEvent = () => { + const preSharedKeyRegenerate = () => { setPass( btoa( cryptoRandomString({ @@ -56,6 +58,11 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { ), ); setValidationText(undefined); + setPreSharedDialogOpen(false); + }; + + const preSharedClickEvent = () => { + setPreSharedDialogOpen(true); }; const validatePass = (input: string, count: number) => { @@ -79,132 +86,139 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { }; return ( - - onSubmit={onSubmit} - submitType="onSubmit" - hasSubmitButton={true} - defaultValues={{ - ...channel, - ...{ - settings: { - ...channel?.settings, - psk: pass, - positionEnabled: - channel?.settings?.moduleSettings?.positionPrecision !== - undefined && - channel?.settings?.moduleSettings?.positionPrecision > 0, - preciseLocation: - channel?.settings?.moduleSettings?.positionPrecision === 32, - positionPrecision: - channel?.settings?.moduleSettings?.positionPrecision === undefined - ? 10 - : channel?.settings?.moduleSettings?.positionPrecision, + <> + + onSubmit={onSubmit} + submitType="onSubmit" + hasSubmitButton={true} + defaultValues={{ + ...channel, + ...{ + settings: { + ...channel?.settings, + psk: pass, + positionEnabled: + channel?.settings?.moduleSettings?.positionPrecision !== + undefined && + channel?.settings?.moduleSettings?.positionPrecision > 0, + preciseLocation: + channel?.settings?.moduleSettings?.positionPrecision === 32, + positionPrecision: + channel?.settings?.moduleSettings?.positionPrecision === undefined + ? 10 + : channel?.settings?.moduleSettings?.positionPrecision, + }, }, - }, - }} - fieldGroups={[ - { - label: "Channel Settings", - description: "Crypto, MQTT & misc settings", - fields: [ - { - type: "select", - name: "role", - label: "Role", - disabled: channel.index === 0, - description: - "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", - properties: { - enumValue: - channel.index === 0 - ? { PRIMARY: 1 } - : { DISABLED: 0, SECONDARY: 2 }, + }} + fieldGroups={[ + { + label: "Channel Settings", + description: "Crypto, MQTT & misc settings", + fields: [ + { + type: "select", + name: "role", + label: "Role", + disabled: channel.index === 0, + description: + "Device telemetry is sent over PRIMARY. Only one PRIMARY allowed", + properties: { + enumValue: + channel.index === 0 + ? { PRIMARY: 1 } + : { DISABLED: 0, SECONDARY: 2 }, + }, }, - }, - { - type: "passwordGenerator", - name: "settings.psk", - label: "Pre-Shared Key", - description: "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", - validationText: validationText, - devicePSKBitCount: bitCount ?? 0, - inputChange: inputChangeEvent, - selectChange: selectChangeEvent, - buttonClick: clickEvent, - hide: true, - properties: { - value: pass, + { + type: "passwordGenerator", + name: "settings.psk", + label: "Pre-Shared Key", + description: "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + validationText: validationText, + devicePSKBitCount: bitCount ?? 0, + inputChange: inputChangeEvent, + selectChange: selectChangeEvent, + actionButtons: [{ text: 'Generate', variant: 'success', onClick: preSharedClickEvent }], + hide: true, + properties: { + value: pass, + }, }, - }, - { - type: "text", - name: "settings.name", - label: "Name", - description: - "A unique name for the channel <12 bytes, leave blank for default", - }, - { - type: "toggle", - name: "settings.uplinkEnabled", - label: "Uplink Enabled", - description: "Send messages from the local mesh to MQTT", - }, - { - type: "toggle", - name: "settings.downlinkEnabled", - label: "Downlink Enabled", - description: "Send messages from MQTT to the local mesh", - }, - { - type: "toggle", - name: "settings.positionEnabled", - label: "Allow Position Requests", - description: "Send position to channel", - }, - { - type: "toggle", - name: "settings.preciseLocation", - label: "Precise Location", - description: "Send precise location to channel", - }, - { - type: "select", - name: "settings.positionPrecision", - label: "Approximate Location", - description: - "If not sharing precise location, position shared on channel will be accurate within this distance", - properties: { - enumValue: - config.display?.units === 0 - ? { - "Within 23 km": 10, - "Within 12 km": 11, - "Within 5.8 km": 12, - "Within 2.9 km": 13, - "Within 1.5 km": 14, - "Within 700 m": 15, - "Within 350 m": 16, - "Within 200 m": 17, - "Within 90 m": 18, - "Within 50 m": 19, - } - : { - "Within 15 miles": 10, - "Within 7.3 miles": 11, - "Within 3.6 miles": 12, - "Within 1.8 miles": 13, - "Within 0.9 miles": 14, - "Within 0.5 miles": 15, - "Within 0.2 miles": 16, - "Within 600 feet": 17, - "Within 300 feet": 18, - "Within 150 feet": 19, - }, + { + type: "text", + name: "settings.name", + label: "Name", + description: + "A unique name for the channel <12 bytes, leave blank for default", }, - }, - ], - }, - ]} - /> + { + type: "toggle", + name: "settings.uplinkEnabled", + label: "Uplink Enabled", + description: "Send messages from the local mesh to MQTT", + }, + { + type: "toggle", + name: "settings.downlinkEnabled", + label: "Downlink Enabled", + description: "Send messages from MQTT to the local mesh", + }, + { + type: "toggle", + name: "settings.positionEnabled", + label: "Allow Position Requests", + description: "Send position to channel", + }, + { + type: "toggle", + name: "settings.preciseLocation", + label: "Precise Location", + description: "Send precise location to channel", + }, + { + type: "select", + name: "settings.positionPrecision", + label: "Approximate Location", + description: + "If not sharing precise location, position shared on channel will be accurate within this distance", + properties: { + enumValue: + config.display?.units === 0 + ? { + "Within 23 km": 10, + "Within 12 km": 11, + "Within 5.8 km": 12, + "Within 2.9 km": 13, + "Within 1.5 km": 14, + "Within 700 m": 15, + "Within 350 m": 16, + "Within 200 m": 17, + "Within 90 m": 18, + "Within 50 m": 19, + } + : { + "Within 15 miles": 10, + "Within 7.3 miles": 11, + "Within 3.6 miles": 12, + "Within 1.8 miles": 13, + "Within 0.9 miles": 14, + "Within 0.5 miles": 15, + "Within 0.2 miles": 16, + "Within 600 feet": 17, + "Within 300 feet": 18, + "Within 150 feet": 19, + }, + }, + }, + ], + }, + ]} + /> + setPreSharedDialogOpen(false)} + onSubmit={() => preSharedKeyRegenerate()} + /> + ); }; diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index cf675751..d6e76cc9 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -12,7 +12,7 @@ import { Eye, EyeOff } from "lucide-react"; import { useState } from "react"; export const Security = (): JSX.Element => { - const { config, nodes, hardware, setWorkingConfig } = useDevice(); + const { config, nodes, hardware, setWorkingConfig, setDialogOpen } = useDevice(); const [privateKey, setPrivateKey] = useState( fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), @@ -31,7 +31,7 @@ export const Security = (): JSX.Element => { ); const [adminKeyValidationText, setAdminKeyValidationText] = useState(); - const [dialogOpen, setDialogOpen] = useState(false); + const [privateKeyDialogOpen, setPrivateKeyDialogOpen] = useState(false); const onSubmit = (data: SecurityValidation) => { if (privateKeyValidationText || adminKeyValidationText) return; @@ -71,9 +71,13 @@ export const Security = (): JSX.Element => { }; const privateKeyClickEvent = () => { - setDialogOpen(true); + setPrivateKeyDialogOpen(true); }; + const pkiBackupClickEvent = () => { + setDialogOpen("pkiBackup", true); + } + const pkiRegenerate = () => { const privateKey = getX25519PrivateKey(); const publicKey = getX25519PublicKey(privateKey); @@ -86,7 +90,7 @@ export const Security = (): JSX.Element => { setPrivateKeyValidationText, ); - setDialogOpen(false); + setPrivateKeyDialogOpen(false); }; const privateKeyInputChangeEvent = ( @@ -149,7 +153,18 @@ export const Security = (): JSX.Element => { inputChange: privateKeyInputChangeEvent, selectChange: privateKeySelectChangeEvent, hide: !privateKeyVisible, - buttonClick: privateKeyClickEvent, + actionButtons: [ + { + text: "Generate", + onClick: privateKeyClickEvent, + variant: "success", + }, + { + text: "Backup Key", + onClick: pkiBackupClickEvent, + variant: "subtle", + }, + ], properties: { value: privateKey, action: { @@ -228,8 +243,8 @@ export const Security = (): JSX.Element => { ]} /> setDialogOpen(false)} + open={privateKeyDialogOpen} + onOpenChange={() => setPrivateKeyDialogOpen(false)} onSubmit={() => pkiRegenerate()} /> diff --git a/src/components/UI/Button.tsx b/src/components/UI/Button.tsx index 39418551..e1b2d704 100644 --- a/src/components/UI/Button.tsx +++ b/src/components/UI/Button.tsx @@ -35,9 +35,11 @@ const buttonVariants = cva( }, ); +export type ButtonVariant = VariantProps["variant"]; + export interface ButtonProps extends React.ButtonHTMLAttributes, - VariantProps {} + VariantProps { } const Button = React.forwardRef( ({ className, variant, size, ...props }, ref) => { diff --git a/src/components/UI/Generator.tsx b/src/components/UI/Generator.tsx index 5e29ef49..b365d7c9 100644 --- a/src/components/UI/Generator.tsx +++ b/src/components/UI/Generator.tsx @@ -1,6 +1,6 @@ import * as React from "react"; -import { Button } from "@components/UI/Button.tsx"; +import { Button, type ButtonVariant } from "@components/UI/Button.tsx"; import { Input } from "@components/UI/Input.tsx"; import { Select, @@ -16,11 +16,15 @@ export interface GeneratorProps extends React.BaseHTMLAttributes { devicePSKBitCount?: number; value: string; variant: "default" | "invalid"; - buttonText?: string; + actionButtons: { + text: string; + onClick: React.MouseEventHandler; + variant: ButtonVariant; + className?: string; + }[]; bits?: { text: string; value: string; key: string }[]; selectChange: (event: string) => void; inputChange: (event: React.ChangeEvent) => void; - buttonClick: React.MouseEventHandler; action?: { icon: LucideIcon; onClick: () => void; @@ -35,7 +39,7 @@ const Generator = React.forwardRef( devicePSKBitCount, variant, value, - buttonText, + actionButtons, bits = [ { text: "256 bit", value: "32", key: "bit256" }, { text: "128 bit", value: "16", key: "bit128" }, @@ -44,7 +48,6 @@ const Generator = React.forwardRef( ], selectChange, inputChange, - buttonClick, action, disabled, ...props @@ -94,15 +97,21 @@ const Generator = React.forwardRef( ))} - +
+ {actionButtons?.map(({ text, onClick, variant, className }) => ( + + ))} +
); }, diff --git a/src/core/stores/deviceStore.ts b/src/core/stores/deviceStore.ts index a716a85b..bd407611 100644 --- a/src/core/stores/deviceStore.ts +++ b/src/core/stores/deviceStore.ts @@ -25,7 +25,8 @@ export type DialogVariant = | "shutdown" | "reboot" | "deviceName" - | "nodeRemoval"; + | "nodeRemoval" + | "pkiBackup"; export interface Device { id: number; @@ -60,6 +61,7 @@ export interface Device { reboot: boolean; deviceName: boolean; nodeRemoval: boolean; + pkiBackup: boolean; }; setStatus: (status: Types.DeviceStatusEnum) => void; @@ -142,6 +144,7 @@ export const useDeviceStore = create((set, get) => ({ reboot: false, deviceName: false, nodeRemoval: false, + pkiBackup: false, }, pendingSettingsChanges: false, messageDraft: "", From f3a3741216b32c87fb2f762f6b300f883d4f528b Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Fri, 3 Jan 2025 21:40:56 -0500 Subject: [PATCH 155/181] feat: Add key backup reminder. Refactor Toast component to handle dark mode better --- package.json | 2 + pnpm-lock.yaml | 214 +++++++++++++--------- src/App.tsx | 4 +- src/components/Dialog/DialogManager.tsx | 2 +- src/components/Dialog/PKIBackupDialog.tsx | 13 +- src/components/KeyBackupReminder.tsx | 21 +++ src/components/Toaster.tsx | 17 +- src/components/UI/Toast.tsx | 70 +++---- src/core/hooks/useCookie.ts | 35 ++++ src/core/hooks/useKeyBackupReminder.tsx | 85 +++++++++ 10 files changed, 326 insertions(+), 137 deletions(-) create mode 100644 src/components/KeyBackupReminder.tsx create mode 100644 src/core/hooks/useCookie.ts create mode 100644 src/core/hooks/useKeyBackupReminder.tsx diff --git a/package.json b/package.json index 05221d9b..84a49432 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "cmdk": "^1.0.0", "crypto-random-string": "^5.0.0", "immer": "^10.1.1", + "js-cookie": "^3.0.5", "lucide-react": "^0.363.0", "mapbox-gl": "^3.6.0", "maplibre-gl": "4.1.2", @@ -70,6 +71,7 @@ "@rsbuild/core": "^1.0.10", "@rsbuild/plugin-react": "^1.0.3", "@types/chrome": "^0.0.263", + "@types/js-cookie": "^3.0.6", "@types/node": "^20.14.9", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9edbfd5..79d6d5ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,6 +89,9 @@ importers: immer: specifier: ^10.1.1 version: 10.1.1 + js-cookie: + specifier: ^3.0.5 + version: 3.0.5 lucide-react: specifier: ^0.363.0 version: 0.363.0(react@18.3.1) @@ -127,7 +130,7 @@ importers: version: 3.0.6(react@18.3.1) vite-plugin-node-polyfills: specifier: ^0.22.0 - version: 0.22.0(rollup@4.24.0)(vite@5.3.6(@types/node@20.14.9)) + version: 0.22.0(rollup@4.29.1)(vite@5.3.6(@types/node@20.14.9)) zustand: specifier: 4.5.2 version: 4.5.2(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1) @@ -147,6 +150,9 @@ importers: '@types/chrome': specifier: ^0.0.263 version: 0.0.263 + '@types/js-cookie': + specifier: ^3.0.6 + version: 3.0.6 '@types/node': specifier: ^20.14.9 version: 20.14.9 @@ -173,7 +179,7 @@ importers: version: 8.4.38 rollup-plugin-visualizer: specifier: ^5.12.0 - version: 5.12.0(rollup@4.24.0) + version: 5.12.0(rollup@4.29.1) tailwindcss: specifier: ^3.4.4 version: 3.4.4 @@ -1165,83 +1171,98 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.24.0': - resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} + '@rollup/rollup-android-arm-eabi@4.29.1': + resolution: {integrity: sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.24.0': - resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} + '@rollup/rollup-android-arm64@4.29.1': + resolution: {integrity: sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.24.0': - resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} + '@rollup/rollup-darwin-arm64@4.29.1': + resolution: {integrity: sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.24.0': - resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} + '@rollup/rollup-darwin-x64@4.29.1': + resolution: {integrity: sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.24.0': - resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} + '@rollup/rollup-freebsd-arm64@4.29.1': + resolution: {integrity: sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.29.1': + resolution: {integrity: sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.29.1': + resolution: {integrity: sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.24.0': - resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} + '@rollup/rollup-linux-arm-musleabihf@4.29.1': + resolution: {integrity: sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.24.0': - resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} + '@rollup/rollup-linux-arm64-gnu@4.29.1': + resolution: {integrity: sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.24.0': - resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} + '@rollup/rollup-linux-arm64-musl@4.29.1': + resolution: {integrity: sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': - resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} + '@rollup/rollup-linux-loongarch64-gnu@4.29.1': + resolution: {integrity: sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.29.1': + resolution: {integrity: sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.24.0': - resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} + '@rollup/rollup-linux-riscv64-gnu@4.29.1': + resolution: {integrity: sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.24.0': - resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} + '@rollup/rollup-linux-s390x-gnu@4.29.1': + resolution: {integrity: sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.24.0': - resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} + '@rollup/rollup-linux-x64-gnu@4.29.1': + resolution: {integrity: sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.24.0': - resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} + '@rollup/rollup-linux-x64-musl@4.29.1': + resolution: {integrity: sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.24.0': - resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} + '@rollup/rollup-win32-arm64-msvc@4.29.1': + resolution: {integrity: sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.24.0': - resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} + '@rollup/rollup-win32-ia32-msvc@4.29.1': + resolution: {integrity: sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.24.0': - resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} + '@rollup/rollup-win32-x64-msvc@4.29.1': + resolution: {integrity: sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==} cpu: [x64] os: [win32] @@ -1690,6 +1711,9 @@ packages: '@types/har-format@1.2.15': resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==} + '@types/js-cookie@3.0.6': + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + '@types/mapbox-gl@3.1.0': resolution: {integrity: sha512-hI6cQDjw1bkJw7MC/eHMqq5TWUamLwsujnUUeiIX2KDRjxRNSYMjnHz07+LATz9I9XIsKumOtUz4gRYnZOJ/FA==} @@ -1864,8 +1888,8 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - caniuse-lite@1.0.30001638: - resolution: {integrity: sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ==} + caniuse-lite@1.0.30001690: + resolution: {integrity: sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==} cheap-ruler@4.0.0: resolution: {integrity: sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==} @@ -2417,6 +2441,10 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + js-sha3@0.8.0: resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} @@ -2923,8 +2951,8 @@ packages: rollup: optional: true - rollup@4.24.0: - resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} + rollup@4.29.1: + resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -4258,68 +4286,77 @@ snapshots: '@radix-ui/rect@1.1.0': {} - '@rollup/plugin-inject@5.0.5(rollup@4.24.0)': + '@rollup/plugin-inject@5.0.5(rollup@4.29.1)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.24.0) + '@rollup/pluginutils': 5.1.0(rollup@4.29.1) estree-walker: 2.0.2 magic-string: 0.30.11 optionalDependencies: - rollup: 4.24.0 + rollup: 4.29.1 - '@rollup/pluginutils@5.1.0(rollup@4.24.0)': + '@rollup/pluginutils@5.1.0(rollup@4.29.1)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.24.0 + rollup: 4.29.1 - '@rollup/rollup-android-arm-eabi@4.24.0': + '@rollup/rollup-android-arm-eabi@4.29.1': optional: true - '@rollup/rollup-android-arm64@4.24.0': + '@rollup/rollup-android-arm64@4.29.1': optional: true - '@rollup/rollup-darwin-arm64@4.24.0': + '@rollup/rollup-darwin-arm64@4.29.1': optional: true - '@rollup/rollup-darwin-x64@4.24.0': + '@rollup/rollup-darwin-x64@4.29.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + '@rollup/rollup-freebsd-arm64@4.29.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.24.0': + '@rollup/rollup-freebsd-x64@4.29.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.24.0': + '@rollup/rollup-linux-arm-gnueabihf@4.29.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.24.0': + '@rollup/rollup-linux-arm-musleabihf@4.29.1': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + '@rollup/rollup-linux-arm64-gnu@4.29.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.24.0': + '@rollup/rollup-linux-arm64-musl@4.29.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.24.0': + '@rollup/rollup-linux-loongarch64-gnu@4.29.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.24.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.29.1': optional: true - '@rollup/rollup-linux-x64-musl@4.24.0': + '@rollup/rollup-linux-riscv64-gnu@4.29.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.24.0': + '@rollup/rollup-linux-s390x-gnu@4.29.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.24.0': + '@rollup/rollup-linux-x64-gnu@4.29.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.24.0': + '@rollup/rollup-linux-x64-musl@4.29.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.29.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.29.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.29.1': optional: true '@rsbuild/core@1.0.10': @@ -4381,7 +4418,7 @@ snapshots: '@module-federation/runtime-tools': 0.5.1 '@rspack/binding': 1.0.8 '@rspack/lite-tapable': 1.0.1 - caniuse-lite: 1.0.30001638 + caniuse-lite: 1.0.30001690 optionalDependencies: '@swc/helpers': 0.5.13 @@ -5255,6 +5292,8 @@ snapshots: '@types/har-format@1.2.15': {} + '@types/js-cookie@3.0.6': {} + '@types/mapbox-gl@3.1.0': dependencies: '@types/geojson': 7946.0.14 @@ -5343,7 +5382,7 @@ snapshots: autoprefixer@10.4.19(postcss@8.4.38): dependencies: browserslist: 4.23.1 - caniuse-lite: 1.0.30001638 + caniuse-lite: 1.0.30001690 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 @@ -5424,7 +5463,7 @@ snapshots: browserslist@4.23.1: dependencies: - caniuse-lite: 1.0.30001638 + caniuse-lite: 1.0.30001690 electron-to-chromium: 1.4.812 node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.1) @@ -5459,7 +5498,7 @@ snapshots: camelcase-css@2.0.1: {} - caniuse-lite@1.0.30001638: {} + caniuse-lite@1.0.30001690: {} cheap-ruler@4.0.0: {} @@ -6075,6 +6114,8 @@ snapshots: jiti@1.21.6: {} + js-cookie@3.0.5: {} + js-sha3@0.8.0: {} js-tokens@4.0.0: {} @@ -6620,35 +6661,38 @@ snapshots: robust-predicates@3.0.2: {} - rollup-plugin-visualizer@5.12.0(rollup@4.24.0): + rollup-plugin-visualizer@5.12.0(rollup@4.29.1): dependencies: open: 8.4.2 picomatch: 2.3.1 source-map: 0.7.4 yargs: 17.7.2 optionalDependencies: - rollup: 4.24.0 + rollup: 4.29.1 - rollup@4.24.0: + rollup@4.29.1: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.24.0 - '@rollup/rollup-android-arm64': 4.24.0 - '@rollup/rollup-darwin-arm64': 4.24.0 - '@rollup/rollup-darwin-x64': 4.24.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 - '@rollup/rollup-linux-arm-musleabihf': 4.24.0 - '@rollup/rollup-linux-arm64-gnu': 4.24.0 - '@rollup/rollup-linux-arm64-musl': 4.24.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 - '@rollup/rollup-linux-riscv64-gnu': 4.24.0 - '@rollup/rollup-linux-s390x-gnu': 4.24.0 - '@rollup/rollup-linux-x64-gnu': 4.24.0 - '@rollup/rollup-linux-x64-musl': 4.24.0 - '@rollup/rollup-win32-arm64-msvc': 4.24.0 - '@rollup/rollup-win32-ia32-msvc': 4.24.0 - '@rollup/rollup-win32-x64-msvc': 4.24.0 + '@rollup/rollup-android-arm-eabi': 4.29.1 + '@rollup/rollup-android-arm64': 4.29.1 + '@rollup/rollup-darwin-arm64': 4.29.1 + '@rollup/rollup-darwin-x64': 4.29.1 + '@rollup/rollup-freebsd-arm64': 4.29.1 + '@rollup/rollup-freebsd-x64': 4.29.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.29.1 + '@rollup/rollup-linux-arm-musleabihf': 4.29.1 + '@rollup/rollup-linux-arm64-gnu': 4.29.1 + '@rollup/rollup-linux-arm64-musl': 4.29.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.29.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.29.1 + '@rollup/rollup-linux-riscv64-gnu': 4.29.1 + '@rollup/rollup-linux-s390x-gnu': 4.29.1 + '@rollup/rollup-linux-x64-gnu': 4.29.1 + '@rollup/rollup-linux-x64-musl': 4.29.1 + '@rollup/rollup-win32-arm64-msvc': 4.29.1 + '@rollup/rollup-win32-ia32-msvc': 4.29.1 + '@rollup/rollup-win32-x64-msvc': 4.29.1 fsevents: 2.3.3 run-parallel@1.2.0: @@ -6986,9 +7030,9 @@ snapshots: validator@13.12.0: {} - vite-plugin-node-polyfills@0.22.0(rollup@4.24.0)(vite@5.3.6(@types/node@20.14.9)): + vite-plugin-node-polyfills@0.22.0(rollup@4.29.1)(vite@5.3.6(@types/node@20.14.9)): dependencies: - '@rollup/plugin-inject': 5.0.5(rollup@4.24.0) + '@rollup/plugin-inject': 5.0.5(rollup@4.29.1) node-stdlib-browser: 1.2.0 vite: 5.3.6(@types/node@20.14.9) transitivePeerDependencies: @@ -6998,7 +7042,7 @@ snapshots: dependencies: esbuild: 0.21.5 postcss: 8.4.49 - rollup: 4.24.0 + rollup: 4.29.1 optionalDependencies: '@types/node': 20.14.9 fsevents: 2.3.3 diff --git a/src/App.tsx b/src/App.tsx index c936bc9c..8c15dc97 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,7 +2,7 @@ import { DeviceWrapper } from "@app/DeviceWrapper.tsx"; import { PageRouter } from "@app/PageRouter.tsx"; import { CommandPalette } from "@components/CommandPalette.tsx"; import { DeviceSelector } from "@components/DeviceSelector.tsx"; -import { DialogManager } from "@components/Dialog/DialogManager.tsx"; +import { DialogManager } from "@components/Dialog/DialogManager"; import { NewDeviceDialog } from "@components/Dialog/NewDeviceDialog.tsx"; import { Toaster } from "@components/Toaster.tsx"; import Footer from "@components/UI/Footer.tsx"; @@ -11,6 +11,7 @@ import { useAppStore } from "@core/stores/appStore.ts"; import { useDeviceStore } from "@core/stores/deviceStore.ts"; import { Dashboard } from "@pages/Dashboard/index.tsx"; import { MapProvider } from "react-map-gl"; +import { KeyBackupReminder } from "@components/KeyBackupReminder"; export const App = (): JSX.Element => { const { getDevice } = useDeviceStore(); @@ -37,6 +38,7 @@ export const App = (): JSX.Element => { {device ? (
+
diff --git a/src/components/Dialog/DialogManager.tsx b/src/components/Dialog/DialogManager.tsx index 762bd5a7..afebdf5d 100644 --- a/src/components/Dialog/DialogManager.tsx +++ b/src/components/Dialog/DialogManager.tsx @@ -5,7 +5,7 @@ import { QRDialog } from "@components/Dialog/QRDialog.tsx"; import { RebootDialog } from "@components/Dialog/RebootDialog.tsx"; import { ShutdownDialog } from "@components/Dialog/ShutdownDialog.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; -import { PkiBackupDialog } from "./PKIBackupDialog"; +import { PkiBackupDialog } from "@components/Dialog/PKIBackupDialog"; export const DialogManager = (): JSX.Element => { const { channels, config, dialog, setDialogOpen } = useDevice(); diff --git a/src/components/Dialog/PKIBackupDialog.tsx b/src/components/Dialog/PKIBackupDialog.tsx index 3737236a..4b482bf7 100644 --- a/src/components/Dialog/PKIBackupDialog.tsx +++ b/src/components/Dialog/PKIBackupDialog.tsx @@ -21,7 +21,7 @@ export const PkiBackupDialog = ({ open, onOpenChange, }: PkiBackupDialogProps) => { - const { config } = useDevice(); + const { config, setDialogOpen } = useDevice(); const privateKeyData = config.security?.privateKey // If the private data doesn't exist return null @@ -31,6 +31,10 @@ export const PkiBackupDialog = ({ const getPrivateKey = React.useMemo(() => fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), [config.security?.privateKey]); + const closeDialog = React.useCallback(() => { + setDialogOpen("pkiBackup", false) + }, [setDialogOpen]) + const renderPrintWindow = React.useCallback(() => { const printWindow = window.open("", "_blank"); if (printWindow) { @@ -52,8 +56,10 @@ export const PkiBackupDialog = ({ `); printWindow.document.close(); printWindow.print(); + closeDialog() + } - }, [getPrivateKey]); + }, [getPrivateKey, closeDialog]); const createDownloadKeyFile = React.useCallback(() => { const blob = new Blob([getPrivateKey], { type: "text/plain" }); @@ -65,8 +71,9 @@ export const PkiBackupDialog = ({ document.body.appendChild(link); link.click(); document.body.removeChild(link); + closeDialog() URL.revokeObjectURL(url); - }, [getPrivateKey]); + }, [getPrivateKey, closeDialog]); return ( diff --git a/src/components/KeyBackupReminder.tsx b/src/components/KeyBackupReminder.tsx new file mode 100644 index 00000000..45819bd7 --- /dev/null +++ b/src/components/KeyBackupReminder.tsx @@ -0,0 +1,21 @@ +import { useBackupReminder } from "@app/core/hooks/useKeyBackupReminder"; +import { useDevice } from "@app/core/stores/deviceStore"; + +export const KeyBackupReminder = (): JSX.Element => { + const { setDialogOpen } = useDevice(); + + useBackupReminder({ + suppressDays: 7, + message: "We recommend backing up your key data regularly. Would you like to back up now?", + onAccept: () => setDialogOpen("pkiBackup", true), + cookieOptions: { + secure: true, + sameSite: 'strict' + } + }); + + return ( + <> + + ); +}; diff --git a/src/components/Toaster.tsx b/src/components/Toaster.tsx index cfe13a9d..cf322758 100644 --- a/src/components/Toaster.tsx +++ b/src/components/Toaster.tsx @@ -1,5 +1,3 @@ -import { useToast } from "@core/hooks/useToast.ts"; - import { Toast, ToastClose, @@ -7,7 +5,8 @@ import { ToastProvider, ToastTitle, ToastViewport, -} from "@components/UI/Toast.tsx"; +} from "@components/UI/Toast"; +import { useToast } from "@core/hooks/useToast"; export function Toaster() { const { toasts } = useToast(); @@ -15,16 +14,10 @@ export function Toaster() { return ( {toasts.map(({ id, title, description, action, ...props }) => ( - +
- {title && ( - {title} - )} - {description && ( - - {description} - - )} + {title && {title}} + {description && {description}}
{action} diff --git a/src/components/UI/Toast.tsx b/src/components/UI/Toast.tsx index ca8dfc90..d40b294a 100644 --- a/src/components/UI/Toast.tsx +++ b/src/components/UI/Toast.tsx @@ -1,11 +1,11 @@ -import * as ToastPrimitives from "@radix-ui/react-toast"; -import { type VariantProps, cva } from "class-variance-authority"; -import { X } from "lucide-react"; -import * as React from "react"; +import * as React from "react" +import * as ToastPrimitives from "@radix-ui/react-toast" +import { cva, type VariantProps } from "class-variance-authority" +import { X } from 'lucide-react' -import { cn } from "@core/utils/cn.ts"; +import { cn } from "@core/utils/cn" -const ToastProvider = ToastPrimitives.Provider; +const ToastProvider = ToastPrimitives.Provider const ToastViewport = React.forwardRef< React.ElementRef, @@ -14,35 +14,34 @@ const ToastViewport = React.forwardRef< -)); -ToastViewport.displayName = ToastPrimitives.Viewport.displayName; +)) +ToastViewport.displayName = ToastPrimitives.Viewport.displayName const toastVariants = cva( - "data-[swipe=move]:transition-none grow-1 group relative pointer-events-auto flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full mt-4 data-[state=closed]:slide-out-to-right-full dark:border-slate-700 last:mt-0 sm:last:mt-4", + "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", { variants: { variant: { - default: - "bg-white border-slate-200 dark:bg-slate-800 dark:border-slate-700", + default: "border bg-background text-foreground dark:bg-slate-700 dark:border-slate-600 dark:text-slate-50", destructive: - "group destructive bg-red-600 text-white border-red-600 dark:border-red-600", + "group destructive bg-red-600 text-white dark:border-red-900 dark:bg-red-900 dark:text-red-50" }, }, defaultVariants: { variant: "default", }, - }, -); + } +) const Toast = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef & - VariantProps + VariantProps >(({ className, variant, ...props }, ref) => { return ( - ); -}); -Toast.displayName = ToastPrimitives.Root.displayName; + ) +}) +Toast.displayName = ToastPrimitives.Root.displayName const ToastAction = React.forwardRef< React.ElementRef, @@ -61,13 +60,13 @@ const ToastAction = React.forwardRef< -)); -ToastAction.displayName = ToastPrimitives.Action.displayName; +)) +ToastAction.displayName = ToastPrimitives.Action.displayName const ToastClose = React.forwardRef< React.ElementRef, @@ -76,16 +75,16 @@ const ToastClose = React.forwardRef< -)); -ToastClose.displayName = ToastPrimitives.Close.displayName; +)) +ToastClose.displayName = ToastPrimitives.Close.displayName const ToastTitle = React.forwardRef< React.ElementRef, @@ -96,8 +95,8 @@ const ToastTitle = React.forwardRef< className={cn("text-sm font-semibold", className)} {...props} /> -)); -ToastTitle.displayName = ToastPrimitives.Title.displayName; +)) +ToastTitle.displayName = ToastPrimitives.Title.displayName const ToastDescription = React.forwardRef< React.ElementRef, @@ -108,12 +107,12 @@ const ToastDescription = React.forwardRef< className={cn("text-sm opacity-90", className)} {...props} /> -)); -ToastDescription.displayName = ToastPrimitives.Description.displayName; +)) +ToastDescription.displayName = ToastPrimitives.Description.displayName -type ToastProps = React.ComponentPropsWithoutRef; +type ToastProps = React.ComponentPropsWithoutRef -type ToastActionElement = React.ReactElement; +type ToastActionElement = React.ReactElement export { type ToastProps, @@ -125,4 +124,5 @@ export { ToastDescription, ToastClose, ToastAction, -}; +} + diff --git a/src/core/hooks/useCookie.ts b/src/core/hooks/useCookie.ts new file mode 100644 index 00000000..6a1eb311 --- /dev/null +++ b/src/core/hooks/useCookie.ts @@ -0,0 +1,35 @@ +import React from "react"; +import Cookies, { type CookieAttributes } from "js-cookie"; + +type Cookie = [ + T | undefined, + (value: T, options?: CookieAttributes) => void, + () => void, +]; + +const useCookie = ( + cookieName: string, + initialValue?: T, +): Cookie => { + const [cookieValue, setCookieValue] = React.useState(() => { + const cookie = Cookies.get(cookieName); + return cookie ? (JSON.parse(cookie) as T) : initialValue; + }); + + const setCookie = React.useCallback( + (value: T, options?: CookieAttributes) => { + Cookies.set(cookieName, JSON.stringify(value), options); + setCookieValue(value); + }, + [cookieName], + ); + + const removeCookie = React.useCallback(() => { + Cookies.remove(cookieName); + setCookieValue(undefined); + }, [cookieName]); + + return [cookieValue, setCookie, removeCookie]; +}; + +export default useCookie; diff --git a/src/core/hooks/useKeyBackupReminder.tsx b/src/core/hooks/useKeyBackupReminder.tsx new file mode 100644 index 00000000..8ce9e1d8 --- /dev/null +++ b/src/core/hooks/useKeyBackupReminder.tsx @@ -0,0 +1,85 @@ +import { useEffect, useCallback } from 'react'; +import { useToast } from './useToast'; +import useCookie from './useCookie'; +import type { CookieAttributes } from 'js-cookie'; +import { Button } from '@app/components/UI/Button'; + +interface UseBackupReminderOptions { + suppressDays?: number; + message?: string; + onAccept?: () => void | Promise; + cookieName?: string; + cookieOptions?: CookieAttributes; +} + +interface ReminderState { + suppressed: boolean; + lastShown: string; +} + +export function useBackupReminder({ + suppressDays = 365, + message = "It's time to back up your key data. Would you like to do this now?", + onAccept = () => { }, + cookieName = "backup_reminder_state", + cookieOptions = {}, +}: UseBackupReminderOptions = {}) { + const { toast } = useToast(); + + const [reminderState, setReminderState, resetReminderState] = useCookie(cookieName); + + const suppressReminder = useCallback(() => { + const expiryDate = new Date(); + expiryDate.setDate(expiryDate.getDate() + suppressDays); + + setReminderState( + { + suppressed: true, + lastShown: new Date().toISOString(), + }, + { + ...cookieOptions, + expires: expiryDate, + } + ); + + }, [setReminderState, suppressDays, cookieOptions]); + + useEffect(() => { + if (!reminderState) { + const { dismiss: dimissToast } = toast({ + title: "Backup Reminder", + description: message, + action: ( +
+ + +
+ ), + }); + } + }, [reminderState]); + + return { + resetReminder: resetReminderState + }; +} \ No newline at end of file From 0e78d0bd5061cc8d1fa6d6a4f25edf59770bcbe9 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Tue, 7 Jan 2025 15:09:00 -0500 Subject: [PATCH 156/181] feat: added delay to toast appearing to avoid conflicting with messages/node loading. --- src/core/hooks/useKeyBackupReminder.tsx | 62 +++++++++++++------------ 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/core/hooks/useKeyBackupReminder.tsx b/src/core/hooks/useKeyBackupReminder.tsx index 8ce9e1d8..9af1ec70 100644 --- a/src/core/hooks/useKeyBackupReminder.tsx +++ b/src/core/hooks/useKeyBackupReminder.tsx @@ -17,6 +17,8 @@ interface ReminderState { lastShown: string; } +const TOAST_DELAY = 10000; + export function useBackupReminder({ suppressDays = 365, message = "It's time to back up your key data. Would you like to do this now?", @@ -47,35 +49,37 @@ export function useBackupReminder({ useEffect(() => { if (!reminderState) { - const { dismiss: dimissToast } = toast({ - title: "Backup Reminder", - description: message, - action: ( -
- - -
- ), - }); + setTimeout(() => { + const { dismiss: dimissToast } = toast({ + title: "Backup Reminder", + description: message, + action: ( +
+ + +
+ ), + }); + }, TOAST_DELAY); } }, [reminderState]); From b50edb276207300358d323d88ceefafb74c007f4 Mon Sep 17 00:00:00 2001 From: Kyle Wistrand Date: Sat, 11 Jan 2025 20:31:33 -0800 Subject: [PATCH 157/181] fix: Node map detail dark mode --- src/components/PageComponents/Map/NodeDetail.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/PageComponents/Map/NodeDetail.tsx b/src/components/PageComponents/Map/NodeDetail.tsx index cc01b8db..d1cbd8a9 100644 --- a/src/components/PageComponents/Map/NodeDetail.tsx +++ b/src/components/PageComponents/Map/NodeDetail.tsx @@ -30,7 +30,7 @@ export const NodeDetail = ({ node }: NodeDetailProps): JSX.Element => { ].replaceAll("_", " "); return ( - <> +
@@ -166,6 +166,6 @@ export const NodeDetail = ({ node }: NodeDetailProps): JSX.Element => {
)} - +
); }; From c2cdc92ae9baed8650cd5ec8f84c32a885c19b4b Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 12 Jan 2025 18:56:22 +0100 Subject: [PATCH 158/181] feat: Add sidebar close button --- src/components/Sidebar.tsx | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 48c496e5..dba5b3fa 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -12,9 +12,12 @@ import { MapIcon, MessageSquareIcon, SettingsIcon, + SidebarCloseIcon, + SidebarOpenIcon, UsersIcon, ZapIcon, } from "lucide-react"; +import { useState } from "react"; export interface SidebarProps { children?: React.ReactNode; @@ -25,6 +28,7 @@ export const Sidebar = ({ children }: SidebarProps): JSX.Element => { const myNode = nodes.get(hardware.myNodeNum); const myMetadata = metadata.get(0); const { activePage, setActivePage, setDialogOpen } = useDevice(); + const [showSidebar, setShowSidebar] = useState(true); interface NavLink { name: string; @@ -60,7 +64,7 @@ export const Sidebar = ({ children }: SidebarProps): JSX.Element => { }, ]; - return ( + return showSidebar ? (
@@ -76,6 +80,12 @@ export const Sidebar = ({ children }: SidebarProps): JSX.Element => { > +
@@ -109,5 +119,14 @@ export const Sidebar = ({ children }: SidebarProps): JSX.Element => { {children}
+ ) : ( +
+ +
); }; From 2d041ab6d0c778306f4f2493c076361783939486 Mon Sep 17 00:00:00 2001 From: PhotoNomad0 Date: Mon, 13 Jan 2025 06:37:18 -0500 Subject: [PATCH 159/181] Added date to messages displayed --- src/components/PageComponents/Messages/Message.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/PageComponents/Messages/Message.tsx b/src/components/PageComponents/Messages/Message.tsx index d1d35784..22ed52b2 100644 --- a/src/components/PageComponents/Messages/Message.tsx +++ b/src/components/PageComponents/Messages/Message.tsx @@ -44,6 +44,9 @@ export const Message = ({ {sender?.user?.longName ?? "UNK"} + + {message.rxTime.toLocaleDateString()} + {message.rxTime.toLocaleTimeString(undefined, { hour: "2-digit", From 7884991ac6e1d36252dd2575c3abc69977113925 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Tue, 14 Jan 2025 21:51:06 -0500 Subject: [PATCH 160/181] Refactor based on code review. Improved typing of useCookie hook. Added duration/delay to control length of toast. --- src/components/Dialog/PKIBackupDialog.tsx | 85 +++++++---- src/components/KeyBackupReminder.tsx | 16 +- src/components/Toaster.tsx | 12 +- src/core/hooks/useCookie.ts | 55 ++++--- src/core/hooks/useKeyBackupReminder.tsx | 169 +++++++++++++--------- src/core/hooks/useToast.ts | 27 ++-- 6 files changed, 221 insertions(+), 143 deletions(-) diff --git a/src/components/Dialog/PKIBackupDialog.tsx b/src/components/Dialog/PKIBackupDialog.tsx index 4b482bf7..9b6c18d8 100644 --- a/src/components/Dialog/PKIBackupDialog.tsx +++ b/src/components/Dialog/PKIBackupDialog.tsx @@ -1,3 +1,5 @@ +import { useDevice } from "@app/core/stores/deviceStore"; +import { Button } from "@components/UI/Button"; import { Dialog, DialogContent, @@ -6,11 +8,9 @@ import { DialogHeader, DialogTitle, } from "@components/UI/Dialog.tsx"; -import { Button } from "@components/UI/Button"; +import { fromByteArray } from "base64-js"; import { DownloadIcon, PrinterIcon } from "lucide-react"; import React from "react"; -import { useDevice } from "@app/core/stores/deviceStore"; -import { fromByteArray } from "base64-js"; export interface PkiBackupDialogProps { open: boolean; @@ -22,26 +22,30 @@ export const PkiBackupDialog = ({ onOpenChange, }: PkiBackupDialogProps) => { const { config, setDialogOpen } = useDevice(); - const privateKeyData = config.security?.privateKey + const privateKey = config.security?.privateKey; + const publicKey = config.security?.publicKey; - // If the private data doesn't exist return null - if (!privateKeyData) { - return null - } - - const getPrivateKey = React.useMemo(() => fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), [config.security?.privateKey]); + const decodeKeyData = React.useCallback( + (key: Uint8Array) => { + if (!key) return ""; + return fromByteArray(key ?? new Uint8Array(0)); + }, + [], + ); const closeDialog = React.useCallback(() => { - setDialogOpen("pkiBackup", false) - }, [setDialogOpen]) + setDialogOpen("pkiBackup", false); + }, [setDialogOpen]); const renderPrintWindow = React.useCallback(() => { + if (!privateKey || !publicKey) return; + const printWindow = window.open("", "_blank"); if (printWindow) { printWindow.document.write(` - Your Private Key + === MESHTASTIC KEYS === -

Your Private Key

-

${getPrivateKey}

+

=== MESHTASTIC KEYS ===

+
+

Public Key:

+

${decodeKeyData(publicKey)}

+

Private Key:

+

${decodeKeyData(privateKey)}

+
+

=== END OF KEYS ===

`); printWindow.document.close(); printWindow.print(); - closeDialog() - + closeDialog(); } - }, [getPrivateKey, closeDialog]); + }, [decodeKeyData, privateKey, publicKey, closeDialog]); const createDownloadKeyFile = React.useCallback(() => { - const blob = new Blob([getPrivateKey], { type: "text/plain" }); + if (!privateKey || !publicKey) return; + + const decodedPrivateKey = decodeKeyData(privateKey); + const decodedPublicKey = decodeKeyData(publicKey); + + const formattedContent = [ + "=== MESHTASTIC KEYS ===\n\n", + "Private Key:\n", + decodedPrivateKey, + "\n\nPublic Key:\n", + decodedPublicKey, + "\n\n=== END OF KEYS ===", + ].join(""); + + const blob = new Blob([formattedContent], { type: "text/plain" }); const url = URL.createObjectURL(blob); + const link = document.createElement("a"); link.href = url; - link.download = "meshtastic_private_key.txt"; + link.download = "meshtastic_keys.txt"; link.style.display = "none"; document.body.appendChild(link); link.click(); document.body.removeChild(link); - closeDialog() + closeDialog(); URL.revokeObjectURL(url); - }, [getPrivateKey, closeDialog]); - + }, [decodeKeyData, privateKey, publicKey, closeDialog]); return ( - Backup Key + Backup Keys - Its important to backup your private key and store your backup securely! + Its important to backup your public and private keys and store your + backup securely! - If you lose your private key, you will need to reset your device. + + If you lose your keys, you will need to reset your device. + - diff --git a/src/components/KeyBackupReminder.tsx b/src/components/KeyBackupReminder.tsx index 45819bd7..7463d85f 100644 --- a/src/components/KeyBackupReminder.tsx +++ b/src/components/KeyBackupReminder.tsx @@ -5,17 +5,15 @@ export const KeyBackupReminder = (): JSX.Element => { const { setDialogOpen } = useDevice(); useBackupReminder({ - suppressDays: 7, - message: "We recommend backing up your key data regularly. Would you like to back up now?", + reminderInDays: 7, + message: + "We recommend backing up your key data regularly. Would you like to back up now?", onAccept: () => setDialogOpen("pkiBackup", true), + enabled: true, cookieOptions: { secure: true, - sameSite: 'strict' - } + sameSite: "strict", + }, }); - - return ( - <> - - ); + return <>; }; diff --git a/src/components/Toaster.tsx b/src/components/Toaster.tsx index cf322758..f5531bba 100644 --- a/src/components/Toaster.tsx +++ b/src/components/Toaster.tsx @@ -13,8 +13,14 @@ export function Toaster() { return ( - {toasts.map(({ id, title, description, action, ...props }) => ( - + {toasts.map(({ id, title, description, action, duration, ...props }) => ( +
{title && {title}} {description && {description}} @@ -26,4 +32,4 @@ export function Toaster() { ); -} +} \ No newline at end of file diff --git a/src/core/hooks/useCookie.ts b/src/core/hooks/useCookie.ts index 6a1eb311..df3d9d82 100644 --- a/src/core/hooks/useCookie.ts +++ b/src/core/hooks/useCookie.ts @@ -1,35 +1,52 @@ -import React from "react"; import Cookies, { type CookieAttributes } from "js-cookie"; +import { useCallback, useState } from "react"; -type Cookie = [ - T | undefined, - (value: T, options?: CookieAttributes) => void, - () => void, -]; +interface CookieHookResult { + value: T | undefined; + setCookie: (value: T, options?: CookieAttributes) => void; + removeCookie: () => void; +} -const useCookie = ( +function useCookie( cookieName: string, initialValue?: T, -): Cookie => { - const [cookieValue, setCookieValue] = React.useState(() => { - const cookie = Cookies.get(cookieName); - return cookie ? (JSON.parse(cookie) as T) : initialValue; +): CookieHookResult { + const [cookieValue, setCookieValue] = useState(() => { + try { + const cookie = Cookies.get(cookieName); + return cookie ? (JSON.parse(cookie) as T) : initialValue; + } catch (error) { + console.error(`Error parsing cookie ${cookieName}:`, error); + return initialValue; + } }); - const setCookie = React.useCallback( + const setCookie = useCallback( (value: T, options?: CookieAttributes) => { - Cookies.set(cookieName, JSON.stringify(value), options); - setCookieValue(value); + try { + Cookies.set(cookieName, JSON.stringify(value), options); + setCookieValue(value); + } catch (error) { + console.error(`Error setting cookie ${cookieName}:`, error); + } }, [cookieName], ); - const removeCookie = React.useCallback(() => { - Cookies.remove(cookieName); - setCookieValue(undefined); + const removeCookie = useCallback(() => { + try { + Cookies.remove(cookieName); + setCookieValue(undefined); + } catch (error) { + console.error(`Error removing cookie ${cookieName}:`, error); + } }, [cookieName]); - return [cookieValue, setCookie, removeCookie]; -}; + return { + value: cookieValue, + setCookie, + removeCookie, + }; +} export default useCookie; diff --git a/src/core/hooks/useKeyBackupReminder.tsx b/src/core/hooks/useKeyBackupReminder.tsx index 9af1ec70..ee65d161 100644 --- a/src/core/hooks/useKeyBackupReminder.tsx +++ b/src/core/hooks/useKeyBackupReminder.tsx @@ -1,14 +1,14 @@ -import { useEffect, useCallback } from 'react'; -import { useToast } from './useToast'; -import useCookie from './useCookie'; -import type { CookieAttributes } from 'js-cookie'; -import { Button } from '@app/components/UI/Button'; +import { Button } from "@app/components/UI/Button"; +import type { CookieAttributes } from "js-cookie"; +import { useCallback, useEffect, useRef } from "react"; +import useCookie from "./useCookie"; +import { useToast } from "./useToast"; interface UseBackupReminderOptions { - suppressDays?: number; - message?: string; + reminderInDays?: number; + message: string; onAccept?: () => void | Promise; - cookieName?: string; + enabled: boolean; cookieOptions?: CookieAttributes; } @@ -17,73 +17,104 @@ interface ReminderState { lastShown: string; } -const TOAST_DELAY = 10000; +const TOAST_APPEAR_DELAY = 10_000 // 10 seconds; +const TOAST_DURATION = 30_000 // 30 seconds;: + +// remind user in 1 year to backup keys again, if they accept the reminder; +const ON_ACCEPT_REMINDER_DAYS = 365 + +function isReminderExpired(lastShown: string): boolean { + const lastShownDate = new Date(lastShown); + const now = new Date(); + const daysSinceLastShown = + (now.getTime() - lastShownDate.getTime()) / (1000 * 60 * 60 * 24); + return daysSinceLastShown >= 7; +} export function useBackupReminder({ - suppressDays = 365, - message = "It's time to back up your key data. Would you like to do this now?", + reminderInDays = 7, + enabled, + message, onAccept = () => { }, - cookieName = "backup_reminder_state", - cookieOptions = {}, -}: UseBackupReminderOptions = {}) { + cookieOptions, +}: UseBackupReminderOptions) { const { toast } = useToast(); + const toastShownRef = useRef(false); + const { value: reminderCookie, setCookie } = + useCookie("key_backup_reminder"); - const [reminderState, setReminderState, resetReminderState] = useCookie(cookieName); + const suppressReminder = useCallback( + (days: number) => { + const expiryDate = new Date(); + expiryDate.setDate(expiryDate.getDate() + days); - const suppressReminder = useCallback(() => { - const expiryDate = new Date(); - expiryDate.setDate(expiryDate.getDate() + suppressDays); - - setReminderState( - { - suppressed: true, - lastShown: new Date().toISOString(), - }, - { - ...cookieOptions, - expires: expiryDate, - } - ); - - }, [setReminderState, suppressDays, cookieOptions]); + setCookie( + { + suppressed: true, + lastShown: new Date().toISOString(), + }, + { ...cookieOptions, expires: expiryDate }, + ); + }, + [setCookie, cookieOptions], + ); useEffect(() => { - if (!reminderState) { - setTimeout(() => { - const { dismiss: dimissToast } = toast({ - title: "Backup Reminder", - description: message, - action: ( -
- - -
- ), - }); - }, TOAST_DELAY); - } - }, [reminderState]); + if (!enabled || toastShownRef.current) return; - return { - resetReminder: resetReminderState - }; -} \ No newline at end of file + const shouldShowReminder = + !reminderCookie?.suppressed || + isReminderExpired(reminderCookie.lastShown); + if (!shouldShowReminder) return; + + toastShownRef.current = true; + + const { dismiss } = toast( + { + title: "Backup Reminder", + duration: TOAST_DURATION, + delay: TOAST_APPEAR_DELAY, + description: message, + action: ( +
+ + +
+ ), + }, + ); + + return () => { + if (!toastShownRef.current) { + dismiss(); + } + }; + }, [ + enabled, + message, + onAccept, + reminderInDays, + suppressReminder, + toast, + reminderCookie, + ]); +} diff --git a/src/core/hooks/useToast.ts b/src/core/hooks/useToast.ts index f64cf45a..c913d223 100644 --- a/src/core/hooks/useToast.ts +++ b/src/core/hooks/useToast.ts @@ -10,6 +10,7 @@ type ToasterToast = ToastProps & { title?: ReactNode; description?: ReactNode; action?: ToastActionElement; + delay?: number; }; const actionTypes = { @@ -137,7 +138,7 @@ function dispatch(action: Action) { type Toast = Omit; -function toast({ ...props }: Toast) { +function toast({ delay = 0, ...props }: Toast) { const id = genId(); const update = (props: ToasterToast) => @@ -147,17 +148,19 @@ function toast({ ...props }: Toast) { }); const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }); - dispatch({ - type: "ADD_TOAST", - toast: { - ...props, - id, - open: true, - onOpenChange: (open) => { - if (!open) dismiss(); + setTimeout(() => { + dispatch({ + type: "ADD_TOAST", + toast: { + ...props, + id, + open: true, + onOpenChange: (open) => { + if (!open) dismiss(); + }, }, - }, - }); + }); + }, delay); return { id: id, @@ -190,4 +193,4 @@ function useToast() { }; } -export { toast, useToast }; +export { toast, useToast }; \ No newline at end of file From 225d6055d4c39cf258332058b6c4007854269695 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Wed, 15 Jan 2025 20:11:46 -0500 Subject: [PATCH 161/181] Improved error messaging based on feature missing from browser --- src/components/Dialog/NewDeviceDialog.tsx | 138 ++++++++++++------- src/components/UI/Typography/Link.tsx | 7 +- src/core/hooks/useBrowserFeatureDetection.ts | 49 ++++--- 3 files changed, 117 insertions(+), 77 deletions(-) diff --git a/src/components/Dialog/NewDeviceDialog.tsx b/src/components/Dialog/NewDeviceDialog.tsx index 92d4c75a..e03668d7 100644 --- a/src/components/Dialog/NewDeviceDialog.tsx +++ b/src/components/Dialog/NewDeviceDialog.tsx @@ -1,4 +1,7 @@ -import { useBrowserFeatureDetection } from "@app/core/hooks/useBrowserFeatureDetection"; +import { + type BrowserFeature, + useBrowserFeatureDetection, +} from "@app/core/hooks/useBrowserFeatureDetection"; import { BLE } from "@components/PageComponents/Connect/BLE.tsx"; import { HTTP } from "@components/PageComponents/Connect/HTTP.tsx"; import { Serial } from "@components/PageComponents/Connect/Serial.tsx"; @@ -8,14 +11,16 @@ import { DialogHeader, DialogTitle, } from "@components/UI/Dialog.tsx"; +import { AlertCircle, } from "lucide-react"; import { Tabs, TabsContent, TabsList, TabsTrigger, } from "@components/UI/Tabs.tsx"; -import { Link } from "@components/UI/Typography/Link.tsx"; import { Subtle } from "@components/UI/Typography/Subtle.tsx"; +import { Link } from "../UI/Typography/Link"; +import { Fragment } from "react/jsx-runtime"; export interface TabElementProps { closeDialog: () => void; @@ -29,19 +34,88 @@ export interface TabManifest { disabledLink?: string; } - - export interface NewDeviceProps { open: boolean; onOpenChange: (open: boolean) => void; } +interface FeatureErrorProps { + missingFeatures: BrowserFeature[]; +} + +const links: { [key: string]: string } = { + "Web Bluetooth": + "https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility", + "Web Serial": + "https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility", + "Secure Context": + "https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts", +}; + +const listFormatter = new Intl.ListFormat('en', { + style: 'long', + type: 'conjunction' +}); + +const ErrorMessage = ({ missingFeatures }: FeatureErrorProps) => { + if (missingFeatures.length === 0) return null; + + const browserFeatures = missingFeatures.filter(feature => feature !== "Secure Context"); + const needsSecureContext = missingFeatures.includes("Secure Context"); + + const formatFeatureList = (features: string[]) => { + const parts = listFormatter.formatToParts(features); + return parts.map((part) => { + if (part.type === 'element') { + return ( + + {part.value} + + ); + } + return {part.value}; + }); + }; + + return ( + +
+ +
+

+ {browserFeatures.length > 0 && ( + <> + This application requires {formatFeatureList(browserFeatures)}. + Please use a Chromium-based browser like Chrome or Edge. + + )} + {needsSecureContext && ( + <> + {browserFeatures.length > 0 && " Additionally, it"} + {browserFeatures.length === 0 && "This application"} requires a{" "} + + secure context + + . Please connect using HTTPS or localhost. + + )} +

+
+
+
+ ); +}; + export const NewDeviceDialog = ({ open, onOpenChange, }: NewDeviceProps): JSX.Element => { - const { hasRequiredFeatures, isSecureContext, missingFeatures } = useBrowserFeatureDetection(); - console.log(missingFeatures); + const { unsupported } = useBrowserFeatureDetection(); const tabs: TabManifest[] = [ { @@ -53,23 +127,21 @@ export const NewDeviceDialog = ({ { label: "Bluetooth", element: BLE, - disabled: missingFeatures.includes("Web Bluetooth"), - disabledMessage: - "Web Bluetooth is currently only supported by Chromium-based browsers", - disabledLink: - "https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility" + disabled: + unsupported.includes("Web Bluetooth") || + unsupported.includes("Secure Context"), + disabledMessage: "", }, { label: "Serial", element: Serial, - disabled: missingFeatures.includes("Web Serial"), - disabledMessage: - "Web Serial is currently only supported by Chromium based browsers", - disabledLink: "https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility", + disabled: + unsupported.includes("Web Serial") || + unsupported.includes("Secure Context"), + disabledMessage: "", }, ]; - return ( @@ -99,40 +171,8 @@ export const NewDeviceDialog = ({ )} ))} + - - {!isSecureContext && ( - <> - - Web Bluetooth and Web Serial require using a HTTPS connection or to localhost. - - - Read more:  - - Secure Contexts - - - - )} - - {!hasRequiredFeatures && ( - <> - - Web Bluetooth and Web Serial are currently only supported by - Chromium-based browsers. - - - Read more:  - - Web Bluetooth - -   - - Web Serial - - - - )} ); diff --git a/src/components/UI/Typography/Link.tsx b/src/components/UI/Typography/Link.tsx index af1a90ac..efcfbdf6 100644 --- a/src/components/UI/Typography/Link.tsx +++ b/src/components/UI/Typography/Link.tsx @@ -1,14 +1,17 @@ +import { cn } from "@app/core/utils/cn"; + export interface LinkProps { href: string; children: React.ReactNode; + className?: string; } -export const Link = ({ href, children }: LinkProps): JSX.Element => ( +export const Link = ({ href, children, className }: LinkProps): JSX.Element => (
{children} diff --git a/src/core/hooks/useBrowserFeatureDetection.ts b/src/core/hooks/useBrowserFeatureDetection.ts index df103b2c..83a90a7a 100644 --- a/src/core/hooks/useBrowserFeatureDetection.ts +++ b/src/core/hooks/useBrowserFeatureDetection.ts @@ -1,32 +1,29 @@ -type Feature = 'Web Bluetooth' | 'Web Serial'; -type FeatureKey = 'bluetooth' | 'serial'; +import { useMemo } from 'react'; -interface BrowserFeatureDetection { - hasRequiredFeatures: boolean; - missingFeatures: Feature[]; - isSecureContext: boolean; +export type BrowserFeature = 'Web Bluetooth' | 'Web Serial' | 'Secure Context'; + +interface BrowserSupport { + supported: BrowserFeature[]; + unsupported: BrowserFeature[]; } -const featureLabels: Record = { - bluetooth: 'Web Bluetooth', - serial: 'Web Serial' -}; +export function useBrowserFeatureDetection(): BrowserSupport { + const support = useMemo(() => { + const features: [BrowserFeature, boolean][] = [ + ['Web Bluetooth', !!navigator.bluetooth], + ['Web Serial', !!navigator.serial], + ['Secure Context', window.location.protocol === 'https:' || window.location.hostname === 'localhost'] + ]; -export function useBrowserFeatureDetection(): BrowserFeatureDetection { - const { bluetooth, serial } = navigator; - const isSecureContext = window.location.protocol === 'https:' || - window.location.hostname === 'localhost'; + return features.reduce( + (acc, [feature, isSupported]) => { + const list = isSupported ? acc.supported : acc.unsupported; + list.push(feature); + return acc; + }, + { supported: [], unsupported: [] } + ); + }, []); - const features = { - bluetooth, - serial - }; - - return { - hasRequiredFeatures: Object.values(features).every(Boolean), - missingFeatures: Object.entries(features) - .filter(([_, supported]) => !supported) - .map(([feature]) => featureLabels[feature as FeatureKey]), - isSecureContext - }; + return support; } \ No newline at end of file From 4e35cf326e54b3479ce2b6d42336a2c6ee2665f4 Mon Sep 17 00:00:00 2001 From: Anthony Hawk <4062673+tdhawk@users.noreply.github.com> Date: Sat, 18 Jan 2025 14:10:30 -0600 Subject: [PATCH 162/181] updated container port --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ec46a087..5f72c2fa 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,10 @@ The base image used is [Nginx 1.27](https://hub.docker.com/_/nginx) ```bash # With Docker -docker run -d -p 8080:80 --restart always --name Meshtastic-Web ghcr.io/meshtastic/web +docker run -d -p 8080:8080 --restart always --name Meshtastic-Web ghcr.io/meshtastic/web #With Podman -podman run -d -p 8080:80 --restart always --name Meshtastic-Web ghcr.io/meshtastic/web +podman run -d -p 8080:8080 --restart always --name Meshtastic-Web ghcr.io/meshtastic/web ``` ## Development & Building From be6acc5ef2d96031e2bbd1b2aa15259049c1d6cc Mon Sep 17 00:00:00 2001 From: Hunter275 Date: Sun, 19 Jan 2025 00:50:23 -0500 Subject: [PATCH 163/181] add right border --- src/components/Sidebar.tsx | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index dba5b3fa..d4ada2bd 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -80,17 +80,20 @@ export const Sidebar = ({ children }: SidebarProps): JSX.Element => { > -
- {myNode?.deviceMetrics?.batteryLevel ? myNode?.deviceMetrics?.batteryLevel > 100 ? "Charging" : myNode?.deviceMetrics?.batteryLevel + "%" : "UNK"} + + {myNode?.deviceMetrics?.batteryLevel + ? myNode?.deviceMetrics?.batteryLevel > 100 + ? "Charging" + : myNode?.deviceMetrics?.batteryLevel + "%" + : "UNK"} +
@@ -120,13 +123,10 @@ export const Sidebar = ({ children }: SidebarProps): JSX.Element => { {children}
) : ( -
- +
); }; From ebb32f0893eb7093bcd2655ebd88dc599e3dc31f Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sun, 19 Jan 2025 22:42:38 -0500 Subject: [PATCH 164/181] fix: changed position of error message, disabled buttons when error is showing --- src/components/Dialog/NewDeviceDialog.tsx | 26 ++++++------------- .../PageComponents/Connect/Serial.tsx | 11 ++++---- src/core/hooks/useBrowserFeatureDetection.ts | 4 +-- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/components/Dialog/NewDeviceDialog.tsx b/src/components/Dialog/NewDeviceDialog.tsx index e03668d7..e3330cbf 100644 --- a/src/components/Dialog/NewDeviceDialog.tsx +++ b/src/components/Dialog/NewDeviceDialog.tsx @@ -11,7 +11,7 @@ import { DialogHeader, DialogTitle, } from "@components/UI/Dialog.tsx"; -import { AlertCircle, } from "lucide-react"; +import { AlertCircle, InfoIcon, } from "lucide-react"; import { Tabs, TabsContent, @@ -29,9 +29,7 @@ export interface TabElementProps { export interface TabManifest { label: string; element: React.FC; - disabled: boolean; - disabledMessage: string; - disabledLink?: string; + isDisabled: boolean; } export interface NewDeviceProps { @@ -121,24 +119,21 @@ export const NewDeviceDialog = ({ { label: "HTTP", element: HTTP, - disabled: false, - disabledMessage: "Unsuported connection method", + isDisabled: false, }, { label: "Bluetooth", element: BLE, - disabled: + isDisabled: unsupported.includes("Web Bluetooth") || unsupported.includes("Secure Context"), - disabledMessage: "", }, { label: "Serial", element: Serial, - disabled: + isDisabled: unsupported.includes("Web Serial") || unsupported.includes("Secure Context"), - disabledMessage: "", }, ]; @@ -154,7 +149,6 @@ export const NewDeviceDialog = ({ {tab.label} @@ -162,16 +156,12 @@ export const NewDeviceDialog = ({ {tabs.map((tab) => ( - {tab.disabled ? ( -

- {tab.disabledMessage} -

- ) : ( +
+ {tab.isDisabled ? : null} onOpenChange(false)} /> - )} +
))} - diff --git a/src/components/PageComponents/Connect/Serial.tsx b/src/components/PageComponents/Connect/Serial.tsx index 38aab8fb..53c623cb 100644 --- a/src/components/PageComponents/Connect/Serial.tsx +++ b/src/components/PageComponents/Connect/Serial.tsx @@ -14,13 +14,13 @@ export const Serial = ({ closeDialog }: TabElementProps): JSX.Element => { const { setSelectedDevice } = useAppStore(); const updateSerialPortList = useCallback(async () => { - setSerialPorts(await navigator.serial.getPorts()); + setSerialPorts(await navigator?.serial.getPorts()); }, []); - navigator.serial.addEventListener("connect", () => { + navigator?.serial?.addEventListener("connect", () => { updateSerialPortList(); }); - navigator.serial.addEventListener("disconnect", () => { + navigator?.serial?.addEventListener("disconnect", () => { updateSerialPortList(); }); useEffect(() => { @@ -58,9 +58,8 @@ export const Serial = ({ closeDialog }: TabElementProps): JSX.Element => { await onConnect(port); }} > - {`# ${index} - ${usbVendorId ?? "UNK"} - ${ - usbProductId ?? "UNK" - }`} + {`# ${index} - ${usbVendorId ?? "UNK"} - ${usbProductId ?? "UNK" + }`} ); })} diff --git a/src/core/hooks/useBrowserFeatureDetection.ts b/src/core/hooks/useBrowserFeatureDetection.ts index 83a90a7a..a31b7b5a 100644 --- a/src/core/hooks/useBrowserFeatureDetection.ts +++ b/src/core/hooks/useBrowserFeatureDetection.ts @@ -10,8 +10,8 @@ interface BrowserSupport { export function useBrowserFeatureDetection(): BrowserSupport { const support = useMemo(() => { const features: [BrowserFeature, boolean][] = [ - ['Web Bluetooth', !!navigator.bluetooth], - ['Web Serial', !!navigator.serial], + ['Web Bluetooth', !!navigator?.bluetooth], + ['Web Serial', !!navigator?.serial], ['Secure Context', window.location.protocol === 'https:' || window.location.hostname === 'localhost'] ]; From 42ccd953c09ee6bf9707309042a6565395411f14 Mon Sep 17 00:00:00 2001 From: Hunter275 Date: Mon, 20 Jan 2025 20:20:50 -0500 Subject: [PATCH 165/181] remove version spec --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd73ce31..2591421c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,8 +16,6 @@ jobs: - name: Checkout uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 - with: - version: latest - name: Install Dependencies run: pnpm install From 8d35b57d1983029a0e971721823cd0200e4899a8 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Thu, 23 Jan 2025 12:59:57 +0100 Subject: [PATCH 166/181] Add packageManager in package.json --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 84a49432..2946c813 100644 --- a/package.json +++ b/package.json @@ -85,5 +85,6 @@ "tar": "^6.2.1", "tslib": "^2.6.3", "typescript": "^5.5.2" - } + }, + "packageManager": "pnpm@9.15.4" } From ea648ca88712e0d688c4a93402b774b0c2fca117 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Thu, 23 Jan 2025 13:30:16 +0100 Subject: [PATCH 167/181] Just for joke without actions/checkout@v4 --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2591421c..7f568b6c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 - name: Install Dependencies From 2967a74480e88f4c5fe5b7172aeb9ec993b203c2 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Thu, 23 Jan 2025 13:33:13 +0100 Subject: [PATCH 168/181] Blank version --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f568b6c..975a3e9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v4 + with: + version: - name: Install Dependencies run: pnpm install From c16b3a3ce0286603d4e16187f05a3f729b1f0946 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Thu, 23 Jan 2025 13:35:12 +0100 Subject: [PATCH 169/181] Add version --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 975a3e9b..9b467af3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout uses: pnpm/action-setup@v4 with: - version: + version: 9.15.4 - name: Install Dependencies run: pnpm install From c8cd5b0eaa5be59d32622fa726fc0c74638d5700 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Thu, 23 Jan 2025 13:49:44 +0100 Subject: [PATCH 170/181] Define package_json_file: package.json in CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b467af3..3d1fac56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout uses: pnpm/action-setup@v4 with: - version: 9.15.4 + package_json_file: package.json - name: Install Dependencies run: pnpm install From 9493649a69729ed0abea6db950bfc5b2755d0ae8 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Thu, 23 Jan 2025 14:02:21 +0100 Subject: [PATCH 171/181] This works now --- .github/workflows/ci.yml | 7 ++++--- .github/workflows/pr.yml | 2 -- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d1fac56..76f226cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,11 @@ jobs: build-and-package: runs-on: ubuntu-latest steps: - - name: Checkout + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup pnpm uses: pnpm/action-setup@v4 - with: - package_json_file: package.json - name: Install Dependencies run: pnpm install diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 870ca6fe..0e3f324a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -11,8 +11,6 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v4 - with: - version: latest - name: Install Dependencies run: pnpm install From 891a1a95039a2061aac7e948de1a465bf0e7e393 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Fri, 24 Jan 2025 01:26:15 +0100 Subject: [PATCH 172/181] pnpm check:fix --- rsbuild.config.ts | 2 +- src/App.tsx | 2 +- src/components/Dialog/DialogManager.tsx | 2 +- src/components/Dialog/NewDeviceDialog.tsx | 38 ++++----- src/components/Form/FormPasswordGenerator.tsx | 8 +- src/components/PageComponents/Channel.tsx | 63 ++++++++------- .../PageComponents/Config/Bluetooth.tsx | 16 ++-- .../PageComponents/Config/Security.tsx | 10 ++- .../PageComponents/Connect/Serial.tsx | 5 +- .../PageComponents/Map/NodeDetail.tsx | 6 +- .../PageComponents/Messages/Message.tsx | 2 +- src/components/Toaster.tsx | 3 +- src/components/UI/Button.tsx | 2 +- src/components/UI/Toast.tsx | 62 +++++++-------- src/components/UI/Typography/Link.tsx | 5 +- src/core/hooks/useBrowserFeatureDetection.ts | 18 +++-- src/core/hooks/useKeyBackupReminder.tsx | 77 +++++++++---------- src/core/hooks/useToast.ts | 36 ++++----- src/pages/Map.tsx | 9 ++- tsconfig.json | 2 +- 20 files changed, 189 insertions(+), 179 deletions(-) diff --git a/rsbuild.config.ts b/rsbuild.config.ts index 3191db5c..b9076c33 100644 --- a/rsbuild.config.ts +++ b/rsbuild.config.ts @@ -1,6 +1,6 @@ +import { execSync } from "node:child_process"; import { defineConfig } from "@rsbuild/core"; import { pluginReact } from "@rsbuild/plugin-react"; -import { execSync } from "node:child_process"; let hash = ""; diff --git a/src/App.tsx b/src/App.tsx index 8c15dc97..b512b628 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { CommandPalette } from "@components/CommandPalette.tsx"; import { DeviceSelector } from "@components/DeviceSelector.tsx"; import { DialogManager } from "@components/Dialog/DialogManager"; import { NewDeviceDialog } from "@components/Dialog/NewDeviceDialog.tsx"; +import { KeyBackupReminder } from "@components/KeyBackupReminder"; import { Toaster } from "@components/Toaster.tsx"; import Footer from "@components/UI/Footer.tsx"; import { ThemeController } from "@components/generic/ThemeController.tsx"; @@ -11,7 +12,6 @@ import { useAppStore } from "@core/stores/appStore.ts"; import { useDeviceStore } from "@core/stores/deviceStore.ts"; import { Dashboard } from "@pages/Dashboard/index.tsx"; import { MapProvider } from "react-map-gl"; -import { KeyBackupReminder } from "@components/KeyBackupReminder"; export const App = (): JSX.Element => { const { getDevice } = useDeviceStore(); diff --git a/src/components/Dialog/DialogManager.tsx b/src/components/Dialog/DialogManager.tsx index afebdf5d..e1769751 100644 --- a/src/components/Dialog/DialogManager.tsx +++ b/src/components/Dialog/DialogManager.tsx @@ -1,11 +1,11 @@ import { RemoveNodeDialog } from "@app/components/Dialog/RemoveNodeDialog.tsx"; import { DeviceNameDialog } from "@components/Dialog/DeviceNameDialog.tsx"; import { ImportDialog } from "@components/Dialog/ImportDialog.tsx"; +import { PkiBackupDialog } from "@components/Dialog/PKIBackupDialog"; import { QRDialog } from "@components/Dialog/QRDialog.tsx"; import { RebootDialog } from "@components/Dialog/RebootDialog.tsx"; import { ShutdownDialog } from "@components/Dialog/ShutdownDialog.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; -import { PkiBackupDialog } from "@components/Dialog/PKIBackupDialog"; export const DialogManager = (): JSX.Element => { const { channels, config, dialog, setDialogOpen } = useDevice(); diff --git a/src/components/Dialog/NewDeviceDialog.tsx b/src/components/Dialog/NewDeviceDialog.tsx index e3330cbf..c84bdfbb 100644 --- a/src/components/Dialog/NewDeviceDialog.tsx +++ b/src/components/Dialog/NewDeviceDialog.tsx @@ -11,7 +11,6 @@ import { DialogHeader, DialogTitle, } from "@components/UI/Dialog.tsx"; -import { AlertCircle, InfoIcon, } from "lucide-react"; import { Tabs, TabsContent, @@ -19,8 +18,9 @@ import { TabsTrigger, } from "@components/UI/Tabs.tsx"; import { Subtle } from "@components/UI/Typography/Subtle.tsx"; -import { Link } from "../UI/Typography/Link"; +import { AlertCircle, InfoIcon } from "lucide-react"; import { Fragment } from "react/jsx-runtime"; +import { Link } from "../UI/Typography/Link"; export interface TabElementProps { closeDialog: () => void; @@ -50,26 +50,25 @@ const links: { [key: string]: string } = { "https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts", }; -const listFormatter = new Intl.ListFormat('en', { - style: 'long', - type: 'conjunction' +const listFormatter = new Intl.ListFormat("en", { + style: "long", + type: "conjunction", }); const ErrorMessage = ({ missingFeatures }: FeatureErrorProps) => { if (missingFeatures.length === 0) return null; - const browserFeatures = missingFeatures.filter(feature => feature !== "Secure Context"); + const browserFeatures = missingFeatures.filter( + (feature) => feature !== "Secure Context", + ); const needsSecureContext = missingFeatures.includes("Secure Context"); const formatFeatureList = (features: string[]) => { const parts = listFormatter.formatToParts(features); return parts.map((part) => { - if (part.type === 'element') { + if (part.type === "element") { return ( - + {part.value} ); @@ -94,12 +93,8 @@ const ErrorMessage = ({ missingFeatures }: FeatureErrorProps) => { <> {browserFeatures.length > 0 && " Additionally, it"} {browserFeatures.length === 0 && "This application"} requires a{" "} - - secure context - - . Please connect using HTTPS or localhost. + secure context. + Please connect using HTTPS or localhost. )}

@@ -146,10 +141,7 @@ export const NewDeviceDialog = ({ {tabs.map((tab) => ( - + {tab.label} ))} @@ -157,7 +149,9 @@ export const NewDeviceDialog = ({ {tabs.map((tab) => (
- {tab.isDisabled ? : null} + {tab.isDisabled ? ( + + ) : null} onOpenChange(false)} />
diff --git a/src/components/Form/FormPasswordGenerator.tsx b/src/components/Form/FormPasswordGenerator.tsx index 784086fb..622e502e 100644 --- a/src/components/Form/FormPasswordGenerator.tsx +++ b/src/components/Form/FormPasswordGenerator.tsx @@ -2,12 +2,12 @@ import type { BaseFormBuilderProps, GenericFormElementProps, } from "@components/Form/DynamicForm.tsx"; +import type { ButtonVariant } from "@components/UI/Button"; import { Generator } from "@components/UI/Generator.tsx"; import { Eye, EyeOff } from "lucide-react"; import type { ChangeEventHandler, MouseEventHandler } from "react"; import { useState } from "react"; import { Controller, type FieldValues } from "react-hook-form"; -import type { ButtonVariant } from "@components/UI/Button"; export interface PasswordGeneratorProps extends BaseFormBuilderProps { type: "passwordGenerator"; @@ -44,9 +44,9 @@ export function PasswordGenerator({ action={ field.hide ? { - icon: passwordShown ? EyeOff : Eye, - onClick: togglePasswordVisiblity, - } + icon: passwordShown ? EyeOff : Eye, + onClick: togglePasswordVisiblity, + } : undefined } devicePSKBitCount={field.devicePSKBitCount} diff --git a/src/components/PageComponents/Channel.tsx b/src/components/PageComponents/Channel.tsx index ef316c91..dcd69c17 100644 --- a/src/components/PageComponents/Channel.tsx +++ b/src/components/PageComponents/Channel.tsx @@ -23,7 +23,8 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { channel?.settings?.psk.length ?? 16, ); const [validationText, setValidationText] = useState(); - const [preSharedDialogOpen, setPreSharedDialogOpen] = useState(false); + const [preSharedDialogOpen, setPreSharedDialogOpen] = + useState(false); const onSubmit = (data: ChannelValidation) => { const channel = new Protobuf.Channel.Channel({ @@ -99,12 +100,13 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { psk: pass, positionEnabled: channel?.settings?.moduleSettings?.positionPrecision !== - undefined && + undefined && channel?.settings?.moduleSettings?.positionPrecision > 0, preciseLocation: channel?.settings?.moduleSettings?.positionPrecision === 32, positionPrecision: - channel?.settings?.moduleSettings?.positionPrecision === undefined + channel?.settings?.moduleSettings?.positionPrecision === + undefined ? 10 : channel?.settings?.moduleSettings?.positionPrecision, }, @@ -133,12 +135,19 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { type: "passwordGenerator", name: "settings.psk", label: "Pre-Shared Key", - description: "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", + description: + "Supported PSK lengths: 256-bit, 128-bit, 8-bit, Empty (0-bit)", validationText: validationText, devicePSKBitCount: bitCount ?? 0, inputChange: inputChangeEvent, selectChange: selectChangeEvent, - actionButtons: [{ text: 'Generate', variant: 'success', onClick: preSharedClickEvent }], + actionButtons: [ + { + text: "Generate", + variant: "success", + onClick: preSharedClickEvent, + }, + ], hide: true, properties: { value: pass, @@ -185,29 +194,29 @@ export const Channel = ({ channel }: SettingsPanelProps): JSX.Element => { enumValue: config.display?.units === 0 ? { - "Within 23 km": 10, - "Within 12 km": 11, - "Within 5.8 km": 12, - "Within 2.9 km": 13, - "Within 1.5 km": 14, - "Within 700 m": 15, - "Within 350 m": 16, - "Within 200 m": 17, - "Within 90 m": 18, - "Within 50 m": 19, - } + "Within 23 km": 10, + "Within 12 km": 11, + "Within 5.8 km": 12, + "Within 2.9 km": 13, + "Within 1.5 km": 14, + "Within 700 m": 15, + "Within 350 m": 16, + "Within 200 m": 17, + "Within 90 m": 18, + "Within 50 m": 19, + } : { - "Within 15 miles": 10, - "Within 7.3 miles": 11, - "Within 3.6 miles": 12, - "Within 1.8 miles": 13, - "Within 0.9 miles": 14, - "Within 0.5 miles": 15, - "Within 0.2 miles": 16, - "Within 600 feet": 17, - "Within 300 feet": 18, - "Within 150 feet": 19, - }, + "Within 15 miles": 10, + "Within 7.3 miles": 11, + "Within 3.6 miles": 12, + "Within 1.8 miles": 13, + "Within 0.9 miles": 14, + "Within 0.5 miles": 15, + "Within 0.2 miles": 16, + "Within 600 feet": 17, + "Within 300 feet": 18, + "Within 150 feet": 19, + }, }, }, ], diff --git a/src/components/PageComponents/Config/Bluetooth.tsx b/src/components/PageComponents/Config/Bluetooth.tsx index b01d3c69..47eeeca4 100644 --- a/src/components/PageComponents/Config/Bluetooth.tsx +++ b/src/components/PageComponents/Config/Bluetooth.tsx @@ -6,20 +6,16 @@ import { useState } from "react"; export const Bluetooth = (): JSX.Element => { const { config, setWorkingConfig } = useDevice(); - const [bluetoothValidationText, setBluetoothValidationText] = useState(); + const [bluetoothValidationText, setBluetoothValidationText] = + useState(); - const bluetoothPinChangeEvent = ( - e: React.ChangeEvent, - ) => { - if (e.target.value[0] == "0") - { + const bluetoothPinChangeEvent = (e: React.ChangeEvent) => { + if (e.target.value[0] == "0") { setBluetoothValidationText("Bluetooth Pin cannot start with 0."); - } - else - { + } else { setBluetoothValidationText(""); } - } + }; const onSubmit = (data: BluetoothValidation) => { setWorkingConfig( diff --git a/src/components/PageComponents/Config/Security.tsx b/src/components/PageComponents/Config/Security.tsx index d6e76cc9..7152b387 100644 --- a/src/components/PageComponents/Config/Security.tsx +++ b/src/components/PageComponents/Config/Security.tsx @@ -12,7 +12,8 @@ import { Eye, EyeOff } from "lucide-react"; import { useState } from "react"; export const Security = (): JSX.Element => { - const { config, nodes, hardware, setWorkingConfig, setDialogOpen } = useDevice(); + const { config, nodes, hardware, setWorkingConfig, setDialogOpen } = + useDevice(); const [privateKey, setPrivateKey] = useState( fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), @@ -31,7 +32,8 @@ export const Security = (): JSX.Element => { ); const [adminKeyValidationText, setAdminKeyValidationText] = useState(); - const [privateKeyDialogOpen, setPrivateKeyDialogOpen] = useState(false); + const [privateKeyDialogOpen, setPrivateKeyDialogOpen] = + useState(false); const onSubmit = (data: SecurityValidation) => { if (privateKeyValidationText || adminKeyValidationText) return; @@ -76,7 +78,7 @@ export const Security = (): JSX.Element => { const pkiBackupClickEvent = () => { setDialogOpen("pkiBackup", true); - } + }; const pkiRegenerate = () => { const privateKey = getX25519PrivateKey(); @@ -202,7 +204,7 @@ export const Security = (): JSX.Element => { name: "isManaged", label: "Managed", description: - 'If true, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless a suitable Remote Admin node has been setup, and the public key stored in the field below.', + "If true, device configuration options are only able to be changed remotely by a Remote Admin node via admin messages. Do not enable this option unless a suitable Remote Admin node has been setup, and the public key stored in the field below.", }, { type: "text", diff --git a/src/components/PageComponents/Connect/Serial.tsx b/src/components/PageComponents/Connect/Serial.tsx index 53c623cb..4333e668 100644 --- a/src/components/PageComponents/Connect/Serial.tsx +++ b/src/components/PageComponents/Connect/Serial.tsx @@ -58,8 +58,9 @@ export const Serial = ({ closeDialog }: TabElementProps): JSX.Element => { await onConnect(port); }} > - {`# ${index} - ${usbVendorId ?? "UNK"} - ${usbProductId ?? "UNK" - }`} + {`# ${index} - ${usbVendorId ?? "UNK"} - ${ + usbProductId ?? "UNK" + }`} ); })} diff --git a/src/components/PageComponents/Map/NodeDetail.tsx b/src/components/PageComponents/Map/NodeDetail.tsx index d1cbd8a9..00847150 100644 --- a/src/components/PageComponents/Map/NodeDetail.tsx +++ b/src/components/PageComponents/Map/NodeDetail.tsx @@ -1,11 +1,12 @@ -import { Mono } from "@components/generic/Mono.tsx"; +import { Separator } from "@app/components/UI/Seperator"; import { H5 } from "@app/components/UI/Typography/H5.tsx"; import { Subtle } from "@app/components/UI/Typography/Subtle.tsx"; -import { Separator } from "@app/components/UI/Seperator"; +import { Mono } from "@components/generic/Mono.tsx"; import { TimeAgo } from "@components/generic/Table/tmp/TimeAgo.tsx"; import { Hashicon } from "@emeraldpay/hashicon-react"; import { Protobuf } from "@meshtastic/js"; import type { Protobuf as ProtobufType } from "@meshtastic/js"; +import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { BatteryChargingIcon, BatteryFullIcon, @@ -17,7 +18,6 @@ import { MountainSnow, Star, } from "lucide-react"; -import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; export interface NodeDetailProps { node: ProtobufType.Mesh.NodeInfo; diff --git a/src/components/PageComponents/Messages/Message.tsx b/src/components/PageComponents/Messages/Message.tsx index 22ed52b2..fc9a7b95 100644 --- a/src/components/PageComponents/Messages/Message.tsx +++ b/src/components/PageComponents/Messages/Message.tsx @@ -45,7 +45,7 @@ export const Message = ({ {sender?.user?.longName ?? "UNK"} - {message.rxTime.toLocaleDateString()} + {message.rxTime.toLocaleDateString()} {message.rxTime.toLocaleTimeString(undefined, { diff --git a/src/components/Toaster.tsx b/src/components/Toaster.tsx index f5531bba..d50ba3b8 100644 --- a/src/components/Toaster.tsx +++ b/src/components/Toaster.tsx @@ -17,7 +17,6 @@ export function Toaster() { @@ -32,4 +31,4 @@ export function Toaster() { ); -} \ No newline at end of file +} diff --git a/src/components/UI/Button.tsx b/src/components/UI/Button.tsx index e1b2d704..18861065 100644 --- a/src/components/UI/Button.tsx +++ b/src/components/UI/Button.tsx @@ -39,7 +39,7 @@ export type ButtonVariant = VariantProps["variant"]; export interface ButtonProps extends React.ButtonHTMLAttributes, - VariantProps { } + VariantProps {} const Button = React.forwardRef( ({ className, variant, size, ...props }, ref) => { diff --git a/src/components/UI/Toast.tsx b/src/components/UI/Toast.tsx index d40b294a..b2fd7131 100644 --- a/src/components/UI/Toast.tsx +++ b/src/components/UI/Toast.tsx @@ -1,11 +1,11 @@ -import * as React from "react" -import * as ToastPrimitives from "@radix-ui/react-toast" -import { cva, type VariantProps } from "class-variance-authority" -import { X } from 'lucide-react' +import * as ToastPrimitives from "@radix-ui/react-toast"; +import { type VariantProps, cva } from "class-variance-authority"; +import { X } from "lucide-react"; +import * as React from "react"; -import { cn } from "@core/utils/cn" +import { cn } from "@core/utils/cn"; -const ToastProvider = ToastPrimitives.Provider +const ToastProvider = ToastPrimitives.Provider; const ToastViewport = React.forwardRef< React.ElementRef, @@ -15,33 +15,34 @@ const ToastViewport = React.forwardRef< ref={ref} className={cn( "fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-24 sm:right-6 sm:top-auto sm:flex-col md:max-w-[420px]", - className + className, )} {...props} /> -)) -ToastViewport.displayName = ToastPrimitives.Viewport.displayName +)); +ToastViewport.displayName = ToastPrimitives.Viewport.displayName; const toastVariants = cva( "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", { variants: { variant: { - default: "border bg-background text-foreground dark:bg-slate-700 dark:border-slate-600 dark:text-slate-50", + default: + "border bg-background text-foreground dark:bg-slate-700 dark:border-slate-600 dark:text-slate-50", destructive: - "group destructive bg-red-600 text-white dark:border-red-900 dark:bg-red-900 dark:text-red-50" + "group destructive bg-red-600 text-white dark:border-red-900 dark:bg-red-900 dark:text-red-50", }, }, defaultVariants: { variant: "default", }, - } -) + }, +); const Toast = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef & - VariantProps + VariantProps >(({ className, variant, ...props }, ref) => { return ( - ) -}) -Toast.displayName = ToastPrimitives.Root.displayName + ); +}); +Toast.displayName = ToastPrimitives.Root.displayName; const ToastAction = React.forwardRef< React.ElementRef, @@ -61,12 +62,12 @@ const ToastAction = React.forwardRef< ref={ref} className={cn( "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive", - className + className, )} {...props} /> -)) -ToastAction.displayName = ToastPrimitives.Action.displayName +)); +ToastAction.displayName = ToastPrimitives.Action.displayName; const ToastClose = React.forwardRef< React.ElementRef, @@ -76,15 +77,15 @@ const ToastClose = React.forwardRef< ref={ref} className={cn( "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600 dark:text-slate-400 dark:hover:text-slate-50", - className + className, )} toast-close="" {...props} > -)) -ToastClose.displayName = ToastPrimitives.Close.displayName +)); +ToastClose.displayName = ToastPrimitives.Close.displayName; const ToastTitle = React.forwardRef< React.ElementRef, @@ -95,8 +96,8 @@ const ToastTitle = React.forwardRef< className={cn("text-sm font-semibold", className)} {...props} /> -)) -ToastTitle.displayName = ToastPrimitives.Title.displayName +)); +ToastTitle.displayName = ToastPrimitives.Title.displayName; const ToastDescription = React.forwardRef< React.ElementRef, @@ -107,12 +108,12 @@ const ToastDescription = React.forwardRef< className={cn("text-sm opacity-90", className)} {...props} /> -)) -ToastDescription.displayName = ToastPrimitives.Description.displayName +)); +ToastDescription.displayName = ToastPrimitives.Description.displayName; -type ToastProps = React.ComponentPropsWithoutRef +type ToastProps = React.ComponentPropsWithoutRef; -type ToastActionElement = React.ReactElement +type ToastActionElement = React.ReactElement; export { type ToastProps, @@ -124,5 +125,4 @@ export { ToastDescription, ToastClose, ToastAction, -} - +}; diff --git a/src/components/UI/Typography/Link.tsx b/src/components/UI/Typography/Link.tsx index efcfbdf6..4857da1f 100644 --- a/src/components/UI/Typography/Link.tsx +++ b/src/components/UI/Typography/Link.tsx @@ -11,7 +11,10 @@ export const Link = ({ href, children, className }: LinkProps): JSX.Element => ( href={href} target={"_blank"} rel="noopener noreferrer" - className={cn("font-medium text-slate-900 underline underline-offset-4 dark:text-slate-50", className)} + className={cn( + "font-medium text-slate-900 underline underline-offset-4 dark:text-slate-50", + className, + )} > {children} diff --git a/src/core/hooks/useBrowserFeatureDetection.ts b/src/core/hooks/useBrowserFeatureDetection.ts index a31b7b5a..17d35ac2 100644 --- a/src/core/hooks/useBrowserFeatureDetection.ts +++ b/src/core/hooks/useBrowserFeatureDetection.ts @@ -1,6 +1,6 @@ -import { useMemo } from 'react'; +import { useMemo } from "react"; -export type BrowserFeature = 'Web Bluetooth' | 'Web Serial' | 'Secure Context'; +export type BrowserFeature = "Web Bluetooth" | "Web Serial" | "Secure Context"; interface BrowserSupport { supported: BrowserFeature[]; @@ -10,9 +10,13 @@ interface BrowserSupport { export function useBrowserFeatureDetection(): BrowserSupport { const support = useMemo(() => { const features: [BrowserFeature, boolean][] = [ - ['Web Bluetooth', !!navigator?.bluetooth], - ['Web Serial', !!navigator?.serial], - ['Secure Context', window.location.protocol === 'https:' || window.location.hostname === 'localhost'] + ["Web Bluetooth", !!navigator?.bluetooth], + ["Web Serial", !!navigator?.serial], + [ + "Secure Context", + window.location.protocol === "https:" || + window.location.hostname === "localhost", + ], ]; return features.reduce( @@ -21,9 +25,9 @@ export function useBrowserFeatureDetection(): BrowserSupport { list.push(feature); return acc; }, - { supported: [], unsupported: [] } + { supported: [], unsupported: [] }, ); }, []); return support; -} \ No newline at end of file +} diff --git a/src/core/hooks/useKeyBackupReminder.tsx b/src/core/hooks/useKeyBackupReminder.tsx index ee65d161..0da9b0af 100644 --- a/src/core/hooks/useKeyBackupReminder.tsx +++ b/src/core/hooks/useKeyBackupReminder.tsx @@ -17,11 +17,11 @@ interface ReminderState { lastShown: string; } -const TOAST_APPEAR_DELAY = 10_000 // 10 seconds; -const TOAST_DURATION = 30_000 // 30 seconds;: +const TOAST_APPEAR_DELAY = 10_000; // 10 seconds; +const TOAST_DURATION = 30_000; // 30 seconds;: // remind user in 1 year to backup keys again, if they accept the reminder; -const ON_ACCEPT_REMINDER_DAYS = 365 +const ON_ACCEPT_REMINDER_DAYS = 365; function isReminderExpired(lastShown: string): boolean { const lastShownDate = new Date(lastShown); @@ -35,13 +35,14 @@ export function useBackupReminder({ reminderInDays = 7, enabled, message, - onAccept = () => { }, + onAccept = () => {}, cookieOptions, }: UseBackupReminderOptions) { const { toast } = useToast(); const toastShownRef = useRef(false); - const { value: reminderCookie, setCookie } = - useCookie("key_backup_reminder"); + const { value: reminderCookie, setCookie } = useCookie( + "key_backup_reminder", + ); const suppressReminder = useCallback( (days: number) => { @@ -69,39 +70,37 @@ export function useBackupReminder({ toastShownRef.current = true; - const { dismiss } = toast( - { - title: "Backup Reminder", - duration: TOAST_DURATION, - delay: TOAST_APPEAR_DELAY, - description: message, - action: ( -
- - -
- ), - }, - ); + const { dismiss } = toast({ + title: "Backup Reminder", + duration: TOAST_DURATION, + delay: TOAST_APPEAR_DELAY, + description: message, + action: ( +
+ + +
+ ), + }); return () => { if (!toastShownRef.current) { diff --git a/src/core/hooks/useToast.ts b/src/core/hooks/useToast.ts index c913d223..8c4a91b8 100644 --- a/src/core/hooks/useToast.ts +++ b/src/core/hooks/useToast.ts @@ -31,21 +31,21 @@ type ActionType = typeof actionTypes; type Action = | { - type: ActionType["ADD_TOAST"]; - toast: ToasterToast; - } + type: ActionType["ADD_TOAST"]; + toast: ToasterToast; + } | { - type: ActionType["UPDATE_TOAST"]; - toast: Partial; - } + type: ActionType["UPDATE_TOAST"]; + toast: Partial; + } | { - type: ActionType["DISMISS_TOAST"]; - toastId?: ToasterToast["id"]; - } + type: ActionType["DISMISS_TOAST"]; + toastId?: ToasterToast["id"]; + } | { - type: ActionType["REMOVE_TOAST"]; - toastId?: ToasterToast["id"]; - }; + type: ActionType["REMOVE_TOAST"]; + toastId?: ToasterToast["id"]; + }; interface State { toasts: ToasterToast[]; @@ -81,7 +81,7 @@ export const reducer = (state: State, action: Action): State => { return { ...state, toasts: state.toasts.map((t) => - t.id === action.toast.id ? { ...t, ...action.toast } : t + t.id === action.toast.id ? { ...t, ...action.toast } : t, ), }; @@ -103,10 +103,10 @@ export const reducer = (state: State, action: Action): State => { toasts: state.toasts.map((t) => t.id === toastId || toastId === undefined ? { - ...t, - open: false, - } - : t + ...t, + open: false, + } + : t, ), }; } @@ -193,4 +193,4 @@ function useToast() { }; } -export { toast, useToast }; \ No newline at end of file +export { toast, useToast }; diff --git a/src/pages/Map.tsx b/src/pages/Map.tsx index e326b336..1be9455d 100644 --- a/src/pages/Map.tsx +++ b/src/pages/Map.tsx @@ -1,5 +1,5 @@ -import { Subtle } from "@app/components/UI/Typography/Subtle.tsx"; import { NodeDetail } from "@app/components/PageComponents/Map/NodeDetail"; +import { Subtle } from "@app/components/UI/Typography/Subtle.tsx"; import { cn } from "@app/core/utils/cn.ts"; import { PageLayout } from "@components/PageLayout.tsx"; import { Sidebar } from "@components/Sidebar.tsx"; @@ -8,6 +8,7 @@ import { SidebarButton } from "@components/UI/Sidebar/sidebarButton.tsx"; import { useAppStore } from "@core/stores/appStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts"; import { Hashicon } from "@emeraldpay/hashicon-react"; +import type { Protobuf } from "@meshtastic/js"; import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { bbox, lineString } from "@turf/turf"; import { @@ -19,7 +20,6 @@ import { import { useCallback, useEffect, useState } from "react"; import { AttributionControl, Marker, Popup, useMap } from "react-map-gl"; import MapGl from "react-map-gl/maplibre"; -import { Protobuf } from "@meshtastic/js"; export const MapPage = (): JSX.Element => { const { nodes, waypoints } = useDevice(); @@ -148,7 +148,10 @@ export const MapPage = (): JSX.Element => { }} > {waypoints.map((wp) => ( Date: Fri, 24 Jan 2025 01:27:33 +0100 Subject: [PATCH 173/181] Fixes by hand --- src/components/PageComponents/Config/Bluetooth.tsx | 2 +- src/components/PageComponents/Map/NodeDetail.tsx | 4 ++-- src/components/Sidebar.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/PageComponents/Config/Bluetooth.tsx b/src/components/PageComponents/Config/Bluetooth.tsx index 47eeeca4..a9a92a69 100644 --- a/src/components/PageComponents/Config/Bluetooth.tsx +++ b/src/components/PageComponents/Config/Bluetooth.tsx @@ -10,7 +10,7 @@ export const Bluetooth = (): JSX.Element => { useState(); const bluetoothPinChangeEvent = (e: React.ChangeEvent) => { - if (e.target.value[0] == "0") { + if (e.target.value[0] === "0") { setBluetoothValidationText("Bluetooth Pin cannot start with 0."); } else { setBluetoothValidationText(""); diff --git a/src/components/PageComponents/Map/NodeDetail.tsx b/src/components/PageComponents/Map/NodeDetail.tsx index 00847150..f464ecef 100644 --- a/src/components/PageComponents/Map/NodeDetail.tsx +++ b/src/components/PageComponents/Map/NodeDetail.tsx @@ -84,7 +84,7 @@ export const NodeDetail = ({ node }: NodeDetailProps): JSX.Element => { {node.deviceMetrics?.batteryLevel > 100 ? "Charging" - : node.deviceMetrics?.batteryLevel + "%"} + : `${node.deviceMetrics?.batteryLevel}%`}
)} @@ -121,7 +121,7 @@ export const NodeDetail = ({ node }: NodeDetailProps): JSX.Element => {
- {isNaN(node.hopsAway) ? "?" : node.hopsAway} + {Number.isNaN(node.hopsAway) ? "?" : node.hopsAway}
{node.hopsAway === 1 ? "Hop" : "Hops"}
diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index d4ada2bd..2c4f1963 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -91,7 +91,7 @@ export const Sidebar = ({ children }: SidebarProps): JSX.Element => { {myNode?.deviceMetrics?.batteryLevel ? myNode?.deviceMetrics?.batteryLevel > 100 ? "Charging" - : myNode?.deviceMetrics?.batteryLevel + "%" + : `${myNode?.deviceMetrics?.batteryLevel}%` : "UNK"}
From 7930f44109ddfd7fcf45de550eb829254fd15e58 Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Fri, 24 Jan 2025 01:42:01 +0100 Subject: [PATCH 174/181] Try to fix old stuff --- src/components/generic/Table/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/generic/Table/index.tsx b/src/components/generic/Table/index.tsx index ec745963..aef5f6f2 100755 --- a/src/components/generic/Table/index.tsx +++ b/src/components/generic/Table/index.tsx @@ -94,8 +94,7 @@ export const Table = ({ headings, rows }: TableProps): JSX.Element => { {row.map((item, index) => ( {item} From 47150c649f5656bbaba839a3bbe0ce7ac0df8c7d Mon Sep 17 00:00:00 2001 From: Tilen Komel Date: Fri, 24 Jan 2025 01:50:41 +0100 Subject: [PATCH 175/181] Add back pnpm check into build command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2946c813..194cc62c 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "description": "Meshtastic web client", "license": "GPL-3.0-only", "scripts": { - "build": "rsbuild build", + "build": "pnpm check && rsbuild build", "check": "biome check .", "check:fix": "pnpm check --write", "dev": "rsbuild dev --open", From fe2b76eeb98103f4f45b5662407cd1e82c14aed8 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 25 Jan 2025 16:09:59 -0500 Subject: [PATCH 176/181] fix: moving tailwind libs to dev dependency, removed unused deps --- package.json | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 194cc62c..ffa864da 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "@radix-ui/react-tooltip": "^1.1.1", "@turf/turf": "^6.5.0", "base64-js": "^1.5.1", - "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", @@ -59,15 +58,12 @@ "react-map-gl": "7.1.7", "react-qrcode-logo": "^2.10.0", "rfc4648": "^1.5.3", - "tailwind-merge": "^2.3.0", - "tailwindcss-animate": "^1.0.7", "timeago-react": "^3.0.6", "vite-plugin-node-polyfills": "^0.22.0", "zustand": "4.5.2" }, "devDependencies": { "@biomejs/biome": "^1.8.2", - "@buf/meshtastic_protobufs.bufbuild_es": "1.10.0-20240906232734-3da561588c55.1", "@rsbuild/core": "^1.0.10", "@rsbuild/plugin-react": "^1.0.3", "@types/chrome": "^0.0.263", @@ -80,10 +76,10 @@ "autoprefixer": "^10.4.19", "gzipper": "^7.2.0", "postcss": "^8.4.38", - "rollup-plugin-visualizer": "^5.12.0", "tailwindcss": "^3.4.4", + "tailwind-merge": "^2.3.0", + "tailwindcss-animate": "^1.0.7", "tar": "^6.2.1", - "tslib": "^2.6.3", "typescript": "^5.5.2" }, "packageManager": "pnpm@9.15.4" From d0ca24ae6f37f47b86137baf894ae79d904bfa4e Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 25 Jan 2025 16:41:42 -0500 Subject: [PATCH 177/181] feat: debounce message draft state updates to reduce zustand/immer store writes on Messages page --- .../PageComponents/Messages/MessageInput.tsx | 28 +++++++++++++++---- src/core/utils/debounce.ts | 13 +++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 src/core/utils/debounce.ts diff --git a/src/components/PageComponents/Messages/MessageInput.tsx b/src/components/PageComponents/Messages/MessageInput.tsx index 9a7c865a..29dc673d 100644 --- a/src/components/PageComponents/Messages/MessageInput.tsx +++ b/src/components/PageComponents/Messages/MessageInput.tsx @@ -1,8 +1,12 @@ +import { debounce } from "@app/core/utils/debounce"; import { Button } from "@components/UI/Button.tsx"; import { Input } from "@components/UI/Input.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import type { Types } from "@meshtastic/js"; import { SendIcon } from "lucide-react"; +import { useCallback, useState, useMemo } from "react"; + + export interface MessageInputProps { to: Types.Destination; @@ -20,10 +24,15 @@ export const MessageInput = ({ setMessageDraft, hardware, } = useDevice(); - const myNodeNum = hardware.myNodeNum; + const [localDraft, setLocalDraft] = useState(messageDraft); - const sendText = async (message: string) => { + const debouncedSetMessageDraft = useMemo( + () => debounce(setMessageDraft, 300), + [setMessageDraft] + ); + + const sendText = useCallback(async (message: string) => { await connection ?.sendText(message, to, true, channel) .then((id) => @@ -46,6 +55,12 @@ export const MessageInput = ({ e.error, ), ); + }, [channel, connection, myNodeNum, setMessageState, to]); + + const handleInputChange = (e: React.ChangeEvent) => { + const newValue = e.target.value; + setLocalDraft(newValue); + debouncedSetMessageDraft(newValue); }; return ( @@ -54,7 +69,8 @@ export const MessageInput = ({ className="w-full" onSubmit={(e) => { e.preventDefault(); - sendText(messageDraft); + sendText(localDraft); + setLocalDraft(""); setMessageDraft(""); }} > @@ -64,8 +80,8 @@ export const MessageInput = ({ autoFocus={true} minLength={1} placeholder="Enter Message" - value={messageDraft} - onChange={(e) => setMessageDraft(e.target.value)} + value={localDraft} + onChange={handleInputChange} />
); -}; +}; \ No newline at end of file diff --git a/src/core/utils/debounce.ts b/src/core/utils/debounce.ts new file mode 100644 index 00000000..e80b8a2b --- /dev/null +++ b/src/core/utils/debounce.ts @@ -0,0 +1,13 @@ +type Callback = (...args: Args) => void; + +export function debounce( + callback: Callback, + wait: number +): Callback { + let timeoutId: ReturnType; + + return (...args: Args) => { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => callback(...args), wait); + }; +} From f0dd426055a62877ae853dbf4d0c10bfb0191283 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 25 Jan 2025 21:24:43 -0500 Subject: [PATCH 178/181] chore: linting --- .../PageComponents/Messages/MessageInput.tsx | 59 ++++++++++--------- src/core/utils/debounce.ts | 2 +- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/components/PageComponents/Messages/MessageInput.tsx b/src/components/PageComponents/Messages/MessageInput.tsx index 29dc673d..ae88f9ac 100644 --- a/src/components/PageComponents/Messages/MessageInput.tsx +++ b/src/components/PageComponents/Messages/MessageInput.tsx @@ -4,9 +4,7 @@ import { Input } from "@components/UI/Input.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; import type { Types } from "@meshtastic/js"; import { SendIcon } from "lucide-react"; -import { useCallback, useState, useMemo } from "react"; - - +import { useCallback, useMemo, useState } from "react"; export interface MessageInputProps { to: Types.Destination; @@ -29,33 +27,36 @@ export const MessageInput = ({ const debouncedSetMessageDraft = useMemo( () => debounce(setMessageDraft, 300), - [setMessageDraft] + [setMessageDraft], ); - const sendText = useCallback(async (message: string) => { - await connection - ?.sendText(message, to, true, channel) - .then((id) => - setMessageState( - to === "broadcast" ? "broadcast" : "direct", - channel, - to as number, - myNodeNum, - id, - "ack", - ), - ) - .catch((e: Types.PacketError) => - setMessageState( - to === "broadcast" ? "broadcast" : "direct", - channel, - to as number, - myNodeNum, - e.id, - e.error, - ), - ); - }, [channel, connection, myNodeNum, setMessageState, to]); + const sendText = useCallback( + async (message: string) => { + await connection + ?.sendText(message, to, true, channel) + .then((id) => + setMessageState( + to === "broadcast" ? "broadcast" : "direct", + channel, + to as number, + myNodeNum, + id, + "ack", + ), + ) + .catch((e: Types.PacketError) => + setMessageState( + to === "broadcast" ? "broadcast" : "direct", + channel, + to as number, + myNodeNum, + e.id, + e.error, + ), + ); + }, + [channel, connection, myNodeNum, setMessageState, to], + ); const handleInputChange = (e: React.ChangeEvent) => { const newValue = e.target.value; @@ -91,4 +92,4 @@ export const MessageInput = ({
); -}; \ No newline at end of file +}; diff --git a/src/core/utils/debounce.ts b/src/core/utils/debounce.ts index e80b8a2b..b8df658b 100644 --- a/src/core/utils/debounce.ts +++ b/src/core/utils/debounce.ts @@ -2,7 +2,7 @@ type Callback = (...args: Args) => void; export function debounce( callback: Callback, - wait: number + wait: number, ): Callback { let timeoutId: ReturnType; From 4508428160d4c7095713ca70008cea625afbc214 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 25 Jan 2025 21:49:37 -0500 Subject: [PATCH 179/181] feat: add simple-git-hooks to run linting/formatting prior to commit --- package.json | 15 +++-- pnpm-lock.yaml | 151 +++++-------------------------------------------- 2 files changed, 25 insertions(+), 141 deletions(-) diff --git a/package.json b/package.json index ffa864da..6dc5cce3 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,16 @@ "license": "GPL-3.0-only", "scripts": { "build": "pnpm check && rsbuild build", - "check": "biome check .", - "check:fix": "pnpm check --write", + "check": "biome check src/", + "check:fix": "pnpm check --write src/", + "format": "biome format --write src/", "dev": "rsbuild dev --open", - "format": "biome format --write", "preview": "rsbuild preview", - "package": "gzipper c -i html,js,css,png,ico,svg,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ $(ls ./dist/output/)" + "package": "gzipper c -i html,js,css,png,ico,svg,webmanifest,txt dist dist/output && tar -cvf dist/build.tar -C ./dist/output/ $(ls ./dist/output/)", + "postinstall": "npx simple-git-hooks" + }, + "simple-git-hooks": { + "pre-commit": "npm run check:fix && npm run format" }, "repository": { "type": "git", @@ -76,8 +80,9 @@ "autoprefixer": "^10.4.19", "gzipper": "^7.2.0", "postcss": "^8.4.38", - "tailwindcss": "^3.4.4", + "simple-git-hooks": "^2.11.1", "tailwind-merge": "^2.3.0", + "tailwindcss": "^3.4.4", "tailwindcss-animate": "^1.0.7", "tar": "^6.2.1", "typescript": "^5.5.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 79d6d5ff..fd65e849 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,9 +68,6 @@ importers: base64-js: specifier: ^1.5.1 version: 1.5.1 - class-transformer: - specifier: ^0.5.1 - version: 0.5.1 class-validator: specifier: ^0.14.1 version: 0.14.1 @@ -119,12 +116,6 @@ importers: rfc4648: specifier: ^1.5.3 version: 1.5.3 - tailwind-merge: - specifier: ^2.3.0 - version: 2.3.0 - tailwindcss-animate: - specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.4) timeago-react: specifier: ^3.0.6 version: 3.0.6(react@18.3.1) @@ -138,9 +129,6 @@ importers: '@biomejs/biome': specifier: ^1.8.2 version: 1.8.2 - '@buf/meshtastic_protobufs.bufbuild_es': - specifier: 1.10.0-20240906232734-3da561588c55.1 - version: 1.10.0-20240906232734-3da561588c55.1(@bufbuild/protobuf@1.10.0) '@rsbuild/core': specifier: ^1.0.10 version: 1.0.10 @@ -177,18 +165,21 @@ importers: postcss: specifier: ^8.4.38 version: 8.4.38 - rollup-plugin-visualizer: - specifier: ^5.12.0 - version: 5.12.0(rollup@4.29.1) + simple-git-hooks: + specifier: ^2.11.1 + version: 2.11.1 + tailwind-merge: + specifier: ^2.3.0 + version: 2.3.0 tailwindcss: specifier: ^3.4.4 version: 3.4.4 + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@3.4.4) tar: specifier: ^6.2.1 version: 6.2.1 - tslib: - specifier: ^2.6.3 - version: 2.6.3 typescript: specifier: ^5.5.2 version: 5.5.2 @@ -256,11 +247,6 @@ packages: cpu: [x64] os: [win32] - '@buf/meshtastic_protobufs.bufbuild_es@1.10.0-20240906232734-3da561588c55.1': - resolution: {tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/-/meshtastic_protobufs.bufbuild_es-1.10.0-20240906232734-3da561588c55.1.tgz} - peerDependencies: - '@bufbuild/protobuf': ^1.10.0 - '@bufbuild/protobuf@1.10.0': resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} @@ -1905,19 +1891,12 @@ packages: cipher-base@1.0.4: resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} - class-transformer@0.5.1: - resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} - class-validator@0.14.1: resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==} class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} @@ -2029,10 +2008,6 @@ packages: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} - define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -2185,10 +2160,6 @@ packages: geojson-vt@4.0.2: resolution: {integrity: sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==} - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} @@ -2328,11 +2299,6 @@ packages: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} @@ -2409,10 +2375,6 @@ packages: resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} engines: {node: '>= 0.4'} - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - is-zst@1.0.0: resolution: {integrity: sha512-ZA5lvshKAl8z30dX7saXLpVhpsq3d2EHK9uf7qtUjnOtdw4XBpAoWb2RvZ5kyoaebdoidnGI0g2hn9Z7ObPbww==} @@ -2610,10 +2572,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - os-browserify@0.3.0: resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} @@ -2914,10 +2872,6 @@ packages: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - resolve-protobuf-schema@2.1.0: resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} @@ -2941,16 +2895,6 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - rollup-plugin-visualizer@5.12.0: - resolution: {integrity: sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==} - engines: {node: '>=14'} - hasBin: true - peerDependencies: - rollup: 2.x || 3.x || 4.x - peerDependenciesMeta: - rollup: - optional: true - rollup@4.29.1: resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -3010,6 +2954,10 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-git-hooks@2.11.1: + resolution: {integrity: sha512-tgqwPUMDcNDhuf1Xf6KTUsyeqGdgKMhzaH4PAZZuzguOgTl5uuyeYe/8mWgAr6IBxB5V06uqEf6Dy37gIWDtDg==} + hasBin: true + simple-zstd@1.4.2: resolution: {integrity: sha512-kGYEvT33M5XfyQvvW4wxl3eKcWbdbCc1V7OZzuElnaXft0qbVzoIIXHXiCm3JCUki+MZKKmvjl8p2VGLJc5Y/A==} @@ -3036,10 +2984,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - splaytree@3.1.2: resolution: {integrity: sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A==} @@ -3337,10 +3281,6 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -3349,14 +3289,6 @@ packages: engines: {node: '>= 14'} hasBin: true - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -3419,10 +3351,6 @@ snapshots: '@biomejs/cli-win32-x64@1.8.2': optional: true - '@buf/meshtastic_protobufs.bufbuild_es@1.10.0-20240906232734-3da561588c55.1(@bufbuild/protobuf@1.10.0)': - dependencies: - '@bufbuild/protobuf': 1.10.0 - '@bufbuild/protobuf@1.10.0': {} '@emeraldpay/hashicon-react@0.5.2': @@ -5521,8 +5449,6 @@ snapshots: inherits: 2.0.4 safe-buffer: 5.2.1 - class-transformer@0.5.1: {} - class-validator@0.14.1: dependencies: '@types/validator': 13.12.0 @@ -5533,12 +5459,6 @@ snapshots: dependencies: clsx: 2.0.0 - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - clsx@2.0.0: {} clsx@2.1.1: {} @@ -5680,8 +5600,6 @@ snapshots: es-errors: 1.3.0 gopd: 1.0.1 - define-lazy-prop@2.0.0: {} - define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -5873,8 +5791,6 @@ snapshots: geojson-vt@4.0.2: {} - get-caller-file@2.0.5: {} - get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -6023,8 +5939,6 @@ snapshots: dependencies: has-tostringtag: 1.0.2 - is-docker@2.2.1: {} - is-extendable@0.1.1: {} is-extendable@1.0.1: @@ -6090,10 +6004,6 @@ snapshots: call-bind: 1.0.7 get-intrinsic: 1.2.4 - is-wsl@2.2.0: - dependencies: - is-docker: 2.2.1 - is-zst@1.0.0: {} isarray@1.0.0: {} @@ -6328,12 +6238,6 @@ snapshots: dependencies: wrappy: 1.0.2 - open@8.4.2: - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - os-browserify@0.3.0: {} os-tmpdir@1.0.2: {} @@ -6636,8 +6540,6 @@ snapshots: es-errors: 1.3.0 set-function-name: 2.0.2 - require-directory@2.1.1: {} - resolve-protobuf-schema@2.1.0: dependencies: protocol-buffers-schema: 3.6.0 @@ -6661,15 +6563,6 @@ snapshots: robust-predicates@3.0.2: {} - rollup-plugin-visualizer@5.12.0(rollup@4.29.1): - dependencies: - open: 8.4.2 - picomatch: 2.3.1 - source-map: 0.7.4 - yargs: 17.7.2 - optionalDependencies: - rollup: 4.29.1 - rollup@4.29.1: dependencies: '@types/estree': 1.0.6 @@ -6756,6 +6649,8 @@ snapshots: signal-exit@4.1.0: {} + simple-git-hooks@2.11.1: {} + simple-zstd@1.4.2: dependencies: is-zst: 1.0.0 @@ -6782,8 +6677,6 @@ snapshots: source-map-js@1.2.1: {} - source-map@0.7.4: {} - splaytree@3.1.2: {} split-string@3.1.0: @@ -7102,24 +6995,10 @@ snapshots: xtend@4.0.2: {} - y18n@5.0.8: {} - yallist@4.0.0: {} yaml@2.4.5: {} - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - yocto-queue@0.1.0: {} zustand@4.5.2(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1): From cdc2554af6bae5ea589816d238ec70d5d0845061 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 27 Jan 2025 08:31:31 -0500 Subject: [PATCH 180/181] fix: update lock file --- pnpm-lock.yaml | 142 +++---------------------------------------------- 1 file changed, 6 insertions(+), 136 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 79d6d5ff..7046dba9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,9 +68,6 @@ importers: base64-js: specifier: ^1.5.1 version: 1.5.1 - class-transformer: - specifier: ^0.5.1 - version: 0.5.1 class-validator: specifier: ^0.14.1 version: 0.14.1 @@ -119,12 +116,6 @@ importers: rfc4648: specifier: ^1.5.3 version: 1.5.3 - tailwind-merge: - specifier: ^2.3.0 - version: 2.3.0 - tailwindcss-animate: - specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.4) timeago-react: specifier: ^3.0.6 version: 3.0.6(react@18.3.1) @@ -138,9 +129,6 @@ importers: '@biomejs/biome': specifier: ^1.8.2 version: 1.8.2 - '@buf/meshtastic_protobufs.bufbuild_es': - specifier: 1.10.0-20240906232734-3da561588c55.1 - version: 1.10.0-20240906232734-3da561588c55.1(@bufbuild/protobuf@1.10.0) '@rsbuild/core': specifier: ^1.0.10 version: 1.0.10 @@ -177,18 +165,18 @@ importers: postcss: specifier: ^8.4.38 version: 8.4.38 - rollup-plugin-visualizer: - specifier: ^5.12.0 - version: 5.12.0(rollup@4.29.1) + tailwind-merge: + specifier: ^2.3.0 + version: 2.3.0 tailwindcss: specifier: ^3.4.4 version: 3.4.4 + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@3.4.4) tar: specifier: ^6.2.1 version: 6.2.1 - tslib: - specifier: ^2.6.3 - version: 2.6.3 typescript: specifier: ^5.5.2 version: 5.5.2 @@ -256,11 +244,6 @@ packages: cpu: [x64] os: [win32] - '@buf/meshtastic_protobufs.bufbuild_es@1.10.0-20240906232734-3da561588c55.1': - resolution: {tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/-/meshtastic_protobufs.bufbuild_es-1.10.0-20240906232734-3da561588c55.1.tgz} - peerDependencies: - '@bufbuild/protobuf': ^1.10.0 - '@bufbuild/protobuf@1.10.0': resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} @@ -1905,19 +1888,12 @@ packages: cipher-base@1.0.4: resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} - class-transformer@0.5.1: - resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} - class-validator@0.14.1: resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==} class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} @@ -2029,10 +2005,6 @@ packages: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} - define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -2185,10 +2157,6 @@ packages: geojson-vt@4.0.2: resolution: {integrity: sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==} - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} @@ -2328,11 +2296,6 @@ packages: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} @@ -2409,10 +2372,6 @@ packages: resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} engines: {node: '>= 0.4'} - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - is-zst@1.0.0: resolution: {integrity: sha512-ZA5lvshKAl8z30dX7saXLpVhpsq3d2EHK9uf7qtUjnOtdw4XBpAoWb2RvZ5kyoaebdoidnGI0g2hn9Z7ObPbww==} @@ -2610,10 +2569,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - os-browserify@0.3.0: resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} @@ -2914,10 +2869,6 @@ packages: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - resolve-protobuf-schema@2.1.0: resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} @@ -2941,16 +2892,6 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - rollup-plugin-visualizer@5.12.0: - resolution: {integrity: sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==} - engines: {node: '>=14'} - hasBin: true - peerDependencies: - rollup: 2.x || 3.x || 4.x - peerDependenciesMeta: - rollup: - optional: true - rollup@4.29.1: resolution: {integrity: sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -3036,10 +2977,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map@0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - splaytree@3.1.2: resolution: {integrity: sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A==} @@ -3337,10 +3274,6 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -3349,14 +3282,6 @@ packages: engines: {node: '>= 14'} hasBin: true - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -3419,10 +3344,6 @@ snapshots: '@biomejs/cli-win32-x64@1.8.2': optional: true - '@buf/meshtastic_protobufs.bufbuild_es@1.10.0-20240906232734-3da561588c55.1(@bufbuild/protobuf@1.10.0)': - dependencies: - '@bufbuild/protobuf': 1.10.0 - '@bufbuild/protobuf@1.10.0': {} '@emeraldpay/hashicon-react@0.5.2': @@ -5521,8 +5442,6 @@ snapshots: inherits: 2.0.4 safe-buffer: 5.2.1 - class-transformer@0.5.1: {} - class-validator@0.14.1: dependencies: '@types/validator': 13.12.0 @@ -5533,12 +5452,6 @@ snapshots: dependencies: clsx: 2.0.0 - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - clsx@2.0.0: {} clsx@2.1.1: {} @@ -5680,8 +5593,6 @@ snapshots: es-errors: 1.3.0 gopd: 1.0.1 - define-lazy-prop@2.0.0: {} - define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -5873,8 +5784,6 @@ snapshots: geojson-vt@4.0.2: {} - get-caller-file@2.0.5: {} - get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 @@ -6023,8 +5932,6 @@ snapshots: dependencies: has-tostringtag: 1.0.2 - is-docker@2.2.1: {} - is-extendable@0.1.1: {} is-extendable@1.0.1: @@ -6090,10 +5997,6 @@ snapshots: call-bind: 1.0.7 get-intrinsic: 1.2.4 - is-wsl@2.2.0: - dependencies: - is-docker: 2.2.1 - is-zst@1.0.0: {} isarray@1.0.0: {} @@ -6328,12 +6231,6 @@ snapshots: dependencies: wrappy: 1.0.2 - open@8.4.2: - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - os-browserify@0.3.0: {} os-tmpdir@1.0.2: {} @@ -6636,8 +6533,6 @@ snapshots: es-errors: 1.3.0 set-function-name: 2.0.2 - require-directory@2.1.1: {} - resolve-protobuf-schema@2.1.0: dependencies: protocol-buffers-schema: 3.6.0 @@ -6661,15 +6556,6 @@ snapshots: robust-predicates@3.0.2: {} - rollup-plugin-visualizer@5.12.0(rollup@4.29.1): - dependencies: - open: 8.4.2 - picomatch: 2.3.1 - source-map: 0.7.4 - yargs: 17.7.2 - optionalDependencies: - rollup: 4.29.1 - rollup@4.29.1: dependencies: '@types/estree': 1.0.6 @@ -6782,8 +6668,6 @@ snapshots: source-map-js@1.2.1: {} - source-map@0.7.4: {} - splaytree@3.1.2: {} split-string@3.1.0: @@ -7102,24 +6986,10 @@ snapshots: xtend@4.0.2: {} - y18n@5.0.8: {} - yallist@4.0.0: {} yaml@2.4.5: {} - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - yocto-queue@0.1.0: {} zustand@4.5.2(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1): From 9b843f6483b791d12f696ed2a8a3aa5cecf9a58d Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Tue, 28 Jan 2025 12:15:04 -0500 Subject: [PATCH 181/181] chore: update packages to latest version. feat: replace hashicon lib with vanilla component --- package.json | 87 +- pnpm-lock.yaml | 4741 ++++++++--------- src/DeviceWrapper.tsx | 5 +- src/PageRouter.tsx | 12 +- src/components/CommandPalette.tsx | 14 +- src/components/DeviceSelector.tsx | 12 +- src/components/DeviceSelectorButton.tsx | 6 +- src/components/Form/FormSelect.tsx | 2 +- src/components/Form/FormWrapper.tsx | 6 +- .../PageComponents/Map/NodeDetail.tsx | 6 +- .../PageComponents/Messages/Message.tsx | 10 +- src/components/UI/Avatar.tsx | 94 + src/components/UI/Sidebar/SidebarSection.tsx | 4 +- src/components/generic/Table/index.tsx | 15 +- src/index.css | 1 - src/pages/Channels.tsx | 3 +- src/pages/Config/index.tsx | 4 +- src/pages/Map.tsx | 25 +- src/pages/Messages.tsx | 43 +- src/pages/Nodes.tsx | 13 +- 20 files changed, 2437 insertions(+), 2666 deletions(-) create mode 100644 src/components/UI/Avatar.tsx diff --git a/package.json b/package.json index 6dc5cce3..1c055073 100644 --- a/package.json +++ b/package.json @@ -27,65 +27,64 @@ "homepage": "https://meshtastic.org", "dependencies": { "@bufbuild/protobuf": "^1.10.0", - "@emeraldpay/hashicon-react": "^0.5.2", "@meshtastic/js": "2.3.7-5", - "@noble/curves": "^1.5.0", - "@radix-ui/react-accordion": "^1.2.0", - "@radix-ui/react-checkbox": "^1.1.0", - "@radix-ui/react-dialog": "^1.1.1", - "@radix-ui/react-dropdown-menu": "^2.1.1", - "@radix-ui/react-label": "^2.1.0", - "@radix-ui/react-menubar": "^1.1.1", - "@radix-ui/react-popover": "^1.1.1", - "@radix-ui/react-scroll-area": "^1.1.0", - "@radix-ui/react-select": "^2.1.1", - "@radix-ui/react-separator": "^1.1.0", - "@radix-ui/react-switch": "^1.1.0", - "@radix-ui/react-tabs": "^1.1.0", - "@radix-ui/react-toast": "^1.2.1", - "@radix-ui/react-tooltip": "^1.1.1", - "@turf/turf": "^6.5.0", + "@noble/curves": "^1.8.1", + "@radix-ui/react-accordion": "^1.2.2", + "@radix-ui/react-checkbox": "^1.1.3", + "@radix-ui/react-dialog": "^1.1.5", + "@radix-ui/react-dropdown-menu": "^2.1.5", + "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-menubar": "^1.1.5", + "@radix-ui/react-popover": "^1.1.5", + "@radix-ui/react-scroll-area": "^1.2.2", + "@radix-ui/react-select": "^2.1.5", + "@radix-ui/react-separator": "^1.1.1", + "@radix-ui/react-switch": "^1.1.2", + "@radix-ui/react-tabs": "^1.1.2", + "@radix-ui/react-toast": "^1.2.5", + "@radix-ui/react-tooltip": "^1.1.7", + "@turf/turf": "^7.2.0", "base64-js": "^1.5.1", "class-validator": "^0.14.1", - "class-variance-authority": "^0.7.0", + "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "cmdk": "^1.0.0", + "cmdk": "^1.0.4", "crypto-random-string": "^5.0.0", "immer": "^10.1.1", "js-cookie": "^3.0.5", - "lucide-react": "^0.363.0", - "mapbox-gl": "^3.6.0", + "lucide-react": "^0.474.0", + "mapbox-gl": "^3.9.4", "maplibre-gl": "4.1.2", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-hook-form": "^7.52.0", - "react-map-gl": "7.1.7", - "react-qrcode-logo": "^2.10.0", - "rfc4648": "^1.5.3", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-hook-form": "^7.54.2", + "react-map-gl": "7.1.9", + "react-qrcode-logo": "^3.0.0", + "rfc4648": "^1.5.4", "timeago-react": "^3.0.6", - "vite-plugin-node-polyfills": "^0.22.0", - "zustand": "4.5.2" + "vite-plugin-node-polyfills": "^0.23.0", + "zustand": "5.0.3" }, "devDependencies": { - "@biomejs/biome": "^1.8.2", - "@rsbuild/core": "^1.0.10", - "@rsbuild/plugin-react": "^1.0.3", - "@types/chrome": "^0.0.263", + "@biomejs/biome": "^1.9.4", + "@rsbuild/core": "^1.2.3", + "@rsbuild/plugin-react": "^1.1.0", + "@types/chrome": "^0.0.299", "@types/js-cookie": "^3.0.6", - "@types/node": "^20.14.9", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@types/w3c-web-serial": "^1.0.6", + "@types/node": "^22.12.0", + "@types/react": "^19.0.8", + "@types/react-dom": "^19.0.3", + "@types/w3c-web-serial": "^1.0.7", "@types/web-bluetooth": "^0.0.20", - "autoprefixer": "^10.4.19", - "gzipper": "^7.2.0", - "postcss": "^8.4.38", + "autoprefixer": "^10.4.20", + "gzipper": "^8.2.0", + "postcss": "^8.5.1", "simple-git-hooks": "^2.11.1", - "tailwind-merge": "^2.3.0", - "tailwindcss": "^3.4.4", + "tailwind-merge": "^2.6.0", + "tailwindcss": "^3.4.17", "tailwindcss-animate": "^1.0.7", - "tar": "^6.2.1", - "typescript": "^5.5.2" + "tar": "^7.4.3", + "typescript": "^5.7.3" }, "packageManager": "pnpm@9.15.4" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd65e849..f0d0f030 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,60 +11,57 @@ importers: '@bufbuild/protobuf': specifier: ^1.10.0 version: 1.10.0 - '@emeraldpay/hashicon-react': - specifier: ^0.5.2 - version: 0.5.2 '@meshtastic/js': specifier: 2.3.7-5 version: 2.3.7-5 '@noble/curves': - specifier: ^1.5.0 - version: 1.5.0 + specifier: ^1.8.1 + version: 1.8.1 '@radix-ui/react-accordion': - specifier: ^1.2.0 - version: 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^1.2.2 + version: 1.2.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@radix-ui/react-checkbox': - specifier: ^1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^1.1.3 + version: 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@radix-ui/react-dialog': - specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^1.1.5 + version: 1.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@radix-ui/react-dropdown-menu': - specifier: ^2.1.1 - version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^2.1.5 + version: 2.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@radix-ui/react-label': - specifier: ^2.1.0 - version: 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-menubar': - specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-popover': - specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-scroll-area': - specifier: ^1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-select': specifier: ^2.1.1 - version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-menubar': + specifier: ^1.1.5 + version: 1.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-popover': + specifier: ^1.1.5 + version: 1.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-scroll-area': + specifier: ^1.2.2 + version: 1.2.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-select': + specifier: ^2.1.5 + version: 2.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@radix-ui/react-separator': - specifier: ^1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-switch': - specifier: ^1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-tabs': - specifier: ^1.1.0 - version: 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-toast': - specifier: ^1.2.1 - version: 1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-tooltip': specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-switch': + specifier: ^1.1.2 + version: 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-tabs': + specifier: ^1.1.2 + version: 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-toast': + specifier: ^1.2.5 + version: 1.2.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-tooltip': + specifier: ^1.1.7 + version: 1.1.7(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@turf/turf': - specifier: ^6.5.0 - version: 6.5.0 + specifier: ^7.2.0 + version: 7.2.0 base64-js: specifier: ^1.5.1 version: 1.5.1 @@ -72,14 +69,14 @@ importers: specifier: ^0.14.1 version: 0.14.1 class-variance-authority: - specifier: ^0.7.0 - version: 0.7.0 + specifier: ^0.7.1 + version: 0.7.1 clsx: specifier: ^2.1.1 version: 2.1.1 cmdk: - specifier: ^1.0.0 - version: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^1.0.4 + version: 1.0.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) crypto-random-string: specifier: ^5.0.0 version: 5.0.0 @@ -90,99 +87,99 @@ importers: specifier: ^3.0.5 version: 3.0.5 lucide-react: - specifier: ^0.363.0 - version: 0.363.0(react@18.3.1) + specifier: ^0.474.0 + version: 0.474.0(react@19.0.0) mapbox-gl: - specifier: ^3.6.0 - version: 3.6.0 + specifier: ^3.9.4 + version: 3.9.4 maplibre-gl: specifier: 4.1.2 version: 4.1.2 react: - specifier: ^18.3.1 - version: 18.3.1 + specifier: ^19.0.0 + version: 19.0.0 react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) + specifier: ^19.0.0 + version: 19.0.0(react@19.0.0) react-hook-form: - specifier: ^7.52.0 - version: 7.52.0(react@18.3.1) + specifier: ^7.54.2 + version: 7.54.2(react@19.0.0) react-map-gl: - specifier: 7.1.7 - version: 7.1.7(mapbox-gl@3.6.0)(maplibre-gl@4.1.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 7.1.9 + version: 7.1.9(mapbox-gl@3.9.4)(maplibre-gl@4.1.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) react-qrcode-logo: - specifier: ^2.10.0 - version: 2.10.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^3.0.0 + version: 3.0.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) rfc4648: - specifier: ^1.5.3 - version: 1.5.3 + specifier: ^1.5.4 + version: 1.5.4 timeago-react: specifier: ^3.0.6 - version: 3.0.6(react@18.3.1) + version: 3.0.6(react@19.0.0) vite-plugin-node-polyfills: - specifier: ^0.22.0 - version: 0.22.0(rollup@4.29.1)(vite@5.3.6(@types/node@20.14.9)) + specifier: ^0.23.0 + version: 0.23.0(rollup@4.29.1)(vite@5.3.6(@types/node@22.12.0)) zustand: - specifier: 4.5.2 - version: 4.5.2(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1) + specifier: 5.0.3 + version: 5.0.3(@types/react@19.0.8)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.4.0(react@19.0.0)) devDependencies: '@biomejs/biome': - specifier: ^1.8.2 - version: 1.8.2 + specifier: ^1.9.4 + version: 1.9.4 '@rsbuild/core': - specifier: ^1.0.10 - version: 1.0.10 + specifier: ^1.2.3 + version: 1.2.3 '@rsbuild/plugin-react': - specifier: ^1.0.3 - version: 1.0.3(@rsbuild/core@1.0.10) + specifier: ^1.1.0 + version: 1.1.0(@rsbuild/core@1.2.3) '@types/chrome': - specifier: ^0.0.263 - version: 0.0.263 + specifier: ^0.0.299 + version: 0.0.299 '@types/js-cookie': specifier: ^3.0.6 version: 3.0.6 '@types/node': - specifier: ^20.14.9 - version: 20.14.9 + specifier: ^22.12.0 + version: 22.12.0 '@types/react': - specifier: ^18.3.3 - version: 18.3.3 + specifier: ^19.0.8 + version: 19.0.8 '@types/react-dom': - specifier: ^18.3.0 - version: 18.3.0 + specifier: ^19.0.3 + version: 19.0.3(@types/react@19.0.8) '@types/w3c-web-serial': - specifier: ^1.0.6 - version: 1.0.6 + specifier: ^1.0.7 + version: 1.0.7 '@types/web-bluetooth': specifier: ^0.0.20 version: 0.0.20 autoprefixer: - specifier: ^10.4.19 - version: 10.4.19(postcss@8.4.38) + specifier: ^10.4.20 + version: 10.4.20(postcss@8.5.1) gzipper: - specifier: ^7.2.0 - version: 7.2.0 + specifier: ^8.2.0 + version: 8.2.0 postcss: - specifier: ^8.4.38 - version: 8.4.38 + specifier: ^8.5.1 + version: 8.5.1 simple-git-hooks: specifier: ^2.11.1 version: 2.11.1 tailwind-merge: - specifier: ^2.3.0 - version: 2.3.0 + specifier: ^2.6.0 + version: 2.6.0 tailwindcss: - specifier: ^3.4.4 - version: 3.4.4 + specifier: ^3.4.17 + version: 3.4.17 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.4) + version: 1.0.7(tailwindcss@3.4.17) tar: - specifier: ^6.2.1 - version: 6.2.1 + specifier: ^7.4.3 + version: 7.4.3 typescript: - specifier: ^5.5.2 - version: 5.5.2 + specifier: ^5.7.3 + version: 5.7.3 packages: @@ -190,59 +187,55 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@babel/runtime@7.24.7': - resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==} - engines: {node: '>=6.9.0'} - - '@biomejs/biome@1.8.2': - resolution: {integrity: sha512-XafCzLgs0xbH0bCjYKxQ63ig2V86fZQMq1jiy5pyLToWk9aHxA8GAUxyBtklPHtPYZPGEPOYglQHj4jyfUp+Iw==} + '@biomejs/biome@1.9.4': + resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@1.8.2': - resolution: {integrity: sha512-l9msLsTcSIAPqMsPIhodQmb50sEfaXPLQ0YW4cdj6INmd8iaOh/V9NceQb2366vACTJgcWDQ2RzlvURek1T68g==} + '@biomejs/cli-darwin-arm64@1.9.4': + resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@1.8.2': - resolution: {integrity: sha512-Fc4y/FuIxRSiB3TJ+y27vFDE/HJt4QgBuymktsIKEcBZvnKfsRjxvzVDunccRn4xbKgepnp+fn6BoS+ZIg/I3Q==} + '@biomejs/cli-darwin-x64@1.9.4': + resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@1.8.2': - resolution: {integrity: sha512-WpT41QJJvkZa1eZq0WmD513zkC6AYaMI39HJKmKeiUeX2NZirG+bxv1YRDhqkns1NbBqo3+qrJqBkPmOW+xAVA==} + '@biomejs/cli-linux-arm64-musl@1.9.4': + resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@1.8.2': - resolution: {integrity: sha512-Q99qwP0qibkZxm2kfnt37OxeIlliDYf5ogi3zX9ij2DULzc+KtPA9Uj0wCljcJofOBsBYaHc7597Q+Bf/251ww==} + '@biomejs/cli-linux-arm64@1.9.4': + resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@1.8.2': - resolution: {integrity: sha512-rk1Wj4d3LIlAlIAS1m2jlyfOjkNbuY1lfwKvWIAeZC51yDMzwhRD7cReE5PE+jqLDtq60PX38hDPeKd7nA1S6A==} + '@biomejs/cli-linux-x64-musl@1.9.4': + resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@1.8.2': - resolution: {integrity: sha512-bjhhUVFchFid2gOjrvBe4fg8BShcpyFQTHuB/QQnfGxs1ddrGP30yq3fHfc6S6MoCcz9Tjd3Zzq1EfWfyy5iHA==} + '@biomejs/cli-linux-x64@1.9.4': + resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@1.8.2': - resolution: {integrity: sha512-EUbqmCmNWT5xhnxHrCAEBzJB1AnLqxTYoRjlxiCMzGvsy5jQzhCanJ8CT9kNsApW3pfPWBWkoTa7qrwWmwnEGA==} + '@biomejs/cli-win32-arm64@1.9.4': + resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@1.8.2': - resolution: {integrity: sha512-n9H5oRUCk1uNezMgyJh9+hZdtfD8PXLLeq8DUzTycIhl0I1BulIoZ/uxWgRVDFDwAR1JHu1AykISCRFNGnc4iA==} + '@biomejs/cli-win32-x64@1.9.4': + resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -250,14 +243,6 @@ packages: '@bufbuild/protobuf@1.10.0': resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} - '@emeraldpay/hashicon-react@0.5.2': - resolution: {integrity: sha512-XCoYKpq8QQOniiSZf5ouzdvXbKfG6q4ICHRqCO/GNofiF0Ra+LR/7+tomHlXVcLPBS9sDAoZQQw/Sr24KRAbJg==} - engines: {node: '>=8'} - - '@emeraldpay/hashicon@0.5.2': - resolution: {integrity: sha512-MNsjV+Vik+ofOYmGPcdAQW4CoSSrTE2Iq2xYNS8PxV84QrgOLTsC/pV6EWb1N/dTY9ndMV/RAAzGh6cmrZf4zA==} - engines: {node: '>=8'} - '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} @@ -419,6 +404,10 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -431,9 +420,6 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} @@ -471,31 +457,35 @@ packages: resolution: {integrity: sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==} hasBin: true - '@maplibre/maplibre-gl-style-spec@20.3.0': - resolution: {integrity: sha512-eSiQ3E5LUSxAOY9ABXGyfNhout2iEa6mUxKeaQ9nJ8NL1NuaQYU7zKqzx/LEYcXe1neT4uYAgM1wYZj3fTSXtA==} + '@maplibre/maplibre-gl-style-spec@20.4.0': + resolution: {integrity: sha512-AzBy3095fTFPjDjmWpR2w6HVRAZJ6hQZUCwk5Plz6EyfnfuQW1odeW5i2Ai47Y6TBA2hQnC+azscjBSALpaWgw==} hasBin: true '@meshtastic/js@2.3.7-5': resolution: {integrity: sha512-77wYoCl83PgRLkvWE8ko0YFm5LbolrfFPqoBkwLd2AFgZOHGsHTlUwA7cj82yhZM3f4mf7yTFxl+8CBawEAXRA==} - '@module-federation/runtime-tools@0.5.1': - resolution: {integrity: sha512-nfBedkoZ3/SWyO0hnmaxuz0R0iGPSikHZOAZ0N/dVSQaIzlffUo35B5nlC2wgWIc0JdMZfkwkjZRrnuuDIJbzg==} + '@module-federation/error-codes@0.8.4': + resolution: {integrity: sha512-55LYmrDdKb4jt+qr8qE8U3al62ZANp3FhfVaNPOaAmdTh0jHdD8M3yf5HKFlr5xVkVO4eV/F/J2NCfpbh+pEXQ==} - '@module-federation/runtime@0.5.1': - resolution: {integrity: sha512-xgiMUWwGLWDrvZc9JibuEbXIbhXg6z2oUkemogSvQ4LKvrl/n0kbqP1Blk669mXzyWbqtSp6PpvNdwaE1aN5xQ==} + '@module-federation/runtime-tools@0.8.4': + resolution: {integrity: sha512-fjVOsItJ1u5YY6E9FnS56UDwZgqEQUrWFnouRiPtK123LUuqUI9FH4redZoKWlE1PB0ir1Z3tnqy8eFYzPO38Q==} - '@module-federation/sdk@0.5.1': - resolution: {integrity: sha512-exvchtjNURJJkpqjQ3/opdbfeT2wPKvrbnGnyRkrwW5o3FH1LaST1tkiNviT6OXTexGaVc2DahbdniQHVtQ7pA==} + '@module-federation/runtime@0.8.4': + resolution: {integrity: sha512-yZeZ7z2Rx4gv/0E97oLTF3V6N25vglmwXGgoeju/W2YjsFvWzVtCDI7zRRb0mJhU6+jmSM8jP1DeQGbea/AiZQ==} - '@module-federation/webpack-bundler-runtime@0.5.1': - resolution: {integrity: sha512-mMhRFH0k2VjwHt3Jol9JkUsmI/4XlrAoBG3E0o7HoyoPYv1UFOWyqAflfANcUPgbYpvqmyLzDcO+3IT36LXnrA==} + '@module-federation/sdk@0.8.4': + resolution: {integrity: sha512-waABomIjg/5m1rPDBWYG4KUhS5r7OUUY7S+avpaVIY/tkPWB3ibRDKy2dNLLAMaLKq0u+B1qIdEp4NIWkqhqpg==} - '@noble/curves@1.5.0': - resolution: {integrity: sha512-J5EKamIHnKPyClwVrzmaf5wSdQXgdHcPZIZLu3bwnbeCx8/7NPK5q2ZBWF+5FvYGByjiQQsJYX6jfgB2wDPn3A==} + '@module-federation/webpack-bundler-runtime@0.8.4': + resolution: {integrity: sha512-HggROJhvHPUX7uqBD/XlajGygMNM1DG0+4OAkk8MBQe4a18QzrRNzZt6XQbRTSG4OaEoyRWhQHvYD3Yps405tQ==} - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} + '@noble/curves@1.8.1': + resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.7.1': + resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} + engines: {node: ^14.21.3 || >=16} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -516,14 +506,11 @@ packages: '@radix-ui/number@1.1.0': resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==} - '@radix-ui/primitive@1.0.1': - resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} + '@radix-ui/primitive@1.1.1': + resolution: {integrity: sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==} - '@radix-ui/primitive@1.1.0': - resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} - - '@radix-ui/react-accordion@1.2.0': - resolution: {integrity: sha512-HJOzSX8dQqtsp/3jVxCU3CXEONF7/2jlGAB28oX8TTw1Dz8JYbEI1UcL8355PuLBE41/IRRMvCw7VkiK/jcUOQ==} + '@radix-ui/react-accordion@1.2.2': + resolution: {integrity: sha512-b1oh54x4DMCdGsB4/7ahiSrViXxaBwRPotiZNnYXjLha9vfuURSAZErki6qjDoSIV0eXx5v57XnTGVtGwnfp2g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -535,8 +522,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-arrow@1.1.0': - resolution: {integrity: sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==} + '@radix-ui/react-arrow@1.1.1': + resolution: {integrity: sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -548,8 +535,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-checkbox@1.1.0': - resolution: {integrity: sha512-3+kSzVfMONtP3B6CvaOrXLVTyGYws7tGmG5kOY0AfyH9sexkLytIwciNwjZhY0RoGOEbxI7bMS21XYB8H5itWQ==} + '@radix-ui/react-checkbox@1.1.3': + resolution: {integrity: sha512-HD7/ocp8f1B3e6OHygH0n7ZKjONkhciy1Nh0yuBgObqThc3oyx+vuMfFHKAknXRHHWVE9XvXStxJFyjUmB8PIw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -561,8 +548,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collapsible@1.1.0': - resolution: {integrity: sha512-zQY7Epa8sTL0mq4ajSJpjgn2YmCgyrG7RsQgLp3C0LQVkG7+Tf6Pv1CeNWZLyqMjhdPkBa5Lx7wYBeSu7uCSTA==} + '@radix-ui/react-collapsible@1.1.2': + resolution: {integrity: sha512-PliMB63vxz7vggcyq0IxNYk8vGDrLXVWw4+W4B8YnwI1s18x7YZYqlG9PLX7XxAJUi0g2DxP4XKJMFHh/iVh9A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -574,8 +561,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collection@1.1.0': - resolution: {integrity: sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==} + '@radix-ui/react-collection@1.1.1': + resolution: {integrity: sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -587,15 +574,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-compose-refs@1.0.1': - resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-compose-refs@1.1.0': resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==} peerDependencies: @@ -605,17 +583,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-context@1.0.1': - resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-context@1.1.0': - resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==} + '@radix-ui/react-compose-refs@1.1.1': + resolution: {integrity: sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -623,21 +592,17 @@ packages: '@types/react': optional: true - '@radix-ui/react-dialog@1.0.5': - resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==} + '@radix-ui/react-context@1.1.1': + resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} peerDependencies: '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-dialog@1.1.1': - resolution: {integrity: sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==} + '@radix-ui/react-dialog@1.1.5': + resolution: {integrity: sha512-LaO3e5h/NOEL4OfXjxD43k9Dx+vn+8n+PCFt6uhX/BADFflllyv3WJG6rgvvSVBxpTch938Qq/LGc2MMxipXPw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -658,21 +623,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-dismissable-layer@1.0.5': - resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-dismissable-layer@1.1.0': - resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==} + '@radix-ui/react-dismissable-layer@1.1.4': + resolution: {integrity: sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -684,8 +636,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.1': - resolution: {integrity: sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==} + '@radix-ui/react-dropdown-menu@2.1.5': + resolution: {integrity: sha512-50ZmEFL1kOuLalPKHrLWvPFMons2fGx9TqQCWlPwDVpbAnaUJ1g4XNcKqFNMQymYU0kKWR4MDDi+9vUQBGFgcQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -697,17 +649,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-focus-guards@1.0.1': - resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-focus-guards@1.1.0': - resolution: {integrity: sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==} + '@radix-ui/react-focus-guards@1.1.1': + resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -715,21 +658,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-focus-scope@1.0.4': - resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-focus-scope@1.1.0': - resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==} + '@radix-ui/react-focus-scope@1.1.1': + resolution: {integrity: sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -741,15 +671,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-id@1.0.1': - resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-id@1.1.0': resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} peerDependencies: @@ -759,8 +680,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-label@2.1.0': - resolution: {integrity: sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==} + '@radix-ui/react-label@2.1.1': + resolution: {integrity: sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -772,8 +693,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-menu@2.1.1': - resolution: {integrity: sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ==} + '@radix-ui/react-menu@2.1.5': + resolution: {integrity: sha512-uH+3w5heoMJtqVCgYOtYVMECk1TOrkUn0OG0p5MqXC0W2ppcuVeESbou8PTHoqAjbdTEK19AGXBWcEtR5WpEQg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -785,8 +706,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-menubar@1.1.1': - resolution: {integrity: sha512-V05Hryq/BE2m+rs8d5eLfrS0jmSWSDHEbG7jEyLA5D5J9jTvWj/o3v3xDN9YsOlH6QIkJgiaNDaP+S4T1rdykw==} + '@radix-ui/react-menubar@1.1.5': + resolution: {integrity: sha512-Kzbpcf2bxUmI/G+949+LvSvGkyzIaY7ctb8loydt6YpJR8pQF+j4QbVhYvjs7qxaWK0DEJL3XbP2p46YPRkS3A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -798,8 +719,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popover@1.1.1': - resolution: {integrity: sha512-3y1A3isulwnWhvTTwmIreiB8CF4L+qRjZnK1wYLO7pplddzXKby/GnZ2M7OZY3qgnl6p9AodUIHRYGXNah8Y7g==} + '@radix-ui/react-popover@1.1.5': + resolution: {integrity: sha512-YXkTAftOIW2Bt3qKH8vYr6n9gCkVrvyvfiTObVjoHVTHnNj26rmvO87IKa3VgtgCjb8FAQ6qOjNViwl+9iIzlg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -811,8 +732,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popper@1.2.0': - resolution: {integrity: sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==} + '@radix-ui/react-popper@1.2.1': + resolution: {integrity: sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -824,21 +745,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-portal@1.0.4': - resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-portal@1.1.1': - resolution: {integrity: sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==} + '@radix-ui/react-portal@1.1.3': + resolution: {integrity: sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -850,21 +758,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-presence@1.0.1': - resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-presence@1.1.0': - resolution: {integrity: sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==} + '@radix-ui/react-presence@1.1.2': + resolution: {integrity: sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -876,19 +771,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-primitive@1.0.3': - resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-primitive@2.0.0': resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==} peerDependencies: @@ -902,8 +784,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-roving-focus@1.1.0': - resolution: {integrity: sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==} + '@radix-ui/react-primitive@2.0.1': + resolution: {integrity: sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -915,8 +797,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-scroll-area@1.1.0': - resolution: {integrity: sha512-9ArIZ9HWhsrfqS765h+GZuLoxaRHD/j0ZWOWilsCvYTpYJp8XwCqNG7Dt9Nu/TItKOdgLGkOPCodQvDc+UMwYg==} + '@radix-ui/react-roving-focus@1.1.1': + resolution: {integrity: sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -928,8 +810,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-select@2.1.1': - resolution: {integrity: sha512-8iRDfyLtzxlprOo9IicnzvpsO1wNCkuwzzCM+Z5Rb5tNOpCdMvcc2AkzX0Fz+Tz9v6NJ5B/7EEgyZveo4FBRfQ==} + '@radix-ui/react-scroll-area@1.2.2': + resolution: {integrity: sha512-EFI1N/S3YxZEW/lJ/H1jY3njlvTd8tBmgKEn4GHi51+aMm94i6NmAJstsm5cu3yJwYqYc93gpCPm21FeAbFk6g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -941,8 +823,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-separator@1.1.0': - resolution: {integrity: sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==} + '@radix-ui/react-select@2.1.5': + resolution: {integrity: sha512-eVV7N8jBXAXnyrc+PsOF89O9AfVgGnbLxUtBb0clJ8y8ENMWLARGMI/1/SBRLz7u4HqxLgN71BJ17eono3wcjA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -954,14 +836,18 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-slot@1.0.2': - resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} + '@radix-ui/react-separator@1.1.1': + resolution: {integrity: sha512-RRiNRSrD8iUiXriq/Y5n4/3iE8HzqgLHsusUSg5jVpU2+3tqcUFPJXHDymwEypunc2sWxDUS3UC+rkZRlHedsw==} peerDependencies: '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true + '@types/react-dom': + optional: true '@radix-ui/react-slot@1.1.0': resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} @@ -972,8 +858,17 @@ packages: '@types/react': optional: true - '@radix-ui/react-switch@1.1.0': - resolution: {integrity: sha512-OBzy5WAj641k0AOSpKQtreDMe+isX0MQJ1IVyF03ucdF3DunOnROVrjWs8zsXUxC3zfZ6JL9HFVCUlMghz9dJw==} + '@radix-ui/react-slot@1.1.1': + resolution: {integrity: sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-switch@1.1.2': + resolution: {integrity: sha512-zGukiWHjEdBCRyXvKR6iXAQG6qXm2esuAD6kDOi9Cn+1X6ev3ASo4+CsYaD6Fov9r/AQFekqnD/7+V0Cs6/98g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -985,8 +880,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tabs@1.1.0': - resolution: {integrity: sha512-bZgOKB/LtZIij75FSuPzyEti/XBhJH52ExgtdVqjCIh+Nx/FW+LhnbXtbCzIi34ccyMsyOja8T0thCzoHFXNKA==} + '@radix-ui/react-tabs@1.1.2': + resolution: {integrity: sha512-9u/tQJMcC2aGq7KXpGivMm1mgq7oRJKXphDwdypPd/j21j/2znamPU8WkXgnhUaTrSFNIt8XhOyCAupg8/GbwQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -998,8 +893,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-toast@1.2.1': - resolution: {integrity: sha512-5trl7piMXcZiCq7MW6r8YYmu0bK5qDpTWz+FdEPdKyft2UixkspheYbjbrLXVN5NGKHFbOP7lm8eD0biiSqZqg==} + '@radix-ui/react-toast@1.2.5': + resolution: {integrity: sha512-ZzUsAaOx8NdXZZKcFNDhbSlbsCUy8qQWmzTdgrlrhhZAOx2ofLtKrBDW9fkqhFvXgmtv560Uj16pkLkqML7SHA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1011,8 +906,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tooltip@1.1.1': - resolution: {integrity: sha512-LLE8nzNE4MzPMw3O2zlVlkLFid3y9hMUs7uCbSHyKSo+tCN4yMCf+ZCCcfrYgsOC0TiHBPQ1mtpJ2liY3ZT3SQ==} + '@radix-ui/react-tooltip@1.1.7': + resolution: {integrity: sha512-ss0s80BC0+g0+Zc53MvilcnTYSOi4mSuFWBPYPuTOFGjx+pUU+ZrmamMNwS56t8MTFlniA5ocjd4jYm/CdhbOg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1024,15 +919,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-use-callback-ref@1.0.1': - resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-use-callback-ref@1.1.0': resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} peerDependencies: @@ -1042,15 +928,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-controllable-state@1.0.1': - resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-use-controllable-state@1.1.0': resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} peerDependencies: @@ -1060,15 +937,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-escape-keydown@1.0.3': - resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-use-escape-keydown@1.1.0': resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} peerDependencies: @@ -1078,15 +946,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-layout-effect@1.0.1': - resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-use-layout-effect@1.1.0': resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} peerDependencies: @@ -1123,8 +982,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-visually-hidden@1.1.0': - resolution: {integrity: sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==} + '@radix-ui/react-visually-hidden@1.1.1': + resolution: {integrity: sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1252,70 +1111,73 @@ packages: cpu: [x64] os: [win32] - '@rsbuild/core@1.0.10': - resolution: {integrity: sha512-617N8YzDeH5vymeeOyCqK0toO9yt7s2yey49OIvW9jZqBo0IvgbkFNQf34LDLsxVzy+cpf1nGrcYWjPKhVuGfQ==} + '@rsbuild/core@1.2.3': + resolution: {integrity: sha512-lUCt8gQe9E2PI3srcEJ1Na3GQYmsYuvAqK0f/k00HM0pEjrbOFC9Xq2kR85UoXHFqlTCIw/fLLDe91PKRCbKAw==} engines: {node: '>=16.7.0'} hasBin: true - '@rsbuild/plugin-react@1.0.3': - resolution: {integrity: sha512-HVfPiKINmDsIcLLs7YWAYQgzytVZOydBuPOFg5EoJiMHkFVjH0Rg3QViS3Hn6k3INqdc6ylpcYyOHHYItEIkWA==} + '@rsbuild/plugin-react@1.1.0': + resolution: {integrity: sha512-uqdRoV2V91G1XIA14dAmxqYTlTDVf0ktpE7TgwG29oQ2j+DerF1kh29WPHK9HvGE34JTfaBrsme2Zmb6bGD0cw==} peerDependencies: - '@rsbuild/core': 1.x || ^1.0.1-rc.0 + '@rsbuild/core': 1.x - '@rspack/binding-darwin-arm64@1.0.8': - resolution: {integrity: sha512-1l8/eg3HNz53DHQO3fy5O5QKdYh8hSMZaWGtm3NR5IfdrTm2TaLL9tuR8oL2iHHtd87LEvVKHXdjlcuLV5IPNQ==} + '@rspack/binding-darwin-arm64@1.2.2': + resolution: {integrity: sha512-h23F8zEkXWhwMeScm0ZnN78Zh7hCDalxIWsm7bBS0eKadnlegUDwwCF8WE+8NjWr7bRzv0p3QBWlS5ufkcL4eA==} cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-x64@1.0.8': - resolution: {integrity: sha512-7BbG8gXVWjtqJegDpsObzM/B90Eig1piEtcahvPdvlC92uZz3/IwtKPpMaywGBrf5RSI3U0nQMSekwz0cO1SOw==} + '@rspack/binding-darwin-x64@1.2.2': + resolution: {integrity: sha512-vG5s7FkEvwrGLfksyDRHwKAHUkhZt1zHZZXJQn4gZKjTBonje8ezdc7IFlDiWpC4S+oBYp73nDWkUzkGRbSdcQ==} cpu: [x64] os: [darwin] - '@rspack/binding-linux-arm64-gnu@1.0.8': - resolution: {integrity: sha512-QnqCL0wmwYqT/IFx5q0aw7DsIOr8oYUa4+7JI8iiqRf3RuuRJExesVW9VuWr0jS2UvChKgmb8PvRtDy/0tshFw==} + '@rspack/binding-linux-arm64-gnu@1.2.2': + resolution: {integrity: sha512-VykY/kiYOzO8E1nYzfJ9+gQEHxb5B6lt5wa8M6xFi5B6jEGU+OsaGskmAZB9/GFImeFDHxDPvhUalI4R9p8O2Q==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@1.0.8': - resolution: {integrity: sha512-Ns9TsE7zdUjimW5HURRW08BaMyAh16MDh97PPsGEMeRPx9plnRO9aXvuUG6t+0gy4KwlQdeq3BvUsbBpIo5Tow==} + '@rspack/binding-linux-arm64-musl@1.2.2': + resolution: {integrity: sha512-Z5vAC4wGfXi8XXZ6hs8Q06TYjr3zHf819HB4DI5i4C1eQTeKdZSyoFD0NHFG23bP4NWJffp8KhmoObcy9jBT5Q==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-x64-gnu@1.0.8': - resolution: {integrity: sha512-lfqUuKCoyRN/gGeokhX/oNYqB6OpbtgQb57b0QuD8IaiH2a1ee0TtEVvRbyQNEDwht6lW4RTNg0RfMYu52LgXg==} + '@rspack/binding-linux-x64-gnu@1.2.2': + resolution: {integrity: sha512-o3pDaL+cH5EeRbDE9gZcdZpBgp5iXvYZBBhe8vZQllYgI4zN5MJEuleV7WplG3UwTXlgZg3Kht4RORSOPn96vg==} cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@1.0.8': - resolution: {integrity: sha512-MgbHJWV5utVa1/U9skrXClydZ/eZw001++v4B6nb8myU6Ck1D02aMl9ESefb/sSA8TatLLxEXQ2VENG9stnPwQ==} + '@rspack/binding-linux-x64-musl@1.2.2': + resolution: {integrity: sha512-RE3e0xe4DdchHssttKzryDwjLkbrNk/4H59TkkWeGYJcLw41tmcOZVFQUOwKLUvXWVyif/vjvV/w1SMlqB4wQg==} cpu: [x64] os: [linux] - '@rspack/binding-win32-arm64-msvc@1.0.8': - resolution: {integrity: sha512-3NN5VisnSOzhgqX77O/7NvcjPUueg1oIdMKoc5vElJCEu5FEXPqDhwZmr1PpBovaXshAcgExF3j54+20pwdg5g==} + '@rspack/binding-win32-arm64-msvc@1.2.2': + resolution: {integrity: sha512-R+PKBYn6uzTaDdVqTHvjqiJPBr5ZHg1wg5UmFDLNH9OklzVFyQh1JInSdJRb7lzfzTRz6bEkkwUFBPQK/CGScw==} cpu: [arm64] os: [win32] - '@rspack/binding-win32-ia32-msvc@1.0.8': - resolution: {integrity: sha512-17VQNC7PSygzsipSVoukDM/SOcVueVNsk9bZiB0Swl20BaqrlBts2Dvlmo+L+ZGsxOYI97WvA/zomMDv860usg==} + '@rspack/binding-win32-ia32-msvc@1.2.2': + resolution: {integrity: sha512-dBqz3sRAGZ2f31FgzKLDvIRfq2haRP3X3XVCT0PsiMcvt7QJng+26aYYMy2THatd/nM8IwExYeitHWeiMBoruw==} cpu: [ia32] os: [win32] - '@rspack/binding-win32-x64-msvc@1.0.8': - resolution: {integrity: sha512-Vtjt74Soh09XUsV5Nw0YjZVSk/qtsjtPnzbSZluncSAVUs8l+X1ALcM6n1Jrt3TLTfcqf7a+VIsWOXAMqkCGUg==} + '@rspack/binding-win32-x64-msvc@1.2.2': + resolution: {integrity: sha512-eeAvaN831KG553cMSHkVldyk6YQn4ujgRHov6r1wtREq7CD3/ka9LMkJUepCN85K7XtwYT0N4KpFIQyf5GTGoA==} cpu: [x64] os: [win32] - '@rspack/binding@1.0.8': - resolution: {integrity: sha512-abRirbrjobcllLAamyeiWxT6Rb0wELUnITynQdqRbSweWm2lvnhm9YBv4BcOjvJBzhJtvRJo5JBtbKXjDTarug==} + '@rspack/binding@1.2.2': + resolution: {integrity: sha512-GCZwpGFYlLTdJ2soPLwjw9z4LSZ+GdpbHNfBt3Cm/f/bAF8n6mZc7dHUqN893RFh7MPU17HNEL3fMw7XR+6pHg==} - '@rspack/core@1.0.8': - resolution: {integrity: sha512-pbXwXYb4WQwb0l35P5v3l/NpDJXy1WiVE4IcQ/6LxZYU5NyZuqtsK0trR88xIVRZb9qU0JUeCdQq7Xa6Q+c3Xw==} + '@rspack/core@1.2.2': + resolution: {integrity: sha512-EeHAmY65Uj62hSbUKesbrcWGE7jfUI887RD03G++Gj8jS4WPHEu1TFODXNOXg6pa7zyIvs2BK0Bm16Kwz8AEaQ==} engines: {node: '>=16.0.0'} peerDependencies: + '@rspack/tracing': ^1.x '@swc/helpers': '>=0.5.1' peerDependenciesMeta: + '@rspack/tracing': + optional: true '@swc/helpers': optional: true @@ -1331,350 +1193,359 @@ packages: react-refresh: optional: true - '@stablelib/binary@1.0.1': - resolution: {integrity: sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==} + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@stablelib/blake2s@1.0.1': - resolution: {integrity: sha512-Nnp7ULL65b4zEOkf3IdfL74xHhZXMCg7HBjBYO666a0o+DIY6GDEhUCqH6dws8nsSZgZO+V5+s2VyYKKGdFMZw==} + '@turf/along@7.2.0': + resolution: {integrity: sha512-Cf+d2LozABdb0TJoIcJwFKB+qisJY4nMUW9z6PAuZ9UCH7AR//hy2Z06vwYCKFZKP4a7DRPkOMBadQABCyoYuw==} - '@stablelib/hash@1.0.1': - resolution: {integrity: sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg==} + '@turf/angle@7.2.0': + resolution: {integrity: sha512-b28rs1NO8Dt/MXadFhnpqH7GnEWRsl+xF5JeFtg9+eM/+l/zGrdliPYMZtAj12xn33w22J1X4TRprAI0rruvVQ==} - '@stablelib/int@1.0.1': - resolution: {integrity: sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==} + '@turf/area@7.2.0': + resolution: {integrity: sha512-zuTTdQ4eoTI9nSSjerIy4QwgvxqwJVciQJ8tOPuMHbXJ9N/dNjI7bU8tasjhxas/Cx3NE9NxVHtNpYHL0FSzoA==} - '@stablelib/wipe@1.0.1': - resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} + '@turf/bbox-clip@7.2.0': + resolution: {integrity: sha512-q6RXTpqeUQAYLAieUL1n3J6ukRGsNVDOqcYtfzaJbPW+0VsAf+1cI16sN700t0sekbeU1DH/RRVAHhpf8+36wA==} - '@swc/helpers@0.5.13': - resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} + '@turf/bbox-polygon@7.2.0': + resolution: {integrity: sha512-Aj4G1GAAy26fmOqMjUk0Z+Lcax5VQ9g1xYDbHLQWXvfTsaueBT+RzdH6XPnZ/seEEnZkio2IxE8V5af/osupgA==} - '@turf/along@6.5.0': - resolution: {integrity: sha512-LLyWQ0AARqJCmMcIEAXF4GEu8usmd4Kbz3qk1Oy5HoRNpZX47+i5exQtmIWKdqJ1MMhW26fCTXgpsEs5zgJ5gw==} + '@turf/bbox@7.2.0': + resolution: {integrity: sha512-wzHEjCXlYZiDludDbXkpBSmv8Zu6tPGLmJ1sXQ6qDwpLE1Ew3mcWqt8AaxfTP5QwDNQa3sf2vvgTEzNbPQkCiA==} - '@turf/angle@6.5.0': - resolution: {integrity: sha512-4pXMbWhFofJJAOvTMCns6N4C8CMd5Ih4O2jSAG9b3dDHakj3O4yN1+Zbm+NUei+eVEZ9gFeVp9svE3aMDenIkw==} + '@turf/bearing@7.2.0': + resolution: {integrity: sha512-Jm0Xt3GgHjRrWvBtAGvgfnADLm+4exud2pRlmCYx8zfiKuNXQFkrcTZcOiJOgTfG20Agq28iSh15uta47jSIbg==} - '@turf/area@6.5.0': - resolution: {integrity: sha512-xCZdiuojokLbQ+29qR6qoMD89hv+JAgWjLrwSEWL+3JV8IXKeNFl6XkEJz9HGkVpnXvQKJoRz4/liT+8ZZ5Jyg==} + '@turf/bezier-spline@7.2.0': + resolution: {integrity: sha512-7BPkc3ufYB9KLvcaTpTsnpXzh9DZoENxCS0Ms9XUwuRXw45TpevwUpOsa3atO76iKQ5puHntqFO4zs8IUxBaaA==} - '@turf/bbox-clip@6.5.0': - resolution: {integrity: sha512-F6PaIRF8WMp8EmgU/Ke5B1Y6/pia14UAYB5TiBC668w5rVVjy5L8rTm/m2lEkkDMHlzoP9vNY4pxpNthE7rLcQ==} + '@turf/boolean-clockwise@7.2.0': + resolution: {integrity: sha512-0fJeFSARxy6ealGBM4Gmgpa1o8msQF87p2Dx5V6uSqzT8VPDegX1NSWl4b7QgXczYa9qv7IAABttdWP0K7Q7eQ==} - '@turf/bbox-polygon@6.5.0': - resolution: {integrity: sha512-+/r0NyL1lOG3zKZmmf6L8ommU07HliP4dgYToMoTxqzsWzyLjaj/OzgQ8rBmv703WJX+aS6yCmLuIhYqyufyuw==} + '@turf/boolean-concave@7.2.0': + resolution: {integrity: sha512-v3dTN04dfO6VqctQj1a+pjDHb6+/Ev90oAR2QjJuAntY4ubhhr7vKeJdk/w+tWNSMKULnYwfe65Du3EOu3/TeA==} - '@turf/bbox@6.5.0': - resolution: {integrity: sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==} + '@turf/boolean-contains@7.2.0': + resolution: {integrity: sha512-dgRQm4uVO5XuLee4PLVH7CFQZKdefUBMIXTPITm2oRIDmPLJKHDOFKQTNkGJ73mDKKBR2lmt6eVH3br6OYrEYg==} - '@turf/bearing@6.5.0': - resolution: {integrity: sha512-dxINYhIEMzgDOztyMZc20I7ssYVNEpSv04VbMo5YPQsqa80KO3TFvbuCahMsCAW5z8Tncc8dwBlEFrmRjJG33A==} + '@turf/boolean-crosses@7.2.0': + resolution: {integrity: sha512-9GyM4UUWFKQOoNhHVSfJBf5XbPy8Fxfz9djjJNAnm/IOl8NmFUSwFPAjKlpiMcr6yuaAoc9R/1KokS9/eLqPvA==} - '@turf/bezier-spline@6.5.0': - resolution: {integrity: sha512-vokPaurTd4PF96rRgGVm6zYYC5r1u98ZsG+wZEv9y3kJTuJRX/O3xIY2QnTGTdbVmAJN1ouOsD0RoZYaVoXORQ==} + '@turf/boolean-disjoint@7.2.0': + resolution: {integrity: sha512-xdz+pYKkLMuqkNeJ6EF/3OdAiJdiHhcHCV0ykX33NIuALKIEpKik0+NdxxNsZsivOW6keKwr61SI+gcVtHYcnQ==} - '@turf/boolean-clockwise@6.5.0': - resolution: {integrity: sha512-45+C7LC5RMbRWrxh3Z0Eihsc8db1VGBO5d9BLTOAwU4jR6SgsunTfRWR16X7JUwIDYlCVEmnjcXJNi/kIU3VIw==} + '@turf/boolean-equal@7.2.0': + resolution: {integrity: sha512-TmjKYLsxXqEmdDtFq3QgX4aSogiISp3/doeEtDOs3NNSR8susOtBEZkmvwO6DLW+g/rgoQJIBR6iVoWiRqkBxw==} - '@turf/boolean-contains@6.5.0': - resolution: {integrity: sha512-4m8cJpbw+YQcKVGi8y0cHhBUnYT+QRfx6wzM4GI1IdtYH3p4oh/DOBJKrepQyiDzFDaNIjxuWXBh0ai1zVwOQQ==} + '@turf/boolean-intersects@7.2.0': + resolution: {integrity: sha512-GLRyLQgK3F14drkK5Qi9Mv7Z9VT1bgQUd9a3DB3DACTZWDSwfh8YZUFn/HBwRkK8dDdgNEXaavggQHcPi1k9ow==} - '@turf/boolean-crosses@6.5.0': - resolution: {integrity: sha512-gvshbTPhAHporTlQwBJqyfW+2yV8q/mOTxG6PzRVl6ARsqNoqYQWkd4MLug7OmAqVyBzLK3201uAeBjxbGw0Ng==} + '@turf/boolean-overlap@7.2.0': + resolution: {integrity: sha512-ieM5qIE4anO+gUHIOvEN7CjyowF+kQ6v20/oNYJCp63TVS6eGMkwgd+I4uMzBXfVW66nVHIXjODdUelU+Xyctw==} - '@turf/boolean-disjoint@6.5.0': - resolution: {integrity: sha512-rZ2ozlrRLIAGo2bjQ/ZUu4oZ/+ZjGvLkN5CKXSKBcu6xFO6k2bgqeM8a1836tAW+Pqp/ZFsTA5fZHsJZvP2D5g==} + '@turf/boolean-parallel@7.2.0': + resolution: {integrity: sha512-iOtuzzff8nmwv05ROkSvyeGLMrfdGkIi+3hyQ+DH4IVyV37vQbqR5oOJ0Nt3Qq1Tjrq9fvF8G3OMdAv3W2kY9w==} - '@turf/boolean-equal@6.5.0': - resolution: {integrity: sha512-cY0M3yoLC26mhAnjv1gyYNQjn7wxIXmL2hBmI/qs8g5uKuC2hRWi13ydufE3k4x0aNRjFGlg41fjoYLwaVF+9Q==} + '@turf/boolean-point-in-polygon@7.2.0': + resolution: {integrity: sha512-lvEOjxeXIp+wPXgl9kJA97dqzMfNexjqHou+XHVcfxQgolctoJiRYmcVCWGpiZ9CBf/CJha1KmD1qQoRIsjLaA==} - '@turf/boolean-intersects@6.5.0': - resolution: {integrity: sha512-nIxkizjRdjKCYFQMnml6cjPsDOBCThrt+nkqtSEcxkKMhAQj5OO7o2CecioNTaX8EayqwMGVKcsz27oP4mKPTw==} + '@turf/boolean-point-on-line@7.2.0': + resolution: {integrity: sha512-H/bXX8+2VYeSyH8JWrOsu8OGmeA9KVZfM7M6U5/fSqGsRHXo9MyYJ94k39A9kcKSwI0aWiMXVD2UFmiWy8423Q==} - '@turf/boolean-overlap@6.5.0': - resolution: {integrity: sha512-8btMIdnbXVWUa1M7D4shyaSGxLRw6NjMcqKBcsTXcZdnaixl22k7ar7BvIzkaRYN3SFECk9VGXfLncNS3ckQUw==} + '@turf/boolean-touches@7.2.0': + resolution: {integrity: sha512-8qb1CO+cwFATGRGFgTRjzL9aibfsbI91pdiRl7KIEkVdeN/H9k8FDrUA1neY7Yq48IaciuwqjbbojQ16FD9b0w==} - '@turf/boolean-parallel@6.5.0': - resolution: {integrity: sha512-aSHJsr1nq9e5TthZGZ9CZYeXklJyRgR5kCLm5X4urz7+MotMOp/LsGOsvKvK9NeUl9+8OUmfMn8EFTT8LkcvIQ==} + '@turf/boolean-valid@7.2.0': + resolution: {integrity: sha512-xb7gdHN8VV6ivPJh6rPpgxmAEGReiRxqY+QZoEZVGpW2dXcmU1BdY6FA6G/cwvggXAXxJBREoANtEDgp/0ySbA==} - '@turf/boolean-point-in-polygon@6.5.0': - resolution: {integrity: sha512-DtSuVFB26SI+hj0SjrvXowGTUCHlgevPAIsukssW6BG5MlNSBQAo70wpICBNJL6RjukXg8d2eXaAWuD/CqL00A==} + '@turf/boolean-within@7.2.0': + resolution: {integrity: sha512-zB3AiF59zQZ27Dp1iyhp9mVAKOFHat8RDH45TZhLY8EaqdEPdmLGvwMFCKfLryQcUDQvmzP8xWbtUR82QM5C4g==} - '@turf/boolean-point-on-line@6.5.0': - resolution: {integrity: sha512-A1BbuQ0LceLHvq7F/P7w3QvfpmZqbmViIUPHdNLvZimFNLo4e6IQunmzbe+8aSStH9QRZm3VOflyvNeXvvpZEQ==} + '@turf/buffer@7.2.0': + resolution: {integrity: sha512-QH1FTr5Mk4z1kpQNztMD8XBOZfpOXPOtlsxaSAj2kDIf5+LquA6HtJjZrjUngnGtzG5+XwcfyRL4ImvLnFjm5Q==} - '@turf/boolean-within@6.5.0': - resolution: {integrity: sha512-YQB3oU18Inx35C/LU930D36RAVe7LDXk1kWsQ8mLmuqYn9YdPsDQTMTkLJMhoQ8EbN7QTdy333xRQ4MYgToteQ==} + '@turf/center-mean@7.2.0': + resolution: {integrity: sha512-NaW6IowAooTJ35O198Jw3U4diZ6UZCCeJY+4E+WMLpks3FCxMDSHEfO2QjyOXQMGWZnVxVelqI5x9DdniDbQ+A==} - '@turf/buffer@6.5.0': - resolution: {integrity: sha512-qeX4N6+PPWbKqp1AVkBVWFerGjMYMUyencwfnkCesoznU6qvfugFHNAngNqIBVnJjZ5n8IFyOf+akcxnrt9sNg==} + '@turf/center-median@7.2.0': + resolution: {integrity: sha512-/CgVyHNG4zAoZpvkl7qBCe4w7giWNVtLyTU5PoIfg1vWM4VpYw+N7kcBBH46bbzvVBn0vhmZr586r543EwdC/A==} - '@turf/center-mean@6.5.0': - resolution: {integrity: sha512-AAX6f4bVn12pTVrMUiB9KrnV94BgeBKpyg3YpfnEbBpkN/znfVhL8dG8IxMAxAoSZ61Zt9WLY34HfENveuOZ7Q==} + '@turf/center-of-mass@7.2.0': + resolution: {integrity: sha512-ij3pmG61WQPHGTQvOziPOdIgwTMegkYTwIc71Gl7xn4C0vWH6KLDSshCphds9xdWSXt2GbHpUs3tr4XGntHkEQ==} - '@turf/center-median@6.5.0': - resolution: {integrity: sha512-dT8Ndu5CiZkPrj15PBvslpuf01ky41DEYEPxS01LOxp5HOUHXp1oJxsPxvc+i/wK4BwccPNzU1vzJ0S4emd1KQ==} + '@turf/center@7.2.0': + resolution: {integrity: sha512-UTNp9abQ2kuyRg5gCIGDNwwEQeF3NbpYsd1Q0KW9lwWuzbLVNn0sOwbxjpNF4J2HtMOs5YVOcqNvYyuoa2XrXw==} - '@turf/center-of-mass@6.5.0': - resolution: {integrity: sha512-EWrriU6LraOfPN7m1jZi+1NLTKNkuIsGLZc2+Y8zbGruvUW+QV7K0nhf7iZWutlxHXTBqEXHbKue/o79IumAsQ==} + '@turf/centroid@7.2.0': + resolution: {integrity: sha512-yJqDSw25T7P48au5KjvYqbDVZ7qVnipziVfZ9aSo7P2/jTE7d4BP21w0/XLi3T/9bry/t9PR1GDDDQljN4KfDw==} - '@turf/center@6.5.0': - resolution: {integrity: sha512-T8KtMTfSATWcAX088rEDKjyvQCBkUsLnK/Txb6/8WUXIeOZyHu42G7MkdkHRoHtwieLdduDdmPLFyTdG5/e7ZQ==} + '@turf/circle@7.2.0': + resolution: {integrity: sha512-1AbqBYtXhstrHmnW6jhLwsv7TtmT0mW58Hvl1uZXEDM1NCVXIR50yDipIeQPjrCuJ/Zdg/91gU8+4GuDCAxBGA==} - '@turf/centroid@6.5.0': - resolution: {integrity: sha512-MwE1oq5E3isewPprEClbfU5pXljIK/GUOMbn22UM3IFPDJX0KeoyLNwghszkdmFp/qMGL/M13MMWvU+GNLXP/A==} + '@turf/clean-coords@7.2.0': + resolution: {integrity: sha512-+5+J1+D7wW7O/RDXn46IfCHuX1gIV1pIAQNSA7lcDbr3HQITZj334C4mOGZLEcGbsiXtlHWZiBtm785Vg8i+QQ==} - '@turf/circle@6.5.0': - resolution: {integrity: sha512-oU1+Kq9DgRnoSbWFHKnnUdTmtcRUMmHoV9DjTXu9vOLNV5OWtAAh1VZ+mzsioGGzoDNT/V5igbFOkMfBQc0B6A==} + '@turf/clone@7.2.0': + resolution: {integrity: sha512-JlGUT+/5qoU5jqZmf6NMFIoLDY3O7jKd53Up+zbpJ2vzUp6QdwdNzwrsCeONhynWM13F0MVtPXH4AtdkrgFk4g==} - '@turf/clean-coords@6.5.0': - resolution: {integrity: sha512-EMX7gyZz0WTH/ET7xV8MyrExywfm9qUi0/MY89yNffzGIEHuFfqwhcCqZ8O00rZIPZHUTxpmsxQSTfzJJA1CPw==} + '@turf/clusters-dbscan@7.2.0': + resolution: {integrity: sha512-VWVUuDreev56g3/BMlnq/81yzczqaz+NVTypN5CigGgP67e+u/CnijphiuhKjtjDd/MzGjXgEWBJc26Y6LYKAw==} - '@turf/clone@6.5.0': - resolution: {integrity: sha512-mzVtTFj/QycXOn6ig+annKrM6ZlimreKYz6f/GSERytOpgzodbQyOgkfwru100O1KQhhjSudKK4DsQ0oyi9cTw==} + '@turf/clusters-kmeans@7.2.0': + resolution: {integrity: sha512-BxQdK8jc8Mwm9yoClCYkktm4W004uiQGqb/i/6Y7a8xqgJITWDgTu/cy//wOxAWPk4xfe6MThjnqkszWW8JdyQ==} - '@turf/clusters-dbscan@6.5.0': - resolution: {integrity: sha512-SxZEE4kADU9DqLRiT53QZBBhu8EP9skviSyl+FGj08Y01xfICM/RR9ACUdM0aEQimhpu+ZpRVcUK+2jtiCGrYQ==} + '@turf/clusters@7.2.0': + resolution: {integrity: sha512-sKOrIKHHtXAuTKNm2USnEct+6/MrgyzMW42deZ2YG2RRKWGaaxHMFU2Yw71Yk4DqStOqTIBQpIOdrRuSOwbuQw==} - '@turf/clusters-kmeans@6.5.0': - resolution: {integrity: sha512-DwacD5+YO8kwDPKaXwT9DV46tMBVNsbi1IzdajZu1JDSWoN7yc7N9Qt88oi+p30583O0UPVkAK+A10WAQv4mUw==} + '@turf/collect@7.2.0': + resolution: {integrity: sha512-zRVGDlYS8Bx/Zz4vnEUyRg4dmqHhkDbW/nIUIJh657YqaMj1SFi4Iv2i9NbcurlUBDJFkpuOhCvvEvAdskJ8UA==} - '@turf/clusters@6.5.0': - resolution: {integrity: sha512-Y6gfnTJzQ1hdLfCsyd5zApNbfLIxYEpmDibHUqR5z03Lpe02pa78JtgrgUNt1seeO/aJ4TG1NLN8V5gOrHk04g==} + '@turf/combine@7.2.0': + resolution: {integrity: sha512-VEjm3IvnbMt3IgeRIhCDhhQDbLqCU1/5uN1+j1u6fyA095pCizPThGp4f/COSzC3t1s/iiV+fHuDsB6DihHffQ==} - '@turf/collect@6.5.0': - resolution: {integrity: sha512-4dN/T6LNnRg099m97BJeOcTA5fSI8cu87Ydgfibewd2KQwBexO69AnjEFqfPX3Wj+Zvisj1uAVIZbPmSSrZkjg==} + '@turf/concave@7.2.0': + resolution: {integrity: sha512-cpaDDlumK762kdadexw5ZAB6g/h2pJdihZ+e65lbQVe3WukJHAANnIEeKsdFCuIyNKrwTz2gWu5ws+OpjP48Yw==} - '@turf/combine@6.5.0': - resolution: {integrity: sha512-Q8EIC4OtAcHiJB3C4R+FpB4LANiT90t17uOd851qkM2/o6m39bfN5Mv0PWqMZIHWrrosZqRqoY9dJnzz/rJxYQ==} + '@turf/convex@7.2.0': + resolution: {integrity: sha512-HsgHm+zHRE8yPCE/jBUtWFyaaBmpXcSlyHd5/xsMhSZRImFzRzBibaONWQo7xbKZMISC3Nc6BtUjDi/jEVbqyA==} - '@turf/concave@6.5.0': - resolution: {integrity: sha512-I/sUmUC8TC5h/E2vPwxVht+nRt+TnXIPRoztDFvS8/Y0+cBDple9inLSo9nnPXMXidrBlGXZ9vQx/BjZUJgsRQ==} + '@turf/destination@7.2.0': + resolution: {integrity: sha512-8DUxtOO0Fvrh1xclIUj3d9C5WS20D21F5E+j+X9Q+ju6fcM4huOqTg5ckV1DN2Pg8caABEc5HEZJnGch/5YnYQ==} - '@turf/convex@6.5.0': - resolution: {integrity: sha512-x7ZwC5z7PJB0SBwNh7JCeCNx7Iu+QSrH7fYgK0RhhNop13TqUlvHMirMLRgf2db1DqUetrAO2qHJeIuasquUWg==} + '@turf/difference@7.2.0': + resolution: {integrity: sha512-NHKD1v3s8RX+9lOpvHJg6xRuJOKiY3qxHhz5/FmE0VgGqnCkE7OObqWZ5SsXG+Ckh0aafs5qKhmDdDV/gGi6JA==} - '@turf/destination@6.5.0': - resolution: {integrity: sha512-4cnWQlNC8d1tItOz9B4pmJdWpXqS0vEvv65bI/Pj/genJnsL7evI0/Xw42RvEGROS481MPiU80xzvwxEvhQiMQ==} + '@turf/dissolve@7.2.0': + resolution: {integrity: sha512-gPG5TE3mAYuZqBut8tPYCKwi4hhx5Cq0ALoQMB9X0hrVtFIKrihrsj98XQM/5pL/UIpAxQfwisQvy6XaOFaoPA==} - '@turf/difference@6.5.0': - resolution: {integrity: sha512-l8iR5uJqvI+5Fs6leNbhPY5t/a3vipUF/3AeVLpwPQcgmedNXyheYuy07PcMGH5Jdpi5gItOiTqwiU/bUH4b3A==} + '@turf/distance-weight@7.2.0': + resolution: {integrity: sha512-NeoyV0fXDH+7nIoNtLjAoH9XL0AS1pmTIyDxEE6LryoDTsqjnuR0YQxIkLCCWDqECoqaOmmBqpeWONjX5BwWCg==} - '@turf/dissolve@6.5.0': - resolution: {integrity: sha512-WBVbpm9zLTp0Bl9CE35NomTaOL1c4TQCtEoO43YaAhNEWJOOIhZMFJyr8mbvYruKl817KinT3x7aYjjCMjTAsQ==} + '@turf/distance@7.2.0': + resolution: {integrity: sha512-HBjjXIgEcD/wJYjv7/6OZj5yoky2oUvTtVeIAqO3lL80XRvoYmVg6vkOIu6NswkerwLDDNT9kl7+BFLJoHbh6Q==} - '@turf/distance-weight@6.5.0': - resolution: {integrity: sha512-a8qBKkgVNvPKBfZfEJZnC3DV7dfIsC3UIdpRci/iap/wZLH41EmS90nM+BokAJflUHYy8PqE44wySGWHN1FXrQ==} + '@turf/ellipse@7.2.0': + resolution: {integrity: sha512-/Y75S5hE2+xjnTw4dXpQ5r/Y2HPM4xrwkPRCCQRpuuboKdEvm42azYmh7isPnMnBTVcmGb9UmGKj0HHAbiwt1g==} - '@turf/distance@6.5.0': - resolution: {integrity: sha512-xzykSLfoURec5qvQJcfifw/1mJa+5UwByZZ5TZ8iaqjGYN0vomhV9aiSLeYdUGtYRESZ+DYC/OzY+4RclZYgMg==} + '@turf/envelope@7.2.0': + resolution: {integrity: sha512-xOMtDeNKHwUuDfzQeoSNmdabsP0/IgVDeyzitDe/8j9wTeW+MrKzVbGz7627PT3h6gsO+2nUv5asfKtUbmTyHA==} - '@turf/ellipse@6.5.0': - resolution: {integrity: sha512-kuXtwFviw/JqnyJXF1mrR/cb496zDTSbGKtSiolWMNImYzGGkbsAsFTjwJYgD7+4FixHjp0uQPzo70KDf3AIBw==} + '@turf/explode@7.2.0': + resolution: {integrity: sha512-jyMXg93J1OI7/65SsLE1k9dfQD3JbcPNMi4/O3QR2Qb3BAs2039oFaSjtW+YqhMqVC4V3ZeKebMcJ8h9sK1n+A==} - '@turf/envelope@6.5.0': - resolution: {integrity: sha512-9Z+FnBWvOGOU4X+fMZxYFs1HjFlkKqsddLuMknRaqcJd6t+NIv5DWvPtDL8ATD2GEExYDiFLwMdckfr1yqJgHA==} + '@turf/flatten@7.2.0': + resolution: {integrity: sha512-q38Qsqr4l7mxp780zSdn0gp/WLBX+sa+gV6qIbDQ1HKCrrPK8QQJmNx7gk1xxEXVot6tq/WyAPysCQdX+kLmMA==} - '@turf/explode@6.5.0': - resolution: {integrity: sha512-6cSvMrnHm2qAsace6pw9cDmK2buAlw8+tjeJVXMfMyY+w7ZUi1rprWMsY92J7s2Dar63Bv09n56/1V7+tcj52Q==} + '@turf/flip@7.2.0': + resolution: {integrity: sha512-X0TQ0U/UYh4tyXdLO5itP1sO2HOvfrZC0fYSWmTfLDM14jEPkEK8PblofznfBygL+pIFtOS2is8FuVcp5XxYpQ==} - '@turf/flatten@6.5.0': - resolution: {integrity: sha512-IBZVwoNLVNT6U/bcUUllubgElzpMsNoCw8tLqBw6dfYg9ObGmpEjf9BIYLr7a2Yn5ZR4l7YIj2T7kD5uJjZADQ==} + '@turf/geojson-rbush@7.2.0': + resolution: {integrity: sha512-ST8fLv+EwxVkDgsmhHggM0sPk2SfOHTZJkdgMXVFT7gB9o4lF8qk4y4lwvCCGIfFQAp2yv/PN5EaGMEKutk6xw==} - '@turf/flip@6.5.0': - resolution: {integrity: sha512-oyikJFNjt2LmIXQqgOGLvt70RgE2lyzPMloYWM7OR5oIFGRiBvqVD2hA6MNw6JewIm30fWZ8DQJw1NHXJTJPbg==} + '@turf/great-circle@7.2.0': + resolution: {integrity: sha512-n30OiADyOKHhor0aXNgYfXQYXO3UtsOKmhQsY1D89/Oh1nCIXG/1ZPlLL9ZoaRXXBTUBjh99a+K8029NQbGDhw==} - '@turf/great-circle@6.5.0': - resolution: {integrity: sha512-7ovyi3HaKOXdFyN7yy1yOMa8IyOvV46RC1QOQTT+RYUN8ke10eyqExwBpL9RFUPvlpoTzoYbM/+lWPogQlFncg==} + '@turf/helpers@7.2.0': + resolution: {integrity: sha512-cXo7bKNZoa7aC7ydLmUR02oB3IgDe7MxiPuRz3cCtYQHn+BJ6h1tihmamYDWWUlPHgSNF0i3ATc4WmDECZafKw==} - '@turf/helpers@6.5.0': - resolution: {integrity: sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==} + '@turf/hex-grid@7.2.0': + resolution: {integrity: sha512-Yo2yUGxrTCQfmcVsSjDt0G3Veg8YD26WRd7etVPD9eirNNgXrIyZkbYA7zVV/qLeRWVmYIKRXg1USWl7ORQOGA==} - '@turf/hex-grid@6.5.0': - resolution: {integrity: sha512-Ln3tc2tgZT8etDOldgc6e741Smg1CsMKAz1/Mlel+MEL5Ynv2mhx3m0q4J9IB1F3a4MNjDeVvm8drAaf9SF33g==} + '@turf/interpolate@7.2.0': + resolution: {integrity: sha512-Ifgjm1SEo6XujuSAU6lpRMvoJ1SYTreil1Rf5WsaXj16BQJCedht/4FtWCTNhSWTwEz2motQ1WNrjTCuPG94xA==} - '@turf/interpolate@6.5.0': - resolution: {integrity: sha512-LSH5fMeiGyuDZ4WrDJNgh81d2DnNDUVJtuFryJFup8PV8jbs46lQGfI3r1DJ2p1IlEJIz3pmAZYeTfMMoeeohw==} + '@turf/intersect@7.2.0': + resolution: {integrity: sha512-81GMzKS9pKqLPa61qSlFxLFeAC8XbwyCQ9Qv4z6o5skWk1qmMUbEHeMqaGUTEzk+q2XyhZ0sju1FV4iLevQ/aw==} - '@turf/intersect@6.5.0': - resolution: {integrity: sha512-2legGJeKrfFkzntcd4GouPugoqPUjexPZnOvfez+3SfIMrHvulw8qV8u7pfVyn2Yqs53yoVCEjS5sEpvQ5YRQg==} + '@turf/invariant@7.2.0': + resolution: {integrity: sha512-kV4u8e7Gkpq+kPbAKNC21CmyrXzlbBgFjO1PhrHPgEdNqXqDawoZ3i6ivE3ULJj2rSesCjduUaC/wyvH/sNr2Q==} - '@turf/invariant@6.5.0': - resolution: {integrity: sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==} + '@turf/isobands@7.2.0': + resolution: {integrity: sha512-lYoHeRieFzpBp29Jh19QcDIb0E+dzo/K5uwZuNga4wxr6heNU0AfkD4ByAHYIXHtvmp4m/JpSKq/2N6h/zvBkg==} - '@turf/isobands@6.5.0': - resolution: {integrity: sha512-4h6sjBPhRwMVuFaVBv70YB7eGz+iw0bhPRnp+8JBdX1UPJSXhoi/ZF2rACemRUr0HkdVB/a1r9gC32vn5IAEkw==} + '@turf/isolines@7.2.0': + resolution: {integrity: sha512-4ZXKxvA/JKkxAXixXhN3UVza5FABsdYgOWXyYm3L5ryTPJVOYTVSSd9A+CAVlv9dZc3YdlsqMqLTXNOOre/kwg==} - '@turf/isolines@6.5.0': - resolution: {integrity: sha512-6ElhiLCopxWlv4tPoxiCzASWt/jMRvmp6mRYrpzOm3EUl75OhHKa/Pu6Y9nWtCMmVC/RcWtiiweUocbPLZLm0A==} + '@turf/jsts@2.7.2': + resolution: {integrity: sha512-zAezGlwWHPyU0zxwcX2wQY3RkRpwuoBmhhNE9HY9kWhFDkCxZ3aWK5URKwa/SWKJbj9aztO+8vtdiBA28KVJFg==} - '@turf/kinks@6.5.0': - resolution: {integrity: sha512-ViCngdPt1eEL7hYUHR2eHR662GvCgTc35ZJFaNR6kRtr6D8plLaDju0FILeFFWSc+o8e3fwxZEJKmFj9IzPiIQ==} + '@turf/kinks@7.2.0': + resolution: {integrity: sha512-BtxDxGewJR0Q5WR9HKBSxZhirFX+GEH1rD7/EvgDsHS8e1Y5/vNQQUmXdURjdPa4StzaUBsWRU5T3A356gLbPA==} - '@turf/length@6.5.0': - resolution: {integrity: sha512-5pL5/pnw52fck3oRsHDcSGrj9HibvtlrZ0QNy2OcW8qBFDNgZ4jtl6U7eATVoyWPKBHszW3dWETW+iLV7UARig==} + '@turf/length@7.2.0': + resolution: {integrity: sha512-LBmYN+iCgVtWNLsckVnpQIJENqIIPO63mogazMp23lrDGfWXu07zZQ9ZinJVO5xYurXNhc/QI2xxoqt2Xw90Ig==} - '@turf/line-arc@6.5.0': - resolution: {integrity: sha512-I6c+V6mIyEwbtg9P9zSFF89T7QPe1DPTG3MJJ6Cm1MrAY0MdejwQKOpsvNl8LDU2ekHOlz2kHpPVR7VJsoMllA==} + '@turf/line-arc@7.2.0': + resolution: {integrity: sha512-kfWzA5oYrTpslTg5fN50G04zSypiYQzjZv3FLjbZkk6kta5fo4JkERKjTeA8x4XNojb+pfmjMBB0yIh2w2dDRw==} - '@turf/line-chunk@6.5.0': - resolution: {integrity: sha512-i1FGE6YJaaYa+IJesTfyRRQZP31QouS+wh/pa6O3CC0q4T7LtHigyBSYjrbjSLfn2EVPYGlPCMFEqNWCOkC6zg==} + '@turf/line-chunk@7.2.0': + resolution: {integrity: sha512-1ODyL5gETtWSL85MPI0lgp/78vl95M39gpeBxePXyDIqx8geDP9kXfAzctuKdxBoR4JmOVM3NT7Fz7h+IEkC+g==} - '@turf/line-intersect@6.5.0': - resolution: {integrity: sha512-CS6R1tZvVQD390G9Ea4pmpM6mJGPWoL82jD46y0q1KSor9s6HupMIo1kY4Ny+AEYQl9jd21V3Scz20eldpbTVA==} + '@turf/line-intersect@7.2.0': + resolution: {integrity: sha512-GhCJVEkc8EmggNi85EuVLoXF5T5jNVxmhIetwppiVyJzMrwkYAkZSYB3IBFYGUUB9qiNFnTwungVSsBV/S8ZiA==} - '@turf/line-offset@6.5.0': - resolution: {integrity: sha512-CEXZbKgyz8r72qRvPchK0dxqsq8IQBdH275FE6o4MrBkzMcoZsfSjghtXzKaz9vvro+HfIXal0sTk2mqV1lQTw==} + '@turf/line-offset@7.2.0': + resolution: {integrity: sha512-1+OkYueDCbnEWzbfBh3taVr+3SyM2bal5jfnSEuDiLA6jnlScgr8tn3INo+zwrUkPFZPPAejL1swVyO5TjUahw==} - '@turf/line-overlap@6.5.0': - resolution: {integrity: sha512-xHOaWLd0hkaC/1OLcStCpfq55lPHpPNadZySDXYiYjEz5HXr1oKmtMYpn0wGizsLwrOixRdEp+j7bL8dPt4ojQ==} + '@turf/line-overlap@7.2.0': + resolution: {integrity: sha512-NNn7/jg53+N10q2Kyt66bEDqN3101iW/1zA5FW7J6UbKApDFkByh+18YZq1of71kS6oUYplP86WkDp16LFpqqw==} - '@turf/line-segment@6.5.0': - resolution: {integrity: sha512-jI625Ho4jSuJESNq66Mmi290ZJ5pPZiQZruPVpmHkUw257Pew0alMmb6YrqYNnLUuiVVONxAAKXUVeeUGtycfw==} + '@turf/line-segment@7.2.0': + resolution: {integrity: sha512-E162rmTF9XjVN4rINJCd15AdQGCBlNqeWN3V0YI1vOUpZFNT2ii4SqEMCcH2d+5EheHLL8BWVwZoOsvHZbvaWA==} - '@turf/line-slice-along@6.5.0': - resolution: {integrity: sha512-KHJRU6KpHrAj+BTgTNqby6VCTnDzG6a1sJx/I3hNvqMBLvWVA2IrkR9L9DtsQsVY63IBwVdQDqiwCuZLDQh4Ng==} + '@turf/line-slice-along@7.2.0': + resolution: {integrity: sha512-4/gPgP0j5Rp+1prbhXqn7kIH/uZTmSgiubUnn67F8nb9zE+MhbRglhSlRYEZxAVkB7VrGwjyolCwvrROhjHp2A==} - '@turf/line-slice@6.5.0': - resolution: {integrity: sha512-vDqJxve9tBHhOaVVFXqVjF5qDzGtKWviyjbyi2QnSnxyFAmLlLnBfMX8TLQCAf2GxHibB95RO5FBE6I2KVPRuw==} + '@turf/line-slice@7.2.0': + resolution: {integrity: sha512-bHotzZIaU1GPV3RMwttYpDrmcvb3X2i1g/WUttPZWtKrEo2VVAkoYdeZ2aFwtogERYS4quFdJ/TDzAtquBC8WQ==} - '@turf/line-split@6.5.0': - resolution: {integrity: sha512-/rwUMVr9OI2ccJjw7/6eTN53URtGThNSD5I0GgxyFXMtxWiloRJ9MTff8jBbtPWrRka/Sh2GkwucVRAEakx9Sw==} + '@turf/line-split@7.2.0': + resolution: {integrity: sha512-yJTZR+c8CwoKqdW/aIs+iLbuFwAa3Yan+EOADFQuXXIUGps3bJUXx/38rmowNoZbHyP1np1+OtrotyHu5uBsfQ==} - '@turf/line-to-polygon@6.5.0': - resolution: {integrity: sha512-qYBuRCJJL8Gx27OwCD1TMijM/9XjRgXH/m/TyuND4OXedBpIWlK5VbTIO2gJ8OCfznBBddpjiObLBrkuxTpN4Q==} + '@turf/line-to-polygon@7.2.0': + resolution: {integrity: sha512-iKpJqc7EYc5NvlD4KaqrKKO6mXR7YWO/YwtW60E2FnsF/blnsy9OfAOcilYHgH3S/V/TT0VedC7DW7Kgjy2EIA==} - '@turf/mask@6.5.0': - resolution: {integrity: sha512-RQha4aU8LpBrmrkH8CPaaoAfk0Egj5OuXtv6HuCQnHeGNOQt3TQVibTA3Sh4iduq4EPxnZfDjgsOeKtrCA19lg==} + '@turf/mask@7.2.0': + resolution: {integrity: sha512-ulJ6dQqXC0wrjIoqFViXuMUdIPX5Q6GPViZ3kGfeVijvlLM7kTFBsZiPQwALSr5nTQg4Ppf3FD0Jmg8IErPrgA==} - '@turf/meta@6.5.0': - resolution: {integrity: sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==} + '@turf/meta@7.2.0': + resolution: {integrity: sha512-igzTdHsQc8TV1RhPuOLVo74Px/hyPrVgVOTgjWQZzt3J9BVseCdpfY/0cJBdlSRI4S/yTmmHl7gAqjhpYH5Yaw==} - '@turf/midpoint@6.5.0': - resolution: {integrity: sha512-MyTzV44IwmVI6ec9fB2OgZ53JGNlgOpaYl9ArKoF49rXpL84F9rNATndbe0+MQIhdkw8IlzA6xVP4lZzfMNVCw==} + '@turf/midpoint@7.2.0': + resolution: {integrity: sha512-AMn5S9aSrbXdE+Q4Rj+T5nLdpfpn+mfzqIaEKkYI021HC0vb22HyhQHsQbSeX+AWcS4CjD1hFsYVcgKI+5qCfw==} - '@turf/moran-index@6.5.0': - resolution: {integrity: sha512-ItsnhrU2XYtTtTudrM8so4afBCYWNaB0Mfy28NZwLjB5jWuAsvyV+YW+J88+neK/ougKMTawkmjQqodNJaBeLQ==} + '@turf/moran-index@7.2.0': + resolution: {integrity: sha512-Aexh1EmXVPJhApr9grrd120vbalIthcIsQ3OAN2Tqwf+eExHXArJEJqGBo9IZiQbIpFJeftt/OvUvlI8BeO1bA==} - '@turf/nearest-point-on-line@6.5.0': - resolution: {integrity: sha512-WthrvddddvmymnC+Vf7BrkHGbDOUu6Z3/6bFYUGv1kxw8tiZ6n83/VG6kHz4poHOfS0RaNflzXSkmCi64fLBlg==} + '@turf/nearest-neighbor-analysis@7.2.0': + resolution: {integrity: sha512-LmP/crXb7gilgsL0wL9hsygqc537W/a1W5r9XBKJT4SKdqjoXX5APJatJfd3nwXbRIqwDH0cDA9/YyFjBPlKnA==} - '@turf/nearest-point-to-line@6.5.0': - resolution: {integrity: sha512-PXV7cN0BVzUZdjj6oeb/ESnzXSfWmEMrsfZSDRgqyZ9ytdiIj/eRsnOXLR13LkTdXVOJYDBuf7xt1mLhM4p6+Q==} + '@turf/nearest-point-on-line@7.2.0': + resolution: {integrity: sha512-UOhAeoDPVewBQV+PWg1YTMQcYpJsIqfW5+EuZ5vJl60XwUa0+kqB/eVfSLNXmHENjKKIlEt9Oy9HIDF4VeWmXA==} - '@turf/nearest-point@6.5.0': - resolution: {integrity: sha512-fguV09QxilZv/p94s8SMsXILIAMiaXI5PATq9d7YWijLxWUj6Q/r43kxyoi78Zmwwh1Zfqz9w+bCYUAxZ5+euA==} + '@turf/nearest-point-to-line@7.2.0': + resolution: {integrity: sha512-EorU7Qj30A7nAjh++KF/eTPDlzwuuV4neBz7tmSTB21HKuXZAR0upJsx6M2X1CSyGEgNsbFB0ivNKIvymRTKBw==} - '@turf/planepoint@6.5.0': - resolution: {integrity: sha512-R3AahA6DUvtFbka1kcJHqZ7DMHmPXDEQpbU5WaglNn7NaCQg9HB0XM0ZfqWcd5u92YXV+Gg8QhC8x5XojfcM4Q==} + '@turf/nearest-point@7.2.0': + resolution: {integrity: sha512-0wmsqXZ8CGw4QKeZmS+NdjYTqCMC+HXZvM3XAQIU6k6laNLqjad2oS4nDrtcRs/nWDvcj1CR+Io7OiQ6sbpn5Q==} - '@turf/point-grid@6.5.0': - resolution: {integrity: sha512-Iq38lFokNNtQJnOj/RBKmyt6dlof0yhaHEDELaWHuECm1lIZLY3ZbVMwbs+nXkwTAHjKfS/OtMheUBkw+ee49w==} + '@turf/planepoint@7.2.0': + resolution: {integrity: sha512-8Vno01tvi5gThUEKBQ46CmlEKDAwVpkl7stOPFvJYlA1oywjAL4PsmgwjXgleZuFtXQUPBNgv5a42Pf438XP4g==} - '@turf/point-on-feature@6.5.0': - resolution: {integrity: sha512-bDpuIlvugJhfcF/0awAQ+QI6Om1Y1FFYE8Y/YdxGRongivix850dTeXCo0mDylFdWFPGDo7Mmh9Vo4VxNwW/TA==} + '@turf/point-grid@7.2.0': + resolution: {integrity: sha512-ai7lwBV2FREPW3XiUNohT4opC1hd6+F56qZe20xYhCTkTD9diWjXHiNudQPSmVAUjgMzQGasblQQqvOdL+bJ3Q==} - '@turf/point-to-line-distance@6.5.0': - resolution: {integrity: sha512-opHVQ4vjUhNBly1bob6RWy+F+hsZDH9SA0UW36pIRzfpu27qipU18xup0XXEePfY6+wvhF6yL/WgCO2IbrLqEA==} + '@turf/point-on-feature@7.2.0': + resolution: {integrity: sha512-ksoYoLO9WtJ/qI8VI9ltF+2ZjLWrAjZNsCsu8F7nyGeCh4I8opjf4qVLytFG44XA2qI5yc6iXDpyv0sshvP82Q==} - '@turf/points-within-polygon@6.5.0': - resolution: {integrity: sha512-YyuheKqjliDsBDt3Ho73QVZk1VXX1+zIA2gwWvuz8bR1HXOkcuwk/1J76HuFMOQI3WK78wyAi+xbkx268PkQzQ==} + '@turf/point-to-line-distance@7.2.0': + resolution: {integrity: sha512-fB9Rdnb5w5+t76Gho2dYDkGe20eRrFk8CXi4v1+l1PC8YyLXO+x+l3TrtT8HzL/dVaZeepO6WUIsIw3ditTOPg==} - '@turf/polygon-smooth@6.5.0': - resolution: {integrity: sha512-LO/X/5hfh/Rk4EfkDBpLlVwt3i6IXdtQccDT9rMjXEP32tRgy0VMFmdkNaXoGlSSKf/1mGqLl4y4wHd86DqKbg==} + '@turf/point-to-polygon-distance@7.2.0': + resolution: {integrity: sha512-w+WYuINgTiFjoZemQwOaQSje/8Kq+uqJOynvx7+gleQPHyWQ3VtTodtV4LwzVzXz8Sf7Mngx1Jcp2SNai5CJYA==} - '@turf/polygon-tangents@6.5.0': - resolution: {integrity: sha512-sB4/IUqJMYRQH9jVBwqS/XDitkEfbyqRy+EH/cMRJURTg78eHunvJ708x5r6umXsbiUyQU4eqgPzEylWEQiunw==} + '@turf/points-within-polygon@7.2.0': + resolution: {integrity: sha512-jRKp8/mWNMzA+hKlQhxci97H5nOio9tp14R2SzpvkOt+cswxl+NqTEi1hDd2XetA7tjU0TSoNjEgVY8FfA0S6w==} - '@turf/polygon-to-line@6.5.0': - resolution: {integrity: sha512-5p4n/ij97EIttAq+ewSnKt0ruvuM+LIDzuczSzuHTpq4oS7Oq8yqg5TQ4nzMVuK41r/tALCk7nAoBuw3Su4Gcw==} + '@turf/polygon-smooth@7.2.0': + resolution: {integrity: sha512-KCp9wF2IEynvGXVhySR8oQ2razKP0zwg99K+fuClP21pSKCFjAPaihPEYq6e8uI/1J7ibjL5++6EMl+LrUTrLg==} - '@turf/polygonize@6.5.0': - resolution: {integrity: sha512-a/3GzHRaCyzg7tVYHo43QUChCspa99oK4yPqooVIwTC61npFzdrmnywMv0S+WZjHZwK37BrFJGFrZGf6ocmY5w==} + '@turf/polygon-tangents@7.2.0': + resolution: {integrity: sha512-AHUUPmOjiQDrtP/ODXukHBlUG0C/9I1je7zz50OTfl2ZDOdEqFJQC3RyNELwq07grTXZvg5TS5wYx/Y7nsm47g==} - '@turf/projection@6.5.0': - resolution: {integrity: sha512-/Pgh9mDvQWWu8HRxqpM+tKz8OzgauV+DiOcr3FCjD6ubDnrrmMJlsf6fFJmggw93mtVPrZRL6yyi9aYCQBOIvg==} + '@turf/polygon-to-line@7.2.0': + resolution: {integrity: sha512-9jeTN3LiJ933I5sd4K0kwkcivOYXXm1emk0dHorwXeSFSHF+nlYesEW3Hd889wb9lZd7/SVLMUeX/h39mX+vCA==} - '@turf/random@6.5.0': - resolution: {integrity: sha512-8Q25gQ/XbA7HJAe+eXp4UhcXM9aOOJFaxZ02+XSNwMvY8gtWSCBLVqRcW4OhqilgZ8PeuQDWgBxeo+BIqqFWFQ==} + '@turf/polygonize@7.2.0': + resolution: {integrity: sha512-U9v+lBhUPDv+nsg/VcScdiqCB59afO6CHDGrwIl2+5i6Ve+/KQKjpTV/R+NqoC1iMXAEq3brY6HY8Ukp/pUWng==} - '@turf/rectangle-grid@6.5.0': - resolution: {integrity: sha512-yQZ/1vbW68O2KsSB3OZYK+72aWz/Adnf7m2CMKcC+aq6TwjxZjAvlbCOsNUnMAuldRUVN1ph6RXMG4e9KEvKvg==} + '@turf/projection@7.2.0': + resolution: {integrity: sha512-/qke5vJScv8Mu7a+fU3RSChBRijE6EVuFHU3RYihMuYm04Vw8dBMIs0enEpoq0ke/IjSbleIrGQNZIMRX9EwZQ==} - '@turf/rewind@6.5.0': - resolution: {integrity: sha512-IoUAMcHWotBWYwSYuYypw/LlqZmO+wcBpn8ysrBNbazkFNkLf3btSDZMkKJO/bvOzl55imr/Xj4fi3DdsLsbzQ==} + '@turf/quadrat-analysis@7.2.0': + resolution: {integrity: sha512-fDQh3+ldYNxUqS6QYlvJ7GZLlCeDZR6tD3ikdYtOsSemwW1n/4gm2xcgWJqy3Y0uszBwxc13IGGY7NGEjHA+0w==} - '@turf/rhumb-bearing@6.5.0': - resolution: {integrity: sha512-jMyqiMRK4hzREjQmnLXmkJ+VTNTx1ii8vuqRwJPcTlKbNWfjDz/5JqJlb5NaFDcdMpftWovkW5GevfnuzHnOYA==} + '@turf/random@7.2.0': + resolution: {integrity: sha512-fNXs5mOeXsrirliw84S8UCNkpm4RMNbefPNsuCTfZEXhcr1MuHMzq4JWKb4FweMdN1Yx2l/xcytkO0s71cJ50w==} - '@turf/rhumb-destination@6.5.0': - resolution: {integrity: sha512-RHNP1Oy+7xTTdRrTt375jOZeHceFbjwohPHlr9Hf68VdHHPMAWgAKqiX2YgSWDcvECVmiGaBKWus1Df+N7eE4Q==} + '@turf/rectangle-grid@7.2.0': + resolution: {integrity: sha512-f0o5ifvy0Ml/nHDJzMNcuSk4h11aa3BfvQNnYQhLpuTQu03j/ICZNlzKTLxwjcUqvxADUifty7Z9CX5W6zky4A==} - '@turf/rhumb-distance@6.5.0': - resolution: {integrity: sha512-oKp8KFE8E4huC2Z1a1KNcFwjVOqa99isxNOwfo4g3SUABQ6NezjKDDrnvC4yI5YZ3/huDjULLBvhed45xdCrzg==} + '@turf/rewind@7.2.0': + resolution: {integrity: sha512-SZpRAZiZsE22+HVz6pEID+ST25vOdpAMGk5NO1JeqzhpMALIkIGnkG+xnun2CfYHz7wv8/Z0ADiAvei9rkcQYA==} - '@turf/sample@6.5.0': - resolution: {integrity: sha512-kSdCwY7el15xQjnXYW520heKUrHwRvnzx8ka4eYxX9NFeOxaFITLW2G7UtXb6LJK8mmPXI8Aexv23F2ERqzGFg==} + '@turf/rhumb-bearing@7.2.0': + resolution: {integrity: sha512-jbdexlrR8X2ZauUciHx3tRwG+BXoMXke4B8p8/IgDlAfIrVdzAxSQN89FMzIKnjJ/kdLjo9bFGvb92bu31Etug==} - '@turf/sector@6.5.0': - resolution: {integrity: sha512-cYUOkgCTWqa23SOJBqxoFAc/yGCUsPRdn/ovbRTn1zNTm/Spmk6hVB84LCKOgHqvSF25i0d2kWqpZDzLDdAPbw==} + '@turf/rhumb-destination@7.2.0': + resolution: {integrity: sha512-U9OLgLAHlH4Wfx3fBZf3jvnkDjdTcfRan5eI7VPV1+fQWkOteATpzkiRjCvSYK575GljVwWBjkKca8LziGWitQ==} - '@turf/shortest-path@6.5.0': - resolution: {integrity: sha512-4de5+G7+P4hgSoPwn+SO9QSi9HY5NEV/xRJ+cmoFVRwv2CDsuOPDheHKeuIAhKyeKDvPvPt04XYWbac4insJMg==} + '@turf/rhumb-distance@7.2.0': + resolution: {integrity: sha512-NsijTPON1yOc9tirRPEQQuJ5aQi7pREsqchQquaYKbHNWsexZjcDi4wnw2kM3Si4XjmgynT+2f7aXH7FHarHzw==} - '@turf/simplify@6.5.0': - resolution: {integrity: sha512-USas3QqffPHUY184dwQdP8qsvcVH/PWBYdXY5am7YTBACaQOMAlf6AKJs9FT8jiO6fQpxfgxuEtwmox+pBtlOg==} + '@turf/sample@7.2.0': + resolution: {integrity: sha512-f+ZbcbQJ9glQ/F26re8LadxO0ORafy298EJZe6XtbctRTJrNus6UNAsl8+GYXFqMnXM22tbTAznnJX3ZiWNorA==} - '@turf/square-grid@6.5.0': - resolution: {integrity: sha512-mlR0ayUdA+L4c9h7p4k3pX6gPWHNGuZkt2c5II1TJRmhLkW2557d6b/Vjfd1z9OVaajb1HinIs1FMSAPXuuUrA==} + '@turf/sector@7.2.0': + resolution: {integrity: sha512-zL06MjbbMG4DdpiNz+Q9Ax8jsCekt3R76uxeWShulAGkyDB5smdBOUDoRwxn05UX7l4kKv4Ucq2imQXhxKFd1w==} - '@turf/square@6.5.0': - resolution: {integrity: sha512-BM2UyWDmiuHCadVhHXKIx5CQQbNCpOxB6S/aCNOCLbhCeypKX5Q0Aosc5YcmCJgkwO5BERCC6Ee7NMbNB2vHmQ==} + '@turf/shortest-path@7.2.0': + resolution: {integrity: sha512-6fpx8feZ2jMSaeRaFdqFShGWkNb+veUOeyLFSHA/aRD9n/e9F2pWZoRbQWKbKTpcKFJ2FnDEqCZnh/GrcAsqWA==} - '@turf/standard-deviational-ellipse@6.5.0': - resolution: {integrity: sha512-02CAlz8POvGPFK2BKK8uHGUk/LXb0MK459JVjKxLC2yJYieOBTqEbjP0qaWhiBhGzIxSMaqe8WxZ0KvqdnstHA==} + '@turf/simplify@7.2.0': + resolution: {integrity: sha512-9YHIfSc8BXQfi5IvEMbCeQYqNch0UawIGwbboJaoV8rodhtk6kKV2wrpXdGqk/6Thg6/RWvChJFKVVTjVrULyQ==} - '@turf/tag@6.5.0': - resolution: {integrity: sha512-XwlBvrOV38CQsrNfrxvBaAPBQgXMljeU0DV8ExOyGM7/hvuGHJw3y8kKnQ4lmEQcmcrycjDQhP7JqoRv8vFssg==} + '@turf/square-grid@7.2.0': + resolution: {integrity: sha512-EmzGXa90hz+tiCOs9wX+Lak6pH0Vghb7QuX6KZej+pmWi3Yz7vdvQLmy/wuN048+wSkD5c8WUo/kTeNDe7GnmA==} - '@turf/tesselate@6.5.0': - resolution: {integrity: sha512-M1HXuyZFCfEIIKkglh/r5L9H3c5QTEsnMBoZOFQiRnGPGmJWcaBissGb7mTFX2+DKE7FNWXh4TDnZlaLABB0dQ==} + '@turf/square@7.2.0': + resolution: {integrity: sha512-9pMoAGFvqzCDOlO9IRSSBCGXKbl8EwMx6xRRBMKdZgpS0mZgfm9xiptMmx/t1m4qqHIlb/N+3MUF7iMBx6upcA==} - '@turf/tin@6.5.0': - resolution: {integrity: sha512-YLYikRzKisfwj7+F+Tmyy/LE3d2H7D4kajajIfc9mlik2+esG7IolsX/+oUz1biguDYsG0DUA8kVYXDkobukfg==} + '@turf/standard-deviational-ellipse@7.2.0': + resolution: {integrity: sha512-+uC0pR2nRjm90JvMXe/2xOCZsYV2II1ZZ2zmWcBWv6bcFXBspcxk2QfCC3k0bj6jDapELzoQgnn3cG5lbdQV2w==} - '@turf/transform-rotate@6.5.0': - resolution: {integrity: sha512-A2Ip1v4246ZmpssxpcL0hhiVBEf4L8lGnSPWTgSv5bWBEoya2fa/0SnFX9xJgP40rMP+ZzRaCN37vLHbv1Guag==} + '@turf/tag@7.2.0': + resolution: {integrity: sha512-TAFvsbp5TCBqXue8ui+CtcLsPZ6NPC88L8Ad6Hb/R6VAi21qe0U42WJHQYXzWmtThoTNwxi+oKSeFbRDsr0FIA==} - '@turf/transform-scale@6.5.0': - resolution: {integrity: sha512-VsATGXC9rYM8qTjbQJ/P7BswKWXHdnSJ35JlV4OsZyHBMxJQHftvmZJsFbOqVtQnIQIzf2OAly6rfzVV9QLr7g==} + '@turf/tesselate@7.2.0': + resolution: {integrity: sha512-zHGcG85aOJJu1seCm+CYTJ3UempX4Xtyt669vFG6Hbr/Hc7ii6STQ2ysFr7lJwFtU9uyYhphVrrgwIqwglvI/Q==} - '@turf/transform-translate@6.5.0': - resolution: {integrity: sha512-NABLw5VdtJt/9vSstChp93pc6oel4qXEos56RBMsPlYB8hzNTEKYtC146XJvyF4twJeeYS8RVe1u7KhoFwEM5w==} + '@turf/tin@7.2.0': + resolution: {integrity: sha512-y24Vt3oeE6ZXvyLJamP0Ke02rPlDGE9gF7OFADnR0mT+2uectb0UTIBC3kKzON80TEAlA3GXpKFkCW5Fo/O/Kg==} - '@turf/triangle-grid@6.5.0': - resolution: {integrity: sha512-2jToUSAS1R1htq4TyLQYPTIsoy6wg3e3BQXjm2rANzw4wPQCXGOxrur1Fy9RtzwqwljlC7DF4tg0OnWr8RjmfA==} + '@turf/transform-rotate@7.2.0': + resolution: {integrity: sha512-EMCj0Zqy3cF9d3mGRqDlYnX2ZBXe3LgT+piDR0EuF5c5sjuKErcFcaBIsn/lg1gp4xCNZFinkZ3dsFfgGHf6fw==} - '@turf/truncate@6.5.0': - resolution: {integrity: sha512-pFxg71pLk+eJj134Z9yUoRhIi8vqnnKvCYwdT4x/DQl/19RVdq1tV3yqOT3gcTQNfniteylL5qV1uTBDV5sgrg==} + '@turf/transform-scale@7.2.0': + resolution: {integrity: sha512-HYB+pw938eeI8s1/zSWFy6hq+t38fuUaBb0jJsZB1K9zQ1WjEYpPvKF/0//80zNPlyxLv3cOkeBucso3hzI07A==} - '@turf/turf@6.5.0': - resolution: {integrity: sha512-ipMCPnhu59bh92MNt8+pr1VZQhHVuTMHklciQURo54heoxRzt1neNYZOBR6jdL+hNsbDGAECMuIpAutX+a3Y+w==} + '@turf/transform-translate@7.2.0': + resolution: {integrity: sha512-zAglR8MKCqkzDTjGMIQgbg/f+Q3XcKVzr9cELw5l9CrS1a0VTSDtBZLDm0kWx0ankwtam7ZmI2jXyuQWT8Gbug==} - '@turf/union@6.5.0': - resolution: {integrity: sha512-igYWCwP/f0RFHIlC2c0SKDuM/ObBaqSljI3IdV/x71805QbIvY/BYGcJdyNcgEA6cylIGl/0VSlIbpJHZ9ldhw==} + '@turf/triangle-grid@7.2.0': + resolution: {integrity: sha512-4gcAqWKh9hg6PC5nNSb9VWyLgl821cwf9yR9yEzQhEFfwYL/pZONBWCO1cwVF23vSYMSMm+/TwqxH4emxaArfw==} - '@turf/unkink-polygon@6.5.0': - resolution: {integrity: sha512-8QswkzC0UqKmN1DT6HpA9upfa1HdAA5n6bbuzHy8NJOX8oVizVAqfEPY0wqqTgboDjmBR4yyImsdPGUl3gZ8JQ==} + '@turf/truncate@7.2.0': + resolution: {integrity: sha512-jyFzxYbPugK4XjV5V/k6Xr3taBjjvo210IbPHJXw0Zh7Y6sF+hGxeRVtSuZ9VP/6oRyqAOHKUrze+OOkPqBgUg==} - '@turf/voronoi@6.5.0': - resolution: {integrity: sha512-C/xUsywYX+7h1UyNqnydHXiun4UPjK88VDghtoRypR9cLlb7qozkiLRphQxxsCM0KxyxpVPHBVQXdAL3+Yurow==} + '@turf/turf@7.2.0': + resolution: {integrity: sha512-G1kKBu4hYgoNoRJgnpJohNuS7bLnoWHZ2G/4wUMym5xOSiYah6carzdTEsMoTsauyi7ilByWHx5UHwbjjCVcBw==} - '@types/chrome@0.0.263': - resolution: {integrity: sha512-As0vzv99ov3M6ZR7R6VzhMWFZXkPMrFrCEXXVrMN576Cm70fTkj7Df2CF+qEo170JepX50pd11cX6O4DSAtl2Q==} + '@turf/union@7.2.0': + resolution: {integrity: sha512-Xex/cfKSmH0RZRWSJl4RLlhSmEALVewywiEXcu0aIxNbuZGTcpNoI0h4oLFrE/fUd0iBGFg/EGLXRL3zTfpg6g==} - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@turf/unkink-polygon@7.2.0': + resolution: {integrity: sha512-dFPfzlIgkEr15z6oXVxTSWshWi51HeITGVFtl1GAKGMtiXJx1uMqnfRsvljqEjaQu/4AzG1QAp3b+EkSklQSiQ==} + + '@turf/voronoi@7.2.0': + resolution: {integrity: sha512-3K6N0LtJsWTXxPb/5N2qD9e8f4q8+tjTbGV3lE3v8x06iCnNlnuJnqM5NZNPpvgvCatecBkhClO3/3RndE61Fw==} + + '@types/chrome@0.0.299': + resolution: {integrity: sha512-hPoHmFWUaKw2s3wDjUtMsvZqeh9lKL7nFQx6yaAYt7RxBKv/V3rDUaA4BgUR145nnpF6hpNhHaxhtcCSFJ5b7w==} + + '@types/d3-voronoi@1.1.12': + resolution: {integrity: sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==} '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -1691,8 +1562,8 @@ packages: '@types/geojson@7946.0.14': resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} - '@types/geojson@7946.0.8': - resolution: {integrity: sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==} + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} '@types/har-format@1.2.15': resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==} @@ -1709,20 +1580,19 @@ packages: '@types/mapbox__vector-tile@1.3.4': resolution: {integrity: sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==} - '@types/node@20.14.9': - resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} + '@types/node@22.12.0': + resolution: {integrity: sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==} '@types/pbf@3.0.5': resolution: {integrity: sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==} - '@types/prop-types@15.7.12': - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + '@types/react-dom@19.0.3': + resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==} + peerDependencies: + '@types/react': ^19.0.0 - '@types/react-dom@18.3.0': - resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - - '@types/react@18.3.3': - resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + '@types/react@19.0.8': + resolution: {integrity: sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==} '@types/supercluster@7.1.3': resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} @@ -1730,8 +1600,8 @@ packages: '@types/validator@13.12.0': resolution: {integrity: sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==} - '@types/w3c-web-serial@1.0.6': - resolution: {integrity: sha512-5IlDdQ2C56sCVwc7CUlqT9Axxw+0V/FbWRbErklYIzZ5mKL9s4l7epXHygn+4X7L2nmAPnVvRl55XUVo0760Rg==} + '@types/w3c-web-serial@1.0.7': + resolution: {integrity: sha512-jzcwm//EZ0Z306L1/O1GXC3GthRd//9eaNB4/Yagm98UjEQViTzDS8bYvL+y+rTk1r9OFt9Yhp5pprUQFzSiiQ==} '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} @@ -1770,10 +1640,6 @@ packages: resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} engines: {node: '>=0.10.0'} - array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - asn1.js@4.10.1: resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} @@ -1784,8 +1650,8 @@ packages: resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} engines: {node: '>=0.10.0'} - autoprefixer@10.4.19: - resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: @@ -1801,6 +1667,9 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -1843,8 +1712,8 @@ packages: browserify-zlib@0.2.0: resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} - browserslist@4.23.1: - resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1884,9 +1753,9 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} cipher-base@1.0.4: resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} @@ -1894,22 +1763,18 @@ packages: class-validator@0.14.1: resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==} - class-variance-authority@0.7.0: - resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} - - clsx@2.0.0: - resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} - engines: {node: '>=6'} + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} - cmdk@1.0.0: - resolution: {integrity: sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==} + cmdk@1.0.4: + resolution: {integrity: sha512-AnsjfHyHpQ/EFeAnG216WY7A5LiYCoZzCSygiLvfXC3H3LFGCprErteUcszaVluGOhuOTbJS3jWHrSDYPBBygg==} peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 + react: ^18 || ^19 || ^19.0.0-rc + react-dom: ^18 || ^19 || ^19.0.0-rc color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -1918,6 +1783,10 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -1925,10 +1794,6 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - concaveman@1.2.1: resolution: {integrity: sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw==} @@ -1938,8 +1803,8 @@ packages: constants-browserify@1.0.0: resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} - core-js@3.38.1: - resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==} + core-js@3.40.0: + resolution: {integrity: sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -1996,14 +1861,6 @@ packages: d3-voronoi@1.1.2: resolution: {integrity: sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==} - deep-equal@1.1.2: - resolution: {integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==} - engines: {node: '>= 0.4'} - - deep-equal@2.2.3: - resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} - engines: {node: '>= 0.4'} - define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -2012,9 +1869,6 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - density-clustering@1.3.0: - resolution: {integrity: sha512-icpmBubVTwLnsaor9qH/4tG5+7+f61VcqMN3V3pm9sxxSCt2Jcs0zWOgwZW9ARJYaKD3FumIgHiMOcIMRRAzFQ==} - des.js@1.1.0: resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} @@ -2043,14 +1897,14 @@ packages: earcut@2.2.4: resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==} - earcut@3.0.0: - resolution: {integrity: sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg==} + earcut@3.0.1: + resolution: {integrity: sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==} eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.4.812: - resolution: {integrity: sha512-7L8fC2Ey/b6SePDFKR2zHAy4mbdp1/38Yk5TsARO66W3hC5KEaeKMMHoxwtuH+jcu2AYLSn9QX04i95t6Fl1Hg==} + electron-to-chromium@1.5.88: + resolution: {integrity: sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw==} elliptic@6.6.0: resolution: {integrity: sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==} @@ -2075,16 +1929,13 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} hasBin: true - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} estree-walker@2.0.2: @@ -2105,6 +1956,9 @@ packages: resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} engines: {node: '>=0.10.0'} + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -2112,9 +1966,6 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fflate@0.8.2: - resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -2133,10 +1984,6 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2145,14 +1992,11 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + geojson-equality-ts@1.0.2: + resolution: {integrity: sha512-h3Ryq+0mCSN/7yLs0eDgrZhvc9af23o/QuC4aTiuuzP/MRCtd6mf5rLsLRY44jX0RPUfM8c4GqERQmlUxPGPoQ==} - geojson-equality@0.1.6: - resolution: {integrity: sha512-TqG8YbqizP3EfwP5Uw4aLu6pKkg6JQK9uq/XZ1lXQntvTHD1BBKJWhNpJ2M0ax6TuWMP3oyx6Oq7FCIfznrgpQ==} - - geojson-rbush@3.2.0: - resolution: {integrity: sha512-oVltQTXolxvsz1sZnutlSuLDEcQAKYC/uXt9zDzJJ6bu0W+baTI8LZBaTup5afzibEH4N3jlq2p+a152wlBJ7w==} + geojson-polygon-self-intersections@1.2.1: + resolution: {integrity: sha512-/QM1b5u2d172qQVO//9CGRa49jEmclKEsYOQmWP9ooEjj63tBM51m2805xsbxkzlEELQ2REgTf700gUhhlegxA==} geojson-vt@3.2.1: resolution: {integrity: sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==} @@ -2202,14 +2046,11 @@ packages: grid-index@1.1.0: resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==} - gzipper@7.2.0: - resolution: {integrity: sha512-qwYQr7GWBXIm9Cdzud+tyM/s9N+QFzGDZoF9YR8RYJbDKOYowzjMDPEinFtm78EQeeYMC/FJW2FXY0bHkyUgsA==} - engines: {node: '>=14'} + gzipper@8.2.0: + resolution: {integrity: sha512-JUvhzo8dHQWJp1eyYy1ShaPfcowsPbRc2rvwkD4LRyou/80UUz96bn+EOOYLWO4PG0Y5f3+UlUX9Gmu8RZhrtw==} + engines: {node: '>=20.11.0'} hasBin: true - has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -2261,32 +2102,14 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - - invariant@2.2.4: - resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} - is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - - is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -2295,10 +2118,6 @@ packages: resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} engines: {node: '>= 0.4'} - is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} @@ -2323,18 +2142,10 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - is-nan@1.3.2: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} - is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -2343,47 +2154,16 @@ packages: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} - is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - - is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - - is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - is-typed-array@1.1.13: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - is-weakset@2.0.3: - resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} - engines: {node: '>= 0.4'} - is-zst@1.0.0: resolution: {integrity: sha512-ZA5lvshKAl8z30dX7saXLpVhpsq3d2EHK9uf7qtUjnOtdw4XBpAoWb2RvZ5kyoaebdoidnGI0g2hn9Z7ObPbww==} isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -2391,6 +2171,10 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} + isomorphic-rslog@0.0.6: + resolution: {integrity: sha512-HM0q6XqQ93psDlqvuViNs/Ea3hAyGDkIdVAHlrEocjjAwGrs1fZ+EdQjS9eUPacnYB7Y8SoDdSY3H8p3ce205A==} + engines: {node: '>=14.17.6'} + isomorphic-timers-promises@1.0.1: resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==} engines: {node: '>=10'} @@ -2407,18 +2191,16 @@ packages: resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} engines: {node: '>=14'} - js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - json-stringify-pretty-compact@3.0.0: resolution: {integrity: sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==} json-stringify-pretty-compact@4.0.0: resolution: {integrity: sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==} + jsts@2.7.1: + resolution: {integrity: sha512-x2wSZHEBK20CY+Wy+BPE7MrFQHW6sIsdaGUMEqmGAio+3gFzQaBYPwLRonUfQf9Ak8pBieqj9tUofX1+WtAEIg==} + engines: {node: '>= 12'} + kdbush@4.0.2: resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} @@ -2429,12 +2211,8 @@ packages: libphonenumber-js@1.11.4: resolution: {integrity: sha512-F/R50HQuWWYcmU/esP5jrH5LiWYaN7DpN0a/99U8+mnGGtnx8kmRE+649dQh3v+CowXXZc8vpkf5AmYkO0AQ7Q==} - lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - - lilconfig@3.1.2: - resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} lines-and-columns@1.2.4: @@ -2446,30 +2224,30 @@ packages: lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. lru-cache@10.2.2: resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} engines: {node: 14 || >=16.14} - lucide-react@0.363.0: - resolution: {integrity: sha512-AlsfPCsXQyQx7wwsIgzcKOL9LwC498LIMAo+c0Es5PkHJa33xwmYAkkSoKoJWWWSYQEStqu58/jT4tL2gi32uQ==} + lucide-react@0.474.0: + resolution: {integrity: sha512-CmghgHkh0OJNmxGKWc0qfPJCYHASPMVSyGY8fj3xgk4v84ItqDg64JNKFZn5hC6E0vHi6gxnbCgwhyVB09wQtA==} peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} - mapbox-gl@3.6.0: - resolution: {integrity: sha512-xjYHHIJDh6haYcKY+/9jh1eywwYfIOWCgT5Fowj4JriZexx/oOtg2S7BQDMZtpFyg9IN4VLCysmUWxY0pFNRWA==} + mapbox-gl@3.9.4: + resolution: {integrity: sha512-IxfpdyNzjCMzkqj/q5OUamlF1QcS+IFEARteygEgao2B8l8+UF2ahpNRgHT2EpMSE8ma1bq4LKvr+EuJ6gqniw==} maplibre-gl@4.1.2: resolution: {integrity: sha512-98T+3BesL4w/N39q/rgs9q6HzHLG6pgbS9UaTqg6fMISfzy2WGKokjK205ENFDDmEljj54/LTfdXgqg2XfYU4A==} engines: {node: '>=16.14.0', npm: '>=8.1.0'} + marchingsquares@1.3.3: + resolution: {integrity: sha512-gz6nNQoVK7Lkh2pZulrT4qd4347S/toG9RXH2pyzhLgkL5mLkBoqgv4EvAGXcV0ikDW72n/OQb3Xe8bGagQZCg==} + md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} @@ -2498,24 +2276,16 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - - minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} + minizlib@3.0.1: + resolution: {integrity: sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==} + engines: {node: '>= 18'} - mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} engines: {node: '>=10'} hasBin: true @@ -2530,8 +2300,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} node-stdlib-browser@1.2.0: resolution: {integrity: sha512-VSjFxUhRhkyed8AtLwSCkMrJRfQ3e2lGtG3sP6FEgaLKBBbxM/dLfjRe1+iLhjvyLFW3tBQ8+c0pcOtXGbAZJg==} @@ -2615,8 +2385,8 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - pbf@3.2.1: - resolution: {integrity: sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==} + pbf@3.3.0: + resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==} hasBin: true pbkdf2@3.1.2: @@ -2626,9 +2396,6 @@ packages: peek-stream@1.1.3: resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} - picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -2648,11 +2415,14 @@ packages: resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} engines: {node: '>=10'} + point-in-polygon-hao@1.2.4: + resolution: {integrity: sha512-x2pcvXeqhRHlNRdhLs/tgFapAbSSe86wa/eqmj1G6pWftbEs5aVRJhRGM6FYSUERKu0PjekJzMq0gsI2XyiclQ==} + point-in-polygon@1.1.0: resolution: {integrity: sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==} - polygon-clipping@0.15.7: - resolution: {integrity: sha512-nhfdr83ECBg6xtqOAJab1tbksbBAOMUltN60bU+llHVOL0e5Onm1WpAXXWXVB39L8AJFssoIhEVuy/S90MmotA==} + polyclip-ts@0.16.8: + resolution: {integrity: sha512-JPtKbDRuPEuAjuTdhR62Gph7Is2BS1Szx69CFOO3g71lpJDFo78k4tFyi+qFOMVPePEzdSKkpGU3NBXPHHjvKQ==} possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} @@ -2682,25 +2452,21 @@ packages: ts-node: optional: true - postcss-nested@6.0.1: - resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 - postcss-selector-parser@6.1.0: - resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==} + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} - engines: {node: ^10 || ^12 || >=14} - - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + postcss@8.5.1: + resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} engines: {node: ^10 || ^12 || >=14} potpack@2.0.0: @@ -2716,9 +2482,6 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - protocol-buffers-schema@3.6.0: resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} @@ -2766,25 +2529,22 @@ packages: rbush@3.0.1: resolution: {integrity: sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==} - react-dom@18.3.1: - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + react-dom@19.0.0: + resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} peerDependencies: - react: ^18.3.1 + react: ^19.0.0 - react-hook-form@7.52.0: - resolution: {integrity: sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A==} - engines: {node: '>=12.22.0'} + react-hook-form@7.54.2: + resolution: {integrity: sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==} + engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - - react-map-gl@7.1.7: - resolution: {integrity: sha512-mwjc0obkBJOXCcoXQr3VoLqmqwo9vS4bXfbGsdxXzEgVCv/PM0v+1QggL7W0d/ccIy+VCjbXNlGij+PENz6VNg==} + react-map-gl@7.1.9: + resolution: {integrity: sha512-KsCc8Gyn05wVGlHZoopaiiCr0RCAQ6LDISo5sEy1/pV/d7RlozkF946tiX7IgyijJQMRujHol5QdwUPESjh73w==} peerDependencies: mapbox-gl: '>=1.13.0' - maplibre-gl: '>=1.13.0' + maplibre-gl: '>=1.13.0 <5.0.0' react: '>=16.3.0' react-dom: '>=16.3.0' peerDependenciesMeta: @@ -2793,62 +2553,48 @@ packages: maplibre-gl: optional: true - react-qrcode-logo@2.10.0: - resolution: {integrity: sha512-Q1+jLtcyDl5rLR29YdkXVLzYk62p3+541x00HxURVBQhs6SqFyEZZVhvkU/VQ082ytXa3GdCmGWMLK5z0Vhe7g==} + react-qrcode-logo@3.0.0: + resolution: {integrity: sha512-2+vZ3GNBdUpYxIKyt6SFZsDGXa0xniyUQ0wPI4O0hJTzRjttPIx1pPnH9IWQmp/4nDMoN47IBhi3Breu1KudYw==} peerDependencies: - react: '>=16.4.1' - react-dom: '>=16.4.1' + react: '>=18.0.0' + react-dom: '>=18.0.0' - react-refresh@0.14.2: - resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + react-refresh@0.16.0: + resolution: {integrity: sha512-FPvF2XxTSikpJxcr+bHut2H4gJ17+18Uy20D5/F+SKzFap62R3cM5wH6b8WN3LyGSYeQilLEcJcR1fjBSI2S1A==} engines: {node: '>=0.10.0'} - react-remove-scroll-bar@2.3.6: - resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==} + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: '@types/react': optional: true - react-remove-scroll@2.5.5: - resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==} + react-remove-scroll@2.6.3: + resolution: {integrity: sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true - react-remove-scroll@2.5.7: - resolution: {integrity: sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==} + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true - react-style-singleton@2.2.1: - resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - react@16.14.0: - resolution: {integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==} - engines: {node: '>=0.10.0'} - - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + react@19.0.0: + resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} engines: {node: '>=0.10.0'} read-cache@1.0.0: @@ -2865,13 +2611,6 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - resolve-protobuf-schema@2.1.0: resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} @@ -2883,8 +2622,12 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfc4648@1.5.3: - resolution: {integrity: sha512-MjOWxM065+WswwnmNONOT+bD1nXzY9Km6u3kzvnx8F8/HXGZdz3T6e6vZJ8Q/RIMUSp/nxqjH3GwvJDy8ijeQQ==} + rfc4648@1.5.4: + resolution: {integrity: sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==} + + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true ripemd160@2.0.2: resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} @@ -2912,8 +2655,8 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + scheduler@0.25.0: + resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} serialize-to-js@3.1.2: resolution: {integrity: sha512-owllqNuDDEimQat7EPG0tH7JjO090xKNzUtYz6X+Sk2BXDnOCilDdNLwjWeFywG9xkJul1ULvtUQa9O4pUaY0w==} @@ -2923,10 +2666,6 @@ packages: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - set-value@2.0.1: resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} engines: {node: '>=0.10.0'} @@ -2976,16 +2715,12 @@ packages: resolution: {integrity: sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==} engines: {node: '>=0.10.0'} - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - splaytree@3.1.2: - resolution: {integrity: sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A==} + splaytree-ts@1.0.2: + resolution: {integrity: sha512-0kGecIZNIReCSiznK3uheYB8sbstLjCZLiwcQwbmLhgHJj2gz6OnSPkVzJQCMnmEz1BQ4gPK59ylhBoEWOhGNA==} split-string@3.1.0: resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} @@ -3002,10 +2737,6 @@ packages: resolution: {integrity: sha512-PDoQajqiTtJLNDWfJCihzACiTVZyFsXi6hNAVNelNJoNmqj+BaWuhJ/NHaAHxzfSRoMbL+hFgfPqFmxiHhAQSQ==} engines: {node: '>=4.2.4'} - stop-iteration-iterator@1.0.0: - resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} - engines: {node: '>= 0.4'} - stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} @@ -3049,22 +2780,25 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tailwind-merge@2.3.0: - resolution: {integrity: sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==} + sweepline-intersections@1.5.0: + resolution: {integrity: sha512-AoVmx72QHpKtItPu72TzFL+kcYjd67BPLDoR0LarIk+xyaRg+pDTMFXndIEvZf9xEKnJv6JdhgRMnocoG0D3AQ==} + + tailwind-merge@2.6.0: + resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==} tailwindcss-animate@1.0.7: resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@3.4.4: - resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==} + tailwindcss@3.4.17: + resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} engines: {node: '>=14.0.0'} hasBin: true - tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} tempfile@1.1.1: resolution: {integrity: sha512-NjT12fW6pSEKz1eVcADgaKfeM+XZ4+zSaqVz46XH7+CiEwcelnwtGWRRjF1p+xyW2PVgKKKS2UUw1LzRelntxg==} @@ -3119,6 +2853,9 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tslog@4.9.3: resolution: {integrity: sha512-oDWuGVONxhVEBtschLf2cs/Jy8i7h1T+CpdkTNWQgdAF7DhRo2G8vMCgILKe7ojdEkLhICWgI1LYSSKaJsRgcw==} engines: {node: '>=16'} @@ -3126,18 +2863,12 @@ packages: tty-browserify@0.0.1: resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} - turf-jsts@1.2.3: - resolution: {integrity: sha512-Ja03QIJlPuHt4IQ2FfGex4F4JAr8m3jpaHbFbQrgwr7s7L6U8ocrHiF3J1+wf9jzhGKxvDeaCAnGDot8OjGFyA==} - - tweakpane@4.0.4: - resolution: {integrity: sha512-RkWD54zDlEbnN01wQPk0ANHGbdCvlJx/E8A1QxhTfCbX+ROWos1Ws2MnhOm39aUGMOh+36TjUwpDmLfmwTr1Fg==} - type-fest@2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} - typescript@5.5.2: - resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==} + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} engines: {node: '>=14.17'} hasBin: true @@ -3147,15 +2878,15 @@ packages: typewise@1.0.3: resolution: {integrity: sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} union-value@1.0.1: resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} engines: {node: '>=0.10.0'} - update-browserslist-db@1.0.16: - resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} + update-browserslist-db@1.1.2: + resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -3164,30 +2895,30 @@ packages: resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} engines: {node: '>= 0.4'} - use-callback-ref@1.3.2: - resolution: {integrity: sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==} + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true - use-sidecar@1.1.2: - resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true - use-sync-external-store@1.2.0: - resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + use-sync-external-store@1.4.0: + resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -3199,18 +2930,14 @@ packages: resolution: {integrity: sha512-FULf7fayPdpASncVy4DLh3xydlXEJJpvIELjYjNeQWYUZ9pclcpvCZSr2gkmN2FrrGcI7G/cJsIEwk5/8vfXpg==} deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - validator@13.12.0: resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} engines: {node: '>= 0.10'} - vite-plugin-node-polyfills@0.22.0: - resolution: {integrity: sha512-F+G3LjiGbG8QpbH9bZ//GSBr9i1InSTkaulfUHFa9jkLqVGORFBoqc2A/Yu5Mmh1kNAbiAeKeK+6aaQUf3x0JA==} + vite-plugin-node-polyfills@0.23.0: + resolution: {integrity: sha512-4n+Ys+2bKHQohPBKigFlndwWQ5fFKwaGY6muNDMTb0fSQLyBzS+jjUNRZG9sKF0S/Go4ApG6LFnUGopjkILg3w==} peerDependencies: - vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 vite@5.3.6: resolution: {integrity: sha512-es78AlrylO8mTVBygC0gTC0FENv0C6T496vvd33ydbjF/mIi9q3XQ9A3NWo5qLGFKywvz10J26813OkLvcQleA==} @@ -3246,13 +2973,6 @@ packages: vt-pbf@3.1.3: resolution: {integrity: sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==} - which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - which-typed-array@1.1.15: resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} engines: {node: '>= 0.4'} @@ -3281,8 +3001,9 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} yaml@2.4.5: resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} @@ -3293,13 +3014,14 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zustand@4.5.2: - resolution: {integrity: sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==} - engines: {node: '>=12.7.0'} + zustand@5.0.3: + resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} + engines: {node: '>=12.20.0'} peerDependencies: - '@types/react': '>=16.8' + '@types/react': '>=18.0.0' immer: '>=9.0.6' - react: '>=16.8' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' peerDependenciesMeta: '@types/react': optional: true @@ -3307,62 +3029,50 @@ packages: optional: true react: optional: true + use-sync-external-store: + optional: true snapshots: '@alloc/quick-lru@5.2.0': {} - '@babel/runtime@7.24.7': - dependencies: - regenerator-runtime: 0.14.1 - - '@biomejs/biome@1.8.2': + '@biomejs/biome@1.9.4': optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.8.2 - '@biomejs/cli-darwin-x64': 1.8.2 - '@biomejs/cli-linux-arm64': 1.8.2 - '@biomejs/cli-linux-arm64-musl': 1.8.2 - '@biomejs/cli-linux-x64': 1.8.2 - '@biomejs/cli-linux-x64-musl': 1.8.2 - '@biomejs/cli-win32-arm64': 1.8.2 - '@biomejs/cli-win32-x64': 1.8.2 + '@biomejs/cli-darwin-arm64': 1.9.4 + '@biomejs/cli-darwin-x64': 1.9.4 + '@biomejs/cli-linux-arm64': 1.9.4 + '@biomejs/cli-linux-arm64-musl': 1.9.4 + '@biomejs/cli-linux-x64': 1.9.4 + '@biomejs/cli-linux-x64-musl': 1.9.4 + '@biomejs/cli-win32-arm64': 1.9.4 + '@biomejs/cli-win32-x64': 1.9.4 - '@biomejs/cli-darwin-arm64@1.8.2': + '@biomejs/cli-darwin-arm64@1.9.4': optional: true - '@biomejs/cli-darwin-x64@1.8.2': + '@biomejs/cli-darwin-x64@1.9.4': optional: true - '@biomejs/cli-linux-arm64-musl@1.8.2': + '@biomejs/cli-linux-arm64-musl@1.9.4': optional: true - '@biomejs/cli-linux-arm64@1.8.2': + '@biomejs/cli-linux-arm64@1.9.4': optional: true - '@biomejs/cli-linux-x64-musl@1.8.2': + '@biomejs/cli-linux-x64-musl@1.9.4': optional: true - '@biomejs/cli-linux-x64@1.8.2': + '@biomejs/cli-linux-x64@1.9.4': optional: true - '@biomejs/cli-win32-arm64@1.8.2': + '@biomejs/cli-win32-arm64@1.9.4': optional: true - '@biomejs/cli-win32-x64@1.8.2': + '@biomejs/cli-win32-x64@1.9.4': optional: true '@bufbuild/protobuf@1.10.0': {} - '@emeraldpay/hashicon-react@0.5.2': - dependencies: - '@emeraldpay/hashicon': 0.5.2 - react: 16.14.0 - - '@emeraldpay/hashicon@0.5.2': - dependencies: - '@stablelib/blake2s': 1.0.1 - js-sha3: 0.8.0 - '@esbuild/aix-ppc64@0.21.5': optional: true @@ -3441,11 +3151,11 @@ snapshots: '@floating-ui/core': 1.6.3 '@floating-ui/utils': 0.2.3 - '@floating-ui/react-dom@2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@floating-ui/react-dom@2.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@floating-ui/dom': 1.6.6 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) '@floating-ui/utils@0.2.3': {} @@ -3462,24 +3172,26 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} - '@jridgewell/sourcemap-codec@1.4.15': {} - '@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@mapbox/geojson-rewind@0.5.2': dependencies: @@ -3511,7 +3223,7 @@ snapshots: rw: 1.3.3 sort-object: 3.0.3 - '@maplibre/maplibre-gl-style-spec@20.3.0': + '@maplibre/maplibre-gl-style-spec@20.4.0': dependencies: '@mapbox/jsonlint-lines-primitives': 2.0.2 '@mapbox/unitbezier': 0.0.1 @@ -3519,8 +3231,7 @@ snapshots: minimist: 1.2.8 quickselect: 2.0.0 rw: 1.3.3 - sort-object: 3.0.3 - tinyqueue: 2.0.3 + tinyqueue: 3.0.0 '@meshtastic/js@2.3.7-5': dependencies: @@ -3530,27 +3241,32 @@ snapshots: transitivePeerDependencies: - buffer - '@module-federation/runtime-tools@0.5.1': + '@module-federation/error-codes@0.8.4': {} + + '@module-federation/runtime-tools@0.8.4': dependencies: - '@module-federation/runtime': 0.5.1 - '@module-federation/webpack-bundler-runtime': 0.5.1 + '@module-federation/runtime': 0.8.4 + '@module-federation/webpack-bundler-runtime': 0.8.4 - '@module-federation/runtime@0.5.1': + '@module-federation/runtime@0.8.4': dependencies: - '@module-federation/sdk': 0.5.1 + '@module-federation/error-codes': 0.8.4 + '@module-federation/sdk': 0.8.4 - '@module-federation/sdk@0.5.1': {} - - '@module-federation/webpack-bundler-runtime@0.5.1': + '@module-federation/sdk@0.8.4': dependencies: - '@module-federation/runtime': 0.5.1 - '@module-federation/sdk': 0.5.1 + isomorphic-rslog: 0.0.6 - '@noble/curves@1.5.0': + '@module-federation/webpack-bundler-runtime@0.8.4': dependencies: - '@noble/hashes': 1.4.0 + '@module-federation/runtime': 0.8.4 + '@module-federation/sdk': 0.8.4 - '@noble/hashes@1.4.0': {} + '@noble/curves@1.8.1': + dependencies: + '@noble/hashes': 1.7.1 + + '@noble/hashes@1.7.1': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -3569,648 +3285,519 @@ snapshots: '@radix-ui/number@1.1.0': {} - '@radix-ui/primitive@1.0.1': - dependencies: - '@babel/runtime': 7.24.7 + '@radix-ui/primitive@1.1.1': {} - '@radix-ui/primitive@1.1.0': {} - - '@radix-ui/react-accordion@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-accordion@1.2.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collapsible': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collapsible': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-arrow@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-checkbox@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-checkbox@1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-collapsible@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-collapsible@1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-collection@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-compose-refs@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - react: 18.3.1 + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.8)(react@19.0.0)': dependencies: - react: 18.3.1 + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-context@1.0.1(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-context@1.1.1(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - react: 18.3.1 + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-context@1.1.0(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-dialog@1.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.0.1(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.0.1(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.0.2(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.3)(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) aria-hidden: 1.2.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.5(@types/react@18.3.3)(react@18.3.1) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-remove-scroll: 2.6.3(@types/react@19.0.8)(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-dialog@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-direction@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) + react: 19.0.0 + optionalDependencies: + '@types/react': 19.0.8 + + '@radix-ui/react-dismissable-layer@1.1.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) + + '@radix-ui/react-dropdown-menu@2.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-menu': 2.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) + + '@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.8)(react@19.0.0)': + dependencies: + react: 19.0.0 + optionalDependencies: + '@types/react': 19.0.8 + + '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) + + '@radix-ui/react-id@1.1.0(@types/react@19.0.8)(react@19.0.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + optionalDependencies: + '@types/react': 19.0.8 + + '@radix-ui/react-label@2.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) + + '@radix-ui/react-menu@2.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) aria-hidden: 1.2.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.3.3)(react@18.3.1) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-remove-scroll: 2.6.3(@types/react@19.0.8)(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-direction@1.1.0(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-menubar@1.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - react: 18.3.1 + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-menu': 2.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-popover@1.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-dropdown-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-menu': 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.3)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.7 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-focus-guards@1.1.0(@types/react@18.3.3)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-id@1.0.1(@types/react@18.3.3)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-id@1.1.0(@types/react@18.3.3)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-label@2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) aria-hidden: 1.2.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.3.3)(react@18.3.1) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-remove-scroll: 2.6.3(@types/react@19.0.8)(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-menubar@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-popper@1.2.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-menu': 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-popover@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - aria-hidden: 1.2.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.3.3)(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-popper@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/react-dom': 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.3)(react@18.3.1) + '@floating-ui/react-dom': 2.1.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-arrow': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.8)(react@19.0.0) '@radix-ui/rect': 1.1.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-portal@1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-portal@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-presence@1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-primitive@2.0.0(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-presence@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-primitive@2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/react-slot': 1.0.2(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-roving-focus@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 - - '@radix-ui/react-scroll-area@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-scroll-area@1.2.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/number': 1.1.0 - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-select@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-select@2.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@radix-ui/number': 1.1.0 - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) aria-hidden: 1.2.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.5.7(@types/react@18.3.3)(react@18.3.1) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-remove-scroll: 2.6.3(@types/react@19.0.8)(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-separator@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-separator@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-slot@1.0.2(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-slot@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 + '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-slot@1.1.0(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-slot@1.1.1(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-switch@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-switch@1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-previous': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-tabs@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-tabs@1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-direction': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-direction': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-toast@1.2.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-toast@1.2.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-tooltip@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-tooltip@1.1.7(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/primitive': 1.1.0 - '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-context': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.3)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-dismissable-layer': 1.1.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) - '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - react: 18.3.1 + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - react: 18.3.1 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-use-previous@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@babel/runtime': 7.24.7 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.3)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.3)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.24.7 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.3)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.3)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.3 - - '@radix-ui/react-use-rect@1.1.0(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-use-rect@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: '@radix-ui/rect': 1.1.0 - react: 18.3.1 + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-use-size@1.1.0(@types/react@18.3.3)(react@18.3.1)': + '@radix-ui/react-use-size@1.1.0(@types/react@19.0.8)(react@19.0.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.3)(react@18.3.1) - react: 18.3.1 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.8)(react@19.0.0) + react: 19.0.0 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@radix-ui/react-visually-hidden@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-visually-hidden@1.1.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: - '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 - '@types/react-dom': 18.3.0 + '@types/react': 19.0.8 + '@types/react-dom': 19.0.3(@types/react@19.0.8) '@radix-ui/rect@1.1.0': {} @@ -4224,7 +3811,7 @@ snapshots: '@rollup/pluginutils@5.1.0(rollup@4.29.1)': dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: @@ -4287,920 +3874,1198 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.29.1': optional: true - '@rsbuild/core@1.0.10': + '@rsbuild/core@1.2.3': dependencies: - '@rspack/core': 1.0.8(@swc/helpers@0.5.13) + '@rspack/core': 1.2.2(@swc/helpers@0.5.15) '@rspack/lite-tapable': 1.0.1 - '@swc/helpers': 0.5.13 - core-js: 3.38.1 - optionalDependencies: - fsevents: 2.3.3 + '@swc/helpers': 0.5.15 + core-js: 3.40.0 + transitivePeerDependencies: + - '@rspack/tracing' - '@rsbuild/plugin-react@1.0.3(@rsbuild/core@1.0.10)': + '@rsbuild/plugin-react@1.1.0(@rsbuild/core@1.2.3)': dependencies: - '@rsbuild/core': 1.0.10 - '@rspack/plugin-react-refresh': 1.0.0(react-refresh@0.14.2) - react-refresh: 0.14.2 + '@rsbuild/core': 1.2.3 + '@rspack/plugin-react-refresh': 1.0.0(react-refresh@0.16.0) + react-refresh: 0.16.0 - '@rspack/binding-darwin-arm64@1.0.8': + '@rspack/binding-darwin-arm64@1.2.2': optional: true - '@rspack/binding-darwin-x64@1.0.8': + '@rspack/binding-darwin-x64@1.2.2': optional: true - '@rspack/binding-linux-arm64-gnu@1.0.8': + '@rspack/binding-linux-arm64-gnu@1.2.2': optional: true - '@rspack/binding-linux-arm64-musl@1.0.8': + '@rspack/binding-linux-arm64-musl@1.2.2': optional: true - '@rspack/binding-linux-x64-gnu@1.0.8': + '@rspack/binding-linux-x64-gnu@1.2.2': optional: true - '@rspack/binding-linux-x64-musl@1.0.8': + '@rspack/binding-linux-x64-musl@1.2.2': optional: true - '@rspack/binding-win32-arm64-msvc@1.0.8': + '@rspack/binding-win32-arm64-msvc@1.2.2': optional: true - '@rspack/binding-win32-ia32-msvc@1.0.8': + '@rspack/binding-win32-ia32-msvc@1.2.2': optional: true - '@rspack/binding-win32-x64-msvc@1.0.8': + '@rspack/binding-win32-x64-msvc@1.2.2': optional: true - '@rspack/binding@1.0.8': + '@rspack/binding@1.2.2': optionalDependencies: - '@rspack/binding-darwin-arm64': 1.0.8 - '@rspack/binding-darwin-x64': 1.0.8 - '@rspack/binding-linux-arm64-gnu': 1.0.8 - '@rspack/binding-linux-arm64-musl': 1.0.8 - '@rspack/binding-linux-x64-gnu': 1.0.8 - '@rspack/binding-linux-x64-musl': 1.0.8 - '@rspack/binding-win32-arm64-msvc': 1.0.8 - '@rspack/binding-win32-ia32-msvc': 1.0.8 - '@rspack/binding-win32-x64-msvc': 1.0.8 + '@rspack/binding-darwin-arm64': 1.2.2 + '@rspack/binding-darwin-x64': 1.2.2 + '@rspack/binding-linux-arm64-gnu': 1.2.2 + '@rspack/binding-linux-arm64-musl': 1.2.2 + '@rspack/binding-linux-x64-gnu': 1.2.2 + '@rspack/binding-linux-x64-musl': 1.2.2 + '@rspack/binding-win32-arm64-msvc': 1.2.2 + '@rspack/binding-win32-ia32-msvc': 1.2.2 + '@rspack/binding-win32-x64-msvc': 1.2.2 - '@rspack/core@1.0.8(@swc/helpers@0.5.13)': + '@rspack/core@1.2.2(@swc/helpers@0.5.15)': dependencies: - '@module-federation/runtime-tools': 0.5.1 - '@rspack/binding': 1.0.8 + '@module-federation/runtime-tools': 0.8.4 + '@rspack/binding': 1.2.2 '@rspack/lite-tapable': 1.0.1 caniuse-lite: 1.0.30001690 optionalDependencies: - '@swc/helpers': 0.5.13 + '@swc/helpers': 0.5.15 '@rspack/lite-tapable@1.0.1': {} - '@rspack/plugin-react-refresh@1.0.0(react-refresh@0.14.2)': + '@rspack/plugin-react-refresh@1.0.0(react-refresh@0.16.0)': dependencies: error-stack-parser: 2.1.4 html-entities: 2.5.2 optionalDependencies: - react-refresh: 0.14.2 + react-refresh: 0.16.0 - '@stablelib/binary@1.0.1': + '@swc/helpers@0.5.15': dependencies: - '@stablelib/int': 1.0.1 + tslib: 2.8.1 - '@stablelib/blake2s@1.0.1': + '@turf/along@7.2.0': dependencies: - '@stablelib/binary': 1.0.1 - '@stablelib/hash': 1.0.1 - '@stablelib/wipe': 1.0.1 + '@turf/bearing': 7.2.0 + '@turf/destination': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@stablelib/hash@1.0.1': {} - - '@stablelib/int@1.0.1': {} - - '@stablelib/wipe@1.0.1': {} - - '@swc/helpers@0.5.13': + '@turf/angle@7.2.0': dependencies: - tslib: 2.6.3 + '@turf/bearing': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/rhumb-bearing': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/along@6.5.0': + '@turf/area@7.2.0': 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/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/angle@6.5.0': + '@turf/bbox-clip@7.2.0': dependencies: - '@turf/bearing': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/rhumb-bearing': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/area@6.5.0': + '@turf/bbox-polygon@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/bbox-clip@6.5.0': + '@turf/bbox@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/bbox-polygon@6.5.0': + '@turf/bearing@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/bbox@6.5.0': + '@turf/bezier-spline@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/bearing@6.5.0': + '@turf/boolean-clockwise@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/bezier-spline@6.5.0': + '@turf/boolean-concave@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/boolean-clockwise@6.5.0': + '@turf/boolean-contains@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/boolean-point-on-line': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/boolean-contains@6.5.0': + '@turf/boolean-crosses@7.2.0': 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 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/line-intersect': 7.2.0 + '@turf/polygon-to-line': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/boolean-crosses@6.5.0': + '@turf/boolean-disjoint@7.2.0': 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 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/line-intersect': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/polygon-to-line': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/boolean-disjoint@6.5.0': + '@turf/boolean-equal@7.2.0': 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 + '@turf/clean-coords': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + geojson-equality-ts: 1.0.2 + tslib: 2.8.1 - '@turf/boolean-equal@6.5.0': + '@turf/boolean-intersects@7.2.0': dependencies: - '@turf/clean-coords': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - geojson-equality: 0.1.6 + '@turf/boolean-disjoint': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/boolean-intersects@6.5.0': + '@turf/boolean-overlap@7.2.0': dependencies: - '@turf/boolean-disjoint': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/line-intersect': 7.2.0 + '@turf/line-overlap': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + geojson-equality-ts: 1.0.2 + tslib: 2.8.1 - '@turf/boolean-overlap@6.5.0': + '@turf/boolean-parallel@7.2.0': 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 + '@turf/clean-coords': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/line-segment': 7.2.0 + '@turf/rhumb-bearing': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/boolean-parallel@6.5.0': + '@turf/boolean-point-in-polygon@7.2.0': dependencies: - '@turf/clean-coords': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/line-segment': 6.5.0 - '@turf/rhumb-bearing': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + point-in-polygon-hao: 1.2.4 + tslib: 2.8.1 - '@turf/boolean-point-in-polygon@6.5.0': + '@turf/boolean-point-on-line@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/boolean-point-on-line@6.5.0': + '@turf/boolean-touches@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/boolean-point-on-line': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/boolean-within@6.5.0': + '@turf/boolean-valid@7.2.0': 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 + '@turf/bbox': 7.2.0 + '@turf/boolean-crosses': 7.2.0 + '@turf/boolean-disjoint': 7.2.0 + '@turf/boolean-overlap': 7.2.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/boolean-point-on-line': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/line-intersect': 7.2.0 + '@types/geojson': 7946.0.16 + geojson-polygon-self-intersections: 1.2.1 + tslib: 2.8.1 - '@turf/buffer@6.5.0': + '@turf/boolean-within@7.2.0': 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 + '@turf/bbox': 7.2.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/boolean-point-on-line': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 + + '@turf/buffer@7.2.0': + dependencies: + '@turf/bbox': 7.2.0 + '@turf/center': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/jsts': 2.7.2 + '@turf/meta': 7.2.0 + '@turf/projection': 7.2.0 + '@types/geojson': 7946.0.16 d3-geo: 1.7.1 - turf-jsts: 1.2.3 - '@turf/center-mean@6.5.0': + '@turf/center-mean@7.2.0': dependencies: - '@turf/bbox': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/center-median@6.5.0': + '@turf/center-median@7.2.0': 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 + '@turf/center-mean': 7.2.0 + '@turf/centroid': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/center-of-mass@6.5.0': + '@turf/center-of-mass@7.2.0': 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 + '@turf/centroid': 7.2.0 + '@turf/convex': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/center@6.5.0': + '@turf/center@7.2.0': dependencies: - '@turf/bbox': 6.5.0 - '@turf/helpers': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/centroid@6.5.0': + '@turf/centroid@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/circle@6.5.0': + '@turf/circle@7.2.0': dependencies: - '@turf/destination': 6.5.0 - '@turf/helpers': 6.5.0 + '@turf/destination': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/clean-coords@6.5.0': + '@turf/clean-coords@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/clone@6.5.0': + '@turf/clone@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/clusters-dbscan@6.5.0': + '@turf/clusters-dbscan@7.2.0': 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 + '@turf/clone': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + rbush: 3.0.1 + tslib: 2.8.1 - '@turf/clusters-kmeans@6.5.0': + '@turf/clusters-kmeans@7.2.0': dependencies: - '@turf/clone': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 skmeans: 0.9.7 + tslib: 2.8.1 - '@turf/clusters@6.5.0': + '@turf/clusters@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/collect@6.5.0': + '@turf/collect@7.2.0': dependencies: - '@turf/bbox': 6.5.0 - '@turf/boolean-point-in-polygon': 6.5.0 - '@turf/helpers': 6.5.0 - rbush: 2.0.2 + '@turf/bbox': 7.2.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + rbush: 3.0.1 + tslib: 2.8.1 - '@turf/combine@6.5.0': + '@turf/combine@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/concave@6.5.0': + '@turf/concave@7.2.0': 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 + '@turf/clone': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/tin': 7.2.0 + '@types/geojson': 7946.0.16 topojson-client: 3.1.0 topojson-server: 3.0.1 + tslib: 2.8.1 - '@turf/convex@6.5.0': + '@turf/convex@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 concaveman: 1.2.1 + tslib: 2.8.1 - '@turf/destination@6.5.0': + '@turf/destination@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/difference@6.5.0': + '@turf/difference@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - polygon-clipping: 0.15.7 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + polyclip-ts: 0.16.8 + tslib: 2.8.1 - '@turf/dissolve@6.5.0': + '@turf/dissolve@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/meta': 6.5.0 - polygon-clipping: 0.15.7 + '@turf/flatten': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + polyclip-ts: 0.16.8 + tslib: 2.8.1 - '@turf/distance-weight@6.5.0': + '@turf/distance-weight@7.2.0': dependencies: - '@turf/centroid': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/centroid': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/distance@6.5.0': + '@turf/distance@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/ellipse@6.5.0': + '@turf/ellipse@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/rhumb-destination': 6.5.0 - '@turf/transform-rotate': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/rhumb-destination': 7.2.0 + '@turf/transform-rotate': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/envelope@6.5.0': + '@turf/envelope@7.2.0': dependencies: - '@turf/bbox': 6.5.0 - '@turf/bbox-polygon': 6.5.0 - '@turf/helpers': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/bbox-polygon': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/explode@6.5.0': + '@turf/explode@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/flatten@6.5.0': + '@turf/flatten@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/flip@6.5.0': + '@turf/flip@7.2.0': dependencies: - '@turf/clone': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/great-circle@6.5.0': + '@turf/geojson-rbush@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + rbush: 3.0.1 - '@turf/helpers@6.5.0': {} - - '@turf/hex-grid@6.5.0': + '@turf/great-circle@7.2.0': dependencies: - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/intersect': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 - '@turf/interpolate@6.5.0': + '@turf/helpers@7.2.0': 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 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/intersect@6.5.0': + '@turf/hex-grid@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - polygon-clipping: 0.15.7 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/intersect': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/invariant@6.5.0': + '@turf/interpolate@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/centroid': 7.2.0 + '@turf/clone': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/hex-grid': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/point-grid': 7.2.0 + '@turf/square-grid': 7.2.0 + '@turf/triangle-grid': 7.2.0 + '@types/geojson': 7946.0.16 - '@turf/isobands@6.5.0': + '@turf/intersect@7.2.0': 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: 4.1.1 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + polyclip-ts: 0.16.8 + tslib: 2.8.1 - '@turf/isolines@6.5.0': + '@turf/invariant@7.2.0': dependencies: - '@turf/bbox': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/meta': 6.5.0 - object-assign: 4.1.1 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/kinks@6.5.0': + '@turf/isobands@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/area': 7.2.0 + '@turf/bbox': 7.2.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/explode': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + marchingsquares: 1.3.3 + tslib: 2.8.1 - '@turf/length@6.5.0': + '@turf/isolines@7.2.0': dependencies: - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + marchingsquares: 1.3.3 + tslib: 2.8.1 - '@turf/line-arc@6.5.0': + '@turf/jsts@2.7.2': dependencies: - '@turf/circle': 6.5.0 - '@turf/destination': 6.5.0 - '@turf/helpers': 6.5.0 + jsts: 2.7.1 - '@turf/line-chunk@6.5.0': + '@turf/kinks@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/length': 6.5.0 - '@turf/line-slice-along': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/line-intersect@6.5.0': + '@turf/length@7.2.0': 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.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/line-offset@6.5.0': + '@turf/line-arc@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/circle': 7.2.0 + '@turf/destination': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/line-overlap@6.5.0': + '@turf/line-chunk@7.2.0': 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.1.2 - geojson-rbush: 3.2.0 + '@turf/helpers': 7.2.0 + '@turf/length': 7.2.0 + '@turf/line-slice-along': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 - '@turf/line-segment@6.5.0': + '@turf/line-intersect@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + sweepline-intersections: 1.5.0 + tslib: 2.8.1 - '@turf/line-slice-along@6.5.0': + '@turf/line-offset@7.2.0': dependencies: - '@turf/bearing': 6.5.0 - '@turf/destination': 6.5.0 - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 - '@turf/line-slice@6.5.0': + '@turf/line-overlap@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - '@turf/nearest-point-on-line': 6.5.0 + '@turf/boolean-point-on-line': 7.2.0 + '@turf/geojson-rbush': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/line-segment': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/nearest-point-on-line': 7.2.0 + '@types/geojson': 7946.0.16 + fast-deep-equal: 3.1.3 + tslib: 2.8.1 - '@turf/line-split@6.5.0': + '@turf/line-segment@7.2.0': 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.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/line-to-polygon@6.5.0': + '@turf/line-slice-along@7.2.0': dependencies: - '@turf/bbox': 6.5.0 - '@turf/clone': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/bearing': 7.2.0 + '@turf/destination': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 - '@turf/mask@6.5.0': + '@turf/line-slice@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - polygon-clipping: 0.15.7 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/nearest-point-on-line': 7.2.0 + '@types/geojson': 7946.0.16 - '@turf/meta@6.5.0': + '@turf/line-split@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/geojson-rbush': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/line-intersect': 7.2.0 + '@turf/line-segment': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/nearest-point-on-line': 7.2.0 + '@turf/square': 7.2.0 + '@turf/truncate': 7.2.0 + '@types/geojson': 7946.0.16 - '@turf/midpoint@6.5.0': + '@turf/line-to-polygon@7.2.0': dependencies: - '@turf/bearing': 6.5.0 - '@turf/destination': 6.5.0 - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/moran-index@6.5.0': + '@turf/mask@7.2.0': dependencies: - '@turf/distance-weight': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + polyclip-ts: 0.16.8 + tslib: 2.8.1 - '@turf/nearest-point-on-line@6.5.0': + '@turf/meta@7.2.0': 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 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 - '@turf/nearest-point-to-line@6.5.0': + '@turf/midpoint@7.2.0': 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: 4.1.1 + '@turf/bearing': 7.2.0 + '@turf/destination': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/nearest-point@6.5.0': + '@turf/moran-index@7.2.0': dependencies: - '@turf/clone': 6.5.0 - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/distance-weight': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/planepoint@6.5.0': + '@turf/nearest-neighbor-analysis@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/area': 7.2.0 + '@turf/bbox': 7.2.0 + '@turf/bbox-polygon': 7.2.0 + '@turf/centroid': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/nearest-point': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/point-grid@6.5.0': + '@turf/nearest-point-on-line@7.2.0': dependencies: - '@turf/boolean-within': 6.5.0 - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/point-on-feature@6.5.0': + '@turf/nearest-point-to-line@7.2.0': 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 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/point-to-line-distance': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/point-to-line-distance@6.5.0': + '@turf/nearest-point@7.2.0': 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 + '@turf/clone': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/points-within-polygon@6.5.0': + '@turf/planepoint@7.2.0': dependencies: - '@turf/boolean-point-in-polygon': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/polygon-smooth@6.5.0': + '@turf/point-grid@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/boolean-within': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/polygon-tangents@6.5.0': + '@turf/point-on-feature@7.2.0': 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 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/center': 7.2.0 + '@turf/explode': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/nearest-point': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/polygon-to-line@6.5.0': + '@turf/point-to-line-distance@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/bearing': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/nearest-point-on-line': 7.2.0 + '@turf/projection': 7.2.0 + '@turf/rhumb-bearing': 7.2.0 + '@turf/rhumb-distance': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/polygonize@6.5.0': + '@turf/point-to-polygon-distance@7.2.0': 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 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/point-to-line-distance': 7.2.0 + '@turf/polygon-to-line': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/projection@6.5.0': + '@turf/points-within-polygon@7.2.0': dependencies: - '@turf/clone': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/random@6.5.0': + '@turf/polygon-smooth@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/rectangle-grid@6.5.0': + '@turf/polygon-tangents@7.2.0': dependencies: - '@turf/boolean-intersects': 6.5.0 - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/boolean-within': 7.2.0 + '@turf/explode': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/nearest-point': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/rewind@6.5.0': + '@turf/polygon-to-line@7.2.0': 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 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/rhumb-bearing@6.5.0': + '@turf/polygonize@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/envelope': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/rhumb-destination@6.5.0': + '@turf/projection@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/rhumb-distance@6.5.0': + '@turf/quadrat-analysis@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/area': 7.2.0 + '@turf/bbox': 7.2.0 + '@turf/bbox-polygon': 7.2.0 + '@turf/centroid': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/point-grid': 7.2.0 + '@turf/random': 7.2.0 + '@turf/square-grid': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/sample@6.5.0': + '@turf/random@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/sector@6.5.0': + '@turf/rectangle-grid@7.2.0': 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 + '@turf/boolean-intersects': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/shortest-path@6.5.0': + '@turf/rewind@7.2.0': 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 + '@turf/boolean-clockwise': 7.2.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/simplify@6.5.0': + '@turf/rhumb-bearing@7.2.0': dependencies: - '@turf/clean-coords': 6.5.0 - '@turf/clone': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/square-grid@6.5.0': + '@turf/rhumb-destination@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/rectangle-grid': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/square@6.5.0': + '@turf/rhumb-distance@7.2.0': dependencies: - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/standard-deviational-ellipse@6.5.0': + '@turf/sample@7.2.0': 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 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/tag@6.5.0': + '@turf/sector@7.2.0': dependencies: - '@turf/boolean-point-in-polygon': 6.5.0 - '@turf/clone': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/circle': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/line-arc': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/tesselate@6.5.0': + '@turf/shortest-path@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/bbox': 7.2.0 + '@turf/bbox-polygon': 7.2.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/clean-coords': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/transform-scale': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 + + '@turf/simplify@7.2.0': + dependencies: + '@turf/clean-coords': 7.2.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 + + '@turf/square-grid@7.2.0': + dependencies: + '@turf/helpers': 7.2.0 + '@turf/rectangle-grid': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 + + '@turf/square@7.2.0': + dependencies: + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 + + '@turf/standard-deviational-ellipse@7.2.0': + dependencies: + '@turf/center-mean': 7.2.0 + '@turf/ellipse': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/points-within-polygon': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 + + '@turf/tag@7.2.0': + dependencies: + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 + + '@turf/tesselate@7.2.0': + dependencies: + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 earcut: 2.2.4 + tslib: 2.8.1 - '@turf/tin@6.5.0': + '@turf/tin@7.2.0': dependencies: - '@turf/helpers': 6.5.0 + '@turf/helpers': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/transform-rotate@6.5.0': + '@turf/transform-rotate@7.2.0': 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 + '@turf/centroid': 7.2.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/rhumb-bearing': 7.2.0 + '@turf/rhumb-destination': 7.2.0 + '@turf/rhumb-distance': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/transform-scale@6.5.0': + '@turf/transform-scale@7.2.0': 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 + '@turf/bbox': 7.2.0 + '@turf/center': 7.2.0 + '@turf/centroid': 7.2.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/rhumb-bearing': 7.2.0 + '@turf/rhumb-destination': 7.2.0 + '@turf/rhumb-distance': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/transform-translate@6.5.0': + '@turf/transform-translate@7.2.0': 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 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/rhumb-destination': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/triangle-grid@6.5.0': + '@turf/triangle-grid@7.2.0': dependencies: - '@turf/distance': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/intersect': 6.5.0 + '@turf/distance': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/intersect': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/truncate@6.5.0': + '@turf/truncate@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/turf@6.5.0': + '@turf/turf@7.2.0': 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 + '@turf/along': 7.2.0 + '@turf/angle': 7.2.0 + '@turf/area': 7.2.0 + '@turf/bbox': 7.2.0 + '@turf/bbox-clip': 7.2.0 + '@turf/bbox-polygon': 7.2.0 + '@turf/bearing': 7.2.0 + '@turf/bezier-spline': 7.2.0 + '@turf/boolean-clockwise': 7.2.0 + '@turf/boolean-concave': 7.2.0 + '@turf/boolean-contains': 7.2.0 + '@turf/boolean-crosses': 7.2.0 + '@turf/boolean-disjoint': 7.2.0 + '@turf/boolean-equal': 7.2.0 + '@turf/boolean-intersects': 7.2.0 + '@turf/boolean-overlap': 7.2.0 + '@turf/boolean-parallel': 7.2.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/boolean-point-on-line': 7.2.0 + '@turf/boolean-touches': 7.2.0 + '@turf/boolean-valid': 7.2.0 + '@turf/boolean-within': 7.2.0 + '@turf/buffer': 7.2.0 + '@turf/center': 7.2.0 + '@turf/center-mean': 7.2.0 + '@turf/center-median': 7.2.0 + '@turf/center-of-mass': 7.2.0 + '@turf/centroid': 7.2.0 + '@turf/circle': 7.2.0 + '@turf/clean-coords': 7.2.0 + '@turf/clone': 7.2.0 + '@turf/clusters': 7.2.0 + '@turf/clusters-dbscan': 7.2.0 + '@turf/clusters-kmeans': 7.2.0 + '@turf/collect': 7.2.0 + '@turf/combine': 7.2.0 + '@turf/concave': 7.2.0 + '@turf/convex': 7.2.0 + '@turf/destination': 7.2.0 + '@turf/difference': 7.2.0 + '@turf/dissolve': 7.2.0 + '@turf/distance': 7.2.0 + '@turf/distance-weight': 7.2.0 + '@turf/ellipse': 7.2.0 + '@turf/envelope': 7.2.0 + '@turf/explode': 7.2.0 + '@turf/flatten': 7.2.0 + '@turf/flip': 7.2.0 + '@turf/geojson-rbush': 7.2.0 + '@turf/great-circle': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/hex-grid': 7.2.0 + '@turf/interpolate': 7.2.0 + '@turf/intersect': 7.2.0 + '@turf/invariant': 7.2.0 + '@turf/isobands': 7.2.0 + '@turf/isolines': 7.2.0 + '@turf/kinks': 7.2.0 + '@turf/length': 7.2.0 + '@turf/line-arc': 7.2.0 + '@turf/line-chunk': 7.2.0 + '@turf/line-intersect': 7.2.0 + '@turf/line-offset': 7.2.0 + '@turf/line-overlap': 7.2.0 + '@turf/line-segment': 7.2.0 + '@turf/line-slice': 7.2.0 + '@turf/line-slice-along': 7.2.0 + '@turf/line-split': 7.2.0 + '@turf/line-to-polygon': 7.2.0 + '@turf/mask': 7.2.0 + '@turf/meta': 7.2.0 + '@turf/midpoint': 7.2.0 + '@turf/moran-index': 7.2.0 + '@turf/nearest-neighbor-analysis': 7.2.0 + '@turf/nearest-point': 7.2.0 + '@turf/nearest-point-on-line': 7.2.0 + '@turf/nearest-point-to-line': 7.2.0 + '@turf/planepoint': 7.2.0 + '@turf/point-grid': 7.2.0 + '@turf/point-on-feature': 7.2.0 + '@turf/point-to-line-distance': 7.2.0 + '@turf/point-to-polygon-distance': 7.2.0 + '@turf/points-within-polygon': 7.2.0 + '@turf/polygon-smooth': 7.2.0 + '@turf/polygon-tangents': 7.2.0 + '@turf/polygon-to-line': 7.2.0 + '@turf/polygonize': 7.2.0 + '@turf/projection': 7.2.0 + '@turf/quadrat-analysis': 7.2.0 + '@turf/random': 7.2.0 + '@turf/rectangle-grid': 7.2.0 + '@turf/rewind': 7.2.0 + '@turf/rhumb-bearing': 7.2.0 + '@turf/rhumb-destination': 7.2.0 + '@turf/rhumb-distance': 7.2.0 + '@turf/sample': 7.2.0 + '@turf/sector': 7.2.0 + '@turf/shortest-path': 7.2.0 + '@turf/simplify': 7.2.0 + '@turf/square': 7.2.0 + '@turf/square-grid': 7.2.0 + '@turf/standard-deviational-ellipse': 7.2.0 + '@turf/tag': 7.2.0 + '@turf/tesselate': 7.2.0 + '@turf/tin': 7.2.0 + '@turf/transform-rotate': 7.2.0 + '@turf/transform-scale': 7.2.0 + '@turf/transform-translate': 7.2.0 + '@turf/triangle-grid': 7.2.0 + '@turf/truncate': 7.2.0 + '@turf/union': 7.2.0 + '@turf/unkink-polygon': 7.2.0 + '@turf/voronoi': 7.2.0 + '@types/geojson': 7946.0.16 + tslib: 2.8.1 - '@turf/union@6.5.0': + '@turf/union@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - polygon-clipping: 0.15.7 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + polyclip-ts: 0.16.8 + tslib: 2.8.1 - '@turf/unkink-polygon@6.5.0': + '@turf/unkink-polygon@7.2.0': 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.2 + '@turf/area': 7.2.0 + '@turf/boolean-point-in-polygon': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/meta': 7.2.0 + '@types/geojson': 7946.0.16 + rbush: 3.0.1 + tslib: 2.8.1 - '@turf/voronoi@6.5.0': + '@turf/voronoi@7.2.0': dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 + '@turf/clone': 7.2.0 + '@turf/helpers': 7.2.0 + '@turf/invariant': 7.2.0 + '@types/d3-voronoi': 1.1.12 + '@types/geojson': 7946.0.16 d3-voronoi: 1.1.2 + tslib: 2.8.1 - '@types/chrome@0.0.263': + '@types/chrome@0.0.299': dependencies: '@types/filesystem': 0.0.36 '@types/har-format': 1.2.15 - '@types/estree@1.0.5': {} + '@types/d3-voronoi@1.1.12': {} '@types/estree@1.0.6': {} @@ -5212,11 +5077,11 @@ snapshots: '@types/geojson-vt@3.2.5': dependencies: - '@types/geojson': 7946.0.14 + '@types/geojson': 7946.0.16 '@types/geojson@7946.0.14': {} - '@types/geojson@7946.0.8': {} + '@types/geojson@7946.0.16': {} '@types/har-format@1.2.15': {} @@ -5230,34 +5095,31 @@ snapshots: '@types/mapbox__vector-tile@1.3.4': dependencies: - '@types/geojson': 7946.0.14 + '@types/geojson': 7946.0.16 '@types/mapbox__point-geometry': 0.1.4 '@types/pbf': 3.0.5 - '@types/node@20.14.9': + '@types/node@22.12.0': dependencies: - undici-types: 5.26.5 + undici-types: 6.20.0 '@types/pbf@3.0.5': {} - '@types/prop-types@15.7.12': {} - - '@types/react-dom@18.3.0': + '@types/react-dom@19.0.3(@types/react@19.0.8)': dependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - '@types/react@18.3.3': + '@types/react@19.0.8': dependencies: - '@types/prop-types': 15.7.12 csstype: 3.1.3 '@types/supercluster@7.1.3': dependencies: - '@types/geojson': 7946.0.14 + '@types/geojson': 7946.0.16 '@types/validator@13.12.0': {} - '@types/w3c-web-serial@1.0.6': {} + '@types/w3c-web-serial@1.0.7': {} '@types/web-bluetooth@0.0.20': {} @@ -5286,11 +5148,6 @@ snapshots: arr-union@3.1.0: {} - array-buffer-byte-length@1.0.1: - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - asn1.js@4.10.1: dependencies: bn.js: 4.12.0 @@ -5307,14 +5164,14 @@ snapshots: assign-symbols@1.0.0: {} - autoprefixer@10.4.19(postcss@8.4.38): + autoprefixer@10.4.20(postcss@8.5.1): dependencies: - browserslist: 4.23.1 + browserslist: 4.24.4 caniuse-lite: 1.0.30001690 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.1 - postcss: 8.4.38 + picocolors: 1.1.1 + postcss: 8.5.1 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -5325,6 +5182,8 @@ snapshots: base64-js@1.5.1: {} + bignumber.js@9.1.2: {} + binary-extensions@2.3.0: {} bn.js@4.12.0: {} @@ -5389,12 +5248,12 @@ snapshots: dependencies: pako: 1.0.11 - browserslist@4.23.1: + browserslist@4.24.4: dependencies: caniuse-lite: 1.0.30001690 - electron-to-chromium: 1.4.812 - node-releases: 2.0.14 - update-browserslist-db: 1.0.16(browserslist@4.23.1) + electron-to-chromium: 1.5.88 + node-releases: 2.0.19 + update-browserslist-db: 1.1.2(browserslist@4.24.4) buffer-from@1.1.2: {} @@ -5442,7 +5301,7 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chownr@2.0.0: {} + chownr@3.0.0: {} cipher-base@1.0.4: dependencies: @@ -5455,20 +5314,20 @@ snapshots: libphonenumber-js: 1.11.4 validator: 13.12.0 - class-variance-authority@0.7.0: + class-variance-authority@0.7.1: dependencies: - clsx: 2.0.0 - - clsx@2.0.0: {} + clsx: 2.1.1 clsx@2.1.1: {} - cmdk@1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + cmdk@1.0.4(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: - '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@radix-ui/react-dialog': 1.1.5(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@radix-ui/react-id': 1.1.0(@types/react@19.0.8)(react@19.0.0) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + use-sync-external-store: 1.4.0(react@19.0.0) transitivePeerDependencies: - '@types/react' - '@types/react-dom' @@ -5479,12 +5338,12 @@ snapshots: color-name@1.1.4: {} + commander@12.1.0: {} + commander@2.20.3: {} commander@4.1.1: {} - commander@7.2.0: {} - concaveman@1.2.1: dependencies: point-in-polygon: 1.1.0 @@ -5496,7 +5355,7 @@ snapshots: constants-browserify@1.0.0: {} - core-js@3.38.1: {} + core-js@3.40.0: {} core-util-is@1.0.3: {} @@ -5564,36 +5423,6 @@ snapshots: d3-voronoi@1.1.2: {} - deep-equal@1.1.2: - dependencies: - is-arguments: 1.1.1 - is-date-object: 1.0.5 - is-regex: 1.1.4 - object-is: 1.1.6 - object-keys: 1.1.1 - regexp.prototype.flags: 1.5.2 - - deep-equal@2.2.3: - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - es-get-iterator: 1.1.3 - get-intrinsic: 1.2.4 - is-arguments: 1.1.1 - is-array-buffer: 3.0.4 - is-date-object: 1.0.5 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - isarray: 2.0.5 - object-is: 1.1.6 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - side-channel: 1.0.6 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.2 - which-typed-array: 1.1.15 - define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 @@ -5606,8 +5435,6 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - density-clustering@1.3.0: {} - des.js@1.1.0: dependencies: inherits: 2.0.4 @@ -5638,11 +5465,11 @@ snapshots: earcut@2.2.4: {} - earcut@3.0.0: {} + earcut@3.0.1: {} eastasianwidth@0.2.0: {} - electron-to-chromium@1.4.812: {} + electron-to-chromium@1.5.88: {} elliptic@6.6.0: dependencies: @@ -5672,18 +5499,6 @@ snapshots: es-errors@1.3.0: {} - es-get-iterator@1.1.3: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - is-arguments: 1.1.1 - is-map: 2.0.3 - is-set: 2.0.3 - is-string: 1.0.7 - isarray: 2.0.5 - stop-iteration-iterator: 1.0.0 - esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -5710,7 +5525,7 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - escalade@3.1.2: {} + escalade@3.2.0: {} estree-walker@2.0.2: {} @@ -5730,6 +5545,8 @@ snapshots: assign-symbols: 1.0.0 is-extendable: 1.0.1 + fast-deep-equal@3.1.3: {} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -5742,8 +5559,6 @@ snapshots: dependencies: reusify: 1.0.4 - fflate@0.8.2: {} - fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -5764,28 +5579,18 @@ snapshots: fraction.js@4.3.7: {} - fs-minipass@2.1.0: - dependencies: - minipass: 3.3.6 - fsevents@2.3.3: optional: true function-bind@1.1.2: {} - functions-have-names@1.2.3: {} - - geojson-equality@0.1.6: + geojson-equality-ts@1.0.2: dependencies: - deep-equal: 1.1.2 + '@types/geojson': 7946.0.16 - geojson-rbush@3.2.0: + geojson-polygon-self-intersections@1.2.1: dependencies: - '@turf/bbox': 6.5.0 - '@turf/helpers': 6.5.0 - '@turf/meta': 6.5.0 - '@types/geojson': 7946.0.8 - rbush: 3.0.1 + rbush: 2.0.2 geojson-vt@3.2.1: {} @@ -5836,15 +5641,11 @@ snapshots: grid-index@1.1.0: {} - gzipper@7.2.0: + gzipper@8.2.0: dependencies: '@gfx/zopfli': 1.0.15 - commander: 7.2.0 - deep-equal: 2.2.3 + commander: 12.1.0 simple-zstd: 1.4.2 - uuid: 8.3.2 - - has-bigints@1.0.2: {} has-property-descriptors@1.0.2: dependencies: @@ -5896,49 +5697,21 @@ snapshots: ini@1.3.8: {} - internal-slot@1.0.7: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - - invariant@2.2.4: - dependencies: - loose-envify: 1.4.0 - is-arguments@1.1.1: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - is-array-buffer@3.0.4: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - - is-bigint@1.0.4: - dependencies: - has-bigints: 1.0.2 - is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 - is-boolean-object@1.1.2: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - is-callable@1.2.7: {} is-core-module@2.14.0: dependencies: hasown: 2.0.2 - is-date-object@1.0.5: - dependencies: - has-tostringtag: 1.0.2 - is-extendable@0.1.1: {} is-extendable@1.0.1: @@ -5957,63 +5730,31 @@ snapshots: dependencies: is-extglob: 2.1.1 - is-map@2.0.3: {} - is-nan@1.3.2: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - is-number-object@1.0.7: - dependencies: - has-tostringtag: 1.0.2 - is-number@7.0.0: {} is-plain-object@2.0.4: dependencies: isobject: 3.0.1 - is-regex@1.1.4: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.3: - dependencies: - call-bind: 1.0.7 - - is-string@1.0.7: - dependencies: - has-tostringtag: 1.0.2 - - is-symbol@1.0.4: - dependencies: - has-symbols: 1.0.3 - is-typed-array@1.1.13: dependencies: which-typed-array: 1.1.15 - is-weakmap@2.0.2: {} - - is-weakset@2.0.3: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-zst@1.0.0: {} isarray@1.0.0: {} - isarray@2.0.5: {} - isexe@2.0.0: {} isobject@3.0.1: {} + isomorphic-rslog@0.0.6: {} + isomorphic-timers-promises@1.0.1: {} jackspeak@3.4.0: @@ -6026,23 +5767,19 @@ snapshots: js-cookie@3.0.5: {} - js-sha3@0.8.0: {} - - js-tokens@4.0.0: {} - json-stringify-pretty-compact@3.0.0: {} json-stringify-pretty-compact@4.0.0: {} + jsts@2.7.1: {} + kdbush@4.0.2: {} kind-of@6.0.3: {} libphonenumber-js@1.11.4: {} - lilconfig@2.1.0: {} - - lilconfig@3.1.2: {} + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -6052,21 +5789,17 @@ snapshots: lodash.isequal@4.5.0: {} - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - lru-cache@10.2.2: {} - lucide-react@0.363.0(react@18.3.1): + lucide-react@0.474.0(react@19.0.0): dependencies: - react: 18.3.1 + react: 19.0.0 magic-string@0.30.11: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - mapbox-gl@3.6.0: + mapbox-gl@3.9.4: dependencies: '@mapbox/jsonlint-lines-primitives': 2.0.2 '@mapbox/mapbox-gl-supported': 3.0.0 @@ -6075,25 +5808,26 @@ snapshots: '@mapbox/unitbezier': 0.0.1 '@mapbox/vector-tile': 1.3.1 '@mapbox/whoots-js': 3.1.0 - '@types/geojson': 7946.0.14 + '@types/geojson': 7946.0.16 + '@types/geojson-vt': 3.2.5 + '@types/mapbox__point-geometry': 0.1.4 '@types/mapbox__vector-tile': 1.3.4 + '@types/pbf': 3.0.5 + '@types/supercluster': 7.1.3 cheap-ruler: 4.0.0 csscolorparser: 1.0.3 - earcut: 3.0.0 - fflate: 0.8.2 + earcut: 3.0.1 geojson-vt: 4.0.2 gl-matrix: 3.4.3 grid-index: 1.1.0 kdbush: 4.0.2 murmurhash-js: 1.0.0 - pbf: 3.2.1 + pbf: 3.3.0 potpack: 2.0.0 quickselect: 3.0.0 - rw: 1.3.3 serialize-to-js: 3.1.2 supercluster: 8.0.1 tinyqueue: 3.0.0 - tweakpane: 4.0.4 vt-pbf: 3.1.3 maplibre-gl@4.1.2: @@ -6105,8 +5839,8 @@ snapshots: '@mapbox/unitbezier': 0.0.1 '@mapbox/vector-tile': 1.3.1 '@mapbox/whoots-js': 3.1.0 - '@maplibre/maplibre-gl-style-spec': 20.3.0 - '@types/geojson': 7946.0.14 + '@maplibre/maplibre-gl-style-spec': 20.4.0 + '@types/geojson': 7946.0.16 '@types/geojson-vt': 3.2.5 '@types/mapbox__point-geometry': 0.1.4 '@types/mapbox__vector-tile': 1.3.4 @@ -6118,13 +5852,15 @@ snapshots: global-prefix: 3.0.0 kdbush: 4.0.2 murmurhash-js: 1.0.0 - pbf: 3.2.1 + pbf: 3.3.0 potpack: 2.0.0 quickselect: 2.0.0 supercluster: 8.0.1 tinyqueue: 2.0.3 vt-pbf: 3.1.3 + marchingsquares@1.3.3: {} + md5.js@1.3.5: dependencies: hash-base: 3.1.0 @@ -6153,20 +5889,14 @@ snapshots: minimist@1.2.8: {} - minipass@3.3.6: - dependencies: - yallist: 4.0.0 - - minipass@5.0.0: {} - minipass@7.1.2: {} - minizlib@2.1.2: + minizlib@3.0.1: dependencies: - minipass: 3.3.6 - yallist: 4.0.0 + minipass: 7.1.2 + rimraf: 5.0.10 - mkdirp@1.0.4: {} + mkdirp@3.0.1: {} murmurhash-js@1.0.0: {} @@ -6178,7 +5908,7 @@ snapshots: nanoid@3.3.8: {} - node-releases@2.0.14: {} + node-releases@2.0.19: {} node-stdlib-browser@1.2.0: dependencies: @@ -6276,7 +6006,7 @@ snapshots: lru-cache: 10.2.2 minipass: 7.1.2 - pbf@3.2.1: + pbf@3.3.0: dependencies: ieee754: 1.2.1 resolve-protobuf-schema: 2.1.0 @@ -6295,8 +6025,6 @@ snapshots: duplexify: 3.7.1 through2: 2.0.5 - picocolors@1.0.1: {} - picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -6309,53 +6037,51 @@ snapshots: dependencies: find-up: 5.0.0 - point-in-polygon@1.1.0: {} - - polygon-clipping@0.15.7: + point-in-polygon-hao@1.2.4: dependencies: robust-predicates: 3.0.2 - splaytree: 3.1.2 + + point-in-polygon@1.1.0: {} + + polyclip-ts@0.16.8: + dependencies: + bignumber.js: 9.1.2 + splaytree-ts: 1.0.2 possible-typed-array-names@1.0.0: {} - postcss-import@15.1.0(postcss@8.4.38): + postcss-import@15.1.0(postcss@8.5.1): dependencies: - postcss: 8.4.38 + postcss: 8.5.1 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - postcss-js@4.0.1(postcss@8.4.38): + postcss-js@4.0.1(postcss@8.5.1): dependencies: camelcase-css: 2.0.1 - postcss: 8.4.38 + postcss: 8.5.1 - postcss-load-config@4.0.2(postcss@8.4.38): + postcss-load-config@4.0.2(postcss@8.5.1): dependencies: - lilconfig: 3.1.2 + lilconfig: 3.1.3 yaml: 2.4.5 optionalDependencies: - postcss: 8.4.38 + postcss: 8.5.1 - postcss-nested@6.0.1(postcss@8.4.38): + postcss-nested@6.2.0(postcss@8.5.1): dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.1.0 + postcss: 8.5.1 + postcss-selector-parser: 6.1.2 - postcss-selector-parser@6.1.0: + postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 postcss-value-parser@4.2.0: {} - postcss@8.4.38: - dependencies: - nanoid: 3.3.8 - picocolors: 1.0.1 - source-map-js: 1.2.0 - - postcss@8.4.49: + postcss@8.5.1: dependencies: nanoid: 3.3.8 picocolors: 1.1.1 @@ -6373,12 +6099,6 @@ snapshots: process@0.11.10: {} - prop-types@15.8.1: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - protocol-buffers-schema@3.6.0: {} public-encrypt@4.0.3: @@ -6427,85 +6147,62 @@ snapshots: dependencies: quickselect: 2.0.0 - react-dom@18.3.1(react@18.3.1): + react-dom@19.0.0(react@19.0.0): dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 + react: 19.0.0 + scheduler: 0.25.0 - react-hook-form@7.52.0(react@18.3.1): + react-hook-form@7.54.2(react@19.0.0): dependencies: - react: 18.3.1 + react: 19.0.0 - react-is@16.13.1: {} - - react-map-gl@7.1.7(mapbox-gl@3.6.0)(maplibre-gl@4.1.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-map-gl@7.1.9(mapbox-gl@3.9.4)(maplibre-gl@4.1.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@maplibre/maplibre-gl-style-spec': 19.3.3 '@types/mapbox-gl': 3.1.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) optionalDependencies: - mapbox-gl: 3.6.0 + mapbox-gl: 3.9.4 maplibre-gl: 4.1.2 - react-qrcode-logo@2.10.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-qrcode-logo@3.0.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: lodash.isequal: 4.5.0 qrcode-generator: 1.4.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) - react-refresh@0.14.2: {} + react-refresh@0.16.0: {} - react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1): + react-remove-scroll-bar@2.3.8(@types/react@19.0.8)(react@19.0.0): dependencies: - react: 18.3.1 - react-style-singleton: 2.2.1(@types/react@18.3.3)(react@18.3.1) + react: 19.0.0 + react-style-singleton: 2.2.3(@types/react@19.0.8)(react@19.0.0) tslib: 2.6.3 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - react-remove-scroll@2.5.5(@types/react@18.3.3)(react@18.3.1): + react-remove-scroll@2.6.3(@types/react@19.0.8)(react@19.0.0): dependencies: - react: 18.3.1 - react-remove-scroll-bar: 2.3.6(@types/react@18.3.3)(react@18.3.1) - react-style-singleton: 2.2.1(@types/react@18.3.3)(react@18.3.1) + react: 19.0.0 + react-remove-scroll-bar: 2.3.8(@types/react@19.0.8)(react@19.0.0) + react-style-singleton: 2.2.3(@types/react@19.0.8)(react@19.0.0) tslib: 2.6.3 - use-callback-ref: 1.3.2(@types/react@18.3.3)(react@18.3.1) - use-sidecar: 1.1.2(@types/react@18.3.3)(react@18.3.1) + use-callback-ref: 1.3.3(@types/react@19.0.8)(react@19.0.0) + use-sidecar: 1.1.3(@types/react@19.0.8)(react@19.0.0) optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - react-remove-scroll@2.5.7(@types/react@18.3.3)(react@18.3.1): - dependencies: - react: 18.3.1 - react-remove-scroll-bar: 2.3.6(@types/react@18.3.3)(react@18.3.1) - react-style-singleton: 2.2.1(@types/react@18.3.3)(react@18.3.1) - tslib: 2.6.3 - use-callback-ref: 1.3.2(@types/react@18.3.3)(react@18.3.1) - use-sidecar: 1.1.2(@types/react@18.3.3)(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.3 - - react-style-singleton@2.2.1(@types/react@18.3.3)(react@18.3.1): + react-style-singleton@2.2.3(@types/react@19.0.8)(react@19.0.0): dependencies: get-nonce: 1.0.1 - invariant: 2.2.4 - react: 18.3.1 + react: 19.0.0 tslib: 2.6.3 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - react@16.14.0: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - prop-types: 15.8.1 - - react@18.3.1: - dependencies: - loose-envify: 1.4.0 + react@19.0.0: {} read-cache@1.0.0: dependencies: @@ -6531,15 +6228,6 @@ snapshots: dependencies: picomatch: 2.3.1 - regenerator-runtime@0.14.1: {} - - regexp.prototype.flags@1.5.2: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - resolve-protobuf-schema@2.1.0: dependencies: protocol-buffers-schema: 3.6.0 @@ -6552,7 +6240,11 @@ snapshots: reusify@1.0.4: {} - rfc4648@1.5.3: {} + rfc4648@1.5.4: {} + + rimraf@5.0.10: + dependencies: + glob: 10.4.2 ripemd160@2.0.2: dependencies: @@ -6598,9 +6290,7 @@ snapshots: safe-buffer@5.2.1: {} - scheduler@0.23.2: - dependencies: - loose-envify: 1.4.0 + scheduler@0.25.0: {} serialize-to-js@3.1.2: {} @@ -6613,13 +6303,6 @@ snapshots: gopd: 1.0.1 has-property-descriptors: 1.0.2 - set-function-name@2.0.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - set-value@2.0.1: dependencies: extend-shallow: 2.0.1 @@ -6673,11 +6356,9 @@ snapshots: sort-desc: 0.2.0 union-value: 1.0.1 - source-map-js@1.2.0: {} - source-map-js@1.2.1: {} - splaytree@3.1.2: {} + splaytree-ts@1.0.2: {} split-string@3.1.0: dependencies: @@ -6691,10 +6372,6 @@ snapshots: dependencies: ste-core: 3.0.11 - stop-iteration-iterator@1.0.0: - dependencies: - internal-slot: 1.0.7 - stream-browserify@3.0.0: dependencies: inherits: 2.0.4 @@ -6753,15 +6430,17 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tailwind-merge@2.3.0: + sweepline-intersections@1.5.0: dependencies: - '@babel/runtime': 7.24.7 + tinyqueue: 2.0.3 - tailwindcss-animate@1.0.7(tailwindcss@3.4.4): + tailwind-merge@2.6.0: {} + + tailwindcss-animate@1.0.7(tailwindcss@3.4.17): dependencies: - tailwindcss: 3.4.4 + tailwindcss: 3.4.17 - tailwindcss@3.4.4: + tailwindcss@3.4.17: dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -6772,30 +6451,30 @@ snapshots: glob-parent: 6.0.2 is-glob: 4.0.3 jiti: 1.21.6 - lilconfig: 2.1.0 + lilconfig: 3.1.3 micromatch: 4.0.8 normalize-path: 3.0.0 object-hash: 3.0.0 - picocolors: 1.0.1 - postcss: 8.4.38 - postcss-import: 15.1.0(postcss@8.4.38) - postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38) - postcss-nested: 6.0.1(postcss@8.4.38) - postcss-selector-parser: 6.1.0 + picocolors: 1.1.1 + postcss: 8.5.1 + postcss-import: 15.1.0(postcss@8.5.1) + postcss-js: 4.0.1(postcss@8.5.1) + postcss-load-config: 4.0.2(postcss@8.5.1) + postcss-nested: 6.2.0(postcss@8.5.1) + postcss-selector-parser: 6.1.2 resolve: 1.22.8 sucrase: 3.35.0 transitivePeerDependencies: - ts-node - tar@6.2.1: + tar@7.4.3: dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.1 + mkdirp: 3.0.1 + yallist: 5.0.0 tempfile@1.1.1: dependencies: @@ -6819,9 +6498,9 @@ snapshots: dependencies: readable-stream: 3.6.2 - timeago-react@3.0.6(react@18.3.1): + timeago-react@3.0.6(react@19.0.0): dependencies: - react: 18.3.1 + react: 19.0.0 timeago.js: 4.0.2 timeago.js@4.0.2: {} @@ -6850,17 +6529,15 @@ snapshots: tslib@2.6.3: {} + tslib@2.8.1: {} + tslog@4.9.3: {} tty-browserify@0.0.1: {} - turf-jsts@1.2.3: {} - - tweakpane@4.0.4: {} - type-fest@2.19.0: {} - typescript@5.5.2: {} + typescript@5.7.3: {} typewise-core@1.2.0: {} @@ -6868,7 +6545,7 @@ snapshots: dependencies: typewise-core: 1.2.0 - undici-types@5.26.5: {} + undici-types@6.20.0: {} union-value@1.0.1: dependencies: @@ -6877,35 +6554,35 @@ snapshots: is-extendable: 0.1.1 set-value: 2.0.1 - update-browserslist-db@1.0.16(browserslist@4.23.1): + update-browserslist-db@1.1.2(browserslist@4.24.4): dependencies: - browserslist: 4.23.1 - escalade: 3.1.2 - picocolors: 1.0.1 + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 url@0.11.4: dependencies: punycode: 1.4.1 qs: 6.13.0 - use-callback-ref@1.3.2(@types/react@18.3.3)(react@18.3.1): + use-callback-ref@1.3.3(@types/react@19.0.8)(react@19.0.0): dependencies: - react: 18.3.1 + react: 19.0.0 tslib: 2.6.3 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - use-sidecar@1.1.2(@types/react@18.3.3)(react@18.3.1): + use-sidecar@1.1.3(@types/react@19.0.8)(react@19.0.0): dependencies: detect-node-es: 1.1.0 - react: 18.3.1 + react: 19.0.0 tslib: 2.6.3 optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 - use-sync-external-store@1.2.0(react@18.3.1): + use-sync-external-store@1.4.0(react@19.0.0): dependencies: - react: 18.3.1 + react: 19.0.0 util-deprecate@1.0.2: {} @@ -6919,25 +6596,23 @@ snapshots: uuid@2.0.3: {} - uuid@8.3.2: {} - validator@13.12.0: {} - vite-plugin-node-polyfills@0.22.0(rollup@4.29.1)(vite@5.3.6(@types/node@20.14.9)): + vite-plugin-node-polyfills@0.23.0(rollup@4.29.1)(vite@5.3.6(@types/node@22.12.0)): dependencies: '@rollup/plugin-inject': 5.0.5(rollup@4.29.1) node-stdlib-browser: 1.2.0 - vite: 5.3.6(@types/node@20.14.9) + vite: 5.3.6(@types/node@22.12.0) transitivePeerDependencies: - rollup - vite@5.3.6(@types/node@20.14.9): + vite@5.3.6(@types/node@22.12.0): dependencies: esbuild: 0.21.5 - postcss: 8.4.49 + postcss: 8.5.1 rollup: 4.29.1 optionalDependencies: - '@types/node': 20.14.9 + '@types/node': 22.12.0 fsevents: 2.3.3 vm-browserify@1.1.2: {} @@ -6946,22 +6621,7 @@ snapshots: dependencies: '@mapbox/point-geometry': 0.1.0 '@mapbox/vector-tile': 1.3.1 - pbf: 3.2.1 - - which-boxed-primitive@1.0.2: - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.3 + pbf: 3.3.0 which-typed-array@1.1.15: dependencies: @@ -6995,16 +6655,15 @@ snapshots: xtend@4.0.2: {} - yallist@4.0.0: {} + yallist@5.0.0: {} yaml@2.4.5: {} yocto-queue@0.1.0: {} - zustand@4.5.2(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1): - dependencies: - use-sync-external-store: 1.2.0(react@18.3.1) + zustand@5.0.3(@types/react@19.0.8)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.4.0(react@19.0.0)): optionalDependencies: - '@types/react': 18.3.3 + '@types/react': 19.0.8 immer: 10.1.1 - react: 18.3.1 + react: 19.0.0 + use-sync-external-store: 1.4.0(react@19.0.0) diff --git a/src/DeviceWrapper.tsx b/src/DeviceWrapper.tsx index d2420352..dfd66407 100644 --- a/src/DeviceWrapper.tsx +++ b/src/DeviceWrapper.tsx @@ -7,10 +7,7 @@ export interface DeviceWrapperProps { device?: Device; } -export const DeviceWrapper = ({ - children, - device, -}: DeviceWrapperProps): JSX.Element => { +export const DeviceWrapper = ({ children, device }: DeviceWrapperProps) => { return ( {children} ); diff --git a/src/PageRouter.tsx b/src/PageRouter.tsx index 2bec9fdc..025ee623 100644 --- a/src/PageRouter.tsx +++ b/src/PageRouter.tsx @@ -1,11 +1,11 @@ import { useDevice } from "@core/stores/deviceStore.ts"; -import { ChannelsPage } from "@pages/Channels.tsx"; -import { ConfigPage } from "@pages/Config/index.tsx"; -import { MapPage } from "@pages/Map.tsx"; -import { MessagesPage } from "@pages/Messages.tsx"; -import { NodesPage } from "@pages/Nodes.tsx"; +import ChannelsPage from "@pages/Channels.tsx"; +import ConfigPage from "@pages/Config/index.tsx"; +import MapPage from "@pages/Map.tsx"; +import MessagesPage from "@pages/Messages.tsx"; +import NodesPage from "@pages/Nodes.tsx"; -export const PageRouter = (): JSX.Element => { +export const PageRouter = () => { const { activePage } = useDevice(); return ( <> diff --git a/src/components/CommandPalette.tsx b/src/components/CommandPalette.tsx index efcd3954..56baddf4 100644 --- a/src/components/CommandPalette.tsx +++ b/src/components/CommandPalette.tsx @@ -1,3 +1,4 @@ +import { Avatar } from "@components/UI/Avatar"; import { CommandDialog, CommandEmpty, @@ -8,7 +9,6 @@ import { } from "@components/UI/Command.tsx"; import { useAppStore } from "@core/stores/appStore.ts"; import { useDevice, useDeviceStore } from "@core/stores/deviceStore.ts"; -import { Hashicon } from "@emeraldpay/hashicon-react"; import { useCommandState } from "cmdk"; import { ArrowLeftRightIcon, @@ -51,11 +51,11 @@ export interface Command { export interface SubItem { label: string; - icon: JSX.Element; + icon: React.ReactNode; action: () => void; } -export const CommandPalette = (): JSX.Element => { +export const CommandPalette = () => { const { commandPaletteOpen, setCommandPaletteOpen, @@ -125,9 +125,11 @@ export const CommandPalette = (): JSX.Element => { device.nodes.get(device.hardware.myNodeNum)?.user?.longName ?? device.hardware.myNodeNum.toString(), icon: ( - ), action() { diff --git a/src/components/DeviceSelector.tsx b/src/components/DeviceSelector.tsx index 42be3ecf..9816f194 100644 --- a/src/components/DeviceSelector.tsx +++ b/src/components/DeviceSelector.tsx @@ -3,7 +3,6 @@ import { Separator } from "@components/UI/Seperator.tsx"; import { Code } from "@components/UI/Typography/Code.tsx"; import { useAppStore } from "@core/stores/appStore.ts"; import { useDeviceStore } from "@core/stores/deviceStore.ts"; -import { Hashicon } from "@emeraldpay/hashicon-react"; import { HomeIcon, LanguagesIcon, @@ -12,6 +11,8 @@ import { SearchIcon, SunIcon, } from "lucide-react"; +import type { JSX } from "react"; +import { Avatar } from "./UI/Avatar"; export const DeviceSelector = (): JSX.Element => { const { getDevices } = useDeviceStore(); @@ -44,9 +45,12 @@ export const DeviceSelector = (): JSX.Element => { }} active={selectedDevice === device.id} > - ))} diff --git a/src/components/DeviceSelectorButton.tsx b/src/components/DeviceSelectorButton.tsx index 38dff36a..8c50df8e 100644 --- a/src/components/DeviceSelectorButton.tsx +++ b/src/components/DeviceSelectorButton.tsx @@ -8,15 +8,15 @@ export const DeviceSelectorButton = ({ active, onClick, children, -}: DeviceSelectorButtonProps): JSX.Element => ( +}: DeviceSelectorButtonProps) => (
  • - {active && ( + {/* {active && (
    - )} + )} */}
    {children}
    diff --git a/src/components/Form/FormSelect.tsx b/src/components/Form/FormSelect.tsx index a97e390f..95405127 100644 --- a/src/components/Form/FormSelect.tsx +++ b/src/components/Form/FormSelect.tsx @@ -51,7 +51,7 @@ export function SelectInput({ {optionsEnumValues.map(([name, value]) => ( - + {formatEnumName ? name .replace(/_/g, " ") diff --git a/src/components/Form/FormWrapper.tsx b/src/components/Form/FormWrapper.tsx index 7625946f..e9094502 100644 --- a/src/components/Form/FormWrapper.tsx +++ b/src/components/Form/FormWrapper.tsx @@ -15,9 +15,9 @@ export const FieldWrapper = ({ children, valid, validationText, -}: FieldWrapperProps): JSX.Element => ( +}: FieldWrapperProps) => (
    -
    +
    @@ -32,6 +32,6 @@ export const FieldWrapper = ({
    -
    +
    ); diff --git a/src/components/PageComponents/Map/NodeDetail.tsx b/src/components/PageComponents/Map/NodeDetail.tsx index f464ecef..5203d077 100644 --- a/src/components/PageComponents/Map/NodeDetail.tsx +++ b/src/components/PageComponents/Map/NodeDetail.tsx @@ -1,9 +1,9 @@ import { Separator } from "@app/components/UI/Seperator"; import { H5 } from "@app/components/UI/Typography/H5.tsx"; import { Subtle } from "@app/components/UI/Typography/Subtle.tsx"; +import { Avatar } from "@components/UI/Avatar"; import { Mono } from "@components/generic/Mono.tsx"; import { TimeAgo } from "@components/generic/Table/tmp/TimeAgo.tsx"; -import { Hashicon } from "@emeraldpay/hashicon-react"; import { Protobuf } from "@meshtastic/js"; import type { Protobuf as ProtobufType } from "@meshtastic/js"; import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; @@ -23,7 +23,7 @@ export interface NodeDetailProps { node: ProtobufType.Mesh.NodeInfo; } -export const NodeDetail = ({ node }: NodeDetailProps): JSX.Element => { +export const NodeDetail = ({ node }: NodeDetailProps) => { const name = node.user?.longName || `!${numberToHexUnpadded(node.num)}`; const hardwareType = Protobuf.Mesh.HardwareModel[ node.user?.hwModel ?? 0 @@ -33,7 +33,7 @@ export const NodeDetail = ({ node }: NodeDetailProps): JSX.Element => {
    - +
    {node.user?.publicKey && node.user?.publicKey.length > 0 ? ( diff --git a/src/components/PageComponents/Messages/Message.tsx b/src/components/PageComponents/Messages/Message.tsx index fc9a7b95..e8030e2a 100644 --- a/src/components/PageComponents/Messages/Message.tsx +++ b/src/components/PageComponents/Messages/Message.tsx @@ -1,5 +1,5 @@ import type { MessageWithState } from "@app/core/stores/deviceStore.ts"; -import { Hashicon } from "@emeraldpay/hashicon-react"; +import { Avatar } from "@components/UI/Avatar"; import type { Protobuf } from "@meshtastic/js"; import { AlertCircleIcon, @@ -13,11 +13,7 @@ export interface MessageProps { sender?: Protobuf.Mesh.NodeInfo; } -export const Message = ({ - lastMsgSameUser, - message, - sender, -}: MessageProps): JSX.Element => { +export const Message = ({ lastMsgSameUser, message, sender }: MessageProps) => { return lastMsgSameUser ? (
    {message.state === "ack" ? ( @@ -39,7 +35,7 @@ export const Message = ({
    - +
    {sender?.user?.longName ?? "UNK"} diff --git a/src/components/UI/Avatar.tsx b/src/components/UI/Avatar.tsx new file mode 100644 index 00000000..bbb21cb2 --- /dev/null +++ b/src/components/UI/Avatar.tsx @@ -0,0 +1,94 @@ +import { cn } from "@app/core/utils/cn"; +import type React from "react"; + +type RGBColor = { + r: number; + g: number; + b: number; + a: number; +}; + +interface AvatarProps { + text: string; + size?: "sm" | "lg"; + className?: string; +} + +// biome-ignore lint/complexity/noStaticOnlyClass: stop being annoying Biome +class ColorUtils { + static hexToRgb(hex: number): RGBColor { + return { + r: (hex & 0xff0000) >> 16, + g: (hex & 0x00ff00) >> 8, + b: hex & 0x0000ff, + a: 255, + }; + } + + static rgbToHex(color: RGBColor): number { + return ( + (Math.round(color.a) << 24) | + (Math.round(color.r) << 16) | + (Math.round(color.g) << 8) | + Math.round(color.b) + ); + } + + static isLight(color: RGBColor): boolean { + const brightness = (color.r * 299 + color.g * 587 + color.b * 114) / 1000; + return brightness > 127.5; + } +} + +export const Avatar: React.FC = ({ + text, + size = "sm", + className, +}) => { + const sizes = { + sm: "size-11 text-xs", + lg: "size-16 text-lg", + }; + + // Pick a color based on the text provided to function + const getColorFromText = (text: string): RGBColor => { + let hash = 0; + for (let i = 0; i < text.length; i++) { + hash = text.charCodeAt(i) + ((hash << 5) - hash); + } + + return { + r: (hash & 0xff0000) >> 16, + g: (hash & 0x00ff00) >> 8, + b: hash & 0x0000ff, + a: 255, + }; + }; + + const bgColor = getColorFromText(text ?? "UNK"); + const isLight = ColorUtils.isLight(bgColor); + const textColor = isLight ? "#000000" : "#FFFFFF"; + const initials = text?.toUpperCase().slice(0, 4) ?? "UNK"; + + return ( +
    +

    {initials}

    +
    + ); +}; diff --git a/src/components/UI/Sidebar/SidebarSection.tsx b/src/components/UI/Sidebar/SidebarSection.tsx index acff2dab..33306288 100644 --- a/src/components/UI/Sidebar/SidebarSection.tsx +++ b/src/components/UI/Sidebar/SidebarSection.tsx @@ -9,9 +9,9 @@ export interface SidebarSectionProps { export const SidebarSection = ({ label: title, children, -}: SidebarSectionProps): JSX.Element => ( +}: SidebarSectionProps) => (
    -

    {title}

    +

    {title}

    {children}
    ); diff --git a/src/components/generic/Table/index.tsx b/src/components/generic/Table/index.tsx index aef5f6f2..bffffeb2 100755 --- a/src/components/generic/Table/index.tsx +++ b/src/components/generic/Table/index.tsx @@ -74,15 +74,12 @@ export const Table = ({ headings, rows }: TableProps): JSX.Element => { >
    {heading.title} - {sortColumn === heading.title && ( - <> - {sortOrder === "asc" ? ( - - ) : ( - - )} - - )} + {sortColumn === heading.title && + (sortOrder === "asc" ? ( + + ) : ( + + ))}
    ))} diff --git a/src/index.css b/src/index.css index 8a35066d..6b1f61e2 100644 --- a/src/index.css +++ b/src/index.css @@ -97,6 +97,5 @@ } img { - -drag: none; -webkit-user-drag: none; } diff --git a/src/pages/Channels.tsx b/src/pages/Channels.tsx index 3468aa0e..c6a9e87f 100644 --- a/src/pages/Channels.tsx +++ b/src/pages/Channels.tsx @@ -20,7 +20,7 @@ export const getChannelName = (channel: Protobuf.Channel.Channel) => ? "Primary" : `Ch ${channel.index}`; -export const ChannelsPage = (): JSX.Element => { +const ChannelsPage = () => { const { channels, setDialogOpen } = useDevice(); const [activeChannel, setActiveChannel] = useState( Types.ChannelNumber.Primary, @@ -69,3 +69,4 @@ export const ChannelsPage = (): JSX.Element => { ); }; +export default ChannelsPage; diff --git a/src/pages/Config/index.tsx b/src/pages/Config/index.tsx index c942940c..a760f3ba 100644 --- a/src/pages/Config/index.tsx +++ b/src/pages/Config/index.tsx @@ -9,7 +9,7 @@ import { ModuleConfig } from "@pages/Config/ModuleConfig.tsx"; import { BoxesIcon, SaveIcon, SettingsIcon } from "lucide-react"; import { useState } from "react"; -export const ConfigPage = (): JSX.Element => { +const ConfigPage = (): JSX.Element => { const { workingConfig, workingModuleConfig, connection } = useDevice(); const [activeConfigSection, setActiveConfigSection] = useState< "device" | "module" @@ -72,3 +72,5 @@ export const ConfigPage = (): JSX.Element => { ); }; + +export default ConfigPage; diff --git a/src/pages/Map.tsx b/src/pages/Map.tsx index 1be9455d..12a8e884 100644 --- a/src/pages/Map.tsx +++ b/src/pages/Map.tsx @@ -1,4 +1,5 @@ import { NodeDetail } from "@app/components/PageComponents/Map/NodeDetail"; +import { Avatar } from "@app/components/UI/Avatar"; import { Subtle } from "@app/components/UI/Typography/Subtle.tsx"; import { cn } from "@app/core/utils/cn.ts"; import { PageLayout } from "@components/PageLayout.tsx"; @@ -7,7 +8,6 @@ import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.tsx"; import { SidebarButton } from "@components/UI/Sidebar/sidebarButton.tsx"; import { useAppStore } from "@core/stores/appStore.ts"; import { useDevice } from "@core/stores/deviceStore.ts"; -import { Hashicon } from "@emeraldpay/hashicon-react"; import type { Protobuf } from "@meshtastic/js"; import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { bbox, lineString } from "@turf/turf"; @@ -17,11 +17,11 @@ import { ZoomInIcon, ZoomOutIcon, } from "lucide-react"; -import { useCallback, useEffect, useState } from "react"; +import { type JSX, useCallback, useEffect, useMemo, useState } from "react"; import { AttributionControl, Marker, Popup, useMap } from "react-map-gl"; import MapGl from "react-map-gl/maplibre"; -export const MapPage = (): JSX.Element => { +const MapPage = (): JSX.Element => { const { nodes, waypoints } = useDevice(); const { rasterSources, darkMode } = useAppStore(); const { default: map } = useMap(); @@ -30,7 +30,7 @@ export const MapPage = (): JSX.Element => { const [selectedNode, setSelectedNode] = useState(null); - const allNodes = Array.from(nodes.values()); + const allNodes = useMemo(() => Array.from(nodes.values()), [nodes]); const getBBox = useCallback(() => { if (!map) { @@ -135,9 +135,7 @@ export const MapPage = (): JSX.Element => { renderWorldCopies={false} maxPitch={0} style={{ - filter: darkMode - ? "brightness(0.6) invert(1) contrast(3) hue-rotate(200deg) saturate(0.3) brightness(0.7)" - : "", + filter: darkMode ? "brightness(0.8)" : "", }} dragRotate={false} touchZoomRotate={false} @@ -177,7 +175,7 @@ export const MapPage = (): JSX.Element => { key={node.num} longitude={(node.position.longitudeI ?? 0) / 1e7} latitude={(node.position.latitudeI ?? 0) / 1e7} - style={{ filter: darkMode ? "invert(1)" : "" }} + // style={{ filter: darkMode ? "invert(1)" : "" }} anchor="bottom" onClick={() => { setSelectedNode(node); @@ -190,8 +188,13 @@ export const MapPage = (): JSX.Element => { }); }} > -
    - +
    + {node.user?.longName || `!${numberToHexUnpadded(node.num)}`} @@ -217,3 +220,5 @@ export const MapPage = (): JSX.Element => { ); }; + +export default MapPage; diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 28a35d2c..ce866ed8 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -1,18 +1,18 @@ import { ChannelChat } from "@components/PageComponents/Messages/ChannelChat.tsx"; import { PageLayout } from "@components/PageLayout.tsx"; import { Sidebar } from "@components/Sidebar.tsx"; +import { Avatar } from "@components/UI/Avatar.tsx"; import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.tsx"; import { SidebarButton } from "@components/UI/Sidebar/sidebarButton.tsx"; import { useToast } from "@core/hooks/useToast.ts"; -import { useDevice } from "@core/stores/deviceStore.ts"; -import { Hashicon } from "@emeraldpay/hashicon-react"; +import { Device, useDevice, useDeviceStore } from "@core/stores/deviceStore.ts"; import { Protobuf, Types } from "@meshtastic/js"; import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { getChannelName } from "@pages/Channels.tsx"; import { HashIcon, LockIcon, LockOpenIcon, WaypointsIcon } from "lucide-react"; import { useState } from "react"; -export const MessagesPage = (): JSX.Element => { +const MessagesPage = () => { const { channels, nodes, hardware, messages, traceroutes, connection } = useDevice(); const [chatType, setChatType] = @@ -56,18 +56,27 @@ export const MessagesPage = (): JSX.Element => { ))} - {filteredNodes.map((node) => ( - { - setChatType("direct"); - setActiveChat(node.num); - }} - element={} - /> - ))} +
    + {filteredNodes.map((node) => ( + { + setChatType("direct"); + setActiveChat(node.num); + }} + element={ + + } + /> + ))} +
    @@ -76,7 +85,7 @@ export const MessagesPage = (): JSX.Element => { chatType === "broadcast" && currentChannel ? getChannelName(currentChannel) : chatType === "direct" && nodes.get(activeChat) - ? nodes.get(activeChat)?.user?.longName ?? nodeHex + ? (nodes.get(activeChat)?.user?.longName ?? nodeHex) : "Loading..." }`} actions={ @@ -146,3 +155,5 @@ export const MessagesPage = (): JSX.Element => { ); }; + +export default MessagesPage; diff --git a/src/pages/Nodes.tsx b/src/pages/Nodes.tsx index f66ad1ff..2bbcc302 100644 --- a/src/pages/Nodes.tsx +++ b/src/pages/Nodes.tsx @@ -6,11 +6,10 @@ import { Mono } from "@components/generic/Mono.tsx"; import { Table } from "@components/generic/Table/index.tsx"; import { TimeAgo } from "@components/generic/Table/tmp/TimeAgo.tsx"; import { useDevice } from "@core/stores/deviceStore.ts"; -import { Hashicon } from "@emeraldpay/hashicon-react"; import { Protobuf } from "@meshtastic/js"; import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { LockIcon, LockOpenIcon, TrashIcon } from "lucide-react"; -import { Fragment } from "react"; +import { Fragment, type JSX } from "react"; import { base16 } from "rfc4648"; export interface DeleteNoteDialogProps { @@ -18,7 +17,7 @@ export interface DeleteNoteDialogProps { onOpenChange: (open: boolean) => void; } -export const NodesPage = (): JSX.Element => { +const NodesPage = (): JSX.Element => { const { nodes, hardware, setDialogOpen } = useDevice(); const { setNodeNumToBeRemoved } = useAppStore(); @@ -44,7 +43,11 @@ export const NodesPage = (): JSX.Element => { { title: "Remove", type: "normal", sortable: false }, ]} rows={filteredNodes.map((node) => [ - , + , +

    {node.user?.longName ?? (node.user?.macaddr @@ -111,3 +114,5 @@ export const NodesPage = (): JSX.Element => { ); }; + +export default NodesPage;