@pushwoosh/smart-components-kit 1.20.0 → 1.21.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.
@@ -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, getRequestedSize, getStoredOrigin, getStoredSize } 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,14 +108,32 @@ 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');
110
115
  setViewedCrop(crop);
111
116
  };
112
117
  const selectedRatio = RATIOS.find(item => item.value === ratio) ?? RATIOS[0];
113
- const outputWidth = dimension === 'width' ? sizeValue : Math.round(sizeValue * selectedRatio.ar);
114
- const outputHeight = dimension === 'height' ? sizeValue : Math.round(sizeValue / selectedRatio.ar);
118
+ const [ratioW, ratioH] = selectedRatio.label.split(':').map(Number);
119
+ const {
120
+ width: outputWidth,
121
+ height: outputHeight
122
+ } = getRequestedSize(ratioW, ratioH, dimension, sizeValue);
123
+ const srcW = originalMeta?.width ?? 0;
124
+ const srcH = originalMeta?.height ?? 0;
125
+ const canPlaceWindow = !isOriginalView && srcW > 0 && srcH > 0;
126
+ const cropWindow = canPlaceWindow ? getCropWindow(srcW, srcH, ratioW, ratioH, focal) : null;
127
+ const centeredWindow = canPlaceWindow ? getCropWindow(srcW, srcH, ratioW, ratioH, CENTER_FOCAL) : null;
128
+ const isOffCenter = Boolean(cropWindow && centeredWindow && (cropWindow.x !== centeredWindow.x || cropWindow.y !== centeredWindow.y));
129
+ const storedSize = cropWindow ? getStoredSize(cropWindow, {
130
+ width: outputWidth,
131
+ height: outputHeight
132
+ }) : {
133
+ width: outputWidth,
134
+ height: outputHeight
135
+ };
136
+ const isCapped = storedSize.width !== outputWidth || storedSize.height !== outputHeight;
115
137
  // Both inputs are always visible: the driving one is editable, the other is
116
138
  // read-only and shows the value computed from the aspect ratio.
117
139
  const computedText = value => isSizeValid ? String(value) : '';
@@ -126,9 +148,18 @@ export const CreateCropDrawer = ({
126
148
  }
127
149
  setDimension(next);
128
150
  };
129
- // Same ratio with a different size is allowed; only an exact ratio + output
130
- // size match counts as a duplicate.
131
- const duplicateExists = !isOriginalView && isSizeValid && existingCrops.some(crop => crop.meta?.type === 'imageMeta' && crop.meta.data.ratio === selectedRatio.label && crop.meta.data.width === outputWidth && crop.meta.data.height === outputHeight);
151
+ // A crop is the same one only at the same ratio, output size and window position.
152
+ const duplicateExists = !isOriginalView && isSizeValid && existingCrops.some(crop => {
153
+ if (crop.meta?.type !== 'imageMeta') return false;
154
+ const {
155
+ ratio: cropRatio,
156
+ width,
157
+ height
158
+ } = crop.meta.data;
159
+ if (cropRatio !== selectedRatio.label || width !== storedSize.width || height !== storedSize.height) return false;
160
+ const origin = getStoredOrigin(crop.url);
161
+ return isOffCenter ? origin?.x === cropWindow?.x && origin?.y === cropWindow?.y : origin === null;
162
+ });
132
163
  const handleCreate = async () => {
133
164
  if (!original || ratio === 'original' || !isSizeValid || !isQualityValid || duplicateExists) return;
134
165
  // Capture the parent up front so a concurrent reopen for another image
@@ -136,7 +167,7 @@ export const CreateCropDrawer = ({
136
167
  const parent = original;
137
168
  setIsCreating(true);
138
169
  try {
139
- const response = await rpcGateway.mediaFiles.CreateVariant({
170
+ const request = {
140
171
  application,
141
172
  uuid: parent.uuid,
142
173
  ratio,
@@ -146,8 +177,12 @@ export const CreateCropDrawer = ({
146
177
  },
147
178
  ...(isJpeg ? {
148
179
  quality: qualityValue
180
+ } : {}),
181
+ ...(isOffCenter ? {
182
+ focalPoint: focal
149
183
  } : {})
150
- });
184
+ };
185
+ const response = await rpcGateway.mediaFiles.CreateVariant(request);
151
186
  openToast({
152
187
  title: lang({
153
188
  message: 'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS'
@@ -274,19 +309,38 @@ export const CreateCropDrawer = ({
274
309
  }), _jsxs(Vertical, {
275
310
  "$gap": 6,
276
311
  children: [_jsx(PreviewStage, {
277
- children: _jsx(PreviewFrame, {
312
+ children: canPlaceWindow && cropWindow ? _jsx(CropFramePicker, {
313
+ src: original.url,
314
+ alt: original.filename,
315
+ imageRatio: srcW / srcH,
316
+ windowWidth: cropWindow.width / srcW,
317
+ windowHeight: cropWindow.height / srcH,
318
+ focal: focal,
319
+ label: lang({
320
+ message: 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT'
321
+ }),
322
+ onChange: setFocal
323
+ }) : _jsx(PreviewFrame, {
278
324
  "$ratio": isOriginalView ? getAspectRatio(previewFile) : selectedRatio.ar,
279
325
  children: _jsx(PreviewImage, {
280
326
  src: previewFile.url,
281
327
  alt: previewFile.filename
282
328
  })
283
329
  })
330
+ }), canPlaceWindow && _jsx(Text, {
331
+ children: lang({
332
+ message: 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT'
333
+ })
284
334
  }), viewedCrop && _jsx(Text, {
285
335
  children: getCropCaption(viewedCrop)
286
336
  }), isOriginalShown && originalMeta && _jsxs(Text, {
287
337
  children: [originalMeta.width, ' × ', originalMeta.height]
288
338
  }), !isOriginalView && isSizeValid && _jsxs(Text, {
289
- children: [selectedRatio.label, ' · ', outputWidth, ' × ', outputHeight]
339
+ children: [selectedRatio.label, ' · ', storedSize.width, ' × ', storedSize.height]
340
+ }), !isOriginalView && isSizeValid && isCapped && _jsx(Text, {
341
+ children: lang({
342
+ message: 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT'
343
+ })
290
344
  })]
291
345
  }), !isOriginalView && isJpeg && _jsxs("div", {
292
346
  children: [_jsx(FieldLabel, {
@@ -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
+ };
@@ -0,0 +1,35 @@
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;
23
+ /** Size requested by the width/height field, derived like rpc-v2 `targetSize` (integer division). */
24
+ export declare const getRequestedSize: (ratioW: number, ratioH: number, dimension: "width" | "height", size: number) => {
25
+ width: number;
26
+ height: number;
27
+ };
28
+ /** Size rpc-v2 stores for a request: the requested one when smaller than the window, else the window. */
29
+ export declare const getStoredSize: (window: CropRect, requested: {
30
+ width: number;
31
+ height: number;
32
+ }) => {
33
+ width: number;
34
+ height: number;
35
+ };
@@ -0,0 +1,56 @@
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
+ };
37
+ /** Size requested by the width/height field, derived like rpc-v2 `targetSize` (integer division). */
38
+ export const getRequestedSize = (ratioW, ratioH, dimension, size) => {
39
+ const value = Math.floor(size);
40
+ if (!(value > 0)) return {
41
+ width: 0,
42
+ height: 0
43
+ };
44
+ return dimension === 'width' ? {
45
+ width: value,
46
+ height: Math.floor(value * ratioH / ratioW)
47
+ } : {
48
+ width: Math.floor(value * ratioW / ratioH),
49
+ height: value
50
+ };
51
+ };
52
+ /** Size rpc-v2 stores for a request: the requested one when smaller than the window, else the window. */
53
+ export const getStoredSize = (window, requested) => requested.width > 0 && requested.height > 0 && requested.width < window.width ? requested : {
54
+ width: window.width,
55
+ height: window.height
56
+ };
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'لا توجد اقتصاصات بعد',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'تم إنشاء الاقتصاص',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'تعذّر إنشاء الاقتصاص',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'الأصل أصغر، لذلك يُحفظ الاقتصاص بهذا الحجم',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'اسحب الإطار لاختيار منطقة الاقتصاص',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'عرض هذا الاقتصاص',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'حذف الاقتصاص',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'حذف هذا الاقتصاص؟',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'এখনো কোনো ক্রপ নেই',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'ক্রপ তৈরি হয়েছে',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'ক্রপ তৈরি করা যায়নি',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'মূল ছবি ছোট, তাই ক্রপ এই আকারে সংরক্ষিত হবে',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'ক্রপের এলাকা বেছে নিতে ফ্রেম টেনে আনুন',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'এই ক্রপ দেখান',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'ক্রপ মুছুন',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'এই ক্রপটি মুছবেন?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Noch keine Zuschnitte',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Zuschnitt erstellt',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Zuschnitt konnte nicht erstellt werden',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'Das Original ist kleiner, daher wird der Zuschnitt in dieser Größe gespeichert',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Rahmen ziehen, um den Zuschnitt zu wählen',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Zuschnitt anzeigen',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Zuschnitt löschen',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Diesen Zuschnitt löschen?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'No crops yet',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Crop created',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Failed to create crop',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'The original is smaller, so the crop is saved at this size',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Drag the frame to choose the crop area',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Show this crop',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Delete crop',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Delete this crop?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Aún no hay recortes',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Recorte creado',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'No se pudo crear el recorte',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'El original es más pequeño, así que el recorte se guarda con este tamaño',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Arrastra el marco para elegir el área del recorte',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Mostrar este recorte',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Eliminar recorte',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': '¿Eliminar este recorte?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Aucun recadrage pour le moment',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Recadrage créé',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Échec de la création du recadrage',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'L’original est plus petit, le recadrage est donc enregistré à cette taille',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Faites glisser le cadre pour choisir la zone du recadrage',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Afficher ce recadrage',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Supprimer le recadrage',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Supprimer ce recadrage ?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'אין עדיין חיתוכים',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'החיתוך נוצר',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'יצירת החיתוך נכשלה',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'המקור קטן יותר, ולכן החיתוך יישמר בגודל הזה',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'גררו את המסגרת כדי לבחור את אזור החיתוך',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'הצג חיתוך זה',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'מחיקת חיתוך',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'למחוק את החיתוך הזה?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'अभी तक कोई क्रॉप नहीं',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'क्रॉप बनाया गया',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'क्रॉप नहीं बनाया जा सका',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'मूल छवि छोटी है, इसलिए क्रॉप इसी आकार में सहेजा जाएगा',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'क्रॉप क्षेत्र चुनने के लिए फ़्रेम खींचें',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'यह क्रॉप दिखाएँ',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'क्रॉप हटाएँ',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'यह क्रॉप हटाएँ?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'トリミングはまだありません',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'トリミングを作成しました',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'トリミングの作成に失敗しました',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': '元画像が小さいため、このサイズで保存されます',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': '枠をドラッグしてトリミング範囲を選択',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'このトリミングを表示',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'トリミングを削除',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'このトリミングを削除しますか?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': '아직 크롭이 없습니다',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': '크롭이 생성되었습니다',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': '크롭을 생성하지 못했습니다',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': '원본이 더 작아 이 크기로 저장됩니다',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': '프레임을 드래그해 크롭 영역을 선택하세요',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': '이 크롭 보기',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': '크롭 삭제',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': '이 크롭을 삭제하시겠습니까?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Nenhum recorte ainda',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Recorte criado',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Falha ao criar o recorte',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'O original é menor, então o recorte é salvo neste tamanho',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Arraste o quadro para escolher a área do recorte',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Mostrar este recorte',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Excluir recorte',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Excluir este recorte?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'Кропов пока нет',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'Кроп создан',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'Не удалось создать кроп',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'Оригинал меньше, поэтому кроп сохранится в этом размере',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'Перетащите рамку, чтобы выбрать область кропа',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'Показать кроп',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'Удалить кроп',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'Удалить кроп?',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': 'ยังไม่มีครอป',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': 'สร้างครอปแล้ว',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': 'สร้างครอปไม่สำเร็จ',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': 'ภาพต้นฉบับเล็กกว่า จึงบันทึกภาพครอปที่ขนาดนี้',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': 'ลากกรอบเพื่อเลือกพื้นที่ครอป',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': 'แสดงภาพครอปนี้',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': 'ลบครอป',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': 'ลบครอปนี้ใช่ไหม',
@@ -52,6 +52,8 @@ export const messages = {
52
52
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': '暂无裁剪图',
53
53
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': '裁剪图已创建',
54
54
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': '创建裁剪图失败',
55
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': '原图较小,裁剪将按此尺寸保存',
56
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': '拖动框选择裁剪区域',
55
57
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': '查看此裁剪',
56
58
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': '删除裁剪图',
57
59
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': '删除此裁剪图?',
@@ -75,6 +75,8 @@ export type MediaStorageMessages = {
75
75
  'SMART.MEDIA_STORAGE.CREATE_CROP.NO_CROPS': NoParams;
76
76
  'SMART.MEDIA_STORAGE.CREATE_CROP.SUCCESS': NoParams;
77
77
  'SMART.MEDIA_STORAGE.CREATE_CROP.ERROR': NoParams;
78
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.CAPPED_HINT': NoParams;
79
+ 'SMART.MEDIA_STORAGE.CREATE_CROP.DRAG_HINT': NoParams;
78
80
  'SMART.MEDIA_STORAGE.CREATE_CROP.PREVIEW_HINT': NoParams;
79
81
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_HINT': NoParams;
80
82
  'SMART.MEDIA_STORAGE.CREATE_CROP.DELETE_CONFIRM.TITLE': NoParams;
@@ -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;
@@ -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-21"
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-22"
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-23"
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-24"
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-25"
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-26"
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-27"
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-28"
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-29"
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-30"
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-31"
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-32"
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-33"
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-34"
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-35"
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-36"
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-37"
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-38"
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-39"
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-40"
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-41"
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-42"
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-43"
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-44"
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-45"
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-46"
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-47"
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-48"
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-49"
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-50"
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-51"
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-52"
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-53"
255
+ componentId: "sc-uu3cbo-55"
248
256
  })(["position:absolute;top:2px;right:2px;border-radius:4px;background:", ";"], Color.CLEAR);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/smart-components-kit",
3
- "version": "1.20.0",
3
+ "version": "1.21.1",
4
4
  "description": "Stateful, data-connected React components shared by Pushwoosh micro-frontends",
5
5
  "repository": {
6
6
  "type": "git",