From 5126ccd6a703b11aa76cbcec32617cba459f4c52 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Fri, 12 Aug 2022 00:11:26 -0400 Subject: [PATCH] fix(striker-ui): add MessageGroup --- striker-ui/components/MessageGroup.tsx | 104 +++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 striker-ui/components/MessageGroup.tsx diff --git a/striker-ui/components/MessageGroup.tsx b/striker-ui/components/MessageGroup.tsx new file mode 100644 index 00000000..c1c28b89 --- /dev/null +++ b/striker-ui/components/MessageGroup.tsx @@ -0,0 +1,104 @@ +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 = { + 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>(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 = ( + + {messageChildren} + + ); + } + + 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;