@nex-ui/react
Version:
🎉 A beautiful, modern, and reliable React component library.
134 lines (131 loc) • 4.65 kB
JavaScript
"use client";
import { jsx, jsxs } from 'react/jsx-runtime';
import { LoadingOutlined } from '@nex-ui/icons';
import { useMemo } from 'react';
import { useNexUI } from '../provider/Context.mjs';
import { useDefaultProps } from '../utils/useDefaultProps.mjs';
import { useStyles } from '../utils/useStyles.mjs';
import { useSlot } from '../utils/useSlot.mjs';
import { ButtonBase } from '../buttonBase/ButtonBase.mjs';
import { Ripple } from '../utils/ripple/Ripple.mjs';
import { composeClasses } from '../utils/composeClasses.mjs';
import { buttonRecipe } from '../../theme/recipes/button.mjs';
import { getUtilityClass } from '../utils/getUtilityClass.mjs';
const useSlotClasses = (ownerState)=>{
const { prefix } = useNexUI();
const { color, variant, radius, size, iconOnly, loading, disabled, fullWidth, classes, disableRipple, spinnerPlacement } = ownerState;
return useMemo(()=>{
const btnRoot = `${prefix}-btn`;
const slots = {
root: [
'root',
`variant-${variant}`,
`radius-${radius}`,
`size-${size}`,
`color-${color}`,
iconOnly && `icon-only`,
loading && `loading`,
disabled && `disabled`,
fullWidth && `full-width`,
disableRipple && 'disable-ripple'
],
startIcon: [
`icon`,
`start-icon`,
loading && spinnerPlacement === 'start' && `icon-loading`
],
endIcon: [
`icon`,
`end-icon`,
loading && spinnerPlacement === 'end' && `icon-loading`
]
};
return composeClasses(slots, getUtilityClass(btnRoot), classes);
}, [
classes,
color,
disableRipple,
disabled,
fullWidth,
iconOnly,
loading,
prefix,
radius,
size,
spinnerPlacement,
variant
]);
};
const Button = (inProps)=>{
const { primaryThemeColor } = useNexUI();
const props = useDefaultProps({
name: 'Button',
props: inProps
});
const { children, slotProps, spinner, color = primaryThemeColor, variant = 'solid', size = 'md', radius = size, iconOnly = false, loading = false, disabled: disabledProp = false, fullWidth = false, disableRipple = false, startIcon: startIconProp, endIcon: endIconProp, spinnerPlacement = 'start', ...remainingProps } = props;
const disabled = loading || disabledProp;
const ownerState = {
...props,
spinnerPlacement,
variant,
size,
radius,
iconOnly,
loading,
fullWidth,
color,
disableRipple,
disabled: disabledProp
};
const classes = useSlotClasses(ownerState);
const styles = useStyles({
ownerState,
name: 'Button',
recipe: buttonRecipe
});
const [ButtonRoot, getButtonRootProps] = useSlot({
ownerState,
elementType: ButtonBase,
externalForwardedProps: remainingProps,
classNames: classes.root,
style: styles.root,
shouldForwardComponent: false,
additionalProps: {
disabled
}
});
const [ButtonStartIcon, getButtonStartIconProps] = useSlot({
ownerState,
elementType: 'span',
externalSlotProps: slotProps?.startIcon,
classNames: classes.startIcon,
style: styles.startIcon
});
const [ButtonEndIcon, getButtonEndIconProps] = useSlot({
ownerState,
elementType: 'span',
externalSlotProps: slotProps?.endIcon,
classNames: classes.endIcon,
style: styles.endIcon
});
const loadingIcon = spinner ?? /*#__PURE__*/ jsx(LoadingOutlined, {});
return /*#__PURE__*/ jsx(Ripple, {
disabled: disableRipple || disabled,
children: /*#__PURE__*/ jsxs(ButtonRoot, {
...getButtonRootProps(),
children: [
(spinnerPlacement === 'start' && loading || startIconProp) && /*#__PURE__*/ jsx(ButtonStartIcon, {
...getButtonStartIconProps(),
children: loading ? loadingIcon : startIconProp
}),
children,
(spinnerPlacement === 'end' && loading || endIconProp) && /*#__PURE__*/ jsx(ButtonEndIcon, {
...getButtonEndIconProps(),
children: loading ? loadingIcon : endIconProp
})
]
})
});
};
Button.displayName = 'Button';
export { Button };