UNPKG

react-native-trays

Version:

Production-grade, Family inspired, React Native Tray System library

134 lines (133 loc) 4.29 kB
"use strict"; /** * TrayProvider.tsx * * Provides the TrayProvider React context component for managing tray stacks and rendering trays in a React Native app. * This file contains the core logic for tray registration, stack management, and context propagation. */ import React, { useCallback, useMemo, useState } from 'react'; import { StyleSheet, View } from 'react-native'; import { FadeIn, FadeOut } from 'react-native-reanimated'; let BlurView = null; try { BlurView = require('expo-blur').BlurView; } catch (e) { BlurView = null; } import Animated from 'react-native-reanimated'; import uuid from 'react-native-uuid'; import { TrayContext } from "./context.js"; import { TrayStackRenderer } from "./TrayStackRenderer.js"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const defaultStackConfig = { backdropStyles: {}, trayStyles: {}, adjustForKeyboard: true, horizontalSpacing: 20, dismissOnBackdropPress: true }; /** * TrayProvider: Manages tray stacks, context, and rendering. * * @template T - The tray registry type. * @param trays - An object mapping tray keys to their components. * @param children - React children to render inside the provider. * @param stackConfigs - Optional per-stack configuration overrides. * * Provides context to manage multiple, optionally-configurable tray stacks and their lifecycle. */ export const TrayProvider = ({ trays, children, stackConfigs = {} }) => { const [stackMap, setStackMap] = useState({}); const modifyStack = useCallback((stackId, updater) => { setStackMap(prev => { const updated = updater(prev[stackId] || []); if (!updated || updated.length === 0) { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { [stackId]: _, ...rest } = prev; return rest; } return { ...prev, [stackId]: updated }; }); }, []); const push = useCallback((stackId, trayKey, props) => { modifyStack(stackId, stack => [...stack, { id: uuid.v4().toString(), tray: trayKey, stackId, props }]); }, [modifyStack]); const contextValue = useCallback(stackId => ({ push: (trayKey, props) => push(stackId, trayKey, props), pop: () => modifyStack(stackId, stack => stack.slice(0, -1)), replaceById: (trayId, props) => modifyStack(stackId, stack => stack.map(t => t.id === trayId ? { ...t, props } : t)), replace: (trayKey, props) => modifyStack(stackId, stack => stack.map(t => t.tray === trayKey ? { ...t, props } : t)), dismissById: trayId => modifyStack(stackId, stack => stack.filter(t => t.id !== trayId)), dismiss: trayKey => modifyStack(stackId, stack => stack.filter(t => t.tray !== trayKey)), dismissAll: () => setStackMap(prev => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { [stackId]: _, ...rest } = prev; return rest; }) }), [push, modifyStack]); const activeStacks = useMemo(() => Object.entries(stackMap), [stackMap]); return /*#__PURE__*/_jsxs(TrayContext.Provider, { value: contextValue, children: [children, activeStacks.map(([stackId, stack]) => /*#__PURE__*/_jsxs(React.Fragment, { children: [/*#__PURE__*/_jsx(Animated.View, { style: [styles.backdrop, stackConfigs[stackId]?.backdropStyles], entering: FadeIn, exiting: FadeOut, onTouchEnd: () => { contextValue(stackId).pop(); }, children: BlurView && !stackConfigs[stackId]?.disableBackgroundBlur ? /*#__PURE__*/_jsx(BlurView, { style: styles.blurView, ...(stackConfigs[stackId]?.blurViewProps ?? {}) }) : /*#__PURE__*/_jsx(View, { style: styles.blurViewPlaceholder }) }), /*#__PURE__*/_jsx(TrayStackRenderer, { stack: stack, config: stackConfigs[stackId] || defaultStackConfig, trays: trays })] }, stackId))] }); }; const styles = StyleSheet.create({ backdrop: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 998 }, blurView: { flex: 1 }, blurViewPlaceholder: { flex: 1 } }); //# sourceMappingURL=TrayProvider.js.map