@mui/lab 7.0.1-beta.19 → 7.0.1-beta.20

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,92 @@
1
1
  # [Versions](https://mui.com/versions/)
2
2
 
3
+ ## 7.3.6
4
+
5
+ <!-- generated comparing v7.3.5..master -->
6
+
7
+ _Dec 3, 2025_
8
+
9
+ A big thanks to the 22 contributors who made this release possible.
10
+
11
+ ### @mui/material@7.3.6
12
+
13
+ - [Accordion] Move properties to the AccordionOwnProps interface (#47348) @Aleksan4e3
14
+ - [Autocomplete] Remove unnecessary `filterSelectedOptions` dependency from `syncHighlightedIndex` useCallback (#47378) @ZeeshanTamboli
15
+ - [Autocomplete] Fix input caret not showing when focusing after chip navigation (#47249) @vrachuri28
16
+ - [Autocomplete] Fix ArrowLeft crash when value is not set with single-value rendering (#47214) @rithik56
17
+ - [Button] Fix running formAction when passed (#47185) @sai6855
18
+ - [Chip] Remove leftover closing parenthesis in CSS class key (#47345) @ZeeshanTamboli
19
+ - [ListItem] Add `secondaryAction` slot to `ListItem` (#47399) @sai6855
20
+ - [NumberField] Fix scroll behavior (#47397) @oliviertassinari
21
+ - [Select] Fix keyboard navigation while rendering in shadow DOM (#47380) @xBlizZer
22
+ - [Select] Fix cannot pass certain event handlers (#47366) @ZeeshanTamboli
23
+ - [Slider] Accept readonly array for `marks` prop (#47370) @pcorpet
24
+ - [Snackbar] Avoid unnecessary `ownerState` spread into `useSnackbar` (#47373) @ZeeshanTamboli
25
+ - [TextField] Allow custom props in slot props via TS module augmentation (#47367) @kumarvishwajeettrivedi
26
+ - [Tabs] Fix Arrow key navigation failing when component is rendered in shadow DOM (#47178) @sai6855
27
+ - Fix typings for theme `applyStyles` with custom color schemes (#47242) @akankshahu
28
+
29
+ ### @mui/system@7.3.6
30
+
31
+ - Fix unwanted attribute on DOM from InitColorSchemeScript `class` attribute (#47200) @siriwatknp
32
+
33
+ ### @mui/lab@7.3.6
34
+
35
+ - [Masonry] Fix layout flicker and single column issue (#43903) @Fanzzzd
36
+
37
+ ### Docs
38
+
39
+ - Fix default theme viewer styling (#47400) @sai6855
40
+ - Remove repetitive words (#47384) @rifeplight
41
+ - Fix link to Portal API docs (#47383) @ZeeshanTamboli
42
+ - Remove mentions of MUI Base from Material UI docs (#47324) @mapache-salvaje
43
+ - Update CSP guidance (#47342) @rossdakin
44
+ - Fix pathname collision in LLMs docs generator (#47209) @siriwatknp
45
+ - Resolve redirected urls to their final location (#47193) @Janpot
46
+ - Document correct default values for `elevation` and `square` props (#47261) @Ad1tya-007
47
+ - Fix display of colors in dark mode in palette customization page (#47403) @sai6855
48
+ - Add Number Field component page (#47165) @siriwatknp
49
+ - Fix mcp schema change (#47171) @sai6855
50
+
51
+ ### Core
52
+
53
+ - [code-infra] Add types for markdown loader (#47075) @Janpot
54
+ - [code-infra] Build test utils with code-infra pipeline (#47405) @Janpot
55
+ - [code-infra] Vitest test migration (#44325) @JCQuintas
56
+ - [code-infra] Revive docs bundle analyzer (#47401) @Janpot
57
+ - [code-infra] Update tests from vitest PR (#47344) @Janpot
58
+ - [code-infra] Use util from code-infra to fetch changelogs (#47350) @brijeshb42
59
+ - [code-infra] Enable production sourcemaps (#47352) @Janpot
60
+ - [code-infra] Use code-infra orb utils in circle ci (#47179) @brijeshb42
61
+ - [code-infra] Use `next/font` for local fonts (#47351) @Janpot
62
+ - [code-infra] New broken links checker (#47113) @Janpot
63
+ - [code-infra] Remove profiler (#47258) @Janpot
64
+ - [code-infra] Api doc optimizations (#47188) @Janpot
65
+ - [code-infra] Increase type check parallelism (#47192) @Janpot
66
+ - [code-infra] Remove deprecated baseUrl (#47210) @Janpot
67
+ - [code-infra] Disable next.js cache (#47233) @Janpot
68
+ - [code-infra] release:build for bundle checker (#47207) @Janpot
69
+ - [code-infra] Parallelize module augmentation tests (#47208) @Janpot
70
+ - [code-infra] Fix next.js parallelism at 2 for macos runner (#47201) @Janpot
71
+ - [code-infra] Fix bash escape (#46969) @oliviertassinari
72
+ - [code-infra] Utilise eslint cache in CI (#47194) @Janpot
73
+ - [code-infra] Enable Next.js build cache to improve CI performance (#47176) @Copilot
74
+ - [code-infra] Remove `apps` folder (#47183) @Janpot
75
+ - [code-infra] Migrate everything to getStaticProps (#47152) @Janpot
76
+ - [docs-infra] Migrate to `next/font` (#47347) @Janpot
77
+ - [docs-infra] Add some `ComponentLinkHeader` bottom margin (#47328) @Janpot
78
+ - [docs-infra] Exclude a few pages from llms-txt (#47111) @Janpot
79
+ - [examples] Add missing .gitignore to NextJS App Router example (#47251) @shamblonaut
80
+ - [examples] Migrate Next.js `next.config.js` to `next.config.mjs` (#44040) @albarv340
81
+ - [internal] Remove leftover testing-library libraries from `mui-material` package (#47392) @ZeeshanTamboli
82
+ - [internal] Remove unnecessary `clean-css` package from docs (#47314) @ZeeshanTamboli
83
+ - [internal] Fix typo `buidApiDocs` -> `buildApiDocs` (#47235) @Ad1tya-007
84
+ - [internal] Remove unused `@vitest/browser` and `@vitest/coverage-v8` (#47189) @ZeeshanTamboli
85
+ - [test] Update e2e test app (#47252) @Ad1tya-007
86
+ - [test] Fix flaky Virtualize Autocomplete regression test (#47199) @ZeeshanTamboli
87
+
88
+ All contributors of this release in alphabetical order: @Ad1tya-007, @akankshahu, @albarv340, @Aleksan4e3, @brijeshb42, @Copilot, @Fanzzzd, @Janpot, @JCQuintas, @kumarvishwajeettrivedi, @mapache-salvaje, @oliviertassinari, @pcorpet, @rifeplight, @rithik56, @rossdakin, @sai6855, @shamblonaut, @siriwatknp, @vrachuri28, @xBlizZer, @ZeeshanTamboli
89
+
3
90
  ## 7.3.5
4
91
 
5
92
  <!-- generated comparing v7.3.4..master -->
@@ -179,18 +179,21 @@ const Masonry = /*#__PURE__*/React.forwardRef(function Masonry(inProps, ref) {
179
179
  isSSR
180
180
  };
181
181
  const classes = useUtilityClasses(ownerState);
182
- const handleResize = React.useCallback(masonryChildren => {
183
- if (!masonryRef.current || !masonryChildren || masonryChildren.length === 0) {
182
+ const handleResize = React.useCallback(() => {
183
+ if (!masonryRef.current) {
184
184
  return;
185
185
  }
186
186
  const masonry = masonryRef.current;
187
- const masonryFirstChild = masonryRef.current.firstChild;
187
+ const firstVisibleChild = Array.from(masonry.childNodes).find(child => child.nodeType === Node.ELEMENT_NODE && child.dataset.class !== 'line-break' && window.getComputedStyle(child).display !== 'none');
188
+ if (!firstVisibleChild) {
189
+ return;
190
+ }
188
191
  const parentWidth = masonry.clientWidth;
189
- const firstChildWidth = masonryFirstChild.clientWidth;
192
+ const firstChildWidth = firstVisibleChild.clientWidth;
190
193
  if (parentWidth === 0 || firstChildWidth === 0) {
191
194
  return;
192
195
  }
193
- const firstChildComputedStyle = window.getComputedStyle(masonryFirstChild);
196
+ const firstChildComputedStyle = window.getComputedStyle(firstVisibleChild);
194
197
  const firstChildMarginLeft = parseToNumber(firstChildComputedStyle.marginLeft);
195
198
  const firstChildMarginRight = parseToNumber(firstChildComputedStyle.marginRight);
196
199
  const currentNumberOfColumns = Math.round(parentWidth / (firstChildWidth + firstChildMarginLeft + firstChildMarginRight));
@@ -202,15 +205,16 @@ const Masonry = /*#__PURE__*/React.forwardRef(function Masonry(inProps, ref) {
202
205
  return;
203
206
  }
204
207
  const childComputedStyle = window.getComputedStyle(child);
208
+ if (childComputedStyle.display === 'none') {
209
+ return;
210
+ }
205
211
  const childMarginTop = parseToNumber(childComputedStyle.marginTop);
206
212
  const childMarginBottom = parseToNumber(childComputedStyle.marginBottom);
207
- // if any one of children isn't rendered yet, masonry's height shouldn't be computed yet
208
213
  const childHeight = parseToNumber(childComputedStyle.height) ? Math.ceil(parseToNumber(childComputedStyle.height)) + childMarginTop + childMarginBottom : 0;
209
214
  if (childHeight === 0) {
210
215
  skip = true;
211
216
  return;
212
217
  }
213
- // if there is a nested image that isn't rendered yet, masonry's height shouldn't be computed yet
214
218
  for (let i = 0; i < child.childNodes.length; i += 1) {
215
219
  const nestedChild = child.childNodes[i];
216
220
  if (nestedChild.tagName === 'IMG' && nestedChild.clientHeight === 0) {
@@ -227,7 +231,6 @@ const Masonry = /*#__PURE__*/React.forwardRef(function Masonry(inProps, ref) {
227
231
  nextOrder = 1;
228
232
  }
229
233
  } else {
230
- // find the current shortest column (where the current item will be placed)
231
234
  const currentMinColumnIndex = columnHeights.indexOf(Math.min(...columnHeights));
232
235
  columnHeights[currentMinColumnIndex] += childHeight;
233
236
  const order = currentMinColumnIndex + 1;
@@ -236,43 +239,64 @@ const Masonry = /*#__PURE__*/React.forwardRef(function Masonry(inProps, ref) {
236
239
  }
237
240
  });
238
241
  if (!skip) {
239
- // In React 18, state updates in a ResizeObserver's callback are happening after the paint which causes flickering
240
- // when doing some visual updates in it. Using flushSync ensures that the dom will be painted after the states updates happen
241
- // Related issue - https://github.com/facebook/react/issues/24331
242
- ReactDOM.flushSync(() => {
243
- setMaxColumnHeight(Math.max(...columnHeights));
244
- setNumberOfLineBreaks(currentNumberOfColumns > 0 ? currentNumberOfColumns - 1 : 0);
242
+ queueMicrotask(() => {
243
+ if (masonryRef.current) {
244
+ ReactDOM.flushSync(() => {
245
+ setMaxColumnHeight(Math.max(...columnHeights));
246
+ setNumberOfLineBreaks(currentNumberOfColumns > 0 ? currentNumberOfColumns - 1 : 0);
247
+ });
248
+ }
245
249
  });
246
250
  }
247
251
  }, [sequential]);
248
252
  (0, _useEnhancedEffect.default)(() => {
249
- // IE and old browsers are not supported
250
- if (typeof ResizeObserver === 'undefined') {
253
+ if (typeof ResizeObserver === 'undefined' || typeof MutationObserver === 'undefined') {
251
254
  return undefined;
252
255
  }
253
- let animationFrame;
254
- const resizeObserver = new ResizeObserver(() => {
255
- // see https://github.com/mui/material-ui/issues/36909
256
- animationFrame = requestAnimationFrame(handleResize);
256
+ const masonry = masonryRef.current;
257
+ if (!masonry) {
258
+ return undefined;
259
+ }
260
+ let resizeTimeout;
261
+ const debouncedHandleResize = () => {
262
+ clearTimeout(resizeTimeout);
263
+ resizeTimeout = setTimeout(handleResize, 16); // ~60fps
264
+ };
265
+ const resizeObserver = new ResizeObserver(debouncedHandleResize);
266
+ // Observes for child additions or removals to update the layout.
267
+ const mutationObserver = new MutationObserver(mutations => {
268
+ mutations.forEach(mutation => {
269
+ mutation.addedNodes.forEach(node => {
270
+ if (node instanceof HTMLElement && node.dataset.class !== 'line-break') {
271
+ resizeObserver.observe(node);
272
+ }
273
+ });
274
+ mutation.removedNodes.forEach(node => {
275
+ if (node instanceof HTMLElement && node.dataset.class !== 'line-break') {
276
+ resizeObserver.unobserve(node);
277
+ }
278
+ });
279
+ });
280
+ handleResize();
257
281
  });
258
- if (masonryRef.current) {
259
- masonryRef.current.childNodes.forEach(childNode => {
282
+ Array.from(masonry.childNodes).forEach(childNode => {
283
+ if (childNode instanceof HTMLElement && childNode.dataset.class !== 'line-break') {
260
284
  resizeObserver.observe(childNode);
261
- });
262
- }
263
- return () => {
264
- if (animationFrame) {
265
- cancelAnimationFrame(animationFrame);
266
- }
267
- if (resizeObserver) {
268
- resizeObserver.disconnect();
269
285
  }
286
+ });
287
+ mutationObserver.observe(masonry, {
288
+ childList: true
289
+ });
290
+ handleResize();
291
+ return () => {
292
+ clearTimeout(resizeTimeout);
293
+ resizeObserver.disconnect();
294
+ mutationObserver.disconnect();
270
295
  };
271
- }, [columns, spacing, children, handleResize]);
296
+ }, [handleResize, columns, spacing, children]);
272
297
  const handleRef = (0, _useForkRef.default)(ref, masonryRef);
273
298
 
274
- // columns are likely to have different heights and hence can start to merge;
275
- // a line break at the end of each column prevents columns from merging
299
+ // A line break is added to the end of each column to prevent columns from merging.
276
300
  const lineBreaks = new Array(numberOfLineBreaks).fill('').map((_, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
277
301
  "data-class": "line-break",
278
302
  style: {
@@ -170,18 +170,21 @@ const Masonry = /*#__PURE__*/React.forwardRef(function Masonry(inProps, ref) {
170
170
  isSSR
171
171
  };
172
172
  const classes = useUtilityClasses(ownerState);
173
- const handleResize = React.useCallback(masonryChildren => {
174
- if (!masonryRef.current || !masonryChildren || masonryChildren.length === 0) {
173
+ const handleResize = React.useCallback(() => {
174
+ if (!masonryRef.current) {
175
175
  return;
176
176
  }
177
177
  const masonry = masonryRef.current;
178
- const masonryFirstChild = masonryRef.current.firstChild;
178
+ const firstVisibleChild = Array.from(masonry.childNodes).find(child => child.nodeType === Node.ELEMENT_NODE && child.dataset.class !== 'line-break' && window.getComputedStyle(child).display !== 'none');
179
+ if (!firstVisibleChild) {
180
+ return;
181
+ }
179
182
  const parentWidth = masonry.clientWidth;
180
- const firstChildWidth = masonryFirstChild.clientWidth;
183
+ const firstChildWidth = firstVisibleChild.clientWidth;
181
184
  if (parentWidth === 0 || firstChildWidth === 0) {
182
185
  return;
183
186
  }
184
- const firstChildComputedStyle = window.getComputedStyle(masonryFirstChild);
187
+ const firstChildComputedStyle = window.getComputedStyle(firstVisibleChild);
185
188
  const firstChildMarginLeft = parseToNumber(firstChildComputedStyle.marginLeft);
186
189
  const firstChildMarginRight = parseToNumber(firstChildComputedStyle.marginRight);
187
190
  const currentNumberOfColumns = Math.round(parentWidth / (firstChildWidth + firstChildMarginLeft + firstChildMarginRight));
@@ -193,15 +196,16 @@ const Masonry = /*#__PURE__*/React.forwardRef(function Masonry(inProps, ref) {
193
196
  return;
194
197
  }
195
198
  const childComputedStyle = window.getComputedStyle(child);
199
+ if (childComputedStyle.display === 'none') {
200
+ return;
201
+ }
196
202
  const childMarginTop = parseToNumber(childComputedStyle.marginTop);
197
203
  const childMarginBottom = parseToNumber(childComputedStyle.marginBottom);
198
- // if any one of children isn't rendered yet, masonry's height shouldn't be computed yet
199
204
  const childHeight = parseToNumber(childComputedStyle.height) ? Math.ceil(parseToNumber(childComputedStyle.height)) + childMarginTop + childMarginBottom : 0;
200
205
  if (childHeight === 0) {
201
206
  skip = true;
202
207
  return;
203
208
  }
204
- // if there is a nested image that isn't rendered yet, masonry's height shouldn't be computed yet
205
209
  for (let i = 0; i < child.childNodes.length; i += 1) {
206
210
  const nestedChild = child.childNodes[i];
207
211
  if (nestedChild.tagName === 'IMG' && nestedChild.clientHeight === 0) {
@@ -218,7 +222,6 @@ const Masonry = /*#__PURE__*/React.forwardRef(function Masonry(inProps, ref) {
218
222
  nextOrder = 1;
219
223
  }
220
224
  } else {
221
- // find the current shortest column (where the current item will be placed)
222
225
  const currentMinColumnIndex = columnHeights.indexOf(Math.min(...columnHeights));
223
226
  columnHeights[currentMinColumnIndex] += childHeight;
224
227
  const order = currentMinColumnIndex + 1;
@@ -227,43 +230,64 @@ const Masonry = /*#__PURE__*/React.forwardRef(function Masonry(inProps, ref) {
227
230
  }
228
231
  });
229
232
  if (!skip) {
230
- // In React 18, state updates in a ResizeObserver's callback are happening after the paint which causes flickering
231
- // when doing some visual updates in it. Using flushSync ensures that the dom will be painted after the states updates happen
232
- // Related issue - https://github.com/facebook/react/issues/24331
233
- ReactDOM.flushSync(() => {
234
- setMaxColumnHeight(Math.max(...columnHeights));
235
- setNumberOfLineBreaks(currentNumberOfColumns > 0 ? currentNumberOfColumns - 1 : 0);
233
+ queueMicrotask(() => {
234
+ if (masonryRef.current) {
235
+ ReactDOM.flushSync(() => {
236
+ setMaxColumnHeight(Math.max(...columnHeights));
237
+ setNumberOfLineBreaks(currentNumberOfColumns > 0 ? currentNumberOfColumns - 1 : 0);
238
+ });
239
+ }
236
240
  });
237
241
  }
238
242
  }, [sequential]);
239
243
  useEnhancedEffect(() => {
240
- // IE and old browsers are not supported
241
- if (typeof ResizeObserver === 'undefined') {
244
+ if (typeof ResizeObserver === 'undefined' || typeof MutationObserver === 'undefined') {
242
245
  return undefined;
243
246
  }
244
- let animationFrame;
245
- const resizeObserver = new ResizeObserver(() => {
246
- // see https://github.com/mui/material-ui/issues/36909
247
- animationFrame = requestAnimationFrame(handleResize);
247
+ const masonry = masonryRef.current;
248
+ if (!masonry) {
249
+ return undefined;
250
+ }
251
+ let resizeTimeout;
252
+ const debouncedHandleResize = () => {
253
+ clearTimeout(resizeTimeout);
254
+ resizeTimeout = setTimeout(handleResize, 16); // ~60fps
255
+ };
256
+ const resizeObserver = new ResizeObserver(debouncedHandleResize);
257
+ // Observes for child additions or removals to update the layout.
258
+ const mutationObserver = new MutationObserver(mutations => {
259
+ mutations.forEach(mutation => {
260
+ mutation.addedNodes.forEach(node => {
261
+ if (node instanceof HTMLElement && node.dataset.class !== 'line-break') {
262
+ resizeObserver.observe(node);
263
+ }
264
+ });
265
+ mutation.removedNodes.forEach(node => {
266
+ if (node instanceof HTMLElement && node.dataset.class !== 'line-break') {
267
+ resizeObserver.unobserve(node);
268
+ }
269
+ });
270
+ });
271
+ handleResize();
248
272
  });
249
- if (masonryRef.current) {
250
- masonryRef.current.childNodes.forEach(childNode => {
273
+ Array.from(masonry.childNodes).forEach(childNode => {
274
+ if (childNode instanceof HTMLElement && childNode.dataset.class !== 'line-break') {
251
275
  resizeObserver.observe(childNode);
252
- });
253
- }
254
- return () => {
255
- if (animationFrame) {
256
- cancelAnimationFrame(animationFrame);
257
- }
258
- if (resizeObserver) {
259
- resizeObserver.disconnect();
260
276
  }
277
+ });
278
+ mutationObserver.observe(masonry, {
279
+ childList: true
280
+ });
281
+ handleResize();
282
+ return () => {
283
+ clearTimeout(resizeTimeout);
284
+ resizeObserver.disconnect();
285
+ mutationObserver.disconnect();
261
286
  };
262
- }, [columns, spacing, children, handleResize]);
287
+ }, [handleResize, columns, spacing, children]);
263
288
  const handleRef = useForkRef(ref, masonryRef);
264
289
 
265
- // columns are likely to have different heights and hence can start to merge;
266
- // a line break at the end of each column prevents columns from merging
290
+ // A line break is added to the end of each column to prevent columns from merging.
267
291
  const lineBreaks = new Array(numberOfLineBreaks).fill('').map((_, index) => /*#__PURE__*/_jsx("span", {
268
292
  "data-class": "line-break",
269
293
  style: {
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/lab v7.0.1-beta.19
2
+ * @mui/lab v7.0.1-beta.20
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/lab v7.0.1-beta.19
2
+ * @mui/lab v7.0.1-beta.20
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mui/lab",
3
3
  "//": "version should be 'alpha' at all time",
4
- "version": "7.0.1-beta.19",
4
+ "version": "7.0.1-beta.20",
5
5
  "author": "MUI Team",
6
6
  "description": "Laboratory for new Material UI modules.",
7
7
  "keywords": [
@@ -30,9 +30,9 @@
30
30
  "@babel/runtime": "^7.28.4",
31
31
  "clsx": "^2.1.1",
32
32
  "prop-types": "^15.8.1",
33
- "@mui/system": "^7.3.5",
34
- "@mui/types": "^7.4.8",
35
- "@mui/utils": "^7.3.5"
33
+ "@mui/system": "^7.3.6",
34
+ "@mui/types": "^7.4.9",
35
+ "@mui/utils": "^7.3.6"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@emotion/react": "^11.5.0",
@@ -40,8 +40,8 @@
40
40
  "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
41
41
  "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
42
42
  "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
43
- "@mui/material": "^7.3.5",
44
- "@mui/material-pigment-css": "^7.3.5"
43
+ "@mui/material": "^7.3.6",
44
+ "@mui/material-pigment-css": "^7.3.6"
45
45
  },
46
46
  "peerDependenciesMeta": {
47
47
  "@types/react": {