Files
backspace/packages/web/src/components/chat/EmojiPicker.tsx
T
Jannis Braun 4d230711fc feat: launch readiness — PWA, API hardening, memory leak fixes, sticker removal
- Add PWA infrastructure: vite-plugin-pwa, manifest, service worker,
  SW update prompt component, placeholder icons, Apple meta tags
- Harden API client: 401 auto-logout, AbortController timeouts
  (30s standard, 120s uploads), onUnauthorized callback
- Fix memory leaks: clear voice user status on leave, clean up all
  Maps (channelToSpaceMap, permissions, etc.) on removeSpace
- Upgrade error boundary to Aether Drift design with Try Again button,
  collapsible stack trace, and componentDidCatch logging
- Configure desktop icon paths in electron-builder.yml
- Remove sticker feature (server routes, schema, types, UI components)
- Fix Docker build: use **/node_modules in .dockerignore to prevent
  COPY from clobbering pnpm-installed workspace dependencies
- Add vite-env.d.ts declarations for noise suppressor wasm imports
- Exclude test files from tsc build via tsconfig
2026-03-15 15:41:22 +01:00

40 lines
1.2 KiB
TypeScript

import React, { useRef, useEffect } from 'react';
import Picker from '@emoji-mart/react';
import data from '@emoji-mart/data';
interface EmojiPickerProps {
onEmojiSelect: (emoji: { native: string }) => void;
}
export function EmojiPicker({ onEmojiSelect }: EmojiPickerProps) {
const containerRef = useRef<HTMLDivElement>(null);
// Prevent keyboard events from bubbling out (e.g. Enter submitting the chat input)
useEffect(() => {
const el = containerRef.current;
if (!el) return;
const stop = (e: KeyboardEvent) => e.stopPropagation();
el.addEventListener('keydown', stop);
return () => el.removeEventListener('keydown', stop);
}, []);
return (
<div ref={containerRef} className="emoji-picker-wrapper">
<Picker
data={data}
onEmojiSelect={onEmojiSelect}
theme="dark"
set="native"
skinTonePosition="search"
previewPosition="none"
navPosition="bottom"
perLine={10}
maxFrequentRows={2}
emojiSize={24}
emojiButtonSize={32}
categories={['frequent', 'people', 'nature', 'foods', 'activity', 'places', 'objects', 'symbols', 'flags']}
/>
</div>
);
}