@antscorp/antsomi-ui 1.3.5-beta.261 → 1.3.5-beta.263
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/es/components/common/ConfigProvider/GlobalStyle.js +5 -0
- package/es/components/molecules/ImageEditor/ImageEditor.d.ts +18 -0
- package/es/components/molecules/ImageEditor/ImageEditor.js +774 -0
- package/es/components/molecules/ImageEditor/index.d.ts +1 -7
- package/es/components/molecules/ImageEditor/index.js +1 -555
- package/es/components/molecules/ImageEditor/reducer.d.ts +1 -1
- package/es/components/molecules/ImageEditor/styled.d.ts +4 -3
- package/es/components/molecules/ImageEditor/styled.js +12 -6
- package/es/components/molecules/ImageResizeTuiEditor/ImageResizeTuiEditor.d.ts +12 -0
- package/es/components/molecules/ImageResizeTuiEditor/ImageResizeTuiEditor.js +73 -0
- package/es/components/molecules/ImageResizeTuiEditor/index.d.ts +1 -0
- package/es/components/molecules/ImageResizeTuiEditor/index.js +1 -0
- package/es/components/molecules/ImageResizeTuiEditor/types.d.ts +5 -0
- package/es/components/molecules/ImageResizeTuiEditor/types.js +1 -0
- package/es/components/molecules/TemplateSaveAs/TemplateSaveAs.d.ts +4 -0
- package/es/components/molecules/TemplateSaveAs/TemplateSaveAs.js +5 -3
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/BigImage.d.ts +2 -0
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/BigImage.js +12 -6
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/ImageSlider.d.ts +5 -0
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/ImageSlider.js +92 -8
- package/es/components/molecules/TemplateSaveAs/components/ImageSlider/styled.js +70 -5
- package/es/components/molecules/TemplateSaveAs/styled.js +22 -0
- package/es/components/molecules/index.d.ts +2 -0
- package/es/components/molecules/index.js +1 -0
- package/es/providers/ConfigProvider/GlobalStyle.js +5 -0
- package/es/test.js +4 -4
- package/package.json +2 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useEffect, useImperativeHandle, useRef } from 'react';
|
|
2
|
+
import { fabric } from 'fabric';
|
|
3
|
+
const ImageResizeTuiEditor = React.forwardRef(({ className, imageUrl, width, height, defaultValue, hideAction }, ref) => {
|
|
4
|
+
const loadRef = useRef(false);
|
|
5
|
+
const fabricCanvasRef = useRef(null);
|
|
6
|
+
const canvasRef = useRef(null);
|
|
7
|
+
const resetScaleImage = img => {
|
|
8
|
+
const widthRatio = width / img.width;
|
|
9
|
+
const heightRatio = height / img.height;
|
|
10
|
+
img.set({ left: 0, top: 0 }).scale(Math.min(widthRatio, heightRatio));
|
|
11
|
+
img.set({ left: (width - img.oCoords.br.x) / 2, top: (height - img.oCoords.br.y) / 2 });
|
|
12
|
+
img.set({
|
|
13
|
+
borderColor: '#00a1ff',
|
|
14
|
+
cornerColor: '#fff',
|
|
15
|
+
cornerSize: 10,
|
|
16
|
+
cornerStrokeColor: '#00a1ff',
|
|
17
|
+
// transparentCorners: true,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const loadImage = url => {
|
|
21
|
+
fabric.Image.fromURL(url, img => {
|
|
22
|
+
var _a;
|
|
23
|
+
resetScaleImage(img);
|
|
24
|
+
(_a = fabricCanvasRef.current) === null || _a === void 0 ? void 0 : _a.add(img);
|
|
25
|
+
}, {
|
|
26
|
+
crossOrigin: '',
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const changeImage = url => {
|
|
30
|
+
var _a;
|
|
31
|
+
(_a = fabricCanvasRef.current) === null || _a === void 0 ? void 0 : _a.forEachObject(obj => {
|
|
32
|
+
var _a;
|
|
33
|
+
(_a = fabricCanvasRef.current) === null || _a === void 0 ? void 0 : _a.remove(obj);
|
|
34
|
+
});
|
|
35
|
+
loadImage(url);
|
|
36
|
+
};
|
|
37
|
+
useImperativeHandle(ref, () => ({
|
|
38
|
+
getBase64(options) {
|
|
39
|
+
var _a;
|
|
40
|
+
const dataURL = (_a = fabricCanvasRef.current) === null || _a === void 0 ? void 0 : _a.toDataURL(Object.assign({ format: 'png', quality: 1 }, options));
|
|
41
|
+
return dataURL;
|
|
42
|
+
},
|
|
43
|
+
replaceImageWithUrl(imageUrl) {
|
|
44
|
+
changeImage(imageUrl);
|
|
45
|
+
},
|
|
46
|
+
getCurrentState() {
|
|
47
|
+
return fabricCanvasRef.current;
|
|
48
|
+
},
|
|
49
|
+
}), []);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (loadRef.current) {
|
|
52
|
+
changeImage(imageUrl);
|
|
53
|
+
}
|
|
54
|
+
loadRef.current = true;
|
|
55
|
+
fabricCanvasRef.current = new fabric.Canvas('tui-image-editor', {
|
|
56
|
+
width,
|
|
57
|
+
height,
|
|
58
|
+
});
|
|
59
|
+
fabric.Object.prototype.transparentCorners = false;
|
|
60
|
+
if (imageUrl) {
|
|
61
|
+
loadImage(imageUrl);
|
|
62
|
+
}
|
|
63
|
+
else if (defaultValue) {
|
|
64
|
+
defaultValue.forEachObject(obj => {
|
|
65
|
+
var _a;
|
|
66
|
+
(_a = fabricCanvasRef.current) === null || _a === void 0 ? void 0 : _a.add(obj);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}, [imageUrl]);
|
|
70
|
+
return (React.createElement("div", { className: className },
|
|
71
|
+
React.createElement("canvas", { ref: canvasRef, id: "tui-image-editor", style: { width, height } })));
|
|
72
|
+
});
|
|
73
|
+
export { ImageResizeTuiEditor };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ImageResizeTuiEditor } from './ImageResizeTuiEditor';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ImageResizeTuiEditor } from './ImageResizeTuiEditor';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -76,6 +76,10 @@ export interface TemplateSaveAsProps {
|
|
|
76
76
|
form?: FormInstance<FormValue>;
|
|
77
77
|
value?: TemplateValueOptions;
|
|
78
78
|
onChange?: (value: Partial<TemplateValueOptions>, errors?: any[]) => void;
|
|
79
|
+
onSaveThumbnail?: (data: {
|
|
80
|
+
thumbnails: (string | undefined)[];
|
|
81
|
+
thumbnailChange: number;
|
|
82
|
+
}) => void;
|
|
79
83
|
onEvent?: (value: Partial<TemplateValueOptions>) => void;
|
|
80
84
|
}
|
|
81
85
|
export declare const TemplateSaveAs: React.FC<TemplateSaveAsProps>;
|
|
@@ -27,12 +27,12 @@ export const TemplateSaveAs = props => {
|
|
|
27
27
|
var _a;
|
|
28
28
|
const { className, shareAccess, saveOptions, imageReview, isLoadingCategories, categories, omitCategories, templateNames: templateNameList, templateNamesOptions, descriptionOptions,
|
|
29
29
|
// form,
|
|
30
|
-
form: formProps, value, onChange, onEvent, } = props;
|
|
30
|
+
form: formProps, value, onChange, onEvent, onSaveThumbnail, } = props;
|
|
31
31
|
const [internalForm] = Form.useForm();
|
|
32
32
|
const form = formProps || internalForm;
|
|
33
33
|
const { show: isShowShareAccess } = shareAccess, shareAccessProps = __rest(shareAccess, ["show"]);
|
|
34
34
|
const { label: imageReviewLabel } = imageReview, restImageReviewProps = __rest(imageReview, ["label"]);
|
|
35
|
-
console.log('🚀 ~ restImageReviewProps:', restImageReviewProps);
|
|
35
|
+
// console.log('🚀 ~ restImageReviewProps:', restImageReviewProps);
|
|
36
36
|
const { isLoading, label: templateLabel, defaultNewTemplateName = `Untitled Media Template#${dayjs().format('YYYY-MM-DD HH:mm:ss')}`, selectPlaceholder = 'Please select an item', placeholder = 'Enter your media template name', validateName, onSearch, onNamePopupScroll, onScrollToBottom, } = templateNamesOptions || {};
|
|
37
37
|
const { label: descriptionLabel, placeholder: descriptionPlaceholder } = descriptionOptions || {};
|
|
38
38
|
const { saveNewText = 'Save as a new media template', saveExistText = 'Save as an existing media template', saveNewValue = 'save-new', saveExistValue = 'save-exist', } = saveOptions || {};
|
|
@@ -213,7 +213,9 @@ export const TemplateSaveAs = props => {
|
|
|
213
213
|
React.createElement(ImageSlider, Object.assign({ defaultThumbnail: defaultThumbnailValue, onSelectDefault: value => {
|
|
214
214
|
form.setFieldValue('defaultThumbnail', value);
|
|
215
215
|
handleChangeValue({ defaultThumbnail: value });
|
|
216
|
-
}
|
|
216
|
+
},
|
|
217
|
+
// onSelectDefault={value => handleChangeValue({ defaultThumbnail: value })}
|
|
218
|
+
onSaveThumbnail: data => onSaveThumbnail === null || onSaveThumbnail === void 0 ? void 0 : onSaveThumbnail(data) }, restImageReviewProps))),
|
|
217
219
|
isLoadingCategories ? (React.createElement(Flex, { className: "field-container" },
|
|
218
220
|
React.createElement(Text, { className: "field-title" }, "Categories"),
|
|
219
221
|
React.createElement(Space, { style: {
|
|
@@ -7,6 +7,8 @@ interface BigImageProps {
|
|
|
7
7
|
imageFit?: React.CSSProperties['objectFit'];
|
|
8
8
|
index: number;
|
|
9
9
|
onClickDefaultButton?: (index: number) => void;
|
|
10
|
+
onClickEdit?: (index: number) => void;
|
|
11
|
+
onClickUpload?: (index: number) => void;
|
|
10
12
|
}
|
|
11
13
|
export declare const BigImage: React.FC<BigImageProps>;
|
|
12
14
|
export {};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
|
-
import { Image } from 'antd';
|
|
3
|
-
import { Button } from '@antscorp/antsomi-ui/es/components';
|
|
2
|
+
import { ConfigProvider, Image, Tooltip } from 'antd';
|
|
3
|
+
import { Button, Flex, Checkbox } from '@antscorp/antsomi-ui/es/components';
|
|
4
4
|
import Icon from '@antscorp/icons';
|
|
5
5
|
import { checkShowSkeletonBaseUrl, getUrlNoCache } from '@antscorp/antsomi-ui/es/utils';
|
|
6
6
|
export const BigImage = React.memo(props => {
|
|
7
|
-
const { url, isDefaultThumbnail, isHideDefaultButton, index, showSkeleton, imageFit, onClickDefaultButton, } = props;
|
|
7
|
+
const { url, isDefaultThumbnail, isHideDefaultButton, index, showSkeleton, imageFit, onClickDefaultButton, onClickEdit, onClickUpload, } = props;
|
|
8
8
|
const currentTime = useMemo(() => new Date(), []);
|
|
9
9
|
const timeGenerated = Math.floor(currentTime.getTime() / 1000 - (currentTime.getTime() % 3)) * 1000;
|
|
10
10
|
const urlNoCache = getUrlNoCache(url, timeGenerated);
|
|
@@ -13,7 +13,13 @@ export const BigImage = React.memo(props => {
|
|
|
13
13
|
url ? (React.createElement(Image, { preview: false, width: "100%", height: "100%", src: urlNoCache, style: { objectFit: imageFit }, onError: e => {
|
|
14
14
|
e.currentTarget.style.display = 'none';
|
|
15
15
|
} })) : null,
|
|
16
|
-
isHideDefaultButton ? null : (React.createElement(
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
isHideDefaultButton || !isDefaultThumbnail ? null : (React.createElement(ConfigProvider, { theme: {
|
|
17
|
+
components: { Checkbox: { borderRadiusSM: 1000 }, Tooltip: { borderRadius: 10 } },
|
|
18
|
+
} },
|
|
19
|
+
React.createElement(Tooltip, { title: "Default thumbnail", zIndex: 5000 },
|
|
20
|
+
React.createElement(Checkbox, { checked: true, className: "default-checkbox" })))),
|
|
21
|
+
React.createElement(Flex, { className: "set-default-button", gap: 8 },
|
|
22
|
+
isHideDefaultButton || isDefaultThumbnail ? null : (React.createElement(Button, { onClick: () => onClickDefaultButton && onClickDefaultButton(index) }, "Set as default")),
|
|
23
|
+
React.createElement(Button, { icon: React.createElement(Icon, { type: "icon-ants-pencil" }), size: "middle", style: { fontSize: '14px' }, onClick: () => onClickEdit === null || onClickEdit === void 0 ? void 0 : onClickEdit(index) }),
|
|
24
|
+
React.createElement(Button, { icon: React.createElement(Icon, { type: "icon-ants-file-upload" }), size: "middle", style: { fontSize: '14px' }, onClick: () => onClickUpload === null || onClickUpload === void 0 ? void 0 : onClickUpload(index) }))));
|
|
19
25
|
});
|
|
@@ -11,11 +11,16 @@ export interface ImageSliderProps {
|
|
|
11
11
|
imageWidth?: number;
|
|
12
12
|
imageHeight?: number;
|
|
13
13
|
infinity?: boolean;
|
|
14
|
+
useFabric?: boolean;
|
|
14
15
|
thumbnailFit?: React.CSSProperties['objectFit'];
|
|
15
16
|
/**
|
|
16
17
|
* Default thumbnail - order of default thumbnail in thumbnails array
|
|
17
18
|
*/
|
|
18
19
|
defaultThumbnail?: number;
|
|
19
20
|
onSelectDefault?: (imgIndex: number) => void;
|
|
21
|
+
onSaveThumbnail?: (data: {
|
|
22
|
+
thumbnails: (string | undefined)[];
|
|
23
|
+
thumbnailChange: number;
|
|
24
|
+
}) => void;
|
|
20
25
|
}
|
|
21
26
|
export declare const ImageSlider: React.FC<ImageSliderProps>;
|
|
@@ -2,22 +2,30 @@
|
|
|
2
2
|
import React, { useState, useRef, useMemo, useCallback, useEffect } from 'react';
|
|
3
3
|
import Icon from '@antscorp/icons';
|
|
4
4
|
// Components
|
|
5
|
-
import { Flex, Spin } from '@antscorp/antsomi-ui/es/components';
|
|
5
|
+
import { Button, Flex, ImageResize, message, Spin, Typography, ImageResizeTuiEditor, } from '@antscorp/antsomi-ui/es/components';
|
|
6
6
|
// Styles
|
|
7
7
|
import { ImageSliderStyled } from './styled';
|
|
8
8
|
import { SmallImage } from './SmallImage';
|
|
9
9
|
import { BigImage } from './BigImage';
|
|
10
|
+
import { useDropFile } from '@antscorp/antsomi-ui/es/hooks';
|
|
11
|
+
import { checkShowSkeletonBaseUrl, getUrlNoCache } from '@antscorp/antsomi-ui/es/utils';
|
|
12
|
+
// Image size limit to 10MB
|
|
13
|
+
const SIZE_LIMIT = 10 * 1024 * 1024;
|
|
10
14
|
const ButtonSlider = React.memo(({ direction, type, onClick }) => (React.createElement("div", { className: type === 'slider'
|
|
11
15
|
? `slider-button slider-button--${direction}`
|
|
12
16
|
: `change-preview-button change-preview-button--${direction}`, onClick: onClick },
|
|
13
17
|
React.createElement(Icon, { type: `icon-ants-angle-${direction}` }))));
|
|
14
18
|
export const ImageSlider = props => {
|
|
15
|
-
const { thumbnails, isLoading, className, skeleton, previewNavigation, slidesPerView = 3, hideThumbnailsList, hideDefaultButton, imageWidth = 330, imageHeight = 230, infinity = true, defaultThumbnail, thumbnailFit, onSelectDefault, } = props;
|
|
19
|
+
const { thumbnails, isLoading, className, skeleton, previewNavigation, slidesPerView = 3, hideThumbnailsList, hideDefaultButton, imageWidth = 330, imageHeight = 230, infinity = true, defaultThumbnail, thumbnailFit, onSelectDefault, onSaveThumbnail, useFabric = false, } = props;
|
|
16
20
|
const sliderContainerRef = useRef(null);
|
|
17
21
|
const thumbnailSelectedRef = useRef(null);
|
|
22
|
+
const imageResizeRef = useRef(null);
|
|
18
23
|
const smallImageWidth = useMemo(() => imageWidth / slidesPerView - (10 * (slidesPerView - 1)) / slidesPerView, [imageWidth, slidesPerView]);
|
|
19
24
|
const [selectedThumbnail, setSelectedThumbnail] = useState(0);
|
|
20
25
|
const [defaultThumbnailInternal, setDefaultThumbnailInternal] = useState(defaultThumbnail || 0);
|
|
26
|
+
const [editingThumbnail, setEditingThumbnail] = useState();
|
|
27
|
+
const [uploadThumbnail, setUploadThumbnail] = useState();
|
|
28
|
+
const [latestCanvas, setLatestCanvas] = useState();
|
|
21
29
|
// Effects
|
|
22
30
|
useEffect(() => {
|
|
23
31
|
setDefaultThumbnailInternal(defaultThumbnail || 0);
|
|
@@ -33,16 +41,17 @@ export const ImageSlider = props => {
|
|
|
33
41
|
behavior: 'smooth',
|
|
34
42
|
});
|
|
35
43
|
}, [imageWidth, smallImageWidth]);
|
|
44
|
+
const thumbnailsQuantity = thumbnails.length;
|
|
36
45
|
const handleNextThumbnail = useCallback(() => {
|
|
37
46
|
setSelectedThumbnail(prev => {
|
|
38
|
-
const newValue = prev ===
|
|
47
|
+
const newValue = prev === thumbnailsQuantity - 1 ? 0 : prev + 1;
|
|
39
48
|
handleScroll(newValue);
|
|
40
49
|
return newValue;
|
|
41
50
|
});
|
|
42
51
|
}, [thumbnails, handleScroll]);
|
|
43
52
|
const handlePrevThumbnail = useCallback(() => {
|
|
44
53
|
setSelectedThumbnail(prev => {
|
|
45
|
-
const newValue = prev === 0 ?
|
|
54
|
+
const newValue = prev === 0 ? thumbnailsQuantity - 1 : prev - 1;
|
|
46
55
|
handleScroll(newValue);
|
|
47
56
|
return newValue;
|
|
48
57
|
});
|
|
@@ -58,13 +67,88 @@ export const ImageSlider = props => {
|
|
|
58
67
|
onSelectDefault(index);
|
|
59
68
|
}
|
|
60
69
|
}, [onSelectDefault]);
|
|
70
|
+
const handleSaveThumbnail = () => {
|
|
71
|
+
var _a;
|
|
72
|
+
const newThumbnail = [...thumbnails];
|
|
73
|
+
// NOTE: https://konvajs.org/docs/data_and_serialization/High-Quality-Export.html
|
|
74
|
+
newThumbnail[selectedThumbnail] = (_a = imageResizeRef.current) === null || _a === void 0 ? void 0 : _a.getBase64({ pixelRatio: 2.5 });
|
|
75
|
+
onSaveThumbnail === null || onSaveThumbnail === void 0 ? void 0 : onSaveThumbnail({ thumbnails: newThumbnail, thumbnailChange: selectedThumbnail });
|
|
76
|
+
setLatestCanvas(prev => {
|
|
77
|
+
var _a;
|
|
78
|
+
return (Object.assign(Object.assign({}, prev), { [selectedThumbnail]: (_a = imageResizeRef.current) === null || _a === void 0 ? void 0 : _a.getCurrentState() }));
|
|
79
|
+
});
|
|
80
|
+
setEditingThumbnail(undefined);
|
|
81
|
+
};
|
|
82
|
+
const fileRef = useRef(null);
|
|
83
|
+
const onImportImageClick = useCallback(() => {
|
|
84
|
+
var _a;
|
|
85
|
+
(_a = fileRef === null || fileRef === void 0 ? void 0 : fileRef.current) === null || _a === void 0 ? void 0 : _a.click();
|
|
86
|
+
}, []);
|
|
87
|
+
const onImportImageSelect = (e) => {
|
|
88
|
+
var _a, _b, _c;
|
|
89
|
+
if ((_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0]) {
|
|
90
|
+
if (((_b = e.target.files) === null || _b === void 0 ? void 0 : _b[0].size) > SIZE_LIMIT) {
|
|
91
|
+
return message.error('File size too big');
|
|
92
|
+
}
|
|
93
|
+
(_c = imageResizeRef.current) === null || _c === void 0 ? void 0 : _c.replaceImageWithUrl(URL.createObjectURL(e.target.files[0]));
|
|
94
|
+
setUploadThumbnail(undefined);
|
|
95
|
+
}
|
|
96
|
+
e.target.files = null;
|
|
97
|
+
};
|
|
98
|
+
useDropFile('.image-upload-zone', e => {
|
|
99
|
+
var _a, _b, _c, _d;
|
|
100
|
+
if (!((_a = e === null || e === void 0 ? void 0 : e.dataTransfer) === null || _a === void 0 ? void 0 : _a.files[0]))
|
|
101
|
+
return;
|
|
102
|
+
if (((_b = e === null || e === void 0 ? void 0 : e.dataTransfer) === null || _b === void 0 ? void 0 : _b.files[0].size) > SIZE_LIMIT) {
|
|
103
|
+
return message.error('File size too big');
|
|
104
|
+
}
|
|
105
|
+
(_c = imageResizeRef.current) === null || _c === void 0 ? void 0 : _c.replaceImageWithUrl(URL.createObjectURL((_d = e === null || e === void 0 ? void 0 : e.dataTransfer) === null || _d === void 0 ? void 0 : _d.files[0]));
|
|
106
|
+
setUploadThumbnail(undefined);
|
|
107
|
+
});
|
|
108
|
+
const currentTime = useMemo(() => new Date(), []);
|
|
109
|
+
const timeGenerated = Math.floor(currentTime.getTime() / 1000 - (currentTime.getTime() % 3)) * 1000;
|
|
110
|
+
const currentEditing = useMemo(() => editingThumbnail !== null && editingThumbnail !== void 0 ? editingThumbnail : uploadThumbnail, [editingThumbnail, uploadThumbnail]);
|
|
111
|
+
const imageResizeProps = {
|
|
112
|
+
className: 'image-resize-wrapper',
|
|
113
|
+
width: imageWidth,
|
|
114
|
+
height: imageHeight,
|
|
115
|
+
ref: imageResizeRef,
|
|
116
|
+
hideAction: true,
|
|
117
|
+
imageUrl:
|
|
118
|
+
// latestCanvas && isEditPrevious
|
|
119
|
+
(latestCanvas === null || latestCanvas === void 0 ? void 0 : latestCanvas[currentEditing])
|
|
120
|
+
? undefined
|
|
121
|
+
: getUrlNoCache(thumbnails[currentEditing], timeGenerated),
|
|
122
|
+
defaultValue: latestCanvas === null || latestCanvas === void 0 ? void 0 : latestCanvas[currentEditing],
|
|
123
|
+
};
|
|
124
|
+
const ImageResizeComponent = useFabric ? ImageResizeTuiEditor : ImageResize;
|
|
125
|
+
const showSkeletonMemo = skeleton !== undefined
|
|
126
|
+
? skeleton
|
|
127
|
+
: checkShowSkeletonBaseUrl(getUrlNoCache(thumbnails[currentEditing], timeGenerated));
|
|
61
128
|
return (React.createElement(ImageSliderStyled, { className: className || '', "$skeleton": skeleton, "$imageWidth": imageWidth, "$smallImageWidth": smallImageWidth, "$imageHeight": imageHeight, vertical: true, gap: 10 },
|
|
62
|
-
|
|
63
|
-
|
|
129
|
+
typeof editingThumbnail === 'number' || typeof uploadThumbnail === 'number' ? (React.createElement(Flex, { vertical: true, style: { zIndex: 25 }, className: "edit-thumbnail-container" },
|
|
130
|
+
React.createElement(ImageResizeComponent, Object.assign({}, imageResizeProps)),
|
|
131
|
+
typeof uploadThumbnail !== 'number' ? null : (React.createElement(Flex, { className: `image-upload-zone ${!showSkeletonMemo ? 'hide-skeleton' : ''}` },
|
|
132
|
+
React.createElement(Icon, { type: "icon-ants-upload-fill", style: { fontSize: '40px' } }),
|
|
133
|
+
React.createElement(Flex, { vertical: true, align: "flex-start" },
|
|
134
|
+
React.createElement(Typography.Text, { style: { fontSize: 16, marginBottom: '10px' } }, "Drag & Drop file here"),
|
|
135
|
+
React.createElement("input", { type: "file", ref: fileRef, onChange: onImportImageSelect, style: { display: 'none' }, accept: "image/*" }),
|
|
136
|
+
React.createElement(Button, { onClick: onImportImageClick }, "Browse Image"),
|
|
137
|
+
React.createElement(Typography.Text, { style: { marginTop: '5px' } }, "File type: .jpg, .png. File size: under 10MB")))),
|
|
138
|
+
React.createElement(Flex, { justify: "center", align: "center", gap: 8, className: "image-resize-action" },
|
|
139
|
+
React.createElement(Button, { onClick: handleSaveThumbnail, type: "primary", disabled: uploadThumbnail !== undefined }, "Save"),
|
|
140
|
+
React.createElement(Button, { onClick: () => {
|
|
141
|
+
setEditingThumbnail(undefined);
|
|
142
|
+
setUploadThumbnail(undefined);
|
|
143
|
+
} }, "Cancel")))) : (React.createElement(Flex, { className: "thumbnail-preview-container", ref: thumbnailSelectedRef }, isLoading ? (React.createElement(Spin, { spinning: true })) : (thumbnails.map((url, index) => (React.createElement(BigImage, { key: `image-big_${url}_${index * 2}`, url: url, index: index, showSkeleton: skeleton, isDefaultThumbnail: defaultThumbnailInternal === index, isHideDefaultButton: hideDefaultButton || hideThumbnailsList || thumbnailsQuantity <= 1, imageFit: thumbnailFit, onClickDefaultButton: handleClickDefault, onClickEdit: index => setEditingThumbnail(index), onClickUpload: index => {
|
|
144
|
+
setEditingThumbnail(index);
|
|
145
|
+
setUploadThumbnail(index);
|
|
146
|
+
} })))))),
|
|
147
|
+
hideThumbnailsList || thumbnailsQuantity <= 1 ? null : (React.createElement(Flex, { gap: 10, className: "thumbnail-slider-container", ref: sliderContainerRef, style: { justifyContent: thumbnailsQuantity < slidesPerView ? 'center' : 'flex-start' } }, isLoading ? (React.createElement(Spin, { spinning: true })) : (thumbnails.map((url, index) => (React.createElement(SmallImage, { imageFit: thumbnailFit, key: `${url}_${index * 2}`, showSkeleton: skeleton, isSelected: index === selectedThumbnail, url: url, index: index, onClick: handleSelectThumbnail })))))),
|
|
64
148
|
previewNavigation && !isLoading ? (React.createElement(React.Fragment, null,
|
|
65
149
|
React.createElement(ButtonSlider, { direction: "left", type: "preview", onClick: handlePrevThumbnail }),
|
|
66
150
|
React.createElement(ButtonSlider, { direction: "right", type: "preview", onClick: handleNextThumbnail }))) : null,
|
|
67
|
-
hideThumbnailsList || isLoading ||
|
|
151
|
+
hideThumbnailsList || isLoading || thumbnailsQuantity <= 2 ? null : (React.createElement(React.Fragment, null,
|
|
68
152
|
(!infinity && selectedThumbnail !== 0) || infinity ? (React.createElement(ButtonSlider, { direction: "left", type: "slider", onClick: handlePrevThumbnail })) : null,
|
|
69
|
-
(!infinity && selectedThumbnail !==
|
|
153
|
+
(!infinity && selectedThumbnail !== thumbnailsQuantity - 1) || infinity ? (React.createElement(ButtonSlider, { direction: "right", type: "slider", onClick: handleNextThumbnail })) : null))));
|
|
70
154
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var _a, _b;
|
|
1
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2
2
|
// Libraries
|
|
3
3
|
import styled, { css } from 'styled-components';
|
|
4
4
|
import { Flex } from '@antscorp/antsomi-ui/es/components';
|
|
@@ -32,6 +32,60 @@ export const ImageSliderStyled = styled(Flex) `
|
|
|
32
32
|
position: relative;
|
|
33
33
|
margin-top: 6px;
|
|
34
34
|
|
|
35
|
+
.edit-thumbnail-container {
|
|
36
|
+
position: relative;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.image-resize-action {
|
|
40
|
+
margin-top: 20px;
|
|
41
|
+
margin-bottom: 40px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.image-resize-wrapper {
|
|
45
|
+
background: ${props => props.$skeleton ? `url(${SkeletonBg}) no-repeat center center` : 'unset'};
|
|
46
|
+
|
|
47
|
+
background-size: 90% 90%;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.image-resize-wrapper,
|
|
51
|
+
.image-upload-zone {
|
|
52
|
+
border: 1px solid ${(_a = THEME.token) === null || _a === void 0 ? void 0 : _a.blue1_1};
|
|
53
|
+
border-radius: 5px;
|
|
54
|
+
margin-top: 0;
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&:has(.image-upload-zone) #image-editor {
|
|
59
|
+
display: none;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.image-upload-zone {
|
|
63
|
+
justify-content: center;
|
|
64
|
+
align-items: center;
|
|
65
|
+
gap: 20px;
|
|
66
|
+
|
|
67
|
+
position: absolute;
|
|
68
|
+
top: 0;
|
|
69
|
+
left: 0;
|
|
70
|
+
width: ${props => `${props.$imageWidth}px`};
|
|
71
|
+
height: ${props => `${props.$imageHeight}px`};
|
|
72
|
+
background: ${(_b = THEME.token) === null || _b === void 0 ? void 0 : _b.colorBgSkeleton};
|
|
73
|
+
|
|
74
|
+
& > i {
|
|
75
|
+
color: ${(_c = THEME.token) === null || _c === void 0 ? void 0 : _c.bw8};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
& > div > span:last-child {
|
|
79
|
+
color: ${(_d = THEME.token) === null || _d === void 0 ? void 0 : _d.bw7};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&:not(.hide-skeleton) {
|
|
83
|
+
background: ${props => props.$skeleton ? `url(${SkeletonBg}) no-repeat center center` : 'unset'};
|
|
84
|
+
|
|
85
|
+
background-size: 90% 90%;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
35
89
|
.change-preview-button {
|
|
36
90
|
${centerBlock}
|
|
37
91
|
position: absolute;
|
|
@@ -125,7 +179,7 @@ export const ImageSliderStyled = styled(Flex) `
|
|
|
125
179
|
}
|
|
126
180
|
}
|
|
127
181
|
|
|
128
|
-
&:has(> .thumbnail-preview-container
|
|
182
|
+
&:has(> .thumbnail-preview-container) {
|
|
129
183
|
.image-container--big::before {
|
|
130
184
|
content: '';
|
|
131
185
|
position: absolute;
|
|
@@ -148,8 +202,8 @@ export const ImageSliderStyled = styled(Flex) `
|
|
|
148
202
|
&--small {
|
|
149
203
|
position: relative;
|
|
150
204
|
box-sizing: border-box;
|
|
151
|
-
background: ${(
|
|
152
|
-
border: 1px solid ${(
|
|
205
|
+
background: ${(_e = THEME.token) === null || _e === void 0 ? void 0 : _e.colorBgSkeleton};
|
|
206
|
+
border: 1px solid ${(_f = THEME.token) === null || _f === void 0 ? void 0 : _f.blue1_1};
|
|
153
207
|
border-radius: 5px;
|
|
154
208
|
|
|
155
209
|
${centerBlock}
|
|
@@ -196,6 +250,15 @@ export const ImageSliderStyled = styled(Flex) `
|
|
|
196
250
|
}
|
|
197
251
|
}
|
|
198
252
|
|
|
253
|
+
.default-checkbox {
|
|
254
|
+
position: absolute;
|
|
255
|
+
top: 10px;
|
|
256
|
+
left: 10px;
|
|
257
|
+
opacity: 0;
|
|
258
|
+
z-index: 3;
|
|
259
|
+
transition: opacity 150ms ease-in-out;
|
|
260
|
+
}
|
|
261
|
+
|
|
199
262
|
.set-default-button {
|
|
200
263
|
position: absolute;
|
|
201
264
|
top: 50%;
|
|
@@ -205,8 +268,10 @@ export const ImageSliderStyled = styled(Flex) `
|
|
|
205
268
|
opacity: 0;
|
|
206
269
|
transition: opacity 150ms ease-in-out;
|
|
207
270
|
}
|
|
271
|
+
|
|
208
272
|
.image-container--big:hover {
|
|
209
|
-
.set-default-button
|
|
273
|
+
.set-default-button,
|
|
274
|
+
.default-checkbox {
|
|
210
275
|
opacity: 1;
|
|
211
276
|
}
|
|
212
277
|
}
|
|
@@ -8,6 +8,20 @@ export const TemplateSaveAsStyled = styled(Flex) `
|
|
|
8
8
|
/* max-width: 1177px; */
|
|
9
9
|
height: 100%;
|
|
10
10
|
|
|
11
|
+
position: relative;
|
|
12
|
+
|
|
13
|
+
&:has(canvas),
|
|
14
|
+
&:has(.image-upload-zone) {
|
|
15
|
+
&:after {
|
|
16
|
+
content: '';
|
|
17
|
+
position: absolute;
|
|
18
|
+
inset: 0;
|
|
19
|
+
background-color: #fff;
|
|
20
|
+
opacity: 0.5;
|
|
21
|
+
z-index: 20;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
11
25
|
.save-options-container {
|
|
12
26
|
padding: 15px 0;
|
|
13
27
|
margin-bottom: 20px;
|
|
@@ -124,3 +138,11 @@ export const TemplateSaveAsStyled = styled(Flex) `
|
|
|
124
138
|
}
|
|
125
139
|
}
|
|
126
140
|
`;
|
|
141
|
+
// export const FormStyled = styled(Form)`
|
|
142
|
+
// position: relative;
|
|
143
|
+
// &::after {
|
|
144
|
+
// position: absolute;
|
|
145
|
+
// inset: 0;
|
|
146
|
+
// background-color: rgba(255, 255, 255, 0.5);
|
|
147
|
+
// }
|
|
148
|
+
// `;
|
|
@@ -18,6 +18,7 @@ export { InputSearch } from './InputSearch';
|
|
|
18
18
|
export { UploadImage } from './UploadImage';
|
|
19
19
|
export { IconSelection } from './IconSelection';
|
|
20
20
|
export { ImageEditor as ImageResize } from './ImageEditor';
|
|
21
|
+
export { ImageResizeTuiEditor } from './ImageResizeTuiEditor';
|
|
21
22
|
export { IconSelectionRenderer } from './IconSelection/components/Icon';
|
|
22
23
|
export { AlignSetting } from './AlignSetting';
|
|
23
24
|
export { EdgeSetting } from './EdgeSetting';
|
|
@@ -62,3 +63,4 @@ export type { TemplateValueOptions } from './TemplateSaveAs';
|
|
|
62
63
|
export type { SelectProps as SelectV2Props } from './SelectV2';
|
|
63
64
|
export type { InputNumberProps as InputNumberWithLabelProps } from './InputNumber';
|
|
64
65
|
export type { ModalSelectProps } from './ModalSelect';
|
|
66
|
+
export type { ImageResizeHandle } from './ImageEditor';
|
|
@@ -18,6 +18,7 @@ export { InputSearch } from './InputSearch';
|
|
|
18
18
|
export { UploadImage } from './UploadImage';
|
|
19
19
|
export { IconSelection } from './IconSelection';
|
|
20
20
|
export { ImageEditor as ImageResize } from './ImageEditor';
|
|
21
|
+
export { ImageResizeTuiEditor } from './ImageResizeTuiEditor';
|
|
21
22
|
export { IconSelectionRenderer } from './IconSelection/components/Icon';
|
|
22
23
|
export { AlignSetting } from './AlignSetting';
|
|
23
24
|
export { EdgeSetting } from './EdgeSetting';
|
|
@@ -114,6 +114,11 @@ export const GlobalStyle = () => {
|
|
|
114
114
|
height: 36px !important;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
&.antsomi-btn-icon-only.antsomi-btn-default {
|
|
118
|
+
width: 30px !important;
|
|
119
|
+
height: 30px !important;
|
|
120
|
+
}
|
|
121
|
+
|
|
117
122
|
&.antsomi-btn-icon-only.antsomi-btn-sm {
|
|
118
123
|
/* Important to override the above code before */
|
|
119
124
|
width: 24px !important;
|
package/es/test.js
CHANGED
|
@@ -19,7 +19,6 @@ import { GET_LIST_TYPE, OBJECT_TYPES, PUBLIC_LEVEL } from './constants';
|
|
|
19
19
|
import axios from 'axios';
|
|
20
20
|
import { get } from 'lodash';
|
|
21
21
|
import { MENU_PERMISSION } from './components/molecules/ShareAccess/constants';
|
|
22
|
-
import { QueryClientProviderAntsomiUI, queryClientAntsomiUI } from './queries';
|
|
23
22
|
import { ConfigProvider } from './providers';
|
|
24
23
|
const SHARE_ACCESS_DEFAULT_VALUE = {
|
|
25
24
|
ownerId: 1600085510,
|
|
@@ -206,6 +205,7 @@ export const App = () => {
|
|
|
206
205
|
};
|
|
207
206
|
const container = document.getElementById('root');
|
|
208
207
|
const root = createRoot(container);
|
|
209
|
-
root.render(
|
|
210
|
-
|
|
211
|
-
|
|
208
|
+
root.render(
|
|
209
|
+
// <QueryClientProviderAntsomiUI client={queryClientAntsomiUI}>
|
|
210
|
+
React.createElement(ConfigProvider, { locale: "en" },
|
|
211
|
+
React.createElement(App, null)));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antscorp/antsomi-ui",
|
|
3
|
-
"version": "1.3.5-beta.
|
|
3
|
+
"version": "1.3.5-beta.263",
|
|
4
4
|
"description": "An enterprise-class UI design language and React UI library.",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"dist/*",
|
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
"currency-formatter": "1.5.9",
|
|
86
86
|
"d3-interpolate": "^3.0.1",
|
|
87
87
|
"dayjs": "^1.11.10",
|
|
88
|
+
"fabric": "^5.3.0",
|
|
88
89
|
"font-awesome": "4.7.0",
|
|
89
90
|
"highlight.js": "^11.8.0",
|
|
90
91
|
"html-entities": "^2.0.2",
|