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

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,148 @@
1
1
  # [Versions](https://mui.com/versions/)
2
2
 
3
+ ## 7.3.7
4
+
5
+ <!-- generated comparing v7.3.6..master -->
6
+
7
+ _Jan 8, 2026_
8
+
9
+ A big thanks to the 16 contributors who made this release possible.
10
+
11
+ ### `@mui/material@7.3.7`
12
+
13
+ - [accordion] Remove unnecessary handling of `square` prop on Accordion Root (#47457) @ZeeshanTamboli
14
+ - [alert] Remove unnecessary default icon mapping fallback (#47460) @ZeeshanTamboli
15
+ - [appbar] Fix inherit color CSS variable not getting applied (#47518) @ZeeshanTamboli
16
+ - [autocomplete] Fix `ArrowLeft`, `Backspace` & `Delete` behavior for multiple and single-value rendering with proper caret handling (#47411) @jnbain
17
+ - [backdrop] Remove unnecessary passing of `classes` from root slot (#47519) @ZeeshanTamboli
18
+ - [button-group] Fix styles when variant is `contained` (#47499) @ZeeshanTamboli
19
+ - [card-action-area] Remove incorrect root ref being forwarded to focus highlight component (#47523) @ZeeshanTamboli
20
+ - [checkbox] Fix readonly checkboxes (#47503) @mj12albert
21
+ - [click-away-listener] Tighten the parameter type of createHandleSynthetic method (#47525) @ZeeshanTamboli
22
+ - [dialog] Fix backdrop theme style overrides (#47544) @ZeeshanTamboli
23
+ - [focus-trap] Compute `activeElement` inside `loopFocus` on every keydown (#47566) @ZeeshanTamboli
24
+ - [modal] Take non-integer padding-right into consideration when scroll locking (#47420) @Zache
25
+ - [select] Fix dropdown width does not match trigger width on window resize (#47526) @AarishMansur
26
+ - [tabs] Fix passing incorrect slot name props (scrollButton → scrollButtons) (#47215) @rithik56
27
+
28
+ ### Docs
29
+
30
+ - [card] Fix key warning (#47524) @ZeeshanTamboli
31
+ - [dialog] Replace TranstionProps with slotProps.transition (#47569) @sai6855
32
+ - [number-field] Use stable Base UI package (#47504) @siriwatknp
33
+ - [snackbar] Replace TransitionComponent with slots.transition (#47570) @sai6855
34
+ - Fix incorrect indentation in migration guide (#47571) @sai6855
35
+ - Enable MUI chat on Material UI demos (#46837) @siriwatknp
36
+ - Add docs and website banner for Dev survey'25 (#47521) @prakhargupta1
37
+ - Update Tailwind CSS v4 + Next.js Pages Router docs (#47546) @atharva3333
38
+ - Add warning callout to Sync plugin doc (#47511) @mapache-salvaje
39
+ - Update typo in TailwindCSS v4 integration with Next.js docs (#47512) @TimKraemer
40
+ - Fix link to contributing guide (#47473) @oliviertassinari
41
+ - Improve description of Accordion props (#47459) @ZeeshanTamboli
42
+
43
+ ### Core
44
+
45
+ - [blog] Whats new since MUI X v8 [DX-51] (#47140) @joserodolfofreitas
46
+ - [code-infra] Fix React@next CI job (#47493) @Janpot
47
+ - [code-infra] Move font loading to @mui/docs (#47385) @Janpot
48
+ - [code-infra] Fix CI for React 18 (#47560) @Janpot
49
+ - [code-infra] Prevent legacy browsers tests from updating (#47496) @Janpot
50
+ - [code-infra] Move `@mui/internal-test-utils` to code infra repo (#47422) @Janpot
51
+ - [code-infra] Fix React@next CI job (#47493) @Janpot
52
+ - [examples] Update Next.js versions to v16 in Next.js examples (DX-57) (#47453) @alelthomas
53
+ - [internal] Bump Next.js & React version to avoid security vulnerability (#47427) @oliviertassinari
54
+ - [test] Use plain playwright for e2e (#47410) @mj12albert
55
+ - [test] Fix react-18 tests (#47407) @Janpot
56
+
57
+ All contributors of this release in alphabetical order: @AarishMansur, @alelthomas, @atharva3333, @bricefrisco, @Janpot, @jnbain, @joserodolfofreitas, @mapache-salvaje, @mj12albert, @oliviertassinari, @prakhargupta1, @rithik56, @siriwatknp, @TimKraemer, @Zache, @ZeeshanTamboli
58
+
59
+ ## 7.3.6
60
+
61
+ <!-- generated comparing v7.3.5..master -->
62
+
63
+ _Dec 3, 2025_
64
+
65
+ A big thanks to the 22 contributors who made this release possible.
66
+
67
+ ### @mui/material@7.3.6
68
+
69
+ - [Accordion] Move properties to the AccordionOwnProps interface (#47348) @Aleksan4e3
70
+ - [Autocomplete] Remove unnecessary `filterSelectedOptions` dependency from `syncHighlightedIndex` useCallback (#47378) @ZeeshanTamboli
71
+ - [Autocomplete] Fix input caret not showing when focusing after chip navigation (#47249) @vrachuri28
72
+ - [Autocomplete] Fix ArrowLeft crash when value is not set with single-value rendering (#47214) @rithik56
73
+ - [Button] Fix running formAction when passed (#47185) @sai6855
74
+ - [Chip] Remove leftover closing parenthesis in CSS class key (#47345) @ZeeshanTamboli
75
+ - [ListItem] Add `secondaryAction` slot to `ListItem` (#47399) @sai6855
76
+ - [NumberField] Fix scroll behavior (#47397) @oliviertassinari
77
+ - [Select] Fix keyboard navigation while rendering in shadow DOM (#47380) @xBlizZer
78
+ - [Select] Fix cannot pass certain event handlers (#47366) @ZeeshanTamboli
79
+ - [Slider] Accept readonly array for `marks` prop (#47370) @pcorpet
80
+ - [Snackbar] Avoid unnecessary `ownerState` spread into `useSnackbar` (#47373) @ZeeshanTamboli
81
+ - [TextField] Allow custom props in slot props via TS module augmentation (#47367) @kumarvishwajeettrivedi
82
+ - [Tabs] Fix Arrow key navigation failing when component is rendered in shadow DOM (#47178) @sai6855
83
+ - Fix typings for theme `applyStyles` with custom color schemes (#47242) @akankshahu
84
+
85
+ ### @mui/system@7.3.6
86
+
87
+ - Fix unwanted attribute on DOM from InitColorSchemeScript `class` attribute (#47200) @siriwatknp
88
+
89
+ ### @mui/lab@7.3.6
90
+
91
+ - [Masonry] Fix layout flicker and single column issue (#43903) @Fanzzzd
92
+
93
+ ### Docs
94
+
95
+ - Fix default theme viewer styling (#47400) @sai6855
96
+ - Remove repetitive words (#47384) @rifeplight
97
+ - Fix link to Portal API docs (#47383) @ZeeshanTamboli
98
+ - Remove mentions of MUI Base from Material UI docs (#47324) @mapache-salvaje
99
+ - Update CSP guidance (#47342) @rossdakin
100
+ - Fix pathname collision in LLMs docs generator (#47209) @siriwatknp
101
+ - Resolve redirected urls to their final location (#47193) @Janpot
102
+ - Document correct default values for `elevation` and `square` props (#47261) @Ad1tya-007
103
+ - Fix display of colors in dark mode in palette customization page (#47403) @sai6855
104
+ - Add Number Field component page (#47165) @siriwatknp
105
+ - Fix mcp schema change (#47171) @sai6855
106
+
107
+ ### Core
108
+
109
+ - [code-infra] Add types for markdown loader (#47075) @Janpot
110
+ - [code-infra] Build test utils with code-infra pipeline (#47405) @Janpot
111
+ - [code-infra] Vitest test migration (#44325) @JCQuintas
112
+ - [code-infra] Revive docs bundle analyzer (#47401) @Janpot
113
+ - [code-infra] Update tests from vitest PR (#47344) @Janpot
114
+ - [code-infra] Use util from code-infra to fetch changelogs (#47350) @brijeshb42
115
+ - [code-infra] Enable production sourcemaps (#47352) @Janpot
116
+ - [code-infra] Use code-infra orb utils in circle ci (#47179) @brijeshb42
117
+ - [code-infra] Use `next/font` for local fonts (#47351) @Janpot
118
+ - [code-infra] New broken links checker (#47113) @Janpot
119
+ - [code-infra] Remove profiler (#47258) @Janpot
120
+ - [code-infra] Api doc optimizations (#47188) @Janpot
121
+ - [code-infra] Increase type check parallelism (#47192) @Janpot
122
+ - [code-infra] Remove deprecated baseUrl (#47210) @Janpot
123
+ - [code-infra] Disable next.js cache (#47233) @Janpot
124
+ - [code-infra] release:build for bundle checker (#47207) @Janpot
125
+ - [code-infra] Parallelize module augmentation tests (#47208) @Janpot
126
+ - [code-infra] Fix next.js parallelism at 2 for macos runner (#47201) @Janpot
127
+ - [code-infra] Fix bash escape (#46969) @oliviertassinari
128
+ - [code-infra] Utilise eslint cache in CI (#47194) @Janpot
129
+ - [code-infra] Enable Next.js build cache to improve CI performance (#47176) @Copilot
130
+ - [code-infra] Remove `apps` folder (#47183) @Janpot
131
+ - [code-infra] Migrate everything to getStaticProps (#47152) @Janpot
132
+ - [docs-infra] Migrate to `next/font` (#47347) @Janpot
133
+ - [docs-infra] Add some `ComponentLinkHeader` bottom margin (#47328) @Janpot
134
+ - [docs-infra] Exclude a few pages from llms-txt (#47111) @Janpot
135
+ - [examples] Add missing .gitignore to NextJS App Router example (#47251) @shamblonaut
136
+ - [examples] Migrate Next.js `next.config.js` to `next.config.mjs` (#44040) @albarv340
137
+ - [internal] Remove leftover testing-library libraries from `mui-material` package (#47392) @ZeeshanTamboli
138
+ - [internal] Remove unnecessary `clean-css` package from docs (#47314) @ZeeshanTamboli
139
+ - [internal] Fix typo `buidApiDocs` -> `buildApiDocs` (#47235) @Ad1tya-007
140
+ - [internal] Remove unused `@vitest/browser` and `@vitest/coverage-v8` (#47189) @ZeeshanTamboli
141
+ - [test] Update e2e test app (#47252) @Ad1tya-007
142
+ - [test] Fix flaky Virtualize Autocomplete regression test (#47199) @ZeeshanTamboli
143
+
144
+ 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
145
+
3
146
  ## 7.3.5
4
147
 
5
148
  <!-- generated comparing v7.3.4..master -->
@@ -666,7 +809,7 @@ A big thanks to the 7 contributors who made this release possible.
666
809
  - Fix `Grid`, `GridLegacy`, `Stack`, `Badge`, `Select`, `Autocomplete` demos CSS variables (#45693) @DiegoAndai
667
810
  - Add "Material UI v7 is here" to the notifications (#45694) @DiegoAndai
668
811
  - Fix `Breadcrumbs`, `List`, `Divider`, and `Typography` dark mode demos (#45692) @siriwatknp
669
- - Fix Material Icons page in dark mode (#45691) @mnajdova
812
+ - Fix Material Icons page in dark mode (#45691) @mnajdova
670
813
 
671
814
  All contributors of this release in alphabetical order: @aarongarciah, @DiegoAndai, @eduter, @Janpot, @micttyoid, @mnajdova, @siriwatknp
672
815
 
@@ -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.21
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.21
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.21",
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.7",
34
+ "@mui/utils": "^7.3.7",
35
+ "@mui/types": "^7.4.10"
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.7",
44
+ "@mui/material-pigment-css": "^7.3.7"
45
45
  },
46
46
  "peerDependenciesMeta": {
47
47
  "@types/react": {