@opengeni/react 7.6.1-canary.37073905159001 → 7.6.1

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 (136) hide show
  1. package/README.md +2 -19
  2. package/dist/{browser-viewer-63TXMINB.js → browser-viewer-5X47I6T2.js} +5 -6
  3. package/dist/{chunk-TKB4SB44.js → chunk-45GE35O7.js} +2 -10
  4. package/dist/chunk-45GE35O7.js.map +1 -0
  5. package/dist/{chunk-DOJWJQ3F.js → chunk-5EXGU7UF.js} +3 -3
  6. package/dist/{chunk-YN7I3STW.js → chunk-6NEZPF53.js} +32 -153
  7. package/dist/chunk-6NEZPF53.js.map +1 -0
  8. package/dist/{chunk-I7IWRQLN.js → chunk-BI57CQUV.js} +2 -2
  9. package/dist/{chunk-6ZSWSH4I.js → chunk-CHPKSLPN.js} +1 -3
  10. package/dist/chunk-CHPKSLPN.js.map +1 -0
  11. package/dist/{chunk-Q5QBEZIQ.js → chunk-DV2DBNPQ.js} +29 -48
  12. package/dist/chunk-DV2DBNPQ.js.map +1 -0
  13. package/dist/{chunk-RDKBXMWX.js → chunk-FGBCYQOT.js} +74 -120
  14. package/dist/chunk-FGBCYQOT.js.map +1 -0
  15. package/dist/{chunk-AAG4R3QN.js → chunk-KGENSZKS.js} +3 -4
  16. package/dist/chunk-KGENSZKS.js.map +1 -0
  17. package/dist/{chunk-YQEAA6LT.js → chunk-KZ73RL76.js} +3 -7
  18. package/dist/chunk-KZ73RL76.js.map +1 -0
  19. package/dist/{chunk-LFXYGZWK.js → chunk-LZ3KHA55.js} +60 -169
  20. package/dist/chunk-LZ3KHA55.js.map +1 -0
  21. package/dist/{chunk-2QUSQVF2.js → chunk-UINDK6C3.js} +3 -3
  22. package/dist/{chunk-UTRTG6LH.js → chunk-UJRYEWZI.js} +8 -48
  23. package/dist/chunk-UJRYEWZI.js.map +1 -0
  24. package/dist/{chunk-XOAMRDDK.js → chunk-VGIKFIO2.js} +3 -6
  25. package/dist/chunk-VGIKFIO2.js.map +1 -0
  26. package/dist/{chunk-ELCE5SXV.js → chunk-WZ55DVGK.js} +4 -8
  27. package/dist/chunk-WZ55DVGK.js.map +1 -0
  28. package/dist/{chunk-IQUCRAT7.js → chunk-XA6R7DJQ.js} +3 -3
  29. package/dist/{chunk-TOAH2BKA.js → chunk-YCGBREUV.js} +2 -6
  30. package/dist/{chunk-TOAH2BKA.js.map → chunk-YCGBREUV.js.map} +1 -1
  31. package/dist/{chunk-HNFCAQ5R.js → chunk-YRYF2GLG.js} +31 -39
  32. package/dist/chunk-YRYF2GLG.js.map +1 -0
  33. package/dist/{chunk-GISEVGS6.js → chunk-YSMMDOOE.js} +2 -10
  34. package/dist/chunk-YSMMDOOE.js.map +1 -0
  35. package/dist/{chunk-CWWKTNKK.js → chunk-Z3DISEQN.js} +18 -35
  36. package/dist/chunk-Z3DISEQN.js.map +1 -0
  37. package/dist/client.d.ts +1 -4
  38. package/dist/commands/types.d.ts +0 -2
  39. package/dist/components/approval-surface.d.ts +0 -15
  40. package/dist/composer.js +7 -8
  41. package/dist/{computer-viewer-X2MBRZY4.js → computer-viewer-7GF35SNY.js} +4 -5
  42. package/dist/connect.js +3 -3
  43. package/dist/hooks/use-browser-session.d.ts +0 -4
  44. package/dist/hooks/use-composer.d.ts +0 -2
  45. package/dist/hooks/use-computer-session.d.ts +0 -2
  46. package/dist/hooks/use-file-attachments.d.ts +0 -2
  47. package/dist/hooks/use-session-events.d.ts +1 -1
  48. package/dist/hooks/use-workspace-sessions.d.ts +5 -15
  49. package/dist/index.d.ts +2 -2
  50. package/dist/index.js +21 -28
  51. package/dist/index.js.map +1 -1
  52. package/dist/interaction.d.ts +1 -1
  53. package/dist/interaction.js +5 -6
  54. package/dist/interaction.js.map +1 -1
  55. package/dist/{latest-question-CNEZ5KAN.js → latest-question-3BJGKQQ6.js} +3 -3
  56. package/dist/lib/format.d.ts +3 -27
  57. package/dist/lib/interaction-errors.d.ts +0 -3
  58. package/dist/machines.js +4 -5
  59. package/dist/{model-policy-picker-menu-JSA64TNN.js → model-policy-picker-menu-PUTA5JOB.js} +4 -4
  60. package/dist/model-policy.js +1 -1
  61. package/dist/provider.d.ts +1 -5
  62. package/dist/{queue-surface-implementation-HENWYFWA.js → queue-surface-implementation-2CAQAIHM.js} +2 -3
  63. package/dist/{queue-surface-implementation-HENWYFWA.js.map → queue-surface-implementation-2CAQAIHM.js.map} +1 -1
  64. package/dist/realtime.js +2 -2
  65. package/dist/{sandbox-files-BBC47SLD.js → sandbox-files-AEJTWGT4.js} +3 -4
  66. package/dist/session-ui.d.ts +1 -1
  67. package/dist/session-ui.js +12 -13
  68. package/dist/session-ui.js.map +1 -1
  69. package/dist/session.js +6 -7
  70. package/dist/usage.js +1 -2
  71. package/dist/usage.js.map +1 -1
  72. package/package.json +3 -3
  73. package/src/client.ts +1 -5
  74. package/src/commands/registry.ts +15 -18
  75. package/src/commands/types.ts +0 -2
  76. package/src/components/approval-surface.tsx +42 -166
  77. package/src/components/browser-viewer.tsx +9 -38
  78. package/src/components/composer.tsx +2 -9
  79. package/src/components/computer-viewer.tsx +30 -160
  80. package/src/components/generated-video-player.tsx +2 -4
  81. package/src/components/human-input-form.tsx +5 -18
  82. package/src/components/message-timeline.tsx +2 -4
  83. package/src/components/open-geni-chat.tsx +4 -11
  84. package/src/components/queue-surface-state.tsx +1 -3
  85. package/src/components/session-chrome.tsx +2 -5
  86. package/src/components/session-commands-panel.tsx +1 -3
  87. package/src/components/session-conversation.tsx +2 -4
  88. package/src/components/session-list.tsx +5 -7
  89. package/src/components/session-mcp-capability-card.tsx +1 -11
  90. package/src/hooks/internal.ts +2 -3
  91. package/src/hooks/use-browser-session.ts +79 -115
  92. package/src/hooks/use-composer.ts +31 -70
  93. package/src/hooks/use-computer-session.ts +6 -57
  94. package/src/hooks/use-file-attachments.ts +3 -16
  95. package/src/hooks/use-goal.ts +1 -2
  96. package/src/hooks/use-session-capabilities.ts +2 -3
  97. package/src/hooks/use-session-events.ts +8 -15
  98. package/src/hooks/use-slash-commands.ts +11 -6
  99. package/src/hooks/use-turn-queue.ts +1 -2
  100. package/src/hooks/use-workspace-sessions.ts +7 -40
  101. package/src/index.ts +2 -7
  102. package/src/interaction.ts +0 -1
  103. package/src/lib/format.ts +9 -73
  104. package/src/lib/interaction-errors.ts +0 -15
  105. package/src/model-policy.ts +0 -5
  106. package/src/provider.tsx +4 -12
  107. package/src/session-ui.ts +1 -1
  108. package/src/timeline/projection.ts +1 -12
  109. package/styles/compiled.css +0 -14
  110. package/dist/chunk-6ZSWSH4I.js.map +0 -1
  111. package/dist/chunk-AAG4R3QN.js.map +0 -1
  112. package/dist/chunk-CWWKTNKK.js.map +0 -1
  113. package/dist/chunk-ELCE5SXV.js.map +0 -1
  114. package/dist/chunk-GISEVGS6.js.map +0 -1
  115. package/dist/chunk-HNFCAQ5R.js.map +0 -1
  116. package/dist/chunk-LFXYGZWK.js.map +0 -1
  117. package/dist/chunk-Q5QBEZIQ.js.map +0 -1
  118. package/dist/chunk-RDKBXMWX.js.map +0 -1
  119. package/dist/chunk-TKB4SB44.js.map +0 -1
  120. package/dist/chunk-UGLEYEMP.js +0 -33
  121. package/dist/chunk-UGLEYEMP.js.map +0 -1
  122. package/dist/chunk-UTRTG6LH.js.map +0 -1
  123. package/dist/chunk-XOAMRDDK.js.map +0 -1
  124. package/dist/chunk-YN7I3STW.js.map +0 -1
  125. package/dist/chunk-YQEAA6LT.js.map +0 -1
  126. package/dist/lib/error-message.d.ts +0 -7
  127. package/src/lib/error-message.ts +0 -37
  128. /package/dist/{browser-viewer-63TXMINB.js.map → browser-viewer-5X47I6T2.js.map} +0 -0
  129. /package/dist/{chunk-DOJWJQ3F.js.map → chunk-5EXGU7UF.js.map} +0 -0
  130. /package/dist/{chunk-I7IWRQLN.js.map → chunk-BI57CQUV.js.map} +0 -0
  131. /package/dist/{chunk-2QUSQVF2.js.map → chunk-UINDK6C3.js.map} +0 -0
  132. /package/dist/{chunk-IQUCRAT7.js.map → chunk-XA6R7DJQ.js.map} +0 -0
  133. /package/dist/{computer-viewer-X2MBRZY4.js.map → computer-viewer-7GF35SNY.js.map} +0 -0
  134. /package/dist/{latest-question-CNEZ5KAN.js.map → latest-question-3BJGKQQ6.js.map} +0 -0
  135. /package/dist/{model-policy-picker-menu-JSA64TNN.js.map → model-policy-picker-menu-PUTA5JOB.js.map} +0 -0
  136. /package/dist/{sandbox-files-BBC47SLD.js.map → sandbox-files-AEJTWGT4.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/internal.ts"],"sourcesContent":["import type { SessionEvent } from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport type { EmbeddedSessionEventClientLike } from \"../client\";\n\nconst HIDDEN_STREAM_GRACE_MS = 2_000;\n\n/**\n * Keep live browser work active while the page is visible, then suspend it\n * after a short hidden-tab grace period. Returning to the page re-enables the\n * caller, which must reconcile durable state before resuming live delivery.\n */\nexport function usePageLiveActivity(hiddenGraceMs = HIDDEN_STREAM_GRACE_MS): boolean {\n // Keep the server and initial browser render identical; the effect applies\n // visibility after mount and preserves the intentional hidden-tab grace.\n const [active, setActive] = useState(true);\n\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n let hiddenTimer: ReturnType<typeof setTimeout> | null = null;\n const cancelHiddenTimer = () => {\n if (hiddenTimer !== null) {\n clearTimeout(hiddenTimer);\n hiddenTimer = null;\n }\n };\n const sync = () => {\n cancelHiddenTimer();\n if (document.visibilityState !== \"hidden\") {\n setActive(true);\n return;\n }\n hiddenTimer = setTimeout(() => {\n hiddenTimer = null;\n if (document.visibilityState === \"hidden\") setActive(false);\n }, hiddenGraceMs);\n };\n document.addEventListener(\"visibilitychange\", sync);\n window.addEventListener(\"pageshow\", sync);\n sync();\n return () => {\n cancelHiddenTimer();\n document.removeEventListener(\"visibilitychange\", sync);\n window.removeEventListener(\"pageshow\", sync);\n };\n }, [hiddenGraceMs]);\n\n return active;\n}\n\nexport type AsyncListState<T> = {\n data: T | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n};\n\n/**\n * Shared fetch + optional polling loop for the list/read hooks. Stale\n * responses (superseded by a newer load or an unmount) are dropped.\n */\nexport function usePolledValue<T>(\n load: (signal?: AbortSignal) => Promise<T>,\n options: { pollIntervalMs?: number | undefined; enabled?: boolean | undefined } = {},\n): AsyncListState<T> {\n const enabled = options.enabled ?? true;\n const pollIntervalMs = options.pollIntervalMs;\n const pageLive = usePageLiveActivity();\n const [data, setData] = useState<T | null>(null);\n const [loading, setLoading] = useState(enabled);\n const [error, setError] = useState<Error | null>(null);\n const generation = useRef(0);\n const activeLoadRef = useRef(load);\n useLayoutEffect(() => {\n activeLoadRef.current = load;\n }, [load]);\n const requestAbortRef = useRef<AbortController | null>(null);\n const inFlightRef = useRef<{ load: typeof load; promise: Promise<void> } | null>(null);\n const trailingRefreshRef = useRef<{ load: typeof load; promise: Promise<void> } | null>(null);\n const [stateIdentity, setStateIdentity] = useState<{ load: typeof load }>(() => ({ load }));\n\n // A new loader identity means a new query (different session/workspace/...):\n // drop the previous result instead of showing it as the new query's data.\n useEffect(() => {\n if (stateIdentity.load !== load) {\n setStateIdentity({ load });\n setData(null);\n setError(null);\n }\n }, [load, stateIdentity.load]);\n\n const run = useCallback((): Promise<void> => {\n // A callback retained by a completed mutation from the previous query must\n // not supersede or settle the current query's request.\n if (activeLoadRef.current !== load) return Promise.resolve();\n const existing = inFlightRef.current;\n if (existing?.load === load) return existing.promise;\n const ticket = ++generation.current;\n const requestAbort = new AbortController();\n requestAbortRef.current = requestAbort;\n let promise!: Promise<void>;\n promise = (async () => {\n try {\n const result = await load(requestAbort.signal);\n if (\n ticket === generation.current &&\n activeLoadRef.current === load &&\n !requestAbort.signal.aborted\n ) {\n setData(result);\n setError(null);\n setLoading(false);\n }\n } catch (cause) {\n if (\n ticket === generation.current &&\n activeLoadRef.current === load &&\n !requestAbort.signal.aborted\n ) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n setLoading(false);\n }\n } finally {\n if (requestAbortRef.current === requestAbort) requestAbortRef.current = null;\n if (inFlightRef.current?.promise === promise) inFlightRef.current = null;\n }\n })();\n inFlightRef.current = { load, promise };\n return promise;\n }, [load]);\n\n const refresh = useCallback((): Promise<void> => {\n const existing = inFlightRef.current;\n if (existing?.load !== load) return run();\n const trailing = trailingRefreshRef.current;\n if (trailing?.load === load) return trailing.promise;\n let promise!: Promise<void>;\n promise = existing.promise.then(async () => {\n if (trailingRefreshRef.current?.promise === promise) {\n trailingRefreshRef.current = null;\n }\n if (activeLoadRef.current === load) await run();\n });\n trailingRefreshRef.current = { load, promise };\n return promise;\n }, [load, run]);\n\n useEffect(() => {\n if (!enabled || !pageLive) {\n setLoading(false);\n generation.current += 1;\n requestAbortRef.current?.abort();\n inFlightRef.current = null;\n trailingRefreshRef.current = null;\n return;\n }\n setLoading(true);\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n const schedule = () => {\n if (cancelled || pollIntervalMs === undefined || pollIntervalMs <= 0) return;\n timer = setTimeout(() => {\n timer = null;\n void run().finally(schedule);\n }, pollIntervalMs);\n };\n void run().finally(schedule);\n if (pollIntervalMs === undefined || pollIntervalMs <= 0) {\n return () => {\n cancelled = true;\n generation.current += 1;\n requestAbortRef.current?.abort();\n inFlightRef.current = null;\n trailingRefreshRef.current = null;\n };\n }\n return () => {\n cancelled = true;\n if (timer !== null) clearTimeout(timer);\n generation.current += 1;\n requestAbortRef.current?.abort();\n inFlightRef.current = null;\n trailingRefreshRef.current = null;\n };\n }, [run, enabled, pageLive, pollIntervalMs]);\n\n const identityMatches = stateIdentity.load === load;\n return {\n data: identityMatches ? data : null,\n loading: identityMatches ? loading : enabled,\n error: identityMatches ? error : null,\n refresh,\n };\n}\n\nexport type MutationState = {\n mutating: boolean;\n mutationError: Error | null;\n clearMutationError: () => void;\n};\n\n/**\n * Shared async mutation runner for the write hooks. `run` resolves with the\n * operation's value, or `null` after capturing the error in `mutationError`\n * (callers then roll back optimistic state).\n */\nexport function useMutationRunner(identity: unknown = undefined): MutationState & {\n run: <T>(operation: () => Promise<T>) => Promise<T | null>;\n} {\n const [mutating, setMutating] = useState(false);\n const [mutationError, setMutationError] = useState<Error | null>(null);\n const [stateIdentity, setStateIdentity] = useState<unknown>(() => identity);\n const inFlight = useRef(0);\n const generation = useRef(0);\n const identityRef = useRef(identity);\n useLayoutEffect(() => {\n if (Object.is(identityRef.current, identity)) return;\n identityRef.current = identity;\n generation.current += 1;\n inFlight.current = 0;\n }, [identity]);\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n useEffect(() => {\n if (!Object.is(stateIdentity, identity)) {\n setStateIdentity(() => identity);\n setMutating(false);\n setMutationError(null);\n }\n }, [identity, stateIdentity]);\n const run = useCallback(\n async <T>(operation: () => Promise<T>): Promise<T | null> => {\n const ownedIdentity = identity;\n const ownedGeneration = generation.current;\n if (!Object.is(identityRef.current, ownedIdentity)) return null;\n inFlight.current += 1;\n if (mounted.current) {\n setMutating(true);\n setMutationError(null);\n }\n try {\n const result = await operation();\n if (\n !mounted.current ||\n generation.current !== ownedGeneration ||\n !Object.is(identityRef.current, ownedIdentity)\n ) {\n return null;\n }\n return result;\n } catch (cause) {\n if (\n mounted.current &&\n generation.current === ownedGeneration &&\n Object.is(identityRef.current, ownedIdentity)\n ) {\n setMutationError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n return null;\n } finally {\n if (\n generation.current === ownedGeneration &&\n Object.is(identityRef.current, ownedIdentity)\n ) {\n inFlight.current -= 1;\n if (mounted.current && inFlight.current === 0) {\n setMutating(false);\n }\n }\n }\n },\n [identity],\n );\n const identityMatches = Object.is(stateIdentity, identity);\n return {\n mutating: identityMatches && mutating,\n mutationError: identityMatches ? mutationError : null,\n clearMutationError: useCallback(() => {\n if (Object.is(identityRef.current, identity)) setMutationError(null);\n }, [identity]),\n run,\n };\n}\n\nexport type SessionEventFeedOptions = {\n /**\n * Share an existing event log (from `useSessionEvents`) instead of opening\n * a second stream. When omitted the hook tails the session's event stream\n * itself, starting at the current `lastSequence`.\n */\n events?: SessionEvent[] | undefined;\n enabled?: boolean | undefined;\n};\n\n/**\n * Invoke `onEvent` for every session event matching `match` — the live-update\n * primitive behind `useTurnQueue` and `useGoal`. Either watches a shared\n * `events` log or tails the stream directly (reconnect handled by the SDK).\n */\nexport function useSessionEventTrigger(\n client: EmbeddedSessionEventClientLike,\n workspaceId: string,\n sessionId: string | null | undefined,\n match: (event: SessionEvent) => boolean,\n onEvent: (event: SessionEvent) => void,\n options: SessionEventFeedOptions = {},\n reconcileBeforeLive?: (() => void | Promise<void>) | undefined,\n): void {\n const enabled = options.enabled ?? true;\n const pageLive = usePageLiveActivity();\n const liveEnabled = enabled && pageLive;\n const events = options.events;\n const sharedFeed = events !== undefined;\n const matchRef = useRef(match);\n const onEventRef = useRef(onEvent);\n const reconcileBeforeLiveRef = useRef(reconcileBeforeLive);\n useLayoutEffect(() => {\n matchRef.current = match;\n onEventRef.current = onEvent;\n reconcileBeforeLiveRef.current = reconcileBeforeLive;\n }, [match, onEvent, reconcileBeforeLive]);\n const consumedRef = useRef(0);\n const feedKeyRef = useRef<string | null>(null);\n const sharedFeedHasEventsRef = useRef(false);\n\n // Shared-log mode: scan only the unseen tail on every append.\n useEffect(() => {\n if (!sharedFeed || !liveEnabled || !sessionId) {\n return;\n }\n const feedKey = `${workspaceId}\\u0000${sessionId}`;\n const firstSequence = events[0]?.sequence ?? 0;\n if (feedKeyRef.current !== feedKey) {\n feedKeyRef.current = feedKey;\n sharedFeedHasEventsRef.current = events.length > 0;\n // The caller has already loaded its authoritative initial projection.\n // Seed from the shared log's current tail so mounting a large historical\n // session cannot replay every old event as a new live trigger.\n consumedRef.current = events.at(-1)?.sequence ?? 0;\n return;\n }\n const firstNonEmptyBatch = !sharedFeedHasEventsRef.current && events.length > 0;\n if (firstNonEmptyBatch || firstSequence > consumedRef.current + 1) {\n // The usual shared feed mounts empty, then receives a historical tail.\n // A later discontinuity can likewise replace the retained browser\n // window. In either case, reconcile once from the latest relevant event\n // instead of replaying the whole retained window as live traffic.\n sharedFeedHasEventsRef.current = events.length > 0;\n consumedRef.current = events.at(-1)?.sequence ?? consumedRef.current;\n let latestMatch: SessionEvent | undefined;\n for (let index = events.length - 1; index >= 0; index -= 1) {\n const event = events[index];\n if (event && matchRef.current(event)) {\n latestMatch = event;\n break;\n }\n }\n if (latestMatch) {\n onEventRef.current(latestMatch);\n }\n return;\n }\n sharedFeedHasEventsRef.current ||= events.length > 0;\n for (const event of events) {\n if (event.sequence <= consumedRef.current) {\n continue;\n }\n consumedRef.current = event.sequence;\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n }, [sharedFeed, liveEnabled, events, workspaceId, sessionId]);\n\n // Self-stream mode: tail from the session's current lastSequence.\n useEffect(() => {\n if (sharedFeed || !liveEnabled || !sessionId) {\n return;\n }\n const controller = new AbortController();\n void (async () => {\n try {\n const session = await client.getSession(workspaceId, sessionId);\n if (controller.signal.aborted) {\n return;\n }\n const stream = client.streamEvents(workspaceId, sessionId, {\n after: session.lastSequence,\n signal: controller.signal,\n onOpen: () => {\n // Start reconciliation without delaying consumption of live SSE.\n void Promise.resolve()\n .then(() => reconcileBeforeLiveRef.current?.())\n .catch(() => undefined);\n },\n });\n for await (const event of stream) {\n if (matchRef.current(event)) {\n onEventRef.current(event);\n }\n }\n } catch {\n // Live updates are best-effort: the read hooks still expose refresh()\n // and the initial load already populated state.\n }\n })();\n return () => {\n controller.abort();\n };\n }, [sharedFeed, liveEnabled, client, workspaceId, sessionId]);\n}\n\n/** Debounce rapid event bursts into one trailing call (default 150ms). */\nexport function useDebouncedCallback(callback: () => void, delayMs = 150): () => void {\n const callbackRef = useRef(callback);\n useLayoutEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n return () => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n return useCallback(() => {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n }\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n callbackRef.current();\n }, delayMs);\n }, [delayMs]);\n}\n"],"mappings":"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","names":[]}