@atlaskit/editor-plugin-scroll-into-view
Version:
Scroll-into-view plugin for @atlaskit/editor-core
68 lines (66 loc) • 2.66 kB
JavaScript
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();
}
}];
}
};
};