backpack-ui
Version:
Lonely Planet's Components
761 lines (629 loc) • 21.7 kB
JavaScript
"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);