UNPKG

backpack-ui

Version:
409 lines (330 loc) 12.7 kB
"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);