import { isLiquidGlassSupported, LiquidGlassView } from "@callstack/liquid-glass"; import type { ComposerTriggerKind } from "@t3tools/shared/composerTrigger"; import type { ServerProviderSkill, ServerProviderSlashCommand } from "@t3tools/contracts"; import { SymbolView } from "expo-symbols"; import { memo } from "react"; import { Pressable, ScrollView, useColorScheme, View, type ViewStyle } from "react-native"; import { AppText as Text } from "../../components/AppText"; import { PierreEntryIcon } from "../../components/PierreEntryIcon"; export type ComposerCommandItem = | { readonly id: string; readonly type: "path"; readonly path: string; readonly kind: "file" | "directory"; readonly label: string; readonly description: string; } | { readonly id: string; readonly type: "slash-command"; readonly command: string; readonly label: string; readonly description: string; } | { readonly id: string; readonly type: "provider-slash-command"; readonly command: ServerProviderSlashCommand; readonly label: string; readonly description: string; } | { readonly id: string; readonly type: "skill"; readonly skill: ServerProviderSkill; readonly label: string; readonly description: string; }; interface ComposerCommandPopoverProps { readonly items: ReadonlyArray; readonly triggerKind: ComposerTriggerKind | null; readonly isLoading: boolean; readonly onSelect: (item: ComposerCommandItem) => void; } function PopoverSurface(props: { readonly children: React.ReactNode; readonly isDarkMode: boolean; readonly style?: ViewStyle; }) { const baseStyle: ViewStyle = { borderRadius: 16, overflow: "hidden", ...props.style, }; if (isLiquidGlassSupported) { return ( {props.children} ); } return ( {props.children} ); } function itemIcon(item: ComposerCommandItem) { switch (item.type) { case "slash-command": case "provider-slash-command": return "terminal" as const; case "skill": return "cube" as const; case "path": return null; } } function groupLabel(triggerKind: ComposerTriggerKind | null): string | null { switch (triggerKind) { case "slash-command": return "Commands"; case "skill": return "Skills"; case "path": return "Files"; default: return null; } } function emptyText(triggerKind: ComposerTriggerKind | null, isLoading: boolean): string { if (isLoading) { return triggerKind === "path" ? "Searching files…" : "Loading…"; } switch (triggerKind) { case "path": return "No matching files or folders."; case "skill": return "No skills found."; case "slash-command": return "No matching commands."; default: return "No results."; } } const CommandRow = memo(function CommandRow(props: { readonly item: ComposerCommandItem; readonly onPress: () => void; readonly isLast: boolean; }) { const iconName = itemIcon(props.item); const iconColor = "#a1a1aa"; return ( ({ flexDirection: "row", alignItems: "center", paddingHorizontal: 14, paddingVertical: 10, gap: 10, opacity: pressed ? 0.6 : 1, borderBottomWidth: props.isLast ? 0 : 0.5, borderBottomColor: "rgba(255,255,255,0.1)", })} > {props.item.type === "path" ? ( ) : iconName ? ( ) : null} {props.item.label} {props.item.description ? ( {props.item.description} ) : null} ); }); export const ComposerCommandPopover = memo(function ComposerCommandPopover( props: ComposerCommandPopoverProps, ) { const isDarkMode = useColorScheme() === "dark"; const label = groupLabel(props.triggerKind); return ( {label ? ( {label} ) : null} {props.items.length > 0 ? ( {props.items.map((item, index) => ( props.onSelect(item)} isLast={index === props.items.length - 1} /> ))} ) : ( {emptyText(props.triggerKind, props.isLoading)} )} ); });