| 1 |
import React from 'react' |
| 2 |
import { __, sprintf } from '@wordpress/i18n' |
| 3 |
import type { UploadedFile } from './UploadButton' |
| 4 |
|
| 5 |
const FILE_SIZE_FRACTION_DIGITS = 2 |
| 6 |
|
| 7 |
const LOG_BYTES = 0 |
| 8 |
const LOG_KB = 1 |
| 9 |
const LOG_MB = 2 |
| 10 |
const LOG_GB = 3 |
| 11 |
|
| 12 |
const formatFileSize = (bytes: number): string => { |
| 13 |
if (0 === bytes) { |
| 14 |
// translators: %f: file size in bytes. |
| 15 |
return sprintf(__('%f Bytes', 'code-snippets'), 0) |
| 16 |
} |
| 17 |
|
| 18 |
const k = 1024 |
| 19 |
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), LOG_GB) |
| 20 |
|
| 21 |
const n = parseFloat((bytes / Math.pow(k, i)).toFixed(FILE_SIZE_FRACTION_DIGITS)) |
| 22 |
|
| 23 |
switch (i) { |
| 24 |
case LOG_BYTES: |
| 25 |
// translators: %f: file size in bytes. |
| 26 |
return sprintf(__('%f Bytes', 'code-snippets'), n) |
| 27 |
|
| 28 |
case LOG_KB: |
| 29 |
// translators: %f: file size in kilobytes. |
| 30 |
return sprintf(__('%f KB', 'code-snippets'), n) |
| 31 |
|
| 32 |
case LOG_MB: |
| 33 |
// translators: %f: file size in megabytes. |
| 34 |
return sprintf(__('%f MB', 'code-snippets'), n) |
| 35 |
|
| 36 |
default: |
| 37 |
case LOG_GB: |
| 38 |
// translators: %f: file size in gigabytes. |
| 39 |
return sprintf(__('%f GB', 'code-snippets'), n) |
| 40 |
} |
| 41 |
} |
| 42 |
|
| 43 |
export interface SelectedFilesListProps { |
| 44 |
files: UploadedFile[] |
| 45 |
onRemoveFile: (file: UploadedFile) => void |
| 46 |
} |
| 47 |
|
| 48 |
export const SelectedFilesList: React.FC<SelectedFilesListProps> = ({ files, onRemoveFile }) => |
| 49 |
<div className="selected-files"> |
| 50 |
<h3> |
| 51 |
{// translators: %d: number of selected files. |
| 52 |
sprintf(__('Selected files: (%d)', 'code-snippets'), files.length)} |
| 53 |
</h3> |
| 54 |
|
| 55 |
<div className="selected-files-list"> |
| 56 |
{files.map(file => |
| 57 |
<div key={file.id}> |
| 58 |
<div className="selected-file-details"> |
| 59 |
<span className="file-icon" aria-hidden="true">📄</span> |
| 60 |
<div> |
| 61 |
<div><strong>{file.name}</strong></div> |
| 62 |
<div className="file-size">{formatFileSize(file.file.size)}</div> |
| 63 |
</div> |
| 64 |
</div> |
| 65 |
|
| 66 |
<button |
| 67 |
type="button" |
| 68 |
aria-label={ |
| 69 |
sprintf( |
| 70 |
// translators: %s: file name. |
| 71 |
__('Remove file %s', 'code-snippets'), |
| 72 |
file.name |
| 73 |
) |
| 74 |
} |
| 75 |
onClick={event => { |
| 76 |
event.stopPropagation() |
| 77 |
onRemoveFile(file) |
| 78 |
}} |
| 79 |
> |
| 80 |
<span aria-hidden="true">✕</span> |
| 81 |
</button> |
| 82 |
</div> |
| 83 |
)} |
| 84 |
</div> |
| 85 |
</div> |
| 86 |
|