| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- <script lang="ts">
- import { Toolbox } from '@lucide/svelte';
- import { untrack } from 'svelte';
- import * as toolsApi from '$lib/api/tools';
- import { Empty } from '$lib/components/common/empty';
- import { SelectDialog } from '$lib/components/common/select-dialog';
- import { Spinner } from '$lib/components/controls/spinner';
- import { ToolCard } from '$lib/components/tools/card';
- import type { IDRef, Tool } from '$lib/types/entities';
- let {
- workspaceId,
- multiple = true,
- open = $bindable(false),
- value = $bindable([]),
- onselect,
- }: {
- workspaceId: string;
- multiple?: boolean;
- open?: boolean;
- value?: IDRef[];
- onselect?: (tools: IDRef[]) => IDRef[];
- } = $props();
- let query = $state('');
- let loading = $state(false);
- let tools = $state<Tool[]>([]);
- const loadTools = async () => {
- if (loading || tools.length > 0) {
- return;
- }
- loading = true;
- try {
- tools = await toolsApi.list(workspaceId);
- } catch (error) {
- console.error('Failed to load tools', error);
- }
- loading = false;
- };
- $effect(() => {
- if (open) {
- untrack(() => {
- loadTools();
- });
- }
- });
- const select = (tool: Tool) => {
- const newValue = {
- type: tool.mode,
- id: tool.id,
- name: tool.name,
- icon: tool.icon,
- };
- if (multiple) {
- if (value.find((ref) => ref.id === tool.id)) {
- value = value.filter((t) => t.id !== tool.id);
- } else {
- value = [...value, newValue];
- }
- } else {
- value = [newValue];
- }
- if (onselect) {
- value = onselect(value);
- }
- };
- </script>
- <SelectDialog
- selected={value.map((ref) => ref.id)}
- title={multiple ? 'Select Tools' : 'Select Tool'}
- bind:open
- bind:query
- onsave={multiple ? () => (open = false) : undefined}
- >
- {#snippet content()}
- {#if loading}
- <div class="flex h-full w-full items-center justify-center gap-2">
- <Spinner />
- <div class="text-sm text-white/50">Loading Tools...</div>
- </div>
- {:else if tools.length === 0}
- <Empty icon={Toolbox}>
- {#snippet caption()}
- <div>No tools found</div>
- {/snippet}
- </Empty>
- {:else}
- <div class="grid grid-cols-2 gap-2">
- {#each tools as tool (tool.id)}
- <ToolCard
- class={value.find((ref) => ref.id === tool.id)
- ? 'border-primary/50 bg-primary/25 hover:border-primary/75 hover:bg-primary/50'
- : ''}
- {tool}
- onselect={() => select(tool)}
- />
- {/each}
- </div>
- {/if}
- {/snippet}
- </SelectDialog>
|