@useupup/core 3.3.0

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.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +8 -0
  3. package/README.md +75 -0
  4. package/dist/browser-SXR426OQ.cjs +10 -0
  5. package/dist/browser-WD6T5ABJ.js +1 -0
  6. package/dist/chunk-2H5ICKFT.cjs +122 -0
  7. package/dist/chunk-6HF3I2JS.cjs +39 -0
  8. package/dist/chunk-6S5DQDQH.js +212 -0
  9. package/dist/chunk-BMQC27OE.cjs +92 -0
  10. package/dist/chunk-BSGQGINR.cjs +219 -0
  11. package/dist/chunk-CPKZ2CXD.cjs +179 -0
  12. package/dist/chunk-DTKDIMKT.cjs +573 -0
  13. package/dist/chunk-DYE5XJ6Z.cjs +2134 -0
  14. package/dist/chunk-E3ZCNOXG.cjs +74 -0
  15. package/dist/chunk-FEQY2WYY.cjs +2377 -0
  16. package/dist/chunk-FMURBCZ7.js +120 -0
  17. package/dist/chunk-FYQQRULL.js +37 -0
  18. package/dist/chunk-GE4LIVXP.js +133 -0
  19. package/dist/chunk-HFR5HZJZ.js +56 -0
  20. package/dist/chunk-I7ULPCA2.js +72 -0
  21. package/dist/chunk-MHYXDLZR.js +569 -0
  22. package/dist/chunk-N2SLHVAW.cjs +61 -0
  23. package/dist/chunk-OOPDEOTM.js +169 -0
  24. package/dist/chunk-PMBR3OUW.js +2359 -0
  25. package/dist/chunk-QK7HZIVY.cjs +144 -0
  26. package/dist/chunk-T2AQHY7V.cjs +59 -0
  27. package/dist/chunk-TRCP5FUR.js +90 -0
  28. package/dist/chunk-U7KL5M2H.cjs +374 -0
  29. package/dist/chunk-UXNPM54W.js +2108 -0
  30. package/dist/chunk-VV6QCQLL.js +365 -0
  31. package/dist/chunk-ZMS2HXLB.js +56 -0
  32. package/dist/context-shapes-123dd3b6.d.cts +207 -0
  33. package/dist/context-shapes-27b24c8f.d.ts +207 -0
  34. package/dist/contracts-pipeline-cf177270.d.cts +78 -0
  35. package/dist/contracts-pipeline-cf177270.d.ts +78 -0
  36. package/dist/contracts-strategies-378a16b7.d.cts +168 -0
  37. package/dist/contracts-strategies-378a16b7.d.ts +168 -0
  38. package/dist/contracts.cjs +181 -0
  39. package/dist/contracts.d.cts +11 -0
  40. package/dist/contracts.d.ts +11 -0
  41. package/dist/contracts.js +4 -0
  42. package/dist/core-141335ac.d.ts +651 -0
  43. package/dist/core-bea2ceca.d.cts +651 -0
  44. package/dist/create-worker-provider-AA5SRII6.js +58 -0
  45. package/dist/create-worker-provider-KJNUSSTW.cjs +60 -0
  46. package/dist/eligibility-ONLNJ6FB.cjs +10 -0
  47. package/dist/eligibility-ULFC3E4G.js +8 -0
  48. package/dist/error-code-map-9c44a425.d.ts +62 -0
  49. package/dist/error-code-map-dd5becfa.d.cts +62 -0
  50. package/dist/i18n/index.cjs +90 -0
  51. package/dist/i18n/index.d.cts +3 -0
  52. package/dist/i18n/index.d.ts +3 -0
  53. package/dist/i18n/index.js +1 -0
  54. package/dist/index.cjs +1770 -0
  55. package/dist/index.d.cts +280 -0
  56. package/dist/index.d.ts +280 -0
  57. package/dist/index.js +1589 -0
  58. package/dist/internal.cjs +2407 -0
  59. package/dist/internal.d.cts +595 -0
  60. package/dist/internal.d.ts +595 -0
  61. package/dist/internal.js +2275 -0
  62. package/dist/pipeline/index.cjs +10 -0
  63. package/dist/pipeline/index.d.cts +11 -0
  64. package/dist/pipeline/index.d.ts +11 -0
  65. package/dist/pipeline/index.js +1 -0
  66. package/dist/pipeline-worker.cjs +199 -0
  67. package/dist/pipeline-worker.d.cts +2 -0
  68. package/dist/pipeline-worker.d.ts +2 -0
  69. package/dist/pipeline-worker.js +197 -0
  70. package/dist/resolve-locale-81feef21.d.ts +20 -0
  71. package/dist/resolve-locale-9cb63600.d.cts +20 -0
  72. package/dist/resolve-theme-01758105.d.ts +53 -0
  73. package/dist/resolve-theme-66cf8d98.d.cts +53 -0
  74. package/dist/server-mode-drive-controller-b5f8ee12.d.cts +180 -0
  75. package/dist/server-mode-drive-controller-b5f8ee12.d.ts +180 -0
  76. package/dist/steps/compress.cjs +66 -0
  77. package/dist/steps/compress.d.cts +10 -0
  78. package/dist/steps/compress.d.ts +10 -0
  79. package/dist/steps/compress.js +64 -0
  80. package/dist/steps/exif.cjs +44 -0
  81. package/dist/steps/exif.d.cts +5 -0
  82. package/dist/steps/exif.d.ts +5 -0
  83. package/dist/steps/exif.js +42 -0
  84. package/dist/steps/hash.cjs +44 -0
  85. package/dist/steps/hash.d.cts +5 -0
  86. package/dist/steps/hash.d.ts +5 -0
  87. package/dist/steps/hash.js +42 -0
  88. package/dist/steps/heic.cjs +59 -0
  89. package/dist/steps/heic.d.cts +5 -0
  90. package/dist/steps/heic.d.ts +5 -0
  91. package/dist/steps/heic.js +57 -0
  92. package/dist/steps/thumbnail.cjs +54 -0
  93. package/dist/steps/thumbnail.d.cts +10 -0
  94. package/dist/steps/thumbnail.d.ts +10 -0
  95. package/dist/steps/thumbnail.js +52 -0
  96. package/dist/strategies/index.cjs +82 -0
  97. package/dist/strategies/index.d.cts +187 -0
  98. package/dist/strategies/index.d.ts +187 -0
  99. package/dist/strategies/index.js +60 -0
  100. package/dist/strategies/tus-upload.cjs +14 -0
  101. package/dist/strategies/tus-upload.d.cts +15 -0
  102. package/dist/strategies/tus-upload.d.ts +15 -0
  103. package/dist/strategies/tus-upload.js +5 -0
  104. package/dist/theme/index.cjs +38 -0
  105. package/dist/theme/index.d.cts +3 -0
  106. package/dist/theme/index.d.ts +3 -0
  107. package/dist/theme/index.js +1 -0
  108. package/dist/theme-store-2e56a674.d.cts +39 -0
  109. package/dist/theme-store-f13e0315.d.ts +39 -0
  110. package/dist/token-endpoint-5fdb4a35.d.ts +20 -0
  111. package/dist/token-endpoint-a7d15ab6.d.cts +20 -0
  112. package/dist/ui-translations-c5d00392.d.cts +455 -0
  113. package/dist/ui-translations-c5d00392.d.ts +455 -0
  114. package/dist/uploader-props-72242002.d.ts +340 -0
  115. package/dist/uploader-props-7f956e60.d.cts +340 -0
  116. package/dist/vars-d3421f6c.d.cts +240 -0
  117. package/dist/vars-d3421f6c.d.ts +240 -0
  118. package/package.json +182 -0
@@ -0,0 +1,595 @@
1
+ import { d as CoreOptions, I as ImageEditorOptions, b as CloudDrivesConfig, R as ResolvedImageEditorOptions, U as UpupCore } from './core-bea2ceca.cjs';
2
+ export { C as CoreEvents, j as CrashRecoveryManager, E as EventEmitter, i as FileManager, k as IndexedDBStorage, o as PREVIEW_MAX_TEXT_SIZE, p as PREVIEW_TEXT_TRUNCATE_LENGTH, l as PersistentStorage, P as PluginManager, m as bytesToSize, n as checkFileSize, u as fileCanPreviewText, v as fileGetExtension, q as fileGetIsImage, r as fileGetIsPdf, t as fileGetIsText, w as fileIs3D, x as searchDriveFiles, s as sizeToBytes } from './core-bea2ceca.cjs';
3
+ export { PipelineEngine } from './pipeline/index.cjs';
4
+ export { D as DirectUpload, T as TokenEndpointCredentials } from './token-endpoint-a7d15ab6.cjs';
5
+ import { m as RuntimeAdapter, h as UploadResult, k as CredentialStrategy, l as UploadStrategy, R as ResumableUploadOptions, M as MaxFileSizeObject } from './contracts-strategies-378a16b7.cjs';
6
+ export { j as CloudProvider, F as FileMetadata, i as ProgressInfo, U as UploadCredentials } from './contracts-strategies-378a16b7.cjs';
7
+ import { a as UploadFile, F as FileSource, c as UploadStatus } from './contracts-pipeline-cf177270.cjs';
8
+ import { O as OrchestratorCallbacks, U as UploaderOrchestrator } from './context-shapes-123dd3b6.cjs';
9
+ export { g as BaseContextEditor, d as BaseContextFiles, c as BaseContextI18n, a as BaseContextRuntime, b as BaseContextSource, h as BaseContextTheme, B as BaseContextUpload, e as BaseContextUploadControls, f as BaseContextView, i as OrchestratorState, j as UploadProgressInfo } from './context-shapes-123dd3b6.cjs';
10
+ import { L as LocaleBundle, P as PartialMessages, T as Translator, d as UiTranslations, c as Translations } from './ui-translations-c5d00392.cjs';
11
+ export { F as FlatMessageKey, M as MessageNamespace } from './ui-translations-c5d00392.cjs';
12
+ import { f as UpupThemeConfig } from './vars-d3421f6c.cjs';
13
+ export { D as DeepPartial, l as DeepPartialSlots, I as InternalFlatClassNames, g as UpupResolvedTheme, i as tokensToVarRefs } from './vars-d3421f6c.cjs';
14
+ import { a as ThemeStore } from './theme-store-2e56a674.cjs';
15
+ export { T as ThemeStoreState } from './theme-store-2e56a674.cjs';
16
+ import { h as ObservableController, D as DriveUser, d as DriveFolder, a as DriveFile, f as DriveBrowserError, k as DriveProviderDescriptor } from './server-mode-drive-controller-b5f8ee12.cjs';
17
+ export { p as DriveAuthKind, q as DriveFolderKey, r as DriveSelectFolderStrategy, n as ServerDriveSnapshot, m as ServerDriveTransferResult, l as ServerModeDriveController, o as ServerModeDriveDeps } from './server-mode-drive-controller-b5f8ee12.cjs';
18
+ export { b as buildFallbackChain, r as resolveMessage } from './resolve-locale-9cb63600.cjs';
19
+ import { ClassValue } from 'clsx';
20
+
21
+ declare const BrowserRuntime: RuntimeAdapter;
22
+
23
+ interface UploadManagerOptions {
24
+ credentials: CredentialStrategy;
25
+ uploadStrategy: UploadStrategy;
26
+ resolveUploadStrategy?: (file: UploadFile) => {
27
+ uploadStrategy: UploadStrategy;
28
+ presign: boolean;
29
+ };
30
+ maxConcurrentUploads: number;
31
+ maxRetries?: number;
32
+ fastAbortThreshold?: number;
33
+ isSuccessfulCall?: (response: {
34
+ status: number;
35
+ headers: Record<string, string>;
36
+ body: unknown;
37
+ }) => boolean | Promise<boolean>;
38
+ onProgress: (fileId: string, loaded: number, total: number) => void;
39
+ onFileStart?: (file: UploadFile) => void;
40
+ onFileComplete: (file: UploadFile, result: UploadResult) => void;
41
+ onFileError?: (file: UploadFile, error: Error) => void;
42
+ }
43
+ declare class UploadManager {
44
+ private abortController;
45
+ private options;
46
+ constructor(options: UploadManagerOptions);
47
+ uploadAll(files: UploadFile[]): Promise<UploadResult[]>;
48
+ private checkAborted;
49
+ private uploadFile;
50
+ abort(): void;
51
+ pause(): void;
52
+ }
53
+
54
+ type OnMessage = (data: Record<string, unknown>) => void;
55
+ type OnError = (error: Error) => void;
56
+ declare class SSEProcessor {
57
+ private sources;
58
+ private timers;
59
+ subscribe(key: string, endpoint: string, onMessage: OnMessage, onError: OnError, timeout?: number): void;
60
+ unsubscribe(key: string): void;
61
+ destroy(): void;
62
+ }
63
+
64
+ declare function getDir(locale: string | LocaleBundle | undefined): 'ltr' | 'rtl';
65
+ declare function normalizeSource(source: string): FileSource | undefined;
66
+ declare const DEFAULT_SOURCES: FileSource[];
67
+ declare const DEFAULT_MAX_FILE_SIZE: {
68
+ size: number;
69
+ unit: "GB";
70
+ };
71
+
72
+ type MotionMode = 'on' | 'off';
73
+ interface MotionGateParams {
74
+ /** The public `animations` prop. Default true. */
75
+ animations: boolean | undefined;
76
+ /** Injectable for tests/SSR; defaults to window.matchMedia when present. */
77
+ matchMedia?: ((query: string) => {
78
+ matches: boolean;
79
+ addEventListener(type: 'change', cb: (e: {
80
+ matches: boolean;
81
+ }) => void): void;
82
+ removeEventListener(type: 'change', cb: (e: {
83
+ matches: boolean;
84
+ }) => void): void;
85
+ }) | undefined;
86
+ }
87
+ type MotionGate = ObservableController<MotionMode>;
88
+ /**
89
+ * Resolves the ONE `data-motion` value: off when the consumer opted out
90
+ * (`animations={false}`) OR the OS asks for reduced motion. Frameworks write
91
+ * the snapshot onto the uploader-panel element and re-write it on change.
92
+ */
93
+ declare function createMotionGate({ animations, matchMedia, }: MotionGateParams): MotionGate;
94
+
95
+ interface TransientUiSnapshot {
96
+ /** File ids currently playing their exit animation (render upup-fx-exit). */
97
+ leavingFileIds: ReadonlySet<string>;
98
+ /** Add-more overlay: source view mounted above the dimmed file list. */
99
+ sourceOverlayOpen: boolean;
100
+ /** Add-more overlay is playing its reverse (close) slide before it unmounts.
101
+ * Kept mounted while `sourceOverlayOpen || sourceOverlayClosing`. */
102
+ sourceOverlayClosing: boolean;
103
+ /** Provider whose read-only picker just rejected an OS drop (drives the toast). */
104
+ dropRejected: string | null;
105
+ }
106
+ interface TransientUiParams {
107
+ /** Read fresh each call — the motion gate's current snapshot. */
108
+ motion: () => MotionMode;
109
+ /** The REAL removal (orchestrator path). Called exactly once per id. */
110
+ reallyRemove: (fileId: string) => void;
111
+ /** Exit-animation duration. Keep in lockstep with --upup-fx-base. */
112
+ exitMs?: number;
113
+ /** Overlay reverse-slide duration. Keep in lockstep with --upup-fx-overlay. */
114
+ overlayMs?: number;
115
+ /** Drop-rejection toast lifetime. */
116
+ toastMs?: number;
117
+ }
118
+ interface TransientUiState extends ObservableController<TransientUiSnapshot> {
119
+ removeFileAnimated(fileId: string): void;
120
+ openSourceOverlay(): void;
121
+ closeSourceOverlay(): void;
122
+ flagDropRejected(provider: string): void;
123
+ }
124
+ /**
125
+ * The uploader's transient UI state: deferred file removal (marks a file
126
+ * `leaving` so the exit animation can play before the real removal fires),
127
+ * the add-more source overlay flag, and the drop-rejection toast flag. It is a
128
+ * plain observable so frameworks can drive it through `useSyncExternalStore`.
129
+ * All removals go through `reallyRemove` exactly once; when motion is `off`
130
+ * the deferral collapses to an immediate call so reduced-motion users never
131
+ * wait on an animation that will not run.
132
+ */
133
+ declare function createTransientUiState({ motion, reallyRemove, exitMs, overlayMs, toastMs, }: TransientUiParams): TransientUiState;
134
+
135
+ /** i18n option block (identical across frameworks). */
136
+ interface UploaderI18nOptions {
137
+ bundle?: LocaleBundle;
138
+ locale?: LocaleBundle | string;
139
+ fallbackLocale?: LocaleBundle | string;
140
+ overrides?: PartialMessages;
141
+ }
142
+ /** Every callback the orchestrator/commands/proxy may invoke (framework-agnostic superset). */
143
+ interface UploaderCallbacks extends OrchestratorCallbacks {
144
+ onFileAdded?: ((files: UploadFile[]) => void) | undefined;
145
+ onUploadProgress?: ((p: {
146
+ fileId: string;
147
+ loaded: number;
148
+ total: number;
149
+ }) => void) | undefined;
150
+ onStatusChange?: ((status: string) => void) | undefined;
151
+ onFileTypeMismatch?: ((file: File, acceptedTypes: string) => void) | undefined;
152
+ onRestrictionFailed?: ((file: File, reason: 'TYPE_MISMATCH' | 'FILE_TOO_LARGE' | 'FILE_TOO_SMALL' | 'LIMIT_EXCEEDED') => void) | undefined;
153
+ onDoneClicked?: (() => void) | undefined;
154
+ autoUpload?: boolean | undefined;
155
+ }
156
+ /** Options accepted by the factory (framework-agnostic superset; each framework's props satisfy this structurally). */
157
+ interface UploaderControllerOptions extends Omit<CoreOptions, 'onError'>, UploaderCallbacks {
158
+ dark?: boolean | undefined;
159
+ theme?: UpupThemeConfig | undefined;
160
+ sources?: Array<FileSource | string> | undefined;
161
+ mini?: boolean | undefined;
162
+ animations?: boolean | undefined;
163
+ isProcessing?: boolean | undefined;
164
+ allowPreview?: boolean | undefined;
165
+ showBranding?: boolean | undefined;
166
+ quietCompletion?: boolean | undefined;
167
+ disableDragDrop?: boolean | undefined;
168
+ className?: string | undefined;
169
+ folderUpload?: {
170
+ allowDrop?: boolean;
171
+ showSelectFolderButton?: boolean;
172
+ } | undefined;
173
+ imageEditor?: boolean | ImageEditorOptions | undefined;
174
+ enablePaste?: boolean | undefined;
175
+ resumable?: ResumableUploadOptions | undefined;
176
+ i18n?: UploaderI18nOptions | undefined;
177
+ onIntegrationClick?: ((sourceId: string) => void) | undefined;
178
+ onPrepareFiles?: ((files: UploadFile[]) => Promise<UploadFile[]>) | undefined;
179
+ maxFiles?: number | undefined;
180
+ }
181
+ /** All resolved scalars + i18n + cloud-drive config (static, computed once). */
182
+ interface UploaderResolved {
183
+ cloudDrives?: CloudDrivesConfig | undefined;
184
+ mini: boolean;
185
+ animations: boolean;
186
+ sources: FileSource[];
187
+ allowedFileTypes: string;
188
+ limit: number;
189
+ maxFileSize: MaxFileSizeObject;
190
+ multiple: boolean;
191
+ mode: 'client' | 'server';
192
+ serverUrl?: string | undefined;
193
+ folderUploadAllowDrop: boolean;
194
+ folderPickerButtonVisible: boolean;
195
+ imageEditor: ResolvedImageEditorOptions;
196
+ resumable?: ResumableUploadOptions | undefined;
197
+ translator: Translator;
198
+ translations: UiTranslations;
199
+ lang: string;
200
+ dir: 'ltr' | 'rtl';
201
+ }
202
+ /** Output of the pure normalizer: the CoreOptions object to build core with, plus all resolved values. */
203
+ interface NormalizedUploaderOptions {
204
+ coreOptions: CoreOptions;
205
+ resolved: UploaderResolved;
206
+ }
207
+ /** Imperative command surface (delegates to core + orchestrator). */
208
+ interface UploaderCommands {
209
+ handleSetSelectedFiles(newFiles: File[]): Promise<void>;
210
+ handleFileRemove(fileId: string): void;
211
+ handleRemoveAll(): void;
212
+ uploadFiles(newFiles: File[] | UploadFile[]): Promise<UploadFile[] | undefined>;
213
+ replaceFiles(newFiles: File[] | UploadFile[]): void;
214
+ startUpload(): Promise<UploadFile[] | undefined>;
215
+ retryUpload(fileId?: string): Promise<UploadFile[] | undefined>;
216
+ handleCancel(): void;
217
+ handlePause(): void;
218
+ handleResume(): void;
219
+ handleDone(): void;
220
+ resetState(): void;
221
+ openImageEditor(file: UploadFile): void;
222
+ closeImageEditor(): void;
223
+ saveImageEdit(editedImageData: string, mimeType?: string): void;
224
+ replaceFile(fileId: string, newFile: UploadFile): void;
225
+ setActiveSource(source: FileSource | undefined): void;
226
+ setIsAddingMore(value: boolean): void;
227
+ setViewMode(mode: 'grid' | 'list'): void;
228
+ }
229
+ /** Optional host injection points. */
230
+ interface UploaderHostHooks {
231
+ /** Per-framework SSE wiring; called for each completed file in onFilesUploadComplete. Vanilla omits. */
232
+ connectSSE?: (file: UploadFile) => void;
233
+ /** Manual render-loop nudge (vanilla). Frameworks with reactive bridges omit. */
234
+ invalidate?: () => void;
235
+ }
236
+ /** Parameters for the factory: the host-created core, the raw options, and the precomputed normalization. */
237
+ interface CreateUploaderControllerParams {
238
+ core: UpupCore;
239
+ options: UploaderControllerOptions;
240
+ normalized: NormalizedUploaderOptions;
241
+ }
242
+ /** Stable handle returned by the factory. */
243
+ interface UploaderController {
244
+ core: UpupCore;
245
+ orchestrator: UploaderOrchestrator;
246
+ theme: ThemeStore;
247
+ /** Reduced-motion gate: `off` iff `animations={false}` or the OS asks. */
248
+ motionGate: MotionGate;
249
+ /** Deferred-removal / source-overlay / drop-rejection transient UI state. */
250
+ transientUi: TransientUiState;
251
+ resolved: UploaderResolved;
252
+ commands: UploaderCommands;
253
+ registerFileInput(el: HTMLInputElement | null): void;
254
+ getFileInput(): HTMLInputElement | null;
255
+ openFilePicker(): void;
256
+ /** Refresh the proxied callbacks (React calls every render; others once). */
257
+ updateCallbacks(callbacks: UploaderCallbacks): void;
258
+ /** Optional fan-in of core `state-change` + orchestrator + theme notifications. */
259
+ subscribe(listener: () => void): () => void;
260
+ /** Idempotent: orchestrator.init + theme.init + plugin registration + crash recovery + status-change. */
261
+ init(): void;
262
+ /** Idempotent + re-entrant: reverse of init; safe for Angular config rebuild. */
263
+ destroy(): void;
264
+ }
265
+
266
+ declare function normalizeUploaderOptions(options: UploaderControllerOptions): NormalizedUploaderOptions;
267
+
268
+ declare function createUploaderController({ core, options, normalized }: CreateUploaderControllerParams, hostHooks?: UploaderHostHooks): UploaderController;
269
+
270
+ interface ChildControllerLike {
271
+ init?(): void;
272
+ destroy?(): void;
273
+ subscribe?(listener: () => void): () => void;
274
+ }
275
+ interface CreateChildControllerOptions {
276
+ /** If provided and the controller supports subscribe(), wired on init() and unwired on destroy(). */
277
+ onChange?: () => void;
278
+ }
279
+ interface ChildControllerHandle<C extends ChildControllerLike> {
280
+ controller: C;
281
+ init(): void;
282
+ destroy(): void;
283
+ }
284
+ declare function createChildController<C extends ChildControllerLike>(factory: () => C, options?: CreateChildControllerOptions): ChildControllerHandle<C>;
285
+
286
+ interface DriveBrowserState {
287
+ user?: DriveUser | undefined;
288
+ /** Contents of the currently displayed folder (legacy: googleFiles/oneDriveFiles/…). */
289
+ folder?: DriveFolder | undefined;
290
+ path: DriveFolder[];
291
+ selectedFiles: DriveFile[];
292
+ isClickLoading: boolean;
293
+ showLoader: boolean;
294
+ /** GIS: token client ready. Popup: set true after mount restore. */
295
+ isAuthReady: boolean;
296
+ isAuthenticated: boolean;
297
+ isLoading: boolean;
298
+ /** GIS only: user dismissed the consent popup. */
299
+ authCancelled: boolean;
300
+ /** GIS only: the acquired access token. */
301
+ token?: {
302
+ access_token: string;
303
+ expires_in: number;
304
+ } | undefined;
305
+ /** The one drive-failure surface (auth/load/download/search, any provider). undefined = no error. */
306
+ error?: DriveBrowserError | undefined;
307
+ /** Drives the "Load more" button. Wired in F-125 (hasMore/loadMore); defaults false until then. */
308
+ hasMore: boolean;
309
+ /** Load-more button spinner/disabled state. */
310
+ isLoadingMore: boolean;
311
+ }
312
+ interface DriveBrowserCallbacks {
313
+ /** Push downloaded files into the uploader (host maps to context setFiles). */
314
+ onFilesSelected: (files: File[]) => void;
315
+ /** Close the drive browser view (host maps to setActiveSource(undefined)). */
316
+ onClose: () => void;
317
+ }
318
+ /**
319
+ * Framework-agnostic cloud-drive browser store. One instance per provider per
320
+ * mounted drive view. Mirrors UploaderOrchestrator's subscribe/getSnapshot
321
+ * pattern so every framework binds it the same way.
322
+ */
323
+ declare class DriveBrowserController {
324
+ private state;
325
+ private listeners;
326
+ private core;
327
+ private descriptor;
328
+ private callbacks;
329
+ private plugin;
330
+ private tokenClient;
331
+ private unsubs;
332
+ /** Real name of the folder being navigated into, captured at click time. */
333
+ private pendingFolder?;
334
+ /** Opaque continuation token from the most recent files-loaded/loadMoreFiles payload (F-125). */
335
+ private cursor?;
336
+ constructor(core: UpupCore, descriptor: DriveProviderDescriptor, callbacks: DriveBrowserCallbacks);
337
+ subscribe: (listener: () => void) => (() => void);
338
+ getSnapshot: () => DriveBrowserState;
339
+ protected setState(partial: Partial<DriveBrowserState>): void;
340
+ private notify;
341
+ init(): void;
342
+ destroy(): void;
343
+ private restore;
344
+ private bindEvents;
345
+ /**
346
+ * The single session-teardown home (F-127). onSignedOut and onSessionExpired
347
+ * previously drifted independently — onSessionExpired forgot to clear
348
+ * selectedFiles/pendingFolder, leaking a stale selection into the next
349
+ * sign-in. Both now delegate here.
350
+ */
351
+ private resetSession;
352
+ private buildRootFolder;
353
+ private initGis;
354
+ signIn(): void;
355
+ retryAuth(): void;
356
+ private runPopupAuth;
357
+ signOut(): void;
358
+ /**
359
+ * Folder trail for the breadcrumb, owned here so every framework stays consistent
360
+ * (react/vue/svelte previously seeded it in a component effect that collapsed the
361
+ * trail; vanilla/angular had no seed at all). Root load resets to [root]; descending
362
+ * appends; re-loading a folder already in the trail truncates to it. Ids must stay
363
+ * unique — the breadcrumb is keyed by folder id.
364
+ */
365
+ private nextPath;
366
+ setPath(path: DriveFolder[]): void;
367
+ handleClick(file: DriveFile): void;
368
+ handleSubmit(): Promise<void>;
369
+ handleCancelDownload(): void;
370
+ onSelectCurrentFolder(): Promise<void>;
371
+ /**
372
+ * Append-driven pagination (F-125), mirroring onSelectCurrentFolder's
373
+ * await-then-use-the-return-value style rather than reacting to another
374
+ * files-loaded event — the same convention, not a second one. A no-op
375
+ * unless the plugin supports it, the current view has more to fetch, and
376
+ * a continuation token exists.
377
+ */
378
+ loadMore(): Promise<void>;
379
+ private downloadAndClose;
380
+ }
381
+
382
+ /** The subset of uploader options the dropzone reads. */
383
+ interface DragDropOptions {
384
+ enablePaste?: boolean;
385
+ onFilesDragOver?: (files: File[]) => void;
386
+ onFilesDragLeave?: (files: File[]) => void;
387
+ onFilesDrop?: (files: File[]) => void;
388
+ onWarn?: (message: string) => void;
389
+ }
390
+ /** The subset of resolved props the dropzone reads. */
391
+ interface DragDropProps {
392
+ disableDragDrop: boolean;
393
+ isProcessing: boolean;
394
+ folderUploadAllowDrop: boolean;
395
+ }
396
+ interface DragDropDeps {
397
+ core: UpupCore;
398
+ orchestrator: UploaderOrchestrator;
399
+ setFiles: (files: File[]) => void | Promise<void>;
400
+ /**
401
+ * Current selected-file count, read fresh on each recompute. Each host MUST
402
+ * supply the SAME source its file list renders from, so the dropzone border
403
+ * (`absoluteHasBorder`) stays in lockstep with the visible files:
404
+ * - React / Vue / Svelte / Angular → `orchestrator.getSnapshot().files.size`
405
+ * (their lists derive from the orchestrator snapshot, which is now a
406
+ * projection of core.files refreshed on every `state-change` event)
407
+ * - Vanilla → `core.files.size` (its list reads core)
408
+ * Both sources are now in sync after every file mutation: the orchestrator
409
+ * files map is rebuilt from `core.files` on each `state-change`, so
410
+ * `orchestrator.getSnapshot().files.size` always equals `core.files.size`
411
+ * after any mutation completes.
412
+ */
413
+ filesSize: () => number;
414
+ /** Getter so frameworks that re-read options each render (React) stay fresh. */
415
+ options: () => DragDropOptions;
416
+ /** Getter so frameworks that re-read props each render (React) stay fresh. */
417
+ props: () => DragDropProps;
418
+ /**
419
+ * Invoked when a file is dropped while a read-only drive picker is the
420
+ * active source (see `READONLY_DRIVE_SOURCES`). The host resolves the human
421
+ * provider label and raises the drop-rejection toast (core transient-UI
422
+ * store). When omitted, such a drop is silently ignored (the prior
423
+ * behavior). Core owns the DECISION (which source, that files were dropped);
424
+ * the host owns the i18n label + toast.
425
+ */
426
+ onReadonlyDropRejected?: (source: FileSource) => void;
427
+ }
428
+ interface DragDropSnapshot {
429
+ isDragging: boolean;
430
+ absoluteIsDragging: boolean;
431
+ absoluteHasBorder: boolean;
432
+ }
433
+ declare class DragDropController implements ObservableController<DragDropSnapshot> {
434
+ private deps;
435
+ private isDragging;
436
+ private snapshot;
437
+ private listeners;
438
+ private unsubOrchestrator;
439
+ constructor(deps: DragDropDeps);
440
+ subscribe: (listener: () => void) => (() => void);
441
+ getSnapshot: () => DragDropSnapshot;
442
+ /** Subscribe to the orchestrator so border/dragging derive on change. Call on mount. Idempotent. */
443
+ init(): void;
444
+ private get disabled();
445
+ private compute;
446
+ /**
447
+ * Recompute the cached snapshot from current inputs and notify if it changed.
448
+ * Runs automatically on drag events and orchestrator changes. Hosts may also call
449
+ * it to refresh after external state the controller cannot observe via the
450
+ * orchestrator — e.g. a framework that removes files through `core.removeFile`
451
+ * directly (which emits no orchestrator notify), leaving the file-count-derived
452
+ * `absoluteHasBorder` stale.
453
+ */
454
+ recompute(): void;
455
+ private notify;
456
+ handleDragOver(e: DragEvent): void;
457
+ handleDragLeave(e: DragEvent): void;
458
+ /** True when the drag payload carries at least one file. */
459
+ private dropHasFiles;
460
+ handleDrop(e: DragEvent): Promise<void>;
461
+ handlePaste(e: ClipboardEvent): void;
462
+ destroy(): void;
463
+ }
464
+
465
+ interface DriveEventCallbacks {
466
+ onAuthenticated: (payload: unknown) => void;
467
+ onSignedOut: () => void;
468
+ onSessionExpired: () => void;
469
+ onFilesLoaded: (payload: unknown) => void;
470
+ onStateChange: (payload: unknown) => void;
471
+ onError: (payload?: unknown) => void;
472
+ }
473
+ declare function bindDriveEvents(core: UpupCore, provider: string, callbacks: DriveEventCallbacks): () => void;
474
+
475
+ type DroppedFilesResult = {
476
+ files: File[];
477
+ skippedDirectory: boolean;
478
+ };
479
+ declare function collectDroppedFiles(dataTransfer: Pick<DataTransfer, 'items' | 'files'>, allowFolderDrop: boolean): Promise<DroppedFilesResult>;
480
+
481
+ declare function cn(...inputs: ClassValue[]): string;
482
+
483
+ declare function b64EncodeUnicode(str: string): string;
484
+
485
+ declare const fileAppendParams: (file: File) => UploadFile;
486
+ declare const revokeFileUrl: (file: UploadFile) => void;
487
+
488
+ type ImageOutputOptions = {
489
+ mimeType?: string;
490
+ quality?: number;
491
+ fileName?: (original: File) => string;
492
+ };
493
+ /**
494
+ * Convert a data-URL (base64 or plain) string to a Blob.
495
+ * Works with any MIME type encoded as `data:<mime>;base64,<data>`.
496
+ */
497
+ declare function dataURLtoBlob(dataURL: string): Blob;
498
+ /**
499
+ * Create a new UploadFile from a Blob, preserving the identity (`id`)
500
+ * of the original file. A fresh blob URL is created for the new file.
501
+ *
502
+ * @param blob The edited image blob.
503
+ * @param original The original UploadFile being replaced.
504
+ * @param output Optional output settings (mimeType, quality, fileName).
505
+ * @returns A new UploadFile with the same `id` but updated content.
506
+ */
507
+ declare function blobToUploadFile(blob: Blob, original: UploadFile, output?: ImageOutputOptions): UploadFile;
508
+ /**
509
+ * Replace a file in a Map<string, UploadFile>, revoking the old blob URL
510
+ * to prevent memory leaks.
511
+ *
512
+ * @param map The current files map (not mutated — a new Map is returned).
513
+ * @param fileId The id of the file to replace.
514
+ * @param newFile The replacement UploadFile.
515
+ * @returns A new Map with the replaced entry.
516
+ */
517
+ declare function revokeAndReplace(map: Map<string, UploadFile>, fileId: string, newFile: UploadFile): Map<string, UploadFile>;
518
+
519
+ /**
520
+ * Loads the Google Identity Services (GIS) API script.
521
+ * Cached — only loads once per page lifecycle.
522
+ */
523
+ declare function loadGoogleIdentityServices(): Promise<void>;
524
+
525
+ /** Maps each FileSource to its i18n translation key. No React dependency. */
526
+ declare const sourceNameKeys: Record<FileSource, keyof Translations>;
527
+
528
+ declare function isUploadActive(status: UploadStatus): boolean;
529
+ declare function isUploadIdle(status: UploadStatus): boolean;
530
+ /** Whether a file's remove control is locked. "Has progress" used to imply
531
+ * "in flight", but a crash-restored PAUSED file now carries its resumable
532
+ * byte offset as progress too — and a paused file must stay discardable,
533
+ * because discarding is the one path that aborts its server-side upload and
534
+ * drops its persisted session. */
535
+ declare function isFileRemovalLocked(progress: number | null | undefined, fileStatus: UploadStatus): boolean;
536
+
537
+ /**
538
+ * What a paused/reloaded multipart upload needs to find its way back to the
539
+ * server-side upload it left behind. Deliberately NOT stored: the uploadId —
540
+ * the HMAC-signed `token` is its only carrier (server-side S2), so a session
541
+ * leaked out of localStorage still cannot forge a continuation request.
542
+ */
543
+ interface MultipartSession {
544
+ /** The server-issued upload token: the sole carrier of key + uploadId +
545
+ * owner + size envelope. Replaced by a fresh one on every resume. */
546
+ token: string;
547
+ /** Object key the upload targets — diagnostics only; the token is what the
548
+ * server actually binds against. */
549
+ key: string;
550
+ /** Bytes per part for every part except the last one. Resume validates the
551
+ * server-reported part sizes against it before trusting the session. */
552
+ partSize: number;
553
+ /** Epoch ms of the last write — drives the 24h TTL below. */
554
+ updatedAt: number;
555
+ /** Bytes uploaded so far (used for progress pre-population on resume) */
556
+ uploadedBytes?: number;
557
+ /** The serverUrl this session belongs to. A session saved against server A
558
+ * must never be resumed against server B. */
559
+ scope?: string;
560
+ /** `file.metadata.originalContentHash`, when the checksum pipeline step
561
+ * ran. Opportunistic: compared on resume only when both sides have it. */
562
+ contentHash?: string;
563
+ }
564
+ /**
565
+ * Generate a deterministic fingerprint for a file to identify resumable sessions.
566
+ */
567
+ declare function fileFingerprint(file: File): string;
568
+ /**
569
+ * Save a multipart session to localStorage.
570
+ */
571
+ declare function saveSession(fingerprint: string, session: MultipartSession): void;
572
+ /**
573
+ * Load a multipart session from localStorage, if it exists and is not expired.
574
+ */
575
+ declare function loadSession(fingerprint: string): MultipartSession | null;
576
+ /**
577
+ * Update only the progress-related fields of an existing session.
578
+ */
579
+ declare function updateSessionProgress(fingerprint: string, uploadedBytes: number): void;
580
+ /**
581
+ * Remove a multipart session (on complete or abort).
582
+ */
583
+ declare function removeSession(fingerprint: string): void;
584
+ /**
585
+ * Clear all multipart sessions (e.g., on user cancel).
586
+ */
587
+ declare function clearAllSessions(): void;
588
+
589
+ declare const MIME_EXTENSION_MAP: Record<string, string>;
590
+ declare function sanitizeFileName(value: string): string;
591
+ declare function extensionFromMime(type: string): string;
592
+ declare function fileNameFromContentDisposition(header: string | null): string | undefined;
593
+ declare function deriveFetchedFileName(url: string, response: Response, blob: Blob): string;
594
+
595
+ export { BrowserRuntime, type ChildControllerHandle, type ChildControllerLike, type CreateChildControllerOptions, type CreateUploaderControllerParams, CredentialStrategy, DEFAULT_MAX_FILE_SIZE, DEFAULT_SOURCES, DragDropController, type DragDropDeps, type DragDropOptions, type DragDropProps, type DragDropSnapshot, type DriveBrowserCallbacks, DriveBrowserController, type DriveBrowserState, type DriveEventCallbacks, DriveProviderDescriptor, type DroppedFilesResult, MIME_EXTENSION_MAP, type MotionGate, type MotionGateParams, type MotionMode, type MultipartSession, type NormalizedUploaderOptions, OrchestratorCallbacks, RuntimeAdapter, SSEProcessor, ThemeStore, type TransientUiParams, type TransientUiSnapshot, type TransientUiState, UploadManager, UploadResult, UploadStrategy, type UploaderCallbacks, type UploaderCommands, type UploaderController, type UploaderControllerOptions, type UploaderHostHooks, type UploaderI18nOptions, UploaderOrchestrator, type UploaderResolved, b64EncodeUnicode, bindDriveEvents, blobToUploadFile, clearAllSessions, cn, collectDroppedFiles, createChildController, createMotionGate, createTransientUiState, createUploaderController, dataURLtoBlob, deriveFetchedFileName, extensionFromMime, fileAppendParams, fileFingerprint, fileNameFromContentDisposition, getDir, isFileRemovalLocked, isUploadActive, isUploadIdle, loadGoogleIdentityServices, loadSession, normalizeSource, normalizeUploaderOptions, removeSession, revokeAndReplace, revokeFileUrl, sanitizeFileName, saveSession, sourceNameKeys, updateSessionProgress };