UNPKG

@itwin/itwinui-react

Version:

A react component library for iTwinUI

112 lines (111 loc) 3.77 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true, }); Object.defineProperty(exports, 'ShadowRoot', { enumerable: true, get: function () { return ShadowRoot; }, }); 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 _index = require('../hooks/index.js'); const _index1 = require('../providers/index.js'); const isBrowser = 'undefined' != typeof document; const supportsDSD = isBrowser && 'shadowRootMode' in HTMLTemplateElement.prototype; const supportsAdoptedStylesheets = isBrowser && 'adoptedStyleSheets' in Document.prototype; const ShadowRoot = ({ children, css, flush = true }) => { let isHydrating = 'hydrating' === (0, _index1.useHydration)(); if (!isBrowser) return _react.createElement( 'template', { shadowrootmode: 'open', }, css && _react.createElement('style', null, css), children, ); if (supportsDSD && isHydrating) return null; return _react.createElement( ClientShadowRoot, { css: css, flush: flush, }, children, ); }; const ClientShadowRoot = ({ children, css, flush = true }) => { let templateRef = _react.useRef(null); let shadowRoot = useShadowRoot(templateRef, { css, flush, }); let fallbackCss = !supportsAdoptedStylesheets && css ? _react.createElement('style', null, css) : null; return shadowRoot ? _reactdom.createPortal( _react.createElement(_react.Fragment, null, fallbackCss, children), shadowRoot, ) : _react.createElement('template', { ref: templateRef, }); }; function useShadowRoot(templateRef, { css = '', flush = true }) { let [shadowRoot, setShadowRoot] = _react.useState(null); let styleSheet = _react.useRef(void 0); let latestCss = (0, _index.useLatestRef)(css); let latestShadowRoot = (0, _index.useLatestRef)(shadowRoot); let createStyleSheet = _react.useCallback( (shadow) => { if (shadow && supportsAdoptedStylesheets) { let currentWindow = shadow.ownerDocument.defaultView || globalThis; if (styleSheet.current instanceof currentWindow.CSSStyleSheet) return; styleSheet.current = new currentWindow.CSSStyleSheet(); shadow.adoptedStyleSheets.push(styleSheet.current); if (latestCss.current) styleSheet.current.replaceSync(latestCss.current); } }, [latestCss], ); (0, _index.useLayoutEffect)(() => { let parent = templateRef.current?.parentElement; if (!parent) return; let setupOrReuseShadowRoot = () => { if (parent.shadowRoot && null === latestShadowRoot.current) parent.shadowRoot.replaceChildren(); let shadow = parent.shadowRoot || parent.attachShadow({ mode: 'open', }); createStyleSheet(shadow); if (flush) _reactdom.flushSync(() => setShadowRoot(shadow)); else setShadowRoot(shadow); }; if (flush) queueMicrotask(() => setupOrReuseShadowRoot()); else setupOrReuseShadowRoot(); return () => void setShadowRoot(null); }, [templateRef, createStyleSheet, latestShadowRoot, flush]); (0, _index.useLayoutEffect)(() => { if (css && supportsAdoptedStylesheets) styleSheet.current?.replaceSync(css); }, [css]); _react.useEffect(() => { let listener = () => createStyleSheet(latestShadowRoot.current); window.addEventListener('appui:reparent', listener); return () => { window.removeEventListener('appui:reparent', listener); }; }, [createStyleSheet, latestShadowRoot]); return shadowRoot; }