@sanity/ui 4.0.0-static.40 → 4.0.0-static.41

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ui",
3
- "version": "4.0.0-static.40",
3
+ "version": "4.0.0-static.41",
4
4
  "keywords": [
5
5
  "react",
6
6
  "ui",
@@ -1,6 +1,6 @@
1
1
  import type {ResponsiveProp} from '@sanity/ui/css'
2
2
  import {AnimatePresence} from 'framer-motion'
3
- import {startTransition, useMemo, useState} from 'react'
3
+ import {startTransition, useMemo, useRef, useState} from 'react'
4
4
 
5
5
  import {useMounted} from '../../hooks/useMounted'
6
6
  import {LayerProvider} from '../../primitives/layer/LayerProvider'
@@ -28,11 +28,20 @@ export function ToastProvider(props: ToastProviderProps): React.JSX.Element {
28
28
  const [state, setState] = useState<ToastState>([])
29
29
  const mounted = useMounted()
30
30
 
31
+ const timeoutIdsRef = useRef<Record<string, NodeJS.Timeout | undefined>>({})
32
+
31
33
  const value: ToastContextValue = useMemo(() => {
32
34
  const push = (params: ToastParams) => {
33
35
  const id = params.id ?? generateToastId()
34
36
  const duration = params.duration ?? 5000
35
37
 
38
+ // If the `id` is reused, clear the previous timeout
39
+ const existingTimeoutId = timeoutIdsRef.current[id]
40
+ if (existingTimeoutId) {
41
+ clearTimeout(existingTimeoutId)
42
+ timeoutIdsRef.current[id] = undefined
43
+ }
44
+
36
45
  startTransition(() => {
37
46
  setState((prevState): ToastState => {
38
47
  /**
@@ -50,18 +59,24 @@ export function ToastProvider(props: ToastProviderProps): React.JSX.Element {
50
59
  * This function will be passed to the Toast component
51
60
  * and called either on close button click or after duration.
52
61
  */
53
- const dismiss = () => {
62
+ function dismiss() {
54
63
  startTransition(() => {
55
64
  if (timeoutId) {
56
65
  clearTimeout(timeoutId)
57
66
  }
58
67
 
59
68
  setState((currentState) => currentState.filter((toast) => toast.id !== id))
69
+
70
+ // Clear the timeout id from the ref to prevent memory leaks
71
+ timeoutIdsRef.current[id] = undefined
60
72
  })
61
73
  }
62
74
 
63
75
  const timeoutId = duration === Infinity ? undefined : setTimeout(dismiss, duration)
64
76
 
77
+ // Set the timeout id in the ref
78
+ timeoutIdsRef.current[id] = timeoutId
79
+
65
80
  /**
66
81
  * Create updated state by:
67
82
  * 1. Removing any existing toast with the same ID (prevents duplicates)