file-uploader

This commit is contained in:
StyleZhang 2024-07-26 16:54:25 +08:00
parent 6e15d7f777
commit 2498c238b2
9 changed files with 158 additions and 1 deletions

View File

@ -16,7 +16,7 @@
}
.action-btn-l {
@apply p-1.5 w-[34px] h-[34px] rounded-lg
@apply p-1.5 w-8 h-8 rounded-lg
}
/* m is for the regular button */

View File

@ -0,0 +1,36 @@
import {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react'
import type { TextAreaRef } from 'rc-textarea'
export const useTextAreaHeight = () => {
const textareaRef = useRef<TextAreaRef>(null)
const [height, setHeight] = useState(0)
const handleComputeHeight = () => {
const textareaElement = textareaRef.current?.resizableTextArea.textArea
if (textareaElement) {
const { height } = textareaElement.getBoundingClientRect()
setHeight(height)
}
}
useEffect(() => {
handleComputeHeight()
}, [])
const handleTextareaResize = useCallback(() => {
handleComputeHeight()
}, [])
return {
textareaRef,
handleTextareaResize,
isMultipleLine: useMemo(() => height > 32, [height]),
}
}

View File

@ -0,0 +1,51 @@
import {
memo,
} from 'react'
import Textarea from 'rc-textarea'
import { RiSendPlane2Fill } from '@remixicon/react'
import { useTextAreaHeight } from './hooks'
import Button from '@/app/components/base/button'
import { FileUploaderInChatInput } from '@/app/components/base/file-uploader'
import cn from '@/utils/classnames'
const ChatInputArea = () => {
const {
textareaRef,
handleTextareaResize,
isMultipleLine,
} = useTextAreaHeight()
return (
<div
className={cn(
'p-[9px] bg-components-panel-bg-blur border border-components-chat-input-border rounded-xl shadow-md',
'max-h-[210px] overflow-y-auto',
!isMultipleLine && 'flex items-center',
)}
>
<Textarea
ref={textareaRef}
className='grow w-full p-1 leading-6 body-lg-regular text-text-tertiary'
placeholder='Enter message...'
autoSize
onResize={handleTextareaResize}
/>
<div className={cn(
'shrink-0 flex items-center justify-end ml-1',
isMultipleLine && 'sticky bottom-0',
)}>
<div className='flex items-center'>
<FileUploaderInChatInput />
</div>
<Button
className='ml-3 px-0 w-8'
variant='primary'
>
<RiSendPlane2Fill className='w-4 h-4' />
</Button>
</div>
</div>
)
}
export default memo(ChatInputArea)

View File

@ -0,0 +1,9 @@
import { memo } from 'react'
const FileListFlex = () => {
return (
<div className='flex'></div>
)
}
export default memo(FileListFlex)

View File

@ -0,0 +1,9 @@
import { memo } from 'react'
const FileListFullWidth = () => {
return (
<div></div>
)
}
export default memo(FileListFullWidth)

View File

@ -0,0 +1,51 @@
import {
memo,
useState,
} from 'react'
import {
RiAttachmentLine,
} from '@remixicon/react'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import ActionButton from '@/app/components/base/action-button'
import Button from '@/app/components/base/button'
const FileUploaderInChatInput = () => {
const [open, setOpen] = useState(false)
return (
<PortalToFollowElem
open={open}
onOpenChange={setOpen}
placement='top'
offset={4}
>
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
<ActionButton size='l'>
<RiAttachmentLine className='w-5 h-5' />
</ActionButton>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent>
<div className='p-3 w-[280px] bg-components-panel-bg-blur border-[0.5px] border-components-panel-border rounded-xl shadow-lg'>
<div className='flex items-center p-1 bg-components-input-bg-active border border-components-input-border-active rounded-lg shadow-xs'>
<input
className='mr-0.5 p-1 appearance-none system-sm-regular text-text-secondary'
placeholder='Enter URL...'
/>
<Button
size='small'
variant='primary'
>
OK
</Button>
</div>
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
)
}
export default memo(FileUploaderInChatInput)

View File

@ -1,2 +1,3 @@
export { default as FileUploaderInAttachment } from './file-uploader-in-attachment'
export { default as FileUploaderInChatInput } from './file-uploader-in-chat-input'
export { default as FileTypeIcon } from './file-type-icon'