@atlaskit/editor-plugin-selection-marker
Version:
Selection marker plugin for @atlaskit/editor-core.
146 lines (144 loc) • 9.64 kB
JavaScript
"use strict";
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.selectionMarkerPlugin = void 0;
var _react = _interopRequireWildcard(require("react"));
var _hooks = require("@atlaskit/editor-common/hooks");
var _useSharedPluginStateSelector = require("@atlaskit/editor-common/use-shared-plugin-state-selector");
var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _main = require("./pm-plugins/main");
var _globalStyles = require("./ui/global-styles");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
var selectionMarkerPlugin = exports.selectionMarkerPlugin = function selectionMarkerPlugin(_ref) {
var config = _ref.config,
api = _ref.api;
return {
name: 'selectionMarker',
pmPlugins: function pmPlugins() {
return [{
name: 'selectionMarkerPmPlugin',
plugin: function plugin() {
return (0, _main.createPlugin)(api);
}
}];
},
getSharedState: function getSharedState(editorState) {
var _key$getState$forceHi, _key$getState, _key$getState2;
if (!editorState) {
return undefined;
}
return {
isForcedHidden: (_key$getState$forceHi = (_key$getState = _main.key.getState(editorState)) === null || _key$getState === void 0 ? void 0 : _key$getState.forceHide) !== null && _key$getState$forceHi !== void 0 ? _key$getState$forceHi : false,
isMarkerActive: !((_key$getState2 = _main.key.getState(editorState)) !== null && _key$getState2 !== void 0 && _key$getState2.shouldHideDecorations)
};
},
actions: {
// For now this is a very simple locking mechanism that only allows one
// plugin to hide / release at a time.
hideDecoration: function hideDecoration() {
var _api$selectionMarker, _api$core;
if (api !== null && api !== void 0 && (_api$selectionMarker = api.selectionMarker) !== null && _api$selectionMarker !== void 0 && (_api$selectionMarker = _api$selectionMarker.sharedState.currentState()) !== null && _api$selectionMarker !== void 0 && _api$selectionMarker.isForcedHidden) {
return undefined;
}
var success = api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(function (_ref2) {
var tr = _ref2.tr;
return tr.setMeta(_main.key, {
forceHide: true
});
});
if (!success) {
return undefined;
}
return cleanupHiddenDecoration(api);
},
queueHideDecoration: function queueHideDecoration(setCleanup) {
var result = api === null || api === void 0 ? void 0 : api.selectionMarker.actions.hideDecoration();
if (result === undefined) {
var _api$selectionMarker2;
var cleanup = api === null || api === void 0 || (_api$selectionMarker2 = api.selectionMarker) === null || _api$selectionMarker2 === void 0 ? void 0 : _api$selectionMarker2.sharedState.onChange(function (_ref3) {
var nextSharedState = _ref3.nextSharedState;
if ((nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isForcedHidden) === false && (nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.isMarkerActive) === false) {
var _result = api === null || api === void 0 ? void 0 : api.selectionMarker.actions.hideDecoration();
setCleanup(_result);
cleanup === null || cleanup === void 0 || cleanup();
}
});
return cleanup;
}
setCleanup(result);
return function () {};
}
},
usePluginHook: function usePluginHook(_ref4) {
var editorView = _ref4.editorView;
var editorHasNotBeenFocused = (0, _react.useRef)(true);
(0, _react.useEffect)(function () {
// relatch when editorView changes (pretty good signal for reinit)
editorHasNotBeenFocused.current = true;
}, [editorView]);
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['focus', 'typeAhead', 'editorDisabled', 'toolbar', 'decorations', 'userIntent'], function (states) {
var _states$focusState, _states$typeAheadStat, _states$editorDisable, _states$toolbarState, _states$decorationsSt, _states$userIntentSta;
return {
hasFocus: (_states$focusState = states.focusState) === null || _states$focusState === void 0 ? void 0 : _states$focusState.hasFocus,
isOpen: (_states$typeAheadStat = states.typeAheadState) === null || _states$typeAheadStat === void 0 ? void 0 : _states$typeAheadStat.isOpen,
editorDisabled: (_states$editorDisable = states.editorDisabledState) === null || _states$editorDisable === void 0 ? void 0 : _states$editorDisable.editorDisabled,
showToolbar: (_states$toolbarState = states.toolbarState) === null || _states$toolbarState === void 0 ? void 0 : _states$toolbarState.shouldShowToolbar,
hasDangerDecorations: (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true) ? (_states$decorationsSt = states.decorationsState) === null || _states$decorationsSt === void 0 ? void 0 : _states$decorationsSt.hasDangerDecorations : undefined,
currentUserIntent: (_states$userIntentSta = states.userIntentState) === null || _states$userIntentSta === void 0 ? void 0 : _states$userIntentSta.currentUserIntent
};
}),
hasFocus = _useSharedPluginState.hasFocus,
isOpen = _useSharedPluginState.isOpen,
editorDisabled = _useSharedPluginState.editorDisabled,
showToolbar = _useSharedPluginState.showToolbar,
hasDangerDecorations = _useSharedPluginState.hasDangerDecorations,
currentUserIntent = _useSharedPluginState.currentUserIntent;
var isForcedHidden = (0, _useSharedPluginStateSelector.useSharedPluginStateSelector)(api, 'selectionMarker.isForcedHidden');
(0, _react.useEffect)(function () {
// On editor init we should use this latch to keep the marker hidden until
// editor has received focus. This means editor will be initially hidden until
// the first focus occurs, and after first focus the normal above rules will
// apply
if (hasFocus === true) {
editorHasNotBeenFocused.current = false;
}
var isBlockMenuOpen = currentUserIntent === 'blockMenuOpen' && (0, _experiments.editorExperiment)('platform_editor_block_menu', true);
/**
* There are a number of conditions we should not show the marker,
* - Editor has not been focused: to keep the marker hidden until first focus if config is set
* - Focus: to ensure it doesn't interrupt the normal cursor
* - Typeahead Open: To ensure it doesn't show when we're typing in the typeahead
* - Disabled: So that it behaves similar to the renderer in live pages/disabled
* - Via the API: If another plugin has requested it to be hidden (force hidden).
* - If danger styles is shown in decorationsPlugin, then we don't need to show the selection marker
*/
var shouldHide = (config === null || config === void 0 ? void 0 : config.hideCursorOnInit) && editorHasNotBeenFocused.current || hasFocus || (isOpen !== null && isOpen !== void 0 ? isOpen : false) || isForcedHidden || (editorDisabled !== null && editorDisabled !== void 0 ? editorDisabled : false) || (showToolbar !== null && showToolbar !== void 0 ? showToolbar : false) || !!hasDangerDecorations && (0, _experiments.editorExperiment)('platform_editor_block_menu', true) || isBlockMenuOpen;
requestAnimationFrame(function () {
return (0, _main.dispatchShouldHideDecorations)(editorView, shouldHide);
});
}, [editorView, hasFocus, isOpen, isForcedHidden, editorDisabled, showToolbar, hasDangerDecorations, currentUserIntent]);
},
contentComponent: function contentComponent() {
return /*#__PURE__*/_react.default.createElement(_globalStyles.GlobalStylesWrapper, null);
}
};
};
function cleanupHiddenDecoration(api) {
var hasRun = false;
return function () {
var _api$selectionMarker3;
if (!hasRun && api !== null && api !== void 0 && (_api$selectionMarker3 = api.selectionMarker) !== null && _api$selectionMarker3 !== void 0 && (_api$selectionMarker3 = _api$selectionMarker3.sharedState.currentState()) !== null && _api$selectionMarker3 !== void 0 && _api$selectionMarker3.isForcedHidden) {
var _api$core2;
hasRun = true;
return api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(function (_ref5) {
var tr = _ref5.tr;
return tr.setMeta(_main.key, {
forceHide: false
});
});
}
};
}