mirror of
https://github.com/facebook/lexical.git
synced 2025-05-22 09:36:41 +08:00
Deprecate editor.isEmpty (#793)
This commit is contained in:
@ -33,6 +33,7 @@ module.name_mapper='^outline/keys' -> '<PROJECT_ROOT>/packages/outline/src/helpe
|
|||||||
module.name_mapper='^outline/nodes' -> '<PROJECT_ROOT>/packages/outline/src/helpers/OutlineNodeHelpers.js'
|
module.name_mapper='^outline/nodes' -> '<PROJECT_ROOT>/packages/outline/src/helpers/OutlineNodeHelpers.js'
|
||||||
module.name_mapper='^outline/events' -> '<PROJECT_ROOT>/packages/outline/src/helpers/OutlineEventHelpers.js'
|
module.name_mapper='^outline/events' -> '<PROJECT_ROOT>/packages/outline/src/helpers/OutlineEventHelpers.js'
|
||||||
module.name_mapper='^outline/offsets' -> '<PROJECT_ROOT>/packages/outline/src/helpers/OutlineOffsetHelpers.js'
|
module.name_mapper='^outline/offsets' -> '<PROJECT_ROOT>/packages/outline/src/helpers/OutlineOffsetHelpers.js'
|
||||||
|
module.name_mapper='^outline/validation' -> '<PROJECT_ROOT>/packages/outline/src/helpers/OutlineValidationHelpers.js'
|
||||||
|
|
||||||
module.name_mapper='^outline-react/OutlineTreeView' -> '<PROJECT_ROOT>/packages/outline-react/src/OutlineTreeView.js'
|
module.name_mapper='^outline-react/OutlineTreeView' -> '<PROJECT_ROOT>/packages/outline-react/src/OutlineTreeView.js'
|
||||||
module.name_mapper='^outline-react/useOutlineEditor' -> '<PROJECT_ROOT>/packages/outline-react/src/useOutlineEditor.js'
|
module.name_mapper='^outline-react/useOutlineEditor' -> '<PROJECT_ROOT>/packages/outline-react/src/useOutlineEditor.js'
|
||||||
|
@ -49,6 +49,8 @@ module.exports = {
|
|||||||
'<rootDir>/packages/outline/src/helpers/OutlineNodeHelpers.js',
|
'<rootDir>/packages/outline/src/helpers/OutlineNodeHelpers.js',
|
||||||
'^outline/events$':
|
'^outline/events$':
|
||||||
'<rootDir>/packages/outline/src/helpers/OutlineEventHelpers.js',
|
'<rootDir>/packages/outline/src/helpers/OutlineEventHelpers.js',
|
||||||
|
'^outline/validation$':
|
||||||
|
'<rootDir>/packages/outline/src/helpers/OutlineValidationHelpers.js',
|
||||||
'^shared/getDOMTextNodeFromElement$':
|
'^shared/getDOMTextNodeFromElement$':
|
||||||
'<rootDir>/packages/shared/src/getDOMTextNodeFromElement.js',
|
'<rootDir>/packages/shared/src/getDOMTextNodeFromElement.js',
|
||||||
'^shared/isImmutableOrInert$':
|
'^shared/isImmutableOrInert$':
|
||||||
|
@ -18,6 +18,7 @@ module.exports = {
|
|||||||
'outline/nodes': 'outline/dist/OutlineNodeHelpers',
|
'outline/nodes': 'outline/dist/OutlineNodeHelpers',
|
||||||
'outline/events': 'outline/dist/OutlineEventHelpers',
|
'outline/events': 'outline/dist/OutlineEventHelpers',
|
||||||
'outline/offsets': 'outline/dist/OutlineOffsetHelpers',
|
'outline/offsets': 'outline/dist/OutlineOffsetHelpers',
|
||||||
|
'outline/validation': 'outline/dist/OutlineValidationHelpers',
|
||||||
// Outline React
|
// Outline React
|
||||||
'outline-react/OutlineTreeView': 'outline-react/dist/OutlineTreeView',
|
'outline-react/OutlineTreeView': 'outline-react/dist/OutlineTreeView',
|
||||||
'outline-react/useOutlineEditor': 'outline-react/dist/useOutlineEditor',
|
'outline-react/useOutlineEditor': 'outline-react/dist/useOutlineEditor',
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import type {OutlineEditor, EditorThemeClasses, EditorState} from 'outline';
|
import type {OutlineEditor, EditorThemeClasses, EditorState} from 'outline';
|
||||||
|
|
||||||
import {createEditor} from 'outline';
|
import {createEditor} from 'outline';
|
||||||
|
import {canShowPlaceholder} from 'outline/validation';
|
||||||
|
|
||||||
import {useCallback, useMemo, useRef, useState} from 'react';
|
import {useCallback, useMemo, useRef, useState} from 'react';
|
||||||
import useLayoutEffect from './shared/useLayoutEffect';
|
import useLayoutEffect from './shared/useLayoutEffect';
|
||||||
@ -40,11 +41,14 @@ export default function useOutlineEditor<EditorContext>(editorConfig?: {
|
|||||||
return editor.addListener('error', onError);
|
return editor.addListener('error', onError);
|
||||||
}, [editor, onError]);
|
}, [editor, onError]);
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
return editor.addListener('update', () => {
|
return editor.addListener('update', ({editorState}) => {
|
||||||
const canShowPlaceholder = editor.canShowPlaceholder();
|
const currentCanShowPlaceholder = canShowPlaceholder(
|
||||||
if (showPlaceholderRef.current !== canShowPlaceholder) {
|
editorState,
|
||||||
showPlaceholderRef.current = canShowPlaceholder;
|
editor.isComposing(),
|
||||||
setShowPlaceholder(canShowPlaceholder);
|
);
|
||||||
|
if (showPlaceholderRef.current !== currentCanShowPlaceholder) {
|
||||||
|
showPlaceholderRef.current = currentCanShowPlaceholder;
|
||||||
|
setShowPlaceholder(currentCanShowPlaceholder);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [editor]);
|
}, [editor]);
|
||||||
|
29
packages/outline-react/src/useOutlineIsBlank.js
Normal file
29
packages/outline-react/src/useOutlineIsBlank.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type {OutlineEditor} from 'outline';
|
||||||
|
|
||||||
|
import useLayoutEffect from './shared/useLayoutEffect';
|
||||||
|
import {useState} from 'react';
|
||||||
|
import {isBlank} from 'outline/validation';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED. Use useOutlineIsBlank
|
||||||
|
*/
|
||||||
|
export default function useCometOutlineIsBlank(editor: OutlineEditor): boolean {
|
||||||
|
const [isCurrentlyBlank, setIsBlank] = useState(true);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
return editor.addListener('update', ({editorState}) => {
|
||||||
|
const isComposing = editor.isComposing();
|
||||||
|
setIsBlank(isBlank(editorState, isComposing));
|
||||||
|
});
|
||||||
|
}, [editor]);
|
||||||
|
return isCurrentlyBlank;
|
||||||
|
}
|
@ -11,13 +11,18 @@ import type {OutlineEditor} from 'outline';
|
|||||||
|
|
||||||
import useLayoutEffect from './shared/useLayoutEffect';
|
import useLayoutEffect from './shared/useLayoutEffect';
|
||||||
import {useState} from 'react';
|
import {useState} from 'react';
|
||||||
|
import {isBlank} from 'outline/validation';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED. Use useOutlineIsBlank
|
||||||
|
*/
|
||||||
export default function useCometOutlineIsEmpty(editor: OutlineEditor): boolean {
|
export default function useCometOutlineIsEmpty(editor: OutlineEditor): boolean {
|
||||||
const [isCurrentlyEmpty, setIsEmpty] = useState(true);
|
const [isCurrentlyEmpty, setIsEmpty] = useState(true);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
return editor.addListener('update', () => {
|
return editor.addListener('update', ({editorState}) => {
|
||||||
setIsEmpty(editor.isEmpty());
|
const isComposing = editor.isComposing();
|
||||||
|
setIsEmpty(isBlank(editorState, isComposing));
|
||||||
});
|
});
|
||||||
}, [editor]);
|
}, [editor]);
|
||||||
return isCurrentlyEmpty;
|
return isCurrentlyEmpty;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
"./history": "./OutlineHistoryHelpers.js",
|
"./history": "./OutlineHistoryHelpers.js",
|
||||||
"./offsets": "./OutlineOffsetHelpers.js",
|
"./offsets": "./OutlineOffsetHelpers.js",
|
||||||
"./nodes": "./OutlineNodeHelpers.js",
|
"./nodes": "./OutlineNodeHelpers.js",
|
||||||
|
"./validation": "./OutlineValidationHelpers.js",
|
||||||
"./CodeNode": "./OutlineCodeNode.js",
|
"./CodeNode": "./OutlineCodeNode.js",
|
||||||
"./ParagraphNode": "./OutlineParagraphNode.js",
|
"./ParagraphNode": "./OutlineParagraphNode.js",
|
||||||
"./QuoteNode": "./OutlineQuoteNode.js",
|
"./QuoteNode": "./OutlineQuoteNode.js",
|
||||||
|
@ -950,14 +950,5 @@ describe('OutlineEditor tests', () => {
|
|||||||
'<div contenteditable="true" data-outline-editor="true"><p><div><span data-outline-text="true">A</span><div><span data-outline-text="true">C</span></div></div><div><span data-outline-text="true">B</span></div></p></div>',
|
'<div contenteditable="true" data-outline-editor="true"><p><div><span data-outline-text="true">A</span><div><span data-outline-text="true">C</span></div></div><div><span data-outline-text="true">B</span></div></p></div>',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('isEmpty', async () => {
|
|
||||||
expect(editor.isEmpty()).toBe(true);
|
|
||||||
await update((state: State) => {
|
|
||||||
const paragraph = state.getRoot().getFirstChild();
|
|
||||||
paragraph.append(createTextNode('foo'));
|
|
||||||
});
|
|
||||||
expect(editor.isEmpty()).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -247,6 +247,9 @@ class BaseOutlineEditor {
|
|||||||
isComposing(): boolean {
|
isComposing(): boolean {
|
||||||
return this._compositionKey != null;
|
return this._compositionKey != null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Deprecated. To be removed within a week.
|
||||||
|
*/
|
||||||
isEmpty(trim: boolean = true): boolean {
|
isEmpty(trim: boolean = true): boolean {
|
||||||
if (this.isComposing()) {
|
if (this.isComposing()) {
|
||||||
return false;
|
return false;
|
||||||
@ -422,6 +425,9 @@ class BaseOutlineEditor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Deprecated. To be removed within a week.
|
||||||
|
*/
|
||||||
canShowPlaceholder(): boolean {
|
canShowPlaceholder(): boolean {
|
||||||
if (!this.isEmpty(false)) {
|
if (!this.isEmpty(false)) {
|
||||||
return false;
|
return false;
|
||||||
@ -479,7 +485,7 @@ declare export class OutlineEditor {
|
|||||||
|
|
||||||
getObserver(): null | MutationObserver;
|
getObserver(): null | MutationObserver;
|
||||||
isComposing(): boolean;
|
isComposing(): boolean;
|
||||||
isEmpty(trim?: boolean): boolean;
|
// isEmpty(trim?: boolean): boolean;
|
||||||
registerNodeType(nodeType: string, klass: Class<OutlineNode>): void;
|
registerNodeType(nodeType: string, klass: Class<OutlineNode>): void;
|
||||||
addListener(type: 'error', listener: ErrorListener): () => void;
|
addListener(type: 'error', listener: ErrorListener): () => void;
|
||||||
addListener(type: 'update', listener: UpdateListener): () => void;
|
addListener(type: 'update', listener: UpdateListener): () => void;
|
||||||
@ -498,7 +504,7 @@ declare export class OutlineEditor {
|
|||||||
parseEditorState(stringifiedEditorState: string): EditorState;
|
parseEditorState(stringifiedEditorState: string): EditorState;
|
||||||
update(updateFn: (state: State) => void, callbackFn?: () => void): boolean;
|
update(updateFn: (state: State) => void, callbackFn?: () => void): boolean;
|
||||||
focus(callbackFn?: () => void): void;
|
focus(callbackFn?: () => void): void;
|
||||||
canShowPlaceholder(): boolean;
|
// canShowPlaceholder(): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEditorFromElement(element: Element): null | OutlineEditor {
|
export function getEditorFromElement(element: Element): null | OutlineEditor {
|
||||||
|
62
packages/outline/src/helpers/OutlineValidationHelpers.js
Normal file
62
packages/outline/src/helpers/OutlineValidationHelpers.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @flow strict
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type {EditorState} from 'outline';
|
||||||
|
|
||||||
|
import {getEditorStateTextContent} from '../core/OutlineUtils';
|
||||||
|
import {isBlockNode, isTextNode} from 'outline';
|
||||||
|
|
||||||
|
export function isBlank(
|
||||||
|
editorState: EditorState,
|
||||||
|
isEditorComposing: boolean,
|
||||||
|
trim?: boolean = true,
|
||||||
|
): boolean {
|
||||||
|
if (isEditorComposing) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let text = getEditorStateTextContent(editorState);
|
||||||
|
if (trim) {
|
||||||
|
text = text.trim();
|
||||||
|
}
|
||||||
|
return text === '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function canShowPlaceholder(
|
||||||
|
editorState: EditorState,
|
||||||
|
isComposing: boolean,
|
||||||
|
): boolean {
|
||||||
|
if (!isBlank(editorState, isComposing, false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const nodeMap = editorState._nodeMap;
|
||||||
|
// $FlowFixMe: root is always in the Map
|
||||||
|
const root = ((nodeMap.get('root'): any): RootNode);
|
||||||
|
const topBlockIDs = root.__children;
|
||||||
|
const topBlockIDsLength = topBlockIDs.length;
|
||||||
|
if (topBlockIDsLength > 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < topBlockIDsLength; i++) {
|
||||||
|
const topBlock = nodeMap.get(topBlockIDs[i]);
|
||||||
|
|
||||||
|
if (isBlockNode(topBlock)) {
|
||||||
|
if (topBlock.__type !== 'paragraph') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const children = topBlock.__children;
|
||||||
|
for (let s = 0; s < children.length; s++) {
|
||||||
|
const child = nodeMap.get(children[s]);
|
||||||
|
if (!isTextNode(child)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @flow strict
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type {State} from 'outline';
|
||||||
|
|
||||||
|
import {createTextNode} from 'outline';
|
||||||
|
import {createParagraphNode} from 'outline/ParagraphNode';
|
||||||
|
import {isBlank} from 'outline/validation';
|
||||||
|
import {initializeUnitTest} from '../../../__tests__/utils';
|
||||||
|
|
||||||
|
describe('OutlineNodeHelpers tests', () => {
|
||||||
|
initializeUnitTest((testEnv) => {
|
||||||
|
it('isBlank', async () => {
|
||||||
|
const editor = testEnv.editor;
|
||||||
|
expect(isBlank(editor.getEditorState(), editor.isComposing())).toBe(true);
|
||||||
|
await editor.update((state: State) => {
|
||||||
|
const root = state.getRoot();
|
||||||
|
const paragraph = createParagraphNode();
|
||||||
|
const text = createTextNode('foo');
|
||||||
|
root.append(paragraph);
|
||||||
|
paragraph.append(text);
|
||||||
|
});
|
||||||
|
expect(isBlank(editor.getEditorState(), editor.isComposing())).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -172,6 +172,12 @@ async function build(name, inputFile, outputFile) {
|
|||||||
'packages/outline/src/helpers/OutlineOffsetHelpers',
|
'packages/outline/src/helpers/OutlineOffsetHelpers',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
find: isWWW ? 'Outline/validation' : 'outline/validation',
|
||||||
|
replacement: path.resolve(
|
||||||
|
'packages/outline/src/helpers/OutlineValidationHelpers',
|
||||||
|
),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
// Extract error codes from invariant() messages into a file.
|
// Extract error codes from invariant() messages into a file.
|
||||||
|
Reference in New Issue
Block a user