backpack-ui
Version:
Lonely Planet's Components
409 lines (330 loc) • 12.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _regenerator = require("babel-runtime/regenerator");
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator");
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _getPrototypeOf = require("babel-runtime/core-js/object/get-prototype-of");
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn");
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
var _inherits2 = require("babel-runtime/helpers/inherits");
var _inherits3 = _interopRequireDefault(_inherits2);
var _extends2 = require("babel-runtime/helpers/extends");
var _extends3 = _interopRequireDefault(_extends2);
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 _colors = require("../../styles/colors");
var _colors2 = _interopRequireDefault(_colors);
var _timing = require("../../styles/timing");
var _timing2 = _interopRequireDefault(_timing);
var _zIndex = require("../../styles/zIndex");
var _zIndex2 = _interopRequireDefault(_zIndex);
var _color = require("../../utils/color");
var _mixins = require("../../utils/mixins");
var _propTypes3 = require("../../utils/propTypes");
var _propTypes4 = _interopRequireDefault(_propTypes3);
var _typography = require("../../utils/typography");
var _avatar = require("../avatar");
var _avatar2 = _interopRequireDefault(_avatar);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var styles = {
container: {
textAlign: "center"
},
innerContainer: {
display: "inline-block",
position: "relative",
textAlign: "center",
verticalAlign: "middle"
},
input: {
cursor: "pointer",
display: "block",
height: "100%",
left: 0,
opacity: 0,
position: "absolute",
top: 0,
width: "100%",
zIndex: _zIndex2.default.default,
":focus": (0, _mixins.outline)()
},
label: (0, _extends3.default)({}, (0, _typography.textHeading7)("medium"), {
color: _colors2.default.linkPrimary,
display: "block",
lineHeight: 1,
marginTop: "16px",
transition: "color " + _timing2.default.fast + " ease-in-out"
})
};
var scopedStyles = {
"input:focus ~ img": (0, _mixins.outline)(),
"input:hover ~ label": {
color: (0, _color.lighten)(_colors2.default.linkPrimary, 25) + " !important"
},
"input:active ~ label": {
color: (0, _color.lighten)(_colors2.default.linkPrimary, 25) + " !important"
},
"input:focus ~ label": {
color: (0, _color.lighten)(_colors2.default.linkPrimary, 25) + " !important"
}
};
var AvatarUpload = function (_Component) {
(0, _inherits3.default)(AvatarUpload, _Component);
(0, _createClass3.default)(AvatarUpload, null, [{
key: "strToTypedArray",
value: function strToTypedArray(str) {
var byteString = void 0;
if (str.split(",")[0].indexOf("base64") >= 0) {
byteString = atob(str.split(",")[1]);
} else {
byteString = unescape(str.split(",")[1]);
}
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i += 1) {
ia[i] = byteString.charCodeAt(i);
}
return ia;
}
}, {
key: "dataURItoBlob",
value: function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var ia = AvatarUpload.strToTypedArray(dataURI);
// separate out the mime component
var mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0];
return new Blob([ia], { type: mimeString });
}
}, {
key: "getOrientation",
value: function getOrientation(src) {
var view = new DataView(AvatarUpload.strToTypedArray(src).buffer);
if (view.getUint16(0, false) !== 0xFFD8) return -2;
var length = view.byteLength;
var offset = 2;
while (offset < length) {
var marker = view.getUint16(offset, false);
offset += 2;
if (marker === 0xFFE1) {
offset += 2;
if (view.getUint32(offset, false) !== 0x45786966) return -1;
var little = view.getUint16(offset += 6, false) === 0x4949;
offset += view.getUint32(offset + 4, little);
var tags = view.getUint16(offset, little);
offset += 2;
for (var i = 0; i < tags; i += 1) {
if (view.getUint16(offset + i * 12, little) === 0x0112) {
return view.getUint16(offset + i * 12 + 8, little);
}
}
} else if ((marker & 0xFF00) !== 0xFF00) break; // eslint-disable-line no-bitwise
else offset += view.getUint16(offset, false);
}
return -1;
}
}, {
key: "resetOrientation",
value: function resetOrientation(ctx, orientation) {
var width = ctx.canvas.width;
var height = ctx.canvas.height;
// set proper canvas dimensions before transform
if (orientation > 4 && orientation < 9) {
ctx.canvas.width = height;
ctx.canvas.height = width;
}
// transform context before drawing image
switch (orientation) {
case 2:
ctx.transform(-1, 0, 0, 1, width, 0);break;
case 3:
ctx.transform(-1, 0, 0, -1, width, height);break;
case 4:
ctx.transform(1, 0, 0, -1, 0, height);break;
case 5:
ctx.transform(0, 1, 1, 0, 0, 0);break;
case 6:
ctx.transform(0, 1, -1, 0, height, 0);break;
case 7:
ctx.transform(0, -1, -1, 0, height, width);break;
case 8:
ctx.transform(0, -1, 1, 0, 0, width);break;
default:
break;
}
}
}]);
function AvatarUpload(props) {
(0, _classCallCheck3.default)(this, AvatarUpload);
var _this = (0, _possibleConstructorReturn3.default)(this, (AvatarUpload.__proto__ || (0, _getPrototypeOf2.default)(AvatarUpload)).call(this, props));
_this.state = {
src: props.src,
loading: false
};
_this.onChange = _this.onChange.bind(_this);
return _this;
}
(0, _createClass3.default)(AvatarUpload, [{
key: "componentWillReceiveProps",
value: function componentWillReceiveProps(nextProps) {
if (nextProps.src !== this.props.src) {
this.state = {
src: nextProps.src
};
}
}
}, {
key: "onChange",
value: function onChange(event) {
var _this2 = this;
event.preventDefault();
if (this.input.files && this.input.files[0]) {
var reader = new FileReader();
reader.onload = function () {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(e) {
var converterCanvas, ctx, converterImage, orientation;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_context2.next = 2;
return document.createElement("canvas");
case 2:
converterCanvas = _context2.sent;
_context2.next = 5;
return converterCanvas.getContext("2d");
case 5:
ctx = _context2.sent;
converterImage = new Image();
converterImage.src = e.target.result;
_context2.next = 10;
return AvatarUpload.getOrientation(e.target.result);
case 10:
orientation = _context2.sent;
converterImage.onload = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
var targetWidth, originalCtxHeight, convertedUrl, blobImage;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
targetWidth = 160;
ctx.canvas.width = targetWidth;
ctx.canvas.height = converterImage.height * (targetWidth / converterImage.width);
originalCtxHeight = ctx.canvas.height;
_context.next = 6;
return AvatarUpload.resetOrientation(ctx, orientation);
case 6:
_context.next = 8;
return ctx.drawImage(converterImage, 0, 0, targetWidth, originalCtxHeight);
case 8:
_context.next = 10;
return converterCanvas.toDataURL("image/jpeg");
case 10:
convertedUrl = _context.sent;
_context.next = 13;
return AvatarUpload.dataURItoBlob(convertedUrl);
case 13:
blobImage = _context.sent;
_this2.setState({
src: convertedUrl,
loading: false
});
_this2.props.onChangeFiles(blobImage);
if (typeof _this2.props.exposeImageOnChange === "function") {
_this2.props.exposeImageOnChange(blobImage);
}
case 17:
case "end":
return _context.stop();
}
}
}, _callee, _this2);
}));
case 12:
case "end":
return _context2.stop();
}
}
}, _callee2, _this2);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}();
this.setState({
loading: true
});
reader.readAsDataURL(this.input.files[0]);
}
}
}, {
key: "render",
value: function render() {
var _this3 = this;
var style = this.props.style;
return _react2.default.createElement(
"div",
{
className: "AvatarUpload",
style: [styles.container, style]
},
_react2.default.createElement(_radium.Style, {
scopeSelector: ".AvatarUpload",
rules: scopedStyles
}),
_react2.default.createElement(
"div",
{ style: [styles.innerContainer] },
_react2.default.createElement("input", {
id: "avatarUploadInput",
type: "file",
accept: "image/*",
ref: function ref(node) {
return _this3.input = node;
},
onChange: this.onChange,
style: styles.input
}),
_react2.default.createElement(_avatar2.default, {
src: this.state.src,
size: 80,
alt: "Avatar image upload preview"
}),
this.state.loading ? _react2.default.createElement(
"p",
{
style: styles.label
},
"Loading..."
) : _react2.default.createElement(
"label",
{
htmlFor: "avatarUploadInput",
style: styles.label
},
"Change profile photo"
)
)
);
}
}]);
return AvatarUpload;
}(_react.Component);
AvatarUpload.propTypes = {
src: _propTypes2.default.string.isRequired,
style: _propTypes4.default.style,
exposeImageOnChange: _propTypes2.default.func,
onChangeFiles: _propTypes2.default.func
};
exports.default = (0, _radium2.default)(AvatarUpload);