mirror of
https://github.com/facebook/lexical.git
synced 2025-08-06 00:21:47 +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/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/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/useOutlineEditor' -> '<PROJECT_ROOT>/packages/outline-react/src/useOutlineEditor.js'
|
||||
|
@ -49,6 +49,8 @@ module.exports = {
|
||||
'<rootDir>/packages/outline/src/helpers/OutlineNodeHelpers.js',
|
||||
'^outline/events$':
|
||||
'<rootDir>/packages/outline/src/helpers/OutlineEventHelpers.js',
|
||||
'^outline/validation$':
|
||||
'<rootDir>/packages/outline/src/helpers/OutlineValidationHelpers.js',
|
||||
'^shared/getDOMTextNodeFromElement$':
|
||||
'<rootDir>/packages/shared/src/getDOMTextNodeFromElement.js',
|
||||
'^shared/isImmutableOrInert$':
|
||||
|
@ -18,6 +18,7 @@ module.exports = {
|
||||
'outline/nodes': 'outline/dist/OutlineNodeHelpers',
|
||||
'outline/events': 'outline/dist/OutlineEventHelpers',
|
||||
'outline/offsets': 'outline/dist/OutlineOffsetHelpers',
|
||||
'outline/validation': 'outline/dist/OutlineValidationHelpers',
|
||||
// Outline React
|
||||
'outline-react/OutlineTreeView': 'outline-react/dist/OutlineTreeView',
|
||||
'outline-react/useOutlineEditor': 'outline-react/dist/useOutlineEditor',
|
||||
|
@ -10,6 +10,7 @@
|
||||
import type {OutlineEditor, EditorThemeClasses, EditorState} from 'outline';
|
||||
|
||||
import {createEditor} from 'outline';
|
||||
import {canShowPlaceholder} from 'outline/validation';
|
||||
|
||||
import {useCallback, useMemo, useRef, useState} from 'react';
|
||||
import useLayoutEffect from './shared/useLayoutEffect';
|
||||
@ -40,11 +41,14 @@ export default function useOutlineEditor<EditorContext>(editorConfig?: {
|
||||
return editor.addListener('error', onError);
|
||||
}, [editor, onError]);
|
||||
useLayoutEffect(() => {
|
||||
return editor.addListener('update', () => {
|
||||
const canShowPlaceholder = editor.canShowPlaceholder();
|
||||
if (showPlaceholderRef.current !== canShowPlaceholder) {
|
||||
showPlaceholderRef.current = canShowPlaceholder;
|
||||
setShowPlaceholder(canShowPlaceholder);
|
||||
return editor.addListener('update', ({editorState}) => {
|
||||
const currentCanShowPlaceholder = canShowPlaceholder(
|
||||
editorState,
|
||||
editor.isComposing(),
|
||||
);
|
||||
if (showPlaceholderRef.current !== currentCanShowPlaceholder) {
|
||||
showPlaceholderRef.current = currentCanShowPlaceholder;
|
||||
setShowPlaceholder(currentCanShowPlaceholder);
|
||||
}
|
||||
});
|
||||
}, [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 {useState} from 'react';
|
||||
import {isBlank} from 'outline/validation';
|
||||
|
||||
/**
|
||||
* DEPRECATED. Use useOutlineIsBlank
|
||||
*/
|
||||
export default function useCometOutlineIsEmpty(editor: OutlineEditor): boolean {
|
||||
const [isCurrentlyEmpty, setIsEmpty] = useState(true);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
return editor.addListener('update', () => {
|
||||
setIsEmpty(editor.isEmpty());
|
||||
return editor.addListener('update', ({editorState}) => {
|
||||
const isComposing = editor.isComposing();
|
||||
setIsEmpty(isBlank(editorState, isComposing));
|
||||
});
|
||||
}, [editor]);
|
||||
return isCurrentlyEmpty;
|
||||
|
@ -30,6 +30,7 @@
|
||||
"./history": "./OutlineHistoryHelpers.js",
|
||||
"./offsets": "./OutlineOffsetHelpers.js",
|
||||
"./nodes": "./OutlineNodeHelpers.js",
|
||||
"./validation": "./OutlineValidationHelpers.js",
|
||||
"./CodeNode": "./OutlineCodeNode.js",
|
||||
"./ParagraphNode": "./OutlineParagraphNode.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>',
|
||||
);
|
||||
});
|
||||
|
||||
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 {
|
||||
return this._compositionKey != null;
|
||||
}
|
||||
/**
|
||||
* Deprecated. To be removed within a week.
|
||||
*/
|
||||
isEmpty(trim: boolean = true): boolean {
|
||||
if (this.isComposing()) {
|
||||
return false;
|
||||
@ -422,6 +425,9 @@ class BaseOutlineEditor {
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Deprecated. To be removed within a week.
|
||||
*/
|
||||
canShowPlaceholder(): boolean {
|
||||
if (!this.isEmpty(false)) {
|
||||
return false;
|
||||
@ -479,7 +485,7 @@ declare export class OutlineEditor {
|
||||
|
||||
getObserver(): null | MutationObserver;
|
||||
isComposing(): boolean;
|
||||
isEmpty(trim?: boolean): boolean;
|
||||
// isEmpty(trim?: boolean): boolean;
|
||||
registerNodeType(nodeType: string, klass: Class<OutlineNode>): void;
|
||||
addListener(type: 'error', listener: ErrorListener): () => void;
|
||||
addListener(type: 'update', listener: UpdateListener): () => void;
|
||||
@ -498,7 +504,7 @@ declare export class OutlineEditor {
|
||||
parseEditorState(stringifiedEditorState: string): EditorState;
|
||||
update(updateFn: (state: State) => void, callbackFn?: () => void): boolean;
|
||||
focus(callbackFn?: () => void): void;
|
||||
canShowPlaceholder(): boolean;
|
||||
// canShowPlaceholder(): boolean;
|
||||
}
|
||||
|
||||
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',
|
||||
),
|
||||
},
|
||||
{
|
||||
find: isWWW ? 'Outline/validation' : 'outline/validation',
|
||||
replacement: path.resolve(
|
||||
'packages/outline/src/helpers/OutlineValidationHelpers',
|
||||
),
|
||||
},
|
||||
],
|
||||
}),
|
||||
// Extract error codes from invariant() messages into a file.
|
||||
|
Reference in New Issue
Block a user