bump next, use next-themes, remove geist icons and most of geist core
This commit is contained in:
parent
23b7343963
commit
fc79f7df4d
28 changed files with 313 additions and 695 deletions
|
@ -4,11 +4,10 @@ import { useState } from "react"
|
|||
import styles from "./auth.module.css"
|
||||
import Link from "../../components/link"
|
||||
import { signIn } from "next-auth/react"
|
||||
import { Github as GithubIcon } from "@geist-ui/icons"
|
||||
import Input from "@components/input"
|
||||
import Button from "@components/button"
|
||||
import Note from "@components/note"
|
||||
|
||||
import { GitHub } from 'react-feather'
|
||||
const Auth = ({
|
||||
page,
|
||||
requiresServerPassword
|
||||
|
@ -71,7 +70,7 @@ const Auth = ({
|
|||
style={{
|
||||
color: 'var(--fg)'
|
||||
}}
|
||||
iconLeft={<GithubIcon />}
|
||||
iconLeft={<GitHub />}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
signIn("github", {
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.contentWrapper {
|
||||
z-index: 1000;
|
||||
|
||||
}
|
||||
|
||||
.content {
|
||||
list-style: none;
|
||||
width: 100%;
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import Button from "@components/button"
|
||||
import { Popover } from "@components/popover"
|
||||
import ShiftBy from "@components/shift-by"
|
||||
import ChevronDown from "@geist-ui/icons/chevronDown"
|
||||
import CodeIcon from "@geist-ui/icons/fileFunction"
|
||||
import FileIcon from "@geist-ui/icons/fileText"
|
||||
import { codeFileExtensions } from "@lib/constants"
|
||||
import clsx from "clsx"
|
||||
import type { File } from "lib/server/prisma"
|
||||
import styles from "./dropdown.module.css"
|
||||
import buttonStyles from "@components/button/button.module.css"
|
||||
import { ChevronDown, Code, File as FileIcon } from "react-feather"
|
||||
|
||||
type Item = File & {
|
||||
icon: JSX.Element
|
||||
|
@ -20,7 +18,7 @@ const FileDropdown = ({ files }: { files: File[] }) => {
|
|||
if (codeFileExtensions.includes(extension || "")) {
|
||||
return {
|
||||
...file,
|
||||
icon: <CodeIcon />
|
||||
icon: <Code />
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
|
@ -60,7 +58,7 @@ const FileDropdown = ({ files }: { files: File[] }) => {
|
|||
Jump to {files.length} {files.length === 1 ? "file" : "files"}
|
||||
</span>
|
||||
</Popover.Trigger>
|
||||
<Popover.Content>{content}</Popover.Content>
|
||||
<Popover.Content className={styles.contentWrapper}>{content}</Popover.Content>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import Bold from "@geist-ui/icons/bold"
|
||||
import Italic from "@geist-ui/icons/italic"
|
||||
import Link from "@geist-ui/icons/link"
|
||||
import Code from "@geist-ui/icons/code"
|
||||
import List from "@geist-ui/icons/list"
|
||||
|
||||
import ImageIcon from "@geist-ui/icons/image"
|
||||
import { Bold, Code, Image as ImageIcon, Italic, Link, List } from "react-feather"
|
||||
import { RefObject, useMemo } from "react"
|
||||
import styles from "./formatting-icons.module.css"
|
||||
import { TextareaMarkdownRef } from "textarea-markdown-editor"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { ChangeEvent, memo, useCallback } from "react"
|
||||
import { ChangeEvent, useCallback } from "react"
|
||||
import styles from "./document.module.css"
|
||||
import Trash from "@geist-ui/icons/trash"
|
||||
import Button from "@components/button"
|
||||
import Input from "@components/input"
|
||||
import DocumentTabs from "app/(posts)/components/tabs"
|
||||
import { Trash } from "react-feather"
|
||||
|
||||
type Props = {
|
||||
title?: string
|
||||
|
|
|
@ -5,9 +5,6 @@ import DocumentComponent from "./view-document"
|
|||
import styles from "./post-page.module.css"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import Archive from "@geist-ui/icons/archive"
|
||||
import Edit from "@geist-ui/icons/edit"
|
||||
import Parent from "@geist-ui/icons/arrowUpCircle"
|
||||
import FileDropdown from "app/(posts)/components/file-dropdown"
|
||||
import ScrollToTop from "@components/scroll-to-top"
|
||||
import { useRouter } from "next/navigation"
|
||||
|
@ -18,6 +15,7 @@ import VisibilityControl from "@components/badges/visibility-control"
|
|||
import { File, PostWithFilesAndAuthor } from "@lib/server/prisma"
|
||||
import ButtonGroup from "@components/button-group"
|
||||
import Button from "@components/button"
|
||||
import { Archive, ArrowUpCircle, Edit } from "react-feather"
|
||||
|
||||
type Props = {
|
||||
post: string | PostWithFilesAndAuthor
|
||||
|
@ -108,7 +106,7 @@ const PostPage = ({ post: initialPost, isProtected, isAuthor }: Props) => {
|
|||
Edit a Copy
|
||||
</Button>
|
||||
{post.parentId && (
|
||||
<Button iconLeft={<Parent />} onClick={viewParentClick}>
|
||||
<Button iconLeft={<ArrowUpCircle />} onClick={viewParentClick}>
|
||||
View Parent
|
||||
</Button>
|
||||
)}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { memo } from "react"
|
||||
import styles from "./document.module.css"
|
||||
import Download from "@geist-ui/icons/download"
|
||||
import ExternalLink from "@geist-ui/icons/externalLink"
|
||||
import Skeleton from "@components/skeleton"
|
||||
import Link from "next/link"
|
||||
|
||||
|
@ -10,6 +8,7 @@ import Button from "@components/button"
|
|||
import ButtonGroup from "@components/button-group"
|
||||
import DocumentTabs from "app/(posts)/components/tabs"
|
||||
import Input from "@components/input"
|
||||
import { Download, ExternalLink } from "react-feather"
|
||||
|
||||
// import Link from "next/link"
|
||||
type Props = {
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
import { Popover, Button } from "@geist-ui/core/dist"
|
||||
import { MoreVertical } from "@geist-ui/icons"
|
||||
|
||||
type Action = {
|
||||
title: string
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
const ActionDropdown = ({
|
||||
title = "Actions",
|
||||
actions,
|
||||
showTitle = false
|
||||
}: {
|
||||
title?: string
|
||||
showTitle?: boolean
|
||||
actions: Action[]
|
||||
}) => {
|
||||
return (
|
||||
<Popover
|
||||
title={title}
|
||||
content={
|
||||
<>
|
||||
{showTitle && <Popover.Item title>{title}</Popover.Item>}
|
||||
{actions.map((action) => (
|
||||
<Popover.Item onClick={action.onClick} key={action.title}>
|
||||
{action.title}
|
||||
</Popover.Item>
|
||||
))}
|
||||
</>
|
||||
}
|
||||
hideArrow
|
||||
>
|
||||
<Button iconRight={<MoreVertical />} auto></Button>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
export default ActionDropdown
|
|
@ -1,25 +0,0 @@
|
|||
.adminWrapper table {
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border: 1px solid var(--gray);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--gap-half);
|
||||
}
|
||||
|
||||
.adminWrapper table th {
|
||||
text-align: left;
|
||||
background: var(--gray-light);
|
||||
color: var(--gray-dark);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.postModal details {
|
||||
border-radius: var(--radius);
|
||||
padding: var(--gap);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
.postModal summary {
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
"use client"
|
||||
import SettingsGroup from "@components/settings-group"
|
||||
import { Fieldset } from "@geist-ui/core/dist"
|
||||
import byteToMB from "@lib/byte-to-mb"
|
||||
import { PostWithFiles } from "@lib/server/prisma"
|
||||
import Table from "rc-table"
|
||||
import { useMemo } from "react"
|
||||
import ActionDropdown from "./action-dropdown"
|
||||
|
||||
const PostTable = ({ posts }: { posts: PostWithFiles[] }) => {
|
||||
const tablePosts = useMemo(
|
||||
() =>
|
||||
posts?.map((post) => {
|
||||
return {
|
||||
id: post.id,
|
||||
title: post.title,
|
||||
files: post.files?.length || 0,
|
||||
createdAt: `${new Date(
|
||||
post.createdAt
|
||||
).toLocaleDateString()} ${new Date(
|
||||
post.createdAt
|
||||
).toLocaleTimeString()}`,
|
||||
visibility: post.visibility,
|
||||
size: post.files
|
||||
? byteToMB(
|
||||
post.files.reduce((acc, file) => acc + file.html.length, 0)
|
||||
)
|
||||
: 0,
|
||||
actions: ""
|
||||
}
|
||||
}),
|
||||
[posts]
|
||||
)
|
||||
|
||||
const deletePost = async (/* id: string */) => {
|
||||
return alert("Not implemented")
|
||||
|
||||
// const confirm = window.confirm("Are you sure you want to delete this post?")
|
||||
// if (!confirm) return
|
||||
// const res = await adminFetcher(`/posts/${id}`, {
|
||||
// method: "DELETE",
|
||||
// })
|
||||
|
||||
// const json = await res.json()
|
||||
|
||||
// if (res.status === 200) {
|
||||
// setToast({
|
||||
// text: "Post deleted",
|
||||
// type: "success"
|
||||
// })
|
||||
|
||||
// setPosts((posts) => {
|
||||
// const newPosts = posts?.filter((post) => post.id !== id)
|
||||
// return newPosts
|
||||
// })
|
||||
// } else {
|
||||
// setToast({
|
||||
// text: json.error || "Something went wrong",
|
||||
// type: "error"
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
||||
const tableColumns = [
|
||||
{
|
||||
title: "Title",
|
||||
dataIndex: "title",
|
||||
key: "title",
|
||||
width: 50
|
||||
},
|
||||
{
|
||||
title: "Files",
|
||||
dataIndex: "files",
|
||||
key: "files",
|
||||
width: 10
|
||||
},
|
||||
{
|
||||
title: "Created",
|
||||
dataIndex: "createdAt",
|
||||
key: "createdAt",
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: "Visibility",
|
||||
dataIndex: "visibility",
|
||||
key: "visibility",
|
||||
width: 50
|
||||
},
|
||||
{
|
||||
title: "Size (MB)",
|
||||
dataIndex: "size",
|
||||
key: "size",
|
||||
width: 10
|
||||
},
|
||||
{
|
||||
title: "Actions",
|
||||
dataIndex: "",
|
||||
key: "actions",
|
||||
width: 50,
|
||||
render() {
|
||||
return (
|
||||
<ActionDropdown
|
||||
title="Actions"
|
||||
actions={[
|
||||
{
|
||||
title: "Delete",
|
||||
onClick: () => deletePost()
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<SettingsGroup title="Posts">
|
||||
{!posts && <Fieldset.Subtitle>Loading...</Fieldset.Subtitle>}
|
||||
{posts && (
|
||||
<Fieldset.Subtitle>
|
||||
<h5>{posts.length} posts</h5>
|
||||
</Fieldset.Subtitle>
|
||||
)}
|
||||
{posts && <Table columns={tableColumns} data={tablePosts} />}
|
||||
</SettingsGroup>
|
||||
)
|
||||
}
|
||||
|
||||
export default PostTable
|
|
@ -1,157 +0,0 @@
|
|||
"use client"
|
||||
import { Fieldset } from "@geist-ui/core/dist"
|
||||
import Table from "rc-table"
|
||||
import ActionDropdown from "./action-dropdown"
|
||||
import SettingsGroup from "@components/settings-group"
|
||||
import type { User, UserWithPosts } from "@lib/server/prisma"
|
||||
import { useState } from "react"
|
||||
import { useToasts } from "@components/toasts"
|
||||
|
||||
const UserTable = ({ users: initial }: { users: UserWithPosts[] }) => {
|
||||
const [users, setUsers] = useState(initial)
|
||||
const { setToast } = useToasts()
|
||||
|
||||
const toggleRole = async (id: string, role: "admin" | "user") => {
|
||||
const res = await fetch("/api/admin?action=toggle-role", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
userId: id,
|
||||
role
|
||||
})
|
||||
})
|
||||
|
||||
if (res.status === 200) {
|
||||
setToast({
|
||||
message: "Role updated",
|
||||
type: "success"
|
||||
})
|
||||
|
||||
setUsers((users) => {
|
||||
const newUsers = users?.map((user) => {
|
||||
if (user.id === id) {
|
||||
return {
|
||||
...user,
|
||||
role
|
||||
}
|
||||
}
|
||||
return user
|
||||
})
|
||||
return newUsers
|
||||
})
|
||||
} else {
|
||||
setToast({
|
||||
message: "Something went wrong",
|
||||
type: "error"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const deleteUser = async (id: string) => {
|
||||
const confirm = window.confirm("Are you sure you want to delete this user?")
|
||||
if (!confirm) return
|
||||
// const res = await adminFetcher(`/users/${id}`, {
|
||||
// method: "DELETE"
|
||||
// })
|
||||
const res = await fetch("/api/admin?action=delete-user", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
userId: id
|
||||
})
|
||||
})
|
||||
|
||||
setUsers((users) => {
|
||||
const newUsers = users?.filter((user) => user.id !== id)
|
||||
return newUsers
|
||||
})
|
||||
|
||||
if (res.status === 200) {
|
||||
setToast({
|
||||
message: "User deleted",
|
||||
type: "success"
|
||||
})
|
||||
} else {
|
||||
setToast({
|
||||
message: "Something went wrong",
|
||||
type: "error"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const tableUsers = users?.map((user) => {
|
||||
return {
|
||||
id: user.id,
|
||||
displayName: user.displayName,
|
||||
posts: user.posts?.length || 0,
|
||||
createdAt: `${new Date(user.createdAt).toLocaleDateString()} ${new Date(
|
||||
user.createdAt
|
||||
).toLocaleTimeString()}`,
|
||||
role: user.role,
|
||||
actions: ""
|
||||
}
|
||||
})
|
||||
|
||||
const usernameColumns = [
|
||||
{
|
||||
title: "Name",
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
width: 50
|
||||
},
|
||||
{
|
||||
title: "Posts",
|
||||
dataIndex: "posts",
|
||||
key: "posts",
|
||||
width: 10
|
||||
},
|
||||
{
|
||||
title: "Created",
|
||||
dataIndex: "createdAt",
|
||||
key: "createdAt",
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: "Role",
|
||||
dataIndex: "role",
|
||||
key: "role",
|
||||
width: 50
|
||||
},
|
||||
{
|
||||
title: "Actions",
|
||||
dataIndex: "",
|
||||
key: "actions",
|
||||
width: 50,
|
||||
render(user: User) {
|
||||
return (
|
||||
<ActionDropdown
|
||||
title="Actions"
|
||||
actions={[
|
||||
{
|
||||
title: user.role === "admin" ? "Change role" : "Make admin",
|
||||
onClick: () =>
|
||||
toggleRole(user.id, user.role === "admin" ? "user" : "admin")
|
||||
},
|
||||
{
|
||||
title: "Delete",
|
||||
onClick: () => deleteUser(user.id)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<SettingsGroup title="Users">
|
||||
{!users && <Fieldset.Subtitle>Loading...</Fieldset.Subtitle>}
|
||||
{users && (
|
||||
<Fieldset.Subtitle>
|
||||
<h5>{users.length} users</h5>
|
||||
</Fieldset.Subtitle>
|
||||
)}
|
||||
{users && <Table columns={usernameColumns} data={tableUsers} />}
|
||||
</SettingsGroup>
|
||||
)
|
||||
}
|
||||
|
||||
export default UserTable
|
|
@ -1,39 +0,0 @@
|
|||
import { getAllPosts, getAllUsers } from "@lib/server/prisma"
|
||||
import { getCurrentUser } from "@lib/server/session"
|
||||
import { notFound } from "next/navigation"
|
||||
import styles from "./components/admin.module.css"
|
||||
import PostTable from "./components/post-table"
|
||||
import UserTable from "./components/user-table"
|
||||
|
||||
const AdminPage = async () => {
|
||||
const user = await getCurrentUser()
|
||||
if (!user) {
|
||||
return notFound()
|
||||
}
|
||||
|
||||
if (user.role !== "admin") {
|
||||
return notFound()
|
||||
}
|
||||
|
||||
const posts = await getAllPosts()
|
||||
const users = await getAllUsers()
|
||||
|
||||
return (
|
||||
<div className={styles.adminWrapper}>
|
||||
<h2>Administration</h2>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
gap: "var(--gap)"
|
||||
}}
|
||||
>
|
||||
<UserTable users={users} />
|
||||
<PostTable posts={posts} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AdminPage
|
|
@ -1,9 +1,8 @@
|
|||
import Button from "@components/button"
|
||||
import React, { useCallback, useEffect } from "react"
|
||||
import { useState } from "react"
|
||||
import React from "react"
|
||||
import styles from "./dropdown.module.css"
|
||||
import DownIcon from "@geist-ui/icons/arrowDown"
|
||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
|
||||
import { ArrowDown } from "react-feather"
|
||||
type Props = {
|
||||
type?: "primary" | "secondary"
|
||||
loading?: boolean
|
||||
|
@ -35,7 +34,7 @@ const ButtonDropdown: React.FC<
|
|||
asChild
|
||||
>
|
||||
<Button
|
||||
iconLeft={<DownIcon />}
|
||||
iconLeft={<ArrowDown />}
|
||||
type={type}
|
||||
className={styles.icon}
|
||||
/>
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 70px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.mobile button {
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
"use client"
|
||||
|
||||
import { useBodyScroll, useMediaQuery } from "@geist-ui/core/dist"
|
||||
import { useBodyScroll, useMediaQuery } from "@geist-ui/core/dist"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import styles from "./header.module.css"
|
||||
|
||||
import HomeIcon from "@geist-ui/icons/home"
|
||||
import MenuIcon from "@geist-ui/icons/menu"
|
||||
import GitHubIcon from "@geist-ui/icons/github"
|
||||
import SignOutIcon from "@geist-ui/icons/userX"
|
||||
import SignInIcon from "@geist-ui/icons/user"
|
||||
import SignUpIcon from "@geist-ui/icons/userPlus"
|
||||
import NewIcon from "@geist-ui/icons/plusCircle"
|
||||
import YourIcon from "@geist-ui/icons/list"
|
||||
import MoonIcon from "@geist-ui/icons/moon"
|
||||
import SettingsIcon from "@geist-ui/icons/settings"
|
||||
import SunIcon from "@geist-ui/icons/sun"
|
||||
// import useUserData from "@lib/hooks/use-user-data"
|
||||
import Link from "next/link"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { signOut } from "next-auth/react"
|
||||
import { useTheme } from "@components/theme/ThemeClientContextProvider"
|
||||
import Button from "@components/button"
|
||||
import clsx from "clsx"
|
||||
import { useTheme } from "@wits/next-themes"
|
||||
import {
|
||||
GitHub,
|
||||
Home,
|
||||
Menu,
|
||||
Moon,
|
||||
PlusCircle,
|
||||
Settings,
|
||||
Sun,
|
||||
User,
|
||||
UserPlus,
|
||||
UserX
|
||||
} from "react-feather"
|
||||
|
||||
type Tab = {
|
||||
name: string
|
||||
|
@ -55,7 +55,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
{
|
||||
name: isMobile ? "GitHub" : "",
|
||||
href: "https://github.com/maxleiter/drift",
|
||||
icon: <GitHubIcon />,
|
||||
icon: <GitHub />,
|
||||
value: "github"
|
||||
},
|
||||
{
|
||||
|
@ -64,7 +64,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
if (typeof window !== "undefined")
|
||||
setTheme(theme === "light" ? "dark" : "light")
|
||||
},
|
||||
icon: theme === "light" ? <MoonIcon /> : <SunIcon />,
|
||||
icon: theme === "light" ? <Moon /> : <Sun />,
|
||||
value: "theme"
|
||||
}
|
||||
]
|
||||
|
@ -72,7 +72,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
if (isAdmin) {
|
||||
defaultPages.push({
|
||||
name: "Admin",
|
||||
icon: <SettingsIcon />,
|
||||
icon: <Settings />,
|
||||
value: "admin",
|
||||
href: "/admin"
|
||||
})
|
||||
|
@ -82,29 +82,30 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
return [
|
||||
{
|
||||
name: "New",
|
||||
icon: <NewIcon />,
|
||||
icon: <PlusCircle />,
|
||||
value: "new",
|
||||
href: "/new"
|
||||
},
|
||||
{
|
||||
name: "Yours",
|
||||
icon: <YourIcon />,
|
||||
icon: <User />,
|
||||
value: "yours",
|
||||
href: "/mine"
|
||||
},
|
||||
{
|
||||
name: "Settings",
|
||||
icon: <SettingsIcon />,
|
||||
icon: <Settings />,
|
||||
value: "settings",
|
||||
href: "/settings"
|
||||
},
|
||||
{
|
||||
name: "Sign Out",
|
||||
icon: <SignOutIcon />,
|
||||
icon: <UserX />,
|
||||
value: "signout",
|
||||
onClick: () => signOut({
|
||||
callbackUrl: "/",
|
||||
})
|
||||
onClick: () =>
|
||||
signOut({
|
||||
callbackUrl: "/"
|
||||
})
|
||||
},
|
||||
...defaultPages
|
||||
]
|
||||
|
@ -112,19 +113,19 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
return [
|
||||
{
|
||||
name: "Home",
|
||||
icon: <HomeIcon />,
|
||||
icon: <Home />,
|
||||
value: "home",
|
||||
href: "/"
|
||||
},
|
||||
{
|
||||
name: "Sign in",
|
||||
icon: <SignInIcon />,
|
||||
icon: <User />,
|
||||
value: "signin",
|
||||
href: "/signin"
|
||||
},
|
||||
{
|
||||
name: "Sign up",
|
||||
icon: <SignUpIcon />,
|
||||
icon: <UserPlus />,
|
||||
value: "signup",
|
||||
href: "/signup"
|
||||
},
|
||||
|
@ -180,7 +181,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
</div>
|
||||
<div className={styles.controls}>
|
||||
<Button onClick={() => setExpanded(!expanded)} aria-label="Menu">
|
||||
<MenuIcon />
|
||||
<Menu />
|
||||
</Button>
|
||||
</div>
|
||||
{/* setExpanded should occur elsewhere; we don't want to close if they change themes */}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
color: var(--fg);
|
||||
margin: 0;
|
||||
padding: var(--gap);
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { Modal, Note, Spacer, Input } from "@geist-ui/core/dist"
|
||||
import Button from "@components/button"
|
||||
import Input from "@components/input"
|
||||
import Note from "@components/note"
|
||||
import * as Dialog from "@radix-ui/react-dialog"
|
||||
import { useState } from "react"
|
||||
import styles from "./modal.module.css"
|
||||
|
||||
type Props = {
|
||||
creating: boolean
|
||||
|
@ -34,47 +38,60 @@ const PasswordModal = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
{/* TODO: investigate disableBackdropClick not updating state? */}
|
||||
|
||||
{
|
||||
<Modal visible={isOpen} disableBackdropClick={false}>
|
||||
<Modal.Title>Enter a password</Modal.Title>
|
||||
<Modal.Content>
|
||||
{!error && creating && (
|
||||
<Note type="warning" label="Warning">
|
||||
This doesn't protect your post from the server
|
||||
administrator.
|
||||
</Note>
|
||||
)}
|
||||
{error && (
|
||||
<Note type="error" label="Error">
|
||||
{error}
|
||||
</Note>
|
||||
)}
|
||||
<Spacer />
|
||||
<Input
|
||||
width={"100%"}
|
||||
label="Password"
|
||||
marginBottom={1}
|
||||
htmlType="password"
|
||||
placeholder="Password"
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
{creating && (
|
||||
<Input
|
||||
width={"100%"}
|
||||
label="Confirm"
|
||||
htmlType="password"
|
||||
placeholder="Confirm Password"
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
/>
|
||||
)}
|
||||
</Modal.Content>
|
||||
<Modal.Action passive onClick={onClose}>
|
||||
Cancel
|
||||
</Modal.Action>
|
||||
<Modal.Action onClick={onSubmit}>Submit</Modal.Action>
|
||||
</Modal>
|
||||
<Dialog.Root
|
||||
open={isOpen}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) onClose()
|
||||
}}
|
||||
>
|
||||
{/* <Dialog.Trigger asChild>Enter a password</Dialog.Trigger> */}
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay className={styles.overlay} />
|
||||
<Dialog.Content
|
||||
className={styles.content}
|
||||
onEscapeKeyDown={onClose}
|
||||
>
|
||||
<Dialog.Title>
|
||||
{creating ? "Create a password" : "Enter password"}
|
||||
</Dialog.Title>
|
||||
<Dialog.Description>
|
||||
{creating
|
||||
? "Enter a password to protect your post"
|
||||
: "Enter the password to access the post"}
|
||||
</Dialog.Description>
|
||||
<fieldset className={styles.fieldset}>
|
||||
{error && <Note type="error">{error}</Note>}
|
||||
<Input
|
||||
width={"100%"}
|
||||
label="Password"
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
onChange={(e) => setPassword(e.currentTarget.value)}
|
||||
/>
|
||||
{creating && (
|
||||
<Input
|
||||
width={"100%"}
|
||||
label="Confirm"
|
||||
type="password"
|
||||
placeholder="Confirm Password"
|
||||
onChange={(e) => setConfirmPassword(e.currentTarget.value)}
|
||||
/>
|
||||
)}
|
||||
{!error && creating && (
|
||||
<Note type="warning">
|
||||
This doesn't protect your post from the server
|
||||
administrator.
|
||||
</Note>
|
||||
)}
|
||||
</fieldset>
|
||||
<Dialog.Close className={styles.close}>
|
||||
<Button onClick={onSubmit}>Submit</Button>
|
||||
<Button>Cancel</Button>
|
||||
</Dialog.Close>
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
}
|
||||
</>
|
||||
)
|
||||
|
|
66
client/app/components/password-modal/modal.module.css
Normal file
66
client/app/components/password-modal/modal.module.css
Normal file
|
@ -0,0 +1,66 @@
|
|||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: var(--bg);
|
||||
border-radius: var(--radius);
|
||||
box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 90vw;
|
||||
max-width: 450px;
|
||||
max-height: 85vh;
|
||||
padding: 25px;
|
||||
animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
z-index: 2;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.fieldset {
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap-quarter);
|
||||
margin-bottom: var(--gap-half);
|
||||
}
|
||||
|
||||
.content:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.close {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@keyframes overlayShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes contentShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -48%) scale(0.96);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
import VisibilityBadge from "../badges/visibility-badge"
|
||||
import FadeIn from "@components/fade-in"
|
||||
import Trash from "@geist-ui/icons/trash"
|
||||
import ExpirationBadge from "@components/badges/expiration-badge"
|
||||
import CreatedAgoBadge from "@components/badges/created-ago-badge"
|
||||
import Edit from "@geist-ui/icons/edit"
|
||||
import { useRouter } from "next/navigation"
|
||||
import Parent from "@geist-ui/icons/arrowUpCircle"
|
||||
import styles from "./list-item.module.css"
|
||||
import Link from "@components/link"
|
||||
import type { PostWithFiles } from "@lib/server/prisma"
|
||||
|
@ -14,6 +11,7 @@ import Tooltip from "@components/tooltip"
|
|||
import Badge from "@components/badges/badge"
|
||||
import Card from "@components/card"
|
||||
import Button from "@components/button"
|
||||
import { ArrowUpCircle, Edit, Trash } from "react-feather"
|
||||
|
||||
// TODO: isOwner should default to false so this can be used generically
|
||||
const ListItem = ({
|
||||
|
@ -55,7 +53,7 @@ const ListItem = ({
|
|||
{post.parentId && (
|
||||
<Tooltip content={"View parent"}>
|
||||
<Button
|
||||
iconRight={<Parent />}
|
||||
iconRight={<ArrowUpCircle />}
|
||||
onClick={viewParentClick}
|
||||
height={38}
|
||||
/>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Button from "@components/button"
|
||||
import Tooltip from "@components/tooltip"
|
||||
import ChevronUp from "@geist-ui/icons/chevronUp"
|
||||
import { useEffect, useState } from "react"
|
||||
import { ChevronUp } from "react-feather"
|
||||
import styles from "./scroll.module.css"
|
||||
|
||||
const ScrollToTop = () => {
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import {
|
||||
FunctionComponent,
|
||||
PropsWithChildren,
|
||||
useCallback,
|
||||
useMemo
|
||||
} from "react"
|
||||
import React, { useContext, useState, createContext } from "react"
|
||||
import { DEFAULT_THEME, Theme, THEME_COOKIE_NAME } from "./theme"
|
||||
import { setCookie } from "cookies-next"
|
||||
|
||||
interface UseThemeProps {
|
||||
theme: Theme
|
||||
setTheme: (theme: Theme) => void
|
||||
}
|
||||
|
||||
const ThemeContext = createContext<UseThemeProps | null>(null)
|
||||
|
||||
export function useTheme(): {
|
||||
theme: Theme
|
||||
setTheme: (theme: Theme) => void
|
||||
} {
|
||||
return (
|
||||
useContext(ThemeContext) || {
|
||||
theme: DEFAULT_THEME,
|
||||
setTheme: () => {}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
interface Props extends PropsWithChildren<{}> {
|
||||
defaultTheme: Theme
|
||||
}
|
||||
|
||||
const ThemeClientContextProvider: FunctionComponent<Props> = ({
|
||||
defaultTheme,
|
||||
children
|
||||
}) => {
|
||||
const [theme, setThemeState] = useState<Theme>(defaultTheme)
|
||||
const setCookieAndDocument = useCallback(
|
||||
(theme: Theme) => {
|
||||
setThemeState(theme)
|
||||
setCookie(THEME_COOKIE_NAME, theme)
|
||||
document.documentElement.setAttribute("data-theme", theme)
|
||||
},
|
||||
[setThemeState]
|
||||
)
|
||||
|
||||
const setTheme = useCallback(
|
||||
(theme: Theme) => {
|
||||
setCookieAndDocument(theme)
|
||||
},
|
||||
[setCookieAndDocument]
|
||||
)
|
||||
|
||||
const value = useMemo(() => ({ theme, setTheme }), [theme, setTheme])
|
||||
|
||||
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
|
||||
}
|
||||
|
||||
export default ThemeClientContextProvider
|
|
@ -1,28 +0,0 @@
|
|||
import type { FunctionComponent, PropsWithChildren } from "react"
|
||||
import ThemeClientContextProvider from "./ThemeClientContextProvider"
|
||||
import ThemeServerContextProvider, {
|
||||
useServerTheme
|
||||
} from "./ThemeServerContextProvider"
|
||||
|
||||
const ThemeProviderWrapper: FunctionComponent<PropsWithChildren<{}>> = ({
|
||||
children
|
||||
}) => {
|
||||
const theme = useServerTheme()
|
||||
return (
|
||||
<ThemeClientContextProvider defaultTheme={theme}>
|
||||
{children}
|
||||
</ThemeClientContextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
const ThemeProvider: FunctionComponent<PropsWithChildren<{}>> = ({
|
||||
children
|
||||
}) => {
|
||||
return (
|
||||
<ThemeServerContextProvider>
|
||||
<ThemeProviderWrapper>{children}</ThemeProviderWrapper>
|
||||
</ThemeServerContextProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default ThemeProvider
|
|
@ -1,22 +0,0 @@
|
|||
import type { FunctionComponent, PropsWithChildren } from "react"
|
||||
// @ts-ignore -- createServerContext is not in @types/react atm
|
||||
import { useContext, createServerContext } from "react"
|
||||
import { cookies } from "next/headers"
|
||||
import { Theme, THEME_COOKIE_NAME } from "./theme"
|
||||
import { DEFAULT_THEME } from "./theme"
|
||||
|
||||
const ThemeContext = createServerContext<Theme | null>(null)
|
||||
|
||||
export function useServerTheme(): Theme {
|
||||
return useContext(ThemeContext)
|
||||
}
|
||||
|
||||
const ThemeServerContextProvider: FunctionComponent<PropsWithChildren<{}>> = ({
|
||||
children
|
||||
}) => {
|
||||
const cookiesList = cookies()
|
||||
const theme = cookiesList.get(THEME_COOKIE_NAME)?.value ?? DEFAULT_THEME
|
||||
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
|
||||
}
|
||||
|
||||
export default ThemeServerContextProvider
|
|
@ -1,5 +0,0 @@
|
|||
export type Theme = "light" | "dark"
|
||||
|
||||
export const DEFAULT_THEME: Theme = "light"
|
||||
|
||||
export const THEME_COOKIE_NAME = "drift-theme"
|
|
@ -2,8 +2,7 @@ import "@styles/globals.css"
|
|||
import { LayoutWrapper } from "./root-layout-wrapper"
|
||||
import styles from "@styles/Home.module.css"
|
||||
import { getSession } from "@lib/server/session"
|
||||
import ThemeProvider from "@components/theme/ThemeProvider"
|
||||
import { THEME_COOKIE_NAME } from "@components/theme/theme"
|
||||
import { ServerThemeProvider } from "@wits/next-themes"
|
||||
|
||||
interface RootLayoutProps {
|
||||
children: React.ReactNode
|
||||
|
@ -13,23 +12,16 @@ export default async function RootLayout({ children }: RootLayoutProps) {
|
|||
// TODO: this opts out of SSG
|
||||
const session = await getSession()
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
(function() {
|
||||
var theme = document.cookie
|
||||
.split('; ')
|
||||
.find(row => row.startsWith('${THEME_COOKIE_NAME}='))
|
||||
.split('=')[1];
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
})();
|
||||
`
|
||||
}}
|
||||
/>
|
||||
</head>
|
||||
<ThemeProvider>
|
||||
<ServerThemeProvider
|
||||
enableSystem={true}
|
||||
defaultTheme="dark"
|
||||
disableTransitionOnChange
|
||||
cookieName={"drift-theme"}
|
||||
attribute="data-theme"
|
||||
enableColorScheme={true}
|
||||
>
|
||||
<html lang="en">
|
||||
<head />
|
||||
<body className={styles.main}>
|
||||
<LayoutWrapper
|
||||
signedIn={Boolean(session?.user)}
|
||||
|
@ -38,7 +30,7 @@ export default async function RootLayout({ children }: RootLayoutProps) {
|
|||
{children}
|
||||
</LayoutWrapper>
|
||||
</body>
|
||||
</ThemeProvider>
|
||||
</html>
|
||||
</html>
|
||||
</ServerThemeProvider>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import Header from "@components/header"
|
|||
import Page from "@components/page"
|
||||
import { Toasts } from "@components/toasts"
|
||||
import * as RadixTooltip from "@radix-ui/react-tooltip"
|
||||
import { ThemeProvider } from "@wits/next-themes"
|
||||
import { Toaster } from "react-hot-toast"
|
||||
|
||||
export function LayoutWrapper({
|
||||
|
@ -19,7 +20,16 @@ export function LayoutWrapper({
|
|||
<RadixTooltip.Provider delayDuration={200}>
|
||||
<Toasts />
|
||||
<Page>
|
||||
<Header isAdmin={isAdmin} signedIn={signedIn} />
|
||||
<ThemeProvider
|
||||
enableSystem={true}
|
||||
defaultTheme="dark"
|
||||
disableTransitionOnChange
|
||||
cookieName={"drift-theme"}
|
||||
attribute="data-theme"
|
||||
enableColorScheme={true}
|
||||
>
|
||||
<Header isAdmin={isAdmin} signedIn={signedIn} />
|
||||
</ThemeProvider>
|
||||
{children}
|
||||
</Page>
|
||||
</RadixTooltip.Provider>
|
||||
|
|
|
@ -14,30 +14,32 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@geist-ui/core": "^2.3.8",
|
||||
"@geist-ui/icons": "1.0.2",
|
||||
"@next-auth/prisma-adapter": "^1.0.5",
|
||||
"@next/eslint-plugin-next": "13.0.5-canary.3",
|
||||
"@prisma/client": "^4.6.1",
|
||||
"@radix-ui/react-dialog": "^1.0.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.1",
|
||||
"@radix-ui/react-popover": "^1.0.2",
|
||||
"@radix-ui/react-tabs": "^1.0.1",
|
||||
"@radix-ui/react-tooltip": "^1.0.2",
|
||||
"@wcj/markdown-to-html": "^2.1.2",
|
||||
"@wits/next-themes": "^0.2.12",
|
||||
"bcrypt": "^5.1.0",
|
||||
"client-zip": "2.2.1",
|
||||
"cookies-next": "^2.1.1",
|
||||
"jest": "^29.3.1",
|
||||
"next": "13.0.6-canary.1",
|
||||
"next": "13.0.6-canary.2",
|
||||
"next-auth": "^4.17.0",
|
||||
"prisma": "^4.6.1",
|
||||
"rc-table": "7.24.1",
|
||||
"react": "18.2.0",
|
||||
"react-datepicker": "4.8.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-dropzone": "14.2.3",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-hot-toast": "^2.4.0",
|
||||
"server-only": "^0.0.1",
|
||||
"swr": "1.3.0",
|
||||
"prisma": "^4.6.1",
|
||||
"textarea-markdown-editor": "0.1.13",
|
||||
"ts-jest": "^29.0.3"
|
||||
},
|
||||
|
|
|
@ -2,11 +2,11 @@ lockfileVersion: 5.4
|
|||
|
||||
specifiers:
|
||||
'@geist-ui/core': ^2.3.8
|
||||
'@geist-ui/icons': 1.0.2
|
||||
'@next-auth/prisma-adapter': ^1.0.5
|
||||
'@next/bundle-analyzer': 12.1.6
|
||||
'@next/eslint-plugin-next': 13.0.5-canary.3
|
||||
'@prisma/client': ^4.6.1
|
||||
'@radix-ui/react-dialog': ^1.0.2
|
||||
'@radix-ui/react-dropdown-menu': ^2.0.1
|
||||
'@radix-ui/react-popover': ^1.0.2
|
||||
'@radix-ui/react-tabs': ^1.0.1
|
||||
|
@ -17,6 +17,7 @@ specifiers:
|
|||
'@types/react-datepicker': 4.4.1
|
||||
'@types/react-dom': 18.0.3
|
||||
'@wcj/markdown-to-html': ^2.1.2
|
||||
'@wits/next-themes': ^0.2.12
|
||||
bcrypt: ^5.1.0
|
||||
client-zip: 2.2.1
|
||||
clsx: ^1.2.1
|
||||
|
@ -26,7 +27,7 @@ specifiers:
|
|||
eslint-config-next: 13.0.3
|
||||
jest: ^29.3.1
|
||||
katex: ^0.16.3
|
||||
next: 13.0.6-canary.1
|
||||
next: 13.0.6-canary.2
|
||||
next-auth: ^4.17.0
|
||||
next-unused: 0.0.6
|
||||
prettier: 2.6.2
|
||||
|
@ -36,6 +37,7 @@ specifiers:
|
|||
react-datepicker: 4.8.0
|
||||
react-dom: 18.2.0
|
||||
react-dropzone: 14.2.3
|
||||
react-feather: ^2.0.10
|
||||
react-hot-toast: ^2.4.0
|
||||
server-only: ^0.0.1
|
||||
sharp: ^0.31.2
|
||||
|
@ -47,27 +49,29 @@ specifiers:
|
|||
|
||||
dependencies:
|
||||
'@geist-ui/core': 2.3.8_biqbaboplfbrettd7655fr4n2y
|
||||
'@geist-ui/icons': 1.0.2_zhza2kbnl2wkkf7vqdl3ton2f4
|
||||
'@next-auth/prisma-adapter': 1.0.5_o53gfpk3vz2btjrokqfjjwwn3m
|
||||
'@next/eslint-plugin-next': 13.0.5-canary.3
|
||||
'@prisma/client': 4.6.1_prisma@4.6.1
|
||||
'@radix-ui/react-dialog': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
|
||||
'@radix-ui/react-dropdown-menu': 2.0.1_jbvntnid6ohjelon6ccj5dhg2u
|
||||
'@radix-ui/react-popover': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
|
||||
'@radix-ui/react-tabs': 1.0.1_biqbaboplfbrettd7655fr4n2y
|
||||
'@radix-ui/react-tooltip': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
|
||||
'@wcj/markdown-to-html': 2.1.2
|
||||
'@wits/next-themes': 0.2.12_hzq4dmqplfkom7c35ucps6atz4
|
||||
bcrypt: 5.1.0
|
||||
client-zip: 2.2.1
|
||||
cookies-next: 2.1.1
|
||||
jest: 29.3.1_@types+node@17.0.23
|
||||
next: 13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y
|
||||
next-auth: 4.17.0_cejjzyjft5qpe7pbv5t5jzassa
|
||||
next: 13.0.6-canary.2_biqbaboplfbrettd7655fr4n2y
|
||||
next-auth: 4.17.0_hzq4dmqplfkom7c35ucps6atz4
|
||||
prisma: 4.6.1
|
||||
rc-table: 7.24.1_biqbaboplfbrettd7655fr4n2y
|
||||
react: 18.2.0
|
||||
react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
react-dropzone: 14.2.3_react@18.2.0
|
||||
react-feather: 2.0.10_react@18.2.0
|
||||
react-hot-toast: 2.4.0_biqbaboplfbrettd7655fr4n2y
|
||||
server-only: 0.0.1
|
||||
swr: 1.3.0_react@18.2.0
|
||||
|
@ -497,16 +501,6 @@ packages:
|
|||
react-dom: 18.2.0_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/@geist-ui/icons/1.0.2_zhza2kbnl2wkkf7vqdl3ton2f4:
|
||||
resolution: {integrity: sha512-Npfa0NW6fQ31qw/+iMPWbs1hAcJ/3FqBjSLYgEfITDqy/3TJFpFKeVyK04AC/hTmYTsdNruVYczqPNcham5FOQ==}
|
||||
peerDependencies:
|
||||
'@geist-ui/core': '>=1.0.0'
|
||||
react: '>=16.13.0'
|
||||
dependencies:
|
||||
'@geist-ui/core': 2.3.8_biqbaboplfbrettd7655fr4n2y
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@humanwhocodes/config-array/0.11.7:
|
||||
resolution: {integrity: sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==}
|
||||
engines: {node: '>=10.10.0'}
|
||||
|
@ -819,7 +813,7 @@ packages:
|
|||
next-auth: ^4
|
||||
dependencies:
|
||||
'@prisma/client': 4.6.1_prisma@4.6.1
|
||||
next-auth: 4.17.0_cejjzyjft5qpe7pbv5t5jzassa
|
||||
next-auth: 4.17.0_hzq4dmqplfkom7c35ucps6atz4
|
||||
dev: false
|
||||
|
||||
/@next/bundle-analyzer/12.1.6:
|
||||
|
@ -831,8 +825,8 @@ packages:
|
|||
- utf-8-validate
|
||||
dev: true
|
||||
|
||||
/@next/env/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-L88vP2GvU2NvF5YSIDjqYzzJQRNDg3F08qE/pTLClsYXLusRWAJ1lgI9sZFqLrMbZuj2xd0hWYyYjCrrg/LLLw==}
|
||||
/@next/env/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-2qCq6TDCDRGYWYy7gmugOdDZ+d770uMW3+Kxv50CCLIKtCvO6TS+v2ObzHltkvjMI3su7LAaHgGVXHLTx1fO4w==}
|
||||
dev: false
|
||||
|
||||
/@next/eslint-plugin-next/13.0.3:
|
||||
|
@ -847,8 +841,8 @@ packages:
|
|||
glob: 7.1.7
|
||||
dev: false
|
||||
|
||||
/@next/swc-android-arm-eabi/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-3/ZSIsm2yYZXUyqupAri4+6J97wVdHIP2yrcTLoKdYQKm1lp1z5hIZLtxQCV4vLyYNlNIafvIqeasfYWuYzCgw==}
|
||||
/@next/swc-android-arm-eabi/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-9wPxj5uzH3DUNP7dZg9snd6FM7LY/LHvuOgoofAO2x3j0A1udA2sq96T09w3nzRBlRgIL6PKlH/P3kT9+Yihsg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
@ -856,8 +850,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-android-arm64/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-/J2EXT8L82HgV8sf2SzSdpTuT5gtpPGgekPRCF1ttYyN8FAR/VHPKOLYTbKz3NQ95ogttrW28RFPsMSekQpLaQ==}
|
||||
/@next/swc-android-arm64/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-pDDNYMFD3T5WTX0fjKXqYxVcUt3YKr4PXfvH3aci74Vrm732ky7WKhDEEbl0EfHtpQWeJJo5GlrUOhF/a0Lu8Q==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
@ -865,8 +859,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-darwin-arm64/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-n+IxXIJSEm3HdumauULSZCehyKyQ0EfWU/qf5oMjyGOQ/sHQfgT5sGYtfnnNvvhSlVgFhyz7MalPRwJQWAIIZQ==}
|
||||
/@next/swc-darwin-arm64/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-SfeNfQ/gDt9DM1eHIYAapE1PMcI6lru/eqI0jxFupHlgmE2e1zLyhUlADSFqCEQT5sVdm0rWg6Ne7KyYc7X6VQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
@ -874,8 +868,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-darwin-x64/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-0gQ2zLBFJT8rO080APvY/fHxjSIRVD7VpF0C12BXroFJ3XMnCoa6scniVgKwV4pjhTtlJoLSk3y4wNITyouLDQ==}
|
||||
/@next/swc-darwin-x64/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-y9mJQK4DfLiXxcM+85Y5mt5tPIbiW+e1UI1W1nJOGUoQsYcaKfmEDcFxblxFDrTe952D7bv0SHNW984cugIpcw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
@ -883,8 +877,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-freebsd-x64/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-zAnm1JtxgrNkjiBef7U8lO9JOqNhy13mKA0Z27XCeAunhaar0hNZNHnKUlISVhAZovpHs96fp0mm7Skw0WCkpA==}
|
||||
/@next/swc-freebsd-x64/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-kvd/30cQveHC85Ml8rLkh7kWJYNcHgZin6QXYNwJ/pa0a5cOtHkBoyHr/49x4F9wRHB3YGdYHTBY9jRJbVH5HQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
@ -892,8 +886,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-arm-gnueabihf/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-JJCdGBEeNzGXm0AQUfVY9x3C3WvxCcawZ1tCYYkOqLD21Dj5gDTNSZT2cAGFDovfyn5hN/Vltf20Zs8ilUPr1w==}
|
||||
/@next/swc-linux-arm-gnueabihf/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-1uaCAqiPz2DcjfK5Nb/tlrFJuKHz2SCqF8ghQg/dkPNx3B5u2js6irIcCu/Rcz0fGk0mI97Rzx3IeLvwiXsn+A==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
@ -901,8 +895,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-arm64-gnu/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-oE9D+Mm240fRpZWZBhFiztmJ/D7uwQ3jfOZcQVf1aN3P+9De+5jyv2TKoHrjrRh5xjloTEDIpt2wNKimlwZvkg==}
|
||||
/@next/swc-linux-arm64-gnu/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-5GlB7eRwZ1posKCaZnJB09JtsYx1YZ3USZ2OUyQimFEXUQWbOG/dR/+faKdml6LqxFUyOXnpwwZbTFZNYd8tmQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
@ -910,8 +904,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-arm64-musl/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-+DukK2LdoZo4Ds0o2XGAC9324O9auxvHMF4MwDzrXrherBFEeSZUDIxcz4zu5/pd8dyQ8JY9nwILJEevla23pA==}
|
||||
/@next/swc-linux-arm64-musl/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-//xak9BwCQzJrD89n5JTaWz2NFvIwzuvvCHdP8dBDyizrDwhSQ6r5p4IE49mZ8d8VfIGQMG6S8FK/M2ocw574w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
@ -919,8 +913,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-x64-gnu/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-1bULat6aif5E48s23lAh4vmuVogxz3arXMawlqHwHqwJWpzxF2vyAl3Ilh4mXJnD1xvwiGRH7Aov7HMQJhF2+g==}
|
||||
/@next/swc-linux-x64-gnu/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-SeQZy+Fbm9YUedtNjAdOjgtXABmZItxjZ3RENO1RkIt7vJrBpi4emFkMAvsEYJBspM30aWP8g8fS3kO11ETdvw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
@ -928,8 +922,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-x64-musl/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-LN9qXV3Rh1jMcaSXg5DGZYbN6nVCn6A/aQBTw4K5DWu7bHTiEkq4d7/OZN+gfJcqW8BuRtG4zLeraae/1RO9pw==}
|
||||
/@next/swc-linux-x64-musl/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-kUtDYdhKSSfkMn8jgAkfE5pyamMhu5vRNFUr+mF5i1yz05FsBYApDlMcLMC5lhB5JDSta/kDj1gmubZqzX3gNw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
@ -937,8 +931,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-arm64-msvc/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-792QCYO+lF4N1c2bwYVwhLwMJMhnmvQRVOnCmRlGhbaZJ0f6ZuIYCxjqAqV8Por+u0ErenRMv5BGleK8wHfQJA==}
|
||||
/@next/swc-win32-arm64-msvc/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-orQDh3ozGZXGWcocHSPy4f3CxIQMUpHfWk87e6bYPqu4g5Xt7SfBIx4RTopovyc5x3rGswV5zvEtn0mrSlPOFA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
@ -946,8 +940,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-ia32-msvc/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-hwL9JjT7C1ZP+Wj7F4QIoewEErqc70Ax0aeKqQZdKU57djmIWvvvnyh9p/uUQFHLc3M4Um+XvtqpyFZB6RcYbg==}
|
||||
/@next/swc-win32-ia32-msvc/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-GrF/vCKyDUfYOght5lV4RFjV7X+pM8YYrfxo8eBYzSwFW/vWtQCP5m85idNQ/XlJnxUFmhQG9+CCQac+lwKcBQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
@ -955,8 +949,8 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-x64-msvc/13.0.6-canary.1:
|
||||
resolution: {integrity: sha512-KA6/9W7ZEfkN/ecH8f/fg+WyQaJnRG/UE2IKOdQHbL4uVtHJk5PQmYT+nBZFVnbNHJB2ouNmL4pFJM/7JjNBww==}
|
||||
/@next/swc-win32-x64-msvc/13.0.6-canary.2:
|
||||
resolution: {integrity: sha512-zjd7KUJ+wrrWzfR/THoIUGnoa0gnlNV2c07TFk5bFHrjP4VVTQvw1P3wqzx+1bbJB+6O4pwkr6IW3axoy5vtaQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
@ -1070,6 +1064,33 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-dialog/1.0.2_jbvntnid6ohjelon6ccj5dhg2u:
|
||||
resolution: {integrity: sha512-EKxxp2WNSmUPkx4trtWNmZ4/vAYEg7JkAfa1HKBUnaubw9eHzf1Orr9B472lJYaYz327RHDrd4R95fsw7VR8DA==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.1
|
||||
'@radix-ui/primitive': 1.0.0
|
||||
'@radix-ui/react-compose-refs': 1.0.0_react@18.2.0
|
||||
'@radix-ui/react-context': 1.0.0_react@18.2.0
|
||||
'@radix-ui/react-dismissable-layer': 1.0.2_biqbaboplfbrettd7655fr4n2y
|
||||
'@radix-ui/react-focus-guards': 1.0.0_react@18.2.0
|
||||
'@radix-ui/react-focus-scope': 1.0.1_biqbaboplfbrettd7655fr4n2y
|
||||
'@radix-ui/react-id': 1.0.0_react@18.2.0
|
||||
'@radix-ui/react-portal': 1.0.1_biqbaboplfbrettd7655fr4n2y
|
||||
'@radix-ui/react-presence': 1.0.0_biqbaboplfbrettd7655fr4n2y
|
||||
'@radix-ui/react-primitive': 1.0.1_biqbaboplfbrettd7655fr4n2y
|
||||
'@radix-ui/react-slot': 1.0.1_react@18.2.0
|
||||
'@radix-ui/react-use-controllable-state': 1.0.0_react@18.2.0
|
||||
aria-hidden: 1.2.1_ulhmhxukhxjgxaybrsjlob7ffu
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
react-remove-scroll: 2.5.5_ulhmhxukhxjgxaybrsjlob7ffu
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
dev: false
|
||||
|
||||
/@radix-ui/react-direction/1.0.0_react@18.2.0:
|
||||
resolution: {integrity: sha512-2HV05lGUgYcA6xgLQ4BKPDmtL+QbIZYH5fCOTAOOcJ5O0QbWS3i9lKaurLzliYUDhORI2Qr3pyjhJh44lKA3rQ==}
|
||||
peerDependencies:
|
||||
|
@ -1719,6 +1740,18 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@wits/next-themes/0.2.12_hzq4dmqplfkom7c35ucps6atz4:
|
||||
resolution: {integrity: sha512-P/qtLW68n4xBLT8UfLkCD/0jmF0yWxdf3xpGCDbfR6WuvK2brJDQ0DhPbhsucGkJ42ArA6ItKqcIo7/cnKzhGg==}
|
||||
peerDependencies:
|
||||
next: '*'
|
||||
react: '*'
|
||||
react-dom: '*'
|
||||
dependencies:
|
||||
next: 13.0.6-canary.2_biqbaboplfbrettd7655fr4n2y
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/abbrev/1.1.1:
|
||||
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||
dev: false
|
||||
|
@ -5215,7 +5248,7 @@ packages:
|
|||
dev: true
|
||||
optional: true
|
||||
|
||||
/next-auth/4.17.0_cejjzyjft5qpe7pbv5t5jzassa:
|
||||
/next-auth/4.17.0_hzq4dmqplfkom7c35ucps6atz4:
|
||||
resolution: {integrity: sha512-aN2tdnjS0MDeUpB2tBDOaWnegkgeMWrsccujbXRGMJ607b+EwRcy63MFGSr0OAboDJEe0902piXQkt94GqF8Qw==}
|
||||
engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0}
|
||||
peerDependencies:
|
||||
|
@ -5231,7 +5264,7 @@ packages:
|
|||
'@panva/hkdf': 1.0.2
|
||||
cookie: 0.5.0
|
||||
jose: 4.11.0
|
||||
next: 13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y
|
||||
next: 13.0.6-canary.2_biqbaboplfbrettd7655fr4n2y
|
||||
oauth: 0.9.15
|
||||
openid-client: 5.3.0
|
||||
preact: 10.11.2
|
||||
|
@ -5252,8 +5285,8 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/next/13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y:
|
||||
resolution: {integrity: sha512-aLHWxU8tMcsVKyStTQvfATZ8TzX/X/VbfV1erVn+pF4uI5+ETvAGWO1geo1FrLzrW+xB/h+9UPAUiqh21oVZEA==}
|
||||
/next/13.0.6-canary.2_biqbaboplfbrettd7655fr4n2y:
|
||||
resolution: {integrity: sha512-f8/fUo42tlc+IPE7Yo0dtfW08EEsnLel0cjEqv3OqJwOJfGV3xdJAfvPJz0iyGGMx2ig2TS5VzRL/riyBsa/Gg==}
|
||||
engines: {node: '>=14.6.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
@ -5270,7 +5303,7 @@ packages:
|
|||
sass:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@next/env': 13.0.6-canary.1
|
||||
'@next/env': 13.0.6-canary.2
|
||||
'@swc/helpers': 0.4.14
|
||||
caniuse-lite: 1.0.30001431
|
||||
postcss: 8.4.14
|
||||
|
@ -5278,19 +5311,19 @@ packages:
|
|||
react-dom: 18.2.0_react@18.2.0
|
||||
styled-jsx: 5.1.0_react@18.2.0
|
||||
optionalDependencies:
|
||||
'@next/swc-android-arm-eabi': 13.0.6-canary.1
|
||||
'@next/swc-android-arm64': 13.0.6-canary.1
|
||||
'@next/swc-darwin-arm64': 13.0.6-canary.1
|
||||
'@next/swc-darwin-x64': 13.0.6-canary.1
|
||||
'@next/swc-freebsd-x64': 13.0.6-canary.1
|
||||
'@next/swc-linux-arm-gnueabihf': 13.0.6-canary.1
|
||||
'@next/swc-linux-arm64-gnu': 13.0.6-canary.1
|
||||
'@next/swc-linux-arm64-musl': 13.0.6-canary.1
|
||||
'@next/swc-linux-x64-gnu': 13.0.6-canary.1
|
||||
'@next/swc-linux-x64-musl': 13.0.6-canary.1
|
||||
'@next/swc-win32-arm64-msvc': 13.0.6-canary.1
|
||||
'@next/swc-win32-ia32-msvc': 13.0.6-canary.1
|
||||
'@next/swc-win32-x64-msvc': 13.0.6-canary.1
|
||||
'@next/swc-android-arm-eabi': 13.0.6-canary.2
|
||||
'@next/swc-android-arm64': 13.0.6-canary.2
|
||||
'@next/swc-darwin-arm64': 13.0.6-canary.2
|
||||
'@next/swc-darwin-x64': 13.0.6-canary.2
|
||||
'@next/swc-freebsd-x64': 13.0.6-canary.2
|
||||
'@next/swc-linux-arm-gnueabihf': 13.0.6-canary.2
|
||||
'@next/swc-linux-arm64-gnu': 13.0.6-canary.2
|
||||
'@next/swc-linux-arm64-musl': 13.0.6-canary.2
|
||||
'@next/swc-linux-x64-gnu': 13.0.6-canary.2
|
||||
'@next/swc-linux-x64-musl': 13.0.6-canary.2
|
||||
'@next/swc-win32-arm64-msvc': 13.0.6-canary.2
|
||||
'@next/swc-win32-ia32-msvc': 13.0.6-canary.2
|
||||
'@next/swc-win32-x64-msvc': 13.0.6-canary.2
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
@ -5977,6 +6010,15 @@ packages:
|
|||
/react-fast-compare/3.2.0:
|
||||
resolution: {integrity: sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==}
|
||||
|
||||
/react-feather/2.0.10_react@18.2.0:
|
||||
resolution: {integrity: sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.6'
|
||||
dependencies:
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-hot-toast/2.4.0_biqbaboplfbrettd7655fr4n2y:
|
||||
resolution: {integrity: sha512-qnnVbXropKuwUpriVVosgo8QrB+IaPJCpL8oBI6Ov84uvHZ5QQcTp2qg6ku2wNfgJl6rlQXJIQU5q+5lmPOutA==}
|
||||
engines: {node: '>=10'}
|
||||
|
|
Loading…
Reference in a new issue