UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

217 lines • 8.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var prosemirror_1 = require("../../prosemirror"); var utils_1 = require("../../utils"); var input_rules_1 = require("./input-rules"); var keymap_1 = require("./keymap"); var emoji_1 = require("./../../nodeviews/ui/emoji"); var factory_1 = require("../../nodeviews/factory"); var plugin_key_1 = require("./plugin-key"); exports.stateKey = plugin_key_1.default; var EmojiState = (function () { function EmojiState(state, providerFactory) { var _this = this; this.enabled = true; this.queryActive = false; this.onSelectPrevious = function () { return false; }; this.onSelectNext = function () { return false; }; this.onSelectCurrent = function () { return false; }; this.changeHandlers = []; this.queryResult = []; this.handleProvider = function (name, provider) { switch (name) { case 'emojiProvider': provider.then(function (emojiProvider) { _this.emojiProvider = emojiProvider; if (_this.emojiProvider) { _this.emojiProvider.subscribe(_this.onProviderChange); } }).catch(function () { if (_this.emojiProvider) { _this.emojiProvider.unsubscribe(_this.onProviderChange); } _this.emojiProvider = undefined; }); break; } }; this.trySelectCurrent = function () { var emojisCount = _this.getEmojisCount(); if (emojisCount === 1) { _this.insertEmoji(_this.queryResult[0]); return true; } else if (emojisCount === 0 || _this.isEmptyQuery()) { _this.dismiss(); } return false; }; this.getEmojisCount = function () { return (_this.queryResult && _this.queryResult.length) || 0; }; this.isEmptyQuery = function () { return !_this.query || _this.query === ':'; }; this.onSearchResult = function (searchResults) { _this.queryResult = searchResults.emojis; }; this.onProviderChange = { result: this.onSearchResult, }; this.changeHandlers = []; this.state = state; providerFactory.subscribe('emojiProvider', this.handleProvider); } EmojiState.prototype.subscribe = function (cb) { this.changeHandlers.push(cb); cb(this); }; EmojiState.prototype.unsubscribe = function (cb) { this.changeHandlers = this.changeHandlers.filter(function (ch) { return ch !== cb; }); }; EmojiState.prototype.update = function (state) { var _this = this; this.state = state; if (!this.emojiProvider) { return; } var emojiQuery = state.schema.marks.emojiQuery; var doc = state.doc, selection = state.selection; var from = selection.from, to = selection.to; var dirty = false; var newEnabled = this.isEnabled(); if (newEnabled !== this.enabled) { this.enabled = newEnabled; dirty = true; } if (doc.rangeHasMark(from - 1, to, emojiQuery)) { if (!this.queryActive) { dirty = true; this.queryActive = true; } var nodeBefore = selection.$from.nodeBefore; var newQuery = (nodeBefore && nodeBefore.textContent || ''); if (this.query !== newQuery) { dirty = true; this.query = newQuery; } } else if (this.queryActive) { dirty = true; this.dismiss(); return; } var newAnchorElement = this.view.dom.querySelector('[data-emoji-query]'); if (newAnchorElement !== this.anchorElement) { dirty = true; this.anchorElement = newAnchorElement; } if (dirty) { this.changeHandlers.forEach(function (cb) { return cb(_this); }); } }; EmojiState.prototype.dismiss = function () { this.queryActive = false; this.query = undefined; var _a = this, state = _a.state, view = _a.view; if (state) { var schema = state.schema; var tr = state.tr; var markType = schema.mark('emojiQuery'); view.dispatch(tr .removeMark(0, state.doc.nodeSize - 2, markType) .removeStoredMark(markType)); } return true; }; EmojiState.prototype.isEnabled = function () { var schema = this.state.schema; var emojiQuery = schema.marks.emojiQuery; return utils_1.isMarkTypeAllowedAtCurrentPosition(emojiQuery, this.state); }; EmojiState.prototype.findEmojiQueryMark = function () { var state = this.state; var doc = state.doc, schema = state.schema, selection = state.selection; var to = selection.to, from = selection.from; var emojiQuery = schema.marks.emojiQuery; var start = from; var node = doc.nodeAt(start); while (start > 0 && (!node || !emojiQuery.isInSet(node.marks))) { start--; node = doc.nodeAt(start); } var end = start; if (node && emojiQuery.isInSet(node.marks)) { var resolvedPos = doc.resolve(start); // -1 is to include : in replacement // resolvedPos.depth + 1 to make emoji work inside other blocks e.g. "list item" or "blockquote" start = resolvedPos.start(resolvedPos.depth + 1) - 1; end = start + node.nodeSize; } // Emoji inserted via picker if (start === 0 && end === 0) { start = from; end = to; } return { start: start, end: end }; }; EmojiState.prototype.insertEmoji = function (emojiId) { var _a = this, state = _a.state, view = _a.view; var emoji = state.schema.nodes.emoji; if (emoji && emojiId) { var _b = this.findEmojiQueryMark(), start = _b.start, end = _b.end; var node = emoji.create(tslib_1.__assign({}, emojiId, { text: emojiId.fallback || emojiId.shortName })); var textNode = state.schema.text(' '); view.dispatch(state.tr.replaceWith(start, end, [node, textNode])); view.focus(); this.queryActive = false; this.query = undefined; } else { this.dismiss(); } }; EmojiState.prototype.setView = function (view) { this.view = view; }; return EmojiState; }()); exports.EmojiState = EmojiState; function createPlugin(providerFactory) { return new prosemirror_1.Plugin({ state: { init: function (config, state) { return new EmojiState(state, providerFactory); }, apply: function (tr, pluginState, oldState, newState) { // NOTE: Don't call pluginState.update here. return pluginState; } }, props: { nodeViews: { emoji: factory_1.default(providerFactory, { emoji: emoji_1.default }) } }, key: plugin_key_1.default, view: function (view) { var pluginState = plugin_key_1.default.getState(view.state); pluginState.setView(view); return { update: function (view, prevState) { pluginState.update(view.state); }, destroy: function () { providerFactory.unsubscribe('emojiProvider', pluginState.handleProvider); } }; } }); } exports.createPlugin = createPlugin; var plugins = function (schema, providerFactory) { return [createPlugin(providerFactory), input_rules_1.inputRulePlugin(schema), keymap_1.default(schema)].filter(function (plugin) { return !!plugin; }); }; exports.default = plugins; //# sourceMappingURL=index.js.map