/*
* SPDX-FileCopyrightText: 2021-2023 The Refinery Authors
*
* SPDX-License-Identifier: EPL-2.0
*/
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { styled, type SxProps, type Theme } from '@mui/material/styles';
import { type ReactNode, useLayoutEffect, useState } from 'react';
const AnimatedButtonBase = styled(Button, {
shouldForwardProp: (prop) => prop !== 'width',
})<{ width: string }>(({ theme, width }) => {
// Transition copied from `@mui/material/Button`.
const colorTransition = theme.transitions.create(
['background-color', 'box-shadow', 'border-color', 'color'],
{
duration: theme.transitions.duration.short,
},
);
return {
width,
// Make sure the button does not change width if a number is updated.
fontVariantNumeric: 'tabular-nums',
transition: `
${colorTransition},
${theme.transitions.create(['width'], {
duration: theme.transitions.duration.short,
})}
`,
'@media (prefers-reduced-motion: reduce)': {
transition: colorTransition,
},
};
});
export default function AnimatedButton({
'aria-label': ariaLabel,
onClick,
color,
disabled,
startIcon,
sx,
children,
}: {
'aria-label'?: string;
onClick?: () => void;
color: 'error' | 'warning' | 'primary' | 'inherit';
disabled?: boolean;
startIcon: JSX.Element;
sx?: SxProps | undefined;
children?: ReactNode;
}): JSX.Element {
const [width, setWidth] = useState();
const [contentsElement, setContentsElement] = useState(
null,
);
useLayoutEffect(() => {
if (contentsElement !== null) {
const updateWidth = () => {
setWidth(window.getComputedStyle(contentsElement).width);
};
updateWidth();
const observer = new ResizeObserver(updateWidth);
observer.observe(contentsElement);
return () => observer.unobserve(contentsElement);
}
return () => {};
}, [setWidth, contentsElement]);
return (
{children}
);
}
AnimatedButton.defaultProps = {
'aria-label': undefined,
onClick: undefined,
disabled: false,
sx: undefined,
children: undefined,
};