UNPKG

@itwin/itwinui-react

Version:

A react component library for iTwinUI

339 lines (338 loc) 11.3 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true, }); Object.defineProperty(exports, 'ThemeProvider', { enumerable: true, get: function () { return ThemeProvider; }, }); const _interop_require_default = require('@swc/helpers/_/_interop_require_default'); const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard'); const _react = /*#__PURE__*/ _interop_require_wildcard._(require('react')); const _reactdom = /*#__PURE__*/ _interop_require_wildcard._( require('react-dom'), ); const _classnames = /*#__PURE__*/ _interop_require_default._( require('classnames'), ); const _index = require('../../utils/index.js'); const _ThemeContext = require('./ThemeContext.js'); const _Toaster = require('../Toast/Toaster.js'); const _meta = require('../../utils/meta.js'); const versionWithoutDots = _meta.meta.version.replace(/\./g, ''); const OwnerDocumentContext = _react.createContext(void 0); const ThemeProvider = _react.forwardRef((props, forwardedRef) => { var _themeOptions, _themeOptions1; let { theme: themeProp = 'inherit', children, themeOptions = {}, portalContainer: portalContainerProp, includeCss = 'inherit' === themeProp, future: futureProp = {}, ...rest } = props; useInertPolyfill(); let [rootElement, setRootElement] = _react.useState(null); let parent = useParentThemeAndContext(rootElement); let theme = 'inherit' === themeProp ? parent.theme || 'light' : themeProp; (_themeOptions = themeOptions).applyBackground ?? (_themeOptions.applyBackground = !parent.theme); (_themeOptions1 = themeOptions).highContrast ?? (_themeOptions1.highContrast = 'inherit' === themeProp ? parent.highContrast : void 0); let portalContainerFromParent = _react.useContext( _index.PortalContainerContext, ); let themeContextValue = _react.useMemo( () => ({ theme, themeOptions, }), [theme, JSON.stringify(themeOptions)], ); let [portalContainer, setPortalContainer] = _react.useState( portalContainerProp || null, ); return _react.createElement( _index.FutureFlagsProvider, { value: futureProp, }, _react.createElement( _index.PortalContainerContext.Provider, { value: portalContainer, }, _react.createElement( _index.HydrationProvider, null, _react.createElement( _ThemeContext.ThemeContext.Provider, { value: themeContextValue, }, _react.createElement( _Toaster.ToastProvider, { inherit: 'inherit' === themeProp && !portalContainerProp, }, includeCss && rootElement ? _react.createElement(FallbackStyles, { root: rootElement, }) : null, _react.createElement( MainRoot, { theme: theme, themeOptions: themeOptions, ref: (0, _index.useMergedRefs)( forwardedRef, setRootElement, useIuiDebugRef, ), ...rest, }, children, _react.createElement(PortalContainer, { theme: theme, themeOptions: themeOptions, portalContainerProp: portalContainerProp, portalContainerFromParent: portalContainerFromParent, setPortalContainer: setPortalContainer, isInheritingTheme: 'inherit' === themeProp, }), ), ), ), ), ), ); }); if ('development' === process.env.NODE_ENV) ThemeProvider.displayName = 'ThemeProvider'; const MainRoot = _react.forwardRef((props, forwardedRef) => { let [ownerDocument, setOwnerDocument] = _react.useState(void 0); let findOwnerDocumentFromRef = _react.useCallback( (el) => { if (el && el.ownerDocument !== ownerDocument) setOwnerDocument(el.ownerDocument); }, [ownerDocument, setOwnerDocument], ); return _react.createElement( OwnerDocumentContext.Provider, { value: ownerDocument, }, _react.createElement(Root, { ...props, ref: (0, _index.useMergedRefs)(findOwnerDocumentFromRef, forwardedRef), }), ); }); const Root = _react.forwardRef((props, forwardedRef) => { let { theme, children, themeOptions, className, ...rest } = props; let prefersDark = (0, _index.useMediaQuery)('(prefers-color-scheme: dark)'); let prefersHighContrast = (0, _index.useMediaQuery)( '(prefers-contrast: more)', ); let shouldApplyDark = 'dark' === theme || ('os' === theme && prefersDark); let shouldApplyHC = themeOptions?.highContrast ?? prefersHighContrast; let shouldApplyBackground = themeOptions?.applyBackground; let themeBridge = (0, _index.useFutureFlag)('themeBridge'); return _react.createElement( _index.Box, { className: (0, _classnames.default)( 'iui-root', { 'iui-root-background': shouldApplyBackground, }, className, ), 'data-iui-theme': shouldApplyDark ? 'dark' : 'light', 'data-iui-contrast': shouldApplyHC ? 'high' : 'default', 'data-iui-bridge': themeBridge ? 'true' : void 0, ref: forwardedRef, ...rest, }, children, ); }); const useParentThemeAndContext = (rootElement) => { let parentContext = _react.useContext(_ThemeContext.ThemeContext); let [parentThemeState, setParentTheme] = _react.useState( parentContext?.theme, ); let [parentHighContrastState, setParentHighContrastState] = _react.useState( parentContext?.themeOptions?.highContrast, ); let parentThemeRef = (0, _index.useLatestRef)(parentContext?.theme); (0, _index.useLayoutEffect)(() => { if (parentThemeRef.current) return; let closestRoot = rootElement?.parentElement?.closest('[data-iui-theme]'); if (!closestRoot) return; let synchronizeTheme = () => { setParentTheme(closestRoot?.getAttribute('data-iui-theme')); setParentHighContrastState( closestRoot?.getAttribute('data-iui-contrast') === 'high', ); }; synchronizeTheme(); let observer = new MutationObserver(() => synchronizeTheme()); observer.observe(closestRoot, { attributes: true, attributeFilter: ['data-iui-theme', 'data-iui-contrast'], }); return () => { observer.disconnect(); }; }, [rootElement, parentThemeRef]); return { theme: parentContext?.theme ?? parentThemeState, highContrast: parentContext?.themeOptions?.highContrast ?? parentHighContrastState, context: parentContext, }; }; const PortalContainer = _react.memo( ({ portalContainerProp, portalContainerFromParent, setPortalContainer, isInheritingTheme, theme, themeOptions, }) => { let ownerDocument = _react.useContext(OwnerDocumentContext); let shouldSetupPortalContainer = !portalContainerProp && (!isInheritingTheme || !portalContainerFromParent || (!!ownerDocument && portalContainerFromParent.ownerDocument !== ownerDocument)); let id = (0, _index.useId)(); _react.useEffect(() => { if (shouldSetupPortalContainer) return; let portalTarget = portalContainerProp || portalContainerFromParent; if (portalTarget) setPortalContainer(portalTarget); }, [ portalContainerProp, portalContainerFromParent, shouldSetupPortalContainer, setPortalContainer, ]); let isHydrated = 'hydrated' === (0, _index.useHydration)(); if (!isHydrated) return null; if (shouldSetupPortalContainer && ownerDocument) return _reactdom.createPortal( _react.createElement( Root, { theme: theme, themeOptions: { ...themeOptions, applyBackground: false, }, 'data-iui-portal': true, style: { display: 'contents', }, ref: setPortalContainer, id: id, }, _react.createElement(_Toaster.Toaster, null), ), ownerDocument.body, ); if (portalContainerProp) return _reactdom.createPortal( _react.createElement(_Toaster.Toaster, null), portalContainerProp, ); return null; }, ); const FallbackStyles = ({ root }) => { (0, _index.useLayoutEffect)(() => { if ( 'yes' === getComputedStyle(root).getPropertyValue(`--_iui-v${versionWithoutDots}`) ) return; if (_index.isUnitTest) return; (async () => { try { await Promise.resolve().then(() => /*#__PURE__*/ _interop_require_wildcard._( require('../../../styles.css'), ), ); } catch (error) { console.log('Error loading styles.css locally', error); let css = await (0, _index.importCss)( `https://cdn.jsdelivr.net/npm/@itwin/itwinui-react@${_meta.meta.version}/styles.css`, ); document.adoptedStyleSheets = [ ...document.adoptedStyleSheets, css.default, ]; } })(); }, [root]); return _react.createElement(_react.Fragment, null); }; const useIuiDebugRef = () => { var _globalThis; let _globalThis1 = globalThis; (_globalThis = _globalThis1).__iui || (_globalThis.__iui = { versions: new Set(), }); if ('development' === process.env.NODE_ENV && !_index.isUnitTest) _globalThis1.__iui.versions.add = (version) => { Set.prototype.add.call(_globalThis1.__iui.versions, version); if (_globalThis1.__iui.versions.size > 1) { _globalThis1.__iui._shouldWarn = true; if (_globalThis1.__iui._warnTimeout) clearTimeout(_globalThis1.__iui._warnTimeout); _globalThis1.__iui._warnTimeout = setTimeout(() => { if (_globalThis1.__iui._shouldWarn) { console.warn( "Multiple versions of iTwinUI were detected on this page. This can lead to unexpected behavior and duplicated code in the bundle. Make sure you're using a single iTwinUI instance across your app. https://github.com/iTwin/iTwinUI/wiki/Version-conflicts", ); console.groupCollapsed('iTwinUI versions detected:'); let versionsTable = []; _globalThis1.__iui.versions.forEach((version) => { versionsTable.push(JSON.parse(version)); }); console.table(versionsTable); console.groupEnd(); _globalThis1.__iui._shouldWarn = false; } }, 3000); } }; _globalThis1.__iui.versions.add(JSON.stringify(_meta.meta)); }; const useInertPolyfill = () => { let loaded = _react.useRef(false); let modulePath = 'https://cdn.jsdelivr.net/npm/wicg-inert@3.1.2/dist/inert.min.js'; _react.useEffect(() => { (async () => { if ( !HTMLElement.prototype.hasOwnProperty('inert') && !loaded.current && !_index.isUnitTest ) { await new Function('url', 'return import(url)')(modulePath); loaded.current = true; } })(); }, []); };