UNPKG

@wonderflow/react-components

Version:

UI components from Wonderflow's Wanda design system

66 lines (65 loc) 5.68 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; /* * Copyright 2022-2023 Wonderflow Design Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import tkns from '@wonderflow/tokens/platforms/web/tokens.json'; import clsx from 'clsx'; import { domMax, LazyMotion, m } from 'framer-motion'; import { cloneElement, forwardRef, isValidElement, useMemo, } from 'react'; import { FocusOn } from 'react-focus-on'; import { Elevator, OverlayContainer, Spinner, Stack, Text, useResponsiveContext, } from '../..'; import { ModalContent } from './content/modal-content'; import { ModalFooter } from './footer/modal-footer'; import { ModalHeader } from './header/modal-header'; import * as styles from './modal.module.css'; const cssEasingToArray = (cssEasing) => { const [x1, y1, x2, y2] = cssEasing.replace(/[^0-9.,]+/g, '').split(',').map(i => parseFloat(i)); return [x1, y1, x2, y2]; }; export const Modal = forwardRef(({ children, className, size = 'medium', theme = 'light', title, subtitle, hideCloseButton, hideHeaderBorder, hideFooterBorder, content, primaryAction, secondaryAction, tertiaryAction, alignActionCenter, alignContentCenter, isVisible, preventCloseOnClickOutside, isLoading, onCloseModal, ...otherProps }, forwardedRef) => { const { matches } = useResponsiveContext(); const hasActions = tertiaryAction ?? secondaryAction ?? primaryAction; const ModalAnimation = useMemo(() => ({ visible: { scale: 1, opacity: 1, y: 0, transition: { ease: cssEasingToArray(tkns.easing.entrance), duration: parseFloat(tkns.duration[300].replace('s', '')), }, }, hidden: { scale: matches.small ? 0.98 : 1, opacity: matches.small ? 0 : 1, y: matches.small ? 0 : '100%', transition: { ease: cssEasingToArray(tkns.easing.exit), duration: matches.small ? parseFloat(tkns.duration[200].replace('s', '')) : parseFloat(tkns.duration[500].replace('s', '')), }, }, }), [matches]); return (_jsx(_Fragment, { children: isVisible && (_jsx(OverlayContainer, { onClose: onCloseModal, overlayColor: otherProps.overlayColor, root: otherProps.root, index: otherProps.index, obfuscate: otherProps.obfuscate, children: _jsx("div", { "aria-modal": "true", "aria-labelledby": (typeof title === 'string') ? title : 'modal-label', className: clsx(styles.Modal, className), ref: forwardedRef, ...otherProps, children: _jsx(FocusOn, { onClickOutside: preventCloseOnClickOutside ? undefined : onCloseModal, onEscapeKey: onCloseModal, children: _jsx(LazyMotion, { features: domMax, children: _jsx(m.div, { role: "dialog", variants: ModalAnimation, initial: "hidden", animate: "visible", exit: "hidden", className: styles.Container, children: _jsx(Elevator, { resting: 4, children: _jsx("div", { className: clsx(styles.Main, className), ref: forwardedRef, "data-theme": theme, "data-size": size, ...otherProps, children: children ?? (_jsxs(_Fragment, { children: [_jsxs(Modal.Header, { hideCloseButton: hideCloseButton, theme: theme, hideBorder: (!title ?? !subtitle) || hideHeaderBorder, children: [title && _jsx(Text, { variant: "heading-6", children: title }), (title && subtitle) && _jsx(Text, { variant: "subtitle-2", children: subtitle })] }), content && (_jsx(Modal.Content, { theme: theme, alignContentCenter: isLoading ? true : alignContentCenter, children: isLoading ? (_jsx(Stack, { fill: true, hAlign: "center", vPadding: 64, children: _jsxs(Stack, { hAlign: "center", vAlign: "center", rowGap: 16, children: [_jsx(Spinner, { dimension: "big" }), _jsx(Text, { variant: "body-1", children: "Loading..." })] }) })) : content })), hasActions && (_jsx(Modal.Footer, { theme: theme, hideBorder: hideFooterBorder, children: _jsxs(Stack, { direction: matches.small ? 'row' : 'column-reverse', rowGap: matches.small ? undefined : '16', fill: false, hAlign: (alignActionCenter && matches.small) ? 'center' : 'space-between', vAlign: "center", columnGap: 16, children: [_jsx(Stack, { direction: "row", fill: true, children: tertiaryAction }), _jsxs(Stack, { direction: matches.small ? 'row' : 'column-reverse', rowGap: matches.small ? undefined : '16', columnGap: 16, children: [secondaryAction && isValidElement(secondaryAction) && cloneElement(secondaryAction, { ...secondaryAction.props, kind: 'secondary', dimension: 'regular' }), primaryAction && isValidElement(primaryAction) && cloneElement(primaryAction, { ...primaryAction.props, kind: 'primary', dimension: 'regular' })] })] }) }))] })) }) }) }) }) }) }) })) })); }); Modal.displayName = 'Modal'; Modal.Header = ModalHeader; Modal.Content = ModalContent; Modal.Footer = ModalFooter;