mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-09-11 22:51:05 +00:00
- Mobile responsive - new toast design - web document render issue fix - posthog analytics - ui improvements
162 lines
4 KiB
TypeScript
162 lines
4 KiB
TypeScript
"use client"
|
|
|
|
import type { DocumentsWithMemoriesResponseSchema } from "@repo/validation/api"
|
|
import type { z } from "zod"
|
|
import { dmSansClassName } from "@/lib/fonts"
|
|
import { cn } from "@lib/utils"
|
|
import { useMemo } from "react"
|
|
|
|
type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema>
|
|
type DocumentWithMemories = DocumentsResponse["documents"][0]
|
|
|
|
type TipTapNode = {
|
|
type: string
|
|
text?: string
|
|
content?: TipTapNode[]
|
|
attrs?: Record<string, unknown>
|
|
}
|
|
|
|
function extractTextFromTipTapContent(content: string): string {
|
|
try {
|
|
const json = JSON.parse(content) as TipTapNode
|
|
return extractTextFromNode(json)
|
|
} catch {
|
|
return content
|
|
}
|
|
}
|
|
|
|
function extractTextFromNode(node: TipTapNode): string {
|
|
if (node.type === "text" && node.text) {
|
|
return node.text
|
|
}
|
|
|
|
if (!node.content) {
|
|
return ""
|
|
}
|
|
|
|
const texts: string[] = []
|
|
for (const child of node.content) {
|
|
const text = extractTextFromNode(child)
|
|
if (text) {
|
|
texts.push(text)
|
|
}
|
|
}
|
|
|
|
const blockTypes = [
|
|
"paragraph",
|
|
"heading",
|
|
"listItem",
|
|
"blockquote",
|
|
"codeBlock",
|
|
]
|
|
if (blockTypes.includes(node.type)) {
|
|
return `${texts.join("")}\n`
|
|
}
|
|
|
|
return texts.join("")
|
|
}
|
|
|
|
function NoteIcon() {
|
|
return (
|
|
<svg
|
|
width="14"
|
|
height="14"
|
|
viewBox="0 0 14 14"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
>
|
|
<title>Note Icon</title>
|
|
<mask
|
|
id="mask0_344_4970"
|
|
style={{ maskType: "alpha" }}
|
|
maskUnits="userSpaceOnUse"
|
|
x="0"
|
|
y="0"
|
|
width="14"
|
|
height="14"
|
|
>
|
|
<rect width="14" height="14" fill="#D9D9D9" />
|
|
</mask>
|
|
<g mask="url(#mask0_344_4970)">
|
|
<g filter="url(#filter0_i_344_4970)">
|
|
<path
|
|
d="M3.50002 8.75008H7.58335L8.75002 7.58341H3.50002V8.75008ZM3.50002 6.41675H7.00002V5.25008H3.50002V6.41675ZM2.33335 4.08341V9.91675H6.41669L5.25002 11.0834H1.16669V2.91675H12.8334V4.66675H11.6667V4.08341H2.33335ZM13.3584 7.17508C13.407 7.22369 13.4313 7.27716 13.4313 7.3355C13.4313 7.39383 13.407 7.4473 13.3584 7.49591L12.8334 8.02091L11.8125 7.00008L12.3375 6.47508C12.3861 6.42647 12.4396 6.40216 12.4979 6.40216C12.5563 6.40216 12.6097 6.42647 12.6584 6.47508L13.3584 7.17508ZM7.58335 12.2501V11.2292L11.4625 7.35008L12.4834 8.37091L8.60419 12.2501H7.58335Z"
|
|
fill="#FAFAFA"
|
|
/>
|
|
</g>
|
|
</g>
|
|
<defs>
|
|
<filter
|
|
id="filter0_i_344_4970"
|
|
x="1.16669"
|
|
y="2.91675"
|
|
width="12.6176"
|
|
height="9.68628"
|
|
filterUnits="userSpaceOnUse"
|
|
colorInterpolationFilters="sRGB"
|
|
>
|
|
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
|
<feBlend
|
|
mode="normal"
|
|
in="SourceGraphic"
|
|
in2="BackgroundImageFix"
|
|
result="shape"
|
|
/>
|
|
<feColorMatrix
|
|
in="SourceAlpha"
|
|
type="matrix"
|
|
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
|
result="hardAlpha"
|
|
/>
|
|
<feOffset dx="0.353028" dy="0.353028" />
|
|
<feGaussianBlur stdDeviation="0.706055" />
|
|
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1" />
|
|
<feColorMatrix
|
|
type="matrix"
|
|
values="0 0 0 0 0.0431373 0 0 0 0 0.0588235 0 0 0 0 0.0823529 0 0 0 0.4 0"
|
|
/>
|
|
<feBlend
|
|
mode="normal"
|
|
in2="shape"
|
|
result="effect1_innerShadow_344_4970"
|
|
/>
|
|
</filter>
|
|
</defs>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
export function NotePreview({ document }: { document: DocumentWithMemories }) {
|
|
const previewText = useMemo(() => {
|
|
if (!document.content) return ""
|
|
return extractTextFromTipTapContent(document.content).trim()
|
|
}, [document.content])
|
|
|
|
return (
|
|
<div className="bg-[#0B1017] p-3 rounded-[18px] space-y-2">
|
|
<div className="flex items-center gap-1">
|
|
<NoteIcon />
|
|
<p className={cn(dmSansClassName(), "text-[12px] font-semibold")}>
|
|
Note
|
|
</p>
|
|
</div>
|
|
<div>
|
|
{document.title && (
|
|
<p
|
|
className={cn(
|
|
dmSansClassName(),
|
|
"text-[12px] font-semibold line-clamp-2 leading-[125%]",
|
|
)}
|
|
>
|
|
{document.title}
|
|
</p>
|
|
)}
|
|
{previewText && (
|
|
<p className="text-[10px] text-[#737373] line-clamp-4">
|
|
{previewText}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|