@blocklet/editor 2.0.140 → 2.0.141
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/main/plugins/CollapsiblePlugin/Collapsible.css +5 -1
- package/lib/main/plugins/CollapsiblePlugin/CollapsibleContainerNode.d.ts +1 -1
- package/lib/main/plugins/CollapsiblePlugin/CollapsibleContainerNode.js +44 -14
- package/lib/main/plugins/CollapsiblePlugin/CollapsibleContentNode.d.ts +3 -3
- package/lib/main/plugins/CollapsiblePlugin/CollapsibleContentNode.js +26 -3
- package/lib/main/plugins/CollapsiblePlugin/CollapsibleTitleNode.d.ts +2 -3
- package/lib/main/plugins/CollapsiblePlugin/CollapsibleTitleNode.js +13 -6
- package/lib/main/plugins/CollapsiblePlugin/CollapsibleUtils.d.ts +9 -0
- package/lib/main/plugins/CollapsiblePlugin/CollapsibleUtils.js +15 -0
- package/lib/main/plugins/CollapsiblePlugin/index.js +26 -23
- package/lib/shared/environment.d.ts +4 -0
- package/lib/shared/environment.js +4 -1
- package/package.json +3 -3
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
outline: none;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
.Collapsible__title > p {
|
|
27
|
+
margin: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
26
30
|
.Collapsible__title::marker,
|
|
27
31
|
.Collapsible__title::-webkit-details-marker {
|
|
28
32
|
display: none;
|
|
@@ -41,7 +45,7 @@
|
|
|
41
45
|
transform: translateY(-50%);
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
.Collapsible__container[open] .Collapsible__title:before {
|
|
48
|
+
.Collapsible__container[open] > .Collapsible__title:before {
|
|
45
49
|
border-color: transparent;
|
|
46
50
|
border-width: 6px 4px 0 4px;
|
|
47
51
|
border-top-color: #000;
|
|
@@ -9,7 +9,7 @@ import { DOMConversionMap, DOMConversionOutput, DOMExportOutput, EditorConfig, E
|
|
|
9
9
|
type SerializedCollapsibleContainerNode = Spread<{
|
|
10
10
|
open: boolean;
|
|
11
11
|
}, SerializedElementNode>;
|
|
12
|
-
export declare function convertDetailsElement(domNode: HTMLDetailsElement): DOMConversionOutput | null;
|
|
12
|
+
export declare function $convertDetailsElement(domNode: HTMLDetailsElement): DOMConversionOutput | null;
|
|
13
13
|
export declare class CollapsibleContainerNode extends ElementNode {
|
|
14
14
|
__open: boolean;
|
|
15
15
|
constructor(open: boolean, key?: NodeKey);
|
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
import { ElementNode, } from 'lexical';
|
|
9
|
-
|
|
8
|
+
import { ElementNode, isHTMLElement, } from 'lexical';
|
|
9
|
+
import { IS_CHROME } from '../../../shared/environment';
|
|
10
|
+
import invariant from '../../../shared/invariant';
|
|
11
|
+
import { setDomHiddenUntilFound } from './CollapsibleUtils';
|
|
12
|
+
export function $convertDetailsElement(domNode) {
|
|
10
13
|
const isOpen = domNode.open !== undefined ? domNode.open : true;
|
|
11
14
|
const node = $createCollapsibleContainerNode(isOpen);
|
|
12
15
|
return {
|
|
@@ -26,21 +29,47 @@ export class CollapsibleContainerNode extends ElementNode {
|
|
|
26
29
|
return new CollapsibleContainerNode(node.__open, node.__key);
|
|
27
30
|
}
|
|
28
31
|
createDOM(config, editor) {
|
|
29
|
-
|
|
30
|
-
dom
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (element.tagName === 'SUMMARY' || element.parentElement?.tagName === 'SUMMARY') {
|
|
36
|
-
editor.update(() => this.toggleOpen());
|
|
32
|
+
// details is not well supported in Chrome #5582
|
|
33
|
+
let dom;
|
|
34
|
+
if (IS_CHROME) {
|
|
35
|
+
dom = document.createElement('div');
|
|
36
|
+
if (this.__open) {
|
|
37
|
+
dom.setAttribute('open', '');
|
|
37
38
|
}
|
|
38
|
-
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const detailsDom = document.createElement('details');
|
|
42
|
+
detailsDom.open = this.__open;
|
|
43
|
+
detailsDom.addEventListener('toggle', () => {
|
|
44
|
+
const open = editor.getEditorState().read(() => this.getOpen());
|
|
45
|
+
if (open !== detailsDom.open) {
|
|
46
|
+
editor.update(() => this.toggleOpen());
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
dom = detailsDom;
|
|
50
|
+
}
|
|
51
|
+
dom.classList.add('Collapsible__container');
|
|
39
52
|
return dom;
|
|
40
53
|
}
|
|
41
54
|
updateDOM(prevNode, dom) {
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
const currentOpen = this.__open;
|
|
56
|
+
if (prevNode.__open !== currentOpen) {
|
|
57
|
+
// details is not well supported in Chrome #5582
|
|
58
|
+
if (IS_CHROME) {
|
|
59
|
+
const contentDom = dom.children[1];
|
|
60
|
+
invariant(isHTMLElement(contentDom), 'Expected contentDom to be an HTMLElement');
|
|
61
|
+
if (currentOpen) {
|
|
62
|
+
dom.setAttribute('open', '');
|
|
63
|
+
contentDom.hidden = false;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
dom.removeAttribute('open');
|
|
67
|
+
setDomHiddenUntilFound(contentDom);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
dom.open = this.__open;
|
|
72
|
+
}
|
|
44
73
|
}
|
|
45
74
|
return false;
|
|
46
75
|
}
|
|
@@ -48,7 +77,7 @@ export class CollapsibleContainerNode extends ElementNode {
|
|
|
48
77
|
return {
|
|
49
78
|
details: (domNode) => {
|
|
50
79
|
return {
|
|
51
|
-
conversion: convertDetailsElement,
|
|
80
|
+
conversion: $convertDetailsElement,
|
|
52
81
|
priority: 1,
|
|
53
82
|
};
|
|
54
83
|
},
|
|
@@ -60,6 +89,7 @@ export class CollapsibleContainerNode extends ElementNode {
|
|
|
60
89
|
}
|
|
61
90
|
exportDOM() {
|
|
62
91
|
const element = document.createElement('details');
|
|
92
|
+
element.classList.add('Collapsible__container');
|
|
63
93
|
element.setAttribute('open', this.__open.toString());
|
|
64
94
|
return { element };
|
|
65
95
|
}
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
import { DOMConversionMap, DOMConversionOutput, DOMExportOutput, EditorConfig, ElementNode, LexicalNode, SerializedElementNode } from 'lexical';
|
|
8
|
+
import { DOMConversionMap, DOMConversionOutput, DOMExportOutput, EditorConfig, ElementNode, LexicalEditor, LexicalNode, SerializedElementNode } from 'lexical';
|
|
9
9
|
type SerializedCollapsibleContentNode = SerializedElementNode;
|
|
10
|
-
export declare function convertCollapsibleContentElement(domNode: HTMLElement): DOMConversionOutput | null;
|
|
10
|
+
export declare function $convertCollapsibleContentElement(domNode: HTMLElement): DOMConversionOutput | null;
|
|
11
11
|
export declare class CollapsibleContentNode extends ElementNode {
|
|
12
12
|
static getType(): string;
|
|
13
13
|
static clone(node: CollapsibleContentNode): CollapsibleContentNode;
|
|
14
|
-
createDOM(config: EditorConfig): HTMLElement;
|
|
14
|
+
createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement;
|
|
15
15
|
updateDOM(prevNode: CollapsibleContentNode, dom: HTMLElement): boolean;
|
|
16
16
|
static importDOM(): DOMConversionMap | null;
|
|
17
17
|
exportDOM(): DOMExportOutput;
|
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
import { ElementNode, } from 'lexical';
|
|
9
|
-
|
|
9
|
+
import { IS_CHROME } from '../../../shared/environment';
|
|
10
|
+
import invariant from '../../../shared/invariant';
|
|
11
|
+
import { $isCollapsibleContainerNode } from './CollapsibleContainerNode';
|
|
12
|
+
import { domOnBeforeMatch, setDomHiddenUntilFound } from './CollapsibleUtils';
|
|
13
|
+
export function $convertCollapsibleContentElement(domNode) {
|
|
10
14
|
const node = $createCollapsibleContentNode();
|
|
11
15
|
return {
|
|
12
16
|
node,
|
|
@@ -19,9 +23,27 @@ export class CollapsibleContentNode extends ElementNode {
|
|
|
19
23
|
static clone(node) {
|
|
20
24
|
return new CollapsibleContentNode(node.__key);
|
|
21
25
|
}
|
|
22
|
-
createDOM(config) {
|
|
26
|
+
createDOM(config, editor) {
|
|
23
27
|
const dom = document.createElement('div');
|
|
24
28
|
dom.classList.add('Collapsible__content');
|
|
29
|
+
if (IS_CHROME) {
|
|
30
|
+
editor.getEditorState().read(() => {
|
|
31
|
+
const containerNode = this.getParentOrThrow();
|
|
32
|
+
invariant($isCollapsibleContainerNode(containerNode), 'Expected parent node to be a CollapsibleContainerNode');
|
|
33
|
+
if (!containerNode.__open) {
|
|
34
|
+
setDomHiddenUntilFound(dom);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
domOnBeforeMatch(dom, () => {
|
|
38
|
+
editor.update(() => {
|
|
39
|
+
const containerNode = this.getParentOrThrow().getLatest();
|
|
40
|
+
invariant($isCollapsibleContainerNode(containerNode), 'Expected parent node to be a CollapsibleContainerNode');
|
|
41
|
+
if (!containerNode.__open) {
|
|
42
|
+
containerNode.toggleOpen();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
25
47
|
return dom;
|
|
26
48
|
}
|
|
27
49
|
updateDOM(prevNode, dom) {
|
|
@@ -34,7 +56,7 @@ export class CollapsibleContentNode extends ElementNode {
|
|
|
34
56
|
return null;
|
|
35
57
|
}
|
|
36
58
|
return {
|
|
37
|
-
conversion: convertCollapsibleContentElement,
|
|
59
|
+
conversion: $convertCollapsibleContentElement,
|
|
38
60
|
priority: 2,
|
|
39
61
|
};
|
|
40
62
|
},
|
|
@@ -42,6 +64,7 @@ export class CollapsibleContentNode extends ElementNode {
|
|
|
42
64
|
}
|
|
43
65
|
exportDOM() {
|
|
44
66
|
const element = document.createElement('div');
|
|
67
|
+
element.classList.add('Collapsible__content');
|
|
45
68
|
element.setAttribute('data-lexical-collapsible-content', 'true');
|
|
46
69
|
return { element };
|
|
47
70
|
}
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
import { DOMConversionMap, DOMConversionOutput,
|
|
8
|
+
import { DOMConversionMap, DOMConversionOutput, EditorConfig, ElementNode, LexicalEditor, LexicalNode, RangeSelection, SerializedElementNode } from 'lexical';
|
|
9
9
|
type SerializedCollapsibleTitleNode = SerializedElementNode;
|
|
10
|
-
export declare function convertSummaryElement(domNode: HTMLElement): DOMConversionOutput | null;
|
|
10
|
+
export declare function $convertSummaryElement(domNode: HTMLElement): DOMConversionOutput | null;
|
|
11
11
|
export declare class CollapsibleTitleNode extends ElementNode {
|
|
12
12
|
static getType(): string;
|
|
13
13
|
static clone(node: CollapsibleTitleNode): CollapsibleTitleNode;
|
|
@@ -15,7 +15,6 @@ export declare class CollapsibleTitleNode extends ElementNode {
|
|
|
15
15
|
updateDOM(prevNode: CollapsibleTitleNode, dom: HTMLElement): boolean;
|
|
16
16
|
static importDOM(): DOMConversionMap | null;
|
|
17
17
|
static importJSON(serializedNode: SerializedCollapsibleTitleNode): CollapsibleTitleNode;
|
|
18
|
-
exportDOM(): DOMExportOutput;
|
|
19
18
|
exportJSON(): SerializedCollapsibleTitleNode;
|
|
20
19
|
collapseAtStart(_selection: RangeSelection): boolean;
|
|
21
20
|
insertNewAfter(_: RangeSelection, restoreSelection?: boolean): ElementNode;
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
import { $createParagraphNode, $isElementNode, ElementNode, } from 'lexical';
|
|
9
|
+
import { IS_CHROME } from '../../../shared/environment';
|
|
10
|
+
import invariant from '../../../shared/invariant';
|
|
9
11
|
import { $isCollapsibleContainerNode } from './CollapsibleContainerNode';
|
|
10
12
|
import { $isCollapsibleContentNode } from './CollapsibleContentNode';
|
|
11
|
-
export function convertSummaryElement(domNode) {
|
|
13
|
+
export function $convertSummaryElement(domNode) {
|
|
12
14
|
const node = $createCollapsibleTitleNode();
|
|
13
15
|
return {
|
|
14
16
|
node,
|
|
@@ -24,6 +26,15 @@ export class CollapsibleTitleNode extends ElementNode {
|
|
|
24
26
|
createDOM(config, editor) {
|
|
25
27
|
const dom = document.createElement('summary');
|
|
26
28
|
dom.classList.add('Collapsible__title');
|
|
29
|
+
if (IS_CHROME) {
|
|
30
|
+
dom.addEventListener('click', () => {
|
|
31
|
+
editor.update(() => {
|
|
32
|
+
const collapsibleContainer = this.getLatest().getParentOrThrow();
|
|
33
|
+
invariant($isCollapsibleContainerNode(collapsibleContainer), 'Expected parent node to be a CollapsibleContainerNode');
|
|
34
|
+
collapsibleContainer.toggleOpen();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
27
38
|
return dom;
|
|
28
39
|
}
|
|
29
40
|
updateDOM(prevNode, dom) {
|
|
@@ -33,7 +44,7 @@ export class CollapsibleTitleNode extends ElementNode {
|
|
|
33
44
|
return {
|
|
34
45
|
summary: (domNode) => {
|
|
35
46
|
return {
|
|
36
|
-
conversion: convertSummaryElement,
|
|
47
|
+
conversion: $convertSummaryElement,
|
|
37
48
|
priority: 1,
|
|
38
49
|
};
|
|
39
50
|
},
|
|
@@ -42,10 +53,6 @@ export class CollapsibleTitleNode extends ElementNode {
|
|
|
42
53
|
static importJSON(serializedNode) {
|
|
43
54
|
return $createCollapsibleTitleNode();
|
|
44
55
|
}
|
|
45
|
-
exportDOM() {
|
|
46
|
-
const element = document.createElement('summary');
|
|
47
|
-
return { element };
|
|
48
|
-
}
|
|
49
56
|
exportJSON() {
|
|
50
57
|
return {
|
|
51
58
|
...super.exportJSON(),
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
export declare function setDomHiddenUntilFound(dom: HTMLElement): void;
|
|
9
|
+
export declare function domOnBeforeMatch(dom: HTMLElement, callback: () => void): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
export function setDomHiddenUntilFound(dom) {
|
|
9
|
+
// @ts-expect-error
|
|
10
|
+
dom.hidden = 'until-found';
|
|
11
|
+
}
|
|
12
|
+
export function domOnBeforeMatch(dom, callback) {
|
|
13
|
+
// @ts-expect-error
|
|
14
|
+
dom.onbeforematch = callback;
|
|
15
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import './Collapsible.css';
|
|
9
9
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
10
10
|
import { $findMatchingParent, $insertNodeToNearestRoot, mergeRegister } from '@lexical/utils';
|
|
11
|
-
import { $createParagraphNode, $
|
|
11
|
+
import { $createParagraphNode, $getSelection, $isRangeSelection, COMMAND_PRIORITY_LOW, createCommand, DELETE_CHARACTER_COMMAND, INSERT_PARAGRAPH_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, } from 'lexical';
|
|
12
12
|
import { useEffect } from 'react';
|
|
13
13
|
import { $createCollapsibleContainerNode, $isCollapsibleContainerNode, CollapsibleContainerNode, } from './CollapsibleContainerNode';
|
|
14
14
|
import { $createCollapsibleContentNode, $isCollapsibleContentNode, CollapsibleContentNode, } from './CollapsibleContentNode';
|
|
@@ -21,7 +21,7 @@ export default function CollapsiblePlugin() {
|
|
|
21
21
|
if (!editor.hasNodes([CollapsibleContainerNode, CollapsibleTitleNode, CollapsibleContentNode])) {
|
|
22
22
|
throw new Error('CollapsiblePlugin: CollapsibleContainerNode, CollapsibleTitleNode, or CollapsibleContentNode not registered on editor');
|
|
23
23
|
}
|
|
24
|
-
const onEscapeUp = () => {
|
|
24
|
+
const $onEscapeUp = () => {
|
|
25
25
|
const selection = $getSelection();
|
|
26
26
|
if ($isRangeSelection(selection) && selection.isCollapsed() && selection.anchor.offset === 0) {
|
|
27
27
|
const container = $findMatchingParent(selection.anchor.getNode(), $isCollapsibleContainerNode);
|
|
@@ -36,17 +36,21 @@ export default function CollapsiblePlugin() {
|
|
|
36
36
|
}
|
|
37
37
|
return false;
|
|
38
38
|
};
|
|
39
|
-
const onEscapeDown = () => {
|
|
39
|
+
const $onEscapeDown = () => {
|
|
40
40
|
const selection = $getSelection();
|
|
41
41
|
if ($isRangeSelection(selection) && selection.isCollapsed()) {
|
|
42
42
|
const container = $findMatchingParent(selection.anchor.getNode(), $isCollapsibleContainerNode);
|
|
43
43
|
if ($isCollapsibleContainerNode(container)) {
|
|
44
44
|
const parent = container.getParent();
|
|
45
45
|
if (parent !== null && parent.getLastChild() === container) {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
selection.anchor.
|
|
46
|
+
const titleParagraph = container.getFirstDescendant();
|
|
47
|
+
const contentParagraph = container.getLastDescendant();
|
|
48
|
+
if ((contentParagraph !== null &&
|
|
49
|
+
selection.anchor.key === contentParagraph.getKey() &&
|
|
50
|
+
selection.anchor.offset === contentParagraph.getTextContentSize()) ||
|
|
51
|
+
(titleParagraph !== null &&
|
|
52
|
+
selection.anchor.key === titleParagraph.getKey() &&
|
|
53
|
+
selection.anchor.offset === titleParagraph.getTextContentSize())) {
|
|
50
54
|
container.insertAfter($createParagraphNode());
|
|
51
55
|
}
|
|
52
56
|
}
|
|
@@ -106,27 +110,25 @@ export default function CollapsiblePlugin() {
|
|
|
106
110
|
// below it to allow adding more content. It's similar what $insertBlockNode
|
|
107
111
|
// (mainly for decorators), except it'll always be possible to continue adding
|
|
108
112
|
// new content even if trailing paragraph is accidentally deleted
|
|
109
|
-
editor.registerCommand(KEY_ARROW_DOWN_COMMAND, onEscapeDown, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_RIGHT_COMMAND, onEscapeDown, COMMAND_PRIORITY_LOW),
|
|
113
|
+
editor.registerCommand(KEY_ARROW_DOWN_COMMAND, $onEscapeDown, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_RIGHT_COMMAND, $onEscapeDown, COMMAND_PRIORITY_LOW),
|
|
110
114
|
// When collapsible is the first child pressing up/left arrow will insert paragraph
|
|
111
115
|
// above it to allow adding more content. It's similar what $insertBlockNode
|
|
112
116
|
// (mainly for decorators), except it'll always be possible to continue adding
|
|
113
117
|
// new content even if leading paragraph is accidentally deleted
|
|
114
|
-
editor.registerCommand(KEY_ARROW_UP_COMMAND, onEscapeUp, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_LEFT_COMMAND, onEscapeUp, COMMAND_PRIORITY_LOW),
|
|
115
|
-
//
|
|
118
|
+
editor.registerCommand(KEY_ARROW_UP_COMMAND, $onEscapeUp, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ARROW_LEFT_COMMAND, $onEscapeUp, COMMAND_PRIORITY_LOW),
|
|
119
|
+
// Enter goes from Title to Content rather than a new line inside Title
|
|
116
120
|
editor.registerCommand(INSERT_PARAGRAPH_COMMAND, () => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const container = parent.getParent();
|
|
125
|
-
if ($isCollapsibleContainerNode(container)) {
|
|
121
|
+
const selection = $getSelection();
|
|
122
|
+
if ($isRangeSelection(selection)) {
|
|
123
|
+
const titleNode = $findMatchingParent(selection.anchor.getNode(), (node) => $isCollapsibleTitleNode(node));
|
|
124
|
+
if ($isCollapsibleTitleNode(titleNode)) {
|
|
125
|
+
const container = titleNode.getParent();
|
|
126
|
+
if (container && $isCollapsibleContainerNode(container)) {
|
|
127
|
+
if (!container.getOpen()) {
|
|
126
128
|
container.toggleOpen();
|
|
127
|
-
$setSelection(selection.clone());
|
|
128
|
-
return true;
|
|
129
129
|
}
|
|
130
|
+
titleNode.getNextSibling()?.selectEnd();
|
|
131
|
+
return true;
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
134
|
}
|
|
@@ -134,8 +136,9 @@ export default function CollapsiblePlugin() {
|
|
|
134
136
|
}, COMMAND_PRIORITY_LOW), editor.registerCommand(INSERT_COLLAPSIBLE_COMMAND, () => {
|
|
135
137
|
editor.update(() => {
|
|
136
138
|
const title = $createCollapsibleTitleNode();
|
|
137
|
-
|
|
138
|
-
title.
|
|
139
|
+
const paragraph = $createParagraphNode();
|
|
140
|
+
$insertNodeToNearestRoot($createCollapsibleContainerNode(true).append(title.append(paragraph), $createCollapsibleContentNode().append($createParagraphNode())));
|
|
141
|
+
paragraph.select();
|
|
139
142
|
});
|
|
140
143
|
return true;
|
|
141
144
|
}, COMMAND_PRIORITY_LOW));
|
|
@@ -18,3 +18,7 @@ export declare const IS_FIREFOX: boolean;
|
|
|
18
18
|
export declare const CAN_USE_BEFORE_INPUT: boolean;
|
|
19
19
|
export declare const IS_SAFARI: boolean;
|
|
20
20
|
export declare const IS_IOS: boolean;
|
|
21
|
+
export declare const IS_ANDROID: boolean;
|
|
22
|
+
export declare const IS_CHROME: boolean;
|
|
23
|
+
export declare const IS_ANDROID_CHROME: boolean;
|
|
24
|
+
export declare const IS_APPLE_WEBKIT: boolean;
|
|
@@ -12,7 +12,10 @@ export const IS_FIREFOX = CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test
|
|
|
12
12
|
export const CAN_USE_BEFORE_INPUT = CAN_USE_DOM && 'InputEvent' in window && !documentMode ? 'getTargetRanges' in new window.InputEvent('input') : false;
|
|
13
13
|
export const IS_SAFARI = CAN_USE_DOM && /Version\/[\d.]+.*Safari/.test(navigator.userAgent);
|
|
14
14
|
export const IS_IOS = CAN_USE_DOM && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
|
15
|
+
export const IS_ANDROID = CAN_USE_DOM && /Android/.test(navigator.userAgent);
|
|
15
16
|
// Keep these in case we need to use them in the future.
|
|
16
17
|
// export const IS_WINDOWS: boolean = CAN_USE_DOM && /Win/.test(navigator.platform);
|
|
17
|
-
|
|
18
|
+
export const IS_CHROME = CAN_USE_DOM && /^(?=.*Chrome).*/i.test(navigator.userAgent);
|
|
18
19
|
// export const canUseTextInputEvent: boolean = CAN_USE_DOM && 'TextEvent' in window && !documentMode;
|
|
20
|
+
export const IS_ANDROID_CHROME = CAN_USE_DOM && IS_ANDROID && IS_CHROME;
|
|
21
|
+
export const IS_APPLE_WEBKIT = CAN_USE_DOM && /AppleWebKit\/[\d.]+/.test(navigator.userAgent) && !IS_CHROME;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/editor",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.141",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "npm run storybook",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@arcblock/ux": "^2.10.23",
|
|
41
41
|
"@blocklet/embed": "^0.2.0",
|
|
42
42
|
"@blocklet/pages-kit": "^0.2.399",
|
|
43
|
-
"@blocklet/pdf": "2.0.
|
|
43
|
+
"@blocklet/pdf": "2.0.141",
|
|
44
44
|
"@excalidraw/excalidraw": "^0.14.2",
|
|
45
45
|
"@iconify/iconify": "^3.0.1",
|
|
46
46
|
"@iconify/icons-tabler": "^1.2.95",
|
|
@@ -113,5 +113,5 @@
|
|
|
113
113
|
"react": "*",
|
|
114
114
|
"react-dom": "*"
|
|
115
115
|
},
|
|
116
|
-
"gitHead": "
|
|
116
|
+
"gitHead": "8382764c9955da8355361e8f3dfe80064ef6531f"
|
|
117
117
|
}
|