diff --git a/resources/js/wysiwyg/index.ts b/resources/js/wysiwyg/index.ts index 5568b8963..2c8c3b952 100644 --- a/resources/js/wysiwyg/index.ts +++ b/resources/js/wysiwyg/index.ts @@ -91,9 +91,6 @@ export function createPageEditorInstance(container: HTMLElement, htmlContent: st window.debugEditorState = () => { return editor.getEditorState().toJSON(); }; - context.manager.onSelectionChange((selection) => { - console.log(selection, context.editor.getEditorState()); - }); registerCommonNodeMutationListeners(context); diff --git a/resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts b/resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts index ce4dbc467..0329aed6f 100644 --- a/resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts +++ b/resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts @@ -307,7 +307,7 @@ export class ElementNode extends LexicalNode { let anchorOffset = _anchorOffset; let focusOffset = _focusOffset; const childrenCount = this.getChildrenSize(); - if (!this.canBeEmpty()) { + if (!this.canBeEmpty() && !this.shouldSelectDirectly()) { if (_anchorOffset === 0 && _focusOffset === 0) { const firstChild = this.getFirstChild(); if ($isTextNode(firstChild) || $isElementNode(firstChild)) { diff --git a/resources/js/wysiwyg/lexical/rich-text/LexicalDetailsNode.ts b/resources/js/wysiwyg/lexical/rich-text/LexicalDetailsNode.ts index 5e5d6b735..cdf32fdcb 100644 --- a/resources/js/wysiwyg/lexical/rich-text/LexicalDetailsNode.ts +++ b/resources/js/wysiwyg/lexical/rich-text/LexicalDetailsNode.ts @@ -178,6 +178,10 @@ export class DetailsNode extends ElementNode { return true; } + canBeEmpty(): boolean { + return false; + } + } export function $createDetailsNode() { diff --git a/resources/js/wysiwyg/services/keyboard-handling.ts b/resources/js/wysiwyg/services/keyboard-handling.ts index b4f546117..aba0b1aa8 100644 --- a/resources/js/wysiwyg/services/keyboard-handling.ts +++ b/resources/js/wysiwyg/services/keyboard-handling.ts @@ -18,6 +18,7 @@ import {$setInsetForSelection} from "../utils/lists"; import {$isListItemNode} from "@lexical/list"; import {$isDetailsNode, DetailsNode} from "@lexical/rich-text/LexicalDetailsNode"; import {$isDiagramNode} from "../utils/diagrams"; +import {$unwrapDetailsNode} from "../utils/details"; function isSingleSelectedNode(nodes: LexicalNode[]): boolean { if (nodes.length === 1) { @@ -172,6 +173,35 @@ function getDetailsScenario(editor: LexicalEditor): { } } +function unwrapDetailsNode(context: EditorUiContext, event: KeyboardEvent): boolean { + const selection = $getSelection(); + const nodes = selection?.getNodes() || []; + + if (nodes.length !== 1) { + return false; + } + + const selectedNearestBlock = $getNearestNodeBlockParent(nodes[0]); + if (!selectedNearestBlock) { + return false; + } + + const selectedParentBlock = selectedNearestBlock.getParent(); + const selectRange = selection?.getStartEndPoints(); + + if (selectRange && $isDetailsNode(selectedParentBlock) && selectRange[0].offset === 0 && selectedNearestBlock.getIndexWithinParent() === 0) { + event.preventDefault(); + context.editor.update(() => { + $unwrapDetailsNode(selectedParentBlock); + selectedNearestBlock.selectStart(); + context.manager.triggerLayoutUpdate(); + }); + return true; + } + + return false; +} + function $isSingleListItem(nodes: LexicalNode[]): boolean { if (nodes.length !== 1) { return false; @@ -201,9 +231,9 @@ function handleInsetOnTab(editor: LexicalEditor, event: KeyboardEvent|null): boo } export function registerKeyboardHandling(context: EditorUiContext): () => void { - const unregisterBackspace = context.editor.registerCommand(KEY_BACKSPACE_COMMAND, (): boolean => { + const unregisterBackspace = context.editor.registerCommand(KEY_BACKSPACE_COMMAND, (event): boolean => { deleteSingleSelectedNode(context.editor); - return false; + return unwrapDetailsNode(context, event); }, COMMAND_PRIORITY_LOW); const unregisterDelete = context.editor.registerCommand(KEY_DELETE_COMMAND, (): boolean => { diff --git a/resources/js/wysiwyg/ui/defaults/buttons/objects.ts b/resources/js/wysiwyg/ui/defaults/buttons/objects.ts index 1f78f4487..00dc9500e 100644 --- a/resources/js/wysiwyg/ui/defaults/buttons/objects.ts +++ b/resources/js/wysiwyg/ui/defaults/buttons/objects.ts @@ -34,6 +34,7 @@ import {$isDiagramNode, $openDrawingEditorForNode, showDiagramManagerForInsert} import {$createLinkedImageNodeFromImageData, showImageManager} from "../../../utils/images"; import {$showDetailsForm, $showImageForm, $showLinkForm, $showMediaForm} from "../forms/objects"; import {formatCodeBlock} from "../../../utils/formats"; +import {$unwrapDetailsNode} from "../../../utils/details"; export const link: EditorButtonDefinition = { label: 'Insert/edit link', @@ -251,11 +252,7 @@ export const detailsUnwrap: EditorButtonDefinition = { context.editor.update(() => { const details = $getNodeFromSelection($getSelection(), $isDetailsNode); if ($isDetailsNode(details)) { - const children = details.getChildren(); - for (const child of children) { - details.insertBefore(child); - } - details.remove(); + $unwrapDetailsNode(details); context.manager.triggerLayoutUpdate(); } }) diff --git a/resources/js/wysiwyg/utils/details.ts b/resources/js/wysiwyg/utils/details.ts new file mode 100644 index 000000000..79e8600d0 --- /dev/null +++ b/resources/js/wysiwyg/utils/details.ts @@ -0,0 +1,9 @@ +import {DetailsNode} from "@lexical/rich-text/LexicalDetailsNode"; + +export function $unwrapDetailsNode(node: DetailsNode) { + const children = node.getChildren(); + for (const child of children) { + node.insertBefore(child); + } + node.remove(); +} \ No newline at end of file