| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- import {
- useImperativeHandle,
- forwardRef,
- useEffect,
- useRef
- } from "react";
- import {
- Animated,
- Easing,
- View
- } from "react-native";
- import type IDialogProps from "./type";
- import type {
- IDialogRef
- } from "./type";
- import stylesheet, {
- useStyles
- } from "./stylesheet";
- import {
- NCoreUIKitLocalize,
- NCoreUIKitTheme
- } from "../../core/hooks";
- import type {
- RefForwardingComponent
- } from "../../types";
- import type {
- IModalRef
- } from "../modal/type";
- import {
- X as XIcon
- } from "lucide-react-native";
- import Button from "../button";
- import Modal from "../modal";
- import Text from "../text";
- import {
- uuid
- } from "../../utils";
- const Dialog: RefForwardingComponent<IDialogRef, IDialogProps> = ({
- bottomContentContainerStyle,
- contentJustify = "centered",
- closeAnimationDelay = 100,
- openAnimationDelay = 100,
- contentContainerStyle,
- bottomContainerStyle,
- headerContainerStyle,
- secondaryButtonStyle,
- secondaryButtonProps,
- primaryButtonStyle,
- primaryButtonProps,
- closeIconProps = {
- color: "low",
- size: 22
- },
- isVisible = false,
- withModal = true,
- headerComponent,
- bottomComponent,
- onOverlayPress,
- variant = "ok",
- modalProps,
- id: outID,
- onClosed,
- children,
- content,
- style,
- title
- }, ref) => {
- const {
- radiuses,
- colors,
- spaces
- } = NCoreUIKitTheme.useContext();
- const {
- localize
- } = NCoreUIKitLocalize.useContext();
- const id = useRef(outID ? outID : uuid());
- const {
- bottomContentContainer: bottomContentContainerDynamicStyle,
- headerContainer: headerContainerDynamicStyle,
- bottomContainer: bottomContainerDynamicStyle,
- primaryButton: primaryButtonDynamicStyle,
- contentText: contentTextDynamicStyle,
- headerTitle: headerTitleDynamicStyle,
- container: containerDynamicStyle,
- closeIcon: closeIconDynamicStyle,
- content: contentDynamicStyle
- } = useStyles({
- contentJustify,
- isVisible,
- radiuses,
- variant,
- colors,
- spaces
- });
- const scaleAnim = useRef(new Animated.Value(0)).current;
- const modalRef = useRef<IModalRef>(null);
- useEffect(() => {
- if(isVisible) {
- Animated.timing(scaleAnim, {
- duration: openAnimationDelay,
- useNativeDriver: true,
- easing: Easing.linear,
- toValue: 1
- }).start();
- }
- }, [isVisible]);
- useImperativeHandle(
- ref,
- () => ({
- closeAnimation
- }),
- []
- );
- const closeAnimation = (_onClosed?: (props: {
- id: string;
- }) => void) => {
- Animated.timing(scaleAnim, {
- duration: closeAnimationDelay,
- useNativeDriver: true,
- easing: Easing.linear,
- toValue: 0
- }).start(({
- finished
- }) => {
- if(finished) {
- if(_onClosed) _onClosed({
- id: id.current
- });
- if(onClosed) onClosed({
- id: id.current
- });
- if(modalRef && modalRef.current) modalRef.current.closeAnimation();
- }
- });
- };
- const renderHeader = () => {
- return <View
- style={[
- headerContainerStyle,
- stylesheet.headerContainer,
- headerContainerDynamicStyle
- ]}
- >
- {headerComponent || <Text
- style={[
- stylesheet.headerTitle,
- headerTitleDynamicStyle
- ]}
- variant="titleLargeSize"
- color="mid"
- >
- {title}
- </Text>}
- </View>;
- };
- const renderBottom = () => {
- if(variant === "info") {
- return null;
- }
- return <View
- style={[
- bottomContainerStyle,
- stylesheet.bottomContainer,
- bottomContainerDynamicStyle
- ]}
- >
- {bottomComponent || <View
- style={[
- bottomContentContainerStyle,
- stylesheet.bottomContentContainer,
- bottomContentContainerDynamicStyle
- ]}
- >
- {secondaryButton()}
- {primaryButton()}
- </View>}
- </View>;
- };
- const secondaryButton = () => {
- if(variant !== "yes-no") {
- return null;
- }
- return <Button
- onPress={() => {
- if(secondaryButtonProps?.onPress) secondaryButtonProps.onPress({
- closeAnimation: (onClosed?: (props: {
- id: string;
- }) => void) => {
- closeAnimation(onClosed);
- }
- });
- }}
- spreadBehaviour={contentJustify === "centered" ? "stretch" : "free"}
- title={secondaryButtonProps?.title || localize("cancel")}
- isLoading={secondaryButtonProps?.isLoading}
- style={secondaryButtonStyle}
- variant="outline"
- type="neutral"
- />;
- };
- const primaryButton = () => {
- return <Button
- displayBehaviourWhileLoading={primaryButtonProps?.displayBehaviourWhileLoading}
- spreadBehaviour={contentJustify === "centered" ? "stretch" : "free"}
- onPress={() => {
- if(primaryButtonProps?.onPress) primaryButtonProps?.onPress({
- closeAnimation: (onClosed?: (props: {
- id: string;
- }) => void) => {
- closeAnimation(onClosed);
- }
- });
- }}
- title={primaryButtonProps?.title || localize("ok")}
- isLoading={primaryButtonProps?.isLoading}
- style={[
- primaryButtonStyle,
- stylesheet.primaryButton,
- primaryButtonDynamicStyle
- ]}
- variant="filled"
- type="primary"
- size="medium"
- />;
- };
- const renderCloseIcon = () => {
- if(variant !== "info") {
- return null;
- }
- if(contentJustify === "centered") {
- return null;
- }
- return <Button
- onPress={() => {
- if(onOverlayPress) onOverlayPress({
- closeAnimation: (onClosed?: (props: {
- id: string;
- }) => void) => {
- closeAnimation(onClosed);
- }
- });
- }}
- icon={() => <XIcon
- color={closeIconProps.color}
- size={closeIconProps.size}
- />}
- style={[
- stylesheet.closeIcon,
- closeIconDynamicStyle
- ]}
- isCustomPadding={true}
- variant="ghost"
- />;
- };
- const renderDialog = () => {
- if(!isVisible) {
- return null;
- }
- return <Animated.View
- style={[
- style,
- stylesheet.container,
- containerDynamicStyle,
- {
- transform: [{
- scale: scaleAnim
- }]
- }
- ]}
- >
- {renderCloseIcon()}
- {renderHeader()}
- <View
- style={[
- contentContainerStyle,
- stylesheet.content,
- contentDynamicStyle
- ]}
- >
- {children || <Text
- style={[
- stylesheet.contentText,
- contentTextDynamicStyle
- ]}
- variant="bodyLargeSize"
- >
- {content}
- </Text>}
- </View>
- {renderBottom()}
- </Animated.View>;
- };
- if(!isVisible) {
- return null;
- }
- return withModal ? <Modal
- {...modalProps}
- id={`${id.current}-modal`}
- ref={modalRef}
- onOverlayPress={() => {
- if(onOverlayPress) onOverlayPress({
- closeAnimation: (onClosed?: (props: {
- id: string;
- }) => void) => {
- closeAnimation(onClosed);
- }
- });
- }}
- >
- {renderDialog()}
- </Modal> : renderDialog();
- };
- export default forwardRef(Dialog);
|