UNPKG

backpack-ui

Version:
752 lines (641 loc) 21.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof2 = require("babel-runtime/helpers/typeof"); var _typeof3 = _interopRequireDefault(_typeof2); var _defineProperty2 = require("babel-runtime/helpers/defineProperty"); var _defineProperty3 = _interopRequireDefault(_defineProperty2); var _base2, _base4, _base6, _base8, _base10, _noFlexbox2; var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); 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 _colors = require("../../styles/colors"); var _colors2 = _interopRequireDefault(_colors); var _mq = require("../../styles/mq"); var _mq2 = _interopRequireDefault(_mq); var _font = require("../../utils/font"); var _font2 = _interopRequireDefault(_font); var _grid = require("../../utils/grid"); var _svgDataUri = require("../../utils/svgDataUri"); var _svgDataUri2 = _interopRequireDefault(_svgDataUri); var _bookmarkButton = require("../bookmarkButton"); var _bookmarkButton2 = _interopRequireDefault(_bookmarkButton); var _bullet = require("../bullet"); var _bullet2 = _interopRequireDefault(_bullet); var _button = require("../button"); var _button2 = _interopRequireDefault(_button); var _icon = require("../icon"); var _icon2 = _interopRequireDefault(_icon); var _listItemImage = require("../listItemImage"); var _listItemImage2 = _interopRequireDefault(_listItemImage); var _price = require("../price"); var _price2 = _interopRequireDefault(_price); var _tooltip = require("../tooltip"); var _tooltip2 = _interopRequireDefault(_tooltip); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: 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=\"" + _colors2.default.textSecondary + "\"><path d=\"M32,4L12,32L0,20l4-4l8,8L28,0L32,4z\"></path></svg>" }; var styles = { container: { base: { position: "relative" } }, image: { base: (0, _defineProperty3.default)({ float: "left", marginRight: (0, _grid.percentage)("15px", "335px"), overflow: "hidden", position: "relative", width: (0, _grid.percentage)("78px", "335px") }, "@media (min-width: " + _mq2.default.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") }, (0, _defineProperty3.default)(_base2, "@media (min-width: " + _mq2.default.min[768] + ")", { width: (0, _grid.percentage)(contentWidth, containerWidth) }), (0, _defineProperty3.default)(_base2, "@media (min-width: " + _mq2.default.min[1024] + ")", { display: "flex" }), _base2) }, info: { base: (0, _defineProperty3.default)({}, "@media (min-width: " + _mq2.default.min[1024] + ")", { float: "left", paddingRight: (0, _grid.percentage)((0, _grid.span)(1, "static"), contentWidth), width: (0, _grid.percentage)(infoWidth, contentWidth) }), noFlexbox: (0, _defineProperty3.default)({}, "@media (min-width: " + _mq2.default.min[1024] + ") and (max-width: " + 1365 * 0.0625 + "em)", { float: "none", paddingRight: 0, width: "100%" }) }, header: { base: { overflow: "hidden" } }, category: { base: (_base4 = { color: _colors2.default.accentGray, fontSize: "1rem", lineHeight: 1, marginBottom: ".5rem", textTransform: "uppercase" }, (0, _defineProperty3.default)(_base4, "@media (max-width: " + _mq2.default.max[768] + ")", { letterSpacing: ".4px", marginTop: ".1rem" }), (0, _defineProperty3.default)(_base4, "@media (min-width: " + _mq2.default.min[768] + ")", { fontSize: "1.2rem", marginBottom: "1.3rem" }), _base4), sponsored: { color: _colors2.default.accentYellow }, topChoice: { color: _colors2.default.accentRed, fontWeight: 600 }, location: (0, _defineProperty3.default)({}, "@media (max-width: " + _mq2.default.max[768] + ")", { display: "none" }) }, title: { base: (0, _defineProperty3.default)({ color: _colors2.default.textPrimary, float: "left", fontSize: "2rem", fontWeight: 600, letterSpacing: "-1px", lineHeight: 24 / 20, margin: 0, maxWidth: "90%" }, "@media (min-width: " + _mq2.default.min[768] + ")", { fontSize: "2.8rem", lineHeight: 34 / 28 }) }, bookmark: { base: (_base6 = {}, (0, _defineProperty3.default)(_base6, "@media (max-width: " + _mq2.default.max[768] + ")", { bottom: "-2rem", position: "absolute", right: "-.4rem" }), (0, _defineProperty3.default)(_base6, "@media (min-width: " + _mq2.default.min[768] + ")", { display: "inline-block", marginLeft: ".5rem", marginTop: ".3rem" }), _base6) }, largeText: { base: (0, _defineProperty3.default)({ color: _colors2.default.textSecondary, fontSize: "12px", lineHeight: 15.6 / 12, marginTop: 9 / 12 + "em" }, "@media (min-width: " + _mq2.default.min[768] + ")", { fontSize: "18px", marginTop: 9 / 18 + "em" }), item: { display: "inline" } }, reviewedText: { base: (_base8 = {}, (0, _defineProperty3.default)(_base8, "@media (max-width: " + _mq2.default.max[768] + ")", { display: "none" }), (0, _defineProperty3.default)(_base8, "@media (min-width: " + _mq2.default.min[768] + ")", { backgroundImage: "url(\"" + (0, _svgDataUri2.default)(icons.checkmark) + "\")", backgroundPosition: "0 2px", backgroundRepeat: "no-repeat", backgroundSize: "8px 8px", color: _colors2.default.textSecondary, fontFamily: (0, _font2.default)("miller"), fontSize: "1.2rem", fontStyle: "italic", lineHeight: 1, listStyle: "none", marginTop: "2.2rem", paddingLeft: "1.4rem" }), _base8) }, description: { base: (0, _defineProperty3.default)({ color: _colors2.default.textPrimary, fontSize: "1.4rem", lineHeight: 24 / 14, marginBottom: "2.7rem", marginTop: ".9rem" }, "@media (min-width: " + _mq2.default.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" }, (0, _defineProperty3.default)(_base10, "@media (max-width: " + _mq2.default.max[768] + ")", { display: "inline-block" }), (0, _defineProperty3.default)(_base10, "@media (min-width: " + _mq2.default.min[768] + ")", { marginTop: "2.5rem" }), (0, _defineProperty3.default)(_base10, "@media (min-width: " + _mq2.default.min[1024] + ")", { float: "left", textAlign: "right", width: priceWidth }), _base10), noFlexbox: (_noFlexbox2 = {}, (0, _defineProperty3.default)(_noFlexbox2, "@media (min-width: " + _mq2.default.min[1024] + ") and (max-width: " + 1365 * 0.0625 + "em)", { float: "none", textAlign: "left", width: "100%" }), (0, _defineProperty3.default)(_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, slug = _ref.slug, type = _ref.type, subtype = _ref.subtype, place = _ref.place, price = _ref.price, features = _ref.features, image = _ref.image, description = _ref.description, sponsored = _ref.sponsored, topChoice = _ref.topChoice, reviewed = _ref.reviewed, bookmark = _ref.bookmark, bookmarkSize = _ref.bookmarkSize, id = _ref.id, duration = _ref.duration, durationInfo = _ref.durationInfo, showTourDestinations = _ref.showTourDestinations, tourStart = _ref.tourStart, tourEnd = _ref.tourEnd, tourMap = _ref.tourMap, activityType = _ref.activityType, mobile = _ref.mobile, hidePrice = _ref.hidePrice, onShowPrices = _ref.onShowPrices, qaHook = _ref.qaHook; var descriptionString = void 0; if ((typeof description === "undefined" ? "undefined" : (0, _typeof3.default)(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" : (0, _typeof3.default)(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(_bookmarkButton2.default, { onClick: null, size: bookmarkSize }) ) ), description && !type === "sleeping" && _react2.default.createElement( "div", { className: "ListItem-description", style: styles.description.base, "data-testid": qaHook ? "description-div" : null }, _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, "data-testid": qaHook ? "features-ul" : null }, 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: _colors2.default.accentGray }) ); }) ), activityType === "tours" && showTourDestinations && _react2.default.createElement( "div", { "data-testid": qaHook ? "destinations-bookable-div" : null, 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, qaHook: qaHook }, "Show price" ) ) ) ); } ListItemBookable.propTypes = { /** * The name of the POI * key: name */ title: _propTypes2.default.string.isRequired, /** * The URL slug of the POI; constructed via parent (pois/{id}) */ slug: _propTypes2.default.string.isRequired, /** * The type of POI * key: poi_type */ type: _propTypes2.default.string.isRequired, /** * The subtype of POI; i.e. Museum * key: subtypes[0] * partner-activities key: canonical_category */ subtype: _propTypes2.default.string.isRequired, /** * The place data for the POI; required keys are name and type */ place: _propTypes2.default.shape({ name: _propTypes2.default.string, type: _propTypes2.default.string }).isRequired, /** * Price object for the POI; requires amount and rate keys * key: price_string * partner-activities key: minimum_price.formatted_amount */ price: _propTypes2.default.shape({ amount: _propTypes2.default.number, rate: _propTypes2.default.string }), /** * A short list of features; limited to three */ features: _propTypes2.default.arrayOf(_propTypes2.default.string), /** * Image src for the POI; required keys are path and orientation * partner-activities key: links.image */ image: _propTypes2.default.shape({ path: _propTypes2.default.string, orientation: _propTypes2.default.oneOf(["", "portrait", "landscape"]) }), /** * Description for POI * key: review.essential, review.extension * partner-activities key: descriptions.short_description, descriptions.long_description */ description: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]), /** * Add a "sponsored" label */ sponsored: _propTypes2.default.bool, /** * Add a "top choice" label */ topChoice: _propTypes2.default.bool, /** * If the POI has been reviewed by Lonely Planet staff */ reviewed: _propTypes2.default.bool, /** * If list item is able to be bookmarked */ bookmark: _propTypes2.default.bool, /** * Size of bookmark component */ bookmarkSize: _propTypes2.default.oneOf(["small", "large"]), /** * Unique ID for item * key: id */ id: _propTypes2.default.string, /** * The length of the tour or activity; partner activity only * partner-activities key: duration_string */ duration: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]), /** * If tour, whether or not to show tour destination info */ showTourDestinations: _propTypes2.default.bool, /** * City name where the tour or activity begins; partner activity only * partner-activities key: departure_info */ tourStart: _propTypes2.default.string, /** * City name where the tour or activity begins; partner activity only * partner-activities key: return_info */ tourEnd: _propTypes2.default.string, /** * Image URL of the tour or activity; partner activity only * partner-activities key: links.map */ tourMap: _propTypes2.default.string, /** * String to determine whether to show activity or tour info */ activityType: _propTypes2.default.string, /** * Default string for duration */ durationInfo: _propTypes2.default.string, /** * Is the mobile layout active? */ mobile: _propTypes2.default.bool, /** * Hide price and display "Show price" button instead; used with availability */ hidePrice: _propTypes2.default.bool, /** * Method to run to show price; used in tandem with `hidePrice` */ onShowPrices: _propTypes2.default.func, /** * Method to have a custom data hook for QA purposes */ qaHook: _propTypes2.default.bool }; 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, qaHook: false }; ListItemBookable.styles = styles; exports.default = (0, _radium2.default)(ListItemBookable);