173 lines
5.1 KiB
TypeScript
173 lines
5.1 KiB
TypeScript
![]() |
import { html, type TemplateResult } from '@design.estate/dees-element';
|
||
|
import { DeesModal } from '../dees-modal.js';
|
||
|
import { type IBlock } from './wysiwyg.types.js';
|
||
|
|
||
|
export class WysiwygModalManager {
|
||
|
/**
|
||
|
* Shows language selection modal for code blocks
|
||
|
*/
|
||
|
static async showLanguageSelectionModal(): Promise<string | null> {
|
||
|
return new Promise((resolve) => {
|
||
|
let selectedLanguage: string | null = null;
|
||
|
|
||
|
DeesModal.createAndShow({
|
||
|
heading: 'Select Programming Language',
|
||
|
content: html`
|
||
|
<style>
|
||
|
.language-grid {
|
||
|
display: grid;
|
||
|
grid-template-columns: repeat(3, 1fr);
|
||
|
gap: 8px;
|
||
|
padding: 16px;
|
||
|
}
|
||
|
.language-button {
|
||
|
padding: 12px;
|
||
|
background: var(--dees-color-box);
|
||
|
border: 1px solid var(--dees-color-line-bright);
|
||
|
border-radius: 4px;
|
||
|
cursor: pointer;
|
||
|
text-align: center;
|
||
|
transition: all 0.2s;
|
||
|
}
|
||
|
.language-button:hover {
|
||
|
background: var(--dees-color-box-highlight);
|
||
|
border-color: var(--dees-color-primary);
|
||
|
}
|
||
|
</style>
|
||
|
<div class="language-grid">
|
||
|
${this.getLanguages().map(lang => html`
|
||
|
<div class="language-button" @click="${(e: MouseEvent) => {
|
||
|
selectedLanguage = lang.toLowerCase();
|
||
|
const modal = (e.target as HTMLElement).closest('dees-modal');
|
||
|
if (modal) {
|
||
|
const okButton = modal.shadowRoot?.querySelector('.bottomButton.ok') as HTMLElement;
|
||
|
if (okButton) okButton.click();
|
||
|
}
|
||
|
}}">${lang}</div>
|
||
|
`)}
|
||
|
</div>
|
||
|
`,
|
||
|
menuOptions: [
|
||
|
{
|
||
|
name: 'Cancel',
|
||
|
action: async (modal) => {
|
||
|
modal.destroy();
|
||
|
resolve(null);
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
name: 'OK',
|
||
|
action: async (modal) => {
|
||
|
modal.destroy();
|
||
|
resolve(selectedLanguage);
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Shows block settings modal
|
||
|
*/
|
||
|
static async showBlockSettingsModal(
|
||
|
block: IBlock,
|
||
|
onUpdate: (block: IBlock) => void
|
||
|
): Promise<void> {
|
||
|
let content: TemplateResult;
|
||
|
|
||
|
if (block.type === 'code') {
|
||
|
content = this.getCodeBlockSettings(block, onUpdate);
|
||
|
} else {
|
||
|
content = html`<div style="padding: 16px;">No settings available for this block type.</div>`;
|
||
|
}
|
||
|
|
||
|
DeesModal.createAndShow({
|
||
|
heading: 'Block Settings',
|
||
|
content,
|
||
|
menuOptions: [
|
||
|
{
|
||
|
name: 'Close',
|
||
|
action: async (modal) => {
|
||
|
modal.destroy();
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets code block settings content
|
||
|
*/
|
||
|
private static getCodeBlockSettings(
|
||
|
block: IBlock,
|
||
|
onUpdate: (block: IBlock) => void
|
||
|
): TemplateResult {
|
||
|
const currentLanguage = block.metadata?.language || 'plain text';
|
||
|
|
||
|
return html`
|
||
|
<style>
|
||
|
.settings-section {
|
||
|
margin-bottom: 16px;
|
||
|
}
|
||
|
.settings-label {
|
||
|
font-weight: 500;
|
||
|
margin-bottom: 8px;
|
||
|
}
|
||
|
.language-grid {
|
||
|
display: grid;
|
||
|
grid-template-columns: repeat(3, 1fr);
|
||
|
gap: 8px;
|
||
|
}
|
||
|
.language-button {
|
||
|
padding: 8px;
|
||
|
background: var(--dees-color-box);
|
||
|
border: 1px solid var(--dees-color-line-bright);
|
||
|
border-radius: 4px;
|
||
|
cursor: pointer;
|
||
|
text-align: center;
|
||
|
transition: all 0.2s;
|
||
|
}
|
||
|
.language-button:hover {
|
||
|
background: var(--dees-color-box-highlight);
|
||
|
border-color: var(--dees-color-primary);
|
||
|
}
|
||
|
.language-button.selected {
|
||
|
background: var(--dees-color-primary);
|
||
|
color: white;
|
||
|
}
|
||
|
</style>
|
||
|
<div class="settings-section">
|
||
|
<div class="settings-label">Programming Language</div>
|
||
|
<div class="language-grid">
|
||
|
${this.getLanguages().map(lang => html`
|
||
|
<div class="language-button ${currentLanguage === lang.toLowerCase() ? 'selected' : ''}"
|
||
|
@click="${(e: MouseEvent) => {
|
||
|
if (!block.metadata) block.metadata = {};
|
||
|
block.metadata.language = lang.toLowerCase();
|
||
|
onUpdate(block);
|
||
|
|
||
|
// Close modal
|
||
|
const modal = (e.target as HTMLElement).closest('dees-modal');
|
||
|
if (modal) {
|
||
|
const closeButton = modal.shadowRoot?.querySelector('.bottomButton') as HTMLElement;
|
||
|
if (closeButton) closeButton.click();
|
||
|
}
|
||
|
}}">${lang}</div>
|
||
|
`)}
|
||
|
</div>
|
||
|
</div>
|
||
|
`;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets available programming languages
|
||
|
*/
|
||
|
private static getLanguages(): string[] {
|
||
|
return [
|
||
|
'JavaScript', 'TypeScript', 'Python', 'Java',
|
||
|
'C++', 'C#', 'Go', 'Rust', 'HTML', 'CSS',
|
||
|
'SQL', 'Shell', 'JSON', 'YAML', 'Markdown', 'Plain Text'
|
||
|
];
|
||
|
}
|
||
|
}
|