@tangle-network/sandbox-ui 0.113.6 → 0.114.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/WorkflowGraph-B-NsdYz_.js +1961 -0
- package/dist/assets.d.ts +214 -206
- package/dist/assets.js +1057 -908
- package/dist/auth-CWe17Hly.js +37 -0
- package/dist/auth.d.ts +2 -30
- package/dist/auth.js +2 -15
- package/dist/chat-BOvFAe6p.js +903 -0
- package/dist/chat.d.ts +2 -230
- package/dist/chat.js +2 -34
- package/dist/connectors.d.ts +52 -49
- package/dist/connectors.js +595 -643
- package/dist/dashboard-CZ3VgNPR.js +4969 -0
- package/dist/dashboard.d.ts +4 -1297
- package/dist/dashboard.js +4 -152
- package/dist/editor.d.ts +2 -1
- package/dist/editor.js +2 -31
- package/dist/files.d.ts +2 -6
- package/dist/files.js +2 -33
- package/dist/globals.css +63 -3
- package/dist/hooks.d.ts +146 -148
- package/dist/hooks.js +222 -55
- package/dist/index-CKRaj1pM.d.ts +776 -0
- package/dist/index-CXX5IpH2.d.ts +2 -0
- package/dist/index-DPePq7c8.d.ts +1340 -0
- package/dist/index-DiyLLZuJ.d.ts +230 -0
- package/dist/index-DvmZLMT1.d.ts +30 -0
- package/dist/index-I8ZLVtHd.d.ts +330 -0
- package/dist/index-PRM636Ex.d.ts +86 -0
- package/dist/index.d.ts +21 -33
- package/dist/index.js +21 -701
- package/dist/info-panel-C9cqDzOL.js +594 -0
- package/dist/integrations.d.ts +133 -139
- package/dist/integrations.js +491 -673
- package/dist/markdown.d.ts +2 -1
- package/dist/markdown.js +2 -13
- package/dist/model-I-NIxeM-.js +1250 -0
- package/dist/model-brand-B9A4H9pJ.d.ts +98 -0
- package/dist/model-brand-hMyDTUqB.js +624 -0
- package/dist/motion-DkyBRJb9.js +37 -0
- package/dist/openui.d.ts +2 -1
- package/dist/openui.js +2 -7
- package/dist/pages.d.ts +307 -300
- package/dist/pages.js +4404 -4181
- package/dist/primitives-Dh1vG6J3.js +113 -0
- package/dist/primitives.d.ts +2 -74
- package/dist/primitives.js +2 -204
- package/dist/provider-logo-DjqmConF.js +311 -0
- package/dist/run.d.ts +2 -1
- package/dist/run.js +2 -23
- package/dist/sdk-hooks.d.ts +3 -4
- package/dist/sdk-hooks.js +3 -31
- package/dist/sidecar-DgH_vQ6m.d.ts +9 -0
- package/dist/stores.d.ts +14 -15
- package/dist/stores.js +13 -81
- package/dist/styles.css +63 -3
- package/dist/template-card-L-4gmjx2.d.ts +90 -0
- package/dist/terminal-CN9ZgHRt.js +197 -0
- package/dist/terminal.d.ts +60 -60
- package/dist/terminal.js +2 -10
- package/dist/tokens.css +51 -0
- package/dist/types.d.ts +4 -11
- package/dist/types.js +0 -1
- package/dist/use-pty-session-C8cE0adT.js +669 -0
- package/dist/use-sidecar-auth-CCTJcrq7.d.ts +145 -0
- package/dist/use-sidecar-auth-DkdcufOz.js +742 -0
- package/dist/utils-DzWbktWG.js +2 -0
- package/dist/utils.d.ts +2 -1
- package/dist/utils.js +2 -37
- package/dist/workbench-BCaCKl-J.js +8347 -0
- package/dist/workbench.d.ts +2 -310
- package/dist/workbench.js +2 -44
- package/dist/workflows.d.ts +341 -339
- package/dist/workflows.js +74 -109
- package/dist/workspace-B6AtI6ld.js +2510 -0
- package/dist/workspace.d.ts +2 -761
- package/dist/workspace.js +2 -51
- package/package.json +46 -40
- package/dist/WorkflowGraph-2QOORYIR.js +0 -1722
- package/dist/chunk-2BUPSB7O.js +0 -0
- package/dist/chunk-3KBNPQQF.js +0 -2697
- package/dist/chunk-3LIXVEEE.js +0 -279
- package/dist/chunk-72UF2H5H.js +0 -707
- package/dist/chunk-AI25G5MX.js +0 -944
- package/dist/chunk-ANSC5AFC.js +0 -314
- package/dist/chunk-AZ3AWMTM.js +0 -8
- package/dist/chunk-BGVEHENC.js +0 -10
- package/dist/chunk-CZ7CSFO4.js +0 -39
- package/dist/chunk-DYXXYGS4.js +0 -4700
- package/dist/chunk-EI44GEQ5.js +0 -6
- package/dist/chunk-IACRDXER.js +0 -219
- package/dist/chunk-IOB2PW5Z.js +0 -55
- package/dist/chunk-M4K7ZGR2.js +0 -24
- package/dist/chunk-MYZAW4RX.js +0 -665
- package/dist/chunk-OMUIPJQZ.js +0 -555
- package/dist/chunk-RQZRXKMR.js +0 -398
- package/dist/chunk-SOKKTB7W.js +0 -230
- package/dist/chunk-TADGS4Q7.js +0 -1010
- package/dist/chunk-UCQNOUN3.js +0 -7964
- package/dist/chunk-ULPLRBMF.js +0 -34
- package/dist/chunk-WID73FPH.js +0 -89
- package/dist/chunk-X3YXP7FG.js +0 -38
- package/dist/logo-DiAjq759.d.ts +0 -15
- package/dist/model-brand-BNnaUKKZ.d.ts +0 -99
- package/dist/ports-list-CDIvTNnX.d.ts +0 -17
- package/dist/sdk-hooks-Djkjq4cp.d.ts +0 -145
- package/dist/template-card-Bn-Bw5xC.d.ts +0 -87
package/dist/connectors.js
CHANGED
|
@@ -1,683 +1,635 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from "
|
|
4
|
-
import "
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import { Check, ChevronDown, ChevronRight, Copy, Search } from "lucide-react";
|
|
9
|
-
import { useEffect, useMemo, useRef, useState as useState2 } from "react";
|
|
10
|
-
|
|
11
|
-
// src/connectors/integration-step-yaml.ts
|
|
1
|
+
import { t as cn$1 } from "./utils-DzWbktWG.js";
|
|
2
|
+
import { Badge, Button, EmptyState, Input } from "@tangle-network/ui/primitives";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { focusField } from "@tangle-network/ui/utils";
|
|
6
|
+
import { Blocks, Check, ChevronDown, ChevronRight, Copy, Search } from "lucide-react";
|
|
7
|
+
//#region src/connectors/integration-step-yaml.ts
|
|
12
8
|
function asSchemaObject(value) {
|
|
13
|
-
|
|
9
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
14
10
|
}
|
|
11
|
+
/** YAML scalar placeholder for a property schema. A string enum stubs its
|
|
12
|
+
* first string member (a real accepted input beats an empty string, quoted so
|
|
13
|
+
* it stays a string); otherwise — non-string/undefined/object enum values, or
|
|
14
|
+
* no enum — the placeholder is the type's empty value. Non-string enum members
|
|
15
|
+
* are intentionally NOT inlined: `JSON.stringify` on them would emit a
|
|
16
|
+
* type-changing bare token (`true`, `{}`, or even `undefined` for a malformed
|
|
17
|
+
* member), which the type placeholder handles honestly instead. */
|
|
15
18
|
function placeholderFor(propSchema) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return "false";
|
|
31
|
-
case "array":
|
|
32
|
-
return "[]";
|
|
33
|
-
case "object":
|
|
34
|
-
return "{}";
|
|
35
|
-
default:
|
|
36
|
-
return '""';
|
|
37
|
-
}
|
|
19
|
+
const schema = asSchemaObject(propSchema);
|
|
20
|
+
if (!schema) return "\"\"";
|
|
21
|
+
if (Array.isArray(schema.enum)) {
|
|
22
|
+
const firstString = schema.enum.find((value) => typeof value === "string");
|
|
23
|
+
if (firstString !== void 0) return JSON.stringify(firstString);
|
|
24
|
+
}
|
|
25
|
+
switch (Array.isArray(schema.type) ? schema.type[0] : schema.type) {
|
|
26
|
+
case "number":
|
|
27
|
+
case "integer": return "0";
|
|
28
|
+
case "boolean": return "false";
|
|
29
|
+
case "array": return "[]";
|
|
30
|
+
case "object": return "{}";
|
|
31
|
+
default: return "\"\"";
|
|
32
|
+
}
|
|
38
33
|
}
|
|
39
|
-
|
|
34
|
+
/** YAML 1.1 plain scalars a parser would coerce away from a string —
|
|
35
|
+
* booleans, null, and the empty value. Numbers are caught separately (they
|
|
36
|
+
* have no letter, so the "must contain a letter" rule below rejects them). */
|
|
37
|
+
const YAML_RESERVED_SCALAR = /^(?:true|false|null|yes|no|on|off|~)$/i;
|
|
38
|
+
/** True when `value` is safe to emit as a bare (unquoted) YAML scalar: a plain
|
|
39
|
+
* identifier-ish token that a YAML parser will load back as the same string.
|
|
40
|
+
* Requires at least one letter so pure-numeric tokens (`123`, `1.2`) quote,
|
|
41
|
+
* and rejects reserved words so `true`/`null`/`no` quote — both would
|
|
42
|
+
* otherwise load as a non-string type. */
|
|
40
43
|
function isBareYamlScalar(value) {
|
|
41
|
-
|
|
44
|
+
return /^[A-Za-z0-9_.-]+$/.test(value) && /[A-Za-z]/.test(value) && !YAML_RESERVED_SCALAR.test(value);
|
|
42
45
|
}
|
|
46
|
+
/** Bare YAML key when safe, quoted otherwise. Keys use the stricter identifier
|
|
47
|
+
* rule (must start with a letter/underscore) rather than the scalar rule,
|
|
48
|
+
* since a dotted or digit-led key reads poorly unquoted — but a key that spells
|
|
49
|
+
* a reserved scalar word (`true`/`null`/`on`/…) must still be quoted, or a
|
|
50
|
+
* YAML 1.1 parser loads the KEY as a boolean/null instead of the string. */
|
|
43
51
|
function yamlKey(key) {
|
|
44
|
-
|
|
52
|
+
return /^[A-Za-z_][A-Za-z0-9_-]*$/.test(key) && !YAML_RESERVED_SCALAR.test(key) ? key : JSON.stringify(key);
|
|
45
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* The input fields to stub: the schema's `required` list when it names any
|
|
56
|
+
* (in declaration order), else every top-level property — a schema with no
|
|
57
|
+
* required fields gives no signal to cut, and showing all is honest.
|
|
58
|
+
*/
|
|
46
59
|
function stubFields(inputSchema) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
) : [];
|
|
54
|
-
const chosen = required.length > 0 ? required : names;
|
|
55
|
-
return chosen.map((name) => [
|
|
56
|
-
name,
|
|
57
|
-
properties[name]
|
|
58
|
-
]);
|
|
60
|
+
const schema = asSchemaObject(inputSchema);
|
|
61
|
+
const properties = asSchemaObject(schema?.properties);
|
|
62
|
+
if (!properties) return [];
|
|
63
|
+
const names = Object.keys(properties);
|
|
64
|
+
const required = Array.isArray(schema?.required) ? schema.required.filter((name) => typeof name === "string" && names.includes(name)) : [];
|
|
65
|
+
return (required.length > 0 ? required : names).map((name) => [name, properties[name]]);
|
|
59
66
|
}
|
|
67
|
+
/** The `- integration.invoke:` step block for an action, ready to paste into a
|
|
68
|
+
* workflow's `do:` list. */
|
|
60
69
|
function integrationStepYaml(path, inputSchema) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
" input:",
|
|
68
|
-
...fields.map(
|
|
69
|
-
([name, propSchema]) => ` ${yamlKey(name)}: ${placeholderFor(propSchema)}`
|
|
70
|
-
)
|
|
71
|
-
]
|
|
72
|
-
];
|
|
73
|
-
return `${lines.join("\n")}
|
|
74
|
-
`;
|
|
70
|
+
const fields = stubFields(inputSchema);
|
|
71
|
+
return `${[
|
|
72
|
+
"- integration.invoke:",
|
|
73
|
+
` path: ${isBareYamlScalar(path) ? path : JSON.stringify(path)}`,
|
|
74
|
+
...fields.length === 0 ? [" input: {}"] : [" input:", ...fields.map(([name, propSchema]) => ` ${yamlKey(name)}: ${placeholderFor(propSchema)}`)]
|
|
75
|
+
].join("\n")}\n`;
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/connectors/schema-table.tsx
|
|
79
|
+
/** Nested rows beyond this depth collapse to their parent's `object` type —
|
|
80
|
+
* deeper shapes are readable in the raw-JSON view. */
|
|
81
|
+
const MAX_DEPTH = 3;
|
|
81
82
|
function asNode(value) {
|
|
82
|
-
|
|
83
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
83
84
|
}
|
|
84
85
|
function typeLabel(node) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
const type = Array.isArray(node.type) ? node.type.join(" | ") : node.type;
|
|
87
|
+
if (type === "array") {
|
|
88
|
+
const items = asNode(node.items);
|
|
89
|
+
const itemType = items ? Array.isArray(items.type) ? items.type.join(" | ") : items.type : void 0;
|
|
90
|
+
return typeof itemType === "string" ? `array<${itemType}>` : "array";
|
|
91
|
+
}
|
|
92
|
+
if (typeof type === "string") return type;
|
|
93
|
+
if (Array.isArray(node.enum)) return "enum";
|
|
94
|
+
return "any";
|
|
94
95
|
}
|
|
95
96
|
function collectRows(schema, depth, prefix, out) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (depth + 1 >= MAX_DEPTH) continue;
|
|
115
|
-
const child = typeLabel(prop) === "object" || asNode(prop.properties) ? prop : asNode(prop.items)?.properties ?? null ? asNode(prop.items) : null;
|
|
116
|
-
if (child) {
|
|
117
|
-
collectRows(child, depth + 1, prefix ? `${prefix}.${name}` : name, out);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
97
|
+
const properties = asNode(schema.properties);
|
|
98
|
+
if (!properties) return;
|
|
99
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required.filter((n) => typeof n === "string") : []);
|
|
100
|
+
for (const [name, rawProp] of Object.entries(properties)) {
|
|
101
|
+
const prop = asNode(rawProp) ?? {};
|
|
102
|
+
const enumValues = Array.isArray(prop.enum) ? prop.enum.map((v) => JSON.stringify(v)).filter((v) => typeof v === "string") : null;
|
|
103
|
+
out.push({
|
|
104
|
+
name: prefix ? `${prefix}.${name}` : name,
|
|
105
|
+
depth,
|
|
106
|
+
type: typeLabel(prop),
|
|
107
|
+
required: required.has(name),
|
|
108
|
+
description: typeof prop.description === "string" ? prop.description : "",
|
|
109
|
+
enumValues
|
|
110
|
+
});
|
|
111
|
+
if (depth + 1 >= MAX_DEPTH) continue;
|
|
112
|
+
const child = typeLabel(prop) === "object" || asNode(prop.properties) ? prop : asNode(prop.items)?.properties ?? null ? asNode(prop.items) : null;
|
|
113
|
+
if (child) collectRows(child, depth + 1, prefix ? `${prefix}.${name}` : name, out);
|
|
114
|
+
}
|
|
120
115
|
}
|
|
121
116
|
function schemaRows(schema) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
117
|
+
const node = asNode(schema);
|
|
118
|
+
if (!node || !asNode(node.properties)) return null;
|
|
119
|
+
const rows = [];
|
|
120
|
+
collectRows(node, 0, "", rows);
|
|
121
|
+
return rows;
|
|
127
122
|
}
|
|
123
|
+
/** `JSON.stringify` that survives a value it cannot serialize. Schemas arrive
|
|
124
|
+
* over the wire as JSON (acyclic), but the prop is `unknown`, so a hand-built
|
|
125
|
+
* cyclic object must degrade to a readable note in the raw-JSON view rather
|
|
126
|
+
* than throw and take down the host. */
|
|
128
127
|
function safeJsonStringify(value) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
try {
|
|
129
|
+
return JSON.stringify(value, null, 2) ?? "null";
|
|
130
|
+
} catch {
|
|
131
|
+
return "(schema cannot be shown as JSON)";
|
|
132
|
+
}
|
|
134
133
|
}
|
|
135
134
|
function SchemaTable({ schema, label }) {
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
135
|
+
const [showRaw, setShowRaw] = useState(false);
|
|
136
|
+
const rows = schemaRows(schema);
|
|
137
|
+
const rawJson = safeJsonStringify(schema);
|
|
138
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
|
|
139
|
+
className: "mb-1.5 flex items-center justify-between",
|
|
140
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
141
|
+
className: "font-medium text-muted-foreground text-xs uppercase tracking-wide",
|
|
142
|
+
children: label
|
|
143
|
+
}), rows !== null && rows.length > 0 && /* @__PURE__ */ jsx("button", {
|
|
144
|
+
type: "button",
|
|
145
|
+
onClick: () => setShowRaw((v) => !v),
|
|
146
|
+
className: "text-primary text-xs transition-colors hover:underline",
|
|
147
|
+
children: showRaw ? "Field view" : "Raw JSON"
|
|
148
|
+
})]
|
|
149
|
+
}), rows === null || rows.length === 0 || showRaw ? rows !== null && rows.length === 0 && !showRaw ? /* @__PURE__ */ jsx("p", {
|
|
150
|
+
className: "text-muted-foreground text-sm",
|
|
151
|
+
children: "No fields."
|
|
152
|
+
}) : /* @__PURE__ */ jsx("pre", {
|
|
153
|
+
className: "overflow-x-auto rounded-lg bg-surface-container-high p-3 text-xs leading-relaxed",
|
|
154
|
+
children: rawJson
|
|
155
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
156
|
+
className: "overflow-x-auto rounded-lg border border-border",
|
|
157
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
158
|
+
className: "w-full text-sm",
|
|
159
|
+
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", {
|
|
160
|
+
className: "border-border border-b bg-surface-container-high",
|
|
161
|
+
children: [
|
|
162
|
+
/* @__PURE__ */ jsx("th", {
|
|
163
|
+
className: "px-3 py-1.5 text-left font-medium text-muted-foreground text-xs",
|
|
164
|
+
children: "Field"
|
|
165
|
+
}),
|
|
166
|
+
/* @__PURE__ */ jsx("th", {
|
|
167
|
+
className: "px-3 py-1.5 text-left font-medium text-muted-foreground text-xs",
|
|
168
|
+
children: "Type"
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ jsx("th", {
|
|
171
|
+
className: "px-3 py-1.5 text-left font-medium text-muted-foreground text-xs",
|
|
172
|
+
children: "Description"
|
|
173
|
+
})
|
|
174
|
+
]
|
|
175
|
+
}) }), /* @__PURE__ */ jsx("tbody", { children: rows.map((row) => /* @__PURE__ */ jsxs("tr", {
|
|
176
|
+
className: "border-border border-b last:border-b-0",
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ jsxs("td", {
|
|
179
|
+
className: "whitespace-nowrap px-3 py-1.5 align-top font-mono text-foreground text-xs",
|
|
180
|
+
style: { paddingLeft: `${.75 + row.depth * 1}rem` },
|
|
181
|
+
children: [row.name.split(".").at(-1), row.required && /* @__PURE__ */ jsxs("span", {
|
|
182
|
+
className: "ml-0.5 text-destructive",
|
|
183
|
+
title: "Required",
|
|
184
|
+
children: ["*", /* @__PURE__ */ jsx("span", {
|
|
185
|
+
className: "sr-only",
|
|
186
|
+
children: "required"
|
|
187
|
+
})]
|
|
188
|
+
})]
|
|
189
|
+
}),
|
|
190
|
+
/* @__PURE__ */ jsx("td", {
|
|
191
|
+
className: "whitespace-nowrap px-3 py-1.5 align-top font-mono text-muted-foreground text-xs",
|
|
192
|
+
children: row.type
|
|
193
|
+
}),
|
|
194
|
+
/* @__PURE__ */ jsxs("td", {
|
|
195
|
+
className: "px-3 py-1.5 align-top text-muted-foreground text-xs",
|
|
196
|
+
children: [row.description, row.enumValues && /* @__PURE__ */ jsxs("span", {
|
|
197
|
+
className: row.description ? "ml-1" : "",
|
|
198
|
+
children: ["One of: ", row.enumValues.join(", ")]
|
|
199
|
+
})]
|
|
200
|
+
})
|
|
201
|
+
]
|
|
202
|
+
}, row.name)) })]
|
|
203
|
+
})
|
|
204
|
+
})] });
|
|
191
205
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/connectors/action-list.tsx
|
|
208
|
+
const RISK_BADGES = {
|
|
209
|
+
read: {
|
|
210
|
+
label: "read",
|
|
211
|
+
variant: "success"
|
|
212
|
+
},
|
|
213
|
+
write: {
|
|
214
|
+
label: "write",
|
|
215
|
+
variant: "warning"
|
|
216
|
+
},
|
|
217
|
+
destructive: {
|
|
218
|
+
label: "destructive",
|
|
219
|
+
variant: "destructive"
|
|
220
|
+
},
|
|
221
|
+
unknown: {
|
|
222
|
+
label: "unclassified",
|
|
223
|
+
variant: "outline"
|
|
224
|
+
}
|
|
200
225
|
};
|
|
201
226
|
function RiskBadge({ risk }) {
|
|
202
|
-
|
|
203
|
-
|
|
227
|
+
const badge = RISK_BADGES[risk ?? "unknown"] ?? RISK_BADGES.unknown;
|
|
228
|
+
return /* @__PURE__ */ jsx(Badge, {
|
|
229
|
+
variant: badge.variant,
|
|
230
|
+
children: badge.label
|
|
231
|
+
});
|
|
204
232
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
/** Copy-to-clipboard button with a transient confirmation. `navigator.clipboard`
|
|
234
|
+
* is unavailable in insecure contexts (and can reject on a permission denial),
|
|
235
|
+
* so a failure surfaces a visible "Copy failed" state rather than reverting
|
|
236
|
+
* silently — the user learns the copy didn't happen and can select the text
|
|
237
|
+
* manually. */
|
|
238
|
+
function CopyButton({ text, label, title }) {
|
|
239
|
+
const [state, setState] = useState("idle");
|
|
240
|
+
const timerRef = useRef(null);
|
|
241
|
+
useEffect(() => () => {
|
|
242
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
243
|
+
}, []);
|
|
244
|
+
const copy = async () => {
|
|
245
|
+
let next;
|
|
246
|
+
try {
|
|
247
|
+
await navigator.clipboard.writeText(text);
|
|
248
|
+
next = "copied";
|
|
249
|
+
} catch (err) {
|
|
250
|
+
console.warn("Clipboard write failed:", err);
|
|
251
|
+
next = "failed";
|
|
252
|
+
}
|
|
253
|
+
setState(next);
|
|
254
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
255
|
+
timerRef.current = setTimeout(() => setState("idle"), 2e3);
|
|
256
|
+
};
|
|
257
|
+
return /* @__PURE__ */ jsxs(Button, {
|
|
258
|
+
type: "button",
|
|
259
|
+
variant: "outline",
|
|
260
|
+
size: "sm",
|
|
261
|
+
onClick: copy,
|
|
262
|
+
title,
|
|
263
|
+
children: [state === "copied" ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-[var(--surface-success-text)]" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" }), state === "copied" ? "Copied" : state === "failed" ? "Copy failed" : label]
|
|
264
|
+
});
|
|
235
265
|
}
|
|
266
|
+
/** Many catalog action titles repeat the provider ("GitHub: Issues Create");
|
|
267
|
+
* on the provider's own page that prefix is noise, so strip it. */
|
|
236
268
|
function actionDisplayTitle(action, providerTitle) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
269
|
+
const title = action.title ?? action.path;
|
|
270
|
+
const prefix = `${providerTitle.toLowerCase()}: `;
|
|
271
|
+
return title.toLowerCase().startsWith(prefix) ? title.slice(prefix.length) : title;
|
|
240
272
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
273
|
+
/** One expandable action row: title + risk collapsed; path, schemas, and the
|
|
274
|
+
* copy/build affordances expanded. */
|
|
275
|
+
function ActionRow({ action, title, expanded, onToggle, onBuildWithAssistant }) {
|
|
276
|
+
return /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsxs("button", {
|
|
277
|
+
type: "button",
|
|
278
|
+
onClick: onToggle,
|
|
279
|
+
"aria-expanded": expanded,
|
|
280
|
+
className: "flex w-full items-center justify-between gap-4 p-4 text-left transition-colors hover:bg-surface-container-high",
|
|
281
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
282
|
+
className: "flex min-w-0 items-center gap-3",
|
|
283
|
+
children: [expanded ? /* @__PURE__ */ jsx(ChevronDown, {
|
|
284
|
+
"aria-hidden": "true",
|
|
285
|
+
className: "h-4 w-4 shrink-0 text-muted-foreground"
|
|
286
|
+
}) : /* @__PURE__ */ jsx(ChevronRight, {
|
|
287
|
+
"aria-hidden": "true",
|
|
288
|
+
className: "h-4 w-4 shrink-0 text-muted-foreground"
|
|
289
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
290
|
+
className: "min-w-0",
|
|
291
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
292
|
+
className: "font-medium text-foreground",
|
|
293
|
+
children: title
|
|
294
|
+
}), !expanded && action.description && /* @__PURE__ */ jsx("p", {
|
|
295
|
+
className: "truncate text-muted-foreground text-sm",
|
|
296
|
+
children: action.description
|
|
297
|
+
})]
|
|
298
|
+
})]
|
|
299
|
+
}), /* @__PURE__ */ jsx(RiskBadge, { risk: action.risk })]
|
|
300
|
+
}), expanded && /* @__PURE__ */ jsxs("div", {
|
|
301
|
+
className: "space-y-4 border-border border-t bg-surface-container-high/40 p-4 pl-11",
|
|
302
|
+
children: [
|
|
303
|
+
action.description && /* @__PURE__ */ jsx("p", {
|
|
304
|
+
className: "text-muted-foreground text-sm",
|
|
305
|
+
children: action.description
|
|
306
|
+
}),
|
|
307
|
+
/* @__PURE__ */ jsxs("div", {
|
|
308
|
+
className: "flex flex-wrap items-center gap-2",
|
|
309
|
+
children: [/* @__PURE__ */ jsx("code", {
|
|
310
|
+
className: "rounded bg-surface-container-high px-2 py-1 font-mono text-sm",
|
|
311
|
+
children: action.path
|
|
312
|
+
}), /* @__PURE__ */ jsx(CopyButton, {
|
|
313
|
+
text: action.path,
|
|
314
|
+
label: "Copy path"
|
|
315
|
+
})]
|
|
316
|
+
}),
|
|
317
|
+
/* @__PURE__ */ jsx(SchemaTable, {
|
|
318
|
+
schema: action.inputSchema,
|
|
319
|
+
label: "Input"
|
|
320
|
+
}),
|
|
321
|
+
action.outputSchema != null && /* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsxs("summary", {
|
|
322
|
+
className: "cursor-pointer text-muted-foreground text-sm transition-colors hover:text-foreground",
|
|
323
|
+
children: [
|
|
324
|
+
"Output shape (for",
|
|
325
|
+
" ",
|
|
326
|
+
/* @__PURE__ */ jsx("code", {
|
|
327
|
+
className: "rounded bg-surface-container-high px-1 py-0.5 font-mono text-xs",
|
|
328
|
+
children: "${steps[N]…}"
|
|
329
|
+
}),
|
|
330
|
+
" ",
|
|
331
|
+
"expressions)"
|
|
332
|
+
]
|
|
333
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
334
|
+
className: "mt-2",
|
|
335
|
+
children: /* @__PURE__ */ jsx(SchemaTable, {
|
|
336
|
+
schema: action.outputSchema,
|
|
337
|
+
label: "Output"
|
|
338
|
+
})
|
|
339
|
+
})] }),
|
|
340
|
+
/* @__PURE__ */ jsxs("div", {
|
|
341
|
+
className: "flex flex-wrap items-center gap-2",
|
|
342
|
+
children: [/* @__PURE__ */ jsx(CopyButton, {
|
|
343
|
+
text: integrationStepYaml(action.path, action.inputSchema),
|
|
344
|
+
label: "Copy step YAML",
|
|
345
|
+
title: "A ready-to-paste integration.invoke step for a workflow definition's do: list"
|
|
346
|
+
}), onBuildWithAssistant && /* @__PURE__ */ jsx(Button, {
|
|
347
|
+
type: "button",
|
|
348
|
+
size: "sm",
|
|
349
|
+
onClick: () => onBuildWithAssistant(action),
|
|
350
|
+
children: "Build with assistant"
|
|
351
|
+
})]
|
|
352
|
+
})
|
|
353
|
+
]
|
|
354
|
+
})] });
|
|
318
355
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
Button,
|
|
400
|
-
{
|
|
401
|
-
type: "button",
|
|
402
|
-
variant: "outline",
|
|
403
|
-
size: "sm",
|
|
404
|
-
onClick: () => setFilter(""),
|
|
405
|
-
className: "mt-4",
|
|
406
|
-
children: "Clear filter"
|
|
407
|
-
}
|
|
408
|
-
)
|
|
409
|
-
] }) : /* @__PURE__ */ jsx2("ul", { className: "divide-y divide-border", children: filtered.map(({ action, title }) => /* @__PURE__ */ jsx2(
|
|
410
|
-
ActionRow,
|
|
411
|
-
{
|
|
412
|
-
action,
|
|
413
|
-
title,
|
|
414
|
-
expanded: expandedPath === action.path,
|
|
415
|
-
onToggle: () => setExpandedPath(
|
|
416
|
-
(current) => current === action.path ? null : action.path
|
|
417
|
-
),
|
|
418
|
-
onBuildWithAssistant
|
|
419
|
-
},
|
|
420
|
-
action.path
|
|
421
|
-
)) })
|
|
422
|
-
]
|
|
423
|
-
}
|
|
424
|
-
);
|
|
356
|
+
/**
|
|
357
|
+
* Searchable list of a connector's invokable actions. Each row expands to show
|
|
358
|
+
* the action's path, input/output schemas, and copy/build affordances. Purely
|
|
359
|
+
* presentational — the host supplies the actions and the assistant hook.
|
|
360
|
+
*/
|
|
361
|
+
function ConnectorActionList({ actions, providerTitle, onBuildWithAssistant, maybeTruncated, className }) {
|
|
362
|
+
const [filter, setFilter] = useState("");
|
|
363
|
+
const [expandedPath, setExpandedPath] = useState(null);
|
|
364
|
+
const decorated = useMemo(() => actions.map((action) => ({
|
|
365
|
+
action,
|
|
366
|
+
title: actionDisplayTitle(action, providerTitle)
|
|
367
|
+
})).sort((a, b) => a.title.localeCompare(b.title)), [actions, providerTitle]);
|
|
368
|
+
const filtered = useMemo(() => {
|
|
369
|
+
const q = filter.trim().toLowerCase();
|
|
370
|
+
if (!q) return decorated;
|
|
371
|
+
return decorated.filter(({ action, title }) => title.toLowerCase().includes(q) || action.path.toLowerCase().includes(q) || (action.description ?? "").toLowerCase().includes(q));
|
|
372
|
+
}, [decorated, filter]);
|
|
373
|
+
if (actions.length === 0) return /* @__PURE__ */ jsx("section", {
|
|
374
|
+
className: cn$1("rounded-lg border border-border bg-card p-6", className),
|
|
375
|
+
children: /* @__PURE__ */ jsx("p", {
|
|
376
|
+
className: "text-center text-muted-foreground text-sm",
|
|
377
|
+
children: "This connector doesn't expose any invokable actions yet."
|
|
378
|
+
})
|
|
379
|
+
});
|
|
380
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
381
|
+
className: cn$1("overflow-hidden rounded-lg border border-border bg-card", className),
|
|
382
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
383
|
+
className: "border-border border-b p-4",
|
|
384
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
385
|
+
className: "flex flex-wrap items-center gap-3",
|
|
386
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
387
|
+
className: "relative min-w-[12rem] flex-1",
|
|
388
|
+
children: [/* @__PURE__ */ jsx(Search, {
|
|
389
|
+
"aria-hidden": "true",
|
|
390
|
+
className: "pointer-events-none absolute top-1/2 left-2.5 h-4 w-4 -translate-y-1/2 text-muted-foreground"
|
|
391
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
392
|
+
type: "search",
|
|
393
|
+
value: filter,
|
|
394
|
+
onChange: (e) => setFilter(e.target.value),
|
|
395
|
+
placeholder: "Filter actions",
|
|
396
|
+
"aria-label": "Filter actions",
|
|
397
|
+
className: "pl-8"
|
|
398
|
+
})]
|
|
399
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
400
|
+
role: "status",
|
|
401
|
+
"aria-live": "polite",
|
|
402
|
+
className: "text-muted-foreground text-sm",
|
|
403
|
+
children: [
|
|
404
|
+
filtered.length,
|
|
405
|
+
" of ",
|
|
406
|
+
actions.length,
|
|
407
|
+
maybeTruncated ? "+" : "",
|
|
408
|
+
" actions"
|
|
409
|
+
]
|
|
410
|
+
})]
|
|
411
|
+
})
|
|
412
|
+
}), filtered.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
413
|
+
className: "p-6 text-center",
|
|
414
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
415
|
+
className: "text-muted-foreground text-sm",
|
|
416
|
+
children: "No actions match your filter."
|
|
417
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
418
|
+
type: "button",
|
|
419
|
+
variant: "outline",
|
|
420
|
+
size: "sm",
|
|
421
|
+
onClick: () => setFilter(""),
|
|
422
|
+
className: "mt-4",
|
|
423
|
+
children: "Clear filter"
|
|
424
|
+
})]
|
|
425
|
+
}) : /* @__PURE__ */ jsx("ul", {
|
|
426
|
+
className: "divide-y divide-border",
|
|
427
|
+
children: filtered.map(({ action, title }) => /* @__PURE__ */ jsx(ActionRow, {
|
|
428
|
+
action,
|
|
429
|
+
title,
|
|
430
|
+
expanded: expandedPath === action.path,
|
|
431
|
+
onToggle: () => setExpandedPath((current) => current === action.path ? null : action.path),
|
|
432
|
+
onBuildWithAssistant
|
|
433
|
+
}, action.path))
|
|
434
|
+
})]
|
|
435
|
+
});
|
|
425
436
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
import { Button as Button2, EmptyState, Input as Input2 } from "@tangle-network/ui/primitives";
|
|
429
|
-
import { Blocks, ChevronRight as ChevronRight2, Search as Search2 } from "lucide-react";
|
|
430
|
-
import { useEffect as useEffect2, useMemo as useMemo2, useState as useState3 } from "react";
|
|
431
|
-
import { focusField } from "@tangle-network/ui/utils";
|
|
432
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
437
|
+
//#endregion
|
|
438
|
+
//#region src/connectors/catalog-list.tsx
|
|
433
439
|
function optionsFor(entries, pick) {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
+
const map = /* @__PURE__ */ new Map();
|
|
441
|
+
for (const entry of entries) {
|
|
442
|
+
const { value, label } = pick(entry);
|
|
443
|
+
if (value) map.set(value, label ?? value);
|
|
444
|
+
}
|
|
445
|
+
return [...map.entries()].map(([value, label]) => ({
|
|
446
|
+
value,
|
|
447
|
+
label
|
|
448
|
+
})).sort((a, b) => a.label.localeCompare(b.label));
|
|
440
449
|
}
|
|
441
450
|
function rowDetail(entry) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
if (entry.triggerCount != null && entry.triggerCount > 0) {
|
|
451
|
-
parts.push(
|
|
452
|
-
`${entry.triggerCount} trigger ${entry.triggerCount === 1 ? "event" : "events"}`
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
return parts.join(" \xB7 ");
|
|
451
|
+
const parts = [];
|
|
452
|
+
if (entry.category) parts.push(entry.categoryLabel ?? entry.category);
|
|
453
|
+
if (entry.authKind) parts.push(entry.authKindLabel ?? entry.authKind);
|
|
454
|
+
if (entry.actionCount != null) parts.push(`${entry.actionCount} ${entry.actionCount === 1 ? "action" : "actions"}`);
|
|
455
|
+
if (entry.triggerCount != null && entry.triggerCount > 0) parts.push(`${entry.triggerCount} trigger ${entry.triggerCount === 1 ? "event" : "events"}`);
|
|
456
|
+
return parts.join(" · ");
|
|
456
457
|
}
|
|
458
|
+
/** Neutral leading chip used when the host supplies no brand icon. */
|
|
457
459
|
function FallbackIcon() {
|
|
458
|
-
|
|
460
|
+
return /* @__PURE__ */ jsx("div", {
|
|
461
|
+
className: "flex size-9 shrink-0 items-center justify-center rounded-lg bg-surface-container-high",
|
|
462
|
+
children: /* @__PURE__ */ jsx(Blocks, { className: "size-5 text-muted-foreground" })
|
|
463
|
+
});
|
|
459
464
|
}
|
|
460
|
-
function FilterSelect({
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
children: [
|
|
475
|
-
/* @__PURE__ */ jsx3("option", { value: "", children: allLabel }),
|
|
476
|
-
options.map((option) => /* @__PURE__ */ jsx3("option", { value: option.value, children: option.label }, option.value))
|
|
477
|
-
]
|
|
478
|
-
}
|
|
479
|
-
);
|
|
465
|
+
function FilterSelect({ value, onChange, options, allLabel, ariaLabel }) {
|
|
466
|
+
return /* @__PURE__ */ jsxs("select", {
|
|
467
|
+
value,
|
|
468
|
+
onChange: (e) => onChange(e.target.value),
|
|
469
|
+
"aria-label": ariaLabel,
|
|
470
|
+
className: `rounded-lg border bg-card px-3 py-2 text-foreground text-sm ${focusField}`,
|
|
471
|
+
children: [/* @__PURE__ */ jsx("option", {
|
|
472
|
+
value: "",
|
|
473
|
+
children: allLabel
|
|
474
|
+
}), options.map((option) => /* @__PURE__ */ jsx("option", {
|
|
475
|
+
value: option.value,
|
|
476
|
+
children: option.label
|
|
477
|
+
}, option.value))]
|
|
478
|
+
});
|
|
480
479
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
]
|
|
635
|
-
}
|
|
636
|
-
)
|
|
637
|
-
] })
|
|
638
|
-
}
|
|
639
|
-
) : /* @__PURE__ */ jsx3("ul", { className: "divide-y divide-border", children: filtered.map((entry) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsxs3(
|
|
640
|
-
"a",
|
|
641
|
-
{
|
|
642
|
-
href: getConnectorHref(entry.providerId),
|
|
643
|
-
onClick: (e) => {
|
|
644
|
-
if (onOpenConnector && e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey) {
|
|
645
|
-
e.preventDefault();
|
|
646
|
-
onOpenConnector(entry.providerId);
|
|
647
|
-
}
|
|
648
|
-
},
|
|
649
|
-
className: "flex items-center justify-between gap-4 p-4 transition-colors hover:bg-surface-container-high",
|
|
650
|
-
children: [
|
|
651
|
-
/* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
652
|
-
renderIcon ? renderIcon(entry.providerId) : /* @__PURE__ */ jsx3(FallbackIcon, {}),
|
|
653
|
-
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
654
|
-
/* @__PURE__ */ jsx3("p", { className: "font-medium text-foreground", children: entry.title }),
|
|
655
|
-
/* @__PURE__ */ jsx3("p", { className: "truncate text-muted-foreground text-sm", children: rowDetail(entry) })
|
|
656
|
-
] })
|
|
657
|
-
] }),
|
|
658
|
-
/* @__PURE__ */ jsxs3("div", { className: "flex shrink-0 items-center gap-3", children: [
|
|
659
|
-
entry.connected && /* @__PURE__ */ jsxs3("span", { className: "inline-flex items-center gap-1.5 text-muted-foreground text-sm", children: [
|
|
660
|
-
/* @__PURE__ */ jsx3("span", { className: "size-2 rounded-full bg-[var(--surface-success-text)]" }),
|
|
661
|
-
"Connected"
|
|
662
|
-
] }),
|
|
663
|
-
/* @__PURE__ */ jsx3(
|
|
664
|
-
ChevronRight2,
|
|
665
|
-
{
|
|
666
|
-
"aria-hidden": "true",
|
|
667
|
-
className: "h-4 w-4 text-muted-foreground"
|
|
668
|
-
}
|
|
669
|
-
)
|
|
670
|
-
] })
|
|
671
|
-
]
|
|
672
|
-
}
|
|
673
|
-
) }, entry.providerId)) })
|
|
674
|
-
]
|
|
675
|
-
}
|
|
676
|
-
);
|
|
480
|
+
/**
|
|
481
|
+
* Searchable/filterable browse list over every connector the host exposes.
|
|
482
|
+
* Each row links into the connector's detail surface; connect/disconnect and
|
|
483
|
+
* data fetching stay with the host — this list is for discovery.
|
|
484
|
+
*/
|
|
485
|
+
function ConnectorCatalogList({ entries, getConnectorHref, onOpenConnector, renderIcon, onRequestIntegration, className }) {
|
|
486
|
+
const [search, setSearch] = useState("");
|
|
487
|
+
const [categoryFilter, setCategoryFilter] = useState("");
|
|
488
|
+
const [authFilter, setAuthFilter] = useState("");
|
|
489
|
+
const categoryOptions = useMemo(() => optionsFor(entries, (e) => ({
|
|
490
|
+
value: e.category,
|
|
491
|
+
label: e.categoryLabel
|
|
492
|
+
})), [entries]);
|
|
493
|
+
const authOptions = useMemo(() => optionsFor(entries, (e) => ({
|
|
494
|
+
value: e.authKind,
|
|
495
|
+
label: e.authKindLabel
|
|
496
|
+
})), [entries]);
|
|
497
|
+
const filtered = useMemo(() => {
|
|
498
|
+
const q = search.trim().toLowerCase();
|
|
499
|
+
return entries.filter((entry) => {
|
|
500
|
+
if (categoryFilter && entry.category !== categoryFilter) return false;
|
|
501
|
+
if (authFilter && entry.authKind !== authFilter) return false;
|
|
502
|
+
if (!q) return true;
|
|
503
|
+
return entry.title.toLowerCase().includes(q) || entry.providerId.toLowerCase().includes(q);
|
|
504
|
+
}).sort((a, b) => a.title.localeCompare(b.title));
|
|
505
|
+
}, [
|
|
506
|
+
entries,
|
|
507
|
+
search,
|
|
508
|
+
categoryFilter,
|
|
509
|
+
authFilter
|
|
510
|
+
]);
|
|
511
|
+
const clearFilters = () => {
|
|
512
|
+
setSearch("");
|
|
513
|
+
setCategoryFilter("");
|
|
514
|
+
setAuthFilter("");
|
|
515
|
+
};
|
|
516
|
+
useEffect(() => {
|
|
517
|
+
if (categoryFilter && !categoryOptions.some((o) => o.value === categoryFilter)) setCategoryFilter("");
|
|
518
|
+
}, [categoryOptions, categoryFilter]);
|
|
519
|
+
useEffect(() => {
|
|
520
|
+
if (authFilter && !authOptions.some((o) => o.value === authFilter)) setAuthFilter("");
|
|
521
|
+
}, [authOptions, authFilter]);
|
|
522
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
523
|
+
className: cn$1("overflow-hidden rounded-lg border border-border bg-card", className),
|
|
524
|
+
children: [entries.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
525
|
+
className: "border-border border-b p-4",
|
|
526
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
527
|
+
className: "flex flex-wrap items-center gap-3",
|
|
528
|
+
children: [
|
|
529
|
+
/* @__PURE__ */ jsxs("div", {
|
|
530
|
+
className: "relative min-w-[15rem] flex-1",
|
|
531
|
+
children: [/* @__PURE__ */ jsx(Search, {
|
|
532
|
+
"aria-hidden": "true",
|
|
533
|
+
className: "pointer-events-none absolute top-1/2 left-2.5 h-4 w-4 -translate-y-1/2 text-muted-foreground"
|
|
534
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
535
|
+
type: "search",
|
|
536
|
+
value: search,
|
|
537
|
+
onChange: (e) => setSearch(e.target.value),
|
|
538
|
+
placeholder: "Search connectors",
|
|
539
|
+
"aria-label": "Search connectors",
|
|
540
|
+
className: "pl-8"
|
|
541
|
+
})]
|
|
542
|
+
}),
|
|
543
|
+
categoryOptions.length > 1 && /* @__PURE__ */ jsx(FilterSelect, {
|
|
544
|
+
value: categoryFilter,
|
|
545
|
+
onChange: setCategoryFilter,
|
|
546
|
+
options: categoryOptions,
|
|
547
|
+
allLabel: "All categories",
|
|
548
|
+
ariaLabel: "Filter by category"
|
|
549
|
+
}),
|
|
550
|
+
authOptions.length > 1 && /* @__PURE__ */ jsx(FilterSelect, {
|
|
551
|
+
value: authFilter,
|
|
552
|
+
onChange: setAuthFilter,
|
|
553
|
+
options: authOptions,
|
|
554
|
+
allLabel: "All auth",
|
|
555
|
+
ariaLabel: "Filter by auth type"
|
|
556
|
+
}),
|
|
557
|
+
/* @__PURE__ */ jsxs("span", {
|
|
558
|
+
role: "status",
|
|
559
|
+
"aria-live": "polite",
|
|
560
|
+
className: "text-muted-foreground text-sm",
|
|
561
|
+
children: [
|
|
562
|
+
filtered.length,
|
|
563
|
+
" of ",
|
|
564
|
+
entries.length,
|
|
565
|
+
" connectors"
|
|
566
|
+
]
|
|
567
|
+
}),
|
|
568
|
+
onRequestIntegration && /* @__PURE__ */ jsx("button", {
|
|
569
|
+
type: "button",
|
|
570
|
+
onClick: () => onRequestIntegration(search.trim()),
|
|
571
|
+
className: "text-[var(--accent-text)] text-sm transition-colors hover:underline",
|
|
572
|
+
children: "Request an integration"
|
|
573
|
+
})
|
|
574
|
+
]
|
|
575
|
+
})
|
|
576
|
+
}), entries.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {
|
|
577
|
+
title: "No connectors",
|
|
578
|
+
description: "No connectors are available yet."
|
|
579
|
+
}) : filtered.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {
|
|
580
|
+
title: "No matches",
|
|
581
|
+
description: "No connectors match your filters.",
|
|
582
|
+
action: /* @__PURE__ */ jsxs("div", {
|
|
583
|
+
className: "flex flex-wrap items-center justify-center gap-2",
|
|
584
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
585
|
+
type: "button",
|
|
586
|
+
variant: "outline",
|
|
587
|
+
size: "sm",
|
|
588
|
+
onClick: clearFilters,
|
|
589
|
+
children: "Clear filters"
|
|
590
|
+
}), onRequestIntegration && /* @__PURE__ */ jsxs(Button, {
|
|
591
|
+
type: "button",
|
|
592
|
+
size: "sm",
|
|
593
|
+
onClick: () => onRequestIntegration(search.trim()),
|
|
594
|
+
children: ["Request ", search.trim() ? `"${search.trim()}"` : "an integration"]
|
|
595
|
+
})]
|
|
596
|
+
})
|
|
597
|
+
}) : /* @__PURE__ */ jsx("ul", {
|
|
598
|
+
className: "divide-y divide-border",
|
|
599
|
+
children: filtered.map((entry) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("a", {
|
|
600
|
+
href: getConnectorHref(entry.providerId),
|
|
601
|
+
onClick: (e) => {
|
|
602
|
+
if (onOpenConnector && e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey) {
|
|
603
|
+
e.preventDefault();
|
|
604
|
+
onOpenConnector(entry.providerId);
|
|
605
|
+
}
|
|
606
|
+
},
|
|
607
|
+
className: "flex items-center justify-between gap-4 p-4 transition-colors hover:bg-surface-container-high",
|
|
608
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
609
|
+
className: "flex min-w-0 items-center gap-3",
|
|
610
|
+
children: [renderIcon ? renderIcon(entry.providerId) : /* @__PURE__ */ jsx(FallbackIcon, {}), /* @__PURE__ */ jsxs("div", {
|
|
611
|
+
className: "min-w-0",
|
|
612
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
613
|
+
className: "font-medium text-foreground",
|
|
614
|
+
children: entry.title
|
|
615
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
616
|
+
className: "truncate text-muted-foreground text-sm",
|
|
617
|
+
children: rowDetail(entry)
|
|
618
|
+
})]
|
|
619
|
+
})]
|
|
620
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
621
|
+
className: "flex shrink-0 items-center gap-3",
|
|
622
|
+
children: [entry.connected && /* @__PURE__ */ jsxs("span", {
|
|
623
|
+
className: "inline-flex items-center gap-1.5 text-muted-foreground text-sm",
|
|
624
|
+
children: [/* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-[var(--surface-success-text)]" }), "Connected"]
|
|
625
|
+
}), /* @__PURE__ */ jsx(ChevronRight, {
|
|
626
|
+
"aria-hidden": "true",
|
|
627
|
+
className: "h-4 w-4 text-muted-foreground"
|
|
628
|
+
})]
|
|
629
|
+
})]
|
|
630
|
+
}) }, entry.providerId))
|
|
631
|
+
})]
|
|
632
|
+
});
|
|
677
633
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
ConnectorCatalogList,
|
|
681
|
-
SchemaTable,
|
|
682
|
-
integrationStepYaml
|
|
683
|
-
};
|
|
634
|
+
//#endregion
|
|
635
|
+
export { ConnectorActionList, ConnectorCatalogList, SchemaTable, integrationStepYaml };
|