@hipay/hipay-material-ui 2.0.0-beta.60 → 2.0.0-beta.62

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/HiDatePicker/HiDatePicker.js +37 -12
  3. package/HiDatePicker/HiDateRangePicker.js +71 -57
  4. package/HiDatePicker/HiDateRangeSelector.js +34 -20
  5. package/HiDatePicker/stylesheet.js +32 -17
  6. package/HiSelect/HiSelect.js +489 -607
  7. package/HiSelect/index.js +41 -3
  8. package/HiSelectableList/HiSelectableList.js +68 -3
  9. package/HiSelectableList/HiSelectableListItem.js +22 -10
  10. package/README.md +15 -0
  11. package/es/HiDatePicker/HiDatePicker.js +30 -10
  12. package/es/HiDatePicker/HiDateRangePicker.js +38 -21
  13. package/es/HiDatePicker/HiDateRangeSelector.js +24 -13
  14. package/es/HiDatePicker/stylesheet.js +32 -17
  15. package/es/{HiSelectNew → HiSelect}/HiNestedSelect.js +1 -1
  16. package/es/{HiSelectNew → HiSelect}/HiNestedSelectContent.js +1 -1
  17. package/es/HiSelect/HiSelect.js +441 -564
  18. package/es/{HiSelectNew → HiSelect}/HiSelectContent.js +1 -1
  19. package/es/HiSelect/index.js +4 -1
  20. package/es/HiSelectableList/HiSelectableList.js +65 -4
  21. package/es/HiSelectableList/HiSelectableListItem.js +18 -10
  22. package/es/styles/createPalette.js +1 -1
  23. package/es/utils/helpers.js +9 -1
  24. package/index.es.js +1 -1
  25. package/index.js +1 -1
  26. package/package.json +1 -1
  27. package/styles/createPalette.js +1 -1
  28. package/umd/hipay-material-ui.development.js +7860 -7749
  29. package/umd/hipay-material-ui.production.min.js +2 -2
  30. package/utils/helpers.js +9 -1
  31. package/HiSelect/SelectInput.js +0 -369
  32. package/HiSelectNew/HiSelect.js +0 -929
  33. package/HiSelectNew/HiSelectField.js +0 -146
  34. package/HiSelectNew/index.js +0 -69
  35. package/es/HiSelect/SelectInput.js +0 -321
  36. package/es/HiSelectNew/HiSelect.js +0 -852
  37. package/es/HiSelectNew/HiSelectField.js +0 -111
  38. package/es/HiSelectNew/index.js +0 -6
  39. /package/{HiSelectNew → HiSelect}/HiDynamicSelect.js +0 -0
  40. /package/{HiSelectNew → HiSelect}/HiDynamicSelectField.js +0 -0
  41. /package/{HiSelectNew → HiSelect}/HiNestedSelect.js +0 -0
  42. /package/{HiSelectNew → HiSelect}/HiNestedSelectContent.js +0 -0
  43. /package/{HiSelectNew → HiSelect}/HiNestedSelectField.js +0 -0
  44. /package/{HiSelectNew → HiSelect}/HiSelectContent.js +0 -0
  45. /package/{HiSelectNew → HiSelect}/HiSelectInput.js +0 -0
  46. /package/es/{HiSelectNew → HiSelect}/HiDynamicSelect.js +0 -0
  47. /package/es/{HiSelectNew → HiSelect}/HiDynamicSelectField.js +0 -0
  48. /package/es/{HiSelectNew → HiSelect}/HiNestedSelectField.js +0 -0
  49. /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,80 +80,113 @@ 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
188
  this.handleBlur = () => {
189
+ this.handleSearchReset();
135
190
  this.setState({
136
191
  focused: false
137
192
  });
@@ -144,40 +199,55 @@ class HiSelect extends React.PureComponent {
144
199
  this.setState({
145
200
  open: true
146
201
  });
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
-
202
+ this.handleSuggestions(this.props.options);
203
+ if (this.props.onClick) this.props.onClick(); // Gestion du focus
154
204
 
155
205
  if (!this.props.searchable) {
156
- // sinon focus sur le dernier élément selectionné
157
- this.focusOnSelectedItem();
206
+ // Sinon focus sur l'élément sélectionné
207
+ this.focusOnSelectedItem(this.props.value);
158
208
  }
159
209
  }
160
210
  };
161
211
 
212
+ this.focusOnSelectedItem = selectedValue => {
213
+ if (this.overlay && this.overlay.getElementsByTagName('li')[0]) {
214
+ setTimeout(() => {
215
+ // On initialise au premier élément pour être sûr de ne pas se retrouver avec un focus of undefined
216
+ let item = this.overlay.getElementsByTagName('li')[0];
217
+
218
+ if (selectedValue && typeof selectedValue === 'string') {
219
+ item = this.overlay.getElementsByTagName('li')[selectedValue];
220
+ } else if (selectedValue && typeof selectedValue === 'number') {
221
+ item = this.overlay.getElementsByTagName('li')[selectedValue - 1];
222
+ }
223
+
224
+ if (item) {
225
+ item.focus();
226
+ }
227
+ }, 1);
228
+ }
229
+ };
230
+
162
231
  this.handleClickAway = event => {
163
232
  // Au clic sur le bouton, on laisse le handleClick fermer le select
164
- if (!this.selectInputElement.contains(event.target)) {
233
+ if (!this.inputEl.contains(event.target)) {
165
234
  this.handleClose(event);
166
235
  }
167
236
  };
168
237
 
169
238
  this.handleClose = () => {
239
+ this.handleSearchReset();
240
+ this.setState({
241
+ open: false
242
+ });
243
+
170
244
  if (this.props.onClose) {
171
245
  this.props.onClose();
172
246
  }
173
247
 
174
- if (this.selectInputElement) {
175
- this.selectInputElement.focus();
248
+ if (this.inputEl) {
249
+ this.inputEl.focus();
176
250
  }
177
-
178
- this.setState({
179
- open: false
180
- });
181
251
  };
182
252
 
183
253
  this.handleFocus = () => {
@@ -186,310 +256,199 @@ class HiSelect extends React.PureComponent {
186
256
  });
187
257
  };
188
258
 
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
- });
259
+ this.handleKeyDownCapture = event => {
260
+ const key = keycode(event);
261
+
262
+ if (key === 'enter') {
263
+ if (this.state.open) {
264
+ if (this.props.multiple) {
265
+ event.stopPropagation();
266
+ this.handleClose();
267
+ }
268
+ }
203
269
  }
270
+ };
204
271
 
205
- if (nextItem) {
206
- nextItem.focus();
272
+ this.handleKeyDown = event => {
273
+ const key = keycode(event);
274
+
275
+ if (key === 'esc') {
276
+ event.preventDefault();
277
+ this.handleClose();
278
+ } else if (key === 'enter') {
279
+ if (this.state.open) {
280
+ if (this.props.multiple) {
281
+ this.handleClose();
282
+ }
283
+ }
284
+ } else if (key === 'space') {
285
+ event.preventDefault();
286
+
287
+ if (this.state.open) {
288
+ if (!this.props.multiple) {
289
+ this.setState({
290
+ open: false
291
+ });
292
+ }
293
+ } else {
294
+ this.setState({
295
+ open: true
296
+ });
297
+ }
298
+ } else if (key === 'tab') {
299
+ this.handleClose();
207
300
  }
208
301
  };
209
302
 
210
303
  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') {
304
+ const key = keycode(event);
305
+
306
+ if (this.overlay && (key === 'down' || key === 'up')) {
307
+ this.focusOnFirstItem();
308
+ } else if (this.overlay && key === 'esc' || key === 'enter') {
309
+ event.preventDefault();
310
+ this.handleClose();
311
+ } else if (key === 'tab') {
216
312
  this.setState({
217
313
  open: false
218
314
  });
219
315
  }
220
316
  };
221
317
 
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
- }));
318
+ this.handleScroll = e => {
319
+ if (e.target.scrollHeight - e.target.clientHeight - e.target.scrollTop < 15) {
320
+ this.props.onScrollReachBottom();
240
321
  }
241
322
  };
242
323
 
243
324
  this.handleSelect = (event, item) => {
244
325
  const {
326
+ hasAll,
245
327
  multiple,
246
- value,
247
328
  onChange,
248
329
  options,
249
- hierarchic,
250
- pinnedItem
330
+ value
251
331
  } = this.props;
252
- const {
253
- hierarchySelected,
254
- hierarchy,
255
- nbOptions
256
- } = this.state;
257
-
258
- const hiSelected = _objectSpread({}, hierarchySelected);
259
-
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
332
 
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
- }
333
+ if (!multiple) {
334
+ // single value
335
+ this.handleClose();
336
+ onChange(event, item.id, item);
337
+ } else if (hasAll && item.id === '_all') {
338
+ if (value.length === options.length) {
339
+ // unselect _all options
340
+ onChange(event, [], item);
302
341
  } 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
- }
342
+ // select _all options
343
+ onChange(event, options.map(option => option.id), item);
355
344
  }
356
-
357
- this.setState({
358
- hierarchySelected: hiSelected
359
- });
360
- onChange(event, valueList, item);
345
+ } else if (value.includes(item.id)) {
346
+ // unselect item
347
+ onChange(event, value.filter(id => id !== item.id), item);
361
348
  } else {
362
- onChange(event, item.id, item);
363
- this.handleClose();
349
+ onChange(event, [...value, item.id], item);
364
350
  }
365
351
  };
366
352
 
367
353
  this.handleSuggestions = suggestions => {
368
354
  const {
369
- options,
370
355
  hasAll,
371
356
  iconAll,
372
- translations,
373
- multiple
357
+ translations
374
358
  } = this.props;
375
359
 
376
360
  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 = {
361
+ // Add '_no_result' suggestion
362
+ this.setState(prevState => _objectSpread({}, prevState, {
363
+ suggestions: [{
364
+ id: '_no_result',
365
+ type: 'text',
366
+ disabled: true,
367
+ centered: true,
368
+ hideCheckbox: true,
369
+ label: translations.no_result_match
370
+ }]
371
+ }));
372
+ } else {
373
+ this.setState({
374
+ suggestions: [// Add '_all' suggestion
375
+ ...(hasAll ? [_objectSpread({
392
376
  id: '_all',
393
- icon: iconAll,
394
377
  label: translations.all
395
- };
378
+ }, iconAll && {
379
+ type: 'icon',
380
+ icon: iconAll
381
+ })] : []), ...suggestions]
382
+ });
383
+ }
384
+ };
396
385
 
397
- if (iconAll !== false) {
398
- allItem.type = 'icon';
399
- }
386
+ this.handleSearch = (e, inputValue) => {
387
+ const searchValue = inputValue && e.target.value ? inputValue : e.target.value;
400
388
 
401
- suggestions.unshift(allItem);
402
- }
389
+ if (this.props.onSearch) {
390
+ this.props.onSearch(e, searchValue);
391
+ } else {
392
+ this.setState({
393
+ searchValue
394
+ });
403
395
  }
396
+ };
404
397
 
405
- this.setState({
406
- suggestions
407
- });
398
+ this.handleSearchReset = () => {
399
+ this.handleSearch({
400
+ target: {
401
+ value: ''
402
+ }
403
+ }, '');
408
404
  };
409
405
 
410
406
  this.state = {
411
407
  open: false,
412
408
  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;
409
+ searchValue: props.searchValue ? undefined : '',
410
+ suggestions: props.options,
411
+ openDown: true
412
+ };
413
+ this.handleBlur = this.handleBlur.bind(this);
414
+ this.handleClick = this.handleClick.bind(this);
415
+ this.handleClose = this.handleClose.bind(this);
416
+ this.handleClickAway = this.handleClickAway.bind(this);
417
+ this.handleFocus = this.handleFocus.bind(this);
418
+ this.handleSearch = this.handleSearch.bind(this);
419
+ this.handleSearchReset = this.handleSearchReset.bind(this);
420
+ this.handleSelect = this.handleSelect.bind(this);
421
+ this.handleSuggestions = this.handleSuggestions.bind(this);
422
+ this.getInputElement = this.getInputElement.bind(this);
423
+ }
454
424
 
455
- _props.options.forEach(option => {
456
- if (option.hasChildren !== true && option.id !== '_all') {
457
- optionsLength += 1;
458
- }
425
+ static getDerivedStateFromProps(nextProps, prevState) {
426
+ if (nextProps.options !== prevState.suggestions) {
427
+ return _objectSpread({}, prevState, {
428
+ suggestions: nextProps.options
459
429
  });
460
-
461
- this.state.nbOptions = optionsLength;
462
- } else if (!_props.dynamic) {
463
- this.state.dynamic = true;
464
430
  }
431
+
432
+ return null;
465
433
  }
434
+ /**
435
+ * Build itemList & inputValue from select props
436
+ * @param options
437
+ * @param value
438
+ * @param search
439
+ * @param loading
440
+ * @returns {{itemList: *[], inputValue: *}}
441
+ */
466
442
 
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
443
 
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
- });
444
+ componentDidMount() {
445
+ if (this.props.autoFocus) {
446
+ this.inputEl.focus();
487
447
  }
488
448
  }
489
449
 
490
450
  render() {
491
- const _this$props = this.props,
492
- {
451
+ const {
493
452
  classes,
494
453
  disabled,
495
454
  error,
@@ -499,105 +458,42 @@ class HiSelect extends React.PureComponent {
499
458
  displayAsChip,
500
459
  type,
501
460
  value,
461
+ multiple,
502
462
  translations,
503
- parentItemSelectable,
504
- icon,
505
- parentIcon,
506
- hoverIcon,
507
- checkedIcon,
463
+ hiSearchInputProps,
464
+ hiSelectableListProps,
465
+ hiSelectInputProps,
508
466
  id,
467
+ onScrollReachBottom,
468
+ onSubmit,
509
469
  placeholder,
470
+ startAdornment,
510
471
  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"]);
472
+ searchValue = this.state.searchValue,
473
+ buildSelectProps = this.buildSelectProps // use parent builder if defined
518
474
 
475
+ } = this.props;
519
476
  const {
520
477
  open,
521
- suggestions: stateSuggestions,
522
- focused,
523
- dynamic
478
+ focused
524
479
  } = 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
480
 
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
-
587
- if (display) {
588
- display = chipFilter;
481
+ if (multiple) {
482
+ if (!Array.isArray(value)) {
483
+ throw new Error('HiPay Material-UI: the `value` property must be an array ' + 'when using the `HiSelect` component with `multiple`.');
589
484
  }
590
485
  }
591
486
 
592
- const popperClass = classNames(classes.popper, {
593
- [classes.popperWidth]: !this.props.containerWidth
594
- });
595
- let allSelected = false;
487
+ let selectedItemIdList = [];
596
488
 
597
- if (selectedIdList.length === this.state.nbOptions) {
598
- allSelected = true;
489
+ if (value) {
490
+ selectedItemIdList = multiple ? [...value] : [value];
599
491
  }
600
492
 
493
+ const {
494
+ itemList,
495
+ inputValue = this.buildInputValue(options, selectedItemIdList, loading)
496
+ } = buildSelectProps(options, selectedItemIdList, searchValue, loading);
601
497
  let popperStyle = {};
602
498
 
603
499
  if (this.props.containerWidth > 0) {
@@ -610,69 +506,87 @@ class HiSelect extends React.PureComponent {
610
506
  }
611
507
  }
612
508
 
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
- });
509
+ const popperClass = classNames(classes.popper, {
510
+ [classes.popperWidth]: !this.props.containerWidth,
511
+ [classes.popperRightAlign]: this.props.containerWidth && this.props.align === 'right'
512
+ });
513
+
514
+ const searchInput = position => {
515
+ if (searchable) {
516
+ return React.createElement(HiInput, _extends({
517
+ value: searchValue,
518
+ autoFocus: true,
519
+ inputRef: this.getInputElement,
520
+ onKeyDown: this.handleKeyDownSearch,
521
+ onChange: this.handleSearch,
522
+ onReset: this.handleSearchReset,
523
+ placeholder: translations.search,
524
+ startAdornment: 'search',
525
+ tabIndex: 0,
526
+ className: classNames({
527
+ [classes.separator]: position === 'top'
528
+ })
529
+ }, hiSearchInputProps));
530
+ }
531
+
532
+ return null;
533
+ }; // Replace popper onSearch when popper displayed on top of selectButton
534
+
535
+
536
+ if (this.placement && this.placement.indexOf('top') >= 0 && !!searchable) {
537
+ // +1 for search input
538
+ const nbItems = itemList.length <= 10 ? itemList.length + 1 : 11;
539
+ popperStyle.transform = `translate3d(-1px, -${nbItems * 40 + 2}px, 0px)`;
540
+ } else if (this.placement && this.placement.indexOf('top') < 0 && !!searchable) {
541
+ popperStyle.transform = 'translate3d(-1px, 40px, 0px)';
622
542
  }
623
543
 
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'
544
+ const content = ({
545
+ placement
546
+ }) => {
547
+ if (placement !== this.placement) {
548
+ this.placement = placement;
631
549
  }
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))))));
550
+
551
+ return React.createElement(ClickAwayListener, {
552
+ onClickAway: this.handleClickAway
553
+ }, React.createElement(Grow, {
554
+ in: open,
555
+ id: "menu-list",
556
+ style: {
557
+ transformOrigin: '0 0 0'
558
+ }
559
+ }, React.createElement(Paper, {
560
+ className: classes.paper
561
+ }, (this.placement && this.placement.indexOf('bottom') >= 0 || staticPosition) && searchInput('bottom'), startAdornment, React.createElement(Scrollbars, _extends({
562
+ ref: contentEl => {
563
+ this.optionsContent = contentEl;
564
+ },
565
+ autoHeight: true,
566
+ autoHeightMax: 430
567
+ }, onScrollReachBottom && {
568
+ onScroll: this.handleScroll
569
+ }), React.createElement(HiSelectableList, _extends({
570
+ type: type,
571
+ itemList: itemList,
572
+ onSelect: this.handleSelect,
573
+ selectedItemIdList: selectedItemIdList,
574
+ fallbackImage: this.props.fallbackImage,
575
+ overlay: this.overlay,
576
+ value: value
577
+ }, hiSelectableListProps))), this.placement && this.placement.indexOf('top') >= 0 && !staticPosition && searchInput('top'))));
578
+ };
579
+
668
580
  return React.createElement("div", {
669
581
  className: classes.root,
670
582
  ref: el => {
671
583
  this.overlay = el;
672
- }
673
- }, React.createElement(SelectInput, {
584
+ },
585
+ onKeyDown: this.handleKeyDown,
586
+ onKeyDownCapture: this.handleKeyDownCapture
587
+ }, React.createElement(HiSelectInput, _extends({
674
588
  id: id,
675
- value: placeholder || display,
589
+ value: inputValue,
676
590
  open: open,
677
591
  focused: focused,
678
592
  type: type,
@@ -682,42 +596,44 @@ class HiSelect extends React.PureComponent {
682
596
  onClick: this.handleClick,
683
597
  onFocus: this.handleFocus,
684
598
  onBlur: this.handleBlur,
685
- onKeyDown: this.handleKeyDown,
599
+ onSubmit: onSubmit,
686
600
  onMouseEnter: this.props.onMouseEnter,
687
601
  onMouseLeave: this.props.onMouseLeave,
602
+ onReset: this.props.onReset,
603
+ placeholder: placeholder
604
+ }, hiSelectInputProps, {
688
605
  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, {
606
+ this.inputEl = el;
607
+ }
608
+ })), open && staticPosition ? React.createElement("div", {
609
+ style: popperStyle,
610
+ className: popperClass
611
+ }, content({})) : React.createElement(Popper, {
695
612
  anchorEl: this.inputEl,
696
613
  placement: "bottom-start",
697
614
  open: open,
698
615
  className: popperClass,
699
- style: popperStyle,
700
- disablePortal: true
616
+ disablePortal: true,
617
+ style: popperStyle
701
618
  }, content));
702
619
  }
703
620
 
704
621
  }
705
622
 
706
623
  HiSelect.defaultProps = {
707
- containerWidth: 0,
624
+ align: 'left',
625
+ autoFocus: false,
708
626
  disabled: false,
709
627
  displayAsChip: false,
710
- dynamic: false,
711
628
  error: false,
712
629
  hasAll: false,
713
- hasMore: false,
714
- hierarchic: false,
715
- iconAll: false,
716
- infiniteScroll: false,
717
- loadingMoreResults: false,
630
+ hiSelectableListProps: {},
631
+ hiSelectInputProps: {},
632
+ hiSearchInputProps: {},
718
633
  multiple: false,
719
- parentItemSelectable: false,
720
- type: 'text',
634
+ placeholder: '',
635
+ searchable: false,
636
+ staticPosition: false,
721
637
  translations: {
722
638
  all: 'All',
723
639
  no_result_match: 'No result match',
@@ -727,14 +643,16 @@ HiSelect.defaultProps = {
727
643
  n_children: '%s items',
728
644
  one_child: '%s item'
729
645
  },
730
- searchable: false,
731
- staticPosition: false
646
+ type: 'text',
647
+ filterFunc: filterValue
732
648
  };
733
649
  HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
650
+ align: PropTypes.oneOf(['left', 'right']),
651
+
734
652
  /**
735
- * Icon affiché lorsque l'item est sélectionné
653
+ * Permet de forcer le focus sur le composant
736
654
  */
737
- checkedIcon: PropTypes.node,
655
+ autoFocus: PropTypes.bool,
738
656
 
739
657
  /**
740
658
  * Useful to extend the style applied to components.
@@ -756,77 +674,56 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
756
674
  */
757
675
  displayAsChip: PropTypes.bool,
758
676
 
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
677
  /**
767
678
  * Applique le style error
768
679
  */
769
680
  error: PropTypes.bool,
770
681
 
771
682
  /**
772
- * Affiche l'élément 'All'
683
+ * Chemin vers l'image à afficher par défaut si une image n'est pas trouvée
773
684
  */
774
- hasAll: PropTypes.bool,
685
+ fallbackImage: PropTypes.string,
686
+
687
+ /*
688
+ * Fonction de filtrage custom
689
+ */
690
+ filterFunc: PropTypes.func,
775
691
 
776
692
  /**
777
- * Indique si l'infinite scroll doit rechercher de nouveaux résultats
693
+ * Affiche l'élément 'All'
778
694
  */
779
- hasMore: PropTypes.bool,
695
+ hasAll: PropTypes.bool,
780
696
 
781
697
  /**
782
- * Les items sont hiérarchisés
698
+ * Override HiInput props (for search)
783
699
  */
784
- hierarchic: PropTypes.bool,
700
+ hiSearchInputProps: PropTypes.object,
785
701
 
786
702
  /**
787
- * Icon affiché lorsque l'item n'est pas sélectionné et qu'on le survole
703
+ * Override HiSelectableList props
788
704
  */
789
- hoverIcon: PropTypes.node,
705
+ hiSelectableListProps: PropTypes.object,
790
706
 
791
707
  /**
792
- * Icon affiché lorsque l'item n'est pas sélectionné
708
+ * Override HiSelectInput props
793
709
  */
794
- icon: PropTypes.node,
710
+ hiSelectInputProps: PropTypes.object,
795
711
 
796
712
  /**
797
713
  * Nom de l'icône
798
714
  */
799
- iconAll: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
715
+ iconAll: PropTypes.string,
800
716
 
801
717
  /**
802
718
  * id du select
803
719
  */
804
720
  id: PropTypes.string,
805
721
 
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
722
  /**
813
723
  * Ajoute un loader
814
724
  */
815
725
  loading: PropTypes.bool,
816
726
 
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
727
  /**
831
728
  * Autorise la sélection de plusieurs valeurs
832
729
  */
@@ -845,11 +742,6 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
845
742
  */
846
743
  onChange: PropTypes.func.isRequired,
847
744
 
848
- /**
849
- * Fonction de callback appelée click dans l'input
850
- */
851
- onClick: PropTypes.func,
852
-
853
745
  /**
854
746
  * Fonction de callback appelée lorsqu'on ferme le select
855
747
  */
@@ -871,18 +763,14 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
871
763
  onReset: PropTypes.func,
872
764
 
873
765
  /**
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
766
+ * Fonction de callback appelée lorsque le scroll atteint le bas de la liste
879
767
  */
880
- onSearch: PropTypes.func,
768
+ onScrollReachBottom: PropTypes.func,
881
769
 
882
770
  /**
883
- * Fonction de callback à la pression de la touche "Entrée"
771
+ * Fonction de callback appelée lorsque le champs de recherche est utilisé
884
772
  */
885
- onSubmit: PropTypes.func,
773
+ onSearch: PropTypes.func,
886
774
 
887
775
  /**
888
776
  * Listes des options du select
@@ -890,23 +778,7 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
890
778
  options: PropTypes.array.isRequired,
891
779
 
892
780
  /**
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
781
+ * Placeholder affiché lorsque l'input est vide
910
782
  */
911
783
  placeholder: PropTypes.string,
912
784
 
@@ -916,7 +788,12 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
916
788
  searchable: PropTypes.bool,
917
789
 
918
790
  /**
919
- * Si true, le contenu du select sera dans une div static plutot que dans une popper absolute
791
+ * Node qui s'ajoute entre la barre de recherche et la liste de résultats
792
+ */
793
+ startAdornment: PropTypes.object,
794
+
795
+ /**
796
+ * Si true, le contenu du select sera dans une div static plutôt que dans une popper absolute
920
797
  */
921
798
  staticPosition: PropTypes.bool,
922
799