import { customElement, html, DeesElement, type TemplateResult, cssManager, css, state, } from '@design.estate/dees-element'; import { WysiwygFormatting } from './wysiwyg.formatting.js'; declare global { interface HTMLElementTagNameMap { 'dees-formatting-menu': DeesFormattingMenu; } } @customElement('dees-formatting-menu') export class DeesFormattingMenu extends DeesElement { private static instance: DeesFormattingMenu; public static getInstance(): DeesFormattingMenu { if (!DeesFormattingMenu.instance) { DeesFormattingMenu.instance = new DeesFormattingMenu(); document.body.appendChild(DeesFormattingMenu.instance); } return DeesFormattingMenu.instance; } @state() public visible: boolean = false; @state() private position: { x: number; y: number } = { x: 0, y: 0 }; private callback: ((command: string) => void | Promise) | null = null; public static styles = [ cssManager.defaultStyles, css` :host { position: fixed; z-index: 10000; pointer-events: none; } .formatting-menu { position: absolute; background: ${cssManager.bdTheme('#ffffff', '#262626')}; border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#404040')}; border-radius: 6px; box-shadow: 0 2px 16px rgba(0, 0, 0, 0.15); padding: 4px; display: flex; gap: 2px; pointer-events: auto; user-select: none; animation: fadeInScale 0.15s ease-out; } @keyframes fadeInScale { from { opacity: 0; transform: scale(0.95) translateY(5px); } to { opacity: 1; transform: scale(1) translateY(0); } } .format-button { width: 32px; height: 32px; border: none; background: transparent; cursor: pointer; border-radius: 4px; transition: all 0.15s ease; display: flex; align-items: center; justify-content: center; color: ${cssManager.bdTheme('#000000', '#e0e0e0')}; font-weight: 600; font-size: 14px; position: relative; } .format-button:hover { background: ${cssManager.bdTheme('#f0f0f0', '#333333')}; color: ${cssManager.bdTheme('#0066cc', '#4d94ff')}; } .format-button:active { transform: scale(0.95); } .format-button.bold { font-weight: 700; } .format-button.italic { font-style: italic; } .format-button.underline { text-decoration: underline; } .format-button .code-icon { font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace; font-size: 12px; } `, ]; render(): TemplateResult { if (!this.visible) return html``; return html`
${WysiwygFormatting.formatButtons.map(button => html` `)}
`; } private applyFormat(command: string): void { if (this.callback) { this.callback(command); } // Don't hide menu after applying format (except for link) if (command === 'link') { this.hide(); } } public show(position: { x: number; y: number }, callback: (command: string) => void | Promise): void { console.log('FormattingMenu.show called:', { position, visible: this.visible }); this.position = position; this.callback = callback; this.visible = true; console.log('FormattingMenu.show - visible set to:', this.visible); } public hide(): void { this.visible = false; this.callback = null; } public updatePosition(position: { x: number; y: number }): void { this.position = position; } }