@ciridae/ui 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/blocks/mcp-access-grouped-tool-picker.d.ts +19 -0
- package/dist/components/blocks/mcp-access-grouped-tool-picker.js +116 -0
- package/dist/components/blocks/mcp-access-tool-picker-internals.d.ts +35 -0
- package/dist/components/blocks/mcp-access-tool-picker-internals.js +24 -0
- package/dist/components/blocks/mcp-access-tool-picker.d.ts +4 -17
- package/dist/components/blocks/mcp-access-tool-picker.js +4 -12
- package/dist/components/blocks/mcp-access-types.d.ts +2 -0
- package/dist/components/ui/checkbox.js +2 -2
- package/dist/entries/mcp-access-grouped-tool-picker.d.ts +1 -0
- package/dist/entries/mcp-access-grouped-tool-picker.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { McpToolInventoryState } from "./mcp-access-tool-picker-internals";
|
|
2
|
+
import type { McpAccessToolSelector } from "./mcp-access-types";
|
|
3
|
+
/**
|
|
4
|
+
* The tool picker for inventories big enough to need navigation: one scroll
|
|
5
|
+
* region grouped by each tool's first OpenAPI tag, each group split into Read
|
|
6
|
+
* and Actions with a select-all per split, and a filter box on top. An
|
|
7
|
+
* inventory with no tags renders as a single unlabeled group, so the split,
|
|
8
|
+
* the select-alls, and the filter still apply.
|
|
9
|
+
*
|
|
10
|
+
* Every change is rebuilt from the full inventory against the one shared
|
|
11
|
+
* selection, so a tool selected but hidden by the filter is never dropped —
|
|
12
|
+
* only the rows on screen, and the select-alls over them, can change it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function McpAccessGroupedToolPicker({ busy, inventory, selected, onChange, }: {
|
|
15
|
+
busy: boolean;
|
|
16
|
+
inventory: McpToolInventoryState;
|
|
17
|
+
selected: McpAccessToolSelector[];
|
|
18
|
+
onChange: (tools: McpAccessToolSelector[]) => void;
|
|
19
|
+
}): import("@types/react").JSX.Element;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Checkbox } from "../ui/checkbox";
|
|
4
|
+
import { Input } from "../ui/input";
|
|
5
|
+
import { Spinner } from "../ui/spinner";
|
|
6
|
+
import { EmptySelectionWarning, InventoryUnavailableNote, keyOf, PickerRow, } from "./mcp-access-tool-picker-internals";
|
|
7
|
+
const UNTAGGED_LABEL = "Other";
|
|
8
|
+
/**
|
|
9
|
+
* The tool picker for inventories big enough to need navigation: one scroll
|
|
10
|
+
* region grouped by each tool's first OpenAPI tag, each group split into Read
|
|
11
|
+
* and Actions with a select-all per split, and a filter box on top. An
|
|
12
|
+
* inventory with no tags renders as a single unlabeled group, so the split,
|
|
13
|
+
* the select-alls, and the filter still apply.
|
|
14
|
+
*
|
|
15
|
+
* Every change is rebuilt from the full inventory against the one shared
|
|
16
|
+
* selection, so a tool selected but hidden by the filter is never dropped —
|
|
17
|
+
* only the rows on screen, and the select-alls over them, can change it.
|
|
18
|
+
*/
|
|
19
|
+
export function McpAccessGroupedToolPicker({ busy, inventory, selected, onChange, }) {
|
|
20
|
+
const [query, setQuery] = useState("");
|
|
21
|
+
if (inventory.data === undefined) {
|
|
22
|
+
return _jsx(InventoryUnavailableNote, { isPending: inventory.isPending });
|
|
23
|
+
}
|
|
24
|
+
const tools = inventory.data.tools;
|
|
25
|
+
const selectedKeys = new Set(selected.map((tool) => keyOf(tool)));
|
|
26
|
+
const applyKeys = (keys, checked) => {
|
|
27
|
+
const next = new Set(selectedKeys);
|
|
28
|
+
for (const key of keys) {
|
|
29
|
+
if (checked)
|
|
30
|
+
next.add(key);
|
|
31
|
+
else
|
|
32
|
+
next.delete(key);
|
|
33
|
+
}
|
|
34
|
+
onChange(tools
|
|
35
|
+
.filter((tool) => next.has(keyOf(tool)))
|
|
36
|
+
.map((tool) => ({ method: tool.method, pathTemplate: tool.pathTemplate })));
|
|
37
|
+
};
|
|
38
|
+
const needle = query.trim().toLowerCase();
|
|
39
|
+
const groups = groupByFirstTag(tools);
|
|
40
|
+
const visibleGroups = groups
|
|
41
|
+
.map((group) => ({ ...group, visible: group.tools.filter((tool) => matches(tool, needle)) }))
|
|
42
|
+
.filter((group) => group.visible.length > 0);
|
|
43
|
+
const visibleCount = visibleGroups.reduce((count, group) => count + group.visible.length, 0);
|
|
44
|
+
const chosen = tools.filter((tool) => selectedKeys.has(keyOf(tool)));
|
|
45
|
+
return (_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)] gap-2", children: [_jsx(Input, { "aria-label": "Filter tools", className: "h-8 text-xs", onChange: (event) => {
|
|
46
|
+
setQuery(event.target.value);
|
|
47
|
+
}, placeholder: `Filter ${tools.length} tools…`, type: "search", value: query }), _jsx("div", { className: "max-h-96 overflow-y-auto rounded-md border border-border/60", children: visibleGroups.length === 0 ? (_jsx("p", { className: "text-muted-foreground px-3 py-2 text-xs", children: tools.length === 0 ? "This API exposes no tools." : "No tools match the filter." })) : (visibleGroups.map((group) => (_jsx(GroupSection, { busy: busy, group: group, onApply: applyKeys, selectedKeys: selectedKeys }, group.label ?? "")))) }), _jsx(PickerFooter, { busy: busy, chosen: chosen.length, matching: needle === "" ? null : visibleCount, total: tools.length })] }));
|
|
48
|
+
}
|
|
49
|
+
function PickerFooter({ busy, chosen, matching, total, }) {
|
|
50
|
+
return (_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [busy ? _jsx(Spinner, { "aria-label": "Saving selection", className: "text-muted-foreground" }) : null, _jsxs("p", { "aria-live": "polite", className: "text-muted-foreground text-xs", children: [chosen, " of ", total, " tools selected"] }), matching === null ? null : (_jsxs("p", { className: "text-muted-foreground text-xs", children: [matching, " match", matching === 1 ? "es" : "", " the filter"] })), chosen === 0 ? _jsx(EmptySelectionWarning, {}) : null] }));
|
|
51
|
+
}
|
|
52
|
+
function matches(tool, needle) {
|
|
53
|
+
if (needle === "")
|
|
54
|
+
return true;
|
|
55
|
+
return [tool.name, tool.description, `${tool.method} ${tool.pathTemplate}`].some((text) => text.toLowerCase().includes(needle));
|
|
56
|
+
}
|
|
57
|
+
/** One tag group: its sticky header with counts, then the Read and Actions runs. */
|
|
58
|
+
function GroupSection({ busy, group, selectedKeys, onApply, }) {
|
|
59
|
+
const chosenInGroup = group.tools.filter((tool) => selectedKeys.has(keyOf(tool))).length;
|
|
60
|
+
return (_jsxs("section", { children: [group.label === null ? null : (_jsxs("h4", { className: "bg-background sticky top-0 z-10 flex items-baseline justify-between gap-2 border-b border-border/60 px-3 py-1.5 font-mono text-xs font-semibold", children: [_jsx("span", { className: "truncate", children: group.label }), _jsxs("span", { className: "text-muted-foreground shrink-0 text-[10px] font-normal tabular-nums", children: [chosenInGroup, " / ", group.tools.length] })] })), [
|
|
61
|
+
{ label: "Read", rows: group.visible.filter((tool) => tool.readOnly) },
|
|
62
|
+
{ label: "Actions", rows: group.visible.filter((tool) => !tool.readOnly) },
|
|
63
|
+
].map(({ label, rows }) => rows.length === 0 ? null : (_jsx(SubsectionRows, { busy: busy, groupLabel: group.label, label: label, onApply: onApply, rows: rows, selectedKeys: selectedKeys }, label)))] }));
|
|
64
|
+
}
|
|
65
|
+
/** One Read or Actions run within a group: its header with select-all, then rows. */
|
|
66
|
+
function SubsectionRows({ busy, groupLabel, label, rows, selectedKeys, onApply, }) {
|
|
67
|
+
const rowKeys = rows.map((tool) => keyOf(tool));
|
|
68
|
+
const picked = rowKeys.filter((key) => selectedKeys.has(key)).length;
|
|
69
|
+
const allState = picked === 0 ? false : picked === rowKeys.length ? true : "indeterminate";
|
|
70
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-3 pt-2 pb-1", children: [_jsx("span", { className: label === "Actions"
|
|
71
|
+
? "text-primary text-[10px] font-semibold tracking-wide uppercase"
|
|
72
|
+
: "text-muted-foreground text-[10px] font-semibold tracking-wide uppercase", children: label }), _jsx(Checkbox, { "aria-label": `Select all ${label.toLowerCase()}${groupLabel === null ? "" : ` in ${groupLabel}`}`, checked: allState, disabled: busy, onCheckedChange: (next) => {
|
|
73
|
+
// The rows on screen only: with a filter active this is
|
|
74
|
+
// "select what I searched for", never the hidden rest.
|
|
75
|
+
onApply(rowKeys, next === true);
|
|
76
|
+
} })] }), _jsx("ul", { className: "divide-y divide-border/50", children: rows.map((tool) => (_jsx(PickerRow, { checked: selectedKeys.has(keyOf(tool)), disabled: busy,
|
|
77
|
+
// The subheader above already says Read or Actions.
|
|
78
|
+
kindBadge: false, onToggle: (key, checked) => {
|
|
79
|
+
onApply([key], checked);
|
|
80
|
+
}, tool: tool }, keyOf(tool)))) })] }));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Buckets by first tag in first-appearance order — a compiler emits tools in
|
|
84
|
+
* source order, so tag order is the API's own organization. Untagged tools
|
|
85
|
+
* trail as one "Other" bucket, unless nothing is tagged at all: then the one
|
|
86
|
+
* group is unlabeled rather than titled "Other" for no contrast.
|
|
87
|
+
*/
|
|
88
|
+
function groupByFirstTag(tools) {
|
|
89
|
+
const buckets = new Map();
|
|
90
|
+
for (const tool of tools) {
|
|
91
|
+
const firstTag = tool.tags?.[0];
|
|
92
|
+
if (firstTag === undefined)
|
|
93
|
+
continue;
|
|
94
|
+
const bucket = buckets.get(firstTag);
|
|
95
|
+
if (bucket)
|
|
96
|
+
bucket.push(tool);
|
|
97
|
+
else
|
|
98
|
+
buckets.set(firstTag, [tool]);
|
|
99
|
+
}
|
|
100
|
+
if (buckets.size === 0)
|
|
101
|
+
return [{ label: null, tools }];
|
|
102
|
+
const untagged = tools.filter((tool) => (tool.tags?.length ?? 0) === 0);
|
|
103
|
+
if (untagged.length > 0) {
|
|
104
|
+
// Into the real "Other" tag's bucket when one exists, so two groups
|
|
105
|
+
// never share a label (and with it a React key).
|
|
106
|
+
const bucket = buckets.get(UNTAGGED_LABEL);
|
|
107
|
+
if (bucket)
|
|
108
|
+
bucket.push(...untagged);
|
|
109
|
+
else
|
|
110
|
+
buckets.set(UNTAGGED_LABEL, untagged);
|
|
111
|
+
}
|
|
112
|
+
return [...buckets.entries()].map(([label, bucketTools]) => ({
|
|
113
|
+
label,
|
|
114
|
+
tools: bucketTools,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { McpAccessToolListing } from "./mcp-access-types";
|
|
2
|
+
/** The coordinate a selector and a compiled operation are matched on. */
|
|
3
|
+
export declare const keyOf: (tool: {
|
|
4
|
+
method: string;
|
|
5
|
+
pathTemplate: string;
|
|
6
|
+
}) => string;
|
|
7
|
+
/**
|
|
8
|
+
* The slice of the app's inventory query the pickers read, shaped so a
|
|
9
|
+
* TanStack Query result can be passed whole. `data` is `undefined` for both
|
|
10
|
+
* "still loading" and "failed to load"; `isPending` says which.
|
|
11
|
+
*/
|
|
12
|
+
export type McpToolInventoryState = {
|
|
13
|
+
data: {
|
|
14
|
+
tools: McpAccessToolListing[];
|
|
15
|
+
} | undefined;
|
|
16
|
+
isPending: boolean;
|
|
17
|
+
};
|
|
18
|
+
/** The one line an absent inventory renders, in both pickers. */
|
|
19
|
+
export declare function InventoryUnavailableNote({ isPending }: {
|
|
20
|
+
isPending: boolean;
|
|
21
|
+
}): import("@types/react").JSX.Element;
|
|
22
|
+
/** Why an empty selection blocks the mint, in both pickers' footers. */
|
|
23
|
+
export declare function EmptySelectionWarning(): import("@types/react").JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* One selectable tool row. `kindBadge` shows the read-only/action label — the
|
|
26
|
+
* flat list's only signal, redundant under the grouped picker's Read/Actions
|
|
27
|
+
* subheaders.
|
|
28
|
+
*/
|
|
29
|
+
export declare function PickerRow({ checked, disabled, kindBadge, tool, onToggle, }: {
|
|
30
|
+
checked: boolean;
|
|
31
|
+
disabled: boolean;
|
|
32
|
+
kindBadge: boolean;
|
|
33
|
+
tool: McpAccessToolListing;
|
|
34
|
+
onToggle: (key: string, checked: boolean) => void;
|
|
35
|
+
}): import("@types/react").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useId } from "react";
|
|
3
|
+
import { Checkbox } from "../ui/checkbox";
|
|
4
|
+
/** The coordinate a selector and a compiled operation are matched on. */
|
|
5
|
+
export const keyOf = (tool) => `${tool.method} ${tool.pathTemplate}`;
|
|
6
|
+
/** The one line an absent inventory renders, in both pickers. */
|
|
7
|
+
export function InventoryUnavailableNote({ isPending }) {
|
|
8
|
+
return (_jsx("p", { className: "text-muted-foreground text-xs", children: isPending ? "Loading the tool list…" : "Couldn't load the tool list." }));
|
|
9
|
+
}
|
|
10
|
+
/** Why an empty selection blocks the mint, in both pickers' footers. */
|
|
11
|
+
export function EmptySelectionWarning() {
|
|
12
|
+
return (_jsx("p", { className: "text-destructive text-xs", children: "Select at least one tool to generate a connection code." }));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* One selectable tool row. `kindBadge` shows the read-only/action label — the
|
|
16
|
+
* flat list's only signal, redundant under the grouped picker's Read/Actions
|
|
17
|
+
* subheaders.
|
|
18
|
+
*/
|
|
19
|
+
export function PickerRow({ checked, disabled, kindBadge, tool, onToggle, }) {
|
|
20
|
+
const id = useId();
|
|
21
|
+
return (_jsxs("li", { className: "flex min-h-11 items-start gap-3 px-3 py-2", children: [_jsx(Checkbox, { checked: checked, disabled: disabled, id: id, onCheckedChange: (next) => {
|
|
22
|
+
onToggle(keyOf(tool), next === true);
|
|
23
|
+
} }), _jsxs("label", { className: "min-w-0 flex-1 cursor-pointer", htmlFor: id, children: [kindBadge ? (_jsxs("span", { className: "flex flex-wrap items-center gap-x-2", children: [_jsx("span", { className: "truncate font-mono text-xs", children: tool.name }), _jsx("span", { className: "text-muted-foreground text-[10px] uppercase", children: tool.readOnly ? "read-only" : "action" })] })) : (_jsx("span", { className: "block truncate font-mono text-xs", children: tool.name })), _jsx("span", { className: "text-muted-foreground block truncate text-xs", children: tool.description })] })] }));
|
|
24
|
+
}
|
|
@@ -1,20 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
pathTemplate: string;
|
|
6
|
-
}) => string;
|
|
7
|
-
/**
|
|
8
|
-
* The slice of the app's inventory query the picker reads, shaped so a
|
|
9
|
-
* TanStack Query result can be passed whole. `data` is `undefined` for both
|
|
10
|
-
* "still loading" and "failed to load"; `isPending` says which.
|
|
11
|
-
*/
|
|
12
|
-
export type McpToolInventoryState = {
|
|
13
|
-
data: {
|
|
14
|
-
tools: McpAccessToolListing[];
|
|
15
|
-
} | undefined;
|
|
16
|
-
isPending: boolean;
|
|
17
|
-
};
|
|
1
|
+
import type { McpToolInventoryState } from "./mcp-access-tool-picker-internals";
|
|
2
|
+
import type { McpAccessToolSelector } from "./mcp-access-types";
|
|
3
|
+
export { keyOf } from "./mcp-access-tool-picker-internals";
|
|
4
|
+
export type { McpToolInventoryState } from "./mcp-access-tool-picker-internals";
|
|
18
5
|
/**
|
|
19
6
|
* An exact tool selection, applied as it is clicked. There is nothing to
|
|
20
7
|
* confirm: the list on screen is always what a code will be minted with, and an
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useId } from "react";
|
|
3
|
-
import { Checkbox } from "../ui/checkbox";
|
|
4
2
|
import { Spinner } from "../ui/spinner";
|
|
5
|
-
|
|
6
|
-
export
|
|
3
|
+
import { EmptySelectionWarning, InventoryUnavailableNote, keyOf, PickerRow, } from "./mcp-access-tool-picker-internals";
|
|
4
|
+
export { keyOf } from "./mcp-access-tool-picker-internals";
|
|
7
5
|
/**
|
|
8
6
|
* An exact tool selection, applied as it is clicked. There is nothing to
|
|
9
7
|
* confirm: the list on screen is always what a code will be minted with, and an
|
|
@@ -17,7 +15,7 @@ export const keyOf = (tool) => `${tool.method} ${tool.pathTemplate}`;
|
|
|
17
15
|
export function McpAccessToolPicker({ busy, inventory, selected, onChange, }) {
|
|
18
16
|
const selectedKeys = new Set(selected.map((tool) => keyOf(tool)));
|
|
19
17
|
if (inventory.data === undefined) {
|
|
20
|
-
return
|
|
18
|
+
return _jsx(InventoryUnavailableNote, { isPending: inventory.isPending });
|
|
21
19
|
}
|
|
22
20
|
const tools = inventory.data.tools;
|
|
23
21
|
const toggle = (key, checked) => {
|
|
@@ -31,11 +29,5 @@ export function McpAccessToolPicker({ busy, inventory, selected, onChange, }) {
|
|
|
31
29
|
.map((tool) => ({ method: tool.method, pathTemplate: tool.pathTemplate })));
|
|
32
30
|
};
|
|
33
31
|
const chosen = tools.filter((tool) => selectedKeys.has(keyOf(tool)));
|
|
34
|
-
return (_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)] gap-2", children: [_jsx("ul", { className: "max-h-64 divide-y divide-border/50 overflow-y-auto rounded-md border border-border/60", children: tools.map((tool) => (_jsx(PickerRow, { checked: selectedKeys.has(keyOf(tool)), disabled: busy, onToggle: toggle, tool: tool }, keyOf(tool)))) }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [busy ? _jsx(Spinner, { "aria-label": "Saving selection", className: "text-muted-foreground" }) : null, _jsxs("p", { "aria-live": "polite", className: "text-muted-foreground text-xs", children: [chosen.length, " of ", tools.length, " tools selected"] }), chosen.length === 0 ?
|
|
35
|
-
}
|
|
36
|
-
function PickerRow({ checked, disabled, tool, onToggle, }) {
|
|
37
|
-
const id = useId();
|
|
38
|
-
return (_jsxs("li", { className: "flex min-h-11 items-start gap-3 px-3 py-2", children: [_jsx(Checkbox, { checked: checked, disabled: disabled, id: id, onCheckedChange: (next) => {
|
|
39
|
-
onToggle(keyOf(tool), next === true);
|
|
40
|
-
} }), _jsxs("label", { className: "min-w-0 flex-1 cursor-pointer", htmlFor: id, children: [_jsxs("span", { className: "flex flex-wrap items-center gap-x-2", children: [_jsx("span", { className: "truncate font-mono text-xs", children: tool.name }), _jsx("span", { className: "text-muted-foreground text-[10px] uppercase", children: tool.readOnly ? "read-only" : "action" })] }), _jsx("span", { className: "block truncate text-muted-foreground text-xs", children: tool.description })] })] }));
|
|
32
|
+
return (_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)] gap-2", children: [_jsx("ul", { className: "max-h-64 divide-y divide-border/50 overflow-y-auto rounded-md border border-border/60", children: tools.map((tool) => (_jsx(PickerRow, { checked: selectedKeys.has(keyOf(tool)), disabled: busy, kindBadge: true, onToggle: toggle, tool: tool }, keyOf(tool)))) }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [busy ? _jsx(Spinner, { "aria-label": "Saving selection", className: "text-muted-foreground" }) : null, _jsxs("p", { "aria-live": "polite", className: "text-muted-foreground text-xs", children: [chosen.length, " of ", tools.length, " tools selected"] }), chosen.length === 0 ? _jsx(EmptySelectionWarning, {}) : null] })] }));
|
|
41
33
|
}
|
|
@@ -21,6 +21,8 @@ export type McpAccessToolListing = {
|
|
|
21
21
|
readOnly: boolean;
|
|
22
22
|
method: McpHttpMethod;
|
|
23
23
|
pathTemplate: string;
|
|
24
|
+
/** The operation's OpenAPI tags; the grouped picker buckets by the first. */
|
|
25
|
+
tags?: readonly string[];
|
|
24
26
|
};
|
|
25
27
|
/**
|
|
26
28
|
* What a mint produced, as the fields these controls report: the access the
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { CheckIcon } from "lucide-react";
|
|
3
|
+
import { CheckIcon, MinusIcon } from "lucide-react";
|
|
4
4
|
import { Checkbox as CheckboxPrimitive } from "radix-ui";
|
|
5
5
|
import { cn } from "../../lib/utils";
|
|
6
6
|
function Checkbox({ className, ...props }) {
|
|
7
|
-
return (_jsx(CheckboxPrimitive.Root, { "data-slot": "checkbox", className: cn("peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[var(--focus-ring-width)] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary", className), ...props, children: _jsx(CheckboxPrimitive.Indicator, { "data-slot": "checkbox-indicator", className: "grid place-content-center text-current transition-none", children: _jsx(CheckIcon, { className: "size-3.5" }) }) }));
|
|
7
|
+
return (_jsx(CheckboxPrimitive.Root, { "data-slot": "checkbox", className: cn("peer size-4 shrink-0 rounded-[4px] border border-input shadow-xs transition-shadow outline-none focus-visible:border-ring focus-visible:ring-[var(--focus-ring-width)] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=indeterminate]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-[state=checked]:bg-primary dark:data-[state=indeterminate]:bg-primary", className), ...props, children: _jsx(CheckboxPrimitive.Indicator, { "data-slot": "checkbox-indicator", className: "grid place-content-center text-current transition-none", children: props.checked === "indeterminate" ? (_jsx(MinusIcon, { className: "size-3.5" })) : (_jsx(CheckIcon, { className: "size-3.5" })) }) }));
|
|
8
8
|
}
|
|
9
9
|
export { Checkbox };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../components/blocks/mcp-access-grouped-tool-picker";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../components/blocks/mcp-access-grouped-tool-picker";
|