@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
217 lines • 8.33 kB
JavaScript
"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