'use client'; // The plugin UI kit: the app's own controls, for plugin iframes. Plugins get // it as `require('@plugin-host/ui')`; the runtime hands over this module, so // a plugin bundle carries none of it and always matches the app it runs in. // // Every component is built from the same Tailwind classes as its // counterpart in the app (named in each comment), and // ui-kit.test.tsx checks that those classes are still the app's. The CSS // comes from app/(sandbox)/plugin-kit.css, which scans this folder only, so // classes must be written out in full here (no string building). // // Each component's root carries `bk`, which scopes the CSS reset to kit // elements: a plugin's own markup keeps the browser defaults it was written // against. import * as React from 'react'; import { cn } from '@/lib/cn'; import { Button as AppButton } from '@/components/ui/button'; import { Input as AppInput } from '@/components/ui/input'; import { getFileIconByName, getFolderIcon } from '@/components/files/file-icons'; import { iconForName } from '@/components/icons/named'; import { Check, ChevronDown, ChevronRight, ChevronUp, Loader2, Puzzle, Search, X } from '@/components/icons'; import { isFloatingDropdownSupported, openFloatingDropdown, updateFloatingDropdown, closeFloatingDropdown, registerFloatingDropdownListener, } from './floating-dropdown-bridge'; type Children = { children?: React.ReactNode }; type Tone = 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'primary'; // ─── Icons ───────────────────────────────────────────────────── /** An app icon by name (the names api.ui.setActions takes). Unknown names show a puzzle piece. */ export function Icon({ name, size = 'md', className }: { name?: string; size?: 'xs' | 'sm' | 'md' | 'lg'; className?: string }) { const Glyph = (name ? iconForName(name) : null) ?? Puzzle; const sizeClass = { xs: 'w-3 h-3', sm: 'w-3.5 h-3.5', md: 'w-4 h-4', lg: 'w-5 h-5' }[size]; return