@atlaskit/editor-plugin-placeholder-text
Version:
placeholder text plugin for @atlaskit/editor-core
284 lines (282 loc) • 12 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createPlugin = createPlugin;
exports.default = void 0;
var _react = _interopRequireDefault(require("react"));
var _adfSchema = require("@atlaskit/adf-schema");
var _analytics = require("@atlaskit/editor-common/analytics");
var _hooks = require("@atlaskit/editor-common/hooks");
var _messages = require("@atlaskit/editor-common/messages");
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
var _utils = require("@atlaskit/editor-common/utils");
var _state = require("@atlaskit/editor-prosemirror/state");
var _text = _interopRequireDefault(require("@atlaskit/icon/core/text"));
var _actions = require("./editor-actions/actions");
var _cursor = require("./pm-plugins/fake-text-cursor/cursor");
var _placeholderTextNodeview = require("./pm-plugins/placeholder-text-nodeview");
var _pluginKey = require("./pm-plugins/plugin-key");
var _selectionUtils = require("./pm-plugins/utils/selection-utils");
var _PlaceholderFloatingToolbar = _interopRequireDefault(require("./ui/PlaceholderFloatingToolbar"));
var getOpenTypeAhead = function getOpenTypeAhead(trigger, api) {
var _api$typeAhead, _api$typeAhead2;
var typeAheadHandler = api === null || api === void 0 || (_api$typeAhead = api.typeAhead) === null || _api$typeAhead === void 0 || (_api$typeAhead = _api$typeAhead.actions) === null || _api$typeAhead === void 0 ? void 0 : _api$typeAhead.findHandlerByTrigger(trigger);
if (!typeAheadHandler || !typeAheadHandler.id) {
return null;
}
return api === null || api === void 0 || (_api$typeAhead2 = api.typeAhead) === null || _api$typeAhead2 === void 0 || (_api$typeAhead2 = _api$typeAhead2.actions) === null || _api$typeAhead2 === void 0 ? void 0 : _api$typeAhead2.openAtTransaction({
triggerHandler: typeAheadHandler,
inputMethod: _analytics.INPUT_METHOD.KEYBOARD
});
};
function createPlugin(dispatch, options, api) {
var allowInserting = !!options.allowInserting;
return new _safePlugin.SafePlugin({
key: _pluginKey.pluginKey,
state: {
init: function init() {
return {
showInsertPanelAt: null,
allowInserting: allowInserting
};
},
apply: function apply(tr, state) {
var meta = tr.getMeta(_pluginKey.pluginKey);
if (meta && meta.showInsertPanelAt !== undefined) {
var newState = {
showInsertPanelAt: meta.showInsertPanelAt,
allowInserting: allowInserting
};
dispatch(_pluginKey.pluginKey, newState);
return newState;
} else if (state.showInsertPanelAt) {
var _newState = {
showInsertPanelAt: tr.mapping.map(state.showInsertPanelAt),
allowInserting: allowInserting
};
dispatch(_pluginKey.pluginKey, _newState);
return _newState;
}
return state;
}
},
appendTransaction: function appendTransaction(transactions, oldState, newState) {
if (transactions.some(function (txn) {
return txn.docChanged;
})) {
var didPlaceholderExistBeforeTxn = oldState.selection.$head.nodeAfter === newState.selection.$head.nodeAfter;
var adjacentNode = newState.selection.$head.nodeAfter;
var adjacentNodePos = newState.selection.$head.pos;
var placeholderNodeType = newState.schema.nodes.placeholder;
if (adjacentNode && adjacentNode.type === placeholderNodeType && didPlaceholderExistBeforeTxn) {
var _$newHead$nodeBefore;
var $newHead = newState.selection.$head;
var $oldHead = oldState.selection.$head;
// Check that cursor has moved forward in the document **and** that there is content before the cursor
var cursorMoved = $oldHead.pos < $newHead.pos;
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var nodeBeforeHasContent = !(0, _utils.isNodeEmpty)($newHead.nodeBefore);
var nodeBeforeIsInline = (_$newHead$nodeBefore = $newHead.nodeBefore) === null || _$newHead$nodeBefore === void 0 ? void 0 : _$newHead$nodeBefore.type.isInline;
if (cursorMoved && (nodeBeforeHasContent || nodeBeforeIsInline)) {
var _NodeSelection$create = _state.NodeSelection.create(newState.doc, adjacentNodePos),
$from = _NodeSelection$create.$from,
$to = _NodeSelection$create.$to;
return newState.tr.deleteRange($from.pos, $to.pos);
}
}
}
// Handle Fake Text Cursor for Floating Toolbar
if (!_pluginKey.pluginKey.getState(oldState).showInsertPanelAt && _pluginKey.pluginKey.getState(newState).showInsertPanelAt) {
return newState.tr.setSelection(new _cursor.FakeTextCursorSelection(newState.selection.$from));
}
if (_pluginKey.pluginKey.getState(oldState).showInsertPanelAt && !_pluginKey.pluginKey.getState(newState).showInsertPanelAt) {
if (newState.selection instanceof _cursor.FakeTextCursorSelection) {
return newState.tr.setSelection(new _state.TextSelection(newState.selection.$from));
}
}
return;
},
props: {
decorations: _cursor.drawFakeTextCursor,
handleDOMEvents: {
beforeinput: function beforeinput(view, event) {
var state = view.state;
if (event instanceof InputEvent && !event.isComposing && event.inputType === 'insertText' && (0, _selectionUtils.isSelectionAtPlaceholder)(view.state.selection)) {
event.stopPropagation();
event.preventDefault();
var startNodePosition = state.selection.from;
var content = event.data || '';
var tr = view.state.tr;
tr.delete(startNodePosition, startNodePosition + 1);
var openTypeAhead = getOpenTypeAhead(content, api);
if (openTypeAhead) {
openTypeAhead(tr);
} else {
tr.insertText(content);
}
view.dispatch(tr);
return true;
}
return false;
}
},
nodeViews: {
placeholder: function placeholder(node, view, getPos) {
return new _placeholderTextNodeview.PlaceholderTextNodeView(node, view, getPos);
}
}
}
});
}
function ContentComponent(_ref) {
var editorView = _ref.editorView,
dependencyApi = _ref.dependencyApi,
popupsMountPoint = _ref.popupsMountPoint,
popupsBoundariesElement = _ref.popupsBoundariesElement;
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(dependencyApi, ['placeholderText'], function (states) {
var _states$placeholderTe;
return {
showInsertPanelAt: (_states$placeholderTe = states.placeholderTextState) === null || _states$placeholderTe === void 0 ? void 0 : _states$placeholderTe.showInsertPanelAt
};
}),
showInsertPanelAt = _useSharedPluginState.showInsertPanelAt;
var insertPlaceholderText = function insertPlaceholderText(value) {
return (0, _actions.insertPlaceholderTextAtSelection)(value)(editorView.state, editorView.dispatch);
};
var hidePlaceholderToolbar = function hidePlaceholderToolbar() {
return (0, _actions.hidePlaceholderFloatingToolbar)(editorView.state, editorView.dispatch);
};
var getNodeFromPos = function getNodeFromPos(pos) {
return editorView.domAtPos(pos).node;
};
var getFixedCoordinatesFromPos = function getFixedCoordinatesFromPos(pos) {
return editorView.coordsAtPos(pos);
};
var setFocusInEditor = function setFocusInEditor() {
return editorView.focus();
};
if (showInsertPanelAt) {
return /*#__PURE__*/_react.default.createElement(_PlaceholderFloatingToolbar.default
// Ignored via go/ees005
// eslint-disable-next-line @atlaskit/editor/no-as-casting
, {
editorViewDOM: editorView.dom,
popupsMountPoint: popupsMountPoint,
popupsBoundariesElement: popupsBoundariesElement,
getFixedCoordinatesFromPos: getFixedCoordinatesFromPos,
getNodeFromPos: getNodeFromPos,
hidePlaceholderFloatingToolbar: hidePlaceholderToolbar,
showInsertPanelAt: showInsertPanelAt,
insertPlaceholder: insertPlaceholderText,
setFocusInEditor: setFocusInEditor
});
}
return null;
}
var basePlaceholderTextPlugin = function basePlaceholderTextPlugin(_ref2) {
var api = _ref2.api,
options = _ref2.config;
return {
name: 'placeholderText',
nodes: function nodes() {
return [{
name: 'placeholder',
node: _adfSchema.placeholder
}];
},
pmPlugins: function pmPlugins() {
return [{
name: 'placeholderText',
plugin: function plugin(_ref3) {
var dispatch = _ref3.dispatch;
return createPlugin(dispatch, options, api);
}
}];
},
actions: {
showPlaceholderFloatingToolbar: _actions.showPlaceholderFloatingToolbar
},
getSharedState: function getSharedState(editorState) {
if (!editorState) {
return undefined;
}
var _ref4 = _pluginKey.pluginKey.getState(editorState) || {
showInsertPanelAt: null
},
showInsertPanelAt = _ref4.showInsertPanelAt,
allowInserting = _ref4.allowInserting;
return {
showInsertPanelAt: showInsertPanelAt,
allowInserting: !!allowInserting
};
},
contentComponent: function contentComponent(_ref5) {
var editorView = _ref5.editorView,
popupsMountPoint = _ref5.popupsMountPoint,
popupsBoundariesElement = _ref5.popupsBoundariesElement;
if (!editorView) {
return null;
}
return /*#__PURE__*/_react.default.createElement(ContentComponent, {
editorView: editorView,
popupsMountPoint: popupsMountPoint,
popupsBoundariesElement: popupsBoundariesElement,
dependencyApi: api
});
}
};
};
var decorateWithPluginOptions = function decorateWithPluginOptions(plugin, options, api) {
if (!options.allowInserting) {
return plugin;
}
plugin.pluginsOptions = {
quickInsert: function quickInsert(_ref6) {
var formatMessage = _ref6.formatMessage;
return [{
id: 'placeholderText',
title: formatMessage(_messages.toolbarInsertBlockMessages.placeholderText),
description: formatMessage(_messages.toolbarInsertBlockMessages.placeholderTextDescription),
priority: 1400,
keywords: ['placeholder'],
icon: function icon() {
return /*#__PURE__*/_react.default.createElement(_text.default, {
label: ""
});
},
action: function action(insert, state) {
var _api$analytics;
var tr = state.tr;
tr.setMeta(_pluginKey.pluginKey, {
showInsertPanelAt: tr.selection.anchor
});
var resolvedInputMethod = _analytics.INPUT_METHOD.QUICK_INSERT;
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
action: _analytics.ACTION.INSERTED,
actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
actionSubjectId: _analytics.ACTION_SUBJECT_ID.PLACEHOLDER_TEXT,
attributes: {
inputMethod: resolvedInputMethod
},
eventType: _analytics.EVENT_TYPE.TRACK
})(tr);
return tr;
}
}];
}
};
return plugin;
};
var placeholderTextPlugin = function placeholderTextPlugin(_ref7) {
var _ref7$config = _ref7.config,
options = _ref7$config === void 0 ? {} : _ref7$config,
api = _ref7.api;
return decorateWithPluginOptions(basePlaceholderTextPlugin({
config: options,
api: api
}), options, api);
};
var _default = exports.default = placeholderTextPlugin;