rsuite
Version:
A suite of react components
86 lines (83 loc) • 2.85 kB
JavaScript
'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
}))));
}