@hipay/hipay-material-ui 2.0.0-beta.61 → 2.0.0-beta.63

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. package/CHANGELOG.md +136 -0
  2. package/HiDatePicker/HiDateRangeSelector.js +1 -1
  3. package/HiForm/HiInput.js +11 -3
  4. package/{HiSelectNew → HiSelect}/HiDynamicSelect.js +3 -3
  5. package/{HiSelectNew → HiSelect}/HiNestedSelect.js +9 -9
  6. package/{HiSelectNew → HiSelect}/HiNestedSelectContent.js +9 -9
  7. package/HiSelect/HiSelect.js +499 -608
  8. package/{HiSelectNew → HiSelect}/HiSelectContent.js +7 -7
  9. package/HiSelect/index.js +41 -3
  10. package/HiSelectableList/HiSelectableList.js +59 -3
  11. package/HiSelectableList/HiSelectableListItem.js +21 -6
  12. package/README.md +15 -0
  13. package/es/HiDatePicker/HiDateRangeSelector.js +1 -1
  14. package/es/HiForm/HiInput.js +11 -3
  15. package/es/{HiSelectNew → HiSelect}/HiNestedSelect.js +1 -1
  16. package/es/{HiSelectNew → HiSelect}/HiNestedSelectContent.js +1 -1
  17. package/es/HiSelect/HiSelect.js +451 -565
  18. package/es/{HiSelectNew → HiSelect}/HiSelectContent.js +1 -1
  19. package/es/HiSelect/index.js +4 -1
  20. package/es/HiSelectableList/HiSelectableList.js +56 -4
  21. package/es/HiSelectableList/HiSelectableListItem.js +18 -6
  22. package/index.es.js +1 -1
  23. package/index.js +1 -1
  24. package/package.json +2 -1
  25. package/umd/hipay-material-ui.development.js +41761 -39667
  26. package/umd/hipay-material-ui.production.min.js +2 -2
  27. package/HiSelect/SelectInput.js +0 -369
  28. package/HiSelectNew/HiSelect.js +0 -929
  29. package/HiSelectNew/HiSelectField.js +0 -146
  30. package/HiSelectNew/index.js +0 -69
  31. package/es/HiSelect/SelectInput.js +0 -321
  32. package/es/HiSelectNew/HiSelect.js +0 -852
  33. package/es/HiSelectNew/HiSelectField.js +0 -111
  34. package/es/HiSelectNew/index.js +0 -6
  35. /package/{HiSelectNew → HiSelect}/HiDynamicSelectField.js +0 -0
  36. /package/{HiSelectNew → HiSelect}/HiNestedSelectField.js +0 -0
  37. /package/{HiSelectNew → HiSelect}/HiSelectInput.js +0 -0
  38. /package/es/{HiSelectNew → HiSelect}/HiDynamicSelect.js +0 -0
  39. /package/es/{HiSelectNew → HiSelect}/HiDynamicSelectField.js +0 -0
  40. /package/es/{HiSelectNew → HiSelect}/HiNestedSelectField.js +0 -0
  41. /package/es/{HiSelectNew → HiSelect}/HiSelectInput.js +0 -0
@@ -1,24 +1,20 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
2
  import _objectSpread from "@babel/runtime/helpers/objectSpread";
4
- // @inheritedComponent Input
5
3
  import React from 'react';
6
4
  import PropTypes from 'prop-types';
7
- import classNames from 'classnames';
8
- import Grow from '@material-ui/core/Grow';
9
- import { findDOMNode } from 'react-dom';
10
5
  import Scrollbars from 'react-custom-scrollbars';
6
+ import Grow from '@material-ui/core/Grow';
11
7
  import Paper from '@material-ui/core/Paper';
12
- import ClickAwayListener from '@material-ui/core/ClickAwayListener';
13
8
  import Popper from '@material-ui/core/Popper';
9
+ import ClickAwayListener from '@material-ui/core/ClickAwayListener';
14
10
  import HiSelectableList from '../HiSelectableList';
15
- import HiSearchField from '../HiForm/HiSearchField';
16
- import SelectInput from './SelectInput';
17
- import HiChip from '../HiChip/HiChip';
18
- import { withStyles } from '../styles';
19
- import { arrayUnique, getNextItemSelectable } from '../utils/helpers';
11
+ import HiInput from '../HiForm/HiInput';
12
+ import HiSelectInput from './HiSelectInput';
13
+ import withStyles from '../styles/withStyles';
14
+ import { getNextItemSelectable, foldAccents } from '../utils/helpers';
20
15
  import HiIcon from '../HiIcon';
21
- export const INFINITESCROLL_ERROR_MESSAGE = 'La propriété "loadMoreResults" est obligatoire si la prop "infiniteScroll" est à true';
16
+ import keycode from 'keycode';
17
+ import classNames from 'classnames';
22
18
  export const styles = theme => ({
23
19
  root: {
24
20
  backgroundColor: theme.palette.background2,
@@ -32,14 +28,24 @@ export const styles = theme => ({
32
28
  popperWidth: {
33
29
  width: '100% !important'
34
30
  },
31
+ popperRightAlign: {
32
+ right: 0,
33
+ left: 'unset!important'
34
+ },
35
35
  paper: {
36
36
  borderRadius: '0px 2px',
37
- maxHeight: 440,
37
+ maxHeight: 480,
38
38
  transition: 'none !important'
39
39
  },
40
40
  labelIcon: {
41
41
  marginRight: 10
42
42
  },
43
+ labelImg: {
44
+ height: 18,
45
+ width: 'auto',
46
+ margin: '0 4px',
47
+ verticalAlign: 'middle'
48
+ },
43
49
  selectIconLabel: _objectSpread({
44
50
  whiteSpace: 'nowrap',
45
51
  overflow: 'hidden',
@@ -48,8 +54,24 @@ export const styles = theme => ({
48
54
  }, theme.typography.b1, {
49
55
  display: 'inline-flex',
50
56
  width: '100%'
51
- })
57
+ }),
58
+ selectImgLabel: _objectSpread({
59
+ whiteSpace: 'nowrap',
60
+ overflow: 'hidden',
61
+ textOverflow: 'ellipsis',
62
+ paddingRight: 16
63
+ }, theme.typography.b1, {
64
+ display: 'inline-flex',
65
+ width: '100%'
66
+ }),
67
+ separator: {
68
+ borderTop: `1px solid ${theme.palette.input.bottomLine}`
69
+ }
52
70
  });
71
+
72
+ function filterValue(item, search) {
73
+ return search === '' || foldAccents(item.label.toString().toLowerCase()).search(foldAccents(search.toLowerCase())) !== -1;
74
+ }
53
75
  /**
54
76
  *
55
77
  * Utilisé pour tous types de selects dans les formulaires.
@@ -58,83 +80,120 @@ export const styles = theme => ({
58
80
  * - avec / sans barre de recherche
59
81
  * - avec / sans option "All"
60
82
  * - prise en compte du type des éléments (text, image, icon, ...)
83
+ * - les actions du clavier son capturés avec KeyDown
61
84
  *
62
85
  * Ce composant réuni les sous-composants
63
- * - SelectInput : affiche l'élément dans le formulaire
64
- * - HiSearchField : intègre une barre de recherche dans le Popper,
65
- * il filtre la liste des suggestions
86
+ * - HiSelectInput : affiche l'élément dans le formulaire
87
+ * - HiSearchField : intègre une barre de recherche dans le Popper, il filtre la liste des suggestions
66
88
  * - HiSelectableList : affiche la liste des suggestions selon le type des éléments
67
89
  */
68
90
 
91
+
69
92
  class HiSelect extends React.PureComponent {
70
- constructor(_props) {
71
- super(_props);
72
-
73
- this.buildHierarchyTrees = props => {
74
- // Construct two associative arrays
75
- // hierarchy[parentId] => children
76
- // hierarchySelected[parentId] => selected children
77
- const hierarchy = {};
78
- const hierarchySelected = {};
79
- let value = props.value || [];
80
- if (!Array.isArray(value)) value = [props.value];
81
- props.options.forEach(option => {
82
- if (option.hasChildren === true && !hierarchy.hasOwnProperty(option.id)) {
83
- hierarchy[option.id] = [];
84
- hierarchySelected[option.id] = [];
85
- } else if (option.hasOwnProperty('parentId')) {
86
- hierarchy[option.parentId].push(option.id);
87
-
88
- if (value.includes(option.id)) {
89
- hierarchySelected[option.parentId].push(option.id);
90
- }
91
- }
92
- });
93
+ constructor(props) {
94
+ super(props);
95
+
96
+ this.buildSelectProps = (options, value = [], search = '', loading = false) => {
97
+ // build item list
98
+ const itemList = [...(loading ? [{
99
+ id: '_loading',
100
+ type: 'loader',
101
+ disabled: true,
102
+ centered: true,
103
+ hideCheckbox: true,
104
+ label: 'loading'
105
+ }] : []), // simple one level filter on label
106
+ ...(search !== '' ? [...options.filter(item => this.props.filterFunc(item, search))] : [...(this.props.hasAll ? [_objectSpread({
107
+ id: '_all',
108
+ label: this.props.translations.all
109
+ }, this.props.iconAll && {
110
+ type: 'icon',
111
+ icon: this.props.iconAll
112
+ })] : []), ...options])];
93
113
  return {
94
- hierarchy,
95
- hierarchySelected
114
+ itemList,
115
+ inputValue: this.buildInputValue(options, value, loading)
96
116
  };
97
117
  };
98
118
 
99
- this.focusOnSelectedItem = () => {
100
- // On récupère la div parent "overlay"
101
- const overlay = findDOMNode(this.overlay);
102
- const multiple = this.props.multiple;
103
- const value = this.props.value;
104
- const selectedIdList = Array.isArray(value) ? value : [value];
105
- setTimeout(() => {
106
- let focused = false; // Si un ou plusieurs items sont selectionnés, on focus sur le dernier
107
-
108
- if (selectedIdList.length > 0) {
109
- const itemSelected = overlay.querySelector(`[data-id="${selectedIdList[selectedIdList.length - 1]}"]`);
110
-
111
- if (itemSelected && itemSelected.parentElement.tagName === 'LI') {
112
- itemSelected.parentElement.focus();
113
- focused = true;
114
- }
115
- } // Si pas d'item selectionné, ou pas visible (en cas de recherche), focus sur le premier
119
+ this.buildInputValue = (options, value = [], loading = false) => {
120
+ const {
121
+ classes,
122
+ hasAll,
123
+ translations,
124
+ type
125
+ } = this.props; // build input value
126
+
127
+ let inputValue;
128
+
129
+ if (loading && value.length === 1) {
130
+ inputValue = translations.one_item_selected;
131
+ } else if (hasAll && options.length === value.length) {
132
+ inputValue = translations.all;
133
+ value.unshift('_all');
134
+ } else if (value.length > 1) {
135
+ inputValue = translations.n_items_selected.replace('%s', value.length);
136
+ } else if (value.length === 1) {
137
+ const item = options.find(o => o.id === value[0]);
138
+
139
+ if (item === undefined) {
140
+ inputValue = translations.one_item_selected;
141
+ } else if (type === 'icon' || item.type === 'icon') {
142
+ inputValue = React.createElement("span", {
143
+ className: classes.selectIconLabel
144
+ }, React.createElement(HiIcon, {
145
+ className: classes.labelIcon,
146
+ icon: item.icon
147
+ }), item.label);
148
+ } else if (type === 'image' || item.type === 'image') {
149
+ inputValue = React.createElement("span", {
150
+ className: classes.selectIconLabel
151
+ }, React.createElement("img", {
152
+ className: classes.labelImg,
153
+ src: item.img,
154
+ alt: item.label,
155
+ onError: e => {
156
+ if (item.fallbackImage) {
157
+ e.target.src = `${item.fallbackImage}`;
158
+ } else {
159
+ e.target.style.display = 'none';
160
+ }
161
+ }
162
+ }), item.label);
163
+ } else {
164
+ inputValue = item.label;
165
+ }
166
+ }
116
167
 
168
+ return inputValue;
169
+ };
117
170
 
118
- if (selectedIdList.length === 0 || !focused) {
119
- // On recupère tous les items
120
- const items = overlay.getElementsByTagName('li');
121
- let itemToFocus = items[0]; // Si select multiple, et qu'au moins un selectionné, focus sur le 2e item
171
+ this.focusOnFirstItem = () => {
172
+ if (this.overlay && this.overlay.getElementsByTagName('li')[0]) {
173
+ setTimeout(() => {
174
+ const item = this.overlay.getElementsByTagName('li')[0];
175
+ item.focus();
176
+ }, 1);
177
+ }
178
+ };
122
179
 
123
- if (multiple && selectedIdList.length > 0) {
124
- itemToFocus = items[1];
125
- }
180
+ this.getInputElement = el => {
181
+ this.searchField = el;
126
182
 
127
- if (itemToFocus) {
128
- itemToFocus.focus();
129
- }
130
- }
131
- }, 1);
183
+ if (this.props.inputRef) {
184
+ this.props.inputRef(this.searchField);
185
+ }
132
186
  };
133
187
 
134
- this.handleBlur = () => {
188
+ this.handleBlur = event => {
189
+ this.handleSearchReset();
135
190
  this.setState({
136
191
  focused: false
137
192
  });
193
+
194
+ if (this.props.onBlur && !this.inputEl.contains(event.relatedTarget) && !this.state.open) {
195
+ this.props.onBlur(event);
196
+ }
138
197
  };
139
198
 
140
199
  this.handleClick = () => {
@@ -144,40 +203,55 @@ class HiSelect extends React.PureComponent {
144
203
  this.setState({
145
204
  open: true
146
205
  });
147
- const options = this.props.options.slice();
148
- this.handleSuggestions(options);
149
-
150
- if (this.props.onClick) {
151
- this.props.onClick();
152
- } // Gestion du focus
153
-
206
+ this.handleSuggestions(this.props.options);
207
+ if (this.props.onClick) this.props.onClick(); // Gestion du focus
154
208
 
155
209
  if (!this.props.searchable) {
156
- // sinon focus sur le dernier élément selectionné
157
- this.focusOnSelectedItem();
210
+ // Sinon focus sur l'élément sélectionné
211
+ this.focusOnSelectedItem(this.props.value);
158
212
  }
159
213
  }
160
214
  };
161
215
 
216
+ this.focusOnSelectedItem = selectedValue => {
217
+ if (this.overlay && this.overlay.getElementsByTagName('li')[0]) {
218
+ setTimeout(() => {
219
+ // On initialise au premier élément pour être sûr de ne pas se retrouver avec un focus of undefined
220
+ let item = this.overlay.getElementsByTagName('li')[0];
221
+
222
+ if (selectedValue && typeof selectedValue === 'string') {
223
+ item = this.overlay.getElementsByTagName('li')[selectedValue];
224
+ } else if (selectedValue && typeof selectedValue === 'number') {
225
+ item = this.overlay.getElementsByTagName('li')[selectedValue - 1];
226
+ }
227
+
228
+ if (item) {
229
+ item.focus();
230
+ }
231
+ }, 1);
232
+ }
233
+ };
234
+
162
235
  this.handleClickAway = event => {
163
236
  // Au clic sur le bouton, on laisse le handleClick fermer le select
164
- if (!this.selectInputElement.contains(event.target)) {
237
+ if (!this.inputEl.contains(event.target)) {
165
238
  this.handleClose(event);
166
239
  }
167
240
  };
168
241
 
169
242
  this.handleClose = () => {
243
+ this.handleSearchReset();
244
+ this.setState({
245
+ open: false
246
+ });
247
+
170
248
  if (this.props.onClose) {
171
249
  this.props.onClose();
172
250
  }
173
251
 
174
- if (this.selectInputElement) {
175
- this.selectInputElement.focus();
252
+ if (this.inputEl) {
253
+ this.inputEl.focus();
176
254
  }
177
-
178
- this.setState({
179
- open: false
180
- });
181
255
  };
182
256
 
183
257
  this.handleFocus = () => {
@@ -186,310 +260,199 @@ class HiSelect extends React.PureComponent {
186
260
  });
187
261
  };
188
262
 
189
- this.handleKeyDown = event => {
190
- let nextItem;
191
-
192
- if (event.key === 'ArrowDown') {
193
- nextItem = getNextItemSelectable(document.activeElement, 'down');
194
- } else if (event.key === 'ArrowUp') {
195
- nextItem = getNextItemSelectable(document.activeElement, 'up');
196
- } else if (event.key === 'Tab' || event.key === 'Escape') {
197
- /* if (!this.props.staticPosition) {
198
- document.body.style.overflow = 'auto';
199
- } */
200
- this.setState({
201
- open: false
202
- });
263
+ this.handleKeyDownCapture = event => {
264
+ const key = keycode(event);
265
+
266
+ if (key === 'enter') {
267
+ if (this.state.open) {
268
+ if (this.props.multiple) {
269
+ event.stopPropagation();
270
+ this.handleClose();
271
+ }
272
+ }
203
273
  }
274
+ };
275
+
276
+ this.handleKeyDown = event => {
277
+ const key = keycode(event);
278
+
279
+ if (key === 'esc') {
280
+ event.preventDefault();
281
+ this.handleClose();
282
+ } else if (key === 'enter') {
283
+ if (this.state.open) {
284
+ if (this.props.multiple) {
285
+ this.handleClose();
286
+ }
287
+ }
288
+ } else if (key === 'space') {
289
+ event.preventDefault();
204
290
 
205
- if (nextItem) {
206
- nextItem.focus();
291
+ if (this.state.open) {
292
+ if (!this.props.multiple) {
293
+ this.setState({
294
+ open: false
295
+ });
296
+ }
297
+ } else {
298
+ this.setState({
299
+ open: true
300
+ });
301
+ }
302
+ } else if (key === 'tab') {
303
+ this.handleClose();
207
304
  }
208
305
  };
209
306
 
210
307
  this.handleKeyDownSearch = event => {
211
- if (this.overlay && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
212
- this.focusOnSelectedItem();
213
- } else if (event.key === 'Enter' && this.props.onSubmit) {
214
- this.props.onSubmit(event);
215
- } else if (event.key === 'Tab' || event.key === 'Escape') {
308
+ const key = keycode(event);
309
+
310
+ if (this.overlay && (key === 'down' || key === 'up')) {
311
+ this.focusOnFirstItem();
312
+ } else if (this.overlay && key === 'esc' || key === 'enter') {
313
+ event.preventDefault();
314
+ this.handleClose();
315
+ } else if (key === 'tab') {
216
316
  this.setState({
217
317
  open: false
218
318
  });
219
319
  }
220
320
  };
221
321
 
222
- this.handleRequestDelete = event => {
223
- event.stopPropagation();
224
- this.props.onChange(this.props.name, []);
225
- };
226
-
227
- this.handleReset = event => {
228
- if (this.props.onReset) {
229
- event.stopPropagation();
230
- this.props.onReset(event);
231
- }
232
- };
233
-
234
- this.handleScroll = event => {
235
- if (!this.props.loadingMoreResults && this.props.hasMore && event.target.scrollHeight - event.target.clientHeight - event.target.scrollTop < 15) {
236
- this.props.loadMoreResults(this.state.resultsPageNumber + 1);
237
- this.setState(prevState => ({
238
- resultsPageNumber: prevState.resultsPageNumber + 1
239
- }));
322
+ this.handleScroll = e => {
323
+ if (e.target.scrollHeight - e.target.clientHeight - e.target.scrollTop < 15) {
324
+ this.props.onScrollReachBottom();
240
325
  }
241
326
  };
242
327
 
243
328
  this.handleSelect = (event, item) => {
244
329
  const {
330
+ hasAll,
245
331
  multiple,
246
- value,
247
332
  onChange,
248
333
  options,
249
- hierarchic,
250
- pinnedItem
334
+ value
251
335
  } = this.props;
252
- const {
253
- hierarchySelected,
254
- hierarchy,
255
- nbOptions
256
- } = this.state;
257
-
258
- const hiSelected = _objectSpread({}, hierarchySelected);
259
336
 
260
- if (multiple) {
261
- let valueList = value;
262
-
263
- if (item.id === '_all') {
264
- if (valueList.length === nbOptions) {
265
- valueList = [];
266
-
267
- if (hierarchic) {
268
- // if hierarchic select => empty associative array of selected children
269
- Object.keys(hiSelected).forEach(key => {
270
- hiSelected[key] = [];
271
- });
272
- }
273
- } else {
274
- options.forEach(option => {
275
- if (option.hasChildren !== true && !valueList.includes(option.id) && option.id !== '_all') {
276
- valueList.push(option.id);
277
- } else if (option.hasChildren === true) {
278
- // if hierarchic select => fill associative array of selected children
279
- hiSelected[option.id] = hierarchy[option.id];
280
- }
281
- });
282
- }
283
- } else if (valueList.includes(item.id) || item.hasChildren === true && hierarchySelected[item.id].length === hierarchy[item.id].length) {
284
- // item déjà sélectionné => on le déselectionne
285
- if (item.hasChildren !== true) {
286
- valueList = valueList.filter(val => {
287
- return val !== item.id;
288
- });
289
- }
290
-
291
- if (item.hasChildren === true) {
292
- // remove all children
293
- valueList = valueList.filter(val => {
294
- return !this.state.hierarchy[item.id].includes(val);
295
- });
296
- hiSelected[item.id] = [];
297
- } else if (item.hasOwnProperty('parentId')) {
298
- // Si item est un enfant on l'enlève du tableau associatif des
299
- // elmts sélectionnés
300
- hiSelected[item.parentId].splice(hiSelected[item.parentId].indexOf(item.id), 1);
301
- }
337
+ if (!multiple) {
338
+ // single value
339
+ this.handleClose();
340
+ onChange(event, item.id, item);
341
+ } else if (hasAll && item.id === '_all') {
342
+ if (value.length === options.length) {
343
+ // unselect _all options
344
+ onChange(event, [], item);
302
345
  } else {
303
- if (pinnedItem && item.id === pinnedItem.id) {
304
- Object.keys(hiSelected).map(parentItemId => {
305
- hiSelected[parentItemId] = [];
306
- return true;
307
- });
308
- valueList = [item.id];
309
- } else {
310
- // item non sélectionné => on le sélectionne
311
- if (item.hasChildren !== true) valueList.push(item.id);
312
-
313
- if (pinnedItem && valueList.includes(pinnedItem.id)) {
314
- valueList.splice(valueList.indexOf(pinnedItem.id), 1);
315
- }
316
- }
317
-
318
- if (item.hasChildren === true) {
319
- // Si item parent => on ajoute tous les enfants
320
- // Ou on les supprime s'ils sont déjà tous sélectionnés (dans une liste filtrée)
321
- const idsInSuggestions = [];
322
- this.state.suggestions.forEach(suggestion => {
323
- if (this.state.hierarchy[item.id].includes(suggestion.id)) {
324
- idsInSuggestions.push(suggestion.id);
325
- }
326
- }); // if(hierarchySelected[item.id].length > 0) {}
327
-
328
- let allChildrenSuggestionsSelected = true;
329
- idsInSuggestions.forEach(id => {
330
- if (!hierarchySelected[item.id].includes(id)) {
331
- allChildrenSuggestionsSelected = false;
332
- }
333
- });
334
-
335
- if (allChildrenSuggestionsSelected === true) {
336
- // On supprime les enfants car déjà tous sélectionnés
337
- idsInSuggestions.forEach(id => {
338
- valueList.splice(valueList.indexOf(id), 1);
339
- hiSelected[item.id].splice(hiSelected[item.id].indexOf(id), 1);
340
- });
341
- } else {
342
- // On ajoute tous les enfants filtrés au éléments sélectionnés
343
- valueList = arrayUnique(valueList.concat(idsInSuggestions));
344
- hiSelected[item.id] = arrayUnique(hiSelected[item.id].concat(idsInSuggestions));
345
- }
346
-
347
- this.setState({
348
- hierarchySelected: hiSelected
349
- });
350
- } else if (item.hasOwnProperty('parentId')) {
351
- // Si item est un enfant on l'ajoute du tableau associatif des
352
- // elmts sélectionnés
353
- hiSelected[item.parentId].push(item.id);
354
- }
346
+ // select _all options
347
+ onChange(event, options.map(option => option.id), item);
355
348
  }
356
-
357
- this.setState({
358
- hierarchySelected: hiSelected
359
- });
360
- onChange(event, valueList, item);
349
+ } else if (value.includes(item.id)) {
350
+ // unselect item
351
+ onChange(event, value.filter(id => id !== item.id), item);
361
352
  } else {
362
- onChange(event, item.id, item);
363
- this.handleClose();
353
+ onChange(event, [...value, item.id], item);
364
354
  }
365
355
  };
366
356
 
367
357
  this.handleSuggestions = suggestions => {
368
358
  const {
369
- options,
370
359
  hasAll,
371
360
  iconAll,
372
- translations,
373
- multiple
361
+ translations
374
362
  } = this.props;
375
363
 
376
364
  if (suggestions.length === 0) {
377
- // Handle No Result
378
- // FIX to remove all item
379
- suggestions = [];
380
- suggestions.push({
381
- id: '_no_result',
382
- type: 'text',
383
- disabled: true,
384
- centered: true,
385
- checkbox: false,
386
- label: translations.no_result_match
387
- });
388
- } else if (hasAll && suggestions.length > 0 && suggestions.length === options.length && multiple === true) {
389
- // Handle 'All'
390
- if (suggestions.filter(suggestion => suggestion.id === '_all').length === 0) {
391
- const allItem = {
365
+ // Add '_no_result' suggestion
366
+ this.setState(prevState => _objectSpread({}, prevState, {
367
+ suggestions: [{
368
+ id: '_no_result',
369
+ type: 'text',
370
+ disabled: true,
371
+ centered: true,
372
+ hideCheckbox: true,
373
+ label: translations.no_result_match
374
+ }]
375
+ }));
376
+ } else {
377
+ this.setState({
378
+ suggestions: [// Add '_all' suggestion
379
+ ...(hasAll ? [_objectSpread({
392
380
  id: '_all',
393
- icon: iconAll,
394
381
  label: translations.all
395
- };
382
+ }, iconAll && {
383
+ type: 'icon',
384
+ icon: iconAll
385
+ })] : []), ...suggestions]
386
+ });
387
+ }
388
+ };
396
389
 
397
- if (iconAll !== false) {
398
- allItem.type = 'icon';
399
- }
390
+ this.handleSearch = (e, inputValue) => {
391
+ const searchValue = inputValue && e.target.value ? inputValue : e.target.value;
400
392
 
401
- suggestions.unshift(allItem);
402
- }
393
+ if (this.props.onSearch) {
394
+ this.props.onSearch(e, searchValue);
395
+ } else {
396
+ this.setState({
397
+ searchValue
398
+ });
403
399
  }
400
+ };
404
401
 
405
- this.setState({
406
- suggestions
407
- });
402
+ this.handleSearchReset = () => {
403
+ this.handleSearch({
404
+ target: {
405
+ value: ''
406
+ }
407
+ }, '');
408
408
  };
409
409
 
410
410
  this.state = {
411
411
  open: false,
412
412
  focused: false,
413
- suggestions: [],
414
- hierarchySelected: {},
415
- hierarchy: {},
416
- nbOptions: 0,
417
- dynamic: _props.dynamic || false,
418
- resultsPageNumber: 1
419
- }; // Check if value is in options
420
-
421
- let valueInOptions = false;
422
- const _val = _props.value; // No options provided.
423
-
424
- if (!_props.options.length || !_val || !_val.length) {
425
- valueInOptions = true;
426
- } else {
427
- // Check if an option match value prop.
428
- _props.options.forEach(item => {
429
- if (!valueInOptions && _val.indexOf(item.id) !== -1) {
430
- valueInOptions = true;
431
- }
432
- });
433
-
434
- if (!valueInOptions && _props.pinnedItem) {
435
- if (_props.value.indexOf(_props.pinnedItem.id) >= 0) {
436
- valueInOptions = true;
437
- }
438
- }
439
- }
440
-
441
- if (!valueInOptions) {
442
- throw new Error('prop value provided does not match any option.');
443
- }
444
-
445
- if (_props.hierarchic === true && _props.options.length > 1) {
446
- const hierarchyTrees = this.buildHierarchyTrees(_props);
447
- this.state.hierarchy = hierarchyTrees.hierarchy;
448
- this.state.hierarchySelected = hierarchyTrees.hierarchySelected;
449
- }
450
-
451
- if (_props.options.length > 0) {
452
- // Get real options number (parent & _all are not real options)
453
- let optionsLength = 0;
413
+ searchValue: props.searchValue ? undefined : '',
414
+ suggestions: props.options,
415
+ openDown: true
416
+ };
417
+ this.handleBlur = this.handleBlur.bind(this);
418
+ this.handleClick = this.handleClick.bind(this);
419
+ this.handleClose = this.handleClose.bind(this);
420
+ this.handleClickAway = this.handleClickAway.bind(this);
421
+ this.handleFocus = this.handleFocus.bind(this);
422
+ this.handleSearch = this.handleSearch.bind(this);
423
+ this.handleSearchReset = this.handleSearchReset.bind(this);
424
+ this.handleSelect = this.handleSelect.bind(this);
425
+ this.handleSuggestions = this.handleSuggestions.bind(this);
426
+ this.getInputElement = this.getInputElement.bind(this);
427
+ }
454
428
 
455
- _props.options.forEach(option => {
456
- if (option.hasChildren !== true && option.id !== '_all') {
457
- optionsLength += 1;
458
- }
429
+ static getDerivedStateFromProps(nextProps, prevState) {
430
+ if (nextProps.options !== prevState.suggestions) {
431
+ return _objectSpread({}, prevState, {
432
+ suggestions: nextProps.options
459
433
  });
460
-
461
- this.state.nbOptions = optionsLength;
462
- } else if (!_props.dynamic) {
463
- this.state.dynamic = true;
464
434
  }
435
+
436
+ return null;
465
437
  }
438
+ /**
439
+ * Build itemList & inputValue from select props
440
+ * @param options
441
+ * @param value
442
+ * @param search
443
+ * @param loading
444
+ * @returns {{itemList: *[], inputValue: *}}
445
+ */
466
446
 
467
- componentWillReceiveProps(nextProps) {
468
- if (typeof this.props.onSearch !== 'undefined' && this.props.options && this.props.options.length > 0) {
469
- this.handleSuggestions(nextProps.options);
470
- let optionsLength = 0;
471
- nextProps.options.forEach(option => {
472
- if (option.hasChildren !== true && option.id !== '_all') {
473
- optionsLength += 1;
474
- }
475
- });
476
- this.setState({
477
- nbOptions: optionsLength
478
- });
479
- }
480
447
 
481
- if (nextProps.hierarchic === true && nextProps.options.length > 1) {
482
- const hierarchyTrees = this.buildHierarchyTrees(nextProps);
483
- this.setState({
484
- hierarchy: hierarchyTrees.hierarchy,
485
- hierarchySelected: hierarchyTrees.hierarchySelected
486
- });
448
+ componentDidMount() {
449
+ if (this.props.autoFocus) {
450
+ this.inputEl.focus();
487
451
  }
488
452
  }
489
453
 
490
454
  render() {
491
- const _this$props = this.props,
492
- {
455
+ const {
493
456
  classes,
494
457
  disabled,
495
458
  error,
@@ -499,105 +462,42 @@ class HiSelect extends React.PureComponent {
499
462
  displayAsChip,
500
463
  type,
501
464
  value,
465
+ multiple,
502
466
  translations,
503
- parentItemSelectable,
504
- icon,
505
- parentIcon,
506
- hoverIcon,
507
- checkedIcon,
467
+ hiSearchInputProps,
468
+ hiSelectableListProps,
469
+ hiSelectInputProps,
508
470
  id,
471
+ onScrollReachBottom,
472
+ onSubmit,
509
473
  placeholder,
474
+ searchValue = this.state.searchValue,
475
+ startAdornment,
510
476
  staticPosition,
511
- pinnedItem,
512
- hasAll,
513
- infiniteScroll,
514
- loadingMoreResults,
515
- multiple
516
- } = _this$props,
517
- other = _objectWithoutProperties(_this$props, ["classes", "disabled", "error", "loading", "options", "searchable", "displayAsChip", "type", "value", "translations", "parentItemSelectable", "icon", "parentIcon", "hoverIcon", "checkedIcon", "id", "placeholder", "staticPosition", "pinnedItem", "hasAll", "infiniteScroll", "loadingMoreResults", "multiple"]);
477
+ buildSelectProps = this.buildSelectProps // use parent builder if defined
518
478
 
479
+ } = this.props;
519
480
  const {
520
481
  open,
521
- suggestions: stateSuggestions,
522
- focused,
523
- dynamic
482
+ focused
524
483
  } = this.state;
525
- let display = '';
526
- let selectedIdList;
527
-
528
- if (Array.isArray(value)) {
529
- selectedIdList = value;
530
- } else if (value) {
531
- selectedIdList = [value];
532
- } else {
533
- selectedIdList = [];
534
- }
535
-
536
- const suggestions = [...stateSuggestions];
537
-
538
- if (pinnedItem) {
539
- suggestions.unshift(pinnedItem);
540
- } // If loading
541
-
542
-
543
- if (loading && !loadingMoreResults) {
544
- suggestions.unshift({
545
- id: '_loading',
546
- type: 'loader',
547
- disabled: true,
548
- centered: true,
549
- checkbox: false,
550
- label: 'loading'
551
- });
552
- }
553
-
554
- if ((dynamic || loading) && selectedIdList.length === 1) {
555
- display = translations.one_item_selected;
556
- } else if ((this.state.nbOptions !== selectedIdList.length || !hasAll) && selectedIdList.length > 1) {
557
- display = translations.n_items_selected.replace('%s', selectedIdList.length);
558
- } else if (this.state.nbOptions === selectedIdList.length && this.state.nbOptions > 1) {
559
- display = translations.all;
560
- } else if (selectedIdList.length === 1) {
561
- let item = options.find(o => o.id === selectedIdList[0]);
562
-
563
- if (item === undefined) {
564
- display = translations.one_item_selected;
565
- } else if (type !== 'icon') {
566
- if (pinnedItem) {
567
- item = pinnedItem;
568
- }
569
-
570
- display = item.label;
571
- } else {
572
- display = React.createElement("span", {
573
- className: classes.selectIconLabel
574
- }, React.createElement(HiIcon, {
575
- icon: item.icon,
576
- className: classes.labelIcon
577
- }), item.label);
578
- }
579
- }
580
-
581
- if (displayAsChip) {
582
- const chipFilter = React.createElement(HiChip, {
583
- label: placeholder || display,
584
- onDelete: this.handleRequestDelete
585
- });
586
484
 
587
- if (display) {
588
- display = chipFilter;
485
+ if (multiple) {
486
+ if (!Array.isArray(value)) {
487
+ throw new Error('HiPay Material-UI: the `value` property must be an array ' + 'when using the `HiSelect` component with `multiple`.');
589
488
  }
590
489
  }
591
490
 
592
- const popperClass = classNames(classes.popper, {
593
- [classes.popperWidth]: !this.props.containerWidth
594
- });
595
- let allSelected = false;
491
+ let selectedItemIdList = [];
596
492
 
597
- if (selectedIdList.length === this.state.nbOptions) {
598
- allSelected = true;
493
+ if (value) {
494
+ selectedItemIdList = multiple ? [...value] : [value];
599
495
  }
600
496
 
497
+ const {
498
+ itemList,
499
+ inputValue = this.buildInputValue(options, selectedItemIdList, loading)
500
+ } = buildSelectProps(options, selectedItemIdList, searchValue, loading);
601
501
  let popperStyle = {};
602
502
 
603
503
  if (this.props.containerWidth > 0) {
@@ -610,69 +510,87 @@ class HiSelect extends React.PureComponent {
610
510
  }
611
511
  }
612
512
 
613
- if (infiniteScroll && loadingMoreResults) {
614
- suggestions.push({
615
- id: '_loading',
616
- type: 'loader',
617
- disabled: true,
618
- centered: true,
619
- checkbox: false,
620
- label: 'loading'
621
- });
513
+ const popperClass = classNames(classes.popper, {
514
+ [classes.popperWidth]: !this.props.containerWidth,
515
+ [classes.popperRightAlign]: this.props.containerWidth && this.props.align === 'right'
516
+ });
517
+
518
+ const searchInput = position => {
519
+ if (searchable) {
520
+ return React.createElement(HiInput, _extends({
521
+ value: searchValue,
522
+ autoFocus: true,
523
+ inputRef: this.getInputElement,
524
+ onKeyDown: this.handleKeyDownSearch,
525
+ onChange: this.handleSearch,
526
+ onReset: this.handleSearchReset,
527
+ placeholder: translations.search,
528
+ startAdornment: 'search',
529
+ tabIndex: 0,
530
+ className: classNames({
531
+ [classes.separator]: position === 'top'
532
+ })
533
+ }, hiSearchInputProps));
534
+ }
535
+
536
+ return null;
537
+ }; // Replace popper onSearch when popper displayed on top of selectButton
538
+
539
+
540
+ if (this.placement && this.placement.indexOf('top') >= 0 && !!searchable) {
541
+ // +1 for search input
542
+ const nbItems = itemList.length <= 10 ? itemList.length + 1 : 11;
543
+ popperStyle.transform = `translate3d(-1px, -${nbItems * 40 + 2}px, 0px)`;
544
+ } else if (this.placement && this.placement.indexOf('top') < 0 && !!searchable) {
545
+ popperStyle.transform = 'translate3d(-1px, 40px, 0px)';
622
546
  }
623
547
 
624
- const content = React.createElement(ClickAwayListener, {
625
- onClickAway: this.handleClickAway
626
- }, React.createElement(Grow, {
627
- in: open,
628
- id: "menu-list",
629
- style: {
630
- transformOrigin: '0 0 0'
548
+ const content = ({
549
+ placement
550
+ }) => {
551
+ if (placement !== this.placement) {
552
+ this.placement = placement;
631
553
  }
632
- }, React.createElement(Paper, {
633
- className: classes.paper
634
- }, !!searchable && React.createElement(HiSearchField, {
635
- itemList: options,
636
- onFilteredList: this.handleSuggestions,
637
- filterPropertyList: ['label'],
638
- placeholder: translations.search,
639
- autoFocus: true,
640
- onSearch: this.props.onSearch,
641
- inputRef: el => {
642
- this.searchField = el;
643
- },
644
- onKeyDown: this.handleKeyDownSearch
645
- }), React.createElement(Scrollbars, {
646
- ref: contentEl => {
647
- this.optionsContent = contentEl;
648
- },
649
- autoHeight: true,
650
- autoHeightMax: 400,
651
- onScroll: this.handleScroll
652
- }, React.createElement(HiSelectableList, _extends({
653
- type: type,
654
- parentItemSelectable: parentItemSelectable,
655
- itemList: suggestions,
656
- onSelect: this.handleSelect,
657
- selectedItemIdList: selectedIdList,
658
- hideCheckbox: !multiple,
659
- translations: translations,
660
- icon: icon,
661
- parentIcon: parentIcon,
662
- hoverIcon: hoverIcon,
663
- checkedIcon: checkedIcon,
664
- allSelected: allSelected,
665
- value: value,
666
- onKeyDown: this.handleKeyDown
667
- }, other))))));
554
+
555
+ return React.createElement(ClickAwayListener, {
556
+ onClickAway: this.handleClickAway
557
+ }, React.createElement(Grow, {
558
+ in: open,
559
+ id: "menu-list",
560
+ style: {
561
+ transformOrigin: '0 0 0'
562
+ }
563
+ }, React.createElement(Paper, {
564
+ className: classes.paper
565
+ }, (this.placement && this.placement.indexOf('bottom') >= 0 || staticPosition) && searchInput('bottom'), startAdornment, React.createElement(Scrollbars, _extends({
566
+ ref: contentEl => {
567
+ this.optionsContent = contentEl;
568
+ },
569
+ autoHeight: true,
570
+ autoHeightMax: 430
571
+ }, onScrollReachBottom && {
572
+ onScroll: this.handleScroll
573
+ }), React.createElement(HiSelectableList, _extends({
574
+ type: type,
575
+ itemList: itemList,
576
+ onSelect: this.handleSelect,
577
+ selectedItemIdList: selectedItemIdList,
578
+ fallbackImage: this.props.fallbackImage,
579
+ overlay: this.overlay,
580
+ value: value
581
+ }, hiSelectableListProps))), this.placement && this.placement.indexOf('top') >= 0 && !staticPosition && searchInput('top'))));
582
+ };
583
+
668
584
  return React.createElement("div", {
669
585
  className: classes.root,
670
586
  ref: el => {
671
587
  this.overlay = el;
672
- }
673
- }, React.createElement(SelectInput, {
588
+ },
589
+ onKeyDown: this.handleKeyDown,
590
+ onKeyDownCapture: this.handleKeyDownCapture
591
+ }, React.createElement(HiSelectInput, _extends({
674
592
  id: id,
675
- value: placeholder || display,
593
+ value: inputValue,
676
594
  open: open,
677
595
  focused: focused,
678
596
  type: type,
@@ -682,42 +600,44 @@ class HiSelect extends React.PureComponent {
682
600
  onClick: this.handleClick,
683
601
  onFocus: this.handleFocus,
684
602
  onBlur: this.handleBlur,
685
- onKeyDown: this.handleKeyDown,
603
+ onSubmit: onSubmit,
686
604
  onMouseEnter: this.props.onMouseEnter,
687
605
  onMouseLeave: this.props.onMouseLeave,
606
+ onReset: this.props.onReset,
607
+ placeholder: placeholder
608
+ }, hiSelectInputProps, {
688
609
  refElement: el => {
689
- this.selectInputElement = el;
690
- },
691
- onReset: this.props.onReset
692
- }), open && staticPosition ? React.createElement("div", {
693
- style: popperStyle
694
- }, content) : React.createElement(Popper, {
610
+ this.inputEl = el;
611
+ }
612
+ })), open && staticPosition ? React.createElement("div", {
613
+ style: popperStyle,
614
+ className: popperClass
615
+ }, content({})) : React.createElement(Popper, {
695
616
  anchorEl: this.inputEl,
696
617
  placement: "bottom-start",
697
618
  open: open,
698
619
  className: popperClass,
699
- style: popperStyle,
700
- disablePortal: true
620
+ disablePortal: true,
621
+ style: popperStyle
701
622
  }, content));
702
623
  }
703
624
 
704
625
  }
705
626
 
706
627
  HiSelect.defaultProps = {
707
- containerWidth: 0,
628
+ align: 'left',
629
+ autoFocus: false,
708
630
  disabled: false,
709
631
  displayAsChip: false,
710
- dynamic: false,
711
632
  error: false,
712
633
  hasAll: false,
713
- hasMore: false,
714
- hierarchic: false,
715
- iconAll: false,
716
- infiniteScroll: false,
717
- loadingMoreResults: false,
634
+ hiSelectableListProps: {},
635
+ hiSelectInputProps: {},
636
+ hiSearchInputProps: {},
718
637
  multiple: false,
719
- parentItemSelectable: false,
720
- type: 'text',
638
+ placeholder: '',
639
+ searchable: false,
640
+ staticPosition: false,
721
641
  translations: {
722
642
  all: 'All',
723
643
  no_result_match: 'No result match',
@@ -727,14 +647,16 @@ HiSelect.defaultProps = {
727
647
  n_children: '%s items',
728
648
  one_child: '%s item'
729
649
  },
730
- searchable: false,
731
- staticPosition: false
650
+ type: 'text',
651
+ filterFunc: filterValue
732
652
  };
733
653
  HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
654
+ align: PropTypes.oneOf(['left', 'right']),
655
+
734
656
  /**
735
- * Icon affiché lorsque l'item est sélectionné
657
+ * Permet de forcer le focus sur le composant
736
658
  */
737
- checkedIcon: PropTypes.node,
659
+ autoFocus: PropTypes.bool,
738
660
 
739
661
  /**
740
662
  * Useful to extend the style applied to components.
@@ -756,77 +678,56 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
756
678
  */
757
679
  displayAsChip: PropTypes.bool,
758
680
 
759
- /**
760
- * Option permettant de définir si les options du select sont dynamiques.
761
- * Si les options du select sont initialisées à vide, alors ce sera mis à true
762
- * automatiquement.
763
- */
764
- dynamic: PropTypes.bool,
765
-
766
681
  /**
767
682
  * Applique le style error
768
683
  */
769
684
  error: PropTypes.bool,
770
685
 
771
686
  /**
772
- * Affiche l'élément 'All'
687
+ * Chemin vers l'image à afficher par défaut si une image n'est pas trouvée
773
688
  */
774
- hasAll: PropTypes.bool,
689
+ fallbackImage: PropTypes.string,
690
+
691
+ /*
692
+ * Fonction de filtrage custom
693
+ */
694
+ filterFunc: PropTypes.func,
775
695
 
776
696
  /**
777
- * Indique si l'infinite scroll doit rechercher de nouveaux résultats
697
+ * Affiche l'élément 'All'
778
698
  */
779
- hasMore: PropTypes.bool,
699
+ hasAll: PropTypes.bool,
780
700
 
781
701
  /**
782
- * Les items sont hiérarchisés
702
+ * Override HiInput props (for search)
783
703
  */
784
- hierarchic: PropTypes.bool,
704
+ hiSearchInputProps: PropTypes.object,
785
705
 
786
706
  /**
787
- * Icon affiché lorsque l'item n'est pas sélectionné et qu'on le survole
707
+ * Override HiSelectableList props
788
708
  */
789
- hoverIcon: PropTypes.node,
709
+ hiSelectableListProps: PropTypes.object,
790
710
 
791
711
  /**
792
- * Icon affiché lorsque l'item n'est pas sélectionné
712
+ * Override HiSelectInput props
793
713
  */
794
- icon: PropTypes.node,
714
+ hiSelectInputProps: PropTypes.object,
795
715
 
796
716
  /**
797
717
  * Nom de l'icône
798
718
  */
799
- iconAll: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
719
+ iconAll: PropTypes.string,
800
720
 
801
721
  /**
802
722
  * id du select
803
723
  */
804
724
  id: PropTypes.string,
805
725
 
806
- /**
807
- * Infinite scroll dans le select dans le cas où il y a beaucoup de résultats à afficher
808
- * afin d'éviter un lag du navigateur
809
- */
810
- infiniteScroll: PropTypes.bool,
811
-
812
726
  /**
813
727
  * Ajoute un loader
814
728
  */
815
729
  loading: PropTypes.bool,
816
730
 
817
- /**
818
- * Ajoute un loader en bas pour l'infiniteScroll
819
- */
820
- loadingMoreResults: PropTypes.bool,
821
-
822
- /**
823
- * Fonction de callback appelée lorsque l'utilisateur arrive en bas de la liste des options
824
- * afin de charger les nouvelles options
825
- *
826
- * @param {int} pageNumber
827
- */
828
- loadMoreResults: PropTypes.func,
829
-
830
731
  /**
831
732
  * Autorise la sélection de plusieurs valeurs
832
733
  */
@@ -837,6 +738,11 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
837
738
  */
838
739
  name: PropTypes.string.isRequired,
839
740
 
741
+ /**
742
+ * Fonction de callback appelée lorsqu'on perd le focus
743
+ */
744
+ onBlur: PropTypes.func,
745
+
840
746
  /**
841
747
  * Fonction de callback qui renvoit la/les valeurs sélectionnées
842
748
  *
@@ -845,11 +751,6 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
845
751
  */
846
752
  onChange: PropTypes.func.isRequired,
847
753
 
848
- /**
849
- * Fonction de callback appelée click dans l'input
850
- */
851
- onClick: PropTypes.func,
852
-
853
754
  /**
854
755
  * Fonction de callback appelée lorsqu'on ferme le select
855
756
  */
@@ -871,18 +772,14 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
871
772
  onReset: PropTypes.func,
872
773
 
873
774
  /**
874
- * Fonction de callback appelée lorsqu'on écrit dans la barre de recherche
875
- * A utiliser pour les selects avec des données dynamiques
876
- *
877
- * @param {object} event
878
- * @param {string} value
775
+ * Fonction de callback appelée lorsque le scroll atteint le bas de la liste
879
776
  */
880
- onSearch: PropTypes.func,
777
+ onScrollReachBottom: PropTypes.func,
881
778
 
882
779
  /**
883
- * Fonction de callback à la pression de la touche "Entrée"
780
+ * Fonction de callback appelée lorsque le champs de recherche est utilisé
884
781
  */
885
- onSubmit: PropTypes.func,
782
+ onSearch: PropTypes.func,
886
783
 
887
784
  /**
888
785
  * Listes des options du select
@@ -890,23 +787,7 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
890
787
  options: PropTypes.array.isRequired,
891
788
 
892
789
  /**
893
- * Icon affiché lorsqu'un item parent n'est pas sélectionné
894
- */
895
- parentIcon: PropTypes.node,
896
-
897
- /**
898
- * Les items parents sont sélectionnables
899
- */
900
- parentItemSelectable: PropTypes.bool,
901
-
902
- /**
903
- * Item épinglé en début de liste
904
- */
905
- pinnedItem: PropTypes.object,
906
-
907
- /**
908
- * Placeholder affiché lorsque le select est fermé
909
- * Surcharge le placeholder par défaut
790
+ * Placeholder affiché lorsque l'input est vide
910
791
  */
911
792
  placeholder: PropTypes.string,
912
793
 
@@ -916,7 +797,12 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
916
797
  searchable: PropTypes.bool,
917
798
 
918
799
  /**
919
- * Si true, le contenu du select sera dans une div static plutot que dans une popper absolute
800
+ * Node qui s'ajoute entre la barre de recherche et la liste de résultats
801
+ */
802
+ startAdornment: PropTypes.object,
803
+
804
+ /**
805
+ * Si true, le contenu du select sera dans une div static plutôt que dans une popper absolute
920
806
  */
921
807
  staticPosition: PropTypes.bool,
922
808