@sproutsocial/racine 11.3.0-beta.2 → 11.3.0-beta.3
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/__flow__/Input/index.js +23 -7
- package/__flow__/Input/index.stories.js +33 -1
- package/__flow__/Input/index.test.js +28 -0
- package/commonjs/Input/index.js +28 -7
- package/lib/Input/index.js +28 -7
- package/package.json +1 -1
package/__flow__/Input/index.js
CHANGED
|
@@ -78,17 +78,28 @@ type TypeInputContext = $Shape<{
|
|
|
78
78
|
const InputContext = React.createContext<TypeInputContext>({});
|
|
79
79
|
|
|
80
80
|
const ClearButton = () => {
|
|
81
|
-
const { handleClear, clearButtonLabel, hasValue } =
|
|
81
|
+
const { handleClear, clearButtonLabel, hasValue, size } =
|
|
82
82
|
React.useContext(InputContext);
|
|
83
83
|
|
|
84
84
|
// Hide the button when there is no text to clear.
|
|
85
85
|
if (!hasValue) {
|
|
86
86
|
return null;
|
|
87
87
|
}
|
|
88
|
+
|
|
89
|
+
// Cut down the padding for size small Inputs so that the focus ring won't go outside the bounds of the Input.
|
|
90
|
+
// This adjustment is handled automatically for default and large Inputs via Button's size. There is no "small" Button.
|
|
91
|
+
const py = size === "small" ? 100 : undefined;
|
|
92
|
+
const px = size === "small" ? 200 : undefined;
|
|
93
|
+
const buttonSize = size === "small" ? "default" : size;
|
|
94
|
+
|
|
95
|
+
// Warn if clearButtonLabel is not included, so that the unlocalized fallback will not be mistaken for a proper label.
|
|
96
|
+
if (!clearButtonLabel) {
|
|
97
|
+
console.warn(
|
|
98
|
+
"Warning: clearButtonLabel prop is required when using Input.ClearButton. Please pass a localized label to Input."
|
|
99
|
+
);
|
|
100
|
+
}
|
|
88
101
|
return (
|
|
89
|
-
<Button onClick={handleClear}>
|
|
90
|
-
{/*Unlocalized fallback should not be used. Always include a localized
|
|
91
|
-
clearButtonLabel when using <Input.ClearButton/> or <Input type="search"/>.*/}
|
|
102
|
+
<Button onClick={handleClear} size={buttonSize} py={py} px={px}>
|
|
92
103
|
<Icon name="circlex" title={clearButtonLabel || "Clear"} />
|
|
93
104
|
</Button>
|
|
94
105
|
);
|
|
@@ -117,8 +128,10 @@ class Input extends React.Component<TypeProps> {
|
|
|
117
128
|
handleBlur = (e: SyntheticFocusEvent<HTMLInputElement>) =>
|
|
118
129
|
this.props.onBlur?.(e);
|
|
119
130
|
|
|
120
|
-
handleClear = (e: SyntheticEvent<HTMLButtonElement>) =>
|
|
131
|
+
handleClear = (e: SyntheticEvent<HTMLButtonElement>) => {
|
|
121
132
|
this.props.onClear?.(e);
|
|
133
|
+
this.props.innerRef?.current?.focus();
|
|
134
|
+
};
|
|
122
135
|
|
|
123
136
|
handleChange = (e: SyntheticInputEvent<HTMLInputElement>) =>
|
|
124
137
|
this.props.onChange?.(e, e.currentTarget.value);
|
|
@@ -166,6 +179,7 @@ class Input extends React.Component<TypeProps> {
|
|
|
166
179
|
inputProps = {},
|
|
167
180
|
qa = {},
|
|
168
181
|
appearance,
|
|
182
|
+
size,
|
|
169
183
|
...rest
|
|
170
184
|
} = this.props;
|
|
171
185
|
|
|
@@ -178,7 +192,7 @@ class Input extends React.Component<TypeProps> {
|
|
|
178
192
|
// Add default elemBefore and elemAfter elements if type is search.
|
|
179
193
|
const elementBefore =
|
|
180
194
|
type === "search" && !elemBefore ? (
|
|
181
|
-
<Icon name="search" ariaHidden />
|
|
195
|
+
<Icon name="search" ariaHidden color="icon.base" />
|
|
182
196
|
) : (
|
|
183
197
|
elemBefore
|
|
184
198
|
);
|
|
@@ -194,14 +208,16 @@ class Input extends React.Component<TypeProps> {
|
|
|
194
208
|
invalid={!!isInvalid}
|
|
195
209
|
warning={hasWarning}
|
|
196
210
|
appearance={appearance}
|
|
211
|
+
size={size}
|
|
197
212
|
// $FlowIssue - upgrade v0.112.0
|
|
198
213
|
{...rest}
|
|
199
214
|
>
|
|
200
215
|
<InputContext.Provider
|
|
201
216
|
value={{
|
|
202
217
|
handleClear: this.handleClear,
|
|
203
|
-
clearButtonLabel,
|
|
204
218
|
hasValue: !!value,
|
|
219
|
+
clearButtonLabel,
|
|
220
|
+
size,
|
|
205
221
|
}}
|
|
206
222
|
>
|
|
207
223
|
{elementBefore && <Accessory before>{elementBefore}</Accessory>}
|
|
@@ -156,6 +156,38 @@ searchInput.story = {
|
|
|
156
156
|
name: "Search Input",
|
|
157
157
|
};
|
|
158
158
|
|
|
159
|
+
export const smallSearchInput = () => (
|
|
160
|
+
<Input
|
|
161
|
+
type="search"
|
|
162
|
+
size="small"
|
|
163
|
+
placeholder={text("placeholder", "Please enter a value...")}
|
|
164
|
+
value={text("value", "val")}
|
|
165
|
+
onClear={() => window.alert("Cleared!")}
|
|
166
|
+
clearButtonLabel={text("clearButtonLabel", "Clear search")}
|
|
167
|
+
ariaLabel={text("ariaLabel", "Descriptive label goes here")}
|
|
168
|
+
/>
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
smallSearchInput.story = {
|
|
172
|
+
name: "Small Search Input",
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export const largeSearchInput = () => (
|
|
176
|
+
<Input
|
|
177
|
+
type="search"
|
|
178
|
+
size="large"
|
|
179
|
+
placeholder={text("placeholder", "Please enter a value...")}
|
|
180
|
+
value={text("value", "val")}
|
|
181
|
+
onClear={() => window.alert("Cleared!")}
|
|
182
|
+
clearButtonLabel={text("clearButtonLabel", "Clear search")}
|
|
183
|
+
ariaLabel={text("ariaLabel", "Descriptive label goes here")}
|
|
184
|
+
/>
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
largeSearchInput.story = {
|
|
188
|
+
name: "Large Search Input",
|
|
189
|
+
};
|
|
190
|
+
|
|
159
191
|
export const nonSearchClearButtonInput = () => {
|
|
160
192
|
return (
|
|
161
193
|
<Input
|
|
@@ -171,7 +203,7 @@ export const nonSearchClearButtonInput = () => {
|
|
|
171
203
|
};
|
|
172
204
|
|
|
173
205
|
nonSearchClearButtonInput.story = {
|
|
174
|
-
name: "Input.ClearButton usage",
|
|
206
|
+
name: "Manual Input.ClearButton usage",
|
|
175
207
|
};
|
|
176
208
|
|
|
177
209
|
export const autofocus = () => (
|
|
@@ -85,6 +85,20 @@ describe("Input", () => {
|
|
|
85
85
|
expect(getByRole("button")).toBeTruthy();
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
it("should not render a clear button for search Inputs if there is no text", () => {
|
|
89
|
+
const { queryByRole } = render(
|
|
90
|
+
<Input
|
|
91
|
+
id="name"
|
|
92
|
+
name="name"
|
|
93
|
+
value=""
|
|
94
|
+
type="search"
|
|
95
|
+
onClear={jest.fn()}
|
|
96
|
+
clearButtonLabel="Clear search"
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
expect(queryByRole("button")).toBeFalsy();
|
|
100
|
+
});
|
|
101
|
+
|
|
88
102
|
it("should not override an elemAfter prop if passed", () => {
|
|
89
103
|
const { getByText, queryByTitle } = render(
|
|
90
104
|
<Input
|
|
@@ -189,6 +203,20 @@ describe("Input", () => {
|
|
|
189
203
|
expect(getByRole("button")).toBeTruthy();
|
|
190
204
|
});
|
|
191
205
|
|
|
206
|
+
it("should not render a clear button if there is no text", () => {
|
|
207
|
+
const { queryByRole } = render(
|
|
208
|
+
<Input
|
|
209
|
+
id="name"
|
|
210
|
+
name="name"
|
|
211
|
+
value=""
|
|
212
|
+
type="text"
|
|
213
|
+
elemAfter={<Input.ClearButton />}
|
|
214
|
+
clearButtonLabel="Clear search"
|
|
215
|
+
/>
|
|
216
|
+
);
|
|
217
|
+
expect(queryByRole("button")).toBeFalsy();
|
|
218
|
+
});
|
|
219
|
+
|
|
192
220
|
it("should use the fallback title if clearButtonLabel is not provided", () => {
|
|
193
221
|
const { getByTitle } = render(
|
|
194
222
|
<Input
|
package/commonjs/Input/index.js
CHANGED
|
@@ -11,7 +11,7 @@ var _Button = _interopRequireDefault(require("../Button"));
|
|
|
11
11
|
|
|
12
12
|
var _Icon = _interopRequireDefault(require("../Icon"));
|
|
13
13
|
|
|
14
|
-
var _excluded = ["autoComplete", "autoFocus", "disabled", "readOnly", "isInvalid", "hasWarning", "id", "name", "placeholder", "type", "required", "value", "elemBefore", "elemAfter", "maxLength", "ariaLabel", "ariaDescribedby", "clearButtonLabel", "innerRef", "onBlur", "onChange", "onClear", "onFocus", "onKeyDown", "onKeyUp", "onPaste", "inputProps", "qa", "appearance"];
|
|
14
|
+
var _excluded = ["autoComplete", "autoFocus", "disabled", "readOnly", "isInvalid", "hasWarning", "id", "name", "placeholder", "type", "required", "value", "elemBefore", "elemAfter", "maxLength", "ariaLabel", "ariaDescribedby", "clearButtonLabel", "innerRef", "onBlur", "onChange", "onClear", "onFocus", "onKeyDown", "onKeyUp", "onPaste", "inputProps", "qa", "appearance", "size"];
|
|
15
15
|
|
|
16
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
17
|
|
|
@@ -33,15 +33,29 @@ var ClearButton = function ClearButton() {
|
|
|
33
33
|
var _React$useContext = React.useContext(InputContext),
|
|
34
34
|
handleClear = _React$useContext.handleClear,
|
|
35
35
|
clearButtonLabel = _React$useContext.clearButtonLabel,
|
|
36
|
-
hasValue = _React$useContext.hasValue
|
|
36
|
+
hasValue = _React$useContext.hasValue,
|
|
37
|
+
size = _React$useContext.size; // Hide the button when there is no text to clear.
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
if (!hasValue) {
|
|
40
41
|
return null;
|
|
42
|
+
} // Cut down the padding for size small Inputs so that the focus ring won't go outside the bounds of the Input.
|
|
43
|
+
// This adjustment is handled automatically for default and large Inputs via Button's size. There is no "small" Button.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
var py = size === "small" ? 100 : undefined;
|
|
47
|
+
var px = size === "small" ? 200 : undefined;
|
|
48
|
+
var buttonSize = size === "small" ? "default" : size; // Warn if clearButtonLabel is not included, so that the unlocalized fallback will not be mistaken for a proper label.
|
|
49
|
+
|
|
50
|
+
if (!clearButtonLabel) {
|
|
51
|
+
console.warn("Warning: clearButtonLabel prop is required when using Input.ClearButton. Please pass a localized label to Input.");
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
return /*#__PURE__*/React.createElement(_Button.default, {
|
|
44
|
-
onClick: handleClear
|
|
55
|
+
onClick: handleClear,
|
|
56
|
+
size: buttonSize,
|
|
57
|
+
py: py,
|
|
58
|
+
px: px
|
|
45
59
|
}, /*#__PURE__*/React.createElement(_Icon.default, {
|
|
46
60
|
name: "circlex",
|
|
47
61
|
title: clearButtonLabel || "Clear"
|
|
@@ -75,7 +89,10 @@ var Input = /*#__PURE__*/function (_React$Component) {
|
|
|
75
89
|
};
|
|
76
90
|
|
|
77
91
|
_this.handleClear = function (e) {
|
|
78
|
-
|
|
92
|
+
var _this$props$innerRef, _this$props$innerRef$;
|
|
93
|
+
|
|
94
|
+
_this.props.onClear == null ? void 0 : _this.props.onClear(e);
|
|
95
|
+
(_this$props$innerRef = _this.props.innerRef) == null ? void 0 : (_this$props$innerRef$ = _this$props$innerRef.current) == null ? void 0 : _this$props$innerRef$.focus();
|
|
79
96
|
};
|
|
80
97
|
|
|
81
98
|
_this.handleChange = function (e) {
|
|
@@ -136,6 +153,7 @@ var Input = /*#__PURE__*/function (_React$Component) {
|
|
|
136
153
|
_this$props$qa = _this$props.qa,
|
|
137
154
|
qa = _this$props$qa === void 0 ? {} : _this$props$qa,
|
|
138
155
|
appearance = _this$props.appearance,
|
|
156
|
+
size = _this$props.size,
|
|
139
157
|
rest = _objectWithoutPropertiesLoose(_this$props, _excluded); // Convert autoComplete from a boolean prop to a string value.
|
|
140
158
|
|
|
141
159
|
|
|
@@ -148,7 +166,8 @@ var Input = /*#__PURE__*/function (_React$Component) {
|
|
|
148
166
|
|
|
149
167
|
var elementBefore = type === "search" && !elemBefore ? /*#__PURE__*/React.createElement(_Icon.default, {
|
|
150
168
|
name: "search",
|
|
151
|
-
ariaHidden: true
|
|
169
|
+
ariaHidden: true,
|
|
170
|
+
color: "icon.base"
|
|
152
171
|
}) : elemBefore; // Do not add a ClearButton if no onClear callback is provided or if an elemAfter prop was passed.
|
|
153
172
|
|
|
154
173
|
var elementAfter = type === "search" && onClear && !elemAfter ? /*#__PURE__*/React.createElement(ClearButton, null) : elemAfter;
|
|
@@ -158,13 +177,15 @@ var Input = /*#__PURE__*/function (_React$Component) {
|
|
|
158
177
|
disabled: disabled,
|
|
159
178
|
invalid: !!isInvalid,
|
|
160
179
|
warning: hasWarning,
|
|
161
|
-
appearance: appearance
|
|
180
|
+
appearance: appearance,
|
|
181
|
+
size: size // $FlowIssue - upgrade v0.112.0
|
|
162
182
|
|
|
163
183
|
}, rest), /*#__PURE__*/React.createElement(InputContext.Provider, {
|
|
164
184
|
value: {
|
|
165
185
|
handleClear: this.handleClear,
|
|
186
|
+
hasValue: !!value,
|
|
166
187
|
clearButtonLabel: clearButtonLabel,
|
|
167
|
-
|
|
188
|
+
size: size
|
|
168
189
|
}
|
|
169
190
|
}, elementBefore && /*#__PURE__*/React.createElement(_styles.Accessory, {
|
|
170
191
|
before: true
|
package/lib/Input/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var _excluded = ["autoComplete", "autoFocus", "disabled", "readOnly", "isInvalid", "hasWarning", "id", "name", "placeholder", "type", "required", "value", "elemBefore", "elemAfter", "maxLength", "ariaLabel", "ariaDescribedby", "clearButtonLabel", "innerRef", "onBlur", "onChange", "onClear", "onFocus", "onKeyDown", "onKeyUp", "onPaste", "inputProps", "qa", "appearance"];
|
|
1
|
+
var _excluded = ["autoComplete", "autoFocus", "disabled", "readOnly", "isInvalid", "hasWarning", "id", "name", "placeholder", "type", "required", "value", "elemBefore", "elemAfter", "maxLength", "ariaLabel", "ariaDescribedby", "clearButtonLabel", "innerRef", "onBlur", "onChange", "onClear", "onFocus", "onKeyDown", "onKeyUp", "onPaste", "inputProps", "qa", "appearance", "size"];
|
|
2
2
|
|
|
3
3
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
4
4
|
|
|
@@ -18,15 +18,29 @@ var ClearButton = function ClearButton() {
|
|
|
18
18
|
var _React$useContext = React.useContext(InputContext),
|
|
19
19
|
handleClear = _React$useContext.handleClear,
|
|
20
20
|
clearButtonLabel = _React$useContext.clearButtonLabel,
|
|
21
|
-
hasValue = _React$useContext.hasValue
|
|
21
|
+
hasValue = _React$useContext.hasValue,
|
|
22
|
+
size = _React$useContext.size; // Hide the button when there is no text to clear.
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
if (!hasValue) {
|
|
25
26
|
return null;
|
|
27
|
+
} // Cut down the padding for size small Inputs so that the focus ring won't go outside the bounds of the Input.
|
|
28
|
+
// This adjustment is handled automatically for default and large Inputs via Button's size. There is no "small" Button.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
var py = size === "small" ? 100 : undefined;
|
|
32
|
+
var px = size === "small" ? 200 : undefined;
|
|
33
|
+
var buttonSize = size === "small" ? "default" : size; // Warn if clearButtonLabel is not included, so that the unlocalized fallback will not be mistaken for a proper label.
|
|
34
|
+
|
|
35
|
+
if (!clearButtonLabel) {
|
|
36
|
+
console.warn("Warning: clearButtonLabel prop is required when using Input.ClearButton. Please pass a localized label to Input.");
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
return /*#__PURE__*/React.createElement(Button, {
|
|
29
|
-
onClick: handleClear
|
|
40
|
+
onClick: handleClear,
|
|
41
|
+
size: buttonSize,
|
|
42
|
+
py: py,
|
|
43
|
+
px: px
|
|
30
44
|
}, /*#__PURE__*/React.createElement(Icon, {
|
|
31
45
|
name: "circlex",
|
|
32
46
|
title: clearButtonLabel || "Clear"
|
|
@@ -60,7 +74,10 @@ var Input = /*#__PURE__*/function (_React$Component) {
|
|
|
60
74
|
};
|
|
61
75
|
|
|
62
76
|
_this.handleClear = function (e) {
|
|
63
|
-
|
|
77
|
+
var _this$props$innerRef, _this$props$innerRef$;
|
|
78
|
+
|
|
79
|
+
_this.props.onClear == null ? void 0 : _this.props.onClear(e);
|
|
80
|
+
(_this$props$innerRef = _this.props.innerRef) == null ? void 0 : (_this$props$innerRef$ = _this$props$innerRef.current) == null ? void 0 : _this$props$innerRef$.focus();
|
|
64
81
|
};
|
|
65
82
|
|
|
66
83
|
_this.handleChange = function (e) {
|
|
@@ -121,6 +138,7 @@ var Input = /*#__PURE__*/function (_React$Component) {
|
|
|
121
138
|
_this$props$qa = _this$props.qa,
|
|
122
139
|
qa = _this$props$qa === void 0 ? {} : _this$props$qa,
|
|
123
140
|
appearance = _this$props.appearance,
|
|
141
|
+
size = _this$props.size,
|
|
124
142
|
rest = _objectWithoutPropertiesLoose(_this$props, _excluded); // Convert autoComplete from a boolean prop to a string value.
|
|
125
143
|
|
|
126
144
|
|
|
@@ -133,7 +151,8 @@ var Input = /*#__PURE__*/function (_React$Component) {
|
|
|
133
151
|
|
|
134
152
|
var elementBefore = type === "search" && !elemBefore ? /*#__PURE__*/React.createElement(Icon, {
|
|
135
153
|
name: "search",
|
|
136
|
-
ariaHidden: true
|
|
154
|
+
ariaHidden: true,
|
|
155
|
+
color: "icon.base"
|
|
137
156
|
}) : elemBefore; // Do not add a ClearButton if no onClear callback is provided or if an elemAfter prop was passed.
|
|
138
157
|
|
|
139
158
|
var elementAfter = type === "search" && onClear && !elemAfter ? /*#__PURE__*/React.createElement(ClearButton, null) : elemAfter;
|
|
@@ -143,13 +162,15 @@ var Input = /*#__PURE__*/function (_React$Component) {
|
|
|
143
162
|
disabled: disabled,
|
|
144
163
|
invalid: !!isInvalid,
|
|
145
164
|
warning: hasWarning,
|
|
146
|
-
appearance: appearance
|
|
165
|
+
appearance: appearance,
|
|
166
|
+
size: size // $FlowIssue - upgrade v0.112.0
|
|
147
167
|
|
|
148
168
|
}, rest), /*#__PURE__*/React.createElement(InputContext.Provider, {
|
|
149
169
|
value: {
|
|
150
170
|
handleClear: this.handleClear,
|
|
171
|
+
hasValue: !!value,
|
|
151
172
|
clearButtonLabel: clearButtonLabel,
|
|
152
|
-
|
|
173
|
+
size: size
|
|
153
174
|
}
|
|
154
175
|
}, elementBefore && /*#__PURE__*/React.createElement(Accessory, {
|
|
155
176
|
before: true
|