feat: polish
This commit is contained in:
@@ -35,81 +35,70 @@ export default function Router() {
|
|||||||
return { Component: HomeScreen };
|
return { Component: HomeScreen };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "settings",
|
||||||
|
element: <SettingsLayout />,
|
||||||
|
children: [
|
||||||
{
|
{
|
||||||
path: "settings",
|
index: true,
|
||||||
element: <SettingsLayout />,
|
async lazy() {
|
||||||
children: [
|
const { GeneralSettingScreen } = await import(
|
||||||
{
|
"./routes/settings/general"
|
||||||
index: true,
|
);
|
||||||
async lazy() {
|
return { Component: GeneralSettingScreen };
|
||||||
const { UserSettingScreen } = await import(
|
},
|
||||||
"./routes/settings"
|
},
|
||||||
);
|
{
|
||||||
return { Component: UserSettingScreen };
|
path: "profile",
|
||||||
},
|
async lazy() {
|
||||||
},
|
const { ProfileSettingScreen } = await import(
|
||||||
{
|
"./routes/settings/profile"
|
||||||
path: "edit-profile",
|
);
|
||||||
async lazy() {
|
return { Component: ProfileSettingScreen };
|
||||||
const { EditProfileScreen } = await import(
|
},
|
||||||
"./routes/settings/editProfile"
|
},
|
||||||
);
|
{
|
||||||
return { Component: EditProfileScreen };
|
path: "edit-contact",
|
||||||
},
|
async lazy() {
|
||||||
},
|
const { EditContactScreen } = await import(
|
||||||
{
|
"./routes/settings/editContact"
|
||||||
path: "edit-contact",
|
);
|
||||||
async lazy() {
|
return { Component: EditContactScreen };
|
||||||
const { EditContactScreen } = await import(
|
},
|
||||||
"./routes/settings/editContact"
|
},
|
||||||
);
|
{
|
||||||
return { Component: EditContactScreen };
|
path: "backup",
|
||||||
},
|
async lazy() {
|
||||||
},
|
const { BackupSettingScreen } = await import(
|
||||||
{
|
"./routes/settings/backup"
|
||||||
path: "general",
|
);
|
||||||
async lazy() {
|
return { Component: BackupSettingScreen };
|
||||||
const { GeneralSettingScreen } = await import(
|
},
|
||||||
"./routes/settings/general"
|
},
|
||||||
);
|
{
|
||||||
return { Component: GeneralSettingScreen };
|
path: "advanced",
|
||||||
},
|
async lazy() {
|
||||||
},
|
const { AdvancedSettingScreen } = await import(
|
||||||
{
|
"./routes/settings/advanced"
|
||||||
path: "backup",
|
);
|
||||||
async lazy() {
|
return { Component: AdvancedSettingScreen };
|
||||||
const { BackupSettingScreen } = await import(
|
},
|
||||||
"./routes/settings/backup"
|
},
|
||||||
);
|
{
|
||||||
return { Component: BackupSettingScreen };
|
path: "nwc",
|
||||||
},
|
async lazy() {
|
||||||
},
|
const { NWCScreen } = await import("./routes/settings/nwc");
|
||||||
{
|
return { Component: NWCScreen };
|
||||||
path: "advanced",
|
},
|
||||||
async lazy() {
|
},
|
||||||
const { AdvancedSettingScreen } = await import(
|
{
|
||||||
"./routes/settings/advanced"
|
path: "about",
|
||||||
);
|
async lazy() {
|
||||||
return { Component: AdvancedSettingScreen };
|
const { AboutScreen } = await import("./routes/settings/about");
|
||||||
},
|
return { Component: AboutScreen };
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "nwc",
|
|
||||||
async lazy() {
|
|
||||||
const { NWCScreen } = await import("./routes/settings/nwc");
|
|
||||||
return { Component: NWCScreen };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "about",
|
|
||||||
async lazy() {
|
|
||||||
const { AboutScreen } = await import(
|
|
||||||
"./routes/settings/about"
|
|
||||||
);
|
|
||||||
return { Component: AboutScreen };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
43
apps/desktop/src/routes/settings/components/avatarUpload.tsx
Normal file
43
apps/desktop/src/routes/settings/components/avatarUpload.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { useArk } from "@lume/ark";
|
||||||
|
import { LoaderIcon } from "@lume/icons";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export function AvatarUpload({ setPicture }) {
|
||||||
|
const ark = useArk();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const upload = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
// upload image to nostr.build server
|
||||||
|
// #TODO: support multiple server
|
||||||
|
const image = await ark.upload({ fileExts: [] });
|
||||||
|
|
||||||
|
if (!image)
|
||||||
|
toast.error("Failed to upload image, please try again later.");
|
||||||
|
|
||||||
|
setPicture(image);
|
||||||
|
setLoading(false);
|
||||||
|
} catch (e) {
|
||||||
|
setLoading(false);
|
||||||
|
toast.error("Failed to upload image, please try again later.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={upload}
|
||||||
|
disabled={loading}
|
||||||
|
className="inline-flex items-center justify-center w-36 font-medium rounded-lg h-8 bg-blue-500 hover:bg-blue-600 text-white disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<LoaderIcon className="size-4 animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Change avatar"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
43
apps/desktop/src/routes/settings/components/coverUpload.tsx
Normal file
43
apps/desktop/src/routes/settings/components/coverUpload.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { useArk } from "@lume/ark";
|
||||||
|
import { LoaderIcon } from "@lume/icons";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export function CoverUpload({ setBanner }) {
|
||||||
|
const ark = useArk();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const upload = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
// upload image to nostr.build server
|
||||||
|
// #TODO: support multiple server
|
||||||
|
const image = await ark.upload({ fileExts: [] });
|
||||||
|
|
||||||
|
if (!image)
|
||||||
|
toast.error("Failed to upload image, please try again later.");
|
||||||
|
|
||||||
|
setBanner(image);
|
||||||
|
setLoading(false);
|
||||||
|
} catch (e) {
|
||||||
|
setLoading(false);
|
||||||
|
toast.error("Failed to upload image, please try again later.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={upload}
|
||||||
|
disabled={loading}
|
||||||
|
className="inline-flex items-center justify-center w-32 font-medium rounded-lg h-8 bg-blue-500 hover:bg-blue-600 text-white disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<LoaderIcon className="size-4 animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Change cover"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import { ContactCard } from "./components/contactCard";
|
|
||||||
import { PostCard } from "./components/postCard";
|
|
||||||
import { ProfileCard } from "./components/profileCard";
|
|
||||||
import { RelayCard } from "./components/relayCard";
|
|
||||||
import { ZapCard } from "./components/zapCard";
|
|
||||||
|
|
||||||
export function UserSettingScreen() {
|
|
||||||
return (
|
|
||||||
<div className="mx-auto w-full max-w-xl">
|
|
||||||
<ProfileCard />
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
|
||||||
<ContactCard />
|
|
||||||
<RelayCard />
|
|
||||||
<PostCard />
|
|
||||||
<ZapCard />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -5,25 +5,27 @@ import {
|
|||||||
PlusIcon,
|
PlusIcon,
|
||||||
UnverifiedIcon,
|
UnverifiedIcon,
|
||||||
} from "@lume/icons";
|
} from "@lume/icons";
|
||||||
|
import { useStorage } from "@lume/storage";
|
||||||
import { NDKKind, NDKUserProfile } from "@nostr-dev-kit/ndk";
|
import { NDKKind, NDKUserProfile } from "@nostr-dev-kit/ndk";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import { message } from "@tauri-apps/plugin-dialog";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { AvatarUpload } from "./components/avatarUpload";
|
||||||
|
import { CoverUpload } from "./components/coverUpload";
|
||||||
|
|
||||||
|
export function ProfileSettingScreen() {
|
||||||
|
const ark = useArk();
|
||||||
|
const storage = useStorage();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
export function EditProfileScreen() {
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [picture, setPicture] = useState("");
|
const [picture, setPicture] = useState("");
|
||||||
const [banner, setBanner] = useState("");
|
const [banner, setBanner] = useState("");
|
||||||
const [nip05, setNIP05] = useState({ verified: true, text: "" });
|
const [nip05, setNIP05] = useState({ verified: true, text: "" });
|
||||||
|
|
||||||
const ark = useArk();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
reset,
|
|
||||||
setError,
|
setError,
|
||||||
formState: { isValid, errors },
|
formState: { isValid, errors },
|
||||||
} = useForm({
|
} = useForm({
|
||||||
@@ -45,48 +47,6 @@ export function EditProfileScreen() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const uploadAvatar = async () => {
|
|
||||||
try {
|
|
||||||
if (!ark.ndk.signer) return navigate("/new/privkey");
|
|
||||||
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
const image = await ark.upload({ fileExts: [] });
|
|
||||||
if (image) {
|
|
||||||
setPicture(image);
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
setLoading(false);
|
|
||||||
await message(`Upload failed, error: ${e}`, {
|
|
||||||
title: "Lume",
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const uploadBanner = async () => {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
const image = await ark.upload({ fileExts: [] });
|
|
||||||
|
|
||||||
if (image) {
|
|
||||||
setBanner(image);
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
setLoading(false);
|
|
||||||
await message(`Upload failed, error: ${e}`, {
|
|
||||||
title: "Lume",
|
|
||||||
type: "error",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async (data: NDKUserProfile) => {
|
const onSubmit = async (data: NDKUserProfile) => {
|
||||||
// start loading
|
// start loading
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -94,9 +54,12 @@ export function EditProfileScreen() {
|
|||||||
let content = {
|
let content = {
|
||||||
...data,
|
...data,
|
||||||
username: data.name,
|
username: data.name,
|
||||||
display_name: data.name,
|
display_name: data.displayName,
|
||||||
bio: data.about,
|
bio: data.about,
|
||||||
image: data.picture,
|
image: picture,
|
||||||
|
cover: banner,
|
||||||
|
picture,
|
||||||
|
banner,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.nip05) {
|
if (data.nip05) {
|
||||||
@@ -104,13 +67,14 @@ export function EditProfileScreen() {
|
|||||||
pubkey: ark.account.pubkey,
|
pubkey: ark.account.pubkey,
|
||||||
nip05: data.nip05,
|
nip05: data.nip05,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (verify) {
|
if (verify) {
|
||||||
content = { ...content, nip05: data.nip05 };
|
content = { ...content, nip05: data.nip05 };
|
||||||
} else {
|
} else {
|
||||||
setNIP05((prev) => ({ ...prev, verified: false }));
|
setNIP05((prev) => ({ ...prev, verified: false }));
|
||||||
setError("nip05", {
|
setError("nip05", {
|
||||||
type: "manual",
|
type: "manual",
|
||||||
message: "Can't verify your Lume ID / NIP-05, please check again",
|
message: "Can't verify your NIP-05, please check again",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,76 +87,59 @@ export function EditProfileScreen() {
|
|||||||
|
|
||||||
if (publish) {
|
if (publish) {
|
||||||
// invalid cache
|
// invalid cache
|
||||||
queryClient.invalidateQueries({
|
await storage.clearProfileCache(ark.account.pubkey);
|
||||||
|
await queryClient.invalidateQueries({
|
||||||
queryKey: ["user", ark.account.pubkey],
|
queryKey: ["user", ark.account.pubkey],
|
||||||
});
|
});
|
||||||
// reset form
|
|
||||||
reset();
|
|
||||||
// reset state
|
// reset state
|
||||||
setLoading(false);
|
|
||||||
setPicture(null);
|
setPicture(null);
|
||||||
setBanner(null);
|
setBanner(null);
|
||||||
} else {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full max-w-md">
|
<div className="mx-auto w-full max-w-lg">
|
||||||
<form onSubmit={handleSubmit(onSubmit)} className="mb-0">
|
<form onSubmit={handleSubmit(onSubmit)} className="mb-0">
|
||||||
<input type={"hidden"} {...register("picture")} value={picture} />
|
<div className="mb-5 flex flex-col items-center justify-center bg-neutral-100 dark:bg-neutral-900 rounded-xl">
|
||||||
<input type={"hidden"} {...register("banner")} value={banner} />
|
<div className="relative h-44 w-full">
|
||||||
<div className="flex flex-col items-center justify-center">
|
|
||||||
<div className="relative h-36 w-full">
|
|
||||||
{banner ? (
|
{banner ? (
|
||||||
<img
|
<img
|
||||||
src={banner}
|
src={banner}
|
||||||
alt="user's banner"
|
alt="user's banner"
|
||||||
className="h-full w-full rounded-xl object-cover"
|
className="h-full w-full rounded-t-xl object-cover"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-full w-full rounded-xl bg-neutral-200 dark:bg-neutral-900" />
|
<div className="h-full w-full rounded-t-xl bg-neutral-200 dark:bg-neutral-900" />
|
||||||
)}
|
)}
|
||||||
<div className="absolute left-1/2 top-1/2 z-10 h-full w-full -translate-x-1/2 -translate-y-1/2 transform overflow-hidden rounded-xl">
|
<div className="absolute right-4 top-4">
|
||||||
<button
|
<CoverUpload setBanner={setBanner} />
|
||||||
type="button"
|
|
||||||
onClick={() => uploadBanner()}
|
|
||||||
className="inline-flex h-full w-full items-center justify-center bg-black/20 text-white"
|
|
||||||
>
|
|
||||||
<PlusIcon className="h-5 w-5" />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-5 px-4">
|
<div className="-mt-7 mb-5 px-4 flex flex-col gap-4 items-center z-10 relative">
|
||||||
<div className="relative z-10 -mt-7 h-14 w-14 overflow-hidden rounded-xl ring-2 ring-white dark:ring-black">
|
<div className="size-14 overflow-hidden rounded-xl ring-2 ring-white dark:ring-black">
|
||||||
<img
|
<img
|
||||||
src={picture}
|
src={picture}
|
||||||
alt="user's avatar"
|
alt="user's avatar"
|
||||||
className="h-14 w-14 rounded-xl object-cover"
|
className="h-14 w-14 rounded-xl object-cover bg-white dark:bg-black"
|
||||||
/>
|
/>
|
||||||
<div className="absolute left-1/2 top-1/2 z-10 h-full w-full -translate-x-1/2 -translate-y-1/2 transform">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => uploadAvatar()}
|
|
||||||
className="inline-flex h-full w-full items-center justify-center rounded-xl bg-black/50 text-white"
|
|
||||||
>
|
|
||||||
<PlusIcon className="h-5 w-5" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<AvatarUpload setPicture={setPicture} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<label
|
<label
|
||||||
htmlFor="display_name"
|
htmlFor="displayName"
|
||||||
className="text-sm font-semibold uppercase tracking-wider"
|
className="text-sm font-semibold uppercase tracking-wider"
|
||||||
>
|
>
|
||||||
Display Name
|
Display Name
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type={"text"}
|
type={"text"}
|
||||||
{...register("display_name")}
|
{...register("displayName")}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
className="relative h-11 w-full rounded-lg border-transparent bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-100"
|
className="relative h-11 w-full rounded-lg border-transparent bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-100"
|
||||||
/>
|
/>
|
||||||
@@ -282,17 +229,17 @@ export function EditProfileScreen() {
|
|||||||
<textarea
|
<textarea
|
||||||
{...register("about")}
|
{...register("about")}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
className="relative h-20 w-full resize-none rounded-lg border-transparent bg-neutral-100 px-3 py-2 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-100"
|
className="relative h-36 w-full resize-none rounded-lg border-transparent bg-neutral-100 px-3 py-2 text-neutral-900 !outline-none backdrop-blur-xl placeholder:text-neutral-500 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-100"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="absolute right-4 bottom-4">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!isValid}
|
disabled={!isValid || loading}
|
||||||
className="mx-auto inline-flex h-11 w-full transform items-center justify-center gap-1 rounded-lg bg-blue-500 font-medium text-white hover:bg-blue-600 focus:outline-none active:translate-y-1 disabled:pointer-events-none disabled:opacity-50"
|
className="mx-auto inline-flex h-10 w-24 transform items-center justify-center gap-1 rounded-lg bg-blue-500 font-medium text-white hover:bg-blue-600 focus:outline-none active:translate-y-1 disabled:pointer-events-none disabled:opacity-50"
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-white" />
|
<LoaderIcon className="size-4 animate-spin" />
|
||||||
) : (
|
) : (
|
||||||
"Update"
|
"Update"
|
||||||
)}
|
)}
|
||||||
@@ -105,7 +105,7 @@ export class Ark {
|
|||||||
|
|
||||||
public getCleanPubkey(pubkey: string) {
|
public getCleanPubkey(pubkey: string) {
|
||||||
try {
|
try {
|
||||||
let hexstring = pubkey.replace("nostr:", "").split("'")[0];
|
let hexstring = pubkey.replace("nostr:", "").split("'")[0].split(".")[0];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hexstring.startsWith("npub1") ||
|
hexstring.startsWith("npub1") ||
|
||||||
@@ -128,24 +128,10 @@ export class Ark {
|
|||||||
public async getUserProfile(pubkey?: string) {
|
public async getUserProfile(pubkey?: string) {
|
||||||
try {
|
try {
|
||||||
const currentUserPubkey = this.account.pubkey;
|
const currentUserPubkey = this.account.pubkey;
|
||||||
|
const hexstring = pubkey
|
||||||
// get clean pubkey without any special characters
|
? this.getCleanPubkey(pubkey)
|
||||||
let hexstring = pubkey
|
|
||||||
? pubkey.replace("nostr:", "").split("'")[0]
|
|
||||||
: currentUserPubkey;
|
: currentUserPubkey;
|
||||||
|
|
||||||
if (
|
|
||||||
hexstring.startsWith("npub1") ||
|
|
||||||
hexstring.startsWith("nprofile1") ||
|
|
||||||
hexstring.startsWith("naddr1")
|
|
||||||
) {
|
|
||||||
const decoded = nip19.decode(hexstring);
|
|
||||||
|
|
||||||
if (decoded.type === "nprofile") hexstring = decoded.data.pubkey;
|
|
||||||
if (decoded.type === "npub") hexstring = decoded.data;
|
|
||||||
if (decoded.type === "naddr") hexstring = decoded.data.pubkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = this.ndk.getUser({
|
const user = this.ndk.getUser({
|
||||||
pubkey: hexstring,
|
pubkey: hexstring,
|
||||||
});
|
});
|
||||||
@@ -157,6 +143,7 @@ export class Ark {
|
|||||||
if (!profile) return null;
|
if (!profile) return null;
|
||||||
return profile;
|
return profile;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.log(pubkey);
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,24 +151,10 @@ export class Ark {
|
|||||||
public async getUserContacts(pubkey?: string) {
|
public async getUserContacts(pubkey?: string) {
|
||||||
try {
|
try {
|
||||||
const currentUserPubkey = this.account.pubkey;
|
const currentUserPubkey = this.account.pubkey;
|
||||||
|
const hexstring = pubkey
|
||||||
// get clean pubkey without any special characters
|
? this.getCleanPubkey(pubkey)
|
||||||
let hexstring = pubkey
|
|
||||||
? pubkey.replace("nostr:", "").split("'")[0]
|
|
||||||
: currentUserPubkey;
|
: currentUserPubkey;
|
||||||
|
|
||||||
if (
|
|
||||||
hexstring.startsWith("npub1") ||
|
|
||||||
hexstring.startsWith("nprofile1") ||
|
|
||||||
hexstring.startsWith("naddr1")
|
|
||||||
) {
|
|
||||||
const decoded = nip19.decode(hexstring);
|
|
||||||
|
|
||||||
if (decoded.type === "nprofile") hexstring = decoded.data.pubkey;
|
|
||||||
if (decoded.type === "npub") hexstring = decoded.data;
|
|
||||||
if (decoded.type === "naddr") hexstring = decoded.data.pubkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = this.ndk.getUser({
|
const user = this.ndk.getUser({
|
||||||
pubkey: hexstring,
|
pubkey: hexstring,
|
||||||
});
|
});
|
||||||
@@ -252,8 +225,8 @@ export class Ark {
|
|||||||
return [...events];
|
return [...events];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getEventById({ id }: { id: string }) {
|
public async getEventById(id: string) {
|
||||||
let eventId: string = id;
|
let eventId: string = id.replace("nostr:", "").split("'")[0].split(".")[0];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
eventId.startsWith("nevent1") ||
|
eventId.startsWith("nevent1") ||
|
||||||
@@ -264,7 +237,6 @@ export class Ark {
|
|||||||
|
|
||||||
if (decode.type === "nevent") eventId = decode.data.id;
|
if (decode.type === "nevent") eventId = decode.data.id;
|
||||||
if (decode.type === "note") eventId = decode.data;
|
if (decode.type === "note") eventId = decode.data;
|
||||||
|
|
||||||
if (decode.type === "naddr") {
|
if (decode.type === "naddr") {
|
||||||
return await this.ndk.fetchEvent({
|
return await this.ndk.fetchEvent({
|
||||||
kinds: [decode.data.kind],
|
kinds: [decode.data.kind],
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ export function ColumnHeader({
|
|||||||
</button>
|
</button>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Portal>
|
<DropdownMenu.Portal>
|
||||||
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-xl border border-neutral-100 bg-neutral-50 dark:bg-neutral-950 focus:outline-none dark:border-neutral-900">
|
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-black/70 dark:bg-white/20 backdrop-blur-lg focus:outline-none">
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={refresh}
|
onClick={refresh}
|
||||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-neutral-700 hover:bg-blue-100 hover:text-blue-500 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-900 dark:hover:text-neutral-50"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
<RefreshIcon className="size-5" />
|
<RefreshIcon className="size-5" />
|
||||||
Refresh
|
Refresh
|
||||||
@@ -75,7 +75,7 @@ export function ColumnHeader({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={moveLeft}
|
onClick={moveLeft}
|
||||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-neutral-700 hover:bg-blue-100 hover:text-blue-500 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-900 dark:hover:text-neutral-50"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
<MoveLeftIcon className="size-5" />
|
<MoveLeftIcon className="size-5" />
|
||||||
Move left
|
Move left
|
||||||
@@ -85,18 +85,18 @@ export function ColumnHeader({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={moveRight}
|
onClick={moveRight}
|
||||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-neutral-700 hover:bg-blue-100 hover:text-blue-500 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-900 dark:hover:text-neutral-50"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
<MoveRightIcon className="size-5" />
|
<MoveRightIcon className="size-5" />
|
||||||
Move right
|
Move right
|
||||||
</button>
|
</button>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Separator className="h-px my-1 bg-neutral-100 dark:bg-neutral-900" />
|
<DropdownMenu.Separator className="h-px my-1 bg-white/10 dark:bg-black/10" />
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={deleteWidget}
|
onClick={deleteWidget}
|
||||||
className="inline-flex items-center gap-2 px-3 text-sm font-medium text-red-500 rounded-lg h-9 hover:bg-red-500 hover:text-red-50 focus:outline-none"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium text-red-300 rounded-lg h-9 hover:bg-red-500 hover:text-red-50 focus:outline-none"
|
||||||
>
|
>
|
||||||
<TrashIcon className="size-5" />
|
<TrashIcon className="size-5" />
|
||||||
Delete
|
Delete
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
import { ChatsIcon, ReplyIcon } from "@lume/icons";
|
import { ChatsIcon } from "@lume/icons";
|
||||||
import { editorAtom, editorValueAtom } from "@lume/utils";
|
|
||||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||||
import { useSetAtom } from "jotai";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { nip19 } from "nostr-tools";
|
|
||||||
import { useNoteContext } from "../provider";
|
import { useNoteContext } from "../provider";
|
||||||
|
|
||||||
export function NoteReply() {
|
export function NoteReply() {
|
||||||
const event = useNoteContext();
|
const event = useNoteContext();
|
||||||
|
const navigate = useNavigate();
|
||||||
const setEditorValue = useSetAtom(editorValueAtom);
|
|
||||||
const setIsEditorOpen = useSetAtom(editorAtom);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip.Provider>
|
<Tooltip.Provider>
|
||||||
@@ -17,25 +13,7 @@ export function NoteReply() {
|
|||||||
<Tooltip.Trigger asChild>
|
<Tooltip.Trigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => navigate(`/events/${event.id}`)}
|
||||||
setEditorValue([
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
children: [{ text: "" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "event",
|
|
||||||
// @ts-expect-error, useless
|
|
||||||
eventId: `nostr:${nip19.noteEncode(event.id)}`,
|
|
||||||
children: [{ text: "" }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "paragraph",
|
|
||||||
children: [{ text: "" }],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
setIsEditorOpen(true);
|
|
||||||
}}
|
|
||||||
className="inline-flex items-center justify-center group h-7 w-7 text-neutral-600 dark:text-neutral-400"
|
className="inline-flex items-center justify-center group h-7 w-7 text-neutral-600 dark:text-neutral-400"
|
||||||
>
|
>
|
||||||
<ChatsIcon className="size-5 group-hover:text-blue-500" />
|
<ChatsIcon className="size-5 group-hover:text-blue-500" />
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { LoaderIcon, RepostIcon } from "@lume/icons";
|
import { LoaderIcon, RepostIcon } from "@lume/icons";
|
||||||
|
import { editorAtom, editorValueAtom } from "@lume/utils";
|
||||||
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||||
|
import { useSetAtom } from "jotai";
|
||||||
|
import { nip19 } from "nostr-tools";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
@@ -7,11 +11,14 @@ import { useNoteContext } from "../provider";
|
|||||||
|
|
||||||
export function NoteRepost() {
|
export function NoteRepost() {
|
||||||
const event = useNoteContext();
|
const event = useNoteContext();
|
||||||
|
const setEditorValue = useSetAtom(editorValueAtom);
|
||||||
|
const setIsEditorOpen = useSetAtom(editorAtom);
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [isRepost, setIsRepost] = useState(false);
|
const [isRepost, setIsRepost] = useState(false);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const submit = async () => {
|
const repost = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
@@ -30,34 +37,79 @@ export function NoteRepost() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const quote = () => {
|
||||||
|
setEditorValue([
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [{ text: "" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "event",
|
||||||
|
// @ts-expect-error, useless
|
||||||
|
eventId: `nostr:${nip19.noteEncode(event.id)}`,
|
||||||
|
children: [{ text: "" }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [{ text: "" }],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
setIsEditorOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip.Provider>
|
<DropdownMenu.Root open={open} onOpenChange={setOpen}>
|
||||||
<Tooltip.Root delayDuration={150}>
|
<Tooltip.Provider>
|
||||||
<Tooltip.Trigger asChild>
|
<Tooltip.Root delayDuration={150}>
|
||||||
<button
|
<DropdownMenu.Trigger asChild>
|
||||||
type="button"
|
<Tooltip.Trigger asChild>
|
||||||
onClick={submit}
|
<button
|
||||||
className="inline-flex items-center justify-center group h-7 w-7 text-neutral-600 dark:text-neutral-400"
|
type="button"
|
||||||
>
|
className="inline-flex items-center justify-center group h-7 w-7 text-neutral-600 dark:text-neutral-400"
|
||||||
{loading ? (
|
>
|
||||||
<LoaderIcon className="size-4 animate-spin" />
|
{loading ? (
|
||||||
) : (
|
<LoaderIcon className="size-4 animate-spin" />
|
||||||
<RepostIcon
|
) : (
|
||||||
className={twMerge(
|
<RepostIcon
|
||||||
"size-5 group-hover:text-blue-600",
|
className={twMerge(
|
||||||
isRepost ? "text-blue-500" : "",
|
"size-5 group-hover:text-blue-600",
|
||||||
|
isRepost ? "text-blue-500" : "",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
</button>
|
||||||
)}
|
</Tooltip.Trigger>
|
||||||
</button>
|
</DropdownMenu.Trigger>
|
||||||
</Tooltip.Trigger>
|
<Tooltip.Portal>
|
||||||
<Tooltip.Portal>
|
<Tooltip.Content className="inline-flex h-7 select-none text-neutral-50 dark:text-neutral-950 items-center justify-center rounded-md bg-neutral-950 dark:bg-neutral-50 px-3.5 text-sm will-change-[transform,opacity] data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade">
|
||||||
<Tooltip.Content className="inline-flex h-7 select-none text-neutral-50 dark:text-neutral-950 items-center justify-center rounded-md bg-neutral-950 dark:bg-neutral-50 px-3.5 text-sm will-change-[transform,opacity] data-[state=delayed-open]:data-[side=bottom]:animate-slideUpAndFade data-[state=delayed-open]:data-[side=left]:animate-slideRightAndFade data-[state=delayed-open]:data-[side=right]:animate-slideLeftAndFade data-[state=delayed-open]:data-[side=top]:animate-slideDownAndFade">
|
Repost
|
||||||
Repost
|
<Tooltip.Arrow className="fill-neutral-950 dark:fill-neutral-50" />
|
||||||
<Tooltip.Arrow className="fill-neutral-950 dark:fill-neutral-50" />
|
</Tooltip.Content>
|
||||||
</Tooltip.Content>
|
</Tooltip.Portal>
|
||||||
</Tooltip.Portal>
|
</Tooltip.Root>
|
||||||
</Tooltip.Root>
|
</Tooltip.Provider>
|
||||||
</Tooltip.Provider>
|
<DropdownMenu.Portal>
|
||||||
|
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-black/70 dark:bg-white/20 backdrop-blur-lg focus:outline-none">
|
||||||
|
<DropdownMenu.Item asChild>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={repost}
|
||||||
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
|
>
|
||||||
|
Repost
|
||||||
|
</button>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Item asChild>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={quote}
|
||||||
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
|
>
|
||||||
|
Quote
|
||||||
|
</button>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Portal>
|
||||||
|
</DropdownMenu.Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { PinIcon } from "@lume/icons";
|
import { PinIcon, RefreshIcon } from "@lume/icons";
|
||||||
import { COL_TYPES } from "@lume/utils";
|
import { COL_TYPES } from "@lume/utils";
|
||||||
import { memo } from "react";
|
import { memo } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
@@ -18,14 +18,15 @@ export const MentionNote = memo(function MentionNote({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
contentEditable={false}
|
contentEditable={false}
|
||||||
className="w-full p-3 my-1 rounded-lg cursor-default bg-neutral-100 dark:bg-neutral-900"
|
className="flex items-center justify-between w-full p-3 my-1 rounded-lg cursor-default bg-neutral-100 dark:bg-neutral-900"
|
||||||
>
|
>
|
||||||
Loading
|
<p>Loading</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError) {
|
if (isError || !data) {
|
||||||
|
console.log(eventId);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
contentEditable={false}
|
contentEditable={false}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const MentionUser = memo(function MentionUser({
|
|||||||
const ark = useArk();
|
const ark = useArk();
|
||||||
const cleanPubkey = ark.getCleanPubkey(pubkey);
|
const cleanPubkey = ark.getCleanPubkey(pubkey);
|
||||||
|
|
||||||
const { isLoading, user } = useProfile(pubkey);
|
const { isLoading, isError, user } = useProfile(pubkey);
|
||||||
const { addColumn } = useColumnContext();
|
const { addColumn } = useColumnContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -20,7 +20,9 @@ export const MentionUser = memo(function MentionUser({
|
|||||||
<DropdownMenu.Trigger className="text-blue-500 break-words hover:text-blue-600">
|
<DropdownMenu.Trigger className="text-blue-500 break-words hover:text-blue-600">
|
||||||
{isLoading
|
{isLoading
|
||||||
? "@anon"
|
? "@anon"
|
||||||
: `@${user.name || user.display_name || user.username || "anon"}`}
|
: isError
|
||||||
|
? pubkey
|
||||||
|
: `@${user.name || user.displayName || user.username || "anon"}`}
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Content className="left-[50px] z-50 relative flex w-[200px] flex-col overflow-hidden rounded-xl border border-neutral-200 bg-neutral-950 focus:outline-none dark:border-neutral-900">
|
<DropdownMenu.Content className="left-[50px] z-50 relative flex w-[200px] flex-col overflow-hidden rounded-xl border border-neutral-200 bg-neutral-950 focus:outline-none dark:border-neutral-900">
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { nip19 } from "nostr-tools";
|
|||||||
import { type EventPointer } from "nostr-tools/lib/types/nip19";
|
import { type EventPointer } from "nostr-tools/lib/types/nip19";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { useNoteContext } from "./provider";
|
import { useNoteContext } from "./provider";
|
||||||
|
|
||||||
export function NoteMenu() {
|
export function NoteMenu() {
|
||||||
@@ -25,6 +26,10 @@ export function NoteMenu() {
|
|||||||
await writeText(JSON.stringify(await event.toNostrEvent()));
|
await writeText(JSON.stringify(await event.toNostrEvent()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const copyNpub = async () => {
|
||||||
|
await writeText(nip19.npubEncode(event.pubkey));
|
||||||
|
};
|
||||||
|
|
||||||
const copyLink = async () => {
|
const copyLink = async () => {
|
||||||
await writeText(
|
await writeText(
|
||||||
`https://njump.me/${nip19.neventEncode({
|
`https://njump.me/${nip19.neventEncode({
|
||||||
@@ -35,6 +40,11 @@ export function NoteMenu() {
|
|||||||
setOpen(false);
|
setOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const muteUser = async () => {
|
||||||
|
event.muted();
|
||||||
|
toast.info("You've muted this user");
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root open={open} onOpenChange={setOpen}>
|
<DropdownMenu.Root open={open} onOpenChange={setOpen}>
|
||||||
<DropdownMenu.Trigger asChild>
|
<DropdownMenu.Trigger asChild>
|
||||||
@@ -46,12 +56,12 @@ export function NoteMenu() {
|
|||||||
</button>
|
</button>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownMenu.Portal>
|
<DropdownMenu.Portal>
|
||||||
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-xl border border-neutral-200 bg-neutral-950 focus:outline-none dark:border-neutral-900">
|
<DropdownMenu.Content className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-black/70 dark:bg-white/20 backdrop-blur-lg focus:outline-none">
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => copyLink()}
|
onClick={() => copyLink()}
|
||||||
className="inline-flex items-center h-10 px-4 text-sm text-white rounded-lg hover:bg-neutral-900 focus:outline-none"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
Copy shareable link
|
Copy shareable link
|
||||||
</button>
|
</button>
|
||||||
@@ -60,28 +70,47 @@ export function NoteMenu() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => copyID()}
|
onClick={() => copyID()}
|
||||||
className="inline-flex items-center h-10 px-4 text-sm text-white rounded-lg hover:bg-neutral-900 focus:outline-none"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
Copy note ID
|
Copy ID
|
||||||
</button>
|
</button>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => copyRaw()}
|
onClick={() => copyNpub()}
|
||||||
className="inline-flex items-center h-10 px-4 text-sm text-white rounded-lg hover:bg-neutral-900 focus:outline-none"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
Copy raw event
|
Copy npub
|
||||||
</button>
|
</button>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<Link
|
<Link
|
||||||
to={`/users/${event.pubkey}`}
|
to={`/users/${event.pubkey}`}
|
||||||
className="inline-flex items-center h-10 px-4 text-sm text-white rounded-lg hover:bg-neutral-900 focus:outline-none"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
View profile
|
View profile
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Separator className="h-px my-1 bg-white/10 dark:bg-black/10" />
|
||||||
|
<DropdownMenu.Item asChild>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => copyRaw()}
|
||||||
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
|
>
|
||||||
|
Copy raw event
|
||||||
|
</button>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Item asChild>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={muteUser}
|
||||||
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium text-red-300 rounded-lg h-9 hover:bg-red-500 hover:text-red-50 focus:outline-none"
|
||||||
|
>
|
||||||
|
Mute
|
||||||
|
</button>
|
||||||
|
</DropdownMenu.Item>
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Portal>
|
</DropdownMenu.Portal>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ export function LinkPreview({ url }: { url: string }) {
|
|||||||
<div className="flex flex-col items-start px-3 py-3">
|
<div className="flex flex-col items-start px-3 py-3">
|
||||||
<div className="flex flex-col items-start gap-1 text-left">
|
<div className="flex flex-col items-start gap-1 text-left">
|
||||||
{data.title ? (
|
{data.title ? (
|
||||||
<div className="text-base font-semibold break-all text-neutral-900 dark:text-neutral-100">
|
<div className="text-base font-semibold break-p text-neutral-900 dark:text-neutral-100">
|
||||||
{data.title}
|
{data.title}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{data.description ? (
|
{data.description ? (
|
||||||
<div className="mb-2 text-sm break-all line-clamp-3 text-neutral-700 dark:text-neutral-400">
|
<div className="mb-2 text-sm break-p line-clamp-3 text-neutral-700 dark:text-neutral-400">
|
||||||
{data.description}
|
{data.description}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function RepostNote({
|
|||||||
return new NDKEvent(ark.ndk, embed);
|
return new NDKEvent(ark.ndk, embed);
|
||||||
}
|
}
|
||||||
const id = event.tags.find((el) => el[0] === "e")[1];
|
const id = event.tags.find((el) => el[0] === "e")[1];
|
||||||
return await ark.getEventById({ id });
|
return await ark.getEventById(id);
|
||||||
} catch {
|
} catch {
|
||||||
throw new Error("Failed to get repost event");
|
throw new Error("Failed to get repost event");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export function useEvent(id: string) {
|
|||||||
const { status, isLoading, isError, data } = useQuery({
|
const { status, isLoading, isError, data } = useQuery({
|
||||||
queryKey: ["event", id],
|
queryKey: ["event", id],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const event = await ark.getEventById({ id });
|
const event = await ark.getEventById(id);
|
||||||
if (!event)
|
if (!event)
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cannot get event with ${id}, will be retry after 10 seconds`,
|
`Cannot get event with ${id}, will be retry after 10 seconds`,
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ export const LumeProvider = ({ children }: PropsWithChildren<object>) => {
|
|||||||
: ["wss://brb.io/"],
|
: ["wss://brb.io/"],
|
||||||
);
|
);
|
||||||
|
|
||||||
const cacheAdapter = new NDKCacheAdapterTauri(storage);
|
const tauriCache = new NDKCacheAdapterTauri(storage);
|
||||||
const ndk = new NDK({
|
const ndk = new NDK({
|
||||||
cacheAdapter,
|
cacheAdapter: tauriCache,
|
||||||
explicitRelayUrls,
|
explicitRelayUrls,
|
||||||
outboxRelayUrls,
|
outboxRelayUrls,
|
||||||
blacklistRelayUrls,
|
blacklistRelayUrls,
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
import { SVGProps } from 'react';
|
import { SVGProps } from "react";
|
||||||
|
|
||||||
export function LogoutIcon(props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) {
|
export function LogoutIcon(
|
||||||
return (
|
props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>,
|
||||||
<svg
|
) {
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
return (
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="none"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
{...props}
|
fill="none"
|
||||||
>
|
viewBox="0 0 24 24"
|
||||||
<path
|
{...props}
|
||||||
stroke="currentColor"
|
>
|
||||||
strokeLinecap="round"
|
<path
|
||||||
strokeLinejoin="round"
|
stroke="currentColor"
|
||||||
strokeWidth="1.5"
|
strokeLinecap="round"
|
||||||
d="M20.25 12H9m11.25 0l-4.5 4.5m4.5-4.5l-4.5-4.5m-4.5 12.75h-6.5a1 1 0 01-1-1V4.75a1 1 0 011-1h6.5"
|
strokeLinejoin="round"
|
||||||
/>
|
strokeWidth="2"
|
||||||
</svg>
|
d="M18.189 9a15 15 0 012.654 2.556c.105.13.157.287.157.444m-2.811 3a14.998 14.998 0 002.654-2.556A.704.704 0 0021 12m0 0H8m5-7.472A6 6 0 003 9v6a6 6 0 0010 4.472"
|
||||||
);
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ export class NDKCacheAdapterTauri implements NDKCacheAdapter {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const _filter = { ...filter };
|
const _filter = { ...filter };
|
||||||
_filter.limit = undefined;
|
_filter.limit = undefined;
|
||||||
const filterKeys = Object.keys(_filter || {}).sort();
|
const filterKeys = Object.keys(_filter || {})
|
||||||
|
.sort()
|
||||||
|
.filter((e) => e !== "limit" && e !== "since");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.allSettled([
|
await Promise.allSettled([
|
||||||
@@ -119,7 +121,9 @@ export class NDKCacheAdapterTauri implements NDKCacheAdapter {
|
|||||||
id: event.tagId(),
|
id: event.tagId(),
|
||||||
pubkey: event.pubkey,
|
pubkey: event.pubkey,
|
||||||
content: event.content,
|
content: event.content,
|
||||||
|
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||||
kind: event.kind!,
|
kind: event.kind!,
|
||||||
|
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||||
createdAt: event.created_at!,
|
createdAt: event.created_at!,
|
||||||
relay: relay?.url,
|
relay: relay?.url,
|
||||||
event: JSON.stringify(event.rawEvent()),
|
event: JSON.stringify(event.rawEvent()),
|
||||||
@@ -357,8 +361,8 @@ export class NDKCacheAdapterTauri implements NDKCacheAdapter {
|
|||||||
const kinds = filter.kinds as number[];
|
const kinds = filter.kinds as number[];
|
||||||
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
|
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||||
if (!kinds?.includes(event.kind!)) continue;
|
if (!kinds?.includes(event.kind!)) continue;
|
||||||
|
|
||||||
subscription.eventReceived(event, undefined, true);
|
subscription.eventReceived(event, undefined, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -414,6 +414,12 @@ export class LumeStorage {
|
|||||||
await this.#db.execute("DELETE FROM ndk_users;");
|
await this.#db.execute("DELETE FROM ndk_users;");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async clearProfileCache(pubkey: string) {
|
||||||
|
await this.#db.execute("DELETE FROM ndk_users WHERE pubkey = $1;", [
|
||||||
|
pubkey,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public async logout() {
|
public async logout() {
|
||||||
this.currentUser = null;
|
this.currentUser = null;
|
||||||
return await this.#db.execute(
|
return await this.#db.execute(
|
||||||
|
|||||||
@@ -1,45 +1,73 @@
|
|||||||
import { useArk, useProfile } from "@lume/ark";
|
import { useArk, useProfile } from "@lume/ark";
|
||||||
import { useNetworkStatus } from "@lume/utils";
|
import { SettingsIcon } from "@lume/icons";
|
||||||
|
import { cn, useNetworkStatus } from "@lume/utils";
|
||||||
import * as Avatar from "@radix-ui/react-avatar";
|
import * as Avatar from "@radix-ui/react-avatar";
|
||||||
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
||||||
import { minidenticon } from "minidenticons";
|
import { minidenticon } from "minidenticons";
|
||||||
|
import { useMemo } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { Logout } from "./logout";
|
||||||
|
|
||||||
export function ActiveAccount() {
|
export function ActiveAccount() {
|
||||||
const ark = useArk();
|
const ark = useArk();
|
||||||
const isOnline = useNetworkStatus();
|
const isOnline = useNetworkStatus();
|
||||||
|
const svgURI = useMemo(
|
||||||
|
() =>
|
||||||
|
`data:image/svg+xml;utf8,${encodeURIComponent(
|
||||||
|
minidenticon(ark.account.pubkey, 90, 50),
|
||||||
|
)}`,
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
const { user } = useProfile(ark.account.pubkey);
|
const { user } = useProfile(ark.account.pubkey);
|
||||||
|
|
||||||
const svgURI = `data:image/svg+xml;utf8,${encodeURIComponent(
|
|
||||||
minidenticon(ark.account.pubkey, 90, 50),
|
|
||||||
)}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to="/settings/" className="relative inline-block">
|
<DropdownMenu.Root>
|
||||||
<Avatar.Root>
|
<DropdownMenu.Trigger asChild>
|
||||||
<Avatar.Image
|
<div>
|
||||||
src={user?.picture || user?.image}
|
<Avatar.Root>
|
||||||
alt={ark.account.pubkey}
|
<Avatar.Image
|
||||||
loading="lazy"
|
src={user?.picture || user?.image}
|
||||||
decoding="async"
|
alt={ark.account.pubkey}
|
||||||
style={{ contentVisibility: "auto" }}
|
loading="lazy"
|
||||||
className="aspect-square h-auto w-full rounded-xl object-cover"
|
decoding="async"
|
||||||
/>
|
style={{ contentVisibility: "auto" }}
|
||||||
<Avatar.Fallback delayMs={150}>
|
className="aspect-square h-auto w-full rounded-xl object-cover"
|
||||||
<img
|
/>
|
||||||
src={svgURI}
|
<Avatar.Fallback delayMs={150}>
|
||||||
alt={ark.account.pubkey}
|
<img
|
||||||
className="aspect-square h-auto w-full rounded-xl bg-black dark:bg-white"
|
src={svgURI}
|
||||||
|
alt={ark.account.pubkey}
|
||||||
|
className="aspect-square h-auto w-full rounded-xl bg-black dark:bg-white"
|
||||||
|
/>
|
||||||
|
</Avatar.Fallback>
|
||||||
|
</Avatar.Root>
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
"absolute bottom-0 right-0 block h-2 w-2 rounded-full ring-2 ring-neutral-100 dark:ring-neutral-900",
|
||||||
|
isOnline ? "bg-teal-500" : "bg-red-500",
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Avatar.Fallback>
|
</div>
|
||||||
</Avatar.Root>
|
</DropdownMenu.Trigger>
|
||||||
<span
|
<DropdownMenu.Portal>
|
||||||
className={twMerge(
|
<DropdownMenu.Content
|
||||||
"absolute bottom-0 right-0 block h-2 w-2 rounded-full ring-2 ring-neutral-100 dark:ring-neutral-900",
|
side="right"
|
||||||
isOnline ? "bg-teal-500" : "bg-red-500",
|
sideOffset={5}
|
||||||
)}
|
className="flex w-[200px] p-2 flex-col overflow-hidden rounded-2xl bg-black/70 dark:bg-white/20 backdrop-blur-lg focus:outline-none"
|
||||||
/>
|
>
|
||||||
</Link>
|
<DropdownMenu.Item asChild>
|
||||||
|
<Link
|
||||||
|
to="/settings/"
|
||||||
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
|
>
|
||||||
|
<SettingsIcon className="size-5" />
|
||||||
|
Settings
|
||||||
|
</Link>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
<Logout />
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Portal>
|
||||||
|
</DropdownMenu.Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { LogoutIcon } from "@lume/icons";
|
||||||
import { useStorage } from "@lume/storage";
|
import { useStorage } from "@lume/storage";
|
||||||
import * as AlertDialog from "@radix-ui/react-alert-dialog";
|
import * as AlertDialog from "@radix-ui/react-alert-dialog";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
@@ -30,8 +31,9 @@ export function Logout() {
|
|||||||
<AlertDialog.Trigger asChild>
|
<AlertDialog.Trigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="inline-flex h-10 items-center rounded-lg px-2 text-sm font-medium text-white hover:bg-blue-600 focus:outline-none"
|
className="inline-flex items-center gap-2 px-3 text-sm font-medium rounded-lg h-9 text-white/50 hover:bg-black/10 hover:text-white focus:outline-none dark:text-white/50 dark:hover:bg-white/10 dark:hover:text-white"
|
||||||
>
|
>
|
||||||
|
<LogoutIcon className="size-5" />
|
||||||
Logout
|
Logout
|
||||||
</button>
|
</button>
|
||||||
</AlertDialog.Trigger>
|
</AlertDialog.Trigger>
|
||||||
|
|||||||
@@ -1,42 +1,27 @@
|
|||||||
import {
|
import {
|
||||||
AdvancedSettingsIcon,
|
AdvancedSettingsIcon,
|
||||||
InfoIcon,
|
InfoIcon,
|
||||||
NwcFilledIcon,
|
|
||||||
NwcIcon,
|
NwcIcon,
|
||||||
SecureIcon,
|
SecureIcon,
|
||||||
SettingsIcon,
|
SettingsIcon,
|
||||||
UserIcon,
|
UserIcon,
|
||||||
} from "@lume/icons";
|
} from "@lume/icons";
|
||||||
|
import { cn } from "@lume/utils";
|
||||||
import { NavLink, Outlet } from "react-router-dom";
|
import { NavLink, Outlet } from "react-router-dom";
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
|
|
||||||
export function SettingsLayout() {
|
export function SettingsLayout() {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full min-h-0 w-full flex-col gap-8 overflow-y-auto">
|
<div className="flex h-full min-h-0 w-full flex-col rounded-xl overflow-y-auto">
|
||||||
<div className="flex h-24 w-full items-center justify-center border-b border-neutral-200 px-2 dark:border-neutral-900">
|
<div className="flex h-24 shrink-0 w-full items-center justify-center px-2 bg-white/50 backdrop-blur-xl dark:bg-black/50">
|
||||||
<div className="flex items-center gap-0.5">
|
<div className="flex items-center gap-0.5">
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/settings/"
|
|
||||||
end
|
end
|
||||||
|
to="/settings/"
|
||||||
className={({ isActive }) =>
|
className={({ isActive }) =>
|
||||||
twMerge(
|
cn(
|
||||||
"flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900",
|
"flex w-20 shrink-0 flex-col gap-1 items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900",
|
||||||
isActive
|
isActive
|
||||||
? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900"
|
? "bg-black/10 dark:bg-white/10 text-blue-500 hover:bg-black/20 dark:hover:bg-white/20"
|
||||||
: "",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<UserIcon className="size-6" />
|
|
||||||
<p className="text-sm font-medium">User</p>
|
|
||||||
</NavLink>
|
|
||||||
<NavLink
|
|
||||||
to="/settings/general"
|
|
||||||
className={({ isActive }) =>
|
|
||||||
twMerge(
|
|
||||||
"flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900",
|
|
||||||
isActive
|
|
||||||
? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900"
|
|
||||||
: "",
|
: "",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -44,13 +29,28 @@ export function SettingsLayout() {
|
|||||||
<SettingsIcon className="size-6" />
|
<SettingsIcon className="size-6" />
|
||||||
<p className="text-sm font-medium">General</p>
|
<p className="text-sm font-medium">General</p>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
<NavLink
|
||||||
|
to="/settings/profile"
|
||||||
|
end
|
||||||
|
className={({ isActive }) =>
|
||||||
|
cn(
|
||||||
|
"flex w-20 shrink-0 flex-col gap-1 items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-black/10 dark:text-neutral-300 dark:hover:bg-white/10",
|
||||||
|
isActive
|
||||||
|
? "bg-black/10 dark:bg-white/10 text-blue-500 hover:bg-black/20 dark:hover:bg-white/20"
|
||||||
|
: "",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<UserIcon className="size-6" />
|
||||||
|
<p className="text-sm font-medium">User</p>
|
||||||
|
</NavLink>
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/settings/nwc"
|
to="/settings/nwc"
|
||||||
className={({ isActive }) =>
|
className={({ isActive }) =>
|
||||||
twMerge(
|
cn(
|
||||||
"flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900",
|
"flex w-20 shrink-0 flex-col gap-1 items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-black/10 dark:text-neutral-300 dark:hover:bg-white/10",
|
||||||
isActive
|
isActive
|
||||||
? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900"
|
? "bg-black/10 dark:bg-white/10 text-blue-500 hover:bg-black/20 dark:hover:bg-white/20"
|
||||||
: "",
|
: "",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -61,10 +61,10 @@ export function SettingsLayout() {
|
|||||||
<NavLink
|
<NavLink
|
||||||
to="/settings/backup"
|
to="/settings/backup"
|
||||||
className={({ isActive }) =>
|
className={({ isActive }) =>
|
||||||
twMerge(
|
cn(
|
||||||
"flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900",
|
"flex w-20 shrink-0 flex-col gap-1 items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-black/10 dark:text-neutral-300 dark:hover:bg-white/10",
|
||||||
isActive
|
isActive
|
||||||
? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900"
|
? "bg-black/10 dark:bg-white/10 text-blue-500 hover:bg-black/20 dark:hover:bg-white/20"
|
||||||
: "",
|
: "",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -75,10 +75,10 @@ export function SettingsLayout() {
|
|||||||
<NavLink
|
<NavLink
|
||||||
to="/settings/advanced"
|
to="/settings/advanced"
|
||||||
className={({ isActive }) =>
|
className={({ isActive }) =>
|
||||||
twMerge(
|
cn(
|
||||||
"flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900",
|
"flex w-20 shrink-0 flex-col gap-1 items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-black/10 dark:text-neutral-300 dark:hover:bg-white/10",
|
||||||
isActive
|
isActive
|
||||||
? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900"
|
? "bg-black/10 dark:bg-white/10 text-blue-500 hover:bg-black/20 dark:hover:bg-white/20"
|
||||||
: "",
|
: "",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -89,10 +89,10 @@ export function SettingsLayout() {
|
|||||||
<NavLink
|
<NavLink
|
||||||
to="/settings/about"
|
to="/settings/about"
|
||||||
className={({ isActive }) =>
|
className={({ isActive }) =>
|
||||||
twMerge(
|
cn(
|
||||||
"flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900",
|
"flex w-20 shrink-0 flex-col gap-1 items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-black/10 dark:text-neutral-300 dark:hover:bg-white/10",
|
||||||
isActive
|
isActive
|
||||||
? "bg-neutral-100 text-blue-500 hover:bg-neutral-100 dark:bg-neutral-950 dark:hover:bg-neutral-900"
|
? "bg-black/10 dark:bg-white/10 text-blue-500 hover:bg-black/20 dark:hover:bg-white/20"
|
||||||
: "",
|
: "",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,9 @@ export function SettingsLayout() {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Outlet />
|
<div className="flex-1 py-6 min-h-0 overflow-y-auto bg-white shadow-[rgba(50,_50,_105,_0.15)_0px_2px_5px_0px,_rgba(0,_0,_0,_0.05)_0px_1px_1px_0px] dark:bg-black dark:shadow-none dark:ring-1 dark:ring-white/10">
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export function Navigation() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center justify-center h-auto w-full text-black aspect-square rounded-xl hover:text-white dark:text-white",
|
"flex items-center justify-center h-auto w-full text-black aspect-square rounded-xl hover:text-white dark:text-white",
|
||||||
isEditorOpen
|
isEditorOpen
|
||||||
? "bg-blue-500"
|
? "bg-blue-500 text-white"
|
||||||
: "bg-black/5 hover:bg-blue-500 dark:bg-white/5 dark:hover:bg-blue-500",
|
: "bg-black/5 hover:bg-blue-500 dark:bg-white/5 dark:hover:bg-blue-500",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -114,7 +114,7 @@ export function Navigation() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<NavLink
|
<NavLink
|
||||||
to="/settings"
|
to="/settings/"
|
||||||
preventScrollReset={true}
|
preventScrollReset={true}
|
||||||
className="inline-flex flex-col items-center justify-center"
|
className="inline-flex flex-col items-center justify-center"
|
||||||
>
|
>
|
||||||
|
|||||||
480
pnpm-lock.yaml
generated
480
pnpm-lock.yaml
generated
@@ -270,25 +270,25 @@ importers:
|
|||||||
version: 0.15.0(@nostr-dev-kit/ndk@2.3.2)(nostr-fetch@0.15.0)
|
version: 0.15.0(@nostr-dev-kit/ndk@2.3.2)(nostr-fetch@0.15.0)
|
||||||
'@radix-ui/react-avatar':
|
'@radix-ui/react-avatar':
|
||||||
specifier: ^1.0.4
|
specifier: ^1.0.4
|
||||||
version: 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-collapsible':
|
'@radix-ui/react-collapsible':
|
||||||
specifier: ^1.0.3
|
specifier: ^1.0.3
|
||||||
version: 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-dialog':
|
'@radix-ui/react-dialog':
|
||||||
specifier: ^1.0.5
|
specifier: ^1.0.5
|
||||||
version: 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.5(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-dropdown-menu':
|
'@radix-ui/react-dropdown-menu':
|
||||||
specifier: ^2.0.6
|
specifier: ^2.0.6
|
||||||
version: 2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 2.0.6(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-hover-card':
|
'@radix-ui/react-hover-card':
|
||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.7(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-popover':
|
'@radix-ui/react-popover':
|
||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.7(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@radix-ui/react-tooltip':
|
'@radix-ui/react-tooltip':
|
||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
version: 1.0.7(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@tanstack/react-query':
|
'@tanstack/react-query':
|
||||||
specifier: ^5.17.12
|
specifier: ^5.17.12
|
||||||
version: 5.17.12(react@18.2.0)
|
version: 5.17.12(react@18.2.0)
|
||||||
@@ -1933,6 +1933,26 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-arrow@1.0.3(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-avatar@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==}
|
resolution: {integrity: sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1957,6 +1977,29 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-avatar@1.0.4(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==}
|
resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1985,6 +2028,33 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-collapsible@1.0.3(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2009,6 +2079,29 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-collection@1.0.3(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react@18.2.0):
|
/@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.48)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
|
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2071,6 +2164,39 @@ packages:
|
|||||||
react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
|
react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-dialog@1.0.5(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-portal': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-direction@1.0.1(@types/react@18.2.48)(react@18.2.0):
|
/@radix-ui/react-direction@1.0.1(@types/react@18.2.48)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==}
|
resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2110,6 +2236,30 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-dismissable-layer@1.0.5(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==}
|
resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2137,6 +2287,32 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-dropdown-menu@2.0.6(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-menu': 2.0.6(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react@18.2.0):
|
/@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.48)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==}
|
resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2174,6 +2350,28 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-focus-scope@1.0.4(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-hover-card@1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==}
|
resolution: {integrity: sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2203,6 +2401,34 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-hover-card@1.0.7(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-OcUN2FU0YpmajD/qkph3XzMcK/NmSk9hGWnjV68p6QiZMgILugusgQwnLSDs3oFSJYGKf3Y49zgFedhGh04k9A==}
|
||||||
|
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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-popper': 1.1.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-portal': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-id@1.0.1(@types/react@18.2.48)(react@18.2.0):
|
/@radix-ui/react-id@1.0.1(@types/react@18.2.48)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
|
resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2256,6 +2482,43 @@ packages:
|
|||||||
react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
|
react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-menu@2.0.6(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-collection': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-popper': 1.1.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-portal': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-roving-focus': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==}
|
resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2291,6 +2554,40 @@ packages:
|
|||||||
react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
|
react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-popover@1.0.7(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-focus-scope': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-popper': 1.1.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-portal': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==}
|
resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2321,6 +2618,35 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-popper@1.1.3(@types/react@18.2.48)(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.8
|
||||||
|
'@floating-ui/react-dom': 2.0.5(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-arrow': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-size': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/rect': 1.0.1
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==}
|
resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2342,6 +2668,26 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-portal@1.0.4(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
|
resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2364,6 +2710,27 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-presence@1.0.1(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
|
resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2385,6 +2752,26 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-primitive@1.0.3(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==}
|
resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2414,6 +2801,34 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-roving-focus@1.0.4(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-collection': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/react-select@2.0.0(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
/@radix-ui/react-select@2.0.0(@types/react-dom@18.2.18)(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==}
|
resolution: {integrity: sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2529,6 +2944,37 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-tooltip@1.0.7(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/primitive': 1.0.1
|
||||||
|
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-dismissable-layer': 1.0.5(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-popper': 1.1.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-portal': 1.0.4(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-presence': 1.0.1(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0)
|
||||||
|
'@radix-ui/react-visually-hidden': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
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.48)(react@18.2.0):
|
/@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.48)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
|
resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2652,6 +3098,26 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@radix-ui/react-visually-hidden@1.0.3(@types/react@18.2.48)(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.8
|
||||||
|
'@radix-ui/react-primitive': 1.0.3(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
'@types/react': 18.2.48
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@radix-ui/rect@1.0.1:
|
/@radix-ui/rect@1.0.1:
|
||||||
resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==}
|
resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user