orc-shared 1.5.0-dev.12 → 1.5.0-dev.13

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.
@@ -21,12 +21,6 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
21
21
  var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
22
22
  enterModule && enterModule(module);
23
23
  })();
24
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
25
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
26
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
27
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
28
- function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
29
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
30
24
  var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) {
31
25
  return a;
32
26
  };
@@ -107,15 +101,9 @@ var useStyles = (0, _styles.makeStyles)(function (theme) {
107
101
  },
108
102
  parentInput: {
109
103
  flex: "13 0 0",
110
- zIndex: function zIndex(props) {
111
- return props.focused ? 99 : 1;
112
- },
113
- border: function border(props) {
114
- return props.focused ? "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.focus) : "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.grey.borders);
115
- },
116
- boxShadow: function boxShadow(props) {
117
- return props.focused ? "0 0 4px ".concat(theme.palette.focus) : "none";
118
- },
104
+ zIndex: 1,
105
+ border: "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.grey.borders),
106
+ boxShadow: "none",
119
107
  width: "100%",
120
108
  display: "inherit",
121
109
  marginLeft: theme.spacing(-0.1),
@@ -133,6 +121,11 @@ var useStyles = (0, _styles.makeStyles)(function (theme) {
133
121
  borderTopLeftRadius: 0,
134
122
  borderBottomLeftRadius: 0
135
123
  }
124
+ },
125
+ "&:focus-within": {
126
+ zIndex: 99,
127
+ border: "".concat(theme.spacing(0.1), " solid ").concat(theme.palette.focus),
128
+ boxShadow: "0 0 4px ".concat(theme.palette.focus)
136
129
  }
137
130
  },
138
131
  selectRoot: {
@@ -184,19 +177,27 @@ var SearchControl = function SearchControl(_ref) {
184
177
  onSearch = _ref$onSearch === void 0 ? function () {} : _ref$onSearch,
185
178
  disabled = _ref.disabled,
186
179
  _ref$focusAndSelectSe = _ref.focusAndSelectSearchFieldOnLoad,
187
- focusAndSelectSearchFieldOnLoad = _ref$focusAndSelectSe === void 0 ? true : _ref$focusAndSelectSe;
180
+ focusAndSelectSearchFieldOnLoad = _ref$focusAndSelectSe === void 0 ? true : _ref$focusAndSelectSe,
181
+ _ref$focusSearchOnSea = _ref.focusSearchOnSearchOptionChange,
182
+ focusSearchOnSearchOptionChange = _ref$focusSearchOnSea === void 0 ? false : _ref$focusSearchOnSea;
188
183
  searchOptions = !((_searchOptions = searchOptions) != null && _searchOptions.length) ? null : searchOptions;
189
184
  searchOption = getSearchOptionValue(searchOptions, searchOption);
190
- var _useState = (0, _react.useState)(false),
191
- _useState2 = _slicedToArray(_useState, 2),
192
- inputFocused = _useState2[0],
193
- setInputFocused = _useState2[1];
194
- var classes = useStyles({
195
- focused: inputFocused
196
- });
185
+ var classes = useStyles();
197
186
  var inputRef = (0, _react.useRef)();
198
187
  var update = function update(value) {
199
- onSearch(value, defaultValue);
188
+ if (focusSearchOnSearchOptionChange && inputRef.current) {
189
+ onSearch(value, "");
190
+ setTimeout(function () {
191
+ /* istanbul ignore next */
192
+ if (inputRef.current) {
193
+ inputRef.current.value = "";
194
+ inputRef.current.focus();
195
+ inputRef.current.select();
196
+ }
197
+ }, 0);
198
+ } else {
199
+ onSearch(value, defaultValue);
200
+ }
200
201
  };
201
202
  var selectProps = new _SelectProps.default();
202
203
  selectProps.set(_SelectProps.default.propNames.update, update);
@@ -213,23 +214,11 @@ var SearchControl = function SearchControl(_ref) {
213
214
  });
214
215
  selectProps.setStyle(_SelectProps.default.ruleNames.root, classes.selectRoot);
215
216
  selectProps.setStyle(_SelectProps.default.ruleNames.paper, classes.selectPaper);
216
- var handleKeyDown = function handleKeyDown(e) {
217
- if (e.key === "Enter") {
218
- onSearch(searchOption, e.target.value);
219
- e.preventDefault();
220
- e.stopPropagation();
221
- }
222
- };
223
- var onFocusedEvent = function onFocusedEvent(event, focused) {
224
- setInputFocused(focused);
225
- event.preventDefault();
226
- event.stopPropagation();
227
- };
228
217
  (0, _react.useEffect)(function () {
218
+ /* istanbul ignore next */
229
219
  if (focusAndSelectSearchFieldOnLoad && inputRef.current) {
230
220
  inputRef.current.focus();
231
221
  inputRef.current.select();
232
- setInputFocused(true);
233
222
  }
234
223
  }, [focusAndSelectSearchFieldOnLoad]);
235
224
  var SelectSection = function SelectSection() {
@@ -239,13 +228,19 @@ var SearchControl = function SearchControl(_ref) {
239
228
  selectProps: selectProps
240
229
  });
241
230
  };
231
+ var onSubmit = function onSubmit(event) {
232
+ var _inputRef$current;
233
+ // using form submit instead of a keydown (with key=enter) to allow the 'enter key' event to be canceled elsewhere to avoid the submit event
234
+ onSearch(searchOption, (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.value);
235
+ event.preventDefault();
236
+ };
242
237
  var inputSection = /*#__PURE__*/_react.default.createElement("div", {
243
238
  "data-qa": "searchInput",
244
- "data-qa-is-focused": inputFocused,
245
239
  className: classes.parentInput
246
240
  }, /*#__PURE__*/_react.default.createElement("form", {
247
241
  "data-qa": "searchForm",
248
- className: classes.fullWidth
242
+ className: classes.fullWidth,
243
+ onSubmitCapture: onSubmit
249
244
  }, /*#__PURE__*/_react.default.createElement(_Input.default, {
250
245
  placeholder: placeholder,
251
246
  defaultValue: defaultValue,
@@ -255,14 +250,7 @@ var SearchControl = function SearchControl(_ref) {
255
250
  classes: {
256
251
  input: classes.controlInput
257
252
  },
258
- onKeyDown: handleKeyDown,
259
253
  disableUnderline: true,
260
- onFocus: function onFocus(e) {
261
- return onFocusedEvent(e, true);
262
- },
263
- onBlur: function onBlur(e) {
264
- return onFocusedEvent(e, false);
265
- },
266
254
  endAdornment: /*#__PURE__*/_react.default.createElement(_InputAdornment.default, {
267
255
  position: "start"
268
256
  }, /*#__PURE__*/_react.default.createElement(_IconButton.default, {
@@ -296,10 +284,10 @@ var SearchControl = function SearchControl(_ref) {
296
284
  className: classes.container
297
285
  }, /*#__PURE__*/_react.default.createElement(SelectSection, null), inputSection, searchSection);
298
286
  };
299
- __signature__(SearchControl, "useState{[inputFocused, setInputFocused](false)}\nuseStyles{classes}\nuseRef{inputRef}\nuseEffect{}", function () {
287
+ __signature__(SearchControl, "useStyles{classes}\nuseRef{inputRef}\nuseEffect{}", function () {
300
288
  return [useStyles];
301
289
  });
302
- __signature__(SearchControl, "useState{[inputFocused, setInputFocused](false)}\nuseStyles{classes}\nuseRef{inputRef}\nuseEffect{}", function () {
290
+ __signature__(SearchControl, "useStyles{classes}\nuseRef{inputRef}\nuseEffect{}", function () {
303
291
  return [useStyles];
304
292
  });
305
293
  var _default = SearchControl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orc-shared",
3
- "version": "1.5.0-dev.12",
3
+ "version": "1.5.0-dev.13",
4
4
  "description": "Shared code for Orckestra applications",
5
5
  "main": "./src/index.js",
6
6
  "exports": {
@@ -1,4 +1,4 @@
1
- import React, { useState, useRef, useEffect } from "react";
1
+ import React, { useRef, useEffect } from "react";
2
2
  import { makeStyles } from "@material-ui/core/styles";
3
3
  import SelectProps from "../SelectProps";
4
4
  import Icon from "../../DataDisplay/Icon";
@@ -80,12 +80,9 @@ export const useStyles = makeStyles(theme => ({
80
80
  },
81
81
  parentInput: {
82
82
  flex: "13 0 0",
83
- zIndex: props => (props.focused ? 99 : 1),
84
- border: props =>
85
- props.focused
86
- ? `${theme.spacing(0.1)} solid ${theme.palette.focus}`
87
- : `${theme.spacing(0.1)} solid ${theme.palette.grey.borders}`,
88
- boxShadow: props => (props.focused ? `0 0 4px ${theme.palette.focus}` : "none"),
83
+ zIndex: 1,
84
+ border: `${theme.spacing(0.1)} solid ${theme.palette.grey.borders}`,
85
+ boxShadow: "none",
89
86
  width: "100%",
90
87
  display: "inherit",
91
88
  marginLeft: theme.spacing(-0.1),
@@ -104,6 +101,11 @@ export const useStyles = makeStyles(theme => ({
104
101
  borderBottomLeftRadius: 0,
105
102
  },
106
103
  },
104
+ "&:focus-within": {
105
+ zIndex: 99,
106
+ border: `${theme.spacing(0.1)} solid ${theme.palette.focus}`,
107
+ boxShadow: `0 0 4px ${theme.palette.focus}`,
108
+ },
107
109
  },
108
110
  selectRoot: {
109
111
  zIndex: 10,
@@ -150,17 +152,29 @@ const SearchControl = ({
150
152
  onSearch = () => {},
151
153
  disabled,
152
154
  focusAndSelectSearchFieldOnLoad = true,
155
+ focusSearchOnSearchOptionChange = false,
153
156
  }) => {
154
157
  searchOptions = !searchOptions?.length ? null : searchOptions;
155
158
  searchOption = getSearchOptionValue(searchOptions, searchOption);
156
- const [inputFocused, setInputFocused] = useState(false);
157
159
 
158
- const classes = useStyles({ focused: inputFocused });
160
+ const classes = useStyles();
159
161
 
160
162
  const inputRef = useRef();
161
163
 
162
164
  const update = value => {
163
- onSearch(value, defaultValue);
165
+ if (focusSearchOnSearchOptionChange && inputRef.current) {
166
+ onSearch(value, "");
167
+ setTimeout(() => {
168
+ /* istanbul ignore next */
169
+ if (inputRef.current) {
170
+ inputRef.current.value = "";
171
+ inputRef.current.focus();
172
+ inputRef.current.select();
173
+ }
174
+ }, 0);
175
+ } else {
176
+ onSearch(value, defaultValue);
177
+ }
164
178
  };
165
179
 
166
180
  const selectProps = new SelectProps();
@@ -179,25 +193,11 @@ const SearchControl = ({
179
193
  selectProps.setStyle(SelectProps.ruleNames.root, classes.selectRoot);
180
194
  selectProps.setStyle(SelectProps.ruleNames.paper, classes.selectPaper);
181
195
 
182
- const handleKeyDown = e => {
183
- if (e.key === "Enter") {
184
- onSearch(searchOption, e.target.value);
185
- e.preventDefault();
186
- e.stopPropagation();
187
- }
188
- };
189
-
190
- const onFocusedEvent = (event, focused) => {
191
- setInputFocused(focused);
192
- event.preventDefault();
193
- event.stopPropagation();
194
- };
195
-
196
196
  useEffect(() => {
197
+ /* istanbul ignore next */
197
198
  if (focusAndSelectSearchFieldOnLoad && inputRef.current) {
198
199
  inputRef.current.focus();
199
200
  inputRef.current.select();
200
- setInputFocused(true);
201
201
  }
202
202
  }, [focusAndSelectSearchFieldOnLoad]);
203
203
 
@@ -206,9 +206,15 @@ const SearchControl = ({
206
206
  else return <Select className={classes.selectInput} options={searchOptions} selectProps={selectProps} />;
207
207
  };
208
208
 
209
+ const onSubmit = event => {
210
+ // using form submit instead of a keydown (with key=enter) to allow the 'enter key' event to be canceled elsewhere to avoid the submit event
211
+ onSearch(searchOption, inputRef.current?.value);
212
+ event.preventDefault();
213
+ };
214
+
209
215
  const inputSection = (
210
- <div data-qa="searchInput" data-qa-is-focused={inputFocused} className={classes.parentInput}>
211
- <form data-qa="searchForm" className={classes.fullWidth}>
216
+ <div data-qa="searchInput" className={classes.parentInput}>
217
+ <form data-qa="searchForm" className={classes.fullWidth} onSubmitCapture={onSubmit}>
212
218
  <Input
213
219
  placeholder={placeholder}
214
220
  defaultValue={defaultValue}
@@ -216,10 +222,7 @@ const SearchControl = ({
216
222
  type="text"
217
223
  disabled={disabled}
218
224
  classes={{ input: classes.controlInput }}
219
- onKeyDown={handleKeyDown}
220
225
  disableUnderline={true}
221
- onFocus={e => onFocusedEvent(e, true)}
222
- onBlur={e => onFocusedEvent(e, false)}
223
226
  endAdornment={
224
227
  <InputAdornment position="start">
225
228
  <IconButton
@@ -53,10 +53,11 @@ describe("useStyles", () => {
53
53
  });
54
54
 
55
55
  describe("SearchControl Component", () => {
56
- const stateSetter = sinon.spy().named("focus");
57
- const useStateMock = initState => [initState, stateSetter];
58
-
56
+ beforeEach(() => {
57
+ jest.useFakeTimers();
58
+ });
59
59
  afterEach(() => {
60
+ jest.useRealTimers();
60
61
  jest.clearAllMocks();
61
62
  });
62
63
 
@@ -232,8 +233,7 @@ describe("SearchControl Component", () => {
232
233
  expect(searchInput.length, "to be", 1);
233
234
 
234
235
  searchInput.instance().value = "abc";
235
- searchInput.simulate("keydown", { key: "Tab" });
236
- searchInput.simulate("keydown", { key: "Enter" });
236
+ mountedComponent.find("form").simulate("submit", { preventDefault: () => {} });
237
237
 
238
238
  expect(onSearchEvent, "to have calls satisfying", [{ args: ["aValue", "abc"] }]);
239
239
  });
@@ -371,7 +371,7 @@ describe("SearchControl Component", () => {
371
371
  expect(onSearchEvent, "to have calls satisfying", [{ args: ["anotherValue", "abcdef123"] }]);
372
372
  });
373
373
 
374
- it("Search Control should render with the 2nd value", () => {
374
+ it("Search Control should clear the search when changing the option", () => {
375
375
  const options = [
376
376
  { value: "aValue", label: "aLabel" },
377
377
  { value: "anotherValue", label: "anotherLabel" },
@@ -385,8 +385,8 @@ describe("SearchControl Component", () => {
385
385
  placeholder="placeHolderTest"
386
386
  defaultValue={"abcdef123"}
387
387
  searchOptions={options}
388
- searchOption={"anotherValue"}
389
388
  onSearch={onSearchEvent}
389
+ focusSearchOnSearchOptionChange={true}
390
390
  />
391
391
  </TestWrapper>
392
392
  );
@@ -395,48 +395,53 @@ describe("SearchControl Component", () => {
395
395
 
396
396
  const selectMui = mountedComponent.find(SelectMUI);
397
397
 
398
- expect(selectMui.props().value, "to equal", "anotherValue");
399
- });
398
+ const event = {
399
+ target: {
400
+ value: "anotherValue",
401
+ },
402
+ };
403
+
404
+ onSearchEvent.resetHistory();
405
+
406
+ selectMui.invoke("onChange")(event);
407
+
408
+ expect(onSearchEvent.callCount, "to equal", 1);
409
+ expect(onSearchEvent, "to have calls satisfying", [{ args: ["anotherValue", ""] }]);
410
+
411
+ const allInputs = mountedComponent.find("input");
412
+ const searchInput = allInputs.find("[placeholder='placeHolderTest']");
413
+ expect(searchInput.length, "to be", 1);
400
414
 
401
- it("focusing text input should set focus on container", () => {
402
- jest.spyOn(React, "useState").mockImplementation(useStateMock);
415
+ expect(searchInput.instance().value, "to be", "abcdef123");
416
+ jest.runOnlyPendingTimers();
417
+ expect(searchInput.instance().value, "to be", "");
418
+ });
403
419
 
420
+ it("Search Control should render with the 2nd value", () => {
404
421
  const options = [
405
422
  { value: "aValue", label: "aLabel" },
406
423
  { value: "anotherValue", label: "anotherLabel" },
407
424
  ];
408
425
 
426
+ const onSearchEvent = sinon.spy().named("search");
427
+
409
428
  const component = (
410
429
  <TestWrapper stylesProvider muiThemeProvider={{ theme }}>
411
- <SearchControl placeholder="placeHolderTest" searchOptions={options} focusAndSelectSearchFieldOnLoad={false} />
430
+ <SearchControl
431
+ placeholder="placeHolderTest"
432
+ defaultValue={"abcdef123"}
433
+ searchOptions={options}
434
+ searchOption={"anotherValue"}
435
+ onSearch={onSearchEvent}
436
+ />
412
437
  </TestWrapper>
413
438
  );
414
439
 
415
440
  const mountedComponent = mount(component);
416
441
 
417
- const allInputs = mountedComponent.find("input");
418
- const searchInput = allInputs.find("[placeholder='placeHolderTest']");
419
- expect(searchInput.length, "to be", 1);
420
-
421
- let searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
422
- expect(searchEditParent.length, "to be", 1);
423
-
424
- expect(searchEditParent.props()["data-qa-is-focused"], "to be", false);
425
-
426
- const event = {
427
- preventDefault: () => {},
428
- stopPropagation: () => {},
429
- };
430
-
431
- searchInput.invoke("onFocus")(event);
432
-
433
- searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
434
- expect(searchEditParent.props()["data-qa-is-focused"], "to be", true);
435
-
436
- searchInput.invoke("onBlur")(event);
442
+ const selectMui = mountedComponent.find(SelectMUI);
437
443
 
438
- searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
439
- expect(searchEditParent.props()["data-qa-is-focused"], "to be", false);
444
+ expect(selectMui.props().value, "to equal", "anotherValue");
440
445
  });
441
446
 
442
447
  it("Renders Search Control component without errors when disabled", () => {
@@ -484,46 +489,6 @@ describe("SearchControl Component", () => {
484
489
 
485
490
  expect(component, "when mounted", "to satisfy", expected);
486
491
  });
487
-
488
- it("focusAndSelectSearchFieldOnLoad set to true gives focus to control", () => {
489
- jest.spyOn(React, "useState").mockImplementation(useStateMock);
490
-
491
- const options = [
492
- { value: "aValue", label: "aLabel" },
493
- { value: "anotherValue", label: "anotherLabel" },
494
- ];
495
-
496
- const component = (
497
- <TestWrapper stylesProvider muiThemeProvider={{ theme }}>
498
- <SearchControl placeholder="placeHolderTest" searchOptions={options} focusAndSelectSearchFieldOnLoad={true} />
499
- </TestWrapper>
500
- );
501
-
502
- const mountedComponent = mount(component);
503
- const searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
504
-
505
- expect(searchEditParent.props()["data-qa-is-focused"], "to be", true);
506
- });
507
-
508
- it("focusAndSelectSearchFieldOnLoad set to false does not give focus to control", () => {
509
- jest.spyOn(React, "useState").mockImplementation(useStateMock);
510
-
511
- const options = [
512
- { value: "aValue", label: "aLabel" },
513
- { value: "anotherValue", label: "anotherLabel" },
514
- ];
515
-
516
- const component = (
517
- <TestWrapper stylesProvider muiThemeProvider={{ theme }}>
518
- <SearchControl placeholder="placeHolderTest" searchOptions={options} focusAndSelectSearchFieldOnLoad={false} />
519
- </TestWrapper>
520
- );
521
-
522
- const mountedComponent = mount(component);
523
- const searchEditParent = mountedComponent.find('[data-qa="searchInput"]');
524
-
525
- expect(searchEditParent.props()["data-qa-is-focused"], "to be", false);
526
- });
527
492
  });
528
493
 
529
494
  describe("getSearchOptionValue function", () => {