@hipay/hipay-material-ui 2.0.0-beta.50 → 2.0.0-beta.52

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.
@@ -0,0 +1,457 @@
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 Scrollbars from 'react-custom-scrollbars';
6
+ import HiSelectableList from '../HiSelectableList';
7
+ import HiInput from '../HiForm/HiInput';
8
+ import withStyles from '../styles/withStyles';
9
+ import { getNextItemSelectable, foldAccents } from '../utils/helpers';
10
+ import HiIcon from '../HiIcon';
11
+ import keycode from 'keycode';
12
+ export const styles = theme => ({
13
+ labelIcon: {
14
+ marginRight: 10
15
+ },
16
+ labelImg: {
17
+ height: 18,
18
+ width: 'auto',
19
+ margin: '0 4px',
20
+ verticalAlign: 'middle'
21
+ },
22
+ selectIconLabel: _objectSpread({
23
+ whiteSpace: 'nowrap',
24
+ overflow: 'hidden',
25
+ textOverflow: 'ellipsis',
26
+ paddingRight: 16
27
+ }, theme.typography.b1, {
28
+ display: 'inline-flex',
29
+ width: '100%'
30
+ }),
31
+ selectImgLabel: _objectSpread({
32
+ whiteSpace: 'nowrap',
33
+ overflow: 'hidden',
34
+ textOverflow: 'ellipsis',
35
+ paddingRight: 16
36
+ }, theme.typography.b1, {
37
+ display: 'inline-flex',
38
+ width: '100%'
39
+ })
40
+ });
41
+ /**
42
+ *
43
+ * Utilisé pour tous types de selects dans les formulaires.
44
+ * - single / multiple ( multi-select )
45
+ * - avec / sans checkboxes
46
+ * - avec / sans barre de recherche
47
+ * - avec / sans option "All"
48
+ * - prise en compte du type des éléments (text, image, icon, ...)
49
+ *
50
+ * Ce composant réuni les sous-composants
51
+ * - HiSelectInput : affiche l'élément dans le formulaire
52
+ * - HiSearchField : intègre une barre de recherche dans le Popper, il filtre la liste des suggestions
53
+ * - HiSelectableList : affiche la liste des suggestions selon le type des éléments
54
+ */
55
+
56
+ class HiSelectContent extends React.PureComponent {
57
+ constructor(props) {
58
+ super(props);
59
+
60
+ this.handleKeyDown = event => {
61
+ let nextItem;
62
+ const key = keycode(event);
63
+
64
+ if (key === 'down') {
65
+ event.preventDefault();
66
+ nextItem = getNextItemSelectable(document.activeElement, 'down');
67
+ } else if (key === 'up') {
68
+ event.preventDefault();
69
+ nextItem = getNextItemSelectable(document.activeElement, 'up');
70
+ } else if (key === 'tab' || key === 'esc') {
71
+ this.setState({
72
+ open: false
73
+ });
74
+ } else if (key === 'space' || key === 'enter' && !this.props.multiple) {
75
+ event.preventDefault();
76
+ const item = this.props.options.find(elem => String(elem.id) === event.target.id);
77
+ this.handleSelect(null, item);
78
+ } else if (key === 'enter' && this.props.multiple) {
79
+ event.preventDefault();
80
+ this.handleClose();
81
+ }
82
+
83
+ if (nextItem) {
84
+ nextItem.focus();
85
+ }
86
+ };
87
+
88
+ this.handleKeyDownSearch = event => {
89
+ const key = keycode(event);
90
+
91
+ if (this.overlay && (key === 'down' || key === 'up')) {
92
+ this.focusOnFirstItem();
93
+ } else if (this.overlay && key === 'esc' || key === 'enter') {
94
+ event.preventDefault();
95
+ this.handleClose();
96
+ }
97
+ };
98
+
99
+ this.handleSelect = (event, item) => {
100
+ const {
101
+ hasAll,
102
+ multiple,
103
+ onChange,
104
+ options,
105
+ value
106
+ } = this.props;
107
+
108
+ if (!multiple) {
109
+ // single value
110
+ this.handleClose();
111
+ onChange(event, item.id, item);
112
+ } else if (hasAll && item.id === '_all') {
113
+ if (value.length === options.length) {
114
+ // unselect _all options
115
+ onChange(event, [], item);
116
+ } else {
117
+ // select _all options
118
+ onChange(event, options.map(option => option.id), item);
119
+ }
120
+ } else if (value.includes(item.id)) {
121
+ // unselect item
122
+ onChange(event, value.filter(id => id !== item.id), item);
123
+ } else {
124
+ onChange(event, [...value, item.id], item);
125
+ }
126
+ };
127
+
128
+ this.handleClose = () => {
129
+ if (this.props.onClose) this.props.onClose();
130
+ };
131
+
132
+ this.handleSuggestions = suggestions => {
133
+ const {
134
+ hasAll,
135
+ iconAll,
136
+ translations
137
+ } = this.props;
138
+
139
+ if (suggestions.length === 0) {
140
+ // Add '_no_result' suggestion
141
+ this.setState(prevState => _objectSpread({}, prevState, {
142
+ suggestions: [{
143
+ id: '_no_result',
144
+ type: 'text',
145
+ disabled: true,
146
+ centered: true,
147
+ hideCheckbox: true,
148
+ label: translations.no_result_match
149
+ }]
150
+ }));
151
+ } else {
152
+ this.setState({
153
+ suggestions: [// Add '_all' suggestion
154
+ ...(hasAll ? [_objectSpread({
155
+ id: '_all',
156
+ label: translations.all
157
+ }, iconAll && {
158
+ type: 'icon',
159
+ icon: iconAll
160
+ })] : []), ...suggestions]
161
+ });
162
+ }
163
+ };
164
+
165
+ this.handleScroll = e => {
166
+ if (e.target.scrollHeight - e.target.clientHeight - e.target.scrollTop < 15) {
167
+ this.props.onScrollReachBottom();
168
+ }
169
+ };
170
+
171
+ this.handleSearch = (e, inputValue) => {
172
+ const searchValue = inputValue && e.target.value ? inputValue : e.target.value;
173
+
174
+ if (this.props.onSearch) {
175
+ this.props.onSearch(e, searchValue);
176
+ } else {
177
+ this.setState({
178
+ searchValue
179
+ });
180
+ }
181
+ };
182
+
183
+ this.handleSearchReset = () => {
184
+ this.handleSearch({
185
+ target: {
186
+ value: ''
187
+ }
188
+ }, '');
189
+ };
190
+
191
+ this.buildSelectProps = (options, value = [], search = '', loading = false) => {
192
+ // build item list
193
+ const itemList = [...(loading ? [{
194
+ id: '_loading',
195
+ type: 'loader',
196
+ disabled: true,
197
+ centered: true,
198
+ hideCheckbox: true,
199
+ label: 'loading'
200
+ }] : []), // simple one level filter on label
201
+ ...(search !== '' ? [...options.filter(item => item.label && foldAccents(item.label.toString().toLowerCase()).search(foldAccents(search.toLowerCase())) !== -1)] : [...(this.props.hasAll ? [_objectSpread({
202
+ id: '_all',
203
+ label: this.props.translations.all
204
+ }, this.props.iconAll && {
205
+ type: 'icon',
206
+ icon: this.props.iconAll
207
+ })] : []), ...options])];
208
+ return {
209
+ itemList
210
+ };
211
+ };
212
+
213
+ this.getInputElement = el => {
214
+ this.searchField = el;
215
+
216
+ if (this.props.inputRef) {
217
+ this.props.inputRef(this.searchField);
218
+ }
219
+ };
220
+
221
+ this.state = {
222
+ open: false,
223
+ focused: false,
224
+ searchValue: props.searchValue ? undefined : '',
225
+ suggestions: props.options
226
+ };
227
+ this.handleSearch = this.handleSearch.bind(this);
228
+ this.handleSearchReset = this.handleSearchReset.bind(this);
229
+ this.handleSelect = this.handleSelect.bind(this);
230
+ this.handleSuggestions = this.handleSuggestions.bind(this);
231
+ }
232
+
233
+ static getDerivedStateFromProps(nextProps, prevState) {
234
+ if (nextProps.options !== prevState.suggestions) {
235
+ return _objectSpread({}, prevState, {
236
+ suggestions: nextProps.options
237
+ });
238
+ }
239
+
240
+ return null;
241
+ } // Key down on list items
242
+
243
+
244
+ render() {
245
+ const {
246
+ classes,
247
+ disabled,
248
+ error,
249
+ loading,
250
+ options,
251
+ searchable,
252
+ type,
253
+ value,
254
+ multiple,
255
+ translations,
256
+ hiSelectableListProps,
257
+ hiSelectInputProps,
258
+ id,
259
+ onScrollReachBottom,
260
+ onSubmit,
261
+ startAdornment,
262
+ searchValue = this.state.searchValue,
263
+ buildSelectProps = this.buildSelectProps,
264
+ // use parent builder if defined
265
+ autoHeight,
266
+ height
267
+ } = this.props;
268
+
269
+ if (multiple) {
270
+ if (!Array.isArray(value)) {
271
+ throw new Error('HiPay Material-UI: the `value` property must be an array ' + 'when using the `HiSelect` component with `multiple`.');
272
+ }
273
+ }
274
+
275
+ let selectedItemIdList = [];
276
+
277
+ if (value) {
278
+ selectedItemIdList = multiple ? [...value] : [value];
279
+ }
280
+
281
+ const {
282
+ itemList
283
+ } = buildSelectProps(options, selectedItemIdList, searchValue, loading);
284
+ return React.createElement(React.Fragment, null, !!searchable && React.createElement(HiInput, {
285
+ value: searchValue,
286
+ autoFocus: true,
287
+ inputRef: this.getInputElement,
288
+ onKeyDown: this.handleKeyDownSearch,
289
+ onChange: this.handleSearch,
290
+ onReset: this.handleSearchReset,
291
+ placeholder: translations.search,
292
+ startAdornment: 'search',
293
+ tabIndex: 0
294
+ }), startAdornment, React.createElement(Scrollbars, _extends({
295
+ ref: contentEl => {
296
+ this.optionsContent = contentEl;
297
+ }
298
+ }, autoHeight ? {
299
+ autoHeight: true,
300
+ autoHeightMax: height
301
+ } : {
302
+ autoHeightMax: height,
303
+ autoHeightMin: height
304
+ }, {
305
+ autoHeight: true,
306
+ autoHeightMax: height // TODO ?
307
+
308
+ }, onScrollReachBottom && {
309
+ onScroll: this.handleScroll
310
+ }), React.createElement(HiSelectableList, _extends({
311
+ type: type,
312
+ itemList: itemList,
313
+ onKeyDown: this.handleKeyDown,
314
+ onSelect: this.handleSelect,
315
+ selectedItemIdList: selectedItemIdList,
316
+ fallbackImage: this.props.fallbackImage
317
+ }, hiSelectableListProps))));
318
+ }
319
+
320
+ }
321
+
322
+ HiSelectContent.defaultProps = {
323
+ autoHeight: true,
324
+ height: 400,
325
+ disabled: false,
326
+ error: false,
327
+ hasAll: false,
328
+ hiSelectableListProps: {},
329
+ hiSelectInputProps: {},
330
+ multiple: false,
331
+ searchable: false,
332
+ translations: {
333
+ all: 'All',
334
+ no_result_match: 'No result match',
335
+ search: 'Search',
336
+ n_items_selected: '%s items selected',
337
+ one_item_selected: '%s item selected',
338
+ n_children: '%s items',
339
+ one_child: '%s item'
340
+ },
341
+ type: 'text'
342
+ };
343
+ HiSelectContent.propTypes = process.env.NODE_ENV !== "production" ? {
344
+ autoHeight: PropTypes.bool,
345
+
346
+ /**
347
+ * Useful to extend the style applied to components.
348
+ */
349
+ classes: PropTypes.object,
350
+
351
+ /**
352
+ * Inactif
353
+ */
354
+ disabled: PropTypes.bool,
355
+
356
+ /**
357
+ * Applique le style error
358
+ */
359
+ error: PropTypes.bool,
360
+
361
+ /**
362
+ * Chemin vers l'image à afficher par défaut si une image n'est pas trouvée
363
+ */
364
+ fallbackImage: PropTypes.string,
365
+
366
+ /**
367
+ * Affiche l'élément 'All'
368
+ */
369
+ hasAll: PropTypes.bool,
370
+
371
+ /**
372
+ * Hauteur du container scrollable
373
+ */
374
+ height: PropTypes.number,
375
+
376
+ /**
377
+ * Override HiSelectableList props (
378
+ */
379
+ hiSelectableListProps: PropTypes.object,
380
+
381
+ /**
382
+ * Override HiSelectInput props
383
+ */
384
+ hiSelectInputProps: PropTypes.object,
385
+
386
+ /**
387
+ * Nom de l'icône
388
+ */
389
+ iconAll: PropTypes.string,
390
+
391
+ /**
392
+ * id du select
393
+ */
394
+ id: PropTypes.string,
395
+
396
+ /**
397
+ * Ajoute un loader
398
+ */
399
+ loading: PropTypes.bool,
400
+
401
+ /**
402
+ * Autorise la sélection de plusieurs valeurs
403
+ */
404
+ multiple: PropTypes.bool,
405
+
406
+ /**
407
+ * Fonction de callback qui renvoit la/les valeurs sélectionnées
408
+ *
409
+ * @param {object} event
410
+ * @param {string || array} value
411
+ */
412
+ onChange: PropTypes.func.isRequired,
413
+
414
+ /**
415
+ * Fonction de callback appelée lorsque le scroll atteint le bas de la liste
416
+ */
417
+ onScrollReachBottom: PropTypes.func,
418
+
419
+ /**
420
+ * Fonction de callback appelée lorsque le champs de recherche est utilisé
421
+ */
422
+ onSearch: PropTypes.func,
423
+
424
+ /**
425
+ * Listes des options du select
426
+ */
427
+ options: PropTypes.array.isRequired,
428
+
429
+ /**
430
+ * Affiche un input de recherche permettant de filtrer les options
431
+ */
432
+ searchable: PropTypes.bool,
433
+
434
+ /**
435
+ * Node qui s'ajoute entre la barre de recherche et la liste de résultats
436
+ */
437
+ startAdornment: PropTypes.object,
438
+
439
+ /**
440
+ * Traductions (par défaut en anglais)
441
+ */
442
+ translations: PropTypes.object,
443
+
444
+ /**
445
+ * Type des éléments du select, définit le rendu d'un élément
446
+ */
447
+ type: PropTypes.oneOf(['icon', 'text', 'image', 'primary-highlight']),
448
+
449
+ /**
450
+ * Value(s) du select
451
+ */
452
+ value: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.array])
453
+ } : {};
454
+ export default withStyles(styles, {
455
+ hiComponent: true,
456
+ name: 'HmuiHiSelectContent'
457
+ })(HiSelectContent);
@@ -1,4 +1,6 @@
1
1
  export { default } from './HiSelect';
2
2
  export { default as HiNestedSelect } from './HiNestedSelect';
3
3
  export { default as HiSelectField } from './HiSelectField';
4
- export { default as HiSelectInput } from './HiSelectInput';
4
+ export { default as HiSelectInput } from './HiSelectInput';
5
+ export { default as HiSelectContent } from './HiSelectContent';
6
+ export { default as HiNestedSelectContent, findFinalItemRecursively, getRecursiveFinalItemIdList } from './HiNestedSelectContent';
@@ -11,6 +11,9 @@ import HiColoredLabel from '../HiColoredLabel';
11
11
  import HiLoader from '../HiLoader';
12
12
  import withStyles from '../styles/withStyles';
13
13
  import { escapeHTML } from '../utils/helpers';
14
+ import pure from 'recompose/pure';
15
+ const PureListSubheader = pure(ListSubheader);
16
+ const PureListItem = pure(ListItem);
14
17
  export const styles = theme => ({
15
18
  root: {
16
19
  paddingLeft: 4
@@ -106,8 +109,7 @@ export const styles = theme => ({
106
109
  textOverflow: 'ellipsis',
107
110
  textAlign: 'right',
108
111
  margin: '4px 12px 4px 8px',
109
- alignSelf: 'center',
110
- width: '100%'
112
+ alignSelf: 'center'
111
113
  }),
112
114
  checkbox: {
113
115
  marginTop: 3
@@ -130,7 +132,7 @@ export const styles = theme => ({
130
132
  * Construit un élément de liste sélectionnable (avec checkbox)
131
133
  */
132
134
 
133
- class HiSelectableListItem extends React.Component {
135
+ class HiSelectableListItem extends React.PureComponent {
134
136
  constructor(props) {
135
137
  super(props);
136
138
 
@@ -236,7 +238,7 @@ class HiSelectableListItem extends React.Component {
236
238
  displayedIcon = icon;
237
239
  }
238
240
 
239
- const ListItemComponentName = pinned ? ListSubheader : ListItem;
241
+ const ListItemComponentName = pinned ? PureListSubheader : PureListItem;
240
242
  return React.createElement(ListItemComponentName, _extends({
241
243
  id: id,
242
244
  tabIndex: disabled ? '-1' : 0,
@@ -2,6 +2,7 @@
2
2
  import React from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import keycode from 'keycode';
5
+ import classNames from 'classnames';
5
6
  import withStyles from '../styles/withStyles';
6
7
  import TableRow from '@material-ui/core/TableRow';
7
8
  import HiCellBuilder from './HiCellBuilder';
@@ -17,6 +18,9 @@ export const styles = theme => ({
17
18
  '&:hover, &:focus': {
18
19
  backgroundColor: `${theme.palette.action.hover} !important`
19
20
  }
21
+ },
22
+ clicableRow: {
23
+ cursor: 'pointer'
20
24
  }
21
25
  });
22
26
 
@@ -42,7 +46,9 @@ class HiTableRow extends React.PureComponent {
42
46
  rowdata
43
47
  } = this.props;
44
48
  return React.createElement(TableRow, {
45
- className: classes.row,
49
+ className: classNames(classes.row, {
50
+ [classes.clicableRow]: this.props.onClick
51
+ }),
46
52
  hover: true,
47
53
  onClick: event => this.handleClick(event, rowdata),
48
54
  onKeyDown: event => {
@@ -56,10 +62,10 @@ class HiTableRow extends React.PureComponent {
56
62
  height: dense ? cst.CELL_HEIGHT_DENSE : cst.CELL_HEIGHT
57
63
  },
58
64
  tabIndex: 0
59
- }, Object.keys(columns).map(key => {
65
+ }, Object.keys(columns).map(column => {
60
66
  return React.createElement(HiCellBuilder, {
61
- key: columns[key].colId,
62
- column: columns[key],
67
+ key: columns[column].colId,
68
+ column: columns[column],
63
69
  data: rowdata,
64
70
  locale: locale
65
71
  });
@@ -132,6 +132,7 @@ export default function createPalette(palette) {
132
132
  contrastText: '#FFFFFF'
133
133
  },
134
134
  negative = {
135
+ ultraLight: '#EA9494',
135
136
  light: '#E66666',
136
137
  main: '#D50000',
137
138
  dark: '#A00000',
@@ -144,6 +145,7 @@ export default function createPalette(palette) {
144
145
  contrastText: '#FFFFFF'
145
146
  },
146
147
  neutral = {
148
+ ultraLight: '#8B8B8B',
147
149
  light: '#838383',
148
150
  main: '#737373',
149
151
  dark: '#20272B',
@@ -154,13 +156,17 @@ export default function createPalette(palette) {
154
156
  main: red[500],
155
157
  dark: red[700]
156
158
  },
159
+ lookup = {
160
+ light: '#FFFF8D',
161
+ main: '#EDED14'
162
+ },
157
163
  type = 'light',
158
164
  contrastThreshold = 2.9,
159
165
  // max light contrast
160
166
  tonalOffset = 0.2,
161
167
  context = 'local'
162
168
  } = palette,
163
- other = _objectWithoutProperties(palette, ["primary", "secondary", "positive", "negative", "middle", "neutral", "error", "type", "contrastThreshold", "tonalOffset", "context"]);
169
+ other = _objectWithoutProperties(palette, ["primary", "secondary", "positive", "negative", "middle", "neutral", "error", "lookup", "type", "contrastThreshold", "tonalOffset", "context"]);
164
170
 
165
171
  function getContrastText(background) {
166
172
  // Use the same logic as
@@ -225,6 +231,8 @@ export default function createPalette(palette) {
225
231
  neutral,
226
232
  // The colors used to represent interface elements that the user should be made aware of.
227
233
  error,
234
+ // The colors used to represent form elements that have lookup state.
235
+ lookup,
228
236
  // The grey colors.
229
237
  grey,
230
238
  // Used by `getContrastText()` to maximize the contrast between the background and
package/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license HiPay-Material-UI v2.0.0-beta.50
1
+ /** @license HiPay-Material-UI v2.0.0-beta.52
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.50
1
+ /** @license HiPay-Material-UI v2.0.0-beta.52
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.50",
5
+ "version": "2.0.0-beta.52",
6
6
  "description": "React components that implement Google's Material Design.",
7
7
  "keywords": [
8
8
  "react",
@@ -155,6 +155,7 @@ function createPalette(palette) {
155
155
  } : _palette$positive,
156
156
  _palette$negative = palette.negative,
157
157
  negative = _palette$negative === void 0 ? {
158
+ ultraLight: '#EA9494',
158
159
  light: '#E66666',
159
160
  main: '#D50000',
160
161
  dark: '#A00000',
@@ -169,6 +170,7 @@ function createPalette(palette) {
169
170
  } : _palette$middle,
170
171
  _palette$neutral = palette.neutral,
171
172
  neutral = _palette$neutral === void 0 ? {
173
+ ultraLight: '#8B8B8B',
172
174
  light: '#838383',
173
175
  main: '#737373',
174
176
  dark: '#20272B',
@@ -180,6 +182,11 @@ function createPalette(palette) {
180
182
  main: _red.default[500],
181
183
  dark: _red.default[700]
182
184
  } : _palette$error,
185
+ _palette$lookup = palette.lookup,
186
+ lookup = _palette$lookup === void 0 ? {
187
+ light: '#FFFF8D',
188
+ main: '#EDED14'
189
+ } : _palette$lookup,
183
190
  _palette$type = palette.type,
184
191
  type = _palette$type === void 0 ? 'light' : _palette$type,
185
192
  _palette$contrastThre = palette.contrastThreshold,
@@ -188,7 +195,7 @@ function createPalette(palette) {
188
195
  tonalOffset = _palette$tonalOffset === void 0 ? 0.2 : _palette$tonalOffset,
189
196
  _palette$context = palette.context,
190
197
  context = _palette$context === void 0 ? 'local' : _palette$context,
191
- other = (0, _objectWithoutProperties2.default)(palette, ["primary", "secondary", "positive", "negative", "middle", "neutral", "error", "type", "contrastThreshold", "tonalOffset", "context"]);
198
+ other = (0, _objectWithoutProperties2.default)(palette, ["primary", "secondary", "positive", "negative", "middle", "neutral", "error", "lookup", "type", "contrastThreshold", "tonalOffset", "context"]);
192
199
 
193
200
  function getContrastText(background) {
194
201
  // Use the same logic as
@@ -257,6 +264,8 @@ function createPalette(palette) {
257
264
  neutral: neutral,
258
265
  // The colors used to represent interface elements that the user should be made aware of.
259
266
  error: error,
267
+ // The colors used to represent form elements that have lookup state.
268
+ lookup: lookup,
260
269
  // The grey colors.
261
270
  grey: _grey.default,
262
271
  // Used by `getContrastText()` to maximize the contrast between the background and