import type { ComponentType } from 'react' import type { Animated, StyleProp, ViewStyle } from 'react-native' /* ======================== ======================== * * ======================== INTERNAL TYPES ======================== * * ======================== ======================== */ export type ModalfyParams = { [key: string]: any } export type ModalTransitionValue = Animated.AnimatedInterpolation | string | number | undefined | null export type ModalTransitionOptions = (animatedValue: Animated.Value) => { [key: string]: | { [key: string]: ModalTransitionValue }[] | ModalTransitionValue } export type ModalListener = (eventName: ModalEventName, callback: ModalEventCallback) => ModalEventListener export type ModalEventListeners = Set<{ event: string handler: ModalEventCallback }> export type ModalEventName = 'onAnimate' | 'onClose' export type ModalOnAnimateEventCallback = (value?: number) => void export type ModalOnCloseEventCallback = (closingAction: { type: ModalClosingActionName origin: ModalClosingActionOrigin }) => void export type ModalClosingActionName = 'closeModal' | 'closeModals' | 'closeAllModals' export type ModalClosingActionOrigin = 'default' | 'fling' | 'backdrop' export type ModalEventCallback = ModalOnAnimateEventCallback | ModalOnCloseEventCallback export type ModalEventListener = { remove: () => boolean } export type ModalEventAction = 'add' export type ModalEventPayload = { eventName: ModalEventName handler: ModalEventCallback } export type ModalStatePendingClosingAction = | { modalName?: string action: 'closeModal' callback?: () => void } | { modalName: string action: 'closeModals' callback?: () => void } | { modalName?: never action: 'closeAllModals' callback?: () => void } export type ModalPendingClosingAction = | { hash: string currentModalHash?: string modalName?: string action: 'closeModal' callback?: () => void } | { hash: string currentModalHash?: string modalName: string action: 'closeModals' callback?: () => void } | { hash: string modalName?: never currentModalHash?: string action: 'closeAllModals' callback?: () => void } export interface ModalStackItem

{ name: Exclude component: ComponentType & { modalOptions?: ModalOptions } hash: string index: number options?: ModalOptions params?: any callback?: () => void } export interface ModalStack

{ names: Array> content: ModalStackItem

[] defaultOptions: ModalOptions openedItems: Set> openedItemsSize: number pendingClosingActions: Set pendingClosingActionsSize: number } export interface ModalContextProvider< P extends ModalfyParams, M extends Exclude = Exclude, > { currentModal: M | null closeAllModals: (callback?: () => void) => void closeModal: (stackItem?: M | ModalStackItem

, callback?: () => void) => void closeModals: (modalName: M, callback?: () => void) => boolean getParam: ( hash: ModalStackItem

['hash'], paramName: N, defaultValue?: D, ) => D extends P[M][N] ? P[M][N] : undefined openModal: (modalName: N, params?: P[N], callback?: () => void) => void stack: ModalStack

} export type ModalInternalState

= { currentModal: ModalContextProvider

['currentModal'] | string | null stack: ModalContextProvider

['stack'] } export interface ModalStateSubscriber

{ state: ModalInternalState

equalityFn: ModalStateEqualityChecker

error: boolean stateListener: ModalStateListener

unsubscribe: () => boolean } export interface ModalStateSubscription

{ unsubscribe: ModalStateSubscriber

['unsubscribe'] } export type ModalStateListener

= (state: ModalInternalState

| null, error?: Error) => void export type ModalStateEqualityChecker

= ( currentState: ModalInternalState

, newState: ModalInternalState

, ) => boolean export type ModalState

= Omit, 'currentModal' | 'stack' | 'openModal'> & { openModal: , N extends M>(args: { modalName: N params?: P[N] isCalledOutsideOfContext?: boolean callback?: () => void }) => void handleBackPress: () => boolean init: (updater: (currentState: ModalInternalState) => ModalInternalState) => ModalInternalState getState: () => ModalInternalState setState: (updater: (currentState: ModalInternalState) => ModalInternalState) => ModalInternalState subscribe: ( listener: ModalStateListener, equalityFn?: ModalStateEqualityChecker, ) => ModalStateSubscription queueClosingAction: (action: ModalStatePendingClosingAction) => ModalPendingClosingAction | null removeClosingAction: (action: ModalPendingClosingAction) => boolean } export interface SharedProps

extends ModalContextProvider

{ clearListeners: (hash: string) => void eventListeners: ModalEventListeners registerListener: ( hash: ModalStackItem

['hash'], eventName: ModalEventName, handler: ModalEventCallback, ) => ModalEventListener removeClosingAction: ModalState

['removeClosingAction'] rootStyle?: StyleProp } export type UsableModalProp

= Pick< ModalContextProvider

, 'closeAllModals' | 'closeModals' | 'currentModal' | 'openModal' > & { closeModal: (modalName?: Exclude, callback?: () => void) => void } export interface UsableModalComponentProp

extends Omit, 'closeModal' | 'stack' | 'getParam'> { addListener: ModalListener closeModal: (modalName?: M, callback?: () => void) => void getParam: ( paramName: N, defaultValue?: D, ) => D extends P[M][N] ? P[M][N] : undefined removeAllListeners: () => void params?: P[M] } /* ======================== ======================== * * ======================== CONSUMER TYPES ======================== * * ======================== ======================== */ /** * Interface of the modal stack configuration. * These settings will let Modalfy know what modals you will be rendering and how. * * @see https://colorfy-software.gitbook.io/react-native-modalfy/guides/typing#config-and-options */ export interface ModalStackConfig { [key: string]: ComponentType | ModalOptions } /** * Interface of the modal configuration options. * These settings will let Modalfy how to render and animate a modal. * * @see https://colorfy-software.gitbook.io/react-native-modalfy/guides/typing#config-and-options */ export interface ModalOptions { /** * Animation configuration used to animate a modal in, at the top of the stack. * It uses Animated.timing() by default, if you want to use another animation type, see `animationIn`. * * Note: only `easing` and `duration` are needed. * * @default { easing: Easing.inOut(Easing.exp), duration: 450 } * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#animateinconfig */ animateInConfig?: Pick /** * Animation function that receives the `animatedValue` used by the library to animate the modal opening, * and a `toValue` argument representing the modal position in the stack. * * Since Modalfy v3, the function receives a `callback` argument, which _can_ be called when the animation is finished, * depending on whether or not you'll have a callback in a `openModal()`. * * Note: If you just want to use Animated.timing(), check `animateInConfig`. * * @default - * @example * animationIn: (modalAnimatedValue, modalToValue, callback) => { * Animated.parallel([ * Animated.timing(modalAnimatedValue, { * toValue: modalToValue, * duration: 300, * easing: Easing.inOut(Easing.exp), * useNativeDriver: true, * }), * Animated.timing(myOtherAnimatedValue, { * toValue: 1, * duration: 300, * easing: Easing.inOut(Easing.exp), * useNativeDriver: true, * }), * ]).start(({ finished }) => { * if (finished) callback?.() * }) * } * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#animationin */ animationIn?: ( animatedValue: Animated.Value, toValue: number, callback?: () => void, ) => Animated.CompositeAnimation | void /** * Animation configuration used to animate a modal out (underneath other modals or when closing the last one). * Uses Animated.timing(), if you want to use another animation type, use `animationOut`. * * Note: only `easing` and `duration` are needed. * * @default { easing: Easing.inOut(Easing.exp), duration: 450 } * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#animationout */ animateOutConfig?: Pick /** * Animation function that receives the `animatedValue` used by the library to animate the modal closing, * and a `toValue` argument representing the modal position in the stack. * * Since Modalfy v3, the function receives a `callback` argument, which **_must_** be called when the animation is finished. * * Note: If you just want to use Animated.timing(), check `animateOutConfig`. * * @default - * @example * animationOut: (modalAnimatedValue, modalToValue, callback) => { * Animated.parallel([ * Animated.timing(modalAnimatedValue, { * toValue: modalToValue, * duration: 300, * easing: Easing.inOut(Easing.exp), * useNativeDriver: true, * }), * Animated.timing(myOtherAnimatedValue, { * toValue: 1, * duration: 300, * easing: Easing.inOut(Easing.exp), * useNativeDriver: true, * }), * ]).start(({ finished }) => { * if (finished) callback() * }) * } * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#animationout */ animationOut?: ( animatedValue: Animated.Value, toValue: number, callback?: () => void, ) => Animated.CompositeAnimation | void /** * How you want the modal stack to behave when users press the backdrop, but also when the physical back button is pressed on Android. * * @default 'pop' * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#backbehavior */ backBehavior?: 'clear' | 'pop' | 'none' /** * Color of the modal stack backdrop. * * @default 'black' * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#backdropcolor */ backdropColor?: ViewStyle['backgroundColor'] /** * Number between `0` and `1` that defines the backdrop opacity. * * @default 0.6 * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#backdropopacity */ backdropOpacity?: number /** * Number that defines how long the backdrop should take to animate in and out. * * @default 300 * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#backdropanimationduration */ backdropAnimationDuration?: number /** * Styles applied to the `` directly wrapping your modal component. * * @default '{}' * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#containerstyle */ containerStyle?: ViewStyle /** * Disable fling gesture detection to close the modal. * * Note: the fling gesture handler is not enabled when `position` is `center`. * * @default false * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#disableflinggesture */ disableFlingGesture?: boolean /** * React component that will be rendered when you'll open the modal. * * Note: only needed when you're using this inside createModalStack() 1st argument. * * @default - * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#modal */ modal?: ComponentType /** * Vertical positioning of the modal. * * @default 'center' * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#position */ position?: 'center' | 'top' | 'bottom' /** * `transitionOptions(animatedValue)` returns a React Native style object containing values that can use the provided `animatedValue` to run animation interpolations on a modal. * * Note: the object returned by `transitionOptions()` must contain keys that work with `useNativeDriver: true`. * * @default - * @see https://colorfy-software.gitbook.io/react-native-modalfy/api/types/modaloptions#transitionoptions */ transitionOptions?: ModalTransitionOptions } /** * Interface of the `modal` prop exposed by the library to regular components. * * @argument { unknown } ModalStackParamsList? - Interface of the whole modal stack params. * @argument { unknown } Props? - Component's props interface. * * Note: Modal components used in `createModalStack()`'s config should employ `ModalComponentProp` instead. * * @see https://colorfy-software.gitbook.io/react-native-modalfy/guides/typing#modalprop */ export type ModalProp

= Props & { /** * Interface of the `modal` prop exposed by the library to regular components. * * Note: Modal components used in `createModalStack()`'s config should employ `ModalComponentProp` instead. * * @see https://colorfy-software.gitbook.io/react-native-modalfy/guides/typing#modalprop */ modal: UsableModalProp

} /** * Interface of the `modal` prop exposed by the library specifically to modal components. * * @argument { unknown } ModalStackParamsList? - Interface of the whole modal stack params. * @argument { unknown } Props? - Component's props interface. * @argument { string } ModalName? - Name of the current modal * * Note: Components that are not used from `createModalStack()`'s config should employ `ModalProp` instead. * * @see https://colorfy-software.gitbook.io/react-native-modalfy/guides/typing#modalcomponentprop */ export type ModalComponentProp

= Props & { /** * Interface of the `modal` prop exposed by the library specifically to modal components. * * Note: Components that are not used from `createModalStack()`'s config should employ `ModalProp` instead. * * @see https://colorfy-software.gitbook.io/react-native-modalfy/guides/typing#modalcomponentprop */ modal: UsableModalComponentProp } /** * Interface for a React component containing its props and the `modalOptions` static property. * * Note: Only use with Hooks modal components (those present in your `createModalStack()`'s config). * If you're working with a Class modal component, you can directly use `static modalOptions: ModalOptions`. * * @argument { unknown } Props? - Component's props interface. * * @see https://colorfy-software.gitbook.io/react-native-modalfy/guides/typing#modalcomponentwithoptions */ export type ModalComponentWithOptions

= ComponentType

& { modalOptions?: ModalOptions }