terriajs
Version:
Geospatial data visualization platform.
125 lines • 5.77 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import PropTypes from "prop-types";
import createReactClass from "create-react-class";
import classNames from "classnames";
import defined from "terriajs-cesium/Source/Core/defined";
import { withTranslation } from "react-i18next";
import Styles from "./panel.scss";
import Icon from "../../../Styled/Icon";
const InnerPanel = createReactClass({
propTypes: {
/**
* A property that will be looked for on window click events - if it's set, the click event will not cause the
* panel to close.
*/
doNotCloseFlag: PropTypes.string,
/** Disable closing on loss of focus and only allow with close button */
disableCloseOnFocusLoss: PropTypes.bool,
/** Will be called when the panel has finished hiding */
onDismissed: PropTypes.func,
/** Animate as modal instead of dropdown */
showDropdownAsModal: PropTypes.bool,
/** show panel centered instead of offset toward the left */
showDropdownInCenter: PropTypes.bool,
/** Relative width to draw from */
modalWidth: PropTypes.number,
/** Theme to style components */
theme: PropTypes.object,
/** How far the caret at the top of the panel should be from its left, as CSS (so #px or #% are both valid) */
caretOffset: PropTypes.string,
/** Will be passed as "ref" to the outermost element */
innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
/** How far the dropdown should be offset from the left of the container. */
dropdownOffset: PropTypes.string,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.element),
PropTypes.element
]),
t: PropTypes.func.isRequired
},
getDefaultProps() {
return {
onDismissed: () => { }
};
},
getInitialState() {
return {};
},
componentDidMount() {
this.escKeyListener = (e) => {
if (e.keyCode === 27) {
this.close(e);
}
};
window.addEventListener("click", this.close);
window.addEventListener("keydown", this.escKeyListener, true);
setTimeout(() => this.setState({ isOpenCss: true }));
},
componentWillUnmount() {
this.cleanListeners();
},
cleanListeners() {
window.removeEventListener("click", this.close);
window.removeEventListener("keydown", this.escKeyListener, true);
},
forceClose() {
this.cleanListeners();
// If we're closing we want to immediately change the css class to cause it to animate shut, then when it's
// finished actually stop it rendering with isOpen = false
this.setState({
isOpenCss: false
});
setTimeout(() => {
this.props.onDismissed();
}, 200); // TODO: Determine when it stops animating instead of duplicating the 200ms timeout?
},
close(e) {
// Only close if this wasn't a click on an open/close button.
if ((!this.props.doNotCloseFlag || !e[this.props.doNotCloseFlag]) &&
!this.props.disableCloseOnFocusLoss) {
this.forceClose();
}
},
render() {
const { t } = this.props;
return (_jsxs("div", { className: classNames(
// Until we break these few components out of sass, we'll use regular ol classnames
"tjs-sc-InnerPanel", Styles.inner, this.props.theme.inner, { [Styles.isOpen]: this.state.isOpenCss }, { [Styles.showDropdownAsModal]: this.props.showDropdownAsModal }, { [Styles.showDropdownInCenter]: this.props.showDropdownInCenter }), css: `
background: ${(p) => p.theme.dark};
`, ref: this.props.innerRef, onClick: (e) => e.stopPropagation(), style: {
width: this.props.modalWidth,
left: this.props.dropdownOffset,
// the modal should be right-aligned with the button
right: "0px",
transformOrigin: this.props.showDropdownInCenter
? "0 top"
: this.props.caretOffset && `${this.props.caretOffset} top`
}, children: [_jsx("button", { type: "button", className: classNames(
// Until we break these few components out of sass, we'll use regular ol classnames
"tjs-sc-InnerPanelCloseButton", Styles.innerCloseBtn, {
[Styles.innerCloseBtnForModal]: this.props.showDropdownAsModal
}), onClick: this.forceClose, title: t("general.close"), "aria-label": t("general.close"),
// eslint-disable-next-line react/no-unknown-property
showDropdownAsModal: this.props.showDropdownAsModal, css: `
svg {
fill: ${(p) => p.theme.textLight};
}
&:hover,
&:focus {
svg {
fill: ${(p) => p.theme.colorPrimary};
}
}
${(p) => p.showDropdownAsModal &&
`
svg {
fill: ${p.theme.grey};
}
`}
`, children: _jsx(Icon, { glyph: Icon.GLYPHS.close }) }), defined(this.props.caretOffset) && !this.props.showDropdownAsModal && (_jsx("span", { className: classNames(Styles.caret, "tjs-sc-InnerPanel__caret"), style: { left: this.props.caretOffset }, css: `
background: ${(p) => p.theme.dark};
` })), _jsx("div", { className: Styles.content, children: this.props.children })] }));
}
});
export default withTranslation()(InnerPanel);
//# sourceMappingURL=InnerPanel.js.map