fix(dees-modal): theming
This commit is contained in:
@ -42,46 +42,104 @@ export class WysiwygFormatting {
|
||||
`;
|
||||
}
|
||||
|
||||
static applyFormat(command: string, value?: string): void {
|
||||
static applyFormat(command: string, value?: string): boolean {
|
||||
// Save current selection
|
||||
const selection = window.getSelection();
|
||||
if (!selection || selection.rangeCount === 0) return;
|
||||
if (!selection || selection.rangeCount === 0) return false;
|
||||
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
// Apply format based on command
|
||||
switch (command) {
|
||||
case 'bold':
|
||||
this.wrapSelection(range, 'strong');
|
||||
break;
|
||||
|
||||
case 'italic':
|
||||
this.wrapSelection(range, 'em');
|
||||
break;
|
||||
|
||||
case 'underline':
|
||||
this.wrapSelection(range, 'u');
|
||||
break;
|
||||
|
||||
case 'strikeThrough':
|
||||
document.execCommand(command, false);
|
||||
this.wrapSelection(range, 's');
|
||||
break;
|
||||
|
||||
case 'code':
|
||||
// For inline code, wrap selection in <code> tags
|
||||
const codeElement = document.createElement('code');
|
||||
try {
|
||||
codeElement.appendChild(range.extractContents());
|
||||
range.insertNode(codeElement);
|
||||
|
||||
// Select the newly created code element
|
||||
range.selectNodeContents(codeElement);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
} catch (e) {
|
||||
// Fallback to execCommand if range manipulation fails
|
||||
document.execCommand('fontName', false, 'monospace');
|
||||
}
|
||||
this.wrapSelection(range, 'code');
|
||||
break;
|
||||
|
||||
case 'link':
|
||||
const url = value || prompt('Enter URL:');
|
||||
if (url) {
|
||||
document.execCommand('createLink', false, url);
|
||||
// Don't use prompt - return false to indicate we need async input
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
this.wrapSelectionWithLink(range, value);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static wrapSelection(range: Range, tagName: string): void {
|
||||
const selection = window.getSelection();
|
||||
if (!selection) return;
|
||||
|
||||
// Check if we're already wrapped in this tag
|
||||
const parentElement = range.commonAncestorContainer.parentElement;
|
||||
if (parentElement && parentElement.tagName.toLowerCase() === tagName) {
|
||||
// Unwrap
|
||||
const parent = parentElement.parentNode;
|
||||
while (parentElement.firstChild) {
|
||||
parent?.insertBefore(parentElement.firstChild, parentElement);
|
||||
}
|
||||
parent?.removeChild(parentElement);
|
||||
|
||||
// Restore selection
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
} else {
|
||||
// Wrap selection
|
||||
const wrapper = document.createElement(tagName);
|
||||
try {
|
||||
// Extract and wrap contents
|
||||
const contents = range.extractContents();
|
||||
wrapper.appendChild(contents);
|
||||
range.insertNode(wrapper);
|
||||
|
||||
// Select the wrapped content
|
||||
range.selectNodeContents(wrapper);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
} catch (e) {
|
||||
console.error('Failed to wrap selection:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static wrapSelectionWithLink(range: Range, url: string): void {
|
||||
const selection = window.getSelection();
|
||||
if (!selection) return;
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.target = '_blank';
|
||||
link.rel = 'noopener noreferrer';
|
||||
|
||||
try {
|
||||
const contents = range.extractContents();
|
||||
link.appendChild(contents);
|
||||
range.insertNode(link);
|
||||
|
||||
// Select the link
|
||||
range.selectNodeContents(link);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
} catch (e) {
|
||||
console.error('Failed to create link:', e);
|
||||
}
|
||||
}
|
||||
|
||||
static getSelectionCoordinates(shadowRoot?: ShadowRoot): { x: number, y: number } | null {
|
||||
@ -118,10 +176,33 @@ export class WysiwygFormatting {
|
||||
}
|
||||
|
||||
static isFormattingApplied(command: string): boolean {
|
||||
try {
|
||||
return document.queryCommandState(command);
|
||||
} catch {
|
||||
return false;
|
||||
const selection = window.getSelection();
|
||||
if (!selection || selection.rangeCount === 0) return false;
|
||||
|
||||
const range = selection.getRangeAt(0);
|
||||
const container = range.commonAncestorContainer;
|
||||
const element = container.nodeType === Node.TEXT_NODE
|
||||
? container.parentElement
|
||||
: container as Element;
|
||||
|
||||
if (!element) return false;
|
||||
|
||||
// Check if formatting is applied by looking at parent elements
|
||||
switch (command) {
|
||||
case 'bold':
|
||||
return !!element.closest('b, strong');
|
||||
case 'italic':
|
||||
return !!element.closest('i, em');
|
||||
case 'underline':
|
||||
return !!element.closest('u');
|
||||
case 'strikeThrough':
|
||||
return !!element.closest('s, strike');
|
||||
case 'code':
|
||||
return !!element.closest('code');
|
||||
case 'link':
|
||||
return !!element.closest('a');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user