@atlaskit/editor-plugin-type-ahead 0.6.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.
- package/.eslintrc.js +11 -0
- package/CHANGELOG.md +6 -0
- package/dist/cjs/api.js +215 -0
- package/dist/cjs/commands/insert-type-ahead-item.js +205 -0
- package/dist/cjs/commands/update-list-items.js +23 -0
- package/dist/cjs/commands/update-query.js +27 -0
- package/dist/cjs/commands/update-selected-index.js +27 -0
- package/dist/cjs/index.js +8 -1
- package/dist/cjs/insert-utils.js +107 -0
- package/dist/cjs/messages.js +79 -0
- package/dist/cjs/plugin.js +382 -0
- package/dist/cjs/pm-plugins/actions.js +16 -0
- package/dist/cjs/pm-plugins/decorations.js +148 -0
- package/dist/cjs/pm-plugins/input-rules.js +36 -0
- package/dist/cjs/pm-plugins/insert-item-plugin.js +22 -0
- package/dist/cjs/pm-plugins/key.js +8 -0
- package/dist/cjs/pm-plugins/main.js +110 -0
- package/dist/cjs/pm-plugins/reducer.js +158 -0
- package/dist/cjs/pm-plugins/utils.js +18 -0
- package/dist/cjs/stats-modifier.js +42 -0
- package/dist/cjs/transforms/close-type-ahead.js +13 -0
- package/dist/cjs/transforms/open-typeahead-at-cursor.js +75 -0
- package/dist/cjs/transforms/set-selection-before-query.js +18 -0
- package/dist/cjs/ui/AssistiveText.js +120 -0
- package/dist/cjs/ui/InputQuery.js +400 -0
- package/dist/cjs/ui/TypeAheadList.js +285 -0
- package/dist/cjs/ui/TypeAheadListItem.js +181 -0
- package/dist/cjs/ui/TypeAheadPopup.js +230 -0
- package/dist/cjs/ui/WrapperTypeAhead.js +127 -0
- package/dist/cjs/ui/hooks/use-item-insert.js +109 -0
- package/dist/cjs/ui/hooks/use-load-items.js +50 -0
- package/dist/cjs/ui/hooks/use-on-force-select.js +41 -0
- package/dist/cjs/utils.js +130 -0
- package/dist/es2019/api.js +205 -0
- package/dist/es2019/commands/insert-type-ahead-item.js +204 -0
- package/dist/es2019/commands/update-list-items.js +17 -0
- package/dist/es2019/commands/update-query.js +21 -0
- package/dist/es2019/commands/update-selected-index.js +21 -0
- package/dist/es2019/index.js +1 -1
- package/dist/es2019/insert-utils.js +106 -0
- package/dist/es2019/messages.js +73 -0
- package/dist/es2019/plugin.js +381 -0
- package/dist/es2019/pm-plugins/actions.js +10 -0
- package/dist/es2019/pm-plugins/decorations.js +148 -0
- package/dist/es2019/pm-plugins/input-rules.js +29 -0
- package/dist/es2019/pm-plugins/insert-item-plugin.js +16 -0
- package/dist/es2019/pm-plugins/key.js +2 -0
- package/dist/es2019/pm-plugins/main.js +106 -0
- package/dist/es2019/pm-plugins/reducer.js +160 -0
- package/dist/es2019/pm-plugins/utils.js +12 -0
- package/dist/es2019/stats-modifier.js +33 -0
- package/dist/es2019/transforms/close-type-ahead.js +7 -0
- package/dist/es2019/transforms/open-typeahead-at-cursor.js +71 -0
- package/dist/es2019/transforms/set-selection-before-query.js +10 -0
- package/dist/es2019/ui/AssistiveText.js +88 -0
- package/dist/es2019/ui/InputQuery.js +393 -0
- package/dist/es2019/ui/TypeAheadList.js +273 -0
- package/dist/es2019/ui/TypeAheadListItem.js +216 -0
- package/dist/es2019/ui/TypeAheadPopup.js +233 -0
- package/dist/es2019/ui/WrapperTypeAhead.js +109 -0
- package/dist/es2019/ui/hooks/use-item-insert.js +112 -0
- package/dist/es2019/ui/hooks/use-load-items.js +41 -0
- package/dist/es2019/ui/hooks/use-on-force-select.js +38 -0
- package/dist/es2019/utils.js +126 -0
- package/dist/esm/api.js +209 -0
- package/dist/esm/commands/insert-type-ahead-item.js +198 -0
- package/dist/esm/commands/update-list-items.js +17 -0
- package/dist/esm/commands/update-query.js +21 -0
- package/dist/esm/commands/update-selected-index.js +21 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/insert-utils.js +101 -0
- package/dist/esm/messages.js +73 -0
- package/dist/esm/plugin.js +374 -0
- package/dist/esm/pm-plugins/actions.js +10 -0
- package/dist/esm/pm-plugins/decorations.js +141 -0
- package/dist/esm/pm-plugins/input-rules.js +29 -0
- package/dist/esm/pm-plugins/insert-item-plugin.js +16 -0
- package/dist/esm/pm-plugins/key.js +2 -0
- package/dist/esm/pm-plugins/main.js +104 -0
- package/dist/esm/pm-plugins/reducer.js +151 -0
- package/dist/esm/pm-plugins/utils.js +12 -0
- package/dist/esm/stats-modifier.js +35 -0
- package/dist/esm/transforms/close-type-ahead.js +7 -0
- package/dist/esm/transforms/open-typeahead-at-cursor.js +69 -0
- package/dist/esm/transforms/set-selection-before-query.js +12 -0
- package/dist/esm/ui/AssistiveText.js +115 -0
- package/dist/esm/ui/InputQuery.js +390 -0
- package/dist/esm/ui/TypeAheadList.js +276 -0
- package/dist/esm/ui/TypeAheadListItem.js +171 -0
- package/dist/esm/ui/TypeAheadPopup.js +220 -0
- package/dist/esm/ui/WrapperTypeAhead.js +117 -0
- package/dist/esm/ui/hooks/use-item-insert.js +103 -0
- package/dist/esm/ui/hooks/use-load-items.js +43 -0
- package/dist/esm/ui/hooks/use-on-force-select.js +35 -0
- package/dist/esm/utils.js +124 -0
- package/dist/types/api.d.ts +61 -0
- package/dist/types/commands/insert-type-ahead-item.d.ts +12 -0
- package/dist/types/commands/update-list-items.d.ts +3 -0
- package/dist/types/commands/update-query.d.ts +2 -0
- package/dist/types/commands/update-selected-index.d.ts +2 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/insert-utils.d.ts +18 -0
- package/dist/types/messages.d.ts +72 -0
- package/dist/types/plugin.d.ts +10 -0
- package/dist/types/pm-plugins/actions.d.ts +9 -0
- package/dist/types/pm-plugins/decorations.d.ts +14 -0
- package/dist/types/pm-plugins/input-rules.d.ts +6 -0
- package/dist/types/pm-plugins/insert-item-plugin.d.ts +2 -0
- package/dist/types/pm-plugins/key.d.ts +3 -0
- package/dist/types/pm-plugins/main.d.ts +14 -0
- package/dist/types/pm-plugins/reducer.d.ts +10 -0
- package/dist/types/pm-plugins/utils.d.ts +4 -0
- package/dist/types/stats-modifier.d.ts +20 -0
- package/dist/types/transforms/close-type-ahead.d.ts +2 -0
- package/dist/types/transforms/open-typeahead-at-cursor.d.ts +11 -0
- package/dist/types/transforms/set-selection-before-query.d.ts +2 -0
- package/dist/types/ui/AssistiveText.d.ts +33 -0
- package/dist/types/ui/InputQuery.d.ts +26 -0
- package/dist/types/ui/TypeAheadList.d.ts +25 -0
- package/dist/types/ui/TypeAheadListItem.d.ts +18 -0
- package/dist/types/ui/TypeAheadPopup.d.ts +29 -0
- package/dist/types/ui/WrapperTypeAhead.d.ts +20 -0
- package/dist/types/ui/hooks/use-item-insert.d.ts +3 -0
- package/dist/types/ui/hooks/use-load-items.d.ts +3 -0
- package/dist/types/ui/hooks/use-on-force-select.d.ts +11 -0
- package/dist/types/utils.d.ts +27 -0
- package/dist/types-ts4.5/api.d.ts +61 -0
- package/dist/types-ts4.5/commands/insert-type-ahead-item.d.ts +12 -0
- package/dist/types-ts4.5/commands/update-list-items.d.ts +3 -0
- package/dist/types-ts4.5/commands/update-query.d.ts +2 -0
- package/dist/types-ts4.5/commands/update-selected-index.d.ts +2 -0
- package/dist/types-ts4.5/index.d.ts +2 -1
- package/dist/types-ts4.5/insert-utils.d.ts +18 -0
- package/dist/types-ts4.5/messages.d.ts +72 -0
- package/dist/types-ts4.5/plugin.d.ts +10 -0
- package/dist/types-ts4.5/pm-plugins/actions.d.ts +9 -0
- package/dist/types-ts4.5/pm-plugins/decorations.d.ts +14 -0
- package/dist/types-ts4.5/pm-plugins/input-rules.d.ts +6 -0
- package/dist/types-ts4.5/pm-plugins/insert-item-plugin.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/key.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +14 -0
- package/dist/types-ts4.5/pm-plugins/reducer.d.ts +10 -0
- package/dist/types-ts4.5/pm-plugins/utils.d.ts +4 -0
- package/dist/types-ts4.5/stats-modifier.d.ts +20 -0
- package/dist/types-ts4.5/transforms/close-type-ahead.d.ts +2 -0
- package/dist/types-ts4.5/transforms/open-typeahead-at-cursor.d.ts +11 -0
- package/dist/types-ts4.5/transforms/set-selection-before-query.d.ts +2 -0
- package/dist/types-ts4.5/ui/AssistiveText.d.ts +33 -0
- package/dist/types-ts4.5/ui/InputQuery.d.ts +26 -0
- package/dist/types-ts4.5/ui/TypeAheadList.d.ts +25 -0
- package/dist/types-ts4.5/ui/TypeAheadListItem.d.ts +18 -0
- package/dist/types-ts4.5/ui/TypeAheadPopup.d.ts +29 -0
- package/dist/types-ts4.5/ui/WrapperTypeAhead.d.ts +20 -0
- package/dist/types-ts4.5/ui/hooks/use-item-insert.d.ts +7 -0
- package/dist/types-ts4.5/ui/hooks/use-load-items.d.ts +3 -0
- package/dist/types-ts4.5/ui/hooks/use-on-force-select.d.ts +11 -0
- package/dist/types-ts4.5/utils.d.ts +27 -0
- package/package.json +20 -27
- package/report.api.md +29 -1
- package/tmp/api-report-tmp.d.ts +26 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom';
|
|
3
|
+
import { IntlProvider } from 'react-intl-next';
|
|
4
|
+
import uuid from 'uuid';
|
|
5
|
+
import { keyName as keyNameNormalized } from 'w3c-keyname';
|
|
6
|
+
import { redo, undo } from '@atlaskit/editor-prosemirror/history';
|
|
7
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
8
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
9
|
+
import { B400 } from '@atlaskit/theme/colors';
|
|
10
|
+
import { TYPE_AHEAD_DECORATION_DATA_ATTRIBUTE, TYPE_AHEAD_DECORATION_KEY } from '../constants';
|
|
11
|
+
import { StatsModifier } from '../stats-modifier';
|
|
12
|
+
import { closeTypeAhead } from '../transforms/close-type-ahead';
|
|
13
|
+
import { WrapperTypeAhead } from '../ui/WrapperTypeAhead';
|
|
14
|
+
import { getTypeAheadQuery } from '../utils';
|
|
15
|
+
export var factoryDecorations = function factoryDecorations(_ref) {
|
|
16
|
+
var intl = _ref.intl,
|
|
17
|
+
popupMountRef = _ref.popupMountRef,
|
|
18
|
+
createAnalyticsEvent = _ref.createAnalyticsEvent;
|
|
19
|
+
var createDecorations = function createDecorations(tr, _ref2) {
|
|
20
|
+
var triggerHandler = _ref2.triggerHandler,
|
|
21
|
+
inputMethod = _ref2.inputMethod,
|
|
22
|
+
reopenQuery = _ref2.reopenQuery;
|
|
23
|
+
var selection = tr.selection;
|
|
24
|
+
if (!(selection instanceof TextSelection) || !selection.$cursor) {
|
|
25
|
+
return {
|
|
26
|
+
decorationSet: DecorationSet.empty,
|
|
27
|
+
stats: null,
|
|
28
|
+
decorationElement: null
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
var decorationId = "decoration_id_".concat(TYPE_AHEAD_DECORATION_KEY, "_").concat(uuid());
|
|
32
|
+
var $cursor = selection.$cursor;
|
|
33
|
+
var typeaheadComponent = document.createElement('mark');
|
|
34
|
+
var stats = new StatsModifier();
|
|
35
|
+
var shouldFocusCursorInsideQuery = true;
|
|
36
|
+
var deco = Decoration.widget($cursor.pos, function (editorView, getDecorationPosition) {
|
|
37
|
+
var _popupMountRef$curren, _popupMountRef$curren2, _popupMountRef$curren3;
|
|
38
|
+
typeaheadComponent.setAttribute('id', decorationId);
|
|
39
|
+
typeaheadComponent.setAttribute('role', 'search');
|
|
40
|
+
typeaheadComponent.dataset.typeAheadQuery = 'true';
|
|
41
|
+
typeaheadComponent.dataset.trigger = triggerHandler.trigger;
|
|
42
|
+
|
|
43
|
+
// This line below seems weird,
|
|
44
|
+
// we need that cuz the clickAreaHelper
|
|
45
|
+
// will try to hijack any click event coming
|
|
46
|
+
// from the inside of the Editor
|
|
47
|
+
// packages/editor/editor-core/src/ui/Addon/click-area-helper.ts
|
|
48
|
+
typeaheadComponent.dataset.editorPopup = 'true';
|
|
49
|
+
typeaheadComponent.dataset.typeAhead = TYPE_AHEAD_DECORATION_DATA_ATTRIBUTE;
|
|
50
|
+
typeaheadComponent.style.color = "var(--ds-text-accent-blue, ".concat(B400, ")");
|
|
51
|
+
typeaheadComponent.style.backgroundColor = 'transparent';
|
|
52
|
+
var onUndoRedo = function onUndoRedo(inputType) {
|
|
53
|
+
if (!['historyUndo', 'historyRedo'].includes(inputType)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
var hasReopenQuery = typeof reopenQuery === 'string' && reopenQuery.trim().length > 0;
|
|
57
|
+
var currentQuery = getTypeAheadQuery(editorView.state);
|
|
58
|
+
if (hasReopenQuery || (currentQuery === null || currentQuery === void 0 ? void 0 : currentQuery.length) === 0) {
|
|
59
|
+
var command = inputType === 'historyUndo' ? undo : redo;
|
|
60
|
+
var _tr = editorView.state.tr;
|
|
61
|
+
var fakeDispatch = function fakeDispatch(customTr) {
|
|
62
|
+
_tr = customTr;
|
|
63
|
+
};
|
|
64
|
+
var result = command(editorView.state, fakeDispatch);
|
|
65
|
+
if (result) {
|
|
66
|
+
closeTypeAhead(_tr);
|
|
67
|
+
editorView.dispatch(_tr);
|
|
68
|
+
editorView.focus();
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
};
|
|
74
|
+
ReactDOM.render( /*#__PURE__*/React.createElement(IntlProvider, {
|
|
75
|
+
locale: intl.locale || 'en',
|
|
76
|
+
messages: intl.messages,
|
|
77
|
+
formats: intl.formats
|
|
78
|
+
}, /*#__PURE__*/React.createElement(WrapperTypeAhead, {
|
|
79
|
+
triggerHandler: triggerHandler,
|
|
80
|
+
editorView: editorView,
|
|
81
|
+
anchorElement: typeaheadComponent,
|
|
82
|
+
createAnalyticsEvent: createAnalyticsEvent,
|
|
83
|
+
inputMethod: inputMethod,
|
|
84
|
+
getDecorationPosition: getDecorationPosition,
|
|
85
|
+
shouldFocusCursorInsideQuery: shouldFocusCursorInsideQuery,
|
|
86
|
+
popupsMountPoint: (_popupMountRef$curren = popupMountRef.current) === null || _popupMountRef$curren === void 0 ? void 0 : _popupMountRef$curren.popupsMountPoint,
|
|
87
|
+
popupsBoundariesElement: (_popupMountRef$curren2 = popupMountRef.current) === null || _popupMountRef$curren2 === void 0 ? void 0 : _popupMountRef$curren2.popupsBoundariesElement,
|
|
88
|
+
popupsScrollableElement: (_popupMountRef$curren3 = popupMountRef.current) === null || _popupMountRef$curren3 === void 0 ? void 0 : _popupMountRef$curren3.popupsScrollableElement,
|
|
89
|
+
onUndoRedo: onUndoRedo,
|
|
90
|
+
reopenQuery: reopenQuery
|
|
91
|
+
})), typeaheadComponent);
|
|
92
|
+
shouldFocusCursorInsideQuery = false;
|
|
93
|
+
return typeaheadComponent;
|
|
94
|
+
}, {
|
|
95
|
+
isTypeAheadDecoration: true,
|
|
96
|
+
key: decorationId,
|
|
97
|
+
side: 0,
|
|
98
|
+
stopEvent: function stopEvent(e) {
|
|
99
|
+
var key = keyNameNormalized(e);
|
|
100
|
+
var sel = document.getSelection();
|
|
101
|
+
if ('ArrowLeft' === key && (sel === null || sel === void 0 ? void 0 : sel.anchorOffset) === 0) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
},
|
|
106
|
+
ignoreSelection: false
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
decorationSet: DecorationSet.create(tr.doc, [deco]),
|
|
110
|
+
decorationElement: typeaheadComponent,
|
|
111
|
+
stats: stats
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
var removeDecorations = function removeDecorations(decorationSet) {
|
|
115
|
+
if (!decorationSet || decorationSet === DecorationSet.empty) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
var typeAheadDecorations = decorationSet.find(undefined, undefined, function (spec) {
|
|
119
|
+
return spec.isTypeAheadDecoration;
|
|
120
|
+
});
|
|
121
|
+
if (!typeAheadDecorations || typeAheadDecorations.length === 0) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
typeAheadDecorations.forEach(function (_ref3) {
|
|
125
|
+
var spec = _ref3.spec;
|
|
126
|
+
if (!spec.key) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
var decoElement = document.querySelector("#".concat(spec.key));
|
|
130
|
+
if (!decoElement) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
ReactDOM.unmountComponentAtNode(decoElement);
|
|
134
|
+
});
|
|
135
|
+
return true;
|
|
136
|
+
};
|
|
137
|
+
return {
|
|
138
|
+
createDecorations: createDecorations,
|
|
139
|
+
removeDecorations: removeDecorations
|
|
140
|
+
};
|
|
141
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { createPlugin, createRule, leafNodeReplacementCharacter } from '@atlaskit/prosemirror-input-rules';
|
|
3
|
+
import { openTypeAheadAtCursor } from '../transforms/open-typeahead-at-cursor';
|
|
4
|
+
export function inputRulePlugin(schema, typeAheads, featureFlags) {
|
|
5
|
+
if (!typeAheads || typeAheads.length === 0) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
var rules = typeAheads.reduce(function (acc, typeAhead) {
|
|
9
|
+
var trigger = typeAhead.customRegex || typeAhead.trigger;
|
|
10
|
+
if (!trigger) {
|
|
11
|
+
return acc;
|
|
12
|
+
}
|
|
13
|
+
var regex = new RegExp("(^|[.!?\\s".concat(leafNodeReplacementCharacter, "])(").concat(trigger, ")$"));
|
|
14
|
+
acc.push(createRule(regex, function (state, match) {
|
|
15
|
+
return openTypeAheadAtCursor({
|
|
16
|
+
triggerHandler: typeAhead,
|
|
17
|
+
inputMethod: INPUT_METHOD.KEYBOARD
|
|
18
|
+
})({
|
|
19
|
+
tr: state.tr
|
|
20
|
+
});
|
|
21
|
+
}));
|
|
22
|
+
return acc;
|
|
23
|
+
}, []);
|
|
24
|
+
var plugin = createPlugin('type-ahead', rules, {
|
|
25
|
+
allowInsertTextOnDocument: false
|
|
26
|
+
});
|
|
27
|
+
return plugin;
|
|
28
|
+
}
|
|
29
|
+
export default inputRulePlugin;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { ACTIONS } from './actions';
|
|
3
|
+
import { isInsertionTransaction } from './utils';
|
|
4
|
+
export function createPlugin() {
|
|
5
|
+
return new SafePlugin({
|
|
6
|
+
appendTransaction: function appendTransaction(transactions, _oldState, newState) {
|
|
7
|
+
var insertItemCallback = isInsertionTransaction(transactions, ACTIONS.INSERT_ITEM);
|
|
8
|
+
if (insertItemCallback) {
|
|
9
|
+
var tr = insertItemCallback(newState);
|
|
10
|
+
if (tr) {
|
|
11
|
+
return tr;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { InsertTypeAheadStep } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import { closest } from '@atlaskit/editor-common/utils';
|
|
4
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
+
import { TYPE_AHEAD_DECORATION_DATA_ATTRIBUTE } from '../constants';
|
|
6
|
+
import { ACTIONS } from './actions';
|
|
7
|
+
import { factoryDecorations } from './decorations';
|
|
8
|
+
import { pluginKey } from './key';
|
|
9
|
+
import { createReducer } from './reducer';
|
|
10
|
+
import { isInsertionTransaction } from './utils';
|
|
11
|
+
var hasValidTypeAheadStep = function hasValidTypeAheadStep(tr) {
|
|
12
|
+
var steps = tr.steps.filter(function (step) {
|
|
13
|
+
return step instanceof InsertTypeAheadStep;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// There are some cases, like collab rebase, where the steps are re-applied
|
|
17
|
+
// We should not re open the type-ahead for those cases
|
|
18
|
+
if (steps.length === 1) {
|
|
19
|
+
return steps[0];
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
export function createPlugin(_ref) {
|
|
24
|
+
var reactDispatch = _ref.reactDispatch,
|
|
25
|
+
popupMountRef = _ref.popupMountRef,
|
|
26
|
+
createAnalyticsEvent = _ref.createAnalyticsEvent,
|
|
27
|
+
typeAheadHandlers = _ref.typeAheadHandlers,
|
|
28
|
+
getIntl = _ref.getIntl;
|
|
29
|
+
var intl = getIntl();
|
|
30
|
+
var _factoryDecorations = factoryDecorations({
|
|
31
|
+
intl: intl,
|
|
32
|
+
popupMountRef: popupMountRef,
|
|
33
|
+
createAnalyticsEvent: createAnalyticsEvent
|
|
34
|
+
}),
|
|
35
|
+
createDecorations = _factoryDecorations.createDecorations,
|
|
36
|
+
removeDecorations = _factoryDecorations.removeDecorations;
|
|
37
|
+
var reducer = createReducer({
|
|
38
|
+
createDecorations: createDecorations,
|
|
39
|
+
removeDecorations: removeDecorations,
|
|
40
|
+
typeAheadHandlers: typeAheadHandlers,
|
|
41
|
+
popupMountRef: popupMountRef
|
|
42
|
+
});
|
|
43
|
+
return new SafePlugin({
|
|
44
|
+
key: pluginKey,
|
|
45
|
+
state: {
|
|
46
|
+
init: function init() {
|
|
47
|
+
return {
|
|
48
|
+
typeAheadHandlers: typeAheadHandlers,
|
|
49
|
+
query: '',
|
|
50
|
+
decorationSet: DecorationSet.empty,
|
|
51
|
+
decorationElement: null,
|
|
52
|
+
items: [],
|
|
53
|
+
selectedIndex: -1,
|
|
54
|
+
stats: null,
|
|
55
|
+
inputMethod: null
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
apply: function apply(tr, currentPluginState, oldEditorState, state) {
|
|
59
|
+
var customStep = hasValidTypeAheadStep(tr);
|
|
60
|
+
var nextPluginState = reducer(tr, currentPluginState, customStep);
|
|
61
|
+
if (currentPluginState !== nextPluginState) {
|
|
62
|
+
reactDispatch(pluginKey, nextPluginState);
|
|
63
|
+
}
|
|
64
|
+
return nextPluginState;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
appendTransaction: function appendTransaction(transactions, _oldState, newState) {
|
|
68
|
+
var insertItemCallback = isInsertionTransaction(transactions, ACTIONS.INSERT_RAW_QUERY);
|
|
69
|
+
if (insertItemCallback) {
|
|
70
|
+
var tr = insertItemCallback(newState);
|
|
71
|
+
if (tr) {
|
|
72
|
+
return tr;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
view: function view() {
|
|
77
|
+
return {
|
|
78
|
+
update: function update(editorView) {}
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
props: {
|
|
82
|
+
decorations: function decorations(state) {
|
|
83
|
+
var _pluginKey$getState;
|
|
84
|
+
return (_pluginKey$getState = pluginKey.getState(state)) === null || _pluginKey$getState === void 0 ? void 0 : _pluginKey$getState.decorationSet;
|
|
85
|
+
},
|
|
86
|
+
handleDOMEvents: {
|
|
87
|
+
compositionend: function compositionend(view, event) {
|
|
88
|
+
return false;
|
|
89
|
+
},
|
|
90
|
+
click: function click(view, event) {
|
|
91
|
+
var target = event.target;
|
|
92
|
+
// ProseMirror view listen to any click event inside of it
|
|
93
|
+
// When this event is coming from the typeahead
|
|
94
|
+
// we should tell to ProseMirror to sit down and relax
|
|
95
|
+
// cuz we know what we are doing (I hope)
|
|
96
|
+
if (target instanceof HTMLElement && closest(target, "[data-type-ahead=".concat(TYPE_AHEAD_DECORATION_DATA_ATTRIBUTE, "]"))) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
import { InsertTypeAheadStages, InsertTypeAheadStep } from '@atlaskit/adf-schema/steps';
|
|
5
|
+
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
6
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
7
|
+
import { isTypeAheadHandler } from '../utils';
|
|
8
|
+
import { ACTIONS } from './actions';
|
|
9
|
+
import { pluginKey } from './key';
|
|
10
|
+
var shouldForceOpen = function shouldForceOpen(step) {
|
|
11
|
+
if (!(step instanceof InsertTypeAheadStep)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
var isDeletionRawQueryOperation = step.isInsertionStep() && step.stage === InsertTypeAheadStages.DELETING_RAW_QUERY;
|
|
15
|
+
var isUndoingInsertionItem = step.isUndoingStep() && step.stage === InsertTypeAheadStages.INSERTING_ITEM;
|
|
16
|
+
return isDeletionRawQueryOperation || isUndoingInsertionItem;
|
|
17
|
+
};
|
|
18
|
+
var shouldForceClose = function shouldForceClose(step) {
|
|
19
|
+
if (!(step instanceof InsertTypeAheadStep)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
var isInsertingItem = step.isInsertionStep() && step.stage === InsertTypeAheadStages.INSERTING_ITEM;
|
|
23
|
+
var isUndoingDeletionRawQuery = step.isUndoingStep() && step.stage === InsertTypeAheadStages.DELETING_RAW_QUERY;
|
|
24
|
+
return isInsertingItem || isUndoingDeletionRawQuery;
|
|
25
|
+
};
|
|
26
|
+
var createFindHandler = function createFindHandler(typeAheadHandlers) {
|
|
27
|
+
return function (step) {
|
|
28
|
+
if (!(step instanceof InsertTypeAheadStep)) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
var handler = typeAheadHandlers.find(function (h) {
|
|
32
|
+
return h.trigger === step.trigger;
|
|
33
|
+
});
|
|
34
|
+
return handler || null;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export var createReducer = function createReducer(_ref) {
|
|
38
|
+
var typeAheadHandlers = _ref.typeAheadHandlers,
|
|
39
|
+
removeDecorations = _ref.removeDecorations,
|
|
40
|
+
createDecorations = _ref.createDecorations;
|
|
41
|
+
var findHandler = createFindHandler(typeAheadHandlers);
|
|
42
|
+
var openMenu = function openMenu(currentPluginState, _ref2) {
|
|
43
|
+
var tr = _ref2.tr,
|
|
44
|
+
triggerHandler = _ref2.triggerHandler,
|
|
45
|
+
inputMethod = _ref2.inputMethod,
|
|
46
|
+
reopenQuery = _ref2.reopenQuery,
|
|
47
|
+
selectedIndex = _ref2.selectedIndex;
|
|
48
|
+
removeDecorations(currentPluginState.decorationSet);
|
|
49
|
+
var _createDecorations = createDecorations(tr, {
|
|
50
|
+
triggerHandler: triggerHandler,
|
|
51
|
+
inputMethod: inputMethod,
|
|
52
|
+
reopenQuery: reopenQuery
|
|
53
|
+
}),
|
|
54
|
+
decorationSet = _createDecorations.decorationSet,
|
|
55
|
+
decorationElement = _createDecorations.decorationElement,
|
|
56
|
+
stats = _createDecorations.stats;
|
|
57
|
+
return _objectSpread(_objectSpread({}, currentPluginState), {}, {
|
|
58
|
+
stats: stats,
|
|
59
|
+
decorationSet: decorationSet,
|
|
60
|
+
triggerHandler: triggerHandler,
|
|
61
|
+
decorationElement: decorationElement,
|
|
62
|
+
inputMethod: inputMethod,
|
|
63
|
+
selectedIndex: typeof selectedIndex === 'number' ? selectedIndex : -1,
|
|
64
|
+
items: [],
|
|
65
|
+
query: reopenQuery || ''
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
var closeMenu = function closeMenu(currentPluginState) {
|
|
69
|
+
removeDecorations(currentPluginState.decorationSet);
|
|
70
|
+
return _objectSpread(_objectSpread({}, currentPluginState), {}, {
|
|
71
|
+
inputMethod: null,
|
|
72
|
+
query: '',
|
|
73
|
+
decorationElement: null,
|
|
74
|
+
decorationSet: DecorationSet.empty,
|
|
75
|
+
stats: null,
|
|
76
|
+
triggerHandler: undefined,
|
|
77
|
+
items: []
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
return function (tr, currentPluginState, typeAheadStepOverride) {
|
|
81
|
+
var meta = tr.getMeta(pluginKey) || {};
|
|
82
|
+
|
|
83
|
+
// This code below controls when we should force
|
|
84
|
+
// the menu to open or close during undo/redo operations
|
|
85
|
+
var overrideHandler = findHandler(typeAheadStepOverride);
|
|
86
|
+
if (typeAheadStepOverride && overrideHandler && shouldForceOpen(typeAheadStepOverride)) {
|
|
87
|
+
return openMenu(currentPluginState, {
|
|
88
|
+
tr: tr,
|
|
89
|
+
triggerHandler: overrideHandler,
|
|
90
|
+
inputMethod: INPUT_METHOD.KEYBOARD,
|
|
91
|
+
reopenQuery: typeAheadStepOverride.query,
|
|
92
|
+
selectedIndex: typeAheadStepOverride.selectedIndex
|
|
93
|
+
});
|
|
94
|
+
} else if (shouldForceClose(typeAheadStepOverride)) {
|
|
95
|
+
return closeMenu(currentPluginState);
|
|
96
|
+
}
|
|
97
|
+
var _ref3 = meta || {},
|
|
98
|
+
action = _ref3.action,
|
|
99
|
+
params = _ref3.params;
|
|
100
|
+
var shouldOpenMenu = action === ACTIONS.OPEN_TYPEAHEAD_AT_CURSOR && isTypeAheadHandler(params === null || params === void 0 ? void 0 : params.triggerHandler);
|
|
101
|
+
var selectionChanged = tr.selectionSet && (tr.isGeneric || Boolean(tr.getMeta('pointer')));
|
|
102
|
+
var shouldCloseMenu = [ACTIONS.CLOSE_TYPE_AHEAD, ACTIONS.INSERT_ITEM].includes(action) || selectionChanged;
|
|
103
|
+
var shouldUpdateQuery = action === ACTIONS.CHANGE_QUERY;
|
|
104
|
+
var shouldUpdateListItems = action === ACTIONS.UPDATE_LIST_ITEMS;
|
|
105
|
+
var shouldUpdateSelectedIndex = action === ACTIONS.UPDATE_SELECTED_INDEX;
|
|
106
|
+
if (shouldOpenMenu) {
|
|
107
|
+
return openMenu(currentPluginState, {
|
|
108
|
+
tr: tr,
|
|
109
|
+
triggerHandler: params.triggerHandler,
|
|
110
|
+
inputMethod: params.inputMethod
|
|
111
|
+
});
|
|
112
|
+
} else if (shouldCloseMenu) {
|
|
113
|
+
return closeMenu(currentPluginState);
|
|
114
|
+
} else if (shouldUpdateQuery) {
|
|
115
|
+
return _objectSpread(_objectSpread({}, currentPluginState), {}, {
|
|
116
|
+
query: params.query
|
|
117
|
+
});
|
|
118
|
+
} else if (shouldUpdateListItems) {
|
|
119
|
+
var items = params.items;
|
|
120
|
+
var selectedIndex = currentPluginState.selectedIndex;
|
|
121
|
+
return _objectSpread(_objectSpread({}, currentPluginState), {}, {
|
|
122
|
+
items: items,
|
|
123
|
+
selectedIndex: Math.max(selectedIndex >= items.length ? items.length - 1 : selectedIndex, -1)
|
|
124
|
+
});
|
|
125
|
+
} else if (shouldUpdateSelectedIndex) {
|
|
126
|
+
return _objectSpread(_objectSpread({}, currentPluginState), {}, {
|
|
127
|
+
selectedIndex: params.selectedIndex
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (tr.docChanged) {
|
|
131
|
+
var decorationSet = currentPluginState.decorationSet;
|
|
132
|
+
var onRemove = function onRemove() {
|
|
133
|
+
// Make sure we are unmounting the component
|
|
134
|
+
// from the react tree when this decoration is removed
|
|
135
|
+
removeDecorations(currentPluginState.decorationSet);
|
|
136
|
+
};
|
|
137
|
+
var mappedDecorationSet = decorationSet.map(tr.mapping, tr.doc, {
|
|
138
|
+
onRemove: onRemove
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// return same pluginState if decorationSet did not change
|
|
142
|
+
if (mappedDecorationSet === currentPluginState.decorationSet) {
|
|
143
|
+
return currentPluginState;
|
|
144
|
+
}
|
|
145
|
+
return _objectSpread(_objectSpread({}, currentPluginState), {}, {
|
|
146
|
+
decorationSet: mappedDecorationSet
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return currentPluginState;
|
|
150
|
+
};
|
|
151
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { pluginKey } from './key';
|
|
2
|
+
export var isInsertionTransaction = function isInsertionTransaction(transactions, action) {
|
|
3
|
+
var _tr$getMeta2;
|
|
4
|
+
var tr = transactions.find(function (tr) {
|
|
5
|
+
var _tr$getMeta;
|
|
6
|
+
return ((_tr$getMeta = tr.getMeta(pluginKey)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.action) === action;
|
|
7
|
+
});
|
|
8
|
+
if (!tr) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return (_tr$getMeta2 = tr.getMeta(pluginKey)) === null || _tr$getMeta2 === void 0 ? void 0 : _tr$getMeta2.params;
|
|
12
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import _createClass from "@babel/runtime/helpers/createClass";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
|
+
export var StatsModifier = /*#__PURE__*/_createClass(function StatsModifier() {
|
|
5
|
+
var _this = this;
|
|
6
|
+
_classCallCheck(this, StatsModifier);
|
|
7
|
+
_defineProperty(this, "startedAt", 0);
|
|
8
|
+
_defineProperty(this, "endedAt", 0);
|
|
9
|
+
_defineProperty(this, "keyCount", {
|
|
10
|
+
arrowUp: 0,
|
|
11
|
+
arrowDown: 0
|
|
12
|
+
});
|
|
13
|
+
_defineProperty(this, "increaseArrowUp", function () {
|
|
14
|
+
_this.keyCount.arrowUp += 1;
|
|
15
|
+
});
|
|
16
|
+
_defineProperty(this, "increaseArrowDown", function () {
|
|
17
|
+
_this.keyCount.arrowDown += 1;
|
|
18
|
+
});
|
|
19
|
+
_defineProperty(this, "serialize", function () {
|
|
20
|
+
var _this$keyCount, _this$keyCount2;
|
|
21
|
+
return {
|
|
22
|
+
startedAt: _this.startedAt,
|
|
23
|
+
endedAt: performance.now(),
|
|
24
|
+
keyCount: {
|
|
25
|
+
arrowUp: ((_this$keyCount = _this.keyCount) === null || _this$keyCount === void 0 ? void 0 : _this$keyCount.arrowUp) || 0,
|
|
26
|
+
arrowDown: ((_this$keyCount2 = _this.keyCount) === null || _this$keyCount2 === void 0 ? void 0 : _this$keyCount2.arrowDown) || 0
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
this.startedAt = performance.now();
|
|
31
|
+
this.keyCount = {
|
|
32
|
+
arrowUp: 0,
|
|
33
|
+
arrowDown: 0
|
|
34
|
+
};
|
|
35
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { GapCursorSelection } from '@atlaskit/editor-common/selection';
|
|
2
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import { ACTIONS } from '../pm-plugins/actions';
|
|
4
|
+
import { pluginKey } from '../pm-plugins/key';
|
|
5
|
+
export var openTypeAhead = function openTypeAhead(props) {
|
|
6
|
+
return function (tr) {
|
|
7
|
+
var triggerHandler = props.triggerHandler,
|
|
8
|
+
inputMethod = props.inputMethod,
|
|
9
|
+
query = props.query;
|
|
10
|
+
tr.setMeta(pluginKey, {
|
|
11
|
+
action: ACTIONS.OPEN_TYPEAHEAD_AT_CURSOR,
|
|
12
|
+
params: {
|
|
13
|
+
triggerHandler: triggerHandler,
|
|
14
|
+
inputMethod: inputMethod,
|
|
15
|
+
query: query
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export var openTypeAheadAtCursor = function openTypeAheadAtCursor(_ref) {
|
|
21
|
+
var triggerHandler = _ref.triggerHandler,
|
|
22
|
+
inputMethod = _ref.inputMethod,
|
|
23
|
+
query = _ref.query;
|
|
24
|
+
return function (_ref2) {
|
|
25
|
+
var tr = _ref2.tr;
|
|
26
|
+
openTypeAhead({
|
|
27
|
+
triggerHandler: triggerHandler,
|
|
28
|
+
inputMethod: inputMethod,
|
|
29
|
+
query: query
|
|
30
|
+
})(tr);
|
|
31
|
+
var selection = tr.selection;
|
|
32
|
+
if (!(selection instanceof TextSelection || selection instanceof GapCursorSelection)) {
|
|
33
|
+
return tr;
|
|
34
|
+
}
|
|
35
|
+
if (selection instanceof GapCursorSelection) {
|
|
36
|
+
// Create space for the typeahead menu in gap cursor
|
|
37
|
+
tr.insertText(' ');
|
|
38
|
+
// delete 1 pos before wherever selection is now - that will delete the empty space
|
|
39
|
+
tr.delete(tr.selection.from - 1, tr.selection.from);
|
|
40
|
+
} else {
|
|
41
|
+
var _selection$$head, _selection$$head$pare, _selection$$head$pare2;
|
|
42
|
+
if (!selection.$cursor) {
|
|
43
|
+
tr.deleteSelection();
|
|
44
|
+
return tr;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Search & Destroy placeholder
|
|
48
|
+
var cursorPos = selection.$cursor.pos;
|
|
49
|
+
var nodeAtCursor = tr.doc.nodeAt(cursorPos);
|
|
50
|
+
var isPlaceholderAtCursorPosition = nodeAtCursor && nodeAtCursor.type.name === 'placeholder';
|
|
51
|
+
if (nodeAtCursor && isPlaceholderAtCursorPosition) {
|
|
52
|
+
tr.delete(cursorPos, cursorPos + nodeAtCursor.nodeSize);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ME-2375 remove the superfluous '@' inserted before decoration
|
|
56
|
+
// by composition (https://github.com/ProseMirror/prosemirror/issues/903)
|
|
57
|
+
//
|
|
58
|
+
// Update:
|
|
59
|
+
// Now also handles any use case with superfluous typeahead triggers (ie. '@', ':', '/')
|
|
60
|
+
// being inserted due to composition by checking if we have the trigger
|
|
61
|
+
// directly before the typeahead. This should not happen unless it has
|
|
62
|
+
// been eroneously added because we require whitespace/newline for typeahead.
|
|
63
|
+
if (cursorPos >= 2 && !!(selection !== null && selection !== void 0 && (_selection$$head = selection.$head) !== null && _selection$$head !== void 0 && (_selection$$head = _selection$$head.parent) !== null && _selection$$head !== void 0 && _selection$$head.textContent) && (_selection$$head$pare = (_selection$$head$pare2 = selection.$head.parent.textContent).endsWith) !== null && _selection$$head$pare !== void 0 && _selection$$head$pare.call(_selection$$head$pare2, triggerHandler.trigger)) {
|
|
64
|
+
tr.delete(cursorPos - 1, cursorPos);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return tr;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
export var setSelectionBeforeQuery = function setSelectionBeforeQuery(rawText) {
|
|
3
|
+
return function (tr) {
|
|
4
|
+
var currentPosition = tr.selection.$from.pos;
|
|
5
|
+
var positionBeforeRawText = Math.max(currentPosition - rawText.length, 0);
|
|
6
|
+
var resolvedPositionBeforeText = tr.doc.resolve(positionBeforeRawText);
|
|
7
|
+
var nextSelection = TextSelection.findFrom(resolvedPositionBeforeText, -1, true);
|
|
8
|
+
if (nextSelection) {
|
|
9
|
+
tr.setSelection(nextSelection);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
};
|