migrate from transform API to change API

This commit is contained in:
Shawn Erquhart 2017-10-02 11:23:47 -04:00
parent 8c04b4f1d5
commit af2eb78e2b
5 changed files with 61 additions and 61 deletions

View File

@ -18,16 +18,16 @@ export default class RawEditor extends React.Component {
return !this.state.editorState.equals(nextState.editorState);
}
handleChange = editorState => {
this.setState({ editorState });
}
handleChange = change => {
this.setState({ editorState: change.state });
};
/**
* When the document value changes, serialize from Slate's AST back to plain
* text (which is Markdown) and pass that up as the new value.
*/
handleDocumentChange = debounce((doc, editorState) => {
const value = Plain.serialize(editorState);
handleDocumentChange = debounce((doc, change) => {
const value = Plain.serialize(change.state);
this.props.onChange(value);
}, 150);
@ -36,10 +36,10 @@ export default class RawEditor extends React.Component {
* to the document. Selection logic (where to insert, whether to replace) is
* handled by Slate.
*/
handlePaste = (e, data, state) => {
handlePaste = (e, data, change) => {
if (data.text) {
const fragment = Plain.deserialize(data.text).document;
return state.transform().insertFragment(fragment).apply();
return change.insertFragment(fragment);
}
};

View File

@ -35,17 +35,17 @@ export default class Editor extends Component {
return !this.state.editorState.equals(nextState.editorState);
}
handlePaste = (e, data, state) => {
handlePaste = (e, data, change) => {
if (data.type !== 'html' || data.isShift) {
return;
}
const ast = htmlToSlate(data.html);
const { document: doc } = Raw.deserialize(ast, { terse: true });
return state.transform().insertFragment(doc).apply();
return change.insertFragment(doc);
}
handleDocumentChange = debounce((doc, editorState) => {
const raw = Raw.serialize(editorState, { terse: true });
handleDocumentChange = debounce((doc, change) => {
const raw = Raw.serialize(change.state, { terse: true });
const plugins = this.state.shortcodePlugins;
const markdown = slateToMarkdown(raw, plugins);
this.props.onChange(markdown);
@ -56,21 +56,22 @@ export default class Editor extends Component {
handleMarkClick = (event, type) => {
event.preventDefault();
const resolvedState = this.state.editorState.transform().focus().toggleMark(type).apply();
this.ref.onChange(resolvedState);
this.setState({ editorState: resolvedState });
const resolvedChange = this.state.editorState.change().focus().toggleMark(type);
this.ref.onChange(resolvedChange);
this.setState({ editorState: resolvedChange.state });
};
handleBlockClick = (event, type) => {
event.preventDefault();
let { editorState } = this.state;
const { document: doc, selection } = editorState;
const transform = editorState.transform();
const { unwrapList, wrapInList } = EditListConfigured.changes;
let change = editorState.change();
// Handle everything except list buttons.
if (!['bulleted-list', 'numbered-list'].includes(type)) {
const isActive = this.hasBlock(type);
const transformed = transform.setBlock(isActive ? 'paragraph' : type);
change = change.setBlock(isActive ? 'paragraph' : type);
}
// Handle the extra wrapping required for list buttons.
@ -81,19 +82,18 @@ export default class Editor extends Component {
const isInList = EditListConfigured.utils.isSelectionInList(editorState);
if (isInList && isSameListType) {
EditListConfigured.transforms.unwrapList(transform, type);
change = change.call(unwrapList, type);
} else if (isInList) {
const currentListType = type === 'bulleted-list' ? 'numbered-list' : 'bulleted-list';
EditListConfigured.transforms.unwrapList(transform, currentListType);
EditListConfigured.transforms.wrapInList(transform, type);
change = change.call(unwrapList, currentListType).call(wrapInList, type);
} else {
EditListConfigured.transforms.wrapInList(transform, type);
change = change.call(wrapInList, type);
}
}
const resolvedState = transform.focus().apply();
this.ref.onChange(resolvedState);
this.setState({ editorState: resolvedState });
const resolvedChange = change.focus();
this.ref.onChange(resolvedChange);
this.setState({ editorState: resolvedChange.state });
};
hasLinks = () => {
@ -101,12 +101,12 @@ export default class Editor extends Component {
};
handleLink = () => {
let { editorState } = this.state;
let change = this.state.editorState.change();
// If the current selection contains links, clicking the "link" button
// should simply unlink them.
if (this.hasLinks()) {
editorState = editorState.transform().unwrapInline('link').apply();
change = change.unwrapInline('link');
}
else {
@ -115,23 +115,20 @@ export default class Editor extends Component {
// If nothing is entered in the URL prompt, do nothing.
if (!url) return;
let transform = editorState.transform();
// If no text is selected, use the entered URL as text.
if (editorState.isCollapsed) {
transform = transform
if (change.state.isCollapsed) {
change = change
.insertText(url)
.extend(0 - url.length);
}
editorState = transform
change = change
.wrapInline({ type: 'link', data: { url } })
.collapseToEnd()
.apply();
.collapseToEnd();
}
this.ref.onChange(editorState);
this.setState({ editorState });
this.ref.onChange(change);
this.setState({ editorState: change.state });
};
handlePluginSubmit = (plugin, shortcodeData) => {
@ -142,9 +139,9 @@ export default class Editor extends Component {
};
const nodes = [Text.createFromString('')];
const block = { kind: 'block', type: 'shortcode', data, isVoid: true, nodes };
const resolvedState = editorState.transform().insertBlock(block).focus().apply();
this.ref.onChange(resolvedState);
this.setState({ editorState: resolvedState });
const resolvedChange = editorState.change().insertBlock(block).focus();
this.ref.onChange(resolvedChange);
this.setState({ editorState: resolvedChange.state });
};
handleToggle = () => {
@ -158,6 +155,10 @@ export default class Editor extends Component {
return { onAction: e => handler(e, type), active: isActive(type) };
};
handleChange = change => {
this.setState({ editorState: change.state });
};
render() {
const { onAddAsset, onRemoveAsset, getAsset } = this.props;
@ -194,7 +195,7 @@ export default class Editor extends Component {
state={this.state.editorState}
schema={this.state.schema}
plugins={plugins}
onChange={editorState => this.setState({ editorState })}
onChange={this.handleChange}
onDocumentChange={this.handleDocumentChange}
onKeyDown={onKeyDown}
onPaste={this.handlePaste}

View File

@ -2,7 +2,7 @@ import { Block, Text } from 'slate';
export default onKeyDown;
function onKeyDown(e, data, state) {
function onKeyDown(e, data, change) {
const createDefaultBlock = () => {
return Block.create({
type: 'paragraph',
@ -18,7 +18,7 @@ function onKeyDown(e, data, state) {
* 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.
*/
const { document: doc, selection, anchorBlock, focusBlock } = state;
const { document: doc, selection, anchorBlock, focusBlock } = change.state;
const singleBlockSelected = anchorBlock === focusBlock;
if (!singleBlockSelected || !focusBlock.isVoid) return;
@ -31,10 +31,9 @@ function onKeyDown(e, data, state) {
const newBlock = createDefaultBlock();
const newBlockIndex = focusBlockIsFirstChild ? 0 : focusBlockIndex + 1;
return state.transform()
return change
.insertNodeByKey(focusBlockParent.key, newBlockIndex, newBlock)
.collapseToStartOf(newBlock)
.apply();
.collapseToStartOf(newBlock);
}
if (data.isMod) {
@ -61,7 +60,7 @@ function onKeyDown(e, data, state) {
if (mark) {
e.preventDefault();
return state.transform().toggleMark(mark).apply();
return change.toggleMark(mark);
}
}
};

View File

@ -4,31 +4,30 @@ import EditList from 'slate-edit-list';
import EditTable from 'slate-edit-table';
const SoftBreak = (options = {}) => ({
onKeyDown(e, data, state) {
onKeyDown(e, data, change) {
if (data.key != 'enter') return;
if (options.shift && e.shiftKey == false) return;
const { onlyIn, ignoreIn, closeAfter, unwrapBlocks, defaultBlock = 'paragraph' } = options;
const { type, nodes } = state.startBlock;
const { type, nodes } = change.state.startBlock;
if (onlyIn && !onlyIn.includes(type)) return;
if (ignoreIn && ignoreIn.includes(type)) return;
const shouldClose = nodes.last().characters.takeLast(closeAfter).every(c => c.text === '\n');
if (closeAfter && shouldClose) {
const trimmed = state.transform().deleteBackward(closeAfter);
const trimmed = change.deleteBackward(closeAfter);
const unwrapped = unwrapBlocks
? unwrapBlocks.reduce((acc, blockType) => acc.unwrapBlock(blockType), trimmed)
: trimmed;
return unwrapped.insertBlock(defaultBlock).apply();
return unwrapped.insertBlock(defaultBlock);
}
const textNode = Text.createFromString('\n');
const breakNode = Inline.create({ type: 'break', nodes: [ textNode ] });
return state.transform()
return change
.insertInline(breakNode)
.insertText('')
.collapseToStartOfNextText()
.apply();
.collapseToStartOfNextText();
}
});
@ -42,10 +41,11 @@ export const SoftBreakConfigured = SoftBreak(SoftBreakOpts);
export const ParagraphSoftBreakConfigured = SoftBreak({ onlyIn: ['paragraph'], shift: true });
const BreakToDefaultBlock = ({ onlyIn = [], defaultBlock = 'paragraph' }) => ({
onKeyDown(e, data, state) {
onKeyDown(e, data, change) {
const { state } = change;
if (data.key != 'enter' || e.shiftKey == true || state.isExpanded) return;
if (onlyIn.includes(state.startBlock.type)) {
return state.transform().insertBlock(defaultBlock).apply();
return change.insertBlock(defaultBlock);
}
}
});
@ -57,11 +57,11 @@ const BreakToDefaultBlockOpts = {
export const BreakToDefaultBlockConfigured = BreakToDefaultBlock(BreakToDefaultBlockOpts);
const BackspaceCloseBlock = (options = {}) => ({
onKeyDown(e, data, state) {
onKeyDown(e, data, change) {
if (data.key != 'backspace') return;
const { defaultBlock = 'paragraph', ignoreIn, onlyIn } = options;
const { startBlock } = state;
const { startBlock } = change.state;
const { type } = startBlock;
if (onlyIn && !onlyIn.includes(type)) return;
@ -71,7 +71,7 @@ const BackspaceCloseBlock = (options = {}) => ({
const isEmpty = !characters || characters.isEmpty();
if (isEmpty) {
return state.transform().insertBlock(defaultBlock).focus().apply();
return change.insertBlock(defaultBlock).focus();
}
}
});

View File

@ -15,13 +15,13 @@ const enforceNeverEmpty = {
const hasBlocks = !doc.getBlocks().isEmpty();
return hasBlocks ? null : {};
},
normalize: transform => {
normalize: change => {
const block = Block.create({
type: 'paragraph',
nodes: [Text.createFromString('')],
});
const { key } = transform.state.document;
return transform.insertNodeByKey(key, 0, block).focus();
const { key } = change.state.document;
return change.insertNodeByKey(key, 0, block).focus();
},
};
@ -35,8 +35,8 @@ const shortcodesAtRoot = {
return node.type === 'shortcode' && doc.getParent(node.key).key !== doc.key;
});
},
normalize: (transform, doc, node) => {
return transform.unwrapNodeByKey(node.key);
normalize: (change, doc, node) => {
return change.unwrapNodeByKey(node.key);
},
};