@masters-union/union-stack 0.3.8 → 0.3.10

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 (42) hide show
  1. package/README.md +42 -16
  2. package/dist/cdn/loader.v1.global.js +4 -2
  3. package/dist/cdn/loader.v1.global.js.map +1 -1
  4. package/dist/{chunk-TNWAUSLA.js → chunk-F4EVNUJZ.cjs} +10 -140
  5. package/dist/chunk-F4EVNUJZ.cjs.map +1 -0
  6. package/dist/chunk-IIVRPVNX.js +140 -0
  7. package/dist/chunk-IIVRPVNX.js.map +1 -0
  8. package/dist/chunk-IV76YPDA.cjs +142 -0
  9. package/dist/chunk-IV76YPDA.cjs.map +1 -0
  10. package/dist/{chunk-ACQDEKCW.cjs → chunk-MFZ2JGLP.js} +6 -142
  11. package/dist/chunk-MFZ2JGLP.js.map +1 -0
  12. package/dist/client-C0qMOfb3.d.ts +112 -0
  13. package/dist/client-DOTa3Mai.d.cts +112 -0
  14. package/dist/index.cjs +4 -3
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +3 -2
  17. package/dist/index.d.ts +3 -2
  18. package/dist/index.js +3 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/node.cjs +244 -0
  21. package/dist/node.cjs.map +1 -0
  22. package/dist/node.d.cts +56 -0
  23. package/dist/node.d.ts +56 -0
  24. package/dist/node.js +221 -0
  25. package/dist/node.js.map +1 -0
  26. package/dist/picker.cjs +213 -11
  27. package/dist/picker.cjs.map +1 -1
  28. package/dist/picker.d.cts +10 -2
  29. package/dist/picker.d.ts +10 -2
  30. package/dist/picker.js +213 -11
  31. package/dist/picker.js.map +1 -1
  32. package/dist/react.cjs +3 -2
  33. package/dist/react.cjs.map +1 -1
  34. package/dist/react.d.cts +4 -2
  35. package/dist/react.d.ts +4 -2
  36. package/dist/react.js +2 -1
  37. package/dist/react.js.map +1 -1
  38. package/dist/{client-I6TadQ-m.d.cts → types-ZCfjNZls.d.cts} +20 -93
  39. package/dist/{client-I6TadQ-m.d.ts → types-ZCfjNZls.d.ts} +20 -93
  40. package/package.json +7 -1
  41. package/dist/chunk-ACQDEKCW.cjs.map +0 -1
  42. package/dist/chunk-TNWAUSLA.js.map +0 -1
@@ -1,5 +1,3 @@
1
- 'use strict';
2
-
3
1
  // src/errors.ts
4
2
  function makeError(code, message, opts = {}) {
5
3
  return {
@@ -45,8 +43,9 @@ function fromApiResponse(status, body) {
45
43
  }
46
44
 
47
45
  // src/version.ts
48
- var SDK_VERSION = "0.3.8" ;
46
+ var SDK_VERSION = "0.3.10" ;
49
47
  var SDK_VERSION_HEADER = `js/${SDK_VERSION}`;
48
+ var NODE_SDK_VERSION_HEADER = `node/${SDK_VERSION}`;
50
49
 
51
50
  // src/uploader.ts
52
51
  var DEFAULT_CONCURRENCY = 3;
@@ -220,7 +219,7 @@ var Uploader = class {
220
219
  headers: {
221
220
  Authorization: `Bearer ${this.cfg.apiKey}`,
222
221
  "Content-Type": "application/json",
223
- "X-UnionStack-SDK": SDK_VERSION_HEADER
222
+ "X-UnionStack-SDK": this.cfg.sdkHeader ?? SDK_VERSION_HEADER
224
223
  },
225
224
  body: body === void 0 ? void 0 : JSON.stringify(body),
226
225
  signal
@@ -261,141 +260,6 @@ function withSessionId(err, sessionId) {
261
260
  return err;
262
261
  }
263
262
 
264
- // src/client.ts
265
- var API_BASE = "https://api.unionstack.link/v1";
266
- var PRELOADER_STYLE_ID = "unionstack-preloader-styles";
267
- function showPickerPreloader() {
268
- if (typeof document === "undefined") return () => {
269
- };
270
- if (!document.getElementById(PRELOADER_STYLE_ID)) {
271
- const style = document.createElement("style");
272
- style.id = PRELOADER_STYLE_ID;
273
- style.textContent = "@keyframes us-preload-spin{to{transform:rotate(360deg)}}@keyframes us-preload-fade{from{opacity:0}to{opacity:1}}";
274
- document.head.appendChild(style);
275
- }
276
- const backdrop = document.createElement("div");
277
- backdrop.setAttribute("role", "status");
278
- backdrop.setAttribute("aria-label", "Loading file picker");
279
- backdrop.style.cssText = "position:fixed;inset:0;z-index:2147483000;display:flex;align-items:center;justify-content:center;background:rgba(2,6,23,0.4);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);animation:us-preload-fade 140ms ease-out;";
280
- const spinner = document.createElement("div");
281
- spinner.style.cssText = "width:36px;height:36px;border-radius:50%;border:3px solid rgba(220,225,251,0.25);border-top-color:#c0c1ff;animation:us-preload-spin 0.8s linear infinite;";
282
- backdrop.appendChild(spinner);
283
- document.body.appendChild(backdrop);
284
- let removed = false;
285
- return () => {
286
- if (removed) return;
287
- removed = true;
288
- backdrop.remove();
289
- };
290
- }
291
- var UnionStackClient = class {
292
- constructor(cfg) {
293
- if (!cfg.apiKey) {
294
- console.error(
295
- "[UnionStack] apiKey is not set. Uploads and the picker are disabled until a valid apiKey is provided."
296
- );
297
- }
298
- this.resolvedCfg = { ...cfg, apiBase: API_BASE };
299
- this.uploader = new Uploader(this.resolvedCfg);
300
- this.pickerConfigPromise = !cfg.apiKey || this.resolvedCfg.skipConfigPrefetch ? Promise.resolve(null) : this.uploader.fetchPickerConfig().then((cfg2) => {
301
- if (cfg2?.sdkWarning) console.warn(`[UnionStack] ${cfg2.sdkWarning}`);
302
- return cfg2;
303
- }).catch(() => null);
304
- }
305
- missingKeyError() {
306
- if (this.resolvedCfg.apiKey) return null;
307
- return makeError("CONFIG", "apiKey is required.", { retryable: false });
308
- }
309
- upload(file, opts = {}) {
310
- const keyErr = this.missingKeyError();
311
- if (keyErr) return Promise.reject(keyErr);
312
- return this.uploader.upload(file, opts);
313
- }
314
- async uploadMany(files, opts = {}) {
315
- const keyErr = this.missingKeyError();
316
- if (keyErr) {
317
- opts.onError?.(keyErr);
318
- throw keyErr;
319
- }
320
- if (!Array.isArray(files) || files.length === 0) {
321
- const err = makeError("VALIDATION", "uploadMany requires a non-empty array of files.", { retryable: false });
322
- opts.onError?.(err);
323
- throw err;
324
- }
325
- const picked = files.map(
326
- (f) => this.uploader.describe(f, { filename: opts.filename, mimeType: opts.mimeType })
327
- );
328
- opts.onUploadStarted?.(picked);
329
- const filesUploaded = [];
330
- const filesFailed = [];
331
- await Promise.all(files.map(async (f, i) => {
332
- try {
333
- const uploaded = await this.uploader.upload(f, opts);
334
- uploaded.uploadId = picked[i].uploadId;
335
- filesUploaded.push(uploaded);
336
- } catch (err) {
337
- filesFailed.push({ file: picked[i], error: err });
338
- }
339
- }));
340
- const result = { filesUploaded, filesFailed };
341
- opts.onUploadDone?.(result);
342
- return result;
343
- }
344
- picker(opts = {}) {
345
- let real = null;
346
- let opened = false;
347
- let pendingResolve;
348
- let pendingReject;
349
- const donePromise = new Promise((res, rej) => {
350
- pendingResolve = res;
351
- pendingReject = rej;
352
- });
353
- return {
354
- open: async () => {
355
- if (opened) return donePromise;
356
- const keyErr = this.missingKeyError();
357
- if (keyErr) {
358
- pendingReject(keyErr);
359
- throw keyErr;
360
- }
361
- opened = true;
362
- const hidePreloader = showPickerPreloader();
363
- try {
364
- const mod = await import('./picker.cjs');
365
- real = mod.openPicker(this, {
366
- ...opts,
367
- // Picker fires onOpen right after the modal mounts — that's the
368
- // moment the preloader hands off to the real UI.
369
- onOpen: () => {
370
- hidePreloader();
371
- opts.onOpen?.();
372
- }
373
- });
374
- const result = await real.open();
375
- hidePreloader();
376
- pendingResolve(result);
377
- return result;
378
- } catch (err) {
379
- hidePreloader();
380
- const e = err?.code ? err : makeError("CONFIG", "Failed to load picker.", { retryable: false, cause: err });
381
- pendingReject(e);
382
- throw e;
383
- }
384
- },
385
- close: () => {
386
- real?.close();
387
- },
388
- cancel: () => {
389
- real?.cancel();
390
- }
391
- };
392
- }
393
- /** Read-only accessor used by the React/picker packages. */
394
- get config() {
395
- return this.resolvedCfg;
396
- }
397
- };
398
-
399
- exports.UnionStackClient = UnionStackClient;
400
- //# sourceMappingURL=chunk-ACQDEKCW.cjs.map
401
- //# sourceMappingURL=chunk-ACQDEKCW.cjs.map
263
+ export { NODE_SDK_VERSION_HEADER, Uploader, makeError };
264
+ //# sourceMappingURL=chunk-MFZ2JGLP.js.map
265
+ //# sourceMappingURL=chunk-MFZ2JGLP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/version.ts","../src/uploader.ts"],"names":[],"mappings":"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","file":"chunk-MFZ2JGLP.js","sourcesContent":["import type { UploadError, UploadErrorCode } from './types.js';\n\nexport function makeError(\n code: UploadErrorCode,\n message: string,\n opts: { status?: number; retryable?: boolean; cause?: unknown } = {}\n): UploadError {\n return {\n code,\n message,\n status: opts.status,\n retryable: opts.retryable ?? defaultRetryable(code, opts.status),\n cause: opts.cause,\n };\n}\n\nfunction defaultRetryable(code: UploadErrorCode, status?: number): boolean {\n if (code === 'NETWORK' || code === 'PART_FAILED') return true;\n if (code === 'SERVER' && status && status >= 500) return true;\n return false;\n}\n\n/** Map an HTTP error response from the cdn-be API to an UploadError. */\nexport function fromApiResponse(status: number, body: unknown): UploadError {\n const err = (body as { error?: { code?: string; message?: string } } | null)?.error;\n const msg = err?.message || `Request failed with status ${status}`;\n const code = (err?.code || '').toUpperCase();\n\n if (status === 401) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 403) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 413) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 415) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 426) {\n // Server-enforced minimum SDK version. Not retryable — the integrator\n // must upgrade the package (or reload, for script-loader users).\n return makeError('CONFIG', msg, { status, retryable: false });\n }\n if (status === 429) {\n const isQuota = code === 'QUOTA_EXCEEDED';\n return makeError(isQuota ? 'QUOTA' : 'NETWORK', msg, { status, retryable: !isQuota });\n }\n if (status >= 500) {\n return makeError('SERVER', msg, { status, retryable: true });\n }\n return makeError('SERVER', msg, { status, retryable: false });\n}\n","// __SDK_VERSION__ is replaced at build time by tsup's `define` with the\n// package.json version. The typeof guard keeps tsc/tests working unreplaced.\ndeclare const __SDK_VERSION__: string | undefined;\n\nexport const SDK_VERSION: string =\n typeof __SDK_VERSION__ === 'string' ? __SDK_VERSION__ : '0.0.0-dev';\n\n/** Wire format sent to cdn-be on every API call, e.g. \"js/0.1.9\". */\nexport const SDK_VERSION_HEADER = `js/${SDK_VERSION}`;\n\n/** Wire format for the Node server-to-server SDK, e.g. \"node/0.4.0\". */\nexport const NODE_SDK_VERSION_HEADER = `node/${SDK_VERSION}`;\n","import type {\n ResolvedClientConfig,\n PickedFile,\n PickerConfig,\n UploadedFile,\n UploadOptions,\n ProgressEvent as USProgressEvent,\n} from './types.js';\nimport { fromApiResponse, makeError } from './errors.js';\nimport { SDK_VERSION_HEADER } from './version.js';\n\ninterface InitResponse {\n sessionId: string;\n fileId: string;\n chunkSize: number;\n totalParts: number;\n partUrls: Array<{ partNumber: number; url: string }>;\n expiresAt: string;\n}\n\ninterface CompleteResponse {\n handle: string;\n fileId: string;\n url: string;\n filename: string;\n mimetype: string;\n size: number;\n key: string;\n container: string;\n status: 'Stored';\n etag?: string;\n metadata?: Record<string, unknown>;\n}\n\ninterface PartResult {\n partNumber: number;\n etag: string;\n size: number;\n}\n\nconst DEFAULT_CONCURRENCY = 3;\nconst DEFAULT_MAX_RETRIES_PER_PART = 3;\n// Backoff schedule between part retries. Capped — past this we surrender.\nconst BACKOFF_MS = [400, 1200, 3600];\n\nexport class Uploader {\n constructor(private cfg: ResolvedClientConfig) {}\n\n /** Returns a stable PickedFile descriptor for the input blob/file. */\n describe(file: File | Blob, opts: { filename?: string; mimeType?: string } = {}): PickedFile {\n const isFile = typeof File !== 'undefined' && file instanceof File;\n const filename =\n opts.filename ||\n (isFile ? (file as File).name : 'untitled');\n const mimetype =\n opts.mimeType || (file as Blob).type || 'application/octet-stream';\n return {\n uploadId: cryptoRandomId(),\n filename,\n mimetype,\n size: file.size,\n source: 'local',\n };\n }\n\n async upload(file: File | Blob, opts: UploadOptions = {}): Promise<UploadedFile> {\n const picked = this.describe(file, { filename: opts.filename, mimeType: opts.mimeType });\n opts.onFileUploadStarted?.(picked);\n\n try {\n const init = await this.initUpload(picked, opts);\n const parts = await this.uploadAllParts(file, init, picked, opts);\n const completed = await this.completeUpload(init.sessionId, parts, opts);\n\n const uploaded: UploadedFile = {\n ...picked,\n handle: completed.handle,\n fileId: completed.fileId,\n url: completed.url,\n size: completed.size,\n mimetype: completed.mimetype,\n filename: completed.filename,\n key: completed.key,\n container: completed.container,\n status: 'Stored',\n etag: completed.etag,\n metadata: completed.metadata,\n };\n opts.onFileUploadFinished?.(uploaded);\n return uploaded;\n } catch (rawErr) {\n const err = normalizeError(rawErr);\n opts.onFileUploadFailed?.(picked, err);\n // Best effort: tell the server to clean up the multipart, but ignore failures.\n if ((rawErr as { sessionId?: string })?.sessionId) {\n this.abortSilently((rawErr as { sessionId: string }).sessionId).catch(() => {});\n }\n throw err;\n }\n }\n\n /** Cancel an in-flight session server-side. */\n async abort(sessionId: string): Promise<void> {\n await this.api('POST', '/sdk/v1/uploads/abort', { sessionId });\n }\n\n /** Fetch the server-managed picker config (branding, theme, constraints). */\n async fetchPickerConfig(): Promise<PickerConfig> {\n return this.api<PickerConfig>('GET', '/sdk/v1/picker-config');\n }\n\n private async initUpload(picked: PickedFile, opts: UploadOptions): Promise<InitResponse> {\n return this.api<InitResponse>('POST', '/sdk/v1/uploads/init', {\n filename: picked.filename,\n mimeType: picked.mimetype,\n size: picked.size,\n metadata: opts.metadata,\n }, opts.signal);\n }\n\n private async uploadAllParts(\n file: File | Blob,\n init: InitResponse,\n picked: PickedFile,\n opts: UploadOptions,\n ): Promise<PartResult[]> {\n const totalParts = init.totalParts;\n const chunkSize = init.chunkSize;\n const concurrency = Math.max(1, opts.concurrency ?? DEFAULT_CONCURRENCY);\n const maxRetries = opts.maxRetriesPerPart ?? DEFAULT_MAX_RETRIES_PER_PART;\n\n // Quick lookup: partNumber → presigned URL.\n const urlByPart = new Map(init.partUrls.map(p => [p.partNumber, p.url] as const));\n\n const results: PartResult[] = new Array(totalParts);\n const loadedPerPart: number[] = new Array(totalParts).fill(0);\n let cursor = 1;\n\n const totalBytes = file.size;\n\n const reportProgress = () => {\n const loaded = loadedPerPart.reduce((a, b) => a + b, 0);\n const totalPercent = totalBytes > 0 ? Math.min(100, Math.round((loaded / totalBytes) * 100)) : 100;\n const ev: USProgressEvent = { totalBytes, loaded, totalPercent };\n opts.onFileUploadProgress?.(picked, ev);\n };\n\n const worker = async (): Promise<void> => {\n while (true) {\n if (opts.signal?.aborted) {\n throw makeError('ABORTED', 'Upload aborted by caller.', { retryable: false });\n }\n const partNumber = cursor++;\n if (partNumber > totalParts) return;\n\n const start = (partNumber - 1) * chunkSize;\n const end = Math.min(start + chunkSize, file.size);\n const chunk = file.slice(start, end);\n\n let attempt = 0;\n let lastErr: unknown;\n while (attempt <= maxRetries) {\n if (opts.signal?.aborted) {\n throw makeError('ABORTED', 'Upload aborted by caller.', { retryable: false });\n }\n try {\n let url = urlByPart.get(partNumber);\n if (!url) {\n const refreshed = await this.api<{ url: string }>(\n 'POST', '/sdk/v1/uploads/sign-part',\n { sessionId: init.sessionId, partNumber }, opts.signal,\n );\n url = refreshed.url;\n urlByPart.set(partNumber, url);\n }\n\n const res = await this.cfg.fetch?.(url, {\n method: 'PUT',\n body: chunk,\n signal: opts.signal,\n }) ?? await fetch(url, { method: 'PUT', body: chunk, signal: opts.signal });\n\n if (!res.ok) {\n // If R2 rejects with 403 the URL likely expired — drop it so the\n // next attempt re-signs.\n if (res.status === 403 || res.status === 401) urlByPart.delete(partNumber);\n throw makeError('PART_FAILED', `Part ${partNumber} PUT failed (HTTP ${res.status})`, { status: res.status });\n }\n const etag = res.headers.get('etag');\n if (!etag) {\n throw makeError('PART_FAILED', `Part ${partNumber}: R2 did not return an ETag.`);\n }\n\n results[partNumber - 1] = { partNumber, etag, size: chunk.size };\n loadedPerPart[partNumber - 1] = chunk.size;\n reportProgress();\n break;\n } catch (err) {\n lastErr = err;\n attempt++;\n if (attempt > maxRetries) break;\n await sleep(BACKOFF_MS[Math.min(attempt - 1, BACKOFF_MS.length - 1)]);\n }\n }\n if (!results[partNumber - 1]) {\n throw withSessionId(\n normalizeError(lastErr ?? makeError('PART_FAILED', `Part ${partNumber} failed after ${maxRetries} retries.`)),\n init.sessionId,\n );\n }\n }\n };\n\n const workers = Array.from({ length: Math.min(concurrency, totalParts) }, worker);\n await Promise.all(workers);\n return results;\n }\n\n private async completeUpload(\n sessionId: string,\n parts: PartResult[],\n opts: UploadOptions,\n ): Promise<CompleteResponse> {\n return this.api<CompleteResponse>('POST', '/sdk/v1/uploads/complete', {\n sessionId,\n parts: parts.map(p => ({ partNumber: p.partNumber, etag: p.etag })),\n }, opts.signal);\n }\n\n private async abortSilently(sessionId: string): Promise<void> {\n try { await this.abort(sessionId); } catch { /* ignore */ }\n }\n\n private async api<T>(\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n signal?: AbortSignal,\n ): Promise<T> {\n const fetchImpl = this.cfg.fetch ?? fetch;\n const url = `${this.cfg.apiBase}${path}`;\n let res: Response;\n try {\n res = await fetchImpl(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.cfg.apiKey}`,\n 'Content-Type': 'application/json',\n 'X-UnionStack-SDK': this.cfg.sdkHeader ?? SDK_VERSION_HEADER,\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n });\n } catch (cause) {\n if ((cause as Error)?.name === 'AbortError') {\n throw makeError('ABORTED', 'Request aborted.', { retryable: false, cause });\n }\n throw makeError('NETWORK', 'Network request failed.', { retryable: true, cause });\n }\n let parsed: unknown = null;\n try { parsed = await res.json(); } catch { /* tolerate empty body */ }\n if (!res.ok) throw fromApiResponse(res.status, parsed);\n return parsed as T;\n }\n}\n\nfunction cryptoRandomId(): string {\n // Cheap unique id for client-side uploadId. Not security-sensitive.\n if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {\n return (crypto as { randomUUID: () => string }).randomUUID().replace(/-/g, '');\n }\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(r => setTimeout(r, ms));\n}\n\nfunction normalizeError(err: unknown): ReturnType<typeof makeError> {\n if (err && typeof err === 'object' && 'code' in err && 'message' in err && 'retryable' in err) {\n return err as ReturnType<typeof makeError>;\n }\n const msg = (err as Error)?.message || 'Upload failed.';\n return makeError('NETWORK', msg, { cause: err });\n}\n\nfunction withSessionId<T>(err: T, sessionId: string): T {\n if (err && typeof err === 'object') (err as { sessionId?: string }).sessionId = sessionId;\n return err;\n}\n"]}
@@ -0,0 +1,112 @@
1
+ import { B as BatchUploadOptions, a as PickedFile, P as PickResponse, f as PickerConfig, C as ClientConfig, d as UploadOptions, e as UploadedFile, R as ResolvedClientConfig } from './types-ZCfjNZls.js';
2
+
3
+ interface PickerTheme {
4
+ /** Primary accent color (buttons, progress bar, focus rings). */
5
+ primary?: string;
6
+ /** Modal background. */
7
+ background?: string;
8
+ /** Default text color. */
9
+ foreground?: string;
10
+ /** Muted text (filenames, hints). */
11
+ muted?: string;
12
+ /** Border color for dropzone + cards. */
13
+ border?: string;
14
+ /** Border radius — accepts any CSS length. */
15
+ radius?: string;
16
+ /** Color mode hint — used to pick contrast-friendly defaults. */
17
+ mode?: 'light' | 'dark';
18
+ }
19
+ interface PickerBranding {
20
+ /** URL of a small logo to show in the modal header. */
21
+ logoUrl?: string;
22
+ /** Header title. Default: "Upload". */
23
+ title?: string;
24
+ /** Hide "Powered by UnionStack" footer. */
25
+ hideFooter?: boolean;
26
+ }
27
+ /** Source tabs available in the picker. Pass an array to hide ones you don't want. */
28
+ type PickerSource = 'device' | 'url';
29
+ interface PickerOptions extends Omit<BatchUploadOptions, 'signal'> {
30
+ /** Constrain selectable files (HTML accept syntax). */
31
+ /** Adding this to make this a true drop-in replacement for filestack */
32
+ accept?: string | string[];
33
+ /** Cap on file count selected at once. */
34
+ maxFiles?: number;
35
+ /** Max file size in bytes — additional client-side check before init. */
36
+ maxFileSize?: number;
37
+ /**
38
+ * Which file sources to surface as tabs in the picker. Default is
39
+ * `['device', 'url']` (both tabs visible). Set to `['device']` to hide
40
+ * the URL-import tab entirely.
41
+ */
42
+ fromSources?: PickerSource[];
43
+ /**
44
+ * Allow per-image editing (crop / circle / rotate) on queued image rows
45
+ * before upload starts. Defaults to `true`. Set to `false` to hide the
46
+ * Edit affordance — useful if your flow forbids client-side mutation.
47
+ */
48
+ imageEditing?: boolean;
49
+ /**
50
+ * Start uploading immediately when the user finishes picking/dropping files,
51
+ * skipping the explicit "Upload" button click. Defaults to `false` — users
52
+ * pick, optionally edit images, then click Upload. Set to `true` to skip the
53
+ * review step and kick the upload as soon as the selection is in.
54
+ * @default false
55
+ */
56
+ autoUpload?: boolean;
57
+ /**
58
+ * Lock the crop tool to a fixed aspect ratio. Overrides the per-key server
59
+ * setting. Omit to inherit whatever the API key is configured with.
60
+ */
61
+ cropAspectRatio?: {
62
+ width: number;
63
+ height: number;
64
+ };
65
+ /**
66
+ * Require every image to be cropped to {@link cropAspectRatio} before it can
67
+ * upload. Only takes effect when a ratio is set and image editing is enabled.
68
+ */
69
+ forceCrop?: boolean;
70
+ /** Reject images narrower than this many pixels (natural width). */
71
+ minImageWidth?: number;
72
+ /** Reject images shorter than this many pixels (natural height). */
73
+ minImageHeight?: number;
74
+ theme?: PickerTheme;
75
+ branding?: PickerBranding;
76
+ /** Where to mount the modal. Default: document.body. */
77
+ container?: HTMLElement;
78
+ onOpen?: () => void;
79
+ onClose?: () => void;
80
+ onCancel?: () => void;
81
+ onFileSelected?: (file: PickedFile) => void | PickedFile | Promise<PickedFile | void>;
82
+ }
83
+ interface PickerHandle {
84
+ open(): Promise<PickResponse>;
85
+ close(): void;
86
+ cancel(): void;
87
+ }
88
+
89
+ interface PickerHandleLike {
90
+ open(): Promise<PickResponse>;
91
+ close(): void;
92
+ cancel(): void;
93
+ }
94
+ declare class UnionStackClient {
95
+ private uploader;
96
+ private resolvedCfg;
97
+ /**
98
+ * Promise that resolves to the server-managed picker config. Pre-fetched on
99
+ * construction (unless `skipConfigPrefetch: true`) so the picker opens
100
+ * without a network hit. Fails silently — picker falls back to defaults.
101
+ */
102
+ pickerConfigPromise: Promise<PickerConfig | null>;
103
+ constructor(cfg: ClientConfig);
104
+ private missingKeyError;
105
+ upload(file: File | Blob, opts?: UploadOptions): Promise<UploadedFile>;
106
+ uploadMany(files: (File | Blob)[], opts?: BatchUploadOptions): Promise<PickResponse>;
107
+ picker(opts?: PickerOptions): PickerHandleLike;
108
+ /** Read-only accessor used by the React/picker packages. */
109
+ get config(): Readonly<ResolvedClientConfig>;
110
+ }
111
+
112
+ export { type PickerOptions as P, UnionStackClient as U, type PickerHandle as a, type PickerBranding as b, type PickerTheme as c };
@@ -0,0 +1,112 @@
1
+ import { B as BatchUploadOptions, a as PickedFile, P as PickResponse, f as PickerConfig, C as ClientConfig, d as UploadOptions, e as UploadedFile, R as ResolvedClientConfig } from './types-ZCfjNZls.cjs';
2
+
3
+ interface PickerTheme {
4
+ /** Primary accent color (buttons, progress bar, focus rings). */
5
+ primary?: string;
6
+ /** Modal background. */
7
+ background?: string;
8
+ /** Default text color. */
9
+ foreground?: string;
10
+ /** Muted text (filenames, hints). */
11
+ muted?: string;
12
+ /** Border color for dropzone + cards. */
13
+ border?: string;
14
+ /** Border radius — accepts any CSS length. */
15
+ radius?: string;
16
+ /** Color mode hint — used to pick contrast-friendly defaults. */
17
+ mode?: 'light' | 'dark';
18
+ }
19
+ interface PickerBranding {
20
+ /** URL of a small logo to show in the modal header. */
21
+ logoUrl?: string;
22
+ /** Header title. Default: "Upload". */
23
+ title?: string;
24
+ /** Hide "Powered by UnionStack" footer. */
25
+ hideFooter?: boolean;
26
+ }
27
+ /** Source tabs available in the picker. Pass an array to hide ones you don't want. */
28
+ type PickerSource = 'device' | 'url';
29
+ interface PickerOptions extends Omit<BatchUploadOptions, 'signal'> {
30
+ /** Constrain selectable files (HTML accept syntax). */
31
+ /** Adding this to make this a true drop-in replacement for filestack */
32
+ accept?: string | string[];
33
+ /** Cap on file count selected at once. */
34
+ maxFiles?: number;
35
+ /** Max file size in bytes — additional client-side check before init. */
36
+ maxFileSize?: number;
37
+ /**
38
+ * Which file sources to surface as tabs in the picker. Default is
39
+ * `['device', 'url']` (both tabs visible). Set to `['device']` to hide
40
+ * the URL-import tab entirely.
41
+ */
42
+ fromSources?: PickerSource[];
43
+ /**
44
+ * Allow per-image editing (crop / circle / rotate) on queued image rows
45
+ * before upload starts. Defaults to `true`. Set to `false` to hide the
46
+ * Edit affordance — useful if your flow forbids client-side mutation.
47
+ */
48
+ imageEditing?: boolean;
49
+ /**
50
+ * Start uploading immediately when the user finishes picking/dropping files,
51
+ * skipping the explicit "Upload" button click. Defaults to `false` — users
52
+ * pick, optionally edit images, then click Upload. Set to `true` to skip the
53
+ * review step and kick the upload as soon as the selection is in.
54
+ * @default false
55
+ */
56
+ autoUpload?: boolean;
57
+ /**
58
+ * Lock the crop tool to a fixed aspect ratio. Overrides the per-key server
59
+ * setting. Omit to inherit whatever the API key is configured with.
60
+ */
61
+ cropAspectRatio?: {
62
+ width: number;
63
+ height: number;
64
+ };
65
+ /**
66
+ * Require every image to be cropped to {@link cropAspectRatio} before it can
67
+ * upload. Only takes effect when a ratio is set and image editing is enabled.
68
+ */
69
+ forceCrop?: boolean;
70
+ /** Reject images narrower than this many pixels (natural width). */
71
+ minImageWidth?: number;
72
+ /** Reject images shorter than this many pixels (natural height). */
73
+ minImageHeight?: number;
74
+ theme?: PickerTheme;
75
+ branding?: PickerBranding;
76
+ /** Where to mount the modal. Default: document.body. */
77
+ container?: HTMLElement;
78
+ onOpen?: () => void;
79
+ onClose?: () => void;
80
+ onCancel?: () => void;
81
+ onFileSelected?: (file: PickedFile) => void | PickedFile | Promise<PickedFile | void>;
82
+ }
83
+ interface PickerHandle {
84
+ open(): Promise<PickResponse>;
85
+ close(): void;
86
+ cancel(): void;
87
+ }
88
+
89
+ interface PickerHandleLike {
90
+ open(): Promise<PickResponse>;
91
+ close(): void;
92
+ cancel(): void;
93
+ }
94
+ declare class UnionStackClient {
95
+ private uploader;
96
+ private resolvedCfg;
97
+ /**
98
+ * Promise that resolves to the server-managed picker config. Pre-fetched on
99
+ * construction (unless `skipConfigPrefetch: true`) so the picker opens
100
+ * without a network hit. Fails silently — picker falls back to defaults.
101
+ */
102
+ pickerConfigPromise: Promise<PickerConfig | null>;
103
+ constructor(cfg: ClientConfig);
104
+ private missingKeyError;
105
+ upload(file: File | Blob, opts?: UploadOptions): Promise<UploadedFile>;
106
+ uploadMany(files: (File | Blob)[], opts?: BatchUploadOptions): Promise<PickResponse>;
107
+ picker(opts?: PickerOptions): PickerHandleLike;
108
+ /** Read-only accessor used by the React/picker packages. */
109
+ get config(): Readonly<ResolvedClientConfig>;
110
+ }
111
+
112
+ export { type PickerOptions as P, UnionStackClient as U, type PickerHandle as a, type PickerBranding as b, type PickerTheme as c };
package/dist/index.cjs CHANGED
@@ -1,17 +1,18 @@
1
1
  'use strict';
2
2
 
3
- var chunkACQDEKCW_cjs = require('./chunk-ACQDEKCW.cjs');
3
+ var chunkIV76YPDA_cjs = require('./chunk-IV76YPDA.cjs');
4
+ require('./chunk-F4EVNUJZ.cjs');
4
5
 
5
6
  // src/index.ts
6
7
  var UnionStack = {
7
8
  init(cfg) {
8
- return new chunkACQDEKCW_cjs.UnionStackClient(cfg);
9
+ return new chunkIV76YPDA_cjs.UnionStackClient(cfg);
9
10
  }
10
11
  };
11
12
 
12
13
  Object.defineProperty(exports, "UnionStackClient", {
13
14
  enumerable: true,
14
- get: function () { return chunkACQDEKCW_cjs.UnionStackClient; }
15
+ get: function () { return chunkIV76YPDA_cjs.UnionStackClient; }
15
16
  });
16
17
  exports.UnionStack = UnionStack;
17
18
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["UnionStackClient"],"mappings":";;;;;AAGO,IAAM,UAAA,GAAa;AAAA,EACxB,KAAK,GAAA,EAAqC;AACxC,IAAA,OAAO,IAAIA,mCAAiB,GAAG,CAAA;AAAA,EACjC;AACF","file":"index.cjs","sourcesContent":["import { UnionStackClient } from './client.js';\nimport type { ClientConfig } from './types.js';\n\nexport const UnionStack = {\n init(cfg: ClientConfig): UnionStackClient {\n return new UnionStackClient(cfg);\n },\n};\n\nexport { UnionStackClient } from './client.js';\nexport type {\n ClientConfig,\n UploadOptions,\n BatchUploadOptions,\n PickedFile,\n UploadedFile,\n ProgressEvent,\n PickResponse,\n UploadError,\n UploadErrorCode,\n Source,\n} from './types.js';\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["UnionStackClient"],"mappings":";;;;;;AAGO,IAAM,UAAA,GAAa;AAAA,EACxB,KAAK,GAAA,EAAqC;AACxC,IAAA,OAAO,IAAIA,mCAAiB,GAAG,CAAA;AAAA,EACjC;AACF","file":"index.cjs","sourcesContent":["import { UnionStackClient } from './client.js';\nimport type { ClientConfig } from './types.js';\n\nexport const UnionStack = {\n init(cfg: ClientConfig): UnionStackClient {\n return new UnionStackClient(cfg);\n },\n};\n\nexport { UnionStackClient } from './client.js';\nexport type {\n ClientConfig,\n UploadOptions,\n BatchUploadOptions,\n PickedFile,\n UploadedFile,\n ProgressEvent,\n PickResponse,\n UploadError,\n UploadErrorCode,\n Source,\n} from './types.js';\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
- import { C as ClientConfig, U as UnionStackClient } from './client-I6TadQ-m.cjs';
2
- export { B as BatchUploadOptions, P as PickResponse, a as PickedFile, b as ProgressEvent, S as Source, c as UploadError, d as UploadErrorCode, e as UploadOptions, f as UploadedFile } from './client-I6TadQ-m.cjs';
1
+ import { U as UnionStackClient } from './client-DOTa3Mai.cjs';
2
+ import { C as ClientConfig } from './types-ZCfjNZls.cjs';
3
+ export { B as BatchUploadOptions, P as PickResponse, a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode, d as UploadOptions, e as UploadedFile } from './types-ZCfjNZls.cjs';
3
4
 
4
5
  declare const UnionStack: {
5
6
  init(cfg: ClientConfig): UnionStackClient;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { C as ClientConfig, U as UnionStackClient } from './client-I6TadQ-m.js';
2
- export { B as BatchUploadOptions, P as PickResponse, a as PickedFile, b as ProgressEvent, S as Source, c as UploadError, d as UploadErrorCode, e as UploadOptions, f as UploadedFile } from './client-I6TadQ-m.js';
1
+ import { U as UnionStackClient } from './client-C0qMOfb3.js';
2
+ import { C as ClientConfig } from './types-ZCfjNZls.js';
3
+ export { B as BatchUploadOptions, P as PickResponse, a as PickedFile, b as ProgressEvent, S as Source, U as UploadError, c as UploadErrorCode, d as UploadOptions, e as UploadedFile } from './types-ZCfjNZls.js';
3
4
 
4
5
  declare const UnionStack: {
5
6
  init(cfg: ClientConfig): UnionStackClient;
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
- import { UnionStackClient } from './chunk-TNWAUSLA.js';
2
- export { UnionStackClient } from './chunk-TNWAUSLA.js';
1
+ import { UnionStackClient } from './chunk-IIVRPVNX.js';
2
+ export { UnionStackClient } from './chunk-IIVRPVNX.js';
3
+ import './chunk-MFZ2JGLP.js';
3
4
 
4
5
  // src/index.ts
5
6
  var UnionStack = {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;AAGO,IAAM,UAAA,GAAa;AAAA,EACxB,KAAK,GAAA,EAAqC;AACxC,IAAA,OAAO,IAAI,iBAAiB,GAAG,CAAA;AAAA,EACjC;AACF","file":"index.js","sourcesContent":["import { UnionStackClient } from './client.js';\nimport type { ClientConfig } from './types.js';\n\nexport const UnionStack = {\n init(cfg: ClientConfig): UnionStackClient {\n return new UnionStackClient(cfg);\n },\n};\n\nexport { UnionStackClient } from './client.js';\nexport type {\n ClientConfig,\n UploadOptions,\n BatchUploadOptions,\n PickedFile,\n UploadedFile,\n ProgressEvent,\n PickResponse,\n UploadError,\n UploadErrorCode,\n Source,\n} from './types.js';\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAGO,IAAM,UAAA,GAAa;AAAA,EACxB,KAAK,GAAA,EAAqC;AACxC,IAAA,OAAO,IAAI,iBAAiB,GAAG,CAAA;AAAA,EACjC;AACF","file":"index.js","sourcesContent":["import { UnionStackClient } from './client.js';\nimport type { ClientConfig } from './types.js';\n\nexport const UnionStack = {\n init(cfg: ClientConfig): UnionStackClient {\n return new UnionStackClient(cfg);\n },\n};\n\nexport { UnionStackClient } from './client.js';\nexport type {\n ClientConfig,\n UploadOptions,\n BatchUploadOptions,\n PickedFile,\n UploadedFile,\n ProgressEvent,\n PickResponse,\n UploadError,\n UploadErrorCode,\n Source,\n} from './types.js';\n"]}