@opensumi/ide-search 2.21.13 → 2.22.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 (103) hide show
  1. package/lib/browser/index.d.ts +1 -2
  2. package/lib/browser/index.d.ts.map +1 -1
  3. package/lib/browser/index.js +14 -1
  4. package/lib/browser/index.js.map +1 -1
  5. package/lib/browser/replace.d.ts +3 -2
  6. package/lib/browser/replace.d.ts.map +1 -1
  7. package/lib/browser/replace.js +34 -15
  8. package/lib/browser/replace.js.map +1 -1
  9. package/lib/browser/search-contextkey.d.ts +6 -8
  10. package/lib/browser/search-contextkey.d.ts.map +1 -1
  11. package/lib/browser/search-contextkey.js +11 -13
  12. package/lib/browser/search-contextkey.js.map +1 -1
  13. package/lib/browser/search-preferences.d.ts +1 -1
  14. package/lib/browser/search-preferences.d.ts.map +1 -1
  15. package/lib/browser/search-preferences.js +5 -5
  16. package/lib/browser/search-preferences.js.map +1 -1
  17. package/lib/browser/search.contribution.d.ts +9 -11
  18. package/lib/browser/search.contribution.d.ts.map +1 -1
  19. package/lib/browser/search.contribution.js +126 -80
  20. package/lib/browser/search.contribution.js.map +1 -1
  21. package/lib/browser/search.input.widget.d.ts +3 -5
  22. package/lib/browser/search.input.widget.d.ts.map +1 -1
  23. package/lib/browser/search.input.widget.js +12 -13
  24. package/lib/browser/search.input.widget.js.map +1 -1
  25. package/lib/browser/search.module.less +23 -49
  26. package/lib/browser/search.replace.widget.d.ts +4 -8
  27. package/lib/browser/search.replace.widget.d.ts.map +1 -1
  28. package/lib/browser/search.replace.widget.js +5 -5
  29. package/lib/browser/search.replace.widget.js.map +1 -1
  30. package/lib/browser/search.rules.widget.d.ts.map +1 -1
  31. package/lib/browser/search.rules.widget.js +6 -6
  32. package/lib/browser/search.rules.widget.js.map +1 -1
  33. package/lib/browser/search.service.d.ts +43 -36
  34. package/lib/browser/search.service.d.ts.map +1 -1
  35. package/lib/browser/search.service.js +127 -187
  36. package/lib/browser/search.service.js.map +1 -1
  37. package/lib/browser/search.view.d.ts +14 -3
  38. package/lib/browser/search.view.d.ts.map +1 -1
  39. package/lib/browser/search.view.js +132 -50
  40. package/lib/browser/search.view.js.map +1 -1
  41. package/lib/browser/tree/search-node.d.ts +22 -0
  42. package/lib/browser/tree/search-node.d.ts.map +1 -0
  43. package/lib/browser/tree/search-node.js +155 -0
  44. package/lib/browser/tree/search-node.js.map +1 -0
  45. package/lib/browser/tree/search-tree.service.d.ts +56 -0
  46. package/lib/browser/tree/search-tree.service.d.ts.map +1 -0
  47. package/lib/browser/tree/search-tree.service.js +277 -0
  48. package/lib/browser/tree/search-tree.service.js.map +1 -0
  49. package/lib/browser/tree/search-tree.view.d.ts +21 -0
  50. package/lib/browser/tree/search-tree.view.d.ts.map +1 -0
  51. package/lib/browser/tree/search-tree.view.js +89 -0
  52. package/lib/browser/tree/search-tree.view.js.map +1 -0
  53. package/lib/browser/tree/tree-model.service.d.ts +59 -0
  54. package/lib/browser/tree/tree-model.service.d.ts.map +1 -0
  55. package/lib/browser/tree/tree-model.service.js +292 -0
  56. package/lib/browser/tree/tree-model.service.js.map +1 -0
  57. package/lib/browser/tree/tree-node.defined.d.ts +32 -0
  58. package/lib/browser/tree/tree-node.defined.d.ts.map +1 -0
  59. package/lib/browser/tree/tree-node.defined.js +55 -0
  60. package/lib/browser/tree/tree-node.defined.js.map +1 -0
  61. package/lib/browser/tree/tree-node.module.less +175 -0
  62. package/lib/common/content-search.d.ts +34 -16
  63. package/lib/common/content-search.d.ts.map +1 -1
  64. package/lib/common/content-search.js +2 -6
  65. package/lib/common/content-search.js.map +1 -1
  66. package/lib/node/content-search.service.d.ts +3 -5
  67. package/lib/node/content-search.service.d.ts.map +1 -1
  68. package/lib/node/content-search.service.js +3 -4
  69. package/lib/node/content-search.service.js.map +1 -1
  70. package/lib/node/index.js.map +1 -1
  71. package/package.json +21 -20
  72. package/src/browser/index.ts +42 -0
  73. package/src/browser/replace.ts +119 -0
  74. package/src/browser/search-contextkey.ts +30 -0
  75. package/src/browser/search-history.ts +113 -0
  76. package/src/browser/search-preferences.ts +78 -0
  77. package/src/browser/search-result-collection.ts +75 -0
  78. package/src/browser/search.contribution.ts +347 -0
  79. package/src/browser/search.input.widget.tsx +129 -0
  80. package/src/browser/search.module.less +352 -0
  81. package/src/browser/search.replace.widget.tsx +38 -0
  82. package/src/browser/search.rules.widget.tsx +204 -0
  83. package/src/browser/search.service.ts +881 -0
  84. package/src/browser/search.view.tsx +282 -0
  85. package/src/browser/tree/search-node.tsx +274 -0
  86. package/src/browser/tree/search-tree.service.ts +323 -0
  87. package/src/browser/tree/search-tree.view.tsx +179 -0
  88. package/src/browser/tree/tree-model.service.ts +338 -0
  89. package/src/browser/tree/tree-node.defined.ts +73 -0
  90. package/src/browser/tree/tree-node.module.less +175 -0
  91. package/src/common/content-search.ts +312 -0
  92. package/src/common/index.ts +1 -0
  93. package/src/index.ts +1 -0
  94. package/src/node/content-search.service.ts +297 -0
  95. package/src/node/index.ts +23 -0
  96. package/lib/browser/search-tree.service.d.ts +0 -76
  97. package/lib/browser/search-tree.service.d.ts.map +0 -1
  98. package/lib/browser/search-tree.service.js +0 -587
  99. package/lib/browser/search-tree.service.js.map +0 -1
  100. package/lib/browser/search-tree.view.d.ts +0 -22
  101. package/lib/browser/search-tree.view.d.ts.map +0 -1
  102. package/lib/browser/search-tree.view.js +0 -102
  103. package/lib/browser/search-tree.view.js.map +0 -1
@@ -0,0 +1,75 @@
1
+ import { SendClientResult, SEARCH_STATE } from '../common';
2
+
3
+ /**
4
+ * 用于收集多个搜索结果后合并,减少更新视图频率
5
+ */
6
+ export class SearchResultCollection {
7
+ list: SendClientResult[] = [];
8
+
9
+ maxLength = 5;
10
+
11
+ pushAndGetResultList(result: SendClientResult) {
12
+ const { id, data, searchState } = result;
13
+ const outResultList: SendClientResult[] = [];
14
+
15
+ if (searchState === SEARCH_STATE.error || searchState === SEARCH_STATE.done) {
16
+ // 搜索结束或出错,把缓存搜索结果抛出
17
+ const tempResult = this.getTempResult();
18
+ if (tempResult) {
19
+ outResultList.push(tempResult);
20
+ }
21
+ outResultList.push(result);
22
+ return outResultList;
23
+ }
24
+
25
+ if (data.length < 1) {
26
+ // 其他数据,原样抛出
27
+ outResultList.push(result);
28
+ return outResultList;
29
+ }
30
+
31
+ if (this.list.length > 0) {
32
+ if (id === this.list[0].id) {
33
+ // 同一个搜索的搜索结果
34
+ this.pushTempResult(result);
35
+ } else {
36
+ // 不同搜索的搜索结果
37
+ const tempResult = this.getTempResult();
38
+ if (tempResult) {
39
+ outResultList.push(tempResult);
40
+ }
41
+ this.pushTempResult(result);
42
+ }
43
+ } else {
44
+ this.pushTempResult(result);
45
+ }
46
+ if (this.list.length >= this.maxLength) {
47
+ outResultList.push(this.getTempResult()!);
48
+ }
49
+
50
+ return outResultList;
51
+ }
52
+
53
+ private getTempResult(): SendClientResult | undefined {
54
+ let outResult: SendClientResult | undefined;
55
+
56
+ if (this.list.length < 1) {
57
+ return outResult;
58
+ }
59
+
60
+ this.list.forEach((result: SendClientResult, index) => {
61
+ if (index === 0) {
62
+ return;
63
+ }
64
+ this.list[0].data = this.list[0].data.concat(result.data);
65
+ });
66
+
67
+ outResult = this.list[0];
68
+ this.list = [];
69
+ return outResult;
70
+ }
71
+
72
+ private pushTempResult(result: SendClientResult) {
73
+ this.list.push(result);
74
+ }
75
+ }
@@ -0,0 +1,347 @@
1
+ import { Autowired } from '@opensumi/di';
2
+ import { localize, PreferenceSchema, SEARCH_COMMANDS, IClipboardService } from '@opensumi/ide-core-browser';
3
+ import {
4
+ KeybindingContribution,
5
+ KeybindingRegistry,
6
+ ClientAppContribution,
7
+ ComponentRegistry,
8
+ ComponentContribution,
9
+ PreferenceContribution,
10
+ } from '@opensumi/ide-core-browser';
11
+ import { getIcon } from '@opensumi/ide-core-browser';
12
+ import { SEARCH_CONTAINER_ID } from '@opensumi/ide-core-browser/lib/common/container-id';
13
+ import { SearchInputBoxFocusedKey } from '@opensumi/ide-core-browser/lib/contextkey/search';
14
+ import { ToolbarRegistry, TabBarToolbarContribution } from '@opensumi/ide-core-browser/lib/layout';
15
+ import { MenuId, MenuContribution, IMenuRegistry } from '@opensumi/ide-core-browser/lib/menu/next';
16
+ import {
17
+ CommandContribution,
18
+ CommandRegistry,
19
+ DisposableCollection,
20
+ formatLocalize,
21
+ MessageType,
22
+ } from '@opensumi/ide-core-common';
23
+ import { Domain } from '@opensumi/ide-core-common/lib/di-helper';
24
+ import { IEditorDocumentModelService } from '@opensumi/ide-editor/lib/browser/index';
25
+ import { MainLayoutContribution } from '@opensumi/ide-main-layout';
26
+ import { IMainLayoutService } from '@opensumi/ide-main-layout/lib/common';
27
+ import { IDialogService } from '@opensumi/ide-overlay';
28
+ import { IWorkspaceEditService } from '@opensumi/ide-workspace-edit';
29
+
30
+ import { ContentSearchResult, IContentSearchClientService, OpenSearchCmdOptions } from '../common';
31
+
32
+ import { replaceAll } from './replace';
33
+ import { searchPreferenceSchema } from './search-preferences';
34
+ import { Search } from './search.view';
35
+ import { SearchTreeService } from './tree/search-tree.service';
36
+ import { SearchModelService } from './tree/tree-model.service';
37
+ import { SearchContentNode, SearchFileNode } from './tree/tree-node.defined';
38
+
39
+ @Domain(
40
+ ClientAppContribution,
41
+ CommandContribution,
42
+ KeybindingContribution,
43
+ ComponentContribution,
44
+ TabBarToolbarContribution,
45
+ PreferenceContribution,
46
+ MainLayoutContribution,
47
+ MenuContribution,
48
+ )
49
+ export class SearchContribution
50
+ implements
51
+ CommandContribution,
52
+ KeybindingContribution,
53
+ ComponentContribution,
54
+ TabBarToolbarContribution,
55
+ PreferenceContribution,
56
+ MainLayoutContribution,
57
+ MenuContribution
58
+ {
59
+ @Autowired(IMainLayoutService)
60
+ private readonly mainLayoutService: IMainLayoutService;
61
+
62
+ @Autowired(IContentSearchClientService)
63
+ private readonly searchBrowserService: IContentSearchClientService;
64
+
65
+ @Autowired(SearchTreeService)
66
+ private readonly searchTreeService: SearchTreeService;
67
+
68
+ @Autowired(IEditorDocumentModelService)
69
+ private readonly documentModelManager: IEditorDocumentModelService;
70
+
71
+ @Autowired(IWorkspaceEditService)
72
+ private readonly workspaceEditService: IWorkspaceEditService;
73
+
74
+ @Autowired(IDialogService)
75
+ private readonly dialogService: IDialogService;
76
+
77
+ @Autowired(SearchModelService)
78
+ private readonly searchModelService: SearchModelService;
79
+
80
+ @Autowired(IClipboardService)
81
+ private readonly clipboardService: IClipboardService;
82
+
83
+ schema: PreferenceSchema = searchPreferenceSchema;
84
+
85
+ private readonly toDispose = new DisposableCollection();
86
+
87
+ registerCommands(commands: CommandRegistry): void {
88
+ commands.registerCommand(SEARCH_COMMANDS.OPEN_SEARCH, {
89
+ execute: (options?: OpenSearchCmdOptions) => {
90
+ const bar = this.mainLayoutService.getTabbarHandler(SEARCH_CONTAINER_ID);
91
+ if (!bar) {
92
+ return;
93
+ }
94
+ bar.activate();
95
+ if (options && options.includeValue) {
96
+ this.searchBrowserService.includeValue = options.includeValue;
97
+ this.searchBrowserService.updateUIState({ isDetailOpen: true });
98
+ this.searchBrowserService.search();
99
+ return;
100
+ }
101
+ this.searchBrowserService.searchEditorSelection();
102
+ this.searchBrowserService.focus();
103
+ this.searchBrowserService.search();
104
+ },
105
+ });
106
+ commands.registerCommand(SEARCH_COMMANDS.REFRESH, {
107
+ execute: () => {
108
+ this.searchBrowserService.search();
109
+ },
110
+ });
111
+ commands.registerCommand(SEARCH_COMMANDS.CLEAN, {
112
+ execute: () => {
113
+ this.searchBrowserService.clean();
114
+ },
115
+ });
116
+ commands.registerCommand(SEARCH_COMMANDS.GET_RECENT_SEARCH_WORD, {
117
+ execute: (e) => {
118
+ this.searchBrowserService.setRecentSearchWord();
119
+ },
120
+ });
121
+ commands.registerCommand(SEARCH_COMMANDS.GET_BACK_RECENT_SEARCH_WORD, {
122
+ execute: () => {
123
+ this.searchBrowserService.setBackRecentSearchWord();
124
+ },
125
+ });
126
+ commands.registerCommand(SEARCH_COMMANDS.MENU_REPLACE, {
127
+ execute: async (node: SearchFileNode | SearchContentNode) => {
128
+ if (!SearchFileNode.is(node)) {
129
+ const resultMap: Map<string, ContentSearchResult[]> = new Map();
130
+ resultMap.set(node.resource.toString(), [node.contentResult]);
131
+ await replaceAll(
132
+ this.documentModelManager,
133
+ this.workspaceEditService,
134
+ resultMap,
135
+ this.searchBrowserService.replaceValue,
136
+ this.searchBrowserService.searchValue,
137
+ this.searchBrowserService.UIState.isUseRegexp,
138
+ );
139
+ }
140
+ },
141
+ isVisible: () => !SearchFileNode.is(this.searchModelService.contextMenuNode),
142
+ });
143
+ commands.registerCommand(SEARCH_COMMANDS.MENU_REPLACE_ALL, {
144
+ execute: async (node: SearchFileNode | SearchContentNode) => {
145
+ if (!SearchFileNode.is(node)) {
146
+ return;
147
+ }
148
+ const resultMap: Map<string, ContentSearchResult[]> = new Map();
149
+ if (!node.children) {
150
+ return;
151
+ }
152
+ const contentSearchResult: ContentSearchResult[] = node.children.map(
153
+ (child: SearchContentNode) => child.contentResult,
154
+ );
155
+ const buttons = {
156
+ [localize('search.replace.buttonCancel')]: false,
157
+ [localize('search.replace.buttonOK')]: true,
158
+ };
159
+ const selection = await this.dialogService.open(
160
+ formatLocalize('search.removeAll.occurrences.file.confirmation.message', String(contentSearchResult.length)),
161
+ MessageType.Warning,
162
+ Object.keys(buttons),
163
+ );
164
+ if (selection && !buttons[selection]) {
165
+ return buttons[selection];
166
+ }
167
+ resultMap.set(node.resource.toString(), contentSearchResult);
168
+ await replaceAll(
169
+ this.documentModelManager,
170
+ this.workspaceEditService,
171
+ resultMap,
172
+ this.searchBrowserService.replaceValue,
173
+ this.searchBrowserService.searchValue,
174
+ this.searchBrowserService.UIState.isUseRegexp,
175
+ );
176
+ },
177
+ isVisible: () => !SearchFileNode.is(this.searchModelService.contextMenuNode),
178
+ });
179
+ commands.registerCommand(SEARCH_COMMANDS.MENU_HIDE, {
180
+ execute: (node: SearchFileNode | SearchContentNode) => {
181
+ if (SearchFileNode.is(node)) {
182
+ this.searchBrowserService.resultTotal.fileNum -= 1;
183
+ this.searchBrowserService.resultTotal.resultNum -= node.branchSize;
184
+ this.searchModelService.treeModel.root.unlinkItem(node);
185
+ } else {
186
+ this.searchBrowserService.resultTotal.resultNum -= 1;
187
+ if (node.parent?.children?.length === 1) {
188
+ this.searchBrowserService.resultTotal.fileNum -= 1;
189
+ this.searchModelService.treeModel.root.unlinkItem(node.parent);
190
+ }
191
+ (node.parent as SearchFileNode).unlinkItem(node);
192
+ }
193
+ this.searchBrowserService.fireTitleChange();
194
+ },
195
+ });
196
+ commands.registerCommand(SEARCH_COMMANDS.MENU_COPY, {
197
+ execute: (node: SearchFileNode | SearchContentNode) => {
198
+ if (!SearchFileNode.is(node)) {
199
+ const result = node.contentResult;
200
+ this.clipboardService.writeText(`${result.line},${result.matchStart}: ${result.renderLineText}`);
201
+ } else {
202
+ const uri = node.resource;
203
+ let text = `${uri.codeUri.fsPath.toString()}\n`;
204
+
205
+ node.children?.forEach((node: SearchContentNode) => {
206
+ const result = node.contentResult;
207
+ text = text + `${result.line},${result.matchStart}: ${result.renderLineText} \n`;
208
+ });
209
+ this.clipboardService.writeText(text);
210
+ }
211
+ },
212
+ });
213
+ commands.registerCommand(SEARCH_COMMANDS.MENU_COPY_ALL, {
214
+ execute: (node: SearchFileNode | SearchContentNode) => {
215
+ let nodes: SearchFileNode[];
216
+ if (!node) {
217
+ nodes = this.searchModelService.treeModel.root.children as SearchFileNode[];
218
+ } else {
219
+ if (SearchFileNode.is(node)) {
220
+ nodes = [node];
221
+ } else {
222
+ nodes = [node.parent as SearchFileNode];
223
+ }
224
+ }
225
+ if (!nodes) {
226
+ return;
227
+ }
228
+ let copyText = '';
229
+
230
+ for (let i = 0, len = nodes.length; i < len; i++) {
231
+ const uri = nodes[i].resource;
232
+ let text = `${uri.codeUri.fsPath.toString()}\n`;
233
+ nodes[i].children?.forEach((node: SearchContentNode) => {
234
+ const result = node.contentResult;
235
+ text = text + `${result.line},${result.matchStart}: ${result.renderLineText} \n`;
236
+ });
237
+ copyText += text;
238
+ if (i < len) {
239
+ copyText += '\n';
240
+ }
241
+ }
242
+ this.clipboardService.writeText(copyText);
243
+ },
244
+ });
245
+ commands.registerCommand(SEARCH_COMMANDS.MENU_COPY_PATH, {
246
+ execute: (node: SearchFileNode | SearchContentNode) => {
247
+ this.clipboardService.writeText(node.resource.codeUri.fsPath.toString());
248
+ },
249
+ });
250
+ }
251
+
252
+ registerMenus(menuRegistry: IMenuRegistry): void {
253
+ menuRegistry.registerMenuItem(MenuId.SearchContext, {
254
+ command: SEARCH_COMMANDS.MENU_REPLACE.id,
255
+ order: 1,
256
+ group: '0_operator',
257
+ });
258
+ menuRegistry.registerMenuItem(MenuId.SearchContext, {
259
+ command: SEARCH_COMMANDS.MENU_REPLACE_ALL.id,
260
+ order: 2,
261
+ group: '0_operator',
262
+ });
263
+ menuRegistry.registerMenuItem(MenuId.SearchContext, {
264
+ command: SEARCH_COMMANDS.MENU_HIDE.id,
265
+ order: 3,
266
+ group: '0_operator',
267
+ });
268
+ menuRegistry.registerMenuItem(MenuId.SearchContext, {
269
+ command: SEARCH_COMMANDS.MENU_COPY.id,
270
+ order: 1,
271
+ group: '1_copy',
272
+ });
273
+ menuRegistry.registerMenuItem(MenuId.SearchContext, {
274
+ command: SEARCH_COMMANDS.MENU_COPY_PATH.id,
275
+ order: 2,
276
+ group: '1_copy',
277
+ });
278
+ menuRegistry.registerMenuItem(MenuId.SearchContext, {
279
+ command: SEARCH_COMMANDS.MENU_COPY_ALL.id,
280
+ order: 3,
281
+ group: '1_copy',
282
+ });
283
+ }
284
+
285
+ registerKeybindings(keybindings: KeybindingRegistry): void {
286
+ keybindings.registerKeybinding({
287
+ command: SEARCH_COMMANDS.OPEN_SEARCH.id,
288
+ keybinding: 'ctrlcmd+shift+f',
289
+ });
290
+
291
+ keybindings.registerKeybinding({
292
+ command: SEARCH_COMMANDS.GET_BACK_RECENT_SEARCH_WORD.id,
293
+ keybinding: 'down',
294
+ when: SearchInputBoxFocusedKey.raw,
295
+ });
296
+ keybindings.registerKeybinding({
297
+ command: SEARCH_COMMANDS.GET_RECENT_SEARCH_WORD.id,
298
+ keybinding: 'up',
299
+ when: SearchInputBoxFocusedKey.raw,
300
+ });
301
+ }
302
+
303
+ registerComponent(registry: ComponentRegistry) {
304
+ registry.register('@opensumi/ide-search', [], {
305
+ containerId: SEARCH_CONTAINER_ID,
306
+ iconClass: getIcon('search'),
307
+ title: localize('search.title'),
308
+ component: Search,
309
+ priority: 9,
310
+ });
311
+ }
312
+
313
+ registerToolbarItems(registry: ToolbarRegistry) {
314
+ registry.registerItem({
315
+ id: SEARCH_COMMANDS.CLEAN.id,
316
+ command: SEARCH_COMMANDS.CLEAN.id,
317
+ viewId: SEARCH_CONTAINER_ID,
318
+ tooltip: localize('search.ClearSearchResultsAction.label'),
319
+ enabledWhen: 'canClearSearchResult',
320
+ });
321
+ registry.registerItem({
322
+ id: SEARCH_COMMANDS.REFRESH.id,
323
+ command: SEARCH_COMMANDS.REFRESH.id,
324
+ viewId: SEARCH_CONTAINER_ID,
325
+ tooltip: localize('search.RefreshAction.label'),
326
+ enabledWhen: 'canRefreshSearchResult',
327
+ });
328
+ }
329
+
330
+ onDidRender() {
331
+ const handler = this.mainLayoutService.getTabbarHandler(SEARCH_CONTAINER_ID);
332
+ if (handler) {
333
+ handler.onActivate(() => {
334
+ this.searchBrowserService.initSearchHistory();
335
+ this.searchBrowserService.focus();
336
+ });
337
+ handler.onInActivate(() => {
338
+ this.searchTreeService.removeHighlightRange();
339
+ this.searchBrowserService.blur();
340
+ });
341
+ }
342
+ }
343
+
344
+ dispose() {
345
+ this.toDispose.dispose();
346
+ }
347
+ }
@@ -0,0 +1,129 @@
1
+ import cls from 'classnames';
2
+ import React, { FormEvent, memo, forwardRef } from 'react';
3
+
4
+ import { ValidateInput, CheckBox, ValidateMessage } from '@opensumi/ide-components';
5
+ import { getIcon } from '@opensumi/ide-core-browser/lib/style/icon/icon';
6
+ import { localize } from '@opensumi/ide-core-common/lib/localize';
7
+
8
+ import styles from './search.module.less';
9
+
10
+ export interface SearchInputWidgetProps {
11
+ isDetailOpen: boolean;
12
+ onDetailToggle: () => void;
13
+ onSearchFocus: () => void;
14
+ onSearchBlur: () => void;
15
+ isMatchCase: boolean;
16
+ onMatchCaseToggle: () => void;
17
+ isWholeWord: boolean;
18
+ onWholeWordToggle: () => void;
19
+ isRegex: boolean;
20
+ onRegexToggle: () => void;
21
+ searchValue: string;
22
+ onSearch: () => void;
23
+ onSearchInputChange: (e: FormEvent<HTMLInputElement>) => void;
24
+ isShowValidateMessage: boolean;
25
+ validateMessage?: ValidateMessage;
26
+ }
27
+
28
+ const SearchRuleCheckout = memo(
29
+ ({ isDetailOpen, onDetailToggle }: Pick<SearchInputWidgetProps, 'isDetailOpen' | 'onDetailToggle'>) => (
30
+ <p className={styles.search_input_title}>
31
+ <span className={styles.search_title}>{localize('search.input.title')}</span>
32
+ <CheckBox
33
+ className={cls(styles.checkbox)}
34
+ label={localize('search.input.checkbox')}
35
+ checked={isDetailOpen}
36
+ id='search-input'
37
+ onChange={onDetailToggle}
38
+ />
39
+ </p>
40
+ ),
41
+ (prevProps, nextProps) => prevProps.isDetailOpen === nextProps.isDetailOpen,
42
+ );
43
+
44
+ function isSearchInputPropsEqual(prevProps: SearchInputWidgetProps, nextProps: SearchInputWidgetProps) {
45
+ return (
46
+ prevProps.isDetailOpen === nextProps.isDetailOpen &&
47
+ prevProps.isMatchCase === nextProps.isMatchCase &&
48
+ prevProps.isWholeWord === nextProps.isWholeWord &&
49
+ prevProps.isRegex === nextProps.isRegex &&
50
+ prevProps.searchValue === nextProps.searchValue &&
51
+ prevProps.isShowValidateMessage === nextProps.isShowValidateMessage &&
52
+ prevProps.validateMessage === nextProps.validateMessage
53
+ );
54
+ }
55
+
56
+ export const SearchInputWidget = memo(
57
+ forwardRef<HTMLInputElement, SearchInputWidgetProps>(
58
+ (
59
+ {
60
+ isDetailOpen,
61
+ onDetailToggle,
62
+ onSearchFocus,
63
+ onSearchBlur,
64
+ isMatchCase,
65
+ onMatchCaseToggle,
66
+ isWholeWord,
67
+ onWholeWordToggle,
68
+ isRegex,
69
+ onRegexToggle,
70
+ searchValue,
71
+ onSearch,
72
+ onSearchInputChange,
73
+ isShowValidateMessage,
74
+ validateMessage,
75
+ },
76
+ ref,
77
+ ) => (
78
+ <div className={styles.search_and_replace_container}>
79
+ <div className={styles.search_and_replace_fields}>
80
+ <div className={styles.search_field_container}>
81
+ <SearchRuleCheckout isDetailOpen={isDetailOpen} onDetailToggle={onDetailToggle} />
82
+ <div className={styles.search_field}>
83
+ <ValidateInput
84
+ id='search-input-field'
85
+ title={localize('search.input.placeholder')}
86
+ type='text'
87
+ value={searchValue}
88
+ placeholder={localize('search.input.title')}
89
+ onFocus={onSearchFocus}
90
+ onBlur={onSearchBlur}
91
+ onKeyUp={onSearch}
92
+ onChange={onSearchInputChange}
93
+ ref={ref}
94
+ validateMessage={isShowValidateMessage ? validateMessage : undefined}
95
+ addonAfter={[
96
+ <span
97
+ key={localize('search.caseDescription')}
98
+ className={cls(getIcon('ab'), styles['match-case'], styles.search_option, {
99
+ [styles.select]: isMatchCase,
100
+ })}
101
+ title={localize('search.caseDescription')}
102
+ onClick={onMatchCaseToggle}
103
+ ></span>,
104
+ <span
105
+ key={localize('search.wordsDescription')}
106
+ className={cls(getIcon('abl'), styles['whole-word'], styles.search_option, {
107
+ [styles.select]: isWholeWord,
108
+ })}
109
+ title={localize('search.wordsDescription')}
110
+ onClick={onWholeWordToggle}
111
+ ></span>,
112
+ <span
113
+ key={localize('search.regexDescription')}
114
+ className={cls(getIcon('regex'), styles['use-regexp'], styles.search_option, {
115
+ [styles.select]: isRegex,
116
+ })}
117
+ title={localize('search.regexDescription')}
118
+ onClick={onRegexToggle}
119
+ ></span>,
120
+ ]}
121
+ />
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ ),
127
+ ),
128
+ isSearchInputPropsEqual,
129
+ );