268 lines
8.8 KiB
JavaScript
268 lines
8.8 KiB
JavaScript
'use client';
|
|
import { makeStyles, mergeClasses } from '@griffel/react';
|
|
import { tokens, typographyStyles } from '@fluentui/react-theme';
|
|
import { useSizeStyles } from '../../Avatar';
|
|
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
|
|
export const avatarGroupItemClassNames = {
|
|
root: 'fui-AvatarGroupItem',
|
|
avatar: 'fui-AvatarGroupItem__avatar',
|
|
overflowLabel: 'fui-AvatarGroupItem__overflowLabel'
|
|
};
|
|
const avatarGroupItemDividerWidthVar = '--fuiAvatarGroupItem__divider--width';
|
|
/**
|
|
* Styles for the root slot
|
|
*/ const useRootStyles = makeStyles({
|
|
base: {
|
|
alignItems: 'center',
|
|
display: 'inline-flex',
|
|
flexShrink: 0,
|
|
position: 'relative'
|
|
},
|
|
overflowItem: {
|
|
padding: `${tokens.spacingVerticalXS} ${tokens.spacingHorizontalXS}`
|
|
},
|
|
nonOverflowItem: {
|
|
borderRadius: tokens.borderRadiusCircular
|
|
}
|
|
});
|
|
/**
|
|
* Styles for the avatar slot
|
|
*/ const useAvatarStyles = makeStyles({
|
|
nonOverflowItem: {
|
|
position: 'absolute'
|
|
},
|
|
pie: {
|
|
borderRadius: '0'
|
|
}
|
|
});
|
|
/**
|
|
* Styles for the label slot
|
|
*/ const useOverflowLabelStyles = makeStyles({
|
|
base: {
|
|
marginLeft: tokens.spacingHorizontalS,
|
|
color: tokens.colorNeutralForeground1,
|
|
...typographyStyles.body1
|
|
}
|
|
});
|
|
/**
|
|
* Styles for the stack layout
|
|
*/ const useStackStyles = makeStyles({
|
|
thick: {
|
|
boxShadow: `0 0 0 ${tokens.strokeWidthThick} ${tokens.colorNeutralBackground2}`
|
|
},
|
|
thicker: {
|
|
boxShadow: `0 0 0 ${tokens.strokeWidthThicker} ${tokens.colorNeutralBackground2}`
|
|
},
|
|
thickest: {
|
|
boxShadow: `0 0 0 ${tokens.strokeWidthThickest} ${tokens.colorNeutralBackground2}`
|
|
},
|
|
xxs: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: `calc(-1 * ${tokens.spacingHorizontalXXS})`
|
|
}
|
|
},
|
|
xs: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: `calc(-1 * ${tokens.spacingHorizontalXS})`
|
|
}
|
|
},
|
|
s: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: `calc(-1 * ${tokens.spacingHorizontalS})`
|
|
}
|
|
},
|
|
l: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: `calc(-1 * ${tokens.spacingHorizontalL})`
|
|
}
|
|
}
|
|
});
|
|
/**
|
|
* Styles for the spread layout
|
|
*/ const useSpreadStyles = makeStyles({
|
|
s: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: tokens.spacingHorizontalS
|
|
}
|
|
},
|
|
mNudge: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: tokens.spacingHorizontalMNudge
|
|
}
|
|
},
|
|
m: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: tokens.spacingHorizontalM
|
|
}
|
|
},
|
|
l: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: tokens.spacingHorizontalL
|
|
}
|
|
},
|
|
xl: {
|
|
'&:not(:first-child)': {
|
|
marginLeft: tokens.spacingHorizontalXL
|
|
}
|
|
}
|
|
});
|
|
/**
|
|
* Styles for the pie layout
|
|
*/ const usePieStyles = makeStyles({
|
|
base: {
|
|
position: 'absolute'
|
|
},
|
|
slices: {
|
|
// Two slices
|
|
// 1st of 2 items
|
|
'&:nth-of-type(1):nth-last-of-type(2)': {
|
|
clipPath: `inset(0 calc(25% + (var(${avatarGroupItemDividerWidthVar}) / 2)) 0 25%)`,
|
|
left: '-25%'
|
|
},
|
|
// 2nd of 2 items
|
|
'&:nth-of-type(2):nth-last-of-type(1)': {
|
|
clipPath: `inset(0 25% 0 calc(25% + (var(${avatarGroupItemDividerWidthVar}) / 2)))`,
|
|
left: '25%'
|
|
},
|
|
// Three slices
|
|
// 1st of 3 items
|
|
'&:nth-of-type(1):nth-last-of-type(3)': {
|
|
clipPath: `inset(0 calc(25% + (var(${avatarGroupItemDividerWidthVar}) / 2)) 0 25%)`,
|
|
left: '-25%'
|
|
},
|
|
// 2nd of 3 items
|
|
'&:nth-of-type(2):nth-last-of-type(2)': {
|
|
// Since the two AvatarGroupItems on the right are scaled by 0.5, the divider width should not be halved.
|
|
clipPath: `inset(0 0 var(${avatarGroupItemDividerWidthVar}) var(${avatarGroupItemDividerWidthVar}))`,
|
|
left: '50%',
|
|
transform: 'scale(0.5)',
|
|
transformOrigin: '0 0'
|
|
},
|
|
// 3rd of 3 items
|
|
'&:nth-of-type(3):nth-last-of-type(1)': {
|
|
clipPath: `inset(var(${avatarGroupItemDividerWidthVar}) 0 0 var(${avatarGroupItemDividerWidthVar}))`,
|
|
left: '50%',
|
|
top: '50%',
|
|
transform: 'scale(0.5)',
|
|
transformOrigin: '0 0'
|
|
}
|
|
},
|
|
rtlSlices: {
|
|
// Two slices
|
|
// 1st of 2 items
|
|
'&:nth-of-type(1):nth-last-of-type(2)': {
|
|
clipPath: `inset(0 25% 0 calc(25% + (var(${avatarGroupItemDividerWidthVar}) / 2)))`
|
|
},
|
|
// 2nd of 2 items
|
|
'&:nth-of-type(2):nth-last-of-type(1)': {
|
|
clipPath: `inset(0 calc(25% + (var(${avatarGroupItemDividerWidthVar}) / 2)) 0 25%)`
|
|
},
|
|
// Three slices
|
|
// 1st of 3 items
|
|
'&:nth-of-type(1):nth-last-of-type(3)': {
|
|
clipPath: `inset(0 25% 0 calc(25% + (var(${avatarGroupItemDividerWidthVar}) / 2)))`
|
|
},
|
|
// 2nd of 3 items
|
|
'&:nth-of-type(2):nth-last-of-type(2)': {
|
|
clipPath: `inset(0 var(${avatarGroupItemDividerWidthVar}) var(${avatarGroupItemDividerWidthVar}) 0)`,
|
|
left: '0'
|
|
},
|
|
// 3rd of 3 items
|
|
'&:nth-of-type(3):nth-last-of-type(1)': {
|
|
clipPath: `inset(var(${avatarGroupItemDividerWidthVar}) var(${avatarGroupItemDividerWidthVar}) 0 0)`,
|
|
left: '0'
|
|
}
|
|
},
|
|
thick: {
|
|
[avatarGroupItemDividerWidthVar]: tokens.strokeWidthThick
|
|
},
|
|
thicker: {
|
|
[avatarGroupItemDividerWidthVar]: tokens.strokeWidthThicker
|
|
},
|
|
thickest: {
|
|
[avatarGroupItemDividerWidthVar]: tokens.strokeWidthThickest
|
|
}
|
|
});
|
|
/**
|
|
* Apply styling to the AvatarGroupItem slots based on the state
|
|
*/ export const useAvatarGroupItemStyles_unstable = (state)=>{
|
|
'use no memo';
|
|
const { isOverflowItem, layout, size } = state;
|
|
const { dir } = useFluent();
|
|
const avatarStyles = useAvatarStyles();
|
|
const overflowLabelStyles = useOverflowLabelStyles();
|
|
const pieStyles = usePieStyles();
|
|
const rootStyles = useRootStyles();
|
|
const sizeStyles = useSizeStyles();
|
|
const groupChildClassName = useGroupChildClassName(layout, size);
|
|
const rootClasses = [
|
|
rootStyles.base
|
|
];
|
|
if (!isOverflowItem) {
|
|
rootClasses.push(rootStyles.nonOverflowItem);
|
|
rootClasses.push(groupChildClassName);
|
|
rootClasses.push(sizeStyles[size]);
|
|
if (layout === 'pie') {
|
|
rootClasses.push(pieStyles.base);
|
|
if (size < 56) {
|
|
rootClasses.push(pieStyles.thick);
|
|
} else if (size < 72) {
|
|
rootClasses.push(pieStyles.thicker);
|
|
} else {
|
|
rootClasses.push(pieStyles.thickest);
|
|
}
|
|
rootClasses.push(pieStyles.slices);
|
|
if (dir === 'rtl') {
|
|
rootClasses.push(pieStyles.rtlSlices);
|
|
}
|
|
}
|
|
} else {
|
|
rootClasses.push(rootStyles.overflowItem);
|
|
}
|
|
state.root.className = mergeClasses(avatarGroupItemClassNames.root, ...rootClasses, state.root.className);
|
|
state.avatar.className = mergeClasses(avatarGroupItemClassNames.avatar, !isOverflowItem && avatarStyles.nonOverflowItem, layout === 'pie' && avatarStyles.pie, state.avatar.className);
|
|
if (state.overflowLabel) {
|
|
state.overflowLabel.className = mergeClasses(avatarGroupItemClassNames.overflowLabel, overflowLabelStyles.base, state.overflowLabel.className);
|
|
}
|
|
return state;
|
|
};
|
|
/**
|
|
* Hook for getting the className for the children of AvatarGroup. This hook will provide the spacing and outlines
|
|
* needed for each layout.
|
|
*/ export const useGroupChildClassName = (layout, size)=>{
|
|
const stackStyles = useStackStyles();
|
|
const spreadStyles = useSpreadStyles();
|
|
const layoutClasses = [];
|
|
if (size) {
|
|
if (layout === 'stack') {
|
|
if (size < 56) {
|
|
layoutClasses.push(stackStyles.thick);
|
|
} else if (size < 72) {
|
|
layoutClasses.push(stackStyles.thicker);
|
|
} else {
|
|
layoutClasses.push(stackStyles.thickest);
|
|
}
|
|
if (size < 24) {
|
|
layoutClasses.push(stackStyles.xxs);
|
|
} else if (size < 48) {
|
|
layoutClasses.push(stackStyles.xs);
|
|
} else if (size < 96) {
|
|
layoutClasses.push(stackStyles.s);
|
|
} else {
|
|
layoutClasses.push(stackStyles.l);
|
|
}
|
|
} else if (layout === 'spread') {
|
|
if (size < 20) {
|
|
layoutClasses.push(spreadStyles.s);
|
|
} else if (size < 32) {
|
|
layoutClasses.push(spreadStyles.mNudge);
|
|
} else if (size < 64) {
|
|
layoutClasses.push(spreadStyles.l);
|
|
} else {
|
|
layoutClasses.push(spreadStyles.xl);
|
|
}
|
|
}
|
|
}
|
|
return mergeClasses(...layoutClasses);
|
|
};
|