@janrankenhohn/react-thumbnail-list 0.8.0 → 1.0.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.
Files changed (34) hide show
  1. package/dist/index.esm.js +1372 -449
  2. package/dist/index.js +1365 -442
  3. package/dist/types/src/components/DropdownInput.d.ts +26 -0
  4. package/dist/types/src/components/EllipsisContainer.d.ts +15 -0
  5. package/dist/types/src/components/ThumbnailList.d.ts +46 -0
  6. package/dist/types/src/components/ThumbnailListFilterTag.d.ts +25 -0
  7. package/dist/types/src/components/ThumbnailListFilterTags.d.ts +44 -0
  8. package/dist/types/src/components/ThumbnailListHeader.d.ts +33 -0
  9. package/dist/types/src/components/ThumbnailListHeaderSort.d.ts +30 -0
  10. package/dist/types/src/components/ThumbnailListItem.d.ts +11 -0
  11. package/dist/types/src/components/ThumbnailListItemContext.d.ts +61 -0
  12. package/dist/types/src/components/ThumbnailListItemInfoLabel.d.ts +14 -0
  13. package/dist/types/src/components/ThumbnailListItemTitle.d.ts +15 -0
  14. package/dist/types/src/components/ThumbnailListItemType.d.ts +20 -0
  15. package/dist/types/src/components/ThumbnailListMainContent.d.ts +24 -0
  16. package/dist/types/src/components/ThumbnailListSearchField.d.ts +3 -0
  17. package/dist/types/src/config/ThumbnailListConfiguration.d.ts +23 -0
  18. package/dist/types/src/hooks/useFilteredThumbnailListItems.d.ts +23 -0
  19. package/dist/types/src/hooks/usePagedThumbnailListItems.d.ts +29 -0
  20. package/dist/types/src/hooks/useSortedThumbnailListItems.d.ts +29 -0
  21. package/dist/types/src/hooks/useTagFilteredThumbnailListItems.d.ts +51 -0
  22. package/dist/types/src/hooks/useWithLoading.d.ts +22 -0
  23. package/dist/types/src/index.d.ts +5 -0
  24. package/dist/types/src/interfaces/ThumbnailListItemInterface.d.ts +21 -0
  25. package/dist/types/src/stories/Button.d.ts +15 -0
  26. package/dist/types/src/stories/Header.d.ts +12 -0
  27. package/dist/types/src/stories/Page.d.ts +3 -0
  28. package/dist/types/src/tests/mocks/MockListItems.d.ts +41 -0
  29. package/dist/types/src/types/AlignType.d.ts +7 -0
  30. package/dist/types/src/types/BreakpointType.d.ts +25 -0
  31. package/dist/types/src/utils/arrayHelper.d.ts +26 -0
  32. package/dist/types/src/utils/logHelper.d.ts +24 -0
  33. package/dist/types/vitest.setup.d.ts +1 -0
  34. package/package.json +103 -86
package/dist/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { styled as styled$2, Box, Typography, Card, CardActionArea, Stack as Stack$1, Grid, LinearProgress, FormControl, TextField, InputAdornment, IconButton, useTheme as useTheme$2, useMediaQuery, Chip, Tooltip, InputLabel, Select, MenuItem, Menu } from '@mui/material';
3
3
  import * as React from 'react';
4
- import React__default, { createContext, useContext, useMemo, useState, useCallback, useEffect, Children } from 'react';
4
+ import React__default, { createContext, useContext, useMemo, useState, useEffect, Children } from 'react';
5
5
  import emStyled from '@emotion/styled';
6
6
  import { ThemeContext } from '@emotion/react';
7
7
  import SearchIcon from '@mui/icons-material/Search';
@@ -9,7 +9,24 @@ import ClearIcon from '@mui/icons-material/Clear';
9
9
  import SwapVertIcon from '@mui/icons-material/SwapVert';
10
10
  import SortIcon from '@mui/icons-material/Sort';
11
11
 
12
+ /**
13
+ * React context for sharing thumbnail list state across components.
14
+ * Provides access to items, sorting, filtering, and search functionality.
15
+ */
12
16
  const ThumbnailListItemContext = createContext(undefined);
17
+ /**
18
+ * React hook to access the ThumbnailList context.
19
+ * Must be used within a ThumbnailList component tree.
20
+ *
21
+ * @template T - The type of items in the list
22
+ * @returns {ThumbnailListItemContextType<T>} The context values
23
+ * @throws {Error} Throws error if used outside of ThumbnailList provider
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const { items, setSearchTerm, sortAscending } = useThumbnailListItemContext();
28
+ * ```
29
+ */
13
30
  const useThumbnailListItemContext = () => {
14
31
  const context = useContext(ThumbnailListItemContext);
15
32
  if (!context) {
@@ -18,100 +35,543 @@ const useThumbnailListItemContext = () => {
18
35
  return context;
19
36
  };
20
37
 
38
+ const StyledEllipsisContainer = styled$2('div')(({ theme, lineClamp }) => ({
39
+ [theme.breakpoints.up('xs')]: {
40
+ overflow: 'hidden',
41
+ display: '-webkit-box',
42
+ WebkitLineClamp: lineClamp.xs.toString(),
43
+ WebkitBoxOrient: 'vertical',
44
+ },
45
+ [theme.breakpoints.up('sm')]: {
46
+ overflow: 'hidden',
47
+ display: '-webkit-box',
48
+ WebkitLineClamp: lineClamp.sm.toString(),
49
+ WebkitBoxOrient: 'vertical',
50
+ },
51
+ }));
21
52
  /**
22
- * Creates a ellipies text with webkit css styles
53
+ * Creates ellipsis text with webkit css styles
23
54
  * @param props lineClamp: lines till ellipses
24
55
  * @returns component
25
56
  */
26
57
  function EllipsisContainer(props) {
27
- const EllipsisContainer = styled$2('div')((p) => ({
28
- [p.theme.breakpoints.up('xs')]: {
29
- overflow: 'hidden',
30
- display: '-webkit-box',
31
- WebkitLineClamp: props.lineClamp.xs.toString() /* number of lines to show */,
32
- WebkitBoxOrient: 'vertical',
33
- },
34
- [p.theme.breakpoints.up('sm')]: {
35
- overflow: 'hidden',
36
- display: '-webkit-box',
37
- WebkitLineClamp: props.lineClamp.sm.toString() /* number of lines to show */,
38
- WebkitBoxOrient: 'vertical' /* number of lines to show */,
39
- },
40
- }));
41
- return jsx(EllipsisContainer, { children: props.children });
58
+ return jsx(StyledEllipsisContainer, { lineClamp: props.lineClamp, children: props.children });
42
59
  }
43
60
 
44
61
  /**
45
- * WARNING: Don't import this directly.
46
- * Use `MuiError` from `@mui/internal-babel-macros/MuiError.macro` instead.
62
+ * WARNING: Don't import this directly. It's imported by the code generated by
63
+ * `@mui/interal-babel-plugin-minify-errors`. Make sure to always use string literals in `Error`
64
+ * constructors to ensure the plugin works as expected. Supported patterns include:
65
+ * throw new Error('My message');
66
+ * throw new Error(`My message: ${foo}`);
67
+ * throw new Error(`My message: ${foo}` + 'another string');
68
+ * ...
47
69
  * @param {number} code
48
70
  */
49
- function formatMuiErrorMessage(code) {
50
- // Apply babel-plugin-transform-template-literals in loose mode
51
- // loose mode is safe if we're concatenating primitives
52
- // see https://babeljs.io/docs/en/babel-plugin-transform-template-literals#loose
53
- /* eslint-disable prefer-template */
54
- let url = 'https://mui.com/production-error/?code=' + code;
55
- for (let i = 1; i < arguments.length; i += 1) {
56
- // rest params over-transpile for this case
57
- // eslint-disable-next-line prefer-rest-params
58
- url += '&args[]=' + encodeURIComponent(arguments[i]);
71
+ function formatMuiErrorMessage(code, ...args) {
72
+ const url = new URL(`https://mui.com/production-error/?code=${code}`);
73
+ args.forEach(arg => url.searchParams.append('args[]', arg));
74
+ return `Minified MUI error #${code}; visit ${url} for the full message.`;
75
+ }
76
+
77
+ /* eslint-disable */
78
+ // Inspired by https://github.com/garycourt/murmurhash-js
79
+ // Ported from https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp#L37-L86
80
+ function murmur2(str) {
81
+ // 'm' and 'r' are mixing constants generated offline.
82
+ // They're not really 'magic', they just happen to work well.
83
+ // const m = 0x5bd1e995;
84
+ // const r = 24;
85
+ // Initialize the hash
86
+ var h = 0; // Mix 4 bytes at a time into the hash
87
+
88
+ var k,
89
+ i = 0,
90
+ len = str.length;
91
+
92
+ for (; len >= 4; ++i, len -= 4) {
93
+ k = str.charCodeAt(i) & 0xff | (str.charCodeAt(++i) & 0xff) << 8 | (str.charCodeAt(++i) & 0xff) << 16 | (str.charCodeAt(++i) & 0xff) << 24;
94
+ k =
95
+ /* Math.imul(k, m): */
96
+ (k & 0xffff) * 0x5bd1e995 + ((k >>> 16) * 0xe995 << 16);
97
+ k ^=
98
+ /* k >>> r: */
99
+ k >>> 24;
100
+ h =
101
+ /* Math.imul(k, m): */
102
+ (k & 0xffff) * 0x5bd1e995 + ((k >>> 16) * 0xe995 << 16) ^
103
+ /* Math.imul(h, m): */
104
+ (h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
105
+ } // Handle the last few bytes of the input array
106
+
107
+
108
+ switch (len) {
109
+ case 3:
110
+ h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
111
+
112
+ case 2:
113
+ h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
114
+
115
+ case 1:
116
+ h ^= str.charCodeAt(i) & 0xff;
117
+ h =
118
+ /* Math.imul(h, m): */
119
+ (h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
120
+ } // Do a few final mixes of the hash to ensure the last few
121
+ // bytes are well-incorporated.
122
+
123
+
124
+ h ^= h >>> 13;
125
+ h =
126
+ /* Math.imul(h, m): */
127
+ (h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
128
+ return ((h ^ h >>> 15) >>> 0).toString(36);
129
+ }
130
+
131
+ var unitlessKeys = {
132
+ animationIterationCount: 1,
133
+ aspectRatio: 1,
134
+ borderImageOutset: 1,
135
+ borderImageSlice: 1,
136
+ borderImageWidth: 1,
137
+ boxFlex: 1,
138
+ boxFlexGroup: 1,
139
+ boxOrdinalGroup: 1,
140
+ columnCount: 1,
141
+ columns: 1,
142
+ flex: 1,
143
+ flexGrow: 1,
144
+ flexPositive: 1,
145
+ flexShrink: 1,
146
+ flexNegative: 1,
147
+ flexOrder: 1,
148
+ gridRow: 1,
149
+ gridRowEnd: 1,
150
+ gridRowSpan: 1,
151
+ gridRowStart: 1,
152
+ gridColumn: 1,
153
+ gridColumnEnd: 1,
154
+ gridColumnSpan: 1,
155
+ gridColumnStart: 1,
156
+ msGridRow: 1,
157
+ msGridRowSpan: 1,
158
+ msGridColumn: 1,
159
+ msGridColumnSpan: 1,
160
+ fontWeight: 1,
161
+ lineHeight: 1,
162
+ opacity: 1,
163
+ order: 1,
164
+ orphans: 1,
165
+ scale: 1,
166
+ tabSize: 1,
167
+ widows: 1,
168
+ zIndex: 1,
169
+ zoom: 1,
170
+ WebkitLineClamp: 1,
171
+ // SVG-related properties
172
+ fillOpacity: 1,
173
+ floodOpacity: 1,
174
+ stopOpacity: 1,
175
+ strokeDasharray: 1,
176
+ strokeDashoffset: 1,
177
+ strokeMiterlimit: 1,
178
+ strokeOpacity: 1,
179
+ strokeWidth: 1
180
+ };
181
+
182
+ function memoize$1(fn) {
183
+ var cache = Object.create(null);
184
+ return function (arg) {
185
+ if (cache[arg] === undefined) cache[arg] = fn(arg);
186
+ return cache[arg];
187
+ };
188
+ }
189
+
190
+ var hyphenateRegex = /[A-Z]|^ms/g;
191
+ var animationRegex = /_EMO_([^_]+?)_([^]*?)_EMO_/g;
192
+
193
+ var isCustomProperty = function isCustomProperty(property) {
194
+ return property.charCodeAt(1) === 45;
195
+ };
196
+
197
+ var isProcessableValue = function isProcessableValue(value) {
198
+ return value != null && typeof value !== 'boolean';
199
+ };
200
+
201
+ var processStyleName = /* #__PURE__ */memoize$1(function (styleName) {
202
+ return isCustomProperty(styleName) ? styleName : styleName.replace(hyphenateRegex, '-$&').toLowerCase();
203
+ });
204
+
205
+ var processStyleValue = function processStyleValue(key, value) {
206
+ switch (key) {
207
+ case 'animation':
208
+ case 'animationName':
209
+ {
210
+ if (typeof value === 'string') {
211
+ return value.replace(animationRegex, function (match, p1, p2) {
212
+ cursor = {
213
+ name: p1,
214
+ styles: p2,
215
+ next: cursor
216
+ };
217
+ return p1;
218
+ });
219
+ }
220
+ }
221
+ }
222
+
223
+ if (unitlessKeys[key] !== 1 && !isCustomProperty(key) && typeof value === 'number' && value !== 0) {
224
+ return value + 'px';
225
+ }
226
+
227
+ return value;
228
+ };
229
+
230
+ function handleInterpolation(mergedProps, registered, interpolation) {
231
+ if (interpolation == null) {
232
+ return '';
233
+ }
234
+
235
+ var componentSelector = interpolation;
236
+
237
+ if (componentSelector.__emotion_styles !== undefined) {
238
+
239
+ return componentSelector;
59
240
  }
60
- return 'Minified MUI error #' + code + '; visit ' + url + ' for the full message.';
61
- /* eslint-enable prefer-template */
241
+
242
+ switch (typeof interpolation) {
243
+ case 'boolean':
244
+ {
245
+ return '';
246
+ }
247
+
248
+ case 'object':
249
+ {
250
+ var keyframes = interpolation;
251
+
252
+ if (keyframes.anim === 1) {
253
+ cursor = {
254
+ name: keyframes.name,
255
+ styles: keyframes.styles,
256
+ next: cursor
257
+ };
258
+ return keyframes.name;
259
+ }
260
+
261
+ var serializedStyles = interpolation;
262
+
263
+ if (serializedStyles.styles !== undefined) {
264
+ var next = serializedStyles.next;
265
+
266
+ if (next !== undefined) {
267
+ // not the most efficient thing ever but this is a pretty rare case
268
+ // and there will be very few iterations of this generally
269
+ while (next !== undefined) {
270
+ cursor = {
271
+ name: next.name,
272
+ styles: next.styles,
273
+ next: cursor
274
+ };
275
+ next = next.next;
276
+ }
277
+ }
278
+
279
+ var styles = serializedStyles.styles + ";";
280
+ return styles;
281
+ }
282
+
283
+ return createStringFromObject(mergedProps, registered, interpolation);
284
+ }
285
+ } // finalize string values (regular strings and functions interpolated into css calls)
286
+
287
+
288
+ var asString = interpolation;
289
+
290
+ {
291
+ return asString;
292
+ }
293
+ }
294
+
295
+ function createStringFromObject(mergedProps, registered, obj) {
296
+ var string = '';
297
+
298
+ if (Array.isArray(obj)) {
299
+ for (var i = 0; i < obj.length; i++) {
300
+ string += handleInterpolation(mergedProps, registered, obj[i]) + ";";
301
+ }
302
+ } else {
303
+ for (var key in obj) {
304
+ var value = obj[key];
305
+
306
+ if (typeof value !== 'object') {
307
+ var asString = value;
308
+
309
+ if (isProcessableValue(asString)) {
310
+ string += processStyleName(key) + ":" + processStyleValue(key, asString) + ";";
311
+ }
312
+ } else {
313
+
314
+ if (Array.isArray(value) && typeof value[0] === 'string' && (registered == null)) {
315
+ for (var _i = 0; _i < value.length; _i++) {
316
+ if (isProcessableValue(value[_i])) {
317
+ string += processStyleName(key) + ":" + processStyleValue(key, value[_i]) + ";";
318
+ }
319
+ }
320
+ } else {
321
+ var interpolated = handleInterpolation(mergedProps, registered, value);
322
+
323
+ switch (key) {
324
+ case 'animation':
325
+ case 'animationName':
326
+ {
327
+ string += processStyleName(key) + ":" + interpolated + ";";
328
+ break;
329
+ }
330
+
331
+ default:
332
+ {
333
+
334
+ string += key + "{" + interpolated + "}";
335
+ }
336
+ }
337
+ }
338
+ }
339
+ }
340
+ }
341
+
342
+ return string;
343
+ }
344
+
345
+ var labelPattern = /label:\s*([^\s;{]+)\s*(;|$)/g; // this is the cursor for keyframes
346
+ // keyframes are stored on the SerializedStyles object as a linked list
347
+
348
+ var cursor;
349
+ function serializeStyles(args, registered, mergedProps) {
350
+ if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && args[0].styles !== undefined) {
351
+ return args[0];
352
+ }
353
+
354
+ var stringMode = true;
355
+ var styles = '';
356
+ cursor = undefined;
357
+ var strings = args[0];
358
+
359
+ if (strings == null || strings.raw === undefined) {
360
+ stringMode = false;
361
+ styles += handleInterpolation(mergedProps, registered, strings);
362
+ } else {
363
+ var asTemplateStringsArr = strings;
364
+
365
+ styles += asTemplateStringsArr[0];
366
+ } // we start at 1 since we've already handled the first arg
367
+
368
+
369
+ for (var i = 1; i < args.length; i++) {
370
+ styles += handleInterpolation(mergedProps, registered, args[i]);
371
+
372
+ if (stringMode) {
373
+ var templateStringsArr = strings;
374
+
375
+ styles += templateStringsArr[i];
376
+ }
377
+ } // using a global regex with .exec is stateful so lastIndex has to be reset each time
378
+
379
+
380
+ labelPattern.lastIndex = 0;
381
+ var identifierName = '';
382
+ var match; // https://esbench.com/bench/5b809c2cf2949800a0f61fb5
383
+
384
+ while ((match = labelPattern.exec(styles)) !== null) {
385
+ identifierName += '-' + match[1];
386
+ }
387
+
388
+ var name = murmur2(styles) + identifierName;
389
+
390
+ return {
391
+ name: name,
392
+ styles: styles,
393
+ next: cursor
394
+ };
62
395
  }
63
396
 
64
397
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
65
398
 
66
399
  /**
67
- * @mui/styled-engine v5.15.14
400
+ * @mui/styled-engine v6.5.0
68
401
  *
69
402
  * @license MIT
70
403
  * This source code is licensed under the MIT license found in the
71
404
  * LICENSE file in the root directory of this source tree.
72
405
  */
406
+ /* eslint-disable no-underscore-dangle */
73
407
  function styled$1(tag, options) {
74
408
  const stylesFactory = emStyled(tag, options);
75
409
  return stylesFactory;
76
410
  }
77
411
 
78
412
  // eslint-disable-next-line @typescript-eslint/naming-convention
79
- const internal_processStyles = (tag, processor) => {
413
+ function internal_mutateStyles(tag, processor) {
80
414
  // Emotion attaches all the styles as `__emotion_styles`.
81
415
  // Ref: https://github.com/emotion-js/emotion/blob/16d971d0da229596d6bcc39d282ba9753c9ee7cf/packages/styled/src/base.js#L186
82
416
  if (Array.isArray(tag.__emotion_styles)) {
83
417
  tag.__emotion_styles = processor(tag.__emotion_styles);
84
418
  }
85
- };
419
+ }
86
420
 
87
- function _extends() {
88
- _extends = Object.assign ? Object.assign.bind() : function (target) {
89
- for (var i = 1; i < arguments.length; i++) {
90
- var source = arguments[i];
91
- for (var key in source) {
92
- if (Object.prototype.hasOwnProperty.call(source, key)) {
93
- target[key] = source[key];
94
- }
95
- }
96
- }
97
- return target;
98
- };
99
- return _extends.apply(this, arguments);
421
+ // Emotion only accepts an array, but we want to avoid allocations
422
+ const wrapper = [];
423
+ // eslint-disable-next-line @typescript-eslint/naming-convention
424
+ function internal_serializeStyles(styles) {
425
+ wrapper[0] = styles;
426
+ return serializeStyles(wrapper);
100
427
  }
101
428
 
102
- function _objectWithoutPropertiesLoose(source, excluded) {
103
- if (source == null) return {};
104
- var target = {};
105
- var sourceKeys = Object.keys(source);
106
- var key, i;
107
- for (i = 0; i < sourceKeys.length; i++) {
108
- key = sourceKeys[i];
109
- if (excluded.indexOf(key) >= 0) continue;
110
- target[key] = source[key];
111
- }
112
- return target;
429
+ var reactIs = {exports: {}};
430
+
431
+ var reactIs_production = {};
432
+
433
+ /**
434
+ * @license React
435
+ * react-is.production.js
436
+ *
437
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
438
+ *
439
+ * This source code is licensed under the MIT license found in the
440
+ * LICENSE file in the root directory of this source tree.
441
+ */
442
+
443
+ var hasRequiredReactIs_production;
444
+
445
+ function requireReactIs_production () {
446
+ if (hasRequiredReactIs_production) return reactIs_production;
447
+ hasRequiredReactIs_production = 1;
448
+ var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
449
+ REACT_PORTAL_TYPE = Symbol.for("react.portal"),
450
+ REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
451
+ REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"),
452
+ REACT_PROFILER_TYPE = Symbol.for("react.profiler"),
453
+ REACT_CONSUMER_TYPE = Symbol.for("react.consumer"),
454
+ REACT_CONTEXT_TYPE = Symbol.for("react.context"),
455
+ REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"),
456
+ REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"),
457
+ REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"),
458
+ REACT_MEMO_TYPE = Symbol.for("react.memo"),
459
+ REACT_LAZY_TYPE = Symbol.for("react.lazy"),
460
+ REACT_VIEW_TRANSITION_TYPE = Symbol.for("react.view_transition"),
461
+ REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference");
462
+ function typeOf(object) {
463
+ if ("object" === typeof object && null !== object) {
464
+ var $$typeof = object.$$typeof;
465
+ switch ($$typeof) {
466
+ case REACT_ELEMENT_TYPE:
467
+ switch (((object = object.type), object)) {
468
+ case REACT_FRAGMENT_TYPE:
469
+ case REACT_PROFILER_TYPE:
470
+ case REACT_STRICT_MODE_TYPE:
471
+ case REACT_SUSPENSE_TYPE:
472
+ case REACT_SUSPENSE_LIST_TYPE:
473
+ case REACT_VIEW_TRANSITION_TYPE:
474
+ return object;
475
+ default:
476
+ switch (((object = object && object.$$typeof), object)) {
477
+ case REACT_CONTEXT_TYPE:
478
+ case REACT_FORWARD_REF_TYPE:
479
+ case REACT_LAZY_TYPE:
480
+ case REACT_MEMO_TYPE:
481
+ return object;
482
+ case REACT_CONSUMER_TYPE:
483
+ return object;
484
+ default:
485
+ return $$typeof;
486
+ }
487
+ }
488
+ case REACT_PORTAL_TYPE:
489
+ return $$typeof;
490
+ }
491
+ }
492
+ }
493
+ reactIs_production.ContextConsumer = REACT_CONSUMER_TYPE;
494
+ reactIs_production.ContextProvider = REACT_CONTEXT_TYPE;
495
+ reactIs_production.Element = REACT_ELEMENT_TYPE;
496
+ reactIs_production.ForwardRef = REACT_FORWARD_REF_TYPE;
497
+ reactIs_production.Fragment = REACT_FRAGMENT_TYPE;
498
+ reactIs_production.Lazy = REACT_LAZY_TYPE;
499
+ reactIs_production.Memo = REACT_MEMO_TYPE;
500
+ reactIs_production.Portal = REACT_PORTAL_TYPE;
501
+ reactIs_production.Profiler = REACT_PROFILER_TYPE;
502
+ reactIs_production.StrictMode = REACT_STRICT_MODE_TYPE;
503
+ reactIs_production.Suspense = REACT_SUSPENSE_TYPE;
504
+ reactIs_production.SuspenseList = REACT_SUSPENSE_LIST_TYPE;
505
+ reactIs_production.isContextConsumer = function (object) {
506
+ return typeOf(object) === REACT_CONSUMER_TYPE;
507
+ };
508
+ reactIs_production.isContextProvider = function (object) {
509
+ return typeOf(object) === REACT_CONTEXT_TYPE;
510
+ };
511
+ reactIs_production.isElement = function (object) {
512
+ return (
513
+ "object" === typeof object &&
514
+ null !== object &&
515
+ object.$$typeof === REACT_ELEMENT_TYPE
516
+ );
517
+ };
518
+ reactIs_production.isForwardRef = function (object) {
519
+ return typeOf(object) === REACT_FORWARD_REF_TYPE;
520
+ };
521
+ reactIs_production.isFragment = function (object) {
522
+ return typeOf(object) === REACT_FRAGMENT_TYPE;
523
+ };
524
+ reactIs_production.isLazy = function (object) {
525
+ return typeOf(object) === REACT_LAZY_TYPE;
526
+ };
527
+ reactIs_production.isMemo = function (object) {
528
+ return typeOf(object) === REACT_MEMO_TYPE;
529
+ };
530
+ reactIs_production.isPortal = function (object) {
531
+ return typeOf(object) === REACT_PORTAL_TYPE;
532
+ };
533
+ reactIs_production.isProfiler = function (object) {
534
+ return typeOf(object) === REACT_PROFILER_TYPE;
535
+ };
536
+ reactIs_production.isStrictMode = function (object) {
537
+ return typeOf(object) === REACT_STRICT_MODE_TYPE;
538
+ };
539
+ reactIs_production.isSuspense = function (object) {
540
+ return typeOf(object) === REACT_SUSPENSE_TYPE;
541
+ };
542
+ reactIs_production.isSuspenseList = function (object) {
543
+ return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
544
+ };
545
+ reactIs_production.isValidElementType = function (type) {
546
+ return "string" === typeof type ||
547
+ "function" === typeof type ||
548
+ type === REACT_FRAGMENT_TYPE ||
549
+ type === REACT_PROFILER_TYPE ||
550
+ type === REACT_STRICT_MODE_TYPE ||
551
+ type === REACT_SUSPENSE_TYPE ||
552
+ type === REACT_SUSPENSE_LIST_TYPE ||
553
+ ("object" === typeof type &&
554
+ null !== type &&
555
+ (type.$$typeof === REACT_LAZY_TYPE ||
556
+ type.$$typeof === REACT_MEMO_TYPE ||
557
+ type.$$typeof === REACT_CONTEXT_TYPE ||
558
+ type.$$typeof === REACT_CONSUMER_TYPE ||
559
+ type.$$typeof === REACT_FORWARD_REF_TYPE ||
560
+ type.$$typeof === REACT_CLIENT_REFERENCE ||
561
+ void 0 !== type.getModuleId))
562
+ ? true
563
+ : false;
564
+ };
565
+ reactIs_production.typeOf = typeOf;
566
+ return reactIs_production;
567
+ }
568
+
569
+ {
570
+ reactIs.exports = requireReactIs_production();
113
571
  }
114
572
 
573
+ var reactIsExports = reactIs.exports;
574
+
115
575
  // https://github.com/sindresorhus/is-plain-obj/blob/main/index.js
116
576
  function isPlainObject(item) {
117
577
  if (typeof item !== 'object' || item === null) {
@@ -121,7 +581,7 @@ function isPlainObject(item) {
121
581
  return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in item) && !(Symbol.iterator in item);
122
582
  }
123
583
  function deepClone(source) {
124
- if (!isPlainObject(source)) {
584
+ if (/*#__PURE__*/React.isValidElement(source) || reactIsExports.isValidElementType(source) || !isPlainObject(source)) {
125
585
  return source;
126
586
  }
127
587
  const output = {};
@@ -130,17 +590,38 @@ function deepClone(source) {
130
590
  });
131
591
  return output;
132
592
  }
593
+
594
+ /**
595
+ * Merge objects deeply.
596
+ * It will shallow copy React elements.
597
+ *
598
+ * If `options.clone` is set to `false` the source object will be merged directly into the target object.
599
+ *
600
+ * @example
601
+ * ```ts
602
+ * deepmerge({ a: { b: 1 }, d: 2 }, { a: { c: 2 }, d: 4 });
603
+ * // => { a: { b: 1, c: 2 }, d: 4 }
604
+ * ````
605
+ *
606
+ * @param target The target object.
607
+ * @param source The source object.
608
+ * @param options The merge options.
609
+ * @param options.clone Set to `false` to merge the source object directly into the target object.
610
+ * @returns The merged object.
611
+ */
133
612
  function deepmerge(target, source, options = {
134
613
  clone: true
135
614
  }) {
136
- const output = options.clone ? _extends({}, target) : target;
615
+ const output = options.clone ? {
616
+ ...target
617
+ } : target;
137
618
  if (isPlainObject(target) && isPlainObject(source)) {
138
619
  Object.keys(source).forEach(key => {
620
+ if (/*#__PURE__*/React.isValidElement(source[key]) || reactIsExports.isValidElementType(source[key])) {
621
+ output[key] = source[key];
622
+ } else if (isPlainObject(source[key]) &&
139
623
  // Avoid prototype pollution
140
- if (key === '__proto__') {
141
- return;
142
- }
143
- if (isPlainObject(source[key]) && key in target && isPlainObject(target[key])) {
624
+ Object.prototype.hasOwnProperty.call(target, key) && isPlainObject(target[key])) {
144
625
  // Since `output` is a clone of `target` and we have narrowed `target` in this block we can cast to the same type.
145
626
  output[key] = deepmerge(target[key], source[key], options);
146
627
  } else if (options.clone) {
@@ -153,7 +634,8 @@ function deepmerge(target, source, options = {
153
634
  return output;
154
635
  }
155
636
 
156
- const _excluded$4 = ["values", "unit", "step"];
637
+ // Sorted ASC by size. That's important.
638
+ // It can't be configured as it's used statically for propTypes.
157
639
  const sortBreakpointsValues = values => {
158
640
  const breakpointsAsArray = Object.keys(values).map(key => ({
159
641
  key,
@@ -162,32 +644,33 @@ const sortBreakpointsValues = values => {
162
644
  // Sort in ascending order
163
645
  breakpointsAsArray.sort((breakpoint1, breakpoint2) => breakpoint1.val - breakpoint2.val);
164
646
  return breakpointsAsArray.reduce((acc, obj) => {
165
- return _extends({}, acc, {
647
+ return {
648
+ ...acc,
166
649
  [obj.key]: obj.val
167
- });
650
+ };
168
651
  }, {});
169
652
  };
170
653
 
171
654
  // Keep in mind that @media is inclusive by the CSS specification.
172
655
  function createBreakpoints(breakpoints) {
173
656
  const {
174
- // The breakpoint **start** at this value.
175
- // For instance with the first breakpoint xs: [xs, sm).
176
- values = {
177
- xs: 0,
178
- // phone
179
- sm: 600,
180
- // tablet
181
- md: 900,
182
- // small laptop
183
- lg: 1200,
184
- // desktop
185
- xl: 1536 // large screen
186
- },
187
- unit = 'px',
188
- step = 5
189
- } = breakpoints,
190
- other = _objectWithoutPropertiesLoose(breakpoints, _excluded$4);
657
+ // The breakpoint **start** at this value.
658
+ // For instance with the first breakpoint xs: [xs, sm).
659
+ values = {
660
+ xs: 0,
661
+ // phone
662
+ sm: 600,
663
+ // tablet
664
+ md: 900,
665
+ // small laptop
666
+ lg: 1200,
667
+ // desktop
668
+ xl: 1536 // large screen
669
+ },
670
+ unit = 'px',
671
+ step = 5,
672
+ ...other
673
+ } = breakpoints;
191
674
  const sortedValues = sortBreakpointsValues(values);
192
675
  const keys = Object.keys(sortedValues);
193
676
  function up(key) {
@@ -219,7 +702,7 @@ function createBreakpoints(breakpoints) {
219
702
  }
220
703
  return between(key, keys[keys.indexOf(key) + 1]).replace('@media', '@media not all and');
221
704
  }
222
- return _extends({
705
+ return {
223
706
  keys,
224
707
  values: sortedValues,
225
708
  up,
@@ -227,8 +710,75 @@ function createBreakpoints(breakpoints) {
227
710
  between,
228
711
  only,
229
712
  not,
230
- unit
231
- }, other);
713
+ unit,
714
+ ...other
715
+ };
716
+ }
717
+
718
+ /**
719
+ * For using in `sx` prop to sort the breakpoint from low to high.
720
+ * Note: this function does not work and will not support multiple units.
721
+ * e.g. input: { '@container (min-width:300px)': '1rem', '@container (min-width:40rem)': '2rem' }
722
+ * output: { '@container (min-width:40rem)': '2rem', '@container (min-width:300px)': '1rem' } // since 40 < 300 eventhough 40rem > 300px
723
+ */
724
+ function sortContainerQueries(theme, css) {
725
+ if (!theme.containerQueries) {
726
+ return css;
727
+ }
728
+ const sorted = Object.keys(css).filter(key => key.startsWith('@container')).sort((a, b) => {
729
+ const regex = /min-width:\s*([0-9.]+)/;
730
+ return +(a.match(regex)?.[1] || 0) - +(b.match(regex)?.[1] || 0);
731
+ });
732
+ if (!sorted.length) {
733
+ return css;
734
+ }
735
+ return sorted.reduce((acc, key) => {
736
+ const value = css[key];
737
+ delete acc[key];
738
+ acc[key] = value;
739
+ return acc;
740
+ }, {
741
+ ...css
742
+ });
743
+ }
744
+ function isCqShorthand(breakpointKeys, value) {
745
+ return value === '@' || value.startsWith('@') && (breakpointKeys.some(key => value.startsWith(`@${key}`)) || !!value.match(/^@\d/));
746
+ }
747
+ function getContainerQuery(theme, shorthand) {
748
+ const matches = shorthand.match(/^@([^/]+)?\/?(.+)?$/);
749
+ if (!matches) {
750
+ return null;
751
+ }
752
+ const [, containerQuery, containerName] = matches;
753
+ const value = Number.isNaN(+containerQuery) ? containerQuery || 0 : +containerQuery;
754
+ return theme.containerQueries(containerName).up(value);
755
+ }
756
+ function cssContainerQueries(themeInput) {
757
+ const toContainerQuery = (mediaQuery, name) => mediaQuery.replace('@media', name ? `@container ${name}` : '@container');
758
+ function attachCq(node, name) {
759
+ node.up = (...args) => toContainerQuery(themeInput.breakpoints.up(...args), name);
760
+ node.down = (...args) => toContainerQuery(themeInput.breakpoints.down(...args), name);
761
+ node.between = (...args) => toContainerQuery(themeInput.breakpoints.between(...args), name);
762
+ node.only = (...args) => toContainerQuery(themeInput.breakpoints.only(...args), name);
763
+ node.not = (...args) => {
764
+ const result = toContainerQuery(themeInput.breakpoints.not(...args), name);
765
+ if (result.includes('not all and')) {
766
+ // `@container` does not work with `not all and`, so need to invert the logic
767
+ return result.replace('not all and ', '').replace('min-width:', 'width<').replace('max-width:', 'width>').replace('and', 'or');
768
+ }
769
+ return result;
770
+ };
771
+ }
772
+ const node = {};
773
+ const containerQueries = name => {
774
+ attachCq(node, name);
775
+ return node;
776
+ };
777
+ attachCq(containerQueries);
778
+ return {
779
+ ...themeInput,
780
+ containerQueries
781
+ };
232
782
  }
233
783
 
234
784
  const shape = {
@@ -263,6 +813,17 @@ const defaultBreakpoints = {
263
813
  keys: ['xs', 'sm', 'md', 'lg', 'xl'],
264
814
  up: key => `@media (min-width:${values[key]}px)`
265
815
  };
816
+ const defaultContainerQueries = {
817
+ containerQueries: containerName => ({
818
+ up: key => {
819
+ let result = typeof key === 'number' ? key : values[key] || key;
820
+ if (typeof result === 'number') {
821
+ result = `${result}px`;
822
+ }
823
+ return containerName ? `@container ${containerName} (min-width:${result})` : `@container (min-width:${result})`;
824
+ }
825
+ })
826
+ };
266
827
  function handleBreakpoints(props, propValue, styleFromPropValue) {
267
828
  const theme = props.theme || {};
268
829
  if (Array.isArray(propValue)) {
@@ -275,8 +836,14 @@ function handleBreakpoints(props, propValue, styleFromPropValue) {
275
836
  if (typeof propValue === 'object') {
276
837
  const themeBreakpoints = theme.breakpoints || defaultBreakpoints;
277
838
  return Object.keys(propValue).reduce((acc, breakpoint) => {
839
+ if (isCqShorthand(themeBreakpoints.keys, breakpoint)) {
840
+ const containerKey = getContainerQuery(theme.containerQueries ? theme : defaultContainerQueries, breakpoint);
841
+ if (containerKey) {
842
+ acc[containerKey] = styleFromPropValue(propValue[breakpoint], breakpoint);
843
+ }
844
+ }
278
845
  // key is breakpoint
279
- if (Object.keys(themeBreakpoints.values || values).indexOf(breakpoint) !== -1) {
846
+ else if (Object.keys(themeBreakpoints.values || values).includes(breakpoint)) {
280
847
  const mediaKey = themeBreakpoints.up(breakpoint);
281
848
  acc[mediaKey] = styleFromPropValue(propValue[breakpoint], breakpoint);
282
849
  } else {
@@ -290,8 +857,7 @@ function handleBreakpoints(props, propValue, styleFromPropValue) {
290
857
  return output;
291
858
  }
292
859
  function createEmptyBreakpointObject(breakpointsInput = {}) {
293
- var _breakpointsInput$key;
294
- const breakpointsInOrder = (_breakpointsInput$key = breakpointsInput.keys) == null ? void 0 : _breakpointsInput$key.reduce((acc, key) => {
860
+ const breakpointsInOrder = breakpointsInput.keys?.reduce((acc, key) => {
295
861
  const breakpointStyleKey = breakpointsInput.up(key);
296
862
  acc[breakpointStyleKey] = {};
297
863
  return acc;
@@ -495,22 +1061,32 @@ const marginKeys = ['m', 'mt', 'mr', 'mb', 'ml', 'mx', 'my', 'margin', 'marginTo
495
1061
  const paddingKeys = ['p', 'pt', 'pr', 'pb', 'pl', 'px', 'py', 'padding', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'paddingX', 'paddingY', 'paddingInline', 'paddingInlineStart', 'paddingInlineEnd', 'paddingBlock', 'paddingBlockStart', 'paddingBlockEnd'];
496
1062
  [...marginKeys, ...paddingKeys];
497
1063
  function createUnaryUnit(theme, themeKey, defaultValue, propName) {
498
- var _getPath;
499
- const themeSpacing = (_getPath = getPath(theme, themeKey, false)) != null ? _getPath : defaultValue;
500
- if (typeof themeSpacing === 'number') {
501
- return abs => {
502
- if (typeof abs === 'string') {
503
- return abs;
1064
+ const themeSpacing = getPath(theme, themeKey, true) ?? defaultValue;
1065
+ if (typeof themeSpacing === 'number' || typeof themeSpacing === 'string') {
1066
+ return val => {
1067
+ if (typeof val === 'string') {
1068
+ return val;
1069
+ }
1070
+ if (typeof themeSpacing === 'string') {
1071
+ return `calc(${val} * ${themeSpacing})`;
504
1072
  }
505
- return themeSpacing * abs;
1073
+ return themeSpacing * val;
506
1074
  };
507
1075
  }
508
1076
  if (Array.isArray(themeSpacing)) {
509
- return abs => {
510
- if (typeof abs === 'string') {
511
- return abs;
1077
+ return val => {
1078
+ if (typeof val === 'string') {
1079
+ return val;
1080
+ }
1081
+ const abs = Math.abs(val);
1082
+ const transformed = themeSpacing[abs];
1083
+ if (val >= 0) {
1084
+ return transformed;
512
1085
  }
513
- return themeSpacing[abs];
1086
+ if (typeof transformed === 'number') {
1087
+ return -transformed;
1088
+ }
1089
+ return `-${transformed}`;
514
1090
  };
515
1091
  }
516
1092
  if (typeof themeSpacing === 'function') {
@@ -525,15 +1101,7 @@ function getValue(transformer, propValue) {
525
1101
  if (typeof propValue === 'string' || propValue == null) {
526
1102
  return propValue;
527
1103
  }
528
- const abs = Math.abs(propValue);
529
- const transformed = transformer(abs);
530
- if (propValue >= 0) {
531
- return transformed;
532
- }
533
- if (typeof transformed === 'number') {
534
- return -transformed;
535
- }
536
- return `-${transformed}`;
1104
+ return transformer(propValue);
537
1105
  }
538
1106
  function getStyleFromPropValue(cssProperties, transformer) {
539
1107
  return propValue => cssProperties.reduce((acc, cssProperty) => {
@@ -544,7 +1112,7 @@ function getStyleFromPropValue(cssProperties, transformer) {
544
1112
  function resolveCssProperty(props, keys, prop, transformer) {
545
1113
  // Using a hash computation over an array iteration could be faster, but with only 28 items,
546
1114
  // it's doesn't worth the bundle size.
547
- if (keys.indexOf(prop) === -1) {
1115
+ if (!keys.includes(prop)) {
548
1116
  return null;
549
1117
  }
550
1118
  const cssProperties = getCssProperties(prop);
@@ -570,18 +1138,17 @@ padding.filterProps = paddingKeys;
570
1138
  // The different signatures imply different meaning for their arguments that can't be expressed structurally.
571
1139
  // We express the difference with variable names.
572
1140
 
573
- function createSpacing(spacingInput = 8) {
1141
+ function createSpacing(spacingInput = 8,
1142
+ // Material Design layouts are visually balanced. Most measurements align to an 8dp grid, which aligns both spacing and the overall layout.
1143
+ // Smaller components, such as icons, can align to a 4dp grid.
1144
+ // https://m2.material.io/design/layout/understanding-layout.html
1145
+ transform = createUnarySpacing({
1146
+ spacing: spacingInput
1147
+ })) {
574
1148
  // Already transformed.
575
1149
  if (spacingInput.mui) {
576
1150
  return spacingInput;
577
1151
  }
578
-
579
- // Material Design layouts are visually balanced. Most measurements align to an 8dp grid, which aligns both spacing and the overall layout.
580
- // Smaller components, such as icons, can align to a 4dp grid.
581
- // https://m2.material.io/design/layout/understanding-layout.html
582
- const transform = createUnarySpacing({
583
- spacing: spacingInput
584
- });
585
1152
  const spacing = (...argsInput) => {
586
1153
  const args = argsInput.length === 0 ? [1] : argsInput;
587
1154
  return args.map(argument => {
@@ -765,14 +1332,13 @@ const width = style$2({
765
1332
  const maxWidth = props => {
766
1333
  if (props.maxWidth !== undefined && props.maxWidth !== null) {
767
1334
  const styleFromPropValue = propValue => {
768
- var _props$theme, _props$theme2;
769
- const breakpoint = ((_props$theme = props.theme) == null || (_props$theme = _props$theme.breakpoints) == null || (_props$theme = _props$theme.values) == null ? void 0 : _props$theme[propValue]) || values[propValue];
1335
+ const breakpoint = props.theme?.breakpoints?.values?.[propValue] || values[propValue];
770
1336
  if (!breakpoint) {
771
1337
  return {
772
1338
  maxWidth: sizingTransform(propValue)
773
1339
  };
774
1340
  }
775
- if (((_props$theme2 = props.theme) == null || (_props$theme2 = _props$theme2.breakpoints) == null ? void 0 : _props$theme2.unit) !== 'px') {
1341
+ if (props.theme?.breakpoints?.unit !== 'px') {
776
1342
  return {
777
1343
  maxWidth: `${breakpoint}${props.theme.breakpoints.unit}`
778
1344
  };
@@ -1081,6 +1647,9 @@ const defaultSxConfig = {
1081
1647
  },
1082
1648
  boxSizing: {},
1083
1649
  // typography
1650
+ font: {
1651
+ themeKey: 'font'
1652
+ },
1084
1653
  fontFamily: {
1085
1654
  themeKey: 'typography'
1086
1655
  },
@@ -1161,15 +1730,15 @@ function unstable_createStyleFunctionSx() {
1161
1730
  return handleBreakpoints(props, val, styleFromPropValue);
1162
1731
  }
1163
1732
  function styleFunctionSx(props) {
1164
- var _theme$unstable_sxCon;
1165
1733
  const {
1166
1734
  sx,
1167
- theme = {}
1735
+ theme = {},
1736
+ nested
1168
1737
  } = props || {};
1169
1738
  if (!sx) {
1170
1739
  return null; // Emotion & styled-components will neglect null
1171
1740
  }
1172
- const config = (_theme$unstable_sxCon = theme.unstable_sxConfig) != null ? _theme$unstable_sxCon : defaultSxConfig;
1741
+ const config = theme.unstable_sxConfig ?? defaultSxConfig;
1173
1742
 
1174
1743
  /*
1175
1744
  * Receive `sxInput` as object or callback
@@ -1205,7 +1774,8 @@ function unstable_createStyleFunctionSx() {
1205
1774
  if (objectsHaveSameKeys(breakpointsValues, value)) {
1206
1775
  css[styleKey] = styleFunctionSx({
1207
1776
  sx: value,
1208
- theme
1777
+ theme,
1778
+ nested: true
1209
1779
  });
1210
1780
  } else {
1211
1781
  css = merge(css, breakpointsValues);
@@ -1216,7 +1786,12 @@ function unstable_createStyleFunctionSx() {
1216
1786
  }
1217
1787
  }
1218
1788
  });
1219
- return removeUnusedBreakpoints(breakpointsKeys, css);
1789
+ if (!nested && theme.modularCssLayers) {
1790
+ return {
1791
+ '@layer sx': sortContainerQueries(theme, removeUnusedBreakpoints(breakpointsKeys, css))
1792
+ };
1793
+ }
1794
+ return sortContainerQueries(theme, removeUnusedBreakpoints(breakpointsKeys, css));
1220
1795
  }
1221
1796
  return Array.isArray(sx) ? sx.map(traverse) : traverse(sx);
1222
1797
  }
@@ -1229,15 +1804,19 @@ styleFunctionSx.filterProps = ['sx'];
1229
1804
  * A universal utility to style components with multiple color modes. Always use it from the theme object.
1230
1805
  * It works with:
1231
1806
  * - [Basic theme](https://mui.com/material-ui/customization/dark-mode/)
1232
- * - [CSS theme variables](https://mui.com/material-ui/experimental-api/css-theme-variables/overview/)
1807
+ * - [CSS theme variables](https://mui.com/material-ui/customization/css-theme-variables/overview/)
1233
1808
  * - Zero-runtime engine
1234
1809
  *
1235
1810
  * Tips: Use an array over object spread and place `theme.applyStyles()` last.
1236
1811
  *
1812
+ * With the styled function:
1237
1813
  * ✅ [{ background: '#e5e5e5' }, theme.applyStyles('dark', { background: '#1c1c1c' })]
1238
- *
1239
1814
  * 🚫 { background: '#e5e5e5', ...theme.applyStyles('dark', { background: '#1c1c1c' })}
1240
1815
  *
1816
+ * With the sx prop:
1817
+ * ✅ [{ background: '#e5e5e5' }, theme => theme.applyStyles('dark', { background: '#1c1c1c' })]
1818
+ * 🚫 { background: '#e5e5e5', ...theme => theme.applyStyles('dark', { background: '#1c1c1c' })}
1819
+ *
1241
1820
  * @example
1242
1821
  * 1. using with `styled`:
1243
1822
  * ```jsx
@@ -1253,9 +1832,9 @@ styleFunctionSx.filterProps = ['sx'];
1253
1832
  * @example
1254
1833
  * 2. using with `sx` prop:
1255
1834
  * ```jsx
1256
- * <Box sx={theme => [
1835
+ * <Box sx={[
1257
1836
  * { background: '#e5e5e5' },
1258
- * theme.applyStyles('dark', {
1837
+ * theme => theme.applyStyles('dark', {
1259
1838
  * background: '#1c1c1c',
1260
1839
  * color: '#fff',
1261
1840
  * }),
@@ -1286,10 +1865,19 @@ styleFunctionSx.filterProps = ['sx'];
1286
1865
  function applyStyles(key, styles) {
1287
1866
  // @ts-expect-error this is 'any' type
1288
1867
  const theme = this;
1289
- if (theme.vars && typeof theme.getColorSchemeSelector === 'function') {
1290
- // If CssVarsProvider is used as a provider,
1291
- // returns '* :where([data-mui-color-scheme="light|dark"]) &'
1292
- const selector = theme.getColorSchemeSelector(key).replace(/(\[[^\]]+\])/, '*:where($1)');
1868
+ if (theme.vars) {
1869
+ if (!theme.colorSchemes?.[key] || typeof theme.getColorSchemeSelector !== 'function') {
1870
+ return {};
1871
+ }
1872
+ // If CssVarsProvider is used as a provider, returns '*:where({selector}) &'
1873
+ let selector = theme.getColorSchemeSelector(key);
1874
+ if (selector === '&') {
1875
+ return styles;
1876
+ }
1877
+ if (selector.includes('data-') || selector.includes('.')) {
1878
+ // '*' is required as a workaround for Emotion issue (https://github.com/emotion-js/emotion/issues/2836)
1879
+ selector = `*:where(${selector.replace(/\s*&$/, '')}) &`;
1880
+ }
1293
1881
  return {
1294
1882
  [selector]: styles
1295
1883
  };
@@ -1300,15 +1888,14 @@ function applyStyles(key, styles) {
1300
1888
  return {};
1301
1889
  }
1302
1890
 
1303
- const _excluded$3 = ["breakpoints", "palette", "spacing", "shape"];
1304
1891
  function createTheme(options = {}, ...args) {
1305
1892
  const {
1306
- breakpoints: breakpointsInput = {},
1307
- palette: paletteInput = {},
1308
- spacing: spacingInput,
1309
- shape: shapeInput = {}
1310
- } = options,
1311
- other = _objectWithoutPropertiesLoose(options, _excluded$3);
1893
+ breakpoints: breakpointsInput = {},
1894
+ palette: paletteInput = {},
1895
+ spacing: spacingInput,
1896
+ shape: shapeInput = {},
1897
+ ...other
1898
+ } = options;
1312
1899
  const breakpoints = createBreakpoints(breakpointsInput);
1313
1900
  const spacing = createSpacing(spacingInput);
1314
1901
  let muiTheme = deepmerge({
@@ -1316,15 +1903,23 @@ function createTheme(options = {}, ...args) {
1316
1903
  direction: 'ltr',
1317
1904
  components: {},
1318
1905
  // Inject component definitions.
1319
- palette: _extends({
1320
- mode: 'light'
1321
- }, paletteInput),
1906
+ palette: {
1907
+ mode: 'light',
1908
+ ...paletteInput
1909
+ },
1322
1910
  spacing,
1323
- shape: _extends({}, shape, shapeInput)
1911
+ shape: {
1912
+ ...shape,
1913
+ ...shapeInput
1914
+ }
1324
1915
  }, other);
1916
+ muiTheme = cssContainerQueries(muiTheme);
1325
1917
  muiTheme.applyStyles = applyStyles;
1326
1918
  muiTheme = args.reduce((acc, argument) => deepmerge(acc, argument), muiTheme);
1327
- muiTheme.unstable_sxConfig = _extends({}, defaultSxConfig, other == null ? void 0 : other.unstable_sxConfig);
1919
+ muiTheme.unstable_sxConfig = {
1920
+ ...defaultSxConfig,
1921
+ ...other?.unstable_sxConfig
1922
+ };
1328
1923
  muiTheme.unstable_sx = function sx(props) {
1329
1924
  return styleFunctionSx({
1330
1925
  sx: props,
@@ -1334,12 +1929,12 @@ function createTheme(options = {}, ...args) {
1334
1929
  return muiTheme;
1335
1930
  }
1336
1931
 
1337
- function isObjectEmpty(obj) {
1932
+ function isObjectEmpty$1(obj) {
1338
1933
  return Object.keys(obj).length === 0;
1339
1934
  }
1340
1935
  function useTheme$1(defaultTheme = null) {
1341
1936
  const contextTheme = React.useContext(ThemeContext);
1342
- return !contextTheme || isObjectEmpty(contextTheme) ? defaultTheme : contextTheme;
1937
+ return !contextTheme || isObjectEmpty$1(contextTheme) ? defaultTheme : contextTheme;
1343
1938
  }
1344
1939
 
1345
1940
  const systemDefaultTheme$1 = createTheme();
@@ -1347,14 +1942,12 @@ function useTheme(defaultTheme = systemDefaultTheme$1) {
1347
1942
  return useTheme$1(defaultTheme);
1348
1943
  }
1349
1944
 
1350
- const _excluded$2 = ["sx"];
1351
1945
  const splitProps = props => {
1352
- var _props$theme$unstable, _props$theme;
1353
1946
  const result = {
1354
1947
  systemProps: {},
1355
1948
  otherProps: {}
1356
1949
  };
1357
- const config = (_props$theme$unstable = props == null || (_props$theme = props.theme) == null ? void 0 : _props$theme.unstable_sxConfig) != null ? _props$theme$unstable : defaultSxConfig;
1950
+ const config = props?.theme?.unstable_sxConfig ?? defaultSxConfig;
1358
1951
  Object.keys(props).forEach(prop => {
1359
1952
  if (config[prop]) {
1360
1953
  result.systemProps[prop] = props[prop];
@@ -1366,9 +1959,9 @@ const splitProps = props => {
1366
1959
  };
1367
1960
  function extendSxProp(props) {
1368
1961
  const {
1369
- sx: inSx
1370
- } = props,
1371
- other = _objectWithoutPropertiesLoose(props, _excluded$2);
1962
+ sx: inSx,
1963
+ ...other
1964
+ } = props;
1372
1965
  const {
1373
1966
  systemProps,
1374
1967
  otherProps
@@ -1382,14 +1975,21 @@ function extendSxProp(props) {
1382
1975
  if (!isPlainObject(result)) {
1383
1976
  return systemProps;
1384
1977
  }
1385
- return _extends({}, systemProps, result);
1978
+ return {
1979
+ ...systemProps,
1980
+ ...result
1981
+ };
1386
1982
  };
1387
1983
  } else {
1388
- finalSx = _extends({}, systemProps, inSx);
1984
+ finalSx = {
1985
+ ...systemProps,
1986
+ ...inSx
1987
+ };
1389
1988
  }
1390
- return _extends({}, otherProps, {
1989
+ return {
1990
+ ...otherProps,
1391
1991
  sx: finalSx
1392
- });
1992
+ };
1393
1993
  }
1394
1994
 
1395
1995
  const defaultGenerator = componentName => componentName;
@@ -1430,90 +2030,122 @@ function generateUtilityClass(componentName, slot, globalStatePrefix = 'Mui') {
1430
2030
  return globalStateClass ? `${globalStatePrefix}-${globalStateClass}` : `${ClassNameGenerator.generate(componentName)}-${slot}`;
1431
2031
  }
1432
2032
 
1433
- const _excluded$1 = ["ownerState"],
1434
- _excluded2 = ["variants"],
1435
- _excluded3 = ["name", "slot", "skipVariantsResolver", "skipSx", "overridesResolver"];
1436
- function isEmpty(obj) {
1437
- return Object.keys(obj).length === 0;
1438
- }
2033
+ function preprocessStyles(input) {
2034
+ const {
2035
+ variants,
2036
+ ...style
2037
+ } = input;
2038
+ const result = {
2039
+ variants,
2040
+ style: internal_serializeStyles(style),
2041
+ isProcessed: true
2042
+ };
1439
2043
 
1440
- // https://github.com/emotion-js/emotion/blob/26ded6109fcd8ca9875cc2ce4564fee678a3f3c5/packages/styled/src/utils.js#L40
1441
- function isStringTag(tag) {
1442
- return typeof tag === 'string' &&
1443
- // 96 is one less than the char code
1444
- // for "a" so this is checking that
1445
- // it's a lowercase character
1446
- tag.charCodeAt(0) > 96;
2044
+ // Not supported on styled-components
2045
+ if (result.style === style) {
2046
+ return result;
2047
+ }
2048
+ if (variants) {
2049
+ variants.forEach(variant => {
2050
+ if (typeof variant.style !== 'function') {
2051
+ variant.style = internal_serializeStyles(variant.style);
2052
+ }
2053
+ });
2054
+ }
2055
+ return result;
1447
2056
  }
1448
2057
 
2058
+ /* eslint-disable no-underscore-dangle */
2059
+ /* eslint-disable no-labels */
2060
+ /* eslint-disable no-lone-blocks */
2061
+
2062
+ const systemDefaultTheme = createTheme();
2063
+
1449
2064
  // Update /system/styled/#api in case if this changes
1450
2065
  function shouldForwardProp(prop) {
1451
2066
  return prop !== 'ownerState' && prop !== 'theme' && prop !== 'sx' && prop !== 'as';
1452
2067
  }
1453
- const systemDefaultTheme = createTheme();
1454
- const lowercaseFirstLetter = string => {
1455
- if (!string) {
1456
- return string;
2068
+ function shallowLayer(serialized, layerName) {
2069
+ if (layerName && serialized && typeof serialized === 'object' && serialized.styles && !serialized.styles.startsWith('@layer') // only add the layer if it is not already there.
2070
+ ) {
2071
+ serialized.styles = `@layer ${layerName}{${String(serialized.styles)}}`;
1457
2072
  }
1458
- return string.charAt(0).toLowerCase() + string.slice(1);
1459
- };
1460
- function resolveTheme({
1461
- defaultTheme,
1462
- theme,
1463
- themeId
1464
- }) {
1465
- return isEmpty(theme) ? defaultTheme : theme[themeId] || theme;
2073
+ return serialized;
1466
2074
  }
1467
2075
  function defaultOverridesResolver(slot) {
1468
2076
  if (!slot) {
1469
2077
  return null;
1470
2078
  }
1471
- return (props, styles) => styles[slot];
2079
+ return (_props, styles) => styles[slot];
2080
+ }
2081
+ function attachTheme(props, themeId, defaultTheme) {
2082
+ props.theme = isObjectEmpty(props.theme) ? defaultTheme : props.theme[themeId] || props.theme;
1472
2083
  }
1473
- function processStyleArg(callableStyle, _ref) {
1474
- let {
1475
- ownerState
1476
- } = _ref,
1477
- props = _objectWithoutPropertiesLoose(_ref, _excluded$1);
1478
- const resolvedStylesArg = typeof callableStyle === 'function' ? callableStyle(_extends({
1479
- ownerState
1480
- }, props)) : callableStyle;
1481
- if (Array.isArray(resolvedStylesArg)) {
1482
- return resolvedStylesArg.flatMap(resolvedStyle => processStyleArg(resolvedStyle, _extends({
1483
- ownerState
1484
- }, props)));
2084
+ function processStyle(props, style, layerName) {
2085
+ /*
2086
+ * Style types:
2087
+ * - null/undefined
2088
+ * - string
2089
+ * - CSS style object: { [cssKey]: [cssValue], variants }
2090
+ * - Processed style object: { style, variants, isProcessed: true }
2091
+ * - Array of any of the above
2092
+ */
2093
+
2094
+ const resolvedStyle = typeof style === 'function' ? style(props) : style;
2095
+ if (Array.isArray(resolvedStyle)) {
2096
+ return resolvedStyle.flatMap(subStyle => processStyle(props, subStyle, layerName));
1485
2097
  }
1486
- if (!!resolvedStylesArg && typeof resolvedStylesArg === 'object' && Array.isArray(resolvedStylesArg.variants)) {
1487
- const {
1488
- variants = []
1489
- } = resolvedStylesArg,
1490
- otherStyles = _objectWithoutPropertiesLoose(resolvedStylesArg, _excluded2);
1491
- let result = otherStyles;
1492
- variants.forEach(variant => {
1493
- let isMatch = true;
1494
- if (typeof variant.props === 'function') {
1495
- isMatch = variant.props(_extends({
1496
- ownerState
1497
- }, props, ownerState));
1498
- } else {
1499
- Object.keys(variant.props).forEach(key => {
1500
- if ((ownerState == null ? void 0 : ownerState[key]) !== variant.props[key] && props[key] !== variant.props[key]) {
1501
- isMatch = false;
1502
- }
1503
- });
2098
+ if (Array.isArray(resolvedStyle?.variants)) {
2099
+ let rootStyle;
2100
+ if (resolvedStyle.isProcessed) {
2101
+ rootStyle = layerName ? shallowLayer(resolvedStyle.style, layerName) : resolvedStyle.style;
2102
+ } else {
2103
+ const {
2104
+ variants,
2105
+ ...otherStyles
2106
+ } = resolvedStyle;
2107
+ rootStyle = layerName ? shallowLayer(internal_serializeStyles(otherStyles), layerName) : otherStyles;
2108
+ }
2109
+ return processStyleVariants(props, resolvedStyle.variants, [rootStyle], layerName);
2110
+ }
2111
+ if (resolvedStyle?.isProcessed) {
2112
+ return layerName ? shallowLayer(internal_serializeStyles(resolvedStyle.style), layerName) : resolvedStyle.style;
2113
+ }
2114
+ return layerName ? shallowLayer(internal_serializeStyles(resolvedStyle), layerName) : resolvedStyle;
2115
+ }
2116
+ function processStyleVariants(props, variants, results = [], layerName = undefined) {
2117
+ let mergedState; // We might not need it, initialized lazily
2118
+
2119
+ variantLoop: for (let i = 0; i < variants.length; i += 1) {
2120
+ const variant = variants[i];
2121
+ if (typeof variant.props === 'function') {
2122
+ mergedState ??= {
2123
+ ...props,
2124
+ ...props.ownerState,
2125
+ ownerState: props.ownerState
2126
+ };
2127
+ if (!variant.props(mergedState)) {
2128
+ continue;
1504
2129
  }
1505
- if (isMatch) {
1506
- if (!Array.isArray(result)) {
1507
- result = [result];
2130
+ } else {
2131
+ for (const key in variant.props) {
2132
+ if (props[key] !== variant.props[key] && props.ownerState?.[key] !== variant.props[key]) {
2133
+ continue variantLoop;
1508
2134
  }
1509
- result.push(typeof variant.style === 'function' ? variant.style(_extends({
1510
- ownerState
1511
- }, props, ownerState)) : variant.style);
1512
2135
  }
1513
- });
1514
- return result;
2136
+ }
2137
+ if (typeof variant.style === 'function') {
2138
+ mergedState ??= {
2139
+ ...props,
2140
+ ...props.ownerState,
2141
+ ownerState: props.ownerState
2142
+ };
2143
+ results.push(layerName ? shallowLayer(internal_serializeStyles(variant.style(mergedState)), layerName) : variant.style(mergedState));
2144
+ } else {
2145
+ results.push(layerName ? shallowLayer(internal_serializeStyles(variant.style), layerName) : variant.style);
2146
+ }
1515
2147
  }
1516
- return resolvedStylesArg;
2148
+ return results;
1517
2149
  }
1518
2150
  function createStyled(input = {}) {
1519
2151
  const {
@@ -1522,28 +2154,24 @@ function createStyled(input = {}) {
1522
2154
  rootShouldForwardProp = shouldForwardProp,
1523
2155
  slotShouldForwardProp = shouldForwardProp
1524
2156
  } = input;
1525
- const systemSx = props => {
1526
- return styleFunctionSx(_extends({}, props, {
1527
- theme: resolveTheme(_extends({}, props, {
1528
- defaultTheme,
1529
- themeId
1530
- }))
1531
- }));
1532
- };
1533
- systemSx.__mui_systemSx = true;
1534
- return (tag, inputOptions = {}) => {
1535
- // Filter out the `sx` style function from the previous styled component to prevent unnecessary styles generated by the composite components.
1536
- internal_processStyles(tag, styles => styles.filter(style => !(style != null && style.__mui_systemSx)));
2157
+ function styleAttachTheme(props) {
2158
+ attachTheme(props, themeId, defaultTheme);
2159
+ }
2160
+ const styled = (tag, inputOptions = {}) => {
2161
+ // If `tag` is already a styled component, filter out the `sx` style function
2162
+ // to prevent unnecessary styles generated by the composite components.
2163
+ internal_mutateStyles(tag, styles => styles.filter(style => style !== styleFunctionSx));
1537
2164
  const {
1538
- name: componentName,
1539
- slot: componentSlot,
1540
- skipVariantsResolver: inputSkipVariantsResolver,
1541
- skipSx: inputSkipSx,
1542
- // TODO v6: remove `lowercaseFirstLetter()` in the next major release
1543
- // For more details: https://github.com/mui/material-ui/pull/37908
1544
- overridesResolver = defaultOverridesResolver(lowercaseFirstLetter(componentSlot))
1545
- } = inputOptions,
1546
- options = _objectWithoutPropertiesLoose(inputOptions, _excluded3);
2165
+ name: componentName,
2166
+ slot: componentSlot,
2167
+ skipVariantsResolver: inputSkipVariantsResolver,
2168
+ skipSx: inputSkipSx,
2169
+ // TODO v6: remove `lowercaseFirstLetter()` in the next major release
2170
+ // For more details: https://github.com/mui/material-ui/pull/37908
2171
+ overridesResolver = defaultOverridesResolver(lowercaseFirstLetter(componentSlot)),
2172
+ ...options
2173
+ } = inputOptions;
2174
+ const layerName = componentName && componentName.startsWith('Mui') || !!componentSlot ? 'components' : 'custom';
1547
2175
 
1548
2176
  // if skipVariantsResolver option is defined, take the value, otherwise, true for root and false for other slots.
1549
2177
  const skipVariantsResolver = inputSkipVariantsResolver !== undefined ? inputSkipVariantsResolver :
@@ -1551,7 +2179,6 @@ function createStyled(input = {}) {
1551
2179
  // For more details: https://github.com/mui/material-ui/pull/37908
1552
2180
  componentSlot && componentSlot !== 'Root' && componentSlot !== 'root' || false;
1553
2181
  const skipSx = inputSkipSx || false;
1554
- let label;
1555
2182
  let shouldForwardPropOption = shouldForwardProp;
1556
2183
 
1557
2184
  // TODO v6: remove `Root` in the next major release
@@ -1565,74 +2192,96 @@ function createStyled(input = {}) {
1565
2192
  // for string (html) tag, preserve the behavior in emotion & styled-components.
1566
2193
  shouldForwardPropOption = undefined;
1567
2194
  }
1568
- const defaultStyledResolver = styled$1(tag, _extends({
2195
+ const defaultStyledResolver = styled$1(tag, {
1569
2196
  shouldForwardProp: shouldForwardPropOption,
1570
- label
1571
- }, options));
1572
- const transformStyleArg = stylesArg => {
1573
- // On the server Emotion doesn't use React.forwardRef for creating components, so the created
1574
- // component stays as a function. This condition makes sure that we do not interpolate functions
1575
- // which are basically components used as a selectors.
1576
- if (typeof stylesArg === 'function' && stylesArg.__emotion_real !== stylesArg || isPlainObject(stylesArg)) {
1577
- return props => processStyleArg(stylesArg, _extends({}, props, {
1578
- theme: resolveTheme({
1579
- theme: props.theme,
1580
- defaultTheme,
1581
- themeId
1582
- })
1583
- }));
2197
+ label: generateStyledLabel(),
2198
+ ...options
2199
+ });
2200
+ const transformStyle = style => {
2201
+ // - On the server Emotion doesn't use React.forwardRef for creating components, so the created
2202
+ // component stays as a function. This condition makes sure that we do not interpolate functions
2203
+ // which are basically components used as a selectors.
2204
+ // - `style` could be a styled component from a babel plugin for component selectors, This condition
2205
+ // makes sure that we do not interpolate them.
2206
+ if (style.__emotion_real === style) {
2207
+ return style;
1584
2208
  }
1585
- return stylesArg;
2209
+ if (typeof style === 'function') {
2210
+ return function styleFunctionProcessor(props) {
2211
+ return processStyle(props, style, props.theme.modularCssLayers ? layerName : undefined);
2212
+ };
2213
+ }
2214
+ if (isPlainObject(style)) {
2215
+ const serialized = preprocessStyles(style);
2216
+ return function styleObjectProcessor(props) {
2217
+ if (!serialized.variants) {
2218
+ return props.theme.modularCssLayers ? shallowLayer(serialized.style, layerName) : serialized.style;
2219
+ }
2220
+ return processStyle(props, serialized, props.theme.modularCssLayers ? layerName : undefined);
2221
+ };
2222
+ }
2223
+ return style;
1586
2224
  };
1587
- const muiStyledResolver = (styleArg, ...expressions) => {
1588
- let transformedStyleArg = transformStyleArg(styleArg);
1589
- const expressionsWithDefaultTheme = expressions ? expressions.map(transformStyleArg) : [];
2225
+ const muiStyledResolver = (...expressionsInput) => {
2226
+ const expressionsHead = [];
2227
+ const expressionsBody = expressionsInput.map(transformStyle);
2228
+ const expressionsTail = [];
2229
+
2230
+ // Preprocess `props` to set the scoped theme value.
2231
+ // This must run before any other expression.
2232
+ expressionsHead.push(styleAttachTheme);
1590
2233
  if (componentName && overridesResolver) {
1591
- expressionsWithDefaultTheme.push(props => {
1592
- const theme = resolveTheme(_extends({}, props, {
1593
- defaultTheme,
1594
- themeId
1595
- }));
1596
- if (!theme.components || !theme.components[componentName] || !theme.components[componentName].styleOverrides) {
2234
+ expressionsTail.push(function styleThemeOverrides(props) {
2235
+ const theme = props.theme;
2236
+ const styleOverrides = theme.components?.[componentName]?.styleOverrides;
2237
+ if (!styleOverrides) {
1597
2238
  return null;
1598
2239
  }
1599
- const styleOverrides = theme.components[componentName].styleOverrides;
1600
2240
  const resolvedStyleOverrides = {};
2241
+
1601
2242
  // TODO: v7 remove iteration and use `resolveStyleArg(styleOverrides[slot])` directly
1602
- Object.entries(styleOverrides).forEach(([slotKey, slotStyle]) => {
1603
- resolvedStyleOverrides[slotKey] = processStyleArg(slotStyle, _extends({}, props, {
1604
- theme
1605
- }));
1606
- });
2243
+ // eslint-disable-next-line guard-for-in
2244
+ for (const slotKey in styleOverrides) {
2245
+ resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey], props.theme.modularCssLayers ? 'theme' : undefined);
2246
+ }
1607
2247
  return overridesResolver(props, resolvedStyleOverrides);
1608
2248
  });
1609
2249
  }
1610
2250
  if (componentName && !skipVariantsResolver) {
1611
- expressionsWithDefaultTheme.push(props => {
1612
- var _theme$components;
1613
- const theme = resolveTheme(_extends({}, props, {
1614
- defaultTheme,
1615
- themeId
1616
- }));
1617
- const themeVariants = theme == null || (_theme$components = theme.components) == null || (_theme$components = _theme$components[componentName]) == null ? void 0 : _theme$components.variants;
1618
- return processStyleArg({
1619
- variants: themeVariants
1620
- }, _extends({}, props, {
1621
- theme
1622
- }));
2251
+ expressionsTail.push(function styleThemeVariants(props) {
2252
+ const theme = props.theme;
2253
+ const themeVariants = theme?.components?.[componentName]?.variants;
2254
+ if (!themeVariants) {
2255
+ return null;
2256
+ }
2257
+ return processStyleVariants(props, themeVariants, [], props.theme.modularCssLayers ? 'theme' : undefined);
1623
2258
  });
1624
2259
  }
1625
2260
  if (!skipSx) {
1626
- expressionsWithDefaultTheme.push(systemSx);
2261
+ expressionsTail.push(styleFunctionSx);
1627
2262
  }
1628
- const numOfCustomFnsApplied = expressionsWithDefaultTheme.length - expressions.length;
1629
- if (Array.isArray(styleArg) && numOfCustomFnsApplied > 0) {
1630
- const placeholders = new Array(numOfCustomFnsApplied).fill('');
1631
- // If the type is array, than we need to add placeholders in the template for the overrides, variants and the sx styles.
1632
- transformedStyleArg = [...styleArg, ...placeholders];
1633
- transformedStyleArg.raw = [...styleArg.raw, ...placeholders];
2263
+
2264
+ // This function can be called as a tagged template, so the first argument would contain
2265
+ // CSS `string[]` values.
2266
+ if (Array.isArray(expressionsBody[0])) {
2267
+ const inputStrings = expressionsBody.shift();
2268
+
2269
+ // We need to add placeholders in the tagged template for the custom functions we have
2270
+ // possibly added (attachTheme, overrides, variants, and sx).
2271
+ const placeholdersHead = new Array(expressionsHead.length).fill('');
2272
+ const placeholdersTail = new Array(expressionsTail.length).fill('');
2273
+ let outputStrings;
2274
+ // prettier-ignore
2275
+ {
2276
+ outputStrings = [...placeholdersHead, ...inputStrings, ...placeholdersTail];
2277
+ outputStrings.raw = [...placeholdersHead, ...inputStrings.raw, ...placeholdersTail];
2278
+ }
2279
+
2280
+ // The only case where we put something before `attachTheme`
2281
+ expressionsHead.unshift(outputStrings);
1634
2282
  }
1635
- const Component = defaultStyledResolver(transformedStyleArg, ...expressionsWithDefaultTheme);
2283
+ const expressions = [...expressionsHead, ...expressionsBody, ...expressionsTail];
2284
+ const Component = defaultStyledResolver(...expressions);
1636
2285
  if (tag.muiName) {
1637
2286
  Component.muiName = tag.muiName;
1638
2287
  }
@@ -1643,41 +2292,78 @@ function createStyled(input = {}) {
1643
2292
  }
1644
2293
  return muiStyledResolver;
1645
2294
  };
2295
+ return styled;
2296
+ }
2297
+ function generateStyledLabel(componentName, componentSlot) {
2298
+ let label;
2299
+ return label;
2300
+ }
2301
+ function isObjectEmpty(object) {
2302
+ // eslint-disable-next-line
2303
+ for (const _ in object) {
2304
+ return false;
2305
+ }
2306
+ return true;
2307
+ }
2308
+
2309
+ // https://github.com/emotion-js/emotion/blob/26ded6109fcd8ca9875cc2ce4564fee678a3f3c5/packages/styled/src/utils.js#L40
2310
+ function isStringTag(tag) {
2311
+ return typeof tag === 'string' &&
2312
+ // 96 is one less than the char code
2313
+ // for "a" so this is checking that
2314
+ // it's a lowercase character
2315
+ tag.charCodeAt(0) > 96;
2316
+ }
2317
+ function lowercaseFirstLetter(string) {
2318
+ if (!string) {
2319
+ return string;
2320
+ }
2321
+ return string.charAt(0).toLowerCase() + string.slice(1);
1646
2322
  }
1647
2323
 
1648
2324
  const styled = createStyled();
1649
2325
 
1650
2326
  /**
1651
2327
  * Add keys, values of `defaultProps` that does not exist in `props`
1652
- * @param {object} defaultProps
1653
- * @param {object} props
1654
- * @returns {object} resolved props
2328
+ * @param defaultProps
2329
+ * @param props
2330
+ * @returns resolved props
1655
2331
  */
1656
2332
  function resolveProps(defaultProps, props) {
1657
- const output = _extends({}, props);
1658
- Object.keys(defaultProps).forEach(propName => {
1659
- if (propName.toString().match(/^(components|slots)$/)) {
1660
- output[propName] = _extends({}, defaultProps[propName], output[propName]);
1661
- } else if (propName.toString().match(/^(componentsProps|slotProps)$/)) {
1662
- const defaultSlotProps = defaultProps[propName] || {};
1663
- const slotProps = props[propName];
1664
- output[propName] = {};
1665
- if (!slotProps || !Object.keys(slotProps)) {
1666
- // Reduce the iteration if the slot props is empty
1667
- output[propName] = defaultSlotProps;
1668
- } else if (!defaultSlotProps || !Object.keys(defaultSlotProps)) {
1669
- // Reduce the iteration if the default slot props is empty
1670
- output[propName] = slotProps;
1671
- } else {
1672
- output[propName] = _extends({}, slotProps);
1673
- Object.keys(defaultSlotProps).forEach(slotPropName => {
1674
- output[propName][slotPropName] = resolveProps(defaultSlotProps[slotPropName], slotProps[slotPropName]);
1675
- });
2333
+ const output = {
2334
+ ...props
2335
+ };
2336
+ for (const key in defaultProps) {
2337
+ if (Object.prototype.hasOwnProperty.call(defaultProps, key)) {
2338
+ const propName = key;
2339
+ if (propName === 'components' || propName === 'slots') {
2340
+ output[propName] = {
2341
+ ...defaultProps[propName],
2342
+ ...output[propName]
2343
+ };
2344
+ } else if (propName === 'componentsProps' || propName === 'slotProps') {
2345
+ const defaultSlotProps = defaultProps[propName];
2346
+ const slotProps = props[propName];
2347
+ if (!slotProps) {
2348
+ output[propName] = defaultSlotProps || {};
2349
+ } else if (!defaultSlotProps) {
2350
+ output[propName] = slotProps;
2351
+ } else {
2352
+ output[propName] = {
2353
+ ...slotProps
2354
+ };
2355
+ for (const slotKey in defaultSlotProps) {
2356
+ if (Object.prototype.hasOwnProperty.call(defaultSlotProps, slotKey)) {
2357
+ const slotPropName = slotKey;
2358
+ output[propName][slotPropName] = resolveProps(defaultSlotProps[slotPropName], slotProps[slotPropName]);
2359
+ }
2360
+ }
2361
+ }
2362
+ } else if (output[propName] === undefined) {
2363
+ output[propName] = defaultProps[propName];
1676
2364
  }
1677
- } else if (output[propName] === undefined) {
1678
- output[propName] = defaultProps[propName];
1679
2365
  }
1680
- });
2366
+ }
1681
2367
  return output;
1682
2368
  }
1683
2369
 
@@ -1703,37 +2389,67 @@ function useThemeProps({
1703
2389
  if (themeId) {
1704
2390
  theme = theme[themeId] || theme;
1705
2391
  }
1706
- const mergedProps = getThemeProps({
2392
+ return getThemeProps({
1707
2393
  theme,
1708
2394
  name,
1709
2395
  props
1710
2396
  });
1711
- return mergedProps;
1712
2397
  }
1713
2398
 
2399
+ /* eslint no-restricted-syntax: 0, prefer-template: 0, guard-for-in: 0
2400
+ ---
2401
+ These rules are preventing the performance optimizations below.
2402
+ */
2403
+
2404
+ /**
2405
+ * Compose classes from multiple sources.
2406
+ *
2407
+ * @example
2408
+ * ```tsx
2409
+ * const slots = {
2410
+ * root: ['root', 'primary'],
2411
+ * label: ['label'],
2412
+ * };
2413
+ *
2414
+ * const getUtilityClass = (slot) => `MuiButton-${slot}`;
2415
+ *
2416
+ * const classes = {
2417
+ * root: 'my-root-class',
2418
+ * };
2419
+ *
2420
+ * const output = composeClasses(slots, getUtilityClass, classes);
2421
+ * // {
2422
+ * // root: 'MuiButton-root MuiButton-primary my-root-class',
2423
+ * // label: 'MuiButton-label',
2424
+ * // }
2425
+ * ```
2426
+ *
2427
+ * @param slots a list of classes for each possible slot
2428
+ * @param getUtilityClass a function to resolve the class based on the slot name
2429
+ * @param classes the input classes from props
2430
+ * @returns the resolved classes for all slots
2431
+ */
1714
2432
  function composeClasses(slots, getUtilityClass, classes = undefined) {
1715
2433
  const output = {};
1716
- Object.keys(slots).forEach(
1717
- // `Object.keys(slots)` can't be wider than `T` because we infer `T` from `slots`.
1718
- // @ts-expect-error https://github.com/microsoft/TypeScript/pull/12253#issuecomment-263132208
1719
- slot => {
1720
- output[slot] = slots[slot].reduce((acc, key) => {
1721
- if (key) {
1722
- const utilityClass = getUtilityClass(key);
1723
- if (utilityClass !== '') {
1724
- acc.push(utilityClass);
1725
- }
1726
- if (classes && classes[key]) {
1727
- acc.push(classes[key]);
2434
+ for (const slotName in slots) {
2435
+ const slot = slots[slotName];
2436
+ let buffer = '';
2437
+ let start = true;
2438
+ for (let i = 0; i < slot.length; i += 1) {
2439
+ const value = slot[i];
2440
+ if (value) {
2441
+ buffer += (start === true ? '' : ' ') + getUtilityClass(value);
2442
+ start = false;
2443
+ if (classes && classes[value]) {
2444
+ buffer += ' ' + classes[value];
1728
2445
  }
1729
2446
  }
1730
- return acc;
1731
- }, []).join(' ');
1732
- });
2447
+ }
2448
+ output[slotName] = buffer;
2449
+ }
1733
2450
  return output;
1734
2451
  }
1735
2452
 
1736
- const _excluded = ["component", "direction", "spacing", "divider", "children", "className", "useFlexGap"];
1737
2453
  const defaultTheme = createTheme();
1738
2454
  // widening Theme to any so that the consumer can own the theme structure.
1739
2455
  const defaultCreateStyledComponent = styled('div', {
@@ -1761,7 +2477,7 @@ function joinChildren(children, separator) {
1761
2477
  return childrenArray.reduce((output, child, index) => {
1762
2478
  output.push(child);
1763
2479
  if (index < childrenArray.length - 1) {
1764
- output.push( /*#__PURE__*/React.cloneElement(separator, {
2480
+ output.push(/*#__PURE__*/React.cloneElement(separator, {
1765
2481
  key: `separator-${index}`
1766
2482
  }));
1767
2483
  }
@@ -1780,17 +2496,18 @@ const style = ({
1780
2496
  ownerState,
1781
2497
  theme
1782
2498
  }) => {
1783
- let styles = _extends({
2499
+ let styles = {
1784
2500
  display: 'flex',
1785
- flexDirection: 'column'
1786
- }, handleBreakpoints({
1787
- theme
1788
- }, resolveBreakpointValues({
1789
- values: ownerState.direction,
1790
- breakpoints: theme.breakpoints.values
1791
- }), propValue => ({
1792
- flexDirection: propValue
1793
- })));
2501
+ flexDirection: 'column',
2502
+ ...handleBreakpoints({
2503
+ theme
2504
+ }, resolveBreakpointValues({
2505
+ values: ownerState.direction,
2506
+ breakpoints: theme.breakpoints.values
2507
+ }), propValue => ({
2508
+ flexDirection: propValue
2509
+ }))
2510
+ };
1794
2511
  if (ownerState.spacing) {
1795
2512
  const transformer = createUnarySpacing(theme);
1796
2513
  const base = Object.keys(theme.breakpoints.values).reduce((acc, breakpoint) => {
@@ -1858,29 +2575,29 @@ function createStack(options = {}) {
1858
2575
  const themeProps = useThemeProps(inProps);
1859
2576
  const props = extendSxProp(themeProps); // `color` type conflicts with html color attribute.
1860
2577
  const {
1861
- component = 'div',
1862
- direction = 'column',
1863
- spacing = 0,
1864
- divider,
1865
- children,
1866
- className,
1867
- useFlexGap = false
1868
- } = props,
1869
- other = _objectWithoutPropertiesLoose(props, _excluded);
2578
+ component = 'div',
2579
+ direction = 'column',
2580
+ spacing = 0,
2581
+ divider,
2582
+ children,
2583
+ className,
2584
+ useFlexGap = false,
2585
+ ...other
2586
+ } = props;
1870
2587
  const ownerState = {
1871
2588
  direction,
1872
2589
  spacing,
1873
2590
  useFlexGap
1874
2591
  };
1875
2592
  const classes = useUtilityClasses();
1876
- return /*#__PURE__*/jsx(StackRoot, _extends({
2593
+ return /*#__PURE__*/jsx(StackRoot, {
1877
2594
  as: component,
1878
2595
  ownerState: ownerState,
1879
2596
  ref: ref,
1880
- className: clsx(classes.root, className)
1881
- }, other, {
2597
+ className: clsx(classes.root, className),
2598
+ ...other,
1882
2599
  children: divider ? joinChildren(children, divider) : children
1883
- }));
2600
+ });
1884
2601
  });
1885
2602
  return Stack;
1886
2603
  }
@@ -1899,26 +2616,58 @@ function createStack(options = {}) {
1899
2616
  */
1900
2617
  const Stack = createStack();
1901
2618
 
2619
+ const StyledCardContent = styled$2('div')((p) => ({
2620
+ [p.theme.breakpoints.up('xs')]: {
2621
+ padding: p.theme.spacing(1),
2622
+ flex: '1 0 auto',
2623
+ '&:last-child': { paddingBottom: 0 },
2624
+ overflow: 'hidden',
2625
+ },
2626
+ }));
2627
+ /**
2628
+ * Component that displays the title and subtitle of a thumbnail list item.
2629
+ * Text is automatically truncated with ellipsis when it exceeds the available space.
2630
+ * The number of visible lines adjusts based on screen size.
2631
+ *
2632
+ * @param {Object} props - Component props
2633
+ * @param {string} props.title - Primary title text displayed in bold
2634
+ * @param {ReactNode} props.subTitle - Secondary text displayed below the title
2635
+ * @returns {JSX.Element} The rendered title section with ellipsis overflow handling
2636
+ */
1902
2637
  function ThumbnailListItemTitle(props) {
1903
- const StyledCardContent = styled$2('div')((p) => ({
1904
- [p.theme.breakpoints.up('xs')]: {
1905
- padding: p.theme.spacing(1),
1906
- flex: '1 0 auto',
1907
- '&:last-child': { paddingBottom: 0 },
1908
- overflow: 'hidden',
1909
- },
1910
- }));
1911
- return (jsx(Fragment, { children: jsx(Box, { children: jsxs(StyledCardContent, { children: [jsx(EllipsisContainer, { lineClamp: { xs: 1, sm: 2 }, children: jsx(Typography, { variant: "subtitle2", sx: { fontWeight: 'bold' }, children: props.title }) }), jsx(Stack, { direction: "row", gap: 1, children: jsx(EllipsisContainer, { lineClamp: { xs: 1, sm: 2 }, children: jsx(Typography, { variant: "subtitle2", sx: { fontSize: '0.84rem' }, color: "text.secondary", children: props.subTitle }) }) })] }) }) }));
2638
+ return (jsx(Box, { children: jsxs(StyledCardContent, { children: [jsx(EllipsisContainer, { lineClamp: { xs: 1, sm: 2 }, children: jsx(Typography, { variant: "subtitle2", sx: { fontWeight: 'bold' }, children: props.title }) }), jsx(Stack, { direction: "row", gap: 1, children: jsx(EllipsisContainer, { lineClamp: { xs: 1, sm: 2 }, children: jsx(Typography, { variant: "subtitle2", sx: { fontSize: '0.84rem' }, color: "text.secondary", children: props.subTitle }) }) })] }) }));
1912
2639
  }
1913
2640
 
1914
- const ThumbnailListItem = (props) => {
1915
- return (jsx(Fragment, { children: jsx(Card, { sx: { display: 'flex' }, children: jsx(CardActionArea, { disabled: !props.onClick, onClick: () => props.onClick(props.id), children: jsxs(Stack$1, { direction: "row", width: "100%", children: [jsx("img", { src: props.thumbnailUrl, width: '45%' }), jsxs(Stack$1, { direction: "row", justifyContent: "space-between", width: "100%", gap: 1, children: [jsx(ThumbnailListItemTitle, { title: props.title, subTitle: props.subTitle }), props.infoLabel] })] }) }) }) }));
2641
+ /**
2642
+ * Width percentage for thumbnail image in list items.
2643
+ * Value based on golden ratio proportion for optimal visual balance.
2644
+ */
2645
+ const THUMBNAIL_IMAGE_WIDTH = '38.2%';
2646
+ /**
2647
+ * Individual thumbnail list item component displaying an image, title, subtitle, and optional label.
2648
+ * The component is memoized to prevent unnecessary re-renders.
2649
+ *
2650
+ * @param {ThumbnailListItemProps} props - Component props
2651
+ * @param {string} props.id - Unique identifier for the item
2652
+ * @param {string} props.thumbnailUrl - URL of the thumbnail image
2653
+ * @param {string} props.title - Primary title text
2654
+ * @param {ReactNode} props.subTitle - Secondary text displayed below title
2655
+ * @param {ReactNode} props.infoLabel - Additional label content displayed on the right
2656
+ * @param {function} [props.onClick] - Optional click handler that receives the item id
2657
+ * @returns {JSX.Element} The rendered thumbnail item as a Material-UI Card
2658
+ */
2659
+ const ThumbnailListItem$1 = (props) => {
2660
+ return (jsx(Card, { sx: { display: 'flex' }, children: jsx(CardActionArea, { disabled: !props.onClick, onClick: props.onClick ? () => props.onClick(props.id) : undefined, "aria-label": props.onClick ? `View ${props.title}` : undefined, children: jsxs(Stack$1, { direction: "row", width: "100%", children: [jsx(Box, { component: "img", src: props.thumbnailUrl, width: THUMBNAIL_IMAGE_WIDTH, alt: props.title, sx: { objectFit: 'cover', height: '100%' } }), jsxs(Stack$1, { direction: "row", justifyContent: "space-between", flex: 1, gap: 1, children: [jsx(ThumbnailListItemTitle, { title: props.title, subTitle: props.subTitle }), props.infoLabel] })] }) }) }));
1916
2661
  };
1917
- var ThumbnailListItem$1 = React__default.memo(ThumbnailListItem);
2662
+ var ThumbnailListItem = React__default.memo(ThumbnailListItem$1);
1918
2663
 
2664
+ /**
2665
+ * Padding percentage used to create responsive card height with fixed aspect ratio.
2666
+ * This percentage ensures consistent card dimensions across different screen sizes.
2667
+ */
2668
+ const CARD_ASPECT_RATIO_PADDING = '27.75%';
1919
2669
  const RatioWrapper = styled$2('div')(() => ({
1920
- // Assuming a 16:9 aspect ratio
1921
- paddingTop: '27.75%', // 9 / 16 = 0.5625
2670
+ paddingTop: CARD_ASPECT_RATIO_PADDING,
1922
2671
  position: 'relative',
1923
2672
  width: '100%',
1924
2673
  '& > *': {
@@ -1929,17 +2678,30 @@ const RatioWrapper = styled$2('div')(() => ({
1929
2678
  bottom: 0,
1930
2679
  },
1931
2680
  }));
1932
- function ThumbnailListMainContent(props) {
2681
+ /**
2682
+ * Main content area that displays the grid of thumbnail items.
2683
+ * Handles responsive layout with Material-UI Grid and shows a loading indicator.
2684
+ *
2685
+ * @param {ThumbnailListMainContentProps} props - Component props
2686
+ * @param {BreakpointType} [props.muiBreakpoints={ xs: 12, sm: 6, md: 6, lg: 4, xl: 3 }] - Grid column spans for different screen sizes
2687
+ * @param {number} [props.spacing=2] - Spacing between grid items
2688
+ * @returns {JSX.Element} The rendered grid of thumbnail items with loading indicator
2689
+ *
2690
+ * @example
2691
+ * ```tsx
2692
+ * <ThumbnailList.MainContent
2693
+ * spacing={3}
2694
+ * muiBreakpoints={{ xs: 12, sm: 6, md: 4, lg: 3, xl: 2 }}
2695
+ * />
2696
+ * ```
2697
+ */
2698
+ function ThumbnailListMainContent({ spacing = 2, muiBreakpoints = { xs: 12, sm: 6, md: 6, lg: 4, xl: 3 }, }) {
1933
2699
  const { items, isLoading } = useThumbnailListItemContext();
1934
2700
  const memoizedItems = useMemo(() => {
1935
- return items.map((item) => (jsx(Grid, { item: true, xs: props.muiBreakpoints.xs, sm: props.muiBreakpoints.sm, md: props.muiBreakpoints.md, lg: props.muiBreakpoints.lg, xl: props.muiBreakpoints.xl, children: jsx(RatioWrapper, { children: jsx(ThumbnailListItem$1, { id: item.id, thumbnailUrl: item.thumbnailUrl, title: item.title, subTitle: item.subTitle, infoLabel: item.label, onClick: item.onClick }) }) }, item.id)));
1936
- }, [items, props.muiBreakpoints]);
1937
- return (jsxs(Fragment, { children: [jsx(Box, { sx: { mt: 0.75, mb: 0.75 }, children: jsx(LinearProgress, { sx: { opacity: isLoading ? 1 : 0 } }) }), jsx(Grid, { container: true, spacing: props.spacing, children: memoizedItems })] }));
2701
+ return items.map((item) => (jsx(Grid, { item: true, xs: muiBreakpoints.xs, sm: muiBreakpoints.sm, md: muiBreakpoints.md, lg: muiBreakpoints.lg, xl: muiBreakpoints.xl, children: jsx(RatioWrapper, { children: jsx(ThumbnailListItem, { id: item.id, thumbnailUrl: item.thumbnailUrl, title: item.title, subTitle: item.subTitle, infoLabel: item.label, onClick: item.onClick }) }) }, item.id)));
2702
+ }, [items, muiBreakpoints]);
2703
+ return (jsxs(Fragment, { children: [jsx(Box, { sx: { mt: 0.75, mb: 0.75 }, children: jsx(LinearProgress, { sx: { opacity: isLoading ? 1 : 0 } }) }), jsx(Grid, { container: true, spacing: spacing, children: memoizedItems })] }));
1938
2704
  }
1939
- ThumbnailListMainContent.defaultProps = {
1940
- spacing: 2,
1941
- muiBreakpoints: { xs: 12, sm: 6, md: 6, lg: 4, xl: 3 },
1942
- };
1943
2705
 
1944
2706
  /**
1945
2707
  * Generic method that sorts an array of items based on an item key
@@ -1970,14 +2732,48 @@ function compareValues(a, b) {
1970
2732
  return a < b ? -1 : a > b ? 1 : 0;
1971
2733
  }
1972
2734
  }
2735
+ /**
2736
+ * Filters an array of items based on a tag property and optional condition function.
2737
+ * If no condition is provided, items are filtered based on the truthiness of the tag value.
2738
+ *
2739
+ * @template T - The type of items in the array
2740
+ * @param {T[]} array - The array to filter
2741
+ * @param {keyof T} tagType - The property key to use for filtering
2742
+ * @param {ConditionFunction<T[keyof T]>} [condition] - Optional condition function to apply to tag values
2743
+ * @returns {T[]} A new array containing only items that pass the filter
2744
+ */
1973
2745
  function filterByTag(array, tagType, condition) {
1974
2746
  const filteredArray = array.filter((item) => {
1975
2747
  const tagValue = item[tagType];
1976
2748
  return condition ? condition(tagValue) : !!tagValue;
1977
2749
  });
1978
- return [...filteredArray];
2750
+ return filteredArray;
1979
2751
  }
1980
2752
 
2753
+ /**
2754
+ * React hook that filters thumbnail list items based on a tag property and optional condition.
2755
+ * Special case: when tag is 'id', returns all items without filtering.
2756
+ *
2757
+ * @template T - The type of items in the array
2758
+ * @param {UseTagFilteredThumbnailListItemsProps<T>} props - Hook configuration
2759
+ * @param {T[]} props.allItems - Array of all items to filter
2760
+ * @param {string} props.initialTag - Initial property key to filter by
2761
+ * @param {ConditionFunction<T[keyof T]>} [props.initialCondition] - Optional initial filter condition
2762
+ * @returns {Object} Hook return values
2763
+ * @returns {Object} returns.tagAndCondition - Current tag and condition configuration
2764
+ * @returns {function} returns.setTagAndCondition - Function to update both tag and condition
2765
+ * @returns {T[]} returns.tagFilteredItems - Filtered array of items
2766
+ * @returns {function} returns.setTagWithCondition - Helper function to set tag with condition
2767
+ *
2768
+ * @example
2769
+ * ```tsx
2770
+ * const { tagFilteredItems, setTagAndCondition } = useTagFilteredThumbnailListItems({
2771
+ * allItems: items,
2772
+ * initialTag: 'status',
2773
+ * initialCondition: (val) => val === 'active'
2774
+ * });
2775
+ * ```
2776
+ */
1981
2777
  const useTagFilteredThumbnailListItems = ({ allItems, initialTag, initialCondition, }) => {
1982
2778
  const [tagAndCondition, setTagAndCondition] = useState({ tag: initialTag, condition: initialCondition });
1983
2779
  const setTagWithCondition = (t, c) => {
@@ -1998,33 +2794,68 @@ const useTagFilteredThumbnailListItems = ({ allItems, initialTag, initialConditi
1998
2794
  };
1999
2795
 
2000
2796
  /**
2001
- * Filters a list of event by a search term
2002
- * @param allEvents event list that will be formatted
2003
- * @param initialSearchTerm
2004
- * @returns
2797
+ * React hook that filters thumbnail list items based on a search term.
2798
+ * Performs case-insensitive search against item titles and memoizes results for performance.
2799
+ *
2800
+ * @param {ThumbnailListItemInterface[]} allItems - Array of all items to filter
2801
+ * @param {string} [initialSearchTerm=''] - Initial search term value
2802
+ * @returns {Object} Hook return values
2803
+ * @returns {string} returns.searchTerm - Current search term
2804
+ * @returns {function} returns.setSearchTerm - Function to update the search term
2805
+ * @returns {ThumbnailListItemInterface[]} returns.filteredItems - Items matching the search term
2806
+ *
2807
+ * @example
2808
+ * ```tsx
2809
+ * const { searchTerm, setSearchTerm, filteredItems } = useFilteredThumbnailListItems(items);
2810
+ * ```
2005
2811
  */
2006
2812
  const useFilteredThumbnailListItems = (allItems, initialSearchTerm = '') => {
2007
2813
  const [searchTerm, setSearchTerm] = useState(initialSearchTerm);
2008
2814
  const filteredItems = useMemo(() => {
2009
- const filtered = [...allItems].filter((item) => item.title.toLowerCase().includes(searchTerm.toLowerCase()));
2815
+ const filtered = allItems.filter((item) => item.title.toLowerCase().includes(searchTerm.toLowerCase()));
2010
2816
  return filtered;
2011
2817
  }, [allItems, searchTerm]);
2012
2818
  return { searchTerm, setSearchTerm, filteredItems };
2013
2819
  };
2014
2820
 
2821
+ /**
2822
+ * React hook that provides sorting functionality for thumbnail list items.
2823
+ * Sorts items by a specified property key and supports ascending/descending order.
2824
+ *
2825
+ * @template T - The type of items in the array
2826
+ * @param {T[]} allItems - Array of all items to sort
2827
+ * @param {string} initialSortBy - Initial property key to sort by
2828
+ * @param {boolean} initialSortAscending - Whether to initially sort in ascending order
2829
+ * @returns {Object} Hook return values
2830
+ * @returns {string} returns.sortBy - Current sort property key
2831
+ * @returns {boolean} returns.sortAscending - Current sort direction (true for ascending)
2832
+ * @returns {function} returns.setSortBy - Function to change the sort property
2833
+ * @returns {function} returns.setSortAscending - Function to change the sort direction
2834
+ * @returns {T[]} returns.sortedItems - Sorted array of items
2835
+ *
2836
+ * @example
2837
+ * ```tsx
2838
+ * const { sortBy, sortAscending, setSortBy, setSortAscending, sortedItems } =
2839
+ * useSortedThumbnailListItems(items, 'title', true);
2840
+ * ```
2841
+ */
2015
2842
  const useSortedThumbnailListItems = (allItems, initialSortBy, initialSortAscending) => {
2016
2843
  const [sortBy, setSortBy] = useState(initialSortBy);
2017
2844
  const [sortAscending, setSortAscending] = useState(initialSortAscending);
2018
2845
  const sortedItems = useMemo(() => {
2019
2846
  let sorted = orderByArray(allItems, sortBy);
2020
2847
  if (!sortAscending) {
2021
- sorted = sorted.reverse();
2848
+ sorted = [...sorted].reverse();
2022
2849
  }
2023
2850
  return sorted;
2024
2851
  }, [allItems, sortBy, sortAscending]);
2025
2852
  return { sortBy, sortAscending, setSortBy, setSortAscending, sortedItems };
2026
2853
  };
2027
2854
 
2855
+ /**
2856
+ * Default configuration values for ThumbnailList.
2857
+ * Items are sorted by 'id' in ascending order by default.
2858
+ */
2028
2859
  const defaultConfiguration = {
2029
2860
  sortBy: 'id',
2030
2861
  sortAscending: true,
@@ -2043,7 +2874,7 @@ var lodash = {exports: {}};
2043
2874
  */
2044
2875
  lodash.exports;
2045
2876
 
2046
- (function (module, exports) {
2877
+ (function (module, exports$1) {
2047
2878
  (function() {
2048
2879
 
2049
2880
  /** Used as a safe reference for `undefined` in pre-ES5 environments. */
@@ -2474,7 +3305,7 @@ lodash.exports;
2474
3305
  var root = freeGlobal || freeSelf || Function('return this')();
2475
3306
 
2476
3307
  /** Detect free variable `exports`. */
2477
- var freeExports = exports && !exports.nodeType && exports;
3308
+ var freeExports = exports$1 && !exports$1.nodeType && exports$1;
2478
3309
 
2479
3310
  /** Detect free variable `module`. */
2480
3311
  var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
@@ -7489,7 +8320,7 @@ lodash.exports;
7489
8320
  bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
7490
8321
 
7491
8322
  if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
7492
- bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
8323
+ bitmask &= -4;
7493
8324
  }
7494
8325
  var newData = [
7495
8326
  func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
@@ -7592,7 +8423,7 @@ lodash.exports;
7592
8423
  }
7593
8424
  var length = partials ? partials.length : 0;
7594
8425
  if (!length) {
7595
- bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
8426
+ bitmask &= -97;
7596
8427
  partials = holders = undefined$1;
7597
8428
  }
7598
8429
  ary = ary === undefined$1 ? ary : nativeMax(toInteger(ary), 0);
@@ -7625,7 +8456,7 @@ lodash.exports;
7625
8456
  : nativeMax(newData[9] - length, 0);
7626
8457
 
7627
8458
  if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
7628
- bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
8459
+ bitmask &= -25;
7629
8460
  }
7630
8461
  if (!bitmask || bitmask == WRAP_BIND_FLAG) {
7631
8462
  var result = createBind(func, bitmask, thisArg);
@@ -19235,91 +20066,166 @@ lodash.exports;
19235
20066
 
19236
20067
  var lodashExports = lodash.exports;
19237
20068
 
19238
- const ThumbnailListSearchField = () => {
20069
+ /**
20070
+ * Search field component for filtering thumbnail list items.
20071
+ * Includes a search icon, text input, and clear button. Search is debounced for performance.
20072
+ * The component is memoized to prevent unnecessary re-renders.
20073
+ *
20074
+ * @returns {JSX.Element} The rendered search field with icons and clear functionality
20075
+ *
20076
+ * @example
20077
+ * ```tsx
20078
+ * <ThumbnailList.Header>
20079
+ * <ThumbnailList.Header.SearchField />
20080
+ * </ThumbnailList.Header>
20081
+ * ```
20082
+ */
20083
+ const ThumbnailListSearchField$1 = () => {
19239
20084
  const [input, setInput] = useState('');
19240
20085
  const [showClearIcon, setShowClearIcon] = useState('hidden');
19241
20086
  const { setSearchTerm } = useThumbnailListItemContext();
20087
+ // Create debounced function that's stable across renders unless setSearchTerm changes
20088
+ const debouncedSetSearchTerm = useMemo(() => lodashExports.debounce((value) => setSearchTerm(value), 250), [setSearchTerm]);
19242
20089
  const handleChange = (value) => {
19243
20090
  setInput(value);
19244
20091
  setShowClearIcon(value === '' ? 'hidden' : '');
19245
20092
  };
19246
- const debouncedSetSearchTerm = useCallback(lodashExports.debounce(setSearchTerm, 50), []);
19247
20093
  useEffect(() => {
19248
20094
  debouncedSetSearchTerm(input);
19249
20095
  return () => {
19250
20096
  debouncedSetSearchTerm.cancel();
19251
20097
  };
19252
20098
  }, [input, debouncedSetSearchTerm]);
19253
- return (jsx(Box, { sx: { marginLeft: 'auto' }, children: jsx(FormControl, { children: jsx(TextField, { fullWidth: true, value: input, size: "small", variant: "outlined", onChange: (event) => handleChange(event.target.value), InputProps: {
20099
+ return (jsx(Box, { sx: { marginLeft: 'auto' }, children: jsx(FormControl, { children: jsx(TextField, { fullWidth: true, value: input, size: "small", variant: "outlined", onChange: (event) => handleChange(event.target.value), "aria-label": "Search thumbnails", InputProps: {
19254
20100
  startAdornment: (jsx(InputAdornment, { position: "start", children: jsx(SearchIcon, {}) })),
19255
- endAdornment: (jsx(InputAdornment, { position: "end", children: jsx(IconButton, { onClick: () => handleChange(''), sx: { visibility: showClearIcon, padding: 0 }, children: jsx(ClearIcon, {}) }) })),
20101
+ endAdornment: (jsx(InputAdornment, { position: "end", children: jsx(IconButton, { onClick: () => handleChange(''), sx: { visibility: showClearIcon, padding: 0 }, "aria-label": "Clear search", children: jsx(ClearIcon, {}) }) })),
19256
20102
  } }) }) }));
19257
20103
  };
19258
- ThumbnailListSearchField.defaultProps = {
19259
- align: 'start',
19260
- };
19261
- var ThumbnailListSearchField$1 = React__default.memo(ThumbnailListSearchField);
20104
+ var ThumbnailListSearchField = React__default.memo(ThumbnailListSearchField$1);
19262
20105
 
20106
+ /**
20107
+ * Individual filter tag component that displays as either a chip or icon button.
20108
+ * Automatically collapses to icon-only view on smaller screens if an icon is provided.
20109
+ *
20110
+ * @param {ThumbnailListFilterTagProps} props - Component props
20111
+ * @param {string} props.label - Display text for the tag
20112
+ * @param {string} props.value - Value passed to the callback when clicked
20113
+ * @param {'filled' | 'outlined'} props.variant - Visual style of the chip (filled for active, outlined for inactive)
20114
+ * @param {Breakpoint} [props.collapseBreakpoint] - Screen size below which the chip shows as an icon
20115
+ * @param {ReactNode} [props.icon] - Optional icon to display in collapsed mode
20116
+ * @param {function} [props.onClickCallback] - Callback function triggered when tag is clicked
20117
+ * @returns {JSX.Element} The rendered filter tag as a Chip or IconButton
20118
+ */
19263
20119
  function ThumbnailListFilterTag(props) {
19264
20120
  const theme = useTheme$2();
20121
+ const isAboveBreakpoint = useMediaQuery(theme.breakpoints.up(props.collapseBreakpoint ?? 0));
19265
20122
  const handleOnClick = (value) => {
19266
20123
  if (props.onClickCallback) {
19267
20124
  props.onClickCallback(value);
19268
20125
  }
19269
20126
  };
19270
- return (jsx(Fragment, { children: useMediaQuery(theme.breakpoints.up(props.collapseBreakpoint ?? 0)) || !props.icon ? (jsx(Fragment, { children: jsx(Chip, { label: props.label, variant: props.variant, onClick: props.onClickCallback ? () => handleOnClick(props.value) : undefined }) })) : (jsx(Fragment, { children: jsx(Tooltip, { title: props.label, children: jsx(IconButton, { onClick: props.onClickCallback ? () => handleOnClick(props.value) : undefined, children: props.icon }) }) })) }));
20127
+ return isAboveBreakpoint || !props.icon ? (jsx(Chip, { label: props.label, variant: props.variant, onClick: props.onClickCallback ? () => handleOnClick(props.value) : undefined })) : (jsx(Tooltip, { title: props.label, children: jsx(IconButton, { onClick: props.onClickCallback ? () => handleOnClick(props.value) : undefined, children: props.icon }) }));
19271
20128
  }
19272
20129
 
19273
- function ThumbnailListFilterTags(props) {
20130
+ /**
20131
+ * Container component that renders multiple filter tag buttons.
20132
+ * Each tag can filter items based on a specific property and optional condition function.
20133
+ *
20134
+ * @template T - The type of items in the list
20135
+ * @param {ThumbnailListFilterTagsProps<T>} props - Component props
20136
+ * @param {ThumbnailListItemTagType<T>[]} props.tags - Array of tag configurations
20137
+ * @param {Breakpoint} [props.muiCollapseBreakpoint='md'] - Breakpoint at which tags collapse to icons
20138
+ * @returns {JSX.Element} The rendered collection of filter tags
20139
+ *
20140
+ * @example
20141
+ * ```tsx
20142
+ * <ThumbnailList.Header.FilterTags
20143
+ * tags={[
20144
+ * { label: 'Active', key: 'status', condition: (val) => val === 'active' },
20145
+ * { label: 'Archived', key: 'status', condition: (val) => val === 'archived' }
20146
+ * ]}
20147
+ * />
20148
+ * ```
20149
+ */
20150
+ function ThumbnailListFilterTags({ tags, muiCollapseBreakpoint = 'md', }) {
19274
20151
  const { tagFilterCallback, tagAndCondition } = useThumbnailListItemContext();
19275
- return (jsx(Fragment, { children: props.tags.map((tag, index) => {
19276
- return (jsx(ThumbnailListFilterTag, { label: tag.label, value: tag.key.toString(), variant: tagAndCondition.tag === tag.key ? 'filled' : 'outlined', collapseBreakpoint: props.muiCollapseBreakpoint, onClickCallback: (value) => tagFilterCallback({ tag: value, condition: tag.condition }), icon: tag.icon }, `${index}_${tag.key.toString()}`));
20152
+ return (jsx(Fragment, { children: tags.map((tag, index) => {
20153
+ const isActive = tagAndCondition.tag === tag.key.toString() && tagAndCondition.condition === tag.condition;
20154
+ return (jsx(ThumbnailListFilterTag, { label: tag.label, value: tag.key.toString(), variant: isActive ? 'filled' : 'outlined', collapseBreakpoint: muiCollapseBreakpoint, onClickCallback: (value) => tagFilterCallback({ tag: value, condition: tag.condition }), icon: tag.icon }, `${index}_${tag.key.toString()}`));
19277
20155
  }) }));
19278
20156
  }
19279
- ThumbnailListFilterTags.defaultProps = {
19280
- align: 'start',
19281
- muiCollapseBreakpoint: 'md',
19282
- };
19283
20157
 
19284
20158
  /**
19285
20159
  * Displays a generic MUI select dropdown.
19286
- * Optinal collapses to a sort icon at a certain breakpoint
20160
+ * Optional collapses to a sort icon at a certain breakpoint
19287
20161
  * @param props.label Select Label
19288
20162
  * @param props.width * Width of the input field
19289
20163
  * @param props.collapseBreakPoint * MUI breakpoint after that the select will collapse to the sort icon
19290
20164
  * @param props.onChangeCallback * Callback function that gets triggered once a item is selected
19291
20165
  * @param props.items * Array of items (name-value-pairs) that will be the select options
19292
- * @returns Drowpdown Input Component
20166
+ * @returns Dropdown Input Component
19293
20167
  */
19294
20168
  function DropdownInput(props) {
19295
20169
  const [value, setValue] = useState(props.defaultValue ?? '');
19296
20170
  const theme = useTheme$2();
20171
+ const isAboveBreakpoint = useMediaQuery(theme.breakpoints.up(props.collapseBreakpoint ?? 0));
19297
20172
  const [anchorEl, setAnchorEl] = useState(null);
19298
20173
  const handleChange = (value, name) => {
19299
20174
  setValue(value);
19300
20175
  setAnchorEl(null);
19301
20176
  props.onChangeCallback(value, name);
19302
20177
  };
19303
- return (jsxs(Fragment, { children: [useMediaQuery(theme.breakpoints.up(props.collapseBreakpoint ?? 0)) ? (jsxs(FormControl, { sx: { width: props.width, textAlign: 'start' }, children: [jsx(InputLabel, { size: "small", children: props.label }), jsx(Select, { value: value, size: "small", label: props.label, onChange: (event) => handleChange(event.target.value, event.target.name), children: props.items.map((item) => {
20178
+ return (jsxs(Fragment, { children: [isAboveBreakpoint ? (jsxs(FormControl, { sx: { width: props.width, textAlign: 'start' }, children: [jsx(InputLabel, { size: "small", children: props.label }), jsx(Select, { value: value, size: "small", label: props.label, onChange: (event) => handleChange(event.target.value, event.target.name), children: props.items.map((item) => {
19304
20179
  return (jsx(MenuItem, { value: item.value, children: item.name }, item.value));
19305
- }) })] })) : (jsx(IconButton
19306
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19307
- , {
19308
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
19309
- onClick: (event) => setAnchorEl(event.currentTarget), children: props.icon })), jsx(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => setAnchorEl(null), children: props.items.map((item) => (jsx(MenuItem, { onClick: () => handleChange(item.value), children: item.name }, item.value))) })] }));
20180
+ }) })] })) : (jsx(IconButton, { onClick: (event) => setAnchorEl(event.currentTarget), children: props.icon })), jsx(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => setAnchorEl(null), children: props.items.map((item) => (jsx(MenuItem, { onClick: () => handleChange(item.value), children: item.name }, item.value))) })] }));
19310
20181
  }
19311
20182
 
19312
- function ThumbnailListHeaderSort(props) {
20183
+ /**
20184
+ * Sort control component that provides sorting functionality for the thumbnail list.
20185
+ * Includes a toggle button for ascending/descending order and a dropdown to select the sort field.
20186
+ *
20187
+ * @template T - The type of items in the list
20188
+ * @param {ThumbnailListHeaderSortProps<T>} props - Component props
20189
+ * @param {Array<{label: string, key: keyof T}>} props.items - Array of sortable field options
20190
+ * @param {Breakpoint} [props.muiBreakpoint='md'] - Breakpoint at which the dropdown collapses to an icon
20191
+ * @returns {JSX.Element} The rendered sort controls with ascending/descending toggle and field selector
20192
+ *
20193
+ * @example
20194
+ * ```tsx
20195
+ * <ThumbnailList.Header.Sort
20196
+ * items={[
20197
+ * { label: 'Title', key: 'title' },
20198
+ * { label: 'Date', key: 'date' }
20199
+ * ]}
20200
+ * />
20201
+ * ```
20202
+ */
20203
+ function ThumbnailListHeaderSort({ items, muiBreakpoint = 'md', }) {
19313
20204
  const { setSortAscending, sortAscending, setSortBy, sortBy } = useThumbnailListItemContext();
19314
- return (jsx(Fragment, { children: jsxs(Box, { sx: { minWidth: '80px' }, children: [jsx(Tooltip, { title: "asc/desc", children: jsx(IconButton, { onClick: () => setSortAscending(!sortAscending), children: jsx(SwapVertIcon, {}) }) }), jsx(DropdownInput, { width: "130px", collapseBreakpoint: props.muiBreakpoint, label: 'sort', defaultValue: sortBy, icon: jsx(Tooltip, { title: 'sort', children: jsx(SortIcon, {}) }), items: props.items.map((i) => {
20205
+ return (jsx(Fragment, { children: jsxs(Box, { sx: { minWidth: '80px' }, children: [jsx(Tooltip, { title: "asc/desc", children: jsx(IconButton, { onClick: () => setSortAscending(!sortAscending), "aria-label": sortAscending ? "Sort descending" : "Sort ascending", children: jsx(SwapVertIcon, {}) }) }), jsx(DropdownInput, { width: "130px", collapseBreakpoint: muiBreakpoint, label: 'sort', defaultValue: sortBy, icon: jsx(Tooltip, { title: 'sort', children: jsx(SortIcon, {}) }), items: items.map((i) => {
19315
20206
  return { name: i.label, value: i.key.toString() };
19316
20207
  }), onChangeCallback: (value) => setSortBy(value) })] }) }));
19317
20208
  }
19318
- ThumbnailListHeaderSort.defaultProps = {
19319
- align: 'start',
19320
- muiBreakpoint: 'md',
19321
- };
19322
20209
 
20210
+ /**
20211
+ * Header component for the ThumbnailList that arranges child components horizontally.
20212
+ * Child components can be aligned to 'start' or 'end' using their align prop.
20213
+ *
20214
+ * This component uses a compound component pattern with SearchField, FilterTags, and Sort sub-components.
20215
+ *
20216
+ * @param {ThumbnailListHeaderProps} props - Component props
20217
+ * @param {ReactNode} props.children - Child components to display in the header
20218
+ * @param {'start' | 'center' | 'end' | 'space-between'} [props.justifyContent='space-between'] - Flex justification for header layout
20219
+ * @returns {JSX.Element} The rendered header component
20220
+ *
20221
+ * @example
20222
+ * ```tsx
20223
+ * <ThumbnailList.Header>
20224
+ * <ThumbnailList.Header.SearchField />
20225
+ * <ThumbnailList.Header.Sort items={sortOptions} />
20226
+ * </ThumbnailList.Header>
20227
+ * ```
20228
+ */
19323
20229
  const ThumbnailListHeader = function (props) {
19324
20230
  const startAlignedItems = [];
19325
20231
  const endAlignedItems = [];
@@ -19335,17 +20241,34 @@ const ThumbnailListHeader = function (props) {
19335
20241
  }
19336
20242
  }
19337
20243
  });
19338
- return (jsx(Fragment, { children: jsxs(Stack$1, { direction: "row", alignItems: "center", justifyContent: props.justifyContent ?? 'space-between', gap: 2, children: [jsx(Stack$1, { direction: "row", alignItems: "center", gap: 2, justifyContent: "start", children: startAlignedItems }), endAlignedItems] }) }));
20244
+ return (jsxs(Stack$1, { direction: "row", alignItems: "center", justifyContent: props.justifyContent ?? 'space-between', gap: 2, children: [jsx(Stack$1, { direction: "row", alignItems: "center", gap: 2, justifyContent: "start", children: startAlignedItems }), endAlignedItems] }));
19339
20245
  };
19340
- ThumbnailListHeader.SearchField = ThumbnailListSearchField$1;
20246
+ ThumbnailListHeader.SearchField = ThumbnailListSearchField;
19341
20247
  ThumbnailListHeader.FilterTags = ThumbnailListFilterTags;
19342
20248
  ThumbnailListHeader.Sort = ThumbnailListHeaderSort;
19343
20249
 
19344
20250
  /**
19345
- * Main Component: Renders all sub components
19346
- * Includes ThumbnailList Provider for context data
19347
- * @param props react children, items
19348
- * @returns component
20251
+ * Main ThumbnailList component that displays a list of items with thumbnails.
20252
+ * Provides context for child components and manages state for sorting, filtering, and searching.
20253
+ *
20254
+ * This component uses a compound component pattern with Header and MainContent sub-components.
20255
+ *
20256
+ * @template T - The type of items in the list (must extend ThumbnailListItemInterface)
20257
+ * @param {ThumbnailListProps<T>} props - Component props
20258
+ * @param {ReactNode} props.children - Child components (typically Header and MainContent)
20259
+ * @param {T[]} props.items - Array of items to display in the list
20260
+ * @param {ThumbnailListConfigurationInterface<T>} [props.config] - Optional configuration for sorting and filtering
20261
+ * @returns {JSX.Element} The rendered ThumbnailList component with context provider
20262
+ *
20263
+ * @example
20264
+ * ```tsx
20265
+ * <ThumbnailList items={items} config={{ sortBy: 'title', sortAscending: true }}>
20266
+ * <ThumbnailList.Header>
20267
+ * <ThumbnailList.Header.SearchField />
20268
+ * </ThumbnailList.Header>
20269
+ * <ThumbnailList.MainContent />
20270
+ * </ThumbnailList>
20271
+ * ```
19349
20272
  */
19350
20273
  function ThumbnailList(props) {
19351
20274
  const combinedConfig = {
@@ -19356,20 +20279,20 @@ function ThumbnailList(props) {
19356
20279
  const { sortedItems, setSortBy, setSortAscending, sortAscending } = useSortedThumbnailListItems(listItems, combinedConfig.sortBy.toString(), combinedConfig.sortAscending);
19357
20280
  const { tagFilteredItems, setTagAndCondition, tagAndCondition } = useTagFilteredThumbnailListItems({ allItems: sortedItems, initialTag: combinedConfig.tag.toString() });
19358
20281
  const { setSearchTerm, filteredItems } = useFilteredThumbnailListItems(tagFilteredItems);
19359
- return (jsx(Fragment, { children: jsx(ThumbnailListItemContext.Provider, { value: {
19360
- items: filteredItems,
19361
- setItems: setListItems,
19362
- originalItems: listItems,
19363
- setOriginalItems: setListItems,
19364
- tagFilterCallback: setTagAndCondition,
19365
- tagAndCondition: tagAndCondition,
19366
- setSearchTerm: setSearchTerm,
19367
- setSortAscending: setSortAscending,
19368
- sortAscending: sortAscending,
19369
- setSortBy: setSortBy,
19370
- sortBy: combinedConfig.sortBy.toString(),
19371
- isLoading: false,
19372
- }, children: jsx(Stack$1, { direction: "column", sx: { width: '100%', minWidth: '425px' }, children: props.children }) }) }));
20282
+ return (jsx(ThumbnailListItemContext.Provider, { value: {
20283
+ items: filteredItems,
20284
+ setItems: setListItems,
20285
+ originalItems: listItems,
20286
+ setOriginalItems: setListItems,
20287
+ tagFilterCallback: setTagAndCondition,
20288
+ tagAndCondition: tagAndCondition,
20289
+ setSearchTerm: setSearchTerm,
20290
+ setSortAscending: setSortAscending,
20291
+ sortAscending: sortAscending,
20292
+ setSortBy: setSortBy,
20293
+ sortBy: combinedConfig.sortBy.toString(),
20294
+ isLoading: combinedConfig.isLoading ?? false,
20295
+ }, children: jsx(Stack$1, { direction: "column", sx: { width: '100%', minWidth: '350px' }, children: props.children }) }));
19373
20296
  }
19374
20297
  ThumbnailList.MainContent = ThumbnailListMainContent;
19375
20298
  ThumbnailList.Header = ThumbnailListHeader;