@atlaskit/editor-plugin-emoji 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cjs/commands/insert-emoji.js +47 -0
  3. package/dist/cjs/index.js +8 -1
  4. package/dist/cjs/messages.js +15 -0
  5. package/dist/cjs/nodeviews/emoji.js +34 -0
  6. package/dist/cjs/plugin.js +409 -0
  7. package/dist/cjs/pm-plugins/ascii-input-rules.js +235 -0
  8. package/dist/cjs/ui/Emoji/index.js +19 -0
  9. package/dist/es2019/commands/insert-emoji.js +40 -0
  10. package/dist/es2019/index.js +1 -1
  11. package/dist/es2019/messages.js +8 -0
  12. package/dist/es2019/nodeviews/emoji.js +29 -0
  13. package/dist/es2019/plugin.js +381 -0
  14. package/dist/es2019/pm-plugins/ascii-input-rules.js +168 -0
  15. package/dist/es2019/ui/Emoji/index.js +13 -0
  16. package/dist/esm/commands/insert-emoji.js +39 -0
  17. package/dist/esm/index.js +1 -1
  18. package/dist/esm/messages.js +8 -0
  19. package/dist/esm/nodeviews/emoji.js +27 -0
  20. package/dist/esm/plugin.js +391 -0
  21. package/dist/esm/pm-plugins/ascii-input-rules.js +224 -0
  22. package/dist/esm/ui/Emoji/index.js +12 -0
  23. package/dist/types/commands/insert-emoji.d.ts +4 -0
  24. package/dist/types/index.d.ts +1 -0
  25. package/dist/types/messages.d.ts +7 -0
  26. package/dist/types/nodeviews/emoji.d.ts +7 -0
  27. package/dist/types/plugin.d.ts +38 -0
  28. package/dist/types/pm-plugins/ascii-input-rules.d.ts +10 -0
  29. package/dist/types/ui/Emoji/index.d.ts +4 -0
  30. package/dist/types-ts4.5/commands/insert-emoji.d.ts +4 -0
  31. package/dist/types-ts4.5/index.d.ts +1 -0
  32. package/dist/types-ts4.5/messages.d.ts +7 -0
  33. package/dist/types-ts4.5/nodeviews/emoji.d.ts +7 -0
  34. package/dist/types-ts4.5/plugin.d.ts +38 -0
  35. package/dist/types-ts4.5/pm-plugins/ascii-input-rules.d.ts +10 -0
  36. package/dist/types-ts4.5/ui/Emoji/index.d.ts +4 -0
  37. package/package.json +29 -23
  38. package/report.api.md +3 -0
  39. package/tmp/api-report-tmp.d.ts +46 -0
@@ -0,0 +1,391 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
+ import React from 'react';
5
+ import { emoji } from '@atlaskit/adf-schema';
6
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
7
+ import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
8
+ import { IconEmoji } from '@atlaskit/editor-common/quick-insert';
9
+ import { getInlineNodeViewProducer } from '@atlaskit/editor-common/react-node-view';
10
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
11
+ import { TypeAheadAvailableNodes } from '@atlaskit/editor-common/type-ahead';
12
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
13
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
14
+ import { EmojiTypeAheadItem, recordSelectionFailedSli, recordSelectionSucceededSli, SearchSort } from '@atlaskit/emoji';
15
+ import { insertEmoji } from './commands/insert-emoji';
16
+ import { EmojiNodeView } from './nodeviews/emoji';
17
+ import { inputRulePlugin as asciiInputRulePlugin } from './pm-plugins/ascii-input-rules';
18
+ export var emojiToTypeaheadItem = function emojiToTypeaheadItem(emoji, emojiProvider) {
19
+ return {
20
+ title: emoji.shortName || '',
21
+ key: emoji.id || emoji.shortName,
22
+ render: function render(_ref) {
23
+ var isSelected = _ref.isSelected,
24
+ onClick = _ref.onClick,
25
+ onHover = _ref.onHover;
26
+ return /*#__PURE__*/React.createElement(EmojiTypeAheadItem, {
27
+ emoji: emoji,
28
+ selected: isSelected,
29
+ onMouseMove: onHover,
30
+ onSelection: onClick,
31
+ emojiProvider: emojiProvider
32
+ });
33
+ },
34
+ emoji: emoji
35
+ };
36
+ };
37
+ export function memoize(fn) {
38
+ // Cache results here
39
+ var seen = new Map();
40
+ function memoized(emoji, emojiProvider) {
41
+ // Check cache for hits
42
+ var hit = seen.get(emoji.id || emoji.shortName);
43
+ if (hit) {
44
+ return hit;
45
+ }
46
+
47
+ // Generate new result and cache it
48
+ var result = fn(emoji, emojiProvider);
49
+ seen.set(emoji.id || emoji.shortName, result);
50
+ return result;
51
+ }
52
+ return {
53
+ call: memoized,
54
+ clear: seen.clear.bind(seen)
55
+ };
56
+ }
57
+ var memoizedToItem = memoize(emojiToTypeaheadItem);
58
+ export var defaultListLimit = 50;
59
+ var isFullShortName = function isFullShortName(query) {
60
+ return query && query.length > 1 && query.charAt(0) === ':' && query.charAt(query.length - 1) === ':';
61
+ };
62
+ var TRIGGER = ':';
63
+ export var emojiPlugin = function emojiPlugin(_ref2) {
64
+ var _api$analytics5;
65
+ var options = _ref2.config,
66
+ api = _ref2.api;
67
+ var typeAhead = {
68
+ id: TypeAheadAvailableNodes.EMOJI,
69
+ trigger: TRIGGER,
70
+ // Custom regex must have a capture group around trigger
71
+ // so it's possible to use it without needing to scan through all triggers again
72
+ customRegex: '\\(?(:)',
73
+ headless: options ? options.headless : undefined,
74
+ getItems: function getItems(_ref3) {
75
+ var query = _ref3.query,
76
+ editorState = _ref3.editorState;
77
+ var pluginState = getEmojiPluginState(editorState);
78
+ var emojiProvider = pluginState.emojiProvider;
79
+ if (!emojiProvider) {
80
+ return Promise.resolve([]);
81
+ }
82
+ return new Promise(function (resolve) {
83
+ var emojiProviderChangeHandler = {
84
+ result: function result(emojiResult) {
85
+ if (!emojiResult || !emojiResult.emojis) {
86
+ resolve([]);
87
+ } else {
88
+ var emojiItems = emojiResult.emojis.map(function (emoji) {
89
+ return memoizedToItem.call(emoji, emojiProvider);
90
+ });
91
+ resolve(emojiItems);
92
+ }
93
+ emojiProvider.unsubscribe(emojiProviderChangeHandler);
94
+ }
95
+ };
96
+ emojiProvider.subscribe(emojiProviderChangeHandler);
97
+ emojiProvider.filter(TRIGGER.concat(query), {
98
+ limit: defaultListLimit,
99
+ skinTone: emojiProvider.getSelectedTone(),
100
+ sort: !query.length ? SearchSort.UsageFrequency : SearchSort.Default
101
+ });
102
+ });
103
+ },
104
+ forceSelect: function forceSelect(_ref4) {
105
+ var query = _ref4.query,
106
+ items = _ref4.items,
107
+ editorState = _ref4.editorState;
108
+ var _ref5 = emojiPluginKey.getState(editorState) || {},
109
+ asciiMap = _ref5.asciiMap;
110
+ var normalizedQuery = TRIGGER.concat(query);
111
+
112
+ // if the query has space at the end
113
+ // check the ascii map for emojis
114
+ if (asciiMap && normalizedQuery.length >= 3 && normalizedQuery.endsWith(' ') && asciiMap.has(normalizedQuery.trim())) {
115
+ var _emoji = asciiMap.get(normalizedQuery.trim());
116
+ return {
117
+ title: (_emoji === null || _emoji === void 0 ? void 0 : _emoji.name) || '',
118
+ emoji: _emoji
119
+ };
120
+ }
121
+ var matchedItem = isFullShortName(normalizedQuery) ? items.find(function (item) {
122
+ return item.title.toLowerCase() === normalizedQuery;
123
+ }) : undefined;
124
+ return matchedItem;
125
+ },
126
+ selectItem: function selectItem(state, item, insert, _ref6) {
127
+ var _api$analytics3;
128
+ var mode = _ref6.mode;
129
+ var _item$emoji = item.emoji,
130
+ _item$emoji$id = _item$emoji.id,
131
+ id = _item$emoji$id === void 0 ? '' : _item$emoji$id,
132
+ fallback = _item$emoji.fallback,
133
+ shortName = _item$emoji.shortName;
134
+ var text = fallback || shortName;
135
+ var emojiPluginState = emojiPluginKey.getState(state);
136
+ if (emojiPluginState.emojiProvider && emojiPluginState.emojiProvider.recordSelection && item.emoji) {
137
+ var _api$analytics$shared, _api$analytics, _api$analytics$shared2, _api$analytics$shared3, _api$analytics2, _api$analytics2$share;
138
+ emojiPluginState.emojiProvider.recordSelection(item.emoji).then(recordSelectionSucceededSli({
139
+ createAnalyticsEvent: (_api$analytics$shared = api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$shared2 = _api$analytics.sharedState.currentState()) === null || _api$analytics$shared2 === void 0 ? void 0 : _api$analytics$shared2.createAnalyticsEvent) !== null && _api$analytics$shared !== void 0 ? _api$analytics$shared : undefined
140
+ })).catch(recordSelectionFailedSli({
141
+ createAnalyticsEvent: (_api$analytics$shared3 = api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : (_api$analytics2$share = _api$analytics2.sharedState.currentState()) === null || _api$analytics2$share === void 0 ? void 0 : _api$analytics2$share.createAnalyticsEvent) !== null && _api$analytics$shared3 !== void 0 ? _api$analytics$shared3 : undefined
142
+ }));
143
+ }
144
+ var emojiNode = state.schema.nodes.emoji.createChecked({
145
+ shortName: shortName,
146
+ id: id,
147
+ text: text
148
+ });
149
+ var space = state.schema.text(' ');
150
+ var tr = insert(Fragment.from([emojiNode, space]));
151
+ api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.attachAnalyticsEvent({
152
+ action: ACTION.INSERTED,
153
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
154
+ actionSubjectId: ACTION_SUBJECT_ID.EMOJI,
155
+ attributes: {
156
+ inputMethod: INPUT_METHOD.TYPEAHEAD
157
+ },
158
+ eventType: EVENT_TYPE.TRACK
159
+ })(tr);
160
+ return tr;
161
+ }
162
+ };
163
+ return {
164
+ name: 'emoji',
165
+ nodes: function nodes() {
166
+ return [{
167
+ name: 'emoji',
168
+ node: emoji
169
+ }];
170
+ },
171
+ pmPlugins: function pmPlugins() {
172
+ return [{
173
+ name: 'emoji',
174
+ plugin: function plugin(pmPluginFactoryParams) {
175
+ return createEmojiPlugin(pmPluginFactoryParams);
176
+ }
177
+ }, {
178
+ name: 'emojiAsciiInputRule',
179
+ plugin: function plugin(_ref7) {
180
+ var _api$analytics4;
181
+ var schema = _ref7.schema,
182
+ providerFactory = _ref7.providerFactory,
183
+ featureFlags = _ref7.featureFlags;
184
+ return asciiInputRulePlugin(schema, providerFactory, featureFlags, api === null || api === void 0 ? void 0 : (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 ? void 0 : _api$analytics4.actions);
185
+ }
186
+ }];
187
+ },
188
+ getSharedState: function getSharedState(editorState) {
189
+ if (!editorState) {
190
+ return undefined;
191
+ }
192
+ return emojiPluginKey.getState(editorState);
193
+ },
194
+ commands: {
195
+ insertEmoji: insertEmoji(api === null || api === void 0 ? void 0 : (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 ? void 0 : _api$analytics5.actions)
196
+ },
197
+ pluginsOptions: {
198
+ quickInsert: function quickInsert(_ref8) {
199
+ var formatMessage = _ref8.formatMessage;
200
+ return [{
201
+ id: 'emoji',
202
+ title: formatMessage(messages.emoji),
203
+ description: formatMessage(messages.emojiDescription),
204
+ priority: 500,
205
+ keyshortcut: ':',
206
+ icon: function icon() {
207
+ return /*#__PURE__*/React.createElement(IconEmoji, null);
208
+ },
209
+ action: function action(insert, state) {
210
+ var _api$analytics6;
211
+ var tr = insert(undefined);
212
+ api === null || api === void 0 ? void 0 : api.typeAhead.commands.openTypeAheadAtCursor({
213
+ triggerHandler: typeAhead,
214
+ inputMethod: INPUT_METHOD.QUICK_INSERT
215
+ })({
216
+ tr: tr
217
+ });
218
+ api === null || api === void 0 ? void 0 : (_api$analytics6 = api.analytics) === null || _api$analytics6 === void 0 ? void 0 : _api$analytics6.actions.attachAnalyticsEvent({
219
+ action: ACTION.INVOKED,
220
+ actionSubject: ACTION_SUBJECT.TYPEAHEAD,
221
+ actionSubjectId: ACTION_SUBJECT_ID.TYPEAHEAD_EMOJI,
222
+ attributes: {
223
+ inputMethod: INPUT_METHOD.QUICK_INSERT
224
+ },
225
+ eventType: EVENT_TYPE.UI
226
+ })(tr);
227
+ return tr;
228
+ }
229
+ }];
230
+ },
231
+ typeAhead: typeAhead
232
+ }
233
+ };
234
+ };
235
+
236
+ /**
237
+ * Actions
238
+ */
239
+
240
+ export var ACTIONS = {
241
+ SET_PROVIDER: 'SET_PROVIDER',
242
+ SET_RESULTS: 'SET_RESULTS',
243
+ SET_ASCII_MAP: 'SET_ASCII_MAP'
244
+ };
245
+ var setAsciiMap = function setAsciiMap(asciiMap) {
246
+ return function (state, dispatch) {
247
+ if (dispatch) {
248
+ dispatch(state.tr.setMeta(emojiPluginKey, {
249
+ action: ACTIONS.SET_ASCII_MAP,
250
+ params: {
251
+ asciiMap: asciiMap
252
+ }
253
+ }));
254
+ }
255
+ return true;
256
+ };
257
+ };
258
+
259
+ /**
260
+ *
261
+ * Wrapper to call `onLimitReached` when a specified number of calls of that function
262
+ * have been made within a time period.
263
+ *
264
+ * Note: It does not rate limit
265
+ *
266
+ * @param fn Function to wrap
267
+ * @param limitTime Time limit in milliseconds
268
+ * @param limitCount Number of function calls before `onRateReached` is called (per time period)
269
+ * @returns Wrapped function
270
+ */
271
+ export function createRateLimitReachedFunction(fn, limitTime, limitCount, onLimitReached) {
272
+ var lastCallTime = 0;
273
+ var callCount = 0;
274
+ return function wrappedFn() {
275
+ var now = Date.now();
276
+ if (now - lastCallTime < limitTime) {
277
+ if (++callCount > limitCount) {
278
+ onLimitReached === null || onLimitReached === void 0 ? void 0 : onLimitReached();
279
+ }
280
+ } else {
281
+ lastCallTime = now;
282
+ callCount = 1;
283
+ }
284
+ return fn.apply(void 0, arguments);
285
+ };
286
+ }
287
+
288
+ // At this stage console.error only
289
+ var logRateWarning = function logRateWarning() {
290
+ if (process.env.NODE_ENV === 'development') {
291
+ // eslint-disable-next-line no-console
292
+ console.error('The emoji provider injected in the Editor is being reloaded frequently, this will cause a slow Editor experience.');
293
+ }
294
+ };
295
+ export var setProvider = createRateLimitReachedFunction(function (provider) {
296
+ return function (state, dispatch) {
297
+ if (dispatch) {
298
+ dispatch(state.tr.setMeta(emojiPluginKey, {
299
+ action: ACTIONS.SET_PROVIDER,
300
+ params: {
301
+ provider: provider
302
+ }
303
+ }));
304
+ }
305
+ return true;
306
+ };
307
+ },
308
+ // If we change the emoji provider more than three times every 5 seconds we should warn.
309
+ // This seems like a really long time but the performance can be that laggy that we don't
310
+ // even get 3 events in 3 seconds and miss this indicator.
311
+ 5000, 3, logRateWarning);
312
+ export var emojiPluginKey = new PluginKey('emojiPlugin');
313
+ export function getEmojiPluginState(state) {
314
+ return emojiPluginKey.getState(state) || {};
315
+ }
316
+ export function createEmojiPlugin(pmPluginFactoryParams) {
317
+ return new SafePlugin({
318
+ key: emojiPluginKey,
319
+ state: {
320
+ init: function init() {
321
+ return {};
322
+ },
323
+ apply: function apply(tr, pluginState) {
324
+ var _ref9 = tr.getMeta(emojiPluginKey) || {
325
+ action: null,
326
+ params: null
327
+ },
328
+ action = _ref9.action,
329
+ params = _ref9.params;
330
+ var newPluginState = pluginState;
331
+ switch (action) {
332
+ case ACTIONS.SET_PROVIDER:
333
+ newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
334
+ emojiProvider: params.provider
335
+ });
336
+ pmPluginFactoryParams.dispatch(emojiPluginKey, newPluginState);
337
+ return newPluginState;
338
+ case ACTIONS.SET_ASCII_MAP:
339
+ newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
340
+ asciiMap: params.asciiMap
341
+ });
342
+ pmPluginFactoryParams.dispatch(emojiPluginKey, newPluginState);
343
+ return newPluginState;
344
+ }
345
+ return newPluginState;
346
+ }
347
+ },
348
+ props: {
349
+ nodeViews: {
350
+ emoji: getInlineNodeViewProducer({
351
+ pmPluginFactoryParams: pmPluginFactoryParams,
352
+ Component: EmojiNodeView,
353
+ extraComponentProps: {
354
+ providerFactory: pmPluginFactoryParams.providerFactory
355
+ }
356
+ })
357
+ }
358
+ },
359
+ view: function view(editorView) {
360
+ var providerHandler = function providerHandler(name, providerPromise) {
361
+ switch (name) {
362
+ case 'emojiProvider':
363
+ if (!providerPromise) {
364
+ var _setProvider;
365
+ return setProvider === null || setProvider === void 0 ? void 0 : (_setProvider = setProvider(undefined)) === null || _setProvider === void 0 ? void 0 : _setProvider(editorView.state, editorView.dispatch);
366
+ }
367
+ providerPromise.then(function (provider) {
368
+ var _setProvider2;
369
+ setProvider === null || setProvider === void 0 ? void 0 : (_setProvider2 = setProvider(provider)) === null || _setProvider2 === void 0 ? void 0 : _setProvider2(editorView.state, editorView.dispatch);
370
+ provider.getAsciiMap().then(function (asciiMap) {
371
+ setAsciiMap(asciiMap)(editorView.state, editorView.dispatch);
372
+ });
373
+ }).catch(function () {
374
+ var _setProvider3;
375
+ return setProvider === null || setProvider === void 0 ? void 0 : (_setProvider3 = setProvider(undefined)) === null || _setProvider3 === void 0 ? void 0 : _setProvider3(editorView.state, editorView.dispatch);
376
+ });
377
+ break;
378
+ }
379
+ return;
380
+ };
381
+ pmPluginFactoryParams.providerFactory.subscribe('emojiProvider', providerHandler);
382
+ return {
383
+ destroy: function destroy() {
384
+ if (pmPluginFactoryParams.providerFactory) {
385
+ pmPluginFactoryParams.providerFactory.unsubscribe('emojiProvider', providerHandler);
386
+ }
387
+ }
388
+ };
389
+ }
390
+ });
391
+ }
@@ -0,0 +1,224 @@
1
+ import _get from "@babel/runtime/helpers/get";
2
+ import _inherits from "@babel/runtime/helpers/inherits";
3
+ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
4
+ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
5
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
6
+ import _createClass from "@babel/runtime/helpers/createClass";
7
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
8
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
9
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
10
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
11
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
12
+ import { createPlugin, createRule, leafNodeReplacementCharacter } from '@atlaskit/prosemirror-input-rules';
13
+ var matcher;
14
+ export function inputRulePlugin(schema, providerFactory, featureFlags, editorAnalyticsAPI) {
15
+ if (schema.nodes.emoji && providerFactory) {
16
+ initMatcher(providerFactory);
17
+ var asciiEmojiRule = createRule(AsciiEmojiMatcher.REGEX, inputRuleHandler(editorAnalyticsAPI));
18
+ return createPlugin('emoji', [asciiEmojiRule]);
19
+ }
20
+ return;
21
+ }
22
+ function initMatcher(providerFactory) {
23
+ var handleProvider = function handleProvider(_name, provider) {
24
+ if (!provider) {
25
+ return;
26
+ }
27
+ provider.then(function (emojiProvider) {
28
+ emojiProvider.getAsciiMap().then(function (map) {
29
+ matcher = new RecordingAsciiEmojiMatcher(emojiProvider, map);
30
+ });
31
+ });
32
+ };
33
+ providerFactory.subscribe('emojiProvider', handleProvider);
34
+ }
35
+ var inputRuleHandler = function inputRuleHandler(editorAnalyticsAPI) {
36
+ return function (state, matchParts, start, end) {
37
+ if (!matcher) {
38
+ return null;
39
+ }
40
+ var match = matcher.match(matchParts);
41
+ if (match) {
42
+ var transactionCreator = new AsciiEmojiTransactionCreator(state, match, start, end, editorAnalyticsAPI);
43
+ return transactionCreator.create();
44
+ }
45
+ return null;
46
+ };
47
+ };
48
+ var REGEX_LEADING_CAPTURE_INDEX = 1;
49
+ var REGEX_EMOJI_LEADING_PARENTHESES = 2;
50
+ var REGEX_EMOJI_ASCII_CAPTURE_INDEX = 3;
51
+ var REGEX_TRAILING_CAPTURE_INDEX = 4;
52
+ var getLeadingString = function getLeadingString(match) {
53
+ var withParenthesis = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
54
+ return match[REGEX_LEADING_CAPTURE_INDEX] + (withParenthesis ? match[REGEX_EMOJI_LEADING_PARENTHESES] : '');
55
+ };
56
+ var getLeadingStringWithoutParentheses = function getLeadingStringWithoutParentheses(match) {
57
+ return getLeadingString(match, false);
58
+ };
59
+ var getAscii = function getAscii(match) {
60
+ var withParentheses = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
61
+ return (withParentheses ? match[REGEX_EMOJI_LEADING_PARENTHESES] : '') + match[REGEX_EMOJI_ASCII_CAPTURE_INDEX].trim();
62
+ };
63
+ var getAsciiWithParentheses = function getAsciiWithParentheses(matchParts) {
64
+ return getAscii(matchParts, true);
65
+ };
66
+ var getTrailingString = function getTrailingString(match) {
67
+ return match[REGEX_TRAILING_CAPTURE_INDEX] || '';
68
+ };
69
+ var AsciiEmojiMatcher = /*#__PURE__*/function () {
70
+ function AsciiEmojiMatcher(asciiToEmojiMap) {
71
+ _classCallCheck(this, AsciiEmojiMatcher);
72
+ this.asciiToEmojiMap = asciiToEmojiMap;
73
+ }
74
+ _createClass(AsciiEmojiMatcher, [{
75
+ key: "match",
76
+ value: function match(matchParts) {
77
+ return this.getAsciiEmojiMatch(getLeadingStringWithoutParentheses(matchParts), getAsciiWithParentheses(matchParts), getTrailingString(matchParts)) || this.getAsciiEmojiMatch(getLeadingString(matchParts), getAscii(matchParts), getTrailingString(matchParts));
78
+ }
79
+ }, {
80
+ key: "getAsciiEmojiMatch",
81
+ value: function getAsciiEmojiMatch(leading, ascii, trailing) {
82
+ var emoji = this.asciiToEmojiMap.get(ascii);
83
+ return emoji ? {
84
+ emoji: emoji,
85
+ leadingString: leading,
86
+ trailingString: trailing
87
+ } : undefined;
88
+ }
89
+ }]);
90
+ return AsciiEmojiMatcher;
91
+ }();
92
+ /**
93
+ * A matcher that will record ascii matches as usages of the matched emoji.
94
+ */
95
+ /**
96
+ * This regex matches 2 scenarios:
97
+ * 1. an emoticon starting with a colon character (e.g. :D => 😃)
98
+ * 2. an emoticon not starting with a colon character (e.g. 8-D => 😎)
99
+ *
100
+ * Explanation (${leafNodeReplacementCharacter} is replaced with character \ufffc)
101
+ *
102
+ * 1st Capturing Group ((?:^|[\s\ufffc])(?:\(*?))
103
+ * Non-capturing group (?:^|[\s\ufffc])
104
+ * 1st Alternative ^
105
+ * ^ asserts position at start of the string
106
+ * 2nd Alternative [\s\ufffc]
107
+ * matches a single character present in [\s\ufffc]
108
+ * Non-capturing group (?:\(*?)
109
+ * matches the character ( literally between zero and unlimited times, as few times as possible, expanding as needed (lazy)
110
+ * 2nd Capturing Group (\(?)
111
+ * matches a single ( if present
112
+ * 3rd Capturing Group ([^:\s\ufffc\(]\S{1,3}|:\S{1,3}( ))
113
+ * 1st Alternative [^:\s\ufffc\(]\S{1,3}
114
+ * matches a single character not present in [^:\s\ufffc\(] between 1 and 3 times, as many times as possible, giving back as needed (greedy)
115
+ * 2nd Alternative :\S{1,3}( )
116
+ * : matches the character : literally
117
+ * \S{1,3} matches any non-whitespace character between 1 and 3 times, as many times as possible, giving back as needed (greedy)
118
+ * 4th Capturing Group ( )
119
+ *
120
+ * See https://regex101.com/r/HRS9O2/4
121
+ */
122
+ _defineProperty(AsciiEmojiMatcher, "REGEX", new RegExp("((?:^|[\\s".concat(leafNodeReplacementCharacter, "])(?:\\(*?))(\\(?)([^:\\s").concat(leafNodeReplacementCharacter, "\\(]\\S{1,3}|:\\S{1,3}( ))$")));
123
+ var RecordingAsciiEmojiMatcher = /*#__PURE__*/function (_AsciiEmojiMatcher) {
124
+ _inherits(RecordingAsciiEmojiMatcher, _AsciiEmojiMatcher);
125
+ var _super = _createSuper(RecordingAsciiEmojiMatcher);
126
+ function RecordingAsciiEmojiMatcher(emojiProvider, asciiToEmojiMap) {
127
+ var _this;
128
+ _classCallCheck(this, RecordingAsciiEmojiMatcher);
129
+ _this = _super.call(this, asciiToEmojiMap);
130
+ _this.emojiProvider = emojiProvider;
131
+ return _this;
132
+ }
133
+ _createClass(RecordingAsciiEmojiMatcher, [{
134
+ key: "match",
135
+ value: function match(matchParts) {
136
+ var match = _get(_getPrototypeOf(RecordingAsciiEmojiMatcher.prototype), "match", this).call(this, matchParts);
137
+ if (match && this.emojiProvider.recordSelection) {
138
+ this.emojiProvider.recordSelection(match.emoji);
139
+ }
140
+ return match;
141
+ }
142
+ }]);
143
+ return RecordingAsciiEmojiMatcher;
144
+ }(AsciiEmojiMatcher);
145
+ var AsciiEmojiTransactionCreator = /*#__PURE__*/function () {
146
+ function AsciiEmojiTransactionCreator(state, match, start, end, editorAnalyticsAPI) {
147
+ _classCallCheck(this, AsciiEmojiTransactionCreator);
148
+ this.state = state;
149
+ this.match = match;
150
+ this.start = start;
151
+ this.end = end;
152
+ this.editorAnalyticsAPI = editorAnalyticsAPI;
153
+ }
154
+ _createClass(AsciiEmojiTransactionCreator, [{
155
+ key: "create",
156
+ value: function create() {
157
+ var _this$editorAnalytics;
158
+ var tr = this.state.tr.replaceWith(this.from, this.to, this.createNodes());
159
+ (_this$editorAnalytics = this.editorAnalyticsAPI) === null || _this$editorAnalytics === void 0 ? void 0 : _this$editorAnalytics.attachAnalyticsEvent({
160
+ action: ACTION.INSERTED,
161
+ actionSubject: ACTION_SUBJECT.DOCUMENT,
162
+ actionSubjectId: ACTION_SUBJECT_ID.EMOJI,
163
+ attributes: {
164
+ inputMethod: INPUT_METHOD.ASCII
165
+ },
166
+ eventType: EVENT_TYPE.TRACK
167
+ })(tr);
168
+ return tr;
169
+ }
170
+ }, {
171
+ key: "from",
172
+ get: function get() {
173
+ return this.start + this.match.leadingString.length;
174
+ }
175
+ }, {
176
+ key: "to",
177
+ get: function get() {
178
+ return this.end;
179
+ }
180
+ }, {
181
+ key: "createNodes",
182
+ value: function createNodes() {
183
+ var nodes = [this.createEmojiNode()];
184
+ if (this.trailingTextNodeRequired()) {
185
+ nodes.push(this.createTrailingTextNode());
186
+ }
187
+ return nodes;
188
+ }
189
+ }, {
190
+ key: "createEmojiNode",
191
+ value: function createEmojiNode() {
192
+ var emojiTypeNode = this.state.schema.nodes.emoji;
193
+ return emojiTypeNode.create(this.getEmojiNodeAttrs());
194
+ }
195
+ }, {
196
+ key: "getEmojiNodeAttrs",
197
+ value: function getEmojiNodeAttrs() {
198
+ var emoji = this.match.emoji;
199
+ return {
200
+ id: emoji.id,
201
+ shortName: emoji.shortName,
202
+ text: emoji.fallback || emoji.shortName
203
+ };
204
+ }
205
+ }, {
206
+ key: "trailingTextNodeRequired",
207
+ value: function trailingTextNodeRequired() {
208
+ return this.match.trailingString.length > 0;
209
+ }
210
+ }, {
211
+ key: "createTrailingTextNode",
212
+ value: function createTrailingTextNode() {
213
+ return this.state.schema.text(this.match.trailingString);
214
+ }
215
+ }]);
216
+ return AsciiEmojiTransactionCreator;
217
+ }();
218
+ export var stateKey = new PluginKey('asciiEmojiPlugin');
219
+ var plugins = function plugins(schema, providerFactory, featureFlags, editorAnalyticsAPI) {
220
+ return [inputRulePlugin(schema, providerFactory, featureFlags, editorAnalyticsAPI)].filter(function (plugin) {
221
+ return !!plugin;
222
+ });
223
+ };
224
+ export default plugins;
@@ -0,0 +1,12 @@
1
+ import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
+ var _templateObject;
3
+ /** @jsx jsx */
4
+ import { css, jsx } from '@emotion/react';
5
+ import { Emoji } from '@atlaskit/editor-common/emoji';
6
+ // eslint-disable-next-line
7
+ var clickSelectWrapperStyle = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage\n user-select: all;\n"])));
8
+ export default function EmojiNode(props) {
9
+ return jsx("span", {
10
+ css: clickSelectWrapperStyle
11
+ }, jsx(Emoji, props));
12
+ }
@@ -0,0 +1,4 @@
1
+ import type { EditorAnalyticsAPI, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
+ import type { EditorCommand } from '@atlaskit/editor-common/types';
3
+ import type { EmojiId } from '@atlaskit/emoji';
4
+ export declare const insertEmoji: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (emojiId: EmojiId, inputMethod?: INPUT_METHOD.PICKER | INPUT_METHOD.ASCII | INPUT_METHOD.TYPEAHEAD) => EditorCommand;
@@ -1 +1,2 @@
1
1
  export type { EmojiPlugin, EmojiPluginOptions, EmojiPluginState, } from './types';
2
+ export { emojiPlugin } from './plugin';
@@ -0,0 +1,7 @@
1
+ export declare const messages: {
2
+ emojiNodeLabel: {
3
+ id: string;
4
+ defaultMessage: string;
5
+ description: string;
6
+ };
7
+ };
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import type { ProviderFactory } from '@atlaskit/editor-common/provider-factory';
3
+ import type { InlineNodeViewComponentProps } from '@atlaskit/editor-common/react-node-view';
4
+ export type Props = InlineNodeViewComponentProps & {
5
+ providerFactory: ProviderFactory;
6
+ };
7
+ export declare function EmojiNodeView(props: Props): JSX.Element;