File size: 4,729 Bytes
564e576
0c3e3b2
d433b55
564e576
 
 
 
 
 
d8a31e6
564e576
a1a6daf
 
 
 
 
564e576
 
a1a6daf
564e576
 
a1a6daf
d433b55
a1a6daf
 
 
 
 
fd7f926
0c3e3b2
d433b55
0c3e3b2
 
 
 
 
 
 
 
 
 
 
 
fd7f926
0c3e3b2
d433b55
0c3e3b2
d433b55
564e576
 
 
 
 
 
a1a6daf
564e576
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd7f926
564e576
 
 
835d3bc
564e576
 
 
 
 
fd7f926
 
a1a6daf
 
 
 
fd7f926
 
 
 
 
 
 
564e576
d433b55
0c3e3b2
 
 
 
 
 
 
d433b55
0c3e3b2
 
 
 
564e576
0c3e3b2
 
 
 
 
 
a1a6daf
 
 
0c3e3b2
 
 
 
 
 
 
 
 
 
 
a1a6daf
 
 
0c3e3b2
 
 
 
 
 
 
 
 
 
 
 
d8a31e6
 
 
 
 
 
564e576
 
 
 
 
a5070fd
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<script lang="ts">
	import { base } from "$app/paths";
	import { page } from "$app/state";
	import { clickOutside } from "$lib/actions/clickOutside";
	import { useSettingsStore } from "$lib/stores/settings";
	import type { ToolFront } from "$lib/types/Tool";
	import { isHuggingChat } from "$lib/utils/isHuggingChat";
	import IconTool from "./icons/IconTool.svelte";
	import CarbonInformation from "~icons/carbon/information";
	import CarbonGlobe from "~icons/carbon/earth-filled";

	interface Props {
		loading?: boolean;
	}

	let { loading = false }: Props = $props();
	const settings = useSettingsStore();

	let detailsEl: HTMLDetailsElement | undefined = $state();

	// active tools are all the checked tools, either from settings or on by default
	let activeToolCount = $derived(
		page.data.tools.filter(
			(tool: ToolFront) =>
				// community tools are always on by default
				tool.type === "community" || $settings?.tools?.includes(tool._id)
		).length
	);

	async function setAllTools(value: boolean) {
		const configToolsIds = page.data.tools
			.filter((t: ToolFront) => t.type === "config")
			.map((t: ToolFront) => t._id);

		if (value) {
			await settings.instantSet({
				tools: Array.from(new Set([...configToolsIds, ...($settings?.tools ?? [])])),
			});
		} else {
			await settings.instantSet({
				tools: [],
			});
		}
	}

	let allToolsEnabled = $derived(activeToolCount === page.data.tools.length);

	let tools = $derived(page.data.tools);
</script>

<details
	class="group relative bottom-0 h-full min-h-8"
	bind:this={detailsEl}
	use:clickOutside={() => {
		if (detailsEl?.hasAttribute("open")) {
			detailsEl.removeAttribute("open");
		}
	}}
>
	<summary
		class="absolute bottom-0 flex h-8
	cursor-pointer select-none items-center gap-1 rounded-lg border bg-white px-2 py-1.5 shadow-sm hover:shadow-none dark:border-gray-800 dark:bg-gray-900"
	>
		<IconTool classNames="dark:text-purple-600" />
		Tools
		<span class="text-gray-400 dark:text-gray-500"> ({activeToolCount}) </span>
	</summary>
	<div
		class="absolute bottom-10 h-max w-max select-none items-center gap-1 rounded-lg border bg-white p-0.5 shadow-sm dark:border-gray-800 dark:bg-gray-900"
	>
		<div class="grid grid-cols-2 gap-x-6 gap-y-1 p-3">
			<div class="col-span-2 flex items-center gap-1.5 text-sm text-gray-500">
				Available tools
				{#if isHuggingChat}
					<a
						href="https://huggingface.co./spaces/huggingchat/chat-ui/discussions/470"
						target="_blank"
						class="hover:brightness-0 dark:hover:brightness-200"
						><CarbonInformation class="text-xs" /></a
					>
				{/if}
				<button
					class="ml-auto text-xs underline"
					onclick={(e) => {
						e.stopPropagation();
						setAllTools(!allToolsEnabled);
					}}
				>
					{#if allToolsEnabled}
						Disable all
					{:else}
						Enable all
					{/if}
				</button>
			</div>
			{#if page.data.enableCommunityTools}
				<a
					href="{base}/tools"
					class="col-span-2 my-1 h-fit w-fit items-center justify-center rounded-full bg-purple-500/20 px-2.5 py-1.5 text-sm hover:bg-purple-500/30"
				>
					<span class="mr-1 rounded-full bg-purple-700 px-1.5 py-1 text-xs font-bold uppercase">
						new
					</span>
					Browse community tools ({page.data.communityToolCount ?? 0})
				</a>
			{/if}
			{#each tools as tool}
				{@const isChecked = $settings?.tools?.includes(tool._id)}
				<div class="flex items-center gap-1.5">
					{#if tool.type === "community"}
						<input
							type="checkbox"
							id={tool._id}
							checked={true}
							class="rounded-xs font-semibold accent-purple-500 hover:accent-purple-600"
							onclick={async (e) => {
								e.preventDefault();
								e.stopPropagation();
								await settings.instantSet({
									tools: $settings?.tools?.filter((t) => t !== tool._id) ?? [],
								});
							}}
						/>
					{:else}
						<input
							type="checkbox"
							id={tool._id}
							checked={isChecked}
							disabled={loading}
							onclick={async (e) => {
								e.preventDefault();
								e.stopPropagation();
								if (isChecked) {
									await settings.instantSet({
										tools: ($settings?.tools ?? []).filter((t) => t !== tool._id),
									});
								} else {
									await settings.instantSet({
										tools: [...($settings?.tools ?? []), tool._id],
									});
								}
							}}
						/>
					{/if}
					<label class="cursor-pointer" for={tool._id}>{tool.displayName}</label>
					{#if tool.type === "community"}
						<a href="{base}/tools/{tool._id}" class="text-purple-600 hover:text-purple-700">
							<CarbonGlobe />
						</a>
					{/if}
				</div>
			{/each}
		</div>
	</div>
</details>

<style>
	details summary::-webkit-details-marker {
		display: none;
	}
</style>