@ttt-productions/upload-ui 0.7.16 → 0.7.18

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 (84) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -3
  4. package/dist/index.js.map +1 -1
  5. package/dist/react/guard/guarded-link.d.ts +11 -0
  6. package/dist/react/guard/guarded-link.d.ts.map +1 -0
  7. package/dist/react/guard/guarded-link.js.map +1 -0
  8. package/dist/react/guard/index.d.ts +3 -3
  9. package/dist/react/guard/index.d.ts.map +1 -1
  10. package/dist/react/guard/index.js +3 -3
  11. package/dist/react/guard/index.js.map +1 -1
  12. package/dist/react/guard/local-upload-guard-provider.d.ts +31 -0
  13. package/dist/react/guard/local-upload-guard-provider.d.ts.map +1 -0
  14. package/dist/react/{local-upload-guard-provider.js → guard/local-upload-guard-provider.js} +3 -60
  15. package/dist/react/guard/local-upload-guard-provider.js.map +1 -0
  16. package/dist/react/guard/use-guarded-navigation.d.ts +3 -0
  17. package/dist/react/guard/use-guarded-navigation.d.ts.map +1 -0
  18. package/dist/react/guard/use-guarded-navigation.js +12 -0
  19. package/dist/react/guard/use-guarded-navigation.js.map +1 -0
  20. package/dist/react/tray/in-flight-uploads-provider.d.ts +141 -0
  21. package/dist/react/tray/in-flight-uploads-provider.d.ts.map +1 -0
  22. package/dist/react/{in-flight-uploads-provider.js → tray/in-flight-uploads-provider.js} +16 -136
  23. package/dist/react/tray/in-flight-uploads-provider.js.map +1 -0
  24. package/dist/react/tray/index.d.ts +4 -4
  25. package/dist/react/tray/index.d.ts.map +1 -1
  26. package/dist/react/tray/index.js +4 -4
  27. package/dist/react/tray/index.js.map +1 -1
  28. package/dist/react/tray/use-clear-upload-activity.d.ts +8 -0
  29. package/dist/react/tray/use-clear-upload-activity.d.ts.map +1 -0
  30. package/dist/react/tray/use-clear-upload-activity.js +13 -0
  31. package/dist/react/tray/use-clear-upload-activity.js.map +1 -0
  32. package/dist/react/{use-mark-upload-activity-seen.d.ts → tray/use-mark-upload-activity-seen.d.ts} +0 -4
  33. package/dist/react/tray/use-mark-upload-activity-seen.d.ts.map +1 -0
  34. package/dist/react/{use-mark-upload-activity-seen.js → tray/use-mark-upload-activity-seen.js} +0 -21
  35. package/dist/react/tray/use-mark-upload-activity-seen.js.map +1 -0
  36. package/dist/react/{use-upload-processing.d.ts → tray/use-upload-processing.d.ts} +0 -10
  37. package/dist/react/tray/use-upload-processing.d.ts.map +1 -0
  38. package/dist/react/{use-upload-processing.js → tray/use-upload-processing.js} +10 -20
  39. package/dist/react/tray/use-upload-processing.js.map +1 -0
  40. package/dist/react/upload/deferred-upload-form-shell.d.ts +28 -0
  41. package/dist/react/upload/deferred-upload-form-shell.d.ts.map +1 -0
  42. package/dist/react/{deferred-upload-form-shell.js → upload/deferred-upload-form-shell.js} +5 -2
  43. package/dist/react/upload/deferred-upload-form-shell.js.map +1 -0
  44. package/dist/react/upload/index.d.ts +2 -2
  45. package/dist/react/upload/index.d.ts.map +1 -1
  46. package/dist/react/upload/index.js +2 -2
  47. package/dist/react/upload/index.js.map +1 -1
  48. package/dist/react/upload/use-guarded-upload.d.ts +16 -0
  49. package/dist/react/upload/use-guarded-upload.d.ts.map +1 -0
  50. package/dist/react/{use-guarded-upload.js → upload/use-guarded-upload.js} +2 -15
  51. package/dist/react/upload/use-guarded-upload.js.map +1 -0
  52. package/dist/upload-display.d.ts +0 -14
  53. package/dist/upload-display.d.ts.map +1 -1
  54. package/dist/upload-display.js +11 -12
  55. package/dist/upload-display.js.map +1 -1
  56. package/package.json +5 -5
  57. package/dist/react/deferred-upload-form-shell.d.ts +0 -46
  58. package/dist/react/deferred-upload-form-shell.d.ts.map +0 -1
  59. package/dist/react/deferred-upload-form-shell.js.map +0 -1
  60. package/dist/react/guarded-link.d.ts +0 -38
  61. package/dist/react/guarded-link.d.ts.map +0 -1
  62. package/dist/react/guarded-link.js.map +0 -1
  63. package/dist/react/in-flight-uploads-provider.d.ts +0 -266
  64. package/dist/react/in-flight-uploads-provider.d.ts.map +0 -1
  65. package/dist/react/in-flight-uploads-provider.js.map +0 -1
  66. package/dist/react/local-upload-guard-provider.d.ts +0 -112
  67. package/dist/react/local-upload-guard-provider.d.ts.map +0 -1
  68. package/dist/react/local-upload-guard-provider.js.map +0 -1
  69. package/dist/react/use-clear-upload-activity.d.ts +0 -33
  70. package/dist/react/use-clear-upload-activity.d.ts.map +0 -1
  71. package/dist/react/use-clear-upload-activity.js +0 -31
  72. package/dist/react/use-clear-upload-activity.js.map +0 -1
  73. package/dist/react/use-guarded-navigation.d.ts +0 -10
  74. package/dist/react/use-guarded-navigation.d.ts.map +0 -1
  75. package/dist/react/use-guarded-navigation.js +0 -40
  76. package/dist/react/use-guarded-navigation.js.map +0 -1
  77. package/dist/react/use-guarded-upload.d.ts +0 -45
  78. package/dist/react/use-guarded-upload.d.ts.map +0 -1
  79. package/dist/react/use-guarded-upload.js.map +0 -1
  80. package/dist/react/use-mark-upload-activity-seen.d.ts.map +0 -1
  81. package/dist/react/use-mark-upload-activity-seen.js.map +0 -1
  82. package/dist/react/use-upload-processing.d.ts.map +0 -1
  83. package/dist/react/use-upload-processing.js.map +0 -1
  84. /package/dist/react/{guarded-link.js → guard/guarded-link.js} +0 -0
@@ -1,40 +0,0 @@
1
- 'use client';
2
- /**
3
- * Wraps a navigation action so it prompts the user while an upload or unsaved
4
- * work is registered. Returns a function that takes the consumer's actual navigation
5
- * call and either runs it immediately (nothing registered) or shows a confirm()
6
- * dialog first.
7
- *
8
- * Designed to be framework-agnostic — the consumer supplies the navigator
9
- * (Next.js router.push, React Router navigate, plain location.assign, etc.).
10
- * A FULL-PAGE navigator (`location.assign` / `location.replace`) passes
11
- * `{ fullPageNavigation: true }`, so the unload that follows a confirmed
12
- * navigation does not raise the browser's own "Leave site?" as a second prompt
13
- * (see `ConfirmNavigationOptions`). Router navigations pass nothing.
14
- *
15
- * Typical use inside a button:
16
- *
17
- * const guardedNav = useGuardedNavigation();
18
- * <Button onClick={() => guardedNav(() => router.push('/somewhere'))}>Go</Button>
19
- * <Button onClick={() => guardedNav(() => location.assign(url), { fullPageNavigation: true })}>Leave</Button>
20
- *
21
- * For links, use the `<GuardedLink>` render-prop wrapper.
22
- */
23
- import { useCallback } from 'react';
24
- import { useLocalUploadGuard } from './local-upload-guard-provider.js';
25
- /**
26
- * Returns a callable that wraps a navigation action. Calling the returned
27
- * function with `performNavigation` either invokes it immediately (when
28
- * nothing is registered) or shows a confirmation prompt; if the user confirms,
29
- * `performNavigation` is invoked. `options` passes through to
30
- * `confirmNavigation()`.
31
- */
32
- export function useGuardedNavigation() {
33
- const { confirmNavigation } = useLocalUploadGuard();
34
- return useCallback((performNavigation, options) => {
35
- if (confirmNavigation(options)) {
36
- performNavigation();
37
- }
38
- }, [confirmNavigation]);
39
- }
40
- //# sourceMappingURL=use-guarded-navigation.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-guarded-navigation.js","sourceRoot":"","sources":["../../src/react/use-guarded-navigation.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAiC,MAAM,kCAAkC,CAAC;AAEtG;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB;IAIlC,MAAM,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,EAAE,CAAC;IACpD,OAAO,WAAW,CAChB,CAAC,iBAA6B,EAAE,OAAkC,EAAE,EAAE;QACpE,IAAI,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,iBAAiB,CAAC,CACpB,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\n/**\n * Wraps a navigation action so it prompts the user while an upload or unsaved\n * work is registered. Returns a function that takes the consumer's actual navigation\n * call and either runs it immediately (nothing registered) or shows a confirm()\n * dialog first.\n *\n * Designed to be framework-agnostic — the consumer supplies the navigator\n * (Next.js router.push, React Router navigate, plain location.assign, etc.).\n * A FULL-PAGE navigator (`location.assign` / `location.replace`) passes\n * `{ fullPageNavigation: true }`, so the unload that follows a confirmed\n * navigation does not raise the browser's own \"Leave site?\" as a second prompt\n * (see `ConfirmNavigationOptions`). Router navigations pass nothing.\n *\n * Typical use inside a button:\n *\n * const guardedNav = useGuardedNavigation();\n * <Button onClick={() => guardedNav(() => router.push('/somewhere'))}>Go</Button>\n * <Button onClick={() => guardedNav(() => location.assign(url), { fullPageNavigation: true })}>Leave</Button>\n *\n * For links, use the `<GuardedLink>` render-prop wrapper.\n */\n\nimport { useCallback } from 'react';\nimport { useLocalUploadGuard, type ConfirmNavigationOptions } from './local-upload-guard-provider.js';\n\n/**\n * Returns a callable that wraps a navigation action. Calling the returned\n * function with `performNavigation` either invokes it immediately (when\n * nothing is registered) or shows a confirmation prompt; if the user confirms,\n * `performNavigation` is invoked. `options` passes through to\n * `confirmNavigation()`.\n */\nexport function useGuardedNavigation(): (\n performNavigation: () => void,\n options?: ConfirmNavigationOptions,\n) => void {\n const { confirmNavigation } = useLocalUploadGuard();\n return useCallback(\n (performNavigation: () => void, options?: ConfirmNavigationOptions) => {\n if (confirmNavigation(options)) {\n performNavigation();\n }\n },\n [confirmNavigation],\n );\n}\n"]}
@@ -1,45 +0,0 @@
1
- import type { FirebaseStorage } from 'firebase/storage';
2
- import type { UploadState } from '@ttt-productions/media-schemas';
3
- export interface GuardedUploadArgs {
4
- storage: FirebaseStorage;
5
- path: string;
6
- file: File;
7
- metadata: {
8
- contentType: string;
9
- };
10
- /** Stable identifier for the in-flight upload (used to register/unregister the local-upload guard). */
11
- uploadId: string;
12
- /** Optional progress callback. Fires with preparing → uploading (with percent) → finalizing → null on completion. */
13
- onProgress?: (state: UploadState | null) => void;
14
- /**
15
- * Optional cancellation signal. When aborted, the in-flight Storage upload
16
- * is canceled and `guardedUpload` rejects with the underlying AbortError.
17
- * Callers should treat AbortError as a user-initiated cancel (not a real
18
- * failure) — typically by checking `error.name === 'AbortError'` in the
19
- * mutation's onError and swallowing toasts/error UI for that case.
20
- */
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;
30
- }
31
- /**
32
- * Wraps `uploadFileResumable` with the canonical local-upload guard + phase reporting.
33
- *
34
- * Every upload-capable mutation hook MUST use this helper instead of calling
35
- * `uploadFileResumable` directly. The helper owns:
36
- * - phase reporting: preparing → uploading (with percent) → finalizing
37
- * - beforeunload guard registration during the upload window only
38
- * - error safety: the guard is unregistered in a `finally` block
39
- *
40
- * The helper does NOT call `onProgress?.(null)` — callers do that from the
41
- * mutation's `onSuccess` and `onError` callbacks (because the upload window
42
- * ends when the upload completes, but the mutation may have more work after).
43
- */
44
- export declare function useGuardedUpload(): (args: GuardedUploadArgs) => Promise<void>;
45
- //# sourceMappingURL=use-guarded-upload.d.ts.map
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
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"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-mark-upload-activity-seen.d.ts","sourceRoot":"","sources":["../../src/react/use-mark-upload-activity-seen.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,6BAA6B;IAC5C,yFAAyF;IACzF,MAAM,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,2EAA2E;IAC3E,aAAa,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC7D;AAED,0GAA0G;AAC1G,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;gBAEnB,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE;CAMlD;AAwBD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,6BAA6B,qFAS/E"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-mark-upload-activity-seen.js","sourceRoot":"","sources":["../../src/react/use-mark-upload-activity-seen.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAWpD,0GAA0G;AAC1G,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IAC3C,OAAO,CAAQ;IACf,WAAW,CAAW;IAE/B,YAAY,OAAc,EAAE,WAAqB;QAC/C,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AAED,KAAK,UAAU,aAAa,CAC1B,MAAoD,EACpD,aAAqB,EACrB,eAAyB;IAEzB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,sDAAsD,aAAa,GAAG,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,YAAY,GAAiB,IAAI,CAAC;IACtC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,IAAI,aAAa,EAAE,CAAC;QAC3E,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,aAAa,CAAC,CAAC;QAClE,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,YAAY,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,IAAI,YAAY;QAAE,MAAM,IAAI,2BAA2B,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAsC;IAC9E,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACnD,OAAO,WAAW,CAAwB;QACxC,UAAU,EAAE,CAAC,eAAe,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,eAAe,CAAC;QACtF,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE;YAClC,IAAI,KAAK,YAAY,2BAA2B;gBAAE,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;;gBACzF,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QACzC,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["'use client';\n\n/**\n * Generic mutation hook to mark terminal pendingMedia items as seen in the tray.\n *\n * Pure adapter: the consumer supplies `markFn` (typically a wrapped Firebase\n * callable in the consuming app that writes `uploadTraySeenAt`/`uploadTraySeenBy` on the\n * caller's own terminal pendingMedia docs). The package owns the useMutation\n * wiring and the optional `onError` hook; the consumer owns the network call.\n *\n * The provider's Firestore listener observes the `uploadTraySeenAt` write and\n * updates the in-flight upload records automatically — no optimistic update is\n * needed in this hook. Marking seen is tray UX state, not a sensitive action,\n * so it mirrors `useClearUploadActivity` exactly (no audit event).\n *\n * The mutation takes every id to mark (typically every currently-unseen terminal\n * item when the File-status tab opens) and sends them to `markFn` in sequential\n * calls of at most `maxIdsPerCall` — the app's own per-call cap, so no call is\n * refused for its size. A failed call does not stop the rest: its ids simply stay\n * unseen. When any call failed, the mutation fails, and `onError` receives the first\n * failure and every id left unmarked. An empty array makes no call.\n */\n\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface MarkUploadActivitySeenOptions {\n /** Network call performing the mark-seen for at most `maxIdsPerCall` pendingMediaIds. */\n markFn: (pendingMediaIds: string[]) => Promise<void>;\n /** The most ids one `markFn` call accepts — the app's own per-call cap. */\n maxIdsPerCall: number;\n /** Optional error callback. Receives the first failure and every id that was not marked. */\n onError?: (error: Error, pendingMediaIds: string[]) => void;\n}\n\n/** The mutation's failure when one or more calls failed: the first failure, and the ids left unmarked. */\nexport class MarkUploadActivitySeenError extends Error {\n readonly failure: Error;\n readonly unmarkedIds: string[];\n\n constructor(failure: Error, unmarkedIds: string[]) {\n super(failure.message);\n this.name = 'MarkUploadActivitySeenError';\n this.failure = failure;\n this.unmarkedIds = unmarkedIds;\n }\n}\n\nasync function markInBatches(\n markFn: (pendingMediaIds: string[]) => Promise<void>,\n maxIdsPerCall: number,\n pendingMediaIds: string[],\n): Promise<void> {\n if (!Number.isInteger(maxIdsPerCall) || maxIdsPerCall < 1) {\n throw new Error(`maxIdsPerCall must be a positive whole number, got ${maxIdsPerCall}.`);\n }\n let firstFailure: Error | null = null;\n const unmarkedIds: string[] = [];\n for (let start = 0; start < pendingMediaIds.length; start += maxIdsPerCall) {\n const batch = pendingMediaIds.slice(start, start + maxIdsPerCall);\n try {\n await markFn(batch);\n } catch (err) {\n firstFailure ??= err instanceof Error ? err : new Error(String(err));\n unmarkedIds.push(...batch);\n }\n }\n if (firstFailure) throw new MarkUploadActivitySeenError(firstFailure, unmarkedIds);\n}\n\nexport function useMarkUploadActivitySeen(options: MarkUploadActivitySeenOptions) {\n const { markFn, maxIdsPerCall, onError } = options;\n return useMutation<void, Error, string[]>({\n mutationFn: (pendingMediaIds) => markInBatches(markFn, maxIdsPerCall, pendingMediaIds),\n onError: (error, pendingMediaIds) => {\n if (error instanceof MarkUploadActivitySeenError) onError?.(error.failure, error.unmarkedIds);\n else onError?.(error, pendingMediaIds);\n },\n });\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-upload-processing.d.ts","sourceRoot":"","sources":["../../src/react/use-upload-processing.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,GAAG,gBAAgB,CAAC;IACtG,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB;AAOD,MAAM,WAAW,0BAA0B;IACzC,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0CAA0C;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2CAA2C;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAyED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,SAAS,MAAM,GAAG,MAAM,EACrE,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,EACnD,OAAO,GAAE,0BAA+B,GACvC,qBAAqB,CAqBvB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-upload-processing.js","sourceRoot":"","sources":["../../src/react/use-upload-processing.ts"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\n/**\n * Adapter that maps `useInFlightUpload` state to the legacy\n * `{ isProcessing, message, isComplete, isRejected, isFailed }` shape used\n * by per-component spinners and overlays.\n *\n * Routing of toasts and rejection dialogs lives in `InFlightUploadsProvider`\n * via the consumer-supplied callbacks — `useUploadProcessing` only surfaces\n * local UI state. The `onTerminal` callback fires once per terminal status\n * (completed / failed / rejected) and is intended for local UI cleanup\n * (clearing form state, closing modals, etc.).\n */\n\nimport { useEffect, useRef } from 'react';\nimport { isPendingMediaNonTerminalStatus, PendingMediaStatusSchema } from '@ttt-productions/media-schemas';\nimport { useInFlightUpload, type InFlightUpload } from './in-flight-uploads-provider.js';\n\n// Pending-media status values derive from media-schemas' one declaration.\nconst STATUS = PendingMediaStatusSchema.enum;\n\nexport interface UploadProcessingState {\n status: 'idle' | 'pending' | 'processing' | 'success' | 'failed' | 'rejected-text' | 'rejected-media';\n message: string;\n errorMessage?: string;\n isProcessing: boolean;\n isComplete: boolean;\n isFailed: boolean;\n isRejected: boolean;\n}\n\nconst DEFAULT_PROCESSING_MESSAGE = 'Processing your content...';\nconst DEFAULT_SUCCESS_MESSAGE = 'Complete!';\nconst DEFAULT_FAILED_MESSAGE = 'Processing failed';\nconst DEFAULT_REJECTED_MESSAGE = 'Content rejected';\n\nexport interface UseUploadProcessingOptions {\n /** Override the processing-phase message. */\n processingMessage?: string;\n /** Override the success-phase message. */\n successMessage?: string;\n /** Override the failed-phase message. */\n failedMessage?: string;\n /** Override the rejected-phase message. */\n rejectedMessage?: string;\n}\n\nfunction buildState<TFileOrigin extends string>(\n upload: InFlightUpload<TFileOrigin> | undefined,\n opts: UseUploadProcessingOptions,\n): UploadProcessingState {\n const processingMessage = opts.processingMessage ?? DEFAULT_PROCESSING_MESSAGE;\n const successMessage = opts.successMessage ?? DEFAULT_SUCCESS_MESSAGE;\n const failedMessage = opts.failedMessage ?? DEFAULT_FAILED_MESSAGE;\n const rejectedMessage = opts.rejectedMessage ?? DEFAULT_REJECTED_MESSAGE;\n\n if (!upload) {\n return {\n status: 'idle',\n message: '',\n isProcessing: false,\n isComplete: false,\n isFailed: false,\n isRejected: false,\n };\n }\n if (isPendingMediaNonTerminalStatus(upload.status)) {\n return {\n status: upload.status,\n message: processingMessage,\n isProcessing: true,\n isComplete: false,\n isFailed: false,\n isRejected: false,\n };\n }\n if (upload.status === STATUS.completed) {\n return {\n status: 'success',\n message: successMessage,\n isProcessing: false,\n isComplete: true,\n isFailed: false,\n isRejected: false,\n };\n }\n if (upload.status === STATUS.failed) {\n return {\n status: 'failed',\n message: failedMessage,\n errorMessage: upload.errorMessage,\n isProcessing: false,\n isComplete: false,\n isFailed: true,\n isRejected: false,\n };\n }\n if (upload.status === STATUS.rejected) {\n return {\n status: upload.rejectionType === 'text' ? 'rejected-text' : 'rejected-media',\n message: rejectedMessage,\n errorMessage: upload.errorMessage,\n isProcessing: false,\n isComplete: false,\n isFailed: false,\n isRejected: true,\n };\n }\n return {\n status: 'processing',\n message: processingMessage,\n isProcessing: true,\n isComplete: false,\n isFailed: false,\n isRejected: false,\n };\n}\n\n/**\n * Returns local UI processing state for the given pendingMediaId. If the\n * `onTerminal` callback is provided, it fires once when the doc reaches a\n * terminal status (completed / failed / rejected). Use `onTerminal` for\n * local UI cleanup — global toast/dialog routing belongs in the provider.\n */\nexport function useUploadProcessing<TFileOrigin extends string = string>(\n pendingMediaId: string | null | undefined,\n onTerminal?: (state: UploadProcessingState) => void,\n options: UseUploadProcessingOptions = {},\n): UploadProcessingState {\n const upload = useInFlightUpload<TFileOrigin>(pendingMediaId);\n const state = buildState(upload, options);\n const lastFiredRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (!onTerminal) return;\n if (!pendingMediaId) {\n lastFiredRef.current = null;\n return;\n }\n if (state.isComplete || state.isFailed || state.isRejected) {\n const sig = `${pendingMediaId}:${state.status}`;\n if (lastFiredRef.current !== sig) {\n lastFiredRef.current = sig;\n onTerminal(state);\n }\n }\n }, [pendingMediaId, state.status, state.isComplete, state.isFailed, state.isRejected, state, onTerminal]);\n\n return state;\n}\n"]}