@devultur/convex 1.4.1 → 1.4.3
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/README.md +6 -1
- package/dist/chunk-JZYKPLI4.js +185 -0
- package/dist/{chunk-EX3W77VY.js → chunk-YYOZ3PDH.js} +16 -3
- package/dist/component/_generated/api.d.ts +0 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +0 -1
- package/dist/component/_generated/component.js.map +1 -1
- package/dist/component/_generated/dataModel.d.ts +0 -1
- package/dist/component/_generated/dataModel.js.map +1 -1
- package/dist/component/_generated/server.d.ts +0 -1
- package/dist/component/_generated/server.js.map +1 -1
- package/dist/component/convex.config.d.ts +0 -1
- package/dist/component/convex.config.js.map +1 -1
- package/dist/component/http.d.ts +0 -1
- package/dist/component/http.js.map +1 -1
- package/dist/component/library.d.ts +0 -1
- package/dist/component/library.js.map +1 -1
- package/dist/component/lock.d.ts +0 -1
- package/dist/component/lock.js.map +1 -1
- package/dist/component/lockValidators.d.ts +0 -1
- package/dist/component/lockValidators.js.map +1 -1
- package/dist/component/mediaClient.d.ts +0 -1
- package/dist/component/mediaClient.js.map +1 -1
- package/dist/component/mediaMeta.d.ts +0 -1
- package/dist/component/mediaMeta.js.map +1 -1
- package/dist/component/metadata.d.ts +0 -1
- package/dist/component/metadata.js.map +1 -1
- package/dist/component/public.d.ts +0 -1
- package/dist/component/public.js.map +1 -1
- package/dist/component/schema.d.ts +0 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/component/uploadKeys.d.ts +0 -1
- package/dist/component/uploadKeys.js.map +1 -1
- package/dist/component/uploads.d.ts +0 -1
- package/dist/component/uploads.js.map +1 -1
- package/dist/component/workerErrors.d.ts +0 -1
- package/dist/component/workerErrors.js.map +1 -1
- package/dist/{error-labels-BfqcFh2R.d.ts → error-labels-D0Vbp-qA.d.ts} +1 -1
- package/dist/index.d.ts +12 -8
- package/dist/index.js +1 -1
- package/dist/locales/es-formal.d.ts +14 -0
- package/dist/locales/es-formal.js +64 -0
- package/dist/locales/es.d.ts +7 -4
- package/dist/locales/es.js +10 -156
- package/dist/{media-picker-labels-CiVcNUZo.d.ts → preview-labels-B7HNa7Va.d.ts} +59 -2
- package/dist/react.d.ts +24 -64
- package/dist/react.js +37 -17
- package/dist/types-DZxN6Eij.d.ts +190 -0
- package/package.json +9 -4
- package/dist/component/_generated/api.d.ts.map +0 -1
- package/dist/component/_generated/component.d.ts.map +0 -1
- package/dist/component/_generated/dataModel.d.ts.map +0 -1
- package/dist/component/_generated/server.d.ts.map +0 -1
- package/dist/component/convex.config.d.ts.map +0 -1
- package/dist/component/http.d.ts.map +0 -1
- package/dist/component/library.d.ts.map +0 -1
- package/dist/component/lock.d.ts.map +0 -1
- package/dist/component/lockValidators.d.ts.map +0 -1
- package/dist/component/mediaClient.d.ts.map +0 -1
- package/dist/component/mediaMeta.d.ts.map +0 -1
- package/dist/component/metadata.d.ts.map +0 -1
- package/dist/component/public.d.ts.map +0 -1
- package/dist/component/schema.d.ts.map +0 -1
- package/dist/component/uploadKeys.d.ts.map +0 -1
- package/dist/component/uploads.d.ts.map +0 -1
- package/dist/component/workerErrors.d.ts.map +0 -1
- package/dist/types-LrusGVDf.d.ts +0 -62
package/dist/locales/es.js
CHANGED
|
@@ -1,162 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// src/locales/es.ts
|
|
12
|
-
var LOCALE = "es";
|
|
13
|
-
var devulturErrorLabels = {
|
|
14
|
-
file_too_large: (details) => {
|
|
15
|
-
const limit = typeof details.limit === "number" ? formatBytes(details.limit, LOCALE) : null;
|
|
16
|
-
return limit ? `El archivo supera el tama\xF1o m\xE1ximo (${limit}).` : "El archivo supera el tama\xF1o m\xE1ximo.";
|
|
17
|
-
},
|
|
18
|
-
content_type_not_allowed: "Este tipo de archivo no est\xE1 permitido.",
|
|
19
|
-
content_type_mismatch: "El contenido del archivo no coincide con su tipo.",
|
|
20
|
-
content_unverified: "No se pudo verificar la subida. Vuelve a intentarlo.",
|
|
21
|
-
unsupported_content_type: "Este tipo de archivo no es compatible.",
|
|
22
|
-
media_type_mismatch: "El tipo de archivo no coincide con el tipo de contenido esperado.",
|
|
23
|
-
already_exists: "Ya existe un archivo con este nombre.",
|
|
24
|
-
write_conflict: "El archivo cambi\xF3 mientras se guardaba. Vuelve a intentarlo.",
|
|
25
|
-
upload_not_found: "No se encontr\xF3 la subida o ya venci\xF3. Vuelve a empezarla.",
|
|
26
|
-
invalid_upload_key: "Esta subida no es v\xE1lida.",
|
|
27
|
-
invalid_path: "La ruta del archivo no es v\xE1lida.",
|
|
28
|
-
path_required: "Esta subida necesita una ruta de archivo.",
|
|
29
|
-
invalid_expires_in: "El tiempo de vencimiento no es v\xE1lido.",
|
|
30
|
-
invalid_file_expires_in: "El tiempo de vencimiento del archivo no es v\xE1lido.",
|
|
31
|
-
invalid_cache_control: "La configuraci\xF3n de cach\xE9 no es v\xE1lida.",
|
|
32
|
-
invalid_limits: "Los l\xEDmites de la subida no son v\xE1lidos.",
|
|
33
|
-
invalid_prefix: "La carpeta no es v\xE1lida.",
|
|
34
|
-
invalid_visibility: "La visibilidad debe ser p\xFAblica o privada.",
|
|
35
|
-
invalid_cursor: "La p\xE1gina de resultados no es v\xE1lida. Vuelve a cargar la lista.",
|
|
36
|
-
invalid_sha256: "La suma de verificaci\xF3n del archivo no es v\xE1lida.",
|
|
37
|
-
sha256_mismatch: "El archivo se da\xF1\xF3 durante la subida. Vuelve a intentarlo.",
|
|
38
|
-
max_files_reached: "Alcanzaste el n\xFAmero m\xE1ximo de archivos para esta subida.",
|
|
39
|
-
invalid_multipart: "La solicitud de subida no es v\xE1lida.",
|
|
40
|
-
invalid_size: "El tama\xF1o del archivo no es v\xE1lido.",
|
|
41
|
-
invalid_part: "Una parte de la subida no es v\xE1lida. Vuelve a intentarlo.",
|
|
42
|
-
invalid_parts: "La subida est\xE1 incompleta. Vuelve a intentarlo.",
|
|
43
|
-
part_size_mismatch: "Una parte de la subida tiene un tama\xF1o incorrecto. Vuelve a intentarlo.",
|
|
44
|
-
part_sha256_required: "A una parte de la subida le falta la suma de verificaci\xF3n.",
|
|
45
|
-
invalid_media_metadata: (details) => {
|
|
46
|
-
if (details.field === "title") return "El t\xEDtulo no puede tener m\xE1s de 200 caracteres.";
|
|
47
|
-
if (details.field === "alt") return "El texto alternativo no puede tener m\xE1s de 1000 caracteres.";
|
|
48
|
-
if (details.field === "tags") return "Usa como m\xE1ximo 20 etiquetas, de hasta 50 caracteres cada una.";
|
|
49
|
-
return "Los datos del archivo no son v\xE1lidos.";
|
|
50
|
-
},
|
|
51
|
-
expired: "Este archivo ya venci\xF3.",
|
|
52
|
-
invalid_key: "La referencia del archivo no es v\xE1lida.",
|
|
53
|
-
invalid_max_uses: "El n\xFAmero de usos no es v\xE1lido.",
|
|
54
|
-
link_exists: "Este enlace de descarga ya existe.",
|
|
55
|
-
link_not_found: "Este enlace de descarga no existe.",
|
|
56
|
-
link_expired: "Este enlace de descarga ya venci\xF3.",
|
|
57
|
-
link_used: "Este enlace de descarga ya se us\xF3.",
|
|
58
|
-
not_configured: "Esta funci\xF3n no est\xE1 configurada.",
|
|
59
|
-
retention_active: (details) => {
|
|
60
|
-
if (details.hold === true) return "Este archivo tiene una retenci\xF3n legal y no se puede modificar ni eliminar.";
|
|
61
|
-
const until = formatDate(details.until, LOCALE);
|
|
62
|
-
return until ? `Este archivo est\xE1 protegido hasta el ${until} y no se puede modificar ni eliminar antes de esa fecha.` : "Este archivo est\xE1 protegido y no se puede modificar ni eliminar.";
|
|
63
|
-
},
|
|
64
|
-
lock_conflict: "La protecci\xF3n del archivo cambi\xF3 mientras tanto. Vuelve a intentarlo.",
|
|
65
|
-
compliance_extend_only: "La protecci\xF3n de este archivo solo se puede extender.",
|
|
66
|
-
lock_privilege_required: "No tienes permiso para acortar ni quitar la protecci\xF3n de este archivo.",
|
|
67
|
-
lock_record_unreadable: "No se pudo leer la protecci\xF3n del archivo.",
|
|
68
|
-
lock_below_minimum: "Esta subida requiere una protecci\xF3n m\xE1s estricta.",
|
|
69
|
-
invalid_lock: "La configuraci\xF3n de protecci\xF3n no es v\xE1lida.",
|
|
70
|
-
invalid_hold: "La configuraci\xF3n de retenci\xF3n legal no es v\xE1lida.",
|
|
71
|
-
reserved_key: "Este nombre de archivo est\xE1 reservado.",
|
|
72
|
-
keys_bucket_missing: "En este momento no se pueden guardar archivos de forma segura.",
|
|
73
|
-
encryption_key_missing: "Este archivo ya no se puede leer. Vuelve a subirlo.",
|
|
74
|
-
unauthorized: "No tienes autorizaci\xF3n para hacer esto.",
|
|
75
|
-
session_mismatch: "Tu sesi\xF3n cambi\xF3. Vuelve a cargar la p\xE1gina.",
|
|
76
|
-
token_rejected: "Se deneg\xF3 el acceso.",
|
|
77
|
-
reserved_user_id: "Este identificador de usuario est\xE1 reservado.",
|
|
78
|
-
invalid_scopes: "Los permisos solicitados no son v\xE1lidos.",
|
|
79
|
-
user_mismatch: "Solo puedes ver y cambiar tu propio progreso.",
|
|
80
|
-
transcode_not_configured: "El procesamiento de video no est\xE1 configurado.",
|
|
81
|
-
transcode_runner_unavailable: "El procesamiento de video est\xE1 ocupado en este momento. Vuelve a intentarlo m\xE1s tarde.",
|
|
82
|
-
transcode_launch_failed: "No se pudo procesar el video.",
|
|
83
|
-
original_not_retained: "El video original ya no est\xE1 disponible, as\xED que no se puede volver a procesar. Vuelve a subirlo.",
|
|
84
|
-
locale_not_allowed: "Los subt\xEDtulos no est\xE1n disponibles en este idioma.",
|
|
85
|
-
captions_provider_rate_limited: "El servicio de subt\xEDtulos est\xE1 ocupado en este momento. Vuelve a intentarlo m\xE1s tarde.",
|
|
86
|
-
captions_provider_error: "No se pudieron generar los subt\xEDtulos.",
|
|
87
|
-
captions_failed: "No se pudieron generar los subt\xEDtulos.",
|
|
88
|
-
webhook_secret_missing: "El procesamiento de video no est\xE1 configurado.",
|
|
89
|
-
worker_auth_secret_missing: "El servicio de medios no est\xE1 configurado.",
|
|
90
|
-
worker_error: "El servicio de medios no pudo completar la solicitud.",
|
|
91
|
-
http_error: "No se pudo cargar el archivo.",
|
|
92
|
-
too_large: "El archivo es demasiado grande para la vista previa.",
|
|
93
|
-
unsupported_type: "Este tipo de archivo no tiene vista previa.",
|
|
94
|
-
type_mismatch: "El contenido del archivo no coincide con su tipo.",
|
|
95
|
-
token_unavailable: "No se pudo autorizar el acceso a este archivo. Vuelve a intentarlo.",
|
|
96
|
-
capability_unavailable: "Esta aplicaci\xF3n no puede hacer eso aqu\xED."
|
|
97
|
-
};
|
|
98
|
-
var KIND_TEXT = {
|
|
99
|
-
image: "Imagen",
|
|
100
|
-
video: "Video",
|
|
101
|
-
pdf: "PDF",
|
|
102
|
-
audio: "Audio",
|
|
103
|
-
text: "Texto",
|
|
104
|
-
file: "Archivo"
|
|
105
|
-
};
|
|
106
|
-
var attachmentLabels = {
|
|
107
|
-
locale: LOCALE,
|
|
108
|
-
size: formatFileSize,
|
|
109
|
-
pages: (pageCount) => pageCount === 1 ? "1 p\xE1gina" : `${pageCount.toLocaleString(LOCALE)} p\xE1ginas`,
|
|
110
|
-
duration: formatDuration,
|
|
111
|
-
kind: (kind) => KIND_TEXT[kind],
|
|
112
|
-
download: "Descargar",
|
|
113
|
-
open: "Abrir vista previa",
|
|
114
|
-
untitled: "Archivo sin t\xEDtulo"
|
|
115
|
-
};
|
|
116
|
-
var mediaLibraryLabels = {
|
|
117
|
-
search: "Buscar archivos",
|
|
118
|
-
searchPlaceholder: "Busca por t\xEDtulo o nombre de archivo",
|
|
119
|
-
typeFilter: "Tipo",
|
|
120
|
-
allTypes: "Todos los tipos",
|
|
121
|
-
types: { image: "Im\xE1genes", video: "Videos", file: "Archivos" },
|
|
122
|
-
results: "Archivos",
|
|
123
|
-
loading: "Cargando archivos\u2026",
|
|
124
|
-
empty: "Todav\xEDa no hay archivos.",
|
|
125
|
-
noResults: (search) => `Nada coincide con \xAB${search}\xBB.`,
|
|
126
|
-
loadMore: "Cargar m\xE1s",
|
|
127
|
-
loadingMore: "Cargando\u2026",
|
|
128
|
-
error: (error) => describeDevulturError(error, devulturErrorLabels) ?? "No se pudieron cargar los archivos.",
|
|
129
|
-
retry: "Reintentar",
|
|
130
|
-
size: (bytes) => formatFileSize(bytes, LOCALE)
|
|
131
|
-
};
|
|
132
|
-
var mediaPickerLabels = {
|
|
133
|
-
upload: (multiple) => multiple ? "Subir archivos" : "Subir un archivo",
|
|
134
|
-
dropHint: (multiple) => multiple ? "o suelta los archivos aqu\xED" : "o suelta un archivo aqu\xED",
|
|
135
|
-
uploads: "Subidas",
|
|
136
|
-
progress: (filename) => `Subiendo ${filename}`,
|
|
137
|
-
percent: (percent) => `${percent} %`,
|
|
138
|
-
uploading: (filename) => `Subiendo ${filename}.`,
|
|
139
|
-
uploaded: (filename) => `${filename} se subi\xF3 y qued\xF3 seleccionado.`,
|
|
140
|
-
cancel: "Cancelar",
|
|
141
|
-
cancelUpload: (filename) => `Cancelar la subida de ${filename}`,
|
|
142
|
-
cancelled: (filename) => `Se cancel\xF3 la subida de ${filename}.`,
|
|
143
|
-
notAccepted: (filename) => `${filename} no es un tipo de archivo que se pueda elegir aqu\xED.`,
|
|
144
|
-
uploadError: (error) => describeDevulturError(error, devulturErrorLabels) ?? "La subida fall\xF3. Vuelve a intentarlo.",
|
|
145
|
-
retry: "Reintentar",
|
|
146
|
-
dismiss: "Descartar",
|
|
147
|
-
selection: "Archivos seleccionados",
|
|
148
|
-
empty: "No hay nada seleccionado.",
|
|
149
|
-
remove: "Quitar",
|
|
150
|
-
removeItem: (name) => `Quitar ${name}`,
|
|
151
|
-
clear: "Limpiar",
|
|
152
|
-
replace: "Reemplazar",
|
|
153
|
-
selected: (name) => `${name} seleccionado.`,
|
|
154
|
-
removed: (name) => `${name} se quit\xF3.`,
|
|
155
|
-
cleared: "Se limpi\xF3 la selecci\xF3n."
|
|
156
|
-
};
|
|
2
|
+
attachmentLabels,
|
|
3
|
+
devulturErrorLabels,
|
|
4
|
+
mediaLibraryLabels,
|
|
5
|
+
mediaPickerLabels,
|
|
6
|
+
previewLabels
|
|
7
|
+
} from "../chunk-JZYKPLI4.js";
|
|
8
|
+
import "../chunk-QBHIZBOQ.js";
|
|
9
|
+
import "../chunk-YYOZ3PDH.js";
|
|
157
10
|
export {
|
|
158
11
|
attachmentLabels,
|
|
159
12
|
devulturErrorLabels,
|
|
160
13
|
mediaLibraryLabels,
|
|
161
|
-
mediaPickerLabels
|
|
14
|
+
mediaPickerLabels,
|
|
15
|
+
previewLabels
|
|
162
16
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as MediaRecord } from './types-
|
|
1
|
+
import { M as MediaRecord } from './types-DZxN6Eij.js';
|
|
2
2
|
|
|
3
3
|
/** What an attachment is, for its icon and type label. */
|
|
4
4
|
type AttachmentKind = "image" | "video" | "pdf" | "audio" | "text" | "file";
|
|
@@ -111,4 +111,61 @@ interface MediaPickerLabels {
|
|
|
111
111
|
}
|
|
112
112
|
declare const defaultMediaPickerLabels: MediaPickerLabels;
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
/** Why a media couldn't be fetched or shown. Stable: match on it, not on `message`. */
|
|
115
|
+
type MediaFetchErrorCode =
|
|
116
|
+
/** The delivery answered with a non-2xx status (`status` has it), or never answered (a network failure: no `status`). */
|
|
117
|
+
"http_error"
|
|
118
|
+
/** `Content-Length`, or the streamed body, exceeds `maxBytes`. */
|
|
119
|
+
| "too_large"
|
|
120
|
+
/** The expected content type isn't one that can be previewed inline. */
|
|
121
|
+
| "unsupported_type"
|
|
122
|
+
/** The response's `Content-Type` doesn't agree with the expected one. */
|
|
123
|
+
| "type_mismatch"
|
|
124
|
+
/** No viewer token for private media: its issuance failed (`useDevultur().tokenError` has why) or was refused. */
|
|
125
|
+
| "token_unavailable"
|
|
126
|
+
/** The delivery refused the token for this browser session, also after a re-issue (video playback). */
|
|
127
|
+
| "session_mismatch"
|
|
128
|
+
/** A PDF has more pages than `maxPages`: only the first ones are shown (`details: { shown, total }`). */
|
|
129
|
+
| "page_cap"
|
|
130
|
+
/** The bytes arrived but couldn't be shown: pdf.js can't open the PDF, or the video can't be played. */
|
|
131
|
+
| "render_failed";
|
|
132
|
+
/** `ErrorOptions` plus the code's `details`. */
|
|
133
|
+
interface MediaFetchErrorOptions extends ErrorOptions {
|
|
134
|
+
details?: Readonly<Record<string, unknown>>;
|
|
135
|
+
}
|
|
136
|
+
declare class MediaFetchError extends Error {
|
|
137
|
+
readonly code: MediaFetchErrorCode;
|
|
138
|
+
/** HTTP status, for `http_error` when the delivery answered. */
|
|
139
|
+
readonly status?: number;
|
|
140
|
+
/** The code's extra fields, e.g. `page_cap`'s `{ shown, total }`. */
|
|
141
|
+
readonly details?: Readonly<Record<string, unknown>>;
|
|
142
|
+
constructor(code: MediaFetchErrorCode, message: string, status?: number, options?: MediaFetchErrorOptions);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Every string `<Preview>`, `<PdfThumbnail>` and their PDF pages show or announce. Pass any subset as `labels` on a
|
|
147
|
+
* component or on `PdfPreviewProvider`; the component's wins over the provider's, which wins over the English defaults.
|
|
148
|
+
*/
|
|
149
|
+
interface PreviewLabels {
|
|
150
|
+
/** Accessible name of a pdf.js document: its title and page count. */
|
|
151
|
+
document: (title: string, pageCount: number) => string;
|
|
152
|
+
/** Accessible name of one pdf.js page. */
|
|
153
|
+
page: (page: number, pageCount: number) => string;
|
|
154
|
+
/** Announced (visually hidden) while a preview loads, when no `loading` is passed. */
|
|
155
|
+
loading: string;
|
|
156
|
+
/** Note after the last rendered page when a PDF has more than `maxPages`; `fallback` follows it. */
|
|
157
|
+
pageCap: (shown: number, total: number) => string;
|
|
158
|
+
/** `title` of the default fallback's download link, for why it's shown (see `<Preview>`'s `fallback`). */
|
|
159
|
+
error: (code: MediaFetchErrorCode) => string;
|
|
160
|
+
/** Accessible name of a `<PdfThumbnail>`, from its title. */
|
|
161
|
+
thumbnail: (title: string) => string;
|
|
162
|
+
/** Name of a PDF (pdf.js document, `<iframe>` title, thumbnail) with no `title` and no filename. */
|
|
163
|
+
untitledPdf: string;
|
|
164
|
+
/** Name of an image or audio preview with no `title` and no filename. */
|
|
165
|
+
untitledMedia: string;
|
|
166
|
+
/** Text of the default fallback's download link when the media has no filename. */
|
|
167
|
+
download: string;
|
|
168
|
+
}
|
|
169
|
+
declare const defaultPreviewLabels: PreviewLabels;
|
|
170
|
+
|
|
171
|
+
export { type AttachmentLabels as A, type MediaLibraryLabels as M, type PreviewLabels as P, type MediaPickerLabels as a, MediaFetchError as b, type AttachmentKind as c, type MediaFetchErrorCode as d, defaultAttachmentLabels as e, defaultMediaLibraryLabels as f, defaultMediaPickerLabels as g, defaultPreviewLabels as h, formatDuration as i, formatFileSize as j };
|
package/dist/react.d.ts
CHANGED
|
@@ -3,34 +3,13 @@ import { DevulturMedia, MediaUrlOptions, Visibility, ProcessingPhase, FailureRea
|
|
|
3
3
|
import { BakeOutputFormat, MediaUploadState, MediaUploadError, UploadProgress } from '@devultur/react';
|
|
4
4
|
export { MediaUploadError, MediaUploadState, UploadProgress } from '@devultur/react';
|
|
5
5
|
import { FunctionReference } from 'convex/server';
|
|
6
|
+
import { A as AttachmentLabels, M as MediaLibraryLabels, P as PreviewLabels, a as MediaPickerLabels, b as MediaFetchError } from './preview-labels-B7HNa7Va.js';
|
|
7
|
+
export { c as AttachmentKind, d as MediaFetchErrorCode, e as defaultAttachmentLabels, f as defaultMediaLibraryLabels, g as defaultMediaPickerLabels, h as defaultPreviewLabels, i as formatDuration, j as formatFileSize } from './preview-labels-B7HNa7Va.js';
|
|
6
8
|
import { Value } from 'convex/values';
|
|
7
|
-
import {
|
|
8
|
-
export { b as AttachmentKind, d as defaultAttachmentLabels, c as defaultMediaLibraryLabels, e as defaultMediaPickerLabels, f as formatDuration, g as formatFileSize } from './media-picker-labels-CiVcNUZo.js';
|
|
9
|
-
import { M as MediaRecord } from './types-LrusGVDf.js';
|
|
9
|
+
import { M as MediaRecord } from './types-DZxN6Eij.js';
|
|
10
10
|
import { P as PdfjsLoader } from './pdf-render-BwJGagvz.js';
|
|
11
11
|
export { a as PdfjsModule } from './pdf-render-BwJGagvz.js';
|
|
12
12
|
|
|
13
|
-
/** Why a media fetch was refused. Stable: match on it, not on `message`. */
|
|
14
|
-
type MediaFetchErrorCode =
|
|
15
|
-
/** The delivery answered with a non-2xx status (`status` has it). */
|
|
16
|
-
"http_error"
|
|
17
|
-
/** `Content-Length`, or the streamed body, exceeds `maxBytes`. */
|
|
18
|
-
| "too_large"
|
|
19
|
-
/** The expected content type isn't one that can be previewed inline. */
|
|
20
|
-
| "unsupported_type"
|
|
21
|
-
/** The response's `Content-Type` doesn't agree with the expected one. */
|
|
22
|
-
| "type_mismatch"
|
|
23
|
-
/** No viewer token for private media: its issuance failed (`useDevultur().tokenError` has why) or was refused. */
|
|
24
|
-
| "token_unavailable"
|
|
25
|
-
/** The delivery refused the token for this browser session, also after a re-issue (video playback). */
|
|
26
|
-
| "session_mismatch";
|
|
27
|
-
declare class MediaFetchError extends Error {
|
|
28
|
-
readonly code: MediaFetchErrorCode;
|
|
29
|
-
/** HTTP status, for `http_error`. */
|
|
30
|
-
readonly status?: number;
|
|
31
|
-
constructor(code: MediaFetchErrorCode, message: string, status?: number, options?: ErrorOptions);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
13
|
/** What a viewer token action returns: the token with its lifetime, or the bare token (default lifetime). */
|
|
35
14
|
type ViewerTokenResult = {
|
|
36
15
|
token: string;
|
|
@@ -46,8 +25,12 @@ type TokenStatus = "idle" | "loading" | "ready" | "error";
|
|
|
46
25
|
|
|
47
26
|
/** Transform/delivery options for media URLs (without `token`, which the context injects). */
|
|
48
27
|
type MediaRenderOptions = Omit<MediaUrlOptions, "token">;
|
|
28
|
+
/**
|
|
29
|
+
* The viewer token action: the component's `issueViewerToken` (as `defineDevulturFunctions` or `exposeApi` export it,
|
|
30
|
+
* where `sessionSecret` is optional) or an app's own, which may require it. The providers always send it.
|
|
31
|
+
*/
|
|
49
32
|
type ViewerTokenAction = FunctionReference<"action", "public", {
|
|
50
|
-
sessionSecret
|
|
33
|
+
sessionSecret?: string;
|
|
51
34
|
}>;
|
|
52
35
|
interface MediaSession {
|
|
53
36
|
token: string | null;
|
|
@@ -311,32 +294,6 @@ interface MediaObjectUrl {
|
|
|
311
294
|
*/
|
|
312
295
|
declare function useMediaObjectUrl(media: DevulturMedia | null | undefined, options?: UseMediaObjectUrlOptions): MediaObjectUrl;
|
|
313
296
|
|
|
314
|
-
/**
|
|
315
|
-
* Every string `<Preview>`, `<PdfThumbnail>` and their PDF pages show or announce. Pass any subset as `labels` on a
|
|
316
|
-
* component or on `PdfPreviewProvider`; the component's wins over the provider's, which wins over the English defaults.
|
|
317
|
-
*/
|
|
318
|
-
interface PreviewLabels {
|
|
319
|
-
/** Accessible name of a pdf.js document: its title and page count. */
|
|
320
|
-
document: (title: string, pageCount: number) => string;
|
|
321
|
-
/** Accessible name of one pdf.js page. */
|
|
322
|
-
page: (page: number, pageCount: number) => string;
|
|
323
|
-
/** Announced (visually hidden) while a preview loads, when no `loading` is passed. */
|
|
324
|
-
loading: string;
|
|
325
|
-
/** Note after the last rendered page when a PDF has more than `maxPages`; `fallback` follows it. */
|
|
326
|
-
pageCap: (shown: number, total: number) => string;
|
|
327
|
-
/** `title` of the default fallback's download link when a fetch was refused or the type can't be previewed. */
|
|
328
|
-
error: (code: MediaFetchErrorCode) => string;
|
|
329
|
-
/** Accessible name of a `<PdfThumbnail>`, from its title. */
|
|
330
|
-
thumbnail: (title: string) => string;
|
|
331
|
-
/** Name of a PDF (pdf.js document, `<iframe>` title, thumbnail) with no `title` and no filename. */
|
|
332
|
-
untitledPdf: string;
|
|
333
|
-
/** Name of an image or audio preview with no `title` and no filename. */
|
|
334
|
-
untitledMedia: string;
|
|
335
|
-
/** Text of the default fallback's download link when the media has no filename. */
|
|
336
|
-
download: string;
|
|
337
|
-
}
|
|
338
|
-
declare const defaultPreviewLabels: PreviewLabels;
|
|
339
|
-
|
|
340
297
|
interface PdfPreviewConfig {
|
|
341
298
|
/**
|
|
342
299
|
* Imports pdf.js. Without it, PDFs render in an `<iframe>` (the browser's own viewer) and `<PdfThumbnail>` renders
|
|
@@ -489,12 +446,13 @@ type MediaPickerProps = CommonProps & (SingleValueProps | MultipleValueProps);
|
|
|
489
446
|
* @example
|
|
490
447
|
* <MediaPicker accept={["image/*"]} value={cover} onChange={setCover} />
|
|
491
448
|
*/
|
|
492
|
-
declare function
|
|
493
|
-
declare
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
449
|
+
declare function MediaPickerRoot(props: MediaPickerProps): React.JSX.Element;
|
|
450
|
+
declare const MediaPicker: typeof MediaPickerRoot & {
|
|
451
|
+
displayName: string;
|
|
452
|
+
Upload: typeof MediaPickerUpload;
|
|
453
|
+
Library: typeof MediaPickerLibrary;
|
|
454
|
+
Selection: typeof MediaPickerSelection;
|
|
455
|
+
};
|
|
498
456
|
|
|
499
457
|
/** A file's name and type, or a record's filename and content type. */
|
|
500
458
|
interface Candidate {
|
|
@@ -547,13 +505,15 @@ interface PreviewProps {
|
|
|
547
505
|
/** Size cap for text previews. Default 1 MiB. */
|
|
548
506
|
maxTextBytes?: number;
|
|
549
507
|
/**
|
|
550
|
-
* Shown for types that don't preview inline
|
|
551
|
-
* As a function it receives why
|
|
552
|
-
* `
|
|
553
|
-
*
|
|
554
|
-
* (a
|
|
508
|
+
* Shown for types that don't preview inline, when the fetch or render fails, and after the `maxPages` note.
|
|
509
|
+
* Default: a `<DownloadLink>`. As a function it receives why, always a `MediaFetchError` (never `null`: it's only
|
|
510
|
+
* called with a cause): `http_error` when the delivery refused the fetch (`status`) or never answered (a network
|
|
511
|
+
* failure, no `status`), `too_large`, `type_mismatch`, `token_unavailable` (no viewer token, nothing fetched),
|
|
512
|
+
* `session_mismatch` (a video's session was refused), `unsupported_type` (the type doesn't preview inline, nothing
|
|
513
|
+
* fetched), `render_failed` (pdf.js can't open the PDF, or the video can't be played) or `page_cap` (the link after
|
|
514
|
+
* the `maxPages` note, with `details: { shown, total }`).
|
|
555
515
|
*/
|
|
556
|
-
fallback?: React.ReactNode | ((error: MediaFetchError
|
|
516
|
+
fallback?: React.ReactNode | ((error: MediaFetchError) => React.ReactNode);
|
|
557
517
|
/** Shown while a file loads. Default: `labels.loading`, visually hidden, in a `role="status"`. `null` → nothing. */
|
|
558
518
|
loading?: React.ReactNode;
|
|
559
519
|
/** Accessible name of the preview (`alt`, `title`, `aria-label`). Default: the filename (text: none). */
|
|
@@ -869,4 +829,4 @@ interface UseMediaUploadReturn {
|
|
|
869
829
|
*/
|
|
870
830
|
declare function useMediaUpload(options?: UseMediaUploadOptions): UseMediaUploadReturn;
|
|
871
831
|
|
|
872
|
-
export { AttachmentCard, type AttachmentCardProps, AttachmentLabels, type CaptionTrack, CropUpload, type CropUploadLabels, type CropUploadProps, type CropUploadRenderProps, type DevulturApi, type DevulturCapability, DevulturCapabilityError, DevulturProvider, DevulturViewerProvider, DocumentLink, type DocumentLinkProps, DownloadLink, Image, type ImageProps, MediaFetchError,
|
|
832
|
+
export { AttachmentCard, type AttachmentCardProps, AttachmentLabels, type CaptionTrack, CropUpload, type CropUploadLabels, type CropUploadProps, type CropUploadRenderProps, type DevulturApi, type DevulturCapability, DevulturCapabilityError, DevulturProvider, DevulturViewerProvider, DocumentLink, type DocumentLinkProps, DownloadLink, Image, type ImageProps, MediaFetchError, MediaLibrary, type MediaLibraryItemState, MediaLibraryLabels, type MediaLibraryPart, type MediaLibraryProps, type MediaLibraryState, type MediaLibraryStatus, type MediaObjectUrl, MediaPicker, MediaPickerLabels, type MediaPickerLibraryProps, type MediaPickerProps, type MediaPickerSelectionProps, type MediaPickerState, type MediaPickerUpload$1 as MediaPickerUpload, type MediaPickerUploadProps, type MediaPickerUploads, type PdfPreviewConfig, PdfPreviewProvider, PdfThumbnail, type PdfThumbnailProps, PdfjsLoader, Preview, type PreviewKind, PreviewLabels, type PreviewProps, type TokenStatus, type UploadedMedia, type UseMediaLibraryOptions, type UseMediaObjectUrlOptions, type UseMediaUploadOptions, type UseMediaUploadReturn, type VideoProps, type VideoState, type ViewerTokenArgs, type ViewerTokenResult, matchesAccept, useDevultur, useDevulturApi, useDevulturMedia, useDevulturProgress, useMediaLibrary, useMediaObjectUrl, useMediaPicker, useMediaUpload, useMediaUrl, useVideoProps, useVideoState };
|
package/dist/react.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "./chunk-QBHIZBOQ.js";
|
|
24
24
|
import {
|
|
25
25
|
describeDevulturError
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-YYOZ3PDH.js";
|
|
27
27
|
|
|
28
28
|
// src/react.tsx
|
|
29
29
|
import React22 from "react";
|
|
@@ -71,15 +71,28 @@ async function isSessionMismatch(response) {
|
|
|
71
71
|
// src/media-fetch.ts
|
|
72
72
|
var MediaFetchError = class extends Error {
|
|
73
73
|
code;
|
|
74
|
-
/** HTTP status, for `http_error
|
|
74
|
+
/** HTTP status, for `http_error` when the delivery answered. */
|
|
75
75
|
status;
|
|
76
|
+
/** The code's extra fields, e.g. `page_cap`'s `{ shown, total }`. */
|
|
77
|
+
details;
|
|
76
78
|
constructor(code, message, status, options) {
|
|
77
79
|
super(message, options);
|
|
78
80
|
this.name = "MediaFetchError";
|
|
79
81
|
this.code = code;
|
|
80
82
|
this.status = status;
|
|
83
|
+
this.details = options?.details;
|
|
81
84
|
}
|
|
82
85
|
};
|
|
86
|
+
function networkError(cause) {
|
|
87
|
+
return new MediaFetchError("http_error", "Media fetch failed: no response", void 0, { cause });
|
|
88
|
+
}
|
|
89
|
+
function pageCapError(shown, total) {
|
|
90
|
+
const message = `Showing the first ${shown} of ${total} pages`;
|
|
91
|
+
return new MediaFetchError("page_cap", message, void 0, { details: { shown, total } });
|
|
92
|
+
}
|
|
93
|
+
function renderFailedError(cause) {
|
|
94
|
+
return new MediaFetchError("render_failed", "The media couldn't be rendered", void 0, { cause });
|
|
95
|
+
}
|
|
83
96
|
function tokenUnavailableError(cause) {
|
|
84
97
|
return new MediaFetchError("token_unavailable", "No viewer token: its issuance failed", void 0, { cause });
|
|
85
98
|
}
|
|
@@ -753,7 +766,9 @@ var ERROR_TEXT = {
|
|
|
753
766
|
unsupported_type: "This file type can't be previewed.",
|
|
754
767
|
type_mismatch: "The file's content doesn't match its type.",
|
|
755
768
|
token_unavailable: "Access to this file couldn't be granted. Try again.",
|
|
756
|
-
session_mismatch: "Your session changed. Reload the page."
|
|
769
|
+
session_mismatch: "Your session changed. Reload the page.",
|
|
770
|
+
page_cap: "Download the file to see every page.",
|
|
771
|
+
render_failed: "The file couldn't be displayed."
|
|
757
772
|
};
|
|
758
773
|
var defaultPreviewLabels = {
|
|
759
774
|
document: (title, pageCount) => `${title}, ${pageCount === 1 ? "1 page" : `${pageCount} pages`}`,
|
|
@@ -778,7 +793,7 @@ function mergePreviewLabels(...sources) {
|
|
|
778
793
|
|
|
779
794
|
// src/pdf-context.tsx
|
|
780
795
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
781
|
-
var PdfPreviewContext = React7.createContext({});
|
|
796
|
+
var PdfPreviewContext = /* @__PURE__ */ React7.createContext({});
|
|
782
797
|
function PdfPreviewProvider({
|
|
783
798
|
pdfjs,
|
|
784
799
|
workerSrc,
|
|
@@ -961,7 +976,7 @@ function PdfCanvasDocument(props) {
|
|
|
961
976
|
React9.useLayoutEffect(() => {
|
|
962
977
|
if (document2) setWidth(containerRef.current?.clientWidth ?? 0);
|
|
963
978
|
}, [document2]);
|
|
964
|
-
if (error) return /* @__PURE__ */ jsx6(Fragment2, { children: renderFallback(error) });
|
|
979
|
+
if (error) return /* @__PURE__ */ jsx6(Fragment2, { children: renderFallback(renderFailedError(error)) });
|
|
965
980
|
if (!document2) return /* @__PURE__ */ jsx6(Fragment2, { children: loading });
|
|
966
981
|
const shownPageCount = Math.min(document2.numPages, Math.max(1, maxPages));
|
|
967
982
|
const isTruncated = shownPageCount < document2.numPages;
|
|
@@ -987,7 +1002,7 @@ function PdfCanvasDocument(props) {
|
|
|
987
1002
|
isTruncated && /* @__PURE__ */ jsxs3("p", { children: [
|
|
988
1003
|
labels.pageCap(shownPageCount, document2.numPages),
|
|
989
1004
|
" ",
|
|
990
|
-
renderFallback(
|
|
1005
|
+
renderFallback(pageCapError(shownPageCount, document2.numPages))
|
|
991
1006
|
] })
|
|
992
1007
|
]
|
|
993
1008
|
}
|
|
@@ -1511,7 +1526,7 @@ function recordMatchesAccept(record, accept) {
|
|
|
1511
1526
|
|
|
1512
1527
|
// src/media-picker-context.ts
|
|
1513
1528
|
import React15 from "react";
|
|
1514
|
-
var MediaPickerContext = React15.createContext(null);
|
|
1529
|
+
var MediaPickerContext = /* @__PURE__ */ React15.createContext(null);
|
|
1515
1530
|
function useMediaPicker() {
|
|
1516
1531
|
const picker = React15.use(MediaPickerContext);
|
|
1517
1532
|
if (!picker) throw new Error("useMediaPicker must be used within <MediaPicker>");
|
|
@@ -1591,13 +1606,15 @@ import React17 from "react";
|
|
|
1591
1606
|
import { VideoPlayer } from "@devultur/react";
|
|
1592
1607
|
import { Fragment as Fragment6, jsx as jsx11 } from "react/jsx-runtime";
|
|
1593
1608
|
var UNAUTHORIZED = 401;
|
|
1609
|
+
var HLS_NETWORK_FAILURE = /Load(Error|TimeOut)$/;
|
|
1594
1610
|
function fetchErrorOf(error) {
|
|
1595
1611
|
if (error.status === UNAUTHORIZED && error.code === "session_mismatch") {
|
|
1596
1612
|
return new MediaFetchError("session_mismatch", "The delivery refused this session's token", UNAUTHORIZED);
|
|
1597
1613
|
}
|
|
1598
1614
|
if (error.status === UNAUTHORIZED) return tokenUnavailableError();
|
|
1599
1615
|
if (error.status) return new MediaFetchError("http_error", `Video fetch failed: ${error.status}`, error.status);
|
|
1600
|
-
return
|
|
1616
|
+
if (HLS_NETWORK_FAILURE.test(error.details)) return networkError(error);
|
|
1617
|
+
return renderFailedError(error);
|
|
1601
1618
|
}
|
|
1602
1619
|
function VideoPreview({ media, renderFallback, className }) {
|
|
1603
1620
|
const { tokenStatus, tokenError, reissueToken } = useDevultur();
|
|
@@ -1633,7 +1650,7 @@ function Preview({ media, contentType, fallback, loading, labels, ...viewProps }
|
|
|
1633
1650
|
const text = usePreviewLabels(labels);
|
|
1634
1651
|
if (!media) return null;
|
|
1635
1652
|
const renderFallback = (error) => {
|
|
1636
|
-
const fetchError = error instanceof MediaFetchError ? error :
|
|
1653
|
+
const fetchError = error instanceof MediaFetchError ? error : networkError(error);
|
|
1637
1654
|
if (typeof fallback === "function") return fallback(fetchError);
|
|
1638
1655
|
if (fallback !== void 0) return fallback;
|
|
1639
1656
|
return /* @__PURE__ */ jsx12(DefaultFallback, { media, error: fetchError, labels: text });
|
|
@@ -1660,7 +1677,7 @@ function Preview({ media, contentType, fallback, loading, labels, ...viewProps }
|
|
|
1660
1677
|
}
|
|
1661
1678
|
var unsupportedType = (contentType) => new MediaFetchError("unsupported_type", `Can't preview ${contentType ?? "an unknown type"} inline`);
|
|
1662
1679
|
function DefaultFallback({ media, error, labels }) {
|
|
1663
|
-
return /* @__PURE__ */ jsx12(DownloadLink, { media, title:
|
|
1680
|
+
return /* @__PURE__ */ jsx12(DownloadLink, { media, title: labels.error(error.code), children: media.filename ?? labels.download });
|
|
1664
1681
|
}
|
|
1665
1682
|
function LoadingStatus({ text }) {
|
|
1666
1683
|
return /* @__PURE__ */ jsx12("span", { role: "status", style: VISUALLY_HIDDEN, children: text });
|
|
@@ -1952,7 +1969,7 @@ function emit(props, next) {
|
|
|
1952
1969
|
props.onChange(next[0] ?? null);
|
|
1953
1970
|
}
|
|
1954
1971
|
var isSame = (a, b) => a.id === b.id;
|
|
1955
|
-
function
|
|
1972
|
+
function MediaPickerRoot(props) {
|
|
1956
1973
|
const isMultiple = props.multiple ?? false;
|
|
1957
1974
|
const labels = React21.useMemo(() => mergeMediaPickerLabels(props.labels), [props.labels]);
|
|
1958
1975
|
const accept = uploadAcceptOf(props.accept, props.type);
|
|
@@ -2072,15 +2089,18 @@ function MediaPicker(props) {
|
|
|
2072
2089
|
/* @__PURE__ */ jsx15("div", { role: "status", "aria-live": "polite", style: VISUALLY_HIDDEN, children: announcement })
|
|
2073
2090
|
] }) });
|
|
2074
2091
|
}
|
|
2075
|
-
MediaPicker
|
|
2076
|
-
MediaPicker
|
|
2077
|
-
|
|
2092
|
+
var MediaPicker = /* @__PURE__ */ Object.assign(MediaPickerRoot, {
|
|
2093
|
+
displayName: "MediaPicker",
|
|
2094
|
+
Upload: MediaPickerUpload,
|
|
2095
|
+
Library: MediaPickerLibrary,
|
|
2096
|
+
Selection: MediaPickerSelection
|
|
2097
|
+
});
|
|
2078
2098
|
|
|
2079
2099
|
// src/react.tsx
|
|
2080
2100
|
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
2081
|
-
var DevulturContext = React22.createContext(null);
|
|
2082
|
-
var DevulturApiContext = React22.createContext(null);
|
|
2083
|
-
var ProgressContext = React22.createContext(null);
|
|
2101
|
+
var DevulturContext = /* @__PURE__ */ React22.createContext(null);
|
|
2102
|
+
var DevulturApiContext = /* @__PURE__ */ React22.createContext(null);
|
|
2103
|
+
var ProgressContext = /* @__PURE__ */ React22.createContext(null);
|
|
2084
2104
|
function DevulturProvider({ api, baseUrl, tokenArgs, issueViewerToken, children }) {
|
|
2085
2105
|
const session = useMediaSession({ issueViewerToken: issueViewerToken ?? api.issueViewerToken, tokenArgs, baseUrl });
|
|
2086
2106
|
const createUploadUrlAction = useAction2(api.createUploadUrl);
|