← Components/Utility

ClipboardManager

clipboardmanager-1779379195924.tsx
'use client'
import { useState } from 'react'

interface ClipItem {
  id: number
  content: string
  type: 'text' | 'code' | 'url' | 'email'
  pinned: boolean
  time: number
}

const INITIAL: ClipItem[] = [
  { id: 1, content: 'npx empire-ui-mcp --stdio', type: 'code', pinned: true, time: Date.now() - 60000 },
  { id: 2, content: 'https://empire-ui.com/components/glow-button', type: 'url', pinned: false, time: Date.now() - 180000 },
  { id: 3, content: 'business@digital-empire.uk', type: 'email', pinned: true, time: Date.now() - 300000 },
  { id: 4, content: "import GlowButton from '@empire-ui/components'", type: 'code', pinned: false, time: Date.now() - 600000 },
  { id: 5, content: 'Nq8jpnj17EjQaJ3ciJPb7AEH4ZuZueF9', type: 'text', pinned: false, time: Date.now() - 900000 },
]

const TYPE_ICONS = { text: '📝', code: '💻', url: '🔗', email: '📧' }
const TYPE_COLORS = { text: '#64748b', code: '#6366f1', url: '#3b82f6', email: '#22c55e' }

function timeAgo(ms: number) {
  const s = (Date.now() - ms) / 1000
  if (s < 60) return 'just now'
  if (s < 3600) return `${Math.floor(s / 60)}m ago`
  return `${Math.floor(s / 3600)}h ago`
}

export default function ClipboardManager() {
  const [items, setItems] = useState(INITIAL)
  const [filter, setFilter] = useState('')
  const [copied, setCopied] = useState<number | null>(null)

  function copy(item: ClipItem) {
    navigator.clipboard.writeText(item.content)
    setCopied(item.id)
    setTimeout(() => setCopied(null), 1500)
  }

  function togglePin(id: number) {
    setItems(it => it.map(i => i.id === id ? { ...i, pinned: !i.pinned } : i))
  }

  function remove(id: number) {
    setItems(it => it.filter(i => i.id !== id))
  }

  const filtered = items.filter(i => i.content.toLowerCase().includes(filter.toLowerCase()))
  const pinned = filtered.filter(i => i.pinned)
  const unpinned = filtered.filter(i => !i.pinned)

  return (
    <div style={{ background: '#0D0D0D', border: '1px solid rgba(255,255,255,0.06)', borderRadius: 16, overflow: 'hidden', width: 380 }}>
      <div style={{ padding: '14px 16px', borderBottom: '1px solid rgba(255,255,255,0.06)', display: 'flex', gap: 10, alignItems: 'center' }}>
        <span style={{ fontSize: 14 }}>📋</span>
        <input value={filter} onChange={e => setFilter(e.target.value)} placeholder="Search clipboard..."
          style={{ flex: 1, background: 'none', border: 'none', color: '#F5F5F0', fontSize: 13, outline: 'none' }} />
        <span style={{ color: 'rgba(255,255,255,0.3)', fontSize: 12 }}>{items.length} items</span>
      </div>

      <div style={{ maxHeight: 360, overflowY: 'auto' }}>
        {[...pinned, ...unpinned].map((item, i) => (
          <div key={item.id} style={{ padding: '10px 14px', borderBottom: '1px solid rgba(255,255,255,0.04)', background: item.pinned ? 'rgba(201,168,76,0.03)' : 'transparent' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
              <span style={{ fontSize: 12 }}>{TYPE_ICONS[item.type]}</span>
              <span style={{ color: TYPE_COLORS[item.type], fontSize: 10, fontWeight: 600 }}>{item.type}</span>
              {item.pinned && <span style={{ color: '#C9A84C', fontSize: 10 }}>📌</span>}
              <span style={{ marginLeft: 'auto', color: 'rgba(255,255,255,0.25)', fontSize: 10 }}>{timeAgo(item.time)}</span>
            </div>
            <div style={{ color: 'rgba(255,255,255,0.7)', fontSize: 12, fontFamily: item.type === 'code' ? 'monospace' : 'inherit', marginBottom: 8, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{item.content}</div>
            <div style={{ display: 'flex', gap: 6 }}>
              <button onClick={() => copy(item)} style={{ background: copied === item.id ? 'rgba(34,197,94,0.12)' : 'rgba(255,255,255,0.06)', border: '1px solid', borderColor: copied === item.id ? 'rgba(34,197,94,0.25)' : 'rgba(255,255,255,0.08)', color: copied === item.id ? '#22c55e' : '#F5F5F0', borderRadius: 5, padding: '3px 10px', cursor: 'pointer', fontSize: 11 }}>{copied === item.id ? '✓' : 'Copy'}</button>
              <button onClick={() => togglePin(item.id)} style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.07)', color: item.pinned ? '#C9A84C' : 'rgba(255,255,255,0.4)', borderRadius: 5, padding: '3px 8px', cursor: 'pointer', fontSize: 11 }}>{item.pinned ? 'Unpin' : 'Pin'}</button>
              <button onClick={() => remove(item.id)} style={{ marginLeft: 'auto', background: 'none', border: 'none', color: 'rgba(255,255,255,0.2)', cursor: 'pointer', fontSize: 14, padding: '0 4px' }}>×</button>
            </div>
          </div>
        ))}
        {filtered.length === 0 && <div style={{ padding: 20, textAlign: 'center', color: 'rgba(255,255,255,0.3)', fontSize: 13 }}>No results</div>}
      </div>
    </div>
  )
}

Component info

CategoryUtility
Frameworkreact
TierFREE
Views0
Copies0

About

Clipboard history manager with categories, search, pin items, and quick paste shortcuts

More from Utility

'use client'
import { useState } from 'react'

const PRESETS = [
  { name: 'Gold', primary: '#C9A84C', bg: '#0A0A0A', accent: '#6366f1' },
  { name: 'Neon', primary: '#22d3ee', bg: '#030712', accent: '#a78bfa' },
  { name: 'Crimson', primary: '#ef444
ThemeCustomizer
Utility
'use client'
import { useState, useCallback } from 'react'

interface UploadedFile {
  id: number
  name: string
  size: number
  type: string
  progress: number
  done: boolean
  error?: string
}

const ALLOWED = ['image/png', 'image/jpeg', 'image/w
FileUploadZone
Utility