UNPKG

antd-react-cropper

Version:

An image cropper for Ant Design Upload using React Cropper.

421 lines (363 loc) 18.6 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var antd = require('antd'); var Cropper = require('react-cropper'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var Cropper__default = /*#__PURE__*/_interopDefaultLegacy(Cropper); function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (!css || typeof document === 'undefined') { return; } var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; if (insertAt === 'top') { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } } var css_248z = "/*!\n * Cropper.js v1.5.12\n * https://fengyuanchen.github.io/cropperjs\n *\n * Copyright 2015-present Chen Fengyuan\n * Released under the MIT license\n *\n * Date: 2021-06-12T08:00:11.623Z\n */\n\n.cropper-container {\n direction: ltr;\n font-size: 0;\n line-height: 0;\n position: relative;\n -ms-touch-action: none;\n touch-action: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n\n.cropper-container img {\n display: block;\n height: 100%;\n image-orientation: 0deg;\n max-height: none !important;\n max-width: none !important;\n min-height: 0 !important;\n min-width: 0 !important;\n width: 100%;\n}\n\n.cropper-wrap-box,\n.cropper-canvas,\n.cropper-drag-box,\n.cropper-crop-box,\n.cropper-modal {\n bottom: 0;\n left: 0;\n position: absolute;\n right: 0;\n top: 0;\n}\n\n.cropper-wrap-box,\n.cropper-canvas {\n overflow: hidden;\n}\n\n.cropper-drag-box {\n background-color: #fff;\n opacity: 0;\n}\n\n.cropper-modal {\n background-color: #000;\n opacity: 0.5;\n}\n\n.cropper-view-box {\n display: block;\n height: 100%;\n outline: 1px solid #39f;\n outline-color: rgba(51, 153, 255, 0.75);\n overflow: hidden;\n width: 100%;\n}\n\n.cropper-dashed {\n border: 0 dashed #eee;\n display: block;\n opacity: 0.5;\n position: absolute;\n}\n\n.cropper-dashed.dashed-h {\n border-bottom-width: 1px;\n border-top-width: 1px;\n height: calc(100% / 3);\n left: 0;\n top: calc(100% / 3);\n width: 100%;\n}\n\n.cropper-dashed.dashed-v {\n border-left-width: 1px;\n border-right-width: 1px;\n height: 100%;\n left: calc(100% / 3);\n top: 0;\n width: calc(100% / 3);\n}\n\n.cropper-center {\n display: block;\n height: 0;\n left: 50%;\n opacity: 0.75;\n position: absolute;\n top: 50%;\n width: 0;\n}\n\n.cropper-center::before,\n.cropper-center::after {\n background-color: #eee;\n content: ' ';\n display: block;\n position: absolute;\n}\n\n.cropper-center::before {\n height: 1px;\n left: -3px;\n top: 0;\n width: 7px;\n}\n\n.cropper-center::after {\n height: 7px;\n left: 0;\n top: -3px;\n width: 1px;\n}\n\n.cropper-face,\n.cropper-line,\n.cropper-point {\n display: block;\n height: 100%;\n opacity: 0.1;\n position: absolute;\n width: 100%;\n}\n\n.cropper-face {\n background-color: #fff;\n left: 0;\n top: 0;\n}\n\n.cropper-line {\n background-color: #39f;\n}\n\n.cropper-line.line-e {\n cursor: ew-resize;\n right: -3px;\n top: 0;\n width: 5px;\n}\n\n.cropper-line.line-n {\n cursor: ns-resize;\n height: 5px;\n left: 0;\n top: -3px;\n}\n\n.cropper-line.line-w {\n cursor: ew-resize;\n left: -3px;\n top: 0;\n width: 5px;\n}\n\n.cropper-line.line-s {\n bottom: -3px;\n cursor: ns-resize;\n height: 5px;\n left: 0;\n}\n\n.cropper-point {\n background-color: #39f;\n height: 5px;\n opacity: 0.75;\n width: 5px;\n}\n\n.cropper-point.point-e {\n cursor: ew-resize;\n margin-top: -3px;\n right: -3px;\n top: 50%;\n}\n\n.cropper-point.point-n {\n cursor: ns-resize;\n left: 50%;\n margin-left: -3px;\n top: -3px;\n}\n\n.cropper-point.point-w {\n cursor: ew-resize;\n left: -3px;\n margin-top: -3px;\n top: 50%;\n}\n\n.cropper-point.point-s {\n bottom: -3px;\n cursor: s-resize;\n left: 50%;\n margin-left: -3px;\n}\n\n.cropper-point.point-ne {\n cursor: nesw-resize;\n right: -3px;\n top: -3px;\n}\n\n.cropper-point.point-nw {\n cursor: nwse-resize;\n left: -3px;\n top: -3px;\n}\n\n.cropper-point.point-sw {\n bottom: -3px;\n cursor: nesw-resize;\n left: -3px;\n}\n\n.cropper-point.point-se {\n bottom: -3px;\n cursor: nwse-resize;\n height: 20px;\n opacity: 1;\n right: -3px;\n width: 20px;\n}\n\n@media (min-width: 768px) {\n .cropper-point.point-se {\n height: 15px;\n width: 15px;\n }\n}\n\n@media (min-width: 992px) {\n .cropper-point.point-se {\n height: 10px;\n width: 10px;\n }\n}\n\n@media (min-width: 1200px) {\n .cropper-point.point-se {\n height: 5px;\n opacity: 0.75;\n width: 5px;\n }\n}\n\n.cropper-point.point-se::before {\n background-color: #39f;\n bottom: -50%;\n content: ' ';\n display: block;\n height: 200%;\n opacity: 0;\n position: absolute;\n right: -50%;\n width: 200%;\n}\n\n.cropper-invisible {\n opacity: 0;\n}\n\n.cropper-bg {\n background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');\n}\n\n.cropper-hide {\n display: block;\n height: 0;\n position: absolute;\n width: 0;\n}\n\n.cropper-hidden {\n display: none !important;\n}\n\n.cropper-move {\n cursor: move;\n}\n\n.cropper-crop {\n cursor: crosshair;\n}\n\n.cropper-disabled .cropper-drag-box,\n.cropper-disabled .cropper-face,\n.cropper-disabled .cropper-line,\n.cropper-disabled .cropper-point {\n cursor: not-allowed;\n}\n"; styleInject(css_248z); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } 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; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var css_248z$1 = ".container {\n display: flex;\n width: 100%;\n height: 100%;\n}\n.img-cropper {\n width: 100%;\n height: 100%;\n border-radius: 6px;\n}\n.img-cropper .cropper-container,\n.img-cropper .cropper-crop-box,\n.img-cropper .cropper-drag-box,\n.img-cropper .cropper-wrap-box {\n border-radius: 6px !important;\n}\n.slider-container {\n display: flex;\n align-items: center;\n justify-self: center;\n width: 100%;\n margin: 4px 0px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.slider-container .slider {\n flex: 1;\n margin-right: 20px !important;\n margin-left: 20px !important;\n}\n.preview-container {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: '100%';\n overflow: hidden;\n border-radius: 6px;\n position: 'relative';\n}\n.preview-container .preview-content {\n float: left;\n width: '100%';\n overflow: hidden;\n}\n.divider {\n margin-top: 4px !important;\n margin-bottom: 16px !important;\n}\n.flex {\n display: flex;\n}\n.flex-center {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n}\n.modal-footer {\n display: flex;\n}\n.action-btn {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n width: 20px;\n padding: 0 !important;\n}\n"; styleInject(css_248z$1); var maxZoom = 10; var ImageCropper = function ImageCropper(props) { var aspect = props.aspect, file = props.file, onCropped = props.onCropped, previewMaxHeight = props.previewMaxHeight, title = props.title; var screens = antd.Grid.useBreakpoint(); var _useState = React.useState(), _useState2 = _slicedToArray(_useState, 2), src = _useState2[0], setSrc = _useState2[1]; var _useState3 = React.useState(), _useState4 = _slicedToArray(_useState3, 2), cropper = _useState4[0], setCropper = _useState4[1]; var _useState5 = React.useState(0), _useState6 = _slicedToArray(_useState5, 2), zoom = _useState6[0], setZoom = _useState6[1]; var _useState7 = React.useState(0), _useState8 = _slicedToArray(_useState7, 2), rotate = _useState8[0], setRotate = _useState8[1]; var _useState9 = React.useState(), _useState10 = _slicedToArray(_useState9, 2), canvasData = _useState10[0], setCanvasData = _useState10[1]; React.useEffect(function () { if (file && file.originFileObj) getFileUrl(file.originFileObj, setSrc); }, [file]); React.useEffect(function () { if (!src) { setZoom(0); setRotate(0); setCanvasData(undefined); setCropper(undefined); } }, [src]); React.useEffect(function () { if (cropper) cropper.rotateTo(rotate); }, [rotate]); var onZoomIn = function onZoomIn() { var to = zoom + 1; if (to > maxZoom) to = maxZoom; setZoom(to); onZoom(to); }; var onZoomOut = function onZoomOut() { var to = zoom - 1; if (to <= 0) to = 0; setZoom(to); onZoom(to); }; var onZoomSlide = function onZoomSlide(value) { setZoom(value); onZoom(value); }; var onRotateLeft = function onRotateLeft() { var to = rotate - 15; if (to <= -180) to = -180; setRotate(to); }; var onRotateRight = function onRotateRight() { var to = rotate + 15; if (to >= 180) to = 180; setRotate(to); }; var onCrop = function onCrop() { if (typeof cropper !== 'undefined') { var loader; if (props.showLoader) loader = antd.message.loading('Processing image...', 0); var cropped = cropper.getCroppedCanvas(); var thumbUrl = cropped.toDataURL('image/jpeg'); cropped.toBlob(function (blob) { if (!blob) return; var newFile = new File([blob], file.name); var data = _objectSpread2(_objectSpread2({}, file), {}, { thumbUrl: thumbUrl, originFileObj: newFile }); if (loader) loader(); onCropped === null || onCropped === void 0 ? void 0 : onCropped(data); }, props.exportFileType); } setSrc(undefined); }; var onCancel = function onCancel() { setSrc(undefined); if (props.onCancel) props.onCancel(); }; var onZoom = function onZoom(value) { if (!cropper) return; if (!canvasData) setCanvasData(cropper.getCanvasData()); if (value > maxZoom) return; if (value <= 0) { cropper.setCanvasData(canvasData); } else if (value > zoom) { var diff = value - zoom; cropper.zoom(diff * 0.2); } else { var _diff = zoom - value; cropper.zoom(_diff * -0.2); } }; return /*#__PURE__*/React__default['default'].createElement(antd.Modal, { title: title, zIndex: props.zIndex, centered: props.centered, width: props.width, closable: props.closable || false, bodyStyle: props.bodyStyle || { paddingBottom: 0 }, maskClosable: props.maskClosable, destroyOnClose: true, visible: !!src, onCancel: onCancel, footer: props.customFooter ? props.customFooter({ onCrop: onCrop, onCancel: onCancel }) : /*#__PURE__*/React__default['default'].createElement("div", { className: "modal-footer" }, /*#__PURE__*/React__default['default'].createElement(antd.Button, { onClick: onCancel }, props.cancelText), /*#__PURE__*/React__default['default'].createElement(antd.Button, { block: true, type: "primary", onClick: onCrop }, props.cropText)) }, /*#__PURE__*/React__default['default'].createElement(antd.Row, { gutter: 12 }, /*#__PURE__*/React__default['default'].createElement(antd.Col, { xs: 24, sm: 16 }, /*#__PURE__*/React__default['default'].createElement("div", null, src && /*#__PURE__*/React__default['default'].createElement(Cropper__default['default'], { className: "img-cropper ".concat(props.cropperClassName || ''), style: props.cropperStyle, dragMode: "move", aspectRatio: aspect, preview: ".img-preview", src: src, viewMode: 0, background: true, center: true, autoCropArea: 1, scalable: false, movable: true, onInitialized: setCropper, checkOrientation: false }), /*#__PURE__*/React__default['default'].createElement("div", { className: "slider-container" }, props.zoomOutButton ? props.zoomOutButton(onZoomOut) : /*#__PURE__*/React__default['default'].createElement(antd.Button, { className: "action-btn", type: "link", onClick: onZoomOut }, /*#__PURE__*/React__default['default'].createElement("span", { style: { fontSize: 20 } }, "-")), /*#__PURE__*/React__default['default'].createElement(antd.Slider, { className: "slider", value: zoom, min: 0, max: maxZoom, onChange: onZoomSlide }), props.zoomInButton ? props.zoomInButton(onZoomIn) : /*#__PURE__*/React__default['default'].createElement(antd.Button, { className: "action-btn", type: "link", onClick: onZoomIn }, /*#__PURE__*/React__default['default'].createElement("span", { style: { fontSize: 20 } }, "+"))), /*#__PURE__*/React__default['default'].createElement("div", { className: "slider-container" }, props.rotateLeftButton ? props.rotateLeftButton(onRotateLeft) : /*#__PURE__*/React__default['default'].createElement(antd.Button, { className: "action-btn", type: "link", onClick: onRotateLeft }, /*#__PURE__*/React__default['default'].createElement("span", { style: { fontSize: 15 } }, "\u21BA")), /*#__PURE__*/React__default['default'].createElement("div", { style: { flex: 1 }, onDoubleClick: function onDoubleClick() { return setRotate(0); } }, /*#__PURE__*/React__default['default'].createElement(antd.Slider, { className: "slider", value: rotate, min: -180, max: 180, onChange: setRotate })), props.rotateRightButton ? props.rotateRightButton(onRotateRight) : /*#__PURE__*/React__default['default'].createElement(antd.Button, { className: "action-btn", type: "link", onClick: onRotateRight }, /*#__PURE__*/React__default['default'].createElement("span", { style: { fontSize: 15 } }, "\u21BB"))))), /*#__PURE__*/React__default['default'].createElement(antd.Col, { xs: 24, sm: 8 }, screens.xs && /*#__PURE__*/React__default['default'].createElement(antd.Divider, { className: "divider" }), /*#__PURE__*/React__default['default'].createElement("div", { className: "preview-container ".concat(props.previewClassName || ''), style: _objectSpread2(_objectSpread2({}, props.previewStyle), {}, { maxHeight: previewMaxHeight, backgroundColor: props.previewBackground }) }, /*#__PURE__*/React__default['default'].createElement("div", { className: "img-preview", style: { width: '100%', height: previewMaxHeight, float: 'left', overflow: 'hidden', background: '#000' } }))))); }; var getFileUrl = function getFileUrl(file, callback) { return new Promise(function (resolve) { var reader = new FileReader(); reader.onload = function () { resolve(reader.result); callback === null || callback === void 0 ? void 0 : callback(reader.result); }; reader.readAsDataURL(file); }); }; ImageCropper.defaultProps = { centered: true, width: 500, previewMaxHeight: 150, previewBackground: 'rgba(212, 212, 216)', cropText: 'Crop', cancelText: 'Cancel', showLoader: true, exportFileType: 'image/jpeg' }; exports.ImageCropper = ImageCropper; exports.default = ImageCropper;