@pushwoosh/smart-components-kit 1.3.14 → 1.3.16
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/MediaStorage.js +93 -6
- package/MediaStorage/hooks.d.ts +3 -6
- package/MediaStorage/hooks.js +51 -6
- package/MediaStorage/polyglot/messages_en.js +9 -0
- package/MediaStorage/polyglot/messages_ru.js +9 -0
- package/MediaStorage/polyglot/types.d.ts +17 -0
- package/MediaStorage/styled.d.ts +6 -1
- package/MediaStorage/styled.js +35 -19
- package/package.json +2 -2
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { Button, DropdownMenuButton, DropdownMenuItem, DropdownMenuSection, ModalConfirm, useToast } from '@pushwoosh/dumb-components';
|
|
3
|
+
import { Button, Checkbox, DropdownMenuButton, DropdownMenuItem, DropdownMenuSection, ModalConfirm, useToast } from '@pushwoosh/dumb-components';
|
|
4
4
|
import { FlexContainer, useAsync } from '@pushwoosh/kit-helpers';
|
|
5
5
|
import { CheckIcon, EditIcon, TrashIcon, UploadIcon } from '@pushwoosh/kit-icons';
|
|
6
6
|
import { Text } from '@pushwoosh/kit-typography';
|
|
7
7
|
import { useSPAContext } from '@pushwoosh/spa-context';
|
|
8
8
|
import { CreateCropDrawer } from './CreateCropDrawer';
|
|
9
|
-
import { useDeleteMediaFile } from './hooks';
|
|
9
|
+
import { useDeleteMediaFile, useDeleteMediaFiles } from './hooks';
|
|
10
10
|
import { formatBytes, getCropCaption, getThumbUrl } from './mediaFile.utils';
|
|
11
|
-
import { useLang } from './polyglot';
|
|
12
|
-
import { CropBadge, Dropzone, EmptyState, Grid, HiddenInput, Tile, TileActions, TileImage, UsageLine, WarningBadge } from './styled';
|
|
11
|
+
import { Lang, useLang } from './polyglot';
|
|
12
|
+
import { CropBadge, Dropzone, EmptyState, Grid, HiddenInput, SelectionBar, SelectionCount, Tile, TileActions, TileCheckbox, TileImage, UsageLine, WarningBadge } from './styled';
|
|
13
13
|
const UPLOAD_PATH = '/api/media/upload';
|
|
14
14
|
const ALLOWED_IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp'];
|
|
15
15
|
const isAllowedImage = file => {
|
|
@@ -42,6 +42,7 @@ export const MediaStorage = ({
|
|
|
42
42
|
openToast
|
|
43
43
|
} = useToast();
|
|
44
44
|
const deleteMediaFile = useDeleteMediaFile(application);
|
|
45
|
+
const deleteMediaFiles = useDeleteMediaFiles(application);
|
|
45
46
|
const uploadInputRef = useRef(null);
|
|
46
47
|
// `uploadFiles` resolves asynchronously; read the latest page from the ref so
|
|
47
48
|
// the post-upload decision isn't made on a value captured at click time.
|
|
@@ -58,6 +59,9 @@ export const MediaStorage = ({
|
|
|
58
59
|
const [isDragOver, setIsDragOver] = useState(false);
|
|
59
60
|
const [createCropFor, setCreateCropFor] = useState(null);
|
|
60
61
|
const [pendingDelete, setPendingDelete] = useState(null);
|
|
62
|
+
const [selectedUuids, setSelectedUuids] = useState([]);
|
|
63
|
+
const [isBulkDeleteOpen, setIsBulkDeleteOpen] = useState(false);
|
|
64
|
+
const [isBulkDeleting, setIsBulkDeleting] = useState(false);
|
|
61
65
|
// Format filtering belongs to the query, not the response: `total` and the page count come
|
|
62
66
|
// from the filtered set, so a client-side filter would paginate over files it then hides.
|
|
63
67
|
const listAsync = useAsync(async () => {
|
|
@@ -102,6 +106,7 @@ export const MediaStorage = ({
|
|
|
102
106
|
const originals = listAsync.value?.files;
|
|
103
107
|
if (!originals) return undefined;
|
|
104
108
|
setCropsByUuid({});
|
|
109
|
+
setSelectedUuids([]);
|
|
105
110
|
let cancelled = false;
|
|
106
111
|
originals.forEach(file => {
|
|
107
112
|
void (async () => {
|
|
@@ -209,6 +214,31 @@ export const MediaStorage = ({
|
|
|
209
214
|
}
|
|
210
215
|
setReloadToken(token => token + 1);
|
|
211
216
|
};
|
|
217
|
+
const handleBulkDeleteConfirmed = async () => {
|
|
218
|
+
const uuids = selectedUuids;
|
|
219
|
+
setIsBulkDeleteOpen(false);
|
|
220
|
+
if (uuids.length === 0 || isBulkDeleting) return;
|
|
221
|
+
// The batch outlives the page it started on, so the step-back decision uses
|
|
222
|
+
// the page and count captured here and is skipped if the page moved since.
|
|
223
|
+
const pageAtStart = pageRef.current;
|
|
224
|
+
const countAtStart = filesCountRef.current;
|
|
225
|
+
setIsBulkDeleting(true);
|
|
226
|
+
try {
|
|
227
|
+
const deleted = await deleteMediaFiles(uuids);
|
|
228
|
+
if (deleted === 0) return;
|
|
229
|
+
setSelectedUuids([]);
|
|
230
|
+
if (deleted >= countAtStart && pageAtStart > 0 && pageRef.current === pageAtStart) {
|
|
231
|
+
onPageChange(pageAtStart - 1);
|
|
232
|
+
}
|
|
233
|
+
setReloadToken(token => token + 1);
|
|
234
|
+
} finally {
|
|
235
|
+
setIsBulkDeleting(false);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
const toggleSelected = uuid => {
|
|
239
|
+
setSelectedUuids(prev => prev.includes(uuid) ? prev.filter(item => item !== uuid) : [...prev, uuid]);
|
|
240
|
+
};
|
|
241
|
+
const isAllSelected = files.length > 0 && selectedUuids.length === files.length;
|
|
212
242
|
const totalPages = Math.ceil(total / perPage);
|
|
213
243
|
const showPagination = !loading && files.length > 0 && totalPages > 1;
|
|
214
244
|
return _jsxs(_Fragment, {
|
|
@@ -249,14 +279,55 @@ export const MediaStorage = ({
|
|
|
249
279
|
children: lang({
|
|
250
280
|
message: 'SMART.MEDIA_STORAGE.EMPTY'
|
|
251
281
|
})
|
|
282
|
+
}), !loading && files.length > 0 && _jsxs(SelectionBar, {
|
|
283
|
+
children: [_jsx(Checkbox, {
|
|
284
|
+
label: lang({
|
|
285
|
+
message: 'SMART.MEDIA_STORAGE.SELECT_ALL'
|
|
286
|
+
}),
|
|
287
|
+
isChecked: isAllSelected,
|
|
288
|
+
isDisabled: isBulkDeleting,
|
|
289
|
+
isIndeterminate: selectedUuids.length > 0 && !isAllSelected,
|
|
290
|
+
onChange: () => setSelectedUuids(isAllSelected ? [] : files.map(file => file.uuid))
|
|
291
|
+
}), selectedUuids.length > 0 && _jsxs(_Fragment, {
|
|
292
|
+
children: [_jsx(SelectionCount, {
|
|
293
|
+
children: _jsx(Lang, {
|
|
294
|
+
message: "SMART.MEDIA_STORAGE.SELECTED_COUNT",
|
|
295
|
+
count: selectedUuids.length
|
|
296
|
+
})
|
|
297
|
+
}), _jsx(Button, {
|
|
298
|
+
color: "danger",
|
|
299
|
+
size: "compact",
|
|
300
|
+
view: "ghost",
|
|
301
|
+
icon: _jsx(TrashIcon, {
|
|
302
|
+
size: "small",
|
|
303
|
+
view: "lined"
|
|
304
|
+
}),
|
|
305
|
+
isLoading: isBulkDeleting,
|
|
306
|
+
isDisabled: isBulkDeleting,
|
|
307
|
+
onClick: () => setIsBulkDeleteOpen(true),
|
|
308
|
+
children: _jsx(Lang, {
|
|
309
|
+
message: "SMART.MEDIA_STORAGE.BULK_DELETE_BUTTON"
|
|
310
|
+
})
|
|
311
|
+
})]
|
|
312
|
+
})]
|
|
252
313
|
}), !loading && files.length > 0 && _jsx(Grid, {
|
|
253
314
|
children: files.map(file => {
|
|
254
315
|
const crops = cropsByUuid[file.uuid] ?? [];
|
|
255
316
|
const warning = fileWarning?.(file);
|
|
256
317
|
return _jsxs(Tile, {
|
|
318
|
+
"$selected": selectedUuids.includes(file.uuid),
|
|
257
319
|
children: [_jsx(TileImage, {
|
|
258
320
|
src: getThumbUrl(file),
|
|
259
321
|
alt: file.filename
|
|
322
|
+
}), _jsx(TileCheckbox, {
|
|
323
|
+
title: lang({
|
|
324
|
+
message: 'SMART.MEDIA_STORAGE.SELECT_FILE_HINT'
|
|
325
|
+
}),
|
|
326
|
+
children: _jsx(Checkbox, {
|
|
327
|
+
isChecked: selectedUuids.includes(file.uuid),
|
|
328
|
+
isDisabled: isBulkDeleting,
|
|
329
|
+
onChange: () => toggleSelected(file.uuid)
|
|
330
|
+
})
|
|
260
331
|
}), crops.length > 0 && _jsx(CropBadge, {
|
|
261
332
|
children: lang({
|
|
262
333
|
message: 'SMART.MEDIA_STORAGE.CROPS_BADGE',
|
|
@@ -315,6 +386,7 @@ export const MediaStorage = ({
|
|
|
315
386
|
"aria-label": lang({
|
|
316
387
|
message: 'SMART.MEDIA_STORAGE.DELETE_HINT'
|
|
317
388
|
}),
|
|
389
|
+
isDisabled: isBulkDeleting,
|
|
318
390
|
onClick: () => setPendingDelete(file)
|
|
319
391
|
})]
|
|
320
392
|
})]
|
|
@@ -332,7 +404,7 @@ export const MediaStorage = ({
|
|
|
332
404
|
view: "ghost",
|
|
333
405
|
color: "secondary",
|
|
334
406
|
size: "field",
|
|
335
|
-
isDisabled: page <= 0,
|
|
407
|
+
isDisabled: page <= 0 || isBulkDeleting,
|
|
336
408
|
onClick: () => onPageChange(page - 1),
|
|
337
409
|
children: lang({
|
|
338
410
|
message: 'SMART.MEDIA_STORAGE.PREV_BUTTON'
|
|
@@ -343,7 +415,7 @@ export const MediaStorage = ({
|
|
|
343
415
|
view: "ghost",
|
|
344
416
|
color: "secondary",
|
|
345
417
|
size: "field",
|
|
346
|
-
isDisabled: page + 1 >= totalPages,
|
|
418
|
+
isDisabled: page + 1 >= totalPages || isBulkDeleting,
|
|
347
419
|
onClick: () => onPageChange(page + 1),
|
|
348
420
|
children: lang({
|
|
349
421
|
message: 'SMART.MEDIA_STORAGE.NEXT_BUTTON'
|
|
@@ -378,6 +450,21 @@ export const MediaStorage = ({
|
|
|
378
450
|
confirmButtonColor: "danger",
|
|
379
451
|
onAccept: () => void handleDeleteConfirmed(),
|
|
380
452
|
onCancel: () => setPendingDelete(null)
|
|
453
|
+
}), _jsx(ModalConfirm, {
|
|
454
|
+
isOpen: isBulkDeleteOpen,
|
|
455
|
+
title: lang({
|
|
456
|
+
message: 'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.TITLE',
|
|
457
|
+
count: selectedUuids.length
|
|
458
|
+
}),
|
|
459
|
+
description: lang({
|
|
460
|
+
message: 'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.DESCRIPTION'
|
|
461
|
+
}),
|
|
462
|
+
confirmButtonText: lang({
|
|
463
|
+
message: 'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.BUTTON'
|
|
464
|
+
}),
|
|
465
|
+
confirmButtonColor: "danger",
|
|
466
|
+
onAccept: () => void handleBulkDeleteConfirmed(),
|
|
467
|
+
onCancel: () => setIsBulkDeleteOpen(false)
|
|
381
468
|
})]
|
|
382
469
|
});
|
|
383
470
|
};
|
package/MediaStorage/hooks.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns a function that deletes a media file (original or crop) and shows the
|
|
3
|
-
* success/error toast. Resolves to `true` on success so the caller can run its
|
|
4
|
-
* own post-delete routing (refetch, state update, pagination), `false` on
|
|
5
|
-
* failure. Both `MediaStorage` and `CreateCropDrawer` share this.
|
|
6
|
-
*/
|
|
1
|
+
/** Deletes one media file with its own toast; resolves to `true` on success. */
|
|
7
2
|
export declare function useDeleteMediaFile(application: string): (uuid: string) => Promise<boolean>;
|
|
3
|
+
/** Deletes media files in a bounded-concurrency batch; resolves to the number deleted. */
|
|
4
|
+
export declare function useDeleteMediaFiles(application: string): (uuids: string[]) => Promise<number>;
|
package/MediaStorage/hooks.js
CHANGED
|
@@ -2,12 +2,7 @@ import { useToast } from '@pushwoosh/dumb-components';
|
|
|
2
2
|
import { usePersistentFunction } from '@pushwoosh/kit-helpers';
|
|
3
3
|
import { useSPAContext } from '@pushwoosh/spa-context';
|
|
4
4
|
import { useLang } from './polyglot';
|
|
5
|
-
/**
|
|
6
|
-
* Returns a function that deletes a media file (original or crop) and shows the
|
|
7
|
-
* success/error toast. Resolves to `true` on success so the caller can run its
|
|
8
|
-
* own post-delete routing (refetch, state update, pagination), `false` on
|
|
9
|
-
* failure. Both `MediaStorage` and `CreateCropDrawer` share this.
|
|
10
|
-
*/
|
|
5
|
+
/** Deletes one media file with its own toast; resolves to `true` on success. */
|
|
11
6
|
export function useDeleteMediaFile(application) {
|
|
12
7
|
const {
|
|
13
8
|
rpcGateway
|
|
@@ -39,4 +34,54 @@ export function useDeleteMediaFile(application) {
|
|
|
39
34
|
return false;
|
|
40
35
|
}
|
|
41
36
|
});
|
|
37
|
+
}
|
|
38
|
+
const DELETE_CONCURRENCY = 5;
|
|
39
|
+
/** Deletes media files in a bounded-concurrency batch; resolves to the number deleted. */
|
|
40
|
+
export function useDeleteMediaFiles(application) {
|
|
41
|
+
const {
|
|
42
|
+
rpcGateway
|
|
43
|
+
} = useSPAContext();
|
|
44
|
+
const {
|
|
45
|
+
openToast
|
|
46
|
+
} = useToast();
|
|
47
|
+
const lang = useLang();
|
|
48
|
+
return usePersistentFunction(async uuids => {
|
|
49
|
+
const queue = [...uuids];
|
|
50
|
+
let failed = 0;
|
|
51
|
+
const worker = async () => {
|
|
52
|
+
for (let uuid = queue.shift(); uuid !== undefined; uuid = queue.shift()) {
|
|
53
|
+
try {
|
|
54
|
+
await rpcGateway.mediaFiles.Delete({
|
|
55
|
+
application,
|
|
56
|
+
uuid
|
|
57
|
+
});
|
|
58
|
+
} catch {
|
|
59
|
+
failed += 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
await Promise.all(Array.from({
|
|
64
|
+
length: Math.min(DELETE_CONCURRENCY, queue.length)
|
|
65
|
+
}, () => worker()));
|
|
66
|
+
const deleted = uuids.length - failed;
|
|
67
|
+
if (deleted > 0) {
|
|
68
|
+
openToast({
|
|
69
|
+
title: lang({
|
|
70
|
+
message: 'SMART.MEDIA_STORAGE.BULK_DELETE_SUCCESS',
|
|
71
|
+
count: deleted
|
|
72
|
+
}),
|
|
73
|
+
type: 'success'
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (failed > 0) {
|
|
77
|
+
openToast({
|
|
78
|
+
title: lang({
|
|
79
|
+
message: 'SMART.MEDIA_STORAGE.BULK_DELETE_ERROR',
|
|
80
|
+
count: failed
|
|
81
|
+
}),
|
|
82
|
+
type: 'error'
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return deleted;
|
|
86
|
+
});
|
|
42
87
|
}
|
|
@@ -17,6 +17,15 @@ export const messages = {
|
|
|
17
17
|
'SMART.MEDIA_STORAGE.DELETE_HINT': 'Delete',
|
|
18
18
|
'SMART.MEDIA_STORAGE.DELETE_SUCCESS': 'Deleted',
|
|
19
19
|
'SMART.MEDIA_STORAGE.DELETE_ERROR': 'Failed to delete',
|
|
20
|
+
'SMART.MEDIA_STORAGE.SELECT_ALL': 'Select all on page',
|
|
21
|
+
'SMART.MEDIA_STORAGE.SELECT_FILE_HINT': 'Select file',
|
|
22
|
+
'SMART.MEDIA_STORAGE.SELECTED_COUNT': '{{count}} selected',
|
|
23
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_BUTTON': 'Delete selected',
|
|
24
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_SUCCESS': '{{count}} files deleted',
|
|
25
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_ERROR': 'Failed to delete {{count}} files',
|
|
26
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.TITLE': 'Delete {{count}} files?',
|
|
27
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.DESCRIPTION': 'Deleting an original also removes all of its crops. This can’t be undone.',
|
|
28
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.BUTTON': 'Delete',
|
|
20
29
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.TITLE': 'Delete this file?',
|
|
21
30
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.DESCRIPTION': 'Deleting the original also removes all of its crops. This can’t be undone.',
|
|
22
31
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.BUTTON': 'Delete',
|
|
@@ -17,6 +17,15 @@ export const messages = {
|
|
|
17
17
|
'SMART.MEDIA_STORAGE.DELETE_HINT': 'Удалить',
|
|
18
18
|
'SMART.MEDIA_STORAGE.DELETE_SUCCESS': 'Удалено',
|
|
19
19
|
'SMART.MEDIA_STORAGE.DELETE_ERROR': 'Не удалось удалить',
|
|
20
|
+
'SMART.MEDIA_STORAGE.SELECT_ALL': 'Выбрать все на странице',
|
|
21
|
+
'SMART.MEDIA_STORAGE.SELECT_FILE_HINT': 'Выбрать файл',
|
|
22
|
+
'SMART.MEDIA_STORAGE.SELECTED_COUNT': 'Выбрано: {{count}}',
|
|
23
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_BUTTON': 'Удалить выбранные',
|
|
24
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_SUCCESS': 'Удалено файлов: {{count}}',
|
|
25
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_ERROR': 'Не удалось удалить файлов: {{count}}',
|
|
26
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.TITLE': 'Удалить {{count}} файлов?',
|
|
27
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.DESCRIPTION': 'Удаление оригинала также удалит все его кропы. Действие необратимо.',
|
|
28
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.BUTTON': 'Удалить',
|
|
20
29
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.TITLE': 'Удалить файл?',
|
|
21
30
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.DESCRIPTION': 'Удаление оригинала также удалит все его кропы. Действие необратимо.',
|
|
22
31
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.BUTTON': 'Удалить',
|
|
@@ -23,6 +23,23 @@ export type MediaStorageMessages = {
|
|
|
23
23
|
'SMART.MEDIA_STORAGE.DELETE_HINT': NoParams;
|
|
24
24
|
'SMART.MEDIA_STORAGE.DELETE_SUCCESS': NoParams;
|
|
25
25
|
'SMART.MEDIA_STORAGE.DELETE_ERROR': NoParams;
|
|
26
|
+
'SMART.MEDIA_STORAGE.SELECT_ALL': NoParams;
|
|
27
|
+
'SMART.MEDIA_STORAGE.SELECT_FILE_HINT': NoParams;
|
|
28
|
+
'SMART.MEDIA_STORAGE.SELECTED_COUNT': {
|
|
29
|
+
count: number;
|
|
30
|
+
};
|
|
31
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_BUTTON': NoParams;
|
|
32
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_SUCCESS': {
|
|
33
|
+
count: number;
|
|
34
|
+
};
|
|
35
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_ERROR': {
|
|
36
|
+
count: number;
|
|
37
|
+
};
|
|
38
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.TITLE': {
|
|
39
|
+
count: number;
|
|
40
|
+
};
|
|
41
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.DESCRIPTION': NoParams;
|
|
42
|
+
'SMART.MEDIA_STORAGE.BULK_DELETE_CONFIRM.BUTTON': NoParams;
|
|
26
43
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.TITLE': NoParams;
|
|
27
44
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.DESCRIPTION': NoParams;
|
|
28
45
|
'SMART.MEDIA_STORAGE.DELETE_CONFIRM.BUTTON': NoParams;
|
package/MediaStorage/styled.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export declare const Grid: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
2
|
-
export declare const Tile: import("styled-components").StyledComponent<"div", any, {
|
|
2
|
+
export declare const Tile: import("styled-components").StyledComponent<"div", any, {
|
|
3
|
+
$selected?: boolean;
|
|
4
|
+
}, never>;
|
|
3
5
|
export declare const TileImage: import("styled-components").StyledComponent<"img", any, {}, never>;
|
|
4
6
|
export declare const CropBadge: import("styled-components").StyledComponent<"span", any, {}, never>;
|
|
5
7
|
export declare const WarningBadge: import("styled-components").StyledComponent<"span", any, {}, never>;
|
|
8
|
+
export declare const TileCheckbox: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
9
|
+
export declare const SelectionBar: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
10
|
+
export declare const SelectionCount: import("styled-components").StyledComponent<"span", any, {}, never>;
|
|
6
11
|
export declare const TileActions: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
7
12
|
export declare const EmptyState: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
8
13
|
export declare const Dropzone: import("styled-components").StyledComponent<"button", any, {
|
package/MediaStorage/styled.js
CHANGED
|
@@ -8,7 +8,11 @@ export const Grid = styled.div.withConfig({
|
|
|
8
8
|
export const Tile = styled.div.withConfig({
|
|
9
9
|
displayName: "Tile",
|
|
10
10
|
componentId: "sc-14317rj-1"
|
|
11
|
-
})(["position:relative;border-radius:6px;overflow:hidden;border:1px solid ", ";transition:border-color 0.15s;&:hover{border-color:", ";}"],
|
|
11
|
+
})(["position:relative;border-radius:6px;overflow:hidden;border:1px solid ", ";box-shadow:", ";transition:border-color 0.15s,box-shadow 0.15s;&:hover{border-color:", ";}"], ({
|
|
12
|
+
$selected
|
|
13
|
+
}) => $selected ? Color.PRIMARY : Color.DIVIDER, ({
|
|
14
|
+
$selected
|
|
15
|
+
}) => $selected ? `0 0 0 1px ${Color.PRIMARY}` : 'none', Color.PRIMARY);
|
|
12
16
|
export const TileImage = styled.img.withConfig({
|
|
13
17
|
displayName: "TileImage",
|
|
14
18
|
componentId: "sc-14317rj-2"
|
|
@@ -21,17 +25,29 @@ export const WarningBadge = styled.span.withConfig({
|
|
|
21
25
|
displayName: "WarningBadge",
|
|
22
26
|
componentId: "sc-14317rj-4"
|
|
23
27
|
})(["position:absolute;bottom:0;left:0;right:0;font-size:10px;line-height:1.2;text-align:center;color:", ";background:", ";padding:3px 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none;"], Color.CLEAR, Color.WARNING);
|
|
28
|
+
export const TileCheckbox = styled.div.withConfig({
|
|
29
|
+
displayName: "TileCheckbox",
|
|
30
|
+
componentId: "sc-14317rj-5"
|
|
31
|
+
})(["position:absolute;top:6px;left:6px;z-index:2;padding:2px;border-radius:4px;background:", ";"], Color.CLEAR);
|
|
32
|
+
export const SelectionBar = styled.div.withConfig({
|
|
33
|
+
displayName: "SelectionBar",
|
|
34
|
+
componentId: "sc-14317rj-6"
|
|
35
|
+
})(["display:flex;align-items:center;gap:12px;min-height:32px;margin-bottom:12px;"]);
|
|
36
|
+
export const SelectionCount = styled.span.withConfig({
|
|
37
|
+
displayName: "SelectionCount",
|
|
38
|
+
componentId: "sc-14317rj-7"
|
|
39
|
+
})(["font-size:", ";color:", ";"], FontSize.SMALL, Color.LOCKED);
|
|
24
40
|
export const TileActions = styled.div.withConfig({
|
|
25
41
|
displayName: "TileActions",
|
|
26
|
-
componentId: "sc-14317rj-
|
|
27
|
-
})(["position:absolute;
|
|
42
|
+
componentId: "sc-14317rj-8"
|
|
43
|
+
})(["position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:center;gap:6px;background:rgba(0,0,0,0.45);backdrop-filter:blur(2px);opacity:0;transition:opacity 0.15s;", ":hover &{opacity:1;}@media (hover:none){opacity:1;}"], Tile);
|
|
28
44
|
export const EmptyState = styled.div.withConfig({
|
|
29
45
|
displayName: "EmptyState",
|
|
30
|
-
componentId: "sc-14317rj-
|
|
46
|
+
componentId: "sc-14317rj-9"
|
|
31
47
|
})(["text-align:center;padding:48px 16px;color:", ";"], Color.LOCKED);
|
|
32
48
|
export const Dropzone = styled.button.withConfig({
|
|
33
49
|
displayName: "Dropzone",
|
|
34
|
-
componentId: "sc-14317rj-
|
|
50
|
+
componentId: "sc-14317rj-10"
|
|
35
51
|
})(["width:100%;min-height:96px;margin-bottom:16px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:16px;font:inherit;font-size:13px;color:", ";cursor:pointer;border:2px dashed ", ";border-radius:8px;background:", ";transition:border-color 0.15s,background 0.15s;&:hover{border-color:", ";}&:disabled{cursor:default;opacity:0.7;}"], Color.LOCKED, ({
|
|
36
52
|
$dragOver
|
|
37
53
|
}) => $dragOver ? Color.PRIMARY : Color.DIVIDER, ({
|
|
@@ -39,46 +55,46 @@ export const Dropzone = styled.button.withConfig({
|
|
|
39
55
|
}) => $dragOver ? Color.SOFT_LIGHT : Color.CLEAR, Color.PRIMARY);
|
|
40
56
|
export const HiddenInput = styled.input.withConfig({
|
|
41
57
|
displayName: "HiddenInput",
|
|
42
|
-
componentId: "sc-14317rj-
|
|
58
|
+
componentId: "sc-14317rj-11"
|
|
43
59
|
})(["display:none;"]);
|
|
44
60
|
export const UsageLine = styled.div.withConfig({
|
|
45
61
|
displayName: "UsageLine",
|
|
46
|
-
componentId: "sc-14317rj-
|
|
62
|
+
componentId: "sc-14317rj-12"
|
|
47
63
|
})(["margin-left:auto;font-size:", ";color:", ";"], FontSize.SMALL, Color.LOCKED);
|
|
48
64
|
/* ---------- CreateCropDrawer ---------- */
|
|
49
65
|
export const PreviewStage = styled.div.withConfig({
|
|
50
66
|
displayName: "PreviewStage",
|
|
51
|
-
componentId: "sc-14317rj-
|
|
67
|
+
componentId: "sc-14317rj-13"
|
|
52
68
|
})(["display:flex;align-items:center;justify-content:center;min-height:200px;max-height:360px;padding:12px;border:1px solid ", ";border-radius:6px;overflow:hidden;background:", ";"], Color.DIVIDER, Color.SOFT_LIGHT);
|
|
53
69
|
export const PreviewFrame = styled.div.withConfig({
|
|
54
70
|
displayName: "PreviewFrame",
|
|
55
|
-
componentId: "sc-14317rj-
|
|
71
|
+
componentId: "sc-14317rj-14"
|
|
56
72
|
})(["aspect-ratio:", ";max-width:100%;max-height:336px;overflow:hidden;border-radius:4px;"], ({
|
|
57
73
|
$ratio
|
|
58
74
|
}) => $ratio);
|
|
59
75
|
export const PreviewImage = styled.img.withConfig({
|
|
60
76
|
displayName: "PreviewImage",
|
|
61
|
-
componentId: "sc-14317rj-
|
|
77
|
+
componentId: "sc-14317rj-15"
|
|
62
78
|
})(["width:100%;height:100%;object-fit:cover;display:block;"]);
|
|
63
79
|
export const FieldLabel = styled.div.withConfig({
|
|
64
80
|
displayName: "FieldLabel",
|
|
65
|
-
componentId: "sc-14317rj-
|
|
81
|
+
componentId: "sc-14317rj-16"
|
|
66
82
|
})(["font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.4px;color:", ";margin-bottom:6px;"], Color.LOCKED);
|
|
67
83
|
export const SizeInput = styled(NativeInput).withConfig({
|
|
68
84
|
displayName: "SizeInput",
|
|
69
|
-
componentId: "sc-14317rj-
|
|
85
|
+
componentId: "sc-14317rj-17"
|
|
70
86
|
})(["&[readonly]{background:", ";color:", ";}"], Color.SOFT_LIGHT, Color.LOCKED);
|
|
71
87
|
export const Chips = styled.div.withConfig({
|
|
72
88
|
displayName: "Chips",
|
|
73
|
-
componentId: "sc-14317rj-
|
|
89
|
+
componentId: "sc-14317rj-18"
|
|
74
90
|
})(["display:flex;flex-wrap:wrap;gap:7px;"]);
|
|
75
91
|
export const Segment = styled.div.withConfig({
|
|
76
92
|
displayName: "Segment",
|
|
77
|
-
componentId: "sc-14317rj-
|
|
93
|
+
componentId: "sc-14317rj-19"
|
|
78
94
|
})(["display:inline-flex;border:1px solid ", ";border-radius:6px;overflow:hidden;"], Color.DIVIDER);
|
|
79
95
|
export const SegmentItem = styled.button.withConfig({
|
|
80
96
|
displayName: "SegmentItem",
|
|
81
|
-
componentId: "sc-14317rj-
|
|
97
|
+
componentId: "sc-14317rj-20"
|
|
82
98
|
})(["font:inherit;font-size:13px;cursor:pointer;padding:7px 14px;border:none;background:", ";color:", ";& + &{border-left:1px solid ", ";}"], ({
|
|
83
99
|
$active
|
|
84
100
|
}) => $active ? Color.PRIMARY : Color.CLEAR, ({
|
|
@@ -86,17 +102,17 @@ export const SegmentItem = styled.button.withConfig({
|
|
|
86
102
|
}) => $active ? Color.CLEAR : Color.MAIN, Color.DIVIDER);
|
|
87
103
|
export const CropStrip = styled.div.withConfig({
|
|
88
104
|
displayName: "CropStrip",
|
|
89
|
-
componentId: "sc-14317rj-
|
|
105
|
+
componentId: "sc-14317rj-21"
|
|
90
106
|
})(["display:flex;gap:10px;flex-wrap:wrap;align-items:flex-start;"]);
|
|
91
107
|
export const CropThumb = styled.div.withConfig({
|
|
92
108
|
displayName: "CropThumb",
|
|
93
|
-
componentId: "sc-14317rj-
|
|
109
|
+
componentId: "sc-14317rj-22"
|
|
94
110
|
})(["position:relative;width:88px;border:1px solid ", ";border-radius:6px;overflow:hidden;background:", ";"], Color.DIVIDER, Color.SOFT_LIGHT);
|
|
95
111
|
export const CropThumbDelete = styled.div.withConfig({
|
|
96
112
|
displayName: "CropThumbDelete",
|
|
97
|
-
componentId: "sc-14317rj-
|
|
113
|
+
componentId: "sc-14317rj-23"
|
|
98
114
|
})(["position:absolute;top:4px;right:4px;opacity:0;transition:opacity 0.15s;", ":hover &{opacity:1;}@media (hover:none){opacity:1;}"], CropThumb);
|
|
99
115
|
export const CropThumbCaption = styled.div.withConfig({
|
|
100
116
|
displayName: "CropThumbCaption",
|
|
101
|
-
componentId: "sc-14317rj-
|
|
117
|
+
componentId: "sc-14317rj-24"
|
|
102
118
|
})(["font-size:10px;text-align:center;padding:3px 2px;color:", ";"], Color.LOCKED);
|
package/package.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@floating-ui/react-dom": "^2.1.2",
|
|
27
|
-
"@pushwoosh/dumb-components": "^1.1.
|
|
27
|
+
"@pushwoosh/dumb-components": "^1.1.202",
|
|
28
28
|
"@pushwoosh/kit-constants": "^1.11.1",
|
|
29
29
|
"@pushwoosh/kit-helpers": "^4.12.0",
|
|
30
30
|
"@pushwoosh/kit-icons": "^2.1.22",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"react": "^16.14.0 || ^18.0.0",
|
|
53
53
|
"react-dom": "^16.14.0 || ^18.0.0"
|
|
54
54
|
},
|
|
55
|
-
"version": "1.3.
|
|
55
|
+
"version": "1.3.16"
|
|
56
56
|
}
|