UNPKG

backpack-ui

Version:

Lonely Planet's Components

761 lines (629 loc) 21.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; var _base2, _base4, _base6, _base8, _base10, _noFlexbox2; var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _radium = require("radium"); var _radium2 = _interopRequireDefault(_radium); var _truncate = require("truncate"); var _truncate2 = _interopRequireDefault(_truncate); var _upperFirst = require("lodash/upperFirst"); var _upperFirst2 = _interopRequireDefault(_upperFirst); var _reactRouter = require("react-router"); var _settings = require("../../../settings.json"); var _button = require("../button"); var _button2 = _interopRequireDefault(_button); var _price = require("../price"); var _price2 = _interopRequireDefault(_price); var _bookmark = require("../bookmark"); var _bookmark2 = _interopRequireDefault(_bookmark); var _bullet = require("../decoration/bullet"); var _bullet2 = _interopRequireDefault(_bullet); var _icon = require("../icon"); var _icon2 = _interopRequireDefault(_icon); var _tooltip = require("../tooltip"); var _tooltip2 = _interopRequireDefault(_tooltip); var _listItemImage = require("../listItemImage"); var _listItemImage2 = _interopRequireDefault(_listItemImage); var _grid = require("../../utils/grid"); var _font = require("../../utils/font"); var _font2 = _interopRequireDefault(_font); var _svgDataUri = require("../../utils/svgDataUri"); var _svgDataUri2 = _interopRequireDefault(_svgDataUri); var _partnerActivityProviders = require("../../../../../server/lib/open-planet/partnerActivityProviders"); var _partnerActivityProviders2 = _interopRequireDefault(_partnerActivityProviders); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var _ = { upperFirst: _upperFirst2.default }; var gridOffset = "1.8rem"; // the image is off the grid by this amount var containerWidth = (0, _grid.span)(8, "static"); var imageWidth = (0, _grid.add)([(0, _grid.span)(1, "static"), (0, _grid.gutter)("static"), gridOffset], "static"); var contentWidth = (0, _grid.subtract)([(0, _grid.span)(7, "static"), (0, _grid.gutter)("static"), gridOffset], "static"); var infoWidth = (0, _grid.subtract)([(0, _grid.span)(6, "static"), (0, _grid.gutter)("static"), "1.8rem"], "static"); var priceWidth = (0, _grid.add)([(0, _grid.span)(1, "static"), (0, _grid.gutter)("static")], "static"); var icons = { checkmark: "<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\" fill=\"" + _settings.color.featureCopy + "\"><path d=\"M32,4L12,32L0,20l4-4l8,8L28,0L32,4z\"></path></svg>" }; var styles = { container: { base: { position: "relative" } }, image: { base: _defineProperty({ float: "left", marginRight: (0, _grid.percentage)("15px", "335px"), overflow: "hidden", position: "relative", width: (0, _grid.percentage)("78px", "335px") }, "@media (min-width: " + _settings.media.min["768"] + ")", { marginRight: (0, _grid.gutter)("fluid", 8), width: (0, _grid.percentage)(imageWidth, containerWidth) }), img: { display: "block", width: "100%" } }, content: { base: (_base2 = { float: "left", position: "relative", width: (0, _grid.percentage)("242px", "335px") }, _defineProperty(_base2, "@media (min-width: " + _settings.media.min["768"] + ")", { width: (0, _grid.percentage)(contentWidth, containerWidth) }), _defineProperty(_base2, "@media (min-width: " + _settings.media.min["1024"] + ")", { display: "flex" }), _base2) }, info: { base: _defineProperty({}, "@media (min-width: " + _settings.media.min["1024"] + ")", { float: "left", paddingRight: (0, _grid.percentage)((0, _grid.span)(1, "static"), contentWidth), width: (0, _grid.percentage)(infoWidth, contentWidth) }), noFlexbox: _defineProperty({}, "@media (min-width: " + _settings.media.min["1024"] + ") and (max-width: " + 1365 * 0.0625 + "em)", { float: "none", paddingRight: 0, width: "100%" }) }, header: { base: { overflow: "hidden" } }, category: { base: (_base4 = { color: _settings.color.detailHeaderSmall, fontSize: "1rem", lineHeight: 1, marginBottom: ".5rem", textTransform: "uppercase" }, _defineProperty(_base4, "@media (max-width: " + _settings.media.max["768"] + ")", { letterSpacing: ".4px", marginTop: ".1rem" }), _defineProperty(_base4, "@media (min-width: " + _settings.media.min["768"] + ")", { fontSize: "1.2rem", marginBottom: "1.3rem" }), _base4), sponsored: { color: _settings.color.orange }, topChoice: { color: _settings.color.red, fontWeight: 600 }, location: _defineProperty({}, "@media (max-width: " + _settings.media.max["768"] + ")", { display: "none" }) }, title: { base: _defineProperty({ color: _settings.color.darkGray, float: "left", fontSize: "2rem", fontWeight: 600, letterSpacing: "-1px", lineHeight: 24 / 20, margin: 0, maxWidth: "90%" }, "@media (min-width: " + _settings.media.min["768"] + ")", { fontSize: "2.8rem", lineHeight: 34 / 28 }) }, bookmark: { base: (_base6 = {}, _defineProperty(_base6, "@media (max-width: " + _settings.media.max["768"] + ")", { bottom: "-2rem", position: "absolute", right: "-.4rem" }), _defineProperty(_base6, "@media (min-width: " + _settings.media.min["768"] + ")", { display: "inline-block", marginLeft: ".5rem", marginTop: ".3rem" }), _base6) }, largeText: { base: _defineProperty({ color: _settings.color.featureCopy, fontSize: "12px", lineHeight: 15.6 / 12, marginTop: 9 / 12 + "em" }, "@media (min-width: " + _settings.media.min["768"] + ")", { fontSize: "18px", marginTop: 9 / 18 + "em" }), item: { display: "inline" } }, reviewedText: { base: (_base8 = {}, _defineProperty(_base8, "@media (max-width: " + _settings.media.max["768"] + ")", { display: "none" }), _defineProperty(_base8, "@media (min-width: " + _settings.media.min["768"] + ")", { backgroundImage: "url(\"" + (0, _svgDataUri2.default)(icons.checkmark) + "\")", backgroundPosition: "0 2px", backgroundRepeat: "no-repeat", backgroundSize: "8px 8px", color: _settings.color.featureCopy, fontFamily: (0, _font2.default)("miller"), fontSize: "1.2rem", fontStyle: "italic", lineHeight: 1, listStyle: "none", marginTop: "2.2rem", paddingLeft: "1.4rem" }), _base8) }, description: { base: _defineProperty({ color: _settings.color.titleGray, fontSize: "1.4rem", lineHeight: 24 / 14, marginBottom: "2.7rem", marginTop: ".9rem" }, "@media (min-width: " + _settings.media.min["768"] + ")", { fontSize: "1.8rem", lineHeight: 32 / 18, marginTop: "1.4rem" }), clamp: { display: "-webkit-box", overflow: "hidden", textOverflow: "ellipsis", WebkitBoxOrient: "vertical", WebkitLineClamp: 2 } }, price: { base: (_base10 = { marginTop: "1.1rem" }, _defineProperty(_base10, "@media (max-width: " + _settings.media.max["768"] + ")", { display: "inline-block" }), _defineProperty(_base10, "@media (min-width: " + _settings.media.min["768"] + ")", { marginTop: "2.5rem" }), _defineProperty(_base10, "@media (min-width: " + _settings.media.min["1024"] + ")", { float: "left", textAlign: "right", width: priceWidth }), _base10), noFlexbox: (_noFlexbox2 = {}, _defineProperty(_noFlexbox2, "@media (min-width: " + _settings.media.min["1024"] + ") and (max-width: " + 1365 * 0.0625 + "em)", { float: "none", textAlign: "left", width: "100%" }), _defineProperty(_noFlexbox2, "@media (min-width: " + 1366 * 0.0625 + "em)", { textAlign: "right", width: (0, _grid.percentage)(priceWidth, contentWidth) }), _noFlexbox2), callToBook: { fontSize: "1.6rem", fontWeight: 600, lineHeight: 1 } } }; function ListItemBookable(_ref) { var title = _ref.title; var slug = _ref.slug; var type = _ref.type; var subtype = _ref.subtype; var place = _ref.place; var price = _ref.price; var features = _ref.features; var image = _ref.image; var description = _ref.description; var sponsored = _ref.sponsored; var topChoice = _ref.topChoice; var reviewed = _ref.reviewed; var bookmark = _ref.bookmark; var bookmarkSize = _ref.bookmarkSize; var id = _ref.id; var duration = _ref.duration; var durationInfo = _ref.durationInfo; var showTourDestinations = _ref.showTourDestinations; var tourStart = _ref.tourStart; var tourEnd = _ref.tourEnd; var tourMap = _ref.tourMap; var activityType = _ref.activityType; var mobile = _ref.mobile; var hidePrice = _ref.hidePrice; var onShowPrices = _ref.onShowPrices; var descriptionString = void 0; if ((typeof description === "undefined" ? "undefined" : _typeof(description)) === "object") { descriptionString = function descriptionString() { if (description.short_description) { return description.short_description; } return description.long_description; }; } if (typeof description === "string") { descriptionString = (0, _truncate2.default)(description.replace(/(<([^>]+)>)/ig, ""), 115); } var durationString = void 0; if ((typeof duration === "undefined" ? "undefined" : _typeof(duration)) === "object" && durationInfo) { durationString = function durationString() { if (duration.duration && duration.unit) { var unit = duration.duration === 1 ? duration.unit.replace(/s$/, "") : duration.unit; return duration.duration + " " + unit; } return durationInfo; }; } if (typeof description === "string") { descriptionString = (0, _truncate2.default)(description.replace(/(<([^>]+)>)/ig, ""), 115); } var hasFlexbox = true; if (typeof document !== "undefined" && document.documentElement) { hasFlexbox = document && document.documentElement.classList ? document.documentElement.classList.contains("flexbox") : new RegExp("(^| )flexbox( |$)", "gi").test(document.documentElement.className); } return _react2.default.createElement( "div", { className: "ListItem clearfix", id: id, style: styles.container.base }, _react2.default.createElement( "div", { className: "ListItem-image", style: styles.image.base }, _react2.default.createElement( _reactRouter.Link, { to: slug, style: styles.image.img }, _react2.default.createElement(_listItemImage2.default, { title: title, image: image }) ) ), _react2.default.createElement( "div", { className: "ListItem-content", style: styles.content.base }, _react2.default.createElement( "div", { className: "ListItem-info", style: [styles.info.base, !hasFlexbox && styles.info.noFlexbox] }, _react2.default.createElement( "header", { className: "ListItem-header", style: styles.header.base }, _react2.default.createElement( "div", { className: "ListItem-category", style: styles.category.base }, sponsored && _react2.default.createElement( "span", { style: styles.category.sponsored }, "Sponsored" ), " ", topChoice && _react2.default.createElement( "span", { style: styles.category.topChoice }, "Top Choice" ), " ", subtype, " ", place.name && _react2.default.createElement( "span", { style: styles.category.location }, " in ", place.name ) ), _react2.default.createElement( "h2", { className: "ListItem-title", style: styles.title.base }, _react2.default.createElement( _reactRouter.Link, { to: slug, style: { color: "inherit" } }, title ) ), bookmark && _react2.default.createElement( "div", { className: "ListItem-bookmark", style: styles.bookmark.base }, _react2.default.createElement(_bookmark2.default, { onClick: null, size: bookmarkSize }) ) ), description && !type === "sleeping" && _react2.default.createElement( "div", { className: "ListItem-description", style: styles.description.base }, _react2.default.createElement("div", { style: styles.description.clamp, dangerouslySetInnerHTML: { __html: description } }) ), features.length > 0 && _react2.default.createElement( "ul", { className: "ListItem-features", style: styles.largeText.base }, features.map(function (item, i) { return _react2.default.createElement( "li", { style: styles.largeText.item, key: i }, _.upperFirst(item), i !== features.length - 1 && _react2.default.createElement(_bullet2.default, { space: "both", color: _settings.color.detailHeaderSmall }) ); }) ), activityType === "tours" && showTourDestinations && _react2.default.createElement( "div", { className: "ListItem-tourDestinations", style: styles.largeText.base }, tourStart && tourEnd && _react2.default.createElement( _reactRouter.Link, { to: slug, style: { color: "inherit" } }, !mobile && _react2.default.createElement(_icon2.default.Pin, { height: "11px", width: "11px", style: { marginRight: 7 / 18 + "em", marginTop: 3 / 18 + "em", verticalAlign: "top" } }), !mobile && tourMap && _react2.default.createElement( _tooltip2.default, { label: tourStart + " to " + tourEnd, flyout: { arrow: "down", size: "medium", removePadding: true, shadow: "large", style: { bottom: "40px", left: 0, position: "absolute" } } }, _react2.default.createElement("img", { src: tourMap, alt: "", width: 290, style: { display: "block" } }) ), (mobile || !tourMap) && _react2.default.createElement( "span", null, tourStart, " to ", tourEnd ) ) ), !mobile && activityType === "activities" && _react2.default.createElement( "div", { className: "ListItem-description", style: styles.description.base }, _react2.default.createElement( "div", { style: styles.description.clamp }, descriptionString() ) ), reviewed && _react2.default.createElement( "div", { style: styles.reviewedText.base }, "Lonely Planet reviewed" ) ), !hidePrice && price.amount && _react2.default.createElement( "div", { className: "ListItem-price", style: [styles.price.base, !hasFlexbox && styles.price.noFlexbox] }, _react2.default.createElement(_price2.default, { amount: price.amount, rate: type === "partner_activity" ? durationString() : price.rate, parent: "listItem", emphasized: true }) ), hidePrice && _react2.default.createElement( "div", { className: "ListItem-price", style: [styles.price.base, !hasFlexbox && styles.price.noFlexbox] }, _react2.default.createElement( _button2.default, { color: "white", size: mobile ? "tiny" : "small", onClick: onShowPrices, rounded: true, border: true }, "Show price" ) ) ) ); } ListItemBookable.propTypes = { /** * The name of the POI * key: name */ title: _react2.default.PropTypes.string.isRequired, /** * The URL slug of the POI; constructed via parent (pois/{id}) */ slug: _react2.default.PropTypes.string.isRequired, /** * The type of POI * key: poi_type */ type: _react2.default.PropTypes.string.isRequired, /** * The subtype of POI; i.e. Museum * key: subtypes[0] * partner-activities key: canonical_category */ subtype: _react2.default.PropTypes.string.isRequired, /** * The place data for the POI; required keys are name and type */ place: _react2.default.PropTypes.shape({ name: _react2.default.PropTypes.string, type: _react2.default.PropTypes.string }).isRequired, /** * Price object for the POI; requires amount and rate keys * key: price_string * partner-activities key: minimum_price.formatted_amount */ price: _react2.default.PropTypes.shape({ amount: _react2.default.PropTypes.number, rate: _react2.default.PropTypes.string }), /** * A short list of features; limited to three */ features: _react2.default.PropTypes.arrayOf(_react2.default.PropTypes.string), /** * Image src for the POI; required keys are path and orientation * partner-activities key: links.image */ image: _react2.default.PropTypes.shape({ path: _react2.default.PropTypes.string, orientation: _react2.default.PropTypes.oneOf(["", "portrait", "landscape"]) }), /** * Description for POI * key: review.essential, review.extension * partner-activities key: descriptions.short_description, descriptions.long_description */ description: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.object]), /** * Add a "sponsored" label */ sponsored: _react2.default.PropTypes.bool, /** * Add a "top choice" label */ topChoice: _react2.default.PropTypes.bool, /** * If the POI has been reviewed by Lonely Planet staff */ reviewed: _react2.default.PropTypes.bool, /** * If list item is able to be bookmarked */ bookmark: _react2.default.PropTypes.bool, /** * Size of bookmark component */ bookmarkSize: _react2.default.PropTypes.oneOf(["small", "large"]), /** * Unique ID for item * key: id */ id: _react2.default.PropTypes.string, /** * The length of the tour or activity; partner activity only * partner-activities key: duration_string */ duration: _react2.default.PropTypes.oneOfType([_react2.default.PropTypes.string, _react2.default.PropTypes.object]), /** * If tour, whether or not to show tour destination info */ showTourDestinations: _react2.default.PropTypes.bool, /** * City name where the tour or activity begins; partner activity only * partner-activities key: departure_info */ tourStart: _react2.default.PropTypes.string, /** * City name where the tour or activity begins; partner activity only * partner-activities key: return_info */ tourEnd: _react2.default.PropTypes.string, /** * Image URL of the tour or activity; partner activity only * partner-activities key: links.map */ tourMap: _react2.default.PropTypes.string, /** * String to determine whether to show activity or tour info */ activityType: _react2.default.PropTypes.string, /** * Default string for duration */ durationInfo: _react2.default.PropTypes.string, /** * Is the mobile layout active? */ mobile: _react2.default.PropTypes.bool, /** * Hide price and display "Show price" button instead; used with availability */ hidePrice: _react2.default.PropTypes.bool, /** * Method to run to show price; used in tandem with `hidePrice` */ onShowPrices: _react2.default.PropTypes.func }; ListItemBookable.defaultProps = { title: "", slug: "", type: "", subtype: "", place: {}, price: {}, features: [], image: {}, description: "", sponsored: false, topChoice: false, reviewed: false, bookmark: false, bookmarkSize: "small", id: "", duration: "", difficulty: "", groupSize: {}, showTourDestinations: false, tourStart: "", tourEnd: "", tourMap: "", bookingUrl: "", activityType: "", durationInfo: "", mobile: false, hidePrice: false, onShowPrices: null }; ListItemBookable.styles = styles; exports.default = (0, _radium2.default)(ListItemBookable);