chore: update collapsible node

This commit is contained in:
Aman Harwara
2023-04-01 14:53:22 +05:30
parent fbb0dc0cea
commit f884e2cd66
4 changed files with 96 additions and 23 deletions

View File

@@ -32,7 +32,7 @@
border-style: solid;
border-color: transparent;
border-width: 4px 6px 4px 6px;
border-left-color: #000;
border-left-color: var(--sn-stylekit-contrast-color);
display: block;
content: '';
position: absolute;

View File

@@ -8,8 +8,11 @@
import {
DOMConversionMap,
DOMConversionOutput,
DOMExportOutput,
EditorConfig,
ElementNode,
LexicalEditor,
LexicalNode,
NodeKey,
SerializedElementNode,
@@ -25,6 +28,14 @@ type SerializedCollapsibleContainerNode = Spread<
SerializedElementNode
>
export function convertDetailsElement(domNode: HTMLDetailsElement): DOMConversionOutput | null {
const isOpen = domNode.open !== undefined ? domNode.open : true
const node = $createCollapsibleContainerNode(isOpen)
return {
node,
}
}
export class CollapsibleContainerNode extends ElementNode {
__open: boolean
@@ -41,10 +52,16 @@ export class CollapsibleContainerNode extends ElementNode {
return new CollapsibleContainerNode(node.__open, node.__key)
}
override createDOM(_: EditorConfig): HTMLElement {
override createDOM(_: EditorConfig, editor: LexicalEditor): HTMLElement {
const dom = document.createElement('details')
dom.classList.add('Collapsible__container')
dom.open = this.__open
dom.addEventListener('toggle', () => {
const open = editor.getEditorState().read(() => this.getOpen())
if (open !== dom.open) {
editor.update(() => this.toggleOpen())
}
})
return dom
}
@@ -56,8 +73,15 @@ export class CollapsibleContainerNode extends ElementNode {
return false
}
static importDOM(): DOMConversionMap | null {
return {}
static importDOM(): DOMConversionMap<HTMLDetailsElement> | null {
return {
details: () => {
return {
conversion: convertDetailsElement,
priority: 1,
}
},
}
}
static override importJSON(serializedNode: SerializedCollapsibleContainerNode): CollapsibleContainerNode {
@@ -65,6 +89,14 @@ export class CollapsibleContainerNode extends ElementNode {
return node
}
exportDOM(): DOMExportOutput {
const element = document.createElement('details')
if (this.getLatest().__open) {
element.setAttribute('open', '')
}
return { element }
}
override exportJSON(): SerializedCollapsibleContainerNode {
return {
...super.exportJSON(),
@@ -80,7 +112,7 @@ export class CollapsibleContainerNode extends ElementNode {
}
getOpen(): boolean {
return this.__open
return this.getLatest().__open
}
toggleOpen(): void {

View File

@@ -6,7 +6,16 @@
*
*/
import { DOMConversionMap, EditorConfig, ElementNode, LexicalNode, SerializedElementNode, Spread } from 'lexical'
import {
DOMConversionMap,
DOMConversionOutput,
DOMExportOutput,
EditorConfig,
ElementNode,
LexicalNode,
SerializedElementNode,
Spread,
} from 'lexical'
type SerializedCollapsibleContentNode = Spread<
{
@@ -16,6 +25,13 @@ type SerializedCollapsibleContentNode = Spread<
SerializedElementNode
>
export function convertCollapsibleContentElement(): DOMConversionOutput | null {
const node = $createCollapsibleContentNode()
return {
node,
}
}
export class CollapsibleContentNode extends ElementNode {
static override getType(): string {
return 'collapsible-content'
@@ -36,7 +52,17 @@ export class CollapsibleContentNode extends ElementNode {
}
static importDOM(): DOMConversionMap | null {
return {}
return {
div: (domNode: HTMLElement) => {
if (!domNode.hasAttribute('data-lexical-collapsible-content')) {
return null
}
return {
conversion: convertCollapsibleContentElement,
priority: 2,
}
},
}
}
static override importJSON(_serializedNode: SerializedCollapsibleContentNode): CollapsibleContentNode {
@@ -47,6 +73,12 @@ export class CollapsibleContentNode extends ElementNode {
return true
}
exportDOM(): DOMExportOutput {
const element = document.createElement('div')
element.setAttribute('data-lexical-collapsible-content', 'true')
return { element }
}
override exportJSON(): SerializedCollapsibleContentNode {
return {
...super.exportJSON(),

View File

@@ -10,10 +10,10 @@ import {
$createParagraphNode,
$isElementNode,
DOMConversionMap,
EditorConfig,
DOMConversionOutput,
DOMExportOutput,
ElementFormatType,
ElementNode,
LexicalEditor,
LexicalNode,
NodeKey,
RangeSelection,
@@ -32,6 +32,13 @@ type SerializedCollapsibleTitleNode = Spread<
SerializedElementNode
>
export function convertSummaryElement(): DOMConversionOutput | null {
const node = $createCollapsibleTitleNode()
return {
node,
}
}
export class CollapsibleTitleNode extends ElementNode {
static override getType(): string {
return 'collapsible-title'
@@ -48,21 +55,11 @@ export class CollapsibleTitleNode extends ElementNode {
return new CollapsibleTitleNode({ key: node.__key })
}
override createDOM(_config: EditorConfig, editor: LexicalEditor): HTMLElement {
override createDOM(): HTMLElement {
const dom = document.createElement('summary')
dom.classList.add('Collapsible__title')
const format = this.getFormatType()
dom.style.textAlign = format
dom.onclick = (event) => {
event.preventDefault()
event.stopPropagation()
editor.update(() => {
const containerNode = this.getParentOrThrow()
if ($isCollapsibleContainerNode(containerNode)) {
containerNode.toggleOpen()
}
})
}
return dom
}
@@ -71,13 +68,25 @@ export class CollapsibleTitleNode extends ElementNode {
}
static importDOM(): DOMConversionMap | null {
return {}
return {
summary: () => {
return {
conversion: convertSummaryElement,
priority: 1,
}
},
}
}
static override importJSON(serializedNode: SerializedCollapsibleTitleNode): CollapsibleTitleNode {
return $createCollapsibleTitleNode(serializedNode.format)
}
exportDOM(): DOMExportOutput {
const element = document.createElement('summary')
return { element }
}
override exportJSON(): SerializedCollapsibleTitleNode {
return {
...super.exportJSON(),
@@ -91,7 +100,7 @@ export class CollapsibleTitleNode extends ElementNode {
return true
}
override insertNewAfter(): ElementNode {
override insertNewAfter(_: RangeSelection, restoreSelection = true): ElementNode {
const containerNode = this.getParentOrThrow()
if (!$isCollapsibleContainerNode(containerNode)) {
@@ -114,7 +123,7 @@ export class CollapsibleTitleNode extends ElementNode {
}
} else {
const paragraph = $createParagraphNode()
containerNode.insertAfter(paragraph)
containerNode.insertAfter(paragraph, restoreSelection)
return paragraph
}
}