@pushwoosh/smart-components-kit 1.22.0 → 1.23.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.
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
3
3
|
import { Button, Chip, Drawer, DrawerBody, DrawerHeader, DrawerTitle, ModalConfirm, NativeInput, useToast } from '@pushwoosh/dumb-components';
|
|
4
|
+
import { Color } from '@pushwoosh/kit-constants';
|
|
4
5
|
import { Columns, Vertical } from '@pushwoosh/kit-helpers';
|
|
5
6
|
import { CloseIcon, TrashIcon } from '@pushwoosh/kit-icons';
|
|
6
7
|
import { Text } from '@pushwoosh/kit-typography';
|
|
@@ -10,7 +11,7 @@ import { CENTER_FOCAL, getCropWindow, getRequestedSize, getStoredOrigin, getStor
|
|
|
10
11
|
import { useDeleteMediaFile } from './hooks';
|
|
11
12
|
import { getAspectRatio, getCropCaption, getThumbUrl } from './mediaFile.utils';
|
|
12
13
|
import { useLang } from './polyglot';
|
|
13
|
-
import { Chips, CropStrip, CropThumb, CropThumbButton, CropThumbCaption, CropThumbDelete, CropThumbImage, FieldLabel, PreviewFrame, PreviewImage, PreviewStage,
|
|
14
|
+
import { Chips, CropStrip, CropThumb, CropThumbButton, CropThumbCaption, CropThumbDelete, CropThumbImage, FieldLabel, PreviewFrame, PreviewImage, PreviewStage, SizeInput } from './styles';
|
|
14
15
|
const RATIOS = [{
|
|
15
16
|
value: 'ASPECT_RATIO_1_1',
|
|
16
17
|
label: '1:1',
|
|
@@ -58,6 +59,15 @@ const RATIOS = [{
|
|
|
58
59
|
}];
|
|
59
60
|
const DEFAULT_SIZE = '1080';
|
|
60
61
|
const DEFAULT_QUALITY = '90';
|
|
62
|
+
const flashRecalculated = input => {
|
|
63
|
+
if (!input || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
|
64
|
+
input.animate([{
|
|
65
|
+
color: Color.PRIMARY
|
|
66
|
+
}, {}], {
|
|
67
|
+
duration: 600,
|
|
68
|
+
easing: 'ease-out'
|
|
69
|
+
});
|
|
70
|
+
};
|
|
61
71
|
export const CreateCropDrawer = ({
|
|
62
72
|
application,
|
|
63
73
|
original,
|
|
@@ -76,7 +86,7 @@ export const CreateCropDrawer = ({
|
|
|
76
86
|
} = useToast();
|
|
77
87
|
const deleteMediaFile = useDeleteMediaFile(application);
|
|
78
88
|
const [ratio, setRatio] = useState('original');
|
|
79
|
-
const [
|
|
89
|
+
const [lastEdited, setLastEdited] = useState('width');
|
|
80
90
|
const [size, setSize] = useState(DEFAULT_SIZE);
|
|
81
91
|
const [quality, setQuality] = useState(DEFAULT_QUALITY);
|
|
82
92
|
const [isCreating, setIsCreating] = useState(false);
|
|
@@ -89,7 +99,7 @@ export const CreateCropDrawer = ({
|
|
|
89
99
|
useEffect(() => {
|
|
90
100
|
if (original) {
|
|
91
101
|
setRatio('original');
|
|
92
|
-
|
|
102
|
+
setLastEdited('width');
|
|
93
103
|
setSize(DEFAULT_SIZE);
|
|
94
104
|
setQuality(DEFAULT_QUALITY);
|
|
95
105
|
setViewedCrop(null);
|
|
@@ -119,7 +129,7 @@ export const CreateCropDrawer = ({
|
|
|
119
129
|
const {
|
|
120
130
|
width: outputWidth,
|
|
121
131
|
height: outputHeight
|
|
122
|
-
} = getRequestedSize(ratioW, ratioH,
|
|
132
|
+
} = getRequestedSize(ratioW, ratioH, lastEdited, sizeValue);
|
|
123
133
|
const srcW = originalMeta?.width ?? 0;
|
|
124
134
|
const srcH = originalMeta?.height ?? 0;
|
|
125
135
|
const canPlaceWindow = !isOriginalView && srcW > 0 && srcH > 0;
|
|
@@ -134,20 +144,34 @@ export const CreateCropDrawer = ({
|
|
|
134
144
|
height: outputHeight
|
|
135
145
|
};
|
|
136
146
|
const isCapped = storedSize.width !== outputWidth || storedSize.height !== outputHeight;
|
|
137
|
-
// Both inputs are
|
|
138
|
-
// read-only and shows the value computed from the aspect ratio.
|
|
147
|
+
// Both inputs are editable; the last edited one drives the size, the other follows the ratio.
|
|
139
148
|
const computedText = value => isSizeValid ? String(value) : '';
|
|
140
|
-
const widthText =
|
|
141
|
-
const heightText =
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// numbers stay put and only editability swaps.
|
|
146
|
-
if (isSizeValid) {
|
|
147
|
-
setSize(String(next === 'width' ? outputWidth : outputHeight));
|
|
148
|
-
}
|
|
149
|
-
setDimension(next);
|
|
149
|
+
const widthText = lastEdited === 'width' ? size : computedText(outputWidth);
|
|
150
|
+
const heightText = lastEdited === 'height' ? size : computedText(outputHeight);
|
|
151
|
+
const handleSizeChange = (edited, value) => {
|
|
152
|
+
setLastEdited(edited);
|
|
153
|
+
setSize(value);
|
|
150
154
|
};
|
|
155
|
+
const widthInputRef = useRef(null);
|
|
156
|
+
const heightInputRef = useRef(null);
|
|
157
|
+
const prevSizeRef = useRef({
|
|
158
|
+
original,
|
|
159
|
+
ratio,
|
|
160
|
+
width: widthText,
|
|
161
|
+
height: heightText
|
|
162
|
+
});
|
|
163
|
+
useLayoutEffect(() => {
|
|
164
|
+
const prev = prevSizeRef.current;
|
|
165
|
+
prevSizeRef.current = {
|
|
166
|
+
original,
|
|
167
|
+
ratio,
|
|
168
|
+
width: widthText,
|
|
169
|
+
height: heightText
|
|
170
|
+
};
|
|
171
|
+
if (isOriginalView || prev.original !== original || prev.ratio === 'original') return;
|
|
172
|
+
if (lastEdited === 'width' && heightText && heightText !== prev.height) flashRecalculated(heightInputRef.current);
|
|
173
|
+
if (lastEdited === 'height' && widthText && widthText !== prev.width) flashRecalculated(widthInputRef.current);
|
|
174
|
+
}, [original, ratio, isOriginalView, lastEdited, widthText, heightText]);
|
|
151
175
|
// A crop is the same one only at the same ratio, output size and window position.
|
|
152
176
|
const duplicateExists = !isOriginalView && isSizeValid && existingCrops.some(crop => {
|
|
153
177
|
if (crop.meta?.type !== 'imageMeta') return false;
|
|
@@ -172,7 +196,7 @@ export const CreateCropDrawer = ({
|
|
|
172
196
|
uuid: parent.uuid,
|
|
173
197
|
ratio,
|
|
174
198
|
size: {
|
|
175
|
-
type:
|
|
199
|
+
type: lastEdited,
|
|
176
200
|
data: sizeValue
|
|
177
201
|
},
|
|
178
202
|
...(isJpeg ? {
|
|
@@ -265,45 +289,31 @@ export const CreateCropDrawer = ({
|
|
|
265
289
|
message: 'SMART.MEDIA_STORAGE.CREATE_CROP.SIZE_LABEL'
|
|
266
290
|
})
|
|
267
291
|
}), _jsxs(Columns, {
|
|
268
|
-
"$sizes": "auto 1fr
|
|
292
|
+
"$sizes": "1fr auto 1fr",
|
|
269
293
|
"$gap": 8,
|
|
270
294
|
"$alignItems": "center",
|
|
271
|
-
children: [
|
|
272
|
-
children: [_jsx(SegmentItem, {
|
|
273
|
-
type: "button",
|
|
274
|
-
"$active": dimension === 'width',
|
|
275
|
-
onClick: () => handleDimensionChange('width'),
|
|
276
|
-
children: lang({
|
|
277
|
-
message: 'SMART.MEDIA_STORAGE.CREATE_CROP.WIDTH'
|
|
278
|
-
})
|
|
279
|
-
}), _jsx(SegmentItem, {
|
|
280
|
-
type: "button",
|
|
281
|
-
"$active": dimension === 'height',
|
|
282
|
-
onClick: () => handleDimensionChange('height'),
|
|
283
|
-
children: lang({
|
|
284
|
-
message: 'SMART.MEDIA_STORAGE.CREATE_CROP.HEIGHT'
|
|
285
|
-
})
|
|
286
|
-
})]
|
|
287
|
-
}), _jsx(SizeInput, {
|
|
295
|
+
children: [_jsx(SizeInput, {
|
|
288
296
|
type: "number",
|
|
289
297
|
min: 1,
|
|
290
298
|
value: widthText,
|
|
291
|
-
|
|
292
|
-
|
|
299
|
+
"$isErrored": lastEdited === 'width' && !isSizeValid,
|
|
300
|
+
ref: widthInputRef,
|
|
293
301
|
"aria-label": lang({
|
|
294
302
|
message: 'SMART.MEDIA_STORAGE.CREATE_CROP.WIDTH'
|
|
295
303
|
}),
|
|
296
|
-
onChange: event =>
|
|
304
|
+
onChange: event => handleSizeChange('width', event.target.value)
|
|
305
|
+
}), _jsx(Text, {
|
|
306
|
+
children: "\u00D7"
|
|
297
307
|
}), _jsx(SizeInput, {
|
|
298
308
|
type: "number",
|
|
299
309
|
min: 1,
|
|
300
310
|
value: heightText,
|
|
301
|
-
|
|
302
|
-
|
|
311
|
+
"$isErrored": lastEdited === 'height' && !isSizeValid,
|
|
312
|
+
ref: heightInputRef,
|
|
303
313
|
"aria-label": lang({
|
|
304
314
|
message: 'SMART.MEDIA_STORAGE.CREATE_CROP.HEIGHT'
|
|
305
315
|
}),
|
|
306
|
-
onChange: event =>
|
|
316
|
+
onChange: event => handleSizeChange('height', event.target.value)
|
|
307
317
|
})]
|
|
308
318
|
})]
|
|
309
319
|
}), _jsxs(Vertical, {
|
package/MediaStorage/styles.js
CHANGED
|
@@ -115,7 +115,7 @@ export const FieldLabel = styled.div.withConfig({
|
|
|
115
115
|
export const SizeInput = styled(NativeInput).withConfig({
|
|
116
116
|
displayName: "SizeInput",
|
|
117
117
|
componentId: "sc-uu3cbo-25"
|
|
118
|
-
})(["
|
|
118
|
+
})(["-webkit-text-fill-color:currentColor;"]);
|
|
119
119
|
export const Chips = styled.div.withConfig({
|
|
120
120
|
displayName: "Chips",
|
|
121
121
|
componentId: "sc-uu3cbo-26"
|