@atlaskit/editor-plugin-find-replace 0.2.0 → 0.3.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/CHANGELOG.md +6 -0
- package/dist/cjs/styles.js +16 -3
- package/dist/cjs/ui/Find.js +100 -59
- package/dist/cjs/ui/FindReplace.js +68 -9
- package/dist/cjs/ui/FindReplaceToolbarButton.js +31 -3
- package/dist/cjs/ui/FindReplaceTooltipButton.js +6 -3
- package/dist/cjs/ui/Replace.js +194 -5
- package/dist/cjs/ui/styles.js +30 -4
- package/dist/es2019/styles.js +17 -10
- package/dist/es2019/ui/Find.js +100 -59
- package/dist/es2019/ui/FindReplace.js +61 -7
- package/dist/es2019/ui/FindReplaceToolbarButton.js +31 -3
- package/dist/es2019/ui/FindReplaceTooltipButton.js +6 -3
- package/dist/es2019/ui/Replace.js +190 -6
- package/dist/es2019/ui/styles.js +67 -3
- package/dist/esm/styles.js +17 -4
- package/dist/esm/ui/Find.js +101 -60
- package/dist/esm/ui/FindReplace.js +69 -10
- package/dist/esm/ui/FindReplaceToolbarButton.js +31 -3
- package/dist/esm/ui/FindReplaceTooltipButton.js +6 -3
- package/dist/esm/ui/Replace.js +192 -6
- package/dist/esm/ui/styles.js +32 -4
- package/dist/types/ui/Find.d.ts +6 -0
- package/dist/types/ui/FindReplace.d.ts +10 -0
- package/dist/types/ui/FindReplaceTooltipButton.d.ts +2 -0
- package/dist/types/ui/Replace.d.ts +19 -0
- package/dist/types/ui/styles.d.ts +10 -0
- package/dist/types-ts4.5/ui/Find.d.ts +6 -0
- package/dist/types-ts4.5/ui/FindReplace.d.ts +10 -0
- package/dist/types-ts4.5/ui/FindReplaceTooltipButton.d.ts +2 -0
- package/dist/types-ts4.5/ui/Replace.d.ts +19 -0
- package/dist/types-ts4.5/ui/styles.d.ts +10 -0
- package/package.json +7 -4
|
@@ -4,15 +4,45 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
4
4
|
/** @jsx jsx */
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { jsx } from '@emotion/react';
|
|
7
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
7
8
|
import Find from './Find';
|
|
8
9
|
import Replace from './Replace';
|
|
9
|
-
import { ruleStyles, wrapperStyles } from './styles';
|
|
10
|
+
import { ruleStyles, wrapperPaddingStyles, wrapperStyles } from './styles';
|
|
10
11
|
// eslint-disable-next-line @repo/internal/react/no-class-components
|
|
11
12
|
class FindReplace extends React.PureComponent {
|
|
12
|
-
constructor(
|
|
13
|
-
super(
|
|
13
|
+
constructor(props) {
|
|
14
|
+
super(props);
|
|
14
15
|
_defineProperty(this, "findTextfield", null);
|
|
15
16
|
_defineProperty(this, "replaceTextfield", null);
|
|
17
|
+
_defineProperty(this, "handleTabNavigation", event => {
|
|
18
|
+
if (event.key === 'Tab') {
|
|
19
|
+
event.preventDefault();
|
|
20
|
+
const modalFindReplace = this.modalRef.current;
|
|
21
|
+
if (!modalFindReplace || !modalFindReplace.contains(document.activeElement)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const focusableElements = Array.from(modalFindReplace.querySelectorAll('[tabindex]:not([tabindex="-1"]), input, button')).filter(el => el.getAttribute('tabindex') !== '-1');
|
|
25
|
+
const currentIndex = focusableElements.findIndex(el => el === document.activeElement);
|
|
26
|
+
const isShiftPressed = event.shiftKey;
|
|
27
|
+
if (isShiftPressed) {
|
|
28
|
+
const prevIndex = (currentIndex - 1 + focusableElements.length) % focusableElements.length;
|
|
29
|
+
focusableElements[prevIndex].focus();
|
|
30
|
+
} else {
|
|
31
|
+
const nextIndex = (currentIndex + 1) % focusableElements.length;
|
|
32
|
+
focusableElements[nextIndex].focus();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
_defineProperty(this, "state", {
|
|
37
|
+
findTyped: false
|
|
38
|
+
});
|
|
39
|
+
_defineProperty(this, "setFindTyped", value => {
|
|
40
|
+
if (getBooleanFF('platform.editor.a11y-find-replace')) {
|
|
41
|
+
this.setState({
|
|
42
|
+
findTyped: value
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
16
46
|
_defineProperty(this, "setFindTextfieldRef", findTextfieldRef => {
|
|
17
47
|
this.findTextfield = findTextfieldRef.current;
|
|
18
48
|
});
|
|
@@ -29,6 +59,19 @@ class FindReplace extends React.PureComponent {
|
|
|
29
59
|
this.replaceTextfield.focus();
|
|
30
60
|
}
|
|
31
61
|
});
|
|
62
|
+
this.modalRef = /*#__PURE__*/React.createRef();
|
|
63
|
+
}
|
|
64
|
+
componentDidMount() {
|
|
65
|
+
if (getBooleanFF('platform.editor.a11y-find-replace')) {
|
|
66
|
+
// eslint-disable-next-line
|
|
67
|
+
window.addEventListener('keydown', this.handleTabNavigation);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
componentWillUnmount() {
|
|
71
|
+
if (getBooleanFF('platform.editor.a11y-find-replace')) {
|
|
72
|
+
// eslint-disable-next-line
|
|
73
|
+
window.removeEventListener('keydown', this.handleTabNavigation);
|
|
74
|
+
}
|
|
32
75
|
}
|
|
33
76
|
render() {
|
|
34
77
|
const {
|
|
@@ -48,8 +91,10 @@ class FindReplace extends React.PureComponent {
|
|
|
48
91
|
shouldMatchCase,
|
|
49
92
|
onToggleMatchCase
|
|
50
93
|
} = this.props;
|
|
94
|
+
const focusToolbarButton = getBooleanFF('platform.editor.a11y-find-replace') ? this.props.focusToolbarButton || (() => {}) : () => {};
|
|
51
95
|
return jsx("div", {
|
|
52
|
-
|
|
96
|
+
ref: this.modalRef,
|
|
97
|
+
css: getBooleanFF('platform.editor.a11y-find-replace') ? [wrapperStyles, wrapperPaddingStyles] : wrapperStyles
|
|
53
98
|
}, jsx(Find, {
|
|
54
99
|
allowMatchCase: allowMatchCase,
|
|
55
100
|
shouldMatchCase: shouldMatchCase,
|
|
@@ -63,8 +108,10 @@ class FindReplace extends React.PureComponent {
|
|
|
63
108
|
onFindNext: onFindNext,
|
|
64
109
|
onFindTextfieldRefSet: this.setFindTextfieldRef,
|
|
65
110
|
onCancel: onCancel,
|
|
66
|
-
onArrowDown: this.setFocusToReplace
|
|
67
|
-
|
|
111
|
+
onArrowDown: this.setFocusToReplace,
|
|
112
|
+
findTyped: this.state.findTyped,
|
|
113
|
+
setFindTyped: this.setFindTyped
|
|
114
|
+
}), !getBooleanFF('platform.editor.a11y-find-replace') && jsx("hr", {
|
|
68
115
|
css: ruleStyles,
|
|
69
116
|
id: "replace-hr-element"
|
|
70
117
|
}), jsx(Replace, {
|
|
@@ -74,7 +121,14 @@ class FindReplace extends React.PureComponent {
|
|
|
74
121
|
onReplaceAll: onReplaceAll,
|
|
75
122
|
onReplaceTextfieldRefSet: this.setReplaceTextfieldRef,
|
|
76
123
|
onArrowUp: this.setFocusToFind,
|
|
77
|
-
|
|
124
|
+
onCancel: onCancel,
|
|
125
|
+
count: count,
|
|
126
|
+
onFindPrev: onFindPrev,
|
|
127
|
+
onFindNext: onFindNext,
|
|
128
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
129
|
+
findTyped: this.state.findTyped,
|
|
130
|
+
setFindTyped: this.setFindTyped,
|
|
131
|
+
focusToolbarButton: focusToolbarButton
|
|
78
132
|
}));
|
|
79
133
|
}
|
|
80
134
|
}
|
|
@@ -10,6 +10,7 @@ import { findKeymapByDescription, getAriaKeyshortcuts, tooltip, ToolTipContent }
|
|
|
10
10
|
import { ArrowKeyNavigationType, Dropdown, TOOLBAR_BUTTON, ToolbarButton } from '@atlaskit/editor-common/ui-menu';
|
|
11
11
|
import { akEditorFloatingPanelZIndex, akEditorMobileMaxWidth } from '@atlaskit/editor-shared-styles';
|
|
12
12
|
import EditorSearchIcon from '@atlaskit/icon/glyph/editor/search';
|
|
13
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
13
14
|
import FindReplace from './FindReplace';
|
|
14
15
|
const toolbarButtonWrapper = css`
|
|
15
16
|
display: flex;
|
|
@@ -37,19 +38,36 @@ const messages = defineMessages({
|
|
|
37
38
|
description: '"Find" highlights all instances of a word or phrase on the document, and "Replace" changes one or all of those instances to something else'
|
|
38
39
|
}
|
|
39
40
|
});
|
|
41
|
+
const dropdownWidthNewDesign = 382;
|
|
42
|
+
const dropdownWidthOldDesign = 352;
|
|
40
43
|
// eslint-disable-next-line @repo/internal/react/no-class-components
|
|
41
44
|
class FindReplaceToolbarButton extends React.PureComponent {
|
|
42
45
|
constructor(...args) {
|
|
43
46
|
super(...args);
|
|
47
|
+
_defineProperty(this, "state", {
|
|
48
|
+
openedByClick: false
|
|
49
|
+
});
|
|
44
50
|
_defineProperty(this, "toggleOpen", () => {
|
|
45
51
|
if (this.props.isActive) {
|
|
46
52
|
this.props.onCancel({
|
|
47
53
|
triggerMethod: TRIGGER_METHOD.TOOLBAR
|
|
48
54
|
});
|
|
49
55
|
} else {
|
|
56
|
+
this.setState({
|
|
57
|
+
openedByClick: true
|
|
58
|
+
});
|
|
50
59
|
this.props.onActivate();
|
|
51
60
|
}
|
|
52
61
|
});
|
|
62
|
+
_defineProperty(this, "focusToolbarButton", () => {
|
|
63
|
+
if (this.state.openedByClick && this.toolbarButtonRef.current) {
|
|
64
|
+
this.toolbarButtonRef.current.focus();
|
|
65
|
+
}
|
|
66
|
+
this.setState({
|
|
67
|
+
openedByClick: false
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
_defineProperty(this, "toolbarButtonRef", /*#__PURE__*/React.createRef());
|
|
53
71
|
}
|
|
54
72
|
render() {
|
|
55
73
|
const {
|
|
@@ -82,9 +100,17 @@ class FindReplaceToolbarButton extends React.PureComponent {
|
|
|
82
100
|
this.props.onCancel({
|
|
83
101
|
triggerMethod: TRIGGER_METHOD.KEYBOARD
|
|
84
102
|
});
|
|
103
|
+
if (getBooleanFF('platform.editor.a11y-find-replace')) {
|
|
104
|
+
if (this.state.openedByClick && this.toolbarButtonRef.current) {
|
|
105
|
+
this.toolbarButtonRef.current.focus();
|
|
106
|
+
}
|
|
107
|
+
this.setState({
|
|
108
|
+
openedByClick: false
|
|
109
|
+
});
|
|
110
|
+
}
|
|
85
111
|
}
|
|
86
112
|
},
|
|
87
|
-
fitWidth:
|
|
113
|
+
fitWidth: getBooleanFF('platform.editor.a11y-find-replace') ? dropdownWidthNewDesign : dropdownWidthOldDesign,
|
|
88
114
|
zIndex: stackBelowOtherEditorFloatingPanels,
|
|
89
115
|
arrowKeyNavigationProviderOptions: {
|
|
90
116
|
type: ArrowKeyNavigationType.MENU,
|
|
@@ -105,7 +131,8 @@ class FindReplaceToolbarButton extends React.PureComponent {
|
|
|
105
131
|
"aria-expanded": isActive,
|
|
106
132
|
"aria-haspopup": true,
|
|
107
133
|
"aria-label": keymap ? tooltip(keymap, title) : title,
|
|
108
|
-
"aria-keyshortcuts": getAriaKeyshortcuts(keymap)
|
|
134
|
+
"aria-keyshortcuts": getAriaKeyshortcuts(keymap),
|
|
135
|
+
ref: getBooleanFF('platform.editor.a11y-find-replace') ? this.toolbarButtonRef : null
|
|
109
136
|
})
|
|
110
137
|
}, jsx("div", {
|
|
111
138
|
css: wrapper
|
|
@@ -115,7 +142,8 @@ class FindReplaceToolbarButton extends React.PureComponent {
|
|
|
115
142
|
count: {
|
|
116
143
|
index,
|
|
117
144
|
total: numMatches
|
|
118
|
-
}
|
|
145
|
+
},
|
|
146
|
+
focusToolbarButton: this.focusToolbarButton
|
|
119
147
|
}, this.props)))));
|
|
120
148
|
}
|
|
121
149
|
}
|
|
@@ -19,7 +19,8 @@ export class FindReplaceTooltipButton extends React.PureComponent {
|
|
|
19
19
|
icon,
|
|
20
20
|
keymapDescription,
|
|
21
21
|
disabled,
|
|
22
|
-
isPressed
|
|
22
|
+
isPressed,
|
|
23
|
+
appearance
|
|
23
24
|
} = this.props;
|
|
24
25
|
const pressedProps = {
|
|
25
26
|
...(typeof isPressed === 'boolean' && {
|
|
@@ -34,8 +35,9 @@ export class FindReplaceTooltipButton extends React.PureComponent {
|
|
|
34
35
|
hideTooltipOnClick: true,
|
|
35
36
|
position: 'top'
|
|
36
37
|
}, /*#__PURE__*/React.createElement(Button, _extends({
|
|
38
|
+
id: "afterInputSection",
|
|
37
39
|
label: title,
|
|
38
|
-
appearance:
|
|
40
|
+
appearance: appearance,
|
|
39
41
|
testId: title,
|
|
40
42
|
ref: this.buttonRef,
|
|
41
43
|
iconBefore: icon,
|
|
@@ -47,5 +49,6 @@ export class FindReplaceTooltipButton extends React.PureComponent {
|
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
_defineProperty(FindReplaceTooltipButton, "defaultProps", {
|
|
50
|
-
keymapDescription: 'no-keymap'
|
|
52
|
+
keymapDescription: 'no-keymap',
|
|
53
|
+
appearance: 'subtle'
|
|
51
54
|
});
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
/* eslint-disable @atlaskit/design-system/consistent-css-prop-usage */
|
|
3
3
|
/** @jsx jsx */
|
|
4
|
-
import React from 'react';
|
|
4
|
+
import React, { Fragment } from 'react';
|
|
5
5
|
import { jsx } from '@emotion/react';
|
|
6
6
|
import { defineMessages, injectIntl } from 'react-intl-next';
|
|
7
7
|
import Button from '@atlaskit/button/standard-button';
|
|
8
8
|
import { ACTION, ACTION_SUBJECT, EVENT_TYPE, TRIGGER_METHOD } from '@atlaskit/editor-common/analytics';
|
|
9
|
+
import { Label, ValidMessage } from '@atlaskit/form';
|
|
10
|
+
import ChevronDownIcon from '@atlaskit/icon/glyph/hipchat/chevron-down';
|
|
11
|
+
import ChevronUpIcon from '@atlaskit/icon/glyph/hipchat/chevron-up';
|
|
12
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
9
13
|
import Textfield from '@atlaskit/textfield';
|
|
10
|
-
import {
|
|
14
|
+
import { FindReplaceTooltipButton } from './FindReplaceTooltipButton';
|
|
15
|
+
import { NextPreviousItem, orderOneStyles, orderZeroStyles, replaceSectionButtonStyles, sectionWrapperJustified, sectionWrapperStyles, sectionWrapperStylesAlternate, textFieldWrapper } from './styles';
|
|
11
16
|
const messages = defineMessages({
|
|
12
17
|
replaceWith: {
|
|
13
18
|
id: 'fabric.editor.replaceWith',
|
|
@@ -23,6 +28,36 @@ const messages = defineMessages({
|
|
|
23
28
|
id: 'fabric.editor.replaceAll',
|
|
24
29
|
defaultMessage: 'Replace all',
|
|
25
30
|
description: 'Replace all instances of the word or phrase throughout the entire document'
|
|
31
|
+
},
|
|
32
|
+
replaceSuccess: {
|
|
33
|
+
id: 'fabric.editor.replaceSuccess',
|
|
34
|
+
defaultMessage: '{numberOfMatches} {matchPluralSingularNoun} replaced',
|
|
35
|
+
description: 'Text when replacement succesfully done'
|
|
36
|
+
},
|
|
37
|
+
matchSingularNoun: {
|
|
38
|
+
id: 'fabric.editor.match.singular',
|
|
39
|
+
defaultMessage: 'match',
|
|
40
|
+
description: 'Singular "Match" noun'
|
|
41
|
+
},
|
|
42
|
+
matchPluralNoun: {
|
|
43
|
+
id: 'fabric.editor.match.plural',
|
|
44
|
+
defaultMessage: 'matches',
|
|
45
|
+
description: 'Plural "Match" noun'
|
|
46
|
+
},
|
|
47
|
+
findNext: {
|
|
48
|
+
id: 'fabric.editor.findNext',
|
|
49
|
+
defaultMessage: 'Find next',
|
|
50
|
+
description: 'Locate the next occurrence of the word or phrase that was searched for'
|
|
51
|
+
},
|
|
52
|
+
findPrevious: {
|
|
53
|
+
id: 'fabric.editor.findPrevious',
|
|
54
|
+
defaultMessage: 'Find previous',
|
|
55
|
+
description: 'Locate the previous occurrence of the word or phrase that was searched for'
|
|
56
|
+
},
|
|
57
|
+
closeFindReplaceDialog: {
|
|
58
|
+
id: 'fabric.editor.closeFindReplaceDialog',
|
|
59
|
+
defaultMessage: 'Close',
|
|
60
|
+
description: 'Cancel search and close the "Find and Replace" dialog'
|
|
26
61
|
}
|
|
27
62
|
});
|
|
28
63
|
|
|
@@ -31,6 +66,8 @@ class Replace extends React.PureComponent {
|
|
|
31
66
|
constructor(props) {
|
|
32
67
|
super(props);
|
|
33
68
|
_defineProperty(this, "replaceTextfieldRef", /*#__PURE__*/React.createRef());
|
|
69
|
+
_defineProperty(this, "successReplacementMessageRef", /*#__PURE__*/React.createRef());
|
|
70
|
+
_defineProperty(this, "isComposing", false);
|
|
34
71
|
_defineProperty(this, "skipWhileComposing", fn => {
|
|
35
72
|
if (this.state.isComposing) {
|
|
36
73
|
return;
|
|
@@ -42,6 +79,14 @@ class Replace extends React.PureComponent {
|
|
|
42
79
|
triggerMethod: TRIGGER_METHOD.BUTTON,
|
|
43
80
|
replaceText: this.state.replaceText
|
|
44
81
|
});
|
|
82
|
+
// for replace button replaceCount always 1;
|
|
83
|
+
const replaceCount = 1;
|
|
84
|
+
this.triggerSuccessReplacementMessageUpdate(replaceCount);
|
|
85
|
+
this.setState({
|
|
86
|
+
isHelperMessageVisible: true,
|
|
87
|
+
replaceCount
|
|
88
|
+
});
|
|
89
|
+
this.props.setFindTyped(false);
|
|
45
90
|
}));
|
|
46
91
|
_defineProperty(this, "handleReplaceChange", event => this.skipWhileComposing(() => {
|
|
47
92
|
this.updateReplaceValue(event.target.value);
|
|
@@ -76,6 +121,14 @@ class Replace extends React.PureComponent {
|
|
|
76
121
|
this.props.onReplaceAll({
|
|
77
122
|
replaceText: this.state.replaceText
|
|
78
123
|
});
|
|
124
|
+
this.setState({
|
|
125
|
+
isHelperMessageVisible: true
|
|
126
|
+
});
|
|
127
|
+
this.triggerSuccessReplacementMessageUpdate(this.props.count.total);
|
|
128
|
+
this.setState({
|
|
129
|
+
replaceCount: this.props.count.total
|
|
130
|
+
});
|
|
131
|
+
this.props.setFindTyped(false);
|
|
79
132
|
}));
|
|
80
133
|
_defineProperty(this, "handleCompositionStart", () => {
|
|
81
134
|
this.setState({
|
|
@@ -89,6 +142,28 @@ class Replace extends React.PureComponent {
|
|
|
89
142
|
// type for React.CompositionEvent doesn't set type for target correctly
|
|
90
143
|
this.updateReplaceValue(event.target.value);
|
|
91
144
|
});
|
|
145
|
+
_defineProperty(this, "clearSearch", () => {
|
|
146
|
+
this.props.onCancel({
|
|
147
|
+
triggerMethod: TRIGGER_METHOD.BUTTON
|
|
148
|
+
});
|
|
149
|
+
this.props.focusToolbarButton && this.props.focusToolbarButton();
|
|
150
|
+
});
|
|
151
|
+
_defineProperty(this, "handleFindNextClick", () => {
|
|
152
|
+
if (this.isComposing) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.props.onFindNext({
|
|
156
|
+
triggerMethod: TRIGGER_METHOD.BUTTON
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
_defineProperty(this, "handleFindPrevClick", () => {
|
|
160
|
+
if (this.isComposing) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
this.props.onFindPrev({
|
|
164
|
+
triggerMethod: TRIGGER_METHOD.BUTTON
|
|
165
|
+
});
|
|
166
|
+
});
|
|
92
167
|
const {
|
|
93
168
|
replaceText: _replaceText,
|
|
94
169
|
intl: {
|
|
@@ -97,11 +172,23 @@ class Replace extends React.PureComponent {
|
|
|
97
172
|
} = props;
|
|
98
173
|
this.state = {
|
|
99
174
|
replaceText: _replaceText || '',
|
|
100
|
-
isComposing: false
|
|
175
|
+
isComposing: false,
|
|
176
|
+
isHelperMessageVisible: false,
|
|
177
|
+
fakeSuccessReplacementMessageUpdate: false,
|
|
178
|
+
replaceCount: 0
|
|
101
179
|
};
|
|
102
180
|
this.replaceWith = formatMessage(messages.replaceWith);
|
|
103
181
|
this.replace = formatMessage(messages.replace);
|
|
104
182
|
this.replaceAll = formatMessage(messages.replaceAll);
|
|
183
|
+
this.findNext = formatMessage(messages.findNext);
|
|
184
|
+
this.findPrevious = formatMessage(messages.findPrevious);
|
|
185
|
+
this.findNextIcon = jsx(ChevronDownIcon, {
|
|
186
|
+
label: this.findNext
|
|
187
|
+
});
|
|
188
|
+
this.findPrevIcon = jsx(ChevronUpIcon, {
|
|
189
|
+
label: this.findPrevious
|
|
190
|
+
});
|
|
191
|
+
this.closeFindReplaceDialog = formatMessage(messages.closeFindReplaceDialog);
|
|
105
192
|
}
|
|
106
193
|
componentDidMount() {
|
|
107
194
|
this.props.onReplaceTextfieldRefSet(this.replaceTextfieldRef);
|
|
@@ -118,15 +205,112 @@ class Replace extends React.PureComponent {
|
|
|
118
205
|
isComposing: false
|
|
119
206
|
});
|
|
120
207
|
}
|
|
208
|
+
if (getBooleanFF('platform.editor.a11y-find-replace')) {
|
|
209
|
+
const findTextField = document.getElementById('find-text-field');
|
|
210
|
+
const replaceButton = document.getElementById('replace-button');
|
|
211
|
+
const replaceAllButton = document.getElementById('replaceAll-button');
|
|
212
|
+
if (((replaceButton === null || replaceButton === void 0 ? void 0 : replaceButton.tabIndex) === -1 || (replaceAllButton === null || replaceAllButton === void 0 ? void 0 : replaceAllButton.tabIndex) === -1) && findTextField) {
|
|
213
|
+
findTextField.focus();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
triggerSuccessReplacementMessageUpdate(currentReplaceCount) {
|
|
218
|
+
var _this$state;
|
|
219
|
+
if (((_this$state = this.state) === null || _this$state === void 0 ? void 0 : _this$state.replaceCount) === currentReplaceCount) {
|
|
220
|
+
this.setState({
|
|
221
|
+
fakeSuccessReplacementMessageUpdate: !this.state.fakeSuccessReplacementMessageUpdate
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
if (this.successReplacementMessageRef && this.successReplacementMessageRef.current) {
|
|
225
|
+
const ariaLiveRegion = this.successReplacementMessageRef.current.querySelector('[aria-live="polite"]');
|
|
226
|
+
ariaLiveRegion === null || ariaLiveRegion === void 0 ? void 0 : ariaLiveRegion.removeAttribute('aria-live');
|
|
227
|
+
ariaLiveRegion === null || ariaLiveRegion === void 0 ? void 0 : ariaLiveRegion.setAttribute('aria-live', 'polite');
|
|
228
|
+
}
|
|
121
229
|
}
|
|
122
230
|
render() {
|
|
123
231
|
const {
|
|
124
|
-
replaceText
|
|
232
|
+
replaceText,
|
|
233
|
+
isHelperMessageVisible,
|
|
234
|
+
replaceCount
|
|
125
235
|
} = this.state;
|
|
126
236
|
const {
|
|
127
|
-
canReplace
|
|
237
|
+
canReplace,
|
|
238
|
+
count,
|
|
239
|
+
intl: {
|
|
240
|
+
formatMessage
|
|
241
|
+
}
|
|
128
242
|
} = this.props;
|
|
129
|
-
|
|
243
|
+
const resultsReplace = formatMessage(messages.replaceSuccess, {
|
|
244
|
+
numberOfMatches: replaceCount,
|
|
245
|
+
matchPluralSingularNoun: replaceCount > 1 ? formatMessage(messages.matchPluralNoun) : formatMessage(messages.matchSingularNoun)
|
|
246
|
+
});
|
|
247
|
+
return getBooleanFF('platform.editor.a11y-find-replace') ? jsx(Fragment, null, jsx("div", {
|
|
248
|
+
css: [sectionWrapperStyles, sectionWrapperStylesAlternate]
|
|
249
|
+
}, jsx("div", {
|
|
250
|
+
css: textFieldWrapper
|
|
251
|
+
}, jsx(Label, {
|
|
252
|
+
htmlFor: "replace-text-field"
|
|
253
|
+
}, "Replace with"), jsx(Textfield, {
|
|
254
|
+
name: "replace",
|
|
255
|
+
id: "replace-text-field",
|
|
256
|
+
appearance: "standard",
|
|
257
|
+
defaultValue: replaceText,
|
|
258
|
+
ref: this.replaceTextfieldRef,
|
|
259
|
+
autoComplete: "off",
|
|
260
|
+
onChange: this.handleReplaceChange,
|
|
261
|
+
onKeyDown: this.handleReplaceKeyDown,
|
|
262
|
+
onCompositionStart: this.handleCompositionStart,
|
|
263
|
+
onCompositionEnd: this.handleCompositionEnd
|
|
264
|
+
}), isHelperMessageVisible && this.props.findTyped === false && jsx("div", {
|
|
265
|
+
ref: this.successReplacementMessageRef
|
|
266
|
+
}, jsx(ValidMessage, {
|
|
267
|
+
testId: "message-success-replacement"
|
|
268
|
+
},
|
|
269
|
+
/*
|
|
270
|
+
Replacement needed to trigger the SR announcement if message hasn't changed. e.g Replace button clicked twice.
|
|
271
|
+
'\u00a0' is value for  
|
|
272
|
+
*/
|
|
273
|
+
this.state.fakeSuccessReplacementMessageUpdate ? resultsReplace.replace(/ /, '\u00a0') : resultsReplace)))), jsx("div", {
|
|
274
|
+
css: [sectionWrapperStyles, sectionWrapperStylesAlternate, sectionWrapperJustified]
|
|
275
|
+
}, jsx("div", {
|
|
276
|
+
css: orderOneStyles
|
|
277
|
+
}, jsx("div", {
|
|
278
|
+
css: NextPreviousItem
|
|
279
|
+
}, jsx(FindReplaceTooltipButton, {
|
|
280
|
+
title: this.findNext,
|
|
281
|
+
icon: this.findNextIcon,
|
|
282
|
+
keymapDescription: 'Enter',
|
|
283
|
+
onClick: this.handleFindNextClick,
|
|
284
|
+
disabled: count.total <= 1
|
|
285
|
+
})), jsx("div", {
|
|
286
|
+
css: NextPreviousItem
|
|
287
|
+
}, jsx(FindReplaceTooltipButton, {
|
|
288
|
+
title: this.findPrevious,
|
|
289
|
+
icon: this.findPrevIcon,
|
|
290
|
+
keymapDescription: 'Shift Enter',
|
|
291
|
+
onClick: this.handleFindPrevClick,
|
|
292
|
+
disabled: count.total <= 1
|
|
293
|
+
})), jsx(Button, {
|
|
294
|
+
css: replaceSectionButtonStyles,
|
|
295
|
+
testId: this.replace,
|
|
296
|
+
id: "replace-button",
|
|
297
|
+
onClick: this.handleReplaceClick,
|
|
298
|
+
isDisabled: !canReplace
|
|
299
|
+
}, this.replace), jsx(Button, {
|
|
300
|
+
css: replaceSectionButtonStyles,
|
|
301
|
+
appearance: "primary",
|
|
302
|
+
testId: this.replaceAll,
|
|
303
|
+
id: "replaceAll-button",
|
|
304
|
+
onClick: this.handleReplaceAllClick,
|
|
305
|
+
isDisabled: !canReplace
|
|
306
|
+
}, this.replaceAll)), jsx("div", {
|
|
307
|
+
css: orderZeroStyles
|
|
308
|
+
}, jsx(Button, {
|
|
309
|
+
css: replaceSectionButtonStyles,
|
|
310
|
+
appearance: "subtle",
|
|
311
|
+
testId: this.closeFindReplaceDialog,
|
|
312
|
+
onClick: this.clearSearch
|
|
313
|
+
}, this.closeFindReplaceDialog)))) : jsx("div", {
|
|
130
314
|
css: sectionWrapperStyles
|
|
131
315
|
}, jsx(Textfield, {
|
|
132
316
|
name: "replace",
|
package/dist/es2019/ui/styles.js
CHANGED
|
@@ -3,8 +3,17 @@
|
|
|
3
3
|
/** @jsx jsx */
|
|
4
4
|
import { css } from '@emotion/react';
|
|
5
5
|
import { relativeFontSizeToBase16 } from '@atlaskit/editor-shared-styles';
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
7
|
+
import { N30A } from '@atlaskit/theme/colors';
|
|
8
|
+
import { fontSize as getFontSize,
|
|
9
|
+
// eslint-disable-next-line @atlaskit/design-system/no-deprecated-imports
|
|
10
|
+
gridSize as getGridSize } from '@atlaskit/theme/constants';
|
|
11
|
+
const fontSize = getFontSize();
|
|
12
|
+
const gridSize = getGridSize();
|
|
13
|
+
export const replaceSectionButtonStyles = getBooleanFF('platform.editor.a11y-find-replace') ? css({
|
|
14
|
+
marginLeft: "var(--ds-space-050, 4px)",
|
|
15
|
+
marginRight: "var(--ds-space-050, 2px)"
|
|
16
|
+
}) : css({
|
|
8
17
|
marginLeft: "var(--ds-space-050, 4px)"
|
|
9
18
|
});
|
|
10
19
|
export const ruleStyles = css({
|
|
@@ -22,6 +31,9 @@ export const wrapperStyles = css({
|
|
|
22
31
|
margin: `0px ${"var(--ds-space-050, 4px)"}`
|
|
23
32
|
}
|
|
24
33
|
});
|
|
34
|
+
export const wrapperPaddingStyles = css({
|
|
35
|
+
padding: `${"var(--ds-space-050, 4px)"} ${"var(--ds-space-050, 4px)"}`
|
|
36
|
+
});
|
|
25
37
|
export const sectionWrapperStyles = css`
|
|
26
38
|
display: flex;
|
|
27
39
|
|
|
@@ -36,8 +48,50 @@ export const sectionWrapperStyles = css`
|
|
|
36
48
|
flex: 1 1 auto;
|
|
37
49
|
}
|
|
38
50
|
`;
|
|
51
|
+
export const sectionWrapperStylesAlternate = css`
|
|
52
|
+
display: flex;
|
|
53
|
+
padding: ${"var(--ds-space-100, 8px)"};
|
|
54
|
+
|
|
55
|
+
& > * {
|
|
56
|
+
height: unset;
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
59
|
+
export const sectionWrapperJustified = css`
|
|
60
|
+
justify-content: space-between;
|
|
61
|
+
font-size: ${relativeFontSizeToBase16(14)};
|
|
62
|
+
`;
|
|
63
|
+
export const textFieldWrapper = css`
|
|
64
|
+
flex: 1 100%;
|
|
65
|
+
flex-wrap: wrap;
|
|
66
|
+
|
|
67
|
+
#find-text-field,
|
|
68
|
+
#replace-text-field {
|
|
69
|
+
height: ${gridSize * 4.5 / fontSize}em;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
label {
|
|
73
|
+
font-size: ${relativeFontSizeToBase16(14)};
|
|
74
|
+
line-height: ${gridSize * 2}px;
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
export const afterInputSection = css`
|
|
78
|
+
display: flex;
|
|
79
|
+
flex: 0 0 auto;
|
|
80
|
+
align-items: center;
|
|
81
|
+
`;
|
|
82
|
+
export const matchCaseSection = css`
|
|
83
|
+
padding-right: ${"var(--ds-space-100, 8px)"};
|
|
84
|
+
|
|
85
|
+
button {
|
|
86
|
+
width: 20px;
|
|
87
|
+
height: 20px;
|
|
88
|
+
}
|
|
89
|
+
`;
|
|
90
|
+
export const NextPreviousItem = css`
|
|
91
|
+
padding: 0px 3px;
|
|
92
|
+
`;
|
|
39
93
|
export const countStyles = css({
|
|
40
|
-
color: `${
|
|
94
|
+
color: `${"var(--ds-text-subtlest, #626F86)"}`,
|
|
41
95
|
fontSize: `${relativeFontSizeToBase16(12)}`,
|
|
42
96
|
flex: '0 0 auto',
|
|
43
97
|
justifyContent: 'center',
|
|
@@ -45,6 +99,16 @@ export const countStyles = css({
|
|
|
45
99
|
marginLeft: "var(--ds-space-050, 4px)",
|
|
46
100
|
marginRight: "var(--ds-space-100, 8px)"
|
|
47
101
|
});
|
|
102
|
+
export const countStylesAlternateStyles = css({
|
|
103
|
+
display: 'inline-flex',
|
|
104
|
+
height: '32px'
|
|
105
|
+
});
|
|
48
106
|
export const countWrapperStyles = css({
|
|
49
107
|
alignItems: 'center'
|
|
108
|
+
});
|
|
109
|
+
export const orderZeroStyles = css({
|
|
110
|
+
order: '0'
|
|
111
|
+
});
|
|
112
|
+
export const orderOneStyles = css({
|
|
113
|
+
order: '1'
|
|
50
114
|
});
|
package/dist/esm/styles.js
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
var
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
var _css;
|
|
3
3
|
/* eslint-disable @atlaskit/design-system/ensure-design-token-usage/preview */
|
|
4
4
|
/* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
|
|
5
|
+
/* eslint-disable */
|
|
5
6
|
|
|
6
7
|
// TODO: https://product-fabric.atlassian.net/browse/DSP-4290
|
|
7
8
|
import { css } from '@emotion/react';
|
|
8
|
-
import { B200, B75 } from '@atlaskit/theme/colors';
|
|
9
|
+
import { B200, B75, N40A, N50A, N60A } from '@atlaskit/theme/colors';
|
|
10
|
+
import { getBooleanFF } from '@atlaskit/platform-feature-flags';
|
|
9
11
|
export var searchMatchClass = 'search-match';
|
|
10
12
|
export var selectedSearchMatchClass = 'selected-search-match';
|
|
11
|
-
export var findReplaceStyles = css(
|
|
13
|
+
export var findReplaceStyles = css((_css = {}, _defineProperty(_css, ".".concat(searchMatchClass), getBooleanFF('platform.editor.a11y-find-replace') ? {
|
|
14
|
+
borderRadius: '3px',
|
|
15
|
+
backgroundColor: "var(--ds-background-accent-teal-subtlest, #E7F9FF)",
|
|
16
|
+
boxShadow: "var(--ds-shadow-raised, ".concat("0 1px 1px 0 ".concat(N50A, ", 0 0 1px 0 ").concat(N60A), ")") + ', inset 0 0 0 1px ' + "var(--ds-border-input, ".concat("".concat(N40A), ")")
|
|
17
|
+
} : {
|
|
18
|
+
backgroundColor: B75
|
|
19
|
+
}), _defineProperty(_css, ".".concat(selectedSearchMatchClass), getBooleanFF('platform.editor.a11y-find-replace') ? {
|
|
20
|
+
backgroundColor: "var(--ds-background-accent-teal-subtle, #6CC3E0)"
|
|
21
|
+
} : {
|
|
22
|
+
backgroundColor: B200,
|
|
23
|
+
color: 'white'
|
|
24
|
+
}), _css));
|