@atlaskit/editor-plugin-find-replace 0.1.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 +26 -0
- package/CHANGELOG.md +11 -0
- package/LICENSE.md +13 -0
- package/README.md +30 -0
- package/dist/cjs/FindReplaceToolbarButtonWithState.js +166 -0
- package/dist/cjs/actions.js +19 -0
- package/dist/cjs/commands-with-analytics.js +101 -0
- package/dist/cjs/commands.js +255 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/plugin.js +93 -0
- package/dist/cjs/pm-plugins/keymap.js +24 -0
- package/dist/cjs/pm-plugins/main.js +39 -0
- package/dist/cjs/pm-plugins/plugin-factory.js +109 -0
- package/dist/cjs/pm-plugins/plugin-key.js +8 -0
- package/dist/cjs/reducer.js +61 -0
- package/dist/cjs/styles.js +17 -0
- package/dist/cjs/types.js +5 -0
- package/dist/cjs/ui/Find.js +309 -0
- package/dist/cjs/ui/FindReplace.js +104 -0
- package/dist/cjs/ui/FindReplaceToolbarButton.js +133 -0
- package/dist/cjs/ui/FindReplaceTooltipButton.js +77 -0
- package/dist/cjs/ui/Replace.js +176 -0
- package/dist/cjs/ui/styles.js +46 -0
- package/dist/cjs/utils/array.js +13 -0
- package/dist/cjs/utils/batch-decorations.js +310 -0
- package/dist/cjs/utils/commands.js +16 -0
- package/dist/cjs/utils/index.js +290 -0
- package/dist/es2019/FindReplaceToolbarButtonWithState.js +153 -0
- package/dist/es2019/actions.js +13 -0
- package/dist/es2019/commands-with-analytics.js +72 -0
- package/dist/es2019/commands.js +240 -0
- package/dist/es2019/index.js +1 -0
- package/dist/es2019/plugin.js +88 -0
- package/dist/es2019/pm-plugins/keymap.js +16 -0
- package/dist/es2019/pm-plugins/main.js +30 -0
- package/dist/es2019/pm-plugins/plugin-factory.js +91 -0
- package/dist/es2019/pm-plugins/plugin-key.js +2 -0
- package/dist/es2019/reducer.js +56 -0
- package/dist/es2019/styles.js +18 -0
- package/dist/es2019/types.js +1 -0
- package/dist/es2019/ui/Find.js +286 -0
- package/dist/es2019/ui/FindReplace.js +81 -0
- package/dist/es2019/ui/FindReplaceToolbarButton.js +122 -0
- package/dist/es2019/ui/FindReplaceTooltipButton.js +51 -0
- package/dist/es2019/ui/Replace.js +155 -0
- package/dist/es2019/ui/styles.js +50 -0
- package/dist/es2019/utils/array.js +3 -0
- package/dist/es2019/utils/batch-decorations.js +189 -0
- package/dist/es2019/utils/commands.js +6 -0
- package/dist/es2019/utils/index.js +249 -0
- package/dist/esm/FindReplaceToolbarButtonWithState.js +157 -0
- package/dist/esm/actions.js +13 -0
- package/dist/esm/commands-with-analytics.js +95 -0
- package/dist/esm/commands.js +248 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugin.js +86 -0
- package/dist/esm/pm-plugins/keymap.js +18 -0
- package/dist/esm/pm-plugins/main.js +33 -0
- package/dist/esm/pm-plugins/plugin-factory.js +104 -0
- package/dist/esm/pm-plugins/plugin-key.js +2 -0
- package/dist/esm/reducer.js +54 -0
- package/dist/esm/styles.js +11 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/ui/Find.js +304 -0
- package/dist/esm/ui/FindReplace.js +100 -0
- package/dist/esm/ui/FindReplaceToolbarButton.js +126 -0
- package/dist/esm/ui/FindReplaceTooltipButton.js +70 -0
- package/dist/esm/ui/Replace.js +171 -0
- package/dist/esm/ui/styles.js +39 -0
- package/dist/esm/utils/array.js +7 -0
- package/dist/esm/utils/batch-decorations.js +304 -0
- package/dist/esm/utils/commands.js +10 -0
- package/dist/esm/utils/index.js +280 -0
- package/dist/types/FindReplaceToolbarButtonWithState.d.ts +4 -0
- package/dist/types/actions.d.ts +64 -0
- package/dist/types/commands-with-analytics.d.ts +27 -0
- package/dist/types/commands.d.ts +12 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/plugin.d.ts +2 -0
- package/dist/types/pm-plugins/keymap.d.ts +4 -0
- package/dist/types/pm-plugins/main.d.ts +5 -0
- package/dist/types/pm-plugins/plugin-factory.d.ts +2 -0
- package/dist/types/pm-plugins/plugin-key.d.ts +3 -0
- package/dist/types/reducer.d.ts +4 -0
- package/dist/types/styles.d.ts +3 -0
- package/dist/types/types.d.ts +76 -0
- package/dist/types/ui/Find.d.ts +71 -0
- package/dist/types/ui/FindReplace.d.ts +43 -0
- package/dist/types/ui/FindReplaceToolbarButton.d.ts +21 -0
- package/dist/types/ui/FindReplaceTooltipButton.d.ts +18 -0
- package/dist/types/ui/Replace.d.ts +27 -0
- package/dist/types/ui/styles.d.ts +6 -0
- package/dist/types/utils/array.d.ts +1 -0
- package/dist/types/utils/batch-decorations.d.ts +36 -0
- package/dist/types/utils/commands.d.ts +2 -0
- package/dist/types/utils/index.d.ts +49 -0
- package/dist/types-ts4.5/FindReplaceToolbarButtonWithState.d.ts +4 -0
- package/dist/types-ts4.5/actions.d.ts +64 -0
- package/dist/types-ts4.5/commands-with-analytics.d.ts +27 -0
- package/dist/types-ts4.5/commands.d.ts +12 -0
- package/dist/types-ts4.5/index.d.ts +2 -0
- package/dist/types-ts4.5/plugin.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/keymap.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +5 -0
- package/dist/types-ts4.5/pm-plugins/plugin-factory.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/plugin-key.d.ts +3 -0
- package/dist/types-ts4.5/reducer.d.ts +4 -0
- package/dist/types-ts4.5/styles.d.ts +3 -0
- package/dist/types-ts4.5/types.d.ts +76 -0
- package/dist/types-ts4.5/ui/Find.d.ts +71 -0
- package/dist/types-ts4.5/ui/FindReplace.d.ts +43 -0
- package/dist/types-ts4.5/ui/FindReplaceToolbarButton.d.ts +21 -0
- package/dist/types-ts4.5/ui/FindReplaceTooltipButton.d.ts +18 -0
- package/dist/types-ts4.5/ui/Replace.d.ts +27 -0
- package/dist/types-ts4.5/ui/styles.d.ts +6 -0
- package/dist/types-ts4.5/utils/array.d.ts +1 -0
- package/dist/types-ts4.5/utils/batch-decorations.d.ts +36 -0
- package/dist/types-ts4.5/utils/commands.d.ts +2 -0
- package/dist/types-ts4.5/utils/index.d.ts +49 -0
- package/package.json +117 -0
- package/styles/package.json +17 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
import { FindReplaceActionTypes } from './actions';
|
|
4
|
+
import { createCommand, getPluginState } from './pm-plugins/plugin-factory';
|
|
5
|
+
import { createDecoration, findDecorationFromMatch, findMatches, findSearchIndex, getSelectedText, getSelectionForMatch, nextIndex, prevIndex, removeDecorationsFromSet, removeMatchesFromSet } from './utils';
|
|
6
|
+
import batchDecorations from './utils/batch-decorations';
|
|
7
|
+
import { withScrollIntoView } from './utils/commands';
|
|
8
|
+
export var activate = function activate() {
|
|
9
|
+
return createCommand(function (state) {
|
|
10
|
+
var selection = state.selection;
|
|
11
|
+
var findText;
|
|
12
|
+
var matches;
|
|
13
|
+
var index;
|
|
14
|
+
|
|
15
|
+
// if user has selected text and hit cmd-f, set that as the keyword
|
|
16
|
+
if (selection instanceof TextSelection && !selection.empty) {
|
|
17
|
+
findText = getSelectedText(selection);
|
|
18
|
+
var _getPluginState = getPluginState(state),
|
|
19
|
+
shouldMatchCase = _getPluginState.shouldMatchCase;
|
|
20
|
+
matches = findMatches(state.doc, findText, shouldMatchCase);
|
|
21
|
+
index = findSearchIndex(selection.from, matches);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
type: FindReplaceActionTypes.ACTIVATE,
|
|
25
|
+
findText: findText,
|
|
26
|
+
matches: matches,
|
|
27
|
+
index: index
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
export var find = function find(editorView, containerElement, keyword) {
|
|
32
|
+
return withScrollIntoView(createCommand(function (state) {
|
|
33
|
+
var selection = state.selection;
|
|
34
|
+
var _getPluginState2 = getPluginState(state),
|
|
35
|
+
shouldMatchCase = _getPluginState2.shouldMatchCase;
|
|
36
|
+
var matches = keyword !== undefined ? findMatches(state.doc, keyword, shouldMatchCase) : [];
|
|
37
|
+
var index = findSearchIndex(selection.from, matches);
|
|
38
|
+
|
|
39
|
+
// we can't just apply all the decorations to highlight the search results at once
|
|
40
|
+
// as if there are a lot ProseMirror cries :'(
|
|
41
|
+
batchDecorations.applyAllSearchDecorations(editorView, containerElement, function (decorations) {
|
|
42
|
+
return addDecorations(decorations)(editorView.state, editorView.dispatch);
|
|
43
|
+
}, function (decorations) {
|
|
44
|
+
return removeDecorations(decorations)(editorView.state, editorView.dispatch);
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
type: FindReplaceActionTypes.FIND,
|
|
48
|
+
findText: keyword || '',
|
|
49
|
+
matches: matches,
|
|
50
|
+
index: index
|
|
51
|
+
};
|
|
52
|
+
}, function (tr, state) {
|
|
53
|
+
var selection = state.selection;
|
|
54
|
+
var _getPluginState3 = getPluginState(state),
|
|
55
|
+
shouldMatchCase = _getPluginState3.shouldMatchCase;
|
|
56
|
+
var matches = keyword !== undefined ? findMatches(state.doc, keyword, shouldMatchCase) : [];
|
|
57
|
+
if (matches.length > 0) {
|
|
58
|
+
var index = findSearchIndex(selection.from, matches);
|
|
59
|
+
return tr.setSelection(getSelectionForMatch(tr.selection, tr.doc, index, matches));
|
|
60
|
+
}
|
|
61
|
+
return tr;
|
|
62
|
+
}));
|
|
63
|
+
};
|
|
64
|
+
export var findNext = function findNext() {
|
|
65
|
+
return withScrollIntoView(createCommand(function (state) {
|
|
66
|
+
return findInDirection(state, 'next');
|
|
67
|
+
}, function (tr, state) {
|
|
68
|
+
var _getPluginState4 = getPluginState(state),
|
|
69
|
+
matches = _getPluginState4.matches,
|
|
70
|
+
index = _getPluginState4.index;
|
|
71
|
+
// can't use index from plugin state because if the cursor has moved, it will still be the
|
|
72
|
+
// OLD index (the find next operation should look for the first match forward starting
|
|
73
|
+
// from the current cursor position)
|
|
74
|
+
var searchIndex = findSearchIndex(state.selection.from, matches);
|
|
75
|
+
if (searchIndex === index) {
|
|
76
|
+
// cursor has not moved, so we just want to find the next in matches array
|
|
77
|
+
searchIndex = nextIndex(searchIndex, matches.length);
|
|
78
|
+
}
|
|
79
|
+
return tr.setSelection(getSelectionForMatch(tr.selection, tr.doc, searchIndex, matches));
|
|
80
|
+
}));
|
|
81
|
+
};
|
|
82
|
+
export var findPrevious = function findPrevious() {
|
|
83
|
+
return withScrollIntoView(createCommand(function (state) {
|
|
84
|
+
return findInDirection(state, 'previous');
|
|
85
|
+
}, function (tr, state) {
|
|
86
|
+
var _getPluginState5 = getPluginState(state),
|
|
87
|
+
matches = _getPluginState5.matches;
|
|
88
|
+
// can't use index from plugin state because if the cursor has moved, it will still be the
|
|
89
|
+
// OLD index (the find prev operation should look for the first match backward starting
|
|
90
|
+
// from the current cursor position)
|
|
91
|
+
var searchIndex = findSearchIndex(state.selection.from, matches, true);
|
|
92
|
+
return tr.setSelection(getSelectionForMatch(tr.selection, tr.doc, searchIndex, matches));
|
|
93
|
+
}));
|
|
94
|
+
};
|
|
95
|
+
var findInDirection = function findInDirection(state, dir) {
|
|
96
|
+
var pluginState = getPluginState(state);
|
|
97
|
+
var matches = pluginState.matches,
|
|
98
|
+
findText = pluginState.findText;
|
|
99
|
+
var decorationSet = pluginState.decorationSet,
|
|
100
|
+
index = pluginState.index;
|
|
101
|
+
if (findText) {
|
|
102
|
+
var searchIndex = findSearchIndex(state.selection.from, matches, dir === 'previous');
|
|
103
|
+
// compare index from plugin state and index of first match forward from cursor position
|
|
104
|
+
if (index === searchIndex) {
|
|
105
|
+
// normal case, cycling through matches
|
|
106
|
+
index = dir === 'next' ? nextIndex(index, matches.length) : prevIndex(index, matches.length);
|
|
107
|
+
} else {
|
|
108
|
+
// cursor has moved
|
|
109
|
+
index = searchIndex;
|
|
110
|
+
}
|
|
111
|
+
decorationSet = updateSelectedHighlight(state, index);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
type: dir === 'next' ? FindReplaceActionTypes.FIND_NEXT : FindReplaceActionTypes.FIND_PREVIOUS,
|
|
115
|
+
index: index,
|
|
116
|
+
decorationSet: decorationSet
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
export var replace = function replace(replaceText) {
|
|
120
|
+
return withScrollIntoView(createCommand(function (state) {
|
|
121
|
+
var pluginState = getPluginState(state);
|
|
122
|
+
var findText = pluginState.findText;
|
|
123
|
+
var decorationSet = pluginState.decorationSet,
|
|
124
|
+
matches = pluginState.matches,
|
|
125
|
+
index = pluginState.index;
|
|
126
|
+
decorationSet = updateSelectedHighlight(state, nextIndex(index, matches.length));
|
|
127
|
+
if (replaceText.toLowerCase().indexOf(findText.toLowerCase()) === -1) {
|
|
128
|
+
decorationSet = removeMatchesFromSet(decorationSet, [matches[index]], state.doc);
|
|
129
|
+
matches.splice(index, 1);
|
|
130
|
+
if (index > matches.length - 1) {
|
|
131
|
+
index = 0;
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
index = nextIndex(index, matches.length);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
type: FindReplaceActionTypes.REPLACE,
|
|
138
|
+
replaceText: replaceText,
|
|
139
|
+
decorationSet: decorationSet,
|
|
140
|
+
matches: matches,
|
|
141
|
+
index: index
|
|
142
|
+
};
|
|
143
|
+
}, function (tr, state) {
|
|
144
|
+
var _getPluginState6 = getPluginState(state),
|
|
145
|
+
matches = _getPluginState6.matches,
|
|
146
|
+
index = _getPluginState6.index,
|
|
147
|
+
findText = _getPluginState6.findText;
|
|
148
|
+
if (matches[index]) {
|
|
149
|
+
var _matches$index = matches[index],
|
|
150
|
+
start = _matches$index.start,
|
|
151
|
+
end = _matches$index.end;
|
|
152
|
+
var newIndex = nextIndex(index, matches.length);
|
|
153
|
+
tr.insertText(replaceText, start, end).setSelection(getSelectionForMatch(tr.selection, tr.doc, newIndex, matches, newIndex === 0 ? 0 : replaceText.length - findText.length));
|
|
154
|
+
}
|
|
155
|
+
return tr;
|
|
156
|
+
}));
|
|
157
|
+
};
|
|
158
|
+
export var replaceAll = function replaceAll(replaceText) {
|
|
159
|
+
return createCommand({
|
|
160
|
+
type: FindReplaceActionTypes.REPLACE_ALL,
|
|
161
|
+
replaceText: replaceText,
|
|
162
|
+
decorationSet: DecorationSet.empty,
|
|
163
|
+
matches: [],
|
|
164
|
+
index: 0
|
|
165
|
+
}, function (tr, state) {
|
|
166
|
+
var pluginState = getPluginState(state);
|
|
167
|
+
pluginState.matches.forEach(function (match) {
|
|
168
|
+
tr.insertText(replaceText, tr.mapping.map(match.start), tr.mapping.map(match.end));
|
|
169
|
+
});
|
|
170
|
+
tr.setMeta('scrollIntoView', false);
|
|
171
|
+
return tr;
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
export var addDecorations = function addDecorations(decorations) {
|
|
175
|
+
return createCommand(function (state) {
|
|
176
|
+
var _getPluginState7 = getPluginState(state),
|
|
177
|
+
decorationSet = _getPluginState7.decorationSet;
|
|
178
|
+
return {
|
|
179
|
+
type: FindReplaceActionTypes.UPDATE_DECORATIONS,
|
|
180
|
+
decorationSet: decorationSet.add(state.doc, decorations)
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
export var removeDecorations = function removeDecorations(decorations) {
|
|
185
|
+
return createCommand(function (state) {
|
|
186
|
+
var _getPluginState8 = getPluginState(state),
|
|
187
|
+
decorationSet = _getPluginState8.decorationSet;
|
|
188
|
+
return {
|
|
189
|
+
type: FindReplaceActionTypes.UPDATE_DECORATIONS,
|
|
190
|
+
decorationSet: removeDecorationsFromSet(decorationSet, decorations, state.doc)
|
|
191
|
+
};
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
export var cancelSearch = function cancelSearch() {
|
|
195
|
+
return createCommand(function () {
|
|
196
|
+
batchDecorations.stop();
|
|
197
|
+
return {
|
|
198
|
+
type: FindReplaceActionTypes.CANCEL
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
};
|
|
202
|
+
export var blur = function blur() {
|
|
203
|
+
return createCommand({
|
|
204
|
+
type: FindReplaceActionTypes.BLUR
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
export var toggleMatchCase = function toggleMatchCase() {
|
|
208
|
+
return createCommand({
|
|
209
|
+
type: FindReplaceActionTypes.TOGGLE_MATCH_CASE
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
var updateSelectedHighlight = function updateSelectedHighlight(state, nextSelectedIndex) {
|
|
213
|
+
var _getPluginState9 = getPluginState(state),
|
|
214
|
+
decorationSet = _getPluginState9.decorationSet,
|
|
215
|
+
index = _getPluginState9.index,
|
|
216
|
+
matches = _getPluginState9.matches;
|
|
217
|
+
var currentSelectedMatch = matches[index];
|
|
218
|
+
var nextSelectedMatch = matches[nextSelectedIndex];
|
|
219
|
+
if (index === nextSelectedIndex) {
|
|
220
|
+
return decorationSet;
|
|
221
|
+
}
|
|
222
|
+
var currentSelectedDecoration = findDecorationFromMatch(decorationSet, currentSelectedMatch);
|
|
223
|
+
var nextSelectedDecoration = findDecorationFromMatch(decorationSet, nextSelectedMatch);
|
|
224
|
+
|
|
225
|
+
// Update decorations so the current selected match becomes a normal match
|
|
226
|
+
// and the next selected gets the selected styling
|
|
227
|
+
var decorationsToRemove = [];
|
|
228
|
+
if (currentSelectedDecoration) {
|
|
229
|
+
decorationsToRemove.push(currentSelectedDecoration);
|
|
230
|
+
}
|
|
231
|
+
if (nextSelectedDecoration) {
|
|
232
|
+
decorationsToRemove.push(nextSelectedDecoration);
|
|
233
|
+
}
|
|
234
|
+
if (decorationsToRemove.length > 0) {
|
|
235
|
+
// removeDecorationsFromSet depends on decorations being pre-sorted
|
|
236
|
+
decorationsToRemove.sort(function (a, b) {
|
|
237
|
+
return a.from < b.from ? -1 : 1;
|
|
238
|
+
});
|
|
239
|
+
decorationSet = removeDecorationsFromSet(decorationSet, decorationsToRemove, state.doc);
|
|
240
|
+
}
|
|
241
|
+
if (currentSelectedMatch) {
|
|
242
|
+
decorationSet = decorationSet.add(state.doc, [createDecoration(currentSelectedMatch.start, currentSelectedMatch.end)]);
|
|
243
|
+
}
|
|
244
|
+
if (nextSelectedMatch) {
|
|
245
|
+
decorationSet = decorationSet.add(state.doc, [createDecoration(nextSelectedMatch.start, nextSelectedMatch.end, true)]);
|
|
246
|
+
}
|
|
247
|
+
return decorationSet;
|
|
248
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { findReplacePlugin } from './plugin';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import FindReplaceToolbarButtonWithState from './FindReplaceToolbarButtonWithState';
|
|
3
|
+
import keymapPlugin from './pm-plugins/keymap';
|
|
4
|
+
import { createPlugin } from './pm-plugins/main';
|
|
5
|
+
import { findReplacePluginKey } from './pm-plugins/plugin-key';
|
|
6
|
+
export var findReplacePlugin = function findReplacePlugin(_ref) {
|
|
7
|
+
var _api$featureFlags;
|
|
8
|
+
var props = _ref.config,
|
|
9
|
+
api = _ref.api;
|
|
10
|
+
var featureFlags = (api === null || api === void 0 || (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
|
|
11
|
+
return {
|
|
12
|
+
name: 'findReplace',
|
|
13
|
+
pmPlugins: function pmPlugins() {
|
|
14
|
+
return [{
|
|
15
|
+
name: 'findReplace',
|
|
16
|
+
plugin: function plugin(_ref2) {
|
|
17
|
+
var dispatch = _ref2.dispatch;
|
|
18
|
+
return createPlugin(dispatch);
|
|
19
|
+
}
|
|
20
|
+
}, {
|
|
21
|
+
name: 'findReplaceKeymap',
|
|
22
|
+
plugin: function plugin() {
|
|
23
|
+
var _api$analytics;
|
|
24
|
+
return keymapPlugin(api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions);
|
|
25
|
+
}
|
|
26
|
+
}];
|
|
27
|
+
},
|
|
28
|
+
getSharedState: function getSharedState(editorState) {
|
|
29
|
+
if (!editorState) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
return findReplacePluginKey.getState(editorState) || undefined;
|
|
33
|
+
},
|
|
34
|
+
actions: {
|
|
35
|
+
getToolbarButton: function getToolbarButton(_ref3) {
|
|
36
|
+
var popupsBoundariesElement = _ref3.popupsBoundariesElement,
|
|
37
|
+
popupsMountPoint = _ref3.popupsMountPoint,
|
|
38
|
+
popupsScrollableElement = _ref3.popupsScrollableElement,
|
|
39
|
+
editorView = _ref3.editorView,
|
|
40
|
+
containerElement = _ref3.containerElement,
|
|
41
|
+
dispatchAnalyticsEvent = _ref3.dispatchAnalyticsEvent,
|
|
42
|
+
isToolbarReducedSpacing = _ref3.isToolbarReducedSpacing;
|
|
43
|
+
return /*#__PURE__*/React.createElement(FindReplaceToolbarButtonWithState, {
|
|
44
|
+
popupsBoundariesElement: popupsBoundariesElement,
|
|
45
|
+
popupsMountPoint: popupsMountPoint,
|
|
46
|
+
popupsScrollableElement: popupsScrollableElement,
|
|
47
|
+
editorView: editorView,
|
|
48
|
+
containerElement: containerElement,
|
|
49
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent
|
|
50
|
+
// `allowMatchCase` comes through the preset, but not the feature flags
|
|
51
|
+
// prop with the `ComposableEditor` - grab the FFs from the editor API
|
|
52
|
+
// instead until we clean this up.
|
|
53
|
+
,
|
|
54
|
+
featureFlags: featureFlags,
|
|
55
|
+
isToolbarReducedSpacing: isToolbarReducedSpacing,
|
|
56
|
+
api: api
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
primaryToolbarComponent: function primaryToolbarComponent(_ref4) {
|
|
61
|
+
var popupsBoundariesElement = _ref4.popupsBoundariesElement,
|
|
62
|
+
popupsMountPoint = _ref4.popupsMountPoint,
|
|
63
|
+
popupsScrollableElement = _ref4.popupsScrollableElement,
|
|
64
|
+
isToolbarReducedSpacing = _ref4.isToolbarReducedSpacing,
|
|
65
|
+
editorView = _ref4.editorView,
|
|
66
|
+
containerElement = _ref4.containerElement,
|
|
67
|
+
dispatchAnalyticsEvent = _ref4.dispatchAnalyticsEvent;
|
|
68
|
+
if (props !== null && props !== void 0 && props.twoLineEditorToolbar) {
|
|
69
|
+
return null;
|
|
70
|
+
} else {
|
|
71
|
+
return /*#__PURE__*/React.createElement(FindReplaceToolbarButtonWithState, {
|
|
72
|
+
popupsBoundariesElement: popupsBoundariesElement,
|
|
73
|
+
popupsMountPoint: popupsMountPoint,
|
|
74
|
+
popupsScrollableElement: popupsScrollableElement,
|
|
75
|
+
isToolbarReducedSpacing: isToolbarReducedSpacing,
|
|
76
|
+
editorView: editorView,
|
|
77
|
+
containerElement: containerElement,
|
|
78
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
79
|
+
takeFullWidth: props === null || props === void 0 ? void 0 : props.takeFullWidth,
|
|
80
|
+
featureFlags: featureFlags,
|
|
81
|
+
api: api
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TRIGGER_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { bindKeymapWithCommand, find as findKeymap } from '@atlaskit/editor-common/keymaps';
|
|
3
|
+
import { keymap } from '@atlaskit/editor-prosemirror/keymap';
|
|
4
|
+
import { activateWithAnalytics } from '../commands-with-analytics';
|
|
5
|
+
var activateFindReplace = function activateFindReplace(editorAnalyticsAPI) {
|
|
6
|
+
return function (state, dispatch) {
|
|
7
|
+
activateWithAnalytics(editorAnalyticsAPI)({
|
|
8
|
+
triggerMethod: TRIGGER_METHOD.SHORTCUT
|
|
9
|
+
})(state, dispatch);
|
|
10
|
+
return true;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
var keymapPlugin = function keymapPlugin(editorAnalyticsAPI) {
|
|
14
|
+
var list = {};
|
|
15
|
+
bindKeymapWithCommand(findKeymap.common, activateFindReplace(editorAnalyticsAPI), list);
|
|
16
|
+
return keymap(list);
|
|
17
|
+
};
|
|
18
|
+
export default keymapPlugin;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
import { createPluginState, getPluginState } from './plugin-factory';
|
|
4
|
+
import { findReplacePluginKey } from './plugin-key';
|
|
5
|
+
export var initialState = {
|
|
6
|
+
isActive: false,
|
|
7
|
+
shouldFocus: false,
|
|
8
|
+
findText: '',
|
|
9
|
+
replaceText: '',
|
|
10
|
+
index: 0,
|
|
11
|
+
matches: [],
|
|
12
|
+
decorationSet: DecorationSet.empty,
|
|
13
|
+
shouldMatchCase: false
|
|
14
|
+
};
|
|
15
|
+
export var createPlugin = function createPlugin(dispatch) {
|
|
16
|
+
return new SafePlugin({
|
|
17
|
+
key: findReplacePluginKey,
|
|
18
|
+
state: createPluginState(dispatch, function () {
|
|
19
|
+
return initialState;
|
|
20
|
+
}),
|
|
21
|
+
props: {
|
|
22
|
+
decorations: function decorations(state) {
|
|
23
|
+
var _getPluginState = getPluginState(state),
|
|
24
|
+
isActive = _getPluginState.isActive,
|
|
25
|
+
findText = _getPluginState.findText,
|
|
26
|
+
decorationSet = _getPluginState.decorationSet;
|
|
27
|
+
if (isActive && findText) {
|
|
28
|
+
return decorationSet;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
|
+
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; }
|
|
4
|
+
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; }
|
|
5
|
+
import { pluginFactory, stepHasSlice } from '@atlaskit/editor-common/utils';
|
|
6
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
7
|
+
import reducer from '../reducer';
|
|
8
|
+
import { createDecorations, findDecorationFromMatch, findMatches, findSearchIndex, isMatchAffectedByStep, removeDecorationsFromSet, removeMatchesFromSet } from '../utils';
|
|
9
|
+
import { findUniqueItemsIn } from '../utils/array'; // TODO: move into index export
|
|
10
|
+
|
|
11
|
+
import { initialState } from './main';
|
|
12
|
+
import { findReplacePluginKey } from './plugin-key';
|
|
13
|
+
var handleDocChanged = function handleDocChanged(tr, pluginState) {
|
|
14
|
+
var isActive = pluginState.isActive,
|
|
15
|
+
findText = pluginState.findText;
|
|
16
|
+
if (!isActive || !findText) {
|
|
17
|
+
return pluginState;
|
|
18
|
+
}
|
|
19
|
+
if (!tr.steps.find(stepHasSlice)) {
|
|
20
|
+
return pluginState;
|
|
21
|
+
}
|
|
22
|
+
var index = pluginState.index,
|
|
23
|
+
decorationSet = pluginState.decorationSet,
|
|
24
|
+
matches = pluginState.matches,
|
|
25
|
+
shouldMatchCase = pluginState.shouldMatchCase;
|
|
26
|
+
var newMatches = findMatches(tr.doc, findText, shouldMatchCase);
|
|
27
|
+
decorationSet = decorationSet.map(tr.mapping, tr.doc);
|
|
28
|
+
var numDecorations = decorationSet.find().length;
|
|
29
|
+
var mappedMatches = matches.map(function (match) {
|
|
30
|
+
return {
|
|
31
|
+
start: tr.mapping.map(match.start),
|
|
32
|
+
end: tr.mapping.map(match.end)
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
var matchesToAdd = [];
|
|
36
|
+
var matchesToDelete = [];
|
|
37
|
+
if (newMatches.length > 0 && numDecorations === 0) {
|
|
38
|
+
matchesToAdd = newMatches;
|
|
39
|
+
} else if (newMatches.length === 0 && numDecorations > 0) {
|
|
40
|
+
decorationSet = DecorationSet.empty;
|
|
41
|
+
} else if (newMatches.length > 0 || numDecorations > 0) {
|
|
42
|
+
// go through tr steps and find any new matches from user adding content or
|
|
43
|
+
// any dead matches from user deleting content
|
|
44
|
+
tr.steps.forEach(function (step) {
|
|
45
|
+
if (stepHasSlice(step)) {
|
|
46
|
+
// add all matches that are between the affected positions and don't already have
|
|
47
|
+
// corresponding decorations
|
|
48
|
+
matchesToAdd = [].concat(_toConsumableArray(matchesToAdd), _toConsumableArray(newMatches.filter(function (match) {
|
|
49
|
+
return isMatchAffectedByStep(match, step, tr) && !findDecorationFromMatch(decorationSet, match);
|
|
50
|
+
})));
|
|
51
|
+
|
|
52
|
+
// delete any matches that are missing from the newMatches array and have a
|
|
53
|
+
// corresponding decoration
|
|
54
|
+
matchesToDelete = [].concat(_toConsumableArray(matchesToDelete), _toConsumableArray(findUniqueItemsIn(mappedMatches.filter(function (match) {
|
|
55
|
+
return isMatchAffectedByStep(match, step, tr) && !!findDecorationFromMatch(decorationSet, match);
|
|
56
|
+
}), newMatches, function (firstMatch, secondMatch) {
|
|
57
|
+
return firstMatch.start === secondMatch.start && firstMatch.end === secondMatch.end;
|
|
58
|
+
})));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// update decorations if matches changed following document update
|
|
64
|
+
if (matchesToDelete.length > 0) {
|
|
65
|
+
var decorationsToDelete = matchesToDelete.reduce(function (decorations, match) {
|
|
66
|
+
return [].concat(_toConsumableArray(decorations), _toConsumableArray(decorationSet.find(match.start, match.end)));
|
|
67
|
+
}, []);
|
|
68
|
+
decorationSet = removeDecorationsFromSet(decorationSet, decorationsToDelete, tr.doc);
|
|
69
|
+
}
|
|
70
|
+
if (matchesToAdd.length > 0) {
|
|
71
|
+
decorationSet = decorationSet.add(tr.doc, createDecorations(tr.selection.from, matchesToAdd));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// update selected match if it has changed
|
|
75
|
+
var newIndex = index;
|
|
76
|
+
var selectedMatch = mappedMatches[index];
|
|
77
|
+
if (selectedMatch) {
|
|
78
|
+
newIndex = newMatches.findIndex(function (match) {
|
|
79
|
+
return match.start === selectedMatch.start;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (newIndex === undefined || newIndex === -1) {
|
|
83
|
+
newIndex = findSearchIndex(tr.selection.from, newMatches);
|
|
84
|
+
}
|
|
85
|
+
var newSelectedMatch = newMatches[newIndex];
|
|
86
|
+
decorationSet = removeMatchesFromSet(decorationSet, [selectedMatch, newSelectedMatch], tr.doc);
|
|
87
|
+
if (newSelectedMatch) {
|
|
88
|
+
decorationSet = decorationSet.add(tr.doc, createDecorations(0, [newSelectedMatch]));
|
|
89
|
+
}
|
|
90
|
+
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
91
|
+
matches: newMatches,
|
|
92
|
+
index: newIndex,
|
|
93
|
+
decorationSet: decorationSet
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
var _pluginFactory = pluginFactory(findReplacePluginKey, reducer(function () {
|
|
97
|
+
return initialState;
|
|
98
|
+
}), {
|
|
99
|
+
onDocChanged: handleDocChanged
|
|
100
|
+
}),
|
|
101
|
+
createCommand = _pluginFactory.createCommand,
|
|
102
|
+
getPluginState = _pluginFactory.getPluginState,
|
|
103
|
+
createPluginState = _pluginFactory.createPluginState;
|
|
104
|
+
export { createCommand, getPluginState, createPluginState };
|
|
@@ -0,0 +1,54 @@
|
|
|
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 { FindReplaceActionTypes } from './actions';
|
|
5
|
+
var reducer = function reducer(getInitialState) {
|
|
6
|
+
return function (state, action) {
|
|
7
|
+
switch (action.type) {
|
|
8
|
+
case FindReplaceActionTypes.ACTIVATE:
|
|
9
|
+
case FindReplaceActionTypes.FIND:
|
|
10
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
11
|
+
isActive: true,
|
|
12
|
+
shouldFocus: action.type === FindReplaceActionTypes.ACTIVATE,
|
|
13
|
+
findText: action.findText !== undefined ? action.findText : state.findText,
|
|
14
|
+
matches: action.matches || state.matches,
|
|
15
|
+
index: action.index !== undefined ? action.index : state.index
|
|
16
|
+
});
|
|
17
|
+
case FindReplaceActionTypes.UPDATE_DECORATIONS:
|
|
18
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
19
|
+
decorationSet: action.decorationSet
|
|
20
|
+
});
|
|
21
|
+
case FindReplaceActionTypes.FIND_NEXT:
|
|
22
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
23
|
+
index: action.index,
|
|
24
|
+
decorationSet: action.decorationSet
|
|
25
|
+
});
|
|
26
|
+
case FindReplaceActionTypes.FIND_PREVIOUS:
|
|
27
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
28
|
+
index: action.index,
|
|
29
|
+
decorationSet: action.decorationSet
|
|
30
|
+
});
|
|
31
|
+
case FindReplaceActionTypes.REPLACE:
|
|
32
|
+
case FindReplaceActionTypes.REPLACE_ALL:
|
|
33
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
34
|
+
replaceText: action.replaceText,
|
|
35
|
+
decorationSet: action.decorationSet,
|
|
36
|
+
matches: action.matches,
|
|
37
|
+
index: action.index
|
|
38
|
+
});
|
|
39
|
+
case FindReplaceActionTypes.CANCEL:
|
|
40
|
+
return getInitialState();
|
|
41
|
+
case FindReplaceActionTypes.BLUR:
|
|
42
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
43
|
+
shouldFocus: false
|
|
44
|
+
});
|
|
45
|
+
case FindReplaceActionTypes.TOGGLE_MATCH_CASE:
|
|
46
|
+
return _objectSpread(_objectSpread({}, state), {}, {
|
|
47
|
+
shouldMatchCase: !state.shouldMatchCase
|
|
48
|
+
});
|
|
49
|
+
default:
|
|
50
|
+
return state;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export default reducer;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
|
|
2
|
+
var _templateObject;
|
|
3
|
+
/* eslint-disable @atlaskit/design-system/ensure-design-token-usage/preview */
|
|
4
|
+
/* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
|
|
5
|
+
|
|
6
|
+
// TODO: https://product-fabric.atlassian.net/browse/DSP-4290
|
|
7
|
+
import { css } from '@emotion/react';
|
|
8
|
+
import { B200, B75 } from '@atlaskit/theme/colors';
|
|
9
|
+
export var searchMatchClass = 'search-match';
|
|
10
|
+
export var selectedSearchMatchClass = 'selected-search-match';
|
|
11
|
+
export var findReplaceStyles = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n .", " {\n background-color: ", ";\n }\n\n .", " {\n background-color: ", ";\n color: white;\n }\n"])), searchMatchClass, B75, selectedSearchMatchClass, B200);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|