@sproutsocial/racine 11.6.1-input-beta.1 → 11.6.1-input-beta.2

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.
@@ -52,9 +52,6 @@ type TypeProps = {
52
52
  | ((React.ElementRef<any> | HTMLElement) => void),
53
53
  onBlur?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
54
54
  onChange?: (e: SyntheticInputEvent<HTMLInputElement>, value: string) => void,
55
- /** Input.ClearButton onClick callback. Required when using Input.ClearButton.
56
- The component handles returning focus to Input after onClear is called.
57
- For controlled Inputs, you must reset "value" yourself.*/
58
55
  onClear?: (e: SyntheticEvent<HTMLButtonElement>) => void,
59
56
  onFocus?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
60
57
  onKeyDown?: (
@@ -82,10 +79,8 @@ type TypeState = {
82
79
  // Using Context so that Input's Input.ClearButton-specific props can be passed to Input.ClearButton,
83
80
  // regardless of whether it is manually included as elemAfter or automatically included for type="search" Inputs.
84
81
  type TypeInputContext = $Shape<{
85
- onClear?: (e: SyntheticEvent<HTMLButtonElement>) => void,
86
82
  handleClear: (e: SyntheticEvent<HTMLButtonElement>) => void,
87
83
  clearButtonLabel: string,
88
- isControlled: boolean,
89
84
  hasValue: boolean,
90
85
  size: "large" | "small" | "default",
91
86
  }>;
@@ -102,10 +97,8 @@ const StyledButton: StyledComponent<any, TypeTheme, *> = styled(Button)`
102
97
 
103
98
  const ClearButton = () => {
104
99
  const {
105
- onClear,
106
100
  handleClear,
107
101
  clearButtonLabel,
108
- isControlled,
109
102
  hasValue,
110
103
  size: inputSize,
111
104
  } = React.useContext(InputContext);
@@ -115,12 +108,6 @@ const ClearButton = () => {
115
108
  return null;
116
109
  }
117
110
 
118
- // Hide the button when no onClear callback is provided to a controlled Input.
119
- // For a controlled component, all the button would do without an onClear is focus the input.
120
- if (isControlled && !onClear) {
121
- return null;
122
- }
123
-
124
111
  // Warn if clearButtonLabel is not included, so that the unlocalized fallback will not be mistaken for a proper label.
125
112
  if (!clearButtonLabel) {
126
113
  console.warn(
@@ -186,15 +173,18 @@ class Input extends React.Component<TypeProps, TypeState> {
186
173
  this.props.onBlur?.(e);
187
174
 
188
175
  handleClear = (e: SyntheticEvent<HTMLButtonElement>) => {
189
- // If the component is uncontrolled, clear its value via ref.
190
- if (typeof this.props.value !== "string") {
191
- if (this.inputRef.current) {
192
- this.inputRef.current.value = "";
193
- }
176
+ const input = this.inputRef.current;
177
+ if (input) {
178
+ // Clear the value via ref, then dispatch an input event in order to trigger handleChange
179
+ input.value = "";
180
+ const inputEvent = new Event("input", { bubbles: true });
181
+ input.dispatchEvent(inputEvent);
182
+
183
+ // Focus the input, update hasValue, and call any onClear callback
184
+ input.focus();
185
+ this.updateState("");
186
+ this.props.onClear?.(e);
194
187
  }
195
- this.inputRef.current?.focus();
196
- this.props.onClear?.(e);
197
- this.updateState("");
198
188
  };
199
189
 
200
190
  handleChange = (e: SyntheticInputEvent<HTMLInputElement>) => {
@@ -214,11 +204,11 @@ class Input extends React.Component<TypeProps, TypeState> {
214
204
  handlePaste = (e: SyntheticInputEvent<HTMLInputElement>) =>
215
205
  this.props.onPaste?.(e, e.currentTarget.value);
216
206
 
217
- updateState = (value: string) => {
218
- const hasValue = value !== "";
219
- const hadValue = this.state.hasValue;
220
- // Only update state if the value has changed to avoid unnecessary renders.
221
- if (hasValue !== hadValue) {
207
+ updateState = (inputValue: string) => {
208
+ const hasValue = inputValue !== "";
209
+ const previousHasValue = this.state.hasValue;
210
+ // Only update state if the value of `hasValue` has changed to avoid unnecessary renders.
211
+ if (hasValue !== previousHasValue) {
222
212
  this.setState({ hasValue });
223
213
  }
224
214
  };
@@ -291,9 +281,7 @@ class Input extends React.Component<TypeProps, TypeState> {
291
281
  value={{
292
282
  handleClear: this.handleClear,
293
283
  hasValue: this.state.hasValue,
294
- isControlled: typeof this.props.value === "string",
295
284
  clearButtonLabel,
296
- onClear,
297
285
  size,
298
286
  }}
299
287
  >
@@ -85,13 +85,12 @@ describe("Input", () => {
85
85
  expect(getByRole("button")).toBeTruthy();
86
86
  });
87
87
 
88
- it("should render a clear button for an uncontrolled search Input only once it is typed in", () => {
88
+ it("should render a clear button for an uncontrolled search Input only when it has text", () => {
89
89
  const { getByRole, queryByRole } = render(
90
90
  <Input
91
91
  id="name"
92
92
  name="name"
93
93
  type="search"
94
- onClear={jest.fn()}
95
94
  clearButtonLabel="Clear search"
96
95
  />
97
96
  );
@@ -101,6 +100,9 @@ describe("Input", () => {
101
100
  expect(input).toHaveFocus();
102
101
  userEvent.keyboard("some text");
103
102
  expect(getByRole("button")).toBeTruthy();
103
+ userEvent.tab();
104
+ userEvent.keyboard("{enter}");
105
+ expect(queryByRole("button")).toBeFalsy();
104
106
  });
105
107
 
106
108
  it("should not render a clear button for search Inputs if there is no text", () => {
@@ -41,22 +41,14 @@ var StyledButton = (0, _styledComponents.default)(_Button.default).withConfig({
41
41
 
42
42
  var ClearButton = function ClearButton() {
43
43
  var _React$useContext = React.useContext(InputContext),
44
- onClear = _React$useContext.onClear,
45
44
  handleClear = _React$useContext.handleClear,
46
45
  clearButtonLabel = _React$useContext.clearButtonLabel,
47
- isControlled = _React$useContext.isControlled,
48
46
  hasValue = _React$useContext.hasValue,
49
47
  inputSize = _React$useContext.size; // Hide the button when there is no text to clear.
50
48
 
51
49
 
52
50
  if (!hasValue) {
53
51
  return null;
54
- } // Hide the button when no onClear callback is provided to a controlled Input.
55
- // For a controlled component, all the button would do without an onClear is focus the input.
56
-
57
-
58
- if (isControlled && !onClear) {
59
- return null;
60
52
  } // Warn if clearButtonLabel is not included, so that the unlocalized fallback will not be mistaken for a proper label.
61
53
 
62
54
 
@@ -106,19 +98,22 @@ var Input = /*#__PURE__*/function (_React$Component) {
106
98
  };
107
99
 
108
100
  _this.handleClear = function (e) {
109
- var _this$inputRef$curren;
101
+ var input = _this.inputRef.current;
110
102
 
111
- // If the component is uncontrolled, clear its value via ref.
112
- if (typeof _this.props.value !== "string") {
113
- if (_this.inputRef.current) {
114
- _this.inputRef.current.value = "";
115
- }
116
- }
103
+ if (input) {
104
+ // Clear the value via ref, then dispatch an input event in order to trigger handleChange
105
+ input.value = "";
106
+ var inputEvent = new Event("input", {
107
+ bubbles: true
108
+ });
109
+ input.dispatchEvent(inputEvent); // Focus the input, update hasValue, and call any onClear callback
110
+
111
+ input.focus();
117
112
 
118
- (_this$inputRef$curren = _this.inputRef.current) == null ? void 0 : _this$inputRef$curren.focus();
119
- _this.props.onClear == null ? void 0 : _this.props.onClear(e);
113
+ _this.updateState("");
120
114
 
121
- _this.updateState("");
115
+ _this.props.onClear == null ? void 0 : _this.props.onClear(e);
116
+ }
122
117
  };
123
118
 
124
119
  _this.handleChange = function (e) {
@@ -143,11 +138,11 @@ var Input = /*#__PURE__*/function (_React$Component) {
143
138
  return _this.props.onPaste == null ? void 0 : _this.props.onPaste(e, e.currentTarget.value);
144
139
  };
145
140
 
146
- _this.updateState = function (value) {
147
- var hasValue = value !== "";
148
- var hadValue = _this.state.hasValue; // Only update state if the value has changed to avoid unnecessary renders.
141
+ _this.updateState = function (inputValue) {
142
+ var hasValue = inputValue !== "";
143
+ var previousHasValue = _this.state.hasValue; // Only update state if the value of `hasValue` has changed to avoid unnecessary renders.
149
144
 
150
- if (hasValue !== hadValue) {
145
+ if (hasValue !== previousHasValue) {
151
146
  _this.setState({
152
147
  hasValue: hasValue
153
148
  });
@@ -228,9 +223,7 @@ var Input = /*#__PURE__*/function (_React$Component) {
228
223
  value: {
229
224
  handleClear: this.handleClear,
230
225
  hasValue: this.state.hasValue,
231
- isControlled: typeof this.props.value === "string",
232
226
  clearButtonLabel: clearButtonLabel,
233
- onClear: onClear,
234
227
  size: size
235
228
  }
236
229
  }, elementBefore && /*#__PURE__*/React.createElement(_styles.Accessory, {
@@ -24,22 +24,14 @@ var StyledButton = styled(Button).withConfig({
24
24
 
25
25
  var ClearButton = function ClearButton() {
26
26
  var _React$useContext = React.useContext(InputContext),
27
- onClear = _React$useContext.onClear,
28
27
  handleClear = _React$useContext.handleClear,
29
28
  clearButtonLabel = _React$useContext.clearButtonLabel,
30
- isControlled = _React$useContext.isControlled,
31
29
  hasValue = _React$useContext.hasValue,
32
30
  inputSize = _React$useContext.size; // Hide the button when there is no text to clear.
33
31
 
34
32
 
35
33
  if (!hasValue) {
36
34
  return null;
37
- } // Hide the button when no onClear callback is provided to a controlled Input.
38
- // For a controlled component, all the button would do without an onClear is focus the input.
39
-
40
-
41
- if (isControlled && !onClear) {
42
- return null;
43
35
  } // Warn if clearButtonLabel is not included, so that the unlocalized fallback will not be mistaken for a proper label.
44
36
 
45
37
 
@@ -89,19 +81,22 @@ var Input = /*#__PURE__*/function (_React$Component) {
89
81
  };
90
82
 
91
83
  _this.handleClear = function (e) {
92
- var _this$inputRef$curren;
84
+ var input = _this.inputRef.current;
93
85
 
94
- // If the component is uncontrolled, clear its value via ref.
95
- if (typeof _this.props.value !== "string") {
96
- if (_this.inputRef.current) {
97
- _this.inputRef.current.value = "";
98
- }
99
- }
86
+ if (input) {
87
+ // Clear the value via ref, then dispatch an input event in order to trigger handleChange
88
+ input.value = "";
89
+ var inputEvent = new Event("input", {
90
+ bubbles: true
91
+ });
92
+ input.dispatchEvent(inputEvent); // Focus the input, update hasValue, and call any onClear callback
93
+
94
+ input.focus();
100
95
 
101
- (_this$inputRef$curren = _this.inputRef.current) == null ? void 0 : _this$inputRef$curren.focus();
102
- _this.props.onClear == null ? void 0 : _this.props.onClear(e);
96
+ _this.updateState("");
103
97
 
104
- _this.updateState("");
98
+ _this.props.onClear == null ? void 0 : _this.props.onClear(e);
99
+ }
105
100
  };
106
101
 
107
102
  _this.handleChange = function (e) {
@@ -126,11 +121,11 @@ var Input = /*#__PURE__*/function (_React$Component) {
126
121
  return _this.props.onPaste == null ? void 0 : _this.props.onPaste(e, e.currentTarget.value);
127
122
  };
128
123
 
129
- _this.updateState = function (value) {
130
- var hasValue = value !== "";
131
- var hadValue = _this.state.hasValue; // Only update state if the value has changed to avoid unnecessary renders.
124
+ _this.updateState = function (inputValue) {
125
+ var hasValue = inputValue !== "";
126
+ var previousHasValue = _this.state.hasValue; // Only update state if the value of `hasValue` has changed to avoid unnecessary renders.
132
127
 
133
- if (hasValue !== hadValue) {
128
+ if (hasValue !== previousHasValue) {
134
129
  _this.setState({
135
130
  hasValue: hasValue
136
131
  });
@@ -211,9 +206,7 @@ var Input = /*#__PURE__*/function (_React$Component) {
211
206
  value: {
212
207
  handleClear: this.handleClear,
213
208
  hasValue: this.state.hasValue,
214
- isControlled: typeof this.props.value === "string",
215
209
  clearButtonLabel: clearButtonLabel,
216
- onClear: onClear,
217
210
  size: size
218
211
  }
219
212
  }, elementBefore && /*#__PURE__*/React.createElement(Accessory, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/racine",
3
- "version": "11.6.1-input-beta.1",
3
+ "version": "11.6.1-input-beta.2",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "__flow__",