chayns-components
Version:
A set of beautiful React components for developing chayns® applications.
217 lines (216 loc) • 7.9 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import classnames from 'clsx';
import PropTypes from 'prop-types';
import React, { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from 'react';
import Overlay from '../../components/overlay/Overlay';
import Input from '../../react-chayns-input/component/Input';
import { isFunction } from '../../utils/is';
import { isServer } from '../../utils/isServer';
import Icon from '../../react-chayns-icon/component/Icon';
const InputBox = /*#__PURE__*/React.forwardRef((props, ref) => {
const {
inputComponent: InputComponent = Input,
children,
parent,
inputRef,
onFocus,
className,
overlayProps,
boxClassName,
style,
onBlur,
hasOpenCloseIcon = false,
renderInline = false,
hideInput = false,
...restProps
} = props;
const wrapperRef = useRef();
const boxRef = useRef();
const hasTouchStartedRef = useRef(false);
const [isHidden, setIsHidden] = useState(true);
const [rect, setRect] = useState(null);
useLayoutEffect(() => {
if (wrapperRef.current && !isHidden) {
var _parentRect$top, _parentRect$top2, _parentRect$left;
const wrapperRect = wrapperRef.current.getBoundingClientRect();
const parentElement = !isServer() ? parent || document.body : null;
const parentRect = parentElement === null || parentElement === void 0 ? void 0 : parentElement.getBoundingClientRect();
const isParentRelative = parentElement ? ['absolute', 'relative'].includes(getComputedStyle(parentElement).position) || parentElement === document.body : false;
setRect({
top: wrapperRect.top - (isParentRelative ? ((_parentRect$top = parentRect === null || parentRect === void 0 ? void 0 : parentRect.top) !== null && _parentRect$top !== void 0 ? _parentRect$top : 0) - parentElement.scrollTop : 0),
bottom: wrapperRect.bottom - (isParentRelative ? ((_parentRect$top2 = parentRect === null || parentRect === void 0 ? void 0 : parentRect.top) !== null && _parentRect$top2 !== void 0 ? _parentRect$top2 : 0) - parentElement.scrollTop : 0),
left: wrapperRect.left - (isParentRelative ? (_parentRect$left = parentRect === null || parentRect === void 0 ? void 0 : parentRect.left) !== null && _parentRect$left !== void 0 ? _parentRect$left : 0 : 0),
width: wrapperRect.width
});
}
}, [isHidden, parent]);
useImperativeHandle(ref, () => ({
focus() {
setIsHidden(false);
},
blur() {
setIsHidden(true);
},
getHiddenState() {
return isHidden;
}
}), [isHidden]);
useEffect(() => {
function handleBlur(event) {
var _wrapperRef$current, _boxRef$current;
if (!hasTouchStartedRef.current && event.type === 'click') {
return;
}
if (isHidden) return;
if ((_wrapperRef$current = wrapperRef.current) !== null && _wrapperRef$current !== void 0 && _wrapperRef$current.contains(event.target) || (_boxRef$current = boxRef.current) !== null && _boxRef$current !== void 0 && _boxRef$current.contains(event.target)) {
return;
}
setIsHidden(true);
if (onBlur && isFunction(onBlur)) {
onBlur(event);
}
}
function hide() {
setIsHidden(true);
}
function handleKeyDown(_ref) {
var _wrapperRef$current2;
let {
keyCode,
target
} = _ref;
if (keyCode === 9 && (_wrapperRef$current2 = wrapperRef.current) !== null && _wrapperRef$current2 !== void 0 && _wrapperRef$current2.contains(target)) {
hide();
}
}
function handleTouchStart() {
hasTouchStartedRef.current = true;
}
function handleTouchEnd() {
hasTouchStartedRef.current = false;
}
document.addEventListener('click', handleBlur);
document.addEventListener('mousedown', handleBlur);
document.addEventListener('touchstart', handleTouchStart);
document.addEventListener('touchend', handleTouchEnd);
document.addEventListener('mousemove', handleTouchEnd);
window.addEventListener('blur', hide);
window.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('click', handleBlur);
document.removeEventListener('mousedown', handleBlur);
document.removeEventListener('touchstart', handleTouchStart);
document.removeEventListener('touchend', handleTouchEnd);
document.removeEventListener('mousemove', handleTouchEnd);
window.removeEventListener('blur', hide);
window.removeEventListener('keydown', handleKeyDown);
};
}, [isHidden, onBlur]);
const handleFocus = e => {
setIsHidden(false);
if (onFocus) {
return onFocus(e);
}
return null;
};
const setBoxRef = useCallback(node => {
boxRef.current = node;
if (overlayProps !== null && overlayProps !== void 0 && overlayProps.ref) {
overlayProps.ref(node);
}
}, [overlayProps]);
const toggle = useCallback(event => {
setIsHidden(hidden => !hidden);
event.stopPropagation();
}, []);
if (!InputComponent) {
return null;
}
const positionStyles = rect ? {
width: rect.width,
top: rect.bottom,
left: rect.left
} : null;
let {
right,
icon,
onIconClick
} = restProps;
if (hasOpenCloseIcon) {
if (restProps.design === Input.BORDER_DESIGN && InputComponent.displayName === Input.displayName) {
right = /*#__PURE__*/React.createElement(Icon, {
icon: "fa fa-chevron-down",
style: {
padding: '10px',
alignItems: 'center',
alignSelf: 'stretch'
},
onClick: toggle
});
} else {
icon = 'fa fa-chevron-down';
onIconClick = toggle;
}
}
return /*#__PURE__*/React.createElement("div", {
style: {
display: renderInline ? 'flex' : 'inline-block',
...(renderInline ? {
height: '100%',
flexDirection: 'column'
} : {}),
...style
},
className: classnames(className, !renderInline && 'cc__input-box'),
ref: wrapperRef
}, /*#__PURE__*/React.createElement(InputComponent, _extends({}, restProps, {
right: right,
icon: icon,
onIconClick: onIconClick,
style: renderInline && hideInput ? {
position: 'absolute',
visibility: 'hidden'
} : undefined,
ref: inputRef,
onFocus: handleFocus
})), renderInline ? /*#__PURE__*/React.createElement("div", {
className: "cc__input-box--inline-wrapper scrollbar",
style: {
marginTop: !hideInput ? 20 : 0,
overflow: 'hidden auto'
}
}, children) : /*#__PURE__*/React.createElement(Overlay, {
parent: parent
}, !!(rect && children) && /*#__PURE__*/React.createElement("div", _extends({
onClick: e => e.preventDefault(),
className: classnames("cc__input-box__overlay scrollbar", boxClassName),
style: {
...positionStyles,
...(overlayProps === null || overlayProps === void 0 ? void 0 : overlayProps.style),
...(isHidden ? {
display: 'none'
} : {})
}
}, overlayProps, {
ref: setBoxRef
}), children)));
});
InputBox.propTypes = {
onBlur: PropTypes.func,
inputComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
parent: typeof Element !== 'undefined' ? PropTypes.instanceOf(Element) : () => {},
onFocus: PropTypes.func,
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
className: PropTypes.string,
boxClassName: PropTypes.string,
inputRef: PropTypes.func,
// eslint-disable-next-line react/forbid-prop-types
overlayProps: PropTypes.object,
style: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
hasOpenCloseIcon: PropTypes.bool,
renderInline: PropTypes.bool,
hideInput: PropTypes.bool
};
InputBox.displayName = 'InputBox';
export default InputBox;
//# sourceMappingURL=InputBox.js.map