@onesy/ui-react
Version:
UI for React
338 lines (333 loc) • 14.9 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _utils = require("@onesy/utils");
var _styleReact = require("@onesy/style-react");
var _Portal = _interopRequireDefault(require("../Portal"));
var _Focus = _interopRequireDefault(require("../Focus"));
var _Fade = _interopRequireDefault(require("../Fade"));
var _Surface = _interopRequireDefault(require("../Surface"));
var _useMediaQuery = _interopRequireDefault(require("../useMediaQuery"));
var _utils2 = require("../utils");
var _jsxRuntime = require("react/jsx-runtime");
const _excluded = ["ref", "tonal", "color", "size", "open", "openDefault", "mainRef", "backgroundRef", "partialyOpened", "minWidth", "maxWidth", "fullScreen", "fullWidth", "background", "modalWrapper", "modalWrapperSurface", "portal", "focus", "freezeScroll", "disableKeyboardClose", "disableBackgroundClose", "backgroundInvisible", "onClose", "NoSurfaceProps", "SurfaceProps", "BackgroundProps", "PortalProps", "TransitionComponentProps", "BackgroundComponent", "TransitionComponent", "Component", "className", "children"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
const useStyle = (0, _styleReact.style)(theme => ({
root: {
position: 'fixed',
inset: '0',
zIndex: theme.z_index.modal,
pointerEvents: 'none'
},
// Size
size_small: {
padding: theme.methods.space.value(2, 'px'),
borderRadius: `${theme.shape.radius.unit * 2 + theme.shape.radius.unit / 2}px`
},
size_regular: {
padding: theme.methods.space.value('md', 'px'),
borderRadius: `${theme.shape.radius.unit * 3 + theme.shape.radius.unit / 2}px`
},
size_large: {
padding: theme.methods.space.value('lg', 'px'),
borderRadius: `${theme.shape.radius.unit * 4 + theme.shape.radius.unit / 2}px`
},
background: {
position: 'absolute',
inset: '0',
width: '100%',
height: '100%',
background: 'rgba(0, 0, 0, 0.44)',
zIndex: -1,
pointerEvents: 'all'
},
backgroundInvisible: {
background: 'transparent'
},
modalRoot: {
position: 'relative',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
pointerEvents: 'none'
},
surface: {
display: 'flex',
flexDirection: 'column',
minWidth: `280px`,
maxHeight: `calc(100% - ${theme.methods.space.value('xl') * 2}px)`,
margin: theme.methods.space.value('xl', 'px'),
overflow: 'hidden',
pointerEvents: 'all'
},
noSurface: {
pointerEvents: 'all',
maxWidth: '100%'
},
fullScreen: {
width: '100%',
height: '100%',
borderRadius: '0 !important',
maxWidth: 'unset !important',
maxHeight: 'unset !important',
margin: '0 !important'
},
fullWidth: {
width: `calc(100% - ${theme.methods.space.value('xl') * 2}px)`
},
// minWidth
minWidth_xxs: {
minWidth: 'clamp(0px, 320px, calc(100vw - 48px))'
},
minWidth_xs: {
minWidth: 'clamp(0px, 400px, calc(100vw - 48px))'
},
minWidth_sm: {
minWidth: 'clamp(0px, 480px, calc(100vw - 48px))'
},
minWidth_rg: {
minWidth: 'clamp(0px, 560px, calc(100vw - 48px))'
},
minWidth_lg: {
minWidth: 'clamp(0px, 800px, calc(100vw - 48px))'
},
minWidth_xl: {
minWidth: 'clamp(0px, 1120px, calc(100vw - 48px))'
},
minWidth_xxl: {
minWidth: 'clamp(0px, 1360px, calc(100vw - 48px))'
},
minWidth_unset: {
minWidth: `unset`
},
// maxWidth
maxWidth_xxs: {
maxWidth: `320px`
},
maxWidth_xs: {
maxWidth: `400px`
},
maxWidth_sm: {
maxWidth: `480px`
},
maxWidth_rg: {
maxWidth: `560px`
},
maxWidth_lg: {
maxWidth: `800px`
},
maxWidth_xl: {
maxWidth: `1120px`
},
maxWidth_xxl: {
maxWidth: `1360px`
},
maxWidth_unset: {
maxWidth: `unset`
}
}), {
name: 'onesy-Modal'
});
let MODALS_OPEN = 0;
// To do
// 1. Add padding right for freezeScroll for the scroll bar if it exists and width that it is
const Modal = props_ => {
var _theme$ui, _theme$ui2, _theme$elements, _theme$elements2, _theme$elements3, _theme$elements4;
const theme = (0, _styleReact.useOnesyTheme)();
const props = _objectSpread(_objectSpread(_objectSpread({}, theme === null || theme === void 0 || (_theme$ui = theme.ui) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.elements) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.all) === null || _theme$ui === void 0 || (_theme$ui = _theme$ui.props) === null || _theme$ui === void 0 ? void 0 : _theme$ui.default), theme === null || theme === void 0 || (_theme$ui2 = theme.ui) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.elements) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.onesyModal) === null || _theme$ui2 === void 0 || (_theme$ui2 = _theme$ui2.props) === null || _theme$ui2 === void 0 ? void 0 : _theme$ui2.default), props_);
const Surface = (theme === null || theme === void 0 || (_theme$elements = theme.elements) === null || _theme$elements === void 0 ? void 0 : _theme$elements.Surface) || _Surface.default;
const Portal = (theme === null || theme === void 0 || (_theme$elements2 = theme.elements) === null || _theme$elements2 === void 0 ? void 0 : _theme$elements2.Portal) || _Portal.default;
const Focus = (theme === null || theme === void 0 || (_theme$elements3 = theme.elements) === null || _theme$elements3 === void 0 ? void 0 : _theme$elements3.Focus) || _Focus.default;
const Fade = (theme === null || theme === void 0 || (_theme$elements4 = theme.elements) === null || _theme$elements4 === void 0 ? void 0 : _theme$elements4.Fade) || _Fade.default;
const {
ref,
tonal = true,
color = 'primary',
size = 'regular',
open: open_,
openDefault,
mainRef,
backgroundRef,
partialyOpened,
minWidth: minWidth_,
maxWidth: maxWidth_ = 'rg',
fullScreen,
fullWidth,
background = true,
modalWrapper = true,
modalWrapperSurface = true,
portal = true,
focus = true,
freezeScroll = true,
disableKeyboardClose,
disableBackgroundClose,
backgroundInvisible,
onClose: onClose_,
NoSurfaceProps,
SurfaceProps,
BackgroundProps,
PortalProps: PortalProps_,
TransitionComponentProps,
BackgroundComponent = Fade,
TransitionComponent = Fade,
Component = 'div',
className,
children
} = props,
other = (0, _objectWithoutProperties2.default)(props, _excluded);
const {
classes
} = useStyle();
const [open, setOpen] = _react.default.useState(openDefault !== undefined ? openDefault : open_);
const [inProp, setInProp] = _react.default.useState(open_);
const [portalElement, setPortalElement] = _react.default.useState();
const refs = {
root: _react.default.useRef(undefined),
focus: _react.default.useRef(undefined),
open: _react.default.useRef(open),
freezeScroll: _react.default.useRef(undefined),
interval: _react.default.useRef(undefined)
};
const mobile = (0, _useMediaQuery.default)('(max-width: 767px)', {
element: refs.root.current
});
const minWidth = minWidth_ !== undefined ? minWidth_ : !mobile ? 'sm' : undefined;
refs.open.current = open;
refs.freezeScroll.current = freezeScroll;
const modal = {
open: () => {
var _refs$root$current;
MODALS_OPEN++;
const rootDocument = (0, _utils.isEnvironment)('browser') ? ((_refs$root$current = refs.root.current) === null || _refs$root$current === void 0 ? void 0 : _refs$root$current.ownerDocument) || window.document : undefined;
if (freezeScroll) rootDocument.body.style.overflow = 'hidden';
},
close: () => {
var _refs$root$current2;
MODALS_OPEN--;
const rootDocument_0 = (0, _utils.isEnvironment)('browser') ? ((_refs$root$current2 = refs.root.current) === null || _refs$root$current2 === void 0 ? void 0 : _refs$root$current2.ownerDocument) || window.document : undefined;
if (MODALS_OPEN <= 0 && freezeScroll) rootDocument_0.body.style.removeProperty('overflow');
}
};
let maxWidth = maxWidth_;
if (fullWidth) maxWidth = undefined;
const onClose = () => {
if ((0, _utils.is)('function', onClose_) && open) onClose_();
};
const onKeyDown = event => {
if (!refs.open.current) return;
if (event.key === 'Escape' && !disableKeyboardClose) {
event.stopPropagation();
onClose();
}
};
_react.default.useEffect(() => {
var _refs$root$current3;
const rootDocument_1 = (0, _utils.isEnvironment)('browser') ? ((_refs$root$current3 = refs.root.current) === null || _refs$root$current3 === void 0 ? void 0 : _refs$root$current3.ownerDocument) || window.document : undefined;
if (open) modal.open();
// Bug clean up fix
refs.interval.current = setInterval(() => {
if (MODALS_OPEN <= 0 && refs.freezeScroll.current && rootDocument_1.body.style.overflow === 'hidden') {
rootDocument_1.body.style.removeProperty('overflow');
}
}, 1400);
return () => {
if (open) modal.close();
clearInterval(refs.interval.current);
};
}, []);
_react.default.useEffect(() => {
if (open_ && !open) {
setOpen(true);
setInProp(true);
modal.open();
} else if (!open_ && open) modalWrapper ? setInProp(false) : setOpen(false);
}, [open_]);
_react.default.useEffect(() => {
var _refs$focus$current;
if (open) (_refs$focus$current = refs.focus.current) === null || _refs$focus$current === void 0 || _refs$focus$current.focus();
}, [open]);
const onExited = value => {
setOpen(false);
modal.close();
if ((0, _utils.is)('function', TransitionComponentProps === null || TransitionComponentProps === void 0 ? void 0 : TransitionComponentProps.onExited)) TransitionComponentProps === null || TransitionComponentProps === void 0 || TransitionComponentProps.onExited(value);
};
if (!open && !partialyOpened) return null;
const PortalComponent = portal ? Portal : _react.default.Fragment;
let PortalProps = {};
if (portal) {
var _ref;
const rootDocumentElement = (0, _utils.isEnvironment)('browser') ? ((_ref = portalElement || refs.root.current) === null || _ref === void 0 ? void 0 : _ref.ownerDocument) || window.document : undefined;
if ((0, _utils.isEnvironment)('browser')) PortalProps.element = rootDocumentElement.body;
PortalProps = _objectSpread(_objectSpread({}, PortalProps), PortalProps_);
}
const FocusComponent = focus ? Focus : _react.default.Fragment;
const FocusProps = focus ? {
ref: refs.focus,
onKeyDown
} : {};
const MainProps = {
role: 'dialog',
'aria-labelledby': 'onesy-modal-title',
'aria-describedby': 'onesy-modal-text',
'aria-modal': 'true',
'aria-live': 'assertive'
};
let Main = children && /*#__PURE__*/_react.default.cloneElement(children, _objectSpread({}, MainProps));
if (modalWrapper) Main = /*#__PURE__*/(0, _jsxRuntime.jsx)("div", _objectSpread(_objectSpread({}, MainProps), {}, {
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Modal', theme) && ['onesy-Modal-modal-root'], classes.modalRoot]),
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(TransitionComponent, _objectSpread(_objectSpread({
in: inProp
}, TransitionComponentProps), {}, {
onExited: onExited,
add: true,
children: !modalWrapperSurface ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Modal', theme) && ['onesy-Modal-no-surface'], NoSurfaceProps === null || NoSurfaceProps === void 0 ? void 0 : NoSurfaceProps.className, classes.noSurface]),
children: children
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(Surface, _objectSpread(_objectSpread({
ref: mainRef,
tonal: tonal,
color: color,
tabIndex: "-1"
}, SurfaceProps), {}, {
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Modal', theme) && ['onesy-Modal-surface', `onesy-Modal-size-${size}`], classes.surface, classes[`minWidth_${minWidth}`], classes[`maxWidth_${maxWidth}`], classes[`size_${size}`], fullScreen && classes.fullScreen, fullWidth && classes.fullWidth, SurfaceProps === null || SurfaceProps === void 0 ? void 0 : SurfaceProps.className]),
onKeyDown: onKeyDown,
children: children
}))
}))
}));
return /*#__PURE__*/(0, _jsxRuntime.jsx)(PortalComponent, _objectSpread(_objectSpread({}, PortalProps), {}, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Component, _objectSpread(_objectSpread({
ref: item => {
if (ref) {
if ((0, _utils.is)('function', ref)) ref(item);else ref.current = item;
}
refs.root.current = item;
setPortalElement(item);
},
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Modal', theme) && ['onesy-Modal-root', open && `onesy-Modal-open`, focus && `onesy-Modal-focus`], className, classes.root])
}, other), {}, {
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(FocusComponent, _objectSpread(_objectSpread({}, FocusProps), {}, {
children: [background && /*#__PURE__*/(0, _jsxRuntime.jsx)(BackgroundComponent, _objectSpread(_objectSpread({
in: inProp,
add: true
}, BackgroundProps), {}, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
ref: backgroundRef,
onClick: () => !disableBackgroundClose && onClose(),
className: (0, _styleReact.classNames)([(0, _utils2.staticClassName)('Modal', theme) && ['onesy-Modal-background', backgroundInvisible && 'onesy-Modal-background-invisible'], classes.background, backgroundInvisible && classes.backgroundInvisible])
})
})), Main]
}))
}))
}));
};
Modal.displayName = 'onesy-Modal';
var _default = exports.default = Modal;