From 0986c72b76f938c2f17cb0f0712fb2797ed4e295 Mon Sep 17 00:00:00 2001 From: arvinxx Date: Wed, 24 May 2023 00:01:56 +0800 Subject: [PATCH] :sparkles: feat(editable-message): add EditableMessage components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add EditableMessage component that allows users to edit and display messages in a chat interface. The component includes a modal that appears when a user clicks on the message. The modal has an edit button that allows users to edit the message. If the message is empty, the component displays an edit button by default. The component also has an onChange prop that fires when the message is edited and an onOpenChange prop that fires when the modal is opened or closed. 📝 Add demos and API documentation for the component. --- src/EditableMessage/demos/index.tsx | 5 ++ src/EditableMessage/index.md | 14 ++++ src/EditableMessage/index.tsx | 107 ++++++++++++++++++++++++++++ src/index.ts | 1 + 4 files changed, 127 insertions(+) create mode 100644 src/EditableMessage/demos/index.tsx create mode 100644 src/EditableMessage/index.md create mode 100644 src/EditableMessage/index.tsx diff --git a/src/EditableMessage/demos/index.tsx b/src/EditableMessage/demos/index.tsx new file mode 100644 index 00000000..c3da5896 --- /dev/null +++ b/src/EditableMessage/demos/index.tsx @@ -0,0 +1,5 @@ +import { EditableMessage } from '@lobehub/ui'; + +export default () => { + return ; +}; diff --git a/src/EditableMessage/index.md b/src/EditableMessage/index.md new file mode 100644 index 00000000..f0cc4ffd --- /dev/null +++ b/src/EditableMessage/index.md @@ -0,0 +1,14 @@ +--- +nav: Components +group: Chat +title: EditableMessage +description: EditableMessage +--- + +## Default + + + +## APIs + + diff --git a/src/EditableMessage/index.tsx b/src/EditableMessage/index.tsx new file mode 100644 index 00000000..e0e027e1 --- /dev/null +++ b/src/EditableMessage/index.tsx @@ -0,0 +1,107 @@ +import Markdown from '@/Markdown'; +import MessageInput from '@/MessageInput'; +import MessageModal from '@/MessageModal'; +import { memo } from 'react'; +import useControlledState from 'use-merge-value'; + +export interface EditableMessageProps { + /** + * @title 当前文本值 + */ + value: string; + /** + * @title 值改变时的回调函数 + * @param value - 改变后的值 + */ + onChange?: (value: string) => void; + /** + * @title 是否打开模态框 + * @default false + */ + openModal?: boolean; + /** + * @title 模态框打开状态变化的回调函数 + * @param open - 模态框是否打开 + */ + onOpenChange?: (open: boolean) => void; + /** + * @title 是否处于编辑状态 + * @default false + */ + editing?: boolean; + /** + * @title 编辑状态变化的回调函数 + * @param editing - 是否处于编辑状态 + */ + onEditingChange?: (editing: boolean) => void; + /** + * @title 当文本值为空时是否显示编辑按钮 + * @default false + */ + showEditWhenEmpty?: boolean; + classNames?: { + markdown?: string; + input?: string; + }; +} + +const EditableMessage = memo( + ({ + value, + onChange, + classNames = {}, + onEditingChange, + editing, + openModal, + onOpenChange, + showEditWhenEmpty = false, + }) => { + const [isEdit, setTyping] = useControlledState(false, { + value: editing, + onChange: onEditingChange, + }); + + const [expand, setExpand] = useControlledState(false, { + value: openModal, + onChange: onOpenChange, + }); + + return !value && showEditWhenEmpty ? ( + { + onChange?.(text); + setTyping(false); + }} + className={classNames.input} + /> + ) : ( + <> + { + onChange?.(text); + }} + /> + {!expand && isEdit ? ( + { + onChange?.(text); + setTyping(false); + }} + onCancel={() => setTyping(false)} + defaultValue={value} + className={classNames.input} + /> + ) : ( + {value} + )} + + ); + }, +); + +export default EditableMessage; diff --git a/src/index.ts b/src/index.ts index 860492f0..5d30d1f1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ export { default as Avatar, type AvatarProps } from './Avatar'; export { default as ContextMenu, type ContextMenuProps } from './ContextMenu'; export { default as CopyButton, type CopyButtonProps } from './CopyButton'; export { default as DraggablePanel, type DraggablePanelProps } from './DraggablePanel'; +export { default as EditableMessage, type EditableMessageProps } from './EditableMessage'; export { default as EditableText, type EditableTextProps } from './EditableText'; export { default as Highlighter,