@spaced-out/ui-design-system 0.1.5 → 0.1.6

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 CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.1.6](https://github.com/spaced-out/ui-design-system/compare/v0.1.5...v0.1.6) (2023-04-05)
6
+
7
+
8
+ ### Features
9
+
10
+ * typeahead focus and loading states search input icon changes ([47363ef](https://github.com/spaced-out/ui-design-system/commit/47363efa8b7706f6cc166ffc2b617c796bd342e7))
11
+
5
12
  ### [0.1.5](https://github.com/spaced-out/ui-design-system/compare/v0.1.4...v0.1.5) (2023-04-04)
6
13
 
7
14
 
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.SearchInput = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
+ var _classify = _interopRequireDefault(require("../../utils/classify"));
9
+ var _CircularLoader = require("../CircularLoader");
8
10
  var _Input = require("../Input");
9
11
  var _SearchInputModule = _interopRequireDefault(require("./SearchInput.module.css"));
10
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -19,26 +21,39 @@ const SearchInput = _ref => {
19
21
  placeholder = 'Search...',
20
22
  classNames,
21
23
  onClear,
24
+ isLoading,
25
+ size,
26
+ iconLeftName = 'magnifying-glass',
22
27
  ...searchInputProps
23
28
  } = _ref;
24
29
  const handleClearClick = () => {
25
30
  onClear?.();
26
31
  };
27
- return /*#__PURE__*/React.createElement(_Input.Input, _extends({
32
+ return /*#__PURE__*/React.createElement("div", {
33
+ className: (0, _classify.default)(_SearchInputModule.default.searchInputWrapper, classNames?.wrapper)
34
+ }, /*#__PURE__*/React.createElement(_Input.Input, _extends({
28
35
  type: "text"
29
36
  }, searchInputProps, {
30
37
  classNames: {
31
- ...classNames,
32
38
  iconRight: value && !(disabled || locked) ? _SearchInputModule.default.clickable : '',
33
- iconLeft: value && !disabled ? _SearchInputModule.default.primaryText : ''
39
+ iconLeft: value && !disabled ? _SearchInputModule.default.primaryText : '',
40
+ box: classNames?.box
34
41
  },
35
42
  placeholder: placeholder,
36
43
  value: value,
37
44
  disabled: disabled,
38
45
  locked: locked,
39
- iconLeftName: "magnifying-glass",
46
+ iconLeftName: iconLeftName,
47
+ size: size,
40
48
  iconRightName: value && !(disabled || locked) ? 'xmark' : 'fw',
41
49
  onIconRightClick: handleClearClick
42
- }));
50
+ })), isLoading && /*#__PURE__*/React.createElement("div", {
51
+ className: (0, _classify.default)(_SearchInputModule.default.loaderContainer, {
52
+ [_SearchInputModule.default.small]: size === 'small'
53
+ })
54
+ }, /*#__PURE__*/React.createElement(_CircularLoader.CircularLoader, {
55
+ colorToken: "colorFillPrimary",
56
+ size: size
57
+ })));
43
58
  };
44
59
  exports.SearchInput = SearchInput;
@@ -2,18 +2,25 @@
2
2
 
3
3
  import * as React from 'react';
4
4
 
5
+ import classify from '../../utils/classify';
6
+ import {CircularLoader} from '../CircularLoader';
5
7
  import type {InputProps} from '../Input';
6
8
  import {Input} from '../Input';
7
9
 
8
10
  import css from './SearchInput.module.css';
9
11
 
10
12
 
11
- type ClassNames = $ReadOnly<{box?: string, iconLeft?: string}>;
13
+ type ClassNames = $ReadOnly<{
14
+ wrapper?: string,
15
+ box?: string,
16
+ iconLeft?: string,
17
+ }>;
12
18
 
13
19
  export type SearchInputProps = {
14
20
  ...InputProps,
15
21
  classNames?: ClassNames,
16
22
  onClear?: () => void,
23
+ isLoading?: boolean,
17
24
  };
18
25
 
19
26
  export const SearchInput = ({
@@ -23,6 +30,9 @@ export const SearchInput = ({
23
30
  placeholder = 'Search...',
24
31
  classNames,
25
32
  onClear,
33
+ isLoading,
34
+ size,
35
+ iconLeftName = 'magnifying-glass',
26
36
  ...searchInputProps
27
37
  }: SearchInputProps): React.Node => {
28
38
  const handleClearClick = () => {
@@ -30,21 +40,33 @@ export const SearchInput = ({
30
40
  };
31
41
 
32
42
  return (
33
- <Input
34
- type="text"
35
- {...searchInputProps}
36
- classNames={{
37
- ...classNames,
38
- iconRight: value && !(disabled || locked) ? css.clickable : '',
39
- iconLeft: value && !disabled ? css.primaryText : '',
40
- }}
41
- placeholder={placeholder}
42
- value={value}
43
- disabled={disabled}
44
- locked={locked}
45
- iconLeftName="magnifying-glass"
46
- iconRightName={value && !(disabled || locked) ? 'xmark' : 'fw'}
47
- onIconRightClick={handleClearClick}
48
- />
43
+ <div className={classify(css.searchInputWrapper, classNames?.wrapper)}>
44
+ <Input
45
+ type="text"
46
+ {...searchInputProps}
47
+ classNames={{
48
+ iconRight: value && !(disabled || locked) ? css.clickable : '',
49
+ iconLeft: value && !disabled ? css.primaryText : '',
50
+ box: classNames?.box,
51
+ }}
52
+ placeholder={placeholder}
53
+ value={value}
54
+ disabled={disabled}
55
+ locked={locked}
56
+ iconLeftName={iconLeftName}
57
+ size={size}
58
+ iconRightName={value && !(disabled || locked) ? 'xmark' : 'fw'}
59
+ onIconRightClick={handleClearClick}
60
+ />
61
+ {isLoading && (
62
+ <div
63
+ className={classify(css.loaderContainer, {
64
+ [css.small]: size === 'small',
65
+ })}
66
+ >
67
+ <CircularLoader colorToken="colorFillPrimary" size={size} />
68
+ </div>
69
+ )}
70
+ </div>
49
71
  );
50
72
  };
@@ -2,6 +2,23 @@
2
2
  colorTextPrimary
3
3
  ) from '../../styles/variables/_color.css';
4
4
 
5
+ @value (
6
+ size42,
7
+ size34
8
+ ) from '../../styles/variables/_size.css';
9
+
10
+ @value (
11
+ spaceXXSmall
12
+ ) from '../../styles/variables/_space.css';
13
+
14
+ .searchInputWrapper {
15
+ display: flex;
16
+ position: relative;
17
+ align-items: end;
18
+ gap: spaceXXSmall;
19
+ height: fit-content;
20
+ }
21
+
5
22
  .clickable {
6
23
  cursor: pointer;
7
24
  }
@@ -9,3 +26,19 @@
9
26
  .primaryText {
10
27
  color: colorTextPrimary;
11
28
  }
29
+
30
+ .loaderContainer {
31
+ display: flex;
32
+ height: size42;
33
+ width: size42;
34
+ align-items: center;
35
+ justify-content: center;
36
+ align-items: center;
37
+ margin-right: calc((size42 * -1) - spaceXXSmall);
38
+ }
39
+
40
+ .loaderContainer.small {
41
+ height: size34;
42
+ width: size34;
43
+ margin-right: calc((size34 * -1) - spaceXXSmall);
44
+ }
@@ -30,6 +30,8 @@ const Typeahead = _ref => {
30
30
  onMenuOpen,
31
31
  onMenuClose,
32
32
  typeaheadInputText = '',
33
+ isLoading,
34
+ menuOpenOffset = 1,
33
35
  ...inputProps
34
36
  } = _ref;
35
37
  const typeaheadRef = React.useRef();
@@ -58,7 +60,7 @@ const Typeahead = _ref => {
58
60
  }
59
61
  });
60
62
  setFilteredOptions(optionsFiltered || []);
61
- }, [typeaheadInputText]);
63
+ }, [typeaheadInputText, menu?.options]);
62
64
  return /*#__PURE__*/React.createElement(_clickAway.ClickAway, {
63
65
  onChange: onMenuToggle
64
66
  }, _ref2 => {
@@ -71,7 +73,8 @@ const Typeahead = _ref => {
71
73
  return /*#__PURE__*/React.createElement("div", {
72
74
  "data-testid": "Typeahead",
73
75
  className: (0, _classify.classify)(_TypeaheadModule.default.typeaheadContainer, classNames?.wrapper),
74
- ref: typeaheadRef
76
+ ref: typeaheadRef,
77
+ onClickCapture: cancelNext
75
78
  }, /*#__PURE__*/React.createElement(_SearchInput.SearchInput, _extends({
76
79
  boxRef: reference,
77
80
  size: size,
@@ -79,12 +82,20 @@ const Typeahead = _ref => {
79
82
  value: typeaheadInputText,
80
83
  classNames: {
81
84
  box: classNames?.box
82
- }
85
+ },
86
+ isLoading: isLoading
83
87
  }, inputProps, {
84
88
  onChange: e => {
85
89
  e.stopPropagation();
86
90
  onSearch && onSearch(e);
87
- if (e.target.value.length > 0) {
91
+ if (e.target.value.length >= menuOpenOffset) {
92
+ onOpen();
93
+ } else {
94
+ clickAway();
95
+ }
96
+ },
97
+ onFocus: _e => {
98
+ if (typeaheadInputText.length >= menuOpenOffset) {
88
99
  onOpen();
89
100
  } else {
90
101
  clickAway();
@@ -93,7 +104,7 @@ const Typeahead = _ref => {
93
104
  onClear: _e => {
94
105
  onClear?.();
95
106
  }
96
- })), isOpen && menu && filteredOptions && !!filteredOptions.length && /*#__PURE__*/React.createElement("div", {
107
+ })), isOpen && !isLoading && menu && filteredOptions && !!filteredOptions.length && /*#__PURE__*/React.createElement("div", {
97
108
  onClickCapture: cancelNext,
98
109
  ref: floating,
99
110
  style: {
@@ -37,6 +37,8 @@ export type TypeaheadProps = {
37
37
  typeaheadInputText?: string,
38
38
  menu?: MenuProps,
39
39
  onClear?: () => void,
40
+ isLoading?: boolean,
41
+ menuOpenOffset?: number,
40
42
  };
41
43
 
42
44
  export const Typeahead = ({
@@ -50,6 +52,8 @@ export const Typeahead = ({
50
52
  onMenuOpen,
51
53
  onMenuClose,
52
54
  typeaheadInputText = '',
55
+ isLoading,
56
+ menuOpenOffset = 1,
53
57
  ...inputProps
54
58
  }: TypeaheadProps): React.Node => {
55
59
  const typeaheadRef = React.useRef();
@@ -81,7 +85,7 @@ export const Typeahead = ({
81
85
  }
82
86
  });
83
87
  setFilteredOptions(optionsFiltered || []);
84
- }, [typeaheadInputText]);
88
+ }, [typeaheadInputText, menu?.options]);
85
89
 
86
90
  return (
87
91
  <ClickAway onChange={onMenuToggle}>
@@ -90,6 +94,7 @@ export const Typeahead = ({
90
94
  data-testid="Typeahead"
91
95
  className={classify(css.typeaheadContainer, classNames?.wrapper)}
92
96
  ref={typeaheadRef}
97
+ onClickCapture={cancelNext}
93
98
  >
94
99
  <SearchInput
95
100
  boxRef={reference}
@@ -97,11 +102,19 @@ export const Typeahead = ({
97
102
  placeholder={placeholder}
98
103
  value={typeaheadInputText}
99
104
  classNames={{box: classNames?.box}}
105
+ isLoading={isLoading}
100
106
  {...inputProps}
101
107
  onChange={(e) => {
102
108
  e.stopPropagation();
103
109
  onSearch && onSearch(e);
104
- if (e.target.value.length > 0) {
110
+ if (e.target.value.length >= menuOpenOffset) {
111
+ onOpen();
112
+ } else {
113
+ clickAway();
114
+ }
115
+ }}
116
+ onFocus={(_e) => {
117
+ if (typeaheadInputText.length >= menuOpenOffset) {
105
118
  onOpen();
106
119
  } else {
107
120
  clickAway();
@@ -111,8 +124,11 @@ export const Typeahead = ({
111
124
  onClear?.();
112
125
  }}
113
126
  />
114
-
115
- {isOpen && menu && filteredOptions && !!filteredOptions.length && (
127
+ {isOpen &&
128
+ !isLoading &&
129
+ menu &&
130
+ filteredOptions &&
131
+ !!filteredOptions.length && (
116
132
  <div
117
133
  onClickCapture={cancelNext}
118
134
  ref={floating}
@@ -131,7 +147,7 @@ export const Typeahead = ({
131
147
  onSelect && onSelect(option);
132
148
  if (
133
149
  !menu.optionsVariant ||
134
- menu.optionsVariant === 'normal'
150
+ menu.optionsVariant === 'normal'
135
151
  ) {
136
152
  clickAway();
137
153
  }
@@ -7,4 +7,5 @@
7
7
  position: relative;
8
8
  flex-flow: column;
9
9
  width: sizeFluid;
10
+ height: fit-content;
10
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaced-out/ui-design-system",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "main": "index.js",
5
5
  "description": "Sense UI components library",
6
6
  "author": {