import { html, css, TemplateResult, CSSResultArray } from 'lit'; import { customElement, property, query, state } from 'lit/decorators.js'; import NileElement from '../../internal/nile-element'; import { EMOJI } from '../emoji'; /** * Emoji picker panel (the 😊 toolbar item). Shares the emoji set with the * ":" autocomplete; the search box filters by name. Emits * `wysiwyg-emoji-select` detail: { char } and `wysiwyg-emoji-cancel`. */ @customElement('nile-wysiwyg-emoji-picker') export class NileWysiwygEmojiPicker extends NileElement { @property({ type: Boolean, reflect: true }) open = false; @state() private filter = ''; @query('.emoji-picker__search') searchInput?: HTMLInputElement; public static get styles(): CSSResultArray { return [ css` :host { font-family: var( --nile-font-family-sans-serif, var(--ng-font-family-body, system-ui, -apple-system, sans-serif) ); position: absolute; z-index: 20; display: none; } :host([open]) { display: block; } .panel { width: 316px; padding: 8px; background: var(--nile-wysiwyg-popover-bg, #ffffff); border: 1px solid var(--nile-colors-neutral-400, #d0d5dd); border-radius: 8px; box-shadow: var(--nile-wysiwyg-popover-shadow, 0 4px 12px rgba(16, 24, 40, 0.12)); } input { font: inherit; font-size: 13px; width: 100%; box-sizing: border-box; margin-bottom: 6px; padding: 5px 8px; border: 1px solid var(--nile-colors-neutral-400, #d0d5dd); border-radius: 6px; outline: none; } input:focus { border-color: var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600, #2563eb)); } .grid { display: grid; grid-template-columns: repeat(9, 1fr); gap: 2px; max-height: 200px; overflow-y: auto; overscroll-behavior: contain; } .emoji { font: inherit; font-size: 18px; height: 30px; padding: 0; border: none; border-radius: 5px; background: transparent; cursor: pointer; line-height: 1; } .emoji:hover { background: var(--nile-colors-neutral-100, #f2f4f7); } .empty { padding: 12px 4px; font-size: 12px; color: var(--nile-colors-neutral-500, #98a2b3); text-align: center; } `, ]; } public focusInput(): void { this.filter = ''; this.updateComplete.then(() => { if (this.searchInput) this.searchInput.value = ''; this.searchInput?.focus(); }); } private handleKeydown(event: KeyboardEvent): void { if (event.key === 'Escape') { event.stopPropagation(); this.emit('wysiwyg-emoji-cancel'); } } public render(): TemplateResult { const query = this.filter.trim().toLowerCase(); const shown = query ? EMOJI.filter(e => e.name.includes(query)) : EMOJI; return html`