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

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.42",
4
4
  "keywords": [
5
5
  "react",
6
6
  "ui",
@@ -119,7 +119,7 @@
119
119
  "@sanity/icons": "^3.7.4",
120
120
  "@vanilla-extract/dynamic": "^2.1.5",
121
121
  "csstype": "^3.1.3",
122
- "framer-motion": "^12.23.24",
122
+ "motion": "^12.23.24",
123
123
  "react-refractor": "^4.0.0",
124
124
  "use-effect-event": "^2.0.3"
125
125
  },
@@ -132,10 +132,10 @@
132
132
  "@commitlint/config-conventional": "^19.8.1",
133
133
  "@eslint/js": "^9.37.0",
134
134
  "@sanity/browserslist-config": "^1.0.5",
135
- "@sanity/pkg-utils": "^8.1.19",
135
+ "@sanity/pkg-utils": "^8.1.24",
136
136
  "@sanity/prettier-config": "^2.0.1",
137
137
  "@sanity/semantic-release-preset": "^5.0.0",
138
- "@sanity/ui-workshop": "4.0.0-static.11",
138
+ "@sanity/ui-workshop": "4.0.0-static.12",
139
139
  "@testing-library/dom": "^10.4.1",
140
140
  "@testing-library/jest-dom": "^6.8.0",
141
141
  "@testing-library/react": "^16.3.0",
@@ -1,6 +1,6 @@
1
1
  import {CloseIcon} from '@sanity/icons'
2
2
  import {type RadiusStyleProps, toast} from '@sanity/ui/css'
3
- import {motion, type Variant, type Variants} from 'framer-motion'
3
+ import {motion, type Variant, type Variants} from 'motion/react'
4
4
  import {type ReactNode} from 'react'
5
5
 
6
6
  import {usePrefersReducedMotion} from '../../hooks/usePrefersReducedMotion'
@@ -1,6 +1,6 @@
1
1
  import type {ResponsiveProp} from '@sanity/ui/css'
2
- import {AnimatePresence} from 'framer-motion'
3
- import {startTransition, useMemo, useState} from 'react'
2
+ import {AnimatePresence} from 'motion/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)
@@ -1,4 +1,4 @@
1
- import type {Transition, Variant} from 'framer-motion'
1
+ import type {Transition, Variant} from 'motion/react'
2
2
 
3
3
  export const EMPTY_ARRAY: never[] = []
4
4
 
@@ -11,7 +11,7 @@ import {
11
11
  useFloating,
12
12
  } from '@floating-ui/react-dom'
13
13
  import {type MaxWidth, popover as popoverCss, type ResponsiveProp} from '@sanity/ui/css'
14
- import {AnimatePresence} from 'framer-motion'
14
+ import {AnimatePresence} from 'motion/react'
15
15
  import {
16
16
  cloneElement,
17
17
  type ForwardedRef,
@@ -1,6 +1,6 @@
1
1
  import type {Strategy} from '@floating-ui/react-dom'
2
2
  import {popoverCard} from '@sanity/ui/css'
3
- import {motion} from 'framer-motion'
3
+ import {motion} from 'motion/react'
4
4
  import {type CSSProperties, type ForwardedRef, useMemo} from 'react'
5
5
 
6
6
  import {POPOVER_MOTION_PROPS} from '../../constants'
@@ -10,7 +10,7 @@ import {
10
10
  } from '@floating-ui/react-dom'
11
11
  import {type RadiusStyleProps, type ShadowStyleProps, tooltip} from '@sanity/ui/css'
12
12
  import type {CardTone, ColorScheme} from '@sanity/ui/theme'
13
- import {AnimatePresence} from 'framer-motion'
13
+ import {AnimatePresence} from 'motion/react'
14
14
  import {
15
15
  cloneElement,
16
16
  type FocusEvent,
@@ -1,4 +1,4 @@
1
- import {motion, type MotionStyle} from 'framer-motion'
1
+ import {motion, type MotionStyle} from 'motion/react'
2
2
  import {type CSSProperties, type ForwardedRef, useMemo} from 'react'
3
3
 
4
4
  import {POPOVER_MOTION_PROPS} from '../../constants'