@hipay/hipay-material-ui 2.0.0-beta.75 → 2.0.0-beta.76

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,10 +11,14 @@ import HiSelectableList from '../HiSelectableList';
11
11
  import HiInput from '../HiForm/HiInput';
12
12
  import HiSelectInput from './HiSelectInput';
13
13
  import withStyles from '../styles/withStyles';
14
- import { getNextItemSelectable, foldAccents } from '../utils/helpers';
14
+ import { foldAccents } from '../utils/helpers';
15
15
  import HiIcon from '../HiIcon';
16
16
  import keycode from 'keycode';
17
17
  import classNames from 'classnames';
18
+ import HiAlertModal from '../HiAlertModal';
19
+ import { isMobile } from 'react-device-detect';
20
+ import HiSelectMobile from './HiSelectMobile';
21
+ import { findDOMNode } from 'react-dom';
18
22
  export const styles = theme => ({
19
23
  root: {
20
24
  backgroundColor: theme.palette.background2,
@@ -200,28 +204,46 @@ class HiSelect extends React.PureComponent {
200
204
  this.handleClick = () => {
201
205
  if (this.state.open) {
202
206
  this.handleClose();
207
+ } else if (this.props.alert && !this.state.alertOpen) {
208
+ this.setState({
209
+ open: false,
210
+ alertOpen: true
211
+ });
203
212
  } else {
204
213
  this.setState({
205
- open: true
214
+ open: true,
215
+ alertOpen: false
206
216
  });
207
217
  this.handleSuggestions(this.props.options);
208
218
  if (this.props.onClick) this.props.onClick(); // Gestion du focus
209
219
 
210
- if (!this.props.searchable) {
211
- setTimeout(() => {
220
+ setTimeout(() => {
221
+ if (!this.props.searchable) {
212
222
  // Sinon focus sur l'élément sélectionné
213
223
  this.focusOnSelectedItem(this.props.value);
214
- }, 1);
215
- } else {
216
- if (this.searchField) {
217
- setTimeout(() => {
218
- this.searchField.focus();
219
- }, 1);
220
224
  }
221
- }
225
+ }, 1);
222
226
  }
223
227
  };
224
228
 
229
+ this.handleSubmitAlert = () => {
230
+ this.handleClick();
231
+ };
232
+
233
+ this.handleCancelAlert = () => {
234
+ this.handleClose();
235
+ };
236
+
237
+ this.handleExitedAlert = () => {
238
+ if (this.searchField) {
239
+ this.searchField.focus();
240
+ }
241
+ };
242
+
243
+ this.handleCloseAlert = () => {
244
+ this.handleClose();
245
+ };
246
+
225
247
  this.focusOnSelectedItem = selectedValue => {
226
248
  if (this.overlay && this.overlay.getElementsByTagName('li')[0]) {
227
249
  setTimeout(() => {
@@ -253,7 +275,8 @@ class HiSelect extends React.PureComponent {
253
275
  this.handleClose = () => {
254
276
  this.handleSearchReset();
255
277
  this.setState({
256
- open: false
278
+ open: false,
279
+ alertOpen: false
257
280
  });
258
281
 
259
282
  if (this.props.onClose) {
@@ -287,31 +310,22 @@ class HiSelect extends React.PureComponent {
287
310
  this.handleKeyDown = event => {
288
311
  const key = keycode(event);
289
312
 
290
- if (key === 'esc') {
291
- event.preventDefault();
292
- this.handleClose();
293
- } else if (key === 'enter') {
294
- if (this.state.open) {
295
- if (this.props.multiple) {
296
- this.handleClose();
297
- }
298
- }
299
- } else if (key === 'space' && event.target !== this.searchField) {
300
- event.preventDefault();
301
-
302
- if (this.state.open) {
303
- if (!this.props.multiple) {
304
- this.setState({
305
- open: false
306
- });
313
+ if (!this.state.alertOpen) {
314
+ if (key === 'esc') {
315
+ event.preventDefault();
316
+ this.handleClose();
317
+ } else if (key === 'enter') {
318
+ if (this.state.open) {
319
+ if (this.props.multiple) {
320
+ this.handleClose();
321
+ }
307
322
  }
308
- } else {
309
- this.setState({
310
- open: true
311
- });
323
+ } else if (key === 'space' && event.target !== this.searchField) {
324
+ event.preventDefault();
325
+ this.handleClick();
326
+ } else if (key === 'tab') {
327
+ this.handleClose();
312
328
  }
313
- } else if (key === 'tab') {
314
- this.handleClose();
315
329
  }
316
330
  };
317
331
 
@@ -357,6 +371,9 @@ class HiSelect extends React.PureComponent {
357
371
  // select _all options
358
372
  onChange(event, options.map(option => option.id), item);
359
373
  }
374
+ } else if (isMobile && multiple) {
375
+ // Array of selected values
376
+ onChange(event, item.map(option => option.id), item);
360
377
  } else if (value.includes(item.id)) {
361
378
  // unselect item
362
379
  onChange(event, value.filter(id => id !== item.id), item);
@@ -419,11 +436,13 @@ class HiSelect extends React.PureComponent {
419
436
  };
420
437
 
421
438
  this.state = {
439
+ alertOpen: false,
422
440
  open: false,
423
441
  focused: false,
424
442
  searchValue: props.searchValue ? undefined : '',
425
443
  suggestions: props.options,
426
- openDown: true
444
+ openDown: true,
445
+ overlayWidth: 0
427
446
  };
428
447
  this.handleBlur = this.handleBlur.bind(this);
429
448
  this.handleClick = this.handleClick.bind(this);
@@ -441,6 +460,12 @@ class HiSelect extends React.PureComponent {
441
460
  if (this.props.autoFocus) {
442
461
  this.inputEl.focus();
443
462
  }
463
+
464
+ if (this.overlay) {
465
+ this.setState({
466
+ overlayWidth: findDOMNode(this.overlay).clientWidth
467
+ });
468
+ }
444
469
  }
445
470
 
446
471
  static getDerivedStateFromProps(nextProps, prevState) {
@@ -478,6 +503,7 @@ class HiSelect extends React.PureComponent {
478
503
 
479
504
  render() {
480
505
  const {
506
+ alert,
481
507
  classes,
482
508
  disabled,
483
509
  error,
@@ -503,6 +529,7 @@ class HiSelect extends React.PureComponent {
503
529
 
504
530
  } = this.props;
505
531
  const {
532
+ alertOpen,
506
533
  open,
507
534
  focused
508
535
  } = this.state;
@@ -608,14 +635,24 @@ class HiSelect extends React.PureComponent {
608
635
  }, hiSelectableListProps))), this.placement && this.placement.indexOf('top') >= 0 && !staticPosition && searchInput('top'))));
609
636
  };
610
637
 
611
- return React.createElement("div", {
638
+ return !isMobile ? React.createElement("div", {
612
639
  className: classes.root,
613
640
  ref: el => {
614
641
  this.overlay = el;
615
642
  },
616
643
  onKeyDown: this.handleKeyDown,
617
644
  onKeyDownCapture: this.handleKeyDownCapture
618
- }, React.createElement(HiSelectInput, _extends({
645
+ }, alert && React.createElement(HiAlertModal, {
646
+ open: alertOpen,
647
+ title: alert.title,
648
+ content: alert.content,
649
+ onSubmitClick: this.handleSubmitAlert,
650
+ onCancelClick: this.handleCancelAlert,
651
+ onClose: this.handleCloseAlert,
652
+ onExited: this.handleExitedAlert,
653
+ labelSubmitButton: alert.submitButton,
654
+ labelCancelButton: alert.cancelButton
655
+ }), React.createElement(HiSelectInput, _extends({
619
656
  id: id,
620
657
  value: inputValue,
621
658
  open: open,
@@ -646,7 +683,37 @@ class HiSelect extends React.PureComponent {
646
683
  className: popperClass,
647
684
  disablePortal: true,
648
685
  style: popperStyle
649
- }, content));
686
+ }, content)) : React.createElement("div", {
687
+ ref: el => {
688
+ this.overlay = el;
689
+ }
690
+ }, React.createElement(HiSelectInput, _extends({
691
+ id: id,
692
+ value: inputValue,
693
+ open: open,
694
+ focused: focused,
695
+ type: type,
696
+ disabled: disabled,
697
+ noButton: displayAsChip,
698
+ error: error,
699
+ onFocus: this.handleFocus,
700
+ onBlur: this.handleBlur,
701
+ onMouseEnter: this.props.onMouseEnter,
702
+ onMouseLeave: this.props.onMouseLeave,
703
+ onReset: this.props.onReset,
704
+ placeholder: placeholder
705
+ }, hiSelectInputProps, {
706
+ refElement: el => {
707
+ this.inputEl = el;
708
+ }
709
+ })), React.createElement(HiSelectMobile, {
710
+ onChange: this.handleSelect,
711
+ multiple: multiple,
712
+ id: id,
713
+ itemList: itemList,
714
+ value: value,
715
+ width: this.state.overlayWidth
716
+ }));
650
717
  }
651
718
 
652
719
  }
@@ -678,6 +745,10 @@ HiSelect.defaultProps = {
678
745
  filterFunc: filterValue
679
746
  };
680
747
  HiSelect.propTypes = process.env.NODE_ENV !== "production" ? {
748
+ /**
749
+ * Affiche une alerte à l'ouverture de la liste
750
+ */
751
+ alert: PropTypes.object,
681
752
  align: PropTypes.oneOf(['left', 'right']),
682
753
 
683
754
  /**
@@ -8,6 +8,7 @@ import Icon from '@material-ui/core/Icon';
8
8
  import HiIcon from '../HiIcon';
9
9
  import withStyles from '../styles/withStyles';
10
10
  import keycode from 'keycode';
11
+ import { isMobile } from 'react-device-detect';
11
12
  export const styles = theme => ({
12
13
  root: {
13
14
  width: '100%',
@@ -18,6 +19,9 @@ export const styles = theme => ({
18
19
  padding: 8,
19
20
  cursor: 'pointer'
20
21
  },
22
+ rootMobile: {
23
+ backgroundColor: theme.palette.background2
24
+ },
21
25
  underline: {
22
26
  '&:before': {
23
27
  backgroundColor: theme.palette.input.bottomLine,
@@ -207,7 +211,8 @@ class HiSelectInput extends React.PureComponent {
207
211
  const rootClass = classNames(classes.root, classes.inkbar, classes.underline, {
208
212
  [classes.disabled]: disabled,
209
213
  [classes.focused]: focused,
210
- [classes.error]: error && !focused
214
+ [classes.error]: error && !focused,
215
+ [classes.rootMobile]: isMobile
211
216
  });
212
217
  const iconClass = classNames(classes.icon, {
213
218
  [classes.iconOpen]: open,
@@ -0,0 +1,149 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _objectSpread from "@babel/runtime/helpers/objectSpread";
3
+ import React from 'react';
4
+ import PropTypes from 'prop-types';
5
+ import withStyles from '../styles/withStyles';
6
+ export const styles = theme => ({
7
+ root: {
8
+ position: 'absolute',
9
+ opacity: '0',
10
+ marginTop: -40,
11
+ height: 40
12
+ }
13
+ });
14
+
15
+ class HiSelectMobile extends React.Component {
16
+ constructor(...args) {
17
+ super(...args);
18
+
19
+ this.buildOptionList = itemList => {
20
+ let optionList = [];
21
+
22
+ if (itemList.length) {
23
+ let parentId;
24
+ let groupList = [];
25
+ itemList.forEach(item => {
26
+ if (item.id !== '_all' && item.displayed !== false) {
27
+ if (item.hasChildren) {
28
+ if (groupList.length) {
29
+ optionList.push(this.buildChildrenList(groupList));
30
+ groupList = [];
31
+ }
32
+
33
+ parentId = item.id;
34
+ groupList.push(item);
35
+ } else if (parentId) {
36
+ groupList.push(item);
37
+ } else if (item.children) {
38
+ optionList.push(this.buildChildrenList([item, ...item.children]));
39
+ } else {
40
+ optionList.push(React.createElement("option", {
41
+ key: item.id,
42
+ "data-item": JSON.stringify(item),
43
+ value: item.id
44
+ }, item.label));
45
+ }
46
+ }
47
+ });
48
+
49
+ if (groupList.length) {
50
+ optionList.push(this.buildChildrenList(groupList));
51
+ }
52
+ }
53
+
54
+ return optionList;
55
+ };
56
+
57
+ this.buildChildrenList = itemList => {
58
+ const group = itemList.shift();
59
+ return React.createElement("optgroup", {
60
+ key: group.id,
61
+ label: group.label
62
+ }, itemList.map(item => {
63
+ return React.createElement("option", {
64
+ key: item.id,
65
+ "data-item": JSON.stringify(item),
66
+ value: item.id
67
+ }, item.label);
68
+ }));
69
+ };
70
+
71
+ this.handleChange = event => {
72
+ if (!this.props.multiple) {
73
+ const itemSelected = event.target[event.target.selectedIndex];
74
+ this.props.onChange(event, JSON.parse(itemSelected.getAttribute('data-item')));
75
+ } else {
76
+ // Multiple on mobile trigger on change with all selected items
77
+ let optionsSelected = [];
78
+ Array.prototype.forEach.call(event.target.options, option => {
79
+ if (option.selected) {
80
+ optionsSelected.push(JSON.parse(option.getAttribute('data-item')));
81
+ }
82
+ });
83
+ this.props.onChange(event, optionsSelected);
84
+ }
85
+ };
86
+ }
87
+
88
+ render() {
89
+ const {
90
+ classes,
91
+ id,
92
+ itemList,
93
+ multiple,
94
+ value
95
+ } = this.props;
96
+
97
+ const additionalProps = _objectSpread({}, multiple && {
98
+ multiple: 'multiple'
99
+ });
100
+
101
+ return React.createElement("select", _extends({
102
+ value: value,
103
+ style: {
104
+ width: this.props.width
105
+ },
106
+ onChange: this.handleChange,
107
+ className: classes.root,
108
+ name: id,
109
+ id: id
110
+ }, additionalProps), this.buildOptionList(itemList));
111
+ }
112
+
113
+ }
114
+
115
+ HiSelectMobile.defaultProps = {
116
+ itemList: []
117
+ };
118
+ HiSelectMobile.propTypes = process.env.NODE_ENV !== "production" ? {
119
+ /**
120
+ * Identifiant du select
121
+ */
122
+ id: PropTypes.string,
123
+
124
+ /**
125
+ * Liste des options du select
126
+ */
127
+ itemList: PropTypes.array.isRequired,
128
+
129
+ /**
130
+ * True s'il est possible de sélectionner plusieurs options
131
+ */
132
+ multiple: PropTypes.bool,
133
+
134
+ /**
135
+ * Fonction appelée lors de la sélection/désélection
136
+ */
137
+ onChange: PropTypes.func.isRequired,
138
+
139
+ /**
140
+ * Valeur(s) sélectionnée(s)
141
+ */
142
+ value: PropTypes.any,
143
+
144
+ /**
145
+ * Largeur du select
146
+ */
147
+ width: PropTypes.number
148
+ } : {};
149
+ export default withStyles(styles)(HiSelectMobile);
@@ -47,7 +47,7 @@ export const light = {
47
47
  // The color of a selected action.
48
48
  selected: '#F8F9FB',
49
49
  // The color of a disabled action.
50
- disabled: '#E0E0E0',
50
+ disabled: 'rgba(0, 0, 0, 0.24)',
51
51
  // The background color of a disabled action.
52
52
  disabledBackground: 'rgba(0, 0, 0, 0.12)'
53
53
  },
package/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license HiPay-Material-UI v2.0.0-beta.75
1
+ /** @license HiPay-Material-UI v2.0.0-beta.76
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license HiPay-Material-UI v2.0.0-beta.75
1
+ /** @license HiPay-Material-UI v2.0.0-beta.76
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@hipay/hipay-material-ui",
3
3
  "private": false,
4
4
  "author": "HiPay PSYCHE Team",
5
- "version": "2.0.0-beta.75",
5
+ "version": "2.0.0-beta.76",
6
6
  "description": "React components that implement Google's Material Design.",
7
7
  "keywords": [
8
8
  "react",
@@ -56,6 +56,7 @@
56
56
  "prop-types": "^15.6.0",
57
57
  "react-custom-scrollbars": "^4.2.1",
58
58
  "react-day-picker": "^7.2.4",
59
+ "react-device-detect": "^1.6.2",
59
60
  "react-event-listener": "^0.6.2",
60
61
  "react-jss": "^8.1.0",
61
62
  "react-lazyload": "^2.5.0",
@@ -74,4 +75,4 @@
74
75
  },
75
76
  "main": "./index.js",
76
77
  "module": "./index.es.js"
77
- }
78
+ }
@@ -65,7 +65,7 @@ var light = {
65
65
  // The color of a selected action.
66
66
  selected: '#F8F9FB',
67
67
  // The color of a disabled action.
68
- disabled: '#E0E0E0',
68
+ disabled: 'rgba(0, 0, 0, 0.24)',
69
69
  // The background color of a disabled action.
70
70
  disabledBackground: 'rgba(0, 0, 0, 0.12)'
71
71
  },