@moderneinc/design-system-components 7.7.0-next.19b91c → 7.7.0-next.6ace41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Button/Button.d.ts +7 -5
- package/dist/index.d.ts +4 -3
- package/dist/index.esm.js +88 -61
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +114 -87
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -11,9 +11,10 @@ var Alert = require('@mui/material/Alert');
|
|
|
11
11
|
var ButtonBase = require('@mui/material/ButtonBase');
|
|
12
12
|
var lucideReact = require('lucide-react');
|
|
13
13
|
var IconButton = require('@mui/material/IconButton');
|
|
14
|
-
var
|
|
14
|
+
var react = require('react');
|
|
15
15
|
var Breadcrumbs = require('@mui/material/Breadcrumbs');
|
|
16
16
|
var Link = require('@mui/material/Link');
|
|
17
|
+
var Button = require('@mui/material/Button');
|
|
17
18
|
var CircularProgress = require('@mui/material/CircularProgress');
|
|
18
19
|
var MuiToggleButton = require('@mui/material/ToggleButton');
|
|
19
20
|
var MuiToggleButtonGroup = require('@mui/material/ToggleButtonGroup');
|
|
@@ -21,7 +22,6 @@ var MuiCard = require('@mui/material/Card');
|
|
|
21
22
|
var Checkbox = require('@mui/material/Checkbox');
|
|
22
23
|
var xDataGrid = require('@mui/x-data-grid');
|
|
23
24
|
var xDataGridPro = require('@mui/x-data-grid-pro');
|
|
24
|
-
var Button = require('@mui/material/Button');
|
|
25
25
|
var Divider = require('@mui/material/Divider');
|
|
26
26
|
var InputAdornment = require('@mui/material/InputAdornment');
|
|
27
27
|
var InputBase = require('@mui/material/InputBase');
|
|
@@ -664,7 +664,7 @@ const StyledIconButton = styles.styled(IconButton, {
|
|
|
664
664
|
},
|
|
665
665
|
}));
|
|
666
666
|
const ModBanner = ({ intent = 'info', type = 'outlined', message, messagePosition = 'left', linkText, showClose = false, icon, onClose, onLinkClick, ...props }) => {
|
|
667
|
-
const [dismissed, setDismissed] =
|
|
667
|
+
const [dismissed, setDismissed] = react.useState(false);
|
|
668
668
|
const handleClose = () => {
|
|
669
669
|
setDismissed(true);
|
|
670
670
|
onClose?.();
|
|
@@ -742,39 +742,34 @@ function ModBreadcrumbs({ children, className }) {
|
|
|
742
742
|
return (jsxRuntime.jsx(StyledBreadcrumbs, { separator: jsxRuntime.jsx(lucideReact.ChevronRight, { size: 10.67, color: designSystemTokens.semanticColors.color.icon.utility }), className: className, "aria-label": "breadcrumb", children: children }));
|
|
743
743
|
}
|
|
744
744
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
'size',
|
|
749
|
-
'loading',
|
|
750
|
-
'startIcon',
|
|
751
|
-
'endIcon',
|
|
752
|
-
'fullWidth',
|
|
753
|
-
'disableElevation',
|
|
754
|
-
];
|
|
755
|
-
const StyledButtonBase$1 = styles.styled(ButtonBase, {
|
|
756
|
-
shouldForwardProp: prop => !buttonOnlyProps.includes(prop),
|
|
757
|
-
})(({ theme, variant = 'primary', size = 'medium', loading = false }) => {
|
|
745
|
+
const StyledButton = styles.styled(Button, {
|
|
746
|
+
shouldForwardProp: prop => prop !== 'buttonVariant' && prop !== 'buttonSize',
|
|
747
|
+
})(({ theme, buttonVariant: variant, buttonSize: size }) => {
|
|
758
748
|
// Size configurations
|
|
759
749
|
const sizeConfig = {
|
|
760
750
|
small: {
|
|
761
751
|
height: 32,
|
|
762
|
-
|
|
752
|
+
paddingX: designSystemTokens.spacing.spacing_1_1_2,
|
|
763
753
|
fontSize: theme.typography.pxToRem(14),
|
|
764
754
|
},
|
|
765
755
|
medium: {
|
|
766
756
|
height: designSystemTokens.spacing.spacing_5,
|
|
767
|
-
|
|
757
|
+
paddingX: designSystemTokens.spacing.spacing_2,
|
|
768
758
|
fontSize: theme.typography.pxToRem(14),
|
|
769
759
|
},
|
|
770
760
|
};
|
|
771
761
|
const sizeStyles = sizeConfig[size];
|
|
762
|
+
const paddingX = variant === 'tertiary' ? 0 : sizeStyles.paddingX;
|
|
763
|
+
const spinnerSize = size === 'small' ? designSystemTokens.iconSize.md : designSystemTokens.iconSize.xl;
|
|
764
|
+
const disabled = `&.${Button.buttonClasses.disabled}:not(.${Button.buttonClasses.loading})`;
|
|
772
765
|
// Base styles shared by all variants
|
|
773
766
|
const baseStyles = {
|
|
774
767
|
height: sizeStyles.height,
|
|
775
|
-
padding:
|
|
768
|
+
padding: `0 ${paddingX}px`,
|
|
769
|
+
fontFamily: 'inherit',
|
|
776
770
|
fontSize: sizeStyles.fontSize,
|
|
777
771
|
fontWeight: designSystemTokens.typography.fontWeight.semiBold,
|
|
772
|
+
letterSpacing: 'inherit',
|
|
778
773
|
lineHeight: '1.25rem',
|
|
779
774
|
borderRadius: designSystemTokens.borderRadius.button,
|
|
780
775
|
textTransform: 'none',
|
|
@@ -784,13 +779,48 @@ const StyledButtonBase$1 = styles.styled(ButtonBase, {
|
|
|
784
779
|
position: 'relative',
|
|
785
780
|
minWidth: 'fit-content',
|
|
786
781
|
gap: designSystemTokens.spacing.spacing_1,
|
|
782
|
+
// `gap` spaces the icons; MUI's slot margins would add to it
|
|
783
|
+
[`& .${Button.buttonClasses.startIcon}, & .${Button.buttonClasses.endIcon}`]: {
|
|
784
|
+
margin: 0,
|
|
785
|
+
},
|
|
786
|
+
// MUI sets font-size on the icon slot's first child; IconSlot takes it so 1em icons keep the label's size
|
|
787
|
+
[`& .${Button.buttonClasses.startIcon} > *:nth-of-type(1), & .${Button.buttonClasses.endIcon} > *:nth-of-type(1)`]: {
|
|
788
|
+
fontSize: 'inherit',
|
|
789
|
+
},
|
|
790
|
+
// MUI's indicator is a sibling of the icon; anchoring sizes and places it on the icon
|
|
791
|
+
[`&.${Button.buttonClasses.loadingPositionStart} .${Button.buttonClasses.startIcon}, &.${Button.buttonClasses.loadingPositionEnd} .${Button.buttonClasses.endIcon}`]: {
|
|
792
|
+
anchorName: '--mod-button-icon',
|
|
793
|
+
// MUI fades the icon out while the spinner appears at full opacity
|
|
794
|
+
transition: 'none',
|
|
795
|
+
},
|
|
796
|
+
[`&.${Button.buttonClasses.loadingPositionStart} .${Button.buttonClasses.loadingIndicator}, &.${Button.buttonClasses.loadingPositionEnd} .${Button.buttonClasses.loadingIndicator}`]: {
|
|
797
|
+
// MUI switches it to relative for fullWidth
|
|
798
|
+
position: 'absolute',
|
|
799
|
+
positionAnchor: '--mod-button-icon',
|
|
800
|
+
inset: 'anchor(top) anchor(right) anchor(bottom) anchor(left)',
|
|
801
|
+
},
|
|
802
|
+
// Without anchor positioning, the spinner takes the standard icon size at the icon's edge
|
|
803
|
+
'@supports not (anchor-name: --a)': {
|
|
804
|
+
[`&.${Button.buttonClasses.loadingPositionStart} .${Button.buttonClasses.loadingIndicator}`]: {
|
|
805
|
+
inset: 'auto',
|
|
806
|
+
left: paddingX,
|
|
807
|
+
width: spinnerSize,
|
|
808
|
+
height: spinnerSize,
|
|
809
|
+
},
|
|
810
|
+
[`&.${Button.buttonClasses.loadingPositionEnd} .${Button.buttonClasses.loadingIndicator}`]: {
|
|
811
|
+
inset: 'auto',
|
|
812
|
+
right: paddingX,
|
|
813
|
+
width: spinnerSize,
|
|
814
|
+
height: spinnerSize,
|
|
815
|
+
},
|
|
816
|
+
},
|
|
787
817
|
// Disabled state (always show cursor)
|
|
788
|
-
[`&.${
|
|
818
|
+
[`&.${Button.buttonClasses.disabled}`]: {
|
|
789
819
|
cursor: 'not-allowed',
|
|
790
820
|
pointerEvents: 'auto',
|
|
791
821
|
},
|
|
792
822
|
// Focus visible for keyboard navigation
|
|
793
|
-
[`&.${
|
|
823
|
+
[`&.${Button.buttonClasses.focusVisible}`]: {
|
|
794
824
|
outline: `2px solid ${designSystemTokens.semanticColors.color.border.focus}`,
|
|
795
825
|
outlineOffset: 2,
|
|
796
826
|
},
|
|
@@ -807,14 +837,10 @@ const StyledButtonBase$1 = styles.styled(ButtonBase, {
|
|
|
807
837
|
'&:active': {
|
|
808
838
|
backgroundColor: designSystemTokens.semanticColors.button.primary.bgPressed,
|
|
809
839
|
},
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
:
|
|
813
|
-
|
|
814
|
-
backgroundColor: designSystemTokens.semanticColors.button.primary.bgDisabled,
|
|
815
|
-
color: designSystemTokens.semanticColors.button.fgDisabled,
|
|
816
|
-
},
|
|
817
|
-
}),
|
|
840
|
+
[disabled]: {
|
|
841
|
+
backgroundColor: designSystemTokens.semanticColors.button.primary.bgDisabled,
|
|
842
|
+
color: designSystemTokens.semanticColors.button.fgDisabled,
|
|
843
|
+
},
|
|
818
844
|
},
|
|
819
845
|
secondary: {
|
|
820
846
|
backgroundColor: designSystemTokens.semanticColors.button.secondary.bg,
|
|
@@ -826,15 +852,11 @@ const StyledButtonBase$1 = styles.styled(ButtonBase, {
|
|
|
826
852
|
'&:active': {
|
|
827
853
|
backgroundColor: designSystemTokens.semanticColors.button.secondary.bgPressed,
|
|
828
854
|
},
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
:
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
borderColor: designSystemTokens.semanticColors.color.border.primary,
|
|
835
|
-
color: designSystemTokens.semanticColors.button.fgDisabled,
|
|
836
|
-
},
|
|
837
|
-
}),
|
|
855
|
+
[disabled]: {
|
|
856
|
+
backgroundColor: designSystemTokens.semanticColors.button.secondary.bgDisabled,
|
|
857
|
+
borderColor: designSystemTokens.semanticColors.color.border.primary,
|
|
858
|
+
color: designSystemTokens.semanticColors.button.fgDisabled,
|
|
859
|
+
},
|
|
838
860
|
},
|
|
839
861
|
destructive: {
|
|
840
862
|
backgroundColor: designSystemTokens.semanticColors.button.destructive.bg,
|
|
@@ -847,20 +869,15 @@ const StyledButtonBase$1 = styles.styled(ButtonBase, {
|
|
|
847
869
|
backgroundColor: designSystemTokens.semanticColors.color.status.error.fg,
|
|
848
870
|
filter: 'brightness(0.9)',
|
|
849
871
|
},
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
:
|
|
853
|
-
|
|
854
|
-
backgroundColor: designSystemTokens.semanticColors.button.primary.bgDisabled,
|
|
855
|
-
color: designSystemTokens.semanticColors.button.fgDisabled,
|
|
856
|
-
},
|
|
857
|
-
}),
|
|
872
|
+
[disabled]: {
|
|
873
|
+
backgroundColor: designSystemTokens.semanticColors.button.primary.bgDisabled,
|
|
874
|
+
color: designSystemTokens.semanticColors.button.fgDisabled,
|
|
875
|
+
},
|
|
858
876
|
},
|
|
859
877
|
tertiary: {
|
|
860
878
|
backgroundColor: 'transparent',
|
|
861
879
|
color: designSystemTokens.semanticColors.color.text.input,
|
|
862
880
|
border: 'none',
|
|
863
|
-
padding: 0,
|
|
864
881
|
lineHeight: 1,
|
|
865
882
|
'&:hover': {
|
|
866
883
|
backgroundColor: 'transparent',
|
|
@@ -869,24 +886,26 @@ const StyledButtonBase$1 = styles.styled(ButtonBase, {
|
|
|
869
886
|
'&:active': {
|
|
870
887
|
color: designSystemTokens.semanticColors.button.tertiary.fgPressed,
|
|
871
888
|
},
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
:
|
|
875
|
-
|
|
876
|
-
backgroundColor: 'transparent',
|
|
877
|
-
color: designSystemTokens.semanticColors.button.tertiary.fgDisabled,
|
|
878
|
-
},
|
|
879
|
-
}),
|
|
889
|
+
[disabled]: {
|
|
890
|
+
backgroundColor: 'transparent',
|
|
891
|
+
color: designSystemTokens.semanticColors.button.tertiary.fgDisabled,
|
|
892
|
+
},
|
|
880
893
|
},
|
|
881
894
|
};
|
|
895
|
+
// MUI greys a loading button as disabled; keep the label in the variant's colour
|
|
896
|
+
const { color } = variantStyles[variant];
|
|
882
897
|
return {
|
|
883
898
|
...baseStyles,
|
|
884
899
|
...variantStyles[variant],
|
|
900
|
+
[`&.${Button.buttonClasses.loadingPositionStart}, &.${Button.buttonClasses.loadingPositionEnd}`]: { color },
|
|
885
901
|
};
|
|
886
902
|
});
|
|
903
|
+
const IconSlot = styles.styled('span')({
|
|
904
|
+
display: 'contents',
|
|
905
|
+
});
|
|
887
906
|
const LoadingSpinner = styles.styled(CircularProgress, {
|
|
888
|
-
shouldForwardProp: prop => prop !== '
|
|
889
|
-
})(({
|
|
907
|
+
shouldForwardProp: prop => prop !== 'buttonVariant',
|
|
908
|
+
})(({ buttonVariant }) => {
|
|
890
909
|
// Use appropriate spinner color for each variant to ensure visibility
|
|
891
910
|
const spinnerColors = {
|
|
892
911
|
primary: designSystemTokens.semanticColors.color.surface.raised,
|
|
@@ -895,14 +914,22 @@ const LoadingSpinner = styles.styled(CircularProgress, {
|
|
|
895
914
|
tertiary: designSystemTokens.semanticColors.button.tertiary.fg,
|
|
896
915
|
};
|
|
897
916
|
return {
|
|
898
|
-
color: spinnerColors[
|
|
917
|
+
color: spinnerColors[buttonVariant],
|
|
899
918
|
};
|
|
900
919
|
});
|
|
901
920
|
/**
|
|
902
|
-
* ModButton - Text button component based on MUI
|
|
921
|
+
* ModButton - Text button component based on MUI Button
|
|
903
922
|
*/
|
|
904
|
-
function ModButton({ variant = 'primary', size = 'medium', loading = false, children,
|
|
905
|
-
|
|
923
|
+
function ModButton({ variant = 'primary', size = 'medium', loading = false, children, startIcon, endIcon, ...rest }) {
|
|
924
|
+
const loadingPosition = startIcon ? 'start' : endIcon ? 'end' : 'center';
|
|
925
|
+
// Mirrors MUI: the spinner is named by the button, which gets an id while loading
|
|
926
|
+
const generatedId = react.useId();
|
|
927
|
+
const id = rest.id ?? (loading ? generatedId : undefined);
|
|
928
|
+
return (jsxRuntime.jsx(StyledButton, { buttonVariant: variant, buttonSize: size,
|
|
929
|
+
// Pinned so theme defaultProps or a ButtonGroup can't restyle it; ButtonBase had no focus ripple
|
|
930
|
+
variant: "text", size: "medium", color: "primary", disableFocusRipple: true, loading: loading, loadingPosition: loadingPosition, loadingIndicator: jsxRuntime.jsx(LoadingSpinner, { buttonVariant: variant,
|
|
931
|
+
// With an icon, the anchored indicator is the icon's size and the spinner fills it
|
|
932
|
+
size: loadingPosition === 'center' ? (size === 'small' ? designSystemTokens.iconSize.md : designSystemTokens.iconSize.xl) : '100%', "aria-labelledby": id }), startIcon: startIcon && jsxRuntime.jsx(IconSlot, { children: startIcon }), endIcon: endIcon && jsxRuntime.jsx(IconSlot, { children: endIcon }), "aria-busy": loading || undefined, ...rest, id: id, children: children }));
|
|
906
933
|
}
|
|
907
934
|
ModButton.displayName = 'ModButton';
|
|
908
935
|
|
|
@@ -939,8 +966,8 @@ const StyledButtonTab = styles.styled(MuiToggleButton)(({ theme }) => ({
|
|
|
939
966
|
* the Mui-selected class — we mirror that to aria-selected for tab semantics.
|
|
940
967
|
*/
|
|
941
968
|
function useTabAriaSync() {
|
|
942
|
-
const observerRef =
|
|
943
|
-
return
|
|
969
|
+
const observerRef = react.useRef(null);
|
|
970
|
+
return react.useCallback((node) => {
|
|
944
971
|
if (observerRef.current) {
|
|
945
972
|
observerRef.current.disconnect();
|
|
946
973
|
observerRef.current = null;
|
|
@@ -1764,9 +1791,9 @@ sx: _sx, theme: _theme, ...props }) => {
|
|
|
1764
1791
|
const apiRef = xDataGrid.useGridApiContext();
|
|
1765
1792
|
const columns = xDataGrid.useGridSelector(apiRef, xDataGrid.gridColumnDefinitionsSelector);
|
|
1766
1793
|
const columnVisibilityModel = xDataGrid.useGridSelector(apiRef, xDataGrid.gridColumnVisibilityModelSelector);
|
|
1767
|
-
const [searchText, setSearchText] =
|
|
1794
|
+
const [searchText, setSearchText] = react.useState('');
|
|
1768
1795
|
// Filter columns based on search
|
|
1769
|
-
const filteredColumns =
|
|
1796
|
+
const filteredColumns = react.useMemo(() => {
|
|
1770
1797
|
if (!searchText) {
|
|
1771
1798
|
return columns;
|
|
1772
1799
|
}
|
|
@@ -2205,7 +2232,7 @@ StyledGridFilterPanel.displayName = 'StyledGridFilterPanel';
|
|
|
2205
2232
|
* <ModDataGrid rows={rows} columns={columns} slots={{ baseSelect: ModDataGridSelect }} />
|
|
2206
2233
|
* ```
|
|
2207
2234
|
*/
|
|
2208
|
-
const ModDataGridSelect =
|
|
2235
|
+
const ModDataGridSelect = react.forwardRef(function ModDataGridSelect({ id, label, labelId, disabled, fullWidth, size, style, slotProps, material, onChange, onClose, onKeyDown, ...rest }, ref) {
|
|
2209
2236
|
const theme = styles.useTheme();
|
|
2210
2237
|
const hasLabel = label !== undefined;
|
|
2211
2238
|
// The grid omits `size` in edit cells, where MUI's adapter falls back to the theme's TextField
|
|
@@ -3552,13 +3579,13 @@ ModIconWrapper.displayName = 'ModIconWrapper';
|
|
|
3552
3579
|
function ModInfiniteScrollGrid({ onLoadMore, hasNextPage = true, loadMoreAtScrollPercent = 0.85, slots, slotProps: userSlotProps, sx: userSx, ...props }) {
|
|
3553
3580
|
const defaultApiRef = xDataGridPro.useGridApiRef();
|
|
3554
3581
|
const apiRef = props?.apiRef ? props.apiRef : defaultApiRef;
|
|
3555
|
-
const scrollerRef =
|
|
3556
|
-
const isLoadingRef =
|
|
3557
|
-
const [isScrolling, setIsScrolling] =
|
|
3558
|
-
const scrollTimeoutRef =
|
|
3582
|
+
const scrollerRef = react.useRef(null);
|
|
3583
|
+
const isLoadingRef = react.useRef(false);
|
|
3584
|
+
const [isScrolling, setIsScrolling] = react.useState(false);
|
|
3585
|
+
const scrollTimeoutRef = react.useRef(null);
|
|
3559
3586
|
// Infinite scroll handler
|
|
3560
3587
|
// Based on moderne-ui implementation
|
|
3561
|
-
|
|
3588
|
+
react.useEffect(() => {
|
|
3562
3589
|
if (!onLoadMore) {
|
|
3563
3590
|
return;
|
|
3564
3591
|
}
|
|
@@ -4704,10 +4731,10 @@ const ModNavigationAvatar = ({ children, ...props }) => {
|
|
|
4704
4731
|
};
|
|
4705
4732
|
ModNavigationAvatar.displayName = 'ModNavigationAvatar';
|
|
4706
4733
|
|
|
4707
|
-
const ModSideNavContext =
|
|
4734
|
+
const ModSideNavContext = react.createContext({
|
|
4708
4735
|
collapsed: false,
|
|
4709
4736
|
});
|
|
4710
|
-
const useModSideNav = () =>
|
|
4737
|
+
const useModSideNav = () => react.useContext(ModSideNavContext);
|
|
4711
4738
|
|
|
4712
4739
|
/**
|
|
4713
4740
|
* Variant color configuration
|
|
@@ -4943,11 +4970,11 @@ function ModPageContent({ pageTitle, subtitle, breadcrumbs, action, sticky = fal
|
|
|
4943
4970
|
const isFullBleed = layout === 'fullBleed';
|
|
4944
4971
|
const contentMaxWidth = isFullBleed ? false : contentMaxWidthProp;
|
|
4945
4972
|
const disableGutters = isFullBleed || disableGuttersProp;
|
|
4946
|
-
const [showBackToTopButton, setShowBackToTopButton] =
|
|
4947
|
-
const headerRef =
|
|
4948
|
-
const containerRef =
|
|
4973
|
+
const [showBackToTopButton, setShowBackToTopButton] = react.useState(false);
|
|
4974
|
+
const headerRef = react.useRef(null);
|
|
4975
|
+
const containerRef = react.useRef(null);
|
|
4949
4976
|
// Intersection observer for back to top button
|
|
4950
|
-
|
|
4977
|
+
react.useEffect(() => {
|
|
4951
4978
|
if (!showBackToTop || !headerRef.current) {
|
|
4952
4979
|
return;
|
|
4953
4980
|
}
|
|
@@ -5465,7 +5492,7 @@ const ModSelectField = ({ size = 'medium', destructive = false, label, required
|
|
|
5465
5492
|
ModSelectField.displayName = 'ModSelectField';
|
|
5466
5493
|
|
|
5467
5494
|
// Measure before paint so the fades don't flash; useEffect on the server.
|
|
5468
|
-
const useIsomorphicLayoutEffect = typeof window === 'undefined' ?
|
|
5495
|
+
const useIsomorphicLayoutEffect = typeof window === 'undefined' ? react.useEffect : react.useLayoutEffect;
|
|
5469
5496
|
const EXPANDED_WIDTH = 98;
|
|
5470
5497
|
const COLLAPSED_WIDTH = 68;
|
|
5471
5498
|
// The fade overlay must end on the same color as the rail to blend cleanly.
|
|
@@ -5595,14 +5622,14 @@ const Handle = styles.styled(ButtonBase)(({ theme }) => ({
|
|
|
5595
5622
|
* Attach both `ref` and `onScroll` to the scroll element.
|
|
5596
5623
|
*/
|
|
5597
5624
|
function useScrollEdges() {
|
|
5598
|
-
const ref =
|
|
5599
|
-
const contentRef =
|
|
5625
|
+
const ref = react.useRef(null);
|
|
5626
|
+
const contentRef = react.useRef(null);
|
|
5600
5627
|
// Both start hidden; the layout effect corrects them before first paint.
|
|
5601
|
-
const [edges, setEdges] =
|
|
5628
|
+
const [edges, setEdges] = react.useState({
|
|
5602
5629
|
canScrollUp: false,
|
|
5603
5630
|
canScrollDown: false,
|
|
5604
5631
|
});
|
|
5605
|
-
const measure =
|
|
5632
|
+
const measure = react.useCallback(() => {
|
|
5606
5633
|
const el = ref.current;
|
|
5607
5634
|
if (!el) {
|
|
5608
5635
|
return;
|
|
@@ -5619,7 +5646,7 @@ function useScrollEdges() {
|
|
|
5619
5646
|
// Mount only; later changes come via the observer or onScroll.
|
|
5620
5647
|
useIsomorphicLayoutEffect(measure, [measure]);
|
|
5621
5648
|
// Resizes fire no scroll event: watch the viewport box and the content box.
|
|
5622
|
-
|
|
5649
|
+
react.useEffect(() => {
|
|
5623
5650
|
const el = ref.current;
|
|
5624
5651
|
// Absent in jsdom; without it only resize tracking is lost.
|
|
5625
5652
|
if (!el || typeof ResizeObserver === 'undefined') {
|
|
@@ -5652,7 +5679,7 @@ function useScrollEdges() {
|
|
|
5652
5679
|
* pattern.
|
|
5653
5680
|
*/
|
|
5654
5681
|
function ModSideNav({ collapsed, onCollapsedChange, header, footer, children, className, id, 'aria-label': ariaLabel, }) {
|
|
5655
|
-
const contextValue =
|
|
5682
|
+
const contextValue = react.useMemo(() => ({ collapsed }), [collapsed]);
|
|
5656
5683
|
const { ref: scrollRef, contentRef, onScroll, canScrollUp, canScrollDown } = useScrollEdges();
|
|
5657
5684
|
const HandleIcon = collapsed ? lucideReact.ChevronRight : lucideReact.ChevronLeft;
|
|
5658
5685
|
return (jsxRuntime.jsx(ModSideNavContext.Provider, { value: contextValue, children: jsxRuntime.jsxs(Frame, { collapsed: collapsed, children: [jsxRuntime.jsxs(Root, { collapsed: collapsed, "aria-label": ariaLabel, className: className, id: id, children: [jsxRuntime.jsxs(HeaderRegion, { children: [header, jsxRuntime.jsx(Fade, { edge: "header", visible: canScrollUp })] }), jsxRuntime.jsx(Scroll, { ref: scrollRef, onScroll: onScroll, "data-testid": "mod-side-nav-scroll", children: jsxRuntime.jsx(Stack, { ref: contentRef, sx: {
|
|
@@ -6272,8 +6299,8 @@ const ModToggleButtonGroup = ({ size = 'medium', variant = 'default', children,
|
|
|
6272
6299
|
// Forward size and variant to each ModToggleButton child so consumers don't
|
|
6273
6300
|
// have to set them on every button. MUI's group already does this via
|
|
6274
6301
|
// context for its own size prop, but our shapes don't pass through unchanged.
|
|
6275
|
-
const sized =
|
|
6276
|
-
?
|
|
6302
|
+
const sized = react.Children.map(children, child => react.isValidElement(child) && child.type === ModToggleButton
|
|
6303
|
+
? react.cloneElement(child, { size, variant })
|
|
6277
6304
|
: child);
|
|
6278
6305
|
return (jsxRuntime.jsx(StyledToggleButtonGroup$1, { groupVariant: variant, ...props, children: sized }));
|
|
6279
6306
|
};
|
|
@@ -6351,7 +6378,7 @@ const ModTreeItemLabel = (props) => {
|
|
|
6351
6378
|
*
|
|
6352
6379
|
* Slot data is read from the item model (passed via `items` on ModTreeView).
|
|
6353
6380
|
*/
|
|
6354
|
-
const ModTreeItem =
|
|
6381
|
+
const ModTreeItem = react.forwardRef(function ModTreeItem({ slots, slotProps, ...props }, ref) {
|
|
6355
6382
|
return (jsxRuntime.jsx(TreeItem.TreeItem, { ref: ref, slots: { label: ModTreeItemLabel, ...slots },
|
|
6356
6383
|
// itemId is not in MUI's label slot type but ModTreeItemLabel needs it for useTreeItemModel
|
|
6357
6384
|
slotProps: {
|