From b4dac2d4776b637e048ca15d37a05f1f574eedf3 Mon Sep 17 00:00:00 2001 From: reya Date: Wed, 27 Dec 2023 10:52:13 +0700 Subject: [PATCH] refactor(ark): add note provider --- apps/desktop/src/routes/auth/welcome.tsx | 49 +- packages/@columns/notification/src/home.tsx | 119 +++++ packages/@columns/notification/src/index.ts | 1 - packages/@columns/notification/src/index.tsx | 21 + .../notification/src/notification.tsx | 173 ------- packages/@columns/timeline/src/home.tsx | 8 +- packages/@columns/timeline/src/index.tsx | 34 +- packages/ark/package.json | 1 + packages/ark/src/ark.ts | 8 +- packages/ark/src/components/column/live.tsx | 10 +- .../src/components/note/builds/childReply.tsx | 22 + .../ark/src/components/note/builds/reply.tsx | 89 ++-- .../ark/src/components/note/builds/repost.tsx | 41 +- .../ark/src/components/note/builds/text.tsx | 35 +- .../ark/src/components/note/builds/thread.tsx | 31 +- .../ark/src/components/note/buttons/pin.tsx | 12 +- .../src/components/note/buttons/reaction.tsx | 42 +- .../ark/src/components/note/buttons/reply.tsx | 10 +- .../src/components/note/buttons/repost.tsx | 9 +- .../ark/src/components/note/buttons/zap.tsx | 8 +- packages/ark/src/components/note/index.ts | 3 + packages/ark/src/components/note/menu.tsx | 129 ++--- packages/ark/src/components/note/provider.tsx | 21 + packages/ark/src/components/note/root.tsx | 4 +- packages/ark/src/components/note/thread.tsx | 2 +- packages/ark/src/components/note/user.tsx | 42 +- packages/ark/src/hooks/useRichContent.tsx | 322 ++++++------ packages/icons/src/horizontalDots.tsx | 36 +- packages/icons/src/pin.tsx | 34 +- packages/icons/src/reaction.tsx | 34 +- packages/icons/src/reply.tsx | 34 +- packages/icons/src/repost.tsx | 34 +- packages/icons/src/zap.tsx | 34 +- packages/ui/src/layouts/auth.tsx | 8 +- packages/utils/index.ts | 3 +- packages/utils/package.json | 4 +- packages/utils/src/cn.ts | 6 + pnpm-lock.yaml | 460 +----------------- 38 files changed, 793 insertions(+), 1140 deletions(-) create mode 100644 packages/@columns/notification/src/home.tsx delete mode 100644 packages/@columns/notification/src/index.ts create mode 100644 packages/@columns/notification/src/index.tsx delete mode 100644 packages/@columns/notification/src/notification.tsx create mode 100644 packages/ark/src/components/note/builds/childReply.tsx create mode 100644 packages/ark/src/components/note/provider.tsx create mode 100644 packages/utils/src/cn.ts diff --git a/apps/desktop/src/routes/auth/welcome.tsx b/apps/desktop/src/routes/auth/welcome.tsx index e28d611c..7c7fc18a 100644 --- a/apps/desktop/src/routes/auth/welcome.tsx +++ b/apps/desktop/src/routes/auth/welcome.tsx @@ -1,30 +1,25 @@ -import { Link } from 'react-router-dom'; +import { Link } from "react-router-dom"; export function WelcomeScreen() { - return ( -
-
-
- Lume's logo -

- Welcome to Lume -

-
-
- - Create new account - - - Log in - -
-
-
- ); + return ( +
+
+

Welcome to Nostr!

+
+
+ + Create new account + + + Log in + +
+
+ ); } diff --git a/packages/@columns/notification/src/home.tsx b/packages/@columns/notification/src/home.tsx new file mode 100644 index 00000000..87e2e743 --- /dev/null +++ b/packages/@columns/notification/src/home.tsx @@ -0,0 +1,119 @@ +import { RepostNote, TextNote, useArk, useStorage } from "@lume/ark"; +import { ArrowRightCircleIcon, LoaderIcon } from "@lume/icons"; +import { FETCH_LIMIT } from "@lume/utils"; +import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { useEffect, useMemo, useRef } from "react"; +import { CacheSnapshot, VList, VListHandle } from "virtua"; + +export function HomeRoute({ colKey }: { colKey: string }) { + const ark = useArk(); + const storage = useStorage(); + const ref = useRef(); + const cacheKey = "notification-vlist"; + + const [offset, cache] = useMemo(() => { + const serialized = sessionStorage.getItem(cacheKey); + if (!serialized) return []; + return JSON.parse(serialized) as [number, CacheSnapshot]; + }, []); + + const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = + useInfiniteQuery({ + queryKey: [colKey], + initialPageParam: 0, + queryFn: async ({ + signal, + pageParam, + }: { + signal: AbortSignal; + pageParam: number; + }) => { + const events = await ark.getInfiniteEvents({ + filter: { + kinds: [NDKKind.Text, NDKKind.Repost], + authors: !storage.account.contacts.length + ? [storage.account.pubkey] + : storage.account.contacts, + }, + limit: FETCH_LIMIT, + pageParam, + signal, + }); + + return events; + }, + getNextPageParam: (lastPage) => { + const lastEvent = lastPage.at(-1); + if (!lastEvent) return; + return lastEvent.created_at - 1; + }, + refetchOnWindowFocus: false, + }); + + const allEvents = useMemo( + () => (data ? data.pages.flatMap((page) => page) : []), + [data], + ); + + const renderItem = (event: NDKEvent) => { + switch (event.kind) { + case NDKKind.Text: + return ; + case NDKKind.Repost: + return ; + default: + return ; + } + }; + + useEffect(() => { + if (!ref.current) return; + const handle = ref.current; + + if (offset) { + handle.scrollTo(offset); + } + + return () => { + sessionStorage.setItem( + cacheKey, + JSON.stringify([handle.scrollOffset, handle.cache]), + ); + }; + }, []); + + return ( +
+ + {isLoading ? ( +
+ + Loading +
+ ) : ( + allEvents.map((item) => renderItem(item)) + )} +
+ {hasNextPage ? ( + + ) : null} +
+
+
+ ); +} diff --git a/packages/@columns/notification/src/index.ts b/packages/@columns/notification/src/index.ts deleted file mode 100644 index dd99c4d0..00000000 --- a/packages/@columns/notification/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./notification"; diff --git a/packages/@columns/notification/src/index.tsx b/packages/@columns/notification/src/index.tsx new file mode 100644 index 00000000..a800a7a9 --- /dev/null +++ b/packages/@columns/notification/src/index.tsx @@ -0,0 +1,21 @@ +import { Column } from "@lume/ark"; +import { BellIcon } from "@lume/icons"; +import { HomeRoute } from "./home"; + +export function Notification() { + const colKey = "notification"; + + return ( + + } + /> + + } /> + + + ); +} diff --git a/packages/@columns/notification/src/notification.tsx b/packages/@columns/notification/src/notification.tsx deleted file mode 100644 index 443d3cc5..00000000 --- a/packages/@columns/notification/src/notification.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { NoteSkeleton, TextNote, Widget, useArk, useStorage } from "@lume/ark"; -import { - AnnouncementIcon, - ArrowRightCircleIcon, - LoaderIcon, -} from "@lume/icons"; -import { FETCH_LIMIT, sendNativeNotification } from "@lume/utils"; -import { NDKEvent, NDKKind, NDKSubscription } from "@nostr-dev-kit/ndk"; -import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query"; -import { useEffect, useMemo } from "react"; -import { VList } from "virtua"; - -export function NotificationColumn() { - const ark = useArk(); - const storage = useStorage(); - const queryClient = useQueryClient(); - - const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } = - useInfiniteQuery({ - queryKey: ["notification"], - initialPageParam: 0, - queryFn: async ({ - signal, - pageParam, - }: { - signal: AbortSignal; - pageParam: number; - }) => { - const events = await ark.getInfiniteEvents({ - filter: { - kinds: [ - NDKKind.Text, - NDKKind.Repost, - NDKKind.Reaction, - NDKKind.Zap, - ], - "#p": [storage.account.pubkey], - }, - limit: FETCH_LIMIT, - pageParam, - signal, - }); - - return events; - }, - getNextPageParam: (lastPage) => { - const lastEvent = lastPage.at(-1); - if (!lastEvent) return; - return lastEvent.created_at - 1; - }, - refetchOnWindowFocus: false, - refetchOnMount: false, - refetchOnReconnect: false, - staleTime: Infinity, - }); - - const allEvents = useMemo( - () => (data ? data.pages.flatMap((page) => page) : []), - [data], - ); - - const renderEvent = (event: NDKEvent) => { - if (event.pubkey === storage.account.pubkey) return null; - return ; - }; - - useEffect(() => { - let sub: NDKSubscription = undefined; - - if (status === "success" && storage.account) { - const filter = { - kinds: [NDKKind.Text, NDKKind.Repost, NDKKind.Reaction, NDKKind.Zap], - "#p": [storage.account.pubkey], - since: Math.floor(Date.now() / 1000), - }; - - sub = ark.subscribe({ - filter, - closeOnEose: false, - cb: async (event) => { - queryClient.setQueryData( - ["notification"], - (prev: { pageParams: number; pages: Array }) => ({ - ...prev, - pages: [[event], ...prev.pages], - }), - ); - - const profile = await ark.getUserProfile({ pubkey: event.pubkey }); - - switch (event.kind) { - case NDKKind.Text: - return await sendNativeNotification( - `${ - profile.displayName || profile.name - } has replied to your note`, - ); - case NDKKind.Repost: - return await sendNativeNotification( - `${ - profile.displayName || profile.name - } has reposted to your note`, - ); - case NDKKind.Reaction: - return await sendNativeNotification( - `${profile.displayName || profile.name} has reacted ${ - event.content - } to your note`, - ); - case NDKKind.Zap: - return await sendNativeNotification( - `${ - profile.displayName || profile.name - } has zapped to your note`, - ); - default: - break; - } - }, - }); - } - - return () => { - if (sub) sub.stop(); - }; - }, [status]); - - return ( - - } - /> - - - {status === "pending" ? ( - - ) : allEvents.length < 1 ? ( -
-
🎉
-

- Hmm! Nothing new yet. -

-
- ) : ( - allEvents.map((event) => renderEvent(event)) - )} -
- {hasNextPage ? ( - - ) : null} -
-
-
-
- ); -} diff --git a/packages/@columns/timeline/src/home.tsx b/packages/@columns/timeline/src/home.tsx index a80b3e11..5e95274d 100644 --- a/packages/@columns/timeline/src/home.tsx +++ b/packages/@columns/timeline/src/home.tsx @@ -6,7 +6,7 @@ import { useInfiniteQuery } from "@tanstack/react-query"; import { useEffect, useMemo, useRef } from "react"; import { CacheSnapshot, VList, VListHandle } from "virtua"; -export function HomeRoute() { +export function HomeRoute({ colKey }: { colKey: string }) { const ark = useArk(); const storage = useStorage(); const ref = useRef(); @@ -20,7 +20,7 @@ export function HomeRoute() { const { data, hasNextPage, isLoading, isFetchingNextPage, fetchNextPage } = useInfiniteQuery({ - queryKey: ["newsfeed"], + queryKey: [colKey], initialPageParam: 0, queryFn: async ({ signal, @@ -61,9 +61,9 @@ export function HomeRoute() { case NDKKind.Text: return ; case NDKKind.Repost: - return ; + return ; default: - return ; + return ; } }; diff --git a/packages/@columns/timeline/src/index.tsx b/packages/@columns/timeline/src/index.tsx index fafd6d2d..0518b03d 100644 --- a/packages/@columns/timeline/src/index.tsx +++ b/packages/@columns/timeline/src/index.tsx @@ -1,20 +1,48 @@ -import { Column } from "@lume/ark"; +import { Column, useStorage } from "@lume/ark"; import { TimelineIcon } from "@lume/icons"; +import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; +import { useQueryClient } from "@tanstack/react-query"; +import { useRef } from "react"; import { EventRoute } from "./event"; import { HomeRoute } from "./home"; import { UserRoute } from "./user"; export function Timeline() { + const colKey = "newsfeed"; + const storage = useStorage(); + const queryClient = useQueryClient(); + const since = useRef(Math.floor(Date.now() / 1000)); + + const refreshTimeline = async (events: NDKEvent[]) => { + await queryClient.setQueryData( + [colKey], + (prev: { pageParams: number; pages: Array }) => ({ + ...prev, + pages: [[...events], ...prev.pages], + }), + ); + }; + return ( } /> + - } /> + } /> } /> } /> diff --git a/packages/ark/package.json b/packages/ark/package.json index 2dc110a3..40038843 100644 --- a/packages/ark/package.json +++ b/packages/ark/package.json @@ -15,6 +15,7 @@ "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-hover-card": "^1.0.7", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-tooltip": "^1.0.7", "@tanstack/react-query": "^5.14.2", diff --git a/packages/ark/src/ark.ts b/packages/ark/src/ark.ts index 8bb9947b..1a985b36 100644 --- a/packages/ark/src/ark.ts +++ b/packages/ark/src/ark.ts @@ -1,9 +1,5 @@ import { LumeStorage } from "@lume/storage"; -import { - type Account, - type NDKEventWithReplies, - type NIP05, -} from "@lume/types"; +import { type NDKEventWithReplies, type NIP05 } from "@lume/types"; import NDK, { NDKEvent, NDKFilter, @@ -26,7 +22,6 @@ export class Ark { #storage: LumeStorage; #fetcher: NostrFetcher; public ndk: NDK; - public account: Account; constructor({ ndk, @@ -36,7 +31,6 @@ export class Ark { }: { ndk: NDK; storage: LumeStorage; - fetcher: NostrFetcher; }) { this.ndk = ndk; diff --git a/packages/ark/src/components/column/live.tsx b/packages/ark/src/components/column/live.tsx index e3ecd95d..b15060a8 100644 --- a/packages/ark/src/components/column/live.tsx +++ b/packages/ark/src/components/column/live.tsx @@ -8,11 +8,17 @@ export function ColumnLiveWidget({ onClick, }: { filter: NDKFilter; - onClick: () => void; + onClick: (event: NDKEvent[]) => void; }) { const ark = useArk(); const [events, setEvents] = useState([]); + const update = async () => { + onClick(events); + // reset + setEvents([]); + }; + useEffect(() => { const sub = ark.subscribe({ filter, @@ -31,7 +37,7 @@ export function ColumnLiveWidget({
- + Pin note - + diff --git a/packages/ark/src/components/note/buttons/reaction.tsx b/packages/ark/src/components/note/buttons/reaction.tsx index 023f7224..e5fdb246 100644 --- a/packages/ark/src/components/note/buttons/reaction.tsx +++ b/packages/ark/src/components/note/buttons/reaction.tsx @@ -1,8 +1,8 @@ import { ReactionIcon } from "@lume/icons"; -import { NDKEvent } from "@nostr-dev-kit/ndk"; -import * as Popover from "@radix-ui/react-popover"; +import * as HoverCard from "@radix-ui/react-hover-card"; import { useState } from "react"; import { toast } from "sonner"; +import { useNoteContext } from "../provider"; const REACTIONS = [ { @@ -27,7 +27,9 @@ const REACTIONS = [ }, ]; -export function NoteReaction({ event }: { event: NDKEvent }) { +export function NoteReaction() { + const event = useNoteContext(); + const [open, setOpen] = useState(false); const [reaction, setReaction] = useState(null); @@ -52,8 +54,8 @@ export function NoteReaction({ event }: { event: NDKEvent }) { }; return ( - - + + - - - + + @@ -79,7 +81,7 @@ export function NoteReaction({ event }: { event: NDKEvent }) {
- - - - + + + + ); } diff --git a/packages/ark/src/components/note/buttons/reply.tsx b/packages/ark/src/components/note/buttons/reply.tsx index 5fbddf19..526b4ba9 100644 --- a/packages/ark/src/components/note/buttons/reply.tsx +++ b/packages/ark/src/components/note/buttons/reply.tsx @@ -1,14 +1,14 @@ import { ReplyIcon } from "@lume/icons"; import * as Tooltip from "@radix-ui/react-tooltip"; import { createSearchParams, useNavigate } from "react-router-dom"; +import { useNoteContext } from "../provider"; export function NoteReply({ - eventId, rootEventId, }: { - eventId: string; rootEventId?: string; }) { + const event = useNoteContext(); const navigate = useNavigate(); return ( @@ -21,7 +21,7 @@ export function NoteReply({ navigate({ pathname: "/new/", search: createSearchParams({ - replyTo: eventId, + replyTo: event.id, rootReplyTo: rootEventId, }).toString(), }) @@ -32,9 +32,9 @@ export function NoteReply({ - + Quick reply - + diff --git a/packages/ark/src/components/note/buttons/repost.tsx b/packages/ark/src/components/note/buttons/repost.tsx index 6e1e92cf..65247280 100644 --- a/packages/ark/src/components/note/buttons/repost.tsx +++ b/packages/ark/src/components/note/buttons/repost.tsx @@ -1,11 +1,12 @@ import { RepostIcon } from "@lume/icons"; -import { NDKEvent } from "@nostr-dev-kit/ndk"; import * as Tooltip from "@radix-ui/react-tooltip"; import { useState } from "react"; import { toast } from "sonner"; import { twMerge } from "tailwind-merge"; +import { useNoteContext } from "../provider"; -export function NoteRepost({ event }: { event: NDKEvent }) { +export function NoteRepost() { + const event = useNoteContext(); const [isRepost, setIsRepost] = useState(false); const submit = async () => { @@ -39,9 +40,9 @@ export function NoteRepost({ event }: { event: NDKEvent }) { - + Repost - + diff --git a/packages/ark/src/components/note/buttons/zap.tsx b/packages/ark/src/components/note/buttons/zap.tsx index 09626ee6..6062520b 100644 --- a/packages/ark/src/components/note/buttons/zap.tsx +++ b/packages/ark/src/components/note/buttons/zap.tsx @@ -16,8 +16,9 @@ import CurrencyInput from "react-currency-input-field"; import { useNavigate } from "react-router-dom"; import { useProfile } from "../../../hooks/useProfile"; import { useArk, useStorage } from "../../../provider"; +import { useNoteContext } from "../provider"; -export function NoteZap({ event }: { event: NDKEvent }) { +export function NoteZap() { const [walletConnectURL, setWalletConnectURL] = useState(null); const [amount, setAmount] = useState("21"); const [zapMessage, setZapMessage] = useState(""); @@ -26,13 +27,14 @@ export function NoteZap({ event }: { event: NDKEvent }) { const [isCompleted, setIsCompleted] = useState(false); const [isLoading, setIsLoading] = useState(false); - const { user } = useProfile(event.pubkey); - const ark = useArk(); + const event = useNoteContext(); const storage = useStorage(); const nwc = useRef(null); const navigate = useNavigate(); + const { user } = useProfile(event.pubkey); + const createZapRequest = async () => { try { if (!ark.ndk.signer) return navigate("/new/privkey"); diff --git a/packages/ark/src/components/note/index.ts b/packages/ark/src/components/note/index.ts index 9a0a617d..c1b6a766 100644 --- a/packages/ark/src/components/note/index.ts +++ b/packages/ark/src/components/note/index.ts @@ -8,12 +8,14 @@ import { NoteArticleContent } from "./kinds/article"; import { NoteMediaContent } from "./kinds/media"; import { NoteTextContent } from "./kinds/text"; import { NoteMenu } from "./menu"; +import { NoteProvider } from "./provider"; import { NoteReplyList } from "./reply"; import { NoteRoot } from "./root"; import { NoteThread } from "./thread"; import { NoteUser } from "./user"; export const Note = { + Provider: NoteProvider, Root: NoteRoot, User: NoteUser, Menu: NoteMenu, @@ -30,6 +32,7 @@ export const Note = { ReplyList: NoteReplyList, }; +export * from "./provider"; export * from "./builds/text"; export * from "./builds/repost"; export * from "./builds/skeleton"; diff --git a/packages/ark/src/components/note/menu.tsx b/packages/ark/src/components/note/menu.tsx index c0d92820..f3915787 100644 --- a/packages/ark/src/components/note/menu.tsx +++ b/packages/ark/src/components/note/menu.tsx @@ -1,63 +1,76 @@ -import { HorizontalDotsIcon } from '@lume/icons'; -import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; -import { writeText } from '@tauri-apps/plugin-clipboard-manager'; -import { nip19 } from 'nostr-tools'; -import { EventPointer } from 'nostr-tools/lib/types/nip19'; -import { useState } from 'react'; -import { Link } from 'react-router-dom'; +import { HorizontalDotsIcon } from "@lume/icons"; +import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; +import { writeText } from "@tauri-apps/plugin-clipboard-manager"; +import { nip19 } from "nostr-tools"; +import { EventPointer } from "nostr-tools/lib/types/nip19"; +import { useState } from "react"; +import { Link } from "react-router-dom"; +import { useNoteContext } from "./provider"; -export function NoteMenu({ eventId, pubkey }: { eventId: string; pubkey: string }) { - const [open, setOpen] = useState(false); +export function NoteMenu() { + const event = useNoteContext(); + const [open, setOpen] = useState(false); - const copyID = async () => { - await writeText(nip19.neventEncode({ id: eventId, author: pubkey } as EventPointer)); - setOpen(false); - }; + const copyID = async () => { + await writeText( + nip19.neventEncode({ + id: event.id, + author: event.pubkey, + } as EventPointer), + ); + setOpen(false); + }; - const copyLink = async () => { - await writeText( - `https://njump.me/${nip19.neventEncode({ id: eventId, author: pubkey } as EventPointer)}` - ); - setOpen(false); - }; + const copyLink = async () => { + await writeText( + `https://njump.me/${nip19.neventEncode({ + id: event.id, + author: event.pubkey, + } as EventPointer)}`, + ); + setOpen(false); + }; - return ( - - - - - - - - - - - - - - - View profile - - - - - - ); + return ( + + + + + + + + + + + + + + + View profile + + + + + + ); } diff --git a/packages/ark/src/components/note/provider.tsx b/packages/ark/src/components/note/provider.tsx new file mode 100644 index 00000000..d5ee6920 --- /dev/null +++ b/packages/ark/src/components/note/provider.tsx @@ -0,0 +1,21 @@ +import { NDKEvent } from "@nostr-dev-kit/ndk"; +import { ReactNode, createContext, useContext } from "react"; + +const EventContext = createContext(null); + +export function NoteProvider({ + event, + children, +}: { event: NDKEvent; children: ReactNode }) { + return ( + {children} + ); +} + +export function useNoteContext() { + const context = useContext(EventContext); + if (context === undefined) { + throw new Error("Please import Note Provider to use useNoteContext() hook"); + } + return context; +} diff --git a/packages/ark/src/components/note/root.tsx b/packages/ark/src/components/note/root.tsx index 741e7b32..e1e0e796 100644 --- a/packages/ark/src/components/note/root.tsx +++ b/packages/ark/src/components/note/root.tsx @@ -1,5 +1,5 @@ +import { cn } from "@lume/utils"; import { ReactNode } from "react"; -import { twMerge } from "tailwind-merge"; export function NoteRoot({ children, @@ -10,7 +10,7 @@ export function NoteRoot({ }) { return (
- Show full thread + Show thread
diff --git a/packages/ark/src/components/note/user.tsx b/packages/ark/src/components/note/user.tsx index 18b25044..722a820b 100644 --- a/packages/ark/src/components/note/user.tsx +++ b/packages/ark/src/components/note/user.tsx @@ -5,29 +5,33 @@ import { minidenticon } from "minidenticons"; import { useMemo } from "react"; import { twMerge } from "tailwind-merge"; import { useProfile } from "../../hooks/useProfile"; +import { useNoteContext } from "./provider"; export function NoteUser({ - pubkey, - time, variant = "text", className, }: { - pubkey: string; - time: number; variant?: "text" | "repost" | "mention" | "thread"; className?: string; }) { - const createdAt = useMemo(() => formatCreatedAt(time), [time]); - const fallbackName = useMemo(() => displayNpub(pubkey, 16), [pubkey]); + const event = useNoteContext(); + const createdAt = useMemo( + () => formatCreatedAt(event.created_at), + [event.created_at], + ); + const fallbackName = useMemo( + () => displayNpub(event.pubkey, 16), + [event.pubkey], + ); const fallbackAvatar = useMemo( () => `data:image/svg+xml;utf8,${encodeURIComponent( - minidenticon(pubkey, 90, 50), + minidenticon(event.pubkey, 90, 50), )}`, - [pubkey], + [event.pubkey], ); - const { isLoading, user } = useProfile(pubkey); + const { isLoading, user } = useProfile(event.pubkey); if (variant === "mention") { if (isLoading) { @@ -36,7 +40,7 @@ export function NoteUser({ @@ -58,7 +62,7 @@ export function NoteUser({ {pubkey} @@ -111,7 +115,7 @@ export function NoteUser({ {pubkey} @@ -156,7 +160,7 @@ export function NoteUser({ {pubkey} @@ -189,7 +193,7 @@ export function NoteUser({ @@ -207,7 +211,7 @@ export function NoteUser({ {pubkey} diff --git a/packages/ark/src/hooks/useRichContent.tsx b/packages/ark/src/hooks/useRichContent.tsx index e0193112..ba9bfb1e 100644 --- a/packages/ark/src/hooks/useRichContent.tsx +++ b/packages/ark/src/hooks/useRichContent.tsx @@ -1,183 +1,209 @@ -import { nanoid } from 'nanoid'; -import { nip19 } from 'nostr-tools'; -import { ReactNode } from 'react'; -import { Link } from 'react-router-dom'; -import reactStringReplace from 'react-string-replace'; +import { nip19 } from "nostr-tools"; +import { ReactNode } from "react"; +import { Link } from "react-router-dom"; +import reactStringReplace from "react-string-replace"; import { - Hashtag, - ImagePreview, - LinkPreview, - MentionNote, - MentionUser, - VideoPreview, -} from '../components/note'; -import { useStorage } from '../provider'; + Hashtag, + ImagePreview, + LinkPreview, + MentionNote, + MentionUser, + VideoPreview, +} from "../components/note"; +import { useStorage } from "../provider"; const NOSTR_MENTIONS = [ - '@npub1', - 'nostr:npub1', - 'nostr:nprofile1', - 'nostr:naddr1', - 'npub1', - 'nprofile1', - 'naddr1', - 'Nostr:npub1', - 'Nostr:nprofile1', - 'Nostr:naddre1', + "@npub1", + "nostr:npub1", + "nostr:nprofile1", + "nostr:naddr1", + "npub1", + "nprofile1", + "naddr1", + "Nostr:npub1", + "Nostr:nprofile1", + "Nostr:naddre1", ]; const NOSTR_EVENTS = [ - 'nostr:note1', - 'note1', - 'nostr:nevent1', - 'nevent1', - 'Nostr:note1', - 'Nostr:nevent1', + "nostr:note1", + "note1", + "nostr:nevent1", + "nevent1", + "Nostr:note1", + "Nostr:nevent1", ]; // const BITCOINS = ['lnbc', 'bc1p', 'bc1q']; -const IMAGES = ['.jpg', '.jpeg', '.gif', '.png', '.webp', '.avif', '.tiff']; +const IMAGES = [".jpg", ".jpeg", ".gif", ".png", ".webp", ".avif", ".tiff"]; const VIDEOS = [ - '.mp4', - '.mov', - '.webm', - '.wmv', - '.flv', - '.mts', - '.avi', - '.ogv', - '.mkv', - '.mp3', - '.m3u8', + ".mp4", + ".mov", + ".webm", + ".wmv", + ".flv", + ".mts", + ".avi", + ".ogv", + ".mkv", + ".mp3", + ".m3u8", ]; export function useRichContent(content: string, textmode = false) { - const storage = useStorage(); + const storage = useStorage(); - let parsedContent: string | ReactNode[] = content.replace(/\n+/g, '\n'); - let linkPreview: string; - let images: string[] = []; - let videos: string[] = []; - let events: string[] = []; + let parsedContent: string | ReactNode[] = content.replace(/\n+/g, "\n"); + let linkPreview: string; + let images: string[] = []; + let videos: string[] = []; + let events: string[] = []; - const text = parsedContent; - const words = text.split(/( |\n)/); + const text = parsedContent; + const words = text.split(/( |\n)/); - if (!textmode) { - if (storage.settings.media) { - images = words.filter((word) => IMAGES.some((el) => word.endsWith(el))); - videos = words.filter((word) => VIDEOS.some((el) => word.endsWith(el))); - } - events = words.filter((word) => NOSTR_EVENTS.some((el) => word.startsWith(el))); - } + if (!textmode) { + if (storage.settings.media) { + images = words.filter((word) => IMAGES.some((el) => word.endsWith(el))); + videos = words.filter((word) => VIDEOS.some((el) => word.endsWith(el))); + } + events = words.filter((word) => + NOSTR_EVENTS.some((el) => word.startsWith(el)), + ); + } - const hashtags = words.filter((word) => word.startsWith('#')); - const mentions = words.filter((word) => - NOSTR_MENTIONS.some((el) => word.startsWith(el)) - ); + const hashtags = words.filter((word) => word.startsWith("#")); + const mentions = words.filter((word) => + NOSTR_MENTIONS.some((el) => word.startsWith(el)), + ); - try { - if (images.length) { - for(const image of images) { - parsedContent = reactStringReplace(parsedContent, image, (match, i) => ( - - )); - } - } + try { + if (images.length) { + for (const image of images) { + parsedContent = reactStringReplace(parsedContent, image, (match, i) => ( + + )); + } + } - if (videos.length) { - for(const video of videos) { - parsedContent = reactStringReplace(parsedContent, video, (match, i) => ( - - )); - } - } + if (videos.length) { + for (const video of videos) { + parsedContent = reactStringReplace(parsedContent, video, (match, i) => ( + + )); + } + } - if (hashtags.length) { - for(const hashtag of hashtags) { - parsedContent = reactStringReplace(parsedContent, hashtag, (match, i) => { - if (storage.settings.hashtag) return ; - return null; - }); - } - } + if (hashtags.length) { + for (const hashtag of hashtags) { + parsedContent = reactStringReplace( + parsedContent, + hashtag, + (match, i) => { + if (storage.settings.hashtag) + return ; + return null; + }, + ); + } + } - if (events.length) { - for(const event of events) { - const address = event.replace('nostr:', '').replace(/[^a-zA-Z0-9]/g, ''); - const decoded = nip19.decode(address); + if (events.length) { + for (const event of events) { + const address = event + .replace("nostr:", "") + .replace(/[^a-zA-Z0-9]/g, ""); + const decoded = nip19.decode(address); - if (decoded.type === 'note') { - parsedContent = reactStringReplace(parsedContent, event, (match, i) => ( - - )); - } + if (decoded.type === "note") { + parsedContent = reactStringReplace( + parsedContent, + event, + (match, i) => ( + + ), + ); + } - if (decoded.type === 'nevent') { - parsedContent = reactStringReplace(parsedContent, event, (match, i) => ( - - )); - } - } - } + if (decoded.type === "nevent") { + parsedContent = reactStringReplace( + parsedContent, + event, + (match, i) => ( + + ), + ); + } + } + } - if (mentions.length) { - for(const mention of mentions) { - const address = mention - .replace('nostr:', '') - .replace('@', '') - .replace(/[^a-zA-Z0-9]/g, ''); - const decoded = nip19.decode(address); + if (mentions.length) { + for (const mention of mentions) { + const address = mention + .replace("nostr:", "") + .replace("@", "") + .replace(/[^a-zA-Z0-9]/g, ""); + const decoded = nip19.decode(address); - if (decoded.type === 'npub') { - parsedContent = reactStringReplace(parsedContent, mention, (match, i) => ( - - )); - } + if (decoded.type === "npub") { + parsedContent = reactStringReplace( + parsedContent, + mention, + (match, i) => , + ); + } - if (decoded.type === 'nprofile' || decoded.type === 'naddr') { - parsedContent = reactStringReplace(parsedContent, mention, (match, i) => ( - - )); - } - } - } + if (decoded.type === "nprofile" || decoded.type === "naddr") { + parsedContent = reactStringReplace( + parsedContent, + mention, + (match, i) => ( + + ), + ); + } + } + } - parsedContent = reactStringReplace(parsedContent, /(https?:\/\/\S+)/g, (match, i) => { - const url = new URL(match); - url.search = ''; + parsedContent = reactStringReplace( + parsedContent, + /(https?:\/\/\S+)/g, + (match, i) => { + const url = new URL(match); + url.search = ""; - if (!linkPreview && !textmode) { - linkPreview = match; - return ; - } + if (!linkPreview && !textmode) { + linkPreview = match; + return ; + } - return ( - - {url.toString()} - - ); - }); + return ( + + {url.toString()} + + ); + }, + ); - parsedContent = reactStringReplace(parsedContent, '\n', () => { - return
; - }); + parsedContent = reactStringReplace(parsedContent, "\n", () => { + return null; + }); - if (typeof parsedContent[0] === 'string') { - parsedContent[0] = parsedContent[0].trimStart(); - } + if (typeof parsedContent[0] === "string") { + parsedContent[0] = parsedContent[0].trimStart(); + } - return { parsedContent }; - } catch (e) { - console.warn('[parser] parse failed: ', e); - return { parsedContent }; - } + return { parsedContent }; + } catch (e) { + console.warn("[parser] parse failed: ", e); + return { parsedContent }; + } } diff --git a/packages/icons/src/horizontalDots.tsx b/packages/icons/src/horizontalDots.tsx index de8974e1..1e62dad2 100644 --- a/packages/icons/src/horizontalDots.tsx +++ b/packages/icons/src/horizontalDots.tsx @@ -1,20 +1,18 @@ -export function HorizontalDotsIcon(props: JSX.IntrinsicElements['svg']) { - return ( - - - - - - ); +export function HorizontalDotsIcon(props: JSX.IntrinsicElements["svg"]) { + return ( + + + + ); } diff --git a/packages/icons/src/pin.tsx b/packages/icons/src/pin.tsx index 2908e670..3e63e677 100644 --- a/packages/icons/src/pin.tsx +++ b/packages/icons/src/pin.tsx @@ -1,18 +1,18 @@ -export function PinIcon(props: JSX.IntrinsicElements['svg']) { - return ( - - - - ); +export function PinIcon(props: JSX.IntrinsicElements["svg"]) { + return ( + + + + ); } diff --git a/packages/icons/src/reaction.tsx b/packages/icons/src/reaction.tsx index ff73ba22..b281a45d 100644 --- a/packages/icons/src/reaction.tsx +++ b/packages/icons/src/reaction.tsx @@ -1,18 +1,18 @@ -export function ReactionIcon(props: JSX.IntrinsicElements['svg']) { - return ( - - - - ); +export function ReactionIcon(props: JSX.IntrinsicElements["svg"]) { + return ( + + + + ); } diff --git a/packages/icons/src/reply.tsx b/packages/icons/src/reply.tsx index 2e781c96..58542430 100644 --- a/packages/icons/src/reply.tsx +++ b/packages/icons/src/reply.tsx @@ -1,18 +1,18 @@ -export function ReplyIcon(props: JSX.IntrinsicElements['svg']) { - return ( - - - - ); +export function ReplyIcon(props: JSX.IntrinsicElements["svg"]) { + return ( + + + + ); } diff --git a/packages/icons/src/repost.tsx b/packages/icons/src/repost.tsx index bd2ef69c..0bb7d3da 100644 --- a/packages/icons/src/repost.tsx +++ b/packages/icons/src/repost.tsx @@ -1,18 +1,18 @@ -export function RepostIcon(props: JSX.IntrinsicElements['svg']) { - return ( - - - - ); +export function RepostIcon(props: JSX.IntrinsicElements["svg"]) { + return ( + + + + ); } diff --git a/packages/icons/src/zap.tsx b/packages/icons/src/zap.tsx index 56a8ca29..28634c96 100644 --- a/packages/icons/src/zap.tsx +++ b/packages/icons/src/zap.tsx @@ -1,18 +1,18 @@ -export function ZapIcon(props: JSX.IntrinsicElements['svg']) { - return ( - - - - ); +export function ZapIcon(props: JSX.IntrinsicElements["svg"]) { + return ( + + + + ); } diff --git a/packages/ui/src/layouts/auth.tsx b/packages/ui/src/layouts/auth.tsx index 6b9aa67f..2d3c484f 100644 --- a/packages/ui/src/layouts/auth.tsx +++ b/packages/ui/src/layouts/auth.tsx @@ -1,10 +1,16 @@ +import { cn } from "@lume/utils"; import { type Platform } from "@tauri-apps/plugin-os"; import { Outlet, ScrollRestoration } from "react-router-dom"; import { WindowTitleBar } from "../titlebar"; export function AuthLayout({ platform }: { platform: Platform }) { return ( -
+
{platform !== "macos" ? ( ) : ( diff --git a/packages/utils/index.ts b/packages/utils/index.ts index 347a261d..032ce06d 100644 --- a/packages/utils/index.ts +++ b/packages/utils/index.ts @@ -5,5 +5,4 @@ export * from "./src/nip94"; export * from "./src/notification"; export * from "./src/hooks/useNetworkStatus"; export * from "./src/hooks/useOpenGraph"; -export * from "../ark/src/hooks/useRelay"; -export * from "../ark/src/hooks/useSuggestion"; +export * from "./src/cn"; diff --git a/packages/utils/package.json b/packages/utils/package.json index 692506d7..92344ee8 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -11,9 +11,11 @@ "@tanstack/react-query": "^5.14.2", "@tauri-apps/api": "2.0.0-alpha.11", "@tauri-apps/plugin-notification": "2.0.0-alpha.3", + "clsx": "^2.0.0", "dayjs": "^1.11.10", "nostr-tools": "1.17.0", - "react": "^18.2.0" + "react": "^18.2.0", + "tailwind-merge": "^1.14.0" }, "devDependencies": { "@lume/tsconfig": "workspace:^", diff --git a/packages/utils/src/cn.ts b/packages/utils/src/cn.ts new file mode 100644 index 00000000..e6b1af7d --- /dev/null +++ b/packages/utils/src/cn.ts @@ -0,0 +1,6 @@ +import { ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1601893..60baf1d4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -431,22 +431,25 @@ importers: version: 0.14.1(@nostr-dev-kit/ndk@2.3.1)(nostr-fetch@0.14.1) '@radix-ui/react-avatar': specifier: ^1.0.4 - version: 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-collapsible': specifier: ^1.0.3 - version: 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dialog': specifier: ^1.0.5 - version: 1.0.5(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dropdown-menu': specifier: ^2.0.6 - version: 2.0.6(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + version: 2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-hover-card': + specifier: ^1.0.7 + version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-popover': specifier: ^1.0.7 - version: 1.0.7(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-tooltip': specifier: ^1.0.7 - version: 1.0.7(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) '@tanstack/react-query': specifier: ^5.14.2 version: 5.14.2(react@18.2.0) @@ -744,6 +747,9 @@ importers: '@tauri-apps/plugin-notification': specifier: 2.0.0-alpha.3 version: 2.0.0-alpha.3 + clsx: + specifier: ^2.0.0 + version: 2.0.0 dayjs: specifier: ^1.11.10 version: 1.11.10 @@ -753,6 +759,9 @@ importers: react: specifier: ^18.2.0 version: 18.2.0 + tailwind-merge: + specifier: ^1.14.0 + version: 1.14.0 devDependencies: '@lume/tsconfig': specifier: workspace:^ @@ -1325,26 +1334,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-arrow@1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-avatar@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==} peerDependencies: @@ -1369,29 +1358,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-avatar@1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==} peerDependencies: @@ -1420,33 +1386,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-collapsible@1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} peerDependencies: @@ -1471,29 +1410,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-collection@1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.45)(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -1556,39 +1472,6 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) dev: false - /@radix-ui/react-dialog@1.0.5(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - aria-hidden: 1.2.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) - dev: false - /@radix-ui/react-direction@1.0.1(@types/react@18.2.45)(react@18.2.0): resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} peerDependencies: @@ -1628,30 +1511,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-dismissable-layer@1.0.5(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==} peerDependencies: @@ -1679,32 +1538,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-dropdown-menu@2.0.6(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-menu': 2.0.6(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.45)(react@18.2.0): resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} peerDependencies: @@ -1742,28 +1575,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-focus-scope@1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-hover-card@1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==} peerDependencies: @@ -1846,43 +1657,6 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) dev: false - /@radix-ui/react-menu@2.0.6(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-popper': 1.1.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-roving-focus': 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - aria-hidden: 1.2.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) - dev: false - /@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==} peerDependencies: @@ -1918,40 +1692,6 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) dev: false - /@radix-ui/react-popover@1.0.7(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-popper': 1.1.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - aria-hidden: 1.2.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) - dev: false - /@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} peerDependencies: @@ -1982,35 +1722,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-popper@1.1.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@floating-ui/react-dom': 2.0.4(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-arrow': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/rect': 1.0.1 - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} peerDependencies: @@ -2032,26 +1743,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-portal@1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} peerDependencies: @@ -2074,27 +1765,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-presence@1.0.1(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} peerDependencies: @@ -2116,26 +1786,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-primitive@1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} peerDependencies: @@ -2165,34 +1815,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-roving-focus@1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-separator@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==} peerDependencies: @@ -2365,37 +1987,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-tooltip@1.0.7(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-popper': 1.1.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) - '@radix-ui/react-visually-hidden': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.45)(react@18.2.0): resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} peerDependencies: @@ -2519,26 +2110,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@radix-ui/react-visually-hidden@1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==} - 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 - dependencies: - '@babel/runtime': 7.23.6 - '@radix-ui/react-primitive': 1.0.3(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.45 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /@radix-ui/rect@1.0.1: resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} dependencies: @@ -5887,7 +5458,6 @@ packages: /tailwind-merge@1.14.0: resolution: {integrity: sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==} - dev: true /tailwind-scrollbar@3.0.5(tailwindcss@3.4.0): resolution: {integrity: sha512-0ZwxTivevqq9BY9fRP9zDjHl7Tu+J5giBGbln+0O1R/7nHtBUKnjQcA1aTIhK7Oyjp6Uc/Dj6/dn8Dq58k5Uww==}