@nex-ui/react
Version:
🎉 A beautiful, modern, and reliable React component library.
171 lines (167 loc) • 4.81 kB
JavaScript
"use client";
;
var jsxRuntime = require('react/jsx-runtime');
var react = require('react');
var AvatarGroupContext = require('./AvatarGroupContext.cjs');
var useDefaultProps = require('../utils/useDefaultProps.cjs');
var useStyles = require('../utils/useStyles.cjs');
var useSlot = require('../utils/useSlot.cjs');
var Context = require('../provider/Context.cjs');
var composeClasses = require('../utils/composeClasses.cjs');
var avatar = require('../../theme/recipes/avatar.cjs');
var getUtilityClass = require('../utils/getUtilityClass.cjs');
const useSlotClasses = (ownerState)=>{
const { prefix } = Context.useNexUI();
const { color, size, radius, classes, outlined } = ownerState;
return react.useMemo(()=>{
const avatarRoot = `${prefix}-avatar`;
const slots = {
root: [
'root',
`radius-${radius}`,
`size-${size}`,
`color-${color}`,
outlined && 'outlined'
],
img: [
`img`
]
};
return composeClasses.composeClasses(slots, getUtilityClass.getUtilityClass(avatarRoot), classes);
}, [
classes,
color,
outlined,
prefix,
radius,
size
]);
};
const useLoaded = ({ src, srcSet })=>{
const [loaded, setLoaded] = react.useState(false);
react.useEffect(()=>{
if (!src && !srcSet) {
return;
}
setLoaded(false);
let active = true;
const image = new Image();
image.onload = ()=>{
if (!active) {
return;
}
setLoaded('loaded');
};
image.onerror = ()=>{
if (!active) {
return;
}
setLoaded('error');
};
image.src = src;
if (srcSet) {
image.srcset = srcSet;
}
return ()=>{
active = false;
};
}, [
src,
srcSet
]);
return loaded;
};
const useSlotAriaProps = (ownerState)=>{
const { alt, children, loaded, 'aria-label': ariaLabel, role = 'img' } = ownerState;
return react.useMemo(()=>{
let root = {};
if (loaded === false || loaded === 'error') {
if (typeof children === 'string') {
root = {
role,
'aria-label': ariaLabel ?? children
};
} else if (typeof alt === 'string') {
root = {
role,
'aria-label': ariaLabel ?? alt
};
}
}
return {
root
};
}, [
alt,
ariaLabel,
children,
loaded,
role
]);
};
const Avatar = (inProps)=>{
const props = useDefaultProps.useDefaultProps({
name: 'Avatar',
props: inProps
});
const groupCtx = AvatarGroupContext.useAvatarGroup();
const inGroup = !!groupCtx;
const { src, alt, srcSet, slotProps, children: childrenProp, size = groupCtx?.size ?? 'md', radius = groupCtx?.radius ?? size, color = groupCtx?.color ?? 'gray', outlined = groupCtx?.outlined ?? false, ...remainingProps } = props;
const loaded = useLoaded({
src,
srcSet
});
const ownerState = {
...props,
size,
radius,
color,
outlined,
inGroup,
loaded
};
const styles = useStyles.useStyles({
ownerState,
name: 'Avatar',
recipe: avatar.avatarRecipe
});
const classes = useSlotClasses(ownerState);
const slotAriaProps = useSlotAriaProps(ownerState);
const [AvatarRoot, getAvatarRootProps] = useSlot.useSlot({
ownerState,
elementType: 'div',
externalForwardedProps: remainingProps,
classNames: classes.root,
style: styles.root,
a11y: slotAriaProps.root
});
const [AvatarImg, getAvatarImgProps] = useSlot.useSlot({
ownerState,
elementType: 'img',
externalSlotProps: slotProps?.img,
classNames: classes.img,
style: styles.img,
additionalProps: {
src,
alt,
srcSet
}
});
let children = null;
const hasImg = src || srcSet;
if (hasImg && loaded === 'loaded') {
children = /*#__PURE__*/ jsxRuntime.jsx(AvatarImg, {
...getAvatarImgProps()
});
} else if (childrenProp) {
children = childrenProp;
} else if (hasImg && alt) {
children = alt[0];
}
return /*#__PURE__*/ jsxRuntime.jsx(AvatarRoot, {
...getAvatarRootProps(),
children: children
});
};
Avatar.displayName = 'Avatar';
exports.Avatar = Avatar;