@evg-b/evg-ui
Version:
EVG-UI library inspired by Material Design.
206 lines (183 loc) • 7.49 kB
JavaScript
import _extends from '@babel/runtime/helpers/extends';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import React, { useRef, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Elevation from '../styles/Elevation.js';
import withStyles from '../styles/withStyles.js';
import '@babel/runtime/helpers/construct';
import '@babel/runtime/helpers/toConsumableArray';
import '@babel/runtime/helpers/classCallCheck';
import '@babel/runtime/helpers/createClass';
import TextField from '../TextField/TextField.js';
import List from '../List/List.js';
import SelectOption from '../SelectOption/SelectOption.js';
import Popup from '../Popup/Popup.js';
import ExpandMore from '../internal/icons/Select/ExpandMore.js';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var styles = {
base: {
position: 'relative',
tapHighlightColor: 'rgba(0,0,0,0)',
'-webkit-tap-highlight-color': 'rgba(0,0,0,0)'
},
selectIcon: {
position: 'absolute',
top: '18px',
right: '16px',
transition: 'transform 200ms cubic-bezier(0.4, 0, 0.2, 1)',
pointerEvents: 'none',
'&:disabled,&[disabled]': {
cursor: 'default',
pointerEvents: ' none',
color: '#b4b4b4'
}
},
selectIconOpen: {
transition: 'transform 200ms cubic-bezier(0.4, 0, 0.2, 1)',
transform: 'rotate(180deg)'
},
selectList: _objectSpread({}, Elevation(8))
};
/**
* Select позволяет пользователям выбирать из меню с одним параметром.
*/
var Select = /*#__PURE__*/React.forwardRef(function Select(props, ref) {
var classes = props.classes,
className = props.className,
children = props.children,
value = props.value,
emptyOption = props.emptyOption,
onChange = props.onChange,
color = props.color,
disabled = props.disabled,
otherProps = _objectWithoutProperties(props, ["classes", "className", "children", "value", "emptyOption", "onChange", "color", "disabled"]);
var Select_ref = useRef();
Select_ref = ref || Select_ref;
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
open = _useState2[0],
setOpen = _useState2[1];
var _useState3 = useState(0),
_useState4 = _slicedToArray(_useState3, 2),
minWidth = _useState4[0],
setMinWidth = _useState4[1];
var optionMap = new Map();
React.Children.forEach(children, function (child) {
var value = child.props.value;
var children = child.props.children;
if (value && children) {
optionMap.set(value, children);
}
});
var _useState5 = useState(optionMap.get(value)),
_useState6 = _slicedToArray(_useState5, 2),
valueSelect = _useState6[0],
setValueSelect = _useState6[1];
var handelClick = function handelClick(_ref) {
var currentTarget = _ref.currentTarget;
setValueSelect(optionMap.get(currentTarget.value));
onChange && onChange(currentTarget.value);
handleCloseSelectList();
};
var emptySelectOption = function emptySelectOption() {
return /*#__PURE__*/React.createElement(SelectOption, {
onClick: handelClick
});
};
var handleOpenSelectList = function handleOpenSelectList() {
setOpen(true);
};
var handleCloseSelectList = function handleCloseSelectList() {
Select_ref.current.blur();
setOpen(false);
};
useEffect(function () {
// TODO: оптимизировать и закешировать, чтобы срабатывала только два раза
// в первый render ширина может учитываться margin и clientWidth почему то не помогает(а должен)
// он помогает при первом показе, вот тогда нужно зафиксировать новое значение(правильное) и больше не менять
setMinWidth(Select_ref.current.clientWidth);
}, []);
return /*#__PURE__*/React.createElement("div", {
className: classNames(classes.base, className)
}, /*#__PURE__*/React.createElement(TextField, _extends({
ref: Select_ref,
readOnly: true,
value: valueSelect,
onClick: handleOpenSelectList,
style: {
cursor: 'pointer'
},
color: color,
disabled: disabled
}, otherProps)), /*#__PURE__*/React.createElement(ExpandMore, {
color: open ? color : 'default',
disabled: disabled,
className: classNames(classes.selectIcon, _defineProperty({}, classes.selectIconOpen, open))
}), /*#__PURE__*/React.createElement(Popup, {
target: Select_ref,
open: open,
mode: "click",
onClose: handleCloseSelectList,
style: {
minWidth: minWidth
}
}, /*#__PURE__*/React.createElement(List, {
color: color,
className: classNames(classes.selectList, {})
}, emptyOption && emptySelectOption(), React.Children.map(children, function (child) {
if (child.props.value && child.props.children) {
return child && /*#__PURE__*/React.cloneElement(child, {
onClick: handelClick,
active: child.props.children === valueSelect
});
} else {
console.error("[evg-ui] <Select/>: <SelectOption/> empty 'value' or 'children'");
}
}))));
});
Select.propTypes = {
/**
* Это контент между открывающим и закрывающим тегом компонента.
*/
children: PropTypes.node,
/**
* Объект содержит jss стили компонента.
*/
classes: PropTypes.object,
/**
* Чтобы указать CSS классы, используйте этот атрибут.
*/
className: PropTypes.string,
/**
* Название цвета в разных форматах.
*/
color: PropTypes.string,
/**
* Если true, в список добавиться пустой SelectOption.
*/
emptyOption: PropTypes.bool,
/**
* Вызывается при изменении состояния.
*/
onChange: PropTypes.func,
/**
* Value - number или string.
*/
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/**
* Если true, принимает состоянии disabled.
*/
disabled: PropTypes.bool
};
Select.defaultProps = {
emptyOption: false,
disabled: false,
color: 'default'
};
Select.displayName = 'SelectEVG';
var Select$1 = withStyles(styles)(Select);
export default Select$1;