@ttt-productions/upload-ui 0.7.5 → 0.7.6

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.
@@ -19,6 +19,14 @@ export interface GuardedUploadArgs {
19
19
  * mutation's onError and swallowing toasts/error UI for that case.
20
20
  */
21
21
  signal?: AbortSignal;
22
+ /**
23
+ * EXPLICIT opt-in for the NEUTRAL `application/octet-stream` content type
24
+ * (canonical-upload-content-classification): only for advisory picker files
25
+ * with unknown browser metadata, so the server byte inspector sees unknown
26
+ * as unknown. Threaded verbatim to `uploadFileResumable`, whose media-only
27
+ * default stays intact for every consumer that omits it.
28
+ */
29
+ allowNeutralContentType?: boolean;
22
30
  }
23
31
  /**
24
32
  * Wraps `uploadFileResumable` with the canonical local-upload guard + phase reporting.
@@ -1 +1 @@
1
- {"version":3,"file":"use-guarded-upload.d.ts","sourceRoot":"","sources":["../../src/react/use-guarded-upload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAGlE,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,eAAe,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,uGAAuG;IACvG,QAAQ,EAAE,MAAM,CAAC;IACjB,qHAAqH;IACrH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,WAGI,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC,CAmBpE"}
1
+ {"version":3,"file":"use-guarded-upload.d.ts","sourceRoot":"","sources":["../../src/react/use-guarded-upload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAGlE,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,eAAe,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,uGAAuG;IACvG,QAAQ,EAAE,MAAM,CAAC;IACjB,qHAAqH;IACrH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,WAGI,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC,CAoBpE"}
@@ -17,7 +17,7 @@ import { useLocalUploadGuard } from './local-upload-guard-provider.js';
17
17
  export function useGuardedUpload() {
18
18
  const { registerUpload, unregisterUpload } = useLocalUploadGuard();
19
19
  return useCallback(async (args) => {
20
- const { uploadId, onProgress, storage, path, file, metadata, signal } = args;
20
+ const { uploadId, onProgress, storage, path, file, metadata, signal, allowNeutralContentType } = args;
21
21
  onProgress?.({ phase: 'preparing', percent: null });
22
22
  registerUpload(uploadId);
23
23
  try {
@@ -27,6 +27,7 @@ export function useGuardedUpload() {
27
27
  file,
28
28
  metadata,
29
29
  signal,
30
+ ...(allowNeutralContentType === true ? { allowNeutralContentType: true } : {}),
30
31
  onProgress: ({ percent }) => onProgress?.({ phase: 'uploading', percent }),
31
32
  });
32
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-guarded-upload.js","sourceRoot":"","sources":["../../src/react/use-guarded-upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAG3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAqBvE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB;IAC5B,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAEnE,OAAO,WAAW,CAAC,KAAK,EAAE,IAAuB,EAAiB,EAAE;QAChE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAE7E,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzB,IAAI,CAAC;YACD,MAAM,mBAAmB,CAAC;gBACtB,OAAO;gBACP,IAAI;gBACJ,IAAI;gBACJ,QAAQ;gBACR,MAAM;gBACN,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;aAC7E,CAAC,CAAC;QACP,CAAC;gBAAS,CAAC;YACP,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QACD,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAC3C,CAAC","sourcesContent":["import { useCallback } from 'react';\nimport { uploadFileResumable } from '@ttt-productions/upload-core/browser';\nimport type { FirebaseStorage } from 'firebase/storage';\nimport type { UploadState } from '@ttt-productions/media-schemas';\nimport { useLocalUploadGuard } from './local-upload-guard-provider.js';\n\nexport interface GuardedUploadArgs {\n storage: FirebaseStorage;\n path: string;\n file: File;\n metadata: { contentType: string };\n /** Stable identifier for the in-flight upload (used to register/unregister the local-upload guard). */\n uploadId: string;\n /** Optional progress callback. Fires with preparing → uploading (with percent) → finalizing → null on completion. */\n onProgress?: (state: UploadState | null) => void;\n /**\n * Optional cancellation signal. When aborted, the in-flight Storage upload\n * is canceled and `guardedUpload` rejects with the underlying AbortError.\n * Callers should treat AbortError as a user-initiated cancel (not a real\n * failure) — typically by checking `error.name === 'AbortError'` in the\n * mutation's onError and swallowing toasts/error UI for that case.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Wraps `uploadFileResumable` with the canonical local-upload guard + phase reporting.\n *\n * Every upload-capable mutation hook MUST use this helper instead of calling\n * `uploadFileResumable` directly. The helper owns:\n * - phase reporting: preparing → uploading (with percent) → finalizing\n * - beforeunload guard registration during the upload window only\n * - error safety: the guard is unregistered in a `finally` block\n *\n * The helper does NOT call `onProgress?.(null)` — callers do that from the\n * mutation's `onSuccess` and `onError` callbacks (because the upload window\n * ends when the upload completes, but the mutation may have more work after).\n */\nexport function useGuardedUpload() {\n const { registerUpload, unregisterUpload } = useLocalUploadGuard();\n\n return useCallback(async (args: GuardedUploadArgs): Promise<void> => {\n const { uploadId, onProgress, storage, path, file, metadata, signal } = args;\n\n onProgress?.({ phase: 'preparing', percent: null });\n registerUpload(uploadId);\n try {\n await uploadFileResumable({\n storage,\n path,\n file,\n metadata,\n signal,\n onProgress: ({ percent }) => onProgress?.({ phase: 'uploading', percent }),\n });\n } finally {\n unregisterUpload(uploadId);\n }\n onProgress?.({ phase: 'finalizing', percent: null });\n }, [registerUpload, unregisterUpload]);\n}\n"]}
1
+ {"version":3,"file":"use-guarded-upload.js","sourceRoot":"","sources":["../../src/react/use-guarded-upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAG3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AA6BvE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB;IAC5B,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAEnE,OAAO,WAAW,CAAC,KAAK,EAAE,IAAuB,EAAiB,EAAE;QAChE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC;QAEtG,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzB,IAAI,CAAC;YACD,MAAM,mBAAmB,CAAC;gBACtB,OAAO;gBACP,IAAI;gBACJ,IAAI;gBACJ,QAAQ;gBACR,MAAM;gBACN,GAAG,CAAC,uBAAuB,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9E,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;aAC7E,CAAC,CAAC;QACP,CAAC;gBAAS,CAAC;YACP,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QACD,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC,EAAE,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAC3C,CAAC","sourcesContent":["import { useCallback } from 'react';\nimport { uploadFileResumable } from '@ttt-productions/upload-core/browser';\nimport type { FirebaseStorage } from 'firebase/storage';\nimport type { UploadState } from '@ttt-productions/media-schemas';\nimport { useLocalUploadGuard } from './local-upload-guard-provider.js';\n\nexport interface GuardedUploadArgs {\n storage: FirebaseStorage;\n path: string;\n file: File;\n metadata: { contentType: string };\n /** Stable identifier for the in-flight upload (used to register/unregister the local-upload guard). */\n uploadId: string;\n /** Optional progress callback. Fires with preparing → uploading (with percent) → finalizing → null on completion. */\n onProgress?: (state: UploadState | null) => void;\n /**\n * Optional cancellation signal. When aborted, the in-flight Storage upload\n * is canceled and `guardedUpload` rejects with the underlying AbortError.\n * Callers should treat AbortError as a user-initiated cancel (not a real\n * failure) — typically by checking `error.name === 'AbortError'` in the\n * mutation's onError and swallowing toasts/error UI for that case.\n */\n signal?: AbortSignal;\n /**\n * EXPLICIT opt-in for the NEUTRAL `application/octet-stream` content type\n * (canonical-upload-content-classification): only for advisory picker files\n * with unknown browser metadata, so the server byte inspector sees unknown\n * as unknown. Threaded verbatim to `uploadFileResumable`, whose media-only\n * default stays intact for every consumer that omits it.\n */\n allowNeutralContentType?: boolean;\n}\n\n/**\n * Wraps `uploadFileResumable` with the canonical local-upload guard + phase reporting.\n *\n * Every upload-capable mutation hook MUST use this helper instead of calling\n * `uploadFileResumable` directly. The helper owns:\n * - phase reporting: preparing → uploading (with percent) → finalizing\n * - beforeunload guard registration during the upload window only\n * - error safety: the guard is unregistered in a `finally` block\n *\n * The helper does NOT call `onProgress?.(null)` — callers do that from the\n * mutation's `onSuccess` and `onError` callbacks (because the upload window\n * ends when the upload completes, but the mutation may have more work after).\n */\nexport function useGuardedUpload() {\n const { registerUpload, unregisterUpload } = useLocalUploadGuard();\n\n return useCallback(async (args: GuardedUploadArgs): Promise<void> => {\n const { uploadId, onProgress, storage, path, file, metadata, signal, allowNeutralContentType } = args;\n\n onProgress?.({ phase: 'preparing', percent: null });\n registerUpload(uploadId);\n try {\n await uploadFileResumable({\n storage,\n path,\n file,\n metadata,\n signal,\n ...(allowNeutralContentType === true ? { allowNeutralContentType: true } : {}),\n onProgress: ({ percent }) => onProgress?.({ phase: 'uploading', percent }),\n });\n } finally {\n unregisterUpload(uploadId);\n }\n onProgress?.({ phase: 'finalizing', percent: null });\n }, [registerUpload, unregisterUpload]);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/upload-ui",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Upload UI primitives: local upload guard provider, useGuardedUpload helper, DeferredUploadFormShell for forms that defer Firebase Storage upload until form submit.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -40,10 +40,10 @@
40
40
  "prepublishOnly": "npm run clean && npm run build"
41
41
  },
42
42
  "dependencies": {
43
- "@ttt-productions/file-input": "^0.11.4",
44
- "@ttt-productions/media-schemas": "^0.14.2",
45
- "@ttt-productions/ui-core": "^0.11.7",
46
- "@ttt-productions/upload-core": "^0.7.2"
43
+ "@ttt-productions/file-input": "^0.11.8",
44
+ "@ttt-productions/media-schemas": "^0.14.5",
45
+ "@ttt-productions/ui-core": "^0.11.12",
46
+ "@ttt-productions/upload-core": "^0.7.3"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@tanstack/react-query": ">=5.0.0",