UNPKG

@atlaskit/editor-common

Version:

A package that contains common classes and components for editor and renderer

103 lines (102 loc) 3.42 kB
/** * Creates a ProseMirror plugin's state and handles UI updates. * * Here's a few things to keep in mind: * - plugin's state is stored as a single object * - `Reducer` specifies how plugin's state changes in response to commands * - `Command` describes only what happen, but not how state changes * - `mapping` could be used to map ProseMirror positions stored in plugin's state * * Example: * const { createPluginState, createCommand, getPluginState } = pluginFactory( * reducer, * pluginKey * ); * * export const createPlugin = (dispatch: Dispatch, initialState) => * new SafePlugin({ * state: createPluginState(dispatch, initialState), * key: pluginKey * }); * * Example of a reducer: * * export const reducer = ( * state: TablePluginState, * action: TableAction, * ): TablePluginState => { * switch (action.type) { * case 'TOGGLE_CONTEXTUAL_MENU': * return { * ...state, * isContextualMenuOpen: !state.isContextualMenuOpen, * }; * default: * return state; * } * }; * * * Example of a command: * * export const toggleContextualMenu = createCommand({ * type: 'TOGGLE_CONTEXTUAL_MENU', * }, tr => tr.setMeta('addToHistory', false)); * */ // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any function isFunction(x) { return typeof x === 'function'; } export function pluginFactory(pluginKey, reducer) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var mapping = options.mapping, onDocChanged = options.onDocChanged, onSelectionChanged = options.onSelectionChanged; return { createPluginState: function createPluginState(dispatch, initialState) { return { init: function init(_, state) { return isFunction(initialState) ? initialState(state) : initialState; }, // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/max-params apply: function apply(tr, _pluginState, _oldEditorState, newEditorState) { var oldPluginState = mapping ? mapping(tr, _pluginState, newEditorState) : _pluginState; var newPluginState = oldPluginState; var meta = tr.getMeta(pluginKey); if (meta) { newPluginState = reducer(oldPluginState, meta); } if (onDocChanged && tr.docChanged) { newPluginState = onDocChanged(tr, newPluginState, newEditorState); } else if (onSelectionChanged && tr.selectionSet) { newPluginState = onSelectionChanged(tr, newPluginState, newEditorState); } if (newPluginState !== oldPluginState) { dispatch(pluginKey, newPluginState); } return newPluginState; } }; }, createCommand: function createCommand(action, transform) { return function (state, dispatch) { if (dispatch) { var _tr = transform ? transform(state.tr, state) : state.tr; var resolvedAction = isFunction(action) ? action(state) : action; if (_tr && resolvedAction) { dispatch(_tr.setMeta(pluginKey, resolvedAction)); } else { return false; } } return true; }; }, getPluginState: function getPluginState(state) { return pluginKey.getState(state); } }; }