improve list handling
This commit is contained in:
parent
ae7bd79c7a
commit
7a744bef84
@ -203,10 +203,12 @@ const BackspaceCloseBlock = (options = {}) => ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const EditListPlugin = EditList({ types: ['bulleted-list', 'numbered-list'], typeItem: 'list-item' });
|
||||||
|
|
||||||
const slatePlugins = [
|
const slatePlugins = [
|
||||||
SoftBreak({ ignoreIn: ['paragraph', 'list-item', 'numbered-list', 'bulleted-list', 'table', 'table-row', 'table-cell'], closeAfter: 1 }),
|
SoftBreak({ ignoreIn: ['paragraph', 'list-item', 'numbered-list', 'bulleted-list', 'table', 'table-row', 'table-cell'], closeAfter: 1 }),
|
||||||
BackspaceCloseBlock({ ignoreIn: ['paragraph', 'list-item', 'bulleted-list', 'numbered-list', 'table', 'table-row', 'table-cell'] }),
|
BackspaceCloseBlock({ ignoreIn: ['paragraph', 'list-item', 'bulleted-list', 'numbered-list', 'table', 'table-row', 'table-cell'] }),
|
||||||
EditList({ types: ['bulleted-list', 'numbered-list'], typeItem: 'list-item' }),
|
EditListPlugin,
|
||||||
EditTable({ typeTable: 'table', typeRow: 'table-row', typeCell: 'table-cell' }),
|
EditTable({ typeTable: 'table', typeRow: 'table-row', typeCell: 'table-cell' }),
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -228,6 +230,10 @@ export default class Editor extends Component {
|
|||||||
nodes: NODE_COMPONENTS,
|
nodes: NODE_COMPONENTS,
|
||||||
marks: MARK_COMPONENTS,
|
marks: MARK_COMPONENTS,
|
||||||
rules: [
|
rules: [
|
||||||
|
/**
|
||||||
|
* If the editor is ever in an empty state, insert an empty
|
||||||
|
* paragraph block.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
match: object => object.kind === 'document',
|
match: object => object.kind === 'document',
|
||||||
validate: doc => {
|
validate: doc => {
|
||||||
@ -276,29 +282,30 @@ export default class Editor extends Component {
|
|||||||
};
|
};
|
||||||
if (data.key === 'enter') {
|
if (data.key === 'enter') {
|
||||||
/**
|
/**
|
||||||
* If a single void block is selected, and it's a direct descendant of the
|
* If "Enter" is pressed while a single void block is selected, a new
|
||||||
* document (top level), a new paragraph should be added above or below it
|
* paragraph should be added above or below it, and the current selection
|
||||||
* when 'Enter' is pressed, and the current selection should move to the
|
* should be collapsed to the start of the new paragraph.
|
||||||
* new paragraph.
|
|
||||||
*
|
*
|
||||||
* If the selected block is the first block in the document, create the
|
* If the selected block is the first block in the document, create the
|
||||||
* new block above it. If not, create the new block below it.
|
* new block above it. If not, create the new block below it.
|
||||||
*/
|
*/
|
||||||
const { document: doc, selection, anchorBlock, focusBlock } = state;
|
const { document: doc, selection, anchorBlock, focusBlock } = state;
|
||||||
const focusBlockIndex = doc.nodes.indexOf(focusBlock);
|
|
||||||
const focusBlockIsTopLevel = focusBlockIndex > -1;
|
|
||||||
const focusBlockIsFirstChild = focusBlockIndex === 0;
|
|
||||||
const singleBlockSelected = anchorBlock === focusBlock;
|
const singleBlockSelected = anchorBlock === focusBlock;
|
||||||
|
if (!singleBlockSelected || !focusBlock.isVoid) return;
|
||||||
|
|
||||||
if (focusBlock.isVoid && focusBlockIsTopLevel && singleBlockSelected) {
|
e.preventDefault();
|
||||||
e.preventDefault();
|
|
||||||
const newBlock = createDefaultBlock();
|
const focusBlockParent = doc.getParent(focusBlock.key);
|
||||||
const newBlockIndex = focusBlockIsFirstChild ? 0 : focusBlockIndex + 1;
|
const focusBlockIndex = focusBlockParent.nodes.indexOf(focusBlock);
|
||||||
return state.transform()
|
const focusBlockIsFirstChild = focusBlockIndex === 0;
|
||||||
.insertNodeByKey(doc.key, newBlockIndex, newBlock)
|
|
||||||
.collapseToStartOf(newBlock)
|
const newBlock = createDefaultBlock();
|
||||||
.apply();
|
const newBlockIndex = focusBlockIsFirstChild ? 0 : focusBlockIndex + 1;
|
||||||
}
|
|
||||||
|
return state.transform()
|
||||||
|
.insertNodeByKey(focusBlockParent.key, newBlockIndex, newBlock)
|
||||||
|
.collapseToStartOf(newBlock)
|
||||||
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.isMod) {
|
if (data.isMod) {
|
||||||
@ -340,41 +347,30 @@ export default class Editor extends Component {
|
|||||||
handleBlockClick = (event, type) => {
|
handleBlockClick = (event, type) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let { editorState } = this.state;
|
let { editorState } = this.state;
|
||||||
|
const { document: doc, selection } = editorState;
|
||||||
const transform = editorState.transform();
|
const transform = editorState.transform();
|
||||||
const doc = editorState.document;
|
|
||||||
const isList = this.hasBlock('list-item')
|
|
||||||
|
|
||||||
// Handle everything except list buttons.
|
// Handle everything except list buttons.
|
||||||
if (!['bulleted-list', 'numbered-list'].includes(type)) {
|
if (!['bulleted-list', 'numbered-list'].includes(type)) {
|
||||||
const isActive = this.hasBlock(type);
|
const isActive = this.hasBlock(type);
|
||||||
const transformed = transform.setBlock(isActive ? DEFAULT_NODE : type);
|
const transformed = transform.setBlock(isActive ? DEFAULT_NODE : type);
|
||||||
|
|
||||||
if (isList) {
|
|
||||||
transformed
|
|
||||||
.unwrapBlock('bulleted-list')
|
|
||||||
.unwrapBlock('numbered-list');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the extra wrapping required for list buttons.
|
// Handle the extra wrapping required for list buttons.
|
||||||
else {
|
else {
|
||||||
const isType = editorState.blocks.some(block => {
|
const isSameListType = editorState.blocks.some(block => {
|
||||||
return !!doc.getClosest(block.key, parent => parent.type === type);
|
return !!doc.getClosest(block.key, parent => parent.type === type);
|
||||||
});
|
});
|
||||||
|
const isInList = EditListPlugin.utils.isSelectionInList(editorState);
|
||||||
|
|
||||||
if (isList && isType) {
|
if (isInList && isSameListType) {
|
||||||
transform
|
EditListPlugin.transforms.unwrapList(transform, type);
|
||||||
.setBlock(DEFAULT_NODE)
|
} else if (isInList) {
|
||||||
.unwrapBlock('bulleted-list')
|
const currentListType = type === 'bulleted-list' ? 'numbered-list' : 'bulleted-list';
|
||||||
.unwrapBlock('numbered-list');
|
EditListPlugin.transforms.unwrapList(transform, currentListType);
|
||||||
} else if (isList) {
|
EditListPlugin.transforms.wrapInList(transform, type);
|
||||||
transform
|
|
||||||
.unwrapBlock(type === 'bulleted-list' ? 'numbered-list' : 'bulleted-list')
|
|
||||||
.wrapBlock(type);
|
|
||||||
} else {
|
} else {
|
||||||
transform
|
EditListPlugin.transforms.wrapInList(transform, type);
|
||||||
.setBlock('list-item')
|
|
||||||
.wrapBlock(type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user