Commit 6adb9861 authored by Joel's avatar Joel

feat: expend toggle

parent cc4ca942
...@@ -11,6 +11,7 @@ type Props = { ...@@ -11,6 +11,7 @@ type Props = {
onHeightChange: (height: number) => void onHeightChange: (height: number) => void
children: JSX.Element children: JSX.Element
footer?: JSX.Element footer?: JSX.Element
hideResize?: boolean
} }
const PromptEditorHeightResizeWrap: FC<Props> = ({ const PromptEditorHeightResizeWrap: FC<Props> = ({
...@@ -20,6 +21,7 @@ const PromptEditorHeightResizeWrap: FC<Props> = ({ ...@@ -20,6 +21,7 @@ const PromptEditorHeightResizeWrap: FC<Props> = ({
onHeightChange, onHeightChange,
children, children,
footer, footer,
hideResize,
}) => { }) => {
const [clientY, setClientY] = useState(0) const [clientY, setClientY] = useState(0)
const [isResizing, setIsResizing] = useState(false) const [isResizing, setIsResizing] = useState(false)
...@@ -80,11 +82,13 @@ const PromptEditorHeightResizeWrap: FC<Props> = ({ ...@@ -80,11 +82,13 @@ const PromptEditorHeightResizeWrap: FC<Props> = ({
</div> </div>
{/* resize handler */} {/* resize handler */}
{footer} {footer}
{!hideResize && (
<div <div
className='absolute bottom-0 left-0 w-full flex justify-center h-2 cursor-row-resize' className='absolute bottom-0 left-0 w-full flex justify-center h-2 cursor-row-resize'
onMouseDown={handleStartResize}> onMouseDown={handleStartResize}>
<div className='w-5 h-[3px] rounded-sm bg-gray-300'></div> <div className='w-5 h-[3px] rounded-sm bg-gray-300'></div>
</div> </div>
)}
</div> </div>
) )
} }
......
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 14H10M10 14V20M10 14L3 21M20 10H14M14 10V4M14 10L21 3M20 14V16.8C20 17.9201 20 18.4802 19.782 18.908C19.5903 19.2843 19.2843 19.5903 18.908 19.782C18.4802 20 17.9201 20 16.8 20H14M10 4H7.2C6.0799 4 5.51984 4 5.09202 4.21799C4.71569 4.40973 4.40973 4.71569 4.21799 5.09202C4 5.51984 4 6.07989 4 7.2V10" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "24",
"height": "24",
"viewBox": "0 0 24 24",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M4 14H10M10 14V20M10 14L3 21M20 10H14M14 10V4M14 10L21 3M20 14V16.8C20 17.9201 20 18.4802 19.782 18.908C19.5903 19.2843 19.2843 19.5903 18.908 19.782C18.4802 20 17.9201 20 16.8 20H14M10 4H7.2C6.0799 4 5.51984 4 5.09202 4.21799C4.71569 4.40973 4.40973 4.71569 4.21799 5.09202C4 5.51984 4 6.07989 4 7.2V10",
"stroke": "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
},
"name": "Collapse04"
}
\ No newline at end of file
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Collapse04.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'Collapse04'
export default Icon
...@@ -5,6 +5,7 @@ export { default as ChevronDownDouble } from './ChevronDownDouble' ...@@ -5,6 +5,7 @@ export { default as ChevronDownDouble } from './ChevronDownDouble'
export { default as ChevronDown } from './ChevronDown' export { default as ChevronDown } from './ChevronDown'
export { default as ChevronRight } from './ChevronRight' export { default as ChevronRight } from './ChevronRight'
export { default as ChevronSelectorVertical } from './ChevronSelectorVertical' export { default as ChevronSelectorVertical } from './ChevronSelectorVertical'
export { default as Collapse04 } from './Collapse04'
export { default as FlipBackward } from './FlipBackward' export { default as FlipBackward } from './FlipBackward'
export { default as RefreshCcw01 } from './RefreshCcw01' export { default as RefreshCcw01 } from './RefreshCcw01'
export { default as RefreshCw05 } from './RefreshCw05' export { default as RefreshCw05 } from './RefreshCw05'
...@@ -44,6 +44,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter' ...@@ -44,6 +44,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
export type PromptEditorProps = { export type PromptEditorProps = {
className?: string className?: string
style?: React.CSSProperties
value?: string value?: string
editable?: boolean editable?: boolean
onChange?: (text: string) => void onChange?: (text: string) => void
...@@ -81,6 +82,7 @@ export type PromptEditorProps = { ...@@ -81,6 +82,7 @@ export type PromptEditorProps = {
const PromptEditor: FC<PromptEditorProps> = ({ const PromptEditor: FC<PromptEditorProps> = ({
className, className,
style,
value, value,
editable = true, editable = true,
onChange, onChange,
...@@ -158,7 +160,7 @@ const PromptEditor: FC<PromptEditorProps> = ({ ...@@ -158,7 +160,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
<LexicalComposer initialConfig={{ ...initialConfig, editable }}> <LexicalComposer initialConfig={{ ...initialConfig, editable }}>
<div className='relative'> <div className='relative'>
<RichTextPlugin <RichTextPlugin
contentEditable={<ContentEditable className={`${className} outline-none text-sm text-gray-700 leading-6`} />} contentEditable={<ContentEditable className={`${className} outline-none text-sm text-gray-700 leading-6`} style={style || {}} />}
placeholder={<Placeholder />} placeholder={<Placeholder />}
ErrorBoundary={LexicalErrorBoundary} ErrorBoundary={LexicalErrorBoundary}
/> />
......
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React, { useCallback } from 'react' import React, { useCallback, useEffect, useRef, useState } from 'react'
import cn from 'classnames' import cn from 'classnames'
import copy from 'copy-to-clipboard' import copy from 'copy-to-clipboard'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks' import { useBoolean } from 'ahooks'
import ToggleExpandBtn from '../toggle-expand-btn'
import PromptEditorHeightResizeWrap from '@/app/components/app/configuration/config-prompt/prompt-editor-height-resize-wrap' import PromptEditorHeightResizeWrap from '@/app/components/app/configuration/config-prompt/prompt-editor-height-resize-wrap'
import PromptEditor from '@/app/components/base/prompt-editor' import PromptEditor from '@/app/components/base/prompt-editor'
import { Clipboard, ClipboardCheck } from '@/app/components/base/icons/src/vender/line/files' import { Clipboard, ClipboardCheck } from '@/app/components/base/icons/src/vender/line/files'
import { Expand04 } from '@/app/components/base/icons/src/vender/solid/arrows'
import s from '@/app/components/app/configuration/config-prompt/style.module.css' import s from '@/app/components/app/configuration/config-prompt/style.module.css'
import { Trash03 } from '@/app/components/base/icons/src/vender/line/general' import { Trash03 } from '@/app/components/base/icons/src/vender/line/general'
...@@ -40,19 +40,23 @@ const Editor: FC<Props> = ({ ...@@ -40,19 +40,23 @@ const Editor: FC<Props> = ({
copy(value) copy(value)
setIsCopied(true) setIsCopied(true)
}, [value]) }, [value])
const [isExpanded, setIsExpanded] = React.useState(false)
const toggleExpand = useCallback(() => {
setIsExpanded(!isExpanded)
}, [isExpanded])
const [isFocus, { const [isFocus, {
setTrue: setFocus, setTrue: setFocus,
setFalse: setBlur, setFalse: setBlur,
}] = useBoolean(false) }] = useBoolean(false)
const ref = useRef<HTMLDivElement>(null)
const [isExpand, setIsExpand] = useState(false)
const [wrapHeight, setWrapHeight] = useState(ref.current?.clientHeight)
const editorExpandHeight = isExpand ? wrapHeight! - 56 : 0
useEffect(() => {
setWrapHeight(ref.current?.clientHeight)
}, [isExpand])
return ( return (
<div className={cn(isFocus && s.gradientBorder, '!rounded-[9px] shadow-md')}> <div className={cn(isExpand && 'absolute z-10 left-4 right-6 top-[52px] bottom-0 pb-4 bg-white')}>
<div className={cn(isFocus ? 'bg-white' : 'bg-gray-100', 'rounded-lg')}> <div ref={ref} className={cn(isFocus && s.gradientBorder, isExpand && 'h-full', '!rounded-[9px] shadow-md')}>
<div className={cn(isFocus ? 'bg-white' : 'bg-gray-100', isExpand && 'h-full flex flex-col', 'rounded-lg')}>
<div className='pt-1 pl-3 pr-2 flex justify-between h-6 items-center'> <div className='pt-1 pl-3 pr-2 flex justify-between h-6 items-center'>
<div className='leading-4 text-xs font-semibold text-gray-700 uppercase'>{title}</div> <div className='leading-4 text-xs font-semibold text-gray-700 uppercase'>{title}</div>
<div className='flex items-center'> <div className='flex items-center'>
...@@ -71,14 +75,14 @@ const Editor: FC<Props> = ({ ...@@ -71,14 +75,14 @@ const Editor: FC<Props> = ({
<ClipboardCheck className='mx-1 w-3.5 h-3.5 text-gray-500' /> <ClipboardCheck className='mx-1 w-3.5 h-3.5 text-gray-500' />
) )
} }
<Expand04 className='w-3.5 h-3.5 text-gray-500 cursor-pointer' onClick={toggleExpand} /> <ToggleExpandBtn isExpand={isExpand} onExpandChange={setIsExpand} />
</div> </div>
</div> </div>
</div> </div>
<PromptEditorHeightResizeWrap <PromptEditorHeightResizeWrap
className='px-3 min-h-[102px] overflow-y-auto text-sm text-gray-700' className={cn(isExpand && 'h-0 grow', 'px-3 min-h-[102px] overflow-y-auto text-sm text-gray-700')}
height={editorHeight} height={isExpand ? editorExpandHeight : editorHeight}
minHeight={minHeight} minHeight={minHeight}
onHeightChange={setEditorHeight} onHeightChange={setEditorHeight}
footer={( footer={(
...@@ -88,9 +92,11 @@ const Editor: FC<Props> = ({ ...@@ -88,9 +92,11 @@ const Editor: FC<Props> = ({
: <div className='h-[18px]'></div>} : <div className='h-[18px]'></div>}
</div> </div>
)} )}
hideResize={isExpand}
> >
<PromptEditor <PromptEditor
className='min-h-[84px]' className={cn('min-h-[84px]')}
style={isExpand ? { height: editorExpandHeight - 5 } : {}}
value={value} value={value}
contextBlock={{ contextBlock={{
show: true, show: true,
...@@ -127,6 +133,8 @@ const Editor: FC<Props> = ({ ...@@ -127,6 +133,8 @@ const Editor: FC<Props> = ({
</PromptEditorHeightResizeWrap> </PromptEditorHeightResizeWrap>
</div> </div>
</div> </div>
</div>
) )
} }
export default React.memo(Editor) export default React.memo(Editor)
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import { Expand04 } from '@/app/components/base/icons/src/vender/solid/arrows'
import { Collapse04 } from '@/app/components/base/icons/src/vender/line/arrows'
type Props = {
isExpand: boolean
onExpandChange: (isExpand: boolean) => void
}
const ExpandBtn: FC<Props> = ({
isExpand,
onExpandChange,
}) => {
const handleToggle = useCallback(() => {
onExpandChange(!isExpand)
}, [isExpand])
const Icon = isExpand ? Collapse04 : Expand04
return (
<Icon className='w-3.5 h-3.5 text-gray-500 cursor-pointer' onClick={handleToggle} />
)
}
export default React.memo(ExpandBtn)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment