UNPKG

@fluentui/react-northstar

Version:
217 lines (212 loc) 8.57 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _noop from "lodash/noop"; import _isBoolean from "lodash/isBoolean"; import _isFunction from "lodash/isFunction"; import _forEach from "lodash/forEach"; import _isPlainObject from "lodash/isPlainObject"; import { defaultContextValue, getElementType, useUnhandledProps, RendererContext, Telemetry, useFluentContext, unstable_getStyles, useIsomorphicLayoutEffect, Unstable_FluentContextProvider } from '@fluentui/react-bindings'; import { mergeSiteVariables } from '@fluentui/styles'; import * as PropTypes from 'prop-types'; import * as React from 'react'; import { setUpWhatInput, tryCleanupWhatInput } from '../../utils'; import { mergeProviderContexts } from '../../utils/mergeProviderContexts'; import { ProviderConsumer } from './ProviderConsumer'; import { PortalContext } from './portalContext'; var renderFontFaces = function renderFontFaces(renderer, theme) { if (!theme.fontFaces) { return; } var renderFontObject = function renderFontObject(font) { if (!_isPlainObject(font)) { throw new Error("fontFaces must be objects, got: " + typeof font); } renderer.renderFont(font); }; theme.fontFaces.forEach(function (font) { renderFontObject(font); }); }; var renderStaticStyles = function renderStaticStyles(renderer, theme, siteVariables) { if (!theme.staticStyles) { return; } var renderObject = function renderObject(object) { _forEach(object, function (style, selector) { renderer.renderGlobal(style, selector); }); }; theme.staticStyles.forEach(function (staticStyle) { if (typeof staticStyle === 'string') { renderer.renderGlobal(staticStyle); } else if (_isPlainObject(staticStyle)) { renderObject(staticStyle); } else if (_isFunction(staticStyle)) { var preparedSiteVariables = mergeSiteVariables(undefined, siteVariables); renderObject(staticStyle(preparedSiteVariables)); } else { throw new Error("staticStyles array must contain CSS strings, style objects, or style functions, got: " + typeof staticStyle); } }); }; export var providerClassName = 'ui-provider'; /** * The Provider passes the CSS-in-JS renderer, theme styles and other settings to Fluent UI components. */ export var Provider = /*#__PURE__*/function () { var Provider = function Provider(props) { var children = props.children, className = props.className, design = props.design, overwrite = props.overwrite, styles = props.styles, variables = props.variables, telemetryRef = props.telemetryRef; var ElementType = getElementType(props); var unhandledProps = useUnhandledProps(Provider.handledProps, props); var rendersReactFragment = ElementType === React.Fragment; var telemetry = React.useMemo(function () { if (!telemetryRef) { return undefined; } if (!telemetryRef.current) { telemetryRef.current = new Telemetry(); } return telemetryRef.current; }, [telemetryRef]); var consumedContext = useFluentContext(); var incomingContext = overwrite ? defaultContextValue : consumedContext; var createRenderer = React.useContext(RendererContext); // Memoization of `inputContext` & `outgoingContext` is required to avoid useless notifications of components that // consume `useFluentContext()` on each render // @see https://reactjs.org/docs/context.html#caveats var inputContext = React.useMemo(function () { return { disableAnimations: props.disableAnimations, performance: props.performance, rtl: props.rtl, target: props.target, telemetry: telemetry, theme: props.theme }; }, [props.disableAnimations, props.performance, props.rtl, props.target, telemetry, props.theme]); var outgoingContext = React.useMemo(function () { return mergeProviderContexts(createRenderer, incomingContext, inputContext); }, [createRenderer, incomingContext, inputContext]); var rtlProps = {}; // only add dir attribute for top level provider or when direction changes from parent to child if (consumedContext.rtl !== outgoingContext.rtl && _isBoolean(outgoingContext.rtl)) { rtlProps.dir = outgoingContext.rtl ? 'rtl' : 'ltr'; } // Perf optimisation // Do not invoke styling layer is there is no need var _ref = rendersReactFragment ? { classes: { root: '' } } : unstable_getStyles({ allDisplayNames: [Provider.displayName], className: providerClassName, primaryDisplayName: Provider.displayName, componentProps: {}, inlineStylesProps: { className: className, design: design, styles: styles, variables: variables }, disableAnimations: outgoingContext.disableAnimations, performance: outgoingContext.performance, renderer: outgoingContext.renderer, rtl: outgoingContext.rtl, theme: outgoingContext.theme, saveDebug: _noop, telemetry: undefined }), classes = _ref.classes; var portalContextValue = React.useMemo(function () { return { className: classes.root }; }, [classes.root]); var RenderProvider = outgoingContext.renderer.Provider; useIsomorphicLayoutEffect(function () { renderFontFaces(outgoingContext.renderer, props.theme); renderStaticStyles(outgoingContext.renderer, props.theme, outgoingContext.theme.siteVariables); if (props.target) { setUpWhatInput(props.target); } outgoingContext.renderer.registerUsage(); return function () { if (props.target) { tryCleanupWhatInput(props.target); } outgoingContext.renderer.unregisterUsage(); }; }, []); // If a Fragment is rendered: // - do not spread anything to an element - React.Fragment can only have `key` and `children` props // - as we don't apply styles "PortalContext.Provider" should not be rendered if (rendersReactFragment) { return /*#__PURE__*/React.createElement(RenderProvider, { target: outgoingContext.target }, /*#__PURE__*/React.createElement(Unstable_FluentContextProvider, { value: outgoingContext }, /*#__PURE__*/React.createElement(React.Fragment, null, children))); } return /*#__PURE__*/React.createElement(RenderProvider, { target: outgoingContext.target }, /*#__PURE__*/React.createElement(Unstable_FluentContextProvider, { value: outgoingContext }, /*#__PURE__*/React.createElement(PortalContext.Provider, { value: portalContextValue }, /*#__PURE__*/React.createElement(ElementType, _extends({ className: classes.root }, rtlProps, unhandledProps), children)))); }; Provider.displayName = 'Provider'; Provider.defaultProps = { theme: {} }; Provider.propTypes = { as: PropTypes.elementType, design: PropTypes.object, variables: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), styles: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), theme: PropTypes.shape({ siteVariables: PropTypes.object, componentVariables: PropTypes.object, componentStyles: PropTypes.objectOf(PropTypes.any), fontFaces: PropTypes.arrayOf(PropTypes.exact({ name: PropTypes.string.isRequired, paths: PropTypes.arrayOf(PropTypes.string), props: PropTypes.shape({ fontStretch: PropTypes.string, fontStyle: PropTypes.string, fontVariant: PropTypes.string, fontWeight: PropTypes.number, localAlias: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), unicodeRange: PropTypes.string }) })), staticStyles: PropTypes.array, animations: PropTypes.objectOf(PropTypes.any) }), rtl: PropTypes.bool, disableAnimations: PropTypes.bool, // Heads Up! // Keep in sync with packages/react-bindings/src/styles/types.ts performance: PropTypes.shape({ enableSanitizeCssPlugin: PropTypes.bool, enableStylesCaching: PropTypes.bool, enableVariablesCaching: PropTypes.bool }), children: PropTypes.node.isRequired, overwrite: PropTypes.bool, target: PropTypes.object, telemetryRef: PropTypes.object }; Provider.handledProps = Object.keys(Provider.propTypes); Provider.Consumer = ProviderConsumer; return Provider; }(); //# sourceMappingURL=Provider.js.map