chore: update collapsible node
This commit is contained in:
@@ -32,7 +32,7 @@
|
|||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
border-width: 4px 6px 4px 6px;
|
border-width: 4px 6px 4px 6px;
|
||||||
border-left-color: #000;
|
border-left-color: var(--sn-stylekit-contrast-color);
|
||||||
display: block;
|
display: block;
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -8,8 +8,11 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
DOMConversionMap,
|
DOMConversionMap,
|
||||||
|
DOMConversionOutput,
|
||||||
|
DOMExportOutput,
|
||||||
EditorConfig,
|
EditorConfig,
|
||||||
ElementNode,
|
ElementNode,
|
||||||
|
LexicalEditor,
|
||||||
LexicalNode,
|
LexicalNode,
|
||||||
NodeKey,
|
NodeKey,
|
||||||
SerializedElementNode,
|
SerializedElementNode,
|
||||||
@@ -25,6 +28,14 @@ type SerializedCollapsibleContainerNode = Spread<
|
|||||||
SerializedElementNode
|
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 {
|
export class CollapsibleContainerNode extends ElementNode {
|
||||||
__open: boolean
|
__open: boolean
|
||||||
|
|
||||||
@@ -41,10 +52,16 @@ export class CollapsibleContainerNode extends ElementNode {
|
|||||||
return new CollapsibleContainerNode(node.__open, node.__key)
|
return new CollapsibleContainerNode(node.__open, node.__key)
|
||||||
}
|
}
|
||||||
|
|
||||||
override createDOM(_: EditorConfig): HTMLElement {
|
override createDOM(_: EditorConfig, editor: LexicalEditor): HTMLElement {
|
||||||
const dom = document.createElement('details')
|
const dom = document.createElement('details')
|
||||||
dom.classList.add('Collapsible__container')
|
dom.classList.add('Collapsible__container')
|
||||||
dom.open = this.__open
|
dom.open = this.__open
|
||||||
|
dom.addEventListener('toggle', () => {
|
||||||
|
const open = editor.getEditorState().read(() => this.getOpen())
|
||||||
|
if (open !== dom.open) {
|
||||||
|
editor.update(() => this.toggleOpen())
|
||||||
|
}
|
||||||
|
})
|
||||||
return dom
|
return dom
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,8 +73,15 @@ export class CollapsibleContainerNode extends ElementNode {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
static importDOM(): DOMConversionMap | null {
|
static importDOM(): DOMConversionMap<HTMLDetailsElement> | null {
|
||||||
return {}
|
return {
|
||||||
|
details: () => {
|
||||||
|
return {
|
||||||
|
conversion: convertDetailsElement,
|
||||||
|
priority: 1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static override importJSON(serializedNode: SerializedCollapsibleContainerNode): CollapsibleContainerNode {
|
static override importJSON(serializedNode: SerializedCollapsibleContainerNode): CollapsibleContainerNode {
|
||||||
@@ -65,6 +89,14 @@ export class CollapsibleContainerNode extends ElementNode {
|
|||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exportDOM(): DOMExportOutput {
|
||||||
|
const element = document.createElement('details')
|
||||||
|
if (this.getLatest().__open) {
|
||||||
|
element.setAttribute('open', '')
|
||||||
|
}
|
||||||
|
return { element }
|
||||||
|
}
|
||||||
|
|
||||||
override exportJSON(): SerializedCollapsibleContainerNode {
|
override exportJSON(): SerializedCollapsibleContainerNode {
|
||||||
return {
|
return {
|
||||||
...super.exportJSON(),
|
...super.exportJSON(),
|
||||||
@@ -80,7 +112,7 @@ export class CollapsibleContainerNode extends ElementNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getOpen(): boolean {
|
getOpen(): boolean {
|
||||||
return this.__open
|
return this.getLatest().__open
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleOpen(): void {
|
toggleOpen(): void {
|
||||||
|
|||||||
@@ -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<
|
type SerializedCollapsibleContentNode = Spread<
|
||||||
{
|
{
|
||||||
@@ -16,6 +25,13 @@ type SerializedCollapsibleContentNode = Spread<
|
|||||||
SerializedElementNode
|
SerializedElementNode
|
||||||
>
|
>
|
||||||
|
|
||||||
|
export function convertCollapsibleContentElement(): DOMConversionOutput | null {
|
||||||
|
const node = $createCollapsibleContentNode()
|
||||||
|
return {
|
||||||
|
node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class CollapsibleContentNode extends ElementNode {
|
export class CollapsibleContentNode extends ElementNode {
|
||||||
static override getType(): string {
|
static override getType(): string {
|
||||||
return 'collapsible-content'
|
return 'collapsible-content'
|
||||||
@@ -36,7 +52,17 @@ export class CollapsibleContentNode extends ElementNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static importDOM(): DOMConversionMap | null {
|
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 {
|
static override importJSON(_serializedNode: SerializedCollapsibleContentNode): CollapsibleContentNode {
|
||||||
@@ -47,6 +73,12 @@ export class CollapsibleContentNode extends ElementNode {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exportDOM(): DOMExportOutput {
|
||||||
|
const element = document.createElement('div')
|
||||||
|
element.setAttribute('data-lexical-collapsible-content', 'true')
|
||||||
|
return { element }
|
||||||
|
}
|
||||||
|
|
||||||
override exportJSON(): SerializedCollapsibleContentNode {
|
override exportJSON(): SerializedCollapsibleContentNode {
|
||||||
return {
|
return {
|
||||||
...super.exportJSON(),
|
...super.exportJSON(),
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import {
|
|||||||
$createParagraphNode,
|
$createParagraphNode,
|
||||||
$isElementNode,
|
$isElementNode,
|
||||||
DOMConversionMap,
|
DOMConversionMap,
|
||||||
EditorConfig,
|
DOMConversionOutput,
|
||||||
|
DOMExportOutput,
|
||||||
ElementFormatType,
|
ElementFormatType,
|
||||||
ElementNode,
|
ElementNode,
|
||||||
LexicalEditor,
|
|
||||||
LexicalNode,
|
LexicalNode,
|
||||||
NodeKey,
|
NodeKey,
|
||||||
RangeSelection,
|
RangeSelection,
|
||||||
@@ -32,6 +32,13 @@ type SerializedCollapsibleTitleNode = Spread<
|
|||||||
SerializedElementNode
|
SerializedElementNode
|
||||||
>
|
>
|
||||||
|
|
||||||
|
export function convertSummaryElement(): DOMConversionOutput | null {
|
||||||
|
const node = $createCollapsibleTitleNode()
|
||||||
|
return {
|
||||||
|
node,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class CollapsibleTitleNode extends ElementNode {
|
export class CollapsibleTitleNode extends ElementNode {
|
||||||
static override getType(): string {
|
static override getType(): string {
|
||||||
return 'collapsible-title'
|
return 'collapsible-title'
|
||||||
@@ -48,21 +55,11 @@ export class CollapsibleTitleNode extends ElementNode {
|
|||||||
return new CollapsibleTitleNode({ key: node.__key })
|
return new CollapsibleTitleNode({ key: node.__key })
|
||||||
}
|
}
|
||||||
|
|
||||||
override createDOM(_config: EditorConfig, editor: LexicalEditor): HTMLElement {
|
override createDOM(): HTMLElement {
|
||||||
const dom = document.createElement('summary')
|
const dom = document.createElement('summary')
|
||||||
dom.classList.add('Collapsible__title')
|
dom.classList.add('Collapsible__title')
|
||||||
const format = this.getFormatType()
|
const format = this.getFormatType()
|
||||||
dom.style.textAlign = format
|
dom.style.textAlign = format
|
||||||
dom.onclick = (event) => {
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
editor.update(() => {
|
|
||||||
const containerNode = this.getParentOrThrow()
|
|
||||||
if ($isCollapsibleContainerNode(containerNode)) {
|
|
||||||
containerNode.toggleOpen()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return dom
|
return dom
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,13 +68,25 @@ export class CollapsibleTitleNode extends ElementNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static importDOM(): DOMConversionMap | null {
|
static importDOM(): DOMConversionMap | null {
|
||||||
return {}
|
return {
|
||||||
|
summary: () => {
|
||||||
|
return {
|
||||||
|
conversion: convertSummaryElement,
|
||||||
|
priority: 1,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static override importJSON(serializedNode: SerializedCollapsibleTitleNode): CollapsibleTitleNode {
|
static override importJSON(serializedNode: SerializedCollapsibleTitleNode): CollapsibleTitleNode {
|
||||||
return $createCollapsibleTitleNode(serializedNode.format)
|
return $createCollapsibleTitleNode(serializedNode.format)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exportDOM(): DOMExportOutput {
|
||||||
|
const element = document.createElement('summary')
|
||||||
|
return { element }
|
||||||
|
}
|
||||||
|
|
||||||
override exportJSON(): SerializedCollapsibleTitleNode {
|
override exportJSON(): SerializedCollapsibleTitleNode {
|
||||||
return {
|
return {
|
||||||
...super.exportJSON(),
|
...super.exportJSON(),
|
||||||
@@ -91,7 +100,7 @@ export class CollapsibleTitleNode extends ElementNode {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override insertNewAfter(): ElementNode {
|
override insertNewAfter(_: RangeSelection, restoreSelection = true): ElementNode {
|
||||||
const containerNode = this.getParentOrThrow()
|
const containerNode = this.getParentOrThrow()
|
||||||
|
|
||||||
if (!$isCollapsibleContainerNode(containerNode)) {
|
if (!$isCollapsibleContainerNode(containerNode)) {
|
||||||
@@ -114,7 +123,7 @@ export class CollapsibleTitleNode extends ElementNode {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const paragraph = $createParagraphNode()
|
const paragraph = $createParagraphNode()
|
||||||
containerNode.insertAfter(paragraph)
|
containerNode.insertAfter(paragraph, restoreSelection)
|
||||||
return paragraph
|
return paragraph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user