@mui/utils 9.1.1 → 9.3.0
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 +141 -0
- package/ClassNameGenerator/ClassNameGenerator.d.mts +2 -1
- package/ClassNameGenerator/ClassNameGenerator.d.ts +2 -1
- package/elementAcceptingRef/elementAcceptingRef.js +1 -1
- package/elementAcceptingRef/elementAcceptingRef.mjs +1 -1
- package/elementTypeAcceptingRef/elementTypeAcceptingRef.js +1 -1
- package/elementTypeAcceptingRef/elementTypeAcceptingRef.mjs +1 -1
- package/getDisplayName/getDisplayName.d.mts +1 -1
- package/getDisplayName/getDisplayName.d.ts +1 -1
- package/getDisplayName/getDisplayName.js +1 -1
- package/getDisplayName/getDisplayName.mjs +1 -1
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/isMuiElement/isMuiElement.js +1 -1
- package/isMuiElement/isMuiElement.mjs +1 -1
- package/package.json +4 -4
- package/types/DataAttributes.d.mts +45 -0
- package/types/DataAttributes.d.ts +45 -0
- package/types/DataAttributes.js +5 -0
- package/types/DataAttributes.mjs +1 -0
- package/types/index.d.mts +4 -2
- package/types/index.d.ts +4 -2
- package/useEventCallback/useEventCallback.d.mts +1 -1
- package/useEventCallback/useEventCallback.d.ts +1 -1
- package/useEventCallback/useEventCallback.js +1 -1
- package/useEventCallback/useEventCallback.mjs +1 -1
- package/useForkRef/useForkRef.js +2 -2
- package/useForkRef/useForkRef.mjs +2 -2
- package/useId/useId.js +1 -0
- package/useId/useId.mjs +1 -0
- package/useIsFocusVisible/useIsFocusVisible.js +2 -2
- package/useIsFocusVisible/useIsFocusVisible.mjs +2 -2
- package/useRovingTabIndex/useRovingTabIndex.d.mts +1 -1
- package/useRovingTabIndex/useRovingTabIndex.d.ts +1 -1
- package/useRovingTabIndex/useRovingTabIndex.js +4 -2
- package/useRovingTabIndex/useRovingTabIndex.mjs +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,146 @@
|
|
|
1
1
|
# [Versions](https://mui.com/material-ui/getting-started/versions/)
|
|
2
2
|
|
|
3
|
+
## 9.3.0
|
|
4
|
+
|
|
5
|
+
<!-- generated comparing v9.2.0..master -->
|
|
6
|
+
|
|
7
|
+
_Aug 4, 2026_
|
|
8
|
+
|
|
9
|
+
A big thanks to the 18 contributors who made this release possible. Here are some highlights ✨:
|
|
10
|
+
|
|
11
|
+
- ♿️ Keyboard navigation in the [Toggle Button Group](https://mui.com/material-ui/react-toggle-button/) now follows the roving tabindex pattern.
|
|
12
|
+
- ♿️ The [Autocomplete](https://mui.com/material-ui/react-autocomplete/) announces its loading and no options messages through a new `status` slot.
|
|
13
|
+
|
|
14
|
+
### `@mui/material@9.3.0`
|
|
15
|
+
|
|
16
|
+
- [autocomplete] Wrap the no results and loading messages in an aria live region (#48690) @silviuaavram
|
|
17
|
+
- [buttongroup] Respect global disableRipple / disableFocusRipple in grouped buttons (#48762) @siriwatknp
|
|
18
|
+
- [checkbox][radio] Respect global disableRipple from MuiButtonBase defaultProps (#48795) @siriwatknp
|
|
19
|
+
- [formcontrollabel] Add missing `labelPlacementEnd` class (#48843) @siriwatknp
|
|
20
|
+
- [listitembutton] Fix typos in component code (#48868) @ZeeshanTamboli
|
|
21
|
+
- [menuitem] Add `aria-checked` for checkbox and radio menu items (#48651) @siriwatknp
|
|
22
|
+
- [modal] Replace custom findIndexOf with findIndex (#48827) @ZeeshanTamboli
|
|
23
|
+
- [modal][dialog] Fix scrollbar compensation in Shadow DOM (#48826) @ZeeshanTamboli
|
|
24
|
+
- [select] Fix endAdornment overlapping the open indicator (#48723) @siriwatknp
|
|
25
|
+
- [tablepagination] Add focus style to default InputBase used in Select (#48871) @silviuaavram
|
|
26
|
+
- [togglebuttongroup] Add roving tabindex keyboard navigation (#48849) @silviuaavram
|
|
27
|
+
|
|
28
|
+
### `@mui/system@9.3.0`
|
|
29
|
+
|
|
30
|
+
- Prevent prototype pollution in cssVarsParser (#48822) @Janpot
|
|
31
|
+
|
|
32
|
+
### `@mui/codemod@9.3.0`
|
|
33
|
+
|
|
34
|
+
- Don't leak state between files in v5.0.0/path-imports (#48797) @manbearwiz
|
|
35
|
+
- Remove use of eval() (#48701) @oliviertassinari
|
|
36
|
+
- Transform all style exports in `v5.0.0/path-imports` codemod (#48800) @manbearwiz
|
|
37
|
+
|
|
38
|
+
### Docs
|
|
39
|
+
|
|
40
|
+
- Clarify `container` prop inheritance for Shadow DOM (#48670) @Juan-C-Ceballos
|
|
41
|
+
- Clarify third-party script risk in CSP unsafe-inline note (#48787) @Janpot
|
|
42
|
+
- Document `box-sx-prop` codemod (#48888) @SR0725
|
|
43
|
+
- Document Grid direction column removal in v9 upgrade guide (#48880) @kalayciburak
|
|
44
|
+
- Fix color contrast in GitHub labels example (#48844) @silviuaavram
|
|
45
|
+
- Fix per-page canonical URL and stale SEO link (#48789) @brijeshb42
|
|
46
|
+
- Fix redirect loop on the Design Kits page (#48869) @Janpot
|
|
47
|
+
- Fix typo 'overriden' -> 'overridden' in CHANGELOG (#48785) @ZhouYinLong-lab
|
|
48
|
+
- Improve TransferList examples (#48845) @silviuaavram
|
|
49
|
+
- Link a new theme generator tool (#48847) @mansourcodes
|
|
50
|
+
- Remove broken learning resource links (#48598) @morning-verlu
|
|
51
|
+
- Update the 9.2.0 changelog (#48763) @silviuaavram
|
|
52
|
+
- [autocomplete] Clarify how to render custom start and end adornments (#48883) @DebadityaHait
|
|
53
|
+
- [drawer] Clarify clipped AppBar spacing (#48887) @rushijagani-dev
|
|
54
|
+
- [menu] Fix stale `selected` prop reference in Selected menu section (#48879) @LukasTy
|
|
55
|
+
- [skeleton] Document preserving typography sizing with custom border radius (#48596) @meaqua9420
|
|
56
|
+
|
|
57
|
+
### Core
|
|
58
|
+
|
|
59
|
+
- [blog] Fix caret annotation broken by Prettier wrapping (#48884) @bernardobelchior
|
|
60
|
+
- [code-infra] Automate team sync on about page (#48794) @brijeshb42
|
|
61
|
+
- [code-infra] Bump @mui/internal-code-infra to 0.0.4-canary.101 (#48878) @Janpot
|
|
62
|
+
- [code-infra] Fix Dependabot alerts (#48756) @Janpot
|
|
63
|
+
- [code-infra] Fix team sync PR creation (#48911) @brijeshb42
|
|
64
|
+
- [code-infra] Pin node version in publish CI (#48799) @brijeshb42
|
|
65
|
+
- [core-docs] Tighten service worker host check (#48581) @Janpot
|
|
66
|
+
- [docs-infra] Change branch name to the allowed one (#48910) @brijeshb42
|
|
67
|
+
|
|
68
|
+
All contributors of this release in alphabetical order: @bernardobelchior, @brijeshb42, @DebadityaHait, @Janpot, @Juan-C-Ceballos, @kalayciburak, @LukasTy, @manbearwiz, @mansourcodes, @meaqua9420, @morning-verlu, @oliviertassinari, @rushijagani-dev, @silviuaavram, @siriwatknp, @SR0725, @ZeeshanTamboli, @ZhouYinLong-lab
|
|
69
|
+
|
|
70
|
+
## 9.2.0
|
|
71
|
+
|
|
72
|
+
<!-- generated comparing v9.1.2..master -->
|
|
73
|
+
|
|
74
|
+
_Jul 3, 2026_
|
|
75
|
+
|
|
76
|
+
A big thanks to the 9 contributors who made this release possible.
|
|
77
|
+
|
|
78
|
+
- ⚙️ Add support for [`data-*` attributes on `slotProps`](https://mui.com/material-ui/guides/typescript/#allowing-data-attributes-on-slotprops).
|
|
79
|
+
|
|
80
|
+
### `@mui/material@9.2.0`
|
|
81
|
+
|
|
82
|
+
- [l10n] Add missing MuiPagination localization to zh-CN locale (#48741) @greymoth-jp
|
|
83
|
+
- [select] Guard display ref during mouse down (#48744) @michelengelen
|
|
84
|
+
|
|
85
|
+
### `@mui/utils@9.2.0`
|
|
86
|
+
|
|
87
|
+
- [utils] Add opt-in `DataAttributesOverrides` augmentation for slot props (#48554) @LukasTy
|
|
88
|
+
|
|
89
|
+
### Docs
|
|
90
|
+
|
|
91
|
+
- [docs] Improve Icon Dialog responsiveness on small screens (#48639) @Prakash1185
|
|
92
|
+
- [docs] Fix invalid UTF-8 in skill references (#48739) @mturac
|
|
93
|
+
|
|
94
|
+
### Core
|
|
95
|
+
|
|
96
|
+
- [code-infra] Resolve Renovate dashboard warnings (#48700) @Sushantplive
|
|
97
|
+
- [code-infra] Validate npm publishing through dry run (#48691) @brijeshb42
|
|
98
|
+
- [code-infra] Run prettier after renovate update (#48754) @Janpot
|
|
99
|
+
- [code-infra] Fix 'A11y results committed?' check on react-pinned nightly jobs (#48740) @Janpot
|
|
100
|
+
- [core] Remove leftover Joy UI references (#48719) @siriwatknp
|
|
101
|
+
- [code-infra] Bump react-router to 7.15.1 (#48725) @Janpot
|
|
102
|
+
- [docs-infra] Drive docs analytics IDs via ANALYTICS_ENV (#48694) @Janpot
|
|
103
|
+
- [docs-infra] Pre-render API page descriptions (#48693) @brijeshb42
|
|
104
|
+
- [code-infra][icons-material] Build lib/package.json with code-infra --no-expand (#48689) @Janpot
|
|
105
|
+
- [code-infra] Fix react@18/next nightly workflow (#48635) @Janpot
|
|
106
|
+
|
|
107
|
+
All contributors of this release in alphabetical order: @brijeshb42, @greymoth-jp, @Janpot, @LukasTy, @michelengelen, @mturac, @Prakash1185, @siriwatknp, @Sushantplive
|
|
108
|
+
|
|
109
|
+
## 9.1.2
|
|
110
|
+
|
|
111
|
+
<!-- generated comparing v9.1.1..master -->
|
|
112
|
+
|
|
113
|
+
_Jun 23, 2026_
|
|
114
|
+
|
|
115
|
+
A big thanks to the 5 contributors who made this release possible.
|
|
116
|
+
|
|
117
|
+
### `@mui/material@9.1.2`
|
|
118
|
+
|
|
119
|
+
- [autocomplete] Don't submit forms when committing `freeSolo` value with Enter key (#48679) @mj12albert
|
|
120
|
+
- [transitions] Fix RTG import in ESM (#48645) @mj12albert
|
|
121
|
+
|
|
122
|
+
### `@mui/system@9.1.2`
|
|
123
|
+
|
|
124
|
+
- [InitColorSchemeScript] Fix script tag warning in Next.js 16 dev mode (#48671) @siriwatknp
|
|
125
|
+
|
|
126
|
+
### Docs
|
|
127
|
+
|
|
128
|
+
- Fix typos in release instructions (#48687) @brijeshb42
|
|
129
|
+
- Update @mui/x-\* packages to latest (#48661) @Janpot
|
|
130
|
+
|
|
131
|
+
### Core
|
|
132
|
+
|
|
133
|
+
- [code-infra] Convert leaf @mui/system .js+.d.ts pairs to TypeScript (part 1) (#48578) @Janpot
|
|
134
|
+
- [code-infra] Bump to latest code-infra packages (#48672) @brijeshb42
|
|
135
|
+
- [code-infra] Resolve remaining minimatch advisory (#48662) @Janpot
|
|
136
|
+
- [code-infra] Bump nx to resolve minimatch advisory (#48658) @Janpot
|
|
137
|
+
- [core] Drop @babel/\* pnpm overrides (#48710) @Janpot
|
|
138
|
+
- [docs-infra] Revert "Pin StackBlitz demo vite to v7 and plugin-react to v5" (#48709) @Janpot
|
|
139
|
+
- [docs-infra] Fix code-block copy button broken on direct page load (#48653) @brijeshb42
|
|
140
|
+
- [test] Stabilize Data Grid demo data in Argos screenshots (#48654) @LukasTy
|
|
141
|
+
|
|
142
|
+
All contributors of this release in alphabetical order: @brijeshb42, @Janpot, @LukasTy, @mj12albert, @siriwatknp
|
|
143
|
+
|
|
3
144
|
## 9.1.1
|
|
4
145
|
|
|
5
146
|
<!-- generated comparing v9.1.0..master -->
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
declare const defaultGenerator: (componentName: string) => string;
|
|
1
2
|
declare const ClassNameGenerator: {
|
|
2
|
-
configure(generator:
|
|
3
|
+
configure(generator: typeof defaultGenerator): void;
|
|
3
4
|
generate(componentName: string): string;
|
|
4
5
|
reset(): void;
|
|
5
6
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
declare const defaultGenerator: (componentName: string) => string;
|
|
1
2
|
declare const ClassNameGenerator: {
|
|
2
|
-
configure(generator:
|
|
3
|
+
configure(generator: typeof defaultGenerator): void;
|
|
3
4
|
generate(componentName: string): string;
|
|
4
5
|
reset(): void;
|
|
5
6
|
};
|
|
@@ -21,7 +21,7 @@ function acceptingRef(props, propName, componentName, location, propFullName) {
|
|
|
21
21
|
// When server-side rendering React doesn't warn either.
|
|
22
22
|
// This is not an accurate check for SSR.
|
|
23
23
|
// This is only in place for Emotion compat.
|
|
24
|
-
// TODO: Revisit once https://github.com/
|
|
24
|
+
// TODO: Revisit once https://github.com/react/react/issues/20047 is resolved.
|
|
25
25
|
typeof window === 'undefined') {
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
@@ -14,7 +14,7 @@ function acceptingRef(props, propName, componentName, location, propFullName) {
|
|
|
14
14
|
// When server-side rendering React doesn't warn either.
|
|
15
15
|
// This is not an accurate check for SSR.
|
|
16
16
|
// This is only in place for Emotion compat.
|
|
17
|
-
// TODO: Revisit once https://github.com/
|
|
17
|
+
// TODO: Revisit once https://github.com/react/react/issues/20047 is resolved.
|
|
18
18
|
typeof window === 'undefined') {
|
|
19
19
|
return null;
|
|
20
20
|
}
|
|
@@ -23,7 +23,7 @@ function elementTypeAcceptingRef(props, propName, componentName, location, propF
|
|
|
23
23
|
// When server-side rendering React doesn't warn either.
|
|
24
24
|
// This is not an accurate check for SSR.
|
|
25
25
|
// This is only in place for emotion compat.
|
|
26
|
-
// TODO: Revisit once https://github.com/
|
|
26
|
+
// TODO: Revisit once https://github.com/react/react/issues/20047 is resolved.
|
|
27
27
|
typeof window === 'undefined') {
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
@@ -15,7 +15,7 @@ function elementTypeAcceptingRef(props, propName, componentName, location, propF
|
|
|
15
15
|
// When server-side rendering React doesn't warn either.
|
|
16
16
|
// This is not an accurate check for SSR.
|
|
17
17
|
// This is only in place for emotion compat.
|
|
18
|
-
// TODO: Revisit once https://github.com/
|
|
18
|
+
// TODO: Revisit once https://github.com/react/react/issues/20047 is resolved.
|
|
19
19
|
typeof window === 'undefined') {
|
|
20
20
|
return null;
|
|
21
21
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* cherry-pick from
|
|
4
|
-
* https://github.com/
|
|
4
|
+
* https://github.com/react/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
|
|
5
5
|
* originally forked from recompose/getDisplayName
|
|
6
6
|
*/
|
|
7
7
|
export default function getDisplayName(Component: React.ElementType): string | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
/**
|
|
3
3
|
* cherry-pick from
|
|
4
|
-
* https://github.com/
|
|
4
|
+
* https://github.com/react/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
|
|
5
5
|
* originally forked from recompose/getDisplayName
|
|
6
6
|
*/
|
|
7
7
|
export default function getDisplayName(Component: React.ElementType): string | undefined;
|
|
@@ -15,7 +15,7 @@ function getWrappedName(outerType, innerType, wrapperName) {
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* cherry-pick from
|
|
18
|
-
* https://github.com/
|
|
18
|
+
* https://github.com/react/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
|
|
19
19
|
* originally forked from recompose/getDisplayName
|
|
20
20
|
*/
|
|
21
21
|
function getDisplayName(Component) {
|
|
@@ -9,7 +9,7 @@ function getWrappedName(outerType, innerType, wrapperName) {
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* cherry-pick from
|
|
12
|
-
* https://github.com/
|
|
12
|
+
* https://github.com/react/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
|
|
13
13
|
* originally forked from recompose/getDisplayName
|
|
14
14
|
*/
|
|
15
15
|
export default function getDisplayName(Component) {
|
package/index.js
CHANGED
package/index.mjs
CHANGED
|
@@ -9,7 +9,7 @@ var React = _interopRequireWildcard(require("react"));
|
|
|
9
9
|
function isMuiElement(element, muiNames) {
|
|
10
10
|
return /*#__PURE__*/React.isValidElement(element) && muiNames.indexOf(
|
|
11
11
|
// For server components `muiName` is available in element.type._payload.value.muiName
|
|
12
|
-
// relevant info - https://github.com/
|
|
12
|
+
// relevant info - https://github.com/react/react/blob/2807d781a08db8e9873687fccc25c0f12b4fb3d4/packages/react/src/ReactLazy.js#L45
|
|
13
13
|
// eslint-disable-next-line no-underscore-dangle
|
|
14
14
|
element.type.muiName ?? element.type?._payload?.value?.muiName) !== -1;
|
|
15
15
|
}
|
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
export default function isMuiElement(element, muiNames) {
|
|
3
3
|
return /*#__PURE__*/React.isValidElement(element) && muiNames.indexOf(
|
|
4
4
|
// For server components `muiName` is available in element.type._payload.value.muiName
|
|
5
|
-
// relevant info - https://github.com/
|
|
5
|
+
// relevant info - https://github.com/react/react/blob/2807d781a08db8e9873687fccc25c0f12b4fb3d4/packages/react/src/ReactLazy.js#L45
|
|
6
6
|
// eslint-disable-next-line no-underscore-dangle
|
|
7
7
|
element.type.muiName ?? element.type?._payload?.value?.muiName) !== -1;
|
|
8
8
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/utils",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.3.0",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "Utility functions for React components.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"url": "https://opencollective.com/mui-org"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@babel/runtime": "^7.29.
|
|
27
|
+
"@babel/runtime": "^7.29.7",
|
|
28
28
|
"@types/prop-types": "^15.7.15",
|
|
29
29
|
"clsx": "^2.1.1",
|
|
30
30
|
"prop-types": "^15.8.1",
|
|
31
|
-
"react-is": "^19.2.
|
|
32
|
-
"@mui/types": "^9.
|
|
31
|
+
"react-is": "^19.2.8",
|
|
32
|
+
"@mui/types": "^9.3.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in interface for typing `data-*` attributes on MUI slot props.
|
|
3
|
+
*
|
|
4
|
+
* Slot prop types reject arbitrary `data-*` keys by design, so this interface is
|
|
5
|
+
* empty by default. Augment it to declare the keys you want, and they become
|
|
6
|
+
* assignable on every slot of every component that routes its slot props through
|
|
7
|
+
* `@mui/utils/types`.
|
|
8
|
+
*
|
|
9
|
+
* Choose the form that matches how strict you want to be:
|
|
10
|
+
*
|
|
11
|
+
* - Loose index signature: accepts any `data-*` key, like the underlying DOM
|
|
12
|
+
* element. Simplest to set up, but you get no autocomplete and typos slip through.
|
|
13
|
+
* - Explicit keys: lists each `data-*` key you allow. More to declare up front,
|
|
14
|
+
* in return for autocomplete and typo-checking on those keys.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Loose: accept any `data-*` key.
|
|
18
|
+
* declare module '@mui/utils/types' {
|
|
19
|
+
* interface DataAttributesOverrides {
|
|
20
|
+
* [k: `data-${string}`]: string | number | boolean | undefined;
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Explicit: only the keys you declare, with autocomplete.
|
|
26
|
+
* declare module '@mui/utils/types' {
|
|
27
|
+
* interface DataAttributesOverrides {
|
|
28
|
+
* 'data-testid'?: string;
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*/
|
|
32
|
+
export interface DataAttributesOverrides {}
|
|
33
|
+
/**
|
|
34
|
+
* Widens a slot-props type so that, when a consumer augments
|
|
35
|
+
* `DataAttributesOverrides`, the augmented keys become assignable to the
|
|
36
|
+
* widened branch. `DataAttributesOverrides` is empty by default, so this
|
|
37
|
+
* widening is a no-op until a consumer opts in.
|
|
38
|
+
*
|
|
39
|
+
* Implemented as a union between the original type and the intersected widened
|
|
40
|
+
* form — `T | (T & DataAttributesOverrides)` — so that pre-typed values remain
|
|
41
|
+
* assignable to the original branch without having to declare a `data-*`
|
|
42
|
+
* index signature themselves, while object literals can pick up the widened
|
|
43
|
+
* branch and include the augmented keys.
|
|
44
|
+
*/
|
|
45
|
+
export type WithDataAttributes<T> = T | (T & DataAttributesOverrides);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in interface for typing `data-*` attributes on MUI slot props.
|
|
3
|
+
*
|
|
4
|
+
* Slot prop types reject arbitrary `data-*` keys by design, so this interface is
|
|
5
|
+
* empty by default. Augment it to declare the keys you want, and they become
|
|
6
|
+
* assignable on every slot of every component that routes its slot props through
|
|
7
|
+
* `@mui/utils/types`.
|
|
8
|
+
*
|
|
9
|
+
* Choose the form that matches how strict you want to be:
|
|
10
|
+
*
|
|
11
|
+
* - Loose index signature: accepts any `data-*` key, like the underlying DOM
|
|
12
|
+
* element. Simplest to set up, but you get no autocomplete and typos slip through.
|
|
13
|
+
* - Explicit keys: lists each `data-*` key you allow. More to declare up front,
|
|
14
|
+
* in return for autocomplete and typo-checking on those keys.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Loose: accept any `data-*` key.
|
|
18
|
+
* declare module '@mui/utils/types' {
|
|
19
|
+
* interface DataAttributesOverrides {
|
|
20
|
+
* [k: `data-${string}`]: string | number | boolean | undefined;
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Explicit: only the keys you declare, with autocomplete.
|
|
26
|
+
* declare module '@mui/utils/types' {
|
|
27
|
+
* interface DataAttributesOverrides {
|
|
28
|
+
* 'data-testid'?: string;
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
*/
|
|
32
|
+
export interface DataAttributesOverrides {}
|
|
33
|
+
/**
|
|
34
|
+
* Widens a slot-props type so that, when a consumer augments
|
|
35
|
+
* `DataAttributesOverrides`, the augmented keys become assignable to the
|
|
36
|
+
* widened branch. `DataAttributesOverrides` is empty by default, so this
|
|
37
|
+
* widening is a no-op until a consumer opts in.
|
|
38
|
+
*
|
|
39
|
+
* Implemented as a union between the original type and the intersected widened
|
|
40
|
+
* form — `T | (T & DataAttributesOverrides)` — so that pre-typed values remain
|
|
41
|
+
* assignable to the original branch without having to declare a `data-*`
|
|
42
|
+
* index signature themselves, while object literals can pick up the widened
|
|
43
|
+
* branch and include the augmented keys.
|
|
44
|
+
*/
|
|
45
|
+
export type WithDataAttributes<T> = T | (T & DataAttributesOverrides);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/types/index.d.mts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { WithDataAttributes } from "./DataAttributes.mjs";
|
|
3
|
+
export type { DataAttributesOverrides, WithDataAttributes } from "./DataAttributes.mjs";
|
|
2
4
|
export type EventHandlers = Record<string, React.EventHandler<any>>;
|
|
3
5
|
export type WithOptionalOwnerState<Props extends {
|
|
4
6
|
ownerState: unknown;
|
|
5
7
|
}> = Omit<Props, 'ownerState'> & Partial<Pick<Props, 'ownerState'>>;
|
|
6
|
-
export type SlotComponentProps<TSlotComponent extends React.ElementType, TOverrides, TOwnerState> =
|
|
7
|
-
export type SlotComponentPropsWithSlotState<TSlotComponent extends React.ElementType, TOverrides, TOwnerState, TSlotState> =
|
|
8
|
+
export type SlotComponentProps<TSlotComponent extends React.ElementType, TOverrides, TOwnerState> = WithDataAttributes<Partial<React.ComponentPropsWithRef<TSlotComponent>> & TOverrides> | ((ownerState: TOwnerState) => WithDataAttributes<Partial<React.ComponentPropsWithRef<TSlotComponent>> & TOverrides>);
|
|
9
|
+
export type SlotComponentPropsWithSlotState<TSlotComponent extends React.ElementType, TOverrides, TOwnerState, TSlotState> = WithDataAttributes<Partial<React.ComponentPropsWithRef<TSlotComponent>> & TOverrides> | ((ownerState: TOwnerState, slotState: TSlotState) => WithDataAttributes<Partial<React.ComponentPropsWithRef<TSlotComponent>> & TOverrides>);
|
package/types/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { WithDataAttributes } from "./DataAttributes.js";
|
|
3
|
+
export type { DataAttributesOverrides, WithDataAttributes } from "./DataAttributes.js";
|
|
2
4
|
export type EventHandlers = Record<string, React.EventHandler<any>>;
|
|
3
5
|
export type WithOptionalOwnerState<Props extends {
|
|
4
6
|
ownerState: unknown;
|
|
5
7
|
}> = Omit<Props, 'ownerState'> & Partial<Pick<Props, 'ownerState'>>;
|
|
6
|
-
export type SlotComponentProps<TSlotComponent extends React.ElementType, TOverrides, TOwnerState> =
|
|
7
|
-
export type SlotComponentPropsWithSlotState<TSlotComponent extends React.ElementType, TOverrides, TOwnerState, TSlotState> =
|
|
8
|
+
export type SlotComponentProps<TSlotComponent extends React.ElementType, TOverrides, TOwnerState> = WithDataAttributes<Partial<React.ComponentPropsWithRef<TSlotComponent>> & TOverrides> | ((ownerState: TOwnerState) => WithDataAttributes<Partial<React.ComponentPropsWithRef<TSlotComponent>> & TOverrides>);
|
|
9
|
+
export type SlotComponentPropsWithSlotState<TSlotComponent extends React.ElementType, TOverrides, TOwnerState, TSlotState> = WithDataAttributes<Partial<React.ComponentPropsWithRef<TSlotComponent>> & TOverrides> | ((ownerState: TOwnerState, slotState: TSlotState) => WithDataAttributes<Partial<React.ComponentPropsWithRef<TSlotComponent>> & TOverrides>);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Inspired by https://github.com/
|
|
2
|
+
* Inspired by https://github.com/react/react/issues/14099#issuecomment-440013892
|
|
3
3
|
* See RFC in https://github.com/reactjs/rfcs/pull/220
|
|
4
4
|
*/
|
|
5
5
|
declare function useEventCallback<Fn extends (...args: any[]) => any = (...args: unknown[]) => unknown>(fn: Fn): Fn;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Inspired by https://github.com/
|
|
2
|
+
* Inspired by https://github.com/react/react/issues/14099#issuecomment-440013892
|
|
3
3
|
* See RFC in https://github.com/reactjs/rfcs/pull/220
|
|
4
4
|
*/
|
|
5
5
|
declare function useEventCallback<Fn extends (...args: any[]) => any = (...args: unknown[]) => unknown>(fn: Fn): Fn;
|
|
@@ -10,7 +10,7 @@ exports.default = void 0;
|
|
|
10
10
|
var React = _interopRequireWildcard(require("react"));
|
|
11
11
|
var _useEnhancedEffect = _interopRequireDefault(require("../useEnhancedEffect"));
|
|
12
12
|
/**
|
|
13
|
-
* Inspired by https://github.com/
|
|
13
|
+
* Inspired by https://github.com/react/react/issues/14099#issuecomment-440013892
|
|
14
14
|
* See RFC in https://github.com/reactjs/rfcs/pull/220
|
|
15
15
|
*/
|
|
16
16
|
|
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import useEnhancedEffect from "../useEnhancedEffect/index.mjs";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Inspired by https://github.com/
|
|
7
|
+
* Inspired by https://github.com/react/react/issues/14099#issuecomment-440013892
|
|
8
8
|
* See RFC in https://github.com/reactjs/rfcs/pull/220
|
|
9
9
|
*/
|
|
10
10
|
|
package/useForkRef/useForkRef.js
CHANGED
|
@@ -44,7 +44,7 @@ function useForkRef(...refs) {
|
|
|
44
44
|
return () => {
|
|
45
45
|
cleanups.forEach(refCleanup => refCleanup?.());
|
|
46
46
|
};
|
|
47
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
47
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps, react-hooks/use-memo
|
|
48
48
|
}, refs);
|
|
49
49
|
return React.useMemo(() => {
|
|
50
50
|
if (refs.every(ref => ref == null)) {
|
|
@@ -60,6 +60,6 @@ function useForkRef(...refs) {
|
|
|
60
60
|
}
|
|
61
61
|
};
|
|
62
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
|
|
63
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
63
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps, react-hooks/use-memo
|
|
64
64
|
}, refs);
|
|
65
65
|
}
|
|
@@ -39,7 +39,7 @@ export default function useForkRef(...refs) {
|
|
|
39
39
|
return () => {
|
|
40
40
|
cleanups.forEach(refCleanup => refCleanup?.());
|
|
41
41
|
};
|
|
42
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
42
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps, react-hooks/use-memo
|
|
43
43
|
}, refs);
|
|
44
44
|
return React.useMemo(() => {
|
|
45
45
|
if (refs.every(ref => ref == null)) {
|
|
@@ -55,6 +55,6 @@ export default function useForkRef(...refs) {
|
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
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
|
|
58
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
58
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps, react-hooks/use-memo
|
|
59
59
|
}, refs);
|
|
60
60
|
}
|
package/useId/useId.js
CHANGED
|
@@ -20,6 +20,7 @@ function useGlobalId(idOverride) {
|
|
|
20
20
|
// We can't use it server-side.
|
|
21
21
|
// If you want to use random values please consider the Birthday Problem: https://en.wikipedia.org/wiki/Birthday_problem
|
|
22
22
|
globalId += 1;
|
|
23
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
23
24
|
setDefaultId(`mui-${globalId}`);
|
|
24
25
|
}
|
|
25
26
|
}, [defaultId]);
|
package/useId/useId.mjs
CHANGED
|
@@ -14,6 +14,7 @@ function useGlobalId(idOverride) {
|
|
|
14
14
|
// We can't use it server-side.
|
|
15
15
|
// If you want to use random values please consider the Birthday Problem: https://en.wikipedia.org/wiki/Birthday_problem
|
|
16
16
|
globalId += 1;
|
|
17
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
17
18
|
setDefaultId(`mui-${globalId}`);
|
|
18
19
|
}
|
|
19
20
|
}, [defaultId]);
|
|
@@ -134,8 +134,8 @@ function useIsFocusVisible() {
|
|
|
134
134
|
// checking against potential state variable does not suffice if we focus and blur synchronously.
|
|
135
135
|
// React wouldn't have time to trigger a re-render so `focusVisible` would be stale.
|
|
136
136
|
// Ideally we would adjust `isFocusVisible(event)` to look at `relatedTarget` for blur events.
|
|
137
|
-
// This doesn't work in IE 11 due to https://github.com/
|
|
138
|
-
// TODO: check again if React releases their internal changes to focus event handling (https://github.com/
|
|
137
|
+
// This doesn't work in IE 11 due to https://github.com/react/react/issues/3751
|
|
138
|
+
// TODO: check again if React releases their internal changes to focus event handling (https://github.com/react/react/pull/19186).
|
|
139
139
|
if (isFocusVisibleRef.current) {
|
|
140
140
|
// To detect a tab/window switch, we look for a blur event followed
|
|
141
141
|
// rapidly by a visibility change.
|
|
@@ -127,8 +127,8 @@ export default function useIsFocusVisible() {
|
|
|
127
127
|
// checking against potential state variable does not suffice if we focus and blur synchronously.
|
|
128
128
|
// React wouldn't have time to trigger a re-render so `focusVisible` would be stale.
|
|
129
129
|
// Ideally we would adjust `isFocusVisible(event)` to look at `relatedTarget` for blur events.
|
|
130
|
-
// This doesn't work in IE 11 due to https://github.com/
|
|
131
|
-
// TODO: check again if React releases their internal changes to focus event handling (https://github.com/
|
|
130
|
+
// This doesn't work in IE 11 due to https://github.com/react/react/issues/3751
|
|
131
|
+
// TODO: check again if React releases their internal changes to focus event handling (https://github.com/react/react/pull/19186).
|
|
132
132
|
if (isFocusVisibleRef.current) {
|
|
133
133
|
// To detect a tab/window switch, we look for a blur event followed
|
|
134
134
|
// rapidly by a visibility change.
|
|
@@ -91,7 +91,7 @@ export interface UseRovingTabIndexReturnValue<Key = unknown> {
|
|
|
91
91
|
* Spread these props onto the list or composite root element that should listen for focus
|
|
92
92
|
* and keyboard events.
|
|
93
93
|
*/
|
|
94
|
-
getContainerProps: (ref?: React.Ref<HTMLElement>) => {
|
|
94
|
+
getContainerProps: (ref?: React.Ref<HTMLElement> | undefined, onFocus?: ((event: React.FocusEvent<HTMLElement>) => void) | undefined, onKeyDown?: ((event: React.KeyboardEvent<HTMLElement>) => void) | undefined) => {
|
|
95
95
|
/**
|
|
96
96
|
* Keeps the active item in sync when focus moves onto one of the registered items.
|
|
97
97
|
*/
|
|
@@ -91,7 +91,7 @@ export interface UseRovingTabIndexReturnValue<Key = unknown> {
|
|
|
91
91
|
* Spread these props onto the list or composite root element that should listen for focus
|
|
92
92
|
* and keyboard events.
|
|
93
93
|
*/
|
|
94
|
-
getContainerProps: (ref?: React.Ref<HTMLElement>) => {
|
|
94
|
+
getContainerProps: (ref?: React.Ref<HTMLElement> | undefined, onFocus?: ((event: React.FocusEvent<HTMLElement>) => void) | undefined, onKeyDown?: ((event: React.KeyboardEvent<HTMLElement>) => void) | undefined) => {
|
|
95
95
|
/**
|
|
96
96
|
* Keeps the active item in sync when focus moves onto one of the registered items.
|
|
97
97
|
*/
|
|
@@ -97,8 +97,9 @@ function useRovingTabIndexRoot(params) {
|
|
|
97
97
|
setActiveItemIdState(nextItem.id);
|
|
98
98
|
return nextItem;
|
|
99
99
|
}, [itemFilter]);
|
|
100
|
-
const getContainerProps = React.useCallback(ref => {
|
|
100
|
+
const getContainerProps = React.useCallback((ref, onFocusProp, onKeyDownProp) => {
|
|
101
101
|
const onFocus = event => {
|
|
102
|
+
onFocusProp?.(event);
|
|
102
103
|
const snapshot = getNavigableItemsSnapshot(itemMapRef.current);
|
|
103
104
|
const focusedIndex = findItemIndexByElement(snapshot, event.target);
|
|
104
105
|
if (focusedIndex !== -1) {
|
|
@@ -106,7 +107,8 @@ function useRovingTabIndexRoot(params) {
|
|
|
106
107
|
}
|
|
107
108
|
};
|
|
108
109
|
const onKeyDown = event => {
|
|
109
|
-
|
|
110
|
+
onKeyDownProp?.(event);
|
|
111
|
+
if (event.defaultPrevented || event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) {
|
|
110
112
|
return;
|
|
111
113
|
}
|
|
112
114
|
if (!SUPPORTED_KEYS.includes(event.key)) {
|
|
@@ -88,8 +88,9 @@ export function useRovingTabIndexRoot(params) {
|
|
|
88
88
|
setActiveItemIdState(nextItem.id);
|
|
89
89
|
return nextItem;
|
|
90
90
|
}, [itemFilter]);
|
|
91
|
-
const getContainerProps = React.useCallback(ref => {
|
|
91
|
+
const getContainerProps = React.useCallback((ref, onFocusProp, onKeyDownProp) => {
|
|
92
92
|
const onFocus = event => {
|
|
93
|
+
onFocusProp?.(event);
|
|
93
94
|
const snapshot = getNavigableItemsSnapshot(itemMapRef.current);
|
|
94
95
|
const focusedIndex = findItemIndexByElement(snapshot, event.target);
|
|
95
96
|
if (focusedIndex !== -1) {
|
|
@@ -97,7 +98,8 @@ export function useRovingTabIndexRoot(params) {
|
|
|
97
98
|
}
|
|
98
99
|
};
|
|
99
100
|
const onKeyDown = event => {
|
|
100
|
-
|
|
101
|
+
onKeyDownProp?.(event);
|
|
102
|
+
if (event.defaultPrevented || event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) {
|
|
101
103
|
return;
|
|
102
104
|
}
|
|
103
105
|
if (!SUPPORTED_KEYS.includes(event.key)) {
|