mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-06 02:47:54 +00:00
feat: add memory modal ui
This commit is contained in:
parent
065316e68b
commit
bf1890e3eb
11 changed files with 529 additions and 34 deletions
|
|
@ -1,29 +1,45 @@
|
|||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Header } from "@/components/new/header"
|
||||
import { ChatSidebar } from "@/components/new/chat"
|
||||
import { AnimatePresence } from "motion/react"
|
||||
import { MemoriesGrid } from "@/components/new/memories-grid"
|
||||
import { AnimatedGradientBackground } from "@/components/new/animated-gradient-background"
|
||||
import { AddDocumentModal } from "@/components/new/add-document"
|
||||
import { HotkeysProvider } from "react-hotkeys-hook"
|
||||
import { useHotkeys } from "react-hotkeys-hook"
|
||||
|
||||
export default function NewPage() {
|
||||
return (
|
||||
<div className="h-screen overflow-hidden bg-black">
|
||||
<AnimatedGradientBackground topPosition="15%" animateFromBottom={false} />
|
||||
<Header />
|
||||
<main className="relative">
|
||||
<div className="relative z-10">
|
||||
<div className="flex flex-row h-[calc(100vh-90px)] relative">
|
||||
<div className="flex-1 flex flex-col justify-start p-6 pr-0">
|
||||
<MemoriesGrid />
|
||||
</div>
|
||||
const [isAddDocumentOpen, setIsAddDocumentOpen] = useState(false)
|
||||
useHotkeys("c", () => setIsAddDocumentOpen(true))
|
||||
|
||||
<AnimatePresence mode="popLayout">
|
||||
<ChatSidebar />
|
||||
</AnimatePresence>
|
||||
return (
|
||||
<HotkeysProvider>
|
||||
<div className="h-screen overflow-hidden bg-black">
|
||||
<AnimatedGradientBackground
|
||||
topPosition="15%"
|
||||
animateFromBottom={false}
|
||||
/>
|
||||
<Header onAddMemory={() => setIsAddDocumentOpen(true)} />
|
||||
<main className="relative">
|
||||
<div className="relative z-10">
|
||||
<div className="flex flex-row h-[calc(100vh-90px)] relative">
|
||||
<div className="flex-1 flex flex-col justify-start p-6 pr-0">
|
||||
<MemoriesGrid />
|
||||
</div>
|
||||
|
||||
<AnimatePresence mode="popLayout">
|
||||
<ChatSidebar />
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</main>
|
||||
<AddDocumentModal
|
||||
isOpen={isAddDocumentOpen}
|
||||
onClose={() => setIsAddDocumentOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
</HotkeysProvider>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
98
apps/web/components/new/add-document/connections.tsx
Normal file
98
apps/web/components/new/add-document/connections.tsx
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import { dmSansClassName } from "@/utils/fonts"
|
||||
import { cn } from "@lib/utils"
|
||||
import { GoogleDrive, Notion, OneDrive } from "@ui/assets/icons"
|
||||
import { Check, Zap } from "lucide-react"
|
||||
|
||||
export function ConnectContent() {
|
||||
const isProUser = true
|
||||
return (
|
||||
<div className="h-full flex flex-col pt-4 space-y-4">
|
||||
<div className="flex items-center justify-between px-2">
|
||||
<p className="text-[16px] font-semibold">Supermemory Connections</p>
|
||||
<span className="bg-[#4BA0FA] text-black text-[12px] font-bold px-1 py-[3px] rounded-[3px]">
|
||||
PRO
|
||||
</span>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<div className="bg-[#14161A] rounded-[12px] px-4 py-3 flex items-center gap-3">
|
||||
<GoogleDrive className="w-6 h-6 text-[#737373]" />
|
||||
<div className="space-y-[6px]">
|
||||
<p className="text-[16px] font-medium">Google Drive</p>
|
||||
<p className="text-[16px] text-[#737373]">
|
||||
Connect your Google docs, sheets and slides
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-[#14161A] rounded-[12px] px-4 py-3 flex items-center gap-3">
|
||||
<Notion className="w-6 h-6 text-[#737373]" />
|
||||
<div className="space-y-[6px]">
|
||||
<p className="text-[16px] font-medium">Notion</p>
|
||||
<p className="text-[16px] text-[#737373]">
|
||||
Import your Notion pages and databases
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-[#14161A] rounded-[12px] px-4 py-3 flex items-center gap-3">
|
||||
<OneDrive className="w-6 h-6 text-[#737373]" />
|
||||
<div className="space-y-[6px]">
|
||||
<p className="text-[16px] font-medium">OneDrive</p>
|
||||
<p className="text-[16px] text-[#737373]">
|
||||
Access your Microsoft Office documents
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="no-active-connections"
|
||||
className="bg-[#14161A] shadow-inside-out rounded-[12px] px-4 py-6 h-full mb-4 flex flex-col justify-center items-center"
|
||||
>
|
||||
<Zap className="w-6 h-6 text-[#737373] mb-3" />
|
||||
{!isProUser ? (
|
||||
<>
|
||||
<p className="text-[14px] text-[#737373] mb-4 text-center">
|
||||
<a
|
||||
href="/pricing"
|
||||
className="underline text-[#737373] hover:text-white"
|
||||
>
|
||||
Upgrade to Pro
|
||||
</a>{" "}
|
||||
to get
|
||||
<br />
|
||||
Supermemory Connections
|
||||
</p>
|
||||
<div className="space-y-2 text-[14px]">
|
||||
<div className="flex items-center gap-2">
|
||||
<Check className="w-4 h-4 text-[#4BA0FA]" />
|
||||
<span>Unlimited memories</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Check className="w-4 h-4 text-[#4BA0FA]" />
|
||||
<span>10 connections</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Check className="w-4 h-4 text-[#4BA0FA]" />
|
||||
<span>Advanced search</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Check className="w-4 h-4 text-[#4BA0FA]" />
|
||||
<span>Priority support</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div
|
||||
className={cn(
|
||||
"text-[#737373] text-center max-w-[174px] font-medium",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
>
|
||||
<p>No connections yet</p>
|
||||
<p className="text-[12px]">
|
||||
Choose a service above to import your knowledge
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
96
apps/web/components/new/add-document/file.tsx
Normal file
96
apps/web/components/new/add-document/file.tsx
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
import { useState } from "react"
|
||||
import { cn } from "@lib/utils"
|
||||
import { dmSansClassName } from "@/utils/fonts"
|
||||
import { FileIcon } from "lucide-react"
|
||||
|
||||
export function FileContent() {
|
||||
const [isDragging, setIsDragging] = useState(false)
|
||||
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
||||
|
||||
const handleDragOver = (e: React.DragEvent) => {
|
||||
e.preventDefault()
|
||||
setIsDragging(true)
|
||||
}
|
||||
|
||||
const handleDragLeave = (e: React.DragEvent) => {
|
||||
e.preventDefault()
|
||||
setIsDragging(false)
|
||||
}
|
||||
|
||||
const handleDrop = (e: React.DragEvent) => {
|
||||
e.preventDefault()
|
||||
setIsDragging(false)
|
||||
const file = e.dataTransfer.files[0]
|
||||
if (file) {
|
||||
setSelectedFile(file)
|
||||
}
|
||||
}
|
||||
|
||||
const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0]
|
||||
if (file) {
|
||||
setSelectedFile(file)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn("h-full flex flex-col gap-6 pt-4", dmSansClassName())}>
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-[16px] font-medium pl-2">
|
||||
Upload a file (image, pdf, document, sheet)
|
||||
</p>
|
||||
<label
|
||||
onDragOver={handleDragOver}
|
||||
onDragLeave={handleDragLeave}
|
||||
onDrop={handleDrop}
|
||||
className={cn(
|
||||
"relative flex flex-col items-center justify-center gap-3 p-8 rounded-[14px] bg-[#14161A] shadow-inside-out border-2 border-dashed cursor-pointer transition-all",
|
||||
isDragging
|
||||
? "border-[#4BA0FA] bg-[#4BA0FA]/10"
|
||||
: "border-[#737373]/30 hover:border-[#737373]/50",
|
||||
)}
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
onChange={handleFileSelect}
|
||||
className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
|
||||
accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.csv,.txt"
|
||||
/>
|
||||
<div className="flex items-center justify-center w-12 h-12 rounded-full bg-[#0F1217]">
|
||||
<FileIcon className="size-6 text-[#737373]" />
|
||||
</div>
|
||||
{selectedFile ? (
|
||||
<div className="text-center">
|
||||
<p className="text-white font-medium">{selectedFile.name}</p>
|
||||
<p className="text-[#737373] text-sm">
|
||||
{(selectedFile.size / 1024 / 1024).toFixed(2)} MB
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center">
|
||||
<p className="text-white">
|
||||
<span className="text-[#4BA0FA]">Click to upload</span> or drag
|
||||
and drop
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-[14px] font-semibold pl-2">Title (optional)</p>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Give this file a title"
|
||||
className="w-full p-4 rounded-[14px] bg-[#14161A] shadow-inside-out"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-[14px] font-semibold pl-2">Description (optional)</p>
|
||||
<textarea
|
||||
placeholder="Add notes or context about this file"
|
||||
className="w-full p-4 rounded-[14px] bg-[#14161A] shadow-inside-out"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
207
apps/web/components/new/add-document/index.tsx
Normal file
207
apps/web/components/new/add-document/index.tsx
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Dialog, DialogContent } from "@repo/ui/components/dialog"
|
||||
import { cn } from "@lib/utils"
|
||||
import { dmSansClassName } from "@/utils/fonts"
|
||||
import {
|
||||
FileTextIcon,
|
||||
GlobeIcon,
|
||||
ZapIcon,
|
||||
ChevronsUpDownIcon,
|
||||
} from "lucide-react"
|
||||
import { Button } from "@ui/components/button"
|
||||
import { ConnectContent } from "./connections"
|
||||
import { NoteContent } from "./note"
|
||||
import { LinkContent } from "./link"
|
||||
import { FileContent } from "./file"
|
||||
|
||||
interface AddDocumentModalProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export function AddDocumentModal({ isOpen, onClose }: AddDocumentModalProps) {
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
|
||||
<DialogContent
|
||||
className={cn(
|
||||
"w-[80%]! max-w-[1000px]! h-[80%]! max-h-[800px]! border-none bg-[#1B1F24] flex flex-col p-4 gap-3 rounded-[22px]",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
style={{
|
||||
boxShadow:
|
||||
"0 2.842px 14.211px 0 rgba(0, 0, 0, 0.25), 0.711px 0.711px 0.711px 0 rgba(255, 255, 255, 0.10) inset",
|
||||
}}
|
||||
showCloseButton={false}
|
||||
>
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<AddDocument />
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
type TabType = "note" | "link" | "file" | "connect"
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
id: "note" as const,
|
||||
icon: FileTextIcon,
|
||||
title: "Write a note",
|
||||
description: "Save your thoughts, notes and summaries, as memories",
|
||||
},
|
||||
{
|
||||
id: "link" as const,
|
||||
icon: GlobeIcon,
|
||||
title: "Save a link",
|
||||
description: "Add any webpage into your searchable knowledge base",
|
||||
},
|
||||
{
|
||||
id: "file" as const,
|
||||
icon: FileTextIcon,
|
||||
title: "Upload a file",
|
||||
description: "Turn any image, PDF or document into contextual memories",
|
||||
},
|
||||
{
|
||||
id: "connect" as const,
|
||||
icon: ZapIcon,
|
||||
title: "Connect knowledge bases",
|
||||
description: "Sync with Google Drive, Notion and OneDrive and import data",
|
||||
isPro: true,
|
||||
},
|
||||
]
|
||||
|
||||
export function AddDocument() {
|
||||
const [activeTab, setActiveTab] = useState<TabType>("note")
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-row text-white space-x-6">
|
||||
{/* Tabs - 1/3 width */}
|
||||
<div className="w-1/3 flex flex-col justify-between">
|
||||
<div className="flex flex-col gap-1">
|
||||
{tabs.map((tab) => (
|
||||
<TabButton
|
||||
key={tab.id}
|
||||
active={activeTab === tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
icon={tab.icon}
|
||||
title={tab.title}
|
||||
description={tab.description}
|
||||
isPro={tab.isPro}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Memories counter */}
|
||||
<div
|
||||
className="bg-[#1B1F24] rounded-2xl p-4 mr-4"
|
||||
style={{
|
||||
boxShadow:
|
||||
"0 2.842px 14.211px 0 rgba(0, 0, 0, 0.25), 0.711px 0.711px 0.711px 0 rgba(255, 255, 255, 0.10) inset",
|
||||
}}
|
||||
>
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<span
|
||||
className={cn(
|
||||
"text-white text-[16px] font-medium",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
>
|
||||
Memories
|
||||
</span>
|
||||
<span className={cn("text-[#737373] text-sm", dmSansClassName())}>
|
||||
120/200
|
||||
</span>
|
||||
</div>
|
||||
<div className="h-1.5 bg-[#0D121A] rounded-full overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-[#2261CA] rounded-full"
|
||||
style={{ width: "60%" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content - 2/3 width */}
|
||||
<div className="w-2/3 overflow-auto flex flex-col justify-between">
|
||||
{activeTab === "note" && <NoteContent />}
|
||||
{activeTab === "link" && <LinkContent />}
|
||||
{activeTab === "file" && <FileContent />}
|
||||
{activeTab === "connect" && <ConnectContent />}
|
||||
<div className="flex justify-between">
|
||||
<Button variant="insideOut">
|
||||
My Space <ChevronsUpDownIcon className="size-4" color="#737373" />
|
||||
</Button>
|
||||
<div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="text-[#737373] hover:bg-none! cursor-pointer"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
{activeTab !== "connect" && (
|
||||
<Button variant="insideOut">
|
||||
+ Add {activeTab}{" "}
|
||||
<span
|
||||
className={cn(
|
||||
"bg-[#21212180] border border-[#73737333] text-[#737373] rounded-sm px-1 py-0.5 text-[10px] flex items-center justify-center",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
>
|
||||
⌘+Enter
|
||||
</span>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function TabButton({
|
||||
active,
|
||||
onClick,
|
||||
icon: Icon,
|
||||
title,
|
||||
description,
|
||||
isPro,
|
||||
}: {
|
||||
active: boolean
|
||||
onClick: () => void
|
||||
icon: React.ComponentType<{ className?: string }>
|
||||
title: string
|
||||
description: string
|
||||
isPro?: boolean
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className={cn(
|
||||
"flex items-start gap-3 p-4 rounded-[16px] text-left transition-colors w-full",
|
||||
active
|
||||
? "bg-[#14161A] shadow-inside-out"
|
||||
: "hover:bg-[#14161A]/50 hover:shadow-[inset_0_2px_4px_rgba(0,0,0,0.3),inset_0_1px_2px_rgba(0,0,0,0.1)]",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
>
|
||||
<Icon className={cn("size-5 mt-0.5 shrink-0 text-white")} />
|
||||
<div className="flex flex-col gap-0.5 text-[16px]">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className={cn("font-medium text-white", dmSansClassName())}>
|
||||
{title}
|
||||
</span>
|
||||
{isPro && (
|
||||
<span className="bg-[#4BA0FA] text-black text-[10px] font-semibold px-1.5 py-0.5 rounded">
|
||||
PRO
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="text-[#737373]">{description}</span>
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
58
apps/web/components/new/add-document/link.tsx
Normal file
58
apps/web/components/new/add-document/link.tsx
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { cn } from "@lib/utils"
|
||||
import { Button } from "@ui/components/button"
|
||||
import { dmSansClassName } from "@/utils/fonts"
|
||||
|
||||
export function LinkContent() {
|
||||
return (
|
||||
<div className={cn("flex flex-col space-y-4 pt-4", dmSansClassName())}>
|
||||
<div>
|
||||
<p
|
||||
className={cn("text-[16px] font-medium pl-2 pb-2", dmSansClassName())}
|
||||
>
|
||||
Paste a link to turn it into a memory
|
||||
</p>
|
||||
<div className="flex relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="https://maheshthedev.me"
|
||||
className={cn(
|
||||
"w-full p-4 rounded-xl bg-[#14161A] shadow-inside-out",
|
||||
)}
|
||||
/>
|
||||
<Button variant="linkPreview" className="absolute right-2 top-2">
|
||||
Preview Link
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-[#14161A] rounded-[14px] py-6 px-4 space-y-4 shadow-inside-out">
|
||||
<div>
|
||||
<p className="pl-2 pb-2 font-semibold text-[16px] text-[#737373]">
|
||||
Link title
|
||||
</p>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Mahesh Sanikommu - Portfolio"
|
||||
className="w-full px-4 py-3 bg-[#0F1217] rounded-xl"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="pl-2 pb-2 font-semibold text-[16px] text-[#737373]">
|
||||
Link description
|
||||
</p>
|
||||
<textarea
|
||||
placeholder="Portfolio website of Mahesh Sanikommu"
|
||||
className="w-full px-4 py-3 bg-[#0F1217] rounded-xl"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="pl-2 pb-2 font-semibold text-[16px] text-[#737373]">
|
||||
Link Preview
|
||||
</p>
|
||||
<div className="w-full px-4 py-3 bg-[#0F1217] rounded-xl">
|
||||
<p>Portfolio website of Mahesh Sanikommu</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
8
apps/web/components/new/add-document/note.tsx
Normal file
8
apps/web/components/new/add-document/note.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export function NoteContent() {
|
||||
return (
|
||||
<textarea
|
||||
placeholder="Write your note here..."
|
||||
className="w-full h-full p-4 mb-4! rounded-[14px] bg-[#14161A] shadow-inside-out resize-none"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -37,7 +37,11 @@ interface Project {
|
|||
isExperimental?: boolean
|
||||
}
|
||||
|
||||
export function Header() {
|
||||
interface HeaderProps {
|
||||
onAddMemory?: () => void
|
||||
}
|
||||
|
||||
export function Header({ onAddMemory }: HeaderProps) {
|
||||
const { user } = useAuth()
|
||||
const [name, setName] = useState<string>("")
|
||||
const projectName = useProjectName()
|
||||
|
|
@ -151,7 +155,8 @@ export function Header() {
|
|||
<div className="flex items-center gap-2 z-10!">
|
||||
<Button
|
||||
variant="headers"
|
||||
className="rounded-full text-base gap-2 !h-10"
|
||||
className="rounded-full text-base gap-2 h-10!"
|
||||
onClick={onAddMemory}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Plus className="size-4" />
|
||||
|
|
@ -168,7 +173,7 @@ export function Header() {
|
|||
</Button>
|
||||
<Button
|
||||
variant="headers"
|
||||
className="rounded-full text-base gap-2 !h-10"
|
||||
className="rounded-full text-base gap-2 h-10!"
|
||||
>
|
||||
<SearchIcon className="size-4" />
|
||||
<span className="bg-[#21212180] border border-[#73737333] text-[#737373] rounded-sm text-[10px] flex items-center justify-center gap-0.5 px-1">
|
||||
|
|
|
|||
|
|
@ -82,3 +82,9 @@
|
|||
margin-left: 0;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
.shadow-inside-out {
|
||||
box-shadow:
|
||||
inset 0 2px 4px rgba(0, 0, 0, 0.3),
|
||||
inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,9 @@
|
|||
"react": "19.2.2",
|
||||
"react-dom": "19.2.2",
|
||||
"react-dropzone": "^14.3.8",
|
||||
"react-pdf": "^10.2.0",
|
||||
"react-hotkeys-hook": "^5.2.1",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-pdf": "^10.2.0",
|
||||
"react-tweet": "^3.2.2",
|
||||
"recharts": "2",
|
||||
"slate": "^0.118.0",
|
||||
|
|
|
|||
19
bun.lock
19
bun.lock
|
|
@ -196,6 +196,7 @@
|
|||
"react": "19.2.2",
|
||||
"react-dom": "19.2.2",
|
||||
"react-dropzone": "^14.3.8",
|
||||
"react-hotkeys-hook": "^5.2.1",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-pdf": "^10.2.0",
|
||||
"react-tweet": "^3.2.2",
|
||||
|
|
@ -1546,7 +1547,7 @@
|
|||
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="],
|
||||
|
||||
"@smithy/util-waiter": ["@smithy/util-waiter@2.2.0", "", { "dependencies": { "@smithy/abort-controller": "^2.2.0", "@smithy/types": "^2.12.0", "tslib": "^2.6.2" } }, "sha512-IHk53BVw6MPMi2Gsn+hCng8rFA3ZmR3Rk7GllxDUW9qFJl/hiSvskn7XldkECapQVkIg/1dHpMAxI9xSTaLLSA=="],
|
||||
"@smithy/util-waiter": ["@smithy/util-waiter@4.2.7", "", { "dependencies": { "@smithy/abort-controller": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-vHJFXi9b7kUEpHWUCY3Twl+9NPOZvQ0SAi+Ewtn48mbiJk4JY9MZmKQjGB4SCvVb9WPiSphZJYY6RIbs+grrzw=="],
|
||||
|
||||
"@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="],
|
||||
|
||||
|
|
@ -3786,6 +3787,8 @@
|
|||
|
||||
"react-dropzone": ["react-dropzone@14.3.8", "", { "dependencies": { "attr-accept": "^2.2.4", "file-selector": "^2.1.0", "prop-types": "^15.8.1" }, "peerDependencies": { "react": ">= 16.8 || 18.0.0" } }, "sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug=="],
|
||||
|
||||
"react-hotkeys-hook": ["react-hotkeys-hook@5.2.1", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg=="],
|
||||
|
||||
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
|
||||
"react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="],
|
||||
|
|
@ -4630,14 +4633,10 @@
|
|||
|
||||
"@aws-sdk/client-cloudfront/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@aws-sdk/client-cloudfront/@smithy/util-waiter": ["@smithy/util-waiter@2.2.0", "", { "dependencies": { "@smithy/abort-controller": "^2.2.0", "@smithy/types": "^2.12.0", "tslib": "^2.6.2" } }, "sha512-IHk53BVw6MPMi2Gsn+hCng8rFA3ZmR3Rk7GllxDUW9qFJl/hiSvskn7XldkECapQVkIg/1dHpMAxI9xSTaLLSA=="],
|
||||
|
||||
"@aws-sdk/client-cloudfront/fast-xml-parser": ["fast-xml-parser@4.2.5", "", { "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g=="],
|
||||
|
||||
"@aws-sdk/client-dynamodb/@smithy/util-waiter": ["@smithy/util-waiter@4.2.7", "", { "dependencies": { "@smithy/abort-controller": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-vHJFXi9b7kUEpHWUCY3Twl+9NPOZvQ0SAi+Ewtn48mbiJk4JY9MZmKQjGB4SCvVb9WPiSphZJYY6RIbs+grrzw=="],
|
||||
|
||||
"@aws-sdk/client-lambda/@smithy/util-waiter": ["@smithy/util-waiter@4.2.7", "", { "dependencies": { "@smithy/abort-controller": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-vHJFXi9b7kUEpHWUCY3Twl+9NPOZvQ0SAi+Ewtn48mbiJk4JY9MZmKQjGB4SCvVb9WPiSphZJYY6RIbs+grrzw=="],
|
||||
|
||||
"@aws-sdk/client-s3/@smithy/util-waiter": ["@smithy/util-waiter@4.2.7", "", { "dependencies": { "@smithy/abort-controller": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-vHJFXi9b7kUEpHWUCY3Twl+9NPOZvQ0SAi+Ewtn48mbiJk4JY9MZmKQjGB4SCvVb9WPiSphZJYY6RIbs+grrzw=="],
|
||||
|
||||
"@aws-sdk/client-sts/@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@3.0.0", "", { "dependencies": { "@aws-crypto/ie11-detection": "^3.0.0", "@aws-crypto/sha256-js": "^3.0.0", "@aws-crypto/supports-web-crypto": "^3.0.0", "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@aws-sdk/util-utf8-browser": "^3.0.0", "tslib": "^1.11.1" } }, "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ=="],
|
||||
|
||||
"@aws-sdk/client-sts/@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@3.0.0", "", { "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", "tslib": "^1.11.1" } }, "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ=="],
|
||||
|
|
@ -4980,10 +4979,6 @@
|
|||
|
||||
"@sindresorhus/transliterate/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
|
||||
"@smithy/util-waiter/@smithy/abort-controller": ["@smithy/abort-controller@2.2.0", "", { "dependencies": { "@smithy/types": "^2.12.0", "tslib": "^2.6.2" } }, "sha512-wRlta7GuLWpTqtFfGo+nZyOO1vEvewdNR1R4rTxpC8XU6vG/NDyrFBhwLZsqg1NUoR1noVaXJPC/7ZK47QCySw=="],
|
||||
|
||||
"@smithy/util-waiter/@smithy/types": ["@smithy/types@2.12.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw=="],
|
||||
|
||||
"@stoplight/better-ajv-errors/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
|
||||
|
||||
"@stoplight/better-ajv-errors/leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
|
||||
|
|
@ -5608,6 +5603,8 @@
|
|||
|
||||
"@aws-sdk/client-cloudfront/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@aws-sdk/client-cloudfront/@smithy/util-waiter/@smithy/abort-controller": ["@smithy/abort-controller@2.2.0", "", { "dependencies": { "@smithy/types": "^2.12.0", "tslib": "^2.6.2" } }, "sha512-wRlta7GuLWpTqtFfGo+nZyOO1vEvewdNR1R4rTxpC8XU6vG/NDyrFBhwLZsqg1NUoR1noVaXJPC/7ZK47QCySw=="],
|
||||
|
||||
"@aws-sdk/client-cloudfront/fast-xml-parser/strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="],
|
||||
|
||||
"@aws-sdk/client-sts/@aws-crypto/sha256-browser/@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@3.0.0", "", { "dependencies": { "tslib": "^1.11.1" } }, "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg=="],
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ const buttonVariants = cva(
|
|||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
" text-primary-foreground shadow-xs hover:bg-primary/90",
|
||||
default: " text-primary-foreground shadow-xs hover:bg-primary/90",
|
||||
newDefault:
|
||||
"bg-gradient-to-b from-[#1C2026] to-[#12161C] text-white shadow-[inset_-2px_-2px_6px_0_rgba(0,0,0,0.15),inset_2px_2px_4px_0_rgba(255,255,255,0.05)] hover:from-[#1C2026]/90 hover:to-[#12161C]/90",
|
||||
destructive:
|
||||
|
|
@ -24,7 +23,11 @@ const buttonVariants = cva(
|
|||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
settingsNav: "cursor-pointer rounded-sm bg-transparent",
|
||||
onboarding: "rounded-xl !px-6 !py-3 bg-black border border-[#161F2C] hover:bg-[#161F2C] !h-[40px] cursor-pointer text-white",
|
||||
onboarding:
|
||||
"rounded-xl !px-6 !py-3 bg-black border border-[#161F2C] hover:bg-[#161F2C] !h-[40px] cursor-pointer text-white",
|
||||
linkPreview:
|
||||
"rounded-xl !px-3 !py-1 bg-black border border-[#161F2C] hover:bg-[#161F2C] cursor-pointer text-white border border-[#161F2C]",
|
||||
insideOut: "shadow-inside-out rounded-full bg-[#0D121A]",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue