diff --git a/packages/payload/src/admin/types.ts b/packages/payload/src/admin/types.ts index 4be43d28bb9..05c27971c20 100644 --- a/packages/payload/src/admin/types.ts +++ b/packages/payload/src/admin/types.ts @@ -585,6 +585,7 @@ export type DocumentSlots = { UnpublishButton?: React.ReactNode Upload?: React.ReactNode UploadControls?: React.ReactNode + UploadFilePreview?: React.ReactNode } export type { diff --git a/packages/payload/src/bin/generateImportMap/iterateCollections.ts b/packages/payload/src/bin/generateImportMap/iterateCollections.ts index b9722cd373e..53c40531618 100644 --- a/packages/payload/src/bin/generateImportMap/iterateCollections.ts +++ b/packages/payload/src/bin/generateImportMap/iterateCollections.ts @@ -1,6 +1,6 @@ import type { AdminViewConfig } from '../../admin/views/index.js' import type { SanitizedCollectionConfig } from '../../collections/config/types.js' -import type { SanitizedConfig } from '../../config/types.js' +import type { PayloadComponent, SanitizedConfig } from '../../config/types.js' import type { AddToImportMap, Imports, InternalImportMap } from './index.js' import { genImportMapIterateFields } from './iterateFields.js' @@ -52,6 +52,20 @@ export function iterateCollections({ addToImportMap(collection.upload?.admin?.components?.controls) } + const filePreview = collection.upload?.admin?.components?.filePreview + if (filePreview) { + if ( + typeof filePreview === 'string' || + (typeof filePreview === 'object' && 'path' in filePreview) + ) { + addToImportMap(filePreview as PayloadComponent) + } else { + for (const component of Object.values(filePreview as Record)) { + addToImportMap(component) + } + } + } + if (collection.admin?.components?.views?.edit) { for (const editViewConfig of Object.values(collection.admin?.components?.views?.edit)) { if ('Component' in editViewConfig) { diff --git a/packages/payload/src/collections/config/client.ts b/packages/payload/src/collections/config/client.ts index 260b780fa3f..a7a5698ac89 100644 --- a/packages/payload/src/collections/config/client.ts +++ b/packages/payload/src/collections/config/client.ts @@ -36,6 +36,7 @@ export type ServerOnlyCollectionAdminProperties = keyof Pick< export type ServerOnlyUploadProperties = keyof Pick< SanitizedCollectionConfig['upload'], + | 'admin' | 'adminThumbnail' | 'externalFileHeaderFilter' | 'handlers' @@ -90,6 +91,7 @@ const serverOnlyCollectionProperties: Partial[] ] const serverOnlyUploadProperties: Partial[] = [ + 'admin', 'adminThumbnail', 'externalFileHeaderFilter', 'handlers', diff --git a/packages/payload/src/exports/shared.ts b/packages/payload/src/exports/shared.ts index b91365249ac..4380ddcdd7a 100644 --- a/packages/payload/src/exports/shared.ts +++ b/packages/payload/src/exports/shared.ts @@ -66,6 +66,7 @@ export { validOperators, validOperatorSet } from '../types/constants.js' export { formatFilesize } from '../uploads/formatFilesize.js' export { isImage } from '../uploads/isImage.js' +export { matchMimeType } from '../uploads/matchMimeType.js' export { appendDateTimezoneSelectFields } from '../utilities/appendDateTimezoneSelectFields.js' export { appendUploadSelectFields } from '../utilities/appendUploadSelectFields.js' export { applyLocaleFiltering } from '../utilities/applyLocaleFiltering.js' diff --git a/packages/payload/src/uploads/matchMimeType.ts b/packages/payload/src/uploads/matchMimeType.ts new file mode 100644 index 00000000000..77e69ab9505 --- /dev/null +++ b/packages/payload/src/uploads/matchMimeType.ts @@ -0,0 +1,20 @@ +import type { PayloadComponent } from '../config/types.js' + +/** + * Resolves a PayloadComponent from a MIME-type keyed map. + * + * Priority: exact match → category wildcard (e.g. `video/*`) → universal fallback (`*`). + */ +export function matchMimeType( + map: Record, + mimeType: string, +): PayloadComponent | undefined { + if (map[mimeType]) { + return map[mimeType] + } + const category = mimeType.split('/')[0] + if (map[`${category}/*`]) { + return map[`${category}/*`] + } + return map['*'] +} diff --git a/packages/payload/src/uploads/types.ts b/packages/payload/src/uploads/types.ts index 3fe5e79bc33..fd6806cde0a 100644 --- a/packages/payload/src/uploads/types.ts +++ b/packages/payload/src/uploads/types.ts @@ -116,12 +116,35 @@ export type FileAllowList = Array<{ mimeType: string }> +export type UploadFilePreviewClientProps = { + filename: string + filesize: number + /** Resolved URL of the file (data.url). */ + fileSrc: string + height?: number + mimeType: string + width?: number +} + +type UploadFilePreviewMap = { + [mimeTypePattern: string]: PayloadComponent +} + type Admin = { components?: { /** * The Controls component to extend the upload controls in the admin panel. */ controls?: PayloadComponent[] + /** + * A custom component to render in place of the default Thumbnail in the upload side panel. + * + * Can be a single PayloadComponent (renders for all MIME types) or a Record keyed by + * MIME type patterns. Pattern resolution priority: exact match → category wildcard + * (e.g. `video/*`) → universal fallback (`*`). Falls back to the default Thumbnail + * when nothing matches. + */ + filePreview?: PayloadComponent | UploadFilePreviewMap } } diff --git a/packages/translations/src/clientKeys.ts b/packages/translations/src/clientKeys.ts index c4f90e84857..d3a217efe3f 100644 --- a/packages/translations/src/clientKeys.ts +++ b/packages/translations/src/clientKeys.ts @@ -336,6 +336,7 @@ export const clientTranslationKeys = createClientTranslationKeys([ 'general:only', 'general:or', 'general:order', + 'general:original', 'general:overwriteExistingData', 'general:pageNotFound', 'general:password', @@ -468,7 +469,11 @@ export const clientTranslationKeys = createClientTranslationKeys([ 'upload:focalPoint', 'upload:focalPointDescription', 'upload:height', + 'upload:fromURL', + 'upload:linkToFile', 'upload:pasteURL', + 'upload:renameFile', + 'upload:replaceFile', 'upload:previewSizes', 'upload:selectCollectionToBrowse', 'upload:selectFile', diff --git a/packages/translations/src/languages/ar.ts b/packages/translations/src/languages/ar.ts index 5a9eab0c068..e12df359d2f 100644 --- a/packages/translations/src/languages/ar.ts +++ b/packages/translations/src/languages/ar.ts @@ -400,6 +400,7 @@ export const arTranslations: DefaultTranslationsObject = { openInNewWindow: 'فتح في نافذة جديدة', or: 'أو', order: 'التّرتيب', + original: 'أصلي', overwriteExistingData: 'استبدل بيانات الحقل الموجودة', pageNotFound: 'الصّفحة غير موجودة', password: 'كلمة المرور', @@ -549,12 +550,16 @@ export const arTranslations: DefaultTranslationsObject = { fileToUpload: 'ملف للتحميل', focalPoint: 'نقطة التركيز', focalPointDescription: 'اسحب النقطة المركزية مباشرة على المعاينة أو قم بضبط القيم أدناه.', + fromURL: 'تحميل ملف من عنوان URL', height: 'الطّول', lessInfo: 'معلومات أقلّ', + linkToFile: 'رابط إلى الملف', moreInfo: 'معلومات أكثر', noFile: 'لا يوجد ملف', pasteURL: 'لصق الرابط', previewSizes: 'أحجام المعاينة', + renameFile: 'إعادة تسمية الملف', + replaceFile: 'استبدل الملف', selectCollectionToBrowse: 'حدّد مجموعة لاستعراضها', selectFile: 'اختر ملفّ', setCropArea: 'حدد منطقة القص', diff --git a/packages/translations/src/languages/az.ts b/packages/translations/src/languages/az.ts index 3216402103a..9619d6a168c 100644 --- a/packages/translations/src/languages/az.ts +++ b/packages/translations/src/languages/az.ts @@ -413,6 +413,7 @@ export const azTranslations: DefaultTranslationsObject = { openInNewWindow: 'Yeni pəncərədə aç', or: 'Və ya', order: 'Sıra', + original: 'Orijinal', overwriteExistingData: 'Mövcud sahə məlumatlarını yenidən yazın', pageNotFound: 'Səhifə tapılmadı', password: 'Şifrə', @@ -565,12 +566,16 @@ export const azTranslations: DefaultTranslationsObject = { focalPoint: 'Mərkəzi Nöqtə', focalPointDescription: 'Fokus nöqtəsini birbaşa önizləməyə sürükləyin və ya aşağıdakı dəyərləri düzəltin.', + fromURL: 'URL-dən fayl yüklə', height: 'Hündürlük', lessInfo: 'Daha az məlumat', + linkToFile: 'Fayla keçid', moreInfo: 'Daha çox məlumat', noFile: 'Heç bir fayl', pasteURL: 'URL yapışdır', previewSizes: 'Öncədən baxış ölçüləri', + renameFile: 'Fayl adını dəyişdirin', + replaceFile: 'Faylı əvəz et', selectCollectionToBrowse: 'Gözdən keçirmək üçün bir Kolleksiya seçin', selectFile: 'Fayl seçin', setCropArea: 'Məhsul sahəsini təyin et', diff --git a/packages/translations/src/languages/bg.ts b/packages/translations/src/languages/bg.ts index 149443a87ff..913dece6d33 100644 --- a/packages/translations/src/languages/bg.ts +++ b/packages/translations/src/languages/bg.ts @@ -409,6 +409,7 @@ export const bgTranslations: DefaultTranslationsObject = { openInNewWindow: 'Отвори в нов прозорец', or: 'Или', order: 'Ред', + original: 'Оригинал', overwriteExistingData: 'Презапишете съществуващите данни в полето', pageNotFound: 'Страницата не беше открита', password: 'Парола', @@ -559,12 +560,16 @@ export const bgTranslations: DefaultTranslationsObject = { focalPoint: 'Фокусна точка', focalPointDescription: 'Премести фокусната точка директно върху визуализацията или регулирай стойностите по-долу.', + fromURL: 'Качване на файл от URL адрес', height: 'Височина', lessInfo: 'По-малко информация', + linkToFile: 'Връзка към файл', moreInfo: 'Повече информация', noFile: 'Няма файл', pasteURL: 'Поставяне на URL', previewSizes: 'Преглед на размери', + renameFile: 'Преименувайте файл', + replaceFile: 'Заменете файл', selectCollectionToBrowse: 'Избери колекция, която да разгледаш', selectFile: 'Избери файл', setCropArea: 'Задай област за изрязване', diff --git a/packages/translations/src/languages/bnBd.ts b/packages/translations/src/languages/bnBd.ts index 10098d99807..db5f660e3cb 100644 --- a/packages/translations/src/languages/bnBd.ts +++ b/packages/translations/src/languages/bnBd.ts @@ -415,6 +415,7 @@ export const bnBdTranslations: DefaultTranslationsObject = { openInNewWindow: 'নতুন উইন্ডোতে খুলুন', or: 'বা', order: 'অর্ডার', + original: 'মূল', overwriteExistingData: 'বিদ্যমান ফিল্ড ডেটা ওভাররাইট করুন', pageNotFound: 'পৃষ্ঠা পাওয়া যায়নি', password: 'পাসওয়ার্ড', @@ -567,12 +568,16 @@ export const bnBdTranslations: DefaultTranslationsObject = { fileToUpload: 'আপলোড করার ফাইল', focalPoint: 'ফোকাল পয়েন্ট', focalPointDescription: 'প্রিভিউতে সরাসরি ফোকাল পয়েন্ট টানুন বা নিচের মানগুলি সামঞ্জস্য করুন।', + fromURL: 'URL থেকে ফাইল আপলোড করুন', height: 'উচ্চতা', lessInfo: 'কম তথ্য', + linkToFile: 'ফাইলের লিঙ্ক', moreInfo: 'আরও তথ্য', noFile: 'কোনো ফাইল নেই', pasteURL: 'URL পেস্ট করুন', previewSizes: 'প্রিভিউ আকারগুলি', + renameFile: 'ফাইলের নাম পরিবর্তন করুন', + replaceFile: 'ফাইল পরিবর্তন করুন', selectCollectionToBrowse: 'ব্রাউজ করার জন্য একটি সংগ্রহ নির্বাচন করুন', selectFile: 'একটি ফাইল নির্বাচন করুন', setCropArea: 'ক্রপ অঞ্চল সেট করুন', diff --git a/packages/translations/src/languages/bnIn.ts b/packages/translations/src/languages/bnIn.ts index 3c059775f69..ffa268eaed1 100644 --- a/packages/translations/src/languages/bnIn.ts +++ b/packages/translations/src/languages/bnIn.ts @@ -414,6 +414,7 @@ export const bnInTranslations: DefaultTranslationsObject = { openInNewWindow: 'নতুন উইন্ডোতে খুলুন', or: 'বা', order: 'অর্ডার', + original: 'মূল', overwriteExistingData: 'বিদ্যমান ফিল্ড ডেটা ওভাররাইট করুন', pageNotFound: 'পৃষ্ঠা পাওয়া যায়নি', password: 'পাসওয়ার্ড', @@ -566,12 +567,16 @@ export const bnInTranslations: DefaultTranslationsObject = { fileToUpload: 'আপলোড করার ফাইল', focalPoint: 'ফোকাল পয়েন্ট', focalPointDescription: 'প্রিভিউতে সরাসরি ফোকাল পয়েন্ট টানুন বা নিচের মানগুলি সামঞ্জস্য করুন।', + fromURL: 'URL থেকে ফাইল আপলোড করুন', height: 'উচ্চতা', lessInfo: 'কম তথ্য', + linkToFile: 'ফাইলের লিঙ্ক', moreInfo: 'আরও তথ্য', noFile: 'কোনো ফাইল নেই', pasteURL: 'URL পেস্ট করুন', previewSizes: 'প্রিভিউ আকারগুলি', + renameFile: 'ফাইলের নাম পরিবর্তন করুন', + replaceFile: 'ফাইল প্রতিস্থাপন করুন', selectCollectionToBrowse: 'ব্রাউজ করার জন্য একটি সংগ্রহ নির্বাচন করুন', selectFile: 'একটি ফাইল নির্বাচন করুন', setCropArea: 'ক্রপ অঞ্চল সেট করুন', diff --git a/packages/translations/src/languages/ca.ts b/packages/translations/src/languages/ca.ts index c9eb0f04cdc..e3aa1c1262b 100644 --- a/packages/translations/src/languages/ca.ts +++ b/packages/translations/src/languages/ca.ts @@ -412,6 +412,7 @@ export const caTranslations: DefaultTranslationsObject = { openInNewWindow: 'Obre en una finestra nova', or: 'O', order: 'Ordre', + original: 'Document original', overwriteExistingData: 'Sobreescriu les dades existents', pageNotFound: 'Pàgina no trobada', password: 'Contrasenya', @@ -563,12 +564,16 @@ export const caTranslations: DefaultTranslationsObject = { focalPoint: 'Punt focal', focalPointDescription: 'Arrossega el punt focal directament sobre la vista prèvia o ajusta els valors a continuació.', + fromURL: 'Pujar fitxer des d’una URL', height: 'Alçada', lessInfo: 'Menys informació', + linkToFile: "Enllaç a l'arxiu", moreInfo: 'Més informació', noFile: 'No hi ha cap fitxer', pasteURL: "Enganxa l'URL", previewSizes: 'Mides de la vista prèvia', + renameFile: 'Canviar el nom del fitxer', + replaceFile: 'Reemplaça fitxer', selectCollectionToBrowse: 'Selecciona una col·lecció per explorar', selectFile: 'Selecciona un fitxer', setCropArea: "Estableix l'àrea de retall", diff --git a/packages/translations/src/languages/cs.ts b/packages/translations/src/languages/cs.ts index 61133929eee..636ff28c41a 100644 --- a/packages/translations/src/languages/cs.ts +++ b/packages/translations/src/languages/cs.ts @@ -408,6 +408,7 @@ export const csTranslations: DefaultTranslationsObject = { openInNewWindow: 'Otevřít v novém okně', or: 'Nebo', order: 'Pořadí', + original: 'Originál', overwriteExistingData: 'Přepsat existující data pole', pageNotFound: 'Stránka nenalezena', password: 'Heslo', @@ -558,12 +559,16 @@ export const csTranslations: DefaultTranslationsObject = { focalPoint: 'Středobod', focalPointDescription: 'Přetáhněte bod zaměření přímo na náhled nebo upravte níže uvedené hodnoty.', + fromURL: 'Nahrát soubor z URL', height: 'Výška', lessInfo: 'Méně informací', + linkToFile: 'Odkaz na soubor', moreInfo: 'Více informací', noFile: 'Žádný soubor', pasteURL: 'Vložit URL', previewSizes: 'Náhled velikostí', + renameFile: 'Přejmenovat soubor', + replaceFile: 'Nahradit soubor', selectCollectionToBrowse: 'Vyberte kolekci pro procházení', selectFile: 'Vyberte soubor', setCropArea: 'Nastavit oblast ořezu', diff --git a/packages/translations/src/languages/da.ts b/packages/translations/src/languages/da.ts index 6c0c6b15735..000567b19f8 100644 --- a/packages/translations/src/languages/da.ts +++ b/packages/translations/src/languages/da.ts @@ -409,6 +409,7 @@ export const daTranslations: DefaultTranslationsObject = { openInNewWindow: 'Åbn i nyt vindue', or: 'Eller', order: 'Rækkefølge', + original: 'Original', overwriteExistingData: 'Overskriv eksisterende feltdata', pageNotFound: 'Siden blev ikke fundet', password: 'Adgangskode', @@ -560,12 +561,16 @@ export const daTranslations: DefaultTranslationsObject = { focalPoint: 'Fokuspunkt', focalPointDescription: 'Træk fokuspunktet direkte på forhåndsvisningen eller juster værdierne nedenfor.', + fromURL: 'Upload fil fra URL', height: 'Højde', lessInfo: 'Mindre info', + linkToFile: 'Link til fil', moreInfo: 'Mere info', noFile: 'Ingen fil', pasteURL: 'Indsæt URL', previewSizes: 'Forhåndsvisningsstørrelser', + renameFile: 'Omdøb fil', + replaceFile: 'Erstat fil', selectCollectionToBrowse: 'Vælg en samling for at browse', selectFile: 'Vælg en fil', setCropArea: 'Indstil beskæringsområde', diff --git a/packages/translations/src/languages/de.ts b/packages/translations/src/languages/de.ts index dde33d645cc..e03b0392855 100644 --- a/packages/translations/src/languages/de.ts +++ b/packages/translations/src/languages/de.ts @@ -419,6 +419,7 @@ export const deTranslations: DefaultTranslationsObject = { openInNewWindow: 'In neuem Fenster öffnen', or: 'oder', order: 'Reihenfolge', + original: 'Original', overwriteExistingData: 'Vorhandene Eingaben überschreiben', pageNotFound: 'Seite nicht gefunden', password: 'Passwort', @@ -571,12 +572,16 @@ export const deTranslations: DefaultTranslationsObject = { focalPoint: 'Fokuspunkt', focalPointDescription: 'Setze den Fokuspunkt direkt auf der Vorschau oder passe die Werte unten an.', + fromURL: 'Datei von URL hochladen', height: 'Höhe', lessInfo: 'Weniger Info', + linkToFile: 'Link zur Datei', moreInfo: 'Mehr Info', noFile: 'Keine Datei', pasteURL: 'URL einfügen', previewSizes: 'Bildgrößen anzeigen', + renameFile: 'Datei umbenennen', + replaceFile: 'Datei ersetzen', selectCollectionToBrowse: 'Eine Sammlung zum Durchsuchen auswählen', selectFile: 'Datei auswählen', setCropArea: 'Zuschneide-Bereich festlegen', diff --git a/packages/translations/src/languages/en.ts b/packages/translations/src/languages/en.ts index 900a3872c02..0a6be5c6692 100644 --- a/packages/translations/src/languages/en.ts +++ b/packages/translations/src/languages/en.ts @@ -410,6 +410,7 @@ export const enTranslations = { openInNewWindow: 'Open in new window', or: 'Or', order: 'Order', + original: 'Original', overwriteExistingData: 'Overwrite existing field data', pageNotFound: 'Page not found', password: 'Password', @@ -560,12 +561,16 @@ export const enTranslations = { focalPoint: 'Focal Point', focalPointDescription: 'Drag the focal point directly on the preview or adjust the values below.', + fromURL: 'Upload file from URL', height: 'Height', lessInfo: 'Less info', + linkToFile: 'Link to file', moreInfo: 'More info', noFile: 'No file', pasteURL: 'Paste URL', previewSizes: 'Preview Sizes', + renameFile: 'Rename file', + replaceFile: 'Replace file', selectCollectionToBrowse: 'Select a Collection to Browse', selectFile: 'Select a file', setCropArea: 'Set crop area', diff --git a/packages/translations/src/languages/es.ts b/packages/translations/src/languages/es.ts index c069a41ff6a..4b8e1f17c00 100644 --- a/packages/translations/src/languages/es.ts +++ b/packages/translations/src/languages/es.ts @@ -415,6 +415,7 @@ export const esTranslations: DefaultTranslationsObject = { openInNewWindow: 'Abrir en nueva ventana', or: 'O', order: 'Orden', + original: 'Original', overwriteExistingData: 'Sobrescribir los datos existentes del campo', pageNotFound: 'Página no encontrada', password: 'Contraseña', @@ -566,12 +567,16 @@ export const esTranslations: DefaultTranslationsObject = { focalPoint: 'Punto Focal', focalPointDescription: 'Arrastra el punto focal directamente en la vista previa o ajusta los valores a continuación.', + fromURL: 'Subir archivo desde URL', height: 'Alto', lessInfo: 'Menos info', + linkToFile: 'Enlace al archivo', moreInfo: 'Más info', noFile: 'Ningún archivo', pasteURL: 'Pegar URL', previewSizes: 'Tamaños de Vista Previa', + renameFile: 'Renombrar archivo', + replaceFile: 'Reemplazar archivo', selectCollectionToBrowse: 'Selecciona una Colección para navegar', selectFile: 'Selecciona un archivo', setCropArea: 'Establecer área de recorte', diff --git a/packages/translations/src/languages/et.ts b/packages/translations/src/languages/et.ts index b298534623f..7c072fd62b1 100644 --- a/packages/translations/src/languages/et.ts +++ b/packages/translations/src/languages/et.ts @@ -407,6 +407,7 @@ export const etTranslations: DefaultTranslationsObject = { openInNewWindow: 'Ava uues aknas', or: 'Või', order: 'Järjestus', + original: 'Algne', overwriteExistingData: 'Kirjuta olemasolevad välja andmed üle', pageNotFound: 'Lehte ei leitud', password: 'Parool', @@ -555,12 +556,16 @@ export const etTranslations: DefaultTranslationsObject = { fileToUpload: 'Üleslaetav fail', focalPoint: 'Fookuspunkt', focalPointDescription: 'Lohista fookuspunkti otse eelvaatel või kohanda väärtusi allpool.', + fromURL: 'Laadi fail üles URL-i kaudu', height: 'Kõrgus', lessInfo: 'Vähem infot', + linkToFile: 'Lingid failile', moreInfo: 'Rohkem infot', noFile: 'Pole faili', pasteURL: 'Kleebi URL', previewSizes: 'Eelvaate suurused', + renameFile: 'Faili ümbernimetamine', + replaceFile: 'Asendage fail', selectCollectionToBrowse: 'Vali kollektsioon sirvimiseks', selectFile: 'Vali fail', setCropArea: 'Määra kärpeala', diff --git a/packages/translations/src/languages/fa.ts b/packages/translations/src/languages/fa.ts index c66bb0f80c3..a5669a24f57 100644 --- a/packages/translations/src/languages/fa.ts +++ b/packages/translations/src/languages/fa.ts @@ -403,6 +403,7 @@ export const faTranslations: DefaultTranslationsObject = { openInNewWindow: 'باز کردن در پنجره جدید', or: 'یا', order: 'ترتیب', + original: 'اصلی', overwriteExistingData: 'بازنویسی اطلاعات موجود در فیلدها', pageNotFound: 'صفحه پیدا نشد', password: 'رمز عبور', @@ -552,12 +553,16 @@ export const faTranslations: DefaultTranslationsObject = { fileToUpload: 'فایل برای آپلود', focalPoint: 'نقطه کانونی', focalPointDescription: 'نقطه کانونی را مستقیماً روی تصویر بکشید یا مقادیر زیر را تنظیم کنید.', + fromURL: 'بارگذاری فایل از طریق نشانی اینترنتی', height: 'ارتفاع', lessInfo: 'اطلاعات کمتر', + linkToFile: 'پیوند به فایل', moreInfo: 'اطلاعات بیشتر', noFile: 'فایلی وجود ندارد', pasteURL: 'جای‌گذاری URL', previewSizes: 'اندازه‌های پیش‌نمایش', + renameFile: 'تغییر نام فایل', + replaceFile: 'جایگزینی فایل', selectCollectionToBrowse: 'یک مجموعه را برای مرور انتخاب کنید', selectFile: 'انتخاب فایل', setCropArea: 'تنظیم ناحیه برش', diff --git a/packages/translations/src/languages/fr.ts b/packages/translations/src/languages/fr.ts index a61af034970..75bdb02ce72 100644 --- a/packages/translations/src/languages/fr.ts +++ b/packages/translations/src/languages/fr.ts @@ -420,6 +420,7 @@ export const frTranslations: DefaultTranslationsObject = { openInNewWindow: 'Ouvrir dans une nouvelle fenêtre', or: 'ou', order: 'Ordre', + original: 'Original', overwriteExistingData: 'Écraser les données existantes du champ', pageNotFound: 'Page non trouvée', password: 'Mot de passe', @@ -572,12 +573,16 @@ export const frTranslations: DefaultTranslationsObject = { focalPoint: 'Point focal', focalPointDescription: 'Faites glisser le point focal directement sur l’aperçu ou ajustez les valeurs ci-dessous.', + fromURL: 'Téléverser un fichier à partir d’une URL', height: 'Hauteur', lessInfo: 'Moins d’infos', + linkToFile: 'Lien vers le fichier', moreInfo: 'Plus d’infos', noFile: 'Aucun fichier', pasteURL: "Coller l'URL", previewSizes: 'Tailles d’aperçu', + renameFile: 'Renommer le fichier', + replaceFile: 'Remplacer le fichier', selectCollectionToBrowse: 'Sélectionnez une collection à parcourir', selectFile: 'Sélectionnez un fichier', setCropArea: 'Définir la zone de recadrage', diff --git a/packages/translations/src/languages/he.ts b/packages/translations/src/languages/he.ts index 5edd426cc8d..edb9c7843c9 100644 --- a/packages/translations/src/languages/he.ts +++ b/packages/translations/src/languages/he.ts @@ -396,6 +396,7 @@ export const heTranslations: DefaultTranslationsObject = { openInNewWindow: 'פתח בחלון חדש', or: 'או', order: 'סדר', + original: 'מקורי', overwriteExistingData: 'דרוס את נתוני השדה הקיימים', pageNotFound: 'הדף לא נמצא', password: 'סיסמה', @@ -543,12 +544,16 @@ export const heTranslations: DefaultTranslationsObject = { fileToUpload: 'קובץ להעלאה', focalPoint: 'נקודת מיקוד', focalPointDescription: 'גרור את נקודת המיקוד ישירות על התצוגה המקדימה או התאם את הערכים למטה.', + fromURL: 'העלה קובץ מכתובת URL', height: 'גובה', lessInfo: 'פחות מידע', + linkToFile: 'קישור לקובץ', moreInfo: 'מידע נוסף', noFile: 'אין קובץ', pasteURL: 'הדבק כתובת אתר', previewSizes: 'גדלי תצוגה מקדימה', + renameFile: 'שנה את שם הקובץ', + replaceFile: 'החלף קובץ', selectCollectionToBrowse: 'בחר אוסף לצפייה', selectFile: 'בחר קובץ', setCropArea: 'הגדר אזור חיתוך', diff --git a/packages/translations/src/languages/hr.ts b/packages/translations/src/languages/hr.ts index aabe8d6ea73..1a49f5b8d7f 100644 --- a/packages/translations/src/languages/hr.ts +++ b/packages/translations/src/languages/hr.ts @@ -409,6 +409,7 @@ export const hrTranslations: DefaultTranslationsObject = { openInNewWindow: 'Otvori u novom prozoru', or: 'ili', order: 'Poredak', + original: 'Izvorno', overwriteExistingData: 'Prepišite postojeće podatke u polju', pageNotFound: 'Stranica nije pronađena', password: 'Lozinka', @@ -559,12 +560,16 @@ export const hrTranslations: DefaultTranslationsObject = { focalPoint: 'Središnja točka', focalPointDescription: 'Povucite središnju točku izravno na pregledu ili prilagodite vrijednosti ispod.', + fromURL: 'Prenesite datoteku s URL-a', height: 'Visina', lessInfo: 'Manje informacija', + linkToFile: 'Poveznica na datoteku', moreInfo: 'Više informacija', noFile: 'Nema datoteke', pasteURL: 'Zalijepi URL', previewSizes: 'Veličine pregleda', + renameFile: 'Preimenujte datoteku', + replaceFile: 'Zamijenite datoteku', selectCollectionToBrowse: 'Odaberite kolekciju za pregled', selectFile: 'Odaberite datoteku', setCropArea: 'Postavi područje usjeva', diff --git a/packages/translations/src/languages/hu.ts b/packages/translations/src/languages/hu.ts index 0300a38457a..526a746ed2f 100644 --- a/packages/translations/src/languages/hu.ts +++ b/packages/translations/src/languages/hu.ts @@ -414,6 +414,7 @@ export const huTranslations: DefaultTranslationsObject = { openInNewWindow: 'Megnyitás új ablakban', or: 'Vagy', order: 'Sorrend', + original: 'Eredeti', overwriteExistingData: 'Írja felül a meglévő mezőadatokat', pageNotFound: 'Az oldal nem található', password: 'Jelszó', @@ -565,12 +566,16 @@ export const huTranslations: DefaultTranslationsObject = { focalPoint: 'Fókuszpont', focalPointDescription: 'Húzza az érdekes pontot közvetlenül az előnézetre, vagy állítsa be az alábbi értékeket.', + fromURL: 'Fájl feltöltése URL-ről', height: 'Magasság', lessInfo: 'Kevesebb információ', + linkToFile: 'Hivatkozás a fájlra', moreInfo: 'További információ', noFile: 'Nincs fájl', pasteURL: 'URL beillesztése', previewSizes: 'Előnézeti méretek', + renameFile: 'Fájl átnevezése', + replaceFile: 'Fájl cseréje', selectCollectionToBrowse: 'Válassza ki a böngészni kívánt gyűjteményt', selectFile: 'Válasszon ki egy fájlt', setCropArea: 'Állítsa be a vágási területet', diff --git a/packages/translations/src/languages/hy.ts b/packages/translations/src/languages/hy.ts index 3bcb24b8299..9a585f68c09 100644 --- a/packages/translations/src/languages/hy.ts +++ b/packages/translations/src/languages/hy.ts @@ -410,6 +410,7 @@ export const hyTranslations: DefaultTranslationsObject = { openInNewWindow: 'Բացել նոր պատուհանում', or: 'Կամ', order: 'Հերթականություն', + original: 'Բնօրինակ', overwriteExistingData: 'Վերագրել գոյություն ունեցող դաշտի տվյալները', pageNotFound: 'Էջը չի գտնվել', password: 'Գաղտնաբառ', @@ -563,12 +564,16 @@ export const hyTranslations: DefaultTranslationsObject = { focalPoint: 'Կիզակետ', focalPointDescription: 'Քաշեք կիզակետը անմիջապես նախադիտման վրա կամ կարգավորեք ստորև նշված արժեքները։', + fromURL: 'Վերբեռնել ֆայլը URL-ով', height: 'Բարձրություն', lessInfo: 'Ավելի քիչ տեղեկություն', + linkToFile: 'Հղում դեպի ֆայլ', moreInfo: 'Ավելի շատ տեղեկություն', noFile: 'Ֆայլ չկա', pasteURL: 'Տեղադրել URL', previewSizes: 'Նախադիտման չափեր', + renameFile: 'Վերանվանել ֆայլը', + replaceFile: 'Փոխարինել ֆայլը', selectCollectionToBrowse: 'Ընտրեք հավաքածու՝ դիտելու համար', selectFile: 'Ընտրեք ֆայլ', setCropArea: 'Սահմանել կտրվող տարածքի չափը', diff --git a/packages/translations/src/languages/id.ts b/packages/translations/src/languages/id.ts index 58c3bc72073..b000dac10f5 100644 --- a/packages/translations/src/languages/id.ts +++ b/packages/translations/src/languages/id.ts @@ -412,6 +412,7 @@ export const idTranslations: DefaultTranslationsObject = { openInNewWindow: 'Buka di jendela baru', or: 'Atau', order: 'Urutan', + original: 'Asli', overwriteExistingData: 'Timpa data isian yang ada', pageNotFound: 'Halaman tidak ditemukan', password: 'Kata Sandi', @@ -564,12 +565,16 @@ export const idTranslations: DefaultTranslationsObject = { focalPoint: 'Titik Fokus', focalPointDescription: 'Seret titik fokus langsung pada pratinjau atau sesuaikan nilai di bawah ini.', + fromURL: 'Unggah berkas dari URL', height: 'Tinggi', lessInfo: 'Info lebih sedikit', + linkToFile: 'Tautan ke berkas', moreInfo: 'Info lebih lanjut', noFile: 'Tidak ada file', pasteURL: 'Tempel URL', previewSizes: 'Ukuran Pratinjau', + renameFile: 'Ganti nama file', + replaceFile: 'Ganti berkas', selectCollectionToBrowse: 'Pilih Koleksi untuk Dijelajahi', selectFile: 'Pilih file', setCropArea: 'Atur area pangkas', diff --git a/packages/translations/src/languages/is.ts b/packages/translations/src/languages/is.ts index 62de5e0553a..672ce62b57c 100644 --- a/packages/translations/src/languages/is.ts +++ b/packages/translations/src/languages/is.ts @@ -408,6 +408,7 @@ export const isTranslations: DefaultTranslationsObject = { openInNewWindow: 'Opna í nýjum glugga', or: 'Eða', order: 'Röð', + original: 'Upprunalegt', overwriteExistingData: 'Yfirskrifa skráð gögn í reit', pageNotFound: 'Síða fannst ekki', password: 'Lykilorð', @@ -559,12 +560,16 @@ export const isTranslations: DefaultTranslationsObject = { focalPoint: 'Brennipunktur', focalPointDescription: 'Dragðu brennipunktinn beint á forskoðunina eða stilltu gildin hér að neðan.', + fromURL: 'Hladdu inn skrá úr slóð', height: 'Hæð', lessInfo: 'Minni upplýsingar', + linkToFile: 'Tengill á skrá', moreInfo: 'Fleiri upplýsingar', noFile: 'Engin skrá', pasteURL: 'Líma vefslóð', previewSizes: 'Forskoðunarstærðir', + renameFile: 'Endurnefna skrá', + replaceFile: 'Skipta út skrá', selectCollectionToBrowse: 'Veldu safn til að skoða', selectFile: 'Veldu skrá', setCropArea: 'Stilla klippingarsvæði', diff --git a/packages/translations/src/languages/it.ts b/packages/translations/src/languages/it.ts index 4ccb426667c..5488aee4973 100644 --- a/packages/translations/src/languages/it.ts +++ b/packages/translations/src/languages/it.ts @@ -413,6 +413,7 @@ export const itTranslations: DefaultTranslationsObject = { openInNewWindow: 'Apri in una nuova finestra', or: 'Oppure', order: 'Ordine', + original: 'Originale', overwriteExistingData: 'Sovrascrivi i dati del campo esistente', pageNotFound: 'Pagina non trovata', password: 'Password', @@ -565,12 +566,16 @@ export const itTranslations: DefaultTranslationsObject = { focalPoint: 'Punto Focale', focalPointDescription: "Trascina il punto focale direttamente sull'anteprima o regola i valori sottostanti.", + fromURL: 'Carica file da URL', height: 'Altezza', lessInfo: 'Meno info', + linkToFile: 'Collega al file', moreInfo: 'Più info', noFile: 'Nessun file', pasteURL: 'Incolla URL', previewSizes: 'Anteprime Dimensioni', + renameFile: 'Rinomina file', + replaceFile: 'Sostituisci file', selectCollectionToBrowse: 'Seleziona una Collezione da Sfogliare', selectFile: 'Seleziona un file', setCropArea: 'Imposta area di ritaglio', diff --git a/packages/translations/src/languages/ja.ts b/packages/translations/src/languages/ja.ts index 07f3f83fbe2..9f3c958c94e 100644 --- a/packages/translations/src/languages/ja.ts +++ b/packages/translations/src/languages/ja.ts @@ -411,6 +411,7 @@ export const jaTranslations: DefaultTranslationsObject = { openInNewWindow: '新しいウィンドウで開く', or: 'または', order: '表示順', + original: 'オリジナル', overwriteExistingData: '既存のフィールドデータを上書きする', pageNotFound: 'ページが見つかりません', password: 'パスワード', @@ -559,12 +560,16 @@ export const jaTranslations: DefaultTranslationsObject = { fileToUpload: 'アップロードするファイル', focalPoint: '焦点', focalPointDescription: 'プレビュー上で焦点を直接ドラッグするか、下の値を調整してください。', + fromURL: 'URLからファイルをアップロード', height: '高さ', lessInfo: '詳細を隠す', + linkToFile: 'ファイルへのリンク', moreInfo: '詳細を表示', noFile: 'ファイルなし', pasteURL: 'URLを貼り付け', previewSizes: 'プレビューサイズ', + renameFile: 'ファイル名を変更', + replaceFile: 'ファイルを差し替える', selectCollectionToBrowse: '閲覧するコレクションを選択', selectFile: 'ファイルを選択', setCropArea: 'クロップエリアを設定する', diff --git a/packages/translations/src/languages/ko.ts b/packages/translations/src/languages/ko.ts index 0248adf27cc..07d214800fe 100644 --- a/packages/translations/src/languages/ko.ts +++ b/packages/translations/src/languages/ko.ts @@ -407,6 +407,7 @@ export const koTranslations: DefaultTranslationsObject = { openInNewWindow: '새 창에서 열기', or: '또는', order: '순서', + original: '원본', overwriteExistingData: '기존 필드 데이터 덮어쓰기', pageNotFound: '페이지를 찾을 수 없음', password: '비밀번호', @@ -557,12 +558,16 @@ export const koTranslations: DefaultTranslationsObject = { fileToUpload: '업로드할 파일', focalPoint: '초점', focalPointDescription: '미리보기에서 초점을 직접 드래그하거나 아래의 값을 조정하세요.', + fromURL: 'URL에서 파일 업로드', height: '높이', lessInfo: '정보 숨기기', + linkToFile: '파일로 연결', moreInfo: '정보 더보기', noFile: '파일 없음', pasteURL: 'URL 붙여넣기', previewSizes: '미리보기 크기', + renameFile: '파일 이름 변경', + replaceFile: '파일 교체', selectCollectionToBrowse: '찾을 컬렉션 선택', selectFile: '파일 선택', setCropArea: '자르기 영역 설정', diff --git a/packages/translations/src/languages/lt.ts b/packages/translations/src/languages/lt.ts index 37ea0f17000..6bcde767971 100644 --- a/packages/translations/src/languages/lt.ts +++ b/packages/translations/src/languages/lt.ts @@ -412,6 +412,7 @@ export const ltTranslations: DefaultTranslationsObject = { openInNewWindow: 'Atidaryti naujame lange', or: 'Arba', order: 'Užsakyti', + original: 'Originalas', overwriteExistingData: 'Perrašyti esamus lauko duomenis', pageNotFound: 'Puslapis nerastas', password: 'Slaptažodis', @@ -561,12 +562,16 @@ export const ltTranslations: DefaultTranslationsObject = { focalPoint: 'Fokuso Taškas', focalPointDescription: 'Temkite fokusavimo tašką tiesiogiai peržiūroje arba reguliuokite žemiau esančias reikšmes.', + fromURL: 'Įkelti failą iš URL', height: 'Aukštis', lessInfo: 'Mažiau informacijos', + linkToFile: 'Nuoroda į failą', moreInfo: 'Daugiau informacijos', noFile: 'Nėra failo', pasteURL: 'Įklijuokite URL', previewSizes: 'Peržiūros dydžiai', + renameFile: 'Pervadinti failą', + replaceFile: 'Pakeisti failą', selectCollectionToBrowse: 'Pasirinkite kolekciją, kurią norėtumėte naršyti', selectFile: 'Pasirinkite failą', setCropArea: 'Nustatykite pjovimo plotą', diff --git a/packages/translations/src/languages/lv.ts b/packages/translations/src/languages/lv.ts index 78408516d1c..4cc716e1174 100644 --- a/packages/translations/src/languages/lv.ts +++ b/packages/translations/src/languages/lv.ts @@ -411,6 +411,7 @@ export const lvTranslations: DefaultTranslationsObject = { openInNewWindow: 'Atvērt jaunā logā', or: 'Vai', order: 'Kārtība', + original: 'Oriģināls', overwriteExistingData: 'Pārrakstīt esošos datus', pageNotFound: 'Lapa nav atrasta', password: 'Parole', @@ -560,12 +561,16 @@ export const lvTranslations: DefaultTranslationsObject = { focalPoint: 'Fokusa punkts', focalPointDescription: 'Velciet fokusa punktu tieši priekšskatījumā vai pielāgojiet vērtības zemāk.', + fromURL: 'Augšupielādēt failu no URL', height: 'Augstums', lessInfo: 'Mazāk informācijas', + linkToFile: 'Saite uz failu', moreInfo: 'Vairāk informācijas', noFile: 'Nav faila', pasteURL: 'Ielīmēt URL', previewSizes: 'Priekšskatījuma izmēri', + renameFile: 'Pārsaukt failu', + replaceFile: 'Aizstāt failu', selectCollectionToBrowse: 'Izvēlieties kolekciju, ko pārlūkot', selectFile: 'Izvēlieties failu', setCropArea: 'Iestatīt apgriešanas apgabalu', diff --git a/packages/translations/src/languages/my.ts b/packages/translations/src/languages/my.ts index 2f776750c92..758a5eece4e 100644 --- a/packages/translations/src/languages/my.ts +++ b/packages/translations/src/languages/my.ts @@ -414,6 +414,7 @@ export const myTranslations: DefaultTranslationsObject = { openInNewWindow: 'ဝင်းဒိုးအသစ်တွင် ဖွင့်ပါ', or: 'သို့မဟုတ်', order: 'အစဉ်လိုက်', + original: 'မူရင်း', overwriteExistingData: 'ရှိပြီးသား အကွက်ဒေတာကို အစားထိုးပါ', pageNotFound: 'ရောက်ရှိနေသော စာမျက်နှာသည် မရှိပါ။', password: 'စကားဝှက်', @@ -567,12 +568,16 @@ export const myTranslations: DefaultTranslationsObject = { focalPoint: 'အကန့်အသတ်ချုပ်', focalPointDescription: 'ပြသနားရထားသည့်ပုံအားထိန်းသိမ်းရန် ဖိုကယ်ပိုင်းကို တိုက်ရိုက်ပွဲ့နိုင်သည် သို', + fromURL: 'URL မှတဆင့်ဖိုင် တင်သွင်းပါ', height: 'Height', lessInfo: 'အချက်အလက်နည်းတယ်။', + linkToFile: 'ဖိုင်သို့ ချိတ်ဆက်မှု', moreInfo: 'အချက်အလက်', noFile: 'ဖိုင် မရှိပါ', pasteURL: 'URL ကို ကူးထည့်ပါ', previewSizes: 'အစမ်းကြည့်အရွယ်အစားများ', + renameFile: 'ဖိုင်အမည်ပြောင်းရန်', + replaceFile: 'ဖိုင်ကို ပြန်လည်အစားထိုးပါ', selectCollectionToBrowse: 'စုစည်းမှု တစ်ခုခုကို ရွေးချယ်ပါ။', selectFile: 'ဖိုင်ရွေးပါ။', setCropArea: 'စပြန်းနယ်မြေထားပါ', @@ -671,8 +676,7 @@ export const myTranslations: DefaultTranslationsObject = { restoring: 'ပြန်ယူနေဆဲ...', reverting: 'ပြန်ပြောင်းနေဆဲ...', revertToPublished: 'အများဆိုင်သို့ ပြန်ပြောင်းပါ။', - revertUnsuccessful: - 'ပြန်လည်ပြောင်းခြင်း မအောင်မြင်ပါ။ ယခင်က ထုတ်ဝေထားသော ဗားရှင်း မတွေ့ပါ။', + revertUnsuccessful: 'ပြန်လည်ပြောင်းခြင်း မအောင်မြင်ပါ။ ယခင်က ထုတ်ဝေထားသော ဗားရှင်း မတွေ့ပါ။', saveDraft: 'မှုကြမ်းကို သိမ်းဆည်းမည်။', scheduledSuccessfully: 'အောင်မြင်စွာ နေ့စွဲထားသည်။', schedulePublish: 'ပြဌာန်းထုတ်ဝေချိန်း', diff --git a/packages/translations/src/languages/nb.ts b/packages/translations/src/languages/nb.ts index d3f39f15252..16f7a9c6321 100644 --- a/packages/translations/src/languages/nb.ts +++ b/packages/translations/src/languages/nb.ts @@ -411,6 +411,7 @@ export const nbTranslations: DefaultTranslationsObject = { openInNewWindow: 'Åpne i nytt vindu', or: 'Eller', order: 'Rekkefølge', + original: 'Original', overwriteExistingData: 'Overskriv eksisterende feltdata', pageNotFound: 'Siden ble ikke funnet', password: 'Passord', @@ -562,12 +563,16 @@ export const nbTranslations: DefaultTranslationsObject = { focalPoint: 'Fokuspunkt', focalPointDescription: 'Dra fokuspunktet direkte på forhåndsvisningen eller juster verdiene nedenfor.', + fromURL: 'Last opp fil fra URL', height: 'Høyde', lessInfo: 'Mindre info', + linkToFile: 'Lenke til fil', moreInfo: 'Mer info', noFile: 'Ingen fil', pasteURL: 'Lim inn URL', previewSizes: 'Forhåndsvisningsstørrelser', + renameFile: 'Gi nytt navn til fil', + replaceFile: 'Erstatt fil', selectCollectionToBrowse: 'Velg en samling å bla i', selectFile: 'Velg en fil', setCropArea: 'Angi beskjæringsområde', diff --git a/packages/translations/src/languages/nl.ts b/packages/translations/src/languages/nl.ts index 32970311903..3e47c8663c8 100644 --- a/packages/translations/src/languages/nl.ts +++ b/packages/translations/src/languages/nl.ts @@ -418,6 +418,7 @@ export const nlTranslations: DefaultTranslationsObject = { openInNewWindow: 'Openen in nieuw venster', or: 'Of', order: 'Volgorde', + original: 'Origineel', overwriteExistingData: 'Overschrijf bestaande veldgegevens', pageNotFound: 'Pagina niet gevonden', password: 'Wachtwoord', @@ -569,12 +570,16 @@ export const nlTranslations: DefaultTranslationsObject = { focalPoint: 'Focuspunt', focalPointDescription: 'Sleep het focuspunt rechtstreeks op de voorvertoning of pas de waarden hieronder aan.', + fromURL: 'Bestand uploaden vanaf URL', height: 'Hoogte', lessInfo: 'Minder info', + linkToFile: 'Koppeling naar bestand', moreInfo: 'Meer info', noFile: 'Geen bestand', pasteURL: 'URL plakken', previewSizes: 'Voorbeeldgroottes', + renameFile: 'Bestand hernoemen', + replaceFile: 'Bestand vervangen', selectCollectionToBrowse: 'Selecteer een collectie om door te bladeren', selectFile: 'Selecteer een bestand', setCropArea: 'Stel bijsnijdgebied in', diff --git a/packages/translations/src/languages/pl.ts b/packages/translations/src/languages/pl.ts index c5c663bd807..9192d674a70 100644 --- a/packages/translations/src/languages/pl.ts +++ b/packages/translations/src/languages/pl.ts @@ -410,6 +410,7 @@ export const plTranslations: DefaultTranslationsObject = { openInNewWindow: 'Otwórz w nowym oknie', or: 'lub', order: 'Kolejność', + original: 'Oryginał', overwriteExistingData: 'Nadpisz istniejące dane pola', pageNotFound: 'Strona nie znaleziona', password: 'Hasło', @@ -559,12 +560,16 @@ export const plTranslations: DefaultTranslationsObject = { focalPoint: 'Punkt centralny', focalPointDescription: 'Przeciągnij punkt centralny bezpośrednio na podglądzie lub dostosuj wartości poniżej.', + fromURL: 'Prześlij plik z adresu URL', height: 'Wysokość', lessInfo: 'Mniej informacji', + linkToFile: 'Link do pliku', moreInfo: 'Więcej informacji', noFile: 'Brak pliku', pasteURL: 'Wklej URL', previewSizes: 'Rozmiary podglądu', + renameFile: 'Zmień nazwę pliku', + replaceFile: 'Zastąp plik', selectCollectionToBrowse: 'Wybierz kolekcję aby przejrzeć', selectFile: 'Wybierz plik', setCropArea: 'Ustaw obszar kadrowania', diff --git a/packages/translations/src/languages/pt.ts b/packages/translations/src/languages/pt.ts index 213c8c95303..0ecd276a5fd 100644 --- a/packages/translations/src/languages/pt.ts +++ b/packages/translations/src/languages/pt.ts @@ -411,6 +411,7 @@ export const ptTranslations: DefaultTranslationsObject = { openInNewWindow: 'Abrir em nova janela', or: 'Ou', order: 'Ordem', + original: 'Original', overwriteExistingData: 'Sobrescrever dados de campo existentes', pageNotFound: 'Página não encontrada', password: 'Senha', @@ -562,12 +563,16 @@ export const ptTranslations: DefaultTranslationsObject = { focalPoint: 'Ponto Focal', focalPointDescription: 'Arraste o ponto focal diretamente na pré-visualização ou ajuste os valores abaixo.', + fromURL: 'Carregar arquivo a partir de URL', height: 'Altura', lessInfo: 'Ver menos', + linkToFile: 'Link para arquivo', moreInfo: 'Ver mais', noFile: 'Sem arquivo', pasteURL: 'Colar URL', previewSizes: 'Tamanhos de Pré-visualização', + renameFile: 'Renomear arquivo', + replaceFile: 'Substituir arquivo', selectCollectionToBrowse: 'Selecione uma Coleção para Navegar', selectFile: 'Selecione um arquivo', setCropArea: 'Definir área de corte', diff --git a/packages/translations/src/languages/ro.ts b/packages/translations/src/languages/ro.ts index 9f23d864c1a..1cca30a625a 100644 --- a/packages/translations/src/languages/ro.ts +++ b/packages/translations/src/languages/ro.ts @@ -416,6 +416,7 @@ export const roTranslations: DefaultTranslationsObject = { openInNewWindow: 'Deschide într-o fereastră nouă', or: 'Sau', order: 'ORdine', + original: 'Original', overwriteExistingData: 'Suprascrieți datele existente din câmp', pageNotFound: 'Pagina nu a fost găsită', password: 'Parola', @@ -566,12 +567,16 @@ export const roTranslations: DefaultTranslationsObject = { focalPoint: 'Punct central', focalPointDescription: 'Trageți punctul focal direct pe previzualizare sau ajustați valorile de mai jos.', + fromURL: 'Încarcă fișier din URL', height: 'Înălțime', lessInfo: 'Mai puține informații', + linkToFile: 'Link către fișier', moreInfo: 'Mai multe informații', noFile: 'Niciun fișier', pasteURL: 'Lipește URL', previewSizes: 'Dimensiuni Previzualizare', + renameFile: 'Redenumiți fișierul', + replaceFile: 'Înlocuiți fișierul', selectCollectionToBrowse: 'Selectați o colecție pentru navigare', selectFile: 'Selectați un fișier', setCropArea: 'Setați zona de decupare', diff --git a/packages/translations/src/languages/rs.ts b/packages/translations/src/languages/rs.ts index 59637fa4867..2419683cd0c 100644 --- a/packages/translations/src/languages/rs.ts +++ b/packages/translations/src/languages/rs.ts @@ -410,6 +410,7 @@ export const rsTranslations: DefaultTranslationsObject = { openInNewWindow: 'Отвори у новом прозору', or: 'Или', order: 'Редослед', + original: 'Оригинал', overwriteExistingData: 'Prepišite postojeće podatke u polju', pageNotFound: 'Страница није пронађена', password: 'Лозинка', @@ -559,12 +560,16 @@ export const rsTranslations: DefaultTranslationsObject = { focalPoint: 'Централна тачка', focalPointDescription: 'Превуците средишњу тачку директно на преглед или прилагодите вредности испод.', + fromURL: 'Отпремите датотеку са URL-а', height: 'Висина', lessInfo: 'Мање информација', + linkToFile: 'Веза до фајла', moreInfo: 'Више информација', noFile: 'Nema fajla', pasteURL: 'Налепи URL', previewSizes: 'Величине прегледа', + renameFile: 'Преименујте фајл', + replaceFile: 'Замените датотеку', selectCollectionToBrowse: 'Одаберите колекцију за преглед', selectFile: 'Одаберите датотеку', setCropArea: 'Поставите подручје за исечену слику', diff --git a/packages/translations/src/languages/rsLatin.ts b/packages/translations/src/languages/rsLatin.ts index 9eda7ad9504..3024eb081ba 100644 --- a/packages/translations/src/languages/rsLatin.ts +++ b/packages/translations/src/languages/rsLatin.ts @@ -410,6 +410,7 @@ export const rsLatinTranslations: DefaultTranslationsObject = { openInNewWindow: 'Otvori u novom prozoru', or: 'Ili', order: 'Redosled', + original: 'Original', overwriteExistingData: 'Prepiši postojeće podatke iz polja', pageNotFound: 'Stranica nije pronađena', password: 'Lozinka', @@ -560,12 +561,16 @@ export const rsLatinTranslations: DefaultTranslationsObject = { focalPoint: 'Centralna tačka', focalPointDescription: 'Prevucite središnju tačku direktno na pregled ili prilagodite vrednosti ispod.', + fromURL: 'Otpremite fajl sa URL adrese', height: 'Visina', lessInfo: 'Manje informacija', + linkToFile: 'Link ka fajlu', moreInfo: 'Više informacija', noFile: 'Nema datoteke', pasteURL: 'Nalepi URL', previewSizes: 'Veličine pregleda', + renameFile: 'Preimenujte fajl', + replaceFile: 'Zamenite fajl', selectCollectionToBrowse: 'Odaberite kolekciju za pregled', selectFile: 'Odaberite datoteku', setCropArea: 'Postavite područje za isečenu sliku', diff --git a/packages/translations/src/languages/ru.ts b/packages/translations/src/languages/ru.ts index f4d69a2d024..9f3bc127656 100644 --- a/packages/translations/src/languages/ru.ts +++ b/packages/translations/src/languages/ru.ts @@ -413,6 +413,7 @@ export const ruTranslations: DefaultTranslationsObject = { openInNewWindow: 'Открыть в новом окне', or: 'Или же', order: 'Порядок', + original: 'Оригинал', overwriteExistingData: 'Перезаписать существующие данные поля', pageNotFound: 'Страница не найдена', password: 'Пароль', @@ -564,12 +565,16 @@ export const ruTranslations: DefaultTranslationsObject = { focalPoint: 'Центральная точка', focalPointDescription: 'Перетащите фокусное расстояние прямо на предварительный просмотр или отрегулируйте значения ниже.', + fromURL: 'Загрузить файл по URL', height: 'Высота', lessInfo: 'Меньше информации', + linkToFile: 'Ссылка на файл', moreInfo: 'Больше информации', noFile: 'Нет файла', pasteURL: 'Вставить URL', previewSizes: 'Предварительный просмотр размеров', + renameFile: 'Переименовать файл', + replaceFile: 'Заменить файл', selectCollectionToBrowse: 'Выберите Коллекцию для просмотра', selectFile: 'Выберите файл', setCropArea: 'Установите область обрезки', diff --git a/packages/translations/src/languages/sk.ts b/packages/translations/src/languages/sk.ts index 170a3eee1ed..990e5cedfe3 100644 --- a/packages/translations/src/languages/sk.ts +++ b/packages/translations/src/languages/sk.ts @@ -409,6 +409,7 @@ export const skTranslations: DefaultTranslationsObject = { openInNewWindow: 'Otvoriť v novom okne', or: 'Alebo', order: 'Poradie', + original: 'Originál', overwriteExistingData: 'Prepísať existujúce pole dát', pageNotFound: 'Stránka nenájdená', password: 'Heslo', @@ -558,12 +559,16 @@ export const skTranslations: DefaultTranslationsObject = { focalPoint: 'Stredobod', focalPointDescription: 'Potiahnite bod stredobodu priamo na náhľad alebo upravte hodnoty nižšie.', + fromURL: 'Nahrať súbor z URL adresy', height: 'Výška', lessInfo: 'Menej informácií', + linkToFile: 'Odkaz na súbor', moreInfo: 'Viac informácií', noFile: 'Žiadny súbor', pasteURL: 'Vložiť URL', previewSizes: 'Náhľady veľkostí', + renameFile: 'Premenovať súbor', + replaceFile: 'Nahradiť súbor', selectCollectionToBrowse: 'Vyberte kolekciu na prezeranie', selectFile: 'Vyberte súbor', setCropArea: 'Nastaviť oblasť orezania', diff --git a/packages/translations/src/languages/sl.ts b/packages/translations/src/languages/sl.ts index 623b327f740..47adf9b7c92 100644 --- a/packages/translations/src/languages/sl.ts +++ b/packages/translations/src/languages/sl.ts @@ -409,6 +409,7 @@ export const slTranslations: DefaultTranslationsObject = { openInNewWindow: 'Odpri v novem oknu', or: 'Ali', order: 'Vrstni red', + original: 'Izvirnik', overwriteExistingData: 'Prepišite obstoječe podatke polja', pageNotFound: 'Stran ni najdena', password: 'Geslo', @@ -559,12 +560,16 @@ export const slTranslations: DefaultTranslationsObject = { focalPoint: 'Žarišče', focalPointDescription: 'Povlecite žarišče neposredno na predogledu ali prilagodite vrednosti spodaj.', + fromURL: 'Naloži datoteko iz URL-ja', height: 'Višina', lessInfo: 'Manj informacij', + linkToFile: 'Povezava do datoteke', moreInfo: 'Več informacij', noFile: 'Ni datoteke.', pasteURL: 'Prilepi URL', previewSizes: 'Velikosti predogleda', + renameFile: 'Preimenuj datoteko', + replaceFile: 'Zamenjaj datoteko', selectCollectionToBrowse: 'Izberite zbirko za brskanje', selectFile: 'Izberite datoteko', setCropArea: 'Nastavi območje obrezovanja', diff --git a/packages/translations/src/languages/sv.ts b/packages/translations/src/languages/sv.ts index 8c6fd2325d9..ad84a700f9c 100644 --- a/packages/translations/src/languages/sv.ts +++ b/packages/translations/src/languages/sv.ts @@ -411,6 +411,7 @@ export const svTranslations: DefaultTranslationsObject = { openInNewWindow: 'Öppna i nytt fönster', or: 'Eller', order: 'Ordning', + original: 'Original', overwriteExistingData: 'Skriv över befintlig fältdata', pageNotFound: 'Sidan hittas inte', password: 'Lösenord', @@ -562,12 +563,16 @@ export const svTranslations: DefaultTranslationsObject = { focalPoint: 'Fokuspunkt', focalPointDescription: 'Dra fokuspunkten direkt på förhandsgranskningen eller justera värdena nedan.', + fromURL: 'Ladda upp fil från URL', height: 'Höjd', lessInfo: 'Mindre info', + linkToFile: 'Länk till fil', moreInfo: 'Mer info', noFile: 'Ingen fil', pasteURL: 'Klistra in URL', previewSizes: 'Förhandsgranska storlekar', + renameFile: 'Byt namn på fil', + replaceFile: 'Ersätt fil', selectCollectionToBrowse: 'Välj en samling att bläddra i', selectFile: 'Välj en fil', setCropArea: 'Ange beskärning', diff --git a/packages/translations/src/languages/ta.ts b/packages/translations/src/languages/ta.ts index a389717d90d..9cf4273068b 100644 --- a/packages/translations/src/languages/ta.ts +++ b/packages/translations/src/languages/ta.ts @@ -409,6 +409,7 @@ export const taTranslations: DefaultTranslationsObject = { openInNewWindow: 'புதிய சாளரத்தில் திற', or: 'அல்லது', order: 'வரிசை', + original: 'மூலம்', overwriteExistingData: 'ஏற்கனவே உள்ள புலத் தரவை மேலெழுது', pageNotFound: 'பக்கம் கிடைக்கவில்லை', password: 'கடவுச்சொல்', @@ -560,12 +561,16 @@ export const taTranslations: DefaultTranslationsObject = { focalPoint: 'கவனம் செலுத்தும் புள்ளி', focalPointDescription: 'முன்னோட்டத்தில் புள்ளியை நேரடியாக இழுத்து விடவும் அல்லது கீழே உள்ள மதிப்புகளை மாற்றவும்.', + fromURL: 'URL-ில் இருந்து கோப்பை பதிவேற்று', height: 'உயரம்', lessInfo: 'குறைந்த தகவல்', + linkToFile: 'கோப்பிற்கான இணைப்பு', moreInfo: 'மேலும் தகவல்', noFile: 'கோப்பு இல்லை', pasteURL: 'URL ஒட்டுக', previewSizes: 'முன்னோட்ட அளவுகள்', + renameFile: 'கோப்பை மறுபெயரிடு', + replaceFile: 'கோப்பை மாற்றவும்', selectCollectionToBrowse: 'உலாவ தொகுப்பைத் தேர்ந்தெடுக்கவும்', selectFile: 'கோப்பைத் தேர்ந்தெடுக்கவும்', setCropArea: 'வெட்டும் பகுதியை அமைக்கவும்', diff --git a/packages/translations/src/languages/th.ts b/packages/translations/src/languages/th.ts index 66f88a73b99..6895b8c17f6 100644 --- a/packages/translations/src/languages/th.ts +++ b/packages/translations/src/languages/th.ts @@ -402,6 +402,7 @@ export const thTranslations: DefaultTranslationsObject = { openInNewWindow: 'เปิดในหน้าต่างใหม่', or: 'หรือ', order: 'เรียงตาม', + original: 'ต้นฉบับ', overwriteExistingData: 'เขียนทับข้อมูลในฟิลด์ที่มีอยู่แล้ว', pageNotFound: 'ไม่พบหน้าที่ต้องการ', password: 'รหัสผ่าน', @@ -550,12 +551,16 @@ export const thTranslations: DefaultTranslationsObject = { fileToUpload: 'อัปโหลดไฟล์', focalPoint: 'จุดสนใจ', focalPointDescription: 'ลากจุดโฟกัสตรงบนภาพตัวอย่างหรือปรับค่าที่อยู่ด้านล่าง', + fromURL: 'อัปโหลดไฟล์จาก URL', height: 'ความสูง', lessInfo: 'ซ่อนข้อมูล', + linkToFile: 'ลิงก์ไปยังไฟล์', moreInfo: 'แสดงข้อมูล', noFile: 'ไม่มีไฟล์', pasteURL: 'วาง URL', previewSizes: 'ขนาดตัวอย่าง', + renameFile: 'เปลี่ยนชื่อไฟล์', + replaceFile: 'แทนที่ไฟล์', selectCollectionToBrowse: 'เลือก Collection ที่ต้องการค้นหา', selectFile: 'เลือกไฟล์', setCropArea: 'ตั้งค่าพื้นที่การครอบตัด', diff --git a/packages/translations/src/languages/tr.ts b/packages/translations/src/languages/tr.ts index 82a23c578b3..e78d1ec991e 100644 --- a/packages/translations/src/languages/tr.ts +++ b/packages/translations/src/languages/tr.ts @@ -414,6 +414,7 @@ export const trTranslations: DefaultTranslationsObject = { openInNewWindow: 'Yeni pencerede aç', or: 'Or', order: 'Order', + original: 'Orijinal', overwriteExistingData: 'Mevcut alan verilerinin üzerine yazın', pageNotFound: 'Sayfa bulunamadı', password: 'Parola', @@ -566,12 +567,16 @@ export const trTranslations: DefaultTranslationsObject = { focalPoint: 'Odak Noktası', focalPointDescription: 'Önizlemeye odak noktasını doğrudan sürükleyin veya aşağıdaki değerleri ayarlayın.', + fromURL: 'URL’den dosya yükle', height: 'Yükseklik', lessInfo: 'Daha az bilgi', + linkToFile: 'Dosyaya bağlantı', moreInfo: 'Daha fazla bilgi', noFile: 'Dosya yok', pasteURL: 'URL yapıştır', previewSizes: 'Önizleme Boyutları', + renameFile: 'Dosyayı yeniden adlandır', + replaceFile: 'Dosyayı değiştir', selectCollectionToBrowse: 'Görüntülenecek bir koleksiyon seçin', selectFile: 'Dosya seç', setCropArea: 'Mahsul alanını ayarla', diff --git a/packages/translations/src/languages/uk.ts b/packages/translations/src/languages/uk.ts index d6627bb6a45..cdf103ef69f 100644 --- a/packages/translations/src/languages/uk.ts +++ b/packages/translations/src/languages/uk.ts @@ -408,6 +408,7 @@ export const ukTranslations: DefaultTranslationsObject = { openInNewWindow: 'Відкрити в новому вікні', or: 'або', order: 'Порядок', + original: 'Оригінал', overwriteExistingData: 'Перезаписати існуючі дані поля', pageNotFound: 'Сторінка не знайдена', password: 'Пароль', @@ -557,12 +558,16 @@ export const ukTranslations: DefaultTranslationsObject = { focalPoint: 'Точка фокусу', focalPointDescription: 'Перетягніть точку фокусу безпосередньо на попередньому перегляді або налаштуйте значення нижче.', + fromURL: 'Завантажити файл з URL-адреси', height: 'Висота', lessInfo: 'Менше інформації', + linkToFile: 'Посилання на файл', moreInfo: 'Більше інформації', noFile: 'Немає файлу', pasteURL: 'Вставити URL', previewSizes: 'Попередній перегляд розмірів', + renameFile: 'Перейменувати файл', + replaceFile: 'Замінити файл', selectCollectionToBrowse: 'Оберіть колекцію для перегляду', selectFile: 'Оберіть файл', setCropArea: 'Встановити область обрізки', diff --git a/packages/translations/src/languages/vi.ts b/packages/translations/src/languages/vi.ts index 6e9ddb7f70e..2fb55de4fc7 100644 --- a/packages/translations/src/languages/vi.ts +++ b/packages/translations/src/languages/vi.ts @@ -411,6 +411,7 @@ export const viTranslations: DefaultTranslationsObject = { openInNewWindow: 'Mở trong cửa sổ mới', or: 'hoặc', order: 'Thứ tự', + original: 'Bản gốc', overwriteExistingData: 'Ghi đè dữ liệu trường hiện tại', pageNotFound: 'Không tìm thấy trang', password: 'Mật khẩu', @@ -560,12 +561,16 @@ export const viTranslations: DefaultTranslationsObject = { focalPoint: 'Điểm trọng tâm', focalPointDescription: 'Kéo điểm tiêu điểm trực tiếp trên ảnh xem trước hoặc điều chỉnh giá trị bên dưới.', + fromURL: 'Tải lên tệp từ URL', height: 'Chiều cao', lessInfo: 'Hiển thị ít hơn', + linkToFile: 'Liên kết tới tệp', moreInfo: 'Xem thêm', noFile: 'Không có tệp', pasteURL: 'Dán URL', previewSizes: 'Kích cỡ xem trước', + renameFile: 'Đổi tên tệp', + replaceFile: 'Thay thế tệp', selectCollectionToBrowse: 'Chọn một Collection để tìm', selectFile: 'Chọn một file', setCropArea: 'Đặt khu vực cắt', diff --git a/packages/translations/src/languages/zh.ts b/packages/translations/src/languages/zh.ts index 0abf524ca07..d7a88609025 100644 --- a/packages/translations/src/languages/zh.ts +++ b/packages/translations/src/languages/zh.ts @@ -390,6 +390,7 @@ export const zhTranslations: DefaultTranslationsObject = { openInNewWindow: '在新窗口中打开', or: '或', order: '排序', + original: '原始', overwriteExistingData: '覆盖现有字段数据', pageNotFound: '未找到页面', password: '密码', @@ -536,12 +537,16 @@ export const zhTranslations: DefaultTranslationsObject = { fileToUpload: '要上传的文件', focalPoint: '焦点', focalPointDescription: '直接在预览中拖动焦点或调整下面的值。', + fromURL: '从网址上传文件', height: '高度', lessInfo: '更少信息', + linkToFile: '链接到文件', moreInfo: '更多信息', noFile: '没有文件', pasteURL: '粘贴网址', previewSizes: '预览尺寸', + renameFile: '重命名文件', + replaceFile: '替换文件', selectCollectionToBrowse: '选择一个要浏览的集合', selectFile: '选择一个文件', setCropArea: '设置裁剪区域', diff --git a/packages/translations/src/languages/zhTw.ts b/packages/translations/src/languages/zhTw.ts index b782801cc97..80c5814614f 100644 --- a/packages/translations/src/languages/zhTw.ts +++ b/packages/translations/src/languages/zhTw.ts @@ -388,6 +388,7 @@ export const zhTwTranslations: DefaultTranslationsObject = { openInNewWindow: '在新視窗中開啟', or: '或', order: '順序', + original: '原始', overwriteExistingData: '覆寫現有欄位資料', pageNotFound: '找不到此頁面', password: '密碼', @@ -534,12 +535,16 @@ export const zhTwTranslations: DefaultTranslationsObject = { fileToUpload: '待上傳的檔案', focalPoint: '對焦點', focalPointDescription: '直接在預覽圖上拖曳以設定對焦點,或調整下方數值。', + fromURL: '從網址上傳檔案', height: '高度', lessInfo: '顯示較少資訊', + linkToFile: '連結至檔案', moreInfo: '顯示更多資訊', noFile: '無檔案', pasteURL: '貼上網址', previewSizes: '預覽尺寸', + renameFile: '重新命名檔案', + replaceFile: '更換檔案', selectCollectionToBrowse: '選取要瀏覽的集合', selectFile: '選取檔案', setCropArea: '設定裁剪區域', diff --git a/packages/ui/src/elements/AppHeader/index.tsx b/packages/ui/src/elements/AppHeader/index.tsx index 3d994e43f67..dba97b9baf9 100644 --- a/packages/ui/src/elements/AppHeader/index.tsx +++ b/packages/ui/src/elements/AppHeader/index.tsx @@ -36,9 +36,22 @@ export function AppHeader({ CustomAvatar, settingsItemGroups }: Props) { config: { localization }, } = useConfig() + const headerRef = useRef(null) const customControlsRef = useRef(null) const [isScrollable, setIsScrollable] = useState(false) + useEffect(() => { + const el = headerRef.current + if (!el) { + return + } + const observer = new ResizeObserver(() => { + document.documentElement.style.setProperty('--app-header-height', `${el.offsetHeight}px`) + }) + observer.observe(el) + return () => observer.disconnect() + }, []) + useEffect(() => { const checkIsScrollable = () => { const el = customControlsRef.current @@ -59,7 +72,10 @@ export function AppHeader({ CustomAvatar, settingsItemGroups }: Props) { const ActionComponents = Actions ? Object.values(Actions) : [] return ( -
+
diff --git a/packages/ui/src/elements/Dialog/index.css b/packages/ui/src/elements/Dialog/index.css index 0cfa9c9c0f5..922751170ee 100644 --- a/packages/ui/src/elements/Dialog/index.css +++ b/packages/ui/src/elements/Dialog/index.css @@ -38,7 +38,7 @@ } .dialog--large { - --dialog-width: 640px; + --dialog-width: 840px; } .dialog__header { diff --git a/packages/ui/src/elements/DocumentControls/index.tsx b/packages/ui/src/elements/DocumentControls/index.tsx index e3fd5bfa590..81dcefa5d5e 100644 --- a/packages/ui/src/elements/DocumentControls/index.tsx +++ b/packages/ui/src/elements/DocumentControls/index.tsx @@ -157,7 +157,20 @@ export const DocumentControls: React.FC<{ const processing = useFormProcessing() const initializing = useFormInitializing() + const rootRef = useRef(null) const i18nRef = useRef(i18n) + + useEffect(() => { + const el = rootRef.current + if (!el) { + return + } + const observer = new ResizeObserver(() => { + document.documentElement.style.setProperty('--doc-controls-height', `${el.offsetHeight}px`) + }) + observer.observe(el) + return () => observer.disconnect() + }, []) i18nRef.current = i18n const updateRelativeTime = useCallback(() => { @@ -222,6 +235,7 @@ export const DocumentControls: React.FC<{ className={[baseClass, variant !== 'default' && `${baseClass}--${variant}`] .filter(Boolean) .join(' ')} + ref={rootRef} > {variant === 'default' && (
diff --git a/packages/ui/src/elements/DocumentHeader/DocumentHeaderRoot/index.tsx b/packages/ui/src/elements/DocumentHeader/DocumentHeaderRoot/index.tsx new file mode 100644 index 00000000000..109bdee9aef --- /dev/null +++ b/packages/ui/src/elements/DocumentHeader/DocumentHeaderRoot/index.tsx @@ -0,0 +1,33 @@ +'use client' +import React, { useEffect, useRef } from 'react' + +const baseClass = 'doc-header' + +/** + * Client wrapper for the document header that publishes its rendered height as the + * `--doc-header-height` CSS variable, mirroring how `AppHeader` and `DocumentControls` + * expose their own heights for layout calculations. + * + * @internal + */ +export const DocumentHeaderRoot: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const ref = useRef(null) + + useEffect(() => { + const el = ref.current + if (!el) { + return + } + const observer = new ResizeObserver(() => { + document.documentElement.style.setProperty('--doc-header-height', `${el.offsetHeight}px`) + }) + observer.observe(el) + return () => observer.disconnect() + }, []) + + return ( +
+ {children} +
+ ) +} diff --git a/packages/ui/src/elements/DocumentHeader/index.tsx b/packages/ui/src/elements/DocumentHeader/index.tsx index e4970452e98..315581e4e97 100644 --- a/packages/ui/src/elements/DocumentHeader/index.tsx +++ b/packages/ui/src/elements/DocumentHeader/index.tsx @@ -8,7 +8,7 @@ import type { import React from 'react' // eslint-disable-next-line payload/no-imports-from-exports-dir -- Server component must reference exports dir for proper client boundary -import { Gutter, RenderTitle } from '../../exports/client/index.js' +import { DocumentHeaderRoot, Gutter, RenderTitle } from '../../exports/client/index.js' import { DocumentTabs } from './Tabs/index.js' import './index.css' @@ -28,7 +28,7 @@ export const DocumentHeader: React.FC<{ const { AfterHeader, collectionConfig, globalConfig, hideTabs, permissions, req } = props return ( -
+ {!hideTabs && ( )} {AfterHeader ?
{AfterHeader}
: null} -
+ ) } diff --git a/packages/ui/src/elements/Dropzone/index.css b/packages/ui/src/elements/Dropzone/index.css index 514991a23be..627aac91c36 100644 --- a/packages/ui/src/elements/Dropzone/index.css +++ b/packages/ui/src/elements/Dropzone/index.css @@ -4,7 +4,6 @@ display: flex; align-items: flex-start; background: transparent; - border: var(--stroke-width-small) dashed var(--special-border-translucent); border-radius: var(--field-border-radius); overflow: clip; width: 100%; @@ -18,7 +17,6 @@ } &.dragging { - border-color: var(--color-border-selected); background: var(--color-bg-brand-tertiary); * { @@ -26,22 +24,15 @@ } } - &:focus-within, - &.focused { - border-color: var(--color-border-selected); - background: var(--color-bg-brand-tertiary); - outline: none; - } - - &.dropzone--has-error { - border-color: var(--color-border-danger-strong); - } - @media (max-width: 768px) { display: block; text-align: center; } + &.dropzone--style-default { + padding-block: var(--spacer-3); + } + &.dropzone--style-none { all: unset; } diff --git a/packages/ui/src/elements/EditUpload/index.css b/packages/ui/src/elements/EditUpload/index.css index 171c5d99096..8da9da79adc 100644 --- a/packages/ui/src/elements/EditUpload/index.css +++ b/packages/ui/src/elements/EditUpload/index.css @@ -1,80 +1,117 @@ @layer payload-default { - .edit-upload { - --edit-upload-cell-spacing: var(--spacer-4); - --edit-upload-sidebar-width: calc(350px + var(--gutter-h)); - height: 100%; + /* Allow the ReactCrop 9999px box-shadow overlay to escape the dialog bounds. + Make the body a flex column so edit-upload__content can fill its height. */ + .edit-upload__dialog { + overflow: visible; + + .dialog__body { + overflow: visible; + display: flex; + flex-direction: column; + } + } + + .edit-upload__content { display: flex; - flex-direction: column; + flex-direction: row; + flex: 1 1 auto; + min-height: 480px; + gap: 0; } - .edit-upload__header { - border-bottom: 1px solid var(--color-border); - padding: var(--spacer-2-5); + /* Canvas area — must have a definite height for max-height: 100% to resolve on focal-wrapper */ + .edit-upload__crop { + flex: 1 1 0; + min-width: 0; + height: 100%; display: flex; - justify-content: space-between; align-items: center; + justify-content: center; + padding: var(--spacer-4); + background: var(--color-bg-secondary); + border-radius: var(--radius-small); } - .edit-upload__header h2 { - margin: 0; - text-wrap: nowrap; - overflow: hidden; - text-overflow: ellipsis; + .edit-upload .ReactCrop__selection-addon, + .edit-upload__crop-window { + height: 100%; + width: 100%; } - [dir='rtl'] .edit-upload__actions { - margin-right: auto; - margin-left: unset; + .edit-upload__focal-wrapper { + position: relative; + display: inline-flex; + max-height: 100%; + max-width: 100%; } - .edit-upload__actions { - min-width: 350px; - margin-left: auto; - padding: var(--spacer-2) 0 var(--spacer-2) var(--spacer-4); - justify-content: flex-end; + /* Sidebar */ + .edit-upload__sidebar { + flex-shrink: 0; + width: 240px; + border-left: 1px solid var(--color-border); display: flex; - gap: var(--spacer-3); - text-wrap: nowrap; + flex-direction: column; + margin-inline-start: var(--spacer-3); + padding-inline-start: var(--spacer-3); } - .edit-upload__toolWrap { + .edit-upload__section { display: flex; - justify-content: flex-end; - flex: 1; - min-height: 0; + flex-direction: column; + gap: var(--spacer-2); + padding-block: var(--spacer-3); } - .edit-upload .ReactCrop__selection-addon, - .edit-upload__crop-window { - height: 100%; - width: 100%; + .edit-upload__section + .edit-upload__section { + border-top: 1px solid var(--color-border); } - .edit-upload__focal-wrapper { - position: relative; - display: inline-flex; - max-height: 100%; + .edit-upload__section-header { + display: flex; + align-items: center; + justify-content: space-between; } - .edit-upload__draggable-container { - position: absolute; - left: 0; - right: 0; - bottom: 0; - top: 0; - pointer-events: none; + .edit-upload__section-title { + font-family: var(--text-body-medium-strong-font-family); + font-size: var(--text-body-medium-font-size); + font-weight: var(--text-body-medium-strong-font-weight); + line-height: var(--text-body-medium-strong-line-height); + color: var(--color-text); } - .edit-upload__draggable-container--dragging { - pointer-events: all; + .edit-upload__reset { + height: fit-content; + padding: 0 var(--spacer-2); + } + + .edit-upload__fieldset { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--spacer-2); } - .edit-upload__draggable-container--dragging .edit-upload__focalPoint { - cursor: grabbing; + .edit-upload__field { + margin-bottom: 0; + } + + .edit-upload__suffix { + font-size: var(--text-body-medium-font-size); + color: var(--color-text-secondary); + padding-inline-start: var(--spacer-1); + } + + /* Draggable focal point */ + .edit-upload__draggable-container { + position: absolute; + inset: 0; + pointer-events: none; /* let clicks pass through to the image/crop layer */ } .edit-upload__draggable { position: absolute; + pointer-events: all; /* only the handle itself is interactive */ } .edit-upload__focalPoint { @@ -94,10 +131,7 @@ .edit-upload__focalPoint svg { position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; + inset: 0; background: rgba(0, 0, 0, 0.5); border-radius: 100%; width: var(--spacer-6); @@ -105,122 +139,23 @@ color: white; } - .edit-upload__crop, - .edit-upload__focalOnly { - padding: var(--spacer-4) var(--spacer-4) var(--spacer-4) 0; - width: 100%; - display: flex; - justify-content: center; - } - - .edit-upload__crop { - padding: var(--edit-upload-cell-spacing); - padding-left: var(--gutter-h); - display: flex; - align-items: flex-start; - height: 100%; - } - - .edit-upload__imageWrap { - position: relative; - } - - .edit-upload__point { - cursor: move; - position: absolute; - background: rgba(0, 0, 0, 0.5); - border-radius: 100%; - } - - .edit-upload__point svg { - width: var(--spacer-6); - height: var(--spacer-6); - } - - .edit-upload__sidebar { - border-left: 1px solid var(--color-border); - padding-top: var(--edit-upload-cell-spacing); - min-width: var(--edit-upload-sidebar-width); - } - - .edit-upload__sidebar > div:first-child { - margin-bottom: var(--spacer-3); - } - - .edit-upload__groupWrap { - display: flex; - flex-direction: column; - gap: var(--spacer-2); - padding-right: var(--gutter-h); - padding-left: var(--edit-upload-cell-spacing); - width: 100%; - } - - .edit-upload__groupWrap + .edit-upload__groupWrap { - padding-top: var(--edit-upload-cell-spacing); - margin-top: var(--edit-upload-cell-spacing); - border-top: 1px solid var(--color-border); - } - - .edit-upload__inputsWrap, - .edit-upload__titleWrap { - display: flex; - gap: var(--spacer-3); - } - - .edit-upload__titleWrap { - justify-content: space-between; - align-items: center; - } - - .edit-upload__titleWrap h3 { - margin: 0; - } - - .edit-upload__reset { - height: fit-content; - border-radius: var(--radius-small); - background-color: var(--color-bg-secondary); - padding: 0 var(--spacer-2); - } - - .edit-upload__input { - flex: 1; - } - - @media (max-width: 1024px) { - .edit-upload { - --edit-upload-cell-spacing: var(--gutter-h); - } - - .edit-upload__sidebar { - padding-left: 0; - border-left: 0; - width: 100%; - } - - .edit-upload__toolWrap { - flex-direction: column-reverse; - } - } - @media (max-width: 768px) { - .edit-upload { + .edit-upload__content { flex-direction: column; + min-height: unset; } - .edit-upload__focalPoint { - border-right: none; - padding: var(--spacer-3) 0; + .edit-upload__sidebar { + width: 100%; + border-left: none; + border-top: 1px solid var(--color-border); + margin-inline-start: 0; + padding-inline-start: 0; + padding-top: var(--spacer-3); } - .edit-upload__inputsWrap { + .edit-upload__fieldset { flex-direction: column; - gap: var(--spacer-3); - } - - .edit-upload__sidebar { - min-width: 0; } } } diff --git a/packages/ui/src/elements/EditUpload/index.tsx b/packages/ui/src/elements/EditUpload/index.tsx index f3180f8827f..01837d8c536 100644 --- a/packages/ui/src/elements/EditUpload/index.tsx +++ b/packages/ui/src/elements/EditUpload/index.tsx @@ -7,40 +7,17 @@ import React, { useRef, useState } from 'react' import ReactCrop from 'react-image-crop' import { editDrawerSlug } from '../../elements/Upload/index.js' +import { NumberInput } from '../../fields/Number/Input.js' import { PlusIcon } from '../../icons/Plus/index.js' import { useTranslation } from '../../providers/Translation/index.js' import { appendCacheTag } from '../../utilities/appendCacheTag.js' import { Button } from '../Button/index.js' +import { DialogBody, DialogFooter, DialogHeader, DialogModal } from '../Dialog/index.js' import './index.css' +import './library.scss' const baseClass = 'edit-upload' -type Props = { - disabled?: boolean - name: string - onChange: (value: string) => void - ref?: React.RefObject - value: string -} - -const Input: React.FC = (props) => { - const { name, disabled, onChange, ref, value } = props - - return ( -
- {name} - onChange(e.target.value)} - ref={ref} - type="number" - value={value} - /> -
- ) -} - type FocalPosition = { x: number y: number @@ -49,7 +26,7 @@ type FocalPosition = { export type EditUploadProps = { fileName: string fileSrc: string - imageCacheTag?: string + imageCacheTag?: false | string initialCrop?: UploadEdits['crop'] initialFocalPoint?: FocalPosition onSave?: (uploadEdits: UploadEdits) => void @@ -83,10 +60,7 @@ export const EditUpload: React.FC = ({ ...(initialCrop || {}), })) - const defaultFocalPosition: FocalPosition = { - x: 50, - y: 50, - } + const defaultFocalPosition: FocalPosition = { x: 50, y: 50 } const [focalPosition, setFocalPosition] = useState(() => ({ ...defaultFocalPosition, @@ -101,13 +75,9 @@ export const EditUpload: React.FC = ({ const imageRef = useRef(undefined) const cropRef = useRef(undefined) - const heightInputRef = useRef(null) - const widthInputRef = useRef(null) - const [imageLoaded, setImageLoaded] = useState(false) const onImageLoad = (e) => { - // set the default image height/width on load setUncroppedPixelHeight(e.currentTarget.naturalHeight) setUncroppedPixelWidth(e.currentTarget.naturalWidth) setImageLoaded(true) @@ -115,18 +85,12 @@ export const EditUpload: React.FC = ({ const fineTuneCrop = ({ dimension, value }: { dimension: 'height' | 'width'; value: string }) => { const intValue = parseInt(value) - const percentage = 100 * (intValue / (dimension === 'width' ? uncroppedPixelWidth : uncroppedPixelHeight)) - if (percentage <= 0 || percentage > 100) { return null } - - setCrop((prev) => ({ - ...prev, - [dimension]: percentage, - })) + setCrop((prev) => ({ ...prev, [dimension]: percentage })) } const fineTuneFocalPosition = ({ @@ -147,8 +111,8 @@ export const EditUpload: React.FC = ({ onSave({ crop: crop ? crop : undefined, focalPoint: focalPosition, - heightInPixels: Number(heightInputRef?.current?.value ?? uncroppedPixelHeight), - widthInPixels: Number(widthInputRef?.current?.value ?? uncroppedPixelWidth), + heightInPixels: Math.round((crop.height / 100) * uncroppedPixelHeight), + widthInPixels: Math.round((crop.width / 100) * uncroppedPixelWidth), }) } closeModal(editDrawerSlug) @@ -160,145 +124,122 @@ export const EditUpload: React.FC = ({ }, []) const centerFocalPoint = () => { - const containerRect = focalWrapRef.current.getBoundingClientRect() - const boundsRect = showCrop - ? cropRef.current.getBoundingClientRect() - : imageRef.current.getBoundingClientRect() - const xCenter = - ((boundsRect.left - containerRect.left + boundsRect.width / 2) / containerRect.width) * 100 - const yCenter = - ((boundsRect.top - containerRect.top + boundsRect.height / 2) / containerRect.height) * 100 - setFocalPosition({ x: xCenter, y: yCenter }) + setFocalPosition({ x: 50, y: 50 }) } - const fileSrcToUse = fileSrc ? appendCacheTag(fileSrc, imageCacheTag) : fileSrc + const fileSrcToUse = fileSrc ? appendCacheTag(fileSrc, imageCacheTag) : undefined + + const cropWidthPx = ((crop.width / 100) * uncroppedPixelWidth).toFixed(0) + const cropHeightPx = ((crop.height / 100) * uncroppedPixelHeight).toFixed(0) return ( -
-
-

- {t('general:editing')} {fileName} -

-
- - -
-
-
-
-
- {showCrop ? ( - setCrop(c)} - onComplete={() => setCheckBounds(true)} - renderSelectionAddon={() => { - return
- }} - > + + + +
+ {/* Canvas area */} +
+
+ {showCrop ? ( + setCrop(c)} + onComplete={() => setCheckBounds(true)} + renderSelectionAddon={() => ( +
+ )} + > + {t('upload:setCropArea')} + + ) : ( {t('upload:setCropArea')} - - ) : ( - {t('upload:setFocalPoint')} - )} - {showFocalPoint && ( - - - - )} + )} + {showFocalPoint && ( + + + + )} +
-
- {(showCrop || showFocalPoint) && ( -
- {showCrop && ( -
-
-
-

{t('upload:crop')}

+ + {/* Sidebar */} + {(showCrop || showFocalPoint) && ( +
+ {showCrop && ( +
+
+ {t('upload:crop')}
+
+ + fineTuneCrop({ + dimension: 'width', + value: (e as React.ChangeEvent).target.value, + }) + } + path="cropWidth" + readOnly={!imageLoaded} + value={Number(cropWidthPx)} + /> + + fineTuneCrop({ + dimension: 'height', + value: (e as React.ChangeEvent).target.value, + }) + } + path="cropHeight" + readOnly={!imageLoaded} + value={Number(cropHeightPx)} + /> +
- - {t('upload:cropToolDescription')} - -
- fineTuneCrop({ dimension: 'width', value })} - ref={widthInputRef} - value={((crop.width / 100) * uncroppedPixelWidth).toFixed(0)} - /> - fineTuneCrop({ dimension: 'height', value })} - ref={heightInputRef} - value={((crop.height / 100) * uncroppedPixelHeight).toFixed(0)} - /> -
-
- )} - - {showFocalPoint && ( -
-
-
-

{t('upload:focalPoint')}

+ )} + + {showFocalPoint && ( +
+
+ {t('upload:focalPoint')}
+
+ %} + className={`${baseClass}__field`} + label="X" + max={100} + min={0} + onChange={(e) => + fineTuneFocalPosition({ + coordinate: 'x', + value: (e as React.ChangeEvent).target.value, + }) + } + path="focalX" + value={Math.round(focalPosition.x)} + /> + %} + className={`${baseClass}__field`} + label="Y" + max={100} + min={0} + onChange={(e) => + fineTuneFocalPosition({ + coordinate: 'y', + value: (e as React.ChangeEvent).target.value, + }) + } + path="focalY" + value={Math.round(focalPosition.y)} + /> +
- - {t('upload:focalPointDescription')} - -
- fineTuneFocalPosition({ coordinate: 'x', value })} - value={focalPosition.x.toFixed(0)} - /> - fineTuneFocalPosition({ coordinate: 'y', value })} - value={focalPosition.y.toFixed(0)} - /> -
-
- )} -
- )} -
-
+ )} +
+ )} +
+ + + + + + ) } @@ -345,52 +320,18 @@ const DraggableElement = ({ const [position, setPosition] = useState({ x: initialPosition.x, y: initialPosition.y }) const [isDragging, setIsDragging] = useState(false) const dragRef = useRef(undefined) + // Keep a ref to the latest position so global mouseup handler can read it without a stale closure + const positionRef = useRef(position) + positionRef.current = position const getCoordinates = React.useCallback( - (mouseXArg?: number, mouseYArg?: number, recenter?: boolean) => { + (mouseX: number, mouseY: number) => { const containerRect = containerRef.current.getBoundingClientRect() - const boundsRect = boundsRef.current.getBoundingClientRect() - const mouseX = mouseXArg ?? boundsRect.left - const mouseY = mouseYArg ?? boundsRect.top - - const xOutOfBounds = mouseX < boundsRect.left || mouseX > boundsRect.right - const yOutOfBounds = mouseY < boundsRect.top || mouseY > boundsRect.bottom - - let x = ((mouseX - containerRect.left) / containerRect.width) * 100 - let y = ((mouseY - containerRect.top) / containerRect.height) * 100 - const xCenter = - ((boundsRect.left - containerRect.left + boundsRect.width / 2) / containerRect.width) * 100 - const yCenter = - ((boundsRect.top - containerRect.top + boundsRect.height / 2) / containerRect.height) * 100 - if (xOutOfBounds || yOutOfBounds) { - setIsDragging(false) - if (mouseX < boundsRect.left) { - x = ((boundsRect.left - containerRect.left) / containerRect.width) * 100 - } else if (mouseX > boundsRect.right) { - x = - ((containerRect.width - (containerRect.right - boundsRect.right)) / - containerRect.width) * - 100 - } - - if (mouseY < boundsRect.top) { - y = ((boundsRect.top - containerRect.top) / containerRect.height) * 100 - } else if (mouseY > boundsRect.bottom) { - y = - ((containerRect.height - (containerRect.bottom - boundsRect.bottom)) / - containerRect.height) * - 100 - } - - if (recenter) { - x = xOutOfBounds ? xCenter : x - y = yOutOfBounds ? yCenter : y - } - } - - return { x, y } + const x = ((mouseX - containerRect.left) / containerRect.width) * 100 + const y = ((mouseY - containerRect.top) / containerRect.height) * 100 + return { x: Math.max(0, Math.min(100, x)), y: Math.max(0, Math.min(100, y)) } }, - [boundsRef, containerRef], + [containerRef], ) const handleMouseDown = (event) => { @@ -398,59 +339,62 @@ const DraggableElement = ({ setIsDragging(true) } - const handleMouseMove = (event) => { + // Attach global listeners while dragging — this ensures events fire even when + // the cursor leaves the focal wrapper area during a fast drag + React.useEffect(() => { if (!isDragging) { - return null + return } - const { x, y } = getCoordinates(event.clientX, event.clientY) - setPosition({ x, y }) - } + const handleMove = (e: MouseEvent) => { + if (!containerRef.current) { + return + } + const { x, y } = getCoordinates(e.clientX, e.clientY) + setPosition({ x, y }) + } - const onDrop = () => { - setIsDragging(false) - onDragEnd(position) - } + const handleUp = () => { + setIsDragging(false) + onDragEnd(positionRef.current) + } - React.useEffect(() => { - if (isDragging || !dragRef.current) { - return + document.addEventListener('mousemove', handleMove) + document.addEventListener('mouseup', handleUp) + + return () => { + document.removeEventListener('mousemove', handleMove) + document.removeEventListener('mouseup', handleUp) } - if (checkBounds) { - const { height, left, top, width } = dragRef.current.getBoundingClientRect() - const { x, y } = getCoordinates(left + width / 2, top + height / 2, true) - onDragEnd({ x, y }) - setPosition({ x, y }) - setCheckBounds(false) + }, [isDragging, getCoordinates, onDragEnd, containerRef]) + + // Re-check position when crop changes (the crop window may have moved) + React.useEffect(() => { + if (isDragging || !checkBounds || !dragRef.current) { return } - }, [getCoordinates, isDragging, checkBounds, setCheckBounds, position.x, position.y, onDragEnd]) + const { height, left, top, width } = dragRef.current.getBoundingClientRect() + const { x, y } = getCoordinates(left + width / 2, top + height / 2) + onDragEnd({ x, y }) + setPosition({ x, y }) + setCheckBounds(false) + }, [getCoordinates, isDragging, checkBounds, setCheckBounds, onDragEnd]) React.useEffect(() => { setPosition({ x: initialPosition.x, y: initialPosition.y }) }, [initialPosition.x, initialPosition.y]) return ( -
+
-
) } diff --git a/packages/ui/src/elements/FileDetails/DraggableFileDetails/index.tsx b/packages/ui/src/elements/FileDetails/DraggableFileDetails/index.tsx index 76aa0d5d21f..b4e2d853f40 100644 --- a/packages/ui/src/elements/FileDetails/DraggableFileDetails/index.tsx +++ b/packages/ui/src/elements/FileDetails/DraggableFileDetails/index.tsx @@ -24,7 +24,7 @@ export type DraggableFileDetailsProps = { hasImageSizes?: boolean hasMany: boolean hideRemoveFile?: boolean - imageCacheTag?: string + imageCacheTag?: false | string isSortable?: boolean removeItem?: (index: number) => void rowIndex: number diff --git a/packages/ui/src/elements/FileDetails/StaticFileDetails/index.tsx b/packages/ui/src/elements/FileDetails/StaticFileDetails/index.tsx index f53e9b3a371..ba5e1c7ff73 100644 --- a/packages/ui/src/elements/FileDetails/StaticFileDetails/index.tsx +++ b/packages/ui/src/elements/FileDetails/StaticFileDetails/index.tsx @@ -20,7 +20,7 @@ export type StaticFileDetailsProps = { handleRemove?: () => void hasImageSizes?: boolean hideRemoveFile?: boolean - imageCacheTag?: string + imageCacheTag?: false | string uploadConfig: SanitizedCollectionConfig['upload'] } diff --git a/packages/ui/src/elements/FileDetails/index.tsx b/packages/ui/src/elements/FileDetails/index.tsx index fcbdc61ef79..9e9df479c93 100644 --- a/packages/ui/src/elements/FileDetails/index.tsx +++ b/packages/ui/src/elements/FileDetails/index.tsx @@ -15,7 +15,7 @@ type SharedFileDetailsProps = { enableAdjustments?: boolean hasImageSizes?: boolean hideRemoveFile?: boolean - imageCacheTag?: string + imageCacheTag?: false | string uploadConfig: SanitizedCollectionConfig['upload'] } diff --git a/packages/ui/src/elements/FileManager/FilePreview/AudioPreview/index.css b/packages/ui/src/elements/FileManager/FilePreview/AudioPreview/index.css new file mode 100644 index 00000000000..a767319b78f --- /dev/null +++ b/packages/ui/src/elements/FileManager/FilePreview/AudioPreview/index.css @@ -0,0 +1,6 @@ +@layer payload-default { + .audio-preview { + width: 100%; + max-width: 480px; + } +} diff --git a/packages/ui/src/elements/FileManager/FilePreview/AudioPreview/index.tsx b/packages/ui/src/elements/FileManager/FilePreview/AudioPreview/index.tsx new file mode 100644 index 00000000000..7d61b5c94a9 --- /dev/null +++ b/packages/ui/src/elements/FileManager/FilePreview/AudioPreview/index.tsx @@ -0,0 +1,17 @@ +'use client' +import React from 'react' + +import './index.css' + +const baseClass = 'audio-preview' + +/** + * Built-in preview for native audio files, rendered inside the file manager when the + * uploaded file's mime type is `audio/*` and no custom file preview is provided. + */ +export const AudioPreview: React.FC<{ fileSrc: string }> = ({ fileSrc }) => { + return ( + // eslint-disable-next-line jsx-a11y/media-has-caption -- user-uploaded media, captions unknown +