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 styles from "./auth.module.css"
|
||||||
import Link from "../../components/link"
|
import Link from "../../components/link"
|
||||||
import { signIn } from "next-auth/react"
|
import { signIn } from "next-auth/react"
|
||||||
import { Github as GithubIcon } from "@geist-ui/icons"
|
|
||||||
import Input from "@components/input"
|
import Input from "@components/input"
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
import Note from "@components/note"
|
import Note from "@components/note"
|
||||||
|
import { GitHub } from 'react-feather'
|
||||||
const Auth = ({
|
const Auth = ({
|
||||||
page,
|
page,
|
||||||
requiresServerPassword
|
requiresServerPassword
|
||||||
|
@ -71,7 +70,7 @@ const Auth = ({
|
||||||
style={{
|
style={{
|
||||||
color: 'var(--fg)'
|
color: 'var(--fg)'
|
||||||
}}
|
}}
|
||||||
iconLeft={<GithubIcon />}
|
iconLeft={<GitHub />}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
signIn("github", {
|
signIn("github", {
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.contentWrapper {
|
||||||
|
z-index: 1000;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
import { Popover } from "@components/popover"
|
import { Popover } from "@components/popover"
|
||||||
import ShiftBy from "@components/shift-by"
|
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 { codeFileExtensions } from "@lib/constants"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import type { File } from "lib/server/prisma"
|
import type { File } from "lib/server/prisma"
|
||||||
import styles from "./dropdown.module.css"
|
import styles from "./dropdown.module.css"
|
||||||
import buttonStyles from "@components/button/button.module.css"
|
import buttonStyles from "@components/button/button.module.css"
|
||||||
|
import { ChevronDown, Code, File as FileIcon } from "react-feather"
|
||||||
|
|
||||||
type Item = File & {
|
type Item = File & {
|
||||||
icon: JSX.Element
|
icon: JSX.Element
|
||||||
|
@ -20,7 +18,7 @@ const FileDropdown = ({ files }: { files: File[] }) => {
|
||||||
if (codeFileExtensions.includes(extension || "")) {
|
if (codeFileExtensions.includes(extension || "")) {
|
||||||
return {
|
return {
|
||||||
...file,
|
...file,
|
||||||
icon: <CodeIcon />
|
icon: <Code />
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
@ -60,7 +58,7 @@ const FileDropdown = ({ files }: { files: File[] }) => {
|
||||||
Jump to {files.length} {files.length === 1 ? "file" : "files"}
|
Jump to {files.length} {files.length === 1 ? "file" : "files"}
|
||||||
</span>
|
</span>
|
||||||
</Popover.Trigger>
|
</Popover.Trigger>
|
||||||
<Popover.Content>{content}</Popover.Content>
|
<Popover.Content className={styles.contentWrapper}>{content}</Popover.Content>
|
||||||
</Popover>
|
</Popover>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
import Bold from "@geist-ui/icons/bold"
|
import { Bold, Code, Image as ImageIcon, Italic, Link, List } from "react-feather"
|
||||||
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 { RefObject, useMemo } from "react"
|
import { RefObject, useMemo } from "react"
|
||||||
import styles from "./formatting-icons.module.css"
|
import styles from "./formatting-icons.module.css"
|
||||||
import { TextareaMarkdownRef } from "textarea-markdown-editor"
|
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 styles from "./document.module.css"
|
||||||
import Trash from "@geist-ui/icons/trash"
|
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
import Input from "@components/input"
|
import Input from "@components/input"
|
||||||
import DocumentTabs from "app/(posts)/components/tabs"
|
import DocumentTabs from "app/(posts)/components/tabs"
|
||||||
|
import { Trash } from "react-feather"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
title?: string
|
title?: string
|
||||||
|
|
|
@ -5,9 +5,6 @@ import DocumentComponent from "./view-document"
|
||||||
import styles from "./post-page.module.css"
|
import styles from "./post-page.module.css"
|
||||||
|
|
||||||
import { useEffect, useState } from "react"
|
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 FileDropdown from "app/(posts)/components/file-dropdown"
|
||||||
import ScrollToTop from "@components/scroll-to-top"
|
import ScrollToTop from "@components/scroll-to-top"
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
|
@ -18,6 +15,7 @@ import VisibilityControl from "@components/badges/visibility-control"
|
||||||
import { File, PostWithFilesAndAuthor } from "@lib/server/prisma"
|
import { File, PostWithFilesAndAuthor } from "@lib/server/prisma"
|
||||||
import ButtonGroup from "@components/button-group"
|
import ButtonGroup from "@components/button-group"
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
|
import { Archive, ArrowUpCircle, Edit } from "react-feather"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
post: string | PostWithFilesAndAuthor
|
post: string | PostWithFilesAndAuthor
|
||||||
|
@ -108,7 +106,7 @@ const PostPage = ({ post: initialPost, isProtected, isAuthor }: Props) => {
|
||||||
Edit a Copy
|
Edit a Copy
|
||||||
</Button>
|
</Button>
|
||||||
{post.parentId && (
|
{post.parentId && (
|
||||||
<Button iconLeft={<Parent />} onClick={viewParentClick}>
|
<Button iconLeft={<ArrowUpCircle />} onClick={viewParentClick}>
|
||||||
View Parent
|
View Parent
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { memo } from "react"
|
import { memo } from "react"
|
||||||
import styles from "./document.module.css"
|
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 Skeleton from "@components/skeleton"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
|
||||||
|
@ -10,6 +8,7 @@ import Button from "@components/button"
|
||||||
import ButtonGroup from "@components/button-group"
|
import ButtonGroup from "@components/button-group"
|
||||||
import DocumentTabs from "app/(posts)/components/tabs"
|
import DocumentTabs from "app/(posts)/components/tabs"
|
||||||
import Input from "@components/input"
|
import Input from "@components/input"
|
||||||
|
import { Download, ExternalLink } from "react-feather"
|
||||||
|
|
||||||
// import Link from "next/link"
|
// import Link from "next/link"
|
||||||
type Props = {
|
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 Button from "@components/button"
|
||||||
import React, { useCallback, useEffect } from "react"
|
import React from "react"
|
||||||
import { useState } from "react"
|
|
||||||
import styles from "./dropdown.module.css"
|
import styles from "./dropdown.module.css"
|
||||||
import DownIcon from "@geist-ui/icons/arrowDown"
|
|
||||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
|
||||||
|
import { ArrowDown } from "react-feather"
|
||||||
type Props = {
|
type Props = {
|
||||||
type?: "primary" | "secondary"
|
type?: "primary" | "secondary"
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
|
@ -35,7 +34,7 @@ const ButtonDropdown: React.FC<
|
||||||
asChild
|
asChild
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
iconLeft={<DownIcon />}
|
iconLeft={<ArrowDown />}
|
||||||
type={type}
|
type={type}
|
||||||
className={styles.icon}
|
className={styles.icon}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
background: var(--bg);
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 70px;
|
||||||
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile button {
|
.mobile button {
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
"use client"
|
"use client"
|
||||||
|
import { useBodyScroll, useMediaQuery } from "@geist-ui/core/dist"
|
||||||
import { useBodyScroll, useMediaQuery } from "@geist-ui/core/dist"
|
|
||||||
|
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import styles from "./header.module.css"
|
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 useUserData from "@lib/hooks/use-user-data"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { usePathname } from "next/navigation"
|
import { usePathname } from "next/navigation"
|
||||||
import { signOut } from "next-auth/react"
|
import { signOut } from "next-auth/react"
|
||||||
import { useTheme } from "@components/theme/ThemeClientContextProvider"
|
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
import clsx from "clsx"
|
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 = {
|
type Tab = {
|
||||||
name: string
|
name: string
|
||||||
|
@ -55,7 +55,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
||||||
{
|
{
|
||||||
name: isMobile ? "GitHub" : "",
|
name: isMobile ? "GitHub" : "",
|
||||||
href: "https://github.com/maxleiter/drift",
|
href: "https://github.com/maxleiter/drift",
|
||||||
icon: <GitHubIcon />,
|
icon: <GitHub />,
|
||||||
value: "github"
|
value: "github"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -64,7 +64,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
||||||
if (typeof window !== "undefined")
|
if (typeof window !== "undefined")
|
||||||
setTheme(theme === "light" ? "dark" : "light")
|
setTheme(theme === "light" ? "dark" : "light")
|
||||||
},
|
},
|
||||||
icon: theme === "light" ? <MoonIcon /> : <SunIcon />,
|
icon: theme === "light" ? <Moon /> : <Sun />,
|
||||||
value: "theme"
|
value: "theme"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -72,7 +72,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
defaultPages.push({
|
defaultPages.push({
|
||||||
name: "Admin",
|
name: "Admin",
|
||||||
icon: <SettingsIcon />,
|
icon: <Settings />,
|
||||||
value: "admin",
|
value: "admin",
|
||||||
href: "/admin"
|
href: "/admin"
|
||||||
})
|
})
|
||||||
|
@ -82,29 +82,30 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: "New",
|
name: "New",
|
||||||
icon: <NewIcon />,
|
icon: <PlusCircle />,
|
||||||
value: "new",
|
value: "new",
|
||||||
href: "/new"
|
href: "/new"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Yours",
|
name: "Yours",
|
||||||
icon: <YourIcon />,
|
icon: <User />,
|
||||||
value: "yours",
|
value: "yours",
|
||||||
href: "/mine"
|
href: "/mine"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Settings",
|
name: "Settings",
|
||||||
icon: <SettingsIcon />,
|
icon: <Settings />,
|
||||||
value: "settings",
|
value: "settings",
|
||||||
href: "/settings"
|
href: "/settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Sign Out",
|
name: "Sign Out",
|
||||||
icon: <SignOutIcon />,
|
icon: <UserX />,
|
||||||
value: "signout",
|
value: "signout",
|
||||||
onClick: () => signOut({
|
onClick: () =>
|
||||||
callbackUrl: "/",
|
signOut({
|
||||||
})
|
callbackUrl: "/"
|
||||||
|
})
|
||||||
},
|
},
|
||||||
...defaultPages
|
...defaultPages
|
||||||
]
|
]
|
||||||
|
@ -112,19 +113,19 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: "Home",
|
name: "Home",
|
||||||
icon: <HomeIcon />,
|
icon: <Home />,
|
||||||
value: "home",
|
value: "home",
|
||||||
href: "/"
|
href: "/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Sign in",
|
name: "Sign in",
|
||||||
icon: <SignInIcon />,
|
icon: <User />,
|
||||||
value: "signin",
|
value: "signin",
|
||||||
href: "/signin"
|
href: "/signin"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Sign up",
|
name: "Sign up",
|
||||||
icon: <SignUpIcon />,
|
icon: <UserPlus />,
|
||||||
value: "signup",
|
value: "signup",
|
||||||
href: "/signup"
|
href: "/signup"
|
||||||
},
|
},
|
||||||
|
@ -180,7 +181,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.controls}>
|
<div className={styles.controls}>
|
||||||
<Button onClick={() => setExpanded(!expanded)} aria-label="Menu">
|
<Button onClick={() => setExpanded(!expanded)} aria-label="Menu">
|
||||||
<MenuIcon />
|
<Menu />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{/* setExpanded should occur elsewhere; we don't want to close if they change themes */}
|
{/* setExpanded should occur elsewhere; we don't want to close if they change themes */}
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
color: var(--fg);
|
color: var(--fg);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: var(--gap);
|
padding: var(--gap);
|
||||||
margin-top: 0.5em;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
border-radius: var(--radius);
|
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 { useState } from "react"
|
||||||
|
import styles from "./modal.module.css"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
creating: boolean
|
creating: boolean
|
||||||
|
@ -34,47 +38,60 @@ const PasswordModal = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* TODO: investigate disableBackdropClick not updating state? */}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
<Modal visible={isOpen} disableBackdropClick={false}>
|
<Dialog.Root
|
||||||
<Modal.Title>Enter a password</Modal.Title>
|
open={isOpen}
|
||||||
<Modal.Content>
|
onOpenChange={(open) => {
|
||||||
{!error && creating && (
|
if (!open) onClose()
|
||||||
<Note type="warning" label="Warning">
|
}}
|
||||||
This doesn't protect your post from the server
|
>
|
||||||
administrator.
|
{/* <Dialog.Trigger asChild>Enter a password</Dialog.Trigger> */}
|
||||||
</Note>
|
<Dialog.Portal>
|
||||||
)}
|
<Dialog.Overlay className={styles.overlay} />
|
||||||
{error && (
|
<Dialog.Content
|
||||||
<Note type="error" label="Error">
|
className={styles.content}
|
||||||
{error}
|
onEscapeKeyDown={onClose}
|
||||||
</Note>
|
>
|
||||||
)}
|
<Dialog.Title>
|
||||||
<Spacer />
|
{creating ? "Create a password" : "Enter password"}
|
||||||
<Input
|
</Dialog.Title>
|
||||||
width={"100%"}
|
<Dialog.Description>
|
||||||
label="Password"
|
{creating
|
||||||
marginBottom={1}
|
? "Enter a password to protect your post"
|
||||||
htmlType="password"
|
: "Enter the password to access the post"}
|
||||||
placeholder="Password"
|
</Dialog.Description>
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
<fieldset className={styles.fieldset}>
|
||||||
/>
|
{error && <Note type="error">{error}</Note>}
|
||||||
{creating && (
|
<Input
|
||||||
<Input
|
width={"100%"}
|
||||||
width={"100%"}
|
label="Password"
|
||||||
label="Confirm"
|
type="password"
|
||||||
htmlType="password"
|
placeholder="Password"
|
||||||
placeholder="Confirm Password"
|
onChange={(e) => setPassword(e.currentTarget.value)}
|
||||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
/>
|
||||||
/>
|
{creating && (
|
||||||
)}
|
<Input
|
||||||
</Modal.Content>
|
width={"100%"}
|
||||||
<Modal.Action passive onClick={onClose}>
|
label="Confirm"
|
||||||
Cancel
|
type="password"
|
||||||
</Modal.Action>
|
placeholder="Confirm Password"
|
||||||
<Modal.Action onClick={onSubmit}>Submit</Modal.Action>
|
onChange={(e) => setConfirmPassword(e.currentTarget.value)}
|
||||||
</Modal>
|
/>
|
||||||
|
)}
|
||||||
|
{!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 VisibilityBadge from "../badges/visibility-badge"
|
||||||
import FadeIn from "@components/fade-in"
|
import FadeIn from "@components/fade-in"
|
||||||
import Trash from "@geist-ui/icons/trash"
|
|
||||||
import ExpirationBadge from "@components/badges/expiration-badge"
|
import ExpirationBadge from "@components/badges/expiration-badge"
|
||||||
import CreatedAgoBadge from "@components/badges/created-ago-badge"
|
import CreatedAgoBadge from "@components/badges/created-ago-badge"
|
||||||
import Edit from "@geist-ui/icons/edit"
|
|
||||||
import { useRouter } from "next/navigation"
|
import { useRouter } from "next/navigation"
|
||||||
import Parent from "@geist-ui/icons/arrowUpCircle"
|
|
||||||
import styles from "./list-item.module.css"
|
import styles from "./list-item.module.css"
|
||||||
import Link from "@components/link"
|
import Link from "@components/link"
|
||||||
import type { PostWithFiles } from "@lib/server/prisma"
|
import type { PostWithFiles } from "@lib/server/prisma"
|
||||||
|
@ -14,6 +11,7 @@ import Tooltip from "@components/tooltip"
|
||||||
import Badge from "@components/badges/badge"
|
import Badge from "@components/badges/badge"
|
||||||
import Card from "@components/card"
|
import Card from "@components/card"
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
|
import { ArrowUpCircle, Edit, Trash } from "react-feather"
|
||||||
|
|
||||||
// TODO: isOwner should default to false so this can be used generically
|
// TODO: isOwner should default to false so this can be used generically
|
||||||
const ListItem = ({
|
const ListItem = ({
|
||||||
|
@ -55,7 +53,7 @@ const ListItem = ({
|
||||||
{post.parentId && (
|
{post.parentId && (
|
||||||
<Tooltip content={"View parent"}>
|
<Tooltip content={"View parent"}>
|
||||||
<Button
|
<Button
|
||||||
iconRight={<Parent />}
|
iconRight={<ArrowUpCircle />}
|
||||||
onClick={viewParentClick}
|
onClick={viewParentClick}
|
||||||
height={38}
|
height={38}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
import Tooltip from "@components/tooltip"
|
import Tooltip from "@components/tooltip"
|
||||||
import ChevronUp from "@geist-ui/icons/chevronUp"
|
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
|
import { ChevronUp } from "react-feather"
|
||||||
import styles from "./scroll.module.css"
|
import styles from "./scroll.module.css"
|
||||||
|
|
||||||
const ScrollToTop = () => {
|
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 { LayoutWrapper } from "./root-layout-wrapper"
|
||||||
import styles from "@styles/Home.module.css"
|
import styles from "@styles/Home.module.css"
|
||||||
import { getSession } from "@lib/server/session"
|
import { getSession } from "@lib/server/session"
|
||||||
import ThemeProvider from "@components/theme/ThemeProvider"
|
import { ServerThemeProvider } from "@wits/next-themes"
|
||||||
import { THEME_COOKIE_NAME } from "@components/theme/theme"
|
|
||||||
|
|
||||||
interface RootLayoutProps {
|
interface RootLayoutProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
@ -13,23 +12,16 @@ export default async function RootLayout({ children }: RootLayoutProps) {
|
||||||
// TODO: this opts out of SSG
|
// TODO: this opts out of SSG
|
||||||
const session = await getSession()
|
const session = await getSession()
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<ServerThemeProvider
|
||||||
<head>
|
enableSystem={true}
|
||||||
<script
|
defaultTheme="dark"
|
||||||
dangerouslySetInnerHTML={{
|
disableTransitionOnChange
|
||||||
__html: `
|
cookieName={"drift-theme"}
|
||||||
(function() {
|
attribute="data-theme"
|
||||||
var theme = document.cookie
|
enableColorScheme={true}
|
||||||
.split('; ')
|
>
|
||||||
.find(row => row.startsWith('${THEME_COOKIE_NAME}='))
|
<html lang="en">
|
||||||
.split('=')[1];
|
<head />
|
||||||
document.documentElement.setAttribute('data-theme', theme);
|
|
||||||
})();
|
|
||||||
`
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</head>
|
|
||||||
<ThemeProvider>
|
|
||||||
<body className={styles.main}>
|
<body className={styles.main}>
|
||||||
<LayoutWrapper
|
<LayoutWrapper
|
||||||
signedIn={Boolean(session?.user)}
|
signedIn={Boolean(session?.user)}
|
||||||
|
@ -38,7 +30,7 @@ export default async function RootLayout({ children }: RootLayoutProps) {
|
||||||
{children}
|
{children}
|
||||||
</LayoutWrapper>
|
</LayoutWrapper>
|
||||||
</body>
|
</body>
|
||||||
</ThemeProvider>
|
</html>
|
||||||
</html>
|
</ServerThemeProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Header from "@components/header"
|
||||||
import Page from "@components/page"
|
import Page from "@components/page"
|
||||||
import { Toasts } from "@components/toasts"
|
import { Toasts } from "@components/toasts"
|
||||||
import * as RadixTooltip from "@radix-ui/react-tooltip"
|
import * as RadixTooltip from "@radix-ui/react-tooltip"
|
||||||
|
import { ThemeProvider } from "@wits/next-themes"
|
||||||
import { Toaster } from "react-hot-toast"
|
import { Toaster } from "react-hot-toast"
|
||||||
|
|
||||||
export function LayoutWrapper({
|
export function LayoutWrapper({
|
||||||
|
@ -19,7 +20,16 @@ export function LayoutWrapper({
|
||||||
<RadixTooltip.Provider delayDuration={200}>
|
<RadixTooltip.Provider delayDuration={200}>
|
||||||
<Toasts />
|
<Toasts />
|
||||||
<Page>
|
<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}
|
{children}
|
||||||
</Page>
|
</Page>
|
||||||
</RadixTooltip.Provider>
|
</RadixTooltip.Provider>
|
||||||
|
|
|
@ -14,30 +14,32 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@geist-ui/core": "^2.3.8",
|
"@geist-ui/core": "^2.3.8",
|
||||||
"@geist-ui/icons": "1.0.2",
|
|
||||||
"@next-auth/prisma-adapter": "^1.0.5",
|
"@next-auth/prisma-adapter": "^1.0.5",
|
||||||
"@next/eslint-plugin-next": "13.0.5-canary.3",
|
"@next/eslint-plugin-next": "13.0.5-canary.3",
|
||||||
"@prisma/client": "^4.6.1",
|
"@prisma/client": "^4.6.1",
|
||||||
|
"@radix-ui/react-dialog": "^1.0.2",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.1",
|
"@radix-ui/react-dropdown-menu": "^2.0.1",
|
||||||
"@radix-ui/react-popover": "^1.0.2",
|
"@radix-ui/react-popover": "^1.0.2",
|
||||||
"@radix-ui/react-tabs": "^1.0.1",
|
"@radix-ui/react-tabs": "^1.0.1",
|
||||||
"@radix-ui/react-tooltip": "^1.0.2",
|
"@radix-ui/react-tooltip": "^1.0.2",
|
||||||
"@wcj/markdown-to-html": "^2.1.2",
|
"@wcj/markdown-to-html": "^2.1.2",
|
||||||
|
"@wits/next-themes": "^0.2.12",
|
||||||
"bcrypt": "^5.1.0",
|
"bcrypt": "^5.1.0",
|
||||||
"client-zip": "2.2.1",
|
"client-zip": "2.2.1",
|
||||||
"cookies-next": "^2.1.1",
|
"cookies-next": "^2.1.1",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.3.1",
|
||||||
"next": "13.0.6-canary.1",
|
"next": "13.0.6-canary.2",
|
||||||
"next-auth": "^4.17.0",
|
"next-auth": "^4.17.0",
|
||||||
|
"prisma": "^4.6.1",
|
||||||
"rc-table": "7.24.1",
|
"rc-table": "7.24.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-datepicker": "4.8.0",
|
"react-datepicker": "4.8.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-dropzone": "14.2.3",
|
"react-dropzone": "14.2.3",
|
||||||
|
"react-feather": "^2.0.10",
|
||||||
"react-hot-toast": "^2.4.0",
|
"react-hot-toast": "^2.4.0",
|
||||||
"server-only": "^0.0.1",
|
"server-only": "^0.0.1",
|
||||||
"swr": "1.3.0",
|
"swr": "1.3.0",
|
||||||
"prisma": "^4.6.1",
|
|
||||||
"textarea-markdown-editor": "0.1.13",
|
"textarea-markdown-editor": "0.1.13",
|
||||||
"ts-jest": "^29.0.3"
|
"ts-jest": "^29.0.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,11 +2,11 @@ lockfileVersion: 5.4
|
||||||
|
|
||||||
specifiers:
|
specifiers:
|
||||||
'@geist-ui/core': ^2.3.8
|
'@geist-ui/core': ^2.3.8
|
||||||
'@geist-ui/icons': 1.0.2
|
|
||||||
'@next-auth/prisma-adapter': ^1.0.5
|
'@next-auth/prisma-adapter': ^1.0.5
|
||||||
'@next/bundle-analyzer': 12.1.6
|
'@next/bundle-analyzer': 12.1.6
|
||||||
'@next/eslint-plugin-next': 13.0.5-canary.3
|
'@next/eslint-plugin-next': 13.0.5-canary.3
|
||||||
'@prisma/client': ^4.6.1
|
'@prisma/client': ^4.6.1
|
||||||
|
'@radix-ui/react-dialog': ^1.0.2
|
||||||
'@radix-ui/react-dropdown-menu': ^2.0.1
|
'@radix-ui/react-dropdown-menu': ^2.0.1
|
||||||
'@radix-ui/react-popover': ^1.0.2
|
'@radix-ui/react-popover': ^1.0.2
|
||||||
'@radix-ui/react-tabs': ^1.0.1
|
'@radix-ui/react-tabs': ^1.0.1
|
||||||
|
@ -17,6 +17,7 @@ specifiers:
|
||||||
'@types/react-datepicker': 4.4.1
|
'@types/react-datepicker': 4.4.1
|
||||||
'@types/react-dom': 18.0.3
|
'@types/react-dom': 18.0.3
|
||||||
'@wcj/markdown-to-html': ^2.1.2
|
'@wcj/markdown-to-html': ^2.1.2
|
||||||
|
'@wits/next-themes': ^0.2.12
|
||||||
bcrypt: ^5.1.0
|
bcrypt: ^5.1.0
|
||||||
client-zip: 2.2.1
|
client-zip: 2.2.1
|
||||||
clsx: ^1.2.1
|
clsx: ^1.2.1
|
||||||
|
@ -26,7 +27,7 @@ specifiers:
|
||||||
eslint-config-next: 13.0.3
|
eslint-config-next: 13.0.3
|
||||||
jest: ^29.3.1
|
jest: ^29.3.1
|
||||||
katex: ^0.16.3
|
katex: ^0.16.3
|
||||||
next: 13.0.6-canary.1
|
next: 13.0.6-canary.2
|
||||||
next-auth: ^4.17.0
|
next-auth: ^4.17.0
|
||||||
next-unused: 0.0.6
|
next-unused: 0.0.6
|
||||||
prettier: 2.6.2
|
prettier: 2.6.2
|
||||||
|
@ -36,6 +37,7 @@ specifiers:
|
||||||
react-datepicker: 4.8.0
|
react-datepicker: 4.8.0
|
||||||
react-dom: 18.2.0
|
react-dom: 18.2.0
|
||||||
react-dropzone: 14.2.3
|
react-dropzone: 14.2.3
|
||||||
|
react-feather: ^2.0.10
|
||||||
react-hot-toast: ^2.4.0
|
react-hot-toast: ^2.4.0
|
||||||
server-only: ^0.0.1
|
server-only: ^0.0.1
|
||||||
sharp: ^0.31.2
|
sharp: ^0.31.2
|
||||||
|
@ -47,27 +49,29 @@ specifiers:
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@geist-ui/core': 2.3.8_biqbaboplfbrettd7655fr4n2y
|
'@geist-ui/core': 2.3.8_biqbaboplfbrettd7655fr4n2y
|
||||||
'@geist-ui/icons': 1.0.2_zhza2kbnl2wkkf7vqdl3ton2f4
|
|
||||||
'@next-auth/prisma-adapter': 1.0.5_o53gfpk3vz2btjrokqfjjwwn3m
|
'@next-auth/prisma-adapter': 1.0.5_o53gfpk3vz2btjrokqfjjwwn3m
|
||||||
'@next/eslint-plugin-next': 13.0.5-canary.3
|
'@next/eslint-plugin-next': 13.0.5-canary.3
|
||||||
'@prisma/client': 4.6.1_prisma@4.6.1
|
'@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-dropdown-menu': 2.0.1_jbvntnid6ohjelon6ccj5dhg2u
|
||||||
'@radix-ui/react-popover': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
|
'@radix-ui/react-popover': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
|
||||||
'@radix-ui/react-tabs': 1.0.1_biqbaboplfbrettd7655fr4n2y
|
'@radix-ui/react-tabs': 1.0.1_biqbaboplfbrettd7655fr4n2y
|
||||||
'@radix-ui/react-tooltip': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
|
'@radix-ui/react-tooltip': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
|
||||||
'@wcj/markdown-to-html': 2.1.2
|
'@wcj/markdown-to-html': 2.1.2
|
||||||
|
'@wits/next-themes': 0.2.12_hzq4dmqplfkom7c35ucps6atz4
|
||||||
bcrypt: 5.1.0
|
bcrypt: 5.1.0
|
||||||
client-zip: 2.2.1
|
client-zip: 2.2.1
|
||||||
cookies-next: 2.1.1
|
cookies-next: 2.1.1
|
||||||
jest: 29.3.1_@types+node@17.0.23
|
jest: 29.3.1_@types+node@17.0.23
|
||||||
next: 13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y
|
next: 13.0.6-canary.2_biqbaboplfbrettd7655fr4n2y
|
||||||
next-auth: 4.17.0_cejjzyjft5qpe7pbv5t5jzassa
|
next-auth: 4.17.0_hzq4dmqplfkom7c35ucps6atz4
|
||||||
prisma: 4.6.1
|
prisma: 4.6.1
|
||||||
rc-table: 7.24.1_biqbaboplfbrettd7655fr4n2y
|
rc-table: 7.24.1_biqbaboplfbrettd7655fr4n2y
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y
|
react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y
|
||||||
react-dom: 18.2.0_react@18.2.0
|
react-dom: 18.2.0_react@18.2.0
|
||||||
react-dropzone: 14.2.3_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
|
react-hot-toast: 2.4.0_biqbaboplfbrettd7655fr4n2y
|
||||||
server-only: 0.0.1
|
server-only: 0.0.1
|
||||||
swr: 1.3.0_react@18.2.0
|
swr: 1.3.0_react@18.2.0
|
||||||
|
@ -497,16 +501,6 @@ packages:
|
||||||
react-dom: 18.2.0_react@18.2.0
|
react-dom: 18.2.0_react@18.2.0
|
||||||
dev: false
|
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:
|
/@humanwhocodes/config-array/0.11.7:
|
||||||
resolution: {integrity: sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==}
|
resolution: {integrity: sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==}
|
||||||
engines: {node: '>=10.10.0'}
|
engines: {node: '>=10.10.0'}
|
||||||
|
@ -819,7 +813,7 @@ packages:
|
||||||
next-auth: ^4
|
next-auth: ^4
|
||||||
dependencies:
|
dependencies:
|
||||||
'@prisma/client': 4.6.1_prisma@4.6.1
|
'@prisma/client': 4.6.1_prisma@4.6.1
|
||||||
next-auth: 4.17.0_cejjzyjft5qpe7pbv5t5jzassa
|
next-auth: 4.17.0_hzq4dmqplfkom7c35ucps6atz4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@next/bundle-analyzer/12.1.6:
|
/@next/bundle-analyzer/12.1.6:
|
||||||
|
@ -831,8 +825,8 @@ packages:
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@next/env/13.0.6-canary.1:
|
/@next/env/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-L88vP2GvU2NvF5YSIDjqYzzJQRNDg3F08qE/pTLClsYXLusRWAJ1lgI9sZFqLrMbZuj2xd0hWYyYjCrrg/LLLw==}
|
resolution: {integrity: sha512-2qCq6TDCDRGYWYy7gmugOdDZ+d770uMW3+Kxv50CCLIKtCvO6TS+v2ObzHltkvjMI3su7LAaHgGVXHLTx1fO4w==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@next/eslint-plugin-next/13.0.3:
|
/@next/eslint-plugin-next/13.0.3:
|
||||||
|
@ -847,8 +841,8 @@ packages:
|
||||||
glob: 7.1.7
|
glob: 7.1.7
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@next/swc-android-arm-eabi/13.0.6-canary.1:
|
/@next/swc-android-arm-eabi/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-3/ZSIsm2yYZXUyqupAri4+6J97wVdHIP2yrcTLoKdYQKm1lp1z5hIZLtxQCV4vLyYNlNIafvIqeasfYWuYzCgw==}
|
resolution: {integrity: sha512-9wPxj5uzH3DUNP7dZg9snd6FM7LY/LHvuOgoofAO2x3j0A1udA2sq96T09w3nzRBlRgIL6PKlH/P3kT9+Yihsg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
@ -856,8 +850,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-android-arm64/13.0.6-canary.1:
|
/@next/swc-android-arm64/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-/J2EXT8L82HgV8sf2SzSdpTuT5gtpPGgekPRCF1ttYyN8FAR/VHPKOLYTbKz3NQ95ogttrW28RFPsMSekQpLaQ==}
|
resolution: {integrity: sha512-pDDNYMFD3T5WTX0fjKXqYxVcUt3YKr4PXfvH3aci74Vrm732ky7WKhDEEbl0EfHtpQWeJJo5GlrUOhF/a0Lu8Q==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
@ -865,8 +859,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-darwin-arm64/13.0.6-canary.1:
|
/@next/swc-darwin-arm64/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-n+IxXIJSEm3HdumauULSZCehyKyQ0EfWU/qf5oMjyGOQ/sHQfgT5sGYtfnnNvvhSlVgFhyz7MalPRwJQWAIIZQ==}
|
resolution: {integrity: sha512-SfeNfQ/gDt9DM1eHIYAapE1PMcI6lru/eqI0jxFupHlgmE2e1zLyhUlADSFqCEQT5sVdm0rWg6Ne7KyYc7X6VQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
@ -874,8 +868,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-darwin-x64/13.0.6-canary.1:
|
/@next/swc-darwin-x64/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-0gQ2zLBFJT8rO080APvY/fHxjSIRVD7VpF0C12BXroFJ3XMnCoa6scniVgKwV4pjhTtlJoLSk3y4wNITyouLDQ==}
|
resolution: {integrity: sha512-y9mJQK4DfLiXxcM+85Y5mt5tPIbiW+e1UI1W1nJOGUoQsYcaKfmEDcFxblxFDrTe952D7bv0SHNW984cugIpcw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
@ -883,8 +877,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-freebsd-x64/13.0.6-canary.1:
|
/@next/swc-freebsd-x64/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-zAnm1JtxgrNkjiBef7U8lO9JOqNhy13mKA0Z27XCeAunhaar0hNZNHnKUlISVhAZovpHs96fp0mm7Skw0WCkpA==}
|
resolution: {integrity: sha512-kvd/30cQveHC85Ml8rLkh7kWJYNcHgZin6QXYNwJ/pa0a5cOtHkBoyHr/49x4F9wRHB3YGdYHTBY9jRJbVH5HQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
@ -892,8 +886,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-arm-gnueabihf/13.0.6-canary.1:
|
/@next/swc-linux-arm-gnueabihf/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-JJCdGBEeNzGXm0AQUfVY9x3C3WvxCcawZ1tCYYkOqLD21Dj5gDTNSZT2cAGFDovfyn5hN/Vltf20Zs8ilUPr1w==}
|
resolution: {integrity: sha512-1uaCAqiPz2DcjfK5Nb/tlrFJuKHz2SCqF8ghQg/dkPNx3B5u2js6irIcCu/Rcz0fGk0mI97Rzx3IeLvwiXsn+A==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
@ -901,8 +895,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-arm64-gnu/13.0.6-canary.1:
|
/@next/swc-linux-arm64-gnu/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-oE9D+Mm240fRpZWZBhFiztmJ/D7uwQ3jfOZcQVf1aN3P+9De+5jyv2TKoHrjrRh5xjloTEDIpt2wNKimlwZvkg==}
|
resolution: {integrity: sha512-5GlB7eRwZ1posKCaZnJB09JtsYx1YZ3USZ2OUyQimFEXUQWbOG/dR/+faKdml6LqxFUyOXnpwwZbTFZNYd8tmQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
@ -910,8 +904,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-arm64-musl/13.0.6-canary.1:
|
/@next/swc-linux-arm64-musl/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-+DukK2LdoZo4Ds0o2XGAC9324O9auxvHMF4MwDzrXrherBFEeSZUDIxcz4zu5/pd8dyQ8JY9nwILJEevla23pA==}
|
resolution: {integrity: sha512-//xak9BwCQzJrD89n5JTaWz2NFvIwzuvvCHdP8dBDyizrDwhSQ6r5p4IE49mZ8d8VfIGQMG6S8FK/M2ocw574w==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
@ -919,8 +913,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-x64-gnu/13.0.6-canary.1:
|
/@next/swc-linux-x64-gnu/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-1bULat6aif5E48s23lAh4vmuVogxz3arXMawlqHwHqwJWpzxF2vyAl3Ilh4mXJnD1xvwiGRH7Aov7HMQJhF2+g==}
|
resolution: {integrity: sha512-SeQZy+Fbm9YUedtNjAdOjgtXABmZItxjZ3RENO1RkIt7vJrBpi4emFkMAvsEYJBspM30aWP8g8fS3kO11ETdvw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
@ -928,8 +922,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-linux-x64-musl/13.0.6-canary.1:
|
/@next/swc-linux-x64-musl/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-LN9qXV3Rh1jMcaSXg5DGZYbN6nVCn6A/aQBTw4K5DWu7bHTiEkq4d7/OZN+gfJcqW8BuRtG4zLeraae/1RO9pw==}
|
resolution: {integrity: sha512-kUtDYdhKSSfkMn8jgAkfE5pyamMhu5vRNFUr+mF5i1yz05FsBYApDlMcLMC5lhB5JDSta/kDj1gmubZqzX3gNw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
@ -937,8 +931,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-win32-arm64-msvc/13.0.6-canary.1:
|
/@next/swc-win32-arm64-msvc/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-792QCYO+lF4N1c2bwYVwhLwMJMhnmvQRVOnCmRlGhbaZJ0f6ZuIYCxjqAqV8Por+u0ErenRMv5BGleK8wHfQJA==}
|
resolution: {integrity: sha512-orQDh3ozGZXGWcocHSPy4f3CxIQMUpHfWk87e6bYPqu4g5Xt7SfBIx4RTopovyc5x3rGswV5zvEtn0mrSlPOFA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
@ -946,8 +940,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-win32-ia32-msvc/13.0.6-canary.1:
|
/@next/swc-win32-ia32-msvc/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-hwL9JjT7C1ZP+Wj7F4QIoewEErqc70Ax0aeKqQZdKU57djmIWvvvnyh9p/uUQFHLc3M4Um+XvtqpyFZB6RcYbg==}
|
resolution: {integrity: sha512-GrF/vCKyDUfYOght5lV4RFjV7X+pM8YYrfxo8eBYzSwFW/vWtQCP5m85idNQ/XlJnxUFmhQG9+CCQac+lwKcBQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
@ -955,8 +949,8 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@next/swc-win32-x64-msvc/13.0.6-canary.1:
|
/@next/swc-win32-x64-msvc/13.0.6-canary.2:
|
||||||
resolution: {integrity: sha512-KA6/9W7ZEfkN/ecH8f/fg+WyQaJnRG/UE2IKOdQHbL4uVtHJk5PQmYT+nBZFVnbNHJB2ouNmL4pFJM/7JjNBww==}
|
resolution: {integrity: sha512-zjd7KUJ+wrrWzfR/THoIUGnoa0gnlNV2c07TFk5bFHrjP4VVTQvw1P3wqzx+1bbJB+6O4pwkr6IW3axoy5vtaQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
@ -1070,6 +1064,33 @@ packages:
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: false
|
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:
|
/@radix-ui/react-direction/1.0.0_react@18.2.0:
|
||||||
resolution: {integrity: sha512-2HV05lGUgYcA6xgLQ4BKPDmtL+QbIZYH5fCOTAOOcJ5O0QbWS3i9lKaurLzliYUDhORI2Qr3pyjhJh44lKA3rQ==}
|
resolution: {integrity: sha512-2HV05lGUgYcA6xgLQ4BKPDmtL+QbIZYH5fCOTAOOcJ5O0QbWS3i9lKaurLzliYUDhORI2Qr3pyjhJh44lKA3rQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -1719,6 +1740,18 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
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:
|
/abbrev/1.1.1:
|
||||||
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -5215,7 +5248,7 @@ packages:
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/next-auth/4.17.0_cejjzyjft5qpe7pbv5t5jzassa:
|
/next-auth/4.17.0_hzq4dmqplfkom7c35ucps6atz4:
|
||||||
resolution: {integrity: sha512-aN2tdnjS0MDeUpB2tBDOaWnegkgeMWrsccujbXRGMJ607b+EwRcy63MFGSr0OAboDJEe0902piXQkt94GqF8Qw==}
|
resolution: {integrity: sha512-aN2tdnjS0MDeUpB2tBDOaWnegkgeMWrsccujbXRGMJ607b+EwRcy63MFGSr0OAboDJEe0902piXQkt94GqF8Qw==}
|
||||||
engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0}
|
engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -5231,7 +5264,7 @@ packages:
|
||||||
'@panva/hkdf': 1.0.2
|
'@panva/hkdf': 1.0.2
|
||||||
cookie: 0.5.0
|
cookie: 0.5.0
|
||||||
jose: 4.11.0
|
jose: 4.11.0
|
||||||
next: 13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y
|
next: 13.0.6-canary.2_biqbaboplfbrettd7655fr4n2y
|
||||||
oauth: 0.9.15
|
oauth: 0.9.15
|
||||||
openid-client: 5.3.0
|
openid-client: 5.3.0
|
||||||
preact: 10.11.2
|
preact: 10.11.2
|
||||||
|
@ -5252,8 +5285,8 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/next/13.0.6-canary.1_biqbaboplfbrettd7655fr4n2y:
|
/next/13.0.6-canary.2_biqbaboplfbrettd7655fr4n2y:
|
||||||
resolution: {integrity: sha512-aLHWxU8tMcsVKyStTQvfATZ8TzX/X/VbfV1erVn+pF4uI5+ETvAGWO1geo1FrLzrW+xB/h+9UPAUiqh21oVZEA==}
|
resolution: {integrity: sha512-f8/fUo42tlc+IPE7Yo0dtfW08EEsnLel0cjEqv3OqJwOJfGV3xdJAfvPJz0iyGGMx2ig2TS5VzRL/riyBsa/Gg==}
|
||||||
engines: {node: '>=14.6.0'}
|
engines: {node: '>=14.6.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -5270,7 +5303,7 @@ packages:
|
||||||
sass:
|
sass:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/env': 13.0.6-canary.1
|
'@next/env': 13.0.6-canary.2
|
||||||
'@swc/helpers': 0.4.14
|
'@swc/helpers': 0.4.14
|
||||||
caniuse-lite: 1.0.30001431
|
caniuse-lite: 1.0.30001431
|
||||||
postcss: 8.4.14
|
postcss: 8.4.14
|
||||||
|
@ -5278,19 +5311,19 @@ packages:
|
||||||
react-dom: 18.2.0_react@18.2.0
|
react-dom: 18.2.0_react@18.2.0
|
||||||
styled-jsx: 5.1.0_react@18.2.0
|
styled-jsx: 5.1.0_react@18.2.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@next/swc-android-arm-eabi': 13.0.6-canary.1
|
'@next/swc-android-arm-eabi': 13.0.6-canary.2
|
||||||
'@next/swc-android-arm64': 13.0.6-canary.1
|
'@next/swc-android-arm64': 13.0.6-canary.2
|
||||||
'@next/swc-darwin-arm64': 13.0.6-canary.1
|
'@next/swc-darwin-arm64': 13.0.6-canary.2
|
||||||
'@next/swc-darwin-x64': 13.0.6-canary.1
|
'@next/swc-darwin-x64': 13.0.6-canary.2
|
||||||
'@next/swc-freebsd-x64': 13.0.6-canary.1
|
'@next/swc-freebsd-x64': 13.0.6-canary.2
|
||||||
'@next/swc-linux-arm-gnueabihf': 13.0.6-canary.1
|
'@next/swc-linux-arm-gnueabihf': 13.0.6-canary.2
|
||||||
'@next/swc-linux-arm64-gnu': 13.0.6-canary.1
|
'@next/swc-linux-arm64-gnu': 13.0.6-canary.2
|
||||||
'@next/swc-linux-arm64-musl': 13.0.6-canary.1
|
'@next/swc-linux-arm64-musl': 13.0.6-canary.2
|
||||||
'@next/swc-linux-x64-gnu': 13.0.6-canary.1
|
'@next/swc-linux-x64-gnu': 13.0.6-canary.2
|
||||||
'@next/swc-linux-x64-musl': 13.0.6-canary.1
|
'@next/swc-linux-x64-musl': 13.0.6-canary.2
|
||||||
'@next/swc-win32-arm64-msvc': 13.0.6-canary.1
|
'@next/swc-win32-arm64-msvc': 13.0.6-canary.2
|
||||||
'@next/swc-win32-ia32-msvc': 13.0.6-canary.1
|
'@next/swc-win32-ia32-msvc': 13.0.6-canary.2
|
||||||
'@next/swc-win32-x64-msvc': 13.0.6-canary.1
|
'@next/swc-win32-x64-msvc': 13.0.6-canary.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
|
@ -5977,6 +6010,15 @@ packages:
|
||||||
/react-fast-compare/3.2.0:
|
/react-fast-compare/3.2.0:
|
||||||
resolution: {integrity: sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==}
|
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:
|
/react-hot-toast/2.4.0_biqbaboplfbrettd7655fr4n2y:
|
||||||
resolution: {integrity: sha512-qnnVbXropKuwUpriVVosgo8QrB+IaPJCpL8oBI6Ov84uvHZ5QQcTp2qg6ku2wNfgJl6rlQXJIQU5q+5lmPOutA==}
|
resolution: {integrity: sha512-qnnVbXropKuwUpriVVosgo8QrB+IaPJCpL8oBI6Ov84uvHZ5QQcTp2qg6ku2wNfgJl6rlQXJIQU5q+5lmPOutA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
Loading…
Reference in a new issue