| @@ -31,22 +31,22 @@ const WorkplaceSelector = () => { | |||
| } | |||
| return ( | |||
| <Menu as="div" className="relative h-full w-full"> | |||
| <Menu as="div" className="min-w-0"> | |||
| { | |||
| ({ open }) => ( | |||
| <> | |||
| <MenuButton className={cn( | |||
| ` | |||
| group flex w-full cursor-pointer items-center | |||
| gap-1.5 p-0.5 hover:bg-state-base-hover ${open && 'bg-state-base-hover'} rounded-[10px] | |||
| p-0.5 hover:bg-state-base-hover ${open && 'bg-state-base-hover'} rounded-[10px] | |||
| `, | |||
| )}> | |||
| <div className='flex h-6 w-6 items-center justify-center rounded-md bg-components-icon-bg-blue-solid text-[13px]'> | |||
| <div className='mr-1.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-components-icon-bg-blue-solid text-[13px] max-[800px]:mr-0'> | |||
| <span className='h-6 bg-gradient-to-r from-components-avatar-shape-fill-stop-0 to-components-avatar-shape-fill-stop-100 bg-clip-text align-middle font-semibold uppercase leading-6 text-shadow-shadow-1 opacity-90'>{currentWorkspace?.name[0]?.toLocaleUpperCase()}</span> | |||
| </div> | |||
| <div className='flex flex-row'> | |||
| <div className={'system-sm-medium max-w-[160px] truncate text-text-secondary'}>{currentWorkspace?.name}</div> | |||
| <RiArrowDownSLine className='h-4 w-4 text-text-secondary' /> | |||
| <div className='flex min-w-0 items-center'> | |||
| <div className={'system-sm-medium min-w-0 max-w-[149px] truncate text-text-secondary max-[800px]:hidden'}>{currentWorkspace?.name}</div> | |||
| <RiArrowDownSLine className='h-4 w-4 shrink-0 text-text-secondary' /> | |||
| </div> | |||
| </MenuButton> | |||
| <Transition | |||
| @@ -59,10 +59,11 @@ const WorkplaceSelector = () => { | |||
| leaveTo="transform opacity-0 scale-95" | |||
| > | |||
| <MenuItems | |||
| anchor="bottom start" | |||
| className={cn( | |||
| ` | |||
| shadows-shadow-lg absolute left-[-15px] mt-1 flex max-h-[400px] w-[280px] flex-col items-start overflow-y-auto rounded-xl | |||
| bg-components-panel-bg-blur backdrop-blur-[5px] | |||
| shadows-shadow-lg absolute left-[-15px] z-[1000] mt-1 flex max-h-[400px] w-[280px] flex-col items-start overflow-y-auto | |||
| rounded-xl bg-components-panel-bg-blur backdrop-blur-[5px] | |||
| `, | |||
| )} | |||
| > | |||
| @@ -73,7 +74,7 @@ const WorkplaceSelector = () => { | |||
| { | |||
| workspaces.map(workspace => ( | |||
| <div className='flex items-center gap-2 self-stretch rounded-lg py-1 pl-3 pr-2 hover:bg-state-base-hover' key={workspace.id} onClick={() => handleSwitchWorkspace(workspace.id)}> | |||
| <div className='flex h-6 w-6 items-center justify-center rounded-md bg-components-icon-bg-blue-solid text-[13px]'> | |||
| <div className='flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-components-icon-bg-blue-solid text-[13px]'> | |||
| <span className='h-6 bg-gradient-to-r from-components-avatar-shape-fill-stop-0 to-components-avatar-shape-fill-stop-100 bg-clip-text align-middle font-semibold uppercase leading-6 text-shadow-shadow-1 opacity-90'>{workspace?.name[0]?.toLocaleUpperCase()}</span> | |||
| </div> | |||
| <div className='system-md-regular line-clamp-1 grow cursor-pointer overflow-hidden text-ellipsis text-text-secondary'>{workspace.name}</div> | |||
| @@ -96,7 +96,7 @@ const AppNav = () => { | |||
| link, | |||
| } | |||
| }) | |||
| setNavItems(navItems) | |||
| setNavItems(navItems as any) | |||
| } | |||
| }, [appsData, isCurrentWorkspaceEditor, setNavItems]) | |||
| @@ -122,7 +122,7 @@ const AppNav = () => { | |||
| text={t('common.menus.apps')} | |||
| activeSegment={['apps', 'app']} | |||
| link='/apps' | |||
| curNav={appDetail} | |||
| curNav={appDetail as any} | |||
| navs={navItems} | |||
| createText={t('common.menus.newApp')} | |||
| onCreate={openModal} | |||
| @@ -48,7 +48,7 @@ const DatasetNav = () => { | |||
| text={t('common.menus.datasets')} | |||
| activeSegment='datasets' | |||
| link='/datasets' | |||
| curNav={currentDataset as Omit<NavItem, 'link'>} | |||
| curNav={currentDataset as any} | |||
| navs={datasetItems.map(dataset => ({ | |||
| id: dataset.id, | |||
| name: dataset.name, | |||
| @@ -59,6 +59,7 @@ const DatasetNav = () => { | |||
| createText={t('common.menus.newDataset')} | |||
| onCreate={() => router.push(`${basePath}/datasets/create`)} | |||
| onLoadmore={handleLoadmore} | |||
| isApp={false} | |||
| /> | |||
| ) | |||
| } | |||
| @@ -20,22 +20,22 @@ const EnvNav = () => { | |||
| return ( | |||
| <div className={` | |||
| mr-4 flex h-[22px] items-center rounded-md border px-2 text-xs font-medium | |||
| mr-1 flex h-[22px] items-center rounded-md border px-2 text-xs font-medium | |||
| ${headerEnvClassName[langeniusVersionInfo.current_env]} | |||
| `}> | |||
| { | |||
| langeniusVersionInfo.current_env === 'TESTING' && ( | |||
| <> | |||
| <Beaker02 className='mr-1 h-3 w-3' /> | |||
| {t('common.environment.testing')} | |||
| <Beaker02 className='h-3 w-3' /> | |||
| <div className='ml-1 max-[1280px]:hidden'>{t('common.environment.testing')}</div> | |||
| </> | |||
| ) | |||
| } | |||
| { | |||
| langeniusVersionInfo.current_env === 'DEVELOPMENT' && ( | |||
| <> | |||
| <TerminalSquare className='mr-1 h-3 w-3' /> | |||
| {t('common.environment.development')} | |||
| <TerminalSquare className='h-3 w-3' /> | |||
| <div className='ml-1 max-[1280px]:hidden'>{t('common.environment.development')}</div> | |||
| </> | |||
| ) | |||
| } | |||
| @@ -27,10 +27,12 @@ const ExploreNav = ({ | |||
| )}> | |||
| { | |||
| activated | |||
| ? <RiPlanetFill className='mr-2 h-4 w-4' /> | |||
| : <RiPlanetLine className='mr-2 h-4 w-4' /> | |||
| ? <RiPlanetFill className='h-4 w-4' /> | |||
| : <RiPlanetLine className='h-4 w-4' /> | |||
| } | |||
| {t('common.menus.explore')} | |||
| <div className='ml-2 max-[1024px]:hidden'> | |||
| {t('common.menus.explore')} | |||
| </div> | |||
| </Link> | |||
| ) | |||
| } | |||
| @@ -1,9 +1,6 @@ | |||
| 'use client' | |||
| import { useCallback, useEffect } from 'react' | |||
| import { useCallback } from 'react' | |||
| import Link from 'next/link' | |||
| import { useBoolean } from 'ahooks' | |||
| import { useSelectedLayoutSegment } from 'next/navigation' | |||
| import { Bars3Icon } from '@heroicons/react/20/solid' | |||
| import AccountDropdown from './account-dropdown' | |||
| import AppNav from './app-nav' | |||
| import DatasetNav from './dataset-nav' | |||
| @@ -24,17 +21,15 @@ import { Plan } from '../billing/type' | |||
| import { useGlobalPublicStore } from '@/context/global-public-context' | |||
| const navClassName = ` | |||
| flex items-center relative mr-0 sm:mr-3 px-3 h-8 rounded-xl | |||
| flex items-center relative px-3 h-8 rounded-xl | |||
| font-medium text-sm | |||
| cursor-pointer | |||
| ` | |||
| const Header = () => { | |||
| const { isCurrentWorkspaceEditor, isCurrentWorkspaceDatasetOperator } = useAppContext() | |||
| const selectedSegment = useSelectedLayoutSegment() | |||
| const media = useBreakpoints() | |||
| const isMobile = media === MediaType.mobile | |||
| const [isShowNavMenu, { toggle, setFalse: hideNavMenu }] = useBoolean(false) | |||
| const { enableBilling, plan } = useProviderContext() | |||
| const { setShowPricingModal, setShowAccountSettingModal } = useModalContext() | |||
| const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) | |||
| @@ -46,23 +41,12 @@ const Header = () => { | |||
| setShowAccountSettingModal({ payload: 'billing' }) | |||
| }, [isFreePlan, setShowAccountSettingModal, setShowPricingModal]) | |||
| useEffect(() => { | |||
| hideNavMenu() | |||
| // eslint-disable-next-line react-hooks/exhaustive-deps | |||
| }, [selectedSegment]) | |||
| return ( | |||
| <div className='relative flex flex-1 items-center justify-between bg-background-body'> | |||
| <div className='flex items-center'> | |||
| {isMobile && <div | |||
| className='flex h-8 w-8 cursor-pointer items-center justify-center' | |||
| onClick={toggle} | |||
| > | |||
| <Bars3Icon className="h-4 w-4 text-gray-500" /> | |||
| </div>} | |||
| { | |||
| !isMobile | |||
| && <div className='flex shrink-0 items-center gap-1.5 self-stretch pl-3'> | |||
| <Link href="/apps" className='flex h-8 shrink-0 items-center justify-center gap-2 px-0.5'> | |||
| if (isMobile) { | |||
| return ( | |||
| <div className=''> | |||
| <div className='flex items-center justify-between px-2'> | |||
| <div className='flex items-center'> | |||
| <Link href="/apps" className='flex h-8 shrink-0 items-center justify-center px-0.5'> | |||
| {systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo | |||
| ? <img | |||
| src={systemFeatures.branding.workspace_logo} | |||
| @@ -71,59 +55,61 @@ const Header = () => { | |||
| /> | |||
| : <DifyLogo />} | |||
| </Link> | |||
| <div className='font-light text-divider-deep'>/</div> | |||
| <div className='flex items-center gap-0.5'> | |||
| <WorkspaceProvider> | |||
| <WorkplaceSelector /> | |||
| </WorkspaceProvider> | |||
| {enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />} | |||
| </div> | |||
| <div className='mx-1.5 shrink-0 font-light text-divider-deep'>/</div> | |||
| <WorkspaceProvider> | |||
| <WorkplaceSelector /> | |||
| </WorkspaceProvider> | |||
| {enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />} | |||
| </div> | |||
| } | |||
| </div > | |||
| {isMobile && ( | |||
| <div className='flex'> | |||
| <Link href="/apps" className='mr-4 flex items-center'> | |||
| {systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo | |||
| ? <img | |||
| src={systemFeatures.branding.workspace_logo} | |||
| className='block h-[22px] w-auto object-contain' | |||
| alt='logo' | |||
| /> | |||
| : <DifyLogo />} | |||
| </Link> | |||
| <div className='font-light text-divider-deep'>/</div> | |||
| {enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />} | |||
| </div > | |||
| )} | |||
| { | |||
| !isMobile && ( | |||
| <div className='absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center'> | |||
| {!isCurrentWorkspaceDatasetOperator && <ExploreNav className={navClassName} />} | |||
| {!isCurrentWorkspaceDatasetOperator && <AppNav />} | |||
| {(isCurrentWorkspaceEditor || isCurrentWorkspaceDatasetOperator) && <DatasetNav />} | |||
| {!isCurrentWorkspaceDatasetOperator && <ToolsNav className={navClassName} />} | |||
| <div className='flex items-center'> | |||
| <div className='mr-2'> | |||
| <PluginsNav /> | |||
| </div> | |||
| <AccountDropdown /> | |||
| </div> | |||
| ) | |||
| } | |||
| <div className='flex shrink-0 items-center pr-3'> | |||
| </div> | |||
| <div className='my-1 flex items-center justify-center space-x-1'> | |||
| {!isCurrentWorkspaceDatasetOperator && <ExploreNav className={navClassName} />} | |||
| {!isCurrentWorkspaceDatasetOperator && <AppNav />} | |||
| {(isCurrentWorkspaceEditor || isCurrentWorkspaceDatasetOperator) && <DatasetNav />} | |||
| {!isCurrentWorkspaceDatasetOperator && <ToolsNav className={navClassName} />} | |||
| </div> | |||
| </div> | |||
| ) | |||
| } | |||
| return ( | |||
| <div className='flex h-[60px] items-center'> | |||
| <div className='flex min-w-0 flex-[1] items-center pl-3 pr-2 min-[1280px]:pr-3'> | |||
| <Link href="/apps" className='flex h-8 shrink-0 items-center justify-center px-0.5'> | |||
| {systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo | |||
| ? <img | |||
| src={systemFeatures.branding.workspace_logo} | |||
| className='block h-[22px] w-auto object-contain' | |||
| alt='logo' | |||
| /> | |||
| : <DifyLogo />} | |||
| </Link> | |||
| <div className='mx-1.5 shrink-0 font-light text-divider-deep'>/</div> | |||
| <WorkspaceProvider> | |||
| <WorkplaceSelector /> | |||
| </WorkspaceProvider> | |||
| {enableBilling ? <PlanBadge allowHover sandboxAsUpgrade plan={plan.type} onClick={handlePlanClick} /> : <LicenseNav />} | |||
| </div> | |||
| <div className='flex items-center space-x-2'> | |||
| {!isCurrentWorkspaceDatasetOperator && <ExploreNav className={navClassName} />} | |||
| {!isCurrentWorkspaceDatasetOperator && <AppNav />} | |||
| {(isCurrentWorkspaceEditor || isCurrentWorkspaceDatasetOperator) && <DatasetNav />} | |||
| {!isCurrentWorkspaceDatasetOperator && <ToolsNav className={navClassName} />} | |||
| </div> | |||
| <div className='flex min-w-0 flex-[1] items-center justify-end pl-2 pr-3 min-[1280px]:pl-3'> | |||
| <EnvNav /> | |||
| <div className='mr-2'> | |||
| <PluginsNav /> | |||
| </div> | |||
| <AccountDropdown /> | |||
| </div> | |||
| { | |||
| (isMobile && isShowNavMenu) && ( | |||
| <div className='flex w-full flex-col gap-y-1 p-2'> | |||
| {!isCurrentWorkspaceDatasetOperator && <ExploreNav className={navClassName} />} | |||
| {!isCurrentWorkspaceDatasetOperator && <AppNav />} | |||
| {(isCurrentWorkspaceEditor || isCurrentWorkspaceDatasetOperator) && <DatasetNav />} | |||
| {!isCurrentWorkspaceDatasetOperator && <ToolsNav className={navClassName} />} | |||
| </div> | |||
| ) | |||
| } | |||
| </div > | |||
| </div> | |||
| ) | |||
| } | |||
| export default Header | |||
| @@ -46,7 +46,7 @@ const Nav = ({ | |||
| return ( | |||
| <div className={` | |||
| mr-0 flex h-8 shrink-0 items-center rounded-xl px-0.5 text-sm font-medium sm:mr-3 | |||
| flex h-8 max-w-[670px] shrink-0 items-center rounded-xl px-0.5 text-sm font-medium max-[1024px]:max-w-[400px] | |||
| ${isActivated && 'bg-components-main-nav-nav-button-bg-active font-semibold shadow-md'} | |||
| ${!curNav && !isActivated && 'hover:bg-components-main-nav-nav-button-bg-hover'} | |||
| `}> | |||
| @@ -61,7 +61,7 @@ const Nav = ({ | |||
| onMouseEnter={() => setHovered(true)} | |||
| onMouseLeave={() => setHovered(false)} | |||
| > | |||
| <div className='mr-2'> | |||
| <div> | |||
| { | |||
| (hovered && curNav) | |||
| ? <ArrowNarrowLeft className='h-4 w-4' /> | |||
| @@ -70,7 +70,9 @@ const Nav = ({ | |||
| : icon | |||
| } | |||
| </div> | |||
| {text} | |||
| <div className='ml-2 max-[1024px]:hidden'> | |||
| {text} | |||
| </div> | |||
| </div> | |||
| </Link> | |||
| { | |||
| @@ -53,136 +53,134 @@ const NavSelector = ({ curNav, navs, createText, isApp, onCreate, onLoadmore }: | |||
| }, 50), []) | |||
| return ( | |||
| <div className=""> | |||
| <Menu as="div" className="relative inline-block text-left"> | |||
| {({ open }) => ( | |||
| <> | |||
| <MenuButton className={cn( | |||
| 'hover:hover:bg-components-main-nav-nav-button-bg-active-hover group inline-flex h-7 w-full items-center justify-center rounded-[10px] pl-2 pr-2.5 text-[14px] font-semibold text-components-main-nav-nav-button-text-active', | |||
| open && 'bg-components-main-nav-nav-button-bg-active', | |||
| )}> | |||
| <div className='max-w-[180px] truncate' title={curNav?.name}>{curNav?.name}</div> | |||
| <RiArrowDownSLine | |||
| className={cn('ml-1 h-3 w-3 shrink-0 opacity-50 group-hover:opacity-100', open && '!opacity-100')} | |||
| aria-hidden="true" | |||
| /> | |||
| </MenuButton> | |||
| <MenuItems | |||
| className=" | |||
| absolute -left-11 right-0 mt-1.5 w-60 max-w-80 | |||
| origin-top-right divide-y divide-divider-regular rounded-lg bg-components-panel-bg-blur | |||
| shadow-lg | |||
| " | |||
| > | |||
| <div className="overflow-auto px-1 py-1" style={{ maxHeight: '50vh' }} onScroll={handleScroll}> | |||
| { | |||
| navs.map(nav => ( | |||
| <MenuItem key={nav.id}> | |||
| <div className='flex w-full cursor-pointer items-center truncate rounded-lg px-3 py-[6px] text-[14px] font-normal text-text-secondary hover:bg-state-base-hover' onClick={() => { | |||
| if (curNav?.id === nav.id) | |||
| return | |||
| setAppDetail() | |||
| router.push(nav.link) | |||
| }} title={nav.name}> | |||
| <div className='relative mr-2 h-6 w-6 rounded-md'> | |||
| <AppIcon size='tiny' iconType={nav.icon_type} icon={nav.icon} background={nav.icon_background} imageUrl={nav.icon_url} /> | |||
| {!!nav.mode && ( | |||
| <span className={cn( | |||
| 'absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 rounded border-[0.5px] border-[rgba(0,0,0,0.02)] bg-white p-0.5 shadow-sm', | |||
| )}> | |||
| {nav.mode === 'advanced-chat' && ( | |||
| <ChatBot className='h-2.5 w-2.5 text-[#1570EF]' /> | |||
| )} | |||
| {nav.mode === 'agent-chat' && ( | |||
| <CuteRobot className='h-2.5 w-2.5 text-indigo-600' /> | |||
| )} | |||
| {nav.mode === 'chat' && ( | |||
| <ChatBot className='h-2.5 w-2.5 text-[#1570EF]' /> | |||
| )} | |||
| {nav.mode === 'completion' && ( | |||
| <AiText className='h-2.5 w-2.5 text-[#0E9384]' /> | |||
| )} | |||
| {nav.mode === 'workflow' && ( | |||
| <Route className='h-2.5 w-2.5 text-[#f79009]' /> | |||
| )} | |||
| </span> | |||
| )} | |||
| </div> | |||
| <div className='truncate'> | |||
| {nav.name} | |||
| </div> | |||
| <Menu as="div" className="relative"> | |||
| {({ open }) => ( | |||
| <> | |||
| <MenuButton className={cn( | |||
| 'hover:hover:bg-components-main-nav-nav-button-bg-active-hover group inline-flex h-7 w-full items-center justify-center rounded-[10px] pl-2 pr-2.5 text-[14px] font-semibold text-components-main-nav-nav-button-text-active', | |||
| open && 'bg-components-main-nav-nav-button-bg-active', | |||
| )}> | |||
| <div className='max-w-[157px] truncate' title={curNav?.name}>{curNav?.name}</div> | |||
| <RiArrowDownSLine | |||
| className={cn('ml-1 h-3 w-3 shrink-0 opacity-50 group-hover:opacity-100', open && '!opacity-100')} | |||
| aria-hidden="true" | |||
| /> | |||
| </MenuButton> | |||
| <MenuItems | |||
| className=" | |||
| absolute -left-11 right-0 mt-1.5 w-60 max-w-80 | |||
| origin-top-right divide-y divide-divider-regular rounded-lg bg-components-panel-bg-blur | |||
| shadow-lg | |||
| " | |||
| > | |||
| <div className="overflow-auto px-1 py-1" style={{ maxHeight: '50vh' }} onScroll={handleScroll}> | |||
| { | |||
| navs.map(nav => ( | |||
| <MenuItem key={nav.id}> | |||
| <div className='flex w-full cursor-pointer items-center truncate rounded-lg px-3 py-[6px] text-[14px] font-normal text-text-secondary hover:bg-state-base-hover' onClick={() => { | |||
| if (curNav?.id === nav.id) | |||
| return | |||
| setAppDetail() | |||
| router.push(nav.link) | |||
| }} title={nav.name}> | |||
| <div className='relative mr-2 h-6 w-6 rounded-md'> | |||
| <AppIcon size='tiny' iconType={nav.icon_type} icon={nav.icon} background={nav.icon_background} imageUrl={nav.icon_url} /> | |||
| {!!nav.mode && ( | |||
| <span className={cn( | |||
| 'absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 rounded border-[0.5px] border-[rgba(0,0,0,0.02)] bg-white p-0.5 shadow-sm', | |||
| )}> | |||
| {nav.mode === 'advanced-chat' && ( | |||
| <ChatBot className='h-2.5 w-2.5 text-[#1570EF]' /> | |||
| )} | |||
| {nav.mode === 'agent-chat' && ( | |||
| <CuteRobot className='h-2.5 w-2.5 text-indigo-600' /> | |||
| )} | |||
| {nav.mode === 'chat' && ( | |||
| <ChatBot className='h-2.5 w-2.5 text-[#1570EF]' /> | |||
| )} | |||
| {nav.mode === 'completion' && ( | |||
| <AiText className='h-2.5 w-2.5 text-[#0E9384]' /> | |||
| )} | |||
| {nav.mode === 'workflow' && ( | |||
| <Route className='h-2.5 w-2.5 text-[#f79009]' /> | |||
| )} | |||
| </span> | |||
| )} | |||
| </div> | |||
| <div className='truncate'> | |||
| {nav.name} | |||
| </div> | |||
| </MenuItem> | |||
| )) | |||
| } | |||
| </div> | |||
| {!isApp && isCurrentWorkspaceEditor && ( | |||
| <MenuItem as="div" className='w-full p-1'> | |||
| <div onClick={() => onCreate('')} className={cn( | |||
| 'flex cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-base-hover ', | |||
| )}> | |||
| <div className='flex h-6 w-6 shrink-0 items-center justify-center rounded-[6px] border-[0.5px] border-divider-regular bg-background-default'> | |||
| <RiAddLine className='h-4 w-4 text-text-primary' /> | |||
| </div> | |||
| <div className='grow text-left text-[14px] font-normal text-text-secondary'>{createText}</div> | |||
| </MenuItem> | |||
| )) | |||
| } | |||
| </div> | |||
| {!isApp && isCurrentWorkspaceEditor && ( | |||
| <MenuItem as="div" className='w-full p-1'> | |||
| <div onClick={() => onCreate('')} className={cn( | |||
| 'flex cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-base-hover ', | |||
| )}> | |||
| <div className='flex h-6 w-6 shrink-0 items-center justify-center rounded-[6px] border-[0.5px] border-divider-regular bg-background-default'> | |||
| <RiAddLine className='h-4 w-4 text-text-primary' /> | |||
| </div> | |||
| </MenuItem> | |||
| )} | |||
| {isApp && isCurrentWorkspaceEditor && ( | |||
| <Menu as="div" className="relative h-full w-full"> | |||
| {({ open }) => ( | |||
| <> | |||
| <MenuButton className='w-full p-1'> | |||
| <div className={cn( | |||
| 'flex cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-base-hover', | |||
| open && '!bg-state-base-hover', | |||
| )}> | |||
| <div className='flex h-6 w-6 shrink-0 items-center justify-center rounded-[6px] border-[0.5px] border-divider-regular bg-background-default'> | |||
| <RiAddLine className='h-4 w-4 text-text-primary' /> | |||
| </div> | |||
| <div className='grow text-left text-[14px] font-normal text-text-secondary'>{createText}</div> | |||
| <RiArrowRightSLine className='h-3.5 w-3.5 shrink-0 text-text-primary' /> | |||
| <div className='grow text-left text-[14px] font-normal text-text-secondary'>{createText}</div> | |||
| </div> | |||
| </MenuItem> | |||
| )} | |||
| {isApp && isCurrentWorkspaceEditor && ( | |||
| <Menu as="div" className="relative h-full w-full"> | |||
| {({ open }) => ( | |||
| <> | |||
| <MenuButton className='w-full p-1'> | |||
| <div className={cn( | |||
| 'flex cursor-pointer items-center gap-2 rounded-lg px-3 py-[6px] hover:bg-state-base-hover', | |||
| open && '!bg-state-base-hover', | |||
| )}> | |||
| <div className='flex h-6 w-6 shrink-0 items-center justify-center rounded-[6px] border-[0.5px] border-divider-regular bg-background-default'> | |||
| <RiAddLine className='h-4 w-4 text-text-primary' /> | |||
| </div> | |||
| </MenuButton> | |||
| <Transition | |||
| as={Fragment} | |||
| enter="transition ease-out duration-100" | |||
| enterFrom="transform opacity-0 scale-95" | |||
| enterTo="transform opacity-100 scale-100" | |||
| leave="transition ease-in duration-75" | |||
| leaveFrom="transform opacity-100 scale-100" | |||
| leaveTo="transform opacity-0 scale-95" | |||
| > | |||
| <MenuItems className={cn( | |||
| 'absolute right-[-198px] top-[3px] z-10 min-w-[200px] rounded-lg bg-components-panel-bg-blur shadow-lg', | |||
| )}> | |||
| <div className='p-1'> | |||
| <div className={cn('flex cursor-pointer items-center rounded-lg px-3 py-[6px] font-normal text-text-secondary hover:bg-state-base-hover')} onClick={() => onCreate('blank')}> | |||
| <FilePlus01 className='mr-2 h-4 w-4 shrink-0 text-text-secondary' /> | |||
| {t('app.newApp.startFromBlank')} | |||
| </div> | |||
| <div className={cn('flex cursor-pointer items-center rounded-lg px-3 py-[6px] font-normal text-text-secondary hover:bg-state-base-hover')} onClick={() => onCreate('template')}> | |||
| <FilePlus02 className='mr-2 h-4 w-4 shrink-0 text-text-secondary' /> | |||
| {t('app.newApp.startFromTemplate')} | |||
| </div> | |||
| <div className='grow text-left text-[14px] font-normal text-text-secondary'>{createText}</div> | |||
| <RiArrowRightSLine className='h-3.5 w-3.5 shrink-0 text-text-primary' /> | |||
| </div> | |||
| </MenuButton> | |||
| <Transition | |||
| as={Fragment} | |||
| enter="transition ease-out duration-100" | |||
| enterFrom="transform opacity-0 scale-95" | |||
| enterTo="transform opacity-100 scale-100" | |||
| leave="transition ease-in duration-75" | |||
| leaveFrom="transform opacity-100 scale-100" | |||
| leaveTo="transform opacity-0 scale-95" | |||
| > | |||
| <MenuItems className={cn( | |||
| 'absolute right-[-198px] top-[3px] z-10 min-w-[200px] rounded-lg bg-components-panel-bg-blur shadow-lg', | |||
| )}> | |||
| <div className='p-1'> | |||
| <div className={cn('flex cursor-pointer items-center rounded-lg px-3 py-[6px] font-normal text-text-secondary hover:bg-state-base-hover')} onClick={() => onCreate('blank')}> | |||
| <FilePlus01 className='mr-2 h-4 w-4 shrink-0 text-text-secondary' /> | |||
| {t('app.newApp.startFromBlank')} | |||
| </div> | |||
| <div className={cn('flex cursor-pointer items-center rounded-lg px-3 py-[6px] font-normal text-text-secondary hover:bg-state-base-hover')} onClick={() => onCreate('template')}> | |||
| <FilePlus02 className='mr-2 h-4 w-4 shrink-0 text-text-secondary' /> | |||
| {t('app.newApp.startFromTemplate')} | |||
| </div> | |||
| <div className='border-t border-divider-regular p-1'> | |||
| <div className={cn('flex cursor-pointer items-center rounded-lg px-3 py-[6px] font-normal text-text-secondary hover:bg-state-base-hover')} onClick={() => onCreate('dsl')}> | |||
| <FileArrow01 className='mr-2 h-4 w-4 shrink-0 text-text-secondary' /> | |||
| {t('app.importDSL')} | |||
| </div> | |||
| </div> | |||
| <div className='border-t border-divider-regular p-1'> | |||
| <div className={cn('flex cursor-pointer items-center rounded-lg px-3 py-[6px] font-normal text-text-secondary hover:bg-state-base-hover')} onClick={() => onCreate('dsl')}> | |||
| <FileArrow01 className='mr-2 h-4 w-4 shrink-0 text-text-secondary' /> | |||
| {t('app.importDSL')} | |||
| </div> | |||
| </MenuItems> | |||
| </Transition> | |||
| </> | |||
| )} | |||
| </Menu> | |||
| )} | |||
| </MenuItems> | |||
| </> | |||
| )} | |||
| </Menu> | |||
| </div> | |||
| </div> | |||
| </MenuItems> | |||
| </Transition> | |||
| </> | |||
| )} | |||
| </Menu> | |||
| )} | |||
| </MenuItems> | |||
| </> | |||
| )} | |||
| </Menu> | |||
| ) | |||
| } | |||
| @@ -28,10 +28,12 @@ const ToolsNav = ({ | |||
| )}> | |||
| { | |||
| activated | |||
| ? <RiHammerFill className='mr-2 h-4 w-4' /> | |||
| : <RiHammerLine className='mr-2 h-4 w-4' /> | |||
| ? <RiHammerFill className='h-4 w-4' /> | |||
| : <RiHammerLine className='h-4 w-4' /> | |||
| } | |||
| {t('common.menus.tools')} | |||
| <div className='ml-2 max-[1024px]:hidden'> | |||
| {t('common.menus.tools')} | |||
| </div> | |||
| </Link> | |||
| ) | |||
| } | |||