118 lines · 4.2 KB · TypeScript
RawDownload
import { createEffect, createSignal, For, Match, Show, Switch, type JSX } from "solid-js"import { Collapsible } from "./collapsible"import { Icon, IconProps } from "./icon" export type TriggerTitle = {  title: string  titleClass?: string  subtitle?: string  subtitleClass?: string  args?: string[]  argsClass?: string  action?: JSX.Element} const isTriggerTitle = (val: any): val is TriggerTitle => {  return (    typeof val === "object" && val !== null && "title" in val && (typeof Node === "undefined" || !(val instanceof Node))  )} export interface BasicToolProps {  icon: IconProps["name"]  trigger: TriggerTitle | JSX.Element  children?: JSX.Element  hideDetails?: boolean  defaultOpen?: boolean  forceOpen?: boolean  locked?: boolean  onSubtitleClick?: () => void} export function BasicTool(props: BasicToolProps) {  const [open, setOpen] = createSignal(props.defaultOpen ?? false)   createEffect(() => {    if (props.forceOpen) setOpen(true)  })   const handleOpenChange = (value: boolean) => {    if (props.locked && !value) return    setOpen(value)  }   return (    <Collapsible open={open()} onOpenChange={handleOpenChange}>      <Collapsible.Trigger>        <div data-component="tool-trigger">          <div data-slot="basic-tool-tool-trigger-content">            <Icon name={props.icon} size="small" />            <div data-slot="basic-tool-tool-info">              <Switch>                <Match when={isTriggerTitle(props.trigger) && props.trigger}>                  {(trigger) => (                    <div data-slot="basic-tool-tool-info-structured">                      <div data-slot="basic-tool-tool-info-main">                        <span                          data-slot="basic-tool-tool-title"                          classList={{                            [trigger().titleClass ?? ""]: !!trigger().titleClass,                          }}                        >                          {trigger().title}                        </span>                        <Show when={trigger().subtitle}>                          <span                            data-slot="basic-tool-tool-subtitle"                            classList={{                              [trigger().subtitleClass ?? ""]: !!trigger().subtitleClass,                              clickable: !!props.onSubtitleClick,                            }}                            onClick={(e) => {                              if (props.onSubtitleClick) {                                e.stopPropagation()                                props.onSubtitleClick()                              }                            }}                          >                            {trigger().subtitle}                          </span>                        </Show>                        <Show when={trigger().args?.length}>                          <For each={trigger().args}>                            {(arg) => (                              <span                                data-slot="basic-tool-tool-arg"                                classList={{                                  [trigger().argsClass ?? ""]: !!trigger().argsClass,                                }}                              >                                {arg}                              </span>                            )}                          </For>                        </Show>                      </div>                      <Show when={trigger().action}>{trigger().action}</Show>                    </div>                  )}                </Match>                <Match when={true}>{props.trigger as JSX.Element}</Match>              </Switch>            </div>          </div>          <Show when={props.children && !props.hideDetails && !props.locked}>            <Collapsible.Arrow />          </Show>        </div>      </Collapsible.Trigger>      <Show when={props.children && !props.hideDetails}>        <Collapsible.Content>{props.children}</Collapsible.Content>      </Show>    </Collapsible>  )} export function GenericTool(props: { tool: string; hideDetails?: boolean }) {  return <BasicTool icon="mcp" trigger={{ title: props.tool }} hideDetails={props.hideDetails} />}