{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "pricing", "title": "Pricing", "description": "A block for displaying pricing information with a rough styling.", "dependencies": [ "roughjs" ], "registryDependencies": [ "https://www.bydefaulthuman.fun/r/use-rough.json", "utils", "https://www.bydefaulthuman.fun/r/crumble-theme.json", "https://www.bydefaulthuman.fun/r/rough-lib.json", "https://www.bydefaulthuman.fun/r/badge.json", "https://www.bydefaulthuman.fun/r/button.json", "https://www.bydefaulthuman.fun/r/card.json", "https://www.bydefaulthuman.fun/r/seperator.json", "https://www.bydefaulthuman.fun/r/rough-highlight.json" ], "files": [ { "path": "registry/new-york/blocks/NotificationCenterBlock.tsx", "content": "\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Avatar } from \"@/components/crumble/ui/avatar\";\nimport { Badge } from \"@/components/crumble/ui/badge\";\nimport { Button } from \"@/components/crumble/ui/button\";\nimport { Card } from \"@/components/crumble/ui/card\";\nimport { Separator } from \"@/components/crumble/ui/separator\";\nimport { Toggle } from \"@/components/crumble/ui/toggle\";\n\nexport interface Notification {\n body: string;\n fallback: string;\n id: number | string;\n read: boolean;\n time: string;\n title: string;\n type: \"mention\" | \"deploy\" | \"comment\" | \"alert\";\n}\n\nexport interface NotificationCenterBlockProps {\n markAllReadLabel?: string;\n muteLabel?: string;\n notifications?: Notification[];\n onDismiss?: (id: Notification[\"id\"]) => void;\n onMarkAllRead?: () => void;\n onMuteChange?: (muted: boolean) => void;\n title?: string;\n}\n\nconst DEFAULT_NOTIFICATIONS: Notification[] = [\n {\n id: 1,\n fallback: \"AC\",\n title: \"Alice mentioned you\",\n body: \"Can you review the rough tabs refactor before lunch?\",\n time: \"Just now\",\n read: false,\n type: \"mention\",\n },\n {\n id: 2,\n fallback: \"DP\",\n title: \"Production deploy finished\",\n body: \"Version 0.4.2 reached production without rollout errors.\",\n time: \"18 min ago\",\n read: false,\n type: \"deploy\",\n },\n {\n id: 3,\n fallback: \"CD\",\n title: \"New comment on stat-card\",\n body: \"The trend icon alignment is still off at smaller widths.\",\n time: \"1 hr ago\",\n read: true,\n type: \"comment\",\n },\n {\n id: 4,\n fallback: \"!\",\n title: \"Build warning detected\",\n body: \"A type mismatch appeared in the chart package after the last merge.\",\n time: \"3 hr ago\",\n read: true,\n type: \"alert\",\n },\n];\n\nconst TYPE_VARIANT: Record =\n {\n mention: \"default\",\n deploy: \"success\",\n comment: \"outline\",\n alert: \"warning\",\n };\n\nexport function NotificationCenterBlock({\n markAllReadLabel = \"Mark all read\",\n muteLabel = \"Mute\",\n notifications = DEFAULT_NOTIFICATIONS,\n onDismiss,\n onMarkAllRead,\n onMuteChange,\n title = \"Notifications\",\n}: NotificationCenterBlockProps) {\n const [items, setItems] = useState(notifications);\n const [muted, setMuted] = useState(false);\n\n useEffect(() => {\n setItems(notifications);\n }, [notifications]);\n\n const unreadCount = items.filter((item) => !item.read).length;\n\n return (\n \n
\n
\n

{title}

\n {unreadCount > 0 ? {unreadCount} : null}\n
\n {\n setMuted(nextMuted);\n onMuteChange?.(nextMuted);\n }}\n />\n
\n\n
\n {\n setItems((current) => current.map((item) => ({ ...item, read: true })));\n onMarkAllRead?.();\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n {markAllReadLabel}\n \n
\n\n
\n {items.map((item, index) => (\n
\n
\n \n
\n
\n
\n

\n {item.title}\n

\n {item.type}\n
\n {\n setItems((current) => current.filter((notification) => notification.id !== item.id));\n onDismiss?.(item.id);\n }}\n type=\"button\"\n >\n Dismiss\n \n
\n

{item.body}

\n

\n {item.time}\n

\n
\n
\n {index < items.length - 1 ? : null}\n
\n ))}\n
\n
\n );\n}\n", "type": "registry:ui", "target": "components/crumble/blocks/notification-center.tsx" } ], "type": "registry:block" }