@hipay/hipay-material-ui 2.0.0-beta.57 → 2.0.0-beta.59

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/HiAlertModal/HiAlertModal.js +56 -13
  3. package/HiColoredLabel/HiColoredLabel.js +16 -4
  4. package/HiForm/HiFormControl.js +2 -4
  5. package/HiForm/HiInput.js +29 -4
  6. package/HiForm/HiUploadField.js +2 -1
  7. package/HiSelect/HiSelect.js +6 -5
  8. package/HiSelect/HiSuggestSelect.js +5 -4
  9. package/HiSelect/SelectInput.js +1 -0
  10. package/HiSelectNew/HiNestedSelect.js +20 -6
  11. package/HiSelectNew/HiNestedSelectContent.js +20 -6
  12. package/HiSelectNew/HiSelect.js +104 -32
  13. package/HiSelectNew/HiSelectContent.js +16 -4
  14. package/HiSelectNew/HiSelectInput.js +10 -3
  15. package/HiSelectableList/HiSelectableList.js +2 -35
  16. package/HiSelectableList/HiSelectableListItem.js +6 -4
  17. package/es/HiAlertModal/HiAlertModal.js +55 -13
  18. package/es/HiColoredLabel/HiColoredLabel.js +21 -4
  19. package/es/HiForm/HiFormControl.js +2 -4
  20. package/es/HiForm/HiInput.js +29 -4
  21. package/es/HiForm/HiUploadField.js +2 -1
  22. package/es/HiSelect/HiSelect.js +6 -5
  23. package/es/HiSelect/HiSuggestSelect.js +5 -4
  24. package/es/HiSelect/SelectInput.js +1 -0
  25. package/es/HiSelectNew/HiNestedSelect.js +17 -7
  26. package/es/HiSelectNew/HiNestedSelectContent.js +16 -6
  27. package/es/HiSelectNew/HiSelect.js +106 -31
  28. package/es/HiSelectNew/HiSelectContent.js +11 -2
  29. package/es/HiSelectNew/HiSelectInput.js +10 -3
  30. package/es/HiSelectableList/HiSelectableList.js +3 -29
  31. package/es/HiSelectableList/HiSelectableListItem.js +6 -4
  32. package/index.es.js +1 -1
  33. package/index.js +1 -1
  34. package/package.json +1 -1
  35. package/umd/hipay-material-ui.development.js +15551 -16279
  36. package/umd/hipay-material-ui.production.min.js +2 -2
@@ -8,7 +8,7 @@ import withStyles from '../styles/withStyles';
8
8
  import { capitalize } from '../utils/helpers';
9
9
  import { fade } from '../styles/colorManipulator';
10
10
  export const styles = theme => ({
11
- root: _objectSpread({}, theme.typography.b3, {
11
+ root: {
12
12
  display: 'inline-block',
13
13
  alignItems: 'baseline',
14
14
  maxWidth: '100%',
@@ -18,7 +18,12 @@ export const styles = theme => ({
18
18
  overflow: 'hidden',
19
19
  whiteSpace: 'nowrap',
20
20
  lineHeight: 1
21
- }),
21
+ },
22
+ body1: _objectSpread({}, theme.typography.b1),
23
+ body2: _objectSpread({}, theme.typography.b2),
24
+ body3: _objectSpread({}, theme.typography.b3),
25
+ body4: _objectSpread({}, theme.typography.b4),
26
+ body5: _objectSpread({}, theme.typography.b5),
22
27
  color: {
23
28
  fontWeight: 400
24
29
  },
@@ -111,6 +116,7 @@ function HiColoredLabel(props) {
111
116
  const {
112
117
  classes,
113
118
  className,
119
+ fontSize,
114
120
  label,
115
121
  color,
116
122
  active,
@@ -119,7 +125,7 @@ function HiColoredLabel(props) {
119
125
  style,
120
126
  theme
121
127
  } = props,
122
- other = _objectWithoutProperties(props, ["classes", "className", "label", "color", "active", "outlined", "fontWeight", "style", "theme"]);
128
+ other = _objectWithoutProperties(props, ["classes", "className", "fontSize", "label", "color", "active", "outlined", "fontWeight", "style", "theme"]);
123
129
 
124
130
  const isHiColor = ['primary', 'secondary', 'positive', 'negative', 'middle', 'neutral'].includes(color);
125
131
  const isHexColor = !isHiColor && /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color);
@@ -129,7 +135,12 @@ function HiColoredLabel(props) {
129
135
  [classes.activeColor]: active,
130
136
  [classes.outlined]: outlined,
131
137
  [classes[`activeColor${capitalize(color)}`]]: active && isHiColor,
132
- [classes[`color${capitalize(color)}`]]: !active && isHiColor
138
+ [classes[`color${capitalize(color)}`]]: !active && isHiColor,
139
+ [classes.body1]: fontSize >= 15,
140
+ [classes.body2]: fontSize === 14,
141
+ [classes.body3]: fontSize === 13,
142
+ [classes.body4]: fontSize === 12,
143
+ [classes.body5]: fontSize <= 11
133
144
  }, className),
134
145
  style: _objectSpread({}, style, isHexColor && {
135
146
  backgroundColor: active ? color : fade(color, 0.08),
@@ -162,6 +173,11 @@ HiColoredLabel.propTypes = process.env.NODE_ENV !== "production" ? {
162
173
  */
163
174
  color: PropTypes.string,
164
175
 
176
+ /**
177
+ * Taille du text
178
+ */
179
+ fontSize: PropTypes.number,
180
+
165
181
  /**
166
182
  * Graisse du text
167
183
  */
@@ -180,6 +196,7 @@ HiColoredLabel.propTypes = process.env.NODE_ENV !== "production" ? {
180
196
  HiColoredLabel.defaultProps = {
181
197
  active: false,
182
198
  color: 'primary',
199
+ fontSize: 15,
183
200
  outlined: false
184
201
  };
185
202
  export default withStyles(styles, {
@@ -199,16 +199,14 @@ class HiFormControl extends React.PureComponent {
199
199
  focused: !disabled && (focused || hovered)
200
200
  }, InputLabelProps), error && errorText && React.createElement(HiIconButton, {
201
201
  className: classNames(classes.iconButton, classes.iconButtonError),
202
- onClick: this.handleHelperClick,
203
- onKeyDown: this.handleKeyDown
202
+ onClick: this.handleHelperClick
204
203
  }, React.createElement(Warning, {
205
204
  className: classNames(classes.icon)
206
205
  })), helperIcon && helperText && !error && React.createElement(HiIconButton, {
207
206
  className: classNames(classes.iconButton, classes.iconButtonInfo, {
208
207
  [classes.iconButtonInfoActive]: helperOpen
209
208
  }),
210
- onClick: this.handleHelperClick,
211
- onKeyDown: this.handleKeyDown
209
+ onClick: this.handleHelperClick
212
210
  }, React.createElement(Info, {
213
211
  className: classNames(classes.icon)
214
212
  }))), React.createElement("div", {
@@ -127,6 +127,13 @@ var _ref = React.createElement(HiIcon, {
127
127
  class HiInput extends React.PureComponent {
128
128
  constructor() {
129
129
  super();
130
+
131
+ this.handleClick = () => {
132
+ if (this.props.onClick) {
133
+ this.props.onClick();
134
+ }
135
+ };
136
+
130
137
  this.state = {
131
138
  focused: false
132
139
  };
@@ -177,10 +184,15 @@ class HiInput extends React.PureComponent {
177
184
  // Si on click sur un élément de HiInput, on garde le focus
178
185
  // Par exemple sur l'icone reset
179
186
  if (event.relatedTarget && this.overlayNode && this.overlayNode.contains(event.relatedTarget)) {
180
- if (this.endAdornmentNode.contains(event.relatedTarget) && this.props.onBlur) {
187
+ // If blur came from erase icon => stay focused and don't call onBlur props
188
+ if (this.eraseIconNode && this.eraseIconNode.contains(event.relatedTarget)) {
189
+ event.preventDefault();
190
+ event.stopPropagation();
191
+ } else if (this.endAdornmentNode.contains(event.relatedTarget) && this.props.onBlur) {
181
192
  this.props.onBlur(event);
182
193
  }
183
194
 
195
+ event.preventDefault();
184
196
  event.stopPropagation();
185
197
  } else {
186
198
  this.setState({
@@ -201,9 +213,13 @@ class HiInput extends React.PureComponent {
201
213
  this.setState({
202
214
  focused: true
203
215
  });
204
- }
216
+ } // If focus came from erase icon => stay focused and don't call onFocus props
217
+
205
218
 
206
- if (this.props.onFocus) {
219
+ if (this.eraseIconNode && this.eraseIconNode.contains(event.relatedTarget)) {
220
+ event.preventDefault();
221
+ event.stopPropagation();
222
+ } else if (this.props.onFocus) {
207
223
  this.props.onFocus(event);
208
224
  }
209
225
  }
@@ -306,7 +322,10 @@ class HiInput extends React.PureComponent {
306
322
  label: classes.eraseButtonLabel
307
323
  },
308
324
  onClick: this.handleReset,
309
- onBlur: this.handleBlur
325
+ onBlur: this.handleBlur,
326
+ buttonRef: el => {
327
+ this.eraseIconNode = el;
328
+ }
310
329
  }, _ref);
311
330
  let endAdornment = endAdornmentProps;
312
331
 
@@ -335,6 +354,7 @@ class HiInput extends React.PureComponent {
335
354
  placeholder: placeholder,
336
355
  onFocus: this.handleFocus,
337
356
  onKeyDown: this.props.onKeyDown,
357
+ onClick: this.handleClick,
338
358
  onBlur: this.handleBlur,
339
359
  inputRef: this.getInputElement,
340
360
  disabled: disabled,
@@ -454,6 +474,11 @@ HiInput.propTypes = process.env.NODE_ENV !== "production" ? {
454
474
  */
455
475
  onChange: PropTypes.func,
456
476
 
477
+ /**
478
+ * Fonction de callback appelée au click dans l'input
479
+ */
480
+ onClick: PropTypes.func,
481
+
457
482
  /**
458
483
  * Fonction de callback appelée au focus du champs
459
484
  */
@@ -22,7 +22,8 @@ export const styles = theme => ({
22
22
  fontSize: '80px'
23
23
  },
24
24
  inputContainer: {
25
- flex: '1'
25
+ flex: '1',
26
+ width: 'calc(100% - 88px)'
26
27
  },
27
28
  empty: {
28
29
  border: `1px solid ${theme.palette.input.bottomLine}`,
@@ -193,17 +193,13 @@ class HiSelect extends React.PureComponent {
193
193
  nextItem = getNextItemSelectable(document.activeElement, 'down');
194
194
  } else if (event.key === 'ArrowUp') {
195
195
  nextItem = getNextItemSelectable(document.activeElement, 'up');
196
- } else if (event.key === 'Tab') {
196
+ } else if (event.key === 'Tab' || event.key === 'Escape') {
197
197
  /* if (!this.props.staticPosition) {
198
198
  document.body.style.overflow = 'auto';
199
199
  } */
200
200
  this.setState({
201
201
  open: false
202
202
  });
203
- } else if (event.key === 'Escape') {
204
- this.setState({
205
- open: false
206
- });
207
203
  }
208
204
 
209
205
  if (nextItem) {
@@ -216,6 +212,10 @@ class HiSelect extends React.PureComponent {
216
212
  this.focusOnSelectedItem();
217
213
  } else if (event.key === 'Enter' && this.props.onSubmit) {
218
214
  this.props.onSubmit(event);
215
+ } else if (event.key === 'Tab' || event.key === 'Escape') {
216
+ this.setState({
217
+ open: false
218
+ });
219
219
  }
220
220
  };
221
221
 
@@ -682,6 +682,7 @@ class HiSelect extends React.PureComponent {
682
682
  onClick: this.handleClick,
683
683
  onFocus: this.handleFocus,
684
684
  onBlur: this.handleBlur,
685
+ onKeyDown: this.handleKeyDown,
685
686
  onMouseEnter: this.props.onMouseEnter,
686
687
  onMouseLeave: this.props.onMouseLeave,
687
688
  refElement: el => {
@@ -24,7 +24,8 @@ export const styles = theme => ({
24
24
  width: '100% !important',
25
25
  transform: 'none !important',
26
26
  zIndex: '9 !important',
27
- top: '100% !important'
27
+ top: '100% !important',
28
+ textOverflow: 'ellipsis'
28
29
  },
29
30
  paper: {
30
31
  borderRadius: '0px 2px',
@@ -143,10 +144,10 @@ class HiSuggestSelect extends React.PureComponent {
143
144
  options: [],
144
145
  focused: false
145
146
  });
146
- }
147
147
 
148
- if (this.props.onBlurInput) {
149
- this.props.onBlurInput(event);
148
+ if (this.props.onBlurInput) {
149
+ this.props.onBlurInput(event);
150
+ }
150
151
  }
151
152
  }
152
153
 
@@ -185,6 +185,7 @@ class SelectInput extends React.PureComponent {
185
185
  className: iconClass,
186
186
  icon: "arrow_drop_down"
187
187
  })) : React.createElement(ButtonBase, {
188
+ component: "div",
188
189
  id: id,
189
190
  classes: {
190
191
  root: rootClass
@@ -45,6 +45,10 @@ function findFinalItemRecursively(itemList, searchId) {
45
45
  });
46
46
  return foundItem;
47
47
  }
48
+
49
+ export var filterValue = function (item, searchValue) {
50
+ return searchValue === '' || foldAccents(item.label.toString().toLowerCase()).search(foldAccents(searchValue.toLowerCase())) !== -1;
51
+ };
48
52
  /**
49
53
  * Build item list by settings item props relative to the nested parent/child situation
50
54
  * Reduce the item list to build specified items (displayed, pinned, disabled, selected, indeterminate)
@@ -62,15 +66,14 @@ function findFinalItemRecursively(itemList, searchId) {
62
66
  * @returns {*}
63
67
  */
64
68
 
65
-
66
- function buildFilteredItemList(itemList, selectedItemIdList = [], searchValue = '', visibleParent = false, pinnedParent = false, disabledParent = false, nbChildrenAsInfo = false, translations) {
69
+ function buildFilteredItemList(itemList, selectedItemIdList = [], searchValue = '', visibleParent = false, pinnedParent = false, disabledParent = false, nbChildrenAsInfo = false, translations, filterFunc = filterValue) {
67
70
  return itemList.reduce(({
68
71
  l: memoItemList,
69
72
  s: memoSelected,
70
73
  u: memoUnselected,
71
74
  v: memoVisible
72
75
  }, item) => {
73
- const itemVisible = searchValue === '' || foldAccents(item.label.toString().toLowerCase()).search(foldAccents(searchValue.toLowerCase())) !== -1; // Parent item
76
+ const itemVisible = filterFunc(item, searchValue); // Parent item
74
77
 
75
78
  if (item.children) {
76
79
  const {
@@ -78,7 +81,7 @@ function buildFilteredItemList(itemList, selectedItemIdList = [], searchValue =
78
81
  s: selected,
79
82
  u: unselected,
80
83
  v: visible
81
- } = buildFilteredItemList(item.children, selectedItemIdList, searchValue, itemVisible, pinnedParent, disabledParent);
84
+ } = buildFilteredItemList(item.children, selectedItemIdList, searchValue, itemVisible, pinnedParent, disabledParent, nbChildrenAsInfo, translations, filterFunc);
82
85
 
83
86
  if (nbChildrenAsInfo) {
84
87
  item.info = translations.n_children.replace('%s', item.children.length);
@@ -227,7 +230,8 @@ class HiNestedSelect extends React.PureComponent {
227
230
  multiple,
228
231
  nbChildrenAsInfo,
229
232
  pinnedParent,
230
- translations
233
+ translations,
234
+ filterFunc
231
235
  } = this.props; // build item list
232
236
 
233
237
  const {
@@ -235,7 +239,7 @@ class HiNestedSelect extends React.PureComponent {
235
239
  s: allSelected,
236
240
  u: allUnselected,
237
241
  v: visible
238
- } = buildFilteredItemList(options, value, search, false, pinnedParent, disabledParent || !multiple, nbChildrenAsInfo, translations);
242
+ } = buildFilteredItemList(options, value, search, false, pinnedParent, disabledParent || !multiple, nbChildrenAsInfo, translations, filterFunc);
239
243
  const itemList = !visible ? [...(loading ? [{
240
244
  id: '_loading',
241
245
  type: 'loader',
@@ -367,7 +371,8 @@ HiNestedSelect.defaultProps = {
367
371
  one_item_selected: '%s item selected',
368
372
  n_children: '%s',
369
373
  one_child: '%s item'
370
- }
374
+ },
375
+ filterFunc: filterValue
371
376
  };
372
377
  HiNestedSelect.propTypes = process.env.NODE_ENV !== "production" ? {
373
378
  /**
@@ -385,6 +390,11 @@ HiNestedSelect.propTypes = process.env.NODE_ENV !== "production" ? {
385
390
  */
386
391
  displayAsChip: PropTypes.bool,
387
392
 
393
+ /*
394
+ * Fonction de filtrage custom
395
+ */
396
+ filterFunc: PropTypes.func,
397
+
388
398
  /**
389
399
  * Affiche l'élément 'All'
390
400
  */
@@ -42,6 +42,9 @@ export function findFinalItemRecursively(itemList, searchId) {
42
42
  });
43
43
  return foundItem;
44
44
  }
45
+ export var filterValue = function (item, searchValue) {
46
+ return searchValue === '' || foldAccents(item.label.toString().toLowerCase()).search(foldAccents(searchValue.toLowerCase())) !== -1;
47
+ };
45
48
  /**
46
49
  * Build item list by settings item props relative to the nested parent/child situation
47
50
  * Reduce the item list to build specified items (displayed, pinned, disabled, selected, indeterminate)
@@ -59,14 +62,14 @@ export function findFinalItemRecursively(itemList, searchId) {
59
62
  * @returns {*}
60
63
  */
61
64
 
62
- function buildFilteredItemList(itemList, selectedItemIdList = [], searchValue = '', visibleParent = false, pinnedParent = false, disabledParent = false, nbChildrenAsInfo = false, translations) {
65
+ function buildFilteredItemList(itemList, selectedItemIdList = [], searchValue = '', visibleParent = false, pinnedParent = false, disabledParent = false, nbChildrenAsInfo = false, translations, filterFunc = filterValue) {
63
66
  return itemList.reduce(({
64
67
  l: memoItemList,
65
68
  s: memoSelected,
66
69
  u: memoUnselected,
67
70
  v: memoVisible
68
71
  }, item) => {
69
- const itemVisible = searchValue === '' || foldAccents(item.label.toString().toLowerCase()).search(foldAccents(searchValue.toLowerCase())) !== -1; // Parent item
72
+ const itemVisible = filterFunc(item, searchValue); // Parent item
70
73
 
71
74
  if (item.children) {
72
75
  const {
@@ -74,7 +77,7 @@ function buildFilteredItemList(itemList, selectedItemIdList = [], searchValue =
74
77
  s: selected,
75
78
  u: unselected,
76
79
  v: visible
77
- } = buildFilteredItemList(item.children, selectedItemIdList, searchValue, itemVisible, pinnedParent, disabledParent);
80
+ } = buildFilteredItemList(item.children, selectedItemIdList, searchValue, itemVisible, pinnedParent, disabledParent, nbChildrenAsInfo, translations, filterFunc);
78
81
 
79
82
  if (nbChildrenAsInfo) {
80
83
  item.info = translations.n_children.replace('%s', item.children.length);
@@ -181,7 +184,8 @@ class HiNestedSelectContent extends React.PureComponent {
181
184
  multiple,
182
185
  nbChildrenAsInfo,
183
186
  pinnedParent,
184
- translations
187
+ translations,
188
+ filterFunc
185
189
  } = this.props; // build item list
186
190
 
187
191
  const {
@@ -189,7 +193,7 @@ class HiNestedSelectContent extends React.PureComponent {
189
193
  s: allSelected,
190
194
  u: allUnselected,
191
195
  v: visible
192
- } = buildFilteredItemList(options, value, search, false, pinnedParent, disabledParent || !multiple, nbChildrenAsInfo, translations);
196
+ } = buildFilteredItemList(options, value, search, false, pinnedParent, disabledParent || !multiple, nbChildrenAsInfo, translations, filterFunc);
193
197
  const itemList = !visible ? [...(loading ? [{
194
198
  id: '_loading',
195
199
  type: 'loader',
@@ -272,7 +276,8 @@ HiNestedSelectContent.defaultProps = {
272
276
  search: 'Search',
273
277
  n_children: '%s',
274
278
  one_child: '%s item'
275
- }
279
+ },
280
+ filterFunc: filterValue
276
281
  };
277
282
  HiNestedSelectContent.propTypes = process.env.NODE_ENV !== "production" ? {
278
283
  /**
@@ -285,6 +290,11 @@ HiNestedSelectContent.propTypes = process.env.NODE_ENV !== "production" ? {
285
290
  */
286
291
  disabledParent: PropTypes.bool,
287
292
 
293
+ /*
294
+ * Fonction de filtrage custom
295
+ */
296
+ filterFunc: PropTypes.func,
297
+
288
298
  /**
289
299
  * Affiche l'élément 'All'
290
300
  */
@@ -6,7 +6,6 @@ import Scrollbars from 'react-custom-scrollbars';
6
6
  import Grow from '@material-ui/core/Grow';
7
7
  import Paper from '@material-ui/core/Paper';
8
8
  import Popper from '@material-ui/core/Popper';
9
- import { findDOMNode } from 'react-dom';
10
9
  import ClickAwayListener from '@material-ui/core/ClickAwayListener';
11
10
  import HiSelectableList from '../HiSelectableList';
12
11
  import HiInput from '../HiForm/HiInput';
@@ -69,6 +68,10 @@ export const styles = theme => ({
69
68
  borderTop: `1px solid ${theme.palette.input.bottomLine}`
70
69
  }
71
70
  });
71
+
72
+ function filterValue(item, search) {
73
+ return search === '' || foldAccents(item.label.toString().toLowerCase()).search(foldAccents(search.toLowerCase())) !== -1;
74
+ }
72
75
  /**
73
76
  *
74
77
  * Utilisé pour tous types de selects dans les formulaires.
@@ -84,6 +87,7 @@ export const styles = theme => ({
84
87
  * - HiSelectableList : affiche la liste des suggestions selon le type des éléments
85
88
  */
86
89
 
90
+
87
91
  class HiSelect extends React.PureComponent {
88
92
  constructor(props) {
89
93
  super(props);
@@ -98,7 +102,7 @@ class HiSelect extends React.PureComponent {
98
102
  hideCheckbox: true,
99
103
  label: 'loading'
100
104
  }] : []), // simple one level filter on label
101
- ...(search !== '' ? [...options.filter(item => item.label && foldAccents(item.label.toString().toLowerCase()).search(foldAccents(search.toLowerCase())) !== -1)] : [...(this.props.hasAll ? [_objectSpread({
105
+ ...(search !== '' ? [...options.filter(item => this.props.filterFunc(item, search))] : [...(this.props.hasAll ? [_objectSpread({
102
106
  id: '_all',
103
107
  label: this.props.translations.all
104
108
  }, this.props.iconAll && {
@@ -164,11 +168,12 @@ class HiSelect extends React.PureComponent {
164
168
  };
165
169
 
166
170
  this.focusOnFirstItem = () => {
167
- const overlay = findDOMNode(this.overlay);
168
- setTimeout(() => {
169
- const item = overlay.getElementsByTagName('li')[0];
170
- item.focus();
171
- }, 1);
171
+ if (this.overlay && this.overlay.getElementsByTagName('li')[0]) {
172
+ setTimeout(() => {
173
+ const item = this.overlay.getElementsByTagName('li')[0];
174
+ item.focus();
175
+ }, 1);
176
+ }
172
177
  };
173
178
 
174
179
  this.getInputElement = el => {
@@ -204,21 +209,22 @@ class HiSelect extends React.PureComponent {
204
209
  };
205
210
 
206
211
  this.focusOnSelectedItem = selectedValue => {
207
- const overlay = findDOMNode(this.overlay);
208
- setTimeout(() => {
209
- // On initialise au premier élément pour être sûr de ne pas se retrouver avec un focus of undefined
210
- let item = overlay.getElementsByTagName('li')[0];
211
-
212
- if (selectedValue && typeof selectedValue === 'string') {
213
- item = overlay.getElementsByTagName('li')[selectedValue];
214
- } else if (selectedValue && typeof selectedValue === 'number') {
215
- item = overlay.getElementsByTagName('li')[selectedValue - 1];
216
- }
217
-
218
- if (item) {
219
- item.focus();
220
- }
221
- }, 1);
212
+ if (this.overlay && this.overlay.getElementsByTagName('li')[0]) {
213
+ setTimeout(() => {
214
+ // On initialise au premier élément pour être sûr de ne pas se retrouver avec un focus of undefined
215
+ let item = this.overlay.getElementsByTagName('li')[0];
216
+
217
+ if (selectedValue && typeof selectedValue === 'string') {
218
+ item = this.overlay.getElementsByTagName('li')[selectedValue];
219
+ } else if (selectedValue && typeof selectedValue === 'number') {
220
+ item = this.overlay.getElementsByTagName('li')[selectedValue - 1];
221
+ }
222
+
223
+ if (item) {
224
+ item.focus();
225
+ }
226
+ }, 1);
227
+ }
222
228
  };
223
229
 
224
230
  this.handleClickAway = event => {
@@ -249,6 +255,17 @@ class HiSelect extends React.PureComponent {
249
255
  });
250
256
  };
251
257
 
258
+ this.handleKeyDownInput = event => {
259
+ const key = keycode(event);
260
+
261
+ if (key === 'down' || key === 'up') {
262
+ this.handleClick();
263
+ } else if (key === 'enter' && this.props.onSubmit) {
264
+ event.preventDefault();
265
+ this.props.onSubmit(event);
266
+ }
267
+ };
268
+
252
269
  this.handleKeyDown = event => {
253
270
  let nextItem;
254
271
  const key = keycode(event);
@@ -259,6 +276,13 @@ class HiSelect extends React.PureComponent {
259
276
  } else if (key === 'up') {
260
277
  event.preventDefault();
261
278
  nextItem = getNextItemSelectable(document.activeElement, 'up');
279
+ } else if (key === 'tab' || key === 'esc') {
280
+ this.setState({
281
+ open: false
282
+ });
283
+ } else if (key === 'space') {
284
+ // Cancel scroll
285
+ event.preventDefault();
262
286
  }
263
287
 
264
288
  if (nextItem) {
@@ -266,17 +290,57 @@ class HiSelect extends React.PureComponent {
266
290
  }
267
291
  };
268
292
 
293
+ this.getItemById = id => {
294
+ let item;
295
+
296
+ if (this.props.hasAll && String(id) === '_all') {
297
+ return {
298
+ id: '_all'
299
+ };
300
+ }
301
+
302
+ for (let i = 0; i < this.props.options.length; i += 1) {
303
+ const elem = this.props.options[i];
304
+
305
+ if (String(elem.id) === String(id)) {
306
+ item = elem;
307
+ break;
308
+ }
309
+
310
+ if (elem.children) {
311
+ for (let j = 0; j < elem.children.length; j += 1) {
312
+ if (String(elem.children[j].id) === String(id)) {
313
+ item = elem.children[j];
314
+ break;
315
+ }
316
+ }
317
+ }
318
+ }
319
+
320
+ return item;
321
+ };
322
+
269
323
  this.handleKeyUp = event => {
270
324
  const key = keycode(event);
271
325
 
272
- if (key === 'tab' || key === 'esc') {
326
+ if (key === 'esc') {
273
327
  this.setState({
274
328
  open: false
275
329
  });
276
330
  } else if (key === 'space' || key === 'enter' && !this.props.multiple) {
277
331
  event.preventDefault();
278
- const item = this.props.options.find(elem => String(elem.id) === event.target.id);
279
- this.handleSelect(null, item);
332
+ const item = this.getItemById(event.target.id);
333
+
334
+ if (item) {
335
+ // Select for nested select
336
+ if (this.props.hiSelectableListProps && this.props.hiSelectableListProps.onSelect) {
337
+ this.props.hiSelectableListProps.onSelect(null, item);
338
+ } else {
339
+ this.handleSelect(null, item);
340
+ }
341
+ } else {
342
+ console.warn(`Can not find item #${event.target.id}`);
343
+ }
280
344
  } else if (key === 'enter' && this.props.multiple) {
281
345
  event.preventDefault();
282
346
  this.handleClose();
@@ -291,6 +355,10 @@ class HiSelect extends React.PureComponent {
291
355
  } else if (this.overlay && key === 'esc' || key === 'enter') {
292
356
  event.preventDefault();
293
357
  this.handleClose();
358
+ } else if (key === 'tab') {
359
+ this.setState({
360
+ open: false
361
+ });
294
362
  }
295
363
  };
296
364
 
@@ -484,8 +552,8 @@ class HiSelect extends React.PureComponent {
484
552
  [classes.popperRightAlign]: this.props.containerWidth && this.props.align === 'right'
485
553
  });
486
554
 
487
- let searchInput = position => {
488
- if (!!searchable) {
555
+ const searchInput = position => {
556
+ if (searchable) {
489
557
  return React.createElement(HiInput, _extends({
490
558
  value: searchValue,
491
559
  autoFocus: true,
@@ -508,13 +576,13 @@ class HiSelect extends React.PureComponent {
508
576
 
509
577
  if (this.placement && this.placement.indexOf('top') >= 0 && !!searchable) {
510
578
  // +1 for search input
511
- let nbItems = itemList.length <= 10 ? itemList.length + 1 : 11;
579
+ const nbItems = itemList.length <= 10 ? itemList.length + 1 : 11;
512
580
  popperStyle.transform = `translate3d(-1px, -${nbItems * 40 + 2}px, 0px)`;
513
581
  } else if (this.placement && this.placement.indexOf('top') < 0 && !!searchable) {
514
- popperStyle.transform = `translate3d(-1px, 40px, 0px)`;
582
+ popperStyle.transform = 'translate3d(-1px, 40px, 0px)';
515
583
  }
516
584
 
517
- let content = ({
585
+ const content = ({
518
586
  placement
519
587
  }) => {
520
588
  if (placement !== this.placement) {
@@ -568,6 +636,7 @@ class HiSelect extends React.PureComponent {
568
636
  onClick: this.handleClick,
569
637
  onFocus: this.handleFocus,
570
638
  onBlur: this.handleBlur,
639
+ onKeyDown: this.handleKeyDownInput,
571
640
  onSubmit: onSubmit,
572
641
  onMouseEnter: this.props.onMouseEnter,
573
642
  onMouseLeave: this.props.onMouseLeave,
@@ -614,7 +683,8 @@ HiSelect.defaultProps = {
614
683
  n_children: '%s items',
615
684
  one_child: '%s item'
616
685
  },
617
- type: 'text'
686
+ type: 'text',
687
+ filterFunc: filterValue
618
688
  };
619
689
  HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
620
690
  align: PropTypes.oneOf(['left', 'right']),
@@ -649,6 +719,11 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
649
719
  */
650
720
  fallbackImage: PropTypes.string,
651
721
 
722
+ /*
723
+ * Fonction de filtrage custom
724
+ */
725
+ filterFunc: PropTypes.func,
726
+
652
727
  /**
653
728
  * Affiche l'élément 'All'
654
729
  */