@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.
@@ -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
@@ -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; // Hide the button when there is no text to clear.
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
- return _this.props.onClear == null ? void 0 : _this.props.onClear(e);
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 // $FlowIssue - upgrade v0.112.0
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
- hasValue: !!value
188
+ size: size
168
189
  }
169
190
  }, elementBefore && /*#__PURE__*/React.createElement(_styles.Accessory, {
170
191
  before: true
@@ -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; // Hide the button when there is no text to clear.
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
- return _this.props.onClear == null ? void 0 : _this.props.onClear(e);
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 // $FlowIssue - upgrade v0.112.0
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
- hasValue: !!value
173
+ size: size
153
174
  }
154
175
  }, elementBefore && /*#__PURE__*/React.createElement(Accessory, {
155
176
  before: true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/racine",
3
- "version": "11.3.0-beta.2",
3
+ "version": "11.3.0-beta.3",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "__flow__",