import { html, css, TemplateResult, CSSResultArray } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import NileElement from '../../internal/nile-element'; import '../../nile-input/index'; import '../../nile-button/index'; import '../../nile-button-toggle-group/index'; import '../../nile-button-toggle/index'; /** * Floating math-insert panel: enter a LaTeX expression. Styled to match the * image/embed panels (nile-input + nile-button). Emits `wysiwyg-math-apply` * detail: { latex, display } and `wysiwyg-math-cancel`. Rendering of the * formula itself is the host's job (via a mathRenderer). */ @customElement('nile-wysiwyg-math-panel') export class NileWysiwygMathPanel extends NileElement { @property({ type: Boolean, reflect: true }) open = false; @state() private latexValue = ''; @state() private display: 'inline' | 'block' = 'inline'; 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; } .math-panel { display: flex; flex-direction: column; gap: 12px; min-width: 340px; max-width: 420px; padding: 12px; background: var(--nile-wysiwyg-popover-bg, #ffffff); border: 1px solid var(--nile-colors-neutral-400, #d0d5dd); border-radius: 8px; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); font-size: 13px; } nile-input { width: 100%; } /* Keep the LaTeX field monospaced. */ nile-input::part(input) { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; } .display-row { display: flex; align-items: center; gap: 10px; } .display-label { color: var(--nile-colors-neutral-700, #344054); } .hint { font-size: 12px; color: var(--nile-colors-neutral-500, #98a2b3); } .actions { display: flex; justify-content: flex-end; align-items: center; gap: 8px; width: 100%; } `, ]; } /** Opens with an optional initial value (editing an existing formula). */ public focusInput(initial = ''): void { this.latexValue = initial; this.updateComplete.then(() => { const input = this.shadowRoot?.querySelector('nile-input') as HTMLElement | null; input?.focus(); }); } /** Clears the field. */ public reset(): void { this.latexValue = ''; this.display = 'inline'; } private onLatex(event: CustomEvent): void { this.latexValue = (event.detail?.value ?? '') as string; } private handleSubmit(): void { const latex = this.latexValue.trim(); if (!latex) { this.emit('wysiwyg-math-cancel'); return; } this.emit('wysiwyg-math-apply', { latex, display: this.display }); } private handleKeydown(event: KeyboardEvent): void { if (event.key === 'Escape') { event.stopPropagation(); this.emit('wysiwyg-math-cancel'); } else if (event.key === 'Enter') { event.preventDefault(); event.stopPropagation(); this.handleSubmit(); } } public render(): TemplateResult { return html`