@appbuckets/react-ui
Version:
Just Another React UI Framework
295 lines (292 loc) • 8.19 kB
JavaScript
import { __rest, __read, __assign } from 'tslib';
import * as React from 'react';
import clsx from 'clsx';
import {
useAutoControlledValue,
useElementType,
childrenUtils,
MountNode,
} from '@appbuckets/react-ui-core';
import { useSharedClassName } from '../utils/customHook.js';
import '../BucketTheme/BucketTheme.js';
import { useWithDefaultProps } from '../BucketTheme/BucketContext.js';
import Backdrop from '../Backdrop/Backdrop.js';
import Button from '../Button/Button.js';
import Icon from '../Icon/Icon.js';
import { ModalProvider } from './Modal.context.js';
import ModalActions from './ModalActions.js';
import ModalContent from './ModalContent.js';
import ModalHeader from './ModalHeader.js';
/* --------
* Component Render
* -------- */
var Modal = function (receivedProps) {
var props = useWithDefaultProps('modal', receivedProps);
// ----
// Get Modal Props
// ----
var _a = useSharedClassName(props),
className = _a.className,
_b = _a.rest,
/** Modal Props */
actions = _b.actions,
basic = _b.basic,
children = _b.children,
closeIcon = _b.closeIcon,
closeOnBackdropClick = _b.closeOnBackdropClick,
content = _b.content,
header = _b.header,
icon = _b.icon,
userDefinedMountNode = _b.mountNode,
size = _b.size,
/** Modal handlers */
onActionClick = _b.onActionClick,
onClose = _b.onClose,
onOpen = _b.onOpen,
/** Modal state Prop */
defaultOpen = _b.defaultOpen,
openProp = _b.open,
/** Handled Backdrop Props */
loading = _b.loading,
loaderProps = _b.loaderProps,
timeout = _b.timeout,
/** Handled Portal Props */
closeOnEscape = _b.closeOnEscape,
openOnTriggerClick = _b.openOnTriggerClick,
openOnTriggerFocus = _b.openOnTriggerFocus,
openOnTriggerMouseEnter = _b.openOnTriggerMouseEnter,
trigger = _b.trigger,
triggerRef = _b.triggerRef,
/** All other Props */
rest = __rest(_b, [
'actions',
'basic',
'children',
'closeIcon',
'closeOnBackdropClick',
'content',
'header',
'icon',
'mountNode',
'size',
'onActionClick',
'onClose',
'onOpen',
'defaultOpen',
'open',
'loading',
'loaderProps',
'timeout',
'closeOnEscape',
'openOnTriggerClick',
'openOnTriggerFocus',
'openOnTriggerMouseEnter',
'trigger',
'triggerRef',
]);
// ----
// Init Modal Internal State
// ----
/** Init the AutoControlled open state */
var _c = __read(
useAutoControlledValue(false, {
prop: openProp,
defaultProp: defaultOpen,
}),
2
),
open = _c[0],
trySetOpen = _c[1];
/** Init a state to define if inner modal component must be visible */
var _d = __read(React.useState(open), 2),
innerModalVisible = _d[0],
setInnerModalVisible = _d[1];
/** Get the component element type */
var ElementType = useElementType(Modal, receivedProps, props);
/** Check if in this render modal has children */
var hasChildren = !childrenUtils.isNil(children);
// ----
// Define Modal Handlers
// ----
var handleModalEntering = React.useCallback(function () {
setInnerModalVisible(true);
}, []);
var handleModalExited = React.useCallback(function () {
setInnerModalVisible(false);
}, []);
var handleModalClose = function (e) {
/** Stop Event Propagation */
e.stopPropagation();
/** Call User Handler if Exists */
if (onClose) {
onClose(e, props);
}
/** Try to close the modal */
trySetOpen(false);
};
var handleModalOpen = function (e) {
/** Stop Event Propagation */
e.stopPropagation();
/** Call User Handler if Exists */
if (onOpen) {
onOpen(e, props);
}
/** Try to open the modal */
trySetOpen(true);
};
// ----
// Build Component Classes
// ----
var contentClasses = clsx(
'modal',
size,
{ basic: basic },
icon && 'with-icon',
className
);
var mountNodeClasses = clsx('dimmable', open && 'dimmed');
// ----
// Memoized Elements
// ----
var modalIconElement = React.useMemo(
function () {
return (
icon &&
Icon.create(icon, {
autoGenerateKey: false,
overrideProps: {
solid: 'inverted circle',
},
})
);
},
[icon]
);
var closeIconElement =
closeIcon &&
Button.create(
{
icon: closeIcon,
flat: true,
appearance: 'white shade',
},
{
autoGenerateKey: false,
defaultProps: { className: 'close' },
overrideProps: function (predefinedProps) {
return {
onClick: function (e) {
/** Call original user defined handler on icon */
if (predefinedProps.onClick) {
predefinedProps.onClick(e, predefinedProps);
}
/** Try to close the Modal */
handleModalClose(e);
},
};
},
}
);
var modalHeaderElement = React.useMemo(
function () {
/** Set empty component if is closed */
if (!innerModalVisible || !header) {
return null;
}
/** Create a new Modal Header using Shorthand Factory */
return ModalHeader.create(header, { autoGenerateKey: false });
},
[innerModalVisible, header]
);
var modalActionsElement = React.useMemo(
function () {
/** Set empty component if is closed */
if (hasChildren || !innerModalVisible || !actions) {
return null;
}
/** Create modal action element using Shorthand Factory */
return ModalActions.create(actions, {
autoGenerateKey: false,
overrideProps: function (predefinedProps) {
return {
onActionClick: function (e, buttonProps) {
/** Call predefined on Action Click function */
if (predefinedProps.onActionClick) {
predefinedProps.onActionClick(e, buttonProps);
}
/** Call modal action click if exists */
if (onActionClick) {
onActionClick(e, buttonProps);
}
},
};
},
});
},
[hasChildren, innerModalVisible, actions, onActionClick]
);
// ----
// Init an internal function to build Modal Content
// ----
var renderModalContent = function () {
return React.createElement(
ModalProvider,
{ value: { closeModal: handleModalClose } },
React.createElement(
ElementType,
__assign({}, rest, { className: contentClasses }),
React.createElement(MountNode, {
className: mountNodeClasses,
node:
userDefinedMountNode !== null && userDefinedMountNode !== void 0
? userDefinedMountNode
: document.body,
}),
modalIconElement,
closeIconElement,
modalHeaderElement,
!hasChildren
? React.createElement(
React.Fragment,
null,
ModalContent.create(content, { autoGenerateKey: false }),
modalActionsElement
)
: children
)
);
};
// ----
// Render the Component
// ----
return React.createElement(
Backdrop,
{
page: true,
className: 'modals',
visible: open,
closeOnBackdropClick: closeOnBackdropClick,
closeOnDocumentClick: false,
closeOnEscape: closeOnEscape,
openOnTriggerClick: openOnTriggerClick,
openOnTriggerMouseEnter: openOnTriggerMouseEnter,
openOnTriggerFocus: openOnTriggerFocus,
trigger: trigger,
triggerRef: triggerRef,
verticalAlign: 'on top',
loading: loading,
loaderProps: loaderProps,
timeout: timeout,
onClose: handleModalClose,
onOpen: handleModalOpen,
onEntering: handleModalEntering,
onExited: handleModalExited,
},
renderModalContent()
);
};
Modal.displayName = 'Modal';
Modal.Actions = ModalActions;
Modal.Content = ModalContent;
Modal.Header = ModalHeader;
export { Modal as default };