Local modifications to ClusterLabs/Anvil by Alteeve
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
2.4 KiB

import {
forwardRef,
useCallback,
useImperativeHandle,
useMemo,
useState,
} from 'react';
import { v4 as uuidv4 } from 'uuid';
import MessageBox, { Message, MessageBoxProps } from './MessageBox';
type MessageGroupOptionalProps = {
defaultMessageType?: MessageBoxProps['type'];
};
type MessageGroupProps = MessageGroupOptionalProps & {
count: number;
};
type MessageGroupForwardedRefContent = {
setMessage?: (index: number, message?: Message) => void;
};
const MESSAGE_GROUP_DEFAULT_PROPS: Required<MessageGroupOptionalProps> = {
defaultMessageType: 'info',
};
const MessageGroup = forwardRef<
MessageGroupForwardedRefContent,
MessageGroupProps
>(
(
{
count,
defaultMessageType = MESSAGE_GROUP_DEFAULT_PROPS.defaultMessageType,
},
ref,
) => {
const { keys: messageKeys, init: initialMessages } = useMemo(
() =>
Array.from({ length: count }).reduce<{
keys: string[];
init: undefined[];
}>(
(previous) => {
const { keys, init } = previous;
keys.push(uuidv4());
init.push(undefined);
return previous;
},
{ keys: [], init: [] },
),
[count],
);
const [messages, setMessages] =
useState<Array<Message | undefined>>(initialMessages);
const setMessage = useCallback((index: number, message?: Message) => {
setMessages((previous) => {
previous.splice(index, 1, message);
return [...previous];
});
}, []);
const messageElements = useMemo(
() =>
messages.map((message, messageIndex) => {
let messageElement;
if (message) {
const { children: messageChildren, type = defaultMessageType } =
message;
messageElement = (
<MessageBox
key={`message-${messageKeys[messageIndex]}`}
type={type}
>
{messageChildren}
</MessageBox>
);
}
return messageElement;
}),
[defaultMessageType, messages, messageKeys],
);
useImperativeHandle(ref, () => ({ setMessage }), [setMessage]);
return <>{messageElements}</>;
},
);
MessageGroup.defaultProps = MESSAGE_GROUP_DEFAULT_PROPS;
MessageGroup.displayName = 'MessageGroup';
export type { MessageGroupForwardedRefContent };
export default MessageGroup;