/
Alex_Ural
/
opencode
Обзор
Документация
Войти
/
Alex_Ural
/
opencode
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
packages/session-ui/src/v2/components/basic-tool-v2.tsx
139 строк
5 KB
Victor Navarro
refactor(ui): isolate session components (#33670)
24 июн 2026, 17:56
Не верифицирован
24 июн 2026, 17:56
04c1730
Код
Авторство
О чём код?
import { Collapsible } from "@kobalte/core/collapsible" import { type ComponentProps, type JSX, For, Show, createMemo, splitProps } from "solid-js" import { DiffChanges } from "@opencode-ai/ui/v2/diff-changes-v2" import { TextShimmerV2 } from "@opencode-ai/ui/v2/text-shimmer-v2" import "./basic-tool-v2.css" function ChevronIcon() { return ( <svg data-slot="basic-tool-v2-chevron" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" > <path d="M6.75194 10.6243C6.41861 10.8187 6 10.5783 6 10.1924V5.80837C6 5.42247 6.41861 5.18204 6.75194 5.37648L10.5096 7.56846C10.8404 7.7614 10.8404 8.2393 10.5096 8.43224L6.75194 10.6243Z" fill="currentColor" /> </svg> ) } export interface BasicToolV2TriggerTitle { title: string subtitle?: string args?: string[] changes?: { additions: number; deletions: number } | { additions: number; deletions: number }[] action?: JSX.Element } const isTriggerTitle = (val: unknown): val is BasicToolV2TriggerTitle => typeof val === "object" && val !== null && "title" in val && (typeof Node === "undefined" || !(val instanceof Node)) export interface BasicToolV2Props extends Omit<ComponentProps<"div">, "children" | "title"> { trigger: BasicToolV2TriggerTitle | JSX.Element children?: JSX.Element status?: string open?: boolean defaultOpen?: boolean onOpenChange?: (open: boolean) => void onSubtitleClick?: () => void } export function BasicToolV2(props: BasicToolV2Props) { const [local, rest] = splitProps(props, [ "trigger", "children", "status", "open", "defaultOpen", "onOpenChange", "onSubtitleClick", "class", "classList", ]) const pending = createMemo(() => local.status === "pending" || local.status === "running") const hasChildren = createMemo(() => { const c = local.children if (c == null) return false return true }) const canExpand = createMemo(() => hasChildren() && !pending()) const handleOpenChange = (value: boolean) => { if (pending()) return local.onOpenChange?.(value) } return ( <Collapsible {...rest} data-component="basic-tool-v2" open={local.open} defaultOpen={local.defaultOpen} onOpenChange={handleOpenChange} disabled={!canExpand()} classList={{ ...local.classList, [local.class ?? ""]: !!local.class, }} > <Collapsible.Trigger as="div" role="button" data-slot="basic-tool-v2-trigger"> <div data-slot="basic-tool-v2-labels"> <Show when={isTriggerTitle(local.trigger) && local.trigger} fallback={local.trigger as JSX.Element}> {(title) => ( <> <span data-slot="basic-tool-v2-title"> <TextShimmerV2 text={title().title} active={pending()} /> </span> <Show when={!pending() && title().subtitle}> <span data-slot="basic-tool-v2-sep" aria-hidden="true"> · </span> <span data-slot="basic-tool-v2-subtitle" style={local.onSubtitleClick ? { cursor: "pointer" } : undefined} onClick={(e) => { if (local.onSubtitleClick) { e.stopPropagation() local.onSubtitleClick() } }} > {title().subtitle} </span> </Show> <Show when={!pending() && title().args?.length}> <For each={title().args}>{(arg) => <span data-slot="basic-tool-v2-arg">{arg}</span>}</For> </Show> <Show when={!pending() && title().changes}> <span data-slot="basic-tool-v2-diff"> <DiffChanges changes={title().changes!} /> </span> </Show> <Show when={!pending() && title().action}>{(action) => action()}</Show> </> )} </Show> <Show when={canExpand()}> <span data-slot="basic-tool-v2-chevron-wrap"> <ChevronIcon /> </span> </Show> </div> </Collapsible.Trigger> <Show when={canExpand()}> <Collapsible.Content data-slot="basic-tool-v2-content"> <div data-slot="basic-tool-v2-content-inner">{local.children}</div> </Collapsible.Content> </Show> </Collapsible> ) }