UNPKG

@atlaskit/editor-plugin-scroll-into-view

Version:

Scroll-into-view plugin for @atlaskit/editor-core

68 lines (66 loc) 2.66 kB
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin'; import { PluginKey } from '@atlaskit/editor-prosemirror/state'; import { ReplaceStep, ReplaceAroundStep } from '@atlaskit/editor-prosemirror/transform'; import { TEXT_INPUT_RULE_TRANSACTION_KEY } from '@atlaskit/prosemirror-input-rules'; /** * Plugin to scroll the user's selection into view whenever the user updates * the document eg. inserting, deleting, formatting * * Behaviour is on by default, can be explicitly opted out of for a transaction by * setting scrollIntoView=false meta * We ignore collab transactions, appended transactions, transactions without steps, * transactions with addToHistory=false meta and typeahead trigger transactions */ export var scrollIntoViewPluginKey = new PluginKey('scrollIntoViewPlugin'); /** * Determines if a transaction contains changes that should trigger scrolling into view. * This includes: * - Specific step types (Replace, ReplaceAround) */ var hasRelevantChanges = function hasRelevantChanges(tr) { // Check if there are any steps that modified the document if (!tr.docChanged) { return false; } // Look for specific types of steps that should trigger scrolling var hasRelevantStep = tr.steps.some(function (step) { return step instanceof ReplaceStep || step instanceof ReplaceAroundStep; }); return hasRelevantStep; }; var createPlugin = function createPlugin() { return new SafePlugin({ key: scrollIntoViewPluginKey, appendTransaction: function appendTransaction(transactions, _oldState, newState) { if (!transactions.length) { return; } var tr = transactions[0]; if ((hasRelevantChanges(tr) || tr.storedMarksSet) && !tr.scrolledIntoView && tr.getMeta('scrollIntoView') !== false && // ignore anything we would not want to undo // this covers things like autofixing layouts, hovering table rows/cols tr.getMeta('addToHistory') !== false && // ignore collab changes from another user !tr.getMeta('isRemote') && // ignore any transaction coming from the input text rule plugin !tr.getMeta(TEXT_INPUT_RULE_TRANSACTION_KEY) && // ignore appended transactions as they should be treated as side effects tr.getMeta('appendedTransaction') === undefined) { return newState.tr.scrollIntoView(); } } }); }; export var scrollIntoViewPlugin = function scrollIntoViewPlugin() { return { name: 'scrollIntoView', pmPlugins: function pmPlugins() { return [{ name: 'scrollIntoView', plugin: function plugin() { return createPlugin(); } }]; } }; };