WYSIWYG: Aligned double click to set label for details functionality

Aligned the behaviour across the WYSIWYG editors, and also for nested
details blocks (which wasn't working in the TinyMCE implementation).

Closes #6059
This commit is contained in:
Dan Brown
2026-03-22 17:18:04 +00:00
parent fa1dc162bd
commit a44756168d
5 changed files with 44 additions and 5 deletions

View File

@@ -19,6 +19,8 @@ function setSummary(editor, summaryContent) {
}
summary.textContent = summaryContent;
});
editor.selection.select(details);
}
/**
@@ -202,8 +204,12 @@ function register(editor) {
});
editor.on('dblclick', event => {
if (!getSelectedDetailsBlock(editor) || event.target.closest('doc-root')) return;
showDetailLabelEditWindow(editor);
const domElClass = event?.target?.ownerDocument?.defaultView?.HTMLDetailsElement;
if (domElClass && event.target instanceof domElClass && getSelectedDetailsBlock(editor)) {
showDetailLabelEditWindow(editor);
event.preventDefault();
event.stopPropagation();
}
});
editor.ui.registry.addButton('toggledetails', {

View File

@@ -45,6 +45,7 @@ import {LineBreakNode} from './nodes/LexicalLineBreakNode';
import {ParagraphNode} from './nodes/LexicalParagraphNode';
import {RootNode} from './nodes/LexicalRootNode';
import {TabNode} from './nodes/LexicalTabNode';
import {EditorUiContext} from "../../ui/framework/core";
export type Spread<T1, T2> = Omit<T2, keyof T1> & T1;
@@ -621,6 +622,8 @@ export class LexicalEditor {
_editable: boolean;
/** @internal */
_blockCursorElement: null | HTMLDivElement;
/** @internal */
_context: null | EditorUiContext;
/** @internal */
constructor(
@@ -682,6 +685,7 @@ export class LexicalEditor {
this._headless = parentEditor !== null && parentEditor._headless;
this._window = null;
this._blockCursorElement = null;
this._context = null;
}
/**
@@ -1285,6 +1289,21 @@ export class LexicalEditor {
triggerListeners('editable', this, true, editable);
}
}
/**
* Set the UI context that this editor is intended to be part of.
*/
setUiContext(context: EditorUiContext) {
this._context = context;
}
/**
* Get the UI context that this editor is considered to be part of.
*/
getUiContext(): EditorUiContext|null {
return this._context;
}
/**
* Returns a JSON-serializable javascript object NOT a JSON string.
* You still must call JSON.stringify (or something else) to turn the

View File

@@ -9,6 +9,7 @@ import {
} from 'lexical';
import {extractDirectionFromElement} from "lexical/nodes/common";
import {$showDetailsForm} from "../../ui/defaults/forms/objects";
export type SerializedDetailsNode = Spread<{
id: string;
@@ -90,6 +91,16 @@ export class DetailsNode extends ElementNode {
});
});
summary.addEventListener('dblclick', event => {
event.preventDefault();
const uiContext = _editor.getUiContext();
if (uiContext) {
_editor.read(() => {
$showDetailsForm(this, uiContext);
});
}
});
el.append(summary);
return el;

View File

@@ -221,7 +221,7 @@ export const detailsEditLabel: EditorButtonDefinition = {
if ($isDetailsNode(details)) {
$showDetailsForm(details, context);
}
})
});
},
isActive(selection: BaseSelection | null): boolean {
return false;

View File

@@ -29,7 +29,7 @@ export class EditorUIManager {
setContext(context: EditorUiContext) {
this.context = context;
this.setupEventListeners();
this.setupEditor(context.editor);
this.setupEditor(context.editor, context);
}
getContext(): EditorUiContext {
@@ -256,7 +256,10 @@ export class EditorUIManager {
}
}
protected setupEditor(editor: LexicalEditor) {
protected setupEditor(editor: LexicalEditor, context: EditorUiContext) {
// Pass the context to the editor
editor.setUiContext(context);
// Register our DOM decorate listener with the editor
const domDecorateListener: DecoratorListener<EditorDecoratorAdapter> = (decorators: Record<NodeKey, EditorDecoratorAdapter>) => {
editor.getEditorState().read(() => {