mirror of https://github.com/langgenius/dify.git
feat: add useFloatingRight hook and integrate it into InputFieldEditorPanel and PreviewPanel for dynamic positioning
This commit is contained in:
parent
218e778099
commit
5b433aa2d1
|
|
@ -1,11 +1,13 @@
|
|||
import { RiCloseLine } from '@remixicon/react'
|
||||
import InputFieldForm from './form'
|
||||
import { convertFormDataToINputField, convertToInputFieldFormData } from './utils'
|
||||
import { useCallback } from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import type { InputVar } from '@/models/pipeline'
|
||||
import type { FormData } from './form/types'
|
||||
import type { MoreInfo } from '@/app/components/workflow/types'
|
||||
import { useFloatingRight } from '../hooks'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type InputFieldEditorProps = {
|
||||
onClose: () => void
|
||||
|
|
@ -19,7 +21,12 @@ const InputFieldEditorPanel = ({
|
|||
initialData,
|
||||
}: InputFieldEditorProps) => {
|
||||
const { t } = useTranslation()
|
||||
const formData = convertToInputFieldFormData(initialData)
|
||||
|
||||
const { floatingRight, floatingRightWidth } = useFloatingRight(400)
|
||||
|
||||
const formData = useMemo(() => {
|
||||
return convertToInputFieldFormData(initialData)
|
||||
}, [initialData])
|
||||
|
||||
const handleSubmit = useCallback((value: FormData, moreInfo?: MoreInfo) => {
|
||||
const inputFieldData = convertFormDataToINputField(value)
|
||||
|
|
@ -27,7 +34,16 @@ const InputFieldEditorPanel = ({
|
|||
}, [onSubmit])
|
||||
|
||||
return (
|
||||
<div className='relative mr-1 flex h-fit max-h-full w-[400px] flex-col overflow-y-auto rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-2xl shadow-shadow-shadow-9'>
|
||||
<div
|
||||
className={cn(
|
||||
'relative mr-1 flex h-fit max-h-full w-[400px] flex-col overflow-y-auto rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-2xl shadow-shadow-shadow-9',
|
||||
'transition-all duration-300 ease-in-out',
|
||||
floatingRight && 'absolute right-0 z-[100]',
|
||||
)}
|
||||
style={{
|
||||
width: `${floatingRightWidth}px`,
|
||||
}}
|
||||
>
|
||||
<div className='system-xl-semibold flex items-center pb-1 pl-4 pr-11 pt-3.5 text-text-primary'>
|
||||
{initialData ? t('datasetPipeline.inputFieldPanel.editInputField') : t('datasetPipeline.inputFieldPanel.addInputField')}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { useStore as useReactflow } from 'reactflow'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
|
||||
export const useFloatingRight = (targetElementWidth: number) => {
|
||||
const [floatingRight, setFloatingRight] = useState(false)
|
||||
const nodePanelWidth = useStore(state => state.nodePanelWidth)
|
||||
const workflowCanvasWidth = useStore(state => state.workflowCanvasWidth)
|
||||
const otherPanelWidth = useStore(state => state.otherPanelWidth)
|
||||
|
||||
const selectedNodeId = useReactflow(useShallow((s) => {
|
||||
const nodes = s.getNodes()
|
||||
const currentNode = nodes.find(node => node.data.selected)
|
||||
|
||||
if (currentNode)
|
||||
return currentNode.id
|
||||
}))
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof workflowCanvasWidth === 'number') {
|
||||
const inputFieldPanelWidth = 400
|
||||
const marginRight = 4
|
||||
const leftWidth = workflowCanvasWidth - (selectedNodeId ? nodePanelWidth : 0) - otherPanelWidth - inputFieldPanelWidth - marginRight
|
||||
setFloatingRight(leftWidth < targetElementWidth + marginRight)
|
||||
}
|
||||
}, [workflowCanvasWidth, nodePanelWidth, otherPanelWidth, selectedNodeId, targetElementWidth])
|
||||
|
||||
const floatingRightWidth = useMemo(() => {
|
||||
if (!floatingRight) return targetElementWidth
|
||||
const width = Math.min(targetElementWidth, (selectedNodeId ? nodePanelWidth : 0) + otherPanelWidth)
|
||||
return width
|
||||
}, [floatingRight, selectedNodeId, nodePanelWidth, otherPanelWidth, targetElementWidth])
|
||||
|
||||
return {
|
||||
floatingRight,
|
||||
floatingRightWidth,
|
||||
}
|
||||
}
|
||||
|
|
@ -7,18 +7,31 @@ import Divider from '@/app/components/base/divider'
|
|||
import ProcessDocuments from './process-documents'
|
||||
import type { Datasource } from '../../test-run/types'
|
||||
import { useInputFieldPanel } from '@/app/components/rag-pipeline/hooks'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useFloatingRight } from '../hooks'
|
||||
|
||||
const PreviewPanel = () => {
|
||||
const { t } = useTranslation()
|
||||
const [datasource, setDatasource] = useState<Datasource>()
|
||||
const { toggleInputFieldPreviewPanel } = useInputFieldPanel()
|
||||
|
||||
const { floatingRight, floatingRightWidth } = useFloatingRight(480)
|
||||
|
||||
const handleClosePreviewPanel = useCallback(() => {
|
||||
toggleInputFieldPreviewPanel()
|
||||
}, [toggleInputFieldPreviewPanel])
|
||||
|
||||
return (
|
||||
<div className='mr-1 flex h-full w-[480px] flex-col overflow-y-auto rounded-2xl border-y-[0.5px] border-l-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xl shadow-shadow-shadow-5'>
|
||||
<div
|
||||
className={cn(
|
||||
'mr-1 flex h-full flex-col overflow-y-auto rounded-2xl border-y-[0.5px] border-l-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xl shadow-shadow-shadow-5',
|
||||
'transition-all duration-300 ease-in-out',
|
||||
floatingRight && 'absolute right-0 z-[100]',
|
||||
)}
|
||||
style={{
|
||||
width: `${floatingRightWidth}px`,
|
||||
}}
|
||||
>
|
||||
<div className='flex items-center gap-x-2 px-4 pt-1'>
|
||||
<div className='grow py-1'>
|
||||
<Badge className='border-text-accent-secondary bg-components-badge-bg-dimm text-text-accent-secondary'>
|
||||
|
|
|
|||
Loading…
Reference in New Issue