antd-img-crop 4.9.0 → 4.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -24
- package/README.zh-CN.md +4 -8
- package/dist/antd-img-crop.cjs.js +51 -29
- package/dist/antd-img-crop.d.ts +1 -0
- package/dist/antd-img-crop.esm.js +51 -27
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -37,29 +37,32 @@ const Demo = () => (
|
|
|
37
37
|
|
|
38
38
|
## Props
|
|
39
39
|
|
|
40
|
-
| Prop | Type
|
|
41
|
-
| -------------- |
|
|
42
|
-
| quality | `number`
|
|
43
|
-
| fillColor | `string`
|
|
44
|
-
| zoomSlider | `boolean`
|
|
45
|
-
| rotationSlider | `boolean`
|
|
46
|
-
| aspectSlider | `boolean`
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
40
|
+
| Prop | Type | Default | Description |
|
|
41
|
+
| -------------- | ---------- | -------------- | ----------------------------------------------------------------- |
|
|
42
|
+
| quality | `number` | `0.4` | Cropped image quality, `0` to `1` |
|
|
43
|
+
| fillColor | `string` | `'white'` | Fill color when cropped image smaller than canvas |
|
|
44
|
+
| zoomSlider | `boolean` | `true` | Enable zoom adjustment for image |
|
|
45
|
+
| rotationSlider | `boolean` | `false` | Enable rotation adjustment for image |
|
|
46
|
+
| aspectSlider | `boolean` | `false` | Enable aspect adjustment for crop area |
|
|
47
|
+
| showReset | `boolean` | `false` | show a reset button to reset zoom, rotation, aspect |
|
|
48
|
+
| aspect | `number` | `1 / 1` | Aspect of crop area , `width / height` |
|
|
49
|
+
| minZoom | `number` | `1` | Minimum zoom factor |
|
|
50
|
+
| maxZoom | `number` | `3` | Maximum zoom factor |
|
|
51
|
+
| cropShape | `string` | `'rect'` | Shape of crop area, `'rect'` or `'round'` |
|
|
52
|
+
| showGrid | `boolean` | `false` | Show grid of crop area (third-lines) |
|
|
53
|
+
| cropperProps | `object` | - | [react-easy-crop] props (\* existing props cannot be overridden) |
|
|
54
|
+
| modalClassName | `string` | `''` | Provide your own classname for the Modal container |
|
|
55
|
+
| modalTitle | `string` | `'Edit image'` | Title of modal |
|
|
56
|
+
| modalWidth | `number` | `string` | Width of modal in pixels number or percentages |
|
|
57
|
+
| modalOk | `string` | | Text of modal confirm button |
|
|
58
|
+
| modalCancel | `string` | | Text of modal cancel button |
|
|
59
|
+
| onModalOk | `function` | - | Call when click modal confirm button |
|
|
60
|
+
| onModalCancel | `function` | - | Call when click modal mask, top right "x", or cancel button |
|
|
61
|
+
| modalProps | `object` | | [Ant Design Modal] props (\* existing props cannot be overridden) |
|
|
62
|
+
| beforeCrop | `function` | - | Call before modal open, if return `false`, it'll not open |
|
|
63
|
+
| onUploadFail | `function` | - | Call when upload failed |
|
|
64
|
+
|
|
65
|
+
## FAQ
|
|
63
66
|
|
|
64
67
|
### `ConfigProvider` not work?
|
|
65
68
|
|
|
@@ -73,7 +76,7 @@ module.exports = {
|
|
|
73
76
|
};
|
|
74
77
|
```
|
|
75
78
|
|
|
76
|
-
|
|
79
|
+
### No style? (only `antd<=v4`)
|
|
77
80
|
|
|
78
81
|
If you use `antd<=v4` + `babel-plugin-import`, and no `Modal` or `Slider` were imported, please import these styles manually:
|
|
79
82
|
|
package/README.zh-CN.md
CHANGED
|
@@ -44,6 +44,7 @@ const Demo = () => (
|
|
|
44
44
|
| zoomSlider | `boolean` | `true` | 启用图片缩放调整 |
|
|
45
45
|
| rotationSlider | `boolean` | `false` | 启用图片旋转调整 |
|
|
46
46
|
| aspectSlider | `boolean` | `false` | 启用裁切比率调整 |
|
|
47
|
+
| showReset | `boolean` | `false` | 显示重置按钮,用以重置缩放、旋转、比率 |
|
|
47
48
|
| aspect | `number` | `1 / 1` | 裁切区域宽高比,`width / height` |
|
|
48
49
|
| minZoom | `number` | `1` | 最小缩放倍数 |
|
|
49
50
|
| maxZoom | `number` | `3` | 最大缩放倍数 |
|
|
@@ -61,6 +62,8 @@ const Demo = () => (
|
|
|
61
62
|
| beforeCrop | `function` | - | 弹窗打开前调用,若返回 `false`,弹框将不会打开 |
|
|
62
63
|
| onUploadFail | `function` | - | 上传失败时的回调 |
|
|
63
64
|
|
|
65
|
+
## FAQ
|
|
66
|
+
|
|
64
67
|
### `ConfigProvider` 无效?
|
|
65
68
|
|
|
66
69
|
尝试设置 `libraryDirectory`(`'es'` 或 `'lib'`)到 `babel-plugin-import` 的配置项,看看哪个会生效。
|
|
@@ -73,7 +76,7 @@ module.exports = {
|
|
|
73
76
|
};
|
|
74
77
|
```
|
|
75
78
|
|
|
76
|
-
|
|
79
|
+
### 没有样式?(仅 `antd<=v4`)
|
|
77
80
|
|
|
78
81
|
若使用 `antd<=v4` + `babel-plugin-import`,且未引入 `Modal` 或 `Slider`,请手动引入这些样式:
|
|
79
82
|
|
|
@@ -82,13 +85,6 @@ import 'antd/es/modal/style';
|
|
|
82
85
|
import 'antd/es/slider/style';
|
|
83
86
|
```
|
|
84
87
|
|
|
85
|
-
## 在 antd v5 之前
|
|
86
|
-
|
|
87
|
-
```js
|
|
88
|
-
import 'antd/es/modal/style';
|
|
89
|
-
import 'antd/es/slider/style';
|
|
90
|
-
```
|
|
91
|
-
|
|
92
88
|
## 协议
|
|
93
89
|
|
|
94
90
|
[MIT License](https://github.com/nanxiaobei/antd-img-crop/blob/main/LICENSE) (c) [nanxiaobei](https://lee.so/)
|
|
@@ -1,19 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function __$styleInject(css) {
|
|
6
|
-
if (!css) return;
|
|
7
|
-
|
|
8
|
-
if (typeof window == 'undefined') return;
|
|
9
|
-
var style = document.createElement('style');
|
|
10
|
-
style.setAttribute('media', 'screen');
|
|
11
|
-
|
|
12
|
-
style.innerHTML = css;
|
|
13
|
-
document.head.appendChild(style);
|
|
14
|
-
return css;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
3
|
var tslib = require('tslib');
|
|
18
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
19
5
|
var react = require('react');
|
|
@@ -22,6 +8,7 @@ var AntModal = require('antd/lib/modal');
|
|
|
22
8
|
var AntUpload = require('antd/lib/upload');
|
|
23
9
|
var compareVersions = require('compare-versions');
|
|
24
10
|
var Cropper = require('react-easy-crop');
|
|
11
|
+
var AntButton = require('antd/lib/button');
|
|
25
12
|
var AntSlider = require('antd/lib/slider');
|
|
26
13
|
|
|
27
14
|
const PREFIX = 'img-crop';
|
|
@@ -36,11 +23,19 @@ const ASPECT_MAX = 2;
|
|
|
36
23
|
const ASPECT_STEP = 0.01;
|
|
37
24
|
|
|
38
25
|
const EasyCrop = react.forwardRef((props, ref) => {
|
|
39
|
-
const { cropperRef, zoomSlider, rotationSlider, aspectSlider, image, aspect:
|
|
40
|
-
const [crop, onCropChange] = react.useState({ x: 0, y: 0 });
|
|
26
|
+
const { cropperRef, zoomSlider, rotationSlider, aspectSlider, showReset, image, aspect: ASPECT_INITIAL, minZoom, maxZoom, cropShape, showGrid, cropperProps, isCN, } = props;
|
|
41
27
|
const [zoom, setZoom] = react.useState(ZOOM_INITIAL);
|
|
42
28
|
const [rotation, setRotation] = react.useState(ROTATION_INITIAL);
|
|
43
|
-
const [aspect, setAspect] = react.useState(
|
|
29
|
+
const [aspect, setAspect] = react.useState(ASPECT_INITIAL);
|
|
30
|
+
const isResetActive = zoom !== ZOOM_INITIAL ||
|
|
31
|
+
rotation !== ROTATION_INITIAL ||
|
|
32
|
+
aspect !== ASPECT_INITIAL;
|
|
33
|
+
const onReset = () => {
|
|
34
|
+
setZoom(ZOOM_INITIAL);
|
|
35
|
+
setRotation(ROTATION_INITIAL);
|
|
36
|
+
setAspect(ASPECT_INITIAL);
|
|
37
|
+
};
|
|
38
|
+
const [crop, onCropChange] = react.useState({ x: 0, y: 0 });
|
|
44
39
|
const cropPixelsRef = react.useRef({ width: 0, height: 0, x: 0, y: 0 });
|
|
45
40
|
const onCropComplete = react.useCallback((_, croppedAreaPixels) => {
|
|
46
41
|
cropPixelsRef.current = croppedAreaPixels;
|
|
@@ -51,18 +46,49 @@ const EasyCrop = react.forwardRef((props, ref) => {
|
|
|
51
46
|
setRotation,
|
|
52
47
|
cropPixelsRef,
|
|
53
48
|
}));
|
|
49
|
+
const wrapperClass = 'flex items-center w-3/5 mx-auto';
|
|
50
|
+
const buttonClass = 'flex items-center justify-center w-8 h-8 bg-transparent border-0 font-[inherit] text-[18px] cursor-pointer disabled:opacity-20 disabled:cursor-default';
|
|
51
|
+
const sliderClass = 'flex-1 mx-2';
|
|
54
52
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Cropper, Object.assign({}, cropperProps, { ref: cropperRef, image: image, crop: crop,
|
|
55
53
|
//
|
|
56
54
|
zoom: zoom, rotation: rotation, aspect: aspect, minZoom: minZoom, maxZoom: maxZoom, zoomWithScroll: zoomSlider,
|
|
57
55
|
//
|
|
58
56
|
cropShape: cropShape, showGrid: showGrid, onCropChange: onCropChange, onZoomChange: setZoom, onRotationChange: setRotation, onCropComplete: onCropComplete, classes: {
|
|
59
|
-
containerClassName: `${PREFIX}-container`,
|
|
57
|
+
containerClassName: `${PREFIX}-container !relative w-full h-[40vh] [&~section:first-of-type]:mt-4 [&~section:last-of-type]:mb-4`,
|
|
60
58
|
mediaClassName: `${PREFIX}-media`,
|
|
61
|
-
} })), zoomSlider && (jsxRuntime.jsxs("section", Object.assign({ className: `${PREFIX}-control ${PREFIX}-control-zoom` }, { children: [jsxRuntime.jsx("button", Object.assign({ onClick: () => setZoom(zoom - ZOOM_STEP), disabled:
|
|
59
|
+
} })), zoomSlider && (jsxRuntime.jsxs("section", Object.assign({ className: `${PREFIX}-control ${PREFIX}-control-zoom ${wrapperClass}` }, { children: [jsxRuntime.jsx("button", Object.assign({ className: buttonClass, onClick: () => setZoom(zoom - ZOOM_STEP), disabled: true }, { children: "\uFF0D" })), jsxRuntime.jsx(AntSlider, { className: sliderClass, min: minZoom, max: maxZoom, step: ZOOM_STEP, value: zoom, onChange: setZoom }), jsxRuntime.jsx("button", Object.assign({ className: buttonClass, onClick: () => setZoom(zoom + ZOOM_STEP), disabled: zoom + ZOOM_STEP > maxZoom }, { children: "\uFF0B" }))] }))), rotationSlider && (jsxRuntime.jsxs("section", Object.assign({ className: `${PREFIX}-control ${PREFIX}-control-rotation ${wrapperClass}` }, { children: [jsxRuntime.jsx("button", Object.assign({ className: `${buttonClass} !text-[16px]`, onClick: () => setRotation(rotation - ROTATION_STEP), disabled: rotation === ROTATION_MIN }, { children: "\u21BA" })), jsxRuntime.jsx(AntSlider, { className: sliderClass, min: ROTATION_MIN, max: ROTATION_MAX, step: ROTATION_STEP, value: rotation, onChange: setRotation }), jsxRuntime.jsx("button", Object.assign({ className: `${buttonClass} !text-[16px]`, onClick: () => setRotation(rotation + ROTATION_STEP), disabled: rotation === ROTATION_MAX }, { children: "\u21BB" }))] }))), aspectSlider && (jsxRuntime.jsxs("section", Object.assign({ className: `${PREFIX}-control ${PREFIX}-control-aspect ${wrapperClass}` }, { children: [jsxRuntime.jsx("button", Object.assign({ className: buttonClass, onClick: () => setAspect(aspect - ASPECT_STEP), disabled: aspect - ASPECT_STEP < ASPECT_MIN }, { children: "\u2195\uFE0F" })), jsxRuntime.jsx(AntSlider, { className: sliderClass, min: ASPECT_MIN, max: ASPECT_MAX, step: ASPECT_STEP, value: aspect, onChange: setAspect }), jsxRuntime.jsx("button", Object.assign({ className: buttonClass, onClick: () => setAspect(aspect + ASPECT_STEP), disabled: aspect + ASPECT_STEP > ASPECT_MAX }, { children: "\u2194\uFE0F" }))] }))), showReset && (zoomSlider || rotationSlider || aspectSlider) && (jsxRuntime.jsx(AntButton, Object.assign({ className: "absolute bottom-[20px]", style: isResetActive ? {} : { opacity: 0.3, pointerEvents: 'none' }, onClick: onReset }, { children: isCN ? '重置' : 'Reset' })))] }));
|
|
62
60
|
});
|
|
63
61
|
var EasyCrop$1 = react.memo(EasyCrop);
|
|
64
62
|
|
|
65
|
-
|
|
63
|
+
function styleInject(css, ref) {
|
|
64
|
+
if ( ref === void 0 ) ref = {};
|
|
65
|
+
var insertAt = ref.insertAt;
|
|
66
|
+
|
|
67
|
+
if (!css || typeof document === 'undefined') { return; }
|
|
68
|
+
|
|
69
|
+
var head = document.head || document.getElementsByTagName('head')[0];
|
|
70
|
+
var style = document.createElement('style');
|
|
71
|
+
style.type = 'text/css';
|
|
72
|
+
|
|
73
|
+
if (insertAt === 'top') {
|
|
74
|
+
if (head.firstChild) {
|
|
75
|
+
head.insertBefore(style, head.firstChild);
|
|
76
|
+
} else {
|
|
77
|
+
head.appendChild(style);
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
head.appendChild(style);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (style.styleSheet) {
|
|
84
|
+
style.styleSheet.cssText = css;
|
|
85
|
+
} else {
|
|
86
|
+
style.appendChild(document.createTextNode(css));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
var css_248z = ".container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.absolute{position:absolute}.\\!relative{position:relative!important}.bottom-\\[20px\\]{bottom:20px}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.flex{display:flex}.grid{display:grid}.h-8{height:2rem}.h-\\[40vh\\]{height:40vh}.w-3\\/5{width:60%}.w-8{width:2rem}.w-full{width:100%}.flex-1{flex:1 1 0%}.cursor-pointer{cursor:pointer}.items-center{align-items:center}.justify-center{justify-content:center}.border-0{border-width:0}.bg-transparent{background-color:transparent}.font-\\[inherit\\]{font-family:inherit}.\\!text-\\[16px\\]{font-size:16px!important}.text-\\[18px\\]{font-size:18px}.disabled\\:cursor-default:disabled{cursor:default}.disabled\\:opacity-20:disabled{opacity:.2}.\\[\\&\\~section\\:first-of-type\\]\\:mt-4~section:first-of-type{margin-top:1rem}.\\[\\&\\~section\\:last-of-type\\]\\:mb-4~section:last-of-type{margin-bottom:1rem}";
|
|
91
|
+
styleInject(css_248z);
|
|
66
92
|
|
|
67
93
|
const openKey = compareVersions.compareVersions(antd.version, '4.23.0') === -1 ? 'visible' : 'open';
|
|
68
94
|
const deprecate = (obj, old, now) => {
|
|
@@ -81,7 +107,7 @@ const ImgCrop = react.forwardRef((props, cropperRef) => {
|
|
|
81
107
|
// @ts-ignore
|
|
82
108
|
cropShape: CROP_SHAPE = 'rect',
|
|
83
109
|
// @ts-ignore
|
|
84
|
-
showGrid: SHOW_GRID = false, cropperProps, modalClassName, modalTitle, modalWidth, modalOk, modalCancel, onModalOk, onModalCancel, modalProps, beforeCrop, onUploadFail, children, } = props;
|
|
110
|
+
showGrid: SHOW_GRID = false, cropperProps, modalClassName, modalTitle, modalWidth, modalOk, modalCancel, showReset = false, onModalOk, onModalCancel, modalProps, beforeCrop, onUploadFail, children, } = props;
|
|
85
111
|
const cropShape = deprecate(props, 'shape', 'cropShape');
|
|
86
112
|
const showGrid = deprecate(props, 'grid', 'showGrid');
|
|
87
113
|
const zoomSlider = deprecate(props, 'zoom', 'zoomSlider');
|
|
@@ -234,14 +260,10 @@ const ImgCrop = react.forwardRef((props, cropperRef) => {
|
|
|
234
260
|
}), type, quality);
|
|
235
261
|
}), [fillColor, quality, rotationSlider]);
|
|
236
262
|
const wrapClassName = `${PREFIX}-modal${modalClassName ? ` ${modalClassName}` : ''}`;
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const lang = typeof window !== 'undefined' ? window.navigator.language : '';
|
|
242
|
-
return lang === 'zh-CN' ? '编辑图片' : 'Edit image';
|
|
243
|
-
}, [modalTitle]);
|
|
244
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [uploadComponent, image && (jsxRuntime.jsx(AntModal, Object.assign({}, modalProps, modalBaseProps, { [openKey]: true }, { title: title, onOk: onOk, onCancel: onCancel, wrapClassName: wrapClassName, maskClosable: false, destroyOnClose: true }, { children: jsxRuntime.jsx(EasyCrop$1, { ref: easyCropRef, cropperRef: cropperRef, zoomSlider: zoomSlider, rotationSlider: rotationSlider, aspectSlider: aspectSlider, image: image, aspect: aspect, minZoom: minZoom, maxZoom: maxZoom, cropShape: cropShape, showGrid: showGrid, cropperProps: cropperProps }) })))] }));
|
|
263
|
+
const lang = typeof window === 'undefined' ? '' : window.navigator.language;
|
|
264
|
+
const isCN = lang === 'zh-CN';
|
|
265
|
+
const title = modalTitle || (isCN ? '编辑图片' : 'Edit image');
|
|
266
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [uploadComponent, image && (jsxRuntime.jsx(AntModal, Object.assign({}, modalProps, modalBaseProps, { [openKey]: true }, { title: title, onOk: onOk, onCancel: onCancel, wrapClassName: wrapClassName, maskClosable: false, destroyOnClose: true }, { children: jsxRuntime.jsx(EasyCrop$1, { ref: easyCropRef, cropperRef: cropperRef, zoomSlider: zoomSlider, rotationSlider: rotationSlider, aspectSlider: aspectSlider, showReset: showReset, image: image, aspect: aspect, minZoom: minZoom, maxZoom: maxZoom, cropShape: cropShape, showGrid: showGrid, cropperProps: cropperProps, isCN: isCN }) })))] }));
|
|
245
267
|
});
|
|
246
268
|
|
|
247
269
|
module.exports = ImgCrop;
|
package/dist/antd-img-crop.d.ts
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
function __$styleInject(css) {
|
|
2
|
-
if (!css) return;
|
|
3
|
-
|
|
4
|
-
if (typeof window == 'undefined') return;
|
|
5
|
-
var style = document.createElement('style');
|
|
6
|
-
style.setAttribute('media', 'screen');
|
|
7
|
-
|
|
8
|
-
style.innerHTML = css;
|
|
9
|
-
document.head.appendChild(style);
|
|
10
|
-
return css;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
1
|
import { __rest, __awaiter } from 'tslib';
|
|
14
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
15
3
|
import { forwardRef, useState, useRef, useCallback, useImperativeHandle, memo, useMemo } from 'react';
|
|
@@ -18,6 +6,7 @@ import AntModal from 'antd/es/modal';
|
|
|
18
6
|
import AntUpload from 'antd/es/upload';
|
|
19
7
|
import { compareVersions } from 'compare-versions';
|
|
20
8
|
import Cropper from 'react-easy-crop';
|
|
9
|
+
import AntButton from 'antd/es/button';
|
|
21
10
|
import AntSlider from 'antd/es/slider';
|
|
22
11
|
|
|
23
12
|
const PREFIX = 'img-crop';
|
|
@@ -32,11 +21,19 @@ const ASPECT_MAX = 2;
|
|
|
32
21
|
const ASPECT_STEP = 0.01;
|
|
33
22
|
|
|
34
23
|
const EasyCrop = forwardRef((props, ref) => {
|
|
35
|
-
const { cropperRef, zoomSlider, rotationSlider, aspectSlider, image, aspect:
|
|
36
|
-
const [crop, onCropChange] = useState({ x: 0, y: 0 });
|
|
24
|
+
const { cropperRef, zoomSlider, rotationSlider, aspectSlider, showReset, image, aspect: ASPECT_INITIAL, minZoom, maxZoom, cropShape, showGrid, cropperProps, isCN, } = props;
|
|
37
25
|
const [zoom, setZoom] = useState(ZOOM_INITIAL);
|
|
38
26
|
const [rotation, setRotation] = useState(ROTATION_INITIAL);
|
|
39
|
-
const [aspect, setAspect] = useState(
|
|
27
|
+
const [aspect, setAspect] = useState(ASPECT_INITIAL);
|
|
28
|
+
const isResetActive = zoom !== ZOOM_INITIAL ||
|
|
29
|
+
rotation !== ROTATION_INITIAL ||
|
|
30
|
+
aspect !== ASPECT_INITIAL;
|
|
31
|
+
const onReset = () => {
|
|
32
|
+
setZoom(ZOOM_INITIAL);
|
|
33
|
+
setRotation(ROTATION_INITIAL);
|
|
34
|
+
setAspect(ASPECT_INITIAL);
|
|
35
|
+
};
|
|
36
|
+
const [crop, onCropChange] = useState({ x: 0, y: 0 });
|
|
40
37
|
const cropPixelsRef = useRef({ width: 0, height: 0, x: 0, y: 0 });
|
|
41
38
|
const onCropComplete = useCallback((_, croppedAreaPixels) => {
|
|
42
39
|
cropPixelsRef.current = croppedAreaPixels;
|
|
@@ -47,18 +44,49 @@ const EasyCrop = forwardRef((props, ref) => {
|
|
|
47
44
|
setRotation,
|
|
48
45
|
cropPixelsRef,
|
|
49
46
|
}));
|
|
47
|
+
const wrapperClass = 'flex items-center w-3/5 mx-auto';
|
|
48
|
+
const buttonClass = 'flex items-center justify-center w-8 h-8 bg-transparent border-0 font-[inherit] text-[18px] cursor-pointer disabled:opacity-20 disabled:cursor-default';
|
|
49
|
+
const sliderClass = 'flex-1 mx-2';
|
|
50
50
|
return (jsxs(Fragment, { children: [jsx(Cropper, Object.assign({}, cropperProps, { ref: cropperRef, image: image, crop: crop,
|
|
51
51
|
//
|
|
52
52
|
zoom: zoom, rotation: rotation, aspect: aspect, minZoom: minZoom, maxZoom: maxZoom, zoomWithScroll: zoomSlider,
|
|
53
53
|
//
|
|
54
54
|
cropShape: cropShape, showGrid: showGrid, onCropChange: onCropChange, onZoomChange: setZoom, onRotationChange: setRotation, onCropComplete: onCropComplete, classes: {
|
|
55
|
-
containerClassName: `${PREFIX}-container`,
|
|
55
|
+
containerClassName: `${PREFIX}-container !relative w-full h-[40vh] [&~section:first-of-type]:mt-4 [&~section:last-of-type]:mb-4`,
|
|
56
56
|
mediaClassName: `${PREFIX}-media`,
|
|
57
|
-
} })), zoomSlider && (jsxs("section", Object.assign({ className: `${PREFIX}-control ${PREFIX}-control-zoom` }, { children: [jsx("button", Object.assign({ onClick: () => setZoom(zoom - ZOOM_STEP), disabled:
|
|
57
|
+
} })), zoomSlider && (jsxs("section", Object.assign({ className: `${PREFIX}-control ${PREFIX}-control-zoom ${wrapperClass}` }, { children: [jsx("button", Object.assign({ className: buttonClass, onClick: () => setZoom(zoom - ZOOM_STEP), disabled: true }, { children: "\uFF0D" })), jsx(AntSlider, { className: sliderClass, min: minZoom, max: maxZoom, step: ZOOM_STEP, value: zoom, onChange: setZoom }), jsx("button", Object.assign({ className: buttonClass, onClick: () => setZoom(zoom + ZOOM_STEP), disabled: zoom + ZOOM_STEP > maxZoom }, { children: "\uFF0B" }))] }))), rotationSlider && (jsxs("section", Object.assign({ className: `${PREFIX}-control ${PREFIX}-control-rotation ${wrapperClass}` }, { children: [jsx("button", Object.assign({ className: `${buttonClass} !text-[16px]`, onClick: () => setRotation(rotation - ROTATION_STEP), disabled: rotation === ROTATION_MIN }, { children: "\u21BA" })), jsx(AntSlider, { className: sliderClass, min: ROTATION_MIN, max: ROTATION_MAX, step: ROTATION_STEP, value: rotation, onChange: setRotation }), jsx("button", Object.assign({ className: `${buttonClass} !text-[16px]`, onClick: () => setRotation(rotation + ROTATION_STEP), disabled: rotation === ROTATION_MAX }, { children: "\u21BB" }))] }))), aspectSlider && (jsxs("section", Object.assign({ className: `${PREFIX}-control ${PREFIX}-control-aspect ${wrapperClass}` }, { children: [jsx("button", Object.assign({ className: buttonClass, onClick: () => setAspect(aspect - ASPECT_STEP), disabled: aspect - ASPECT_STEP < ASPECT_MIN }, { children: "\u2195\uFE0F" })), jsx(AntSlider, { className: sliderClass, min: ASPECT_MIN, max: ASPECT_MAX, step: ASPECT_STEP, value: aspect, onChange: setAspect }), jsx("button", Object.assign({ className: buttonClass, onClick: () => setAspect(aspect + ASPECT_STEP), disabled: aspect + ASPECT_STEP > ASPECT_MAX }, { children: "\u2194\uFE0F" }))] }))), showReset && (zoomSlider || rotationSlider || aspectSlider) && (jsx(AntButton, Object.assign({ className: "absolute bottom-[20px]", style: isResetActive ? {} : { opacity: 0.3, pointerEvents: 'none' }, onClick: onReset }, { children: isCN ? '重置' : 'Reset' })))] }));
|
|
58
58
|
});
|
|
59
59
|
var EasyCrop$1 = memo(EasyCrop);
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
function styleInject(css, ref) {
|
|
62
|
+
if ( ref === void 0 ) ref = {};
|
|
63
|
+
var insertAt = ref.insertAt;
|
|
64
|
+
|
|
65
|
+
if (!css || typeof document === 'undefined') { return; }
|
|
66
|
+
|
|
67
|
+
var head = document.head || document.getElementsByTagName('head')[0];
|
|
68
|
+
var style = document.createElement('style');
|
|
69
|
+
style.type = 'text/css';
|
|
70
|
+
|
|
71
|
+
if (insertAt === 'top') {
|
|
72
|
+
if (head.firstChild) {
|
|
73
|
+
head.insertBefore(style, head.firstChild);
|
|
74
|
+
} else {
|
|
75
|
+
head.appendChild(style);
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
head.appendChild(style);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (style.styleSheet) {
|
|
82
|
+
style.styleSheet.cssText = css;
|
|
83
|
+
} else {
|
|
84
|
+
style.appendChild(document.createTextNode(css));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var css_248z = ".container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.absolute{position:absolute}.\\!relative{position:relative!important}.bottom-\\[20px\\]{bottom:20px}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.flex{display:flex}.grid{display:grid}.h-8{height:2rem}.h-\\[40vh\\]{height:40vh}.w-3\\/5{width:60%}.w-8{width:2rem}.w-full{width:100%}.flex-1{flex:1 1 0%}.cursor-pointer{cursor:pointer}.items-center{align-items:center}.justify-center{justify-content:center}.border-0{border-width:0}.bg-transparent{background-color:transparent}.font-\\[inherit\\]{font-family:inherit}.\\!text-\\[16px\\]{font-size:16px!important}.text-\\[18px\\]{font-size:18px}.disabled\\:cursor-default:disabled{cursor:default}.disabled\\:opacity-20:disabled{opacity:.2}.\\[\\&\\~section\\:first-of-type\\]\\:mt-4~section:first-of-type{margin-top:1rem}.\\[\\&\\~section\\:last-of-type\\]\\:mb-4~section:last-of-type{margin-bottom:1rem}";
|
|
89
|
+
styleInject(css_248z);
|
|
62
90
|
|
|
63
91
|
const openKey = compareVersions(version, '4.23.0') === -1 ? 'visible' : 'open';
|
|
64
92
|
const deprecate = (obj, old, now) => {
|
|
@@ -77,7 +105,7 @@ const ImgCrop = forwardRef((props, cropperRef) => {
|
|
|
77
105
|
// @ts-ignore
|
|
78
106
|
cropShape: CROP_SHAPE = 'rect',
|
|
79
107
|
// @ts-ignore
|
|
80
|
-
showGrid: SHOW_GRID = false, cropperProps, modalClassName, modalTitle, modalWidth, modalOk, modalCancel, onModalOk, onModalCancel, modalProps, beforeCrop, onUploadFail, children, } = props;
|
|
108
|
+
showGrid: SHOW_GRID = false, cropperProps, modalClassName, modalTitle, modalWidth, modalOk, modalCancel, showReset = false, onModalOk, onModalCancel, modalProps, beforeCrop, onUploadFail, children, } = props;
|
|
81
109
|
const cropShape = deprecate(props, 'shape', 'cropShape');
|
|
82
110
|
const showGrid = deprecate(props, 'grid', 'showGrid');
|
|
83
111
|
const zoomSlider = deprecate(props, 'zoom', 'zoomSlider');
|
|
@@ -230,14 +258,10 @@ const ImgCrop = forwardRef((props, cropperRef) => {
|
|
|
230
258
|
}), type, quality);
|
|
231
259
|
}), [fillColor, quality, rotationSlider]);
|
|
232
260
|
const wrapClassName = `${PREFIX}-modal${modalClassName ? ` ${modalClassName}` : ''}`;
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const lang = typeof window !== 'undefined' ? window.navigator.language : '';
|
|
238
|
-
return lang === 'zh-CN' ? '编辑图片' : 'Edit image';
|
|
239
|
-
}, [modalTitle]);
|
|
240
|
-
return (jsxs(Fragment, { children: [uploadComponent, image && (jsx(AntModal, Object.assign({}, modalProps, modalBaseProps, { [openKey]: true }, { title: title, onOk: onOk, onCancel: onCancel, wrapClassName: wrapClassName, maskClosable: false, destroyOnClose: true }, { children: jsx(EasyCrop$1, { ref: easyCropRef, cropperRef: cropperRef, zoomSlider: zoomSlider, rotationSlider: rotationSlider, aspectSlider: aspectSlider, image: image, aspect: aspect, minZoom: minZoom, maxZoom: maxZoom, cropShape: cropShape, showGrid: showGrid, cropperProps: cropperProps }) })))] }));
|
|
261
|
+
const lang = typeof window === 'undefined' ? '' : window.navigator.language;
|
|
262
|
+
const isCN = lang === 'zh-CN';
|
|
263
|
+
const title = modalTitle || (isCN ? '编辑图片' : 'Edit image');
|
|
264
|
+
return (jsxs(Fragment, { children: [uploadComponent, image && (jsx(AntModal, Object.assign({}, modalProps, modalBaseProps, { [openKey]: true }, { title: title, onOk: onOk, onCancel: onCancel, wrapClassName: wrapClassName, maskClosable: false, destroyOnClose: true }, { children: jsx(EasyCrop$1, { ref: easyCropRef, cropperRef: cropperRef, zoomSlider: zoomSlider, rotationSlider: rotationSlider, aspectSlider: aspectSlider, showReset: showReset, image: image, aspect: aspect, minZoom: minZoom, maxZoom: maxZoom, cropShape: cropShape, showGrid: showGrid, cropperProps: cropperProps, isCN: isCN }) })))] }));
|
|
241
265
|
});
|
|
242
266
|
|
|
243
267
|
export { ImgCrop as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "antd-img-crop",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.1",
|
|
4
4
|
"description": "An image cropper for Ant Design Upload",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -36,23 +36,26 @@
|
|
|
36
36
|
"@rollup/plugin-replace": "^5.0.2",
|
|
37
37
|
"@rollup/plugin-typescript": "^11.0.0",
|
|
38
38
|
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
|
|
39
|
-
"@types/node": "^18.15.
|
|
39
|
+
"@types/node": "^18.15.3",
|
|
40
40
|
"@types/react": "^18.0.28",
|
|
41
41
|
"@types/react-dom": "^18.0.11",
|
|
42
|
-
"@types/rollup-plugin-less": "^1.1.2",
|
|
43
42
|
"@vitejs/plugin-react": "^3.1.0",
|
|
44
43
|
"antd": "^5.3.1",
|
|
44
|
+
"autoprefixer": "^10.4.14",
|
|
45
45
|
"eslint": "^8.36.0",
|
|
46
46
|
"eslint-config-prettier": "^8.7.0",
|
|
47
47
|
"eslint-config-react-app": "^7.0.1",
|
|
48
|
+
"postcss": "^8.4.21",
|
|
48
49
|
"prettier": "^2.8.4",
|
|
50
|
+
"prettier-plugin-tailwindcss": "^0.2.5",
|
|
49
51
|
"react": "^18.2.0",
|
|
50
52
|
"react-dom": "^18.2.0",
|
|
51
53
|
"rollup": "3.19.1",
|
|
52
|
-
"rollup-plugin-dts": "^5.
|
|
53
|
-
"rollup-plugin-
|
|
54
|
-
"
|
|
55
|
-
"
|
|
54
|
+
"rollup-plugin-dts": "^5.3.0",
|
|
55
|
+
"rollup-plugin-postcss": "^4.0.2",
|
|
56
|
+
"tailwindcss": "^3.2.7",
|
|
57
|
+
"typescript": "^5.0.2",
|
|
58
|
+
"vite": "^4.2.0"
|
|
56
59
|
},
|
|
57
60
|
"scripts": {
|
|
58
61
|
"build": "rm -rf dist && rollup -c --configPlugin @rollup/plugin-typescript"
|