reblend-ui
Version:
Utilities for creating robust overlay components
140 lines (137 loc) • 4.93 kB
JavaScript
"use strict";
exports.__esModule = true;
exports.default = void 0;
var _reblendjs = require("reblendjs");
var Reblend = _reblendjs;
var _reblendHooks = require("reblend-hooks");
var _usePopper = require("./usePopper");
var _useRootClose = require("./useRootClose");
var _useWaitForDOMRef = require("./useWaitForDOMRef");
var _mergeOptionsWithPopperConfig = require("./mergeOptionsWithPopperConfig");
var _ImperativeTransition = require("./ImperativeTransition");
/**
* Built on top of `Popper.js`, the overlay component is
* great for custom tooltip overlays.
*/
const Overlay = class
/* @Reblend: Transformed from function to class */
extends Reblend.Reblend {
static ELEMENT_NAME = "Overlay";
constructor() {
super();
}
async initState() {
const {
flip,
offset,
placement,
containerPadding,
popperConfig = {},
transition: Transition,
runTransition
} = this.props;
this.state.flip = flip;
this.state.offset = offset;
this.state.placement = placement;
this.state.containerPadding = containerPadding;
this.state.popperConfig = popperConfig;
this.state.Transition = Transition;
this.state.runTransition = runTransition;
const [rootElement, attachRef] = _reblendHooks.useCallbackRef.bind(this)();
this.state.rootElement = rootElement;
this.state.attachRef = attachRef;
const [arrowElement, attachArrowRef] = _reblendHooks.useCallbackRef.bind(this)();
this.state.arrowElement = arrowElement;
this.state.attachArrowRef = attachArrowRef;
const mergedRef = _reblendHooks.useMergedRefs.bind(this)(this.state.attachRef, this.props.outerRef);
this.state.mergedRef = mergedRef;
const container = _useWaitForDOMRef.default.bind(this)(this.props.container);
this.state.container = container;
const target = _useWaitForDOMRef.default.bind(this)(this.props.target);
this.state.target = target;
const [exited, setExited] = _reblendjs.useState.bind(this)(!this.props.show, "exited");
this.state.exited = exited;
this.state.setExited = setExited;
const popper = _usePopper.default.bind(this)(this.state.target, this.state.rootElement, (0, _mergeOptionsWithPopperConfig.default)({
placement: this.state.placement,
enableEvents: !!this.props.show,
containerPadding: this.state.containerPadding || 5,
flip: this.state.flip,
offset: this.state.offset,
arrowElement: this.state.arrowElement,
popperConfig: this.state.popperConfig
}));
// TODO: I think this needs to be in an effect
this.state.popper = popper;
if (this.props.show && this.state.exited) {
this.state.setExited(false);
}
const handleHidden = (...args) => {
this.state.setExited(true);
if (this.props.onExited) {
this.props.onExited(...args);
}
};
// Don't un-render the overlay while it's transitioning out.
this.state.handleHidden = handleHidden;
const mountOverlay = this.props.show || !this.state.exited;
this.state.mountOverlay = mountOverlay;
_useRootClose.default.bind(this)(this.state.rootElement, this.props.onHide, {
disabled: !this.props.rootClose || this.props.rootCloseDisabled,
clickTrigger: this.props.rootCloseEvent
});
if (!this.state.mountOverlay) {
// Don't bother showing anything if we don't have to.
return null;
}
const {
onExit,
onExiting,
onEnter,
onEntering,
onEntered
} = this.props;
this.state.onExit = onExit;
this.state.onExiting = onExiting;
this.state.onEnter = onEnter;
this.state.onEntering = onEntering;
this.state.onEntered = onEntered;
let child = this.props.children({
...this.state.popper.attributes.popper,
style: this.state.popper.styles.popper,
ref: this.state.mergedRef
}, {
popper: this.state.popper,
placement: this.state.placement,
show: !!this.props.show,
arrowProps: {
...this.state.popper.attributes.arrow,
style: this.state.popper.styles.arrow,
ref: this.state.attachArrowRef
}
});
this.state.child = child;
this.state.child = (0, _ImperativeTransition.renderTransition)(this.state.Transition, this.state.runTransition, {
in: !!this.props.show,
appear: true,
mountOnEnter: true,
unmountOnExit: true,
children: this.state.child,
onExit: this.state.onExit,
onExiting: this.state.onExiting,
onExited: this.state.handleHidden,
onEnter: this.state.onEnter,
onEntering: this.state.onEntering,
onEntered: this.state.onEntered
});
}
async initProps(props) {
this.props = {};
this.props = props;
}
async html() {
return this.state.container ? Reblend.createPortal(this.state.child, this.state.container) : null;
}
};
Overlay.displayName = 'Overlay';
var _default = exports.default = Overlay;