import { html, render } from "/js/lib/lit-html.js"; import { Component } from "/js/components/component.js"; import { classnames, graphemeCount } from "/js/utils.js"; import { scrollLocks } from "/js/scrollLocks.js"; import { closeWithAnimation, resetScrollOnBlur } from "/js/dialogHelpers.js"; import { enableDragToDismiss } from "/js/dragHelpers.js"; import "/js/components/app-icon.js"; class ImageAltTextDialog extends Component { connectedCallback() { if (this.initialized) { return; } this.setAttribute("data-dialog-wrapper", ""); this.scrollLock = null; this.innerHTML = ""; this.render(); this.initialized = true; } set value(value) { this._value = value; if (this.initialized) { this.render(); } } get value() { return this._value || ""; } set placeholder(value) { this._placeholder = value; if (this.initialized) { this.render(); } } get placeholder() { return this._placeholder || "Alt text"; } render() { const currentCharCount = graphemeCount(this.value); const maxChars = 2000; const charCountPercentage = Math.min( Math.round((currentCharCount / maxChars) * 100), 100, ); const isAboveCharLimit = currentCharCount > maxChars; render( html` { if (e.target === e.currentTarget) { this.close(); } }} @cancel=${(event) => { event.preventDefault(); this.close(); }} @close=${() => { this.scrollLock?.release(); this.scrollLock = null; this.dispatchEvent(new CustomEvent("alt-text-dialog-closed")); }} > Add alt text this.close()} > ${this.imageUrl ? html` ` : ""} { this.value = e.target.value; this.render(); }} maxlength="2000" > `, this, ); } open() { this.scrollLock ??= scrollLocks.acquire({ target: this }); const dialog = this.querySelector(".image-alt-text-dialog"); if (dialog?.open) return; dialog.showModal(); this.querySelector(".image-alt-text-dialog-textarea")?.focus({ preventScroll: true, }); enableDragToDismiss(dialog, { onDismiss: () => this.close(), ignoreTouchTarget: (element) => element.closest("button, textarea") !== null, }); resetScrollOnBlur( dialog, this.querySelector(".image-alt-text-dialog-body"), ); } close() { return closeWithAnimation(this.querySelector(".image-alt-text-dialog")); } save() { this.dispatchEvent( new CustomEvent("alt-text-saved", { detail: { altText: this.value, }, }), ); this.close(); } disconnectedCallback() { this.scrollLock?.release(); this.scrollLock = null; } } ImageAltTextDialog.register();