@mui/utils 6.4.8 → 6.4.9

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/CHANGELOG.md CHANGED
@@ -1,5 +1,59 @@
1
1
  # [Versions](https://mui.com/versions/)
2
2
 
3
+ ## 6.4.10
4
+
5
+ <!-- generated comparing v6.4.9..v6.x -->
6
+
7
+ _Mar 31, 2025_
8
+
9
+ A big thanks to the 4 contributors who made this release possible.
10
+
11
+ ### `@mui/material@6.4.10`
12
+
13
+ - [Autocomplete] Prevent shrink animation in controlled Autocomplete when initial `value` is provided (#45735) @imadx
14
+ - [Popover] Allow `null` in `anchorEl` function return type (#45723) @eduter
15
+
16
+ ### Docs
17
+
18
+ - Fix new React project link, CRA deprecated (#45669) @oliviertassinari
19
+
20
+ ### Core
21
+
22
+ - [utils] Support cleanup callbacks in useForkRef (#45733) @DiegoAndai
23
+
24
+ All contributors of this release in alphabetical order: @DiegoAndai, @eduter, @imadx, @oliviertassinari
25
+
26
+ ## 6.4.9
27
+
28
+ <!-- generated comparing v6.4.8..v6.x -->
29
+
30
+ _Mar 25, 2025_
31
+
32
+ A big thanks to the 7 contributors who made this release possible.
33
+
34
+ ### `@mui/material@6.4.9`
35
+
36
+ - [Autocomplete] Fix when `onHighlightChange` is called (@ZeeshanTamboli) (#45635) @ZeeshanTamboli
37
+ - [StepLabel] Add missing root slot (#45607) @sai6855
38
+ - [Switch] Add slots and slotProps (#45628) @siriwatknp
39
+ - [TextField] Add `root` slot (#45616) @sai6855
40
+ - [Tabs] Fix modifier keys + Left/Right Arrow key from being consumed by tab navigation (#45620) @mushfiqbh
41
+
42
+ ### `@mui/codemon@6.4.9`
43
+
44
+ - Add missing deprecations in deprecations-all file (#45508) @sai6855
45
+
46
+ ### Docs
47
+
48
+ - [docs] Fix grammatical errors in support.md (#45636) @letianpailove
49
+ - [docs] Restore utility component docs from MUI Base to Material UI (#45240) @mapache-salvaje
50
+
51
+ ### Core
52
+
53
+ - [core] Prepare v6 branch for v7 stable release (#45668) @DiegoAndai
54
+
55
+ All contributors of this release in alphabetical order: @DiegoAndai, @letianpailove, @mapache-salvaje, @mushfiqbh, @sai6855, @siriwatknp, @ZeeshanTamboli
56
+
3
57
  ## 6.4.8
4
58
 
5
59
  <!-- generated comparing v6.4.7..v6.x -->
@@ -1,11 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
- import setRef from "../setRef/index.js";
5
4
 
6
5
  /**
7
- * Takes an array of refs and returns a new ref which will apply any modification to all of the refs.
8
- * This is useful when you want to have the ref used in multiple places.
6
+ * Merges refs into a single memoized callback ref or `null`.
9
7
  *
10
8
  * ```tsx
11
9
  * const rootRef = React.useRef<Instance>(null);
@@ -20,19 +18,41 @@ import setRef from "../setRef/index.js";
20
18
  * @returns {React.RefCallback<Instance> | null} The new ref callback.
21
19
  */
22
20
  export default function useForkRef(...refs) {
23
- /**
24
- * This will create a new function if the refs passed to this hook change and are all defined.
25
- * This means react will call the old forkRef with `null` and the new forkRef
26
- * with the ref. Cleanup naturally emerges from this behavior.
27
- */
21
+ const cleanupRef = React.useRef(undefined);
22
+ const refEffect = React.useCallback(instance => {
23
+ const cleanups = refs.map(ref => {
24
+ if (ref == null) {
25
+ return null;
26
+ }
27
+ if (typeof ref === 'function') {
28
+ const refCallback = ref;
29
+ const refCleanup = refCallback(instance);
30
+ return typeof refCleanup === 'function' ? refCleanup : () => {
31
+ refCallback(null);
32
+ };
33
+ }
34
+ ref.current = instance;
35
+ return () => {
36
+ ref.current = null;
37
+ };
38
+ });
39
+ return () => {
40
+ cleanups.forEach(refCleanup => refCleanup?.());
41
+ };
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, refs);
28
44
  return React.useMemo(() => {
29
45
  if (refs.every(ref => ref == null)) {
30
46
  return null;
31
47
  }
32
- return instance => {
33
- refs.forEach(ref => {
34
- setRef(ref, instance);
35
- });
48
+ return value => {
49
+ if (cleanupRef.current) {
50
+ cleanupRef.current();
51
+ cleanupRef.current = undefined;
52
+ }
53
+ if (value != null) {
54
+ cleanupRef.current = refEffect(value);
55
+ }
36
56
  };
37
57
  // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler -- intentionally ignoring that the dependency array must be an array literal
38
58
  // eslint-disable-next-line react-hooks/exhaustive-deps
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v6.4.8
2
+ * @mui/utils v6.4.9
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v6.4.8
2
+ * @mui/utils v6.4.9
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -1,11 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
- import setRef from "../setRef/index.js";
5
4
 
6
5
  /**
7
- * Takes an array of refs and returns a new ref which will apply any modification to all of the refs.
8
- * This is useful when you want to have the ref used in multiple places.
6
+ * Merges refs into a single memoized callback ref or `null`.
9
7
  *
10
8
  * ```tsx
11
9
  * const rootRef = React.useRef<Instance>(null);
@@ -20,19 +18,41 @@ import setRef from "../setRef/index.js";
20
18
  * @returns {React.RefCallback<Instance> | null} The new ref callback.
21
19
  */
22
20
  export default function useForkRef(...refs) {
23
- /**
24
- * This will create a new function if the refs passed to this hook change and are all defined.
25
- * This means react will call the old forkRef with `null` and the new forkRef
26
- * with the ref. Cleanup naturally emerges from this behavior.
27
- */
21
+ const cleanupRef = React.useRef(undefined);
22
+ const refEffect = React.useCallback(instance => {
23
+ const cleanups = refs.map(ref => {
24
+ if (ref == null) {
25
+ return null;
26
+ }
27
+ if (typeof ref === 'function') {
28
+ const refCallback = ref;
29
+ const refCleanup = refCallback(instance);
30
+ return typeof refCleanup === 'function' ? refCleanup : () => {
31
+ refCallback(null);
32
+ };
33
+ }
34
+ ref.current = instance;
35
+ return () => {
36
+ ref.current = null;
37
+ };
38
+ });
39
+ return () => {
40
+ cleanups.forEach(refCleanup => refCleanup?.());
41
+ };
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, refs);
28
44
  return React.useMemo(() => {
29
45
  if (refs.every(ref => ref == null)) {
30
46
  return null;
31
47
  }
32
- return instance => {
33
- refs.forEach(ref => {
34
- setRef(ref, instance);
35
- });
48
+ return value => {
49
+ if (cleanupRef.current) {
50
+ cleanupRef.current();
51
+ cleanupRef.current = undefined;
52
+ }
53
+ if (value != null) {
54
+ cleanupRef.current = refEffect(value);
55
+ }
36
56
  };
37
57
  // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler -- intentionally ignoring that the dependency array must be an array literal
38
58
  // eslint-disable-next-line react-hooks/exhaustive-deps
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/utils",
3
- "version": "6.4.8",
3
+ "version": "6.4.9",
4
4
  "private": false,
5
5
  "author": "MUI Team",
6
6
  "description": "Utility functions for React components.",
@@ -1,7 +1,6 @@
1
1
  import * as React from 'react';
2
2
  /**
3
- * Takes an array of refs and returns a new ref which will apply any modification to all of the refs.
4
- * This is useful when you want to have the ref used in multiple places.
3
+ * Merges refs into a single memoized callback ref or `null`.
5
4
  *
6
5
  * ```tsx
7
6
  * const rootRef = React.useRef<Instance>(null);
@@ -1,17 +1,14 @@
1
1
  "use strict";
2
2
  'use client';
3
3
 
4
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5
4
  var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
6
5
  Object.defineProperty(exports, "__esModule", {
7
6
  value: true
8
7
  });
9
8
  exports.default = useForkRef;
10
9
  var React = _interopRequireWildcard(require("react"));
11
- var _setRef = _interopRequireDefault(require("../setRef"));
12
10
  /**
13
- * Takes an array of refs and returns a new ref which will apply any modification to all of the refs.
14
- * This is useful when you want to have the ref used in multiple places.
11
+ * Merges refs into a single memoized callback ref or `null`.
15
12
  *
16
13
  * ```tsx
17
14
  * const rootRef = React.useRef<Instance>(null);
@@ -26,19 +23,41 @@ var _setRef = _interopRequireDefault(require("../setRef"));
26
23
  * @returns {React.RefCallback<Instance> | null} The new ref callback.
27
24
  */
28
25
  function useForkRef(...refs) {
29
- /**
30
- * This will create a new function if the refs passed to this hook change and are all defined.
31
- * This means react will call the old forkRef with `null` and the new forkRef
32
- * with the ref. Cleanup naturally emerges from this behavior.
33
- */
26
+ const cleanupRef = React.useRef(undefined);
27
+ const refEffect = React.useCallback(instance => {
28
+ const cleanups = refs.map(ref => {
29
+ if (ref == null) {
30
+ return null;
31
+ }
32
+ if (typeof ref === 'function') {
33
+ const refCallback = ref;
34
+ const refCleanup = refCallback(instance);
35
+ return typeof refCleanup === 'function' ? refCleanup : () => {
36
+ refCallback(null);
37
+ };
38
+ }
39
+ ref.current = instance;
40
+ return () => {
41
+ ref.current = null;
42
+ };
43
+ });
44
+ return () => {
45
+ cleanups.forEach(refCleanup => refCleanup?.());
46
+ };
47
+ // eslint-disable-next-line react-hooks/exhaustive-deps
48
+ }, refs);
34
49
  return React.useMemo(() => {
35
50
  if (refs.every(ref => ref == null)) {
36
51
  return null;
37
52
  }
38
- return instance => {
39
- refs.forEach(ref => {
40
- (0, _setRef.default)(ref, instance);
41
- });
53
+ return value => {
54
+ if (cleanupRef.current) {
55
+ cleanupRef.current();
56
+ cleanupRef.current = undefined;
57
+ }
58
+ if (value != null) {
59
+ cleanupRef.current = refEffect(value);
60
+ }
42
61
  };
43
62
  // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler -- intentionally ignoring that the dependency array must be an array literal
44
63
  // eslint-disable-next-line react-hooks/exhaustive-deps