UNPKG

react-add-to-calendar

Version:

A simple and reusable add to calendar button component for React

268 lines (223 loc) 10 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); var _helpers = require("./helpers"); var _helpers2 = _interopRequireDefault(_helpers); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var helpers = new _helpers2.default(); var ReactAddToCalendar = function (_React$Component) { _inherits(ReactAddToCalendar, _React$Component); function ReactAddToCalendar(props) { _classCallCheck(this, ReactAddToCalendar); var _this = _possibleConstructorReturn(this, (ReactAddToCalendar.__proto__ || Object.getPrototypeOf(ReactAddToCalendar)).call(this, props)); _this.state = { optionsOpen: props.optionsOpen || false, isCrappyIE: false }; _this.toggleCalendarDropdown = _this.toggleCalendarDropdown.bind(_this); _this.handleDropdownLinkClick = _this.handleDropdownLinkClick.bind(_this); return _this; } _createClass(ReactAddToCalendar, [{ key: "componentWillMount", value: function componentWillMount() { // polyfill for startsWith to fix IE bug if (!String.prototype.startsWith) { String.prototype.startsWith = function (searchString, position) { position = position || 0; return this.indexOf(searchString, position) === position; }; } var isCrappyIE = false; if (typeof window !== "undefined" && window.navigator.msSaveOrOpenBlob && window.Blob) { isCrappyIE = true; } this.setState({ isCrappyIE: isCrappyIE }); } }, { key: "toggleCalendarDropdown", value: function toggleCalendarDropdown() { var showOptions = !this.state.optionsOpen; if (showOptions) { document.addEventListener("click", this.toggleCalendarDropdown, false); } else { document.removeEventListener("click", this.toggleCalendarDropdown); } this.setState({ optionsOpen: showOptions }); } }, { key: "handleDropdownLinkClick", value: function handleDropdownLinkClick(e) { e.preventDefault(); var url = e.currentTarget.getAttribute("href"); if (!helpers.isMobile() && (url.startsWith("data") || url.startsWith("BEGIN"))) { var filename = "download.ics"; var blob = new Blob([url], { type: "text/calendar;charset=utf-8" }); if (this.state.isCrappyIE) { window.navigator.msSaveOrOpenBlob(blob, filename); } else { /**************************************************************** // many browsers do not properly support downloading data URIs // (even with "download" attribute in use) so this solution // ensures the event will download cross-browser ****************************************************************/ var link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); link.setAttribute("download", filename); document.body.appendChild(link); link.click(); document.body.removeChild(link); } } else { window.open(url, "_blank"); } this.toggleCalendarDropdown(); } }, { key: "renderDropdown", value: function renderDropdown() { var self = this; var items = this.props.listItems.map(function (listItem) { var currentItem = Object.keys(listItem)[0]; var currentLabel = listItem[currentItem]; var icon = null; if (self.props.displayItemIcons) { var currentIcon = currentItem === "outlook" || currentItem === "outlookcom" ? "windows" : currentItem; icon = _react2.default.createElement("i", { className: "fa fa-" + currentIcon }); } return _react2.default.createElement( "li", { key: helpers.getRandomKey() }, _react2.default.createElement( "a", { className: currentItem + "-link", onClick: self.handleDropdownLinkClick, href: helpers.buildUrl(self.props.event, currentItem, self.state.isCrappyIE), target: "_blank" }, icon, currentLabel ) ); }); return _react2.default.createElement( "div", { className: this.props.dropdownClass }, _react2.default.createElement( "ul", null, items ) ); } }, { key: "renderButton", value: function renderButton() { var buttonLabel = this.props.buttonLabel; var buttonIcon = null; var template = Object.keys(this.props.buttonTemplate); if (template[0] !== "textOnly") { var iconPlacement = this.props.buttonTemplate[template]; var buttonClassPrefix = this.props.buttonIconClass === "react-add-to-calendar__icon--" ? "" + this.props.buttonIconClass + iconPlacement : this.props.buttonIconClass; var iconPrefix = this.props.useFontAwesomeIcons ? "fa fa-" : ""; var mainButtonIconClass = template[0] === "caret" ? this.state.optionsOpen ? "caret-up" : "caret-down" : template[0]; var buttonIconClass = buttonClassPrefix + " " + iconPrefix + mainButtonIconClass; buttonIcon = _react2.default.createElement("i", { className: buttonIconClass }); buttonLabel = iconPlacement === "right" ? _react2.default.createElement( "span", null, buttonLabel + " ", buttonIcon ) : _react2.default.createElement( "span", null, buttonIcon, " " + buttonLabel ); } var buttonClass = this.state.optionsOpen ? this.props.buttonClassClosed + " " + this.props.buttonClassOpen : this.props.buttonClassClosed; return _react2.default.createElement( "div", { className: this.props.buttonWrapperClass }, _react2.default.createElement( "a", { className: buttonClass, onClick: this.toggleCalendarDropdown }, buttonLabel ) ); } }, { key: "render", value: function render() { var options = null; if (this.state.optionsOpen) { options = this.renderDropdown(); } var addToCalendarBtn = null; if (this.props.event) { addToCalendarBtn = this.renderButton(); } return _react2.default.createElement( "div", { className: this.props.rootClass }, addToCalendarBtn, options ); } }]); return ReactAddToCalendar; }(_react2.default.Component); exports.default = ReactAddToCalendar; ReactAddToCalendar.displayName = "Add To Calendar"; ReactAddToCalendar.propTypes = { buttonClassClosed: _propTypes2.default.string, buttonClassOpen: _propTypes2.default.string, buttonLabel: _propTypes2.default.string, buttonTemplate: _propTypes2.default.object, buttonIconClass: _propTypes2.default.string, useFontAwesomeIcons: _propTypes2.default.bool, buttonWrapperClass: _propTypes2.default.string, displayItemIcons: _propTypes2.default.bool, optionsOpen: _propTypes2.default.bool, dropdownClass: _propTypes2.default.string, event: _propTypes2.default.shape({ title: _propTypes2.default.string, description: _propTypes2.default.string, location: _propTypes2.default.string, startTime: _propTypes2.default.string, endTime: _propTypes2.default.string }).isRequired, listItems: _propTypes2.default.arrayOf(_propTypes2.default.object), rootClass: _propTypes2.default.string }; ReactAddToCalendar.defaultProps = { buttonClassClosed: "react-add-to-calendar__button", buttonClassOpen: "react-add-to-calendar__button--light", buttonLabel: "Add to My Calendar", buttonTemplate: { caret: "right" }, buttonIconClass: "react-add-to-calendar__icon--", useFontAwesomeIcons: true, buttonWrapperClass: "react-add-to-calendar__wrapper", displayItemIcons: true, optionsOpen: false, dropdownClass: "react-add-to-calendar__dropdown", event: { title: "Sample Event", description: "This is the sample event provided as an example only", location: "Portland, OR", startTime: "2016-09-16T20:15:00-04:00", endTime: "2016-09-16T21:45:00-04:00" }, listItems: [{ apple: "Apple Calendar" }, { google: "Google" }, { outlook: "Outlook" }, { outlookcom: "Outlook.com" }, { yahoo: "Yahoo" }], rootClass: "react-add-to-calendar" };