UNPKG

@fluentui/react

Version:

Reusable React components for building web experiences.

167 lines (166 loc) 8.43 kB
define(["require", "exports", "tslib", "@fluentui/react-portal-compat-context", "react", "react-dom", "../../Fabric", "../../Utilities", "./Layer.notification", "@fluentui/react-hooks"], function (require, exports, tslib_1, react_portal_compat_context_1, React, ReactDOM, Fabric_1, Utilities_1, Layer_notification_1, react_hooks_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LayerBase = void 0; var getClassNames = Utilities_1.classNamesFunction(); exports.LayerBase = React.forwardRef(function (props, ref) { var registerPortalEl = react_portal_compat_context_1.usePortalCompat(); var rootRef = React.useRef(null); var mergedRef = react_hooks_1.useMergedRefs(rootRef, ref); var layerRef = React.useRef(); var fabricElementRef = React.useRef(null); // Tracks if the layer mount events need to be raised. // Required to allow the DOM to render after the layer element is added. var _a = React.useState(false), needRaiseLayerMount = _a[0], setNeedRaiseLayerMount = _a[1]; var children = props.children, className = props.className, eventBubblingEnabled = props.eventBubblingEnabled, fabricProps = props.fabricProps, hostId = props.hostId, insertFirst = props.insertFirst, _b = props.onLayerDidMount, onLayerDidMount = _b === void 0 ? function () { return undefined; } : _b, // eslint-disable-next-line deprecation/deprecation _c = props.onLayerMounted, // eslint-disable-next-line deprecation/deprecation onLayerMounted = _c === void 0 ? function () { return undefined; } : _c, onLayerWillUnmount = props.onLayerWillUnmount, styles = props.styles, theme = props.theme; var fabricRef = react_hooks_1.useMergedRefs(fabricElementRef, fabricProps === null || fabricProps === void 0 ? void 0 : fabricProps.ref); var classNames = getClassNames(styles, { theme: theme, className: className, isNotHost: !hostId, }); // Returns the user provided hostId props element, the default target selector, // or undefined if document doesn't exist. var getHost = function (doc) { var _a, _b; if (hostId) { var layerHost = Layer_notification_1.getLayerHost(hostId); if (layerHost) { return (_a = layerHost.rootRef.current) !== null && _a !== void 0 ? _a : null; } return (_b = doc.getElementById(hostId)) !== null && _b !== void 0 ? _b : null; } else { var defaultHostSelector = Layer_notification_1.getDefaultTarget(); // Find the host. var host = defaultHostSelector ? doc.querySelector(defaultHostSelector) : null; // If no host is available, create a container for injecting layers in. // Having a container scopes layout computation. if (!host) { host = Layer_notification_1.createDefaultLayerHost(doc); } return host; } }; // Removes the current layer element's parentNode and runs onLayerWillUnmount prop if provided. var removeLayerElement = function () { onLayerWillUnmount === null || onLayerWillUnmount === void 0 ? void 0 : onLayerWillUnmount(); var elem = layerRef.current; // Clear ref before removing from the DOM layerRef.current = undefined; if (elem && elem.parentNode) { elem.parentNode.removeChild(elem); } }; // If a doc or host exists, it will remove and update layer parentNodes. var createLayerElement = function () { var _a; var doc = Utilities_1.getDocument(rootRef.current); if (!doc) { return; } var host = getHost(doc); if (!host) { return; } // Remove and re-create any previous existing layer elements. removeLayerElement(); var el = ((_a = host.ownerDocument) !== null && _a !== void 0 ? _a : doc).createElement('div'); el.className = classNames.root; Utilities_1.setPortalAttribute(el); Utilities_1.setVirtualParent(el, rootRef.current); insertFirst ? host.insertBefore(el, host.firstChild) : host.appendChild(el); layerRef.current = el; setNeedRaiseLayerMount(true); }; react_hooks_1.useIsomorphicLayoutEffect(function () { createLayerElement(); // Check if the user provided a hostId prop and register the layer with the ID. if (hostId) { Layer_notification_1.registerLayer(hostId, createLayerElement); } var unregisterPortalEl = layerRef.current ? registerPortalEl(layerRef.current) : undefined; return function () { if (unregisterPortalEl) { unregisterPortalEl(); } removeLayerElement(); if (hostId) { Layer_notification_1.unregisterLayer(hostId, createLayerElement); } }; // eslint-disable-next-line react-hooks/exhaustive-deps -- should run if the hostId updates. }, [hostId]); React.useEffect(function () { if (layerRef.current && needRaiseLayerMount) { onLayerMounted === null || onLayerMounted === void 0 ? void 0 : onLayerMounted(); onLayerDidMount === null || onLayerDidMount === void 0 ? void 0 : onLayerDidMount(); setNeedRaiseLayerMount(false); } }, [needRaiseLayerMount, onLayerMounted, onLayerDidMount]); useDebugWarnings(props); return (React.createElement("span", { className: "ms-layer", ref: mergedRef }, layerRef.current && ReactDOM.createPortal(React.createElement(Utilities_1.FocusRectsProvider, { layerRoot: true, providerRef: fabricRef }, React.createElement(Fabric_1.Fabric, tslib_1.__assign({}, (!eventBubblingEnabled && getFilteredEvents()), fabricProps, { className: Utilities_1.css(classNames.content, fabricProps === null || fabricProps === void 0 ? void 0 : fabricProps.className), ref: fabricRef }), children)), layerRef.current))); }); exports.LayerBase.displayName = 'LayerBase'; var filteredEventProps; var onFilterEvent = function (ev) { // We should just be able to check ev.bubble here and only stop events that are bubbling up. However, even though // mouseenter and mouseleave do NOT bubble up, they are showing up as bubbling. Therefore we stop events based on // event name rather than ev.bubble. if (ev.eventPhase === Event.BUBBLING_PHASE && ev.type !== 'mouseenter' && ev.type !== 'mouseleave' && ev.type !== 'touchstart' && ev.type !== 'touchend') { ev.stopPropagation(); } }; function getFilteredEvents() { if (!filteredEventProps) { filteredEventProps = {}; [ 'onClick', 'onContextMenu', 'onDoubleClick', 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave', 'onDragOver', 'onDragStart', 'onDrop', 'onMouseDown', 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseOver', 'onMouseOut', 'onMouseUp', 'onTouchMove', 'onTouchStart', 'onTouchCancel', 'onTouchEnd', 'onKeyDown', 'onKeyPress', 'onKeyUp', 'onFocus', 'onBlur', 'onChange', 'onInput', 'onInvalid', 'onSubmit', ].forEach(function (name) { return (filteredEventProps[name] = onFilterEvent); }); } return filteredEventProps; } function useDebugWarnings(props) { } }); //# sourceMappingURL=Layer.base.js.map