@atlaskit/editor-plugin-type-ahead 0.5.0 → 0.7.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 (167) hide show
  1. package/.eslintrc.js +11 -0
  2. package/CHANGELOG.md +12 -0
  3. package/dist/cjs/api.js +215 -0
  4. package/dist/cjs/commands/insert-type-ahead-item.js +205 -0
  5. package/dist/cjs/commands/update-list-items.js +23 -0
  6. package/dist/cjs/commands/update-query.js +27 -0
  7. package/dist/cjs/commands/update-selected-index.js +27 -0
  8. package/dist/cjs/constants.js +15 -0
  9. package/dist/cjs/index.js +8 -1
  10. package/dist/cjs/insert-utils.js +107 -0
  11. package/dist/cjs/messages.js +79 -0
  12. package/dist/cjs/plugin.js +382 -0
  13. package/dist/cjs/pm-plugins/actions.js +16 -0
  14. package/dist/cjs/pm-plugins/decorations.js +148 -0
  15. package/dist/cjs/pm-plugins/input-rules.js +36 -0
  16. package/dist/cjs/pm-plugins/insert-item-plugin.js +22 -0
  17. package/dist/cjs/pm-plugins/key.js +8 -0
  18. package/dist/cjs/pm-plugins/main.js +110 -0
  19. package/dist/cjs/pm-plugins/reducer.js +158 -0
  20. package/dist/cjs/pm-plugins/utils.js +18 -0
  21. package/dist/cjs/stats-modifier.js +42 -0
  22. package/dist/cjs/transforms/close-type-ahead.js +13 -0
  23. package/dist/cjs/transforms/open-typeahead-at-cursor.js +75 -0
  24. package/dist/cjs/transforms/set-selection-before-query.js +18 -0
  25. package/dist/cjs/ui/AssistiveText.js +120 -0
  26. package/dist/cjs/ui/InputQuery.js +400 -0
  27. package/dist/cjs/ui/TypeAheadList.js +285 -0
  28. package/dist/cjs/ui/TypeAheadListItem.js +181 -0
  29. package/dist/cjs/ui/TypeAheadPopup.js +230 -0
  30. package/dist/cjs/ui/WrapperTypeAhead.js +127 -0
  31. package/dist/cjs/ui/hooks/use-item-insert.js +109 -0
  32. package/dist/cjs/ui/hooks/use-load-items.js +50 -0
  33. package/dist/cjs/ui/hooks/use-on-force-select.js +41 -0
  34. package/dist/cjs/utils.js +130 -0
  35. package/dist/es2019/api.js +205 -0
  36. package/dist/es2019/commands/insert-type-ahead-item.js +204 -0
  37. package/dist/es2019/commands/update-list-items.js +17 -0
  38. package/dist/es2019/commands/update-query.js +21 -0
  39. package/dist/es2019/commands/update-selected-index.js +21 -0
  40. package/dist/es2019/constants.js +9 -0
  41. package/dist/es2019/index.js +1 -1
  42. package/dist/es2019/insert-utils.js +106 -0
  43. package/dist/es2019/messages.js +73 -0
  44. package/dist/es2019/plugin.js +381 -0
  45. package/dist/es2019/pm-plugins/actions.js +10 -0
  46. package/dist/es2019/pm-plugins/decorations.js +148 -0
  47. package/dist/es2019/pm-plugins/input-rules.js +29 -0
  48. package/dist/es2019/pm-plugins/insert-item-plugin.js +16 -0
  49. package/dist/es2019/pm-plugins/key.js +2 -0
  50. package/dist/es2019/pm-plugins/main.js +106 -0
  51. package/dist/es2019/pm-plugins/reducer.js +160 -0
  52. package/dist/es2019/pm-plugins/utils.js +12 -0
  53. package/dist/es2019/stats-modifier.js +33 -0
  54. package/dist/es2019/transforms/close-type-ahead.js +7 -0
  55. package/dist/es2019/transforms/open-typeahead-at-cursor.js +71 -0
  56. package/dist/es2019/transforms/set-selection-before-query.js +10 -0
  57. package/dist/es2019/ui/AssistiveText.js +88 -0
  58. package/dist/es2019/ui/InputQuery.js +393 -0
  59. package/dist/es2019/ui/TypeAheadList.js +273 -0
  60. package/dist/es2019/ui/TypeAheadListItem.js +216 -0
  61. package/dist/es2019/ui/TypeAheadPopup.js +233 -0
  62. package/dist/es2019/ui/WrapperTypeAhead.js +109 -0
  63. package/dist/es2019/ui/hooks/use-item-insert.js +112 -0
  64. package/dist/es2019/ui/hooks/use-load-items.js +41 -0
  65. package/dist/es2019/ui/hooks/use-on-force-select.js +38 -0
  66. package/dist/es2019/utils.js +126 -0
  67. package/dist/esm/api.js +209 -0
  68. package/dist/esm/commands/insert-type-ahead-item.js +198 -0
  69. package/dist/esm/commands/update-list-items.js +17 -0
  70. package/dist/esm/commands/update-query.js +21 -0
  71. package/dist/esm/commands/update-selected-index.js +21 -0
  72. package/dist/esm/constants.js +9 -0
  73. package/dist/esm/index.js +1 -1
  74. package/dist/esm/insert-utils.js +101 -0
  75. package/dist/esm/messages.js +73 -0
  76. package/dist/esm/plugin.js +374 -0
  77. package/dist/esm/pm-plugins/actions.js +10 -0
  78. package/dist/esm/pm-plugins/decorations.js +141 -0
  79. package/dist/esm/pm-plugins/input-rules.js +29 -0
  80. package/dist/esm/pm-plugins/insert-item-plugin.js +16 -0
  81. package/dist/esm/pm-plugins/key.js +2 -0
  82. package/dist/esm/pm-plugins/main.js +104 -0
  83. package/dist/esm/pm-plugins/reducer.js +151 -0
  84. package/dist/esm/pm-plugins/utils.js +12 -0
  85. package/dist/esm/stats-modifier.js +35 -0
  86. package/dist/esm/transforms/close-type-ahead.js +7 -0
  87. package/dist/esm/transforms/open-typeahead-at-cursor.js +69 -0
  88. package/dist/esm/transforms/set-selection-before-query.js +12 -0
  89. package/dist/esm/ui/AssistiveText.js +115 -0
  90. package/dist/esm/ui/InputQuery.js +390 -0
  91. package/dist/esm/ui/TypeAheadList.js +276 -0
  92. package/dist/esm/ui/TypeAheadListItem.js +171 -0
  93. package/dist/esm/ui/TypeAheadPopup.js +220 -0
  94. package/dist/esm/ui/WrapperTypeAhead.js +117 -0
  95. package/dist/esm/ui/hooks/use-item-insert.js +103 -0
  96. package/dist/esm/ui/hooks/use-load-items.js +43 -0
  97. package/dist/esm/ui/hooks/use-on-force-select.js +35 -0
  98. package/dist/esm/utils.js +124 -0
  99. package/dist/types/api.d.ts +61 -0
  100. package/dist/types/commands/insert-type-ahead-item.d.ts +12 -0
  101. package/dist/types/commands/update-list-items.d.ts +3 -0
  102. package/dist/types/commands/update-query.d.ts +2 -0
  103. package/dist/types/commands/update-selected-index.d.ts +2 -0
  104. package/dist/types/constants.d.ts +8 -0
  105. package/dist/types/index.d.ts +2 -1
  106. package/dist/types/insert-utils.d.ts +18 -0
  107. package/dist/types/messages.d.ts +72 -0
  108. package/dist/types/plugin.d.ts +10 -0
  109. package/dist/types/pm-plugins/actions.d.ts +9 -0
  110. package/dist/types/pm-plugins/decorations.d.ts +14 -0
  111. package/dist/types/pm-plugins/input-rules.d.ts +6 -0
  112. package/dist/types/pm-plugins/insert-item-plugin.d.ts +2 -0
  113. package/dist/types/pm-plugins/key.d.ts +3 -0
  114. package/dist/types/pm-plugins/main.d.ts +14 -0
  115. package/dist/types/pm-plugins/reducer.d.ts +10 -0
  116. package/dist/types/pm-plugins/utils.d.ts +4 -0
  117. package/dist/types/stats-modifier.d.ts +20 -0
  118. package/dist/types/transforms/close-type-ahead.d.ts +2 -0
  119. package/dist/types/transforms/open-typeahead-at-cursor.d.ts +11 -0
  120. package/dist/types/transforms/set-selection-before-query.d.ts +2 -0
  121. package/dist/types/types.d.ts +64 -3
  122. package/dist/types/ui/AssistiveText.d.ts +33 -0
  123. package/dist/types/ui/InputQuery.d.ts +26 -0
  124. package/dist/types/ui/TypeAheadList.d.ts +25 -0
  125. package/dist/types/ui/TypeAheadListItem.d.ts +18 -0
  126. package/dist/types/ui/TypeAheadPopup.d.ts +29 -0
  127. package/dist/types/ui/WrapperTypeAhead.d.ts +20 -0
  128. package/dist/types/ui/hooks/use-item-insert.d.ts +3 -0
  129. package/dist/types/ui/hooks/use-load-items.d.ts +3 -0
  130. package/dist/types/ui/hooks/use-on-force-select.d.ts +11 -0
  131. package/dist/types/utils.d.ts +27 -0
  132. package/dist/types-ts4.5/api.d.ts +61 -0
  133. package/dist/types-ts4.5/commands/insert-type-ahead-item.d.ts +12 -0
  134. package/dist/types-ts4.5/commands/update-list-items.d.ts +3 -0
  135. package/dist/types-ts4.5/commands/update-query.d.ts +2 -0
  136. package/dist/types-ts4.5/commands/update-selected-index.d.ts +2 -0
  137. package/dist/types-ts4.5/constants.d.ts +8 -0
  138. package/dist/types-ts4.5/index.d.ts +2 -1
  139. package/dist/types-ts4.5/insert-utils.d.ts +18 -0
  140. package/dist/types-ts4.5/messages.d.ts +72 -0
  141. package/dist/types-ts4.5/plugin.d.ts +10 -0
  142. package/dist/types-ts4.5/pm-plugins/actions.d.ts +9 -0
  143. package/dist/types-ts4.5/pm-plugins/decorations.d.ts +14 -0
  144. package/dist/types-ts4.5/pm-plugins/input-rules.d.ts +6 -0
  145. package/dist/types-ts4.5/pm-plugins/insert-item-plugin.d.ts +2 -0
  146. package/dist/types-ts4.5/pm-plugins/key.d.ts +3 -0
  147. package/dist/types-ts4.5/pm-plugins/main.d.ts +14 -0
  148. package/dist/types-ts4.5/pm-plugins/reducer.d.ts +10 -0
  149. package/dist/types-ts4.5/pm-plugins/utils.d.ts +4 -0
  150. package/dist/types-ts4.5/stats-modifier.d.ts +20 -0
  151. package/dist/types-ts4.5/transforms/close-type-ahead.d.ts +2 -0
  152. package/dist/types-ts4.5/transforms/open-typeahead-at-cursor.d.ts +11 -0
  153. package/dist/types-ts4.5/transforms/set-selection-before-query.d.ts +2 -0
  154. package/dist/types-ts4.5/types.d.ts +64 -3
  155. package/dist/types-ts4.5/ui/AssistiveText.d.ts +33 -0
  156. package/dist/types-ts4.5/ui/InputQuery.d.ts +26 -0
  157. package/dist/types-ts4.5/ui/TypeAheadList.d.ts +25 -0
  158. package/dist/types-ts4.5/ui/TypeAheadListItem.d.ts +18 -0
  159. package/dist/types-ts4.5/ui/TypeAheadPopup.d.ts +29 -0
  160. package/dist/types-ts4.5/ui/WrapperTypeAhead.d.ts +20 -0
  161. package/dist/types-ts4.5/ui/hooks/use-item-insert.d.ts +7 -0
  162. package/dist/types-ts4.5/ui/hooks/use-load-items.d.ts +3 -0
  163. package/dist/types-ts4.5/ui/hooks/use-on-force-select.d.ts +11 -0
  164. package/dist/types-ts4.5/utils.d.ts +27 -0
  165. package/package.json +21 -28
  166. package/report.api.md +32 -1
  167. package/tmp/api-report-tmp.d.ts +29 -0
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useLoadItems = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _react = require("react");
10
+ var _updateListItems = require("../../commands/update-list-items");
11
+ var EMPTY_LIST_ITEM = [];
12
+ var useLoadItems = exports.useLoadItems = function useLoadItems(triggerHandler, editorView, query) {
13
+ var _useState = (0, _react.useState)(EMPTY_LIST_ITEM),
14
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
15
+ items = _useState2[0],
16
+ setItems = _useState2[1];
17
+ var componentIsMounted = (0, _react.useRef)(true);
18
+ var editorViewRef = (0, _react.useRef)(editorView);
19
+ (0, _react.useEffect)(function () {
20
+ var getItems = triggerHandler === null || triggerHandler === void 0 ? void 0 : triggerHandler.getItems;
21
+ if (!getItems) {
22
+ setItems(EMPTY_LIST_ITEM);
23
+ return;
24
+ }
25
+ var options = {
26
+ query: query || '',
27
+ editorState: editorView.state
28
+ };
29
+ var view = editorViewRef.current;
30
+ getItems(options).then(function (result) {
31
+ var list = result.length > 0 ? result : EMPTY_LIST_ITEM;
32
+ if (componentIsMounted.current) {
33
+ setItems(list);
34
+ }
35
+ queueMicrotask(function () {
36
+ (0, _updateListItems.updateListItem)(list)(view.state, view.dispatch);
37
+ });
38
+ });
39
+
40
+ // ignore because EditorView is mutable but we don't want to
41
+ // call loadItems when it changes, only when the query changes
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, [triggerHandler, query]);
44
+ (0, _react.useEffect)(function () {
45
+ return function () {
46
+ componentIsMounted.current = false;
47
+ };
48
+ }, []);
49
+ return items;
50
+ };
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useOnForceSelect = void 0;
7
+ var _react = require("react");
8
+ var _typeAhead = require("@atlaskit/editor-common/type-ahead");
9
+ var _insertTypeAheadItem = require("../../commands/insert-type-ahead-item");
10
+ var useOnForceSelect = exports.useOnForceSelect = function useOnForceSelect(_ref) {
11
+ var triggerHandler = _ref.triggerHandler,
12
+ items = _ref.items,
13
+ query = _ref.query,
14
+ editorView = _ref.editorView,
15
+ closePopup = _ref.closePopup;
16
+ var editorViewRef = (0, _react.useRef)(editorView);
17
+ (0, _react.useLayoutEffect)(function () {
18
+ if (!query || typeof triggerHandler.forceSelect !== 'function') {
19
+ return;
20
+ }
21
+ var item = triggerHandler.forceSelect({
22
+ items: items,
23
+ query: query,
24
+ editorState: editorViewRef.current.state
25
+ });
26
+ if (!item) {
27
+ return;
28
+ }
29
+ var view = editorViewRef.current;
30
+ closePopup();
31
+ queueMicrotask(function () {
32
+ (0, _insertTypeAheadItem.insertTypeAheadItem)(view)({
33
+ item: item,
34
+ mode: _typeAhead.SelectItemMode.SPACE,
35
+ query: query,
36
+ handler: triggerHandler,
37
+ sourceListItem: items
38
+ });
39
+ });
40
+ }, [triggerHandler, closePopup, query, items]);
41
+ };
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.moveSelectedIndex = exports.isTypeAheadOpen = exports.isTypeAheadHandler = exports.isTypeAheadAllowed = exports.getTypeAheadQuery = exports.getTypeAheadListAriaLabels = exports.getTypeAheadHandler = exports.getPluginState = exports.findHandlerByTrigger = exports.findHandler = void 0;
7
+ var _typeAhead = require("@atlaskit/editor-common/type-ahead");
8
+ var _updateSelectedIndex = require("./commands/update-selected-index");
9
+ var _messages = require("./messages");
10
+ var _key = require("./pm-plugins/key");
11
+ var _statsModifier = require("./stats-modifier");
12
+ var isTypeAheadHandler = exports.isTypeAheadHandler = function isTypeAheadHandler(handler) {
13
+ return handler && Object.values(_typeAhead.TypeAheadAvailableNodes).includes(handler.id) && typeof handler.trigger === 'string' && typeof handler.selectItem === 'function' && typeof handler.getItems === 'function';
14
+ };
15
+
16
+ /** Is a typeahead plugin open? */
17
+ var isTypeAheadOpen = exports.isTypeAheadOpen = function isTypeAheadOpen(editorState) {
18
+ var _typeAheadPluginKey$g;
19
+ return !!(_key.pluginKey !== null && _key.pluginKey !== void 0 && (_typeAheadPluginKey$g = _key.pluginKey.getState(editorState)) !== null && _typeAheadPluginKey$g !== void 0 && (_typeAheadPluginKey$g = _typeAheadPluginKey$g.decorationSet) !== null && _typeAheadPluginKey$g !== void 0 && _typeAheadPluginKey$g.find().length);
20
+ };
21
+ var getPluginState = exports.getPluginState = function getPluginState(editorState) {
22
+ return _key.pluginKey.getState(editorState);
23
+ };
24
+ var getTypeAheadHandler = exports.getTypeAheadHandler = function getTypeAheadHandler(editorState) {
25
+ var _typeAheadPluginKey$g2;
26
+ return (_typeAheadPluginKey$g2 = _key.pluginKey.getState(editorState)) === null || _typeAheadPluginKey$g2 === void 0 ? void 0 : _typeAheadPluginKey$g2.triggerHandler;
27
+ };
28
+ var getTypeAheadQuery = exports.getTypeAheadQuery = function getTypeAheadQuery(editorState) {
29
+ var _typeAheadPluginKey$g3;
30
+ return (_typeAheadPluginKey$g3 = _key.pluginKey.getState(editorState)) === null || _typeAheadPluginKey$g3 === void 0 ? void 0 : _typeAheadPluginKey$g3.query;
31
+ };
32
+ var isTypeAheadAllowed = exports.isTypeAheadAllowed = function isTypeAheadAllowed(state) {
33
+ var isOpen = isTypeAheadOpen(state);
34
+ // if the TypeAhead is open
35
+ // we should not allow it
36
+ return !isOpen;
37
+ };
38
+ var findHandler = exports.findHandler = function findHandler(id, state) {
39
+ var pluginState = _key.pluginKey.getState(state);
40
+ if (!pluginState || !pluginState.typeAheadHandlers || pluginState.typeAheadHandlers.length === 0) {
41
+ return null;
42
+ }
43
+ var typeAheadHandlers = pluginState.typeAheadHandlers;
44
+ return typeAheadHandlers.find(function (h) {
45
+ return h.id === id;
46
+ }) || null;
47
+ };
48
+ var findHandlerByTrigger = exports.findHandlerByTrigger = function findHandlerByTrigger(_ref) {
49
+ var trigger = _ref.trigger,
50
+ editorState = _ref.editorState;
51
+ var pluginState = _key.pluginKey.getState(editorState);
52
+ if (!pluginState || !pluginState.typeAheadHandlers || pluginState.typeAheadHandlers.length === 0) {
53
+ return null;
54
+ }
55
+ var typeAheadHandlers = pluginState.typeAheadHandlers;
56
+ return typeAheadHandlers.find(function (h) {
57
+ return h.trigger === trigger;
58
+ }) || null;
59
+ };
60
+ var moveSelectedIndex = exports.moveSelectedIndex = function moveSelectedIndex(_ref2) {
61
+ var editorView = _ref2.editorView,
62
+ direction = _ref2.direction;
63
+ return function () {
64
+ var typeAheadState = getPluginState(editorView.state);
65
+ if (!typeAheadState) {
66
+ return;
67
+ }
68
+ var selectedIndex = typeAheadState.selectedIndex,
69
+ items = typeAheadState.items;
70
+ var stats = typeAheadState.stats instanceof _statsModifier.StatsModifier ? typeAheadState.stats : new _statsModifier.StatsModifier();
71
+ var nextIndex;
72
+ if (direction === 'next') {
73
+ stats.increaseArrowDown();
74
+
75
+ /**
76
+ * See: https://product-fabric.atlassian.net/browse/ED-17200
77
+ * `selectedIndex` is forced to -1 now to not immediately focus the typeahead
78
+ * and only do so when there is explicit logic to focus into the typeahead
79
+ * options.
80
+ *
81
+ * This check for "set index to 1 when -1"
82
+ * - is a temporary workaround to get back the previous behaviour without
83
+ * entirely reverting the a11y improvements
84
+ *
85
+ */
86
+ if (selectedIndex === -1 && items.length > 1) {
87
+ nextIndex = 1;
88
+ } else {
89
+ nextIndex = selectedIndex >= items.length - 1 ? 0 : selectedIndex + 1;
90
+ }
91
+ } else {
92
+ stats.increaseArrowUp();
93
+ nextIndex = selectedIndex <= 0 ? items.length - 1 : selectedIndex - 1;
94
+ }
95
+ (0, _updateSelectedIndex.updateSelectedIndex)(nextIndex)(editorView.state, editorView.dispatch);
96
+ };
97
+ };
98
+ var getTypeAheadListAriaLabels = exports.getTypeAheadListAriaLabels = function getTypeAheadListAriaLabels(trigger, intl, item) {
99
+ var _item$mention, _item$mention2, _item$emoji, _item$emoji2, _item$emoji3;
100
+ switch (trigger) {
101
+ case '@':
102
+ return {
103
+ popupAriaLabel: intl.formatMessage(_messages.typeAheadListMessages.mentionPopupLabel),
104
+ listItemAriaLabel: intl.formatMessage(_messages.typeAheadListMessages.metionListItemLabel, {
105
+ name: (item === null || item === void 0 || (_item$mention = item.mention) === null || _item$mention === void 0 ? void 0 : _item$mention.name) || '',
106
+ shortName: (item === null || item === void 0 || (_item$mention2 = item.mention) === null || _item$mention2 === void 0 ? void 0 : _item$mention2.mentionName) || ''
107
+ })
108
+ };
109
+ case '/':
110
+ return {
111
+ popupAriaLabel: intl.formatMessage(_messages.typeAheadListMessages.quickInsertPopupLabel),
112
+ listItemAriaLabel: intl.formatMessage(_messages.typeAheadListMessages.emojiListItemLabel, {
113
+ name: (item === null || item === void 0 ? void 0 : item.title) || '',
114
+ shortcut: (item === null || item === void 0 || (_item$emoji = item.emoji) === null || _item$emoji === void 0 ? void 0 : _item$emoji.shortName) || ''
115
+ })
116
+ };
117
+ case ':':
118
+ return {
119
+ popupAriaLabel: intl.formatMessage(_messages.typeAheadListMessages.emojiPopupLabel),
120
+ listItemAriaLabel: intl.formatMessage(_messages.typeAheadListMessages.emojiListItemLabel, {
121
+ name: (item === null || item === void 0 || (_item$emoji2 = item.emoji) === null || _item$emoji2 === void 0 ? void 0 : _item$emoji2.name) || '',
122
+ shortcut: (item === null || item === void 0 || (_item$emoji3 = item.emoji) === null || _item$emoji3 === void 0 ? void 0 : _item$emoji3.shortName) || ''
123
+ })
124
+ };
125
+ default:
126
+ return {
127
+ popupAriaLabel: intl.formatMessage(_messages.typeAheadListMessages.typeAheadPopupLabel)
128
+ };
129
+ }
130
+ };
@@ -0,0 +1,205 @@
1
+ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
+ import { SelectItemMode, TypeAheadAvailableNodes } from '@atlaskit/editor-common/type-ahead';
3
+ import { insertTypeAheadItem } from './commands/insert-type-ahead-item';
4
+ import { updateQuery } from './commands/update-query';
5
+ import { closeTypeAhead } from './transforms/close-type-ahead';
6
+ import { openTypeAheadAtCursor } from './transforms/open-typeahead-at-cursor';
7
+ import { findHandler, getTypeAheadHandler, getTypeAheadQuery, isTypeAheadOpen } from './utils';
8
+ const open = ({
9
+ editorView
10
+ }) => itemType => inputMethod => {
11
+ const {
12
+ state
13
+ } = editorView;
14
+ const handler = findHandler(itemType, state);
15
+ if (!handler) {
16
+ return false;
17
+ }
18
+ const {
19
+ tr
20
+ } = state;
21
+ openTypeAheadAtCursor({
22
+ triggerHandler: handler,
23
+ inputMethod
24
+ })({
25
+ tr
26
+ });
27
+ editorView.dispatch(tr);
28
+ return true;
29
+ };
30
+ const defaultCloseOptions = {
31
+ insertCurrentQueryAsRawText: false
32
+ };
33
+ const close = ({
34
+ editorView
35
+ }) => (options = defaultCloseOptions) => {
36
+ const {
37
+ state
38
+ } = editorView;
39
+ const currentQuery = getTypeAheadQuery(editorView.state);
40
+ let tr = state.tr;
41
+ if (options.attachCommand) {
42
+ const fakeDispatch = customTr => {
43
+ tr = customTr;
44
+ };
45
+ options.attachCommand(state, fakeDispatch);
46
+ }
47
+ closeTypeAhead(tr);
48
+ if (options.insertCurrentQueryAsRawText && currentQuery && currentQuery.length > 0) {
49
+ const handler = getTypeAheadHandler(state);
50
+ const text = handler.trigger.concat(currentQuery);
51
+ tr.replaceSelectionWith(state.schema.text(text));
52
+ }
53
+ editorView.dispatch(tr);
54
+ if (!editorView.hasFocus()) {
55
+ editorView.focus();
56
+ }
57
+ return true;
58
+ };
59
+ const search = ({
60
+ editorView
61
+ }) => itemType => (query = '') => {
62
+ const {
63
+ state
64
+ } = editorView;
65
+ const handler = findHandler(itemType, state);
66
+ if (!handler) {
67
+ throw new Error(`Handler not found, did you load the ${itemType} plugin properly`);
68
+ }
69
+ open({
70
+ editorView
71
+ })(itemType)(INPUT_METHOD.KEYBOARD);
72
+ updateQuery(query)(editorView.state, editorView.dispatch);
73
+ const lastQuery = {
74
+ current: query
75
+ };
76
+ const last = handler.getItems({
77
+ query,
78
+ editorState: state
79
+ }).then(items => {
80
+ if (!handler.forceSelect) {
81
+ return items;
82
+ }
83
+ const forceSelectedItem = handler.forceSelect({
84
+ items,
85
+ query,
86
+ editorState: state
87
+ });
88
+ if (!forceSelectedItem) {
89
+ return items;
90
+ }
91
+ insertTypeAheadItem(editorView)({
92
+ handler,
93
+ item: forceSelectedItem,
94
+ query,
95
+ mode: SelectItemMode.SELECTED,
96
+ sourceListItem: items
97
+ });
98
+ });
99
+ const results = {
100
+ last
101
+ };
102
+ return {
103
+ type: appendValue => {
104
+ if (!appendValue) {
105
+ return;
106
+ }
107
+ lastQuery.current += appendValue;
108
+ updateQuery(lastQuery.current)(editorView.state, editorView.dispatch);
109
+ const promise = handler.getItems({
110
+ query: lastQuery.current,
111
+ editorState: state
112
+ });
113
+ results.last = promise;
114
+ return promise;
115
+ },
116
+ result: () => results.last,
117
+ close: close({
118
+ editorView
119
+ }),
120
+ insert: ({
121
+ index,
122
+ mode
123
+ }) => {
124
+ return results.last.then(result => {
125
+ const item = result ? result[index] : null;
126
+ if (result && item) {
127
+ insertTypeAheadItem(editorView)({
128
+ handler,
129
+ item,
130
+ query,
131
+ mode: mode || SelectItemMode.SELECTED,
132
+ sourceListItem: result
133
+ });
134
+ }
135
+ });
136
+ }
137
+ };
138
+ };
139
+ const insertItem = ({
140
+ editorView
141
+ }) => itemType => ({
142
+ contentItem,
143
+ query,
144
+ sourceListItem
145
+ }) => {
146
+ const {
147
+ state
148
+ } = editorView;
149
+ const handler = findHandler(itemType, state);
150
+ if (!handler) {
151
+ return false;
152
+ }
153
+ insertTypeAheadItem(editorView)({
154
+ handler,
155
+ item: contentItem,
156
+ mode: SelectItemMode.SELECTED,
157
+ query,
158
+ sourceListItem
159
+ });
160
+ return true;
161
+ };
162
+ const isOpen = ({
163
+ editorView
164
+ }) => () => {
165
+ if (!isTypeAheadOpen(editorView.state)) {
166
+ return false;
167
+ }
168
+ const handler = getTypeAheadHandler(editorView.state);
169
+ if (!handler) {
170
+ return false;
171
+ }
172
+ return handler;
173
+ };
174
+ const currentQuery = ({
175
+ editorView
176
+ }) => () => {
177
+ return getTypeAheadQuery(editorView.state);
178
+ };
179
+
180
+ /**
181
+ * Please do not use it. Ping #help-editor and talk to the Lego team before use it.
182
+ *
183
+ * @private
184
+ * @deprecated
185
+ *
186
+ */
187
+ export const createTypeAheadTools = editorView => {
188
+ const props = {
189
+ editorView
190
+ };
191
+ return {
192
+ isOpen: isOpen(props),
193
+ currentQuery: currentQuery(props),
194
+ close: close(props),
195
+ openMention: open(props)(TypeAheadAvailableNodes.MENTION),
196
+ searchMention: search(props)(TypeAheadAvailableNodes.MENTION),
197
+ openQuickInsert: open(props)(TypeAheadAvailableNodes.QUICK_INSERT),
198
+ searchQuickInsert: search(props)(TypeAheadAvailableNodes.QUICK_INSERT),
199
+ openEmoji: open(props)(TypeAheadAvailableNodes.EMOJI),
200
+ searchEmoji: search(props)(TypeAheadAvailableNodes.EMOJI),
201
+ insertItemMention: insertItem(props)(TypeAheadAvailableNodes.MENTION),
202
+ insertItemEmoji: insertItem(props)(TypeAheadAvailableNodes.EMOJI),
203
+ insertItemQuickInsert: insertItem(props)(TypeAheadAvailableNodes.QUICK_INSERT)
204
+ };
205
+ };
@@ -0,0 +1,204 @@
1
+ import { InsertTypeAheadStages, InsertTypeAheadStep } from '@atlaskit/adf-schema/steps';
2
+ import { SelectItemMode } from '@atlaskit/editor-common/type-ahead';
3
+ import { closeHistory } from '@atlaskit/editor-prosemirror/history';
4
+ import { Fragment, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
5
+ import { insertBlockNode, insertInlineNodeOrFragment } from '../insert-utils';
6
+ import { ACTIONS } from '../pm-plugins/actions';
7
+ import { pluginKey } from '../pm-plugins/key';
8
+ import { StatsModifier } from '../stats-modifier';
9
+ import { closeTypeAhead } from '../transforms/close-type-ahead';
10
+ import { getPluginState } from '../utils';
11
+ const validateNode = ({
12
+ schema,
13
+ maybeNode
14
+ }) => {
15
+ if (!maybeNode) {
16
+ return null;
17
+ }
18
+ if (maybeNode instanceof PMNode || maybeNode instanceof Fragment) {
19
+ return maybeNode;
20
+ }
21
+ if (typeof maybeNode === 'string') {
22
+ return schema.text(maybeNode);
23
+ }
24
+ try {
25
+ return PMNode.fromJSON(schema, maybeNode);
26
+ } catch (e) {
27
+ // eslint-disable-next-line no-console
28
+ console.error(e);
29
+ return null;
30
+ }
31
+ };
32
+ const createInsertCallback = ({
33
+ editorState: state,
34
+ handler,
35
+ query,
36
+ wasInsertedBySpace,
37
+ selectedIndex,
38
+ textStartPosition,
39
+ textInserted
40
+ }) => (maybeNode, opts = {}) => {
41
+ const {
42
+ tr
43
+ } = state;
44
+ const position = {
45
+ start: textStartPosition,
46
+ end: textStartPosition + (wasInsertedBySpace ? textInserted.length : 0)
47
+ };
48
+ const node = validateNode({
49
+ schema: state.schema,
50
+ maybeNode
51
+ });
52
+ if (!node) {
53
+ closeTypeAhead(tr);
54
+ // In this kind of situation we need to
55
+ // delete the raw text query
56
+ tr.delete(position.start, position.end);
57
+ return tr;
58
+ }
59
+ node instanceof PMNode && node.isBlock ? insertBlockNode({
60
+ node,
61
+ tr,
62
+ position
63
+ }) : insertInlineNodeOrFragment({
64
+ maybeFragment: node,
65
+ tr,
66
+ position,
67
+ selectInlineNode: Boolean(opts.selectInlineNode)
68
+ });
69
+ closeHistory(tr);
70
+ if (wasInsertedBySpace) {
71
+ return tr;
72
+ }
73
+ const config = {
74
+ stage: InsertTypeAheadStages.INSERTING_ITEM,
75
+ query,
76
+ selectedIndex,
77
+ trigger: handler.trigger
78
+ };
79
+ tr.step(new InsertTypeAheadStep(config));
80
+ return tr;
81
+ };
82
+ const createDeleteRawTextCallback = ({
83
+ trigger,
84
+ selectedIndex,
85
+ position,
86
+ query,
87
+ wasInsertedBySpace,
88
+ insertItem
89
+ }) => {
90
+ return newState => {
91
+ const tr = newState.tr;
92
+ closeHistory(tr);
93
+ if (!wasInsertedBySpace) {
94
+ tr.delete(position.start, position.end);
95
+ const config = {
96
+ stage: InsertTypeAheadStages.DELETING_RAW_QUERY,
97
+ selectedIndex,
98
+ query,
99
+ trigger
100
+ };
101
+ tr.step(new InsertTypeAheadStep(config));
102
+ }
103
+ tr.setMeta(pluginKey, {
104
+ action: ACTIONS.INSERT_ITEM,
105
+ params: insertItem
106
+ });
107
+ return tr;
108
+ };
109
+ };
110
+ export const insertTypeAheadItem = view => ({
111
+ item,
112
+ handler,
113
+ mode,
114
+ query,
115
+ sourceListItem
116
+ }) => {
117
+ const pluginState = getPluginState(view.state);
118
+ if (!pluginState) {
119
+ return;
120
+ }
121
+ const stats = (pluginState.stats || new StatsModifier()).serialize();
122
+ const meta = {
123
+ mode,
124
+ query,
125
+ stats,
126
+ sourceListItem
127
+ };
128
+ const {
129
+ tr
130
+ } = view.state;
131
+ const trigger = handler.trigger;
132
+ let text = `${trigger}${query}`;
133
+ if (mode === SelectItemMode.SPACE) {
134
+ text = text.trim().concat(' ');
135
+ }
136
+
137
+ // We want to always persist selectedIndex as -1 upon selecting an item from typeahead
138
+ // in order to retain exist focus behaviour when undoing
139
+ const selectedIndex = -1;
140
+ const wasInsertedBySpace = mode === SelectItemMode.SPACE;
141
+ const {
142
+ selection: {
143
+ from: textStartPosition
144
+ }
145
+ } = tr;
146
+ const insertItem = newEditorSate => {
147
+ const insertCallback = createInsertCallback({
148
+ editorState: newEditorSate,
149
+ query,
150
+ mode,
151
+ handler,
152
+ wasInsertedBySpace,
153
+ selectedIndex,
154
+ textInserted: text,
155
+ textStartPosition
156
+ });
157
+ let wasInsertCallbackCalled = false;
158
+ // Some wierd plugins doesn't call the insert item callback
159
+ // For example, the link quick insert item
160
+ // For those cases we need to make sure we are closing the typeahead
161
+ const proxyHandler = {
162
+ apply: function (target, _thisContext, argumentsList) {
163
+ wasInsertCallbackCalled = true;
164
+ return target(...argumentsList);
165
+ }
166
+ };
167
+ const insertCallbackProxy = new Proxy(insertCallback, proxyHandler);
168
+ const nextTr = handler.selectItem(newEditorSate, item, insertCallbackProxy, meta);
169
+ if (!wasInsertCallbackCalled && nextTr) {
170
+ closeHistory(nextTr);
171
+
172
+ // In some cases we need to re-open the typeahead
173
+ // e.g.: addign mentions from the quick insert
174
+ //
175
+ // Today, the QuickInsert API doesn't have a tool
176
+ // to help on this. So the code below will close the typeahead
177
+ // only if there is no previous metadata about typeahead in the
178
+ // next transaction
179
+ if (!nextTr.getMeta(pluginKey)) {
180
+ closeTypeAhead(nextTr);
181
+ }
182
+ }
183
+ return nextTr;
184
+ };
185
+ const position = {
186
+ start: tr.selection.from,
187
+ end: tr.selection.from + text.length
188
+ };
189
+ tr.setMeta(pluginKey, {
190
+ action: ACTIONS.INSERT_RAW_QUERY,
191
+ params: createDeleteRawTextCallback({
192
+ wasInsertedBySpace,
193
+ selectedIndex,
194
+ insertItem,
195
+ position,
196
+ query,
197
+ trigger
198
+ })
199
+ });
200
+ tr.insertText(text);
201
+ closeHistory(tr);
202
+ view.dispatch(tr);
203
+ view.focus();
204
+ };
@@ -0,0 +1,17 @@
1
+ import { ACTIONS } from '../pm-plugins/actions';
2
+ import { pluginKey as typeAheadPluginKey } from '../pm-plugins/key';
3
+ export const updateListItem = items => {
4
+ return (state, dispatch) => {
5
+ const tr = state.tr;
6
+ tr.setMeta(typeAheadPluginKey, {
7
+ action: ACTIONS.UPDATE_LIST_ITEMS,
8
+ params: {
9
+ items
10
+ }
11
+ });
12
+ if (dispatch) {
13
+ dispatch(tr);
14
+ }
15
+ return true;
16
+ };
17
+ };
@@ -0,0 +1,21 @@
1
+ import { ACTIONS } from '../pm-plugins/actions';
2
+ import { pluginKey as typeAheadPluginKey } from '../pm-plugins/key';
3
+ export const updateQuery = query => {
4
+ return (state, dispatch) => {
5
+ const pluginState = typeAheadPluginKey.getState(state);
6
+ if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.query) === query) {
7
+ return false;
8
+ }
9
+ const tr = state.tr;
10
+ tr.setMeta(typeAheadPluginKey, {
11
+ action: ACTIONS.CHANGE_QUERY,
12
+ params: {
13
+ query
14
+ }
15
+ });
16
+ if (dispatch) {
17
+ dispatch(tr);
18
+ }
19
+ return true;
20
+ };
21
+ };
@@ -0,0 +1,21 @@
1
+ import { ACTIONS } from '../pm-plugins/actions';
2
+ import { pluginKey as typeAheadPluginKey } from '../pm-plugins/key';
3
+ export const updateSelectedIndex = selectedIndex => {
4
+ return (state, dispatch) => {
5
+ const pluginState = typeAheadPluginKey.getState(state);
6
+ if ((pluginState === null || pluginState === void 0 ? void 0 : pluginState.selectedIndex) === selectedIndex) {
7
+ return false;
8
+ }
9
+ const tr = state.tr;
10
+ tr.setMeta(typeAheadPluginKey, {
11
+ action: ACTIONS.UPDATE_SELECTED_INDEX,
12
+ params: {
13
+ selectedIndex
14
+ }
15
+ });
16
+ if (dispatch) {
17
+ dispatch(tr);
18
+ }
19
+ return true;
20
+ };
21
+ };