@blueprintjs/core
Version:
Core styles & components
113 lines • 4.9 kB
JavaScript
"use strict";
/*
* Copyright 2015 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var React = tslib_1.__importStar(require("react"));
var ReactDOM = tslib_1.__importStar(require("react-dom"));
var Classes = tslib_1.__importStar(require("../../common/classes"));
var Errors = tslib_1.__importStar(require("../../common/errors"));
var props_1 = require("../../common/props");
var utils_1 = require("../../common/utils");
/** Detect if `React.createPortal()` API method does not exist. */
var cannotCreatePortal = !utils_1.isFunction(ReactDOM.createPortal);
var REACT_CONTEXT_TYPES = {
blueprintPortalClassName: function (obj, key) {
if (obj[key] != null && typeof obj[key] !== "string") {
return new Error(Errors.PORTAL_CONTEXT_CLASS_NAME_STRING);
}
return undefined;
},
};
/**
* This component detaches its contents and re-attaches them to document.body.
* Use it when you need to circumvent DOM z-stacking (for dialogs, popovers, etc.).
* Any class names passed to this element will be propagated to the new container element on document.body.
*/
var Portal = /** @class */ (function (_super) {
tslib_1.__extends(Portal, _super);
function Portal() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.state = { hasMounted: false };
return _this;
}
Portal.prototype.render = function () {
// Only render `children` once this component has mounted in a browser environment, so they are
// immediately attached to the DOM tree and can do DOM things like measuring or `autoFocus`.
// See long comment on componentDidMount in https://reactjs.org/docs/portals.html#event-bubbling-through-portals
if (cannotCreatePortal || typeof document === "undefined" || !this.state.hasMounted) {
return null;
}
else {
return ReactDOM.createPortal(this.props.children, this.portalElement);
}
};
Portal.prototype.componentDidMount = function () {
if (!this.props.container) {
return;
}
this.portalElement = this.createContainerElement();
this.props.container.appendChild(this.portalElement);
this.setState({ hasMounted: true }, this.props.onChildrenMount);
if (cannotCreatePortal) {
this.unstableRenderNoPortal();
}
};
Portal.prototype.componentDidUpdate = function (prevProps) {
// update className prop on portal DOM element
if (this.portalElement != null && prevProps.className !== this.props.className) {
this.portalElement.classList.remove(prevProps.className);
maybeAddClass(this.portalElement.classList, this.props.className);
}
if (cannotCreatePortal) {
this.unstableRenderNoPortal();
}
};
Portal.prototype.componentWillUnmount = function () {
if (this.portalElement != null) {
if (cannotCreatePortal) {
ReactDOM.unmountComponentAtNode(this.portalElement);
}
this.portalElement.remove();
}
};
Portal.prototype.createContainerElement = function () {
var container = document.createElement("div");
container.classList.add(Classes.PORTAL);
maybeAddClass(container.classList, this.props.className);
if (this.context != null) {
maybeAddClass(container.classList, this.context.blueprintPortalClassName);
}
return container;
};
Portal.prototype.unstableRenderNoPortal = function () {
ReactDOM.unstable_renderSubtreeIntoContainer(
/* parentComponent */ this, React.createElement("div", null, this.props.children), this.portalElement);
};
Portal.displayName = props_1.DISPLAYNAME_PREFIX + ".Portal";
Portal.contextTypes = REACT_CONTEXT_TYPES;
Portal.defaultProps = {
container: typeof document !== "undefined" ? document.body : null,
};
return Portal;
}(React.Component));
exports.Portal = Portal;
function maybeAddClass(classList, className) {
if (className != null && className !== "") {
classList.add.apply(classList, className.split(" "));
}
}
//# sourceMappingURL=portal.js.map