@pushwoosh/smart-components-kit 1.19.0 → 1.21.0
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/MediaStorage/CreateCropDrawer.js +46 -6
- package/MediaStorage/CropFramePicker.d.ts +15 -0
- package/MediaStorage/CropFramePicker.js +108 -0
- package/MediaStorage/MediaStorage.js +7 -2
- package/MediaStorage/cropWindow.d.ts +22 -0
- package/MediaStorage/cropWindow.js +36 -0
- package/MediaStorage/mediaFile.utils.d.ts +10 -0
- package/MediaStorage/mediaFile.utils.js +16 -0
- package/MediaStorage/polyglot/messages_ar.js +2 -0
- package/MediaStorage/polyglot/messages_bn.js +2 -0
- package/MediaStorage/polyglot/messages_de.js +2 -0
- package/MediaStorage/polyglot/messages_en.js +2 -0
- package/MediaStorage/polyglot/messages_es.js +2 -0
- package/MediaStorage/polyglot/messages_fr.js +2 -0
- package/MediaStorage/polyglot/messages_he.js +2 -0
- package/MediaStorage/polyglot/messages_hi.js +2 -0
- package/MediaStorage/polyglot/messages_ja.js +2 -0
- package/MediaStorage/polyglot/messages_ko.js +2 -0
- package/MediaStorage/polyglot/messages_pt.js +2 -0
- package/MediaStorage/polyglot/messages_ru.js +2 -0
- package/MediaStorage/polyglot/messages_th.js +2 -0
- package/MediaStorage/polyglot/messages_zh.js +2 -0
- package/MediaStorage/polyglot/types.d.ts +5 -0
- package/MediaStorage/styles.d.ts +15 -0
- package/MediaStorage/styles.js +41 -33
- package/package.json +1 -1
|
@@ -5,6 +5,8 @@ import { Columns, Vertical } from '@pushwoosh/kit-helpers';
|
|
|
5
5
|
import { CloseIcon, TrashIcon } from '@pushwoosh/kit-icons';
|
|
6
6
|
import { Text } from '@pushwoosh/kit-typography';
|
|
7
7
|
import { useSPAContext } from '@pushwoosh/spa-context';
|
|
8
|
+
import { CropFramePicker } from './CropFramePicker';
|
|
9
|
+
import { CENTER_FOCAL, getCropWindow, getStoredOrigin } from './cropWindow';
|
|
8
10
|
import { useDeleteMediaFile } from './hooks';
|
|
9
11
|
import { getAspectRatio, getCropCaption, getThumbUrl } from './mediaFile.utils';
|
|
10
12
|
import { useLang } from './polyglot';
|
|
@@ -80,6 +82,7 @@ export const CreateCropDrawer = ({
|
|
|
80
82
|
const [isCreating, setIsCreating] = useState(false);
|
|
81
83
|
const [pendingDeleteCrop, setPendingDeleteCrop] = useState(null);
|
|
82
84
|
const [viewedCrop, setViewedCrop] = useState(null);
|
|
85
|
+
const [focal, setFocal] = useState(CENTER_FOCAL);
|
|
83
86
|
// The drawer mounts once and is toggled via `isOpen`, so reset every field
|
|
84
87
|
// whenever it opens for a different original — otherwise values (and the
|
|
85
88
|
// `ratioExists` guard) leak from the previously edited image.
|
|
@@ -90,6 +93,7 @@ export const CreateCropDrawer = ({
|
|
|
90
93
|
setSize(DEFAULT_SIZE);
|
|
91
94
|
setQuality(DEFAULT_QUALITY);
|
|
92
95
|
setViewedCrop(null);
|
|
96
|
+
setFocal(CENTER_FOCAL);
|
|
93
97
|
}
|
|
94
98
|
}, [original]);
|
|
95
99
|
const isJpeg = /jpe?g/i.test(original?.mimeType ?? '');
|
|
@@ -104,6 +108,7 @@ export const CreateCropDrawer = ({
|
|
|
104
108
|
const chooseRatio = next => {
|
|
105
109
|
setRatio(next);
|
|
106
110
|
setViewedCrop(null);
|
|
111
|
+
setFocal(CENTER_FOCAL);
|
|
107
112
|
};
|
|
108
113
|
const viewCrop = crop => {
|
|
109
114
|
setRatio('original');
|
|
@@ -112,6 +117,13 @@ export const CreateCropDrawer = ({
|
|
|
112
117
|
const selectedRatio = RATIOS.find(item => item.value === ratio) ?? RATIOS[0];
|
|
113
118
|
const outputWidth = dimension === 'width' ? sizeValue : Math.round(sizeValue * selectedRatio.ar);
|
|
114
119
|
const outputHeight = dimension === 'height' ? sizeValue : Math.round(sizeValue / selectedRatio.ar);
|
|
120
|
+
const [ratioW, ratioH] = selectedRatio.label.split(':').map(Number);
|
|
121
|
+
const srcW = originalMeta?.width ?? 0;
|
|
122
|
+
const srcH = originalMeta?.height ?? 0;
|
|
123
|
+
const canPlaceWindow = !isOriginalView && srcW > 0 && srcH > 0;
|
|
124
|
+
const cropWindow = canPlaceWindow ? getCropWindow(srcW, srcH, ratioW, ratioH, focal) : null;
|
|
125
|
+
const centeredWindow = canPlaceWindow ? getCropWindow(srcW, srcH, ratioW, ratioH, CENTER_FOCAL) : null;
|
|
126
|
+
const isOffCenter = Boolean(cropWindow && centeredWindow && (cropWindow.x !== centeredWindow.x || cropWindow.y !== centeredWindow.y));
|
|
115
127
|
// Both inputs are always visible: the driving one is editable, the other is
|
|
116
128
|
// read-only and shows the value computed from the aspect ratio.
|
|
117
129
|
const computedText = value => isSizeValid ? String(value) : '';
|
|
@@ -126,9 +138,18 @@ export const CreateCropDrawer = ({
|
|
|
126
138
|
}
|
|
127
139
|
setDimension(next);
|
|
128
140
|
};
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
141
|
+
// A crop is the same one only at the same ratio, output size and window position.
|
|
142
|
+
const duplicateExists = !isOriginalView && isSizeValid && existingCrops.some(crop => {
|
|
143
|
+
if (crop.meta?.type !== 'imageMeta') return false;
|
|
144
|
+
const {
|
|
145
|
+
ratio: cropRatio,
|
|
146
|
+
width,
|
|
147
|
+
height
|
|
148
|
+
} = crop.meta.data;
|
|
149
|
+
if (cropRatio !== selectedRatio.label || width !== outputWidth || height !== outputHeight) return false;
|
|
150
|
+
const origin = getStoredOrigin(crop.url);
|
|
151
|
+
return isOffCenter ? origin?.x === cropWindow?.x && origin?.y === cropWindow?.y : origin === null;
|
|
152
|
+
});
|
|
132
153
|
const handleCreate = async () => {
|
|
133
154
|
if (!original || ratio === 'original' || !isSizeValid || !isQualityValid || duplicateExists) return;
|
|
134
155
|
// Capture the parent up front so a concurrent reopen for another image
|
|
@@ -136,7 +157,7 @@ export const CreateCropDrawer = ({
|
|
|
136
157
|
const parent = original;
|
|
137
158
|
setIsCreating(true);
|
|
138
159
|
try {
|
|
139
|
-
const
|
|
160
|
+
const request = {
|
|
140
161
|
application,
|
|
141
162
|
uuid: parent.uuid,
|
|
142
163
|
ratio,
|
|
@@ -146,8 +167,12 @@ export const CreateCropDrawer = ({
|
|
|
146
167
|
},
|
|
147
168
|
...(isJpeg ? {
|
|
148
169
|
quality: qualityValue
|
|
170
|
+
} : {}),
|
|
171
|
+
...(isOffCenter ? {
|
|
172
|
+
focalPoint: focal
|
|
149
173
|
} : {})
|
|
150
|
-
}
|
|
174
|
+
};
|
|
175
|
+
const response = await rpcGateway.mediaFiles.CreateVariant(request);
|
|
151
176
|
openToast({
|
|
152
177
|
title: lang({
|
|
153
178
|
message: 'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS'
|
|
@@ -274,13 +299,28 @@ export const CreateCropDrawer = ({
|
|
|
274
299
|
}), _jsxs(Vertical, {
|
|
275
300
|
"$gap": 6,
|
|
276
301
|
children: [_jsx(PreviewStage, {
|
|
277
|
-
children: _jsx(
|
|
302
|
+
children: canPlaceWindow && cropWindow ? _jsx(CropFramePicker, {
|
|
303
|
+
src: original.url,
|
|
304
|
+
alt: original.filename,
|
|
305
|
+
imageRatio: srcW / srcH,
|
|
306
|
+
windowWidth: cropWindow.width / srcW,
|
|
307
|
+
windowHeight: cropWindow.height / srcH,
|
|
308
|
+
focal: focal,
|
|
309
|
+
label: lang({
|
|
310
|
+
message: 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT'
|
|
311
|
+
}),
|
|
312
|
+
onChange: setFocal
|
|
313
|
+
}) : _jsx(PreviewFrame, {
|
|
278
314
|
"$ratio": isOriginalView ? getAspectRatio(previewFile) : selectedRatio.ar,
|
|
279
315
|
children: _jsx(PreviewImage, {
|
|
280
316
|
src: previewFile.url,
|
|
281
317
|
alt: previewFile.filename
|
|
282
318
|
})
|
|
283
319
|
})
|
|
320
|
+
}), canPlaceWindow && _jsx(Text, {
|
|
321
|
+
children: lang({
|
|
322
|
+
message: 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT'
|
|
323
|
+
})
|
|
284
324
|
}), viewedCrop && _jsx(Text, {
|
|
285
325
|
children: getCropCaption(viewedCrop)
|
|
286
326
|
}), isOriginalShown && originalMeta && _jsxs(Text, {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
import { type Focal } from './cropWindow';
|
|
3
|
+
type CropFramePickerProps = {
|
|
4
|
+
src: string;
|
|
5
|
+
alt: string;
|
|
6
|
+
imageRatio: number;
|
|
7
|
+
windowWidth: number;
|
|
8
|
+
windowHeight: number;
|
|
9
|
+
focal: Focal;
|
|
10
|
+
label: string;
|
|
11
|
+
onChange: (focal: Focal) => void;
|
|
12
|
+
};
|
|
13
|
+
/** Original image with a draggable crop window; sizes and focal are fractions of the image. */
|
|
14
|
+
export declare const CropFramePicker: FC<CropFramePickerProps>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { clampFocal } from './cropWindow';
|
|
4
|
+
import { CropFrame, CropFrameWindow, PreviewImage } from './styles';
|
|
5
|
+
const KEY_STEP = 0.01;
|
|
6
|
+
/** Original image with a draggable crop window; sizes and focal are fractions of the image. */
|
|
7
|
+
export const CropFramePicker = ({
|
|
8
|
+
src,
|
|
9
|
+
alt,
|
|
10
|
+
imageRatio,
|
|
11
|
+
windowWidth,
|
|
12
|
+
windowHeight,
|
|
13
|
+
focal,
|
|
14
|
+
label,
|
|
15
|
+
onChange
|
|
16
|
+
}) => {
|
|
17
|
+
const frameRef = useRef(null);
|
|
18
|
+
const dragRef = useRef(null);
|
|
19
|
+
const move = next => onChange(clampFocal(next, windowWidth, windowHeight));
|
|
20
|
+
const handlePointerDown = event => {
|
|
21
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
22
|
+
dragRef.current = {
|
|
23
|
+
clientX: event.clientX,
|
|
24
|
+
clientY: event.clientY,
|
|
25
|
+
focal
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const handlePointerMove = event => {
|
|
29
|
+
const drag = dragRef.current;
|
|
30
|
+
const rect = frameRef.current?.getBoundingClientRect();
|
|
31
|
+
if (!drag || !rect || rect.width === 0 || rect.height === 0) return;
|
|
32
|
+
move({
|
|
33
|
+
x: drag.focal.x + (event.clientX - drag.clientX) / rect.width,
|
|
34
|
+
y: drag.focal.y + (event.clientY - drag.clientY) / rect.height
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
const handlePointerUp = () => {
|
|
38
|
+
dragRef.current = null;
|
|
39
|
+
};
|
|
40
|
+
const handleFrameClick = event => {
|
|
41
|
+
const rect = frameRef.current?.getBoundingClientRect();
|
|
42
|
+
if (!rect || rect.width === 0 || rect.height === 0) return;
|
|
43
|
+
move({
|
|
44
|
+
x: (event.clientX - rect.left) / rect.width,
|
|
45
|
+
y: (event.clientY - rect.top) / rect.height
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
const handleKeyDown = event => {
|
|
49
|
+
const delta = {
|
|
50
|
+
ArrowLeft: {
|
|
51
|
+
x: -KEY_STEP,
|
|
52
|
+
y: 0
|
|
53
|
+
},
|
|
54
|
+
ArrowRight: {
|
|
55
|
+
x: KEY_STEP,
|
|
56
|
+
y: 0
|
|
57
|
+
},
|
|
58
|
+
ArrowUp: {
|
|
59
|
+
x: 0,
|
|
60
|
+
y: -KEY_STEP
|
|
61
|
+
},
|
|
62
|
+
ArrowDown: {
|
|
63
|
+
x: 0,
|
|
64
|
+
y: KEY_STEP
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const step = delta[event.key];
|
|
68
|
+
if (!step) return;
|
|
69
|
+
event.preventDefault();
|
|
70
|
+
move({
|
|
71
|
+
x: focal.x + step.x,
|
|
72
|
+
y: focal.y + step.y
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
return _jsxs(CropFrame, {
|
|
76
|
+
ref: frameRef,
|
|
77
|
+
"$ratio": imageRatio,
|
|
78
|
+
onPointerDown: handleFrameClick,
|
|
79
|
+
children: [_jsx(PreviewImage, {
|
|
80
|
+
src: src,
|
|
81
|
+
alt: alt,
|
|
82
|
+
draggable: false
|
|
83
|
+
}), _jsx(CropFrameWindow, {
|
|
84
|
+
role: "slider",
|
|
85
|
+
tabIndex: 0,
|
|
86
|
+
"aria-label": label,
|
|
87
|
+
"aria-valuemin": 0,
|
|
88
|
+
"aria-valuemax": 100,
|
|
89
|
+
"aria-valuenow": Math.round(focal.x * 100),
|
|
90
|
+
"aria-valuetext": `${Math.round(focal.x * 100)}%, ${Math.round(focal.y * 100)}%`,
|
|
91
|
+
title: label,
|
|
92
|
+
style: {
|
|
93
|
+
left: `${(focal.x - windowWidth / 2) * 100}%`,
|
|
94
|
+
top: `${(focal.y - windowHeight / 2) * 100}%`,
|
|
95
|
+
width: `${windowWidth * 100}%`,
|
|
96
|
+
height: `${windowHeight * 100}%`
|
|
97
|
+
},
|
|
98
|
+
onPointerDown: event => {
|
|
99
|
+
event.stopPropagation();
|
|
100
|
+
handlePointerDown(event);
|
|
101
|
+
},
|
|
102
|
+
onPointerMove: handlePointerMove,
|
|
103
|
+
onPointerUp: handlePointerUp,
|
|
104
|
+
onPointerCancel: handlePointerUp,
|
|
105
|
+
onKeyDown: handleKeyDown
|
|
106
|
+
})]
|
|
107
|
+
});
|
|
108
|
+
};
|
|
@@ -11,7 +11,7 @@ import { CanvaImportDrawer } from './CanvaImportDrawer';
|
|
|
11
11
|
import { CreateCropDrawer } from './CreateCropDrawer';
|
|
12
12
|
import { GenerateImageTab } from './GenerateImageTab';
|
|
13
13
|
import { useCanvaEdit, useDeleteMediaFile, useDeleteMediaFiles } from './hooks';
|
|
14
|
-
import { formatBytes, getCropCaption, getSourceLabel, getThumbUrl, hasVersions } from './mediaFile.utils';
|
|
14
|
+
import { compressionSavings, formatBytes, getCropCaption, getSourceLabel, getThumbUrl, hasVersions } from './mediaFile.utils';
|
|
15
15
|
import { Lang, useLang } from './polyglot';
|
|
16
16
|
import { StockPhotosTab } from './StockPhotosTab';
|
|
17
17
|
import { CanvaActions, CountBadge, Dropzone, DropzoneRow, EmptyState, Grid, HiddenInput, MenuItemPreview, MenuItemThumb, SelectionBar, SearchField, SearchRow, SelectionCount, SourceBadge, TabBody, Tile, TileActions, TileBadges, TileCheckbox, TileImage, TooltipAnchor, UsageLine, VersionsBadge, WarningBadge } from './styles';
|
|
@@ -220,8 +220,13 @@ export const MediaStorage = ({
|
|
|
220
220
|
}));
|
|
221
221
|
const failed = results.filter(result => result.status === 'rejected').length;
|
|
222
222
|
if (failed < images.length) {
|
|
223
|
+
const savings = compressionSavings(results.flatMap(result => result.status === 'fulfilled' ? [result.value] : []));
|
|
223
224
|
openToast({
|
|
224
|
-
title: lang({
|
|
225
|
+
title: savings ? lang({
|
|
226
|
+
message: 'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED',
|
|
227
|
+
percent: savings.percent,
|
|
228
|
+
size: formatBytes(savings.savedBytes)
|
|
229
|
+
}) : lang({
|
|
225
230
|
message: 'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS'
|
|
226
231
|
}),
|
|
227
232
|
type: 'success'
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Center of a crop window as a fraction (0..1) of the original's width and height. */
|
|
2
|
+
export type Focal = {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
};
|
|
6
|
+
/** Crop window on the original, in source pixels. */
|
|
7
|
+
export type CropRect = {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const CENTER_FOCAL: Focal;
|
|
14
|
+
/** Largest ratioW:ratioH window inside srcW×srcH centered on focal; mirrors rpc-v2 `CropWindow`. */
|
|
15
|
+
export declare const getCropWindow: (srcW: number, srcH: number, ratioW: number, ratioH: number, focal: Focal) => CropRect;
|
|
16
|
+
/** The focal a window of that size can actually take: its center, kept inside the image. */
|
|
17
|
+
export declare const clampFocal: (focal: Focal, windowW: number, windowH: number) => Focal;
|
|
18
|
+
/** Window origin a variant was cut at, read from its `_at<x>x<y>` key suffix; null for a centered one. */
|
|
19
|
+
export declare const getStoredOrigin: (url: string) => {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
} | null;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const CENTER_FOCAL = {
|
|
2
|
+
x: 0.5,
|
|
3
|
+
y: 0.5
|
|
4
|
+
};
|
|
5
|
+
const clamp = (value, lo, hi) => Math.max(lo, Math.min(value, hi));
|
|
6
|
+
/** Largest ratioW:ratioH window inside srcW×srcH centered on focal; mirrors rpc-v2 `CropWindow`. */
|
|
7
|
+
export const getCropWindow = (srcW, srcH, ratioW, ratioH, focal) => {
|
|
8
|
+
let width = srcW;
|
|
9
|
+
let height = srcH;
|
|
10
|
+
if (srcW * ratioH > srcH * ratioW) {
|
|
11
|
+
width = Math.floor(srcH * ratioW / ratioH);
|
|
12
|
+
} else {
|
|
13
|
+
height = Math.floor(srcW * ratioH / ratioW);
|
|
14
|
+
}
|
|
15
|
+
const x = clamp(Math.floor(focal.x * srcW - width / 2), 0, srcW - width);
|
|
16
|
+
const y = clamp(Math.floor(focal.y * srcH - height / 2), 0, srcH - height);
|
|
17
|
+
return {
|
|
18
|
+
x,
|
|
19
|
+
y,
|
|
20
|
+
width,
|
|
21
|
+
height
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
/** The focal a window of that size can actually take: its center, kept inside the image. */
|
|
25
|
+
export const clampFocal = (focal, windowW, windowH) => ({
|
|
26
|
+
x: clamp(focal.x, windowW / 2, 1 - windowW / 2),
|
|
27
|
+
y: clamp(focal.y, windowH / 2, 1 - windowH / 2)
|
|
28
|
+
});
|
|
29
|
+
/** Window origin a variant was cut at, read from its `_at<x>x<y>` key suffix; null for a centered one. */
|
|
30
|
+
export const getStoredOrigin = url => {
|
|
31
|
+
const match = /_at(\d+)x(\d+)(?:\.[a-z0-9]+)?$/i.exec(url.split(/[?#]/)[0]);
|
|
32
|
+
return match ? {
|
|
33
|
+
x: Number(match[1]),
|
|
34
|
+
y: Number(match[2])
|
|
35
|
+
} : null;
|
|
36
|
+
};
|
|
@@ -11,3 +11,13 @@ export declare const getAspectRatio: (file: MediaFile) => number;
|
|
|
11
11
|
export declare const hasVersions: (file: MediaFile) => boolean;
|
|
12
12
|
/** Human-readable byte size, e.g. 4404019 -> "4.2 MB". */
|
|
13
13
|
export declare const formatBytes: (bytes: number) => string;
|
|
14
|
+
/** The part of the `/api/media/upload` answer the upload toast reads. */
|
|
15
|
+
export type UploadedFile = {
|
|
16
|
+
file_size: number;
|
|
17
|
+
original_file_size?: number;
|
|
18
|
+
};
|
|
19
|
+
/** Savings of PNG compression over a batch: compressed files only; null when nothing worth a whole percent was saved. */
|
|
20
|
+
export declare const compressionSavings: (files: UploadedFile[]) => {
|
|
21
|
+
percent: number;
|
|
22
|
+
savedBytes: number;
|
|
23
|
+
} | null;
|
|
@@ -33,4 +33,20 @@ export const formatBytes = bytes => {
|
|
|
33
33
|
// Whole numbers for bytes and for values >= 100; one decimal otherwise.
|
|
34
34
|
const rounded = exp === 0 || value >= 100 ? Math.round(value) : Math.round(value * 10) / 10;
|
|
35
35
|
return `${rounded} ${BYTE_UNITS[exp]}`;
|
|
36
|
+
};
|
|
37
|
+
/** Savings of PNG compression over a batch: compressed files only; null when nothing worth a whole percent was saved. */
|
|
38
|
+
export const compressionSavings = files => {
|
|
39
|
+
let before = 0;
|
|
40
|
+
let after = 0;
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
if (file.original_file_size && file.original_file_size > file.file_size) {
|
|
43
|
+
before += file.original_file_size;
|
|
44
|
+
after += file.file_size;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const percent = before === 0 ? 0 : Math.round((1 - after / before) * 100);
|
|
48
|
+
return percent > 0 ? {
|
|
49
|
+
percent,
|
|
50
|
+
savedBytes: before - after
|
|
51
|
+
} : null;
|
|
36
52
|
};
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'تعذّر رفع الصورة',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'تنسيق غير مدعوم. استخدم JPEG أو PNG أو GIF أو WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'تم رفع الصورة',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'تم رفع الصورة. تم ضغط PNG: توفير {{percent}}% ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': 'الملفات: {{count}} · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': 'اقتصاصات: {{count}}',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': 'إصدارات: {{count}}',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'لا توجد اقتصاصات بعد',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'تم إنشاء الاقتصاص',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'تعذّر إنشاء الاقتصاص',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'اسحب الإطار لاختيار منطقة الاقتصاص',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'عرض هذا الاقتصاص',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'حذف الاقتصاص',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'حذف هذا الاقتصاص؟',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'ছবি আপলোড করা যায়নি',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'অসমর্থিত ফরম্যাট। JPEG, PNG, GIF বা WebP ব্যবহার করুন',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'ছবি আপলোড হয়েছে',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'ছবি আপলোড হয়েছে। PNG সংকুচিত: {{percent}}% সাশ্রয় ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}}টি ফাইল · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}}টি ক্রপ',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}}টি সংস্করণ',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'এখনো কোনো ক্রপ নেই',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'ক্রপ তৈরি হয়েছে',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'ক্রপ তৈরি করা যায়নি',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'ক্রপের এলাকা বেছে নিতে ফ্রেম টেনে আনুন',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'এই ক্রপ দেখান',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'ক্রপ মুছুন',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'এই ক্রপটি মুছবেন?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'Bild konnte nicht hochgeladen werden',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'Nicht unterstütztes Format. Verwenden Sie JPEG, PNG, GIF oder WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'Bild hochgeladen',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'Bild hochgeladen. PNG komprimiert: {{percent}} % gespart ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} Dateien · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} Zuschn.',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} Vers.',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Noch keine Zuschnitte',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Zuschnitt erstellt',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Zuschnitt konnte nicht erstellt werden',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Rahmen ziehen, um den Zuschnitt zu wählen',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Zuschnitt anzeigen',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Zuschnitt löschen',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Diesen Zuschnitt löschen?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'Failed to upload image',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'Unsupported format. Use JPEG, PNG, GIF or WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'Image uploaded',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'Image uploaded. PNG compressed: saved {{percent}}% ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} files · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} cr.',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} ver.',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'No crops yet',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Crop created',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Failed to create crop',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Drag the frame to choose the crop area',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Show this crop',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Delete crop',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Delete this crop?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'No se pudo subir la imagen',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'Formato no compatible. Usa JPEG, PNG, GIF o WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'Imagen subida',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'Imagen subida. PNG comprimido: ahorro del {{percent}} % ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} archivos · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} rec.',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} vers.',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Aún no hay recortes',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Recorte creado',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'No se pudo crear el recorte',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Arrastra el marco para elegir el área del recorte',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Mostrar este recorte',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Eliminar recorte',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': '¿Eliminar este recorte?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'Échec de l’importation de l’image',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'Format non pris en charge. Utilisez JPEG, PNG, GIF ou WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'Image importée',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'Image importée. PNG compressé : {{percent}} % économisés ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} fichiers · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} recadr.',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} vers.',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Aucun recadrage pour le moment',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Recadrage créé',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Échec de la création du recadrage',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Faites glisser le cadre pour choisir la zone du recadrage',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Afficher ce recadrage',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Supprimer le recadrage',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Supprimer ce recadrage ?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'העלאת התמונה נכשלה',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'פורמט לא נתמך. השתמשו ב-JPEG, PNG, GIF או WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'התמונה הועלתה',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'התמונה הועלתה. PNG נדחס: חיסכון של {{percent}}% ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} קבצים · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} חית.',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} גרס.',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'אין עדיין חיתוכים',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'החיתוך נוצר',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'יצירת החיתוך נכשלה',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'גררו את המסגרת כדי לבחור את אזור החיתוך',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'הצג חיתוך זה',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'מחיקת חיתוך',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'למחוק את החיתוך הזה?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'छवि अपलोड नहीं हो सकी',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'असमर्थित फ़ॉर्मेट। JPEG, PNG, GIF या WebP का उपयोग करें',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'छवि अपलोड हो गई',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'छवि अपलोड हो गई। PNG संपीड़ित: {{percent}}% की बचत ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} फ़ाइलें · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} क्रॉप',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} संस्करण',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'अभी तक कोई क्रॉप नहीं',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'क्रॉप बनाया गया',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'क्रॉप नहीं बनाया जा सका',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'क्रॉप क्षेत्र चुनने के लिए फ़्रेम खींचें',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'यह क्रॉप दिखाएँ',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'क्रॉप हटाएँ',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'यह क्रॉप हटाएँ?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': '画像のアップロードに失敗しました',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'サポートされていない形式です。JPEG、PNG、GIF、WebPを使用してください',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': '画像をアップロードしました',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': '画像をアップロードしました。PNG を圧縮: {{percent}}% 削減({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}}ファイル · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': 'トリミング{{count}}',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': 'バージョン{{count}}',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'トリミングはまだありません',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'トリミングを作成しました',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'トリミングの作成に失敗しました',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': '枠をドラッグしてトリミング範囲を選択',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'このトリミングを表示',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'トリミングを削除',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'このトリミングを削除しますか?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': '이미지를 업로드하지 못했습니다',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': '지원되지 않는 형식입니다. JPEG, PNG, GIF 또는 WebP를 사용하세요',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': '이미지가 업로드되었습니다',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': '이미지가 업로드되었습니다. PNG 압축: {{percent}}% 절감 ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '파일 {{count}}개 · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '크롭 {{count}}개',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '버전 {{count}}개',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': '아직 크롭이 없습니다',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': '크롭이 생성되었습니다',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': '크롭을 생성하지 못했습니다',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': '프레임을 드래그해 크롭 영역을 선택하세요',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': '이 크롭 보기',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': '크롭 삭제',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': '이 크롭을 삭제하시겠습니까?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'Falha ao enviar a imagem',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'Formato não suportado. Use JPEG, PNG, GIF ou WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'Imagem enviada',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'Imagem enviada. PNG comprimido: economia de {{percent}}% ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} arquivos · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} rec.',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} vers.',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Nenhum recorte ainda',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Recorte criado',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Falha ao criar o recorte',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Arraste o quadro para escolher a área do recorte',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Mostrar este recorte',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Excluir recorte',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Excluir este recorte?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'Не удалось загрузить изображение',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'Неподдерживаемый формат. Используйте JPEG, PNG, GIF или WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'Изображение загружено',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'Изображение загружено. PNG сжат: экономия {{percent}}% ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} файлов · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} кр.',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} вер.',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Кропов пока нет',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Кроп создан',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Не удалось создать кроп',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Перетащите рамку, чтобы выбрать область кропа',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Показать кроп',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Удалить кроп',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Удалить кроп?',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': 'อัปโหลดรูปภาพไม่สำเร็จ',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': 'ไม่รองรับรูปแบบนี้ ใช้ JPEG, PNG, GIF หรือ WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': 'อัปโหลดรูปภาพแล้ว',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': 'อัปโหลดรูปภาพแล้ว บีบอัด PNG: ประหยัด {{percent}}% ({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} ไฟล์ · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} ครอป',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} เวอร์ชัน',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'ยังไม่มีครอป',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'สร้างครอปแล้ว',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'สร้างครอปไม่สำเร็จ',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'ลากกรอบเพื่อเลือกพื้นที่ครอป',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'แสดงภาพครอปนี้',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'ลบครอป',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'ลบครอปนี้ใช่ไหม',
|
|
@@ -10,6 +10,7 @@ export const messages = {
|
|
|
10
10
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': '上传图片失败',
|
|
11
11
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': '不支持的格式。请使用 JPEG、PNG、GIF 或 WebP',
|
|
12
12
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': '图片已上传',
|
|
13
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': '图片已上传。PNG 已压缩:节省 {{percent}}%({{size}})',
|
|
13
14
|
'SMART.MEDIA_STORAGE.USAGE': '{{count}} 个文件 · {{size}}',
|
|
14
15
|
'SMART.MEDIA_STORAGE.CROPS_BADGE': '{{count}} 个裁剪图',
|
|
15
16
|
'SMART.MEDIA_STORAGE.VERSIONS_BADGE': '{{count}} 个版本',
|
|
@@ -51,6 +52,7 @@ export const messages = {
|
|
|
51
52
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': '暂无裁剪图',
|
|
52
53
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': '裁剪图已创建',
|
|
53
54
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': '创建裁剪图失败',
|
|
55
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': '拖动框选择裁剪区域',
|
|
54
56
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': '查看此裁剪',
|
|
55
57
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': '删除裁剪图',
|
|
56
58
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': '删除此裁剪图?',
|
|
@@ -11,6 +11,10 @@ export type MediaStorageMessages = {
|
|
|
11
11
|
'SMART.MEDIA_STORAGE.UPLOAD_ERROR': NoParams;
|
|
12
12
|
'SMART.MEDIA_STORAGE.UNSUPPORTED_FORMAT': NoParams;
|
|
13
13
|
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS': NoParams;
|
|
14
|
+
'SMART.MEDIA_STORAGE.UPLOAD_SUCCESS_COMPRESSED': {
|
|
15
|
+
percent: number;
|
|
16
|
+
size: string;
|
|
17
|
+
};
|
|
14
18
|
'SMART.MEDIA_STORAGE.USAGE': {
|
|
15
19
|
count: number;
|
|
16
20
|
size: string;
|
|
@@ -71,6 +75,7 @@ export type MediaStorageMessages = {
|
|
|
71
75
|
'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': NoParams;
|
|
72
76
|
'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': NoParams;
|
|
73
77
|
'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': NoParams;
|
|
78
|
+
'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': NoParams;
|
|
74
79
|
'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': NoParams;
|
|
75
80
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': NoParams;
|
|
76
81
|
'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': NoParams;
|
package/MediaStorage/styles.d.ts
CHANGED
|
@@ -67,6 +67,21 @@ export declare const PreviewFrame: import("styled-components/dist/types").IStyle
|
|
|
67
67
|
}, {
|
|
68
68
|
$ratio: number;
|
|
69
69
|
}>> & string;
|
|
70
|
+
export declare const CropFrame: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("styled-components").FastOmit<import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
|
|
71
|
+
style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
|
|
72
|
+
}, {
|
|
73
|
+
$ratio: number;
|
|
74
|
+
}>, "as" | "forwardedAs"> & {
|
|
75
|
+
as?: import("styled-components").WebTarget | undefined;
|
|
76
|
+
forwardedAs?: import("styled-components").WebTarget | undefined;
|
|
77
|
+
}, "style"> & {
|
|
78
|
+
style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | (import("react").CSSProperties & {
|
|
79
|
+
[key: `--${string}`]: string | number | undefined;
|
|
80
|
+
}) | undefined;
|
|
81
|
+
}> & string;
|
|
82
|
+
export declare const CropFrameWindow: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
|
|
83
|
+
style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
|
|
84
|
+
}> & string;
|
|
70
85
|
export declare const PreviewImage: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "style"> & {
|
|
71
86
|
style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
|
|
72
87
|
}> & string;
|
package/MediaStorage/styles.js
CHANGED
|
@@ -96,29 +96,37 @@ export const PreviewFrame = styled.div.withConfig({
|
|
|
96
96
|
})(["aspect-ratio:", ";max-width:100%;max-height:336px;overflow:hidden;border-radius:4px;"], ({
|
|
97
97
|
$ratio
|
|
98
98
|
}) => $ratio);
|
|
99
|
+
export const CropFrame = styled(PreviewFrame).withConfig({
|
|
100
|
+
displayName: "CropFrame",
|
|
101
|
+
componentId: "sc-uu3cbo-21"
|
|
102
|
+
})(["position:relative;touch-action:none;user-select:none;cursor:crosshair;"]);
|
|
103
|
+
export const CropFrameWindow = styled.div.withConfig({
|
|
104
|
+
displayName: "CropFrameWindow",
|
|
105
|
+
componentId: "sc-uu3cbo-22"
|
|
106
|
+
})(["position:absolute;box-sizing:border-box;border:2px solid ", ";box-shadow:0 0 0 9999px rgba(0,0,0,0.5);cursor:move;touch-action:none;&:focus-visible{outline:2px solid ", ";outline-offset:2px;}"], Color.CLEAR, Color.PRIMARY);
|
|
99
107
|
export const PreviewImage = styled.img.withConfig({
|
|
100
108
|
displayName: "PreviewImage",
|
|
101
|
-
componentId: "sc-uu3cbo-
|
|
109
|
+
componentId: "sc-uu3cbo-23"
|
|
102
110
|
})(["width:100%;height:100%;object-fit:cover;display:block;"]);
|
|
103
111
|
export const FieldLabel = styled.div.withConfig({
|
|
104
112
|
displayName: "FieldLabel",
|
|
105
|
-
componentId: "sc-uu3cbo-
|
|
113
|
+
componentId: "sc-uu3cbo-24"
|
|
106
114
|
})(["font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.4px;color:", ";margin-bottom:6px;"], Color.LOCKED);
|
|
107
115
|
export const SizeInput = styled(NativeInput).withConfig({
|
|
108
116
|
displayName: "SizeInput",
|
|
109
|
-
componentId: "sc-uu3cbo-
|
|
117
|
+
componentId: "sc-uu3cbo-25"
|
|
110
118
|
})(["&[readonly]{background:", ";color:", ";}"], Color.SOFT_LIGHT, Color.LOCKED);
|
|
111
119
|
export const Chips = styled.div.withConfig({
|
|
112
120
|
displayName: "Chips",
|
|
113
|
-
componentId: "sc-uu3cbo-
|
|
121
|
+
componentId: "sc-uu3cbo-26"
|
|
114
122
|
})(["display:flex;flex-wrap:wrap;gap:7px;"]);
|
|
115
123
|
export const Segment = styled.div.withConfig({
|
|
116
124
|
displayName: "Segment",
|
|
117
|
-
componentId: "sc-uu3cbo-
|
|
125
|
+
componentId: "sc-uu3cbo-27"
|
|
118
126
|
})(["display:inline-flex;border:1px solid ", ";border-radius:6px;overflow:hidden;"], Color.DIVIDER);
|
|
119
127
|
export const SegmentItem = styled.button.withConfig({
|
|
120
128
|
displayName: "SegmentItem",
|
|
121
|
-
componentId: "sc-uu3cbo-
|
|
129
|
+
componentId: "sc-uu3cbo-28"
|
|
122
130
|
})(["font:inherit;font-size:13px;cursor:pointer;padding:7px 14px;border:none;background:", ";color:", ";& + &{border-left:1px solid ", ";}"], ({
|
|
123
131
|
$active
|
|
124
132
|
}) => $active ? Color.PRIMARY : Color.CLEAR, ({
|
|
@@ -126,11 +134,11 @@ export const SegmentItem = styled.button.withConfig({
|
|
|
126
134
|
}) => $active ? Color.CLEAR : Color.MAIN, Color.DIVIDER);
|
|
127
135
|
export const CropStrip = styled.div.withConfig({
|
|
128
136
|
displayName: "CropStrip",
|
|
129
|
-
componentId: "sc-uu3cbo-
|
|
137
|
+
componentId: "sc-uu3cbo-29"
|
|
130
138
|
})(["display:flex;gap:10px;flex-wrap:wrap;align-items:flex-start;"]);
|
|
131
139
|
export const CropThumb = styled.div.withConfig({
|
|
132
140
|
displayName: "CropThumb",
|
|
133
|
-
componentId: "sc-uu3cbo-
|
|
141
|
+
componentId: "sc-uu3cbo-30"
|
|
134
142
|
})(["position:relative;width:88px;border:1px solid ", ";box-shadow:", ";border-radius:6px;overflow:hidden;background:", ";"], ({
|
|
135
143
|
$selected
|
|
136
144
|
}) => $selected ? Color.PRIMARY : Color.DIVIDER, ({
|
|
@@ -138,23 +146,23 @@ export const CropThumb = styled.div.withConfig({
|
|
|
138
146
|
}) => $selected ? `0 0 0 1px ${Color.PRIMARY}` : 'none', Color.SOFT_LIGHT);
|
|
139
147
|
export const CropThumbButton = styled.button.withConfig({
|
|
140
148
|
displayName: "CropThumbButton",
|
|
141
|
-
componentId: "sc-uu3cbo-
|
|
149
|
+
componentId: "sc-uu3cbo-31"
|
|
142
150
|
})(["display:block;width:100%;padding:0;font:inherit;border:none;background:none;cursor:pointer;"]);
|
|
143
151
|
export const CropThumbImage = styled.img.withConfig({
|
|
144
152
|
displayName: "CropThumbImage",
|
|
145
|
-
componentId: "sc-uu3cbo-
|
|
153
|
+
componentId: "sc-uu3cbo-32"
|
|
146
154
|
})(["width:100%;aspect-ratio:1;object-fit:contain;display:block;"]);
|
|
147
155
|
export const CropThumbDelete = styled.div.withConfig({
|
|
148
156
|
displayName: "CropThumbDelete",
|
|
149
|
-
componentId: "sc-uu3cbo-
|
|
157
|
+
componentId: "sc-uu3cbo-33"
|
|
150
158
|
})(["position:absolute;top:4px;right:4px;opacity:0;transition:opacity 0.15s;", ":hover &{opacity:1;}@media (hover:none){opacity:1;}"], CropThumb);
|
|
151
159
|
export const CropThumbCaption = styled.div.withConfig({
|
|
152
160
|
displayName: "CropThumbCaption",
|
|
153
|
-
componentId: "sc-uu3cbo-
|
|
161
|
+
componentId: "sc-uu3cbo-34"
|
|
154
162
|
})(["font-size:10px;text-align:center;padding:3px 2px;color:", ";"], Color.LOCKED);
|
|
155
163
|
export const DesignTile = styled.button.withConfig({
|
|
156
164
|
displayName: "DesignTile",
|
|
157
|
-
componentId: "sc-uu3cbo-
|
|
165
|
+
componentId: "sc-uu3cbo-35"
|
|
158
166
|
})(["display:flex;flex-direction:column;padding:0;font:inherit;text-align:left;cursor:pointer;background:", ";border-radius:6px;overflow:hidden;border:1px solid ", ";box-shadow:", ";transition:border-color 0.15s,box-shadow 0.15s;&:hover:not(:disabled){border-color:", ";}&:disabled{cursor:default;}"], Color.CLEAR, ({
|
|
159
167
|
$selected
|
|
160
168
|
}) => $selected ? Color.PRIMARY : Color.DIVIDER, ({
|
|
@@ -162,27 +170,27 @@ export const DesignTile = styled.button.withConfig({
|
|
|
162
170
|
}) => $selected ? `0 0 0 1px ${Color.PRIMARY}` : 'none', Color.PRIMARY);
|
|
163
171
|
export const DesignCaption = styled.span.withConfig({
|
|
164
172
|
displayName: "DesignCaption",
|
|
165
|
-
componentId: "sc-uu3cbo-
|
|
173
|
+
componentId: "sc-uu3cbo-36"
|
|
166
174
|
})(["display:flex;justify-content:space-between;gap:6px;padding:6px 8px;font-size:", ";color:", ";span:first-child{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}span:last-child{flex-shrink:0;color:", ";}"], FontSize.SMALL, Color.MAIN, Color.LOCKED);
|
|
167
175
|
export const DropzoneRow = styled.div.withConfig({
|
|
168
176
|
displayName: "DropzoneRow",
|
|
169
|
-
componentId: "sc-uu3cbo-
|
|
177
|
+
componentId: "sc-uu3cbo-37"
|
|
170
178
|
})(["display:flex;align-items:stretch;gap:12px;& > :first-child{flex:1;}"]);
|
|
171
179
|
export const CanvaActions = styled.div.withConfig({
|
|
172
180
|
displayName: "CanvaActions",
|
|
173
|
-
componentId: "sc-uu3cbo-
|
|
181
|
+
componentId: "sc-uu3cbo-38"
|
|
174
182
|
})(["display:flex;flex-direction:column;justify-content:center;gap:8px;& > *{width:100%;}"]);
|
|
175
183
|
export const TabBody = styled.div.withConfig({
|
|
176
184
|
displayName: "TabBody",
|
|
177
|
-
componentId: "sc-uu3cbo-
|
|
185
|
+
componentId: "sc-uu3cbo-39"
|
|
178
186
|
})(["padding-top:16px;"]);
|
|
179
187
|
export const SearchRow = styled.div.withConfig({
|
|
180
188
|
displayName: "SearchRow",
|
|
181
|
-
componentId: "sc-uu3cbo-
|
|
189
|
+
componentId: "sc-uu3cbo-40"
|
|
182
190
|
})(["display:flex;gap:8px;margin-bottom:16px;"]);
|
|
183
191
|
export const StockTile = styled.button.withConfig({
|
|
184
192
|
displayName: "StockTile",
|
|
185
|
-
componentId: "sc-uu3cbo-
|
|
193
|
+
componentId: "sc-uu3cbo-41"
|
|
186
194
|
})(["all:unset;background-color:", ";opacity:", ";display:block;width:100%;box-sizing:border-box;cursor:pointer;border-radius:6px;overflow:hidden;border:1px solid ", ";transition:border-color 0.15s,opacity 0.15s;&:hover{border-color:", ";}&:disabled{cursor:default;}"], ({
|
|
187
195
|
$avgColor
|
|
188
196
|
}) => $avgColor || 'transparent', ({
|
|
@@ -190,59 +198,59 @@ export const StockTile = styled.button.withConfig({
|
|
|
190
198
|
}) => $dimmed ? 0.6 : 1, Color.DIVIDER, Color.PRIMARY);
|
|
191
199
|
export const StockCredit = styled.a.withConfig({
|
|
192
200
|
displayName: "StockCredit",
|
|
193
|
-
componentId: "sc-uu3cbo-
|
|
201
|
+
componentId: "sc-uu3cbo-42"
|
|
194
202
|
})(["display:block;margin-top:2px;padding:0 4px 4px;font-size:11px;color:", ";text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;&:hover{text-decoration:underline;}"], Color.LOCKED);
|
|
195
203
|
export const ProviderNote = styled.div.withConfig({
|
|
196
204
|
displayName: "ProviderNote",
|
|
197
|
-
componentId: "sc-uu3cbo-
|
|
205
|
+
componentId: "sc-uu3cbo-43"
|
|
198
206
|
})(["margin-top:16px;text-align:center;font-size:12px;color:", ";a{color:", ";}"], Color.LOCKED, Color.MAIN);
|
|
199
207
|
export const GenerateForm = styled.div.withConfig({
|
|
200
208
|
displayName: "GenerateForm",
|
|
201
|
-
componentId: "sc-uu3cbo-
|
|
209
|
+
componentId: "sc-uu3cbo-44"
|
|
202
210
|
})(["display:flex;flex-direction:column;gap:12px;max-width:560px;"]);
|
|
203
211
|
export const GenerateControls = styled.div.withConfig({
|
|
204
212
|
displayName: "GenerateControls",
|
|
205
|
-
componentId: "sc-uu3cbo-
|
|
213
|
+
componentId: "sc-uu3cbo-45"
|
|
206
214
|
})(["display:flex;align-items:center;gap:8px;"]);
|
|
207
215
|
export const GeneratedPreview = styled.img.withConfig({
|
|
208
216
|
displayName: "GeneratedPreview",
|
|
209
|
-
componentId: "sc-uu3cbo-
|
|
217
|
+
componentId: "sc-uu3cbo-46"
|
|
210
218
|
})(["display:block;max-width:100%;max-height:420px;border-radius:8px;border:1px solid ", ";"], Color.DIVIDER);
|
|
211
219
|
export const SearchField = styled(NativeInput).withConfig({
|
|
212
220
|
displayName: "SearchField",
|
|
213
|
-
componentId: "sc-uu3cbo-
|
|
221
|
+
componentId: "sc-uu3cbo-47"
|
|
214
222
|
})(["flex:1;width:auto;max-width:none;"]);
|
|
215
223
|
export const PromptField = styled(NativeTextarea).withConfig({
|
|
216
224
|
displayName: "PromptField",
|
|
217
|
-
componentId: "sc-uu3cbo-
|
|
225
|
+
componentId: "sc-uu3cbo-48"
|
|
218
226
|
})(["font-family:inherit;resize:vertical;"]);
|
|
219
227
|
export const GeneratedGrid = styled.div.withConfig({
|
|
220
228
|
displayName: "GeneratedGrid",
|
|
221
|
-
componentId: "sc-uu3cbo-
|
|
229
|
+
componentId: "sc-uu3cbo-49"
|
|
222
230
|
})(["display:grid;grid-template-columns:", ";gap:16px;"], ({
|
|
223
231
|
$single
|
|
224
232
|
}) => $single ? '1fr' : 'repeat(2, minmax(0, 1fr))');
|
|
225
233
|
export const GeneratedVariant = styled.div.withConfig({
|
|
226
234
|
displayName: "GeneratedVariant",
|
|
227
|
-
componentId: "sc-uu3cbo-
|
|
235
|
+
componentId: "sc-uu3cbo-50"
|
|
228
236
|
})(["display:flex;flex-direction:column;align-items:flex-start;gap:8px;"]);
|
|
229
237
|
export const StyleRefs = styled.div.withConfig({
|
|
230
238
|
displayName: "StyleRefs",
|
|
231
|
-
componentId: "sc-uu3cbo-
|
|
239
|
+
componentId: "sc-uu3cbo-51"
|
|
232
240
|
})(["display:flex;flex-direction:column;gap:8px;"]);
|
|
233
241
|
export const StyleRefsHeader = styled.div.withConfig({
|
|
234
242
|
displayName: "StyleRefsHeader",
|
|
235
|
-
componentId: "sc-uu3cbo-
|
|
243
|
+
componentId: "sc-uu3cbo-52"
|
|
236
244
|
})(["display:flex;align-items:center;gap:8px;font-size:", ";color:", ";"], FontSize.SMALL, Color.LOCKED);
|
|
237
245
|
export const StyleRefsRow = styled.div.withConfig({
|
|
238
246
|
displayName: "StyleRefsRow",
|
|
239
|
-
componentId: "sc-uu3cbo-
|
|
247
|
+
componentId: "sc-uu3cbo-53"
|
|
240
248
|
})(["display:flex;flex-wrap:wrap;gap:8px;"]);
|
|
241
249
|
export const StyleRefThumb = styled.div.withConfig({
|
|
242
250
|
displayName: "StyleRefThumb",
|
|
243
|
-
componentId: "sc-uu3cbo-
|
|
251
|
+
componentId: "sc-uu3cbo-54"
|
|
244
252
|
})(["position:relative;width:64px;height:64px;border-radius:6px;overflow:hidden;border:1px solid ", ";img{width:100%;height:100%;object-fit:cover;display:block;}"], Color.DIVIDER);
|
|
245
253
|
export const StyleRefRemove = styled.div.withConfig({
|
|
246
254
|
displayName: "StyleRefRemove",
|
|
247
|
-
componentId: "sc-uu3cbo-
|
|
255
|
+
componentId: "sc-uu3cbo-55"
|
|
248
256
|
})(["position:absolute;top:2px;right:2px;border-radius:4px;background:", ";"], Color.CLEAR);
|