mirror of https://github.com/langgenius/dify.git
support create memory var in memory popup
This commit is contained in:
parent
05c05bb6d0
commit
efcaa2bbbd
|
|
@ -25,7 +25,7 @@ import {
|
|||
} from 'lexical'
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER } from '@/app/components/workflow/nodes/_base/components/prompt/add-memory-button'
|
||||
import { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER, MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER, MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER } from '@/app/components/workflow/nodes/_base/components/prompt/type'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import VariableIcon from '@/app/components/workflow/nodes/_base/components/variable/variable-label/base/variable-icon'
|
||||
import type {
|
||||
|
|
@ -135,15 +135,25 @@ export default function MemoryPopupPlugin({
|
|||
setOpen(false)
|
||||
}, [setOpen])
|
||||
|
||||
const handleSelectVariable = useCallback((variable: string[]) => {
|
||||
editor.dispatchCommand(INSERT_WORKFLOW_VARIABLE_BLOCK_COMMAND, variable)
|
||||
closePortal()
|
||||
}, [editor, closePortal])
|
||||
|
||||
const handleCreate = useCallback(() => {
|
||||
eventEmitter?.emit({ type: MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER, instanceId } as any)
|
||||
closePortal()
|
||||
}, [eventEmitter, instanceId, closePortal])
|
||||
|
||||
eventEmitter?.useSubscription((v: any) => {
|
||||
if (v.type === MEMORY_POPUP_SHOW_BY_EVENT_EMITTER && v.instanceId === instanceId)
|
||||
openPortal()
|
||||
})
|
||||
|
||||
const handleSelectVariable = useCallback((variable: string[]) => {
|
||||
editor.dispatchCommand(INSERT_WORKFLOW_VARIABLE_BLOCK_COMMAND, variable)
|
||||
closePortal()
|
||||
}, [editor, closePortal])
|
||||
eventEmitter?.useSubscription((v: any) => {
|
||||
if (v.type === MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER && v.instanceId === instanceId)
|
||||
handleSelectVariable(v.variable)
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
return editor.registerUpdateListener(({ editorState }) => {
|
||||
|
|
@ -245,7 +255,7 @@ export default function MemoryPopupPlugin({
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className='system-xs-medium flex items-center gap-1 border-t border-divider-subtle px-4 py-2 text-text-accent-light-mode-only'>
|
||||
<div className='system-xs-medium flex cursor-pointer items-center gap-1 border-t border-divider-subtle px-4 py-2 text-text-accent-light-mode-only' onClick={handleCreate}>
|
||||
<RiAddLine className='h-4 w-4' />
|
||||
<div>{t('workflow.nodes.llm.memory.createButton')}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ import { useTranslation } from 'react-i18next'
|
|||
import Button from '@/app/components/base/button'
|
||||
import { Memory } from '@/app/components/base/icons/src/vender/line/others'
|
||||
|
||||
export const MEMORY_POPUP_SHOW_BY_EVENT_EMITTER = 'MEMORY_POPUP_SHOW_BY_EVENT_EMITTER'
|
||||
export const PROMPT_EDITOR_INSERT_QUICKLY = 'PROMPT_EDITOR_INSERT_QUICKLY'
|
||||
|
||||
type Props = {
|
||||
onAddMemory: () => void
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,10 +36,12 @@ import Switch from '@/app/components/base/switch'
|
|||
import { Jinja } from '@/app/components/base/icons/src/vender/workflow'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { useWorkflowVariableType } from '@/app/components/workflow/hooks'
|
||||
import AddMemoryButton, { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER } from './add-memory-button'
|
||||
import AddMemoryButton from './add-memory-button'
|
||||
import { MEMORY_POPUP_SHOW_BY_EVENT_EMITTER } from './type'
|
||||
import type {
|
||||
ConversationVariable,
|
||||
} from '@/app/components/workflow/types'
|
||||
import MemoryCreateButton from '@/app/components/workflow/nodes/llm/components/memory-system/memory-create-button'
|
||||
|
||||
type Props = {
|
||||
className?: string
|
||||
|
|
@ -169,175 +171,178 @@ const Editor: FC<Props> = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<Wrap className={cn(className, wrapClassName)} style={wrapStyle} isInNode isExpand={isExpand}>
|
||||
<div ref={ref} className={cn(isFocus ? (gradientBorder && 'bg-gradient-to-r from-components-input-border-active-prompt-1 to-components-input-border-active-prompt-2') : 'bg-transparent', isExpand && 'h-full', '!rounded-[9px] p-0.5', containerClassName)}>
|
||||
<div className={cn(isFocus ? 'bg-background-default' : 'bg-components-input-bg-normal', isExpand && 'flex h-full flex-col', 'rounded-lg', containerClassName)}>
|
||||
<div className={cn('flex items-center justify-between pl-3 pr-2 pt-1', headerClassName)}>
|
||||
<div className='flex gap-2'>
|
||||
<div className={cn('text-xs font-semibold uppercase leading-4 text-text-secondary', titleClassName)}>{title} {required && <span className='text-text-destructive'>*</span>}</div>
|
||||
{titleTooltip && <Tooltip popupContent={titleTooltip} />}
|
||||
</div>
|
||||
<div className='flex items-center'>
|
||||
<div className='text-xs font-medium leading-[18px] text-text-tertiary'>{value?.length || 0}</div>
|
||||
{isSupportPromptGenerator && (
|
||||
<PromptGeneratorBtn
|
||||
nodeId={nodeId!}
|
||||
editorId={editorId}
|
||||
className='ml-[5px]'
|
||||
onGenerated={onGenerated}
|
||||
modelConfig={modelConfig}
|
||||
currentPrompt={value}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className='ml-2 mr-2 h-3 w-px bg-divider-regular'></div>
|
||||
{/* Operations */}
|
||||
<div className='flex items-center space-x-[2px]'>
|
||||
{isSupportJinja && (
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div>
|
||||
<div>{t('workflow.common.enableJinja')}</div>
|
||||
<a className='text-text-accent' target='_blank' href='https://jinja.palletsprojects.com/en/2.10.x/'>{t('workflow.common.learnMore')}</a>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className={cn(editionType === EditionType.jinja2 && 'border-components-button-ghost-bg-hover bg-components-button-ghost-bg-hover', 'flex h-[22px] items-center space-x-0.5 rounded-[5px] border border-transparent px-1.5 hover:border-components-button-ghost-bg-hover')}>
|
||||
<Jinja className='h-3 w-6 text-text-quaternary' />
|
||||
<Switch
|
||||
size='sm'
|
||||
defaultValue={editionType === EditionType.jinja2}
|
||||
onChange={(checked) => {
|
||||
onEditionTypeChange?.(checked ? EditionType.jinja2 : EditionType.basic)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
)}
|
||||
{!readOnly && (
|
||||
<Tooltip
|
||||
popupContent={`${t('workflow.common.insertVarTip')}`}
|
||||
>
|
||||
<ActionButton onClick={handleInsertVariable}>
|
||||
<Variable02 className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showRemove && (
|
||||
<ActionButton onClick={onRemove}>
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
)}
|
||||
{!isCopied
|
||||
? (
|
||||
<ActionButton onClick={handleCopy}>
|
||||
<Copy className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
)
|
||||
: (
|
||||
<ActionButton>
|
||||
<CopyCheck className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
)
|
||||
}
|
||||
<ToggleExpandBtn isExpand={isExpand} onExpandChange={setIsExpand} />
|
||||
<>
|
||||
<Wrap className={cn(className, wrapClassName)} style={wrapStyle} isInNode isExpand={isExpand}>
|
||||
<div ref={ref} className={cn(isFocus ? (gradientBorder && 'bg-gradient-to-r from-components-input-border-active-prompt-1 to-components-input-border-active-prompt-2') : 'bg-transparent', isExpand && 'h-full', '!rounded-[9px] p-0.5', containerClassName)}>
|
||||
<div className={cn(isFocus ? 'bg-background-default' : 'bg-components-input-bg-normal', isExpand && 'flex h-full flex-col', 'rounded-lg', containerClassName)}>
|
||||
<div className={cn('flex items-center justify-between pl-3 pr-2 pt-1', headerClassName)}>
|
||||
<div className='flex gap-2'>
|
||||
<div className={cn('text-xs font-semibold uppercase leading-4 text-text-secondary', titleClassName)}>{title} {required && <span className='text-text-destructive'>*</span>}</div>
|
||||
{titleTooltip && <Tooltip popupContent={titleTooltip} />}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Min: 80 Max: 560. Header: 24 */}
|
||||
<div className={cn('pb-2', isExpand && 'flex grow flex-col', isMemorySupported && isFocus && 'pb-1.5')}>
|
||||
{!(isSupportJinja && editionType === EditionType.jinja2)
|
||||
? (
|
||||
<>
|
||||
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative min-h-[56px] overflow-y-auto px-3', editorContainerClassName)}>
|
||||
<PromptEditor
|
||||
key={controlPromptEditorRerenderKey}
|
||||
placeholder={placeholder}
|
||||
placeholderClassName={placeholderClassName}
|
||||
instanceId={instanceId}
|
||||
compact
|
||||
className={cn('min-h-[56px]', inputClassName)}
|
||||
style={isExpand ? { height: editorExpandHeight - 5 } : {}}
|
||||
value={value}
|
||||
contextBlock={{
|
||||
show: justVar ? false : isShowContext,
|
||||
selectable: !hasSetBlockStatus?.context,
|
||||
canNotAddContext: true,
|
||||
}}
|
||||
historyBlock={{
|
||||
show: justVar ? false : isShowHistory,
|
||||
selectable: !hasSetBlockStatus?.history,
|
||||
history: {
|
||||
user: 'Human',
|
||||
assistant: 'Assistant',
|
||||
},
|
||||
}}
|
||||
queryBlock={{
|
||||
show: false, // use [sys.query] instead of query block
|
||||
selectable: false,
|
||||
}}
|
||||
workflowVariableBlock={{
|
||||
show: true,
|
||||
variables: nodesOutputVars || [],
|
||||
getVarType,
|
||||
workflowNodesMap: availableNodes.reduce((acc, node) => {
|
||||
acc[node.id] = {
|
||||
title: node.data.title,
|
||||
type: node.data.type,
|
||||
width: node.width,
|
||||
height: node.height,
|
||||
position: node.position,
|
||||
}
|
||||
if (node.data.type === BlockEnum.Start) {
|
||||
acc.sys = {
|
||||
title: t('workflow.blocks.start'),
|
||||
type: BlockEnum.Start,
|
||||
}
|
||||
}
|
||||
return acc
|
||||
}, {} as any),
|
||||
showManageInputField: !!pipelineId,
|
||||
onManageInputField: () => setShowInputFieldPanel?.(true),
|
||||
}}
|
||||
onChange={onChange}
|
||||
onBlur={setBlur}
|
||||
onFocus={setFocus}
|
||||
editable={!readOnly}
|
||||
isSupportFileVar={isSupportFileVar}
|
||||
isMemorySupported
|
||||
memoryVarInNode={memoryVarInNode}
|
||||
memoryVarInApp={memoryVarInApp}
|
||||
/>
|
||||
{/* to patch Editor not support dynamic change editable status */}
|
||||
{readOnly && <div className='absolute inset-0 z-10'></div>}
|
||||
</div>
|
||||
{isMemorySupported && <AddMemoryButton onAddMemory={handleAddMemory} />}
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative min-h-[56px] overflow-y-auto px-3', editorContainerClassName)}>
|
||||
<CodeEditor
|
||||
availableVars={nodesOutputVars || []}
|
||||
varList={varList}
|
||||
onAddVar={handleAddVariable}
|
||||
isInNode
|
||||
readOnly={readOnly}
|
||||
language={CodeLanguage.python3}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
noWrapper
|
||||
isExpand={isExpand}
|
||||
className={inputClassName}
|
||||
<div className='flex items-center'>
|
||||
<div className='text-xs font-medium leading-[18px] text-text-tertiary'>{value?.length || 0}</div>
|
||||
{isSupportPromptGenerator && (
|
||||
<PromptGeneratorBtn
|
||||
nodeId={nodeId!}
|
||||
editorId={editorId}
|
||||
className='ml-[5px]'
|
||||
onGenerated={onGenerated}
|
||||
modelConfig={modelConfig}
|
||||
currentPrompt={value}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className='ml-2 mr-2 h-3 w-px bg-divider-regular'></div>
|
||||
{/* Operations */}
|
||||
<div className='flex items-center space-x-[2px]'>
|
||||
{isSupportJinja && (
|
||||
<Tooltip
|
||||
popupContent={
|
||||
<div>
|
||||
<div>{t('workflow.common.enableJinja')}</div>
|
||||
<a className='text-text-accent' target='_blank' href='https://jinja.palletsprojects.com/en/2.10.x/'>{t('workflow.common.learnMore')}</a>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className={cn(editionType === EditionType.jinja2 && 'border-components-button-ghost-bg-hover bg-components-button-ghost-bg-hover', 'flex h-[22px] items-center space-x-0.5 rounded-[5px] border border-transparent px-1.5 hover:border-components-button-ghost-bg-hover')}>
|
||||
<Jinja className='h-3 w-6 text-text-quaternary' />
|
||||
<Switch
|
||||
size='sm'
|
||||
defaultValue={editionType === EditionType.jinja2}
|
||||
onChange={(checked) => {
|
||||
onEditionTypeChange?.(checked ? EditionType.jinja2 : EditionType.basic)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
)}
|
||||
{!readOnly && (
|
||||
<Tooltip
|
||||
popupContent={`${t('workflow.common.insertVarTip')}`}
|
||||
>
|
||||
<ActionButton onClick={handleInsertVariable}>
|
||||
<Variable02 className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showRemove && (
|
||||
<ActionButton onClick={onRemove}>
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
)}
|
||||
{!isCopied
|
||||
? (
|
||||
<ActionButton onClick={handleCopy}>
|
||||
<Copy className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
)
|
||||
: (
|
||||
<ActionButton>
|
||||
<CopyCheck className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
)
|
||||
}
|
||||
<ToggleExpandBtn isExpand={isExpand} onExpandChange={setIsExpand} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Min: 80 Max: 560. Header: 24 */}
|
||||
<div className={cn('pb-2', isExpand && 'flex grow flex-col', isMemorySupported && isFocus && 'pb-1.5')}>
|
||||
{!(isSupportJinja && editionType === EditionType.jinja2)
|
||||
? (
|
||||
<>
|
||||
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative min-h-[56px] overflow-y-auto px-3', editorContainerClassName)}>
|
||||
<PromptEditor
|
||||
key={controlPromptEditorRerenderKey}
|
||||
placeholder={placeholder}
|
||||
placeholderClassName={placeholderClassName}
|
||||
instanceId={instanceId}
|
||||
compact
|
||||
className={cn('min-h-[56px]', inputClassName)}
|
||||
style={isExpand ? { height: editorExpandHeight - 5 } : {}}
|
||||
value={value}
|
||||
contextBlock={{
|
||||
show: justVar ? false : isShowContext,
|
||||
selectable: !hasSetBlockStatus?.context,
|
||||
canNotAddContext: true,
|
||||
}}
|
||||
historyBlock={{
|
||||
show: justVar ? false : isShowHistory,
|
||||
selectable: !hasSetBlockStatus?.history,
|
||||
history: {
|
||||
user: 'Human',
|
||||
assistant: 'Assistant',
|
||||
},
|
||||
}}
|
||||
queryBlock={{
|
||||
show: false, // use [sys.query] instead of query block
|
||||
selectable: false,
|
||||
}}
|
||||
workflowVariableBlock={{
|
||||
show: true,
|
||||
variables: nodesOutputVars || [],
|
||||
getVarType,
|
||||
workflowNodesMap: availableNodes.reduce((acc, node) => {
|
||||
acc[node.id] = {
|
||||
title: node.data.title,
|
||||
type: node.data.type,
|
||||
width: node.width,
|
||||
height: node.height,
|
||||
position: node.position,
|
||||
}
|
||||
if (node.data.type === BlockEnum.Start) {
|
||||
acc.sys = {
|
||||
title: t('workflow.blocks.start'),
|
||||
type: BlockEnum.Start,
|
||||
}
|
||||
}
|
||||
return acc
|
||||
}, {} as any),
|
||||
showManageInputField: !!pipelineId,
|
||||
onManageInputField: () => setShowInputFieldPanel?.(true),
|
||||
}}
|
||||
onChange={onChange}
|
||||
onBlur={setBlur}
|
||||
onFocus={setFocus}
|
||||
editable={!readOnly}
|
||||
isSupportFileVar={isSupportFileVar}
|
||||
isMemorySupported
|
||||
memoryVarInNode={memoryVarInNode}
|
||||
memoryVarInApp={memoryVarInApp}
|
||||
/>
|
||||
{/* to patch Editor not support dynamic change editable status */}
|
||||
{readOnly && <div className='absolute inset-0 z-10'></div>}
|
||||
</div>
|
||||
{isMemorySupported && <AddMemoryButton onAddMemory={handleAddMemory} />}
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative min-h-[56px] overflow-y-auto px-3', editorContainerClassName)}>
|
||||
<CodeEditor
|
||||
availableVars={nodesOutputVars || []}
|
||||
varList={varList}
|
||||
onAddVar={handleAddVariable}
|
||||
isInNode
|
||||
readOnly={readOnly}
|
||||
language={CodeLanguage.python3}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
noWrapper
|
||||
isExpand={isExpand}
|
||||
className={inputClassName}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Wrap>
|
||||
</Wrap>
|
||||
{isMemorySupported && <MemoryCreateButton instanceId={instanceId} hideTrigger />}
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
export const MEMORY_POPUP_SHOW_BY_EVENT_EMITTER = 'MEMORY_POPUP_SHOW_BY_EVENT_EMITTER'
|
||||
export const MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER = 'MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER'
|
||||
export const MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER = 'MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER'
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { useCallback, useState } from 'react'
|
||||
import { RiAddLine } from '@remixicon/react'
|
||||
import VariableModal from '@/app/components/workflow/panel/chat-variable-panel/components/variable-modal'
|
||||
import type { OffsetOptions, Placement } from '@floating-ui/react'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
|
|
@ -11,8 +12,23 @@ import type { ConversationVariable } from '@/app/components/workflow/types'
|
|||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { useNodesSyncDraft } from '@/app/components/workflow/hooks/use-nodes-sync-draft'
|
||||
import useInspectVarsCrud from '@/app/components/workflow/hooks/use-inspect-vars-crud'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER, MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER } from '@/app/components/workflow/nodes/_base/components/prompt/type'
|
||||
|
||||
const MemoryCreateButton = () => {
|
||||
type Props = {
|
||||
placement?: Placement
|
||||
offset?: number | OffsetOptions
|
||||
hideTrigger?: boolean
|
||||
instanceId?: string
|
||||
}
|
||||
|
||||
const MemoryCreateButton = ({
|
||||
placement,
|
||||
offset,
|
||||
hideTrigger,
|
||||
instanceId,
|
||||
}: Props) => {
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
const [open, setOpen] = useState(false)
|
||||
const varList = useStore(s => s.conversationVariables) as ConversationVariable[]
|
||||
const updateChatVarList = useStore(s => s.setConversationVariables)
|
||||
|
|
@ -34,19 +50,30 @@ const MemoryCreateButton = () => {
|
|||
updateChatVarList(newList)
|
||||
handleVarChanged()
|
||||
setOpen(false)
|
||||
}, [varList, updateChatVarList, handleVarChanged, setOpen])
|
||||
if (instanceId)
|
||||
eventEmitter?.emit({ type: MEMORY_VAR_CREATED_BY_MODAL_BY_EVENT_EMITTER, instanceId, variable: ['conversation', newChatVar.name] } as any)
|
||||
}, [varList, updateChatVarList, handleVarChanged, setOpen, eventEmitter, instanceId])
|
||||
|
||||
eventEmitter?.useSubscription((v: any) => {
|
||||
if (v.type === MEMORY_VAR_MODAL_SHOW_BY_EVENT_EMITTER && v.instanceId === instanceId)
|
||||
setOpen(true)
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<PortalToFollowElem
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
placement='left'
|
||||
placement={placement || 'left'}
|
||||
offset={offset}
|
||||
>
|
||||
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
|
||||
<ActionButton className='shrink-0'>
|
||||
<RiAddLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
{hideTrigger && <div></div>}
|
||||
{!hideTrigger && (
|
||||
<ActionButton className='shrink-0'>
|
||||
<RiAddLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
)}
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-[11]'>
|
||||
<VariableModal
|
||||
|
|
|
|||
Loading…
Reference in New Issue