backpack-ui
Version:
Lonely Planet's Components
243 lines (199 loc) • 5.85 kB
JSX
import React from "react";
import radium from "radium";
import ReactDOM from "react-dom";
import styles from "./styles";
import IconButton from "../iconButton";
import Flyout from "../flyout";
import ShareMenuItem from "./item";
class ShareMenu extends React.Component {
static calculateWindowPosition(windowDimension, popUpDimension) {
return Math.round((windowDimension / 2) - (popUpDimension / 2));
}
static windowSettings() {
const windowSettings = {
popUpWidth: 840,
popUpHeight: 420,
popUpLeft: 0,
popUpTop: 0,
height: window.innerHeight,
width: window.innerWidth,
};
windowSettings.popUpLeft = ShareMenu.calculateWindowPosition(
windowSettings.width,
windowSettings.popUpWidth
);
windowSettings.popUpTop = windowSettings.height > windowSettings.popUpHeight
? ShareMenu.calculateWindowPosition(
windowSettings.height,
windowSettings.popUpHeight
) : 0;
windowSettings.windowOptions = "toolbar=no,"
+ "menubar=no,"
+ "location=yes,"
+ "resizable=no,"
+ "scrollbars=yes";
windowSettings.windowSize = `width=${windowSettings.popUpWidth},`
+ `height=${windowSettings.popUpHeight},`
+ `top=${windowSettings.popUpTop},`
+ `left=${windowSettings.popUpLeft}`;
return windowSettings;
}
static openWindow(event) {
const { windowOptions, windowSize } = ShareMenu.windowSettings();
if (event.currentTarget.dataset.network !== "email") {
window.open(
event.currentTarget.href,
"share",
`${windowOptions},${windowSize}`
);
}
event.preventDefault();
}
constructor() {
super();
this.state = {
optionsHidden: true,
};
this.toggleOptions = this.toggleOptions.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
this.handleKeydown = this.handleKeydown.bind(this);
this.shareContent = this.shareContent.bind(this);
this.shareUrl = this.shareUrl.bind(this);
}
componentDidMount() {
document.addEventListener("click", this.handleClickOutside);
document.addEventListener("keydown", this.handleKeydown);
}
componentWillUnmount() {
document.removeEventListener("click", this.handleClickOutside);
document.removeEventListener("keydown", this.handleKeydown);
}
toggleOptions() {
this.setState({
optionsHidden: !this.state.optionsHidden,
});
}
handleClickOutside(event) {
/* eslint-disable */
const button = ReactDOM.findDOMNode(this._button);
const menu = ReactDOM.findDOMNode(this._menu);
/* eslint-enable */
if (button.contains(event.target)) {
return;
} else if (!menu.contains(event.target) && !this.state.optionsHidden) {
this.toggleOptions();
}
}
handleKeydown(event) {
if (event.keyCode === 27 && !this.state.optionsHidden) {
this.toggleOptions();
}
}
shareContent() {
const { url, text } = this.props;
return {
text: encodeURIComponent(text),
url: encodeURIComponent(url),
via: "lonelyplanet",
};
}
shareUrl() {
const { url, text, via } = this.shareContent();
return {
twitter: `https://twitter.com/intent/tweet?text=${text}&url=${url}&via=${via}`,
facebook: `https://www.facebook.com/sharer/sharer.php?u=${url}`,
email: `mailto:?subject=${text}&body=${url}`,
};
}
render() {
const { twitter, facebook, email } = this.shareUrl();
const style = {
container: [styles.container.base],
options: [styles.options.base],
};
const position = {
up: "below",
down: "above",
left: "right",
right: "left",
};
const visibility = {
true: "hidden",
false: "visible",
};
const flyoutArrow = this.props.mobile ? "right" : "up";
style.options.push(styles.options.position[position[flyoutArrow]]);
style.options.push(
styles.options
.state[visibility[this.state.optionsHidden]]
.base,
styles.options
.state[visibility[this.state.optionsHidden]]
.position[position[flyoutArrow]]
);
return (
<div
className="ShareMenu"
style={style.container}
>
<IconButton
className="ShareMenu-button"
iconName="share"
label="Share this article on Twitter, Facebook, or email"
owns="share-menu-options"
onClick={this.toggleOptions}
ref={(node) => { this._button = node; }}
/>
<div
className="ShareMenu-options"
id="share-menu-options"
style={style.options}
aria-hidden={this.state.optionsHidden}
ref={(node) => { this._menu = node; }}
>
<Flyout arrow={flyoutArrow} fill>
<ShareMenuItem
network="twitter"
href={twitter}
label="Share on Twitter"
onClick={ShareMenu.openWindow}
/>
<ShareMenuItem
network="facebook"
href={facebook}
label="Share on Facebook"
onClick={ShareMenu.openWindow}
/>
<ShareMenuItem
network="email"
href={email}
label="Share by email"
/>
</Flyout>
</div>
</div>
);
}
}
ShareMenu.propTypes = {
/**
* URL of page to share
*/
url: React.PropTypes.string.isRequired,
/**
* Text to share
*/
text: React.PropTypes.string,
/**
* Whether or not the layout should be formatted for mobile screen sizes
*/
mobile: React.PropTypes.bool,
};
ShareMenu.defaultProps = {
url: "",
text: "",
alignment: "",
mobile: true,
};
ShareMenu.styles = styles;
export default radium(ShareMenu);