import { html, css, TemplateResult, CSSResultArray, nothing } from 'lit'; import { customElement, property, query } from 'lit/decorators.js'; import NileElement from '../../internal/nile-element'; /** * Floating link create/edit panel. The host positions it absolutely inside * the editor chrome and listens for: * - `wysiwyg-link-apply` detail: { href, text } * - `wysiwyg-link-remove` * - `wysiwyg-link-cancel` */ @customElement('nile-wysiwyg-link-editor') export class NileWysiwygLinkEditor extends NileElement { @property({ type: Boolean, reflect: true }) open = false; @property({ type: String }) href = ''; @property({ type: String }) text = ''; /** Show the text field (only when creating a link from a cursor). */ @property({ type: Boolean }) allowText = false; /** Show the remove button (when editing an existing link). */ @property({ type: Boolean }) canRemove = false; @query('.link-editor__href') hrefInput?: 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; } .link-editor { display: flex; flex-direction: column; gap: 8px; min-width: 280px; padding: 12px; background: var(--nile-wysiwyg-popover-bg, #ffffff); border: 1px solid var(--nile-wysiwyg-border-color, var(--nile-colors-neutral-400, #d0d5dd)); border-radius: var(--nile-wysiwyg-radius, 8px); box-shadow: var( --nile-wysiwyg-popover-shadow, 0 4px 12px rgba(16, 24, 40, 0.12) ); font-size: 13px; } label { display: flex; flex-direction: column; gap: 4px; color: var(--nile-colors-neutral-700, #344054); } input { font: inherit; padding: 6px 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)); } .link-editor__actions { display: flex; gap: 8px; justify-content: flex-end; } button { font: inherit; padding: 6px 12px; border-radius: 6px; border: 1px solid transparent; cursor: pointer; background: transparent; color: var(--nile-colors-neutral-700, #344054); } button.primary { background: var(--nile-colors-primary-600, var(--ng-componentcolors-utility-blue-600, #2563eb)); color: #ffffff; } button.danger { color: var(--nile-colors-error-600, #d92d20); } `, ]; } /** Focuses the URL field; called by the host after opening. */ public focusInput(): void { this.updateComplete.then(() => this.hrefInput?.focus()); } private handleSubmit(event: Event): void { event.preventDefault(); const href = this.hrefInput?.value.trim() ?? ''; if (!href) return; const textInput = this.shadowRoot?.querySelector('.link-editor__text'); this.emit('wysiwyg-link-apply', { href, text: textInput?.value.trim() ?? '' }); } private handleKeydown(event: KeyboardEvent): void { if (event.key === 'Escape') { event.stopPropagation(); this.emit('wysiwyg-link-cancel'); } } public render(): TemplateResult { return html` `; } } declare global { interface HTMLElementTagNameMap { 'nile-wysiwyg-link-editor': NileWysiwygLinkEditor; } }