@itwin/itwinui-react
Version:
A react component library for iTwinUI
112 lines (111 loc) • 3.77 kB
JavaScript
;
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;
}