chore: remove the new folder and fix imports (#740)

This commit is contained in:
Mahesh Sanikommu 2026-02-17 03:00:29 +05:30 committed by GitHub
parent 15613c2421
commit 1b1b34fb66
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
106 changed files with 442 additions and 163 deletions

View file

@ -1,6 +1,6 @@
"use client"
import { MobileBanner } from "@/components/new/mobile-banner"
import { MobileBanner } from "@/components/mobile-banner"
export default function AppLayout({ children }: { children: React.ReactNode }) {
return (

View file

@ -2,12 +2,12 @@
import { motion, AnimatePresence } from "motion/react"
import { RelatableQuestion } from "@/components/new/onboarding/setup/relatable-question"
import { IntegrationsStep } from "@/components/new/onboarding/setup/integrations-step"
import { RelatableQuestion } from "@/components/onboarding/setup/relatable-question"
import { IntegrationsStep } from "@/components/onboarding/setup/integrations-step"
import { SetupHeader } from "@/components/new/onboarding/setup/header"
import { ChatSidebar } from "@/components/new/onboarding/setup/chat-sidebar"
import { AnimatedGradientBackground } from "@/components/new/animated-gradient-background"
import { SetupHeader } from "@/components/onboarding/setup/header"
import { ChatSidebar } from "@/components/onboarding/setup/chat-sidebar"
import { AnimatedGradientBackground } from "@/components/animated-gradient-background"
import { useIsMobile } from "@hooks/use-mobile"
import { useSetupContext, type SetupStep } from "./layout"

View file

@ -3,15 +3,15 @@
import { motion, AnimatePresence } from "motion/react"
import { cn } from "@lib/utils"
import { InputStep } from "@/components/new/onboarding/welcome/input-step"
import { GreetingStep } from "@/components/new/onboarding/welcome/greeting-step"
import { WelcomeStep } from "@/components/new/onboarding/welcome/welcome-step"
import { OnboardingContentStep } from "@/components/new/onboarding/welcome/continue-step"
import { InputStep } from "@/components/onboarding/welcome/input-step"
import { GreetingStep } from "@/components/onboarding/welcome/greeting-step"
import { WelcomeStep } from "@/components/onboarding/welcome/welcome-step"
import { OnboardingContentStep } from "@/components/onboarding/welcome/continue-step"
import { InitialHeader } from "@/components/initial-header"
import { Logo } from "@ui/assets/Logo"
import NovaOrb from "@/components/nova/nova-orb"
import { AnimatedGradientBackground } from "@/components/new/animated-gradient-background"
import { AnimatedGradientBackground } from "@/components/animated-gradient-background"
import {
useWelcomeContext,

View file

@ -2,17 +2,17 @@
import { useState, useCallback, useEffect } from "react"
import { useQueryState } from "nuqs"
import { Header } from "@/components/new/header"
import { ChatSidebar } from "@/components/new/chat"
import { MemoriesGrid } from "@/components/new/memories-grid"
import { GraphLayoutView } from "@/components/new/graph-layout-view"
import { IntegrationsView } from "@/components/new/integrations-view"
import { AnimatedGradientBackground } from "@/components/new/animated-gradient-background"
import { AddDocumentModal } from "@/components/new/add-document"
import { DocumentModal } from "@/components/new/document-modal"
import { DocumentsCommandPalette } from "@/components/new/documents-command-palette"
import { FullscreenNoteModal } from "@/components/new/fullscreen-note-modal"
import type { HighlightItem } from "@/components/new/highlights-card"
import { Header } from "@/components/header"
import { ChatSidebar } from "@/components/chat"
import { MemoriesGrid } from "@/components/memories-grid"
import { GraphLayoutView } from "@/components/graph-layout-view"
import { IntegrationsView } from "@/components/integrations-view"
import { AnimatedGradientBackground } from "@/components/animated-gradient-background"
import { AddDocumentModal } from "@/components/add-document"
import { DocumentModal } from "@/components/document-modal"
import { DocumentsCommandPalette } from "@/components/documents-command-palette"
import { FullscreenNoteModal } from "@/components/fullscreen-note-modal"
import type { HighlightItem } from "@/components/highlights-card"
import { HotkeysProvider } from "react-hotkeys-hook"
import { useHotkeys } from "react-hotkeys-hook"
import { AnimatePresence } from "motion/react"
@ -313,7 +313,7 @@ export default function NewPage() {
{isGraphMode && (
<div
id="graph-dotted-grid"
className="absolute inset-0 pointer-events-none bg-[radial-gradient(circle_at_center,#69A7F0_0.1px,transparent_1px)] bg-size-[24px_24px] mask-[radial-gradient(ellipse_at_center,black_60%,transparent_100%)]"
className="absolute inset-0 pointer-events-none bg-[radial-gradient(circle_at_center,rgba(105,167,240,0.25)_1px,transparent_1px)] bg-size-[32px_32px] mask-[radial-gradient(ellipse_at_center,black_60%,transparent_100%)]"
/>
)}
<Header
@ -336,33 +336,33 @@ export default function NewPage() {
>
<div className={cn("relative z-10 flex flex-col md:flex-row h-full")}>
<ErrorBoundary fallback={<ViewErrorFallback />}>
{viewMode === "integrations" ? (
<div className="flex-1 p-4 md:p-6 md:pr-0 pt-2!">
<IntegrationsView />
</div>
) : viewMode === "graph" && !isMobile ? (
<div className="flex-1">
<GraphLayoutView isChatOpen={chatOpen} />
</div>
) : (
<div className="flex-1 p-4 md:p-6 md:pr-0 pt-2!">
<MemoriesGrid
isChatOpen={chatOpen}
onOpenDocument={handleOpenDocument}
quickNoteProps={{
onSave: handleQuickNoteSave,
onMaximize: handleMaximize,
isSaving: noteMutation.isPending,
}}
highlightsProps={{
items: highlightsData?.highlights || [],
onChat: handleHighlightsChat,
onShowRelated: handleHighlightsShowRelated,
isLoading: isLoadingHighlights,
}}
/>
</div>
)}
{viewMode === "integrations" ? (
<div className="flex-1 p-4 md:p-6 md:pr-0 pt-2!">
<IntegrationsView />
</div>
) : viewMode === "graph" && !isMobile ? (
<div className="flex-1">
<GraphLayoutView isChatOpen={chatOpen} />
</div>
) : (
<div className="flex-1 p-4 md:p-6 md:pr-0 pt-2!">
<MemoriesGrid
isChatOpen={chatOpen}
onOpenDocument={handleOpenDocument}
quickNoteProps={{
onSave: handleQuickNoteSave,
onMaximize: handleMaximize,
isSaving: noteMutation.isPending,
}}
highlightsProps={{
items: highlightsData?.highlights || [],
onChat: handleHighlightsChat,
onShowRelated: handleHighlightsShowRelated,
isLoading: isLoadingHighlights,
}}
/>
</div>
)}
</ErrorBoundary>
<div className="hidden md:block md:sticky md:top-0 md:h-screen">
<AnimatePresence mode="popLayout">

View file

@ -7,10 +7,10 @@ import NovaOrb from "@/components/nova/nova-orb"
import { useState, useEffect, useRef } from "react"
import { cn } from "@lib/utils"
import { dmSansClassName } from "@/lib/fonts"
import Account from "@/components/new/settings/account"
import Integrations from "@/components/new/settings/integrations"
import ConnectionsMCP from "@/components/new/settings/connections-mcp"
import Support from "@/components/new/settings/support"
import Account from "@/components/settings/account"
import Integrations from "@/components/settings/integrations"
import ConnectionsMCP from "@/components/settings/connections-mcp"
import Support from "@/components/settings/support"
import { ErrorBoundary } from "@/components/error-boundary"
import { useRouter } from "next/navigation"
import { useIsMobile } from "@hooks/use-mobile"

View file

@ -13,7 +13,7 @@ import { LinkContent, type LinkData } from "./link"
import { FileContent, type FileData } from "./file"
import { useProject } from "@/stores"
import { toast } from "sonner"
import { useDocumentMutations } from "../../../hooks/use-document-mutations"
import { useDocumentMutations } from "../../hooks/use-document-mutations"
import { useCustomer } from "autumn-js/react"
import { useTokenUsage } from "@/hooks/use-token-usage"
import { tokensToCredits, formatUsageNumber } from "@/lib/billing-utils"

View file

@ -36,7 +36,7 @@ import ChatModelSelector from "./model-selector"
import { GradientLogo, LogoBgGradient } from "@ui/assets/Logo"
import { useProject } from "@/stores"
import type { ModelId } from "@/lib/models"
import { SuperLoader } from "../../superloader"
import { SuperLoader } from "../superloader"
import { UserMessage } from "./message/user-message"
import { AgentMessage } from "./message/agent-message"
import { ChainOfThought } from "./input/chain-of-thought"

View file

@ -5,7 +5,7 @@ import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api"
import type { z } from "zod"
import { dmSansClassName } from "@/lib/fonts"
import { cn } from "@lib/utils"
import { DocumentIcon } from "@/components/new/document-icon"
import { DocumentIcon } from "@/components/document-icon"
type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema>
type DocumentWithMemories = DocumentsResponse["documents"][0]

View file

@ -4,10 +4,7 @@ import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api"
import type { z } from "zod"
import { dmSansClassName } from "@/lib/fonts"
import { cn } from "@lib/utils"
import {
DocumentIcon,
getDocumentTypeLabel,
} from "@/components/new/document-icon"
import { DocumentIcon, getDocumentTypeLabel } from "@/components/document-icon"
type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema>
type DocumentWithMemories = DocumentsResponse["documents"][0]

View file

@ -4,7 +4,7 @@ import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api"
import type { z } from "zod"
import { dmSansClassName } from "@/lib/fonts"
import { cn } from "@lib/utils"
import { DocumentIcon } from "@/components/new/document-icon"
import { DocumentIcon } from "@/components/document-icon"
type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema>
type DocumentWithMemories = DocumentsResponse["documents"][0]

View file

@ -1,7 +1,7 @@
"use client"
import type { Tweet } from "react-tweet/api"
import { TweetPreview } from "@/components/new/document-cards/tweet-preview"
import { TweetPreview } from "@/components/document-cards/tweet-preview"
import { ExternalLinkIcon } from "lucide-react"
interface TweetContentProps {

View file

@ -7,4 +7,4 @@ export {
getDocumentIcon,
getDocumentTypeLabel,
type DocumentIconProps,
} from "@/components/new/document-icon"
} from "@/components/document-icon"

View file

@ -1,6 +1,6 @@
import { cn } from "@lib/utils"
import { dmSansClassName } from "@/lib/fonts"
import { DocumentIcon } from "@/components/new/document-icon"
import { DocumentIcon } from "@/components/document-icon"
function getFileExtension(documentType: string): string | null {
switch (documentType) {

View file

@ -13,7 +13,7 @@ import { dmSansClassName } from "@/lib/fonts"
import { useIsMobile } from "@hooks/use-mobile"
import { Dialog, DialogContent, DialogTitle } from "@repo/ui/components/dialog"
import { SearchIcon, Settings, Home, Plus, Code2, Loader2 } from "lucide-react"
import { DocumentIcon } from "@/components/new/document-icon"
import { DocumentIcon } from "@/components/document-icon"
import { $fetch } from "@lib/api"
type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema>

View file

@ -22,7 +22,7 @@ import { Button } from "@ui/components/button"
import { cn } from "@lib/utils"
import { dmSansClassName } from "@/lib/fonts"
import { Tabs, TabsList, TabsTrigger } from "@ui/components/tabs"
import { GraphIcon } from "@/components/new/integration-icons"
import { GraphIcon, IntegrationsIcon } from "@/components/integration-icons"
import {
DropdownMenu,
DropdownMenuContent,
@ -184,7 +184,7 @@ export function Header({ onAddMemory, onOpenChat, onOpenSearch }: HeaderProps) {
dmSansClassName(),
)}
>
<Sun className="size-4" />
<IntegrationsIcon className="size-4" />
Integrations
</TabsTrigger>
</TabsList>

View file

@ -3,6 +3,47 @@ import { Rotate3d } from "lucide-react"
export { Rotate3d as GraphIcon }
export function IntegrationsIcon({ className }: { className?: string }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 22 22"
fill="none"
className={className}
>
<title>Integrations</title>
<path
d="M15.6654 18.0026C16.954 18.0026 17.9987 16.9579 17.9987 15.6693C17.9987 14.3806 16.954 13.3359 15.6654 13.3359C14.3767 13.3359 13.332 14.3806 13.332 15.6693C13.332 16.9579 14.3767 18.0026 15.6654 18.0026Z"
stroke="currentColor"
strokeWidth="1.55556"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6.33333 8.66667C7.622 8.66667 8.66667 7.622 8.66667 6.33333C8.66667 5.04467 7.622 4 6.33333 4C5.04467 4 4 5.04467 4 6.33333C4 7.622 5.04467 8.66667 6.33333 8.66667Z"
stroke="currentColor"
strokeWidth="1.55556"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M11.7773 6.33594H14.1107C14.5232 6.33594 14.9189 6.49983 15.2106 6.79155C15.5023 7.08327 15.6662 7.47893 15.6662 7.89149V13.3359"
stroke="currentColor"
strokeWidth="1.55556"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6.33203 8.66406V17.9974"
stroke="currentColor"
strokeWidth="1.55556"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
export function ChromeIcon({ className }: { className?: string }) {
return (
<svg

View file

@ -4,18 +4,18 @@ import { useState } from "react"
import { cn } from "@lib/utils"
import { dmSansClassName } from "@/lib/fonts"
import { Button } from "@ui/components/button"
import { MCPDetailView } from "@/components/new/mcp-modal/mcp-detail-view"
import { XBookmarksDetailView } from "@/components/new/onboarding/x-bookmarks-detail-view"
import { ChromeDetail } from "@/components/new/integrations/chrome-detail"
import { ShortcutsDetail } from "@/components/new/integrations/shortcuts-detail"
import { RaycastDetail } from "@/components/new/integrations/raycast-detail"
import { ConnectionsDetail } from "@/components/new/integrations/connections-detail"
import { PluginsDetail } from "@/components/new/integrations/plugins-detail"
import { MCPDetailView } from "@/components/mcp-modal/mcp-detail-view"
import { XBookmarksDetailView } from "@/components/onboarding/x-bookmarks-detail-view"
import { ChromeDetail } from "@/components/integrations/chrome-detail"
import { ShortcutsDetail } from "@/components/integrations/shortcuts-detail"
import { RaycastDetail } from "@/components/integrations/raycast-detail"
import { ConnectionsDetail } from "@/components/integrations/connections-detail"
import { PluginsDetail } from "@/components/integrations/plugins-detail"
import {
ChromeIcon,
AppleShortcutsIcon,
RaycastIcon,
} from "@/components/new/integration-icons"
} from "@/components/integration-icons"
import { GoogleDrive, Notion, OneDrive } from "@ui/assets/icons"
import { ArrowLeft, Sun } from "lucide-react"
import Image from "next/image"

View file

@ -2,7 +2,7 @@
import { cn } from "@lib/utils"
import { dmSans125ClassName } from "@/lib/fonts"
import { ChromeIcon } from "@/components/new/integration-icons"
import { ChromeIcon } from "@/components/integration-icons"
import { Check, Download } from "lucide-react"
import { analytics } from "@/lib/analytics"
@ -61,10 +61,7 @@ export function ChromeDetail() {
Chrome Extension
</p>
<p
className={cn(
dmSans125ClassName(),
"text-[14px] text-[#737373]",
)}
className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}
>
Save any webpage directly from your browser
</p>
@ -88,10 +85,7 @@ export function ChromeDetail() {
<div key={text} className="flex items-center gap-2">
<Check className="size-4 shrink-0 text-[#4BA0FA]" />
<span
className={cn(
dmSans125ClassName(),
"text-[14px] text-white",
)}
className={cn(dmSans125ClassName(), "text-[14px] text-white")}
>
{text}
</span>

View file

@ -13,14 +13,18 @@ import { toast } from "sonner"
import type { ConnectionResponseSchema } from "@repo/validation/api"
import type { z } from "zod"
import { analytics } from "@/lib/analytics"
import { AddDocumentModal } from "@/components/new/add-document"
import { AddDocumentModal } from "@/components/add-document"
import { DEFAULT_PROJECT_ID } from "@repo/lib/constants"
import type { Project } from "@repo/lib/types"
type Connection = z.infer<typeof ConnectionResponseSchema>
const CONNECTORS = {
"google-drive": { title: "Google Drive", icon: GoogleDrive, documentLabel: "documents" },
"google-drive": {
title: "Google Drive",
icon: GoogleDrive,
documentLabel: "documents",
},
notion: { title: "Notion", icon: Notion, documentLabel: "pages" },
onedrive: { title: "OneDrive", icon: OneDrive, documentLabel: "documents" },
} as const
@ -44,7 +48,8 @@ function ConnectionRow({
if (!config) return null
const Icon = config.icon
const isConnected = !connection.expiresAt || new Date(connection.expiresAt) > new Date()
const isConnected =
!connection.expiresAt || new Date(connection.expiresAt) > new Date()
const formatRelativeTime = (date: string | null | undefined) => {
if (!date) return "Never"
@ -61,29 +66,63 @@ function ConnectionRow({
const getProjectName = (tag: string): string => {
if (tag === DEFAULT_PROJECT_ID) return "Default Project"
return projects.find((p) => p.containerTag === tag)?.name ?? tag.replace(/^sm_project_/, "")
return (
projects.find((p) => p.containerTag === tag)?.name ??
tag.replace(/^sm_project_/, "")
)
}
const documentCount = (connection.metadata?.documentCount as number) ?? 0
const containerTags = (connection as Connection & { containerTags?: string[] }).containerTags
const projectName = containerTags?.[0] ? getProjectName(containerTags[0]) : null
const containerTags = (
connection as Connection & { containerTags?: string[] }
).containerTags
const projectName = containerTags?.[0]
? getProjectName(containerTags[0])
: null
return (
<div className={cn("bg-[#14161A] border border-[rgba(82,89,102,0.2)] rounded-[12px] px-4 py-3", "shadow-[0px_1px_2px_0px_rgba(0,43,87,0.1)]")}>
<div
className={cn(
"bg-[#14161A] border border-[rgba(82,89,102,0.2)] rounded-[12px] px-4 py-3",
"shadow-[0px_1px_2px_0px_rgba(0,43,87,0.1)]",
)}
>
<div className="flex flex-col gap-3">
<div className="flex items-center gap-4">
<Icon className="size-6 shrink-0" />
<div className="flex-1 flex flex-col gap-1">
<div className="flex items-center gap-3">
<span className={cn(dmSans125ClassName(), "font-medium text-[16px] text-[#FAFAFA]")}>{config.title}</span>
<span
className={cn(
dmSans125ClassName(),
"font-medium text-[16px] text-[#FAFAFA]",
)}
>
{config.title}
</span>
<div className="flex items-center gap-2">
<div className={cn("size-[7px] rounded-full", isConnected ? "bg-[#00AC3F]" : "bg-[#737373]")} />
<span className={cn(dmSans125ClassName(), "text-[14px]", isConnected ? "text-[#00AC3F]" : "text-[#737373]")}>
<div
className={cn(
"size-[7px] rounded-full",
isConnected ? "bg-[#00AC3F]" : "bg-[#737373]",
)}
/>
<span
className={cn(
dmSans125ClassName(),
"text-[14px]",
isConnected ? "text-[#00AC3F]" : "text-[#737373]",
)}
>
{isConnected ? "Connected" : "Disconnected"}
</span>
</div>
</div>
<span className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}>{connection.email || "Unknown"}</span>
<span
className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}
>
{connection.email || "Unknown"}
</span>
</div>
<button
type="button"
@ -97,13 +136,28 @@ function ConnectionRow({
<div className="flex items-center gap-2 flex-wrap">
{projectName && (
<>
<span className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}>Project: {projectName}</span>
<span
className={cn(
dmSans125ClassName(),
"text-[14px] text-[#737373]",
)}
>
Project: {projectName}
</span>
<div className="size-[3px] rounded-full bg-[#737373]" />
</>
)}
<span className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}>Added: {formatRelativeTime(connection.createdAt)}</span>
<span
className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}
>
Added: {formatRelativeTime(connection.createdAt)}
</span>
<div className="size-[3px] rounded-full bg-[#737373]" />
<span className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}>{documentCount} {config.documentLabel} connected</span>
<span
className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}
>
{documentCount} {config.documentLabel} connected
</span>
</div>
</div>
</div>
@ -115,10 +169,13 @@ export function ConnectionsDetail() {
const autumn = useCustomer()
const [isAddDocumentOpen, setIsAddDocumentOpen] = useState(false)
const projects = (queryClient.getQueryData<Project[]>(["projects"]) || []) as Project[]
const projects = (queryClient.getQueryData<Project[]>(["projects"]) ||
[]) as Project[]
const { data: status = { api_pro: { allowed: false, status: null } }, isLoading: isCheckingStatus } =
fetchSubscriptionStatus(autumn, !autumn.isLoading)
const {
data: status = { api_pro: { allowed: false, status: null } },
isLoading: isCheckingStatus,
} = fetchSubscriptionStatus(autumn, !autumn.isLoading)
const hasProProduct = status.api_pro?.status !== null
@ -127,11 +184,18 @@ export function ConnectionsDetail() {
const connectionsLimit = connectionsFeature?.included_usage ?? 10
const canAddConnection = connectionsUsed < connectionsLimit
const { data: connections = [], isLoading: isLoadingConnections, error: connectionsError } = useQuery({
const {
data: connections = [],
isLoading: isLoadingConnections,
error: connectionsError,
} = useQuery({
queryKey: ["connections"],
queryFn: async () => {
const response = await $fetch("@post/connections/list", { body: { containerTags: [] } })
if (response.error) throw new Error(response.error?.message || "Failed to load connections")
const response = await $fetch("@post/connections/list", {
body: { containerTags: [] },
})
if (response.error)
throw new Error(response.error?.message || "Failed to load connections")
return response.data as Connection[]
},
staleTime: 30 * 1000,
@ -142,7 +206,10 @@ export function ConnectionsDetail() {
useEffect(() => {
if (connectionsError) {
toast.error("Failed to load connections", {
description: connectionsError instanceof Error ? connectionsError.message : "Unknown error",
description:
connectionsError instanceof Error
? connectionsError.message
: "Unknown error",
})
}
}, [connectionsError])
@ -153,7 +220,9 @@ export function ConnectionsDetail() {
},
onSuccess: () => {
analytics.connectionDeleted()
toast.success("Connection removal has started. Documents will be permanently deleted in the next few minutes.")
toast.success(
"Connection removal has started. Documents will be permanently deleted in the next few minutes.",
)
queryClient.invalidateQueries({ queryKey: ["connections"] })
},
onError: (error) => {
@ -165,7 +234,10 @@ export function ConnectionsDetail() {
const handleUpgrade = async () => {
try {
await autumn.attach({ productId: "api_pro", successUrl: "https://app.supermemory.ai/?view=integrations" })
await autumn.attach({
productId: "api_pro",
successUrl: "https://app.supermemory.ai/?view=integrations",
})
window.location.reload()
} catch (error) {
console.error(error)
@ -176,21 +248,44 @@ export function ConnectionsDetail() {
return (
<>
<div className={cn("bg-[#14161A] rounded-[14px] p-6 relative overflow-hidden", "shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]")}>
<div
className={cn(
"bg-[#14161A] rounded-[14px] p-6 relative overflow-hidden",
"shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]",
)}
>
{!hasProProduct && !isLoading && (
<>
<div className="absolute inset-0 bg-[#14161A]/80 backdrop-blur-sm z-5" />
<div className="absolute inset-0 flex items-center justify-center z-10">
<div className="flex flex-col items-center gap-4">
<Zap className="size-6 text-[#737373]" />
<p className={cn(dmSans125ClassName(), "text-[14px] text-[#737373] text-center max-w-[220px]")}>
Connect Google Drive, Notion, and OneDrive to import your knowledge
<p
className={cn(
dmSans125ClassName(),
"text-[14px] text-[#737373] text-center max-w-[220px]",
)}
>
Connect Google Drive, Notion, and OneDrive to import your
knowledge
</p>
<div className="flex flex-col gap-2">
{["Unlimited memories", "10 connections", "Advanced search", "Priority support"].map((text) => (
{[
"Unlimited memories",
"10 connections",
"Advanced search",
"Priority support",
].map((text) => (
<div key={text} className="flex items-center gap-2">
<Check className="size-4 shrink-0 text-[#4BA0FA]" />
<span className={cn(dmSans125ClassName(), "text-[14px] text-white")}>{text}</span>
<span
className={cn(
dmSans125ClassName(),
"text-[14px] text-white",
)}
>
{text}
</span>
</div>
))}
</div>
@ -211,12 +306,27 @@ export function ConnectionsDetail() {
</>
)}
<div className={cn("flex flex-col gap-4", !hasProProduct && !isLoading && "opacity-30 pointer-events-none")}>
<div
className={cn(
"flex flex-col gap-4",
!hasProProduct && !isLoading && "opacity-30 pointer-events-none",
)}
>
<div className="flex items-center justify-between">
<span className={cn(dmSans125ClassName(), "font-semibold text-[16px] text-[#FAFAFA]")}>
<span
className={cn(
dmSans125ClassName(),
"font-semibold text-[16px] text-[#FAFAFA]",
)}
>
Connected to Supermemory
</span>
<span className={cn(dmSans125ClassName(), "font-semibold text-[16px] text-[#737373]")}>
<span
className={cn(
dmSans125ClassName(),
"font-semibold text-[16px] text-[#737373]",
)}
>
{connections.length}/{connectionsLimit} connections used
</span>
</div>
@ -231,7 +341,9 @@ export function ConnectionsDetail() {
<ConnectionRow
key={connection.id}
connection={connection}
onDelete={() => deleteConnectionMutation.mutate(connection.id)}
onDelete={() =>
deleteConnectionMutation.mutate(connection.id)
}
isDeleting={deleteConnectionMutation.isPending}
disabled={!hasProProduct}
projects={projects}
@ -240,8 +352,22 @@ export function ConnectionsDetail() {
) : (
<div className="flex flex-col items-center justify-center py-8 text-center">
<Zap className="size-6 text-[#737373] mb-2" />
<p className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}>No connections yet</p>
<p className={cn(dmSans125ClassName(), "text-[12px] text-[#737373]")}>Connect a service below to import your knowledge</p>
<p
className={cn(
dmSans125ClassName(),
"text-[14px] text-[#737373]",
)}
>
No connections yet
</p>
<p
className={cn(
dmSans125ClassName(),
"text-[12px] text-[#737373]",
)}
>
Connect a service below to import your knowledge
</p>
</div>
)}
</div>
@ -260,12 +386,18 @@ export function ConnectionsDetail() {
)}
>
<Plus className="size-[10px] text-[#FAFAFA]" />
<span className="text-[14px] text-[#FAFAFA] font-medium">Connect knowledge bases</span>
<span className="text-[14px] text-[#FAFAFA] font-medium">
Connect knowledge bases
</span>
</button>
</div>
</div>
<AddDocumentModal isOpen={isAddDocumentOpen} onClose={() => setIsAddDocumentOpen(false)} defaultTab="connect" />
<AddDocumentModal
isOpen={isAddDocumentOpen}
onClose={() => setIsAddDocumentOpen(false)}
defaultTab="connect"
/>
</>
)
}

View file

@ -2,7 +2,7 @@
import { cn } from "@lib/utils"
import { dmSans125ClassName } from "@/lib/fonts"
import { RaycastIcon } from "@/components/new/integration-icons"
import { RaycastIcon } from "@/components/integration-icons"
import { authClient } from "@lib/auth"
import { useAuth } from "@lib/auth-context"
import { generateId } from "@lib/generate-id"
@ -101,17 +101,30 @@ export function RaycastDetail() {
<div className="flex items-center gap-4">
<RaycastIcon className="shrink-0 w-10 h-10" />
<div className="flex flex-col gap-1">
<p className={cn(dmSans125ClassName(), "font-semibold text-[16px] text-[#FAFAFA]")}>
<p
className={cn(
dmSans125ClassName(),
"font-semibold text-[16px] text-[#FAFAFA]",
)}
>
Raycast Extension
</p>
<p className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}>
<p
className={cn(
dmSans125ClassName(),
"text-[14px] text-[#737373]",
)}
>
Add and search memories from Mac and Windows
</p>
</div>
</div>
<div className="flex gap-4">
<PillButton onClick={() => createKeyMutation.mutate()} disabled={createKeyMutation.isPending}>
<PillButton
onClick={() => createKeyMutation.mutate()}
disabled={createKeyMutation.isPending}
>
{createKeyMutation.isPending ? (
<Loader className="size-4 text-[#FAFAFA] animate-spin" />
) : (
@ -121,28 +134,49 @@ export function RaycastDetail() {
{createKeyMutation.isPending ? "Generating..." : "Get API key"}
</span>
</PillButton>
<PillButton onClick={() => window.open(RAYCAST_EXTENSION_URL, "_blank")}>
<PillButton
onClick={() => window.open(RAYCAST_EXTENSION_URL, "_blank")}
>
<Download className="size-4 text-[#FAFAFA]" />
<span className="text-[14px] text-[#FAFAFA] font-medium">Install extension</span>
<span className="text-[14px] text-[#FAFAFA] font-medium">
Install extension
</span>
</PillButton>
</div>
</div>
</div>
<Dialog open={showModal} onOpenChange={(open) => {
setShowModal(open)
if (!open) { setApiKey(""); setCopied(false) }
}}>
<Dialog
open={showModal}
onOpenChange={(open) => {
setShowModal(open)
if (!open) {
setApiKey("")
setCopied(false)
}
}}
>
<DialogPortal>
<DialogContent className="bg-[#14161A] border border-white/10 text-[#FAFAFA] md:max-w-md z-100">
<DialogHeader>
<DialogTitle className={cn(dmSans125ClassName(), "text-[#FAFAFA] text-lg font-semibold")}>
<DialogTitle
className={cn(
dmSans125ClassName(),
"text-[#FAFAFA] text-lg font-semibold",
)}
>
Setup Raycast Extension
</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
<label htmlFor={apiKeyId} className={cn(dmSans125ClassName(), "text-sm font-medium text-[#737373]")}>
<label
htmlFor={apiKeyId}
className={cn(
dmSans125ClassName(),
"text-sm font-medium text-[#737373]",
)}
>
Your Raycast API Key
</label>
<div className="flex items-center gap-2">
@ -151,30 +185,51 @@ export function RaycastDetail() {
type="text"
value={apiKey}
readOnly
className={cn("flex-1 bg-[#0D121A] border border-white/10 rounded-lg px-3 py-2 text-sm text-[#FAFAFA] font-mono", dmSans125ClassName())}
className={cn(
"flex-1 bg-[#0D121A] border border-white/10 rounded-lg px-3 py-2 text-sm text-[#FAFAFA] font-mono",
dmSans125ClassName(),
)}
/>
<button
type="button"
onClick={() => handleCopy(apiKey)}
className="p-2 rounded-lg bg-[#0D121A] border border-white/10 text-[#737373] hover:text-[#FAFAFA] transition-colors"
>
{copied ? <Check className="h-4 w-4 text-[#4BA0FA]" /> : <Copy className="h-4 w-4" />}
{copied ? (
<Check className="h-4 w-4 text-[#4BA0FA]" />
) : (
<Copy className="h-4 w-4" />
)}
</button>
</div>
</div>
<div className="space-y-3">
<h4 className={cn(dmSans125ClassName(), "text-sm font-medium text-[#737373]")}>Follow these steps:</h4>
<h4
className={cn(
dmSans125ClassName(),
"text-sm font-medium text-[#737373]",
)}
>
Follow these steps:
</h4>
<div className="space-y-2">
{[
"Install the Raycast extension from the Raycast Store",
"Open Raycast preferences and paste your API key",
"Use \"Add Memory\" or \"Search Memories\" commands!",
'Use "Add Memory" or "Search Memories" commands!',
].map((text, i) => (
<div key={text} className="flex items-start gap-3">
<div className="shrink-0 w-6 h-6 bg-[#FF6363]/20 text-[#FF6363] rounded-full flex items-center justify-center text-xs font-medium">
{i + 1}
</div>
<p className={cn(dmSans125ClassName(), "text-sm text-[#737373]")}>{text}</p>
<p
className={cn(
dmSans125ClassName(),
"text-sm text-[#737373]",
)}
>
{text}
</p>
</div>
))}
</div>

View file

@ -2,7 +2,7 @@
import { cn } from "@lib/utils"
import { dmSans125ClassName } from "@/lib/fonts"
import { AppleShortcutsIcon } from "@/components/new/integration-icons"
import { AppleShortcutsIcon } from "@/components/integration-icons"
import { authClient } from "@lib/auth"
import { useAuth } from "@lib/auth-context"
import { generateId } from "@lib/generate-id"
@ -120,10 +120,20 @@ export function ShortcutsDetail() {
<div className="flex items-center gap-4">
<AppleShortcutsIcon />
<div className="flex flex-col gap-1">
<p className={cn(dmSans125ClassName(), "font-semibold text-[16px] text-[#FAFAFA]")}>
<p
className={cn(
dmSans125ClassName(),
"font-semibold text-[16px] text-[#FAFAFA]",
)}
>
Apple Shortcuts
</p>
<p className={cn(dmSans125ClassName(), "text-[14px] text-[#737373]")}>
<p
className={cn(
dmSans125ClassName(),
"text-[14px] text-[#737373]",
)}
>
Add memories directly from iPhone, iPad or Mac
</p>
</div>
@ -134,13 +144,15 @@ export function ShortcutsDetail() {
onClick={() => handleShortcutClick("add")}
disabled={createApiKeyMutation.isPending}
>
{createApiKeyMutation.isPending && selectedShortcutType === "add" ? (
{createApiKeyMutation.isPending &&
selectedShortcutType === "add" ? (
<Loader className="size-4 text-[#FAFAFA] animate-spin" />
) : (
<Plus className="size-4 text-[#FAFAFA]" />
)}
<span className="text-[14px] text-[#FAFAFA] font-medium">
{createApiKeyMutation.isPending && selectedShortcutType === "add"
{createApiKeyMutation.isPending &&
selectedShortcutType === "add"
? "Creating..."
: "Add memory shortcut"}
</span>
@ -149,13 +161,15 @@ export function ShortcutsDetail() {
onClick={() => handleShortcutClick("search")}
disabled={createApiKeyMutation.isPending}
>
{createApiKeyMutation.isPending && selectedShortcutType === "search" ? (
{createApiKeyMutation.isPending &&
selectedShortcutType === "search" ? (
<Loader className="size-4 text-[#FAFAFA] animate-spin" />
) : (
<Search className="size-4 text-[#FAFAFA]" />
)}
<span className="text-[14px] text-[#FAFAFA] font-medium">
{createApiKeyMutation.isPending && selectedShortcutType === "search"
{createApiKeyMutation.isPending &&
selectedShortcutType === "search"
? "Creating..."
: "Search memory shortcut"}
</span>
@ -164,20 +178,38 @@ export function ShortcutsDetail() {
</div>
</div>
<Dialog open={showApiKeyModal} onOpenChange={(open) => {
setShowApiKeyModal(open)
if (!open) { setSelectedShortcutType(null); setApiKey(""); setCopied(false) }
}}>
<Dialog
open={showApiKeyModal}
onOpenChange={(open) => {
setShowApiKeyModal(open)
if (!open) {
setSelectedShortcutType(null)
setApiKey("")
setCopied(false)
}
}}
>
<DialogPortal>
<DialogContent className="bg-[#14161A] border border-white/10 text-[#FAFAFA] md:max-w-md z-100">
<DialogHeader>
<DialogTitle className={cn(dmSans125ClassName(), "text-[#FAFAFA] text-lg font-semibold")}>
<DialogTitle
className={cn(
dmSans125ClassName(),
"text-[#FAFAFA] text-lg font-semibold",
)}
>
Setup Apple Shortcut
</DialogTitle>
</DialogHeader>
<div className="space-y-4">
<div className="space-y-2">
<label htmlFor={apiKeyId} className={cn(dmSans125ClassName(), "text-sm font-medium text-[#737373]")}>
<label
htmlFor={apiKeyId}
className={cn(
dmSans125ClassName(),
"text-sm font-medium text-[#737373]",
)}
>
Your API Key
</label>
<div className="flex items-center gap-2">
@ -186,26 +218,51 @@ export function ShortcutsDetail() {
type="text"
value={apiKey}
readOnly
className={cn("flex-1 bg-[#0D121A] border border-white/10 rounded-lg px-3 py-2 text-sm text-[#FAFAFA] font-mono", dmSans125ClassName())}
className={cn(
"flex-1 bg-[#0D121A] border border-white/10 rounded-lg px-3 py-2 text-sm text-[#FAFAFA] font-mono",
dmSans125ClassName(),
)}
/>
<button
type="button"
onClick={() => handleCopyApiKey(apiKey)}
className="p-2 rounded-lg bg-[#0D121A] border border-white/10 text-[#737373] hover:text-[#FAFAFA] transition-colors"
>
{copied ? <Check className="h-4 w-4 text-[#4BA0FA]" /> : <Copy className="h-4 w-4" />}
{copied ? (
<Check className="h-4 w-4 text-[#4BA0FA]" />
) : (
<Copy className="h-4 w-4" />
)}
</button>
</div>
</div>
<div className="space-y-3">
<h4 className={cn(dmSans125ClassName(), "text-sm font-medium text-[#737373]")}>Follow these steps:</h4>
<h4
className={cn(
dmSans125ClassName(),
"text-sm font-medium text-[#737373]",
)}
>
Follow these steps:
</h4>
<div className="space-y-2">
{["Click \"Add to Shortcuts\" below to open the shortcut", "Paste your API key when prompted", "Start using your shortcut!"].map((text, i) => (
{[
'Click "Add to Shortcuts" below to open the shortcut',
"Paste your API key when prompted",
"Start using your shortcut!",
].map((text, i) => (
<div key={text} className="flex items-start gap-3">
<div className="shrink-0 w-6 h-6 bg-[#4BA0FA]/20 text-[#4BA0FA] rounded-full flex items-center justify-center text-xs font-medium">
{i + 1}
</div>
<p className={cn(dmSans125ClassName(), "text-sm text-[#737373]")}>{text}</p>
<p
className={cn(
dmSans125ClassName(),
"text-sm text-[#737373]",
)}
>
{text}
</p>
</div>
))}
</div>
@ -222,7 +279,12 @@ export function ShortcutsDetail() {
dmSans125ClassName(),
)}
>
<Image src="/images/ios-shortcuts.png" alt="iOS Shortcuts" width={16} height={16} />
<Image
src="/images/ios-shortcuts.png"
alt="iOS Shortcuts"
width={16}
height={16}
/>
Add to Shortcuts
</button>
</div>

View file

@ -2,8 +2,8 @@
import { useState } from "react"
import { Button } from "@ui/components/button"
import { MCPDetailView } from "@/components/new/mcp-modal/mcp-detail-view"
import { XBookmarksDetailView } from "@/components/new/onboarding/x-bookmarks-detail-view"
import { MCPDetailView } from "@/components/mcp-modal/mcp-detail-view"
import { XBookmarksDetailView } from "@/components/onboarding/x-bookmarks-detail-view"
import { useRouter } from "next/navigation"
import { cn } from "@lib/utils"
import { dmSansClassName } from "@/lib/fonts"

View file

@ -1,7 +1,6 @@
"use client"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
import { useState } from "react"
export const QueryProvider = ({ children }: { children: React.ReactNode }) => {

View file

@ -14,7 +14,7 @@ import type { ConnectionResponseSchema } from "@repo/validation/api"
import type { z } from "zod"
import { analytics } from "@/lib/analytics"
import { ConnectAIModal } from "@/components/connect-ai-modal"
import { AddDocumentModal } from "@/components/new/add-document"
import { AddDocumentModal } from "@/components/add-document"
import { DEFAULT_PROJECT_ID } from "@repo/lib/constants"
import type { Project } from "@repo/lib/types"

View file

@ -28,7 +28,7 @@ import {
ChromeIcon,
AppleShortcutsIcon,
RaycastIcon,
} from "@/components/new/integration-icons"
} from "@/components/integration-icons"
function SectionTitle({ children }: { children: React.ReactNode }) {
return (
@ -111,7 +111,6 @@ function FeatureItem({ text }: { text: string }) {
)
}
export default function Integrations() {
const { org } = useAuth()
const searchParams = useSearchParams()

Some files were not shown because too many files have changed in this diff Show more