basic-tool.tsx 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { For, Match, Show, Switch, type JSX } from "solid-js"
  2. import { Collapsible } from "./collapsible"
  3. import { Icon, IconProps } from "./icon"
  4. export type TriggerTitle = {
  5. title: string
  6. titleClass?: string
  7. subtitle?: string
  8. subtitleClass?: string
  9. args?: string[]
  10. argsClass?: string
  11. action?: JSX.Element
  12. }
  13. const isTriggerTitle = (val: any): val is TriggerTitle => {
  14. return (
  15. typeof val === "object" && val !== null && "title" in val && (typeof Node === "undefined" || !(val instanceof Node))
  16. )
  17. }
  18. export interface BasicToolProps {
  19. icon: IconProps["name"]
  20. trigger: TriggerTitle | JSX.Element
  21. children?: JSX.Element
  22. hideDetails?: boolean
  23. defaultOpen?: boolean
  24. }
  25. export function BasicTool(props: BasicToolProps) {
  26. return (
  27. <Collapsible defaultOpen={props.defaultOpen}>
  28. <Collapsible.Trigger>
  29. <div data-component="tool-trigger">
  30. <div data-slot="basic-tool-tool-trigger-content">
  31. <Icon name={props.icon} size="small" />
  32. <div data-slot="basic-tool-tool-info">
  33. <Switch>
  34. <Match when={isTriggerTitle(props.trigger) && props.trigger}>
  35. {(trigger) => (
  36. <div data-slot="basic-tool-tool-info-structured">
  37. <div data-slot="basic-tool-tool-info-main">
  38. <span
  39. data-slot="basic-tool-tool-title"
  40. classList={{
  41. [trigger().titleClass ?? ""]: !!trigger().titleClass,
  42. }}
  43. >
  44. {trigger().title}
  45. </span>
  46. <Show when={trigger().subtitle}>
  47. <span
  48. data-slot="basic-tool-tool-subtitle"
  49. classList={{
  50. [trigger().subtitleClass ?? ""]: !!trigger().subtitleClass,
  51. }}
  52. >
  53. {trigger().subtitle}
  54. </span>
  55. </Show>
  56. <Show when={trigger().args?.length}>
  57. <For each={trigger().args}>
  58. {(arg) => (
  59. <span
  60. data-slot="basic-tool-tool-arg"
  61. classList={{
  62. [trigger().argsClass ?? ""]: !!trigger().argsClass,
  63. }}
  64. >
  65. {arg}
  66. </span>
  67. )}
  68. </For>
  69. </Show>
  70. </div>
  71. <Show when={trigger().action}>{trigger().action}</Show>
  72. </div>
  73. )}
  74. </Match>
  75. <Match when={true}>{props.trigger as JSX.Element}</Match>
  76. </Switch>
  77. </div>
  78. </div>
  79. <Show when={props.children && !props.hideDetails}>
  80. <Collapsible.Arrow />
  81. </Show>
  82. </div>
  83. </Collapsible.Trigger>
  84. <Show when={props.children && !props.hideDetails}>
  85. <Collapsible.Content>{props.children}</Collapsible.Content>
  86. </Show>
  87. </Collapsible>
  88. )
  89. }
  90. export function GenericTool(props: { tool: string; hideDetails?: boolean }) {
  91. return <BasicTool icon="mcp" trigger={{ title: props.tool }} hideDetails={props.hideDetails} />
  92. }