@ttt-productions/upload-ui 0.7.4 → 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.
- package/dist/index.js.map +1 -1
- package/dist/react/deferred-upload-form-shell.js.map +1 -1
- package/dist/react/guard/index.js.map +1 -1
- package/dist/react/guarded-link.js.map +1 -1
- package/dist/react/in-flight-uploads-provider.js.map +1 -1
- package/dist/react/local-upload-guard-provider.js.map +1 -1
- package/dist/react/tray/index.js.map +1 -1
- package/dist/react/upload/index.js.map +1 -1
- package/dist/react/upload-activity-tray.js.map +1 -1
- package/dist/react/use-clear-upload-activity.js.map +1 -1
- package/dist/react/use-guarded-navigation.js.map +1 -1
- package/dist/react/use-guarded-upload.d.ts +8 -0
- package/dist/react/use-guarded-upload.d.ts.map +1 -1
- package/dist/react/use-guarded-upload.js +2 -1
- package/dist/react/use-guarded-upload.js.map +1 -1
- package/dist/react/use-mark-upload-activity-seen.js.map +1 -1
- package/dist/react/use-upload-processing.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"","sourcesContent":["// Server-safe entry. React code lives at `@ttt-productions/upload-ui/react/guard`, `/react/upload`, and `/react/tray`.\n// This file is intentionally empty; the package's public surface is exposed via\n// the `./react/guard`, `./react/upload`, and `./react/tray` subpaths. Keeping main\n// empty preserves the server-safe contract (no React imports leak through\n// `import x from '@ttt-productions/upload-ui'`).\nexport { };"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deferred-upload-form-shell.js","sourceRoot":"","sources":["../../src/react/deferred-upload-form-shell.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"deferred-upload-form-shell.js","sourceRoot":"","sources":["../../src/react/deferred-upload-form-shell.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport React, {\n useState,\n useRef,\n useCallback,\n useImperativeHandle,\n forwardRef,\n type ReactNode,\n type Ref,\n} from 'react';\nimport { MediaInput } from '@ttt-productions/file-input/react';\nimport type { MediaInputChangePayload } from '@ttt-productions/file-input';\nimport type { MediaOriginSpec, UploadState } from '@ttt-productions/media-schemas';\n\nexport interface DeferredUploadFormShellHandle {\n submit: () => void;\n}\n\nexport interface DeferredUploadFormShellProps<\n TVariables extends {\n onProgress?: (s: UploadState | null) => void;\n signal?: AbortSignal;\n },\n TResult = unknown,\n> {\n /** The media-origin spec describing accept patterns, size caps, and label.\n * Consumers pass this directly — the shell does not look it up from a registry. */\n spec: MediaOriginSpec;\n mutation: {\n mutateAsync: (vars: TVariables) => Promise<TResult>;\n isPending: boolean;\n };\n buildVariables: (\n file: File | null,\n onProgress: (s: UploadState | null) => void,\n signal: AbortSignal,\n ) => TVariables;\n onSuccess?: (result: TResult) => void;\n onError?: (err: unknown) => void;\n /**\n * Optional callback fired whenever the shell's internal selectedFile state\n * changes — on user select, on user clear, and on the post-success internal\n * reset. Forms typically use this to mirror selectedFile externally so they\n * can compute their own submit-button `disabled` flag (e.g. require-a-file\n * submit gating).\n */\n onFileChange?: (file: File | null) => void;\n /**\n * Optional guard forwarded to MediaInput, fired before the picker/capture\n * opens for any action. Return false (or a Promise resolving false) to abort\n * — e.g. an email-verification gate. See MediaInputProps.onBeforeSelect.\n */\n onBeforeSelect?: () => boolean | Promise<boolean>;\n children?: ReactNode;\n}\n\nfunction DeferredUploadFormShellInner<\n TVariables extends {\n onProgress?: (s: UploadState | null) => void;\n signal?: AbortSignal;\n },\n TResult = unknown,\n>(\n props: DeferredUploadFormShellProps<TVariables, TResult>,\n ref: Ref<DeferredUploadFormShellHandle>,\n) {\n const {\n spec,\n mutation,\n buildVariables,\n onSuccess,\n onError,\n onFileChange,\n onBeforeSelect,\n children,\n } = props;\n\n const [selectedFile, setSelectedFile] = useState<File | null>(null);\n const [uploadState, setUploadState] = useState<UploadState | null>(null);\n const fileAreaRef = useRef<HTMLDivElement>(null);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const handleMediaChange = useCallback((payload: MediaInputChangePayload) => {\n const next = payload.error ? null : (payload.file ?? null);\n setSelectedFile(next);\n onFileChange?.(next);\n }, [onFileChange]);\n\n const handleClear = useCallback(() => {\n setSelectedFile(null);\n onFileChange?.(null);\n }, [onFileChange]);\n\n const handleCancel = useCallback(() => {\n abortControllerRef.current?.abort();\n }, []);\n\n const handleSubmit = useCallback(async () => {\n if (mutation.isPending) return;\n if (selectedFile) {\n fileAreaRef.current?.focus();\n }\n const controller = new AbortController();\n abortControllerRef.current = controller;\n try {\n const result = await mutation.mutateAsync(\n buildVariables(selectedFile, setUploadState, controller.signal),\n );\n setUploadState(null);\n setSelectedFile(null);\n onFileChange?.(null);\n onSuccess?.(result);\n } catch (err) {\n setUploadState(null);\n // User-initiated cancel: swallow the AbortError, reset selection, do not fire onError.\n if (err instanceof Error && err.name === 'AbortError') {\n setSelectedFile(null);\n onFileChange?.(null);\n return;\n }\n onError?.(err);\n } finally {\n abortControllerRef.current = null;\n }\n }, [mutation, selectedFile, buildVariables, onSuccess, onError, onFileChange]);\n\n useImperativeHandle(ref, () => ({ submit: () => { void handleSubmit(); } }), [handleSubmit]);\n\n return (\n <>\n {children}\n\n <div\n ref={fileAreaRef}\n tabIndex={-1}\n aria-live=\"polite\"\n className=\"outline-none\"\n >\n <MediaInput\n spec={spec}\n selectedFile={selectedFile}\n uploadState={uploadState}\n isLoading={mutation.isPending}\n disabled={mutation.isPending}\n onChange={handleMediaChange}\n onClear={handleClear}\n onCancel={handleCancel}\n onBeforeSelect={onBeforeSelect}\n />\n </div>\n </>\n );\n}\n\nexport const DeferredUploadFormShell = forwardRef(DeferredUploadFormShellInner) as <\n TVariables extends {\n onProgress?: (s: UploadState | null) => void;\n signal?: AbortSignal;\n },\n TResult = unknown,\n>(\n props: DeferredUploadFormShellProps<TVariables, TResult> & { ref?: Ref<DeferredUploadFormShellHandle> },\n) => React.ReactElement;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/guard/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,GAE5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EACL,WAAW,GAGZ,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/guard/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,2BAA2B,GAE5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EACL,WAAW,GAGZ,MAAM,oBAAoB,CAAC","sourcesContent":["export {\n LocalUploadGuardProvider,\n useLocalUploadGuard,\n useLocalUploadGuardContext,\n useOptionalLocalUploadGuard,\n type LocalUploadGuardProviderProps,\n} from '../local-upload-guard-provider.js';\nexport { useGuardedNavigation } from '../use-guarded-navigation.js';\nexport {\n GuardedLink,\n type GuardedLinkProps,\n type GuardedLinkRenderArgs,\n} from '../guarded-link.js';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guarded-link.js","sourceRoot":"","sources":["../../src/react/guarded-link.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AA6Bb,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAcvE,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IACvC,MAAM,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAEpD,MAAM,OAAO,GAAG,CAAC,KAA8B,EAAE,EAAE;QACjD,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YACzB,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,4BAAG,UAAU,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAI,CAAC;AAClD,CAAC"}
|
|
1
|
+
{"version":3,"file":"guarded-link.js","sourceRoot":"","sources":["../../src/react/guarded-link.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AA6Bb,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAcvE,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IACvC,MAAM,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAEpD,MAAM,OAAO,GAAG,CAAC,KAA8B,EAAE,EAAE;QACjD,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YACzB,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,4BAAG,UAAU,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAI,CAAC;AAClD,CAAC","sourcesContent":["'use client';\n\n/**\n * Render-prop link wrapper that guards navigation when an upload is in\n * progress. The consumer owns the actual navigator component (Next.js Link,\n * React Router Link, plain anchor, etc.) — this wrapper only injects the\n * onClick interceptor.\n *\n * Why render-prop and not `as={Link}`? Polymorphic `as` props create\n * notoriously bad TypeScript inference and force the wrapper to forward all\n * link-specific props. Render-prop keeps the consumer in full control of the\n * link API, costs one extra wrapper closure, and keeps upload-ui agnostic of\n * Next.js / React Router / etc.\n *\n * Design note: the design spec lists `<GuardedNavigationButton>` as a second\n * component. We deliberately don't ship it — buttons that navigate use\n * `useGuardedNavigation()` directly in one line. A second component would\n * split the same surface for no payoff.\n *\n * Usage:\n *\n * <GuardedLink renderLink={({ onClick, children }) => (\n * <Link href=\"/your/destination\" onClick={onClick}>{children}</Link>\n * )}>\n * View all uploads →\n * </GuardedLink>\n */\n\nimport type { MouseEvent, ReactNode } from 'react';\nimport { useLocalUploadGuard } from './local-upload-guard-provider.js';\n\nexport interface GuardedLinkRenderArgs {\n /** Click handler the consumer MUST attach to its underlying link element. */\n onClick: (event: MouseEvent<HTMLElement>) => void;\n /** The children passed to `<GuardedLink>` — forward them to the link. */\n children: ReactNode;\n}\n\nexport interface GuardedLinkProps {\n children: ReactNode;\n renderLink: (args: GuardedLinkRenderArgs) => ReactNode;\n}\n\nexport function GuardedLink(props: GuardedLinkProps) {\n const { children, renderLink } = props;\n const { confirmNavigation } = useLocalUploadGuard();\n\n const onClick = (event: MouseEvent<HTMLElement>) => {\n if (!confirmNavigation()) {\n event.preventDefault();\n }\n };\n\n return <>{renderLink({ onClick, children })}</>;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"in-flight-uploads-provider.js","sourceRoot":"","sources":["../../src/react/in-flight-uploads-provider.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"in-flight-uploads-provider.js","sourceRoot":"","sources":["../../src/react/in-flight-uploads-provider.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// SANCTIONED EXCEPTION to the \"packages read/write Firestore only through\n// @ttt-productions/query-core\" rule (see docs/packages/package-architecture.md →\n// \"Firestore access goes through query-core\").\n//\n// WHY this provider reads Firestore directly instead of via a query-core hook:\n// 1. It needs snapshot *transition events* — onSnapshot's `docChanges()` with\n// added / modified / removed — to fire one-shot terminal callbacks and to\n// suppress the initial snapshot. query-core's hooks return \"the current\n// list\", not per-doc transitions, so they cannot express this state machine.\n// 2. The subscription is already abstracted behind an injectable\n// `FirestoreSubscribeFn` (the `subscribe` prop); the direct firebase code\n// path lives ONLY in `defaultFirestoreSubscribe` below and is fully\n// swappable (tests / alternate backends inject their own).\n// 3. The static ESM `firebase/firestore` import is load-bearing for Next.js +\n// Turbopack module identity (see defaultFirestoreSubscribe's comment).\n//\n// Do NOT \"migrate\" this onto query-core without preserving docChanges() semantics.\n// ─────────────────────────────────────────────────────────────────────────────\nimport { collection, onSnapshot, query, where } from 'firebase/firestore';\n\n/**\n * Generic in-flight uploads provider.\n *\n * Provides a global Map of in-flight upload state by `pendingMediaId`, derived\n * from a Firestore listener over the consumer-supplied collection. On terminal\n * status transitions observed THIS SESSION, fires consumer-supplied success /\n * failure / rejection callbacks. Records monitoring breadcrumbs and parse\n * errors through the injected monitoring callback.\n *\n * EVERY app-specific value is supplied by the consumer:\n * - userId resolution\n * - Firestore `db` reference\n * - collection path\n * - listener time window (ms)\n * - parser/schema for raw Firestore doc → typed PendingMedia\n * - success copy per origin\n * - notification callback (cache invalidation, etc.)\n * - toast callback\n * - rejection callback (for the media-rejection dialog or equivalent)\n * - monitoring callback (breadcrumbs + captured errors)\n *\n * Read APIs:\n * - `useInFlightUploadsState()` — full Map.\n * - `useInFlightUpload(id)` — single doc, narrowable on status.\n * - `useUploadActivityState()` — tray-visible items, sorted newest-first.\n *\n * The package owns the deduplication, initial-snapshot suppression, and\n * non-terminal → terminal transition tracking. It does NOT own anything about\n * what a file-origin is or what message text appears in toasts.\n */\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\n// =============================================================================\n// Generic shape of the data the provider tracks\n// =============================================================================\n\n/**\n * Generic pending-media status. Defined here so upload-ui has no dependency\n * on any app-specific package.\n */\nexport type InFlightUploadStatus =\n | 'pending'\n | 'processing'\n | 'completed'\n | 'failed'\n | 'rejected';\n\n/**\n * Generic in-flight upload record. The provider keeps a Map<id, InFlightUpload>\n * built from each parsed PendingMedia. Consumers parameterize the `fileOrigin`\n * type via the parser's return type (the provider treats it as opaque).\n *\n * `TFileOrigin` defaults to `string` so unannotated consumers get a permissive\n * shape; consuming apps bind it to their own `FileOrigin` union at the call site.\n */\nexport type InFlightUploadBase<TFileOrigin extends string = string> = {\n id: string;\n fileOrigin: TFileOrigin;\n surface: string;\n createdAt: number;\n targetIds?: string[];\n originalContentType?: string;\n originalSize?: number;\n};\n\nexport type InFlightUploadActive<TFileOrigin extends string = string> =\n InFlightUploadBase<TFileOrigin> & {\n status: 'pending' | 'processing';\n };\n\nexport type InFlightUploadCompleted<TFileOrigin extends string = string> =\n InFlightUploadBase<TFileOrigin> & {\n status: 'completed';\n completedAt: number;\n uploadTrayClearedAt?: number;\n uploadTrayClearedBy?: string;\n uploadTraySeenAt?: number;\n uploadTraySeenBy?: string;\n };\n\nexport type InFlightUploadFailed<TFileOrigin extends string = string> =\n InFlightUploadBase<TFileOrigin> & {\n status: 'failed';\n failedAt: number;\n errorCategory: string;\n errorMessage: string;\n uploadTrayClearedAt?: number;\n uploadTrayClearedBy?: string;\n uploadTraySeenAt?: number;\n uploadTraySeenBy?: string;\n };\n\nexport type InFlightUploadRejected<TFileOrigin extends string = string> =\n InFlightUploadBase<TFileOrigin> & {\n status: 'rejected';\n rejectedAt: number;\n rejectionType: 'text' | 'media';\n errorMessage: string;\n violationId?: string;\n uploadTrayClearedAt?: number;\n uploadTrayClearedBy?: string;\n uploadTraySeenAt?: number;\n uploadTraySeenBy?: string;\n };\n\nexport type InFlightUpload<TFileOrigin extends string = string> =\n | InFlightUploadActive<TFileOrigin>\n | InFlightUploadCompleted<TFileOrigin>\n | InFlightUploadFailed<TFileOrigin>\n | InFlightUploadRejected<TFileOrigin>;\n\n// =============================================================================\n// Adapter contract — every app-specific behavior is injected here\n// =============================================================================\n\n/**\n * Result of the consumer-supplied parser. The provider keeps the raw parsed\n * record for callbacks (so consumers can read domain events, target IDs, etc.)\n * AND derives the generic InFlightUpload from it for the public Map.\n *\n * The parser MUST throw if validation fails; the provider catches and routes\n * the error to the monitoring callback.\n */\nexport type ParsedPendingMedia<TFileOrigin extends string = string> = {\n id: string;\n userId: string;\n fileOrigin: TFileOrigin;\n status: InFlightUploadStatus;\n createdAt: number;\n surface: string;\n targetIds?: string[];\n originalContentType?: string;\n originalSize?: number;\n // Terminal-status fields (only meaningful for the matching status)\n completedAt?: number;\n failedAt?: number;\n rejectedAt?: number;\n errorCategory?: string;\n errorMessage?: string;\n rejectionType?: 'text' | 'media';\n violationId?: string;\n uploadTrayClearedAt?: number;\n uploadTrayClearedBy?: string;\n uploadTraySeenAt?: number;\n uploadTraySeenBy?: string;\n /**\n * Opaque consumer-controlled domain-event payload, surfaced to the\n * `onUploadCompleted` and `onUploadRejected` callbacks for cache\n * invalidation. The provider does not interpret it.\n */\n domainEvents?: unknown;\n};\n\nexport type InFlightUploadsAdapter<TFileOrigin extends string = string> = {\n /** Returns the current user's uid, or null if not signed in. */\n getCurrentUserId: () => string | null;\n\n /** Firestore database adapter (loose typing — `unknown` keeps zero firebase coupling at the type level). */\n db: unknown;\n\n /** Collection path holding pending-media docs (e.g. \"pendingMedia\"). */\n collectionPath: string;\n\n /** Listener window in milliseconds — only docs with `createdAt >= now - window` are tracked. */\n listenerWindowMs: number;\n\n /**\n * Parse a raw Firestore doc snapshot's `.data()` into the generic shape the\n * provider tracks. Throws on validation failure; the provider routes thrown\n * errors to `onMonitoringEvent`.\n */\n parsePendingMedia: (raw: unknown) => ParsedPendingMedia<TFileOrigin>;\n\n /** Called once per observed non-terminal → terminal completed transition. */\n onUploadCompleted: (parsed: ParsedPendingMedia<TFileOrigin>) => void;\n\n /** Called once per observed non-terminal → terminal failed transition. */\n onUploadFailed: (parsed: ParsedPendingMedia<TFileOrigin>) => void;\n\n /** Called once per observed non-terminal → terminal rejected transition. */\n onUploadRejected: (parsed: ParsedPendingMedia<TFileOrigin>) => void;\n\n /**\n * Monitoring callback. Receives:\n * - `breadcrumb`: informational, fired on every observed terminal transition.\n * - `parse-error`: when `parsePendingMedia` throws.\n * - `listener-error`: when the Firestore listener's error callback fires.\n *\n * Consumers wire this to Sentry, OpenTelemetry, or any other observability\n * provider. The provider does NOT import any monitoring SDK directly.\n */\n onMonitoringEvent: (event: InFlightUploadsMonitoringEvent<TFileOrigin>) => void;\n};\n\nexport type InFlightUploadsMonitoringEvent<TFileOrigin extends string = string> =\n | {\n type: 'breadcrumb';\n category: 'upload.terminal';\n level: 'info';\n message: string;\n data: {\n id: string;\n fileOrigin: TFileOrigin;\n status: InFlightUploadStatus;\n surface: string;\n };\n }\n | {\n type: 'parse-error';\n docId: string;\n error: unknown;\n data: unknown;\n }\n | {\n type: 'listener-error';\n error: unknown;\n };\n\n// =============================================================================\n// Firestore subscription contract — abstracted to avoid firebase coupling\n// =============================================================================\n\n/**\n * Minimal subscription contract used by the provider. The default\n * implementation lives in `firestore-subscribe.ts` and uses the standard\n * `firebase/firestore` `onSnapshot` + `query` + `where` builders.\n *\n * Tests inject a fake to drive the listener without spinning up Firestore.\n */\nexport type FirestoreSubscribeFn = (args: {\n db: unknown;\n collectionPath: string;\n userId: string;\n windowStartMs: number;\n onSnapshot: (snapshot: FirestoreLikeSnapshot) => void;\n onError: (error: unknown) => void;\n}) => () => void;\n\nexport type FirestoreLikeSnapshot = {\n docChanges: () => FirestoreLikeDocChange[];\n /**\n * Snapshot metadata. Present when the subscription is opened with\n * `{ includeMetadataChanges: true }` (the default firebase implementation does).\n * `fromCache === false` means a server-confirmed snapshot. Optional so injected\n * test fakes need not supply it (absent ⇒ treated as server-confirmed).\n */\n metadata?: { fromCache: boolean };\n};\n\n/**\n * Metadata-derived liveness of the uploads listener, mirroring query-core's\n * `FirestoreSourceState`. Firestore serves cached snapshots offline WITHOUT\n * firing the error callback, so the Files tray source needs this to show a\n * degraded indicator instead of a false \"all caught up\":\n * - `connecting` — no server-confirmed snapshot yet.\n * - `live` — at least one server-confirmed snapshot (`fromCache === false`).\n * - `offline` — only cached data after having been live.\n * - `error` — the listener error callback fired.\n */\nexport type UploadsSourceState = 'connecting' | 'live' | 'offline' | 'error';\n\nexport type FirestoreLikeDocChange = {\n type: 'added' | 'modified' | 'removed';\n doc: {\n id: string;\n data: () => unknown;\n };\n};\n\n// =============================================================================\n// Provider\n// =============================================================================\n\ninterface InFlightUploadsContextValue<TFileOrigin extends string = string> {\n uploads: Map<string, InFlightUpload<TFileOrigin>>;\n sourceState: UploadsSourceState;\n}\n\nconst InFlightUploadsContext = createContext<InFlightUploadsContextValue | undefined>(undefined);\n\nexport interface InFlightUploadsProviderProps<TFileOrigin extends string = string> {\n adapter: InFlightUploadsAdapter<TFileOrigin>;\n /** Firestore subscription function. Defaults to the firebase/firestore implementation. */\n subscribe?: FirestoreSubscribeFn;\n children: ReactNode;\n}\n\nfunction fromParsed<TFileOrigin extends string>(\n parsed: ParsedPendingMedia<TFileOrigin>,\n): InFlightUpload<TFileOrigin> {\n const base: InFlightUploadBase<TFileOrigin> = {\n id: parsed.id,\n fileOrigin: parsed.fileOrigin,\n surface: parsed.surface,\n createdAt: parsed.createdAt,\n targetIds: parsed.targetIds,\n originalContentType: parsed.originalContentType,\n originalSize: parsed.originalSize,\n };\n if (parsed.status === 'pending' || parsed.status === 'processing') {\n return { ...base, status: parsed.status };\n }\n if (parsed.status === 'completed') {\n return {\n ...base,\n status: 'completed',\n completedAt: parsed.completedAt ?? parsed.createdAt,\n uploadTrayClearedAt: parsed.uploadTrayClearedAt,\n uploadTrayClearedBy: parsed.uploadTrayClearedBy,\n uploadTraySeenAt: parsed.uploadTraySeenAt,\n uploadTraySeenBy: parsed.uploadTraySeenBy,\n };\n }\n if (parsed.status === 'failed') {\n return {\n ...base,\n status: 'failed',\n failedAt: parsed.failedAt ?? parsed.createdAt,\n errorCategory: parsed.errorCategory ?? 'system',\n errorMessage: parsed.errorMessage ?? '',\n uploadTrayClearedAt: parsed.uploadTrayClearedAt,\n uploadTrayClearedBy: parsed.uploadTrayClearedBy,\n uploadTraySeenAt: parsed.uploadTraySeenAt,\n uploadTraySeenBy: parsed.uploadTraySeenBy,\n };\n }\n // rejected\n return {\n ...base,\n status: 'rejected',\n rejectedAt: parsed.rejectedAt ?? parsed.createdAt,\n rejectionType: parsed.rejectionType ?? 'media',\n errorMessage: parsed.errorMessage ?? '',\n violationId: parsed.violationId,\n uploadTrayClearedAt: parsed.uploadTrayClearedAt,\n uploadTrayClearedBy: parsed.uploadTrayClearedBy,\n // Carry the seen fields through (round-9 finding 9): dropping them on the\n // `rejected` branch — while `completed`/`failed` keep them — made a seen\n // rejected upload relight the Files dot forever, because the tray's\n // unseen-terminal check never saw `uploadTraySeenAt`.\n uploadTraySeenAt: parsed.uploadTraySeenAt,\n uploadTraySeenBy: parsed.uploadTraySeenBy,\n };\n}\n\nexport function InFlightUploadsProvider<TFileOrigin extends string = string>(\n props: InFlightUploadsProviderProps<TFileOrigin>,\n) {\n const { adapter, subscribe = defaultFirestoreSubscribe, children } = props;\n\n const [uploads, setUploads] = useState<Map<string, InFlightUpload<TFileOrigin>>>(new Map());\n const [sourceState, setSourceState] = useState<UploadsSourceState>('connecting');\n const seenTerminalIdsRef = useRef<Set<string>>(new Set());\n const statusByIdRef = useRef<Map<string, InFlightUploadStatus>>(new Map());\n const hasProcessedInitialSnapshotRef = useRef(false);\n\n // Stable refs for adapter callbacks — read from latest adapter inside effect.\n const adapterRef = useRef(adapter);\n useEffect(() => {\n adapterRef.current = adapter;\n });\n\n const userId = adapter.getCurrentUserId();\n\n useEffect(() => {\n // Reset all in-memory state for the new identity. Runs on every userId\n // change — including UID-A → UID-B with no intermediate null user.\n // Do not rely on an intermediate sign-out to clear refs between two\n // authenticated UIDs.\n setUploads(new Map());\n setSourceState('connecting');\n seenTerminalIdsRef.current = new Set();\n statusByIdRef.current = new Map();\n hasProcessedInitialSnapshotRef.current = false;\n\n if (!userId) {\n return;\n }\n\n const a = adapterRef.current;\n const windowStartMs = Date.now() - a.listenerWindowMs;\n\n const handleSnapshot = (snapshot: FirestoreLikeSnapshot) => {\n const updates: Array<{ id: string; upload: InFlightUpload<TFileOrigin> | null }> = [];\n const newlyTerminal: Array<ParsedPendingMedia<TFileOrigin>> = [];\n const isInitialSnapshot = !hasProcessedInitialSnapshotRef.current;\n\n for (const change of snapshot.docChanges()) {\n if (change.type === 'removed') {\n updates.push({ id: change.doc.id, upload: null });\n statusByIdRef.current.delete(change.doc.id);\n seenTerminalIdsRef.current.delete(change.doc.id);\n continue;\n }\n\n let parsed: ParsedPendingMedia<TFileOrigin>;\n try {\n parsed = adapterRef.current.parsePendingMedia(change.doc.data());\n } catch (error) {\n adapterRef.current.onMonitoringEvent({\n type: 'parse-error',\n docId: change.doc.id,\n error,\n data: change.doc.data(),\n });\n continue;\n }\n\n const upload = fromParsed(parsed);\n updates.push({ id: parsed.id, upload });\n\n const previousStatus = statusByIdRef.current.get(parsed.id);\n const currentStatus = parsed.status;\n const currentIsTerminal =\n currentStatus === 'completed' ||\n currentStatus === 'failed' ||\n currentStatus === 'rejected';\n const previousWasNonTerminal =\n previousStatus === 'pending' || previousStatus === 'processing';\n\n if (isInitialSnapshot) {\n // First snapshot after mount: mark already-terminal docs as seen,\n // but DO NOT fire callbacks. Prevents duplicate toasts on refresh.\n if (currentIsTerminal) {\n seenTerminalIdsRef.current.add(parsed.id);\n }\n } else if (\n currentIsTerminal &&\n previousWasNonTerminal &&\n !seenTerminalIdsRef.current.has(parsed.id)\n ) {\n seenTerminalIdsRef.current.add(parsed.id);\n newlyTerminal.push(parsed);\n } else if (currentIsTerminal) {\n // Terminal doc appeared without an observed non-terminal predecessor\n // (race in a non-initial snapshot). Mark as seen, no callback fire.\n seenTerminalIdsRef.current.add(parsed.id);\n }\n\n statusByIdRef.current.set(parsed.id, currentStatus);\n }\n\n hasProcessedInitialSnapshotRef.current = true;\n\n // Metadata-derived source state: stay `connecting` until a server-confirmed\n // snapshot, `offline` if only cached data arrives after being live.\n const fromCache = snapshot.metadata?.fromCache ?? false;\n setSourceState((prev) => (fromCache ? (prev === 'connecting' ? 'connecting' : 'offline') : 'live'));\n\n if (updates.length > 0) {\n setUploads((prev) => {\n const next = new Map(prev);\n for (const { id, upload } of updates) {\n if (upload === null) next.delete(id);\n else next.set(id, upload);\n }\n return next;\n });\n }\n\n for (const parsed of newlyTerminal) {\n handleTerminal(parsed);\n }\n };\n\n function handleTerminal(parsed: ParsedPendingMedia<TFileOrigin>) {\n adapterRef.current.onMonitoringEvent({\n type: 'breadcrumb',\n category: 'upload.terminal',\n level: 'info',\n message: `${parsed.fileOrigin}:${parsed.status}`,\n data: {\n id: parsed.id,\n fileOrigin: parsed.fileOrigin,\n status: parsed.status,\n surface: parsed.surface,\n },\n });\n\n if (parsed.status === 'completed') {\n adapterRef.current.onUploadCompleted(parsed);\n } else if (parsed.status === 'failed') {\n adapterRef.current.onUploadFailed(parsed);\n } else if (parsed.status === 'rejected') {\n adapterRef.current.onUploadRejected(parsed);\n }\n }\n\n // Bounded RESUBSCRIBE on listener error: a cold-session race (e.g. Firestore\n // App Check enforcement rejecting the first attach before the token is\n // minted) must not kill the listener for the whole session — observed live:\n // one permission-denied at first login → sourceState 'error' forever, every\n // tray file status dead until reload. Retry on a short ladder; a snapshot\n // resets the ladder (healthy again); exhausting it goes terminal 'error'\n // (a real rules denial stays denied — retries are cheap and bounded).\n const RESUBSCRIBE_DELAYS_MS = [1_000, 3_000, 10_000, 30_000];\n let attempt = 0;\n let disposed = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n let unsubscribe: (() => void) | undefined;\n\n const start = () => {\n unsubscribe = subscribe({\n db: a.db,\n collectionPath: a.collectionPath,\n userId,\n windowStartMs,\n onSnapshot: (snapshot) => {\n attempt = 0; // healthy — future errors get a fresh ladder\n handleSnapshot(snapshot);\n },\n onError: (error) => {\n adapterRef.current.onMonitoringEvent({ type: 'listener-error', error });\n unsubscribe?.();\n unsubscribe = undefined;\n if (disposed || attempt >= RESUBSCRIBE_DELAYS_MS.length) {\n setSourceState('error');\n return;\n }\n setSourceState('connecting');\n retryTimer = setTimeout(() => {\n if (disposed) return;\n attempt += 1;\n start();\n }, RESUBSCRIBE_DELAYS_MS[attempt]);\n },\n });\n };\n start();\n\n return () => {\n disposed = true;\n if (retryTimer) clearTimeout(retryTimer);\n unsubscribe?.();\n };\n // adapter is intentionally NOT in the deps array — adapter is read via\n // adapterRef on every snapshot, so identity changes don't re-subscribe.\n\n }, [userId, subscribe]);\n\n const value = useMemo<InFlightUploadsContextValue<TFileOrigin>>(\n () => ({ uploads, sourceState }),\n [uploads, sourceState],\n );\n\n return (\n <InFlightUploadsContext.Provider value={value as InFlightUploadsContextValue}>\n {children}\n </InFlightUploadsContext.Provider>\n );\n}\n\n// =============================================================================\n// Read APIs\n// =============================================================================\n\nexport function useInFlightUploadsState<TFileOrigin extends string = string>(): Map<\n string,\n InFlightUpload<TFileOrigin>\n> {\n const ctx = useContext(InFlightUploadsContext);\n if (ctx === undefined) {\n throw new Error('useInFlightUploadsState must be used within InFlightUploadsProvider');\n }\n return ctx.uploads as Map<string, InFlightUpload<TFileOrigin>>;\n}\n\nexport function useInFlightUpload<TFileOrigin extends string = string>(\n id: string | null | undefined,\n): InFlightUpload<TFileOrigin> | undefined {\n const ctx = useContext(InFlightUploadsContext);\n if (ctx === undefined) {\n throw new Error('useInFlightUpload must be used within InFlightUploadsProvider');\n }\n if (!id) return undefined;\n return ctx.uploads.get(id) as InFlightUpload<TFileOrigin> | undefined;\n}\n\n/**\n * Metadata-derived source state of the uploads listener\n * (`connecting | live | offline | error`). The Files tray uses this to show a\n * degraded indicator and never display \"all caught up\" while the source is\n * `offline`/`error`/`connecting`.\n */\nexport function useUploadsSourceState(): UploadsSourceState {\n const ctx = useContext(InFlightUploadsContext);\n if (ctx === undefined) {\n throw new Error('useUploadsSourceState must be used within InFlightUploadsProvider');\n }\n return ctx.sourceState;\n}\n\n// =============================================================================\n// Tray helpers\n// =============================================================================\n\n/**\n * `true` for `completed` / `failed` / `rejected`. Used by tray UI to decide\n * whether a Clear action is available for an item.\n */\nexport function isTerminalUpload<TFileOrigin extends string = string>(\n item: InFlightUpload<TFileOrigin>,\n): item is Exclude<InFlightUpload<TFileOrigin>, { status: 'pending' | 'processing' }> {\n return (\n item.status === 'completed' ||\n item.status === 'failed' ||\n item.status === 'rejected'\n );\n}\n\n/**\n * Tray-visible items. Includes every pending/processing upload, plus terminal\n * uploads that have NOT been cleared from the tray. Sorted newest-first by\n * createdAt.\n *\n * The public selector name in upload-ui is `useUploadActivityState`. The\n * mutation hook is `useClearUploadActivity` (in a separate file).\n */\nexport function useUploadActivityState<TFileOrigin extends string = string>(): InFlightUpload<TFileOrigin>[] {\n const uploads = useInFlightUploadsState<TFileOrigin>();\n return useMemo(() => {\n return Array.from(uploads.values())\n .filter((item) => {\n if (!isTerminalUpload(item)) return true;\n return item.uploadTrayClearedAt === undefined;\n })\n .sort((a, b) => b.createdAt - a.createdAt);\n }, [uploads]);\n}\n\n// =============================================================================\n// Default Firestore subscription implementation\n// =============================================================================\n\n/**\n * Default Firestore subscription using the consumer's `firebase/firestore`\n * module instance (via static ESM import at the top of this file).\n *\n * Using static ESM import — NOT `require()` — is load-bearing. CommonJS\n * `require('firebase/firestore')` and ESM `import 'firebase/firestore'` resolve\n * to different module instances under Next.js + Turbopack. If the consumer\n * constructs `db` via ESM and we receive it here, but we then call\n * `collection()` from a CJS-loaded copy of firebase, the firebase runtime\n * does not recognize the db as a Firestore instance and throws\n * \"Expected first argument to collection() to be a CollectionReference,\n * a DocumentReference or FirebaseFirestore\".\n *\n * Consumers who want to skip the firebase code path entirely (tests, alt\n * backends) supply their own `subscribe` prop to `InFlightUploadsProvider`.\n */\nconst defaultFirestoreSubscribe: FirestoreSubscribeFn = (args) => {\n const q = query(\n\n collection(args.db as any, args.collectionPath),\n where('userId', '==', args.userId),\n where('createdAt', '>=', args.windowStartMs),\n );\n // includeMetadataChanges so the provider can derive a `connecting|live|offline|error`\n // source state from `snapshot.metadata.fromCache` (the Files tray degraded indicator).\n return onSnapshot(q, { includeMetadataChanges: true }, args.onSnapshot as never, args.onError as never);\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-upload-guard-provider.js","sourceRoot":"","sources":["../../src/react/local-upload-guard-provider.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"local-upload-guard-provider.js","sourceRoot":"","sources":["../../src/react/local-upload-guard-provider.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\n/**\n * Local upload navigation guard provider.\n *\n * Tracks the count of in-progress LOCAL byte uploads (file → Firebase\n * Storage). While the count is > 0, installs a `beforeunload` listener\n * to warn the user before they close the tab or reload mid-upload.\n *\n * Scope:\n * - Covers phases `preparing` and `uploading` only.\n * - Does NOT cover `finalizing` — at that point bytes are already in\n * Storage and the only remaining work is the `startUpload` callable.\n * - Does NOT cover backend `pendingMedia` status (`pending` /\n * `processing`). Those run server-side and are safe to leave.\n *\n * Consumers register with a stable id (typically the local upload\n * session id or `pendingMedia` doc id once known) on entering\n * `preparing`/`uploading`, and unregister on transition to\n * `finalizing`/success/error/cancel/unmount.\n *\n * Public hook: `useLocalUploadGuard()` returns\n * `{ activeUploadCount, registerUpload, unregisterUpload }`. Throws if\n * used outside a `LocalUploadGuardProvider`.\n */\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\ninterface LocalUploadGuardContextValue {\n activeUploadCount: number;\n registerUpload: (id: string) => void;\n unregisterUpload: (id: string) => void;\n /** Returns true iff at least one upload is currently registered. Pure read. */\n shouldConfirmNavigation: () => boolean;\n /**\n * Shows a confirm() dialog with the configured message and returns the user's\n * choice. Safe to call when no upload is active — returns true without prompting.\n */\n confirmNavigation: () => boolean;\n}\n\nconst LocalUploadGuardContext = createContext<LocalUploadGuardContextValue | undefined>(undefined);\n\nexport interface LocalUploadGuardProviderProps {\n /**\n * Message shown by the browser when the user attempts to close the tab or\n * reload during an active upload. Modern browsers may ignore the custom\n * string and show a generic dialog.\n */\n beforeUnloadMessage?: string;\n /**\n * Message shown by `confirmNavigation()` when an upload is in progress and\n * the user attempts to navigate away within the app. Defaults to a\n * reasonable English string.\n */\n navigationConfirmMessage?: string;\n children: ReactNode;\n}\n\nconst DEFAULT_BEFORE_UNLOAD_MESSAGE =\n 'File upload in progress. Are you sure you want to leave and end the file upload?';\nconst DEFAULT_NAVIGATION_CONFIRM_MESSAGE =\n 'An upload is currently in progress. If you leave this page, the upload will be canceled. Continue?';\n\nexport function LocalUploadGuardProvider(props: LocalUploadGuardProviderProps) {\n const {\n children,\n beforeUnloadMessage = DEFAULT_BEFORE_UNLOAD_MESSAGE,\n navigationConfirmMessage = DEFAULT_NAVIGATION_CONFIRM_MESSAGE,\n } = props;\n const activeIdsRef = useRef<Set<string>>(new Set());\n const [activeUploadCount, setActiveUploadCount] = useState(0);\n\n const registerUpload = useCallback((id: string) => {\n if (activeIdsRef.current.has(id)) return;\n activeIdsRef.current.add(id);\n setActiveUploadCount(activeIdsRef.current.size);\n }, []);\n\n const unregisterUpload = useCallback((id: string) => {\n if (!activeIdsRef.current.has(id)) return;\n activeIdsRef.current.delete(id);\n setActiveUploadCount(activeIdsRef.current.size);\n }, []);\n\n useEffect(() => {\n if (activeUploadCount <= 0) return;\n\n const handleBeforeUnload = (event: BeforeUnloadEvent) => {\n event.preventDefault();\n // Modern browsers may ignore the custom string and show their own\n // generic confirmation. The key behavior is that navigation is\n // blocked/warned, not the exact text.\n event.returnValue = beforeUnloadMessage;\n return event.returnValue;\n };\n\n window.addEventListener('beforeunload', handleBeforeUnload);\n return () => {\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n }, [activeUploadCount, beforeUnloadMessage]);\n\n const shouldConfirmNavigation = useCallback(\n () => activeIdsRef.current.size > 0,\n [],\n );\n\n const confirmNavigation = useCallback((): boolean => {\n if (activeIdsRef.current.size === 0) return true;\n // SSR / non-browser safety: if `window` isn't available, default to allow.\n if (typeof window === 'undefined') return true;\n return window.confirm(navigationConfirmMessage);\n }, [navigationConfirmMessage]);\n\n const value = useMemo<LocalUploadGuardContextValue>(\n () => ({\n activeUploadCount,\n registerUpload,\n unregisterUpload,\n shouldConfirmNavigation,\n confirmNavigation,\n }),\n [activeUploadCount, registerUpload, unregisterUpload, shouldConfirmNavigation, confirmNavigation],\n );\n\n return (\n <LocalUploadGuardContext.Provider value={value}>\n {children}\n </LocalUploadGuardContext.Provider>\n );\n}\n\n/**\n * Low-level accessor for the local-upload guard context. Throws if used\n * outside a `LocalUploadGuardProvider`. Most consumers should use\n * `useLocalUploadGuard` (the public re-export below) instead.\n */\nexport function useLocalUploadGuardContext(): LocalUploadGuardContextValue {\n const ctx = useContext(LocalUploadGuardContext);\n if (ctx === undefined) {\n throw new Error(\n 'useLocalUploadGuard must be used within LocalUploadGuardProvider',\n );\n }\n return ctx;\n}\n\n/**\n * Optional accessor: returns the guard context, or `null` when rendered\n * outside a `LocalUploadGuardProvider`. For package components (e.g. the\n * chat composer registering an in-flight send) that must degrade gracefully\n * in consumers that don't mount the provider, instead of throwing.\n */\nexport function useOptionalLocalUploadGuard(): LocalUploadGuardContextValue | null {\n return useContext(LocalUploadGuardContext) ?? null;\n}\n\n/**\n * Public hook for the local upload navigation guard.\n *\n * Returns `{ activeUploadCount, registerUpload, unregisterUpload }`.\n *\n * Typical usage in an upload flow:\n *\n * const { registerUpload, unregisterUpload } = useLocalUploadGuard();\n * useEffect(() => {\n * if (phase === 'preparing' || phase === 'uploading') {\n * registerUpload(uploadId);\n * return () => unregisterUpload(uploadId);\n * }\n * }, [phase, uploadId, registerUpload, unregisterUpload]);\n */\nexport function useLocalUploadGuard(): LocalUploadGuardContextValue {\n return useLocalUploadGuardContext();\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/tray/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,GAgBjB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,kBAAkB,GAInB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,sBAAsB,GAEvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,yBAAyB,GAE1B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,mBAAmB,GAGpB,MAAM,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/tray/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,GAgBjB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,kBAAkB,GAInB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,sBAAsB,GAEvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,yBAAyB,GAE1B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,mBAAmB,GAGpB,MAAM,6BAA6B,CAAC","sourcesContent":["export {\n InFlightUploadsProvider,\n useInFlightUploadsState,\n useInFlightUpload,\n useUploadActivityState,\n useUploadsSourceState,\n isTerminalUpload,\n type UploadsSourceState,\n type InFlightUpload,\n type InFlightUploadActive,\n type InFlightUploadCompleted,\n type InFlightUploadFailed,\n type InFlightUploadRejected,\n type InFlightUploadBase,\n type InFlightUploadStatus,\n type InFlightUploadsAdapter,\n type InFlightUploadsMonitoringEvent,\n type InFlightUploadsProviderProps,\n type ParsedPendingMedia,\n type FirestoreSubscribeFn,\n type FirestoreLikeSnapshot,\n type FirestoreLikeDocChange,\n} from '../in-flight-uploads-provider.js';\nexport {\n UploadActivityTray,\n type UploadActivityTrayProps,\n type UploadTrayLabelers,\n type ViewAllLinkRenderArgs,\n} from '../upload-activity-tray.js';\nexport {\n useClearUploadActivity,\n type ClearUploadActivityOptions,\n} from '../use-clear-upload-activity.js';\nexport {\n useMarkUploadActivitySeen,\n type MarkUploadActivitySeenOptions,\n} from '../use-mark-upload-activity-seen.js';\nexport {\n useUploadProcessing,\n type UploadProcessingState,\n type UseUploadProcessingOptions,\n} from '../use-upload-processing.js';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/upload/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,GAEjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,uBAAuB,GAGxB,MAAM,kCAAkC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/upload/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,GAEjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,uBAAuB,GAGxB,MAAM,kCAAkC,CAAC","sourcesContent":["export {\n useGuardedUpload,\n type GuardedUploadArgs,\n} from '../use-guarded-upload.js';\nexport {\n DeferredUploadFormShell,\n type DeferredUploadFormShellHandle,\n type DeferredUploadFormShellProps,\n} from '../deferred-upload-form-shell.js';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-activity-tray.js","sourceRoot":"","sources":["../../src/react/upload-activity-tray.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"upload-activity-tray.js","sourceRoot":"","sources":["../../src/react/upload-activity-tray.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\n/**\n * Global upload activity tray.\n *\n * Renders a fixed bottom-left floating action button when there is any\n * active or non-cleared terminal upload. Opens a popover listing each\n * item with backend status. Terminal items (completed / failed / rejected)\n * get a Clear (×) button that calls the consumer-supplied clear mutation.\n *\n * Framework-agnostic via render props:\n * - `renderViewAllLink` lets the consumer plug in their app's Link\n * component (Next.js Link, React Router Link, anchor, etc.) routed at\n * their canonical \"view all uploads\" destination.\n * - `renderFooter` lets the consumer fully replace the footer slot.\n * - Both omitted — footer is not rendered.\n */\n\nimport { useMemo, type ReactNode } from 'react';\nimport { Cloud, Loader2, CheckCircle2, AlertCircle, XCircle, X } from 'lucide-react';\nimport {\n Button,\n Popover,\n PopoverTrigger,\n PopoverContent,\n ScrollArea,\n Separator,\n} from '@ttt-productions/ui-core/react';\nimport { cn } from '@ttt-productions/ui-core';\nimport {\n isTerminalUpload,\n useUploadActivityState,\n type InFlightUpload,\n} from './in-flight-uploads-provider.js';\n\n/**\n * Consumer-supplied formatters used by `UploadActivityTray` to render row\n * labels. The tray is intentionally domain-agnostic — consumers map their\n * own `FileOrigin` union to user-facing strings and choose their preferred\n * timestamp / size / content-type formatting.\n */\nexport interface UploadTrayLabelers<TFileOrigin extends string = string> {\n /** User-facing label for a file origin (e.g. 'support-ticket' -> 'Support reply'). */\n originLabel: (fileOrigin: TFileOrigin) => string;\n /** Human file size string, e.g. 1572864 -> '1.5 MB'. Return null when unknown. */\n fileSizeLabel: (bytes: number | undefined) => string | null;\n /** Friendly content-type label, e.g. 'image/png' -> 'Image'. Return null when unknown. */\n fileTypeLabel: (contentType: string | undefined) => string | null;\n /** Timestamp label, e.g. '3m ago' / 'Yesterday 3:42 PM'. */\n timestampLabel: (createdAtMs: number, nowMs: number) => string;\n}\n\ninterface RowMeta {\n statusLabel: string;\n errorDetail?: string;\n originLabel: string;\n fileTypeLabel: string | null;\n fileSizeLabel: string | null;\n timestampLabel: string;\n icon: ReactNode;\n iconClassName: string;\n}\n\nfunction getRowMeta<TFileOrigin extends string>(\n item: InFlightUpload<TFileOrigin>,\n nowMs: number,\n labelers: UploadTrayLabelers<TFileOrigin>,\n): RowMeta {\n let statusLabel: string;\n let icon: ReactNode;\n let iconClassName: string;\n let errorDetail: string | undefined;\n\n switch (item.status) {\n case 'pending':\n statusLabel = 'Waiting to process…';\n icon = <Loader2 className=\"icon-sm animate-spin\" />;\n iconClassName = 'text-muted-foreground';\n break;\n case 'processing':\n statusLabel = 'Processing…';\n icon = <Loader2 className=\"icon-sm animate-spin\" />;\n iconClassName = 'text-primary';\n break;\n case 'completed':\n statusLabel = 'Completed';\n icon = <CheckCircle2 className=\"icon-sm\" />;\n iconClassName = 'text-green-600 dark:text-green-500';\n break;\n case 'failed':\n statusLabel = 'Failed';\n errorDetail = item.errorMessage;\n icon = <AlertCircle className=\"icon-sm\" />;\n iconClassName = 'text-destructive';\n break;\n case 'rejected':\n statusLabel = 'Rejected';\n errorDetail = item.errorMessage;\n icon = <XCircle className=\"icon-sm\" />;\n iconClassName = 'text-destructive';\n break;\n }\n\n return {\n statusLabel,\n errorDetail,\n originLabel: labelers.originLabel(item.fileOrigin),\n fileTypeLabel: labelers.fileTypeLabel(item.originalContentType),\n fileSizeLabel: labelers.fileSizeLabel(item.originalSize),\n timestampLabel: labelers.timestampLabel(item.createdAt, nowMs),\n icon,\n iconClassName,\n };\n}\n\ninterface UploadActivityTrayRowProps<TFileOrigin extends string> {\n item: InFlightUpload<TFileOrigin>;\n nowMs: number;\n onClear: (() => void) | undefined;\n isClearPending: boolean;\n labelers: UploadTrayLabelers<TFileOrigin>;\n}\n\nfunction UploadActivityTrayRow<TFileOrigin extends string>({\n item,\n nowMs,\n onClear,\n isClearPending,\n labelers,\n}: UploadActivityTrayRowProps<TFileOrigin>) {\n const meta = getRowMeta(item, nowMs, labelers);\n const subline = [meta.originLabel, meta.fileTypeLabel, meta.fileSizeLabel]\n .filter(Boolean)\n .join(' · ');\n return (\n <div className=\"flex items-start gap-3 p-3\">\n <div className={cn('mt-0.5 shrink-0', meta.iconClassName)}>{meta.icon}</div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">{meta.statusLabel}</p>\n <p className=\"text-xs text-muted-foreground truncate\">{subline}</p>\n {meta.errorDetail && (\n <p className=\"text-xs text-muted-foreground mt-1 line-clamp-2\">{meta.errorDetail}</p>\n )}\n <p className=\"text-xs text-muted-foreground mt-1\">{meta.timestampLabel}</p>\n </div>\n {onClear && (\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-7 w-7 shrink-0\"\n onClick={onClear}\n disabled={isClearPending}\n aria-label={`Clear ${meta.statusLabel.toLowerCase()} upload`}\n >\n <X className=\"icon-sm\" />\n </Button>\n )}\n </div>\n );\n}\n\nexport interface ViewAllLinkRenderArgs {\n /** The href the consumer's link should navigate to (passed through verbatim). */\n href: string;\n /** Children for the link element (i.e. the label text + arrow). */\n children: ReactNode;\n}\n\nexport interface UploadActivityTrayProps<TFileOrigin extends string = string> {\n /**\n * Mutation hook result from `useClearUploadActivity({ clearFn })`. The tray\n * uses `.mutate(item.id)`, `.isPending`, and `.variables`. The consumer\n * owns the underlying network call.\n */\n clearMutation: {\n mutate: (pendingMediaId: string) => void;\n isPending: boolean;\n variables: string | undefined;\n };\n /**\n * Consumer-supplied formatters for row labels. Required — the tray has\n * no built-in opinion about how to render origin / file type / size /\n * timestamp strings.\n */\n labelers: UploadTrayLabelers<TFileOrigin>;\n /**\n * Optional view-all destination href. When omitted, no footer is rendered\n * unless `renderFooter` is also supplied.\n */\n viewAllHref?: string;\n /**\n * Render-prop for the view-all link. Receives the href and label children\n * the consumer should attach. Omit to drop the link.\n */\n renderViewAllLink?: (args: ViewAllLinkRenderArgs) => ReactNode;\n /**\n * Fully custom footer slot. Replaces the default footer entirely. If both\n * `renderFooter` and `viewAllHref + renderViewAllLink` are supplied,\n * `renderFooter` wins.\n */\n renderFooter?: () => ReactNode;\n /** Visible label for the view-all link. Default: \"View all uploads →\". */\n viewAllLabel?: ReactNode;\n}\n\nexport function UploadActivityTray<TFileOrigin extends string = string>(\n props: UploadActivityTrayProps<TFileOrigin>,\n) {\n const {\n clearMutation,\n labelers,\n viewAllHref,\n renderViewAllLink,\n renderFooter,\n viewAllLabel = 'View all uploads →',\n } = props;\n const items = useUploadActivityState<TFileOrigin>();\n const nowMs = Date.now();\n\n const activeCount = useMemo(\n () =>\n items.filter((item) => item.status === 'pending' || item.status === 'processing').length,\n [items],\n );\n\n const footerContent: ReactNode = (() => {\n if (renderFooter) return renderFooter();\n if (viewAllHref && renderViewAllLink) {\n return (\n <div className=\"p-3\">\n {renderViewAllLink({\n href: viewAllHref,\n children: (\n <span className=\"text-sm text-primary hover:underline\">{viewAllLabel}</span>\n ),\n })}\n </div>\n );\n }\n return null;\n })();\n\n return (\n <div className=\"fixed bottom-6 left-6 z-50\">\n <Popover>\n <PopoverTrigger asChild>\n <Button\n size=\"icon\"\n variant={items.length === 0 ? 'ghost' : 'inverted'}\n className=\"relative h-14 w-14 rounded-full shadow-lg\"\n aria-label={\n items.length === 0\n ? 'Upload activity (no recent uploads)'\n : activeCount > 0\n ? `Upload activity: ${activeCount} in progress`\n : `Upload activity: ${items.length} item${items.length === 1 ? '' : 's'}`\n }\n >\n {activeCount > 0 ? (\n <Loader2 className=\"icon-md animate-spin\" />\n ) : (\n <Cloud className=\"icon-md\" />\n )}\n {items.length > 0 && (\n <span\n className=\"absolute -top-1 -right-1 min-w-[1.25rem] h-5 px-1 rounded-full bg-destructive text-destructive-foreground text-xs font-medium flex items-center justify-center\"\n aria-hidden=\"true\"\n >\n {items.length}\n </span>\n )}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" side=\"top\" className=\"app-popover p-0 w-80\">\n <div className=\"flex items-center justify-between p-3\">\n <h2 className=\"text-sm font-semibold\">Upload Activity</h2>\n <span className=\"text-xs text-muted-foreground\">\n {items.length === 0\n ? 'No recent uploads'\n : activeCount > 0\n ? `${activeCount} in progress`\n : `${items.length} item${items.length === 1 ? '' : 's'}`}\n </span>\n </div>\n <Separator />\n {items.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-muted-foreground\">\n No recent uploads.\n </div>\n ) : (\n <ScrollArea className=\"max-h-80\">\n <ul className=\"divide-y\">\n {items.map((item) => (\n <li key={item.id}>\n <UploadActivityTrayRow\n item={item}\n nowMs={nowMs}\n onClear={isTerminalUpload(item) ? () => clearMutation.mutate(item.id) : undefined}\n isClearPending={clearMutation.isPending && clearMutation.variables === item.id}\n labelers={labelers}\n />\n </li>\n ))}\n </ul>\n </ScrollArea>\n )}\n {footerContent !== null && (\n <>\n <Separator />\n {footerContent}\n </>\n )}\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-clear-upload-activity.js","sourceRoot":"","sources":["../../src/react/use-clear-upload-activity.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AASpD,MAAM,UAAU,sBAAsB,CAAC,OAAmC;IACxE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACrC,OAAO,WAAW,CAAsB;QACtC,UAAU,EAAE,OAAO;QACnB,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE;YACjC,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QACnC,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"use-clear-upload-activity.js","sourceRoot":"","sources":["../../src/react/use-clear-upload-activity.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AASpD,MAAM,UAAU,sBAAsB,CAAC,OAAmC;IACxE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACrC,OAAO,WAAW,CAAsB;QACtC,UAAU,EAAE,OAAO;QACnB,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE;YACjC,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QACnC,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["'use client';\n\n/**\n * Generic mutation hook to clear a terminal pendingMedia item from the tray.\n *\n * Pure adapter: the consumer supplies `clearFn` (typically a wrapped Firebase\n * callable in the consuming app, or a fetch call elsewhere). The package owns the\n * useMutation wiring and the optional `onError` toast hook; the consumer owns\n * the network call.\n *\n * The provider's Firestore listener observes the `uploadTrayClearedAt` write\n * and removes the item from the tray selector automatically — no optimistic\n * update is needed in this hook.\n */\n\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface ClearUploadActivityOptions {\n /** Network call performing the clear. Receives the pendingMediaId. */\n clearFn: (pendingMediaId: string) => Promise<void>;\n /** Optional error callback. Receives the error and the pendingMediaId that failed. */\n onError?: (error: Error, pendingMediaId: string) => void;\n}\n\nexport function useClearUploadActivity(options: ClearUploadActivityOptions) {\n const { clearFn, onError } = options;\n return useMutation<void, Error, string>({\n mutationFn: clearFn,\n onError: (error, pendingMediaId) => {\n onError?.(error, pendingMediaId);\n },\n });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-guarded-navigation.js","sourceRoot":"","sources":["../../src/react/use-guarded-navigation.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,EAAE,CAAC;IACpD,OAAO,WAAW,CAChB,CAAC,iBAA6B,EAAE,EAAE;QAChC,IAAI,iBAAiB,EAAE,EAAE,CAAC;YACxB,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,iBAAiB,CAAC,CACpB,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"use-guarded-navigation.js","sourceRoot":"","sources":["../../src/react/use-guarded-navigation.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,EAAE,CAAC;IACpD,OAAO,WAAW,CAChB,CAAC,iBAA6B,EAAE,EAAE;QAChC,IAAI,iBAAiB,EAAE,EAAE,CAAC;YACxB,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 when an upload is in\n * progress. Returns a function that takes the consumer's actual navigation\n * call and either runs it immediately (no active uploads) 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 *\n * Typical use inside a button:\n *\n * const guardedNav = useGuardedNavigation();\n * <Button onClick={() => guardedNav(() => router.push('/somewhere'))}>Go</Button>\n *\n * For links, use the `<GuardedLink>` render-prop wrapper.\n */\n\nimport { useCallback } from 'react';\nimport { useLocalUploadGuard } 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 no\n * active uploads) or shows a confirmation prompt; if the user confirms,\n * `performNavigation` is invoked.\n */\nexport function useGuardedNavigation(): (performNavigation: () => void) => void {\n const { confirmNavigation } = useLocalUploadGuard();\n return useCallback(\n (performNavigation: () => void) => {\n if (confirmNavigation()) {\n performNavigation();\n }\n },\n [confirmNavigation],\n );\n}\n"]}
|
|
@@ -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;
|
|
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;
|
|
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 +1 @@
|
|
|
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;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AASpD,MAAM,UAAU,yBAAyB,CAAC,OAAsC;IAC9E,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACpC,OAAO,WAAW,CAAwB;QACxC,UAAU,EAAE,MAAM;QAClB,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE;YAClC,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QACpC,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
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;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AASpD,MAAM,UAAU,yBAAyB,CAAC,OAAsC;IAC9E,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACpC,OAAO,WAAW,CAAwB;QACxC,UAAU,EAAE,MAAM;QAClB,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE;YAClC,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QACpC,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 * `markFn` receives the full batch of pendingMediaIds to mark seen at once\n * (typically every currently-unseen terminal item when the File-status tab\n * opens). An empty array is a no-op the consumer's callable can short-circuit.\n */\n\nimport { useMutation } from '@tanstack/react-query';\n\nexport interface MarkUploadActivitySeenOptions {\n /** Network call performing the mark-seen. Receives the pendingMediaIds. */\n markFn: (pendingMediaIds: string[]) => Promise<void>;\n /** Optional error callback. Receives the error and the ids that failed. */\n onError?: (error: Error, pendingMediaIds: string[]) => void;\n}\n\nexport function useMarkUploadActivitySeen(options: MarkUploadActivitySeenOptions) {\n const { markFn, onError } = options;\n return useMutation<void, Error, string[]>({\n mutationFn: markFn,\n onError: (error, pendingMediaIds) => {\n onError?.(error, pendingMediaIds);\n },\n });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-upload-processing.js","sourceRoot":"","sources":["../../src/react/use-upload-processing.ts"],"names":[],"mappings":"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"}
|
|
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 { useInFlightUpload, type InFlightUpload } from './in-flight-uploads-provider.js';\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 (upload.status === 'pending' || upload.status === 'processing') {\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 === '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 === '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 === '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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/upload-ui",
|
|
3
|
-
"version": "0.7.
|
|
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.
|
|
44
|
-
"@ttt-productions/media-schemas": "^0.14.
|
|
45
|
-
"@ttt-productions/ui-core": "^0.11.
|
|
46
|
-
"@ttt-productions/upload-core": "^0.7.
|
|
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",
|