'use client' import type { FC } from 'react' import React, { useMemo } from 'react' import { useState } from 'react' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' import type { OffsetOptions, Placement, } from '@floating-ui/react' import Input from '@/app/components/base/input' import AppIcon from '@/app/components/base/app-icon' import type { App } from '@/types/app' type Props = { appList: App[] scope: string disabled: boolean trigger: React.ReactNode placement?: Placement offset?: OffsetOptions isShow: boolean onShowChange: (isShow: boolean) => void onSelect: (app: App) => void } const AppPicker: FC = ({ scope, appList, disabled, trigger, placement = 'right-start', offset = 0, isShow, onShowChange, onSelect, }) => { const [searchText, setSearchText] = useState('') const filteredAppList = useMemo(() => { return (appList || []) .filter(app => app.name.toLowerCase().includes(searchText.toLowerCase())) .filter(app => (app.mode !== 'advanced-chat' && app.mode !== 'workflow') || !!app.workflow) .filter(app => scope === 'all' || (scope === 'completion' && app.mode === 'completion') || (scope === 'workflow' && app.mode === 'workflow') || (scope === 'chat' && app.mode === 'advanced-chat') || (scope === 'chat' && app.mode === 'agent-chat') || (scope === 'chat' && app.mode === 'chat')) }, [appList, scope, searchText]) const getAppType = (app: App) => { switch (app.mode) { case 'advanced-chat': return 'chatflow' case 'agent-chat': return 'agent' case 'chat': return 'chat' case 'completion': return 'completion' case 'workflow': return 'workflow' } } const handleTriggerClick = () => { if (disabled) return onShowChange(true) } return ( {trigger}
setSearchText(e.target.value)} onClear={() => setSearchText('')} />
{filteredAppList.map(app => (
onSelect(app)} >
{app.name}
{getAppType(app)}
))}
) } export default React.memo(AppPicker)