improvement(cleanup): remove unused old ui components (#3589)

This commit is contained in:
Waleed
2026-03-14 15:08:44 -07:00
committed by GitHub
parent 5ba3118495
commit cbc9f4248c
39 changed files with 38 additions and 977 deletions
@@ -1,6 +1,6 @@
'use client'
import { Skeleton } from '@/components/ui/skeleton'
import { Skeleton } from '@/components/emcn'
export function ChatLoadingState() {
return (
@@ -1,6 +1,6 @@
'use client'
import { Skeleton } from '@/components/ui/skeleton'
import { Skeleton } from '@/components/emcn'
import AuthBackground from '@/app/(auth)/components/auth-background'
export function FormLoadingState() {
+1 -1
View File
@@ -27,8 +27,8 @@ import {
PopoverContent,
PopoverItem,
PopoverTrigger,
Skeleton,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui/skeleton'
import { VerifiedBadge } from '@/components/ui/verified-badge'
import { useSession } from '@/lib/auth/auth-client'
import { cn } from '@/lib/core/utils/cn'
@@ -23,9 +23,9 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
Tooltip,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui/skeleton'
import { cn } from '@/lib/core/utils/cn'
import {
getCanonicalScopesForProvider,
@@ -19,8 +19,8 @@ import {
ModalTabsContent,
ModalTabsList,
ModalTabsTrigger,
Skeleton,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui/skeleton'
import { CONNECTOR_REGISTRY } from '@/connectors/registry'
import type { ConnectorConfig } from '@/connectors/types'
import type { ConnectorData } from '@/hooks/queries/kb/connectors'
@@ -2,7 +2,7 @@
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Loader2 } from 'lucide-react'
import { Skeleton } from '@/components/ui/skeleton'
import { Skeleton } from '@/components/emcn'
import { formatLatency } from '@/app/workspace/[workspaceId]/logs/utils'
import type { DashboardStatsResponse, WorkflowStats } from '@/hooks/queries/logs'
import { useFilterStore } from '@/stores/logs/filters/store'
@@ -16,7 +16,6 @@ import {
Tooltip,
} from '@/components/emcn'
import { Copy as CopyIcon, Search as SearchIcon } from '@/components/emcn/icons'
import { ScrollArea } from '@/components/ui/scroll-area'
import { BASE_EXECUTION_CHARGE } from '@/lib/billing/constants'
import { cn } from '@/lib/core/utils/cn'
import { formatDuration } from '@/lib/core/utils/formatting'
@@ -396,7 +395,7 @@ export const LogDetails = memo(function LogDetails({
</div>
{/* Content - Scrollable */}
<ScrollArea className='mt-[20px] h-full w-full overflow-y-auto' ref={scrollAreaRef}>
<div className='mt-[20px] h-full w-full overflow-y-auto' ref={scrollAreaRef}>
<div className='flex flex-col gap-[10px] pb-[16px]'>
{/* Timestamp & Workflow Row */}
<div className='flex min-w-0 items-center gap-[16px] px-[1px]'>
@@ -632,7 +631,7 @@ export const LogDetails = memo(function LogDetails({
</div>
)}
</div>
</ScrollArea>
</div>
</div>
)}
@@ -2,8 +2,7 @@
import { useMemo } from 'react'
import { X } from 'lucide-react'
import { Badge, Combobox, type ComboboxOption, Label } from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { Badge, Combobox, type ComboboxOption, Label, Skeleton } from '@/components/emcn'
import { useWorkflows } from '@/hooks/queries/workflows'
interface WorkflowSelectorProps {
@@ -18,11 +18,11 @@ import {
ModalTabsContent,
ModalTabsList,
ModalTabsTrigger,
Skeleton,
TagInput,
type TagItem,
} from '@/components/emcn'
import { SlackIcon } from '@/components/icons'
import { Skeleton } from '@/components/ui'
import { dollarsToCredits } from '@/lib/billing/credits/conversion'
import { getTriggerOptions } from '@/lib/logs/get-trigger-options'
import { quickValidateEmail } from '@/lib/messaging/email/validation'
@@ -11,10 +11,11 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
Switch,
Tooltip,
} from '@/components/emcn'
import { Input, Skeleton } from '@/components/ui'
import { Input } from '@/components/ui'
import { useSession } from '@/lib/auth/auth-client'
import { formatDate } from '@/lib/core/utils/formatting'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
@@ -17,11 +17,12 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
TagInput,
type TagItem,
} from '@/components/emcn'
import { GmailIcon, OutlookIcon } from '@/components/icons'
import { Input as BaseInput, Skeleton } from '@/components/ui'
import { Input as BaseInput } from '@/components/ui'
import { useSession } from '@/lib/auth/auth-client'
import { getSubscriptionStatus } from '@/lib/billing/client'
import { cn } from '@/lib/core/utils/cn'
@@ -17,11 +17,12 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
Textarea,
Tooltip,
Trash,
} from '@/components/emcn'
import { Input, Skeleton } from '@/components/ui'
import { Input } from '@/components/ui'
import { useSession } from '@/lib/auth/auth-client'
import {
clearPendingCredentialCreateRequest,
@@ -17,10 +17,11 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
Textarea,
Tooltip,
} from '@/components/emcn'
import { Skeleton, Input as UiInput } from '@/components/ui'
import { Input as UiInput } from '@/components/ui'
import { useSession } from '@/lib/auth/auth-client'
import {
clearPendingCredentialCreateRequest,
@@ -14,10 +14,10 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
Switch,
Tooltip,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { useSession, useSubscription } from '@/lib/auth/auth-client'
import { USAGE_THRESHOLDS } from '@/lib/billing/client/consts'
import { useSubscriptionUpgrade } from '@/lib/billing/client/upgrade'
@@ -1,5 +1,4 @@
import { Badge, Button } from '@/components/emcn'
import { Skeleton } from '@/components/ui/skeleton'
import { Badge, Button, Skeleton } from '@/components/emcn'
import { checkEnterprisePlan } from '@/lib/billing/subscriptions/utils'
import { cn } from '@/lib/core/utils/cn'
@@ -2,8 +2,7 @@
import { useCallback, useEffect, useState } from 'react'
import { createLogger } from '@sim/logger'
import type { TagItem } from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { Skeleton, type TagItem } from '@/components/emcn'
import { useSession } from '@/lib/auth/auth-client'
import { getPlanTierCredits, getPlanTierDollars } from '@/lib/billing/plan-helpers'
import { checkEnterprisePlan } from '@/lib/billing/subscriptions/utils'
@@ -4,9 +4,8 @@ import { useEffect, useState } from 'react'
import { createLogger } from '@sim/logger'
import { Camera, Globe, Linkedin, Mail } from 'lucide-react'
import Image from 'next/image'
import { Button, Combobox, Input, Textarea } from '@/components/emcn'
import { Button, Combobox, Input, Skeleton, Textarea } from '@/components/emcn'
import { AgentIcon, xIcon as XIcon } from '@/components/icons'
import { Skeleton } from '@/components/ui/skeleton'
import { useSession } from '@/lib/auth/auth-client'
import { quickValidateEmail } from '@/lib/messaging/email/validation'
import type { CreatorProfileDetails } from '@/app/_types/creator-profile'
@@ -19,6 +19,7 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
SModalTabs,
SModalTabsBody,
SModalTabsContent,
@@ -27,7 +28,7 @@ import {
Textarea,
Tooltip,
} from '@/components/emcn'
import { Input, Skeleton } from '@/components/ui'
import { Input } from '@/components/ui'
import { getBaseUrl } from '@/lib/core/utils/urls'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import { useApiKeys } from '@/hooks/queries/api-keys'
@@ -12,11 +12,11 @@ import {
Code,
Input,
Label,
Skeleton,
TagInput,
Textarea,
Tooltip,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import type { AgentAuthentication, AgentCapabilities } from '@/lib/a2a/types'
import { getBaseUrl } from '@/lib/core/utils/urls'
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
@@ -9,9 +9,9 @@ import {
Code,
Combobox,
Label,
Skeleton,
Tooltip,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { OutputSelect } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/output-select/output-select'
interface WorkflowDeploymentInfo {
@@ -14,12 +14,13 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
TagInput,
type TagItem,
Textarea,
Tooltip,
} from '@/components/emcn'
import { Alert, AlertDescription, Skeleton } from '@/components/ui'
import { Alert, AlertDescription } from '@/components/ui'
import { getEnv, isTruthy } from '@/lib/core/config/env'
import { generatePassword } from '@/lib/core/security/encryption'
import { cn } from '@/lib/core/utils/cn'
@@ -8,12 +8,12 @@ import {
ButtonGroupItem,
Input,
Label,
Skeleton,
TagInput,
type TagItem,
Textarea,
Tooltip,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { isDev } from '@/lib/core/config/feature-flags'
import { cn } from '@/lib/core/utils/cn'
import { getBaseUrl, getEmailDomain } from '@/lib/core/utils/urls'
@@ -9,9 +9,9 @@ import {
PopoverContent,
PopoverItem,
PopoverTrigger,
Skeleton,
Tooltip,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { formatDateTime } from '@/lib/core/utils/formatting'
import type { WorkflowDeploymentVersionResponse } from '@/lib/workflows/persistence/utils'
import { useUpdateDeploymentVersion } from '@/hooks/queries/deployments'
@@ -13,9 +13,9 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
Tooltip,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import type { WorkflowDeploymentVersionResponse } from '@/lib/workflows/persistence/utils'
import { Preview, PreviewWorkflow } from '@/app/workspace/[workspaceId]/w/components/preview'
import { useDeploymentVersionState, useRevertToVersion } from '@/hooks/queries/workflows'
@@ -10,9 +10,9 @@ import {
type ComboboxOption,
Input,
Label,
Skeleton,
Textarea,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { generateToolInputSchema, sanitizeToolName } from '@/lib/mcp/workflow-tool-schema'
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
@@ -12,10 +12,10 @@ import {
ModalContent,
ModalFooter,
ModalHeader,
Skeleton,
TagInput,
Textarea,
} from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { useSession } from '@/lib/auth/auth-client'
import { cn } from '@/lib/core/utils/cn'
import { captureAndUploadOGImage, OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH } from '@/lib/og'
@@ -3,8 +3,7 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
import { createLogger } from '@sim/logger'
import { useQueryClient } from '@tanstack/react-query'
import { Badge } from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { Badge, Skeleton } from '@/components/emcn'
import { USAGE_PILL_COLORS, USAGE_THRESHOLDS } from '@/lib/billing/client/consts'
import { useSubscriptionUpgrade } from '@/lib/billing/client/upgrade'
import {
@@ -1,7 +1,6 @@
import { useEffect, useMemo, useState } from 'react'
import { Loader2, RotateCw, X } from 'lucide-react'
import { Badge, Button, Tooltip } from '@/components/emcn'
import { Skeleton } from '@/components/ui/skeleton'
import { Badge, Button, Skeleton, Tooltip } from '@/components/emcn'
import { useSession } from '@/lib/auth/auth-client'
import type { PermissionType } from '@/lib/workspaces/permissions/utils'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
-54
View File
@@ -1,54 +0,0 @@
import * as React from 'react'
import { cn } from '@/lib/core/utils/cn'
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn('rounded-lg border bg-card text-card-foreground shadow-sm', className)}
{...props}
/>
)
)
Card.displayName = 'Card'
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
)
)
CardHeader.displayName = 'CardHeader'
const CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn('font-semibold text-2xl leading-none tracking-tight', className)}
{...props}
/>
)
)
CardTitle.displayName = 'CardTitle'
const CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn('text-muted-foreground text-sm', className)} {...props} />
)
)
CardDescription.displayName = 'CardDescription'
const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
)
)
CardContent.displayName = 'CardContent'
const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />
)
)
CardFooter.displayName = 'CardFooter'
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
-11
View File
@@ -1,11 +0,0 @@
'use client'
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'
const Collapsible = CollapsiblePrimitive.Root
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
-184
View File
@@ -1,184 +0,0 @@
'use client'
import * as React from 'react'
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
import { Check, ChevronRight, Circle } from 'lucide-react'
import { cn } from '@/lib/core/utils/cn'
const DropdownMenu = DropdownMenuPrimitive.Root
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
const DropdownMenuGroup = DropdownMenuPrimitive.Group
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
const DropdownMenuSub = DropdownMenuPrimitive.Sub
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean
}
>(({ className, inset, children, ...props }, ref) => (
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
'flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
inset && 'pl-8',
className
)}
{...props}
>
{children}
<ChevronRight className='ml-auto' />
</DropdownMenuPrimitive.SubTrigger>
))
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=open]:animate-in',
className
)}
{...props}
/>
))
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] origin-[--radix-dropdown-menu-content-transform-origin] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=closed]:animate-out data-[state=open]:animate-in',
className
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
))
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
inset && 'pl-8',
className
)}
{...props}
/>
))
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className
)}
checked={checked}
{...props}
>
<span className='absolute left-2 flex h-3.5 w-3.5 items-center justify-center'>
<DropdownMenuPrimitive.ItemIndicator>
<Check className='h-4 w-4' />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
))
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pr-2 pl-8 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className
)}
{...props}
>
<span className='absolute left-2 flex h-3.5 w-3.5 items-center justify-center'>
<DropdownMenuPrimitive.ItemIndicator>
<Circle className='h-2 w-2 fill-current' />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
))
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Label
ref={ref}
className={cn('px-2 py-1.5 font-semibold text-sm', inset && 'pl-8', className)}
{...props}
/>
))
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn('-mx-1 my-1 h-px bg-muted', className)}
{...props}
/>
))
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
return <span className={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...props} />
}
DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'
export {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuGroup,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
}
-24
View File
@@ -1,7 +1,5 @@
export { Alert, AlertDescription, AlertTitle } from './alert'
export { Button, buttonVariants } from './button'
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './card'
export { Collapsible, CollapsibleContent, CollapsibleTrigger } from './collapsible'
export {
Dialog,
DialogClose,
@@ -14,28 +12,10 @@ export {
DialogTitle,
DialogTrigger,
} from './dialog'
export {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuPortal,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from './dropdown-menu'
export { Input } from './input'
export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from './input-otp'
export { Label } from './label'
export { Progress } from './progress'
export { ScrollArea, ScrollBar } from './scroll-area'
export { SearchHighlight } from './search-highlight'
export {
Select,
@@ -49,7 +29,3 @@ export {
SelectTrigger,
SelectValue,
} from './select'
export { Separator } from './separator'
export { Skeleton } from './skeleton'
export { TagInput } from './tag-input'
export { ToolCallCompletion, ToolCallExecution } from './tool-call'
-52
View File
@@ -1,52 +0,0 @@
'use client'
import * as React from 'react'
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'
import { cn } from '@/lib/core/utils/cn'
const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> & {
hideScrollbar?: boolean
}
>(({ className, children, hideScrollbar = false, ...props }, ref) => (
<ScrollAreaPrimitive.Root
ref={ref}
className={cn('relative overflow-hidden', className)}
{...props}
>
<ScrollAreaPrimitive.Viewport className='h-full w-full rounded-[inherit]'>
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar hidden={hideScrollbar} />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
))
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar> & {
hidden?: boolean
}
>(({ className, orientation = 'vertical', hidden = false, ...props }, ref) => (
<ScrollAreaPrimitive.ScrollAreaScrollbar
ref={ref}
orientation={orientation}
className={cn(
'flex touch-none select-none transition-colors',
orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-[1px]',
orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-[1px]',
hidden && 'pointer-events-none w-0 border-0 p-0 opacity-0',
className
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb
className={cn('relative flex-1 rounded-full bg-border', hidden && 'hidden')}
/>
</ScrollAreaPrimitive.ScrollAreaScrollbar>
))
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
export { ScrollArea, ScrollBar }
-25
View File
@@ -1,25 +0,0 @@
'use client'
import * as React from 'react'
import * as SeparatorPrimitive from '@radix-ui/react-separator'
import { cn } from '@/lib/core/utils/cn'
const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (
<SeparatorPrimitive.Root
ref={ref}
decorative={decorative}
orientation={orientation}
className={cn(
'shrink-0 bg-border',
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
className
)}
{...props}
/>
))
Separator.displayName = SeparatorPrimitive.Root.displayName
export { Separator }
-7
View File
@@ -1,7 +0,0 @@
import { cn } from '@/lib/core/utils/cn'
function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
return <div className={cn('animate-pulse rounded-md bg-muted', className)} {...props} />
}
export { Skeleton }
-112
View File
@@ -1,112 +0,0 @@
'use client'
import { type KeyboardEvent, useRef, useState } from 'react'
import { X } from 'lucide-react'
import { Input } from '@/components/ui/input'
import { cn } from '@/lib/core/utils/cn'
interface TagInputProps {
value: string[]
onChange: (tags: string[]) => void
placeholder?: string
maxTags?: number
disabled?: boolean
className?: string
}
export function TagInput({
value = [],
onChange,
placeholder = 'Type and press Enter',
maxTags = 10,
disabled = false,
className,
}: TagInputProps) {
const [inputValue, setInputValue] = useState('')
const inputRef = useRef<HTMLInputElement>(null)
const addTag = (tag: string) => {
const trimmedTag = tag.trim()
if (trimmedTag && !value.includes(trimmedTag) && value.length < maxTags) {
onChange([...value, trimmedTag])
setInputValue('')
}
}
const removeTag = (tagToRemove: string) => {
onChange(value.filter((tag) => tag !== tagToRemove))
}
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter' && inputValue.trim()) {
e.preventDefault()
addTag(inputValue)
} else if (e.key === 'Backspace' && !inputValue && value.length > 0) {
removeTag(value[value.length - 1])
}
}
const handleBlur = () => {
if (inputValue.trim()) {
addTag(inputValue)
}
}
return (
<div
className={cn(
'scrollbar-hide flex max-h-32 min-h-9 flex-wrap items-center gap-x-[8px] gap-y-[4px] overflow-y-auto rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-5)] px-[6px] py-[4px] focus-within:outline-none',
disabled && 'cursor-not-allowed opacity-50',
className
)}
onClick={() => !disabled && inputRef.current?.focus()}
>
{value.map((tag) => (
<Tag key={tag} value={tag} onRemove={() => removeTag(tag)} disabled={disabled} />
))}
{!disabled && value.length < maxTags && (
<Input
ref={inputRef}
type='text'
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
placeholder={value.length === 0 ? placeholder : ''}
disabled={disabled}
className={cn(
'h-6 min-w-[180px] flex-1 border-none bg-transparent p-0 font-medium font-sans text-sm placeholder:text-[var(--text-muted)] focus-visible:ring-0 focus-visible:ring-offset-0',
value.length > 0 ? 'pl-[4px]' : 'pl-[4px]'
)}
/>
)}
</div>
)
}
interface TagProps {
value: string
onRemove: () => void
disabled?: boolean
}
function Tag({ value, onRemove, disabled }: TagProps) {
return (
<div className='flex w-auto items-center gap-[4px] rounded-[4px] border border-[var(--border-1)] bg-[var(--surface-4)] px-[6px] py-[2px] text-[12px] text-[var(--text-secondary)] hover:text-[var(--text-primary)]'>
<span className='max-w-[200px] truncate'>{value}</span>
{!disabled && (
<button
type='button'
onClick={(e) => {
e.stopPropagation()
onRemove()
}}
className='flex-shrink-0 text-[var(--text-tertiary)] transition-colors hover:text-[var(--text-primary)] focus:outline-none'
aria-label={`Remove ${value}`}
>
<X className='h-[12px] w-[12px] translate-y-[0.2px]' />
</button>
)}
</div>
)
}
-469
View File
@@ -1,469 +0,0 @@
'use client'
import { useState } from 'react'
import { CheckCircle, ChevronDown, ChevronRight, Loader2, Settings, XCircle } from 'lucide-react'
import { Badge } from '@/components/emcn'
import { Button } from '@/components/ui/button'
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
import { cn } from '@/lib/core/utils/cn'
import { formatDuration } from '@/lib/core/utils/formatting'
interface ToolCallState {
id: string
name: string
displayName?: string
parameters?: Record<string, unknown>
state:
| 'detecting'
| 'pending'
| 'executing'
| 'completed'
| 'error'
| 'rejected'
| 'applied'
| 'ready_for_review'
| 'aborted'
| 'skipped'
| 'background'
startTime?: number
endTime?: number
duration?: number
result?: unknown
error?: string
progress?: string
}
interface ToolCallGroup {
id: string
toolCalls: ToolCallState[]
status: 'pending' | 'in_progress' | 'completed' | 'error'
startTime?: number
endTime?: number
summary?: string
}
interface ToolCallProps {
toolCall: ToolCallState
isCompact?: boolean
}
interface ToolCallGroupProps {
group: ToolCallGroup
isCompact?: boolean
}
interface ToolCallIndicatorProps {
type: 'status' | 'thinking' | 'execution'
content: string
toolNames?: string[]
}
// Detection State Component
export function ToolCallDetection({ content }: { content: string }) {
return (
<div className='flex min-w-0 items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-3 py-2 text-sm dark:border-blue-800 dark:bg-blue-950'>
<Loader2 className='h-4 w-4 shrink-0 animate-spin text-blue-600 dark:text-blue-400' />
<span className='min-w-0 truncate text-blue-800 dark:text-blue-200'>{content}</span>
</div>
)
}
// Execution State Component
export function ToolCallExecution({ toolCall, isCompact = false }: ToolCallProps) {
const [isExpanded, setIsExpanded] = useState(!isCompact)
return (
<div className='min-w-0 rounded-lg border border-amber-200 bg-amber-50 dark:border-amber-800 dark:bg-amber-950'>
<Collapsible open={isExpanded} onOpenChange={setIsExpanded}>
<CollapsibleTrigger asChild>
<Button
variant='ghost'
className='w-full min-w-0 justify-between px-3 py-4 hover:bg-amber-100 dark:hover:bg-amber-900'
>
<div className='flex min-w-0 items-center gap-2 overflow-hidden'>
<Settings className='h-4 w-4 shrink-0 animate-pulse text-amber-600 dark:text-amber-400' />
<span className='min-w-0 truncate font-mono text-amber-800 text-xs dark:text-amber-200'>
{toolCall.displayName || toolCall.name}
</span>
{toolCall.progress && (
<Badge
variant='outline'
className='shrink-0 text-amber-700 text-xs dark:text-amber-300'
>
{toolCall.progress}
</Badge>
)}
</div>
{isExpanded ? (
<ChevronDown className='h-4 w-4 shrink-0 text-amber-600 dark:text-amber-400' />
) : (
<ChevronRight className='h-4 w-4 shrink-0 text-amber-600 dark:text-amber-400' />
)}
</Button>
</CollapsibleTrigger>
<CollapsibleContent className='min-w-0 max-w-full px-3 pb-3'>
<div className='min-w-0 max-w-full space-y-2'>
<div className='flex items-center gap-2 text-amber-700 text-xs dark:text-amber-300'>
<Loader2 className='h-3 w-3 shrink-0 animate-spin' />
<span>Executing...</span>
</div>
{toolCall.parameters &&
Object.keys(toolCall.parameters).length > 0 &&
(toolCall.name === 'make_api_request' ||
toolCall.name === 'set_environment_variables' ||
toolCall.name === 'set_global_workflow_variables') && (
<div className='min-w-0 max-w-full rounded border border-amber-200 bg-amber-50 p-2 dark:border-amber-800 dark:bg-amber-950'>
{toolCall.name === 'make_api_request' ? (
<div className='w-full overflow-hidden rounded border border-muted bg-card'>
<div className='grid grid-cols-2 gap-0 border-muted/60 border-b bg-muted/40 px-2 py-1.5'>
<div className='font-medium text-[10px] text-muted-foreground uppercase tracking-wide'>
Method
</div>
<div className='font-medium text-[10px] text-muted-foreground uppercase tracking-wide'>
Endpoint
</div>
</div>
<div className='grid grid-cols-[auto_1fr] items-center gap-2 px-2 py-2'>
<div>
<span className='inline-flex rounded bg-muted px-1.5 py-0.5 font-mono text-muted-foreground text-xs'>
{String((toolCall.parameters as any).method || '').toUpperCase() ||
'GET'}
</span>
</div>
<div className='min-w-0'>
<span
className='block overflow-x-auto whitespace-nowrap font-mono text-foreground text-xs'
title={String((toolCall.parameters as any).url || '')}
>
{String((toolCall.parameters as any).url || '') || 'URL not provided'}
</span>
</div>
</div>
</div>
) : null}
{toolCall.name === 'set_environment_variables'
? (() => {
const variables =
(toolCall.parameters as any).variables &&
typeof (toolCall.parameters as any).variables === 'object'
? (toolCall.parameters as any).variables
: {}
const entries = Object.entries(variables)
return (
<div className='w-full overflow-hidden rounded border border-amber-200 bg-amber-50 dark:border-amber-800 dark:bg-amber-950'>
<div className='grid grid-cols-2 gap-0 border-amber-200/60 border-b px-2 py-1.5 dark:border-amber-800/60'>
<div className='font-medium text-[10px] text-amber-700 uppercase tracking-wide dark:text-amber-300'>
Name
</div>
<div className='font-medium text-[10px] text-amber-700 uppercase tracking-wide dark:text-amber-300'>
Value
</div>
</div>
{entries.length === 0 ? (
<div className='px-2 py-2 text-muted-foreground text-xs'>
No variables provided
</div>
) : (
<div className='divide-y divide-amber-200 dark:divide-amber-800'>
{entries.map(([k, v]) => (
<div
key={k}
className='grid grid-cols-[auto_1fr] items-center gap-2 px-2 py-1.5'
>
<div className='truncate font-medium text-amber-800 text-xs dark:text-amber-200'>
{k}
</div>
<div className='min-w-0'>
<span className='block overflow-x-auto whitespace-nowrap font-mono text-amber-700 text-xs dark:text-amber-300'>
{String(v)}
</span>
</div>
</div>
))}
</div>
)}
</div>
)
})()
: null}
{toolCall.name === 'set_global_workflow_variables'
? (() => {
const ops = Array.isArray((toolCall.parameters as any).operations)
? ((toolCall.parameters as any).operations as any[])
: []
return (
<div className='w-full overflow-hidden rounded border border-amber-200 bg-amber-50 dark:border-amber-800 dark:bg-amber-950'>
<div className='grid grid-cols-3 gap-0 border-amber-200/60 border-b px-2 py-1.5 dark:border-amber-800/60'>
<div className='font-medium text-[10px] text-amber-700 uppercase tracking-wide dark:text-amber-300'>
Name
</div>
<div className='font-medium text-[10px] text-amber-700 uppercase tracking-wide dark:text-amber-300'>
Type
</div>
<div className='font-medium text-[10px] text-amber-700 uppercase tracking-wide dark:text-amber-300'>
Value
</div>
</div>
{ops.length === 0 ? (
<div className='px-2 py-2 text-muted-foreground text-xs'>
No operations provided
</div>
) : (
<div className='divide-y divide-amber-200 dark:divide-amber-800'>
{ops.map((op, idx) => (
<div
key={idx}
className='grid grid-cols-3 items-center gap-0 px-2 py-1.5'
>
<div className='min-w-0'>
<span className='truncate text-amber-800 text-xs dark:text-amber-200'>
{String(op.name || '')}
</span>
</div>
<div>
<span className='rounded border px-1 py-0.5 text-[10px] text-muted-foreground'>
{String(op.type || '')}
</span>
</div>
<div className='min-w-0'>
{op.value !== undefined ? (
<span className='block overflow-x-auto whitespace-nowrap font-mono text-amber-700 text-xs dark:text-amber-300'>
{String(op.value)}
</span>
) : (
<span className='text-muted-foreground text-xs'>—</span>
)}
</div>
</div>
))}
</div>
)}
</div>
)
})()
: null}
</div>
)}
</div>
</CollapsibleContent>
</Collapsible>
</div>
)
}
export function ToolCallCompletion({ toolCall, isCompact = false }: ToolCallProps) {
const [isExpanded, setIsExpanded] = useState(false)
const isSuccess = toolCall.state === 'completed'
const isError = toolCall.state === 'error'
const isAborted = toolCall.state === 'aborted'
return (
<div
className={cn(
'min-w-0 rounded-lg border',
isSuccess && 'border-green-200 bg-green-50 dark:border-green-800 dark:bg-green-950',
isError && 'border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950',
isAborted && 'border-orange-200 bg-orange-50 dark:border-orange-800 dark:bg-orange-950'
)}
>
<Collapsible open={isExpanded} onOpenChange={setIsExpanded}>
<CollapsibleTrigger asChild>
<Button
variant='ghost'
className={cn(
'w-full min-w-0 justify-between px-3 py-4',
isSuccess && 'hover:bg-green-100 dark:hover:bg-green-900',
isError && 'hover:bg-red-100 dark:hover:bg-red-900',
isAborted && 'hover:bg-orange-100 dark:hover:bg-orange-900'
)}
>
<div className='flex min-w-0 items-center gap-2 overflow-hidden'>
{isSuccess && (
<CheckCircle className='h-4 w-4 shrink-0 text-green-600 dark:text-green-400' />
)}
{isError && <XCircle className='h-4 w-4 shrink-0 text-red-600 dark:text-red-400' />}
{isAborted && (
<XCircle className='h-4 w-4 shrink-0 text-orange-600 dark:text-orange-400' />
)}
<span
className={cn(
'min-w-0 truncate font-mono text-xs',
isSuccess && 'text-green-800 dark:text-green-200',
isError && 'text-red-800 dark:text-red-200',
isAborted && 'text-orange-800 dark:text-orange-200'
)}
>
{toolCall.displayName || toolCall.name}
</span>
{toolCall.duration && (
<Badge
variant='outline'
className={cn(
'shrink-0 text-xs',
isSuccess && 'text-green-700 dark:text-green-300',
isError && 'text-red-700 dark:text-red-300',
isAborted && 'text-orange-700 dark:text-orange-300'
)}
style={{ fontSize: '0.625rem' }}
>
{toolCall.duration ? formatDuration(toolCall.duration, { precision: 1 }) : ''}
</Badge>
)}
</div>
<div className='flex shrink-0 items-center'>
{isExpanded ? (
<ChevronDown
className={cn(
'h-4 w-4',
isSuccess && 'text-green-600 dark:text-green-400',
isError && 'text-red-600 dark:text-red-400'
)}
/>
) : (
<ChevronRight
className={cn(
'h-4 w-4',
isSuccess && 'text-green-600 dark:text-green-400',
isError && 'text-red-600 dark:text-red-400'
)}
/>
)}
</div>
</Button>
</CollapsibleTrigger>
<CollapsibleContent className='min-w-0 max-w-full px-3 pb-3'>
<div className='min-w-0 max-w-full space-y-2'>
{toolCall.parameters &&
Object.keys(toolCall.parameters).length > 0 &&
(toolCall.name === 'make_api_request' ||
toolCall.name === 'set_environment_variables') && (
<div
className={cn(
'min-w-0 max-w-full rounded p-2',
isSuccess && 'bg-green-100 dark:bg-green-900',
isError && 'bg-red-100 dark:bg-red-900'
)}
>
<div
className={cn(
'mb-1 font-medium text-xs',
isSuccess && 'text-green-800 dark:text-green-200',
isError && 'text-red-800 dark:text-red-200'
)}
>
Parameters:
</div>
<div
className={cn(
'min-w-0 max-w-full break-all font-mono text-xs',
isSuccess && 'text-green-700 dark:text-green-300',
isError && 'text-red-700 dark:text-red-300'
)}
>
{JSON.stringify(toolCall.parameters, null, 2)}
</div>
</div>
)}
{toolCall.error && (
<div className='min-w-0 max-w-full rounded bg-red-100 p-2 dark:bg-red-900'>
<div className='mb-1 font-medium text-red-800 text-xs dark:text-red-200'>
Error:
</div>
<div className='min-w-0 max-w-full break-all font-mono text-red-700 text-xs dark:text-red-300'>
{toolCall.error}
</div>
</div>
)}
</div>
</CollapsibleContent>
</Collapsible>
</div>
)
}
// Group Component for Multiple Tool Calls
export function ToolCallGroupComponent({ group, isCompact = false }: ToolCallGroupProps) {
const [isExpanded, setIsExpanded] = useState(true)
const completedCount = group.toolCalls.filter((t) => t.state === 'completed').length
const totalCount = group.toolCalls.length
const isAllCompleted = completedCount === totalCount
const hasErrors = group.toolCalls.some((t) => t.state === 'error')
return (
<div className='min-w-0 space-y-2'>
{group.summary && (
<div className='flex min-w-0 items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-3 py-2 text-sm dark:border-blue-800 dark:bg-blue-950'>
<Settings className='h-4 w-4 shrink-0 text-blue-600 dark:text-blue-400' />
<span className='min-w-0 truncate text-blue-800 dark:text-blue-200'>{group.summary}</span>
{!isAllCompleted && (
<Badge variant='outline' className='shrink-0 text-blue-700 text-xs dark:text-blue-300'>
{completedCount}/{totalCount}
</Badge>
)}
</div>
)}
<Collapsible open={isExpanded} onOpenChange={setIsExpanded}>
<CollapsibleTrigger asChild>
<Button
variant='ghost'
className='w-full min-w-0 justify-between px-3 py-3 text-sm hover:bg-muted'
>
<div className='flex min-w-0 items-center gap-2 overflow-hidden'>
<span className='min-w-0 truncate text-muted-foreground'>
{isAllCompleted ? 'Completed' : 'In Progress'} ({completedCount}/{totalCount})
</span>
{hasErrors && (
<Badge variant='red' className='shrink-0 text-xs'>
Errors
</Badge>
)}
</div>
{isExpanded ? (
<ChevronDown className='h-4 w-4 shrink-0 text-muted-foreground' />
) : (
<ChevronRight className='h-4 w-4 shrink-0 text-muted-foreground' />
)}
</Button>
</CollapsibleTrigger>
<CollapsibleContent className='min-w-0 max-w-full space-y-2'>
{group.toolCalls.map((toolCall) => (
<div key={toolCall.id} className='min-w-0 max-w-full'>
{toolCall.state === 'executing' && (
<ToolCallExecution toolCall={toolCall} isCompact={isCompact} />
)}
{(toolCall.state === 'completed' || toolCall.state === 'error') && (
<ToolCallCompletion toolCall={toolCall} isCompact={isCompact} />
)}
</div>
))}
</CollapsibleContent>
</Collapsible>
</div>
)
}
// Status Indicator Component
export function ToolCallIndicator({ type, content, toolNames }: ToolCallIndicatorProps) {
if (type === 'status' && toolNames) {
return (
<div className='flex min-w-0 items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-3 py-2 text-sm dark:border-blue-800 dark:bg-blue-950'>
<Loader2 className='h-4 w-4 shrink-0 animate-spin text-blue-600 dark:text-blue-400' />
<span className='min-w-0 truncate text-blue-800 dark:text-blue-200'>
🔄 {toolNames.join(' • ')}
</span>
</div>
)
}
return (
<div className='flex min-w-0 items-center gap-2 rounded-lg border border-blue-200 bg-blue-50 px-3 py-2 text-sm dark:border-blue-800 dark:bg-blue-950'>
<Loader2 className='h-4 w-4 shrink-0 animate-spin text-blue-600 dark:text-blue-400' />
<span className='min-w-0 truncate text-blue-800 dark:text-blue-200'>{content}</span>
</div>
)
}
@@ -20,9 +20,10 @@ import {
ModalTabsContent,
ModalTabsList,
ModalTabsTrigger,
Skeleton,
Switch,
} from '@/components/emcn'
import { Input as BaseInput, Skeleton } from '@/components/ui'
import { Input as BaseInput } from '@/components/ui'
import { useSession } from '@/lib/auth/auth-client'
import { getSubscriptionStatus } from '@/lib/billing/client'
import type { PermissionGroupConfig } from '@/lib/permission-groups/types'
+1 -2
View File
@@ -3,8 +3,7 @@
import { useState } from 'react'
import { createLogger } from '@sim/logger'
import { Check, ChevronDown, Clipboard, Eye, EyeOff } from 'lucide-react'
import { Button, Combobox, Input, Switch, Textarea } from '@/components/emcn'
import { Skeleton } from '@/components/ui'
import { Button, Combobox, Input, Skeleton, Switch, Textarea } from '@/components/emcn'
import { useSession } from '@/lib/auth/auth-client'
import { getSubscriptionStatus } from '@/lib/billing/client/utils'
import { isBillingEnabled } from '@/lib/core/config/feature-flags'