mezame 0.8.43

An ACP client that bridges a local agent (Kiro CLI, Claude Agent CLI, Gemini CLI, Codex, ...) to a browser UI over WebSockets.
import { CheckIcon, CopyIcon } from 'lucide-react';
import { useEffect, useState } from 'react';
import { cn } from '@/lib/utils';

type Props = {
  text: string;
  className?: string;
  title?: string;
};

// Small copy-to-clipboard button. Falls back to a hidden textarea +
// execCommand for insecure-context environments (local http over
// non-localhost), though mezame is loopback-only so navigator.clipboard
// should always work in practice.

export const CopyButton = ({ text, className, title = 'Copy' }: Props) => {
  const [copied, setCopied] = useState(false);

  useEffect(() => {
    if (!copied) {
      return;
    }
    const id = window.setTimeout(() => setCopied(false), 1500);
    return () => clearTimeout(id);
  }, [copied]);

  const copy = async () => {
    try {
      if (navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(text);
      } else {
        const ta = document.createElement('textarea');
        ta.value = text;
        ta.style.position = 'fixed';
        ta.style.opacity = '0';
        document.body.appendChild(ta);
        ta.select();
        document.execCommand('copy');
        ta.remove();
      }
      setCopied(true);
    } catch {
      // Clipboard blocked: do nothing, user can select and copy manually.
    }
  };

  return (
    <button
      type="button"
      onClick={copy}
      title={copied ? 'Copied' : title}
      aria-label={copied ? 'Copied' : title}
      className={cn(
        'inline-flex size-6 items-center justify-center rounded-sm border border-border bg-card/80 text-muted-foreground backdrop-blur-sm',
        'transition-colors hover:text-foreground hover:bg-accent',
        'cursor-pointer',
        className
      )}
    >
      {copied ? <CheckIcon className="size-3" /> : <CopyIcon className="size-3" />}
    </button>
  );
};