UNPKG

rsuite

Version:

A suite of react components

86 lines (83 loc) 2.85 kB
'use client'; import React, { useRef, useMemo } from 'react'; import IconProvider from '@rsuite/icons/IconProvider'; import { usePortal, useIsomorphicLayoutEffect } from "../internals/hooks/index.js"; import { getClassNamePrefix, prefix } from "../internals/utils/index.js"; import { addClass, removeClass, canUseDOM } from "../DOMHelper/index.js"; import { CustomContext } from "../internals/Provider/CustomContext.js"; import ToastContainer, { toastPlacements, defaultToasterContainer } from "../toaster/ToastContainer.js"; import DialogContainer from "../useDialog/DialogContainer.js"; const themes = ['light', 'dark', 'high-contrast']; /** * CustomProvider is used to provide global configuration, such as language, theme, etc. * * @see https://rsuitejs.com/components/custom-provider */ export default function CustomProvider(props) { const { children, classPrefix = getClassNamePrefix(), components, iconClassPrefix = classPrefix, theme, toastContainer = defaultToasterContainer, disableRipple, csp, disableInlineStyles, ...rest } = props; const toasters = useRef(new Map()); // This creates a ref that matches the expected type in CustomContext const dialogContainerRef = useRef(null); const { Portal } = usePortal({ container: toastContainer, waitMount: true }); const value = useMemo(() => ({ classPrefix, theme, toasters, disableRipple, components, toastContainer, ...rest }), [classPrefix, theme, disableRipple, components, toastContainer, rest]); const iconContext = useMemo(() => ({ classPrefix: iconClassPrefix, csp, disableInlineStyles }), [iconClassPrefix, csp, disableInlineStyles]); useIsomorphicLayoutEffect(() => { if (canUseDOM && theme) { addClass(document.body, prefix(classPrefix, `theme-${theme}`)); // Remove the className that will cause style conflicts themes.forEach(t => { if (t !== theme) { removeClass(document.body, prefix(classPrefix, `theme-${t}`)); } }); } }, [classPrefix, theme]); // Create a context value with proper types const contextValue = { dialogContainer: dialogContainerRef, ...value }; return /*#__PURE__*/React.createElement(CustomContext.Provider, { value: contextValue }, /*#__PURE__*/React.createElement(IconProvider, { value: iconContext }, children, /*#__PURE__*/React.createElement(Portal, null, /*#__PURE__*/React.createElement("div", { className: `${classPrefix}toast-provider` }, toastPlacements.map(placement => /*#__PURE__*/React.createElement(ToastContainer, { key: placement, placement: placement, ref: ref => { toasters.current.set(placement, ref); } }))), /*#__PURE__*/React.createElement(DialogContainer, { ref: dialogContainerRef })))); }