@hipay/hipay-material-ui 1.0.0-beta.26 → 1.0.0-beta.28

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 (72) hide show
  1. package/HI-CHANGELOG.md +37 -0
  2. package/HiCheckbox/HiCheckbox.js +6 -3
  3. package/HiColoredLabel/HiColoredLabel.js +2 -2
  4. package/HiDatePicker/HiDateRangeSelector.js +32 -9
  5. package/HiForm/HiFormControl.js +4 -4
  6. package/HiForm/HiSearchField.js +7 -1
  7. package/HiSelect/HiSelect.js +195 -83
  8. package/HiSelect/HiSuggestSelect.js +22 -6
  9. package/HiSelect/SelectInput.js +63 -10
  10. package/HiSelectableList/HiSelectableListItem.js +2 -1
  11. package/HiTable/BodyCellBuilder.js +22 -16
  12. package/HiTable/BodyCells/CellAccount.js +1 -5
  13. package/HiTable/BodyCells/CellAddress.js +3 -50
  14. package/HiTable/BodyCells/CellCountry.js +0 -4
  15. package/HiTable/BodyCells/CellDate.js +4 -13
  16. package/HiTable/BodyCells/CellIcon.js +10 -27
  17. package/HiTable/BodyCells/CellImage.js +1 -21
  18. package/HiTable/BodyCells/CellLayout.js +11 -4
  19. package/HiTable/BodyCells/CellNumeric.js +3 -23
  20. package/HiTable/BodyCells/CellRate.js +3 -3
  21. package/HiTable/BodyCells/CellSentinel.js +20 -49
  22. package/HiTable/BodyCells/CellStatus.js +11 -19
  23. package/HiTable/BodyCells/CellText.js +3 -10
  24. package/HiTable/BodyCells/CellThirdPartySecurity.js +4 -18
  25. package/HiTable/BodyCells/index.js +0 -9
  26. package/HiTable/BodyRow.js +15 -17
  27. package/HiTable/HiTable.js +41 -26
  28. package/HiTable/HiTableBody.js +2 -1
  29. package/HiTable/HiTableContextMenu.js +4 -3
  30. package/HiTable/HiTableFooter.js +5 -6
  31. package/HiTable/constants.js +2 -2
  32. package/es/HiCheckbox/HiCheckbox.js +6 -3
  33. package/es/HiColoredLabel/HiColoredLabel.js +2 -2
  34. package/es/HiDatePicker/HiDateRangeSelector.js +27 -9
  35. package/es/HiForm/HiFormControl.js +4 -4
  36. package/es/HiForm/HiSearchField.js +2 -1
  37. package/es/HiSelect/HiSelect.js +141 -42
  38. package/es/HiSelect/HiSuggestSelect.js +22 -7
  39. package/es/HiSelect/SelectInput.js +50 -10
  40. package/es/HiSelectableList/HiSelectableListItem.js +2 -1
  41. package/es/HiTable/BodyCellBuilder.js +21 -19
  42. package/es/HiTable/BodyCells/CellAccount.js +1 -5
  43. package/es/HiTable/BodyCells/CellAddress.js +3 -44
  44. package/es/HiTable/BodyCells/CellCountry.js +0 -2
  45. package/es/HiTable/BodyCells/CellDate.js +4 -10
  46. package/es/HiTable/BodyCells/CellIcon.js +10 -24
  47. package/es/HiTable/BodyCells/CellImage.js +1 -21
  48. package/es/HiTable/BodyCells/CellLayout.js +10 -4
  49. package/es/HiTable/BodyCells/CellNumeric.js +3 -16
  50. package/es/HiTable/BodyCells/CellRate.js +3 -3
  51. package/es/HiTable/BodyCells/CellSentinel.js +20 -46
  52. package/es/HiTable/BodyCells/CellStatus.js +11 -16
  53. package/es/HiTable/BodyCells/CellText.js +3 -7
  54. package/es/HiTable/BodyCells/CellThirdPartySecurity.js +3 -15
  55. package/es/HiTable/BodyCells/index.js +0 -2
  56. package/es/HiTable/BodyRow.js +12 -14
  57. package/es/HiTable/HiTable.js +41 -26
  58. package/es/HiTable/HiTableBody.js +2 -1
  59. package/es/HiTable/HiTableContextMenu.js +4 -3
  60. package/es/HiTable/HiTableFooter.js +6 -6
  61. package/es/HiTable/constants.js +7 -7
  62. package/es/utils/HiIconBuilder.js +12 -4
  63. package/es/utils/hiHelpers.js +1 -1
  64. package/index.es.js +1 -1
  65. package/index.js +1 -1
  66. package/package.json +1 -1
  67. package/umd/hipay-material-ui.development.js +9093 -9629
  68. package/umd/hipay-material-ui.production.min.js +5 -5
  69. package/utils/HiIconBuilder.js +13 -3
  70. package/utils/hiHelpers.js +1 -1
  71. package/HiTable/BodyCells/CellAccountNumber.js +0 -229
  72. package/es/HiTable/BodyCells/CellAccountNumber.js +0 -171
@@ -72,7 +72,7 @@ export function buildDateRangeOptionByKey(key, t, format) {
72
72
  label = t.previous_quarter;
73
73
  from = moment().subtract(1, 'quarter').startOf('quarter');
74
74
  to = moment().subtract(1, 'quarter').endOf('quarter');
75
- info = `${from.format('YYYY')}-Q${from.format('Q')}, ${to.diff(from, 'days')} ${t.days}`;
75
+ info = `${from.format('YYYY')}-${t.short_quarter}${from.format('Q')}, ${to.diff(from, 'days')} ${t.days}`;
76
76
  break;
77
77
  case 'cy':
78
78
  label = t.current_year;
@@ -129,21 +129,38 @@ class HiDateRangeSelector extends React.Component {
129
129
  this.props.onChange('from', selectedOption.from.toDate());
130
130
  this.props.onChange('to', selectedOption.to.toDate());
131
131
  }
132
+ } else {
133
+ this.setState({
134
+ defaultFrom: undefined,
135
+ defaultTo: undefined
136
+ });
132
137
  }
133
138
  if (this.props.returnSelectValue === true) {
134
139
  this.props.onChange('period', value);
135
140
  }
136
141
  };
137
142
 
138
- this.state = {
139
- selectedPreset: props.defaultPreset,
140
- containerWidth: 0
141
- };
142
-
143
143
  this.handleReset = this.handleReset.bind(this);
144
144
  this.handleSelectChange = this.handleSelectChange.bind(this);
145
145
 
146
146
  this.options = props.availableOptionKeys.map(key => buildDateRangeOptionByKey(key, props.translations, props.format));
147
+
148
+ let from;
149
+ let to;
150
+ if (props.defaultPreset !== 'custom') {
151
+ const selectedOption = this.options.find(option => option.id === props.defaultPreset);
152
+ if (selectedOption) {
153
+ from = selectedOption.from.toDate();
154
+ to = selectedOption.to.toDate();
155
+ }
156
+ }
157
+
158
+ this.state = {
159
+ selectedPreset: props.defaultPreset,
160
+ containerWidth: 0,
161
+ defaultFrom: from,
162
+ defaultTo: to
163
+ };
147
164
  }
148
165
 
149
166
  static getDerivedStateFromProps(props, state) {
@@ -192,7 +209,7 @@ class HiDateRangeSelector extends React.Component {
192
209
  } = _props,
193
210
  props = _objectWithoutProperties(_props, ['disabled', 'enableTime', 'error', 'errorText', 'helperIcon', 'helperText', 'idRange', 'idSelect', 'label', 'from', 'onChange', 'required', 'to', 'translations', 'classes', 'selectProps', 'staticPosition']);
194
211
 
195
- const { selectedPreset } = this.state;
212
+ const { defaultFrom, defaultTo, selectedPreset } = this.state;
196
213
 
197
214
  return React.createElement(
198
215
  Grid,
@@ -230,8 +247,8 @@ class HiDateRangeSelector extends React.Component {
230
247
  React.createElement(HiDateRangePicker, _extends({
231
248
  classes: { root: classes.dateRangePicker },
232
249
  id: idRange,
233
- from: from,
234
- to: to,
250
+ from: from || defaultFrom,
251
+ to: to || defaultTo,
235
252
  enableTime: enableTime,
236
253
  onChange: onChange,
237
254
  onReset: this.handleReset,
@@ -260,6 +277,7 @@ HiDateRangeSelector.defaultProps = {
260
277
  quarter: 'Quarter',
261
278
  week: 'Week',
262
279
  short_week: 'W',
280
+ short_quarter: 'Q',
263
281
  year: 'Year',
264
282
  days: 'days',
265
283
  custom_period: 'Custom Period',
@@ -150,7 +150,7 @@ class HiFormControl extends React.PureComponent {
150
150
  error: error,
151
151
  ref: rootRef
152
152
  }, others),
153
- !disabled && error && errorText && helperOpen && React.createElement(
153
+ error && errorText && helperOpen && React.createElement(
154
154
  'div',
155
155
  { className: classes.errorDiv },
156
156
  React.createElement('div', {
@@ -158,7 +158,7 @@ class HiFormControl extends React.PureComponent {
158
158
  }),
159
159
  errorText
160
160
  ),
161
- !disabled && helperIcon && helperText && !error && helperOpen && React.createElement(
161
+ helperIcon && helperText && !error && helperOpen && React.createElement(
162
162
  'div',
163
163
  {
164
164
  className: classes.helperDiv
@@ -181,11 +181,11 @@ class HiFormControl extends React.PureComponent {
181
181
  disabled: disabled,
182
182
  focused: !disabled && (focused || hovered)
183
183
  }, InputLabelProps),
184
- !disabled && error && React.createElement(Alert, {
184
+ error && React.createElement(Alert, {
185
185
  className: classes.errorIcon,
186
186
  onClick: this.handleHelperClick
187
187
  }),
188
- !disabled && helperIcon && helperText && !error && React.createElement(Information, {
188
+ helperIcon && helperText && !error && React.createElement(Information, {
189
189
  className: classNames(classes.helperIcon, {
190
190
  [classes.helperIconActive]: helperOpen
191
191
  }),
@@ -2,6 +2,7 @@ import _extends from 'babel-runtime/helpers/extends';
2
2
  import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
3
3
  import React from 'react';
4
4
  import PropTypes from 'prop-types';
5
+ import isRequiredIf from 'react-proptype-conditional-require';
5
6
  import HiInput from '../HiForm/HiInput';
6
7
 
7
8
  /**
@@ -112,7 +113,7 @@ HiSearchField.propTypes = process.env.NODE_ENV !== "production" ? {
112
113
  *
113
114
  * @param {array} suggestions
114
115
  */
115
- callbackFilteredList: PropTypes.func.isRequired,
116
+ callbackFilteredList: isRequiredIf(PropTypes.func, props => !props.hasOwnProperty('onSearch'), 'callbackFilteredList required'),
116
117
  /**
117
118
  * Liste des propriété de l'élément sur lesquelles filtrer (par défaut l'item lui même)
118
119
  */
@@ -1,4 +1,5 @@
1
1
  import _Object$keys from 'babel-runtime/core-js/object/keys';
2
+ import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
2
3
  import _extends from 'babel-runtime/helpers/extends';
3
4
  // @inheritedComponent Input
4
5
 
@@ -11,6 +12,7 @@ import Paper from 'material-ui/Paper';
11
12
  import ClickAwayListener from 'material-ui/utils/ClickAwayListener';
12
13
  import { Manager, Target, Popper } from 'react-popper';
13
14
  import { CheckboxBlankOutline, CheckboxMarked } from 'mdi-material-ui';
15
+ import isRequiredIf from 'react-proptype-conditional-require';
14
16
  import HiSelectableList from '../HiSelectableList';
15
17
  import { HiSearchField } from '../HiForm';
16
18
  import SelectInput from './SelectInput';
@@ -19,6 +21,8 @@ import { withStyles } from '../styles';
19
21
  import { arrayUnique, getNextItemSelectable } from '../utils/hiHelpers';
20
22
  import HiIconBuilder from '../utils/HiIconBuilder';
21
23
 
24
+ export const INFINITESCROLL_ERROR_MESSAGE = 'La propriété "loadMoreResults" est obligatoire si la prop "infiniteScroll" est à true';
25
+
22
26
  export const styles = theme => ({
23
27
  root: {
24
28
  backgroundColor: theme.palette.background2,
@@ -78,7 +82,8 @@ class HiSelect extends React.PureComponent {
78
82
  hierarchySelected: {},
79
83
  hierarchy: {},
80
84
  nbOptions: 0,
81
- dynamic: props.dynamic || false
85
+ dynamic: props.dynamic || false,
86
+ resultsPageNumber: 1
82
87
  };
83
88
 
84
89
  // Check if value is in options
@@ -135,6 +140,21 @@ class HiSelect extends React.PureComponent {
135
140
  this.handleBlur = this.handleBlur.bind(this);
136
141
  }
137
142
 
143
+ componentDidUpdate(prevProps, prevState, prevContext) {
144
+ if (this.props.infiniteScroll && !prevState.open && this.state.open && this.optionsContent) {
145
+ let optionList = this.optionsContent.querySelector('div').querySelector('div');
146
+ optionList.addEventListener('scroll', event => {
147
+ if (optionList.scrollTop >= event.target.scrollHeight - optionList.offsetHeight && !this.props.loadingMoreResults && this.props.hasMore) {
148
+ this.props.loadMoreResults(this.state.resultsPageNumber + 1);
149
+ this.setState({ resultsPageNumber: this.state.resultsPageNumber + 1 });
150
+ }
151
+ });
152
+ } else if (this.optionsContent && this.props.infiniteScroll && !this.state.open && prevState.open) {
153
+ let optionList = this.optionsContent.querySelector('div').querySelector('div');
154
+ optionList.removeEventListener('scroll');
155
+ }
156
+ }
157
+
138
158
  componentWillReceiveProps(nextProps) {
139
159
  if (typeof this.props.onSearch !== 'undefined' && this.props.options && this.props.options.length > 0) {
140
160
  this.handleSuggestions(nextProps.options);
@@ -175,6 +195,13 @@ class HiSelect extends React.PureComponent {
175
195
  return { hierarchy, hierarchySelected };
176
196
  }
177
197
 
198
+ handleReset(event) {
199
+ if (this.props.onReset) {
200
+ event.stopPropagation();
201
+ this.props.onReset(event);
202
+ }
203
+ }
204
+
178
205
  // Key down on list items
179
206
 
180
207
 
@@ -202,7 +229,8 @@ class HiSelect extends React.PureComponent {
202
229
 
203
230
 
204
231
  render() {
205
- const {
232
+ const _props = this.props,
233
+ {
206
234
  classes,
207
235
  disabled,
208
236
  error,
@@ -224,8 +252,13 @@ class HiSelect extends React.PureComponent {
224
252
  placeholder,
225
253
  staticPosition,
226
254
  pinnedItem,
227
- hasAll
228
- } = this.props;
255
+ hasAll,
256
+ infiniteScroll,
257
+ loadingMoreResults,
258
+ showNoResults,
259
+ showMinLength
260
+ } = _props,
261
+ other = _objectWithoutProperties(_props, ['classes', 'disabled', 'error', 'loading', 'options', 'checkbox', 'searchable', 'displayAsChip', 'type', 'value', 'translations', 'parentItemSelectable', 'icon', 'parentIcon', 'hoverIcon', 'checkedIcon', 'hierarchic', 'id', 'placeholder', 'staticPosition', 'pinnedItem', 'hasAll', 'infiniteScroll', 'loadingMoreResults', 'showNoResults', 'showMinLength']);
229
262
 
230
263
  const { open, suggestions, focused, dynamic } = this.state;
231
264
 
@@ -239,7 +272,7 @@ class HiSelect extends React.PureComponent {
239
272
  }
240
273
 
241
274
  // If loading
242
- if (loading) {
275
+ if (loading && !loadingMoreResults) {
243
276
  _suggestions.unshift({
244
277
  id: '_loading',
245
278
  type: 'loader',
@@ -296,6 +329,28 @@ class HiSelect extends React.PureComponent {
296
329
  popperStyle = { width: this.props.containerWidth };
297
330
  }
298
331
 
332
+ if (infiniteScroll && loadingMoreResults) {
333
+ _suggestions.push({
334
+ id: '_loading',
335
+ type: 'loader',
336
+ disabled: true,
337
+ centered: true,
338
+ checkbox: false,
339
+ label: 'loading'
340
+ });
341
+ }
342
+
343
+ if (!loading && !loadingMoreResults && _suggestions.length === 0 && (showNoResults || showMinLength)) {
344
+ suggestions.push({
345
+ id: '_no_result',
346
+ type: 'text',
347
+ disabled: true,
348
+ centered: true,
349
+ checkbox: false,
350
+ label: showNoResults ? translations.no_result_match : translations.min_length
351
+ });
352
+ }
353
+
299
354
  const content = React.createElement(
300
355
  ClickAwayListener,
301
356
  { onClickAway: this.handleClickAway },
@@ -317,25 +372,29 @@ class HiSelect extends React.PureComponent {
317
372
  },
318
373
  onKeyDown: this.handleKeyDownSearch
319
374
  }),
320
- React.createElement(HiSelectableList, {
321
- type: type,
322
- parentItemSelectable: parentItemSelectable,
323
- itemList: _suggestions,
324
- onSelect: this.handleSelect,
325
- selectedIdList: selectedIdList,
326
- checkbox: checkbox,
327
- hierarchy: this.state.hierarchy,
328
- hierarchic: hierarchic,
329
- hierarchySelected: this.state.hierarchySelected,
330
- translations: translations,
331
- icon: icon,
332
- parentIcon: parentIcon,
333
- hoverIcon: hoverIcon,
334
- checkedIcon: checkedIcon,
335
- allSelected: allSelected,
336
- value: value,
337
- onKeyDown: this.handleKeyDown
338
- })
375
+ React.createElement(
376
+ 'div',
377
+ { ref: content => this.optionsContent = content },
378
+ React.createElement(HiSelectableList, _extends({
379
+ type: type,
380
+ parentItemSelectable: parentItemSelectable,
381
+ itemList: _suggestions,
382
+ onSelect: this.handleSelect,
383
+ selectedIdList: selectedIdList,
384
+ checkbox: checkbox,
385
+ hierarchy: this.state.hierarchy,
386
+ hierarchic: hierarchic,
387
+ hierarchySelected: this.state.hierarchySelected,
388
+ translations: translations,
389
+ icon: icon,
390
+ parentIcon: parentIcon,
391
+ hoverIcon: hoverIcon,
392
+ checkedIcon: checkedIcon,
393
+ allSelected: allSelected,
394
+ value: value,
395
+ onKeyDown: this.handleKeyDown
396
+ }, other))
397
+ )
339
398
  )
340
399
  )
341
400
  );
@@ -370,7 +429,9 @@ class HiSelect extends React.PureComponent {
370
429
  onMouseLeave: this.props.onMouseLeave,
371
430
  refElement: el => {
372
431
  this.selectInputElement = el;
373
- }
432
+ },
433
+ onSubmit: this.props.onSubmit,
434
+ onReset: this.props.onReset
374
435
  })
375
436
  ),
376
437
  open && (staticPosition ? React.createElement(
@@ -405,12 +466,14 @@ HiSelect.defaultProps = {
405
466
  parentItemSelectable: false,
406
467
  displayAsChip: false,
407
468
  dynamic: false,
469
+ infiniteScroll: false,
408
470
  icon: React.createElement(CheckboxBlankOutline, { style: { width: 20, height: 20 } }),
409
471
  parentIcon: React.createElement(CheckboxBlankOutline, { style: { width: 20, height: 20 } }),
410
472
  hoverIcon: React.createElement(CheckboxBlankOutline, { style: { width: 20, height: 20 } }),
411
473
  checkedIcon: React.createElement(CheckboxMarked, { style: { width: 20, height: 20 } }),
412
474
  translations: {
413
475
  all: 'All',
476
+ min_length: 'Veuillez saisir 3 caractères minimum',
414
477
  no_result_match: 'No result match',
415
478
  search: 'Search',
416
479
  n_items_selected: '%s items selected',
@@ -418,7 +481,9 @@ HiSelect.defaultProps = {
418
481
  n_children: '%s items',
419
482
  one_child: '%s item'
420
483
  },
421
- staticPosition: false
484
+ staticPosition: false,
485
+ loadingMoreResults: false,
486
+ hasMore: false
422
487
  };
423
488
 
424
489
  var _initialiseProps = function () {
@@ -426,9 +491,9 @@ var _initialiseProps = function () {
426
491
  if (this.state.open) {
427
492
  this.handleClose();
428
493
  } else {
429
- if (!this.props.staticPosition) {
430
- //document.body.style.overflow = 'hidden';
431
- }
494
+ /*if (!this.props.staticPosition) {
495
+ // document.body.style.overflow = 'hidden';
496
+ }*/
432
497
  this.setState({ open: true });
433
498
  const options = this.props.options.slice();
434
499
  this.handleSuggestions(options);
@@ -438,13 +503,7 @@ var _initialiseProps = function () {
438
503
  }
439
504
 
440
505
  // Gestion du focus
441
- if (this.searchField) {
442
- // si searchable, focus sur le champs de recherche
443
- const searchField = this.searchField;
444
- setTimeout(() => {
445
- searchField.focus();
446
- }, 1);
447
- } else if (this.overlay) {
506
+ if (!this.props.searchable) {
448
507
  // sinon focus sur le dernier élément selectionné
449
508
  this.focusOnSelectedItem();
450
509
  }
@@ -490,9 +549,11 @@ var _initialiseProps = function () {
490
549
  } else if (event.key === 'ArrowUp') {
491
550
  nextItem = getNextItemSelectable(document.activeElement, 'up');
492
551
  } else if (event.key === 'Tab') {
493
- if (!this.props.staticPosition) {
494
- //document.body.style.overflow = 'auto';
495
- }
552
+ /* if (!this.props.staticPosition) {
553
+ document.body.style.overflow = 'auto';
554
+ } */
555
+ this.setState({ open: false });
556
+ } else if (event.key === 'Escape') {
496
557
  this.setState({ open: false });
497
558
  }
498
559
  if (nextItem) {
@@ -503,6 +564,8 @@ var _initialiseProps = function () {
503
564
  this.handleKeyDownSearch = event => {
504
565
  if (this.overlay && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
505
566
  this.focusOnSelectedItem();
567
+ } else if (event.key === 'Enter' && this.props.onSubmit) {
568
+ this.props.onSubmit(event);
506
569
  }
507
570
  };
508
571
 
@@ -643,9 +706,9 @@ var _initialiseProps = function () {
643
706
  };
644
707
 
645
708
  this.handleSuggestions = suggestions => {
646
- const { options, hasAll, iconAll, translations, multiple } = this.props;
709
+ const { options, hasAll, iconAll, translations, multiple, showNoResults, showMinLength } = this.props;
647
710
 
648
- if (suggestions.length === 0) {
711
+ if (suggestions.length === 0 && (showNoResults || showMinLength)) {
649
712
  // Handle No Result
650
713
  // FIX to remove all item
651
714
  suggestions = [];
@@ -655,7 +718,7 @@ var _initialiseProps = function () {
655
718
  disabled: true,
656
719
  centered: true,
657
720
  checkbox: false,
658
- label: translations.no_result_match
721
+ label: showNoResults ? translations.no_result_match : translations.min_length
659
722
  });
660
723
  } else if (hasAll && suggestions.length > 0 && suggestions.length === options.length && multiple === true) {
661
724
  // Handle 'All'
@@ -722,6 +785,10 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
722
785
  * Les items sont hiérarchisés
723
786
  */
724
787
  hierarchic: PropTypes.bool,
788
+ /**
789
+ * Indique si l'infinite scroll doit rechercher de nouveaux résultats
790
+ */
791
+ hasMore: PropTypes.bool,
725
792
  /**
726
793
  * Icon affiché lorsque l'item n'est pas sélectionné et qu'on le survole
727
794
  */
@@ -738,10 +805,26 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
738
805
  * id du select
739
806
  */
740
807
  id: PropTypes.string,
808
+ /**
809
+ * Infinite scroll dans le select dans le cas où il y a beaucoup de résultats à afficher
810
+ * afin d'éviter un lag du navigateur
811
+ */
812
+ infiniteScroll: PropTypes.bool.isRequired,
741
813
  /**
742
814
  * Ajoute un loader
743
815
  */
744
816
  loading: PropTypes.bool,
817
+ /**
818
+ * Ajoute un loader en bas pour l'infiniteScroll
819
+ */
820
+ loadingMoreResults: PropTypes.bool,
821
+ /**
822
+ * Fonction de callback appelée lorsque l'utilisateur arrive en bas de la liste des options
823
+ * afin de charger les nouvelles options
824
+ *
825
+ * @param {int} pageNumber
826
+ */
827
+ loadMoreResults: isRequiredIf(PropTypes.func, props => props.hasOwnProperty('infiniteScroll') && props.infiniteScroll === true, INFINITESCROLL_ERROR_MESSAGE),
745
828
  /**
746
829
  * Autorise la sélection de plusieurs valeurs
747
830
  */
@@ -769,6 +852,10 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
769
852
  * Fonction de callback appelée lorsque le curseur quitte le champs
770
853
  */
771
854
  onMouseLeave: PropTypes.func,
855
+ /**
856
+ * Fonction de callback appelée lorsqu'on vide le champs
857
+ */
858
+ onReset: PropTypes.func,
772
859
  /**
773
860
  * Fonction de callback appelée lorsqu'on écrit dans la barre de recherche
774
861
  * A utiliser pour les selects avec des données dynamiques
@@ -777,6 +864,10 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
777
864
  * @param {string} value
778
865
  */
779
866
  onSearch: PropTypes.func,
867
+ /**
868
+ * Fonction de callback à la pression de la touche "Entrée"
869
+ */
870
+ onSubmit: PropTypes.func,
780
871
  /**
781
872
  * Listes des options du select
782
873
  */
@@ -806,6 +897,14 @@ HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
806
897
  * Si true, le contenu du select sera dans une div static plutot que dans une popper absolute
807
898
  */
808
899
  staticPosition: PropTypes.bool,
900
+ /**
901
+ * Permet d'afficher un message si pas assez de caractères
902
+ */
903
+ showMinLength: PropTypes.bool,
904
+ /**
905
+ * Permet d'afficher un message si aucune options n'est présente
906
+ */
907
+ showNoResults: PropTypes.bool,
809
908
  /**
810
909
  * Traductions (par défaut en anglais)
811
910
  */
@@ -116,24 +116,35 @@ class HiSuggestSelect extends React.PureComponent {
116
116
 
117
117
  render() {
118
118
  const _props = this.props,
119
- { classes, id, showMinLength, showNoResults, onSearch, translations } = _props,
120
- otherProps = _objectWithoutProperties(_props, ['classes', 'id', 'showMinLength', 'showNoResults', 'onSearch', 'translations']);
119
+ { classes, id, loading, showMinLength, showNoResults, onSearch, translations } = _props,
120
+ otherProps = _objectWithoutProperties(_props, ['classes', 'id', 'loading', 'showMinLength', 'showNoResults', 'onSearch', 'translations']);
121
121
 
122
122
  const { focused, options } = this.state;
123
123
 
124
124
  let optionsShown = options;
125
125
 
126
- // If no results match
127
- if (options.length === 0 && (showNoResults || showMinLength)) {
126
+ // If loading
127
+ if (loading) {
128
128
  optionsShown = [{
129
- id: '_no_result',
130
- type: 'text',
129
+ id: '_loading',
130
+ type: 'loader',
131
131
  disabled: true,
132
132
  centered: true,
133
133
  checkbox: false,
134
- label: showNoResults ? translations.no_result_match : translations.min_length
134
+ label: 'loading'
135
135
  }];
136
136
  }
137
+ // If no results match
138
+ else if (options.length === 0 && (showNoResults || showMinLength)) {
139
+ optionsShown = [{
140
+ id: '_no_result',
141
+ type: 'text',
142
+ disabled: true,
143
+ centered: true,
144
+ checkbox: false,
145
+ label: showNoResults ? translations.no_result_match : translations.min_length
146
+ }];
147
+ }
137
148
 
138
149
  const open = !!optionsShown.length && focused;
139
150
 
@@ -211,6 +222,10 @@ HiSuggestSelect.propTypes = process.env.NODE_ENV !== "production" ? {
211
222
  * id de l'élément input
212
223
  */
213
224
  id: PropTypes.string,
225
+ /**
226
+ * Ajoute un loader
227
+ */
228
+ loading: PropTypes.bool,
214
229
  /**
215
230
  * Fonction de callback appelée lorsqu'on écrit dans le champ
216
231
  */
@@ -2,12 +2,13 @@ import _extends from 'babel-runtime/helpers/extends';
2
2
  import React from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import classNames from 'classnames';
5
-
6
- import ArrowDropDownIcon from '../svg-icons/ArrowDropDown';
5
+ import keycode from 'keycode';
7
6
  import Icon from 'material-ui/Icon';
8
- import { withStyles } from '../styles';
9
-
7
+ import IconButton from 'material-ui/IconButton';
10
8
  import ButtonBase from 'material-ui/ButtonBase';
9
+ import ArrowDropDownIcon from '../svg-icons/ArrowDropDown';
10
+ import { withStyles } from '../styles';
11
+ import HiIconBuilder from '../utils/HiIconBuilder';
11
12
 
12
13
  export const styles = theme => ({
13
14
  root: {
@@ -87,6 +88,11 @@ export const styles = theme => ({
87
88
  backgroundColor: theme.palette.background3
88
89
  },
89
90
  error: {},
91
+ eraseButton: {
92
+ height: 24,
93
+ width: 24,
94
+ display: 'inline-block'
95
+ },
90
96
  label: _extends({
91
97
  whiteSpace: 'nowrap',
92
98
  overflow: 'hidden',
@@ -120,14 +126,24 @@ class SelectInput extends React.PureComponent {
120
126
  super(props);
121
127
 
122
128
  this.handleKeyDown = event => {
123
- if (event.key === 'ArrowDown') {
124
- this.props.onClick();
125
- } else if (event.key === 'ArrowUp') {
129
+ const key = keycode(event);
130
+ if (['up', 'down', 'space'].includes(key)) {
131
+ event.preventDefault();
126
132
  this.props.onClick();
133
+ } else if (key === 'enter' && this.props.onSubmit) {
134
+ event.preventDefault();
135
+ this.props.onSubmit(event);
136
+ }
137
+ };
138
+
139
+ this.handleClick = event => {
140
+ if ((!this.resetIcon || !this.resetIcon.contains(event.target)) && this.props.onClick) {
141
+ this.props.onClick(event);
127
142
  }
128
143
  };
129
144
 
130
145
  this.handleKeyDown = this.handleKeyDown.bind(this);
146
+ this.handleClick = this.handleClick.bind(this);
131
147
  }
132
148
 
133
149
  render() {
@@ -141,7 +157,9 @@ class SelectInput extends React.PureComponent {
141
157
  focused,
142
158
  error,
143
159
  id,
144
- refElement
160
+ refElement,
161
+ onReset,
162
+ theme
145
163
  } = this.props;
146
164
 
147
165
  // On utilise classNames pour variabiliser les styles et merge les classes appliquées
@@ -185,7 +203,7 @@ class SelectInput extends React.PureComponent {
185
203
  {
186
204
  id: id,
187
205
  className: rootClass,
188
- onClick: onClick,
206
+ onClick: this.handleClick,
189
207
  disabled: disabled,
190
208
  onMouseEnter: this.props.onMouseEnter,
191
209
  onMouseLeave: this.props.onMouseLeave,
@@ -201,6 +219,20 @@ class SelectInput extends React.PureComponent {
201
219
  { className: classes.label },
202
220
  value
203
221
  ),
222
+ onReset && React.createElement(
223
+ 'div',
224
+ {
225
+ ref: el => {
226
+ this.resetIcon = el;
227
+ }
228
+ },
229
+ React.createElement(HiIconBuilder, {
230
+ icon: 'close',
231
+ size: 24,
232
+ color: theme.palette.neutral.normal,
233
+ onClick: onReset
234
+ })
235
+ ),
204
236
  React.createElement(
205
237
  Icon,
206
238
  { classes: { root: iconClass } },
@@ -262,6 +294,14 @@ SelectInput.propTypes = process.env.NODE_ENV !== "production" ? {
262
294
  * Fonction de callback à la pression de touche
263
295
  */
264
296
  onKeyDown: PropTypes.func,
297
+ /**
298
+ * Fonction de callback appelée lorsqu'on vide le champs
299
+ */
300
+ onReset: PropTypes.func,
301
+ /**
302
+ * Fonction de callback à la pression de la touche "Entrée"
303
+ */
304
+ onSubmit: PropTypes.func,
265
305
  /**
266
306
  * Applique le style open et effectue une rotation de l'icône
267
307
  */
@@ -275,4 +315,4 @@ SelectInput.propTypes = process.env.NODE_ENV !== "production" ? {
275
315
  */
276
316
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.node])
277
317
  } : {};
278
- export default withStyles(styles, { name: 'HmuiSelectInput' })(SelectInput);
318
+ export default withStyles(styles, { name: 'HmuiSelectInput', withTheme: true })(SelectInput);
@@ -368,7 +368,8 @@ class HiSelectableListItem extends React.Component {
368
368
  checkedIcon: checkedIcon,
369
369
  indeterminate: indeterminate,
370
370
  classes: { checked: classes.listItemIconChecked },
371
- className: classes.checkbox
371
+ className: classes.checkbox,
372
+ disabled: effectiveDisabled
372
373
  }),
373
374
  this.buildListItem(),
374
375
  !!item.info && React.createElement(