grain-tools 0.10.12 → 0.10.14
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/mcp-app.html +702 -268
- package/dist/web-app.html +1946 -1060
- package/out/server/standalone.js +1312 -799
- package/package.json +1 -2
- package/server.json +2 -2
package/dist/web-app.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Grain</title>
|
|
6
|
+
<title>Grain (Beta)</title>
|
|
7
7
|
<meta name="theme-color" content="#1e1e1e" />
|
|
8
8
|
<link
|
|
9
9
|
rel="icon"
|
|
@@ -12808,6 +12808,7 @@ function detectInitialTheme() {
|
|
|
12808
12808
|
}
|
|
12809
12809
|
const useAppStore = create$3((set2, get2) => ({
|
|
12810
12810
|
theme: detectInitialTheme(),
|
|
12811
|
+
panelTheme: "inherit",
|
|
12811
12812
|
activeView: "query",
|
|
12812
12813
|
copyIncludesHeaders: true,
|
|
12813
12814
|
rowDensity: "normal",
|
|
@@ -12902,41 +12903,23 @@ const useAppStore = create$3((set2, get2) => ({
|
|
|
12902
12903
|
if (c.fontSize !== void 0) {
|
|
12903
12904
|
newState.fontSize = c.fontSize !== null && c.fontSize !== void 0 && c.fontSize > 0 ? c.fontSize : null;
|
|
12904
12905
|
}
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
|
|
12908
|
-
|
|
12909
|
-
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12916
|
-
|
|
12917
|
-
|
|
12918
|
-
|
|
12919
|
-
|
|
12920
|
-
|
|
12921
|
-
newState
|
|
12922
|
-
}
|
|
12923
|
-
if (c.mcpEntitled !== void 0) {
|
|
12924
|
-
newState.mcpEntitled = c.mcpEntitled;
|
|
12925
|
-
}
|
|
12926
|
-
if (c.mcpSafeMode !== void 0) {
|
|
12927
|
-
newState.mcpSafeMode = c.mcpSafeMode;
|
|
12928
|
-
}
|
|
12929
|
-
if (c.activeConnectorType !== void 0) {
|
|
12930
|
-
newState.activeConnectorType = c.activeConnectorType;
|
|
12931
|
-
}
|
|
12932
|
-
if (c.activeConnectionId !== void 0) {
|
|
12933
|
-
newState.activeConnectionId = c.activeConnectionId;
|
|
12934
|
-
}
|
|
12935
|
-
if (c.activeConnectionName !== void 0) {
|
|
12936
|
-
newState.activeConnectionName = c.activeConnectionName;
|
|
12937
|
-
}
|
|
12938
|
-
if (c.confirmWriteQueries !== void 0) {
|
|
12939
|
-
newState.confirmWriteQueries = c.confirmWriteQueries;
|
|
12906
|
+
const passthrough = [
|
|
12907
|
+
"maxRowsToDisplay",
|
|
12908
|
+
"telemetryEnabled",
|
|
12909
|
+
"chartsEnabled",
|
|
12910
|
+
"chartLayout",
|
|
12911
|
+
"panelTheme",
|
|
12912
|
+
"filterResultsByActiveFile",
|
|
12913
|
+
"mcpEnabled",
|
|
12914
|
+
"mcpEntitled",
|
|
12915
|
+
"mcpSafeMode",
|
|
12916
|
+
"activeConnectorType",
|
|
12917
|
+
"activeConnectionId",
|
|
12918
|
+
"activeConnectionName",
|
|
12919
|
+
"confirmWriteQueries"
|
|
12920
|
+
];
|
|
12921
|
+
for (const key of passthrough) {
|
|
12922
|
+
if (c[key] !== void 0) Object.assign(newState, { [key]: c[key] });
|
|
12940
12923
|
}
|
|
12941
12924
|
if (c.mcpStatus !== void 0) {
|
|
12942
12925
|
newState.mcpPort = ((_a3 = c.mcpStatus) == null ? void 0 : _a3.port) ?? null;
|
|
@@ -12965,7 +12948,8 @@ const useAppStore = create$3((set2, get2) => ({
|
|
|
12965
12948
|
};
|
|
12966
12949
|
set2((state) => ({
|
|
12967
12950
|
tabs: [...state.tabs, newTab],
|
|
12968
|
-
activeTabId: activate ? id : state.activeTabId
|
|
12951
|
+
activeTabId: activate ? id : state.activeTabId,
|
|
12952
|
+
guideHub: activate ? null : state.guideHub
|
|
12969
12953
|
}));
|
|
12970
12954
|
return id;
|
|
12971
12955
|
},
|
|
@@ -12981,7 +12965,7 @@ const useAppStore = create$3((set2, get2) => ({
|
|
|
12981
12965
|
activeTabId: newActiveId
|
|
12982
12966
|
};
|
|
12983
12967
|
}),
|
|
12984
|
-
setActiveTab: (id) => set2({ activeTabId: id }),
|
|
12968
|
+
setActiveTab: (id) => set2({ activeTabId: id, guideHub: null }),
|
|
12985
12969
|
updateTab: (id, updates) => set2((state) => ({
|
|
12986
12970
|
tabs: state.tabs.map((tab) => {
|
|
12987
12971
|
if (tab.id !== id) {
|
|
@@ -12991,6 +12975,10 @@ const useAppStore = create$3((set2, get2) => ({
|
|
|
12991
12975
|
if (updates.isLoading === true && !tab.isLoading) {
|
|
12992
12976
|
next.loadingStartedAt = Date.now();
|
|
12993
12977
|
next.cancelled = false;
|
|
12978
|
+
next.notPersisted = false;
|
|
12979
|
+
}
|
|
12980
|
+
if (updates.result) {
|
|
12981
|
+
next.notPersisted = false;
|
|
12994
12982
|
}
|
|
12995
12983
|
if (updates.result !== void 0 && updates.chartSpec === void 0) {
|
|
12996
12984
|
const signature = (r) => r ? r.columns.map((c) => `${c.name}:${c.type}`).join(" ") : "";
|
|
@@ -13079,6 +13067,35 @@ function useWebBootstrap() {
|
|
|
13079
13067
|
return unsubscribe;
|
|
13080
13068
|
}, []);
|
|
13081
13069
|
}
|
|
13070
|
+
const ALL_TOOLS = [
|
|
13071
|
+
"list_connectors",
|
|
13072
|
+
"run_query",
|
|
13073
|
+
"get_tab_info",
|
|
13074
|
+
"list_sessions",
|
|
13075
|
+
"list_connections",
|
|
13076
|
+
"save_connection",
|
|
13077
|
+
"request_connection_credentials",
|
|
13078
|
+
"test_connection",
|
|
13079
|
+
"delete_connection",
|
|
13080
|
+
"list_schemas",
|
|
13081
|
+
"list_tables",
|
|
13082
|
+
"describe_table",
|
|
13083
|
+
"cancel_query",
|
|
13084
|
+
"close_tab",
|
|
13085
|
+
"render_chart",
|
|
13086
|
+
"save_chart",
|
|
13087
|
+
"list_charts",
|
|
13088
|
+
"ledger_stats",
|
|
13089
|
+
"verify_ledger",
|
|
13090
|
+
"record_ui_event"
|
|
13091
|
+
];
|
|
13092
|
+
const WEB_PROXIED_TOOLS = [
|
|
13093
|
+
"list_connectors",
|
|
13094
|
+
"list_connections",
|
|
13095
|
+
"save_connection",
|
|
13096
|
+
"test_connection",
|
|
13097
|
+
"delete_connection"
|
|
13098
|
+
];
|
|
13082
13099
|
const TELEMETRY_EVENTS = [
|
|
13083
13100
|
"extension_activated",
|
|
13084
13101
|
"command_invoked",
|
|
@@ -13129,7 +13146,14 @@ const TELEMETRY_MCP_CLIENTS = [
|
|
|
13129
13146
|
"unknown"
|
|
13130
13147
|
];
|
|
13131
13148
|
new Set(TELEMETRY_MCP_CLIENTS);
|
|
13132
|
-
const TELEMETRY_UI_ACTIONS = [
|
|
13149
|
+
const TELEMETRY_UI_ACTIONS = [
|
|
13150
|
+
"sort",
|
|
13151
|
+
"filter",
|
|
13152
|
+
"export",
|
|
13153
|
+
"tab_switch",
|
|
13154
|
+
"run_query",
|
|
13155
|
+
"connection_created"
|
|
13156
|
+
];
|
|
13133
13157
|
new Set(TELEMETRY_UI_ACTIONS);
|
|
13134
13158
|
const TELEMETRY_CONNECTORS = [
|
|
13135
13159
|
"trino",
|
|
@@ -13145,29 +13169,7 @@ const TELEMETRY_CONNECTORS = [
|
|
|
13145
13169
|
"custom",
|
|
13146
13170
|
"unknown"
|
|
13147
13171
|
];
|
|
13148
|
-
const TELEMETRY_TOOL_NAMES = [
|
|
13149
|
-
"list_connectors",
|
|
13150
|
-
"run_query",
|
|
13151
|
-
"get_tab_info",
|
|
13152
|
-
"list_sessions",
|
|
13153
|
-
"list_connections",
|
|
13154
|
-
"save_connection",
|
|
13155
|
-
"request_connection_credentials",
|
|
13156
|
-
"test_connection",
|
|
13157
|
-
"delete_connection",
|
|
13158
|
-
"list_schemas",
|
|
13159
|
-
"list_tables",
|
|
13160
|
-
"describe_table",
|
|
13161
|
-
"cancel_query",
|
|
13162
|
-
"close_tab",
|
|
13163
|
-
"render_chart",
|
|
13164
|
-
"save_chart",
|
|
13165
|
-
"list_charts",
|
|
13166
|
-
"ledger_stats",
|
|
13167
|
-
"verify_ledger",
|
|
13168
|
-
"record_ui_event",
|
|
13169
|
-
"unknown"
|
|
13170
|
-
];
|
|
13172
|
+
const TELEMETRY_TOOL_NAMES = [...ALL_TOOLS, "unknown"];
|
|
13171
13173
|
const TELEMETRY_COMMAND_IDS = [
|
|
13172
13174
|
"grain.showDaemonInfo",
|
|
13173
13175
|
"grain.mcp.restart",
|
|
@@ -13210,6 +13212,7 @@ const TELEMETRY_STATES = [
|
|
|
13210
13212
|
"extension_host",
|
|
13211
13213
|
"onboarding",
|
|
13212
13214
|
"query_editor",
|
|
13215
|
+
"workspace_ready",
|
|
13213
13216
|
"connection_manager",
|
|
13214
13217
|
"connection_form",
|
|
13215
13218
|
"results_grid",
|
|
@@ -13545,6 +13548,7 @@ const TELEMETRY_ERROR_IDS = [
|
|
|
13545
13548
|
"connection_save_unknown",
|
|
13546
13549
|
/** The supervisor rejected registration of the installed service. */
|
|
13547
13550
|
"service_supervisor_registration_failed",
|
|
13551
|
+
"service_runtime_provision_failed",
|
|
13548
13552
|
/** The supervisor rejected starting the installed service. */
|
|
13549
13553
|
"service_supervisor_start_failed",
|
|
13550
13554
|
/** The supervisor accepted the service, but it never published a reachable endpoint. */
|
|
@@ -13783,6 +13787,27 @@ function resolveProjectedTarget(tabId, payload) {
|
|
|
13783
13787
|
projectedTabId: tabId && parsed ? tabId : createProjectedTabId(sessionId === "all" ? WEB_SESSION_ID : sessionId, remoteTabId)
|
|
13784
13788
|
};
|
|
13785
13789
|
}
|
|
13790
|
+
const WRITE_NOT_CONFIRMED_MESSAGE = "Not run. The write was not confirmed.";
|
|
13791
|
+
async function postWebQuery(body, confirm = (message) => window.confirm(message)) {
|
|
13792
|
+
var _a3;
|
|
13793
|
+
const send = async (payload) => {
|
|
13794
|
+
const res = await authorizedFetch("/api/v1/query", {
|
|
13795
|
+
method: "POST",
|
|
13796
|
+
headers: { "Content-Type": "application/json" },
|
|
13797
|
+
body: JSON.stringify(payload)
|
|
13798
|
+
});
|
|
13799
|
+
return { status: res.status, ok: res.ok, data: await res.json() };
|
|
13800
|
+
};
|
|
13801
|
+
const first = await send(body);
|
|
13802
|
+
if (first.status !== 409 || ((_a3 = first.data) == null ? void 0 : _a3.status) !== "confirmation_required") {
|
|
13803
|
+
return { ok: first.ok, data: first.data };
|
|
13804
|
+
}
|
|
13805
|
+
if (!confirm(`${first.data.error} Run it anyway?`)) {
|
|
13806
|
+
return { ok: false, data: { error: WRITE_NOT_CONFIRMED_MESSAGE } };
|
|
13807
|
+
}
|
|
13808
|
+
const second = await send({ ...body, confirmWrite: true });
|
|
13809
|
+
return { ok: second.ok, data: second.data };
|
|
13810
|
+
}
|
|
13786
13811
|
function useWebCommandDispatcher(dispatch) {
|
|
13787
13812
|
return reactExports.useCallback(
|
|
13788
13813
|
(command, payload) => {
|
|
@@ -13938,19 +13963,14 @@ function useWebCommandDispatcher(dispatch) {
|
|
|
13938
13963
|
clientType: tab == null ? void 0 : tab.clientType,
|
|
13939
13964
|
isRemote: true
|
|
13940
13965
|
});
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
connectionId,
|
|
13948
|
-
tabId: target.remoteTabId
|
|
13949
|
-
})
|
|
13950
|
-
}).then(async (res) => {
|
|
13966
|
+
postWebQuery({
|
|
13967
|
+
query: sql,
|
|
13968
|
+
sessionId: target.sessionId,
|
|
13969
|
+
connectionId,
|
|
13970
|
+
tabId: target.remoteTabId
|
|
13971
|
+
}).then(({ ok, data }) => {
|
|
13951
13972
|
var _a3;
|
|
13952
|
-
|
|
13953
|
-
if (!res.ok) {
|
|
13973
|
+
if (!ok) {
|
|
13954
13974
|
dispatch({
|
|
13955
13975
|
type: "queryError",
|
|
13956
13976
|
tabId: target.projectedTabId,
|
|
@@ -14180,13 +14200,6 @@ function useWebTabSync(options) {
|
|
|
14180
14200
|
]);
|
|
14181
14201
|
return { syncState };
|
|
14182
14202
|
}
|
|
14183
|
-
const WEB_PROXIED_TOOLS = [
|
|
14184
|
-
"list_connectors",
|
|
14185
|
-
"list_connections",
|
|
14186
|
-
"save_connection",
|
|
14187
|
-
"test_connection",
|
|
14188
|
-
"delete_connection"
|
|
14189
|
-
];
|
|
14190
14203
|
const PROXIED_TOOLS = new Set(WEB_PROXIED_TOOLS);
|
|
14191
14204
|
function useWebToolProxy() {
|
|
14192
14205
|
return reactExports.useCallback(async (name, args) => {
|
|
@@ -14205,18 +14218,13 @@ function useWebToolProxy() {
|
|
|
14205
14218
|
}
|
|
14206
14219
|
if (name === "run_query") {
|
|
14207
14220
|
const sessionId = args.session || WEB_SESSION_ID;
|
|
14208
|
-
const
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
sessionId,
|
|
14214
|
-
connectionId: args.connectionId,
|
|
14215
|
-
tabId: args.tabId
|
|
14216
|
-
})
|
|
14221
|
+
const { ok, data } = await postWebQuery({
|
|
14222
|
+
query: args.sql,
|
|
14223
|
+
sessionId,
|
|
14224
|
+
connectionId: args.connectionId,
|
|
14225
|
+
tabId: args.tabId
|
|
14217
14226
|
});
|
|
14218
|
-
|
|
14219
|
-
if (!res.ok) {
|
|
14227
|
+
if (!ok) {
|
|
14220
14228
|
throw new Error(data.error || "Query failed");
|
|
14221
14229
|
}
|
|
14222
14230
|
return {
|
|
@@ -14327,18 +14335,32 @@ function WebHostProvider({ children }) {
|
|
|
14327
14335
|
function ReauthorizeNotice({
|
|
14328
14336
|
reason
|
|
14329
14337
|
}) {
|
|
14338
|
+
const [copied, setCopied] = reactExports.useState(false);
|
|
14339
|
+
const copyCommand = async () => {
|
|
14340
|
+
try {
|
|
14341
|
+
await navigator.clipboard.writeText("grain open");
|
|
14342
|
+
setCopied(true);
|
|
14343
|
+
} catch {
|
|
14344
|
+
setCopied(false);
|
|
14345
|
+
}
|
|
14346
|
+
};
|
|
14330
14347
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-reauth", role: "alert", children: [
|
|
14331
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-title", children:
|
|
14332
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
14333
|
-
|
|
14334
|
-
reason === "no-session" && "A workspace session is short-lived. A new tab, a restart, or a session left open for a while all end up here.",
|
|
14335
|
-
reason === "unreachable" && "The service stopped, or it came back on a different port. This page cannot find it again on its own."
|
|
14336
|
-
] }),
|
|
14337
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
|
|
14338
|
-
"Run ",
|
|
14348
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-title", children: "Grain is running. Reconnect this browser tab." }),
|
|
14349
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Run this command in your terminal to open your workspace again:" }),
|
|
14350
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-reauth-action", children: [
|
|
14339
14351
|
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "sp-web-reauth-command", children: "grain open" }),
|
|
14340
|
-
|
|
14341
|
-
|
|
14352
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
14353
|
+
"button",
|
|
14354
|
+
{
|
|
14355
|
+
type: "button",
|
|
14356
|
+
className: "sp-web-secondary-button",
|
|
14357
|
+
onClick: () => void copyCommand(),
|
|
14358
|
+
"aria-label": "Copy grain open",
|
|
14359
|
+
children: copied ? "Copied" : "Copy"
|
|
14360
|
+
}
|
|
14361
|
+
)
|
|
14362
|
+
] }),
|
|
14363
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-reauth-detail", children: reason === "expired-link" ? "This link has expired or was already used." : reason === "unreachable" ? "Grain may have restarted since this tab opened." : "This tab needs a fresh workspace link." })
|
|
14342
14364
|
] });
|
|
14343
14365
|
}
|
|
14344
14366
|
function isUpdateMarkerStatus(value) {
|
|
@@ -14459,20 +14481,25 @@ function fieldVisible(field, values) {
|
|
|
14459
14481
|
}
|
|
14460
14482
|
function ConnectionSetupPage({
|
|
14461
14483
|
onDone,
|
|
14462
|
-
onCancel
|
|
14484
|
+
onCancel,
|
|
14485
|
+
initialConnection
|
|
14463
14486
|
}) {
|
|
14464
14487
|
var _a3;
|
|
14465
14488
|
const { callServerTool, isReady } = useHostContext();
|
|
14466
14489
|
const [connectors, setConnectors] = reactExports.useState([]);
|
|
14467
|
-
const [type, setType] = reactExports.useState("");
|
|
14468
|
-
const [values, setValues] = reactExports.useState({});
|
|
14469
|
-
const [name, setName] = reactExports.useState("");
|
|
14490
|
+
const [type, setType] = reactExports.useState(String((initialConnection == null ? void 0 : initialConnection["type"]) ?? ""));
|
|
14491
|
+
const [values, setValues] = reactExports.useState(initialConnection ?? {});
|
|
14492
|
+
const [name, setName] = reactExports.useState(String((initialConnection == null ? void 0 : initialConnection["name"]) ?? ""));
|
|
14470
14493
|
const [password, setPassword] = reactExports.useState("");
|
|
14471
14494
|
const [showPassword, setShowPassword] = reactExports.useState(false);
|
|
14472
14495
|
const [busy, setBusy] = reactExports.useState(null);
|
|
14473
14496
|
const [error, setError] = reactExports.useState("");
|
|
14474
14497
|
const [tested, setTested] = reactExports.useState(false);
|
|
14475
|
-
const [draftId] = reactExports.useState(
|
|
14498
|
+
const [draftId] = reactExports.useState(
|
|
14499
|
+
() => String(
|
|
14500
|
+
(initialConnection == null ? void 0 : initialConnection["id"]) ?? `conn_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
14501
|
+
)
|
|
14502
|
+
);
|
|
14476
14503
|
reactExports.useEffect(() => {
|
|
14477
14504
|
if (!isReady) {
|
|
14478
14505
|
return;
|
|
@@ -14498,11 +14525,12 @@ function ConnectionSetupPage({
|
|
|
14498
14525
|
setConnectors(available);
|
|
14499
14526
|
const first = available[0];
|
|
14500
14527
|
setType((current2) => current2 || (first == null ? void 0 : first.id) || "");
|
|
14501
|
-
|
|
14502
|
-
|
|
14503
|
-
Object.
|
|
14504
|
-
|
|
14505
|
-
|
|
14528
|
+
if (!initialConnection)
|
|
14529
|
+
setValues(
|
|
14530
|
+
Object.fromEntries(
|
|
14531
|
+
Object.entries(((_a4 = first == null ? void 0 : first.schema) == null ? void 0 : _a4.properties) ?? {}).filter(([key, field]) => key !== "password" && field.default !== void 0).map(([key, field]) => [key, field.default])
|
|
14532
|
+
)
|
|
14533
|
+
);
|
|
14506
14534
|
}).catch((cause) => {
|
|
14507
14535
|
if (active) {
|
|
14508
14536
|
setError(cause instanceof Error ? cause.message : String(cause));
|
|
@@ -14511,7 +14539,7 @@ function ConnectionSetupPage({
|
|
|
14511
14539
|
return () => {
|
|
14512
14540
|
active = false;
|
|
14513
14541
|
};
|
|
14514
|
-
}, [callServerTool, isReady]);
|
|
14542
|
+
}, [callServerTool, isReady, initialConnection]);
|
|
14515
14543
|
const selected = connectors.find((connector) => connector.id === type);
|
|
14516
14544
|
const properties = ((_a3 = selected == null ? void 0 : selected.schema) == null ? void 0 : _a3.properties) ?? {};
|
|
14517
14545
|
const entries = Object.entries(properties).filter(([key, field]) => {
|
|
@@ -14537,10 +14565,10 @@ function ConnectionSetupPage({
|
|
|
14537
14565
|
...Object.fromEntries(entries.map(([key, field]) => [key, values[key] ?? field.default]))
|
|
14538
14566
|
});
|
|
14539
14567
|
const test = async () => {
|
|
14540
|
-
const result = await callServerTool(
|
|
14541
|
-
|
|
14542
|
-
connectionProfile: { ...profile(), ...password ? { password } : {} }
|
|
14543
|
-
|
|
14568
|
+
const result = await callServerTool(
|
|
14569
|
+
"test_connection",
|
|
14570
|
+
initialConnection && !password ? { connectionId: draftId } : { type, connectionProfile: { ...profile(), ...password ? { password } : {} } }
|
|
14571
|
+
);
|
|
14544
14572
|
const structured = result.structuredContent;
|
|
14545
14573
|
if (result.isError || (structured == null ? void 0 : structured.success) === false || /failed|error/i.test(toolMessage(result))) {
|
|
14546
14574
|
throw new Error(toolMessage(result));
|
|
@@ -14641,7 +14669,7 @@ function ConnectionSetupPage({
|
|
|
14641
14669
|
};
|
|
14642
14670
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("main", { className: "grain-connection-page", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-content", children: [
|
|
14643
14671
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grain-connection-intro", children: [
|
|
14644
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: "Connect a database" }),
|
|
14672
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: initialConnection ? "Edit connection" : "Connect a database" }),
|
|
14645
14673
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Add a connection to start querying your data." })
|
|
14646
14674
|
] }),
|
|
14647
14675
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("form", { onSubmit: handleSubmit, children: [
|
|
@@ -149282,9 +149310,6 @@ function FileIcon({ size = 20 }) {
|
|
|
149282
149310
|
function PlugIcon({ size = 17 }) {
|
|
149283
149311
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5.5 1.5h1.4v3h2.2v-3h1.4v3h1a.5.5 0 01.5.5v2a4 4 0 01-3.3 3.94v1.06a1.5 1.5 0 01-3 0v-1.06A4 4 0 012.4 7V5a.5.5 0 01.5-.5h2.6v-3z" }) });
|
|
149284
149312
|
}
|
|
149285
|
-
function UndoIcon({ size = 16 }) {
|
|
149286
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C20.48 10.9 16.89 8 12.5 8z" }) });
|
|
149287
|
-
}
|
|
149288
149313
|
const MIN_WIDTH = 200;
|
|
149289
149314
|
const KEYBOARD_RESIZE_STEP = 16;
|
|
149290
149315
|
function maxWidth() {
|
|
@@ -149772,6 +149797,199 @@ function ConnectorGlyph({ type }) {
|
|
|
149772
149797
|
function getConnectorGroup(id) {
|
|
149773
149798
|
return id === "duckdb" || id === "sqlite" ? "local" : "server";
|
|
149774
149799
|
}
|
|
149800
|
+
const PATHS = {
|
|
149801
|
+
play: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5 3.5v9l7-4.5-7-4.5z" }),
|
|
149802
|
+
stop: /* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1" }),
|
|
149803
|
+
copy: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
149804
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "5.5", y: "5.5", width: "8", height: "8", rx: "1.5" }),
|
|
149805
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M10.5 3.5v-.5a1 1 0 0 0-1-1H3.5a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h.5" })
|
|
149806
|
+
] }),
|
|
149807
|
+
download: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M8 2.5v8M4.5 7L8 10.5 11.5 7M3 13.5h10" }),
|
|
149808
|
+
filter: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M2.5 3.5h11L9.25 8.5v4l-2.5 1.25V8.5L2.5 3.5z" }),
|
|
149809
|
+
close: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M4 4l8 8M12 4l-8 8" }),
|
|
149810
|
+
settings: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
149811
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "8", cy: "8", r: "2" }),
|
|
149812
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M8 1.75v1.5M8 12.75v1.5M14.25 8h-1.5M3.25 8h-1.5M12.42 3.58l-1.06 1.06M4.64 11.36l-1.06 1.06M12.42 12.42l-1.06-1.06M4.64 4.64L3.58 3.58" })
|
|
149813
|
+
] }),
|
|
149814
|
+
refresh: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M13.5 8a5.5 5.5 0 1 1-1.61-3.89M13.5 2.5v3h-3" }),
|
|
149815
|
+
undo: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M5.5 3L2.5 6l3 3M2.5 6h7a4 4 0 0 1 0 8H7" }),
|
|
149816
|
+
"arrow-left": /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M13 8H3M7 4L3 8l4 4" }),
|
|
149817
|
+
"chevron-down": /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M4 6l4 4 4-4" }),
|
|
149818
|
+
alert: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
149819
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "8", cy: "8", r: "6" }),
|
|
149820
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M8 4.75v3.75M8 10.75v.5" })
|
|
149821
|
+
] }),
|
|
149822
|
+
info: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
149823
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "8", cy: "8", r: "6" }),
|
|
149824
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M8 7.25v3.75M8 4.75v.5" })
|
|
149825
|
+
] }),
|
|
149826
|
+
warning: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M8 2.25L14.25 13H1.75L8 2.25zM8 6.5v3M8 11.25v.25" }),
|
|
149827
|
+
check: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M3 8.5l3 3 7-7" }),
|
|
149828
|
+
plus: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M8 3v10M3 8h10" }),
|
|
149829
|
+
file: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
149830
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 1.75H4.25a1 1 0 0 0-1 1v10.5a1 1 0 0 0 1 1h7.5a1 1 0 0 0 1-1V5.5L9 1.75z" }),
|
|
149831
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 1.75V5.5h3.75" })
|
|
149832
|
+
] }),
|
|
149833
|
+
grid: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
149834
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "2.5", y: "2.5", width: "11", height: "11", rx: "1.5" }),
|
|
149835
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M2.5 6.5h11M2.5 10h11M6.5 6.5v7" })
|
|
149836
|
+
] }),
|
|
149837
|
+
chart: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M2.5 13.5h11M4.5 11V8M8 11V4M11.5 11V6.5" }),
|
|
149838
|
+
more: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
149839
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "3.5", cy: "8", r: "0.75" }),
|
|
149840
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "8", cy: "8", r: "0.75" }),
|
|
149841
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12.5", cy: "8", r: "0.75" })
|
|
149842
|
+
] })
|
|
149843
|
+
};
|
|
149844
|
+
function Icon({ name, size = 14, className }) {
|
|
149845
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
149846
|
+
"svg",
|
|
149847
|
+
{
|
|
149848
|
+
className: className ? `sp-icon ${className}` : "sp-icon",
|
|
149849
|
+
width: size,
|
|
149850
|
+
height: size,
|
|
149851
|
+
viewBox: "0 0 16 16",
|
|
149852
|
+
fill: "none",
|
|
149853
|
+
stroke: "currentColor",
|
|
149854
|
+
strokeWidth: 1.4,
|
|
149855
|
+
strokeLinecap: "round",
|
|
149856
|
+
strokeLinejoin: "round",
|
|
149857
|
+
"aria-hidden": "true",
|
|
149858
|
+
focusable: "false",
|
|
149859
|
+
children: PATHS[name]
|
|
149860
|
+
}
|
|
149861
|
+
);
|
|
149862
|
+
}
|
|
149863
|
+
const VARIANT_CLASS = {
|
|
149864
|
+
primary: "sp-btn sp-btn-primary",
|
|
149865
|
+
secondary: "sp-btn",
|
|
149866
|
+
ghost: "sp-btn sp-btn-ghost",
|
|
149867
|
+
danger: "sp-btn sp-btn-danger"
|
|
149868
|
+
};
|
|
149869
|
+
const Button = reactExports.forwardRef(function Button2({ variant = "secondary", icon, children, className, type = "button", ...rest }, ref) {
|
|
149870
|
+
const classes = className ? `${VARIANT_CLASS[variant]} ${className}` : VARIANT_CLASS[variant];
|
|
149871
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { ref, type, className: classes, ...rest, children: [
|
|
149872
|
+
icon && /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: icon, size: 14 }),
|
|
149873
|
+
children
|
|
149874
|
+
] });
|
|
149875
|
+
});
|
|
149876
|
+
const IconButton = reactExports.forwardRef(function IconButton2({ icon, label, active, className, type = "button", title, ...rest }, ref) {
|
|
149877
|
+
const classes = ["sp-icon-btn", active ? "active" : "", className ?? ""].filter(Boolean).join(" ");
|
|
149878
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
149879
|
+
"button",
|
|
149880
|
+
{
|
|
149881
|
+
ref,
|
|
149882
|
+
type,
|
|
149883
|
+
className: classes,
|
|
149884
|
+
"aria-label": label,
|
|
149885
|
+
title: title ?? label,
|
|
149886
|
+
...rest,
|
|
149887
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: icon, size: 14 })
|
|
149888
|
+
}
|
|
149889
|
+
);
|
|
149890
|
+
});
|
|
149891
|
+
const TONE_ICON = {
|
|
149892
|
+
error: "alert",
|
|
149893
|
+
warning: "warning",
|
|
149894
|
+
info: "info",
|
|
149895
|
+
neutral: "info"
|
|
149896
|
+
};
|
|
149897
|
+
function Notice({
|
|
149898
|
+
tone,
|
|
149899
|
+
title,
|
|
149900
|
+
children,
|
|
149901
|
+
actions: actions2,
|
|
149902
|
+
onDismiss,
|
|
149903
|
+
dismissLabel = "Dismiss",
|
|
149904
|
+
role = tone === "error" ? "alert" : "status"
|
|
149905
|
+
}) {
|
|
149906
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `sp-notice sp-notice-${tone}`, role, children: [
|
|
149907
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-notice-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: TONE_ICON[tone], size: 14 }) }),
|
|
149908
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-notice-body", children: [
|
|
149909
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-notice-title", children: title }),
|
|
149910
|
+
children && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-notice-detail", children })
|
|
149911
|
+
] }),
|
|
149912
|
+
actions2 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-notice-actions", children: actions2 }),
|
|
149913
|
+
onDismiss && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
149914
|
+
"button",
|
|
149915
|
+
{
|
|
149916
|
+
type: "button",
|
|
149917
|
+
className: "sp-icon-btn sp-notice-dismiss",
|
|
149918
|
+
onClick: onDismiss,
|
|
149919
|
+
"aria-label": dismissLabel,
|
|
149920
|
+
title: dismissLabel,
|
|
149921
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: "close", size: 12 })
|
|
149922
|
+
}
|
|
149923
|
+
)
|
|
149924
|
+
] });
|
|
149925
|
+
}
|
|
149926
|
+
function EmptyState({
|
|
149927
|
+
icon,
|
|
149928
|
+
tone = "neutral",
|
|
149929
|
+
title,
|
|
149930
|
+
children,
|
|
149931
|
+
actions: actions2,
|
|
149932
|
+
role,
|
|
149933
|
+
live
|
|
149934
|
+
}) {
|
|
149935
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
149936
|
+
"div",
|
|
149937
|
+
{
|
|
149938
|
+
className: `sp-empty-state sp-empty-state-${tone}`,
|
|
149939
|
+
role,
|
|
149940
|
+
"aria-live": live ? "polite" : void 0,
|
|
149941
|
+
children: [
|
|
149942
|
+
icon && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-empty-state-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: icon, size: 18 }) }),
|
|
149943
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-empty-state-title", children: title }),
|
|
149944
|
+
children && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-empty-state-detail", children }),
|
|
149945
|
+
actions2 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-empty-state-actions", children: actions2 })
|
|
149946
|
+
]
|
|
149947
|
+
}
|
|
149948
|
+
);
|
|
149949
|
+
}
|
|
149950
|
+
function ProgressBar({ label = "Working" }) {
|
|
149951
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-progress", role: "progressbar", "aria-label": label, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-progress-bar" }) });
|
|
149952
|
+
}
|
|
149953
|
+
function BusyDot({ label }) {
|
|
149954
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-busy-dot", role: label ? "img" : void 0, "aria-label": label, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", {}) });
|
|
149955
|
+
}
|
|
149956
|
+
function PageHeader({ title, backLabel, onBack, meta, actions: actions2 }) {
|
|
149957
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("header", { className: "sp-page-header", children: [
|
|
149958
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "sp-page-back", onClick: onBack, children: [
|
|
149959
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: "arrow-left", size: 14 }),
|
|
149960
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: backLabel })
|
|
149961
|
+
] }),
|
|
149962
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-page-header-sep", "aria-hidden": "true", children: "/" }),
|
|
149963
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "sp-page-title", children: title }),
|
|
149964
|
+
meta && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-page-meta", children: meta }),
|
|
149965
|
+
actions2 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-page-actions", children: actions2 })
|
|
149966
|
+
] });
|
|
149967
|
+
}
|
|
149968
|
+
function ToggleChip({
|
|
149969
|
+
checked,
|
|
149970
|
+
onChange,
|
|
149971
|
+
icon,
|
|
149972
|
+
children,
|
|
149973
|
+
title,
|
|
149974
|
+
ariaLabel
|
|
149975
|
+
}) {
|
|
149976
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
149977
|
+
"button",
|
|
149978
|
+
{
|
|
149979
|
+
type: "button",
|
|
149980
|
+
role: "switch",
|
|
149981
|
+
"aria-checked": checked,
|
|
149982
|
+
"aria-label": ariaLabel,
|
|
149983
|
+
title,
|
|
149984
|
+
className: `sp-chip${checked ? " on" : ""}`,
|
|
149985
|
+
onClick: () => onChange(!checked),
|
|
149986
|
+
children: [
|
|
149987
|
+
icon && /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { name: icon, size: 12 }),
|
|
149988
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-chip-label", children })
|
|
149989
|
+
]
|
|
149990
|
+
}
|
|
149991
|
+
);
|
|
149992
|
+
}
|
|
149775
149993
|
const OPTIONAL_DRIVERS = [
|
|
149776
149994
|
{
|
|
149777
149995
|
connectorType: "snowflake",
|
|
@@ -149971,7 +150189,7 @@ function schemaForConnectionMode(schema, connectorId, mode) {
|
|
|
149971
150189
|
}
|
|
149972
150190
|
};
|
|
149973
150191
|
}
|
|
149974
|
-
const ConnectionsManager = ({ initialAdd = false }) => {
|
|
150192
|
+
const ConnectionsManager = ({ initialAdd = false, onSubpageChange }) => {
|
|
149975
150193
|
const { callServerTool, isReady, mode, sendMessage, onMessage } = useHostContext();
|
|
149976
150194
|
const supportsActiveConnection = mode === "vscode";
|
|
149977
150195
|
const trackUi = useTrackUi();
|
|
@@ -149999,6 +150217,7 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
149999
150217
|
const [isPopoverOpen, setIsPopoverOpen] = reactExports.useState(false);
|
|
150000
150218
|
const switcherWrapRef = reactExports.useRef(null);
|
|
150001
150219
|
const isFormVisible = isFormOpen || !!selectedConnectionId;
|
|
150220
|
+
reactExports.useEffect(() => onSubpageChange == null ? void 0 : onSubpageChange(isFormVisible), [isFormVisible, onSubpageChange]);
|
|
150002
150221
|
reactExports.useEffect(() => {
|
|
150003
150222
|
if (isFormVisible) {
|
|
150004
150223
|
trackUi("ui_state_shown", { state: "connection_form" });
|
|
@@ -150040,7 +150259,6 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150040
150259
|
}
|
|
150041
150260
|
setConnectionsUnreachable(false);
|
|
150042
150261
|
} catch (e2) {
|
|
150043
|
-
console.error("Failed to fetch data:", e2);
|
|
150044
150262
|
setConnectionsUnreachable(true);
|
|
150045
150263
|
} finally {
|
|
150046
150264
|
setIsLoading(false);
|
|
@@ -150050,7 +150268,16 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150050
150268
|
fetchData();
|
|
150051
150269
|
}, [fetchData]);
|
|
150052
150270
|
reactExports.useEffect(() => {
|
|
150053
|
-
if (!
|
|
150271
|
+
if (!connectionsUnreachable) {
|
|
150272
|
+
return;
|
|
150273
|
+
}
|
|
150274
|
+
const timer = setInterval(() => void fetchData(), 5e3);
|
|
150275
|
+
return () => clearInterval(timer);
|
|
150276
|
+
}, [connectionsUnreachable, fetchData]);
|
|
150277
|
+
reactExports.useEffect(() => {
|
|
150278
|
+
if (!onMessage) {
|
|
150279
|
+
return;
|
|
150280
|
+
}
|
|
150054
150281
|
return onMessage((msg) => {
|
|
150055
150282
|
if ((msg == null ? void 0 : msg.type) === "connectionsImported" || (msg == null ? void 0 : msg.type) === "updateConfig") {
|
|
150056
150283
|
void fetchData();
|
|
@@ -150223,7 +150450,9 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150223
150450
|
}
|
|
150224
150451
|
};
|
|
150225
150452
|
const handleDeleteConnection = (id, name) => {
|
|
150226
|
-
if (!isReady)
|
|
150453
|
+
if (!isReady) {
|
|
150454
|
+
return;
|
|
150455
|
+
}
|
|
150227
150456
|
setPendingConfirm({
|
|
150228
150457
|
title: "Delete connection",
|
|
150229
150458
|
message: `Delete connection '${name}'? This can't be undone.`,
|
|
@@ -150334,6 +150563,23 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150334
150563
|
setSelectedType("");
|
|
150335
150564
|
setToast(null);
|
|
150336
150565
|
}, []);
|
|
150566
|
+
reactExports.useEffect(() => {
|
|
150567
|
+
if (!isFormVisible) {
|
|
150568
|
+
return;
|
|
150569
|
+
}
|
|
150570
|
+
const onKeyDown = (event) => {
|
|
150571
|
+
if (event.key !== "Escape" || pendingConfirm) {
|
|
150572
|
+
return;
|
|
150573
|
+
}
|
|
150574
|
+
const target = event.target;
|
|
150575
|
+
if (target instanceof Element && target.closest("input, select, textarea")) {
|
|
150576
|
+
return;
|
|
150577
|
+
}
|
|
150578
|
+
closeForm();
|
|
150579
|
+
};
|
|
150580
|
+
document.addEventListener("keydown", onKeyDown);
|
|
150581
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
150582
|
+
}, [isFormVisible, pendingConfirm, closeForm]);
|
|
150337
150583
|
reactExports.useEffect(() => {
|
|
150338
150584
|
function handleClickOutside(event) {
|
|
150339
150585
|
if (isPopoverOpen && switcherWrapRef.current && !switcherWrapRef.current.contains(event.target)) {
|
|
@@ -150352,7 +150598,9 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150352
150598
|
);
|
|
150353
150599
|
const emptyFormInitialData = reactExports.useMemo(() => ({}), []);
|
|
150354
150600
|
const renderToast = () => {
|
|
150355
|
-
if (!toast)
|
|
150601
|
+
if (!toast) {
|
|
150602
|
+
return null;
|
|
150603
|
+
}
|
|
150356
150604
|
const advice = toast.advice;
|
|
150357
150605
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
150358
150606
|
"div",
|
|
@@ -150456,71 +150704,62 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150456
150704
|
}
|
|
150457
150705
|
return null;
|
|
150458
150706
|
};
|
|
150459
|
-
const renderConnectionForm = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-detail", children: [
|
|
150460
|
-
|
|
150461
|
-
|
|
150462
|
-
|
|
150463
|
-
|
|
150464
|
-
|
|
150465
|
-
|
|
150466
|
-
|
|
150467
|
-
|
|
150468
|
-
|
|
150469
|
-
|
|
150470
|
-
|
|
150471
|
-
|
|
150472
|
-
|
|
150473
|
-
|
|
150474
|
-
|
|
150475
|
-
|
|
150476
|
-
|
|
150477
|
-
|
|
150478
|
-
|
|
150479
|
-
|
|
150480
|
-
|
|
150481
|
-
|
|
150482
|
-
|
|
150483
|
-
|
|
150484
|
-
|
|
150485
|
-
|
|
150486
|
-
onClick: () => {
|
|
150487
|
-
setSelectedType(c.id);
|
|
150488
|
-
trackUi("first_value_step", {
|
|
150489
|
-
step: "connector_selected",
|
|
150490
|
-
outcome: "success"
|
|
150491
|
-
});
|
|
150492
|
-
},
|
|
150493
|
-
"aria-pressed": selectedType === c.id,
|
|
150494
|
-
children: [
|
|
150495
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-type-card-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ConnectorGlyph, { type: c.id }) }),
|
|
150496
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-type-card-name", children: c.displayName || c.id })
|
|
150497
|
-
]
|
|
150707
|
+
const renderConnectionForm = () => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-detail", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-detail-body", children: [
|
|
150708
|
+
renderToast(),
|
|
150709
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-form-section", children: "Database Type" }),
|
|
150710
|
+
["local", "server"].map((group) => {
|
|
150711
|
+
const groupConnectors = connectors.filter((c) => getConnectorGroup(c.id) === group);
|
|
150712
|
+
if (groupConnectors.length === 0) {
|
|
150713
|
+
return null;
|
|
150714
|
+
}
|
|
150715
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(React$2.Fragment, { children: [
|
|
150716
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-type-group-label", id: `sp-conn-type-group-${group}`, children: CONNECTOR_GROUP_LABELS[group] }),
|
|
150717
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150718
|
+
"div",
|
|
150719
|
+
{
|
|
150720
|
+
className: "sp-conn-type-grid",
|
|
150721
|
+
role: "group",
|
|
150722
|
+
"aria-labelledby": `sp-conn-type-group-${group}`,
|
|
150723
|
+
children: groupConnectors.map((c) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
150724
|
+
"button",
|
|
150725
|
+
{
|
|
150726
|
+
type: "button",
|
|
150727
|
+
className: `sp-conn-type-card${selectedType === c.id ? " selected" : ""}`,
|
|
150728
|
+
onClick: () => {
|
|
150729
|
+
setSelectedType(c.id);
|
|
150730
|
+
trackUi("first_value_step", {
|
|
150731
|
+
step: "connector_selected",
|
|
150732
|
+
outcome: "success"
|
|
150733
|
+
});
|
|
150498
150734
|
},
|
|
150499
|
-
c.id
|
|
150500
|
-
|
|
150501
|
-
|
|
150502
|
-
|
|
150503
|
-
|
|
150504
|
-
|
|
150505
|
-
|
|
150506
|
-
|
|
150507
|
-
|
|
150508
|
-
|
|
150509
|
-
|
|
150510
|
-
|
|
150511
|
-
|
|
150512
|
-
|
|
150513
|
-
|
|
150514
|
-
}
|
|
150515
|
-
|
|
150516
|
-
|
|
150517
|
-
|
|
150735
|
+
"aria-pressed": selectedType === c.id,
|
|
150736
|
+
children: [
|
|
150737
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-type-card-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ConnectorGlyph, { type: c.id }) }),
|
|
150738
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-type-card-name", children: c.displayName || c.id })
|
|
150739
|
+
]
|
|
150740
|
+
},
|
|
150741
|
+
c.id
|
|
150742
|
+
))
|
|
150743
|
+
}
|
|
150744
|
+
)
|
|
150745
|
+
] }, group);
|
|
150746
|
+
}),
|
|
150747
|
+
activeSchemaDef && activeFormSchema ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150748
|
+
DynamicForm,
|
|
150749
|
+
{
|
|
150750
|
+
schema: { ...activeFormSchema, type: "object" },
|
|
150751
|
+
initialData: emptyFormInitialData,
|
|
150752
|
+
onSubmit: (formData) => handleSaveConnection(formData),
|
|
150753
|
+
onTest: (formData) => handleTestFormData(formData),
|
|
150754
|
+
onCancel: closeForm,
|
|
150755
|
+
isSubmitting: isLoading
|
|
150756
|
+
}
|
|
150757
|
+
) : selectedType ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-form-hint sp-conn-schema-error", children: "This connector does not define a configuration schema." }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-empty sp-conn-empty-compact", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-empty-text", children: "Choose a database type to begin." }) })
|
|
150758
|
+
] }) });
|
|
150518
150759
|
const renderConnectionDetails = () => {
|
|
150519
150760
|
if (!selectedConnection) {
|
|
150520
150761
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-detail", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-empty sp-conn-empty-compact", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-empty-text", children: "Select a connection to view details, test it, or use it for queries." }) }) });
|
|
150521
150762
|
}
|
|
150522
|
-
const status = statuses[selectedConnection.id] || "unknown";
|
|
150523
|
-
const isActive = supportsActiveConnection && activeConnectionId === selectedConnection.id;
|
|
150524
150763
|
const schemaDef = connectors.find((c) => c.id === selectedConnection.type);
|
|
150525
150764
|
const canManagePassword = supportsActiveConnection && schemaHasPasswordField(schemaDef == null ? void 0 : schemaDef.schema);
|
|
150526
150765
|
const editSchema = (schemaDef == null ? void 0 : schemaDef.schema) && canManagePassword ? schemaWithoutPasswordField(schemaDef.schema) : schemaDef == null ? void 0 : schemaDef.schema;
|
|
@@ -150564,78 +150803,22 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150564
150803
|
] })
|
|
150565
150804
|
] });
|
|
150566
150805
|
};
|
|
150567
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-detail", children: [
|
|
150568
|
-
|
|
150569
|
-
|
|
150806
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-detail", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-detail-body", children: [
|
|
150807
|
+
renderToast(),
|
|
150808
|
+
modeAwareEditSchema ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150809
|
+
DynamicForm,
|
|
150570
150810
|
{
|
|
150571
|
-
|
|
150572
|
-
|
|
150573
|
-
|
|
150574
|
-
|
|
150575
|
-
|
|
150576
|
-
|
|
150577
|
-
|
|
150578
|
-
|
|
150579
|
-
|
|
150580
|
-
|
|
150581
|
-
|
|
150582
|
-
children: [
|
|
150583
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px", flexWrap: "wrap" }, children: [
|
|
150584
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: 600, fontSize: "14px", color: "var(--sp-fg)" }, children: selectedConnection ? "Edit Connection" : "New Connection" }),
|
|
150585
|
-
selectedConnection && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
150586
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-type-badge", children: selectedConnection.type }),
|
|
150587
|
-
isActive && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-active-badge", children: "Active" }),
|
|
150588
|
-
selectedConnection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-built-in-label", children: "Built-in" })
|
|
150589
|
-
] })
|
|
150590
|
-
] }),
|
|
150591
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
150592
|
-
"div",
|
|
150593
|
-
{
|
|
150594
|
-
className: "sp-conn-detail-actions",
|
|
150595
|
-
style: { display: "flex", gap: "8px", flexWrap: "wrap" },
|
|
150596
|
-
children: [
|
|
150597
|
-
supportsActiveConnection && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150598
|
-
"button",
|
|
150599
|
-
{
|
|
150600
|
-
className: `sp-btn${isActive ? " sp-btn-primary" : ""}`,
|
|
150601
|
-
onClick: () => handleSetActiveConnection(selectedConnection),
|
|
150602
|
-
disabled: isActive || status === "testing",
|
|
150603
|
-
"aria-label": `Set ${selectedConnection.name} as the active connection for queries`,
|
|
150604
|
-
children: isActive ? "Active" : "Set active"
|
|
150605
|
-
}
|
|
150606
|
-
),
|
|
150607
|
-
!selectedConnection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150608
|
-
"button",
|
|
150609
|
-
{
|
|
150610
|
-
className: "sp-btn sp-btn-ghost-danger",
|
|
150611
|
-
onClick: () => handleDeleteConnection(selectedConnection.id, selectedConnection.name),
|
|
150612
|
-
"aria-label": `Delete connection ${selectedConnection.name}`,
|
|
150613
|
-
children: "Delete"
|
|
150614
|
-
}
|
|
150615
|
-
)
|
|
150616
|
-
]
|
|
150617
|
-
}
|
|
150618
|
-
)
|
|
150619
|
-
]
|
|
150620
|
-
}
|
|
150621
|
-
),
|
|
150622
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-detail-body", children: [
|
|
150623
|
-
renderToast(),
|
|
150624
|
-
modeAwareEditSchema ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150625
|
-
DynamicForm,
|
|
150626
|
-
{
|
|
150627
|
-
schema: { ...modeAwareEditSchema, type: "object" },
|
|
150628
|
-
initialData: selectedFormInitialData,
|
|
150629
|
-
onSubmit: (formData) => handleSaveConnection(formData, selectedConnection),
|
|
150630
|
-
onTest: (formData) => handleTestFormData(formData, selectedConnection),
|
|
150631
|
-
isSubmitting: isLoading,
|
|
150632
|
-
renderAfterField: renderPasswordManagementField,
|
|
150633
|
-
actionStatus: renderConnectionStatusMessage(selectedConnection),
|
|
150634
|
-
submitFeedback: lastSavedConnectionId === selectedConnection.id ? "Saved successfully" : void 0
|
|
150635
|
-
}
|
|
150636
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-form-hint", style: { color: "var(--sp-error)" }, children: "This connector does not define a configuration schema." })
|
|
150637
|
-
] })
|
|
150638
|
-
] });
|
|
150811
|
+
schema: { ...modeAwareEditSchema, type: "object" },
|
|
150812
|
+
initialData: selectedFormInitialData,
|
|
150813
|
+
onSubmit: (formData) => handleSaveConnection(formData, selectedConnection),
|
|
150814
|
+
onTest: (formData) => handleTestFormData(formData, selectedConnection),
|
|
150815
|
+
isSubmitting: isLoading,
|
|
150816
|
+
renderAfterField: renderPasswordManagementField,
|
|
150817
|
+
actionStatus: renderConnectionStatusMessage(selectedConnection),
|
|
150818
|
+
submitFeedback: lastSavedConnectionId === selectedConnection.id ? "Saved successfully" : void 0
|
|
150819
|
+
}
|
|
150820
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-form-hint sp-conn-schema-error", children: "This connector does not define a configuration schema." })
|
|
150821
|
+
] }) });
|
|
150639
150822
|
};
|
|
150640
150823
|
const renderGrid = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-grid-view", children: [
|
|
150641
150824
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-head", style: { marginBottom: 16 }, children: [
|
|
@@ -150701,7 +150884,11 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150701
150884
|
gap: "12px"
|
|
150702
150885
|
},
|
|
150703
150886
|
children: connections.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-empty", style: { gridColumn: "1 / -1" }, children: [
|
|
150704
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: connectionsUnreachable ? "Can't reach
|
|
150887
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: connectionsUnreachable ? "Can't reach Grain. Start Grain and try again." : "No connections configured." }),
|
|
150888
|
+
connectionsUnreachable && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { marginTop: 12, display: "flex", gap: 8 }, children: [
|
|
150889
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: fetchData, children: "Retry" }),
|
|
150890
|
+
mode === "vscode" && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: () => sendMessage == null ? void 0 : sendMessage("startGrain"), children: "Start Grain" })
|
|
150891
|
+
] }),
|
|
150705
150892
|
mode === "vscode" && !connectionsUnreachable && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginTop: 12 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150706
150893
|
"button",
|
|
150707
150894
|
{
|
|
@@ -150791,30 +150978,45 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150791
150978
|
}
|
|
150792
150979
|
)
|
|
150793
150980
|
] });
|
|
150794
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-conn-page", children: [
|
|
150795
|
-
|
|
150981
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: isFormVisible ? "sp-conn-subpage" : "sp-conn-page", children: [
|
|
150982
|
+
isFormVisible ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
150796
150983
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150797
|
-
|
|
150984
|
+
PageHeader,
|
|
150798
150985
|
{
|
|
150799
|
-
|
|
150800
|
-
|
|
150801
|
-
|
|
150802
|
-
|
|
150986
|
+
backLabel: "Connections",
|
|
150987
|
+
onBack: closeForm,
|
|
150988
|
+
title: isFormOpen ? "New connection" : (selectedConnection == null ? void 0 : selectedConnection.name) ?? "Connection",
|
|
150989
|
+
meta: selectedConnection && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
150990
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-type-badge", children: selectedConnection.type }),
|
|
150991
|
+
supportsActiveConnection && activeConnectionId === selectedConnection.id && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-active-badge", children: "Active" }),
|
|
150992
|
+
selectedConnection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-conn-built-in-label", children: "Built-in" })
|
|
150993
|
+
] }),
|
|
150994
|
+
actions: isFormOpen ? /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", onClick: closeForm, "aria-label": "Cancel", children: "Cancel" }) : selectedConnection && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
150995
|
+
supportsActiveConnection && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150996
|
+
Button,
|
|
150997
|
+
{
|
|
150998
|
+
variant: "ghost",
|
|
150999
|
+
onClick: () => handleSetActiveConnection(selectedConnection),
|
|
151000
|
+
disabled: activeConnectionId === selectedConnection.id || statuses[selectedConnection.id] === "testing",
|
|
151001
|
+
"aria-label": `Set ${selectedConnection.name} as the active connection for queries`,
|
|
151002
|
+
children: activeConnectionId === selectedConnection.id ? "Active" : "Set active"
|
|
151003
|
+
}
|
|
151004
|
+
),
|
|
151005
|
+
!selectedConnection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151006
|
+
Button,
|
|
151007
|
+
{
|
|
151008
|
+
variant: "secondary",
|
|
151009
|
+
className: "sp-btn-ghost-danger",
|
|
151010
|
+
onClick: () => handleDeleteConnection(selectedConnection.id, selectedConnection.name),
|
|
151011
|
+
"aria-label": `Delete connection ${selectedConnection.name}`,
|
|
151012
|
+
children: "Delete"
|
|
151013
|
+
}
|
|
151014
|
+
)
|
|
151015
|
+
] })
|
|
150803
151016
|
}
|
|
150804
151017
|
),
|
|
150805
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150806
|
-
|
|
150807
|
-
{
|
|
150808
|
-
"aria-label": "Connection details",
|
|
150809
|
-
style: {
|
|
150810
|
-
background: "var(--sp-bg)",
|
|
150811
|
-
border: "1px solid var(--sp-border)",
|
|
150812
|
-
borderRadius: 6
|
|
150813
|
-
},
|
|
150814
|
-
children: isFormOpen ? renderConnectionForm() : renderConnectionDetails()
|
|
150815
|
-
}
|
|
150816
|
-
)
|
|
150817
|
-
] }) }),
|
|
151018
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn-subpage-body", children: /* @__PURE__ */ jsxRuntimeExports.jsx("section", { "aria-label": "Connection details", className: "sp-conn-subpage-column", children: isFormOpen ? renderConnectionForm() : renderConnectionDetails() }) })
|
|
151019
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-conn", children: renderGrid() }),
|
|
150818
151020
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
150819
151021
|
ConfirmDialog,
|
|
150820
151022
|
{
|
|
@@ -150831,6 +151033,33 @@ const ConnectionsManager = ({ initialAdd = false }) => {
|
|
|
150831
151033
|
)
|
|
150832
151034
|
] });
|
|
150833
151035
|
};
|
|
151036
|
+
const OPTIONS = [
|
|
151037
|
+
["inherit", "Inherit"],
|
|
151038
|
+
["grain-light", "Grain Light"],
|
|
151039
|
+
["grain-dark", "Grain Dark"]
|
|
151040
|
+
];
|
|
151041
|
+
function PanelThemeSetting({
|
|
151042
|
+
value,
|
|
151043
|
+
onChange
|
|
151044
|
+
}) {
|
|
151045
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row", children: [
|
|
151046
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151047
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Theme" }),
|
|
151048
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Inherit follows VS Code. Grain themes use the brand palette." })
|
|
151049
|
+
] }),
|
|
151050
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-segmented", role: "group", "aria-label": "Panel theme", children: OPTIONS.map(([option, label]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151051
|
+
"button",
|
|
151052
|
+
{
|
|
151053
|
+
type: "button",
|
|
151054
|
+
className: `sp-segmented-item${value === option ? " active" : ""}`,
|
|
151055
|
+
"aria-pressed": value === option,
|
|
151056
|
+
onClick: () => onChange(option),
|
|
151057
|
+
children: label
|
|
151058
|
+
},
|
|
151059
|
+
option
|
|
151060
|
+
)) })
|
|
151061
|
+
] });
|
|
151062
|
+
}
|
|
150834
151063
|
const FONT_SIZE_MIN = 8;
|
|
150835
151064
|
const FONT_SIZE_MAX = 20;
|
|
150836
151065
|
function formatFontSize(fontSize) {
|
|
@@ -150890,6 +151119,68 @@ function mcpHttpClientConfig(mcpServerUrl, mcpAuthToken) {
|
|
|
150890
151119
|
}
|
|
150891
151120
|
}`;
|
|
150892
151121
|
}
|
|
151122
|
+
const GROUPS = [
|
|
151123
|
+
{
|
|
151124
|
+
key: "query",
|
|
151125
|
+
label: "Query execution",
|
|
151126
|
+
description: "Run SQL, inspect result tabs, and manage long-running work."
|
|
151127
|
+
},
|
|
151128
|
+
{
|
|
151129
|
+
key: "connections",
|
|
151130
|
+
label: "Connections",
|
|
151131
|
+
description: "Discover connector types and manage saved connection profiles."
|
|
151132
|
+
},
|
|
151133
|
+
{
|
|
151134
|
+
key: "catalog",
|
|
151135
|
+
label: "Catalog",
|
|
151136
|
+
description: "Browse schemas, tables, views, and column metadata."
|
|
151137
|
+
},
|
|
151138
|
+
{
|
|
151139
|
+
key: "charts",
|
|
151140
|
+
label: "Charts",
|
|
151141
|
+
description: "Render result charts and save them as workspace documents."
|
|
151142
|
+
},
|
|
151143
|
+
{
|
|
151144
|
+
key: "ledger",
|
|
151145
|
+
label: "Execution ledger",
|
|
151146
|
+
description: "Check the local record of executed queries."
|
|
151147
|
+
},
|
|
151148
|
+
{
|
|
151149
|
+
key: "sessions",
|
|
151150
|
+
label: "Sessions",
|
|
151151
|
+
description: "Inspect active assistant sessions and their open result tabs."
|
|
151152
|
+
}
|
|
151153
|
+
];
|
|
151154
|
+
const TOOL_ENTRIES = {
|
|
151155
|
+
run_query: ["query", "Execute SQL and open the result in a tab."],
|
|
151156
|
+
get_tab_info: ["query", "Read tab status, columns, rows, and errors."],
|
|
151157
|
+
cancel_query: ["query", "Stop a query that is still running."],
|
|
151158
|
+
close_tab: ["query", "Close a tab from an MCP session."],
|
|
151159
|
+
list_connectors: ["connections", "Show available connector types and schemas."],
|
|
151160
|
+
list_connections: ["connections", "Show saved connection profiles."],
|
|
151161
|
+
save_connection: ["connections", "Create or update a connection profile."],
|
|
151162
|
+
request_connection_credentials: ["connections", "Ask the user to enter a connection password."],
|
|
151163
|
+
test_connection: ["connections", "Verify a saved or draft profile."],
|
|
151164
|
+
delete_connection: ["connections", "Remove a saved profile."],
|
|
151165
|
+
list_schemas: ["catalog", "List schemas for a stored connection."],
|
|
151166
|
+
list_tables: ["catalog", "List tables and views in a schema."],
|
|
151167
|
+
describe_table: ["catalog", "Show column details for a table."],
|
|
151168
|
+
render_chart: ["charts", "Render a chart from a result tab."],
|
|
151169
|
+
save_chart: ["charts", "Save a chart document into the workspace."],
|
|
151170
|
+
list_charts: ["charts", "List chart documents saved in the workspace."],
|
|
151171
|
+
ledger_stats: ["ledger", "Show ledger health and counts."],
|
|
151172
|
+
verify_ledger: ["ledger", "Verify the ledger hash chain."],
|
|
151173
|
+
list_sessions: ["sessions", "Show active MCP sessions and their tabs."],
|
|
151174
|
+
record_ui_event: null
|
|
151175
|
+
};
|
|
151176
|
+
const MCP_TOOL_GROUPS = GROUPS.map((group) => ({
|
|
151177
|
+
label: group.label,
|
|
151178
|
+
description: group.description,
|
|
151179
|
+
tools: ALL_TOOLS.flatMap((name) => {
|
|
151180
|
+
const entry = TOOL_ENTRIES[name];
|
|
151181
|
+
return entry && entry[0] === group.key ? [[name, entry[1]]] : [];
|
|
151182
|
+
})
|
|
151183
|
+
}));
|
|
150893
151184
|
const DUMMY_PREVIEW_DATA = {
|
|
150894
151185
|
query: "SELECT * FROM preview_data",
|
|
150895
151186
|
columns: [
|
|
@@ -150961,43 +151252,6 @@ const MCP_LOGO = /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 1
|
|
|
150961
151252
|
}
|
|
150962
151253
|
)
|
|
150963
151254
|
] });
|
|
150964
|
-
const MCP_TOOL_GROUPS = [
|
|
150965
|
-
{
|
|
150966
|
-
label: "Query execution",
|
|
150967
|
-
description: "Run SQL, inspect result tabs, and manage long-running work.",
|
|
150968
|
-
tools: [
|
|
150969
|
-
["run_query", "Execute SQL and open the result in a tab."],
|
|
150970
|
-
["get_tab_info", "Read tab status, columns, rows, and errors."],
|
|
150971
|
-
["cancel_query", "Stop a query that is still running."],
|
|
150972
|
-
["close_tab", "Close a tab from an MCP session."]
|
|
150973
|
-
]
|
|
150974
|
-
},
|
|
150975
|
-
{
|
|
150976
|
-
label: "Connections",
|
|
150977
|
-
description: "Discover connector types and manage saved connection profiles.",
|
|
150978
|
-
tools: [
|
|
150979
|
-
["list_connectors", "Show available connector types and schemas."],
|
|
150980
|
-
["list_connections", "Show saved connection profiles."],
|
|
150981
|
-
["save_connection", "Create or update a connection profile."],
|
|
150982
|
-
["test_connection", "Verify a saved or draft profile."],
|
|
150983
|
-
["delete_connection", "Remove a saved profile."]
|
|
150984
|
-
]
|
|
150985
|
-
},
|
|
150986
|
-
{
|
|
150987
|
-
label: "Catalog",
|
|
150988
|
-
description: "Browse schemas, tables, views, and column metadata.",
|
|
150989
|
-
tools: [
|
|
150990
|
-
["list_schemas", "List schemas for a stored connection."],
|
|
150991
|
-
["list_tables", "List tables and views in a schema."],
|
|
150992
|
-
["describe_table", "Show column details for a table."]
|
|
150993
|
-
]
|
|
150994
|
-
},
|
|
150995
|
-
{
|
|
150996
|
-
label: "Sessions",
|
|
150997
|
-
description: "Inspect active assistant sessions and their open result tabs.",
|
|
150998
|
-
tools: [["list_sessions", "Show active MCP sessions and their tabs."]]
|
|
150999
|
-
}
|
|
151000
|
-
];
|
|
151001
151255
|
const PREVIEW_MAX_WIDTH = (() => {
|
|
151002
151256
|
const gutterWidth = 42;
|
|
151003
151257
|
const colWidths = DUMMY_PREVIEW_DATA.columns.reduce((sum2, col) => {
|
|
@@ -151031,6 +151285,7 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
151031
151285
|
}, [trackUi]);
|
|
151032
151286
|
const {
|
|
151033
151287
|
theme: theme2,
|
|
151288
|
+
panelTheme,
|
|
151034
151289
|
copyIncludesHeaders,
|
|
151035
151290
|
setCopyIncludesHeaders,
|
|
151036
151291
|
fontSize,
|
|
@@ -151064,6 +151319,9 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
151064
151319
|
const showMcpTab = isStandalone || mcpEntitled;
|
|
151065
151320
|
const actualInitialTab = !showMcpTab && initialTab === "mcp" ? "general" : initialTab;
|
|
151066
151321
|
const [activeTab, setActiveTab] = reactExports.useState(actualInitialTab);
|
|
151322
|
+
const [connectionsSubpage, setConnectionsSubpage] = reactExports.useState(
|
|
151323
|
+
connectionsInitialAdd && actualInitialTab === "connections"
|
|
151324
|
+
);
|
|
151067
151325
|
const [fontSizeError, setFontSizeError] = reactExports.useState(null);
|
|
151068
151326
|
const [testMcpStatus, setTestMcpStatus] = reactExports.useState(null);
|
|
151069
151327
|
reactExports.useEffect(() => {
|
|
@@ -151205,7 +151463,7 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
151205
151463
|
}, 1e4);
|
|
151206
151464
|
};
|
|
151207
151465
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-page", children: [
|
|
151208
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-page-header", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-header-row", children: [
|
|
151466
|
+
!(connectionsSubpage && activeTab === "connections") && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-page-header", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-header-row", children: [
|
|
151209
151467
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-title-group", children: [
|
|
151210
151468
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151211
151469
|
"button",
|
|
@@ -151226,7 +151484,7 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
151226
151484
|
),
|
|
151227
151485
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-settings-page-title", children: "Settings" })
|
|
151228
151486
|
] }),
|
|
151229
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151487
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151230
151488
|
"div",
|
|
151231
151489
|
{
|
|
151232
151490
|
className: "sp-tab-bar-tabs sp-settings-tabs",
|
|
@@ -151234,455 +151492,445 @@ function SettingsPanel({ onSave, onClose, onShowWelcome, initialTab = "general"
|
|
|
151234
151492
|
"aria-label": "Settings sections",
|
|
151235
151493
|
onKeyDown: handleTabListKeyDown,
|
|
151236
151494
|
children: [
|
|
151237
|
-
|
|
151238
|
-
|
|
151239
|
-
|
|
151240
|
-
|
|
151241
|
-
|
|
151242
|
-
|
|
151243
|
-
|
|
151244
|
-
|
|
151245
|
-
|
|
151246
|
-
|
|
151247
|
-
|
|
151248
|
-
|
|
151249
|
-
}
|
|
151250
|
-
|
|
151251
|
-
|
|
151252
|
-
|
|
151253
|
-
|
|
151254
|
-
|
|
151255
|
-
role: "tab",
|
|
151256
|
-
id: "sp-settings-tab-connections",
|
|
151257
|
-
"aria-controls": "sp-settings-panel-connections",
|
|
151258
|
-
"aria-selected": activeTab === "connections",
|
|
151259
|
-
tabIndex: activeTab === "connections" ? 0 : -1,
|
|
151260
|
-
className: `sp-tab${activeTab === "connections" ? " active" : ""}`,
|
|
151261
|
-
onClick: () => setActiveTab("connections"),
|
|
151262
|
-
children: "Connections"
|
|
151263
|
-
}
|
|
151264
|
-
),
|
|
151265
|
-
showMcpTab && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151266
|
-
"button",
|
|
151267
|
-
{
|
|
151268
|
-
type: "button",
|
|
151269
|
-
role: "tab",
|
|
151270
|
-
id: "sp-settings-tab-mcp",
|
|
151271
|
-
"aria-controls": "sp-settings-panel-mcp",
|
|
151272
|
-
"aria-selected": activeTab === "mcp",
|
|
151273
|
-
tabIndex: activeTab === "mcp" ? 0 : -1,
|
|
151274
|
-
className: `sp-tab${activeTab === "mcp" ? " active" : ""}`,
|
|
151275
|
-
onClick: () => setActiveTab("mcp"),
|
|
151276
|
-
children: "MCP Server"
|
|
151277
|
-
}
|
|
151278
|
-
)
|
|
151279
|
-
]
|
|
151495
|
+
["general", "General"],
|
|
151496
|
+
["connections", "Connections"],
|
|
151497
|
+
...showMcpTab ? [["mcp", "MCP Server"]] : []
|
|
151498
|
+
].map(([tab, label]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151499
|
+
"button",
|
|
151500
|
+
{
|
|
151501
|
+
type: "button",
|
|
151502
|
+
role: "tab",
|
|
151503
|
+
id: `sp-settings-tab-${tab}`,
|
|
151504
|
+
"aria-controls": `sp-settings-panel-${tab}`,
|
|
151505
|
+
"aria-selected": activeTab === tab,
|
|
151506
|
+
tabIndex: activeTab === tab ? 0 : -1,
|
|
151507
|
+
className: `sp-tab${activeTab === tab ? " active" : ""}`,
|
|
151508
|
+
onClick: () => setActiveTab(tab),
|
|
151509
|
+
children: label
|
|
151510
|
+
},
|
|
151511
|
+
tab
|
|
151512
|
+
))
|
|
151280
151513
|
}
|
|
151281
151514
|
)
|
|
151282
151515
|
] }) }),
|
|
151283
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151284
|
-
|
|
151285
|
-
|
|
151286
|
-
{
|
|
151287
|
-
|
|
151288
|
-
|
|
151289
|
-
|
|
151290
|
-
|
|
151291
|
-
|
|
151292
|
-
|
|
151293
|
-
|
|
151294
|
-
|
|
151295
|
-
|
|
151296
|
-
|
|
151297
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151298
|
-
"
|
|
151299
|
-
{
|
|
151300
|
-
|
|
151301
|
-
|
|
151302
|
-
|
|
151303
|
-
|
|
151304
|
-
|
|
151305
|
-
|
|
151306
|
-
|
|
151307
|
-
|
|
151308
|
-
|
|
151309
|
-
|
|
151310
|
-
|
|
151311
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-
|
|
151312
|
-
|
|
151313
|
-
|
|
151314
|
-
|
|
151315
|
-
|
|
151316
|
-
|
|
151317
|
-
|
|
151318
|
-
|
|
151319
|
-
|
|
151320
|
-
|
|
151321
|
-
|
|
151322
|
-
|
|
151323
|
-
|
|
151324
|
-
|
|
151325
|
-
|
|
151326
|
-
|
|
151327
|
-
|
|
151328
|
-
|
|
151329
|
-
|
|
151330
|
-
|
|
151331
|
-
|
|
151332
|
-
|
|
151333
|
-
|
|
151334
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151335
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Row density" }),
|
|
151336
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Height of grid rows." })
|
|
151337
|
-
] }),
|
|
151338
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-density-group", role: "group", "aria-label": "Row density", children: ["compact", "normal", "comfortable"].map((d) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151339
|
-
"button",
|
|
151340
|
-
{
|
|
151341
|
-
className: `sp-icon-btn${rowDensity === d ? " active" : ""}`,
|
|
151342
|
-
onClick: () => {
|
|
151343
|
-
setRowDensity(d);
|
|
151344
|
-
onSave({ rowHeight: d });
|
|
151345
|
-
},
|
|
151346
|
-
title: getDensityLabel(d),
|
|
151347
|
-
"aria-label": `${getDensityLabel(d)} row density`,
|
|
151348
|
-
"aria-pressed": rowDensity === d,
|
|
151349
|
-
children: DENSITY_ICONS[d]
|
|
151350
|
-
},
|
|
151351
|
-
d
|
|
151352
|
-
)) })
|
|
151353
|
-
] }),
|
|
151354
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "sp-settings-row", children: [
|
|
151355
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151356
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Font size" }),
|
|
151357
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Results grid font size. Leave blank to inherit." })
|
|
151516
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151517
|
+
"div",
|
|
151518
|
+
{
|
|
151519
|
+
className: `sp-settings-page-body${connectionsSubpage && activeTab === "connections" ? " sp-settings-page-body-subpage" : ""}`,
|
|
151520
|
+
children: [
|
|
151521
|
+
activeTab === "general" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151522
|
+
"div",
|
|
151523
|
+
{
|
|
151524
|
+
className: "sp-settings-layout",
|
|
151525
|
+
role: "tabpanel",
|
|
151526
|
+
id: "sp-settings-panel-general",
|
|
151527
|
+
"aria-labelledby": "sp-settings-tab-general",
|
|
151528
|
+
children: [
|
|
151529
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-main", children: [
|
|
151530
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-card", children: [
|
|
151531
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "Results" }),
|
|
151532
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "sp-settings-row", children: [
|
|
151533
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Copy includes headers" }),
|
|
151534
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151535
|
+
"input",
|
|
151536
|
+
{
|
|
151537
|
+
type: "checkbox",
|
|
151538
|
+
className: "sp-settings-check",
|
|
151539
|
+
checked: copyIncludesHeaders,
|
|
151540
|
+
onChange: (e2) => setCopyIncludesHeaders(e2.target.checked)
|
|
151541
|
+
}
|
|
151542
|
+
)
|
|
151543
|
+
] }),
|
|
151544
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-divider" }),
|
|
151545
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "sp-settings-row", children: [
|
|
151546
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151547
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Max rows to display" }),
|
|
151548
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Rows fetched per query. Increase for larger exports." })
|
|
151549
|
+
] }),
|
|
151550
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151551
|
+
"input",
|
|
151552
|
+
{
|
|
151553
|
+
type: "number",
|
|
151554
|
+
className: "sp-settings-input",
|
|
151555
|
+
value: localMaxRows,
|
|
151556
|
+
min: 1,
|
|
151557
|
+
max: 1e5,
|
|
151558
|
+
placeholder: "e.g. 1000",
|
|
151559
|
+
onChange: (e2) => handleMaxRowsChange(e2.target.value),
|
|
151560
|
+
onBlur: handleMaxRowsDone,
|
|
151561
|
+
onKeyDown: (e2) => {
|
|
151562
|
+
if (e2.key === "Enter") handleMaxRowsDone();
|
|
151563
|
+
}
|
|
151564
|
+
}
|
|
151565
|
+
)
|
|
151566
|
+
] })
|
|
151358
151567
|
] }),
|
|
151359
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151360
|
-
"
|
|
151361
|
-
{
|
|
151362
|
-
|
|
151363
|
-
|
|
151364
|
-
|
|
151365
|
-
|
|
151366
|
-
|
|
151367
|
-
|
|
151368
|
-
|
|
151369
|
-
|
|
151370
|
-
|
|
151371
|
-
|
|
151372
|
-
|
|
151373
|
-
|
|
151374
|
-
|
|
151375
|
-
|
|
151376
|
-
|
|
151377
|
-
|
|
151378
|
-
|
|
151379
|
-
|
|
151380
|
-
|
|
151381
|
-
|
|
151382
|
-
|
|
151383
|
-
|
|
151384
|
-
{
|
|
151385
|
-
className: "sp-settings-row",
|
|
151386
|
-
title: isStandalone ? "Telemetry is sent by the VS Code extension; this browser tab has no sender to control." : void 0,
|
|
151387
|
-
children: [
|
|
151568
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-card", children: [
|
|
151569
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "Display" }),
|
|
151570
|
+
mode === "vscode" && /* @__PURE__ */ jsxRuntimeExports.jsx(PanelThemeSetting, { value: panelTheme, onChange: (t) => onSave({ panelTheme: t }) }),
|
|
151571
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row", children: [
|
|
151572
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151573
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Row density" }),
|
|
151574
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Height of grid rows." })
|
|
151575
|
+
] }),
|
|
151576
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-density-group", role: "group", "aria-label": "Row density", children: ["compact", "normal", "comfortable"].map((d) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151577
|
+
"button",
|
|
151578
|
+
{
|
|
151579
|
+
className: `sp-icon-btn${rowDensity === d ? " active" : ""}`,
|
|
151580
|
+
onClick: () => {
|
|
151581
|
+
setRowDensity(d);
|
|
151582
|
+
onSave({ rowHeight: d });
|
|
151583
|
+
},
|
|
151584
|
+
title: getDensityLabel(d),
|
|
151585
|
+
"aria-label": `${getDensityLabel(d)} row density`,
|
|
151586
|
+
"aria-pressed": rowDensity === d,
|
|
151587
|
+
children: DENSITY_ICONS[d]
|
|
151588
|
+
},
|
|
151589
|
+
d
|
|
151590
|
+
)) })
|
|
151591
|
+
] }),
|
|
151592
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "sp-settings-row", children: [
|
|
151388
151593
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151389
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "
|
|
151390
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children:
|
|
151594
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Font size" }),
|
|
151595
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Results grid font size. Leave blank to inherit." })
|
|
151391
151596
|
] }),
|
|
151392
151597
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151393
151598
|
"input",
|
|
151394
151599
|
{
|
|
151395
|
-
type: "
|
|
151396
|
-
className: "sp-settings-
|
|
151397
|
-
|
|
151398
|
-
|
|
151600
|
+
type: "number",
|
|
151601
|
+
className: "sp-settings-input",
|
|
151602
|
+
value: localFontSize,
|
|
151603
|
+
min: FONT_SIZE_MIN,
|
|
151604
|
+
max: FONT_SIZE_MAX,
|
|
151605
|
+
placeholder: "Inherit",
|
|
151399
151606
|
onChange: (e2) => {
|
|
151400
|
-
|
|
151401
|
-
|
|
151607
|
+
handleFontSizeChange(e2.target.value);
|
|
151608
|
+
},
|
|
151609
|
+
onBlur: handleFontSizeDone,
|
|
151610
|
+
onKeyDown: (e2) => {
|
|
151611
|
+
if (e2.key === "Enter") handleFontSizeDone();
|
|
151402
151612
|
}
|
|
151403
151613
|
}
|
|
151404
151614
|
)
|
|
151405
|
-
]
|
|
151406
|
-
}
|
|
151407
|
-
)
|
|
151408
|
-
] }),
|
|
151409
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-card", children: [
|
|
151410
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "About" }),
|
|
151411
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151412
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151413
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Grain version" }),
|
|
151414
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row-hint", children: [
|
|
151415
|
-
"Installed: ",
|
|
151416
|
-
currentVersion ? `v${currentVersion}` : "Checking…",
|
|
151417
|
-
!isStandalone && (latestVersion ? ` · Latest: v${latestVersion}` : " · Checking for updates…")
|
|
151418
151615
|
] }),
|
|
151419
|
-
|
|
151616
|
+
fontSizeError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-validation-error", role: "alert", children: fontSizeError })
|
|
151420
151617
|
] }),
|
|
151421
|
-
|
|
151422
|
-
"
|
|
151423
|
-
|
|
151424
|
-
|
|
151425
|
-
|
|
151426
|
-
|
|
151427
|
-
|
|
151428
|
-
|
|
151429
|
-
|
|
151430
|
-
|
|
151431
|
-
|
|
151432
|
-
|
|
151433
|
-
|
|
151434
|
-
|
|
151435
|
-
|
|
151436
|
-
|
|
151437
|
-
|
|
151438
|
-
|
|
151439
|
-
|
|
151440
|
-
|
|
151441
|
-
|
|
151442
|
-
|
|
151443
|
-
|
|
151444
|
-
|
|
151445
|
-
|
|
151618
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-card", children: [
|
|
151619
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "Privacy" }),
|
|
151620
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151621
|
+
"label",
|
|
151622
|
+
{
|
|
151623
|
+
className: "sp-settings-row",
|
|
151624
|
+
title: isStandalone ? "Telemetry is sent by the VS Code extension; this browser tab has no sender to control." : void 0,
|
|
151625
|
+
children: [
|
|
151626
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151627
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Product telemetry" }),
|
|
151628
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: isStandalone ? "Set from the VS Code extension — this browser tab doesn't send telemetry itself." : "Anonymous usage metrics only. SQL, results, credentials, names, and paths are never sent." })
|
|
151629
|
+
] }),
|
|
151630
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151631
|
+
"input",
|
|
151632
|
+
{
|
|
151633
|
+
type: "checkbox",
|
|
151634
|
+
className: "sp-settings-check",
|
|
151635
|
+
checked: localTelemetryEnabled,
|
|
151636
|
+
disabled: isStandalone,
|
|
151637
|
+
onChange: (e2) => {
|
|
151638
|
+
setLocalTelemetryEnabled(e2.target.checked);
|
|
151639
|
+
onSave({ telemetryEnabled: e2.target.checked });
|
|
151640
|
+
}
|
|
151641
|
+
}
|
|
151642
|
+
)
|
|
151643
|
+
]
|
|
151644
|
+
}
|
|
151645
|
+
)
|
|
151446
151646
|
] }),
|
|
151447
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151448
|
-
|
|
151449
|
-
|
|
151450
|
-
|
|
151451
|
-
|
|
151452
|
-
|
|
151453
|
-
|
|
151454
|
-
|
|
151455
|
-
|
|
151456
|
-
|
|
151457
|
-
|
|
151458
|
-
|
|
151459
|
-
|
|
151460
|
-
|
|
151647
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-card", children: [
|
|
151648
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "About" }),
|
|
151649
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151650
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151651
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Grain version" }),
|
|
151652
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row-hint", children: [
|
|
151653
|
+
"Installed: ",
|
|
151654
|
+
currentVersion ? `v${currentVersion}` : "Checking…",
|
|
151655
|
+
!isStandalone && (latestVersion ? ` · Latest: v${latestVersion}` : " · Checking for updates…")
|
|
151656
|
+
] }),
|
|
151657
|
+
updateAvailable && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-version-update", children: "An update is available." })
|
|
151658
|
+
] }),
|
|
151659
|
+
isStandalone ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151660
|
+
"a",
|
|
151661
|
+
{
|
|
151662
|
+
className: "sp-btn",
|
|
151663
|
+
href: "https://github.com/pattrnlabs/grain/releases",
|
|
151664
|
+
target: "_blank",
|
|
151665
|
+
rel: "noreferrer",
|
|
151666
|
+
title: "This daemon can run standalone or inside VS Code; check the releases page for the latest version.",
|
|
151667
|
+
children: "View Releases"
|
|
151668
|
+
}
|
|
151669
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151670
|
+
"button",
|
|
151671
|
+
{
|
|
151672
|
+
type: "button",
|
|
151673
|
+
className: "sp-btn",
|
|
151674
|
+
onClick: () => sendMessage("openExtensionPage", {}),
|
|
151675
|
+
children: updateAvailable ? "Open Update" : "Open Extension"
|
|
151676
|
+
}
|
|
151677
|
+
)
|
|
151678
|
+
] }),
|
|
151679
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-divider" }),
|
|
151680
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151681
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151682
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Welcome guide" }),
|
|
151683
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Reopen setup help, latest highlights, and the getting-started checklist." })
|
|
151684
|
+
] }),
|
|
151685
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-btn", onClick: onShowWelcome, children: "View welcome guide" })
|
|
151686
|
+
] })
|
|
151687
|
+
] })
|
|
151688
|
+
] }),
|
|
151689
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151690
|
+
"aside",
|
|
151691
|
+
{
|
|
151692
|
+
className: "sp-settings-preview",
|
|
151693
|
+
style: { maxWidth: PREVIEW_MAX_WIDTH },
|
|
151694
|
+
"aria-label": "Settings change preview",
|
|
151695
|
+
children: [
|
|
151696
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-preview-header", children: [
|
|
151697
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "Live preview" }),
|
|
151698
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-preview-note", children: "Grid preview" })
|
|
151699
|
+
] }),
|
|
151700
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-preview-body", style: previewFontSizeStyle, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151701
|
+
DataGrid,
|
|
151702
|
+
{
|
|
151703
|
+
theme: theme2,
|
|
151704
|
+
data: DUMMY_PREVIEW_DATA,
|
|
151705
|
+
copyIncludesHeaders,
|
|
151706
|
+
density: rowDensity,
|
|
151707
|
+
domLayout: "normal",
|
|
151708
|
+
disableFilters: true
|
|
151709
|
+
}
|
|
151710
|
+
) }),
|
|
151711
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "sp-settings-preview-copy", children: [
|
|
151712
|
+
"Copy output will include",
|
|
151713
|
+
" ",
|
|
151714
|
+
copyIncludesHeaders ? "column headers and rows" : "rows only",
|
|
151715
|
+
"."
|
|
151716
|
+
] })
|
|
151717
|
+
]
|
|
151718
|
+
}
|
|
151719
|
+
)
|
|
151720
|
+
]
|
|
151721
|
+
}
|
|
151722
|
+
),
|
|
151723
|
+
activeTab === "connections" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151724
|
+
"div",
|
|
151725
|
+
{
|
|
151726
|
+
className: connectionsSubpage ? "sp-settings-conn-panel-subpage" : void 0,
|
|
151727
|
+
role: "tabpanel",
|
|
151728
|
+
id: "sp-settings-panel-connections",
|
|
151729
|
+
"aria-labelledby": connectionsSubpage ? void 0 : "sp-settings-tab-connections",
|
|
151730
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151731
|
+
ConnectionsManager,
|
|
151732
|
+
{
|
|
151733
|
+
theme: theme2,
|
|
151734
|
+
initialAdd: connectionsInitialAdd,
|
|
151735
|
+
onSubpageChange: setConnectionsSubpage
|
|
151736
|
+
}
|
|
151737
|
+
)
|
|
151738
|
+
}
|
|
151739
|
+
),
|
|
151740
|
+
activeTab === "mcp" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151741
|
+
"div",
|
|
151742
|
+
{
|
|
151743
|
+
className: "sp-settings-layout",
|
|
151744
|
+
role: "tabpanel",
|
|
151745
|
+
id: "sp-settings-panel-mcp",
|
|
151746
|
+
"aria-labelledby": "sp-settings-tab-mcp",
|
|
151747
|
+
children: [
|
|
151748
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-main", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-card sp-settings-mcp-card", children: [
|
|
151749
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-mcp-hero", children: [
|
|
151750
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-mcp-logo", children: MCP_LOGO }),
|
|
151751
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151752
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "Model Context Protocol" }),
|
|
151753
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-settings-mcp-description", children: "Enable the MCP server to allow AI assistants like Claude Desktop to connect to your databases." })
|
|
151754
|
+
] })
|
|
151461
151755
|
] }),
|
|
151462
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151463
|
-
|
|
151756
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151757
|
+
"label",
|
|
151464
151758
|
{
|
|
151465
|
-
|
|
151466
|
-
|
|
151467
|
-
|
|
151468
|
-
|
|
151469
|
-
|
|
151470
|
-
|
|
151759
|
+
className: "sp-settings-row",
|
|
151760
|
+
title: isStandalone ? "This daemon always serves the MCP endpoint while running; disabling it here would have no effect." : void 0,
|
|
151761
|
+
children: [
|
|
151762
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151763
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Enable MCP Server" }),
|
|
151764
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: isStandalone ? "This daemon always serves MCP over HTTP while it runs." : "Start a local MCP server alongside the extension." })
|
|
151765
|
+
] }),
|
|
151766
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151767
|
+
"input",
|
|
151768
|
+
{
|
|
151769
|
+
type: "checkbox",
|
|
151770
|
+
className: "sp-settings-check",
|
|
151771
|
+
checked: isStandalone ? true : localMcpEnabled,
|
|
151772
|
+
disabled: isStandalone,
|
|
151773
|
+
onChange: (e2) => {
|
|
151774
|
+
setLocalMcpEnabled(e2.target.checked);
|
|
151775
|
+
onSave({ mcpEnabled: e2.target.checked });
|
|
151776
|
+
}
|
|
151777
|
+
}
|
|
151778
|
+
)
|
|
151779
|
+
]
|
|
151471
151780
|
}
|
|
151472
|
-
)
|
|
151473
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("
|
|
151474
|
-
"Copy output will include",
|
|
151475
|
-
" ",
|
|
151476
|
-
copyIncludesHeaders ? "column headers and rows" : "rows only",
|
|
151477
|
-
"."
|
|
151478
|
-
] })
|
|
151479
|
-
]
|
|
151480
|
-
}
|
|
151481
|
-
)
|
|
151482
|
-
]
|
|
151483
|
-
}
|
|
151484
|
-
),
|
|
151485
|
-
activeTab === "connections" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151486
|
-
"div",
|
|
151487
|
-
{
|
|
151488
|
-
role: "tabpanel",
|
|
151489
|
-
id: "sp-settings-panel-connections",
|
|
151490
|
-
"aria-labelledby": "sp-settings-tab-connections",
|
|
151491
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ConnectionsManager, { theme: theme2, initialAdd: connectionsInitialAdd })
|
|
151492
|
-
}
|
|
151493
|
-
),
|
|
151494
|
-
activeTab === "mcp" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151495
|
-
"div",
|
|
151496
|
-
{
|
|
151497
|
-
className: "sp-settings-layout",
|
|
151498
|
-
role: "tabpanel",
|
|
151499
|
-
id: "sp-settings-panel-mcp",
|
|
151500
|
-
"aria-labelledby": "sp-settings-tab-mcp",
|
|
151501
|
-
children: [
|
|
151502
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-main", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-card sp-settings-mcp-card", children: [
|
|
151503
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-mcp-hero", children: [
|
|
151504
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-mcp-logo", children: MCP_LOGO }),
|
|
151505
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151506
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "Model Context Protocol" }),
|
|
151507
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-settings-mcp-description", children: "Enable the MCP server to allow AI assistants like Claude Desktop to connect to your databases." })
|
|
151508
|
-
] })
|
|
151509
|
-
] }),
|
|
151510
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151511
|
-
"label",
|
|
151512
|
-
{
|
|
151513
|
-
className: "sp-settings-row",
|
|
151514
|
-
title: isStandalone ? "This daemon always serves the MCP endpoint while running; disabling it here would have no effect." : void 0,
|
|
151515
|
-
children: [
|
|
151781
|
+
),
|
|
151782
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "sp-settings-row", children: [
|
|
151516
151783
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151517
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "
|
|
151518
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children:
|
|
151784
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Safe mode" }),
|
|
151785
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Block agent writes. Your own editor queries are unaffected." })
|
|
151519
151786
|
] }),
|
|
151520
151787
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151521
151788
|
"input",
|
|
151522
151789
|
{
|
|
151523
151790
|
type: "checkbox",
|
|
151524
151791
|
className: "sp-settings-check",
|
|
151525
|
-
checked:
|
|
151526
|
-
disabled: isStandalone,
|
|
151792
|
+
checked: localMcpSafeMode,
|
|
151527
151793
|
onChange: (e2) => {
|
|
151528
|
-
|
|
151529
|
-
onSave({
|
|
151794
|
+
setLocalMcpSafeMode(e2.target.checked);
|
|
151795
|
+
onSave({ mcpSafeMode: e2.target.checked });
|
|
151530
151796
|
}
|
|
151531
151797
|
}
|
|
151532
151798
|
)
|
|
151533
|
-
]
|
|
151534
|
-
}
|
|
151535
|
-
),
|
|
151536
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "sp-settings-row", children: [
|
|
151537
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151538
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Safe mode" }),
|
|
151539
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Block agent writes. Your own editor queries are unaffected." })
|
|
151540
|
-
] }),
|
|
151541
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151542
|
-
"input",
|
|
151543
|
-
{
|
|
151544
|
-
type: "checkbox",
|
|
151545
|
-
className: "sp-settings-check",
|
|
151546
|
-
checked: localMcpSafeMode,
|
|
151547
|
-
onChange: (e2) => {
|
|
151548
|
-
setLocalMcpSafeMode(e2.target.checked);
|
|
151549
|
-
onSave({ mcpSafeMode: e2.target.checked });
|
|
151550
|
-
}
|
|
151551
|
-
}
|
|
151552
|
-
)
|
|
151553
|
-
] }),
|
|
151554
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "sp-settings-row", children: [
|
|
151555
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151556
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Confirm write queries" }),
|
|
151557
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Ask for confirmation before running a query that modifies data from the editor." })
|
|
151558
|
-
] }),
|
|
151559
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151560
|
-
"input",
|
|
151561
|
-
{
|
|
151562
|
-
type: "checkbox",
|
|
151563
|
-
className: "sp-settings-check",
|
|
151564
|
-
checked: localConfirmWriteQueries,
|
|
151565
|
-
onChange: (e2) => {
|
|
151566
|
-
setLocalConfirmWriteQueries(e2.target.checked);
|
|
151567
|
-
onSave({ confirmWriteQueries: e2.target.checked });
|
|
151568
|
-
}
|
|
151569
|
-
}
|
|
151570
|
-
)
|
|
151571
|
-
] }),
|
|
151572
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-divider" }),
|
|
151573
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151574
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row-fill", children: [
|
|
151575
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Connection Test" }),
|
|
151576
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Verify the MCP server is running and reachable." }),
|
|
151577
|
-
testMcpStatus && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151578
|
-
"div",
|
|
151579
|
-
{
|
|
151580
|
-
className: `sp-settings-status ${testMcpStatus.status}`,
|
|
151581
|
-
role: testMcpStatus.status === "error" ? "alert" : "status",
|
|
151582
|
-
children: testMcpStatus.message
|
|
151583
|
-
}
|
|
151584
|
-
)
|
|
151585
|
-
] }),
|
|
151586
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151587
|
-
"button",
|
|
151588
|
-
{
|
|
151589
|
-
type: "button",
|
|
151590
|
-
className: "sp-btn",
|
|
151591
|
-
onClick: handleTestMcp,
|
|
151592
|
-
"aria-label": "Test Local MCP",
|
|
151593
|
-
children: "Test MCP Server"
|
|
151594
|
-
}
|
|
151595
|
-
)
|
|
151596
|
-
] }),
|
|
151597
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-divider" }),
|
|
151598
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151599
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row-fill", children: [
|
|
151600
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Current Port" }),
|
|
151601
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Port the server is configured to listen on." })
|
|
151602
|
-
] }),
|
|
151603
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-port", children: mcpPort || "Not configured" })
|
|
151604
|
-
] }),
|
|
151605
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-divider" }),
|
|
151606
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151607
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row-fill", children: [
|
|
151608
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Credential Storage" }),
|
|
151609
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "How database passwords are saved locally." })
|
|
151610
|
-
] }),
|
|
151611
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-port", style: { fontSize: "0.85em", opacity: 0.8 }, children: credentialBackend === "keychain" ? "OS Keychain" : credentialBackend === "extension" ? "VS Code Secure Storage" : credentialBackend === "file" ? "Local File (Permission Protected)" : credentialBackend || "Unknown" })
|
|
151612
|
-
] })
|
|
151613
|
-
] }) }),
|
|
151614
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151615
|
-
"aside",
|
|
151616
|
-
{
|
|
151617
|
-
className: "sp-settings-preview sp-settings-mcp-guide",
|
|
151618
|
-
"aria-label": "MCP setup guide",
|
|
151619
|
-
children: [
|
|
151620
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-preview-header", children: [
|
|
151621
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "MCP setup" }),
|
|
151622
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-preview-note", children: mcpStatusLabel })
|
|
151623
151799
|
] }),
|
|
151624
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("
|
|
151625
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
151626
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "
|
|
151627
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151800
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "sp-settings-row", children: [
|
|
151801
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151802
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Confirm write queries" }),
|
|
151803
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Ask for confirmation before running a query that modifies data from the editor." })
|
|
151628
151804
|
] }),
|
|
151629
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151805
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151806
|
+
"input",
|
|
151807
|
+
{
|
|
151808
|
+
type: "checkbox",
|
|
151809
|
+
className: "sp-settings-check",
|
|
151810
|
+
checked: localConfirmWriteQueries,
|
|
151811
|
+
onChange: (e2) => {
|
|
151812
|
+
setLocalConfirmWriteQueries(e2.target.checked);
|
|
151813
|
+
onSave({ confirmWriteQueries: e2.target.checked });
|
|
151814
|
+
}
|
|
151815
|
+
}
|
|
151816
|
+
)
|
|
151630
151817
|
] }),
|
|
151631
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151632
|
-
|
|
151633
|
-
|
|
151634
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151635
|
-
|
|
151636
|
-
|
|
151637
|
-
|
|
151638
|
-
|
|
151639
|
-
|
|
151818
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-divider" }),
|
|
151819
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151820
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row-fill", children: [
|
|
151821
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Connection Test" }),
|
|
151822
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Verify the MCP server is running and reachable." }),
|
|
151823
|
+
testMcpStatus && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151824
|
+
"div",
|
|
151825
|
+
{
|
|
151826
|
+
className: `sp-settings-status ${testMcpStatus.status}`,
|
|
151827
|
+
role: testMcpStatus.status === "error" ? "alert" : "status",
|
|
151828
|
+
children: testMcpStatus.message
|
|
151829
|
+
}
|
|
151830
|
+
)
|
|
151640
151831
|
] }),
|
|
151641
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151832
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151833
|
+
"button",
|
|
151834
|
+
{
|
|
151835
|
+
type: "button",
|
|
151836
|
+
className: "sp-btn",
|
|
151837
|
+
onClick: handleTestMcp,
|
|
151838
|
+
"aria-label": "Test Local MCP",
|
|
151839
|
+
children: "Test MCP Server"
|
|
151840
|
+
}
|
|
151841
|
+
)
|
|
151642
151842
|
] }),
|
|
151643
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151644
|
-
|
|
151645
|
-
|
|
151646
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151843
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-divider" }),
|
|
151844
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151845
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row-fill", children: [
|
|
151846
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Current Port" }),
|
|
151847
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "Port the server is configured to listen on." })
|
|
151647
151848
|
] }),
|
|
151648
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-
|
|
151649
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "sp-settings-code-block", "data-testid": "mcp-client-config-npx", children: mcpClientConfigNpx })
|
|
151849
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-port", children: mcpPort || "Not configured" })
|
|
151650
151850
|
] }),
|
|
151651
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151652
|
-
|
|
151653
|
-
|
|
151654
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
151851
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-divider" }),
|
|
151852
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row sp-settings-row-top", children: [
|
|
151853
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-row-fill", children: [
|
|
151854
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Credential Storage" }),
|
|
151855
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-hint", children: "How database passwords are saved locally." })
|
|
151655
151856
|
] }),
|
|
151656
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-
|
|
151657
|
-
|
|
151658
|
-
|
|
151659
|
-
|
|
151660
|
-
|
|
151661
|
-
|
|
151662
|
-
|
|
151663
|
-
|
|
151664
|
-
|
|
151665
|
-
|
|
151857
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-port", style: { fontSize: "0.85em", opacity: 0.8 }, children: credentialBackend === "keychain" ? "OS Keychain" : credentialBackend === "extension" ? "VS Code Secure Storage" : credentialBackend === "file" ? "Local File (Permission Protected)" : credentialBackend || "Unknown" })
|
|
151858
|
+
] })
|
|
151859
|
+
] }) }),
|
|
151860
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
151861
|
+
"aside",
|
|
151862
|
+
{
|
|
151863
|
+
className: "sp-settings-preview sp-settings-mcp-guide",
|
|
151864
|
+
"aria-label": "MCP setup guide",
|
|
151865
|
+
children: [
|
|
151866
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-preview-header", children: [
|
|
151867
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-section-label", children: "MCP setup" }),
|
|
151868
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-preview-note", children: mcpStatusLabel })
|
|
151869
|
+
] }),
|
|
151870
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section", children: [
|
|
151871
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section-header", children: [
|
|
151872
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Server URL" }),
|
|
151873
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsCopyButton, { text: mcpServerUrl, label: "Copy server URL" })
|
|
151666
151874
|
] }),
|
|
151667
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151668
|
-
group.tools.length,
|
|
151669
|
-
" tool",
|
|
151670
|
-
group.tools.length === 1 ? "" : "s"
|
|
151671
|
-
] })
|
|
151875
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "sp-settings-code-line", children: mcpServerUrl })
|
|
151672
151876
|
] }),
|
|
151673
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151674
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
151675
|
-
|
|
151676
|
-
|
|
151677
|
-
|
|
151678
|
-
|
|
151679
|
-
|
|
151680
|
-
|
|
151681
|
-
|
|
151682
|
-
|
|
151683
|
-
|
|
151684
|
-
|
|
151685
|
-
|
|
151877
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section", children: [
|
|
151878
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section-header", children: [
|
|
151879
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "If you installed the Grain CLI" }),
|
|
151880
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsCopyButton, { text: mcpClientConfigCli, label: "Copy CLI configuration" })
|
|
151881
|
+
] }),
|
|
151882
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-mcp-description", children: [
|
|
151883
|
+
"Run ",
|
|
151884
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Grain: Install Grain CLI" }),
|
|
151885
|
+
" to add it to your PATH."
|
|
151886
|
+
] }),
|
|
151887
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "sp-settings-code-block", "data-testid": "mcp-client-config-cli", children: mcpClientConfigCli })
|
|
151888
|
+
] }),
|
|
151889
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section", children: [
|
|
151890
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section-header", children: [
|
|
151891
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "If you only have the extension" }),
|
|
151892
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsCopyButton, { text: mcpClientConfigNpx, label: "Copy npx configuration" })
|
|
151893
|
+
] }),
|
|
151894
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-mcp-description", children: "npx starts Grain without installing the CLI separately." }),
|
|
151895
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "sp-settings-code-block", "data-testid": "mcp-client-config-npx", children: mcpClientConfigNpx })
|
|
151896
|
+
] }),
|
|
151897
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section", children: [
|
|
151898
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section-header", children: [
|
|
151899
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "HTTP configuration (advanced)" }),
|
|
151900
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SettingsCopyButton, { text: mcpHttpConfig, label: "Copy HTTP configuration" })
|
|
151901
|
+
] }),
|
|
151902
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-mcp-description", children: "For clients that support custom headers, such as Cursor and VS Code. The token authorizes access to your connections and results — treat it like a password." }),
|
|
151903
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "sp-settings-code-block", "data-testid": "mcp-http-config", children: mcpHttpConfig })
|
|
151904
|
+
] }),
|
|
151905
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-guide-section", children: [
|
|
151906
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-row-label", children: "Available tools" }),
|
|
151907
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-tool-groups", children: MCP_TOOL_GROUPS.map((group) => /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "sp-settings-tool-group", children: [
|
|
151908
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-tool-group-heading", children: [
|
|
151909
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
151910
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-tool-group-title", children: group.label }),
|
|
151911
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-tool-group-description", children: group.description })
|
|
151912
|
+
] }),
|
|
151913
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "sp-settings-tool-count", children: [
|
|
151914
|
+
group.tools.length,
|
|
151915
|
+
" tool",
|
|
151916
|
+
group.tools.length === 1 ? "" : "s"
|
|
151917
|
+
] })
|
|
151918
|
+
] }),
|
|
151919
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-settings-tool-list", children: group.tools.map(([name, description]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-settings-tool-item", children: [
|
|
151920
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "sp-settings-tool-name", children: name }),
|
|
151921
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: description })
|
|
151922
|
+
] }, name)) })
|
|
151923
|
+
] }, group.label)) })
|
|
151924
|
+
] })
|
|
151925
|
+
]
|
|
151926
|
+
}
|
|
151927
|
+
)
|
|
151928
|
+
]
|
|
151929
|
+
}
|
|
151930
|
+
)
|
|
151931
|
+
]
|
|
151932
|
+
}
|
|
151933
|
+
)
|
|
151686
151934
|
] });
|
|
151687
151935
|
}
|
|
151688
151936
|
const FEATURE_ICONS = {
|
|
@@ -151928,6 +152176,85 @@ function TabContextMenu({
|
|
|
151928
152176
|
}
|
|
151929
152177
|
);
|
|
151930
152178
|
}
|
|
152179
|
+
function formatExecutionTime(ms) {
|
|
152180
|
+
return ms < 1e3 ? `${Math.round(ms)} ms` : `${(ms / 1e3).toFixed(1)} s`;
|
|
152181
|
+
}
|
|
152182
|
+
function ElapsedTime({ since }) {
|
|
152183
|
+
const [, setTick] = reactExports.useState(0);
|
|
152184
|
+
reactExports.useEffect(() => {
|
|
152185
|
+
const interval = setInterval(() => setTick((t) => t + 1), 100);
|
|
152186
|
+
return () => clearInterval(interval);
|
|
152187
|
+
}, []);
|
|
152188
|
+
return (
|
|
152189
|
+
// aria-hidden: this sits inside the loading live region; announcing every tick would spam screen readers.
|
|
152190
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-loading-elapsed", "aria-hidden": "true", children: formatExecutionTime(Date.now() - since) })
|
|
152191
|
+
);
|
|
152192
|
+
}
|
|
152193
|
+
function LoadingState({
|
|
152194
|
+
since,
|
|
152195
|
+
onCancel
|
|
152196
|
+
}) {
|
|
152197
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-loading", children: [
|
|
152198
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ProgressBar, { label: "Running query" }),
|
|
152199
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152200
|
+
EmptyState,
|
|
152201
|
+
{
|
|
152202
|
+
role: "status",
|
|
152203
|
+
live: true,
|
|
152204
|
+
title: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152205
|
+
"Running query…",
|
|
152206
|
+
since != null && /* @__PURE__ */ jsxRuntimeExports.jsx(ElapsedTime, { since })
|
|
152207
|
+
] }),
|
|
152208
|
+
actions: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152209
|
+
Button,
|
|
152210
|
+
{
|
|
152211
|
+
variant: "ghost",
|
|
152212
|
+
icon: "stop",
|
|
152213
|
+
onClick: onCancel,
|
|
152214
|
+
"aria-label": "Cancel query execution",
|
|
152215
|
+
children: "Cancel"
|
|
152216
|
+
}
|
|
152217
|
+
)
|
|
152218
|
+
}
|
|
152219
|
+
)
|
|
152220
|
+
] });
|
|
152221
|
+
}
|
|
152222
|
+
function QueryErrorState({
|
|
152223
|
+
message,
|
|
152224
|
+
onRerun,
|
|
152225
|
+
onCopy,
|
|
152226
|
+
rerunDisabled
|
|
152227
|
+
}) {
|
|
152228
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152229
|
+
EmptyState,
|
|
152230
|
+
{
|
|
152231
|
+
icon: "alert",
|
|
152232
|
+
tone: "error",
|
|
152233
|
+
role: "alert",
|
|
152234
|
+
title: "Query failed",
|
|
152235
|
+
actions: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152236
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", icon: "play", onClick: onRerun, disabled: rerunDisabled, children: "Run again" }),
|
|
152237
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", icon: "copy", onClick: onCopy, children: "Copy error" })
|
|
152238
|
+
] }),
|
|
152239
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "sp-empty-state-message", children: message })
|
|
152240
|
+
}
|
|
152241
|
+
);
|
|
152242
|
+
}
|
|
152243
|
+
function NotPersistedState({
|
|
152244
|
+
onRerun,
|
|
152245
|
+
rerunDisabled
|
|
152246
|
+
}) {
|
|
152247
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152248
|
+
EmptyState,
|
|
152249
|
+
{
|
|
152250
|
+
icon: "refresh",
|
|
152251
|
+
role: "status",
|
|
152252
|
+
title: "Results from your last session weren't kept",
|
|
152253
|
+
actions: /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "primary", icon: "play", onClick: onRerun, disabled: rerunDisabled, children: "Run again" }),
|
|
152254
|
+
children: "Grain keeps the query, not the rows, so VS Code stays light. Run it again to see results."
|
|
152255
|
+
}
|
|
152256
|
+
);
|
|
152257
|
+
}
|
|
151931
152258
|
const LandingScreen = ({
|
|
151932
152259
|
onNewConnection,
|
|
151933
152260
|
onNewQueryFile,
|
|
@@ -151942,13 +152269,19 @@ const LandingScreen = ({
|
|
|
151942
152269
|
} = useAppStore();
|
|
151943
152270
|
const [fetchedConnName, setFetchedConnName] = reactExports.useState(null);
|
|
151944
152271
|
const [fetchedConnType, setFetchedConnType] = reactExports.useState(null);
|
|
152272
|
+
const [grainUnavailable, setGrainUnavailable] = reactExports.useState(false);
|
|
151945
152273
|
reactExports.useEffect(() => {
|
|
151946
|
-
if (!isReady || storeConnName)
|
|
152274
|
+
if (!isReady || storeConnName) {
|
|
152275
|
+
return;
|
|
152276
|
+
}
|
|
151947
152277
|
let mounted = true;
|
|
151948
152278
|
(async () => {
|
|
151949
152279
|
try {
|
|
151950
152280
|
const result = await callServerTool("list_connections", {});
|
|
151951
|
-
if (!mounted)
|
|
152281
|
+
if (!mounted) {
|
|
152282
|
+
return;
|
|
152283
|
+
}
|
|
152284
|
+
setGrainUnavailable(false);
|
|
151952
152285
|
const connections = result == null ? void 0 : result.structuredContent;
|
|
151953
152286
|
const active = Array.isArray(connections) ? connections.find((c) => c == null ? void 0 : c.activeForQueries) : null;
|
|
151954
152287
|
if (active == null ? void 0 : active.name) {
|
|
@@ -151958,6 +152291,9 @@ const LandingScreen = ({
|
|
|
151958
152291
|
setFetchedConnType(active.type);
|
|
151959
152292
|
}
|
|
151960
152293
|
} catch {
|
|
152294
|
+
if (mounted) {
|
|
152295
|
+
setGrainUnavailable(true);
|
|
152296
|
+
}
|
|
151961
152297
|
}
|
|
151962
152298
|
})();
|
|
151963
152299
|
return () => {
|
|
@@ -152004,6 +152340,10 @@ const LandingScreen = ({
|
|
|
152004
152340
|
] }),
|
|
152005
152341
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-landing-subtitle", children: "Execute SQL queries directly in your IDE." })
|
|
152006
152342
|
] }),
|
|
152343
|
+
!hasActiveConnection && grainUnavailable && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-landing-active-connection", children: [
|
|
152344
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Grain is stopped. Start Grain to see your connections." }),
|
|
152345
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-btn", onClick: () => sendMessage("startGrain"), children: "Start Grain" })
|
|
152346
|
+
] }),
|
|
152007
152347
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
152008
152348
|
"div",
|
|
152009
152349
|
{
|
|
@@ -152098,20 +152438,6 @@ function parseOptionalDependencyDetails(details) {
|
|
|
152098
152438
|
}
|
|
152099
152439
|
return null;
|
|
152100
152440
|
}
|
|
152101
|
-
function formatExecutionTime(ms) {
|
|
152102
|
-
return ms < 1e3 ? `${Math.round(ms)} ms` : `${(ms / 1e3).toFixed(1)} s`;
|
|
152103
|
-
}
|
|
152104
|
-
function ElapsedTime({ since }) {
|
|
152105
|
-
const [, setTick] = reactExports.useState(0);
|
|
152106
|
-
reactExports.useEffect(() => {
|
|
152107
|
-
const interval = setInterval(() => setTick((t) => t + 1), 100);
|
|
152108
|
-
return () => clearInterval(interval);
|
|
152109
|
-
}, []);
|
|
152110
|
-
return (
|
|
152111
|
-
// aria-hidden: this sits inside the loading live region; announcing every tick would spam screen readers.
|
|
152112
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-loading-elapsed", "aria-hidden": "true", children: formatExecutionTime(Date.now() - since) })
|
|
152113
|
-
);
|
|
152114
|
-
}
|
|
152115
152441
|
function formatTabTooltip(tab) {
|
|
152116
152442
|
var _a3;
|
|
152117
152443
|
const lines = [tab.sql || ""];
|
|
@@ -152154,7 +152480,8 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152154
152480
|
activeTabId,
|
|
152155
152481
|
setActiveTab,
|
|
152156
152482
|
closeTab,
|
|
152157
|
-
theme:
|
|
152483
|
+
theme: hostTheme,
|
|
152484
|
+
panelTheme,
|
|
152158
152485
|
updateTab,
|
|
152159
152486
|
copyIncludesHeaders,
|
|
152160
152487
|
rowDensity,
|
|
@@ -152181,9 +152508,12 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152181
152508
|
setTabChartLayout
|
|
152182
152509
|
} = useAppStore();
|
|
152183
152510
|
const trackUi = useTrackUi();
|
|
152511
|
+
const theme2 = panelTheme === "grain-dark" ? "dark" : panelTheme === "grain-light" ? "light" : hostTheme;
|
|
152184
152512
|
const { mode, sendMessage, onMessage } = useHostContext();
|
|
152185
152513
|
const gridRef = reactExports.useRef(null);
|
|
152186
|
-
const [copyFeedback, setCopyFeedback] = reactExports.useState(
|
|
152514
|
+
const [copyFeedback, setCopyFeedback] = reactExports.useState(
|
|
152515
|
+
null
|
|
152516
|
+
);
|
|
152187
152517
|
const [contextMenu, setContextMenu] = reactExports.useState(null);
|
|
152188
152518
|
const [sidePanel, setSidePanel] = reactExports.useState(null);
|
|
152189
152519
|
const [pendingConfirm, setPendingConfirm] = reactExports.useState(null);
|
|
@@ -152471,6 +152801,7 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152471
152801
|
const handleSaveSettings = (settings) => {
|
|
152472
152802
|
sendMessage("saveSettings", { settings });
|
|
152473
152803
|
applyConfig({
|
|
152804
|
+
...settings.panelTheme !== void 0 ? { panelTheme: settings.panelTheme } : {},
|
|
152474
152805
|
...settings.fontSize !== void 0 ? { fontSize: settings.fontSize > 0 ? settings.fontSize : null } : {},
|
|
152475
152806
|
...settings.maxRowsToDisplay !== void 0 ? { maxRowsToDisplay: settings.maxRowsToDisplay } : {},
|
|
152476
152807
|
...settings.telemetryEnabled !== void 0 ? { telemetryEnabled: settings.telemetryEnabled } : {},
|
|
@@ -152490,10 +152821,35 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152490
152821
|
return navigator.clipboard.writeText(text);
|
|
152491
152822
|
}, []);
|
|
152492
152823
|
const optionalDependencyDetails = parseOptionalDependencyDetails(activeTab == null ? void 0 : activeTab.errorDetails);
|
|
152493
|
-
const
|
|
152494
|
-
|
|
152495
|
-
|
|
152496
|
-
|
|
152824
|
+
const showErrorState = Boolean(
|
|
152825
|
+
(activeTab == null ? void 0 : activeTab.error) && !activeTab.result && !activeTab.isLoading && !optionalDependencyDetails
|
|
152826
|
+
);
|
|
152827
|
+
const handleCopyError = () => {
|
|
152828
|
+
if (!(activeTab == null ? void 0 : activeTab.error)) return;
|
|
152829
|
+
const text = activeTab.errorDetails ? `${activeTab.error}
|
|
152830
|
+
|
|
152831
|
+
${activeTab.errorDetails}` : activeTab.error;
|
|
152832
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
152833
|
+
setCopyFeedback("error");
|
|
152834
|
+
setTimeout(() => setCopyFeedback(null), 2e3);
|
|
152835
|
+
});
|
|
152836
|
+
};
|
|
152837
|
+
const fileFilterChip = activeFileName && activeFileUri && // The filter used to be invisible and unswitchable: focusing a .sql file
|
|
152838
|
+
// silently hid every tab belonging to anything else, with no way back (#151).
|
|
152839
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152840
|
+
ToggleChip,
|
|
152841
|
+
{
|
|
152842
|
+
checked: filterResultsByActiveFile,
|
|
152843
|
+
icon: "filter",
|
|
152844
|
+
ariaLabel: `Only show results from ${activeFileName}`,
|
|
152845
|
+
title: filterResultsByActiveFile ? `Showing only results from ${activeFileName}. Click to show every result tab.` : `Showing every result tab. Click to show only results from ${activeFileName}.`,
|
|
152846
|
+
onChange: (next) => {
|
|
152847
|
+
setFilterResultsByActiveFile(next);
|
|
152848
|
+
sendMessage("saveSettings", { settings: { filterResultsByActiveFile: next } });
|
|
152849
|
+
},
|
|
152850
|
+
children: filterResultsByActiveFile ? activeFileName : "All results"
|
|
152851
|
+
}
|
|
152852
|
+
);
|
|
152497
152853
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `sp-app ${theme2 === "dark" ? "vscode-dark" : "vscode-light"}`, children: [
|
|
152498
152854
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-tab-bar", children: [
|
|
152499
152855
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-tab-bar-tabs", role: "tablist", "aria-label": "Result tabs", children: visibleTabs.map((tab) => {
|
|
@@ -152515,7 +152871,7 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152515
152871
|
onKeyDown: (e2) => handleTabKeyDown(e2, tab.id),
|
|
152516
152872
|
onContextMenu: (e2) => handleTabContextMenu(e2, tab.id),
|
|
152517
152873
|
children: [
|
|
152518
|
-
tab.isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152874
|
+
tab.isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(BusyDot, { label: "Running" }),
|
|
152519
152875
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-tab-label", title: formatTabTooltip(tab), children: tab.title }),
|
|
152520
152876
|
showProvenance && tab.clientType && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { id: `sp-tab-provenance-${tab.id}`, className: "sp-visually-hidden", children: formatTabTooltip(tab) }) }),
|
|
152521
152877
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -152535,68 +152891,16 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152535
152891
|
);
|
|
152536
152892
|
}) }),
|
|
152537
152893
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-tab-bar-actions", children: [
|
|
152538
|
-
|
|
152539
|
-
"button",
|
|
152540
|
-
{
|
|
152541
|
-
type: "button",
|
|
152542
|
-
className: "sp-active-file-indicator",
|
|
152543
|
-
title: "Open Source File",
|
|
152544
|
-
"aria-label": `Open active SQL file ${activeFileName}`,
|
|
152545
|
-
onClick: () => sendMessage("openFile", { fileUri: activeFileUri }),
|
|
152546
|
-
children: [
|
|
152547
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152548
|
-
"svg",
|
|
152549
|
-
{
|
|
152550
|
-
className: "sp-active-file-icon",
|
|
152551
|
-
width: "12",
|
|
152552
|
-
height: "12",
|
|
152553
|
-
viewBox: "0 0 16 16",
|
|
152554
|
-
fill: "currentColor",
|
|
152555
|
-
"aria-hidden": "true",
|
|
152556
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M13.71 4.29l-3-3L10 1H4L3 2v12l1 1h9l1-1V5l-.29-.71zM10 2.41L12.59 5H10V2.41zM13 14H4V2h5v4l1 1h3v7z" })
|
|
152557
|
-
}
|
|
152558
|
-
),
|
|
152559
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-active-file-name", children: activeFileName })
|
|
152560
|
-
]
|
|
152561
|
-
}
|
|
152562
|
-
),
|
|
152563
|
-
activeFileName && activeFileUri && // The filter used to be invisible and unswitchable: focusing a .sql file
|
|
152564
|
-
// silently hid every tab belonging to anything else, with no way back (#151).
|
|
152565
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152566
|
-
"button",
|
|
152567
|
-
{
|
|
152568
|
-
type: "button",
|
|
152569
|
-
className: `sp-active-file-toggle${filterResultsByActiveFile ? " on" : ""}`,
|
|
152570
|
-
role: "switch",
|
|
152571
|
-
"aria-checked": filterResultsByActiveFile,
|
|
152572
|
-
title: filterResultsByActiveFile ? `Showing only results from ${activeFileName}. Click to show every result tab.` : `Showing every result tab. Click to show only results from ${activeFileName}.`,
|
|
152573
|
-
onClick: () => {
|
|
152574
|
-
const next = !filterResultsByActiveFile;
|
|
152575
|
-
setFilterResultsByActiveFile(next);
|
|
152576
|
-
sendMessage("saveSettings", { settings: { filterResultsByActiveFile: next } });
|
|
152577
|
-
},
|
|
152578
|
-
children: filterResultsByActiveFile ? "This file" : "All files"
|
|
152579
|
-
}
|
|
152580
|
-
),
|
|
152894
|
+
fileFilterChip,
|
|
152581
152895
|
mcpEnabled && (mode === "standalone" || mcpEntitled) && /* @__PURE__ */ jsxRuntimeExports.jsx(SafeModeIndicator, { safeMode: mcpSafeMode, connectorType: activeConnectorType }),
|
|
152582
|
-
pendingCloses.size > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152583
|
-
"button",
|
|
152584
|
-
{
|
|
152585
|
-
className: "sp-icon-btn active",
|
|
152586
|
-
onClick: handleUndoLastClose,
|
|
152587
|
-
title: "Undo Close Tab",
|
|
152588
|
-
"aria-label": "Undo Close Tab",
|
|
152589
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(UndoIcon, {})
|
|
152590
|
-
}
|
|
152591
|
-
),
|
|
152896
|
+
pendingCloses.size > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(IconButton, { icon: "undo", label: "Undo Close Tab", active: true, onClick: handleUndoLastClose }),
|
|
152592
152897
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152593
|
-
|
|
152898
|
+
IconButton,
|
|
152594
152899
|
{
|
|
152595
|
-
|
|
152596
|
-
|
|
152597
|
-
|
|
152598
|
-
|
|
152599
|
-
children: gearIcon
|
|
152900
|
+
icon: "settings",
|
|
152901
|
+
label: "Settings",
|
|
152902
|
+
active: Boolean(settingsPanelTab),
|
|
152903
|
+
onClick: settingsPanelTab ? closeSettingsPanel : handleOpenSettings
|
|
152600
152904
|
}
|
|
152601
152905
|
)
|
|
152602
152906
|
] })
|
|
@@ -152626,74 +152930,61 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152626
152930
|
id: "sp-result-tabpanel",
|
|
152627
152931
|
"aria-labelledby": `sp-tab-${activeTab.id}`,
|
|
152628
152932
|
children: [
|
|
152629
|
-
activeConfirmation && /* @__PURE__ */ jsxRuntimeExports.
|
|
152630
|
-
|
|
152631
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152632
|
-
"button",
|
|
152633
|
-
{
|
|
152634
|
-
ref: runAnywayRef,
|
|
152635
|
-
className: "sp-btn sp-btn-primary",
|
|
152636
|
-
onClick: handleConfirmRunAnyway,
|
|
152637
|
-
children: "Run anyway"
|
|
152638
|
-
}
|
|
152639
|
-
),
|
|
152640
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "sp-btn", onClick: handleCancelConfirmation, children: "Cancel" })
|
|
152641
|
-
] }),
|
|
152642
|
-
activeTab.error && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
152643
|
-
"div",
|
|
152933
|
+
activeConfirmation && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152934
|
+
Notice,
|
|
152644
152935
|
{
|
|
152645
|
-
|
|
152936
|
+
tone: "warning",
|
|
152646
152937
|
role: "alert",
|
|
152647
|
-
|
|
152648
|
-
|
|
152649
|
-
|
|
152650
|
-
|
|
152651
|
-
|
|
152652
|
-
optionalDependencyDetails.cause && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "sp-error-details", children: [
|
|
152653
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("summary", { children: "Technical details" }),
|
|
152654
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: optionalDependencyDetails.cause })
|
|
152655
|
-
] })
|
|
152656
|
-
] })
|
|
152657
|
-
] }),
|
|
152658
|
-
optionalDependencyDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
152659
|
-
"button",
|
|
152660
|
-
{
|
|
152661
|
-
className: "sp-btn sp-btn-primary",
|
|
152662
|
-
onClick: () => handleInstallOptionalDependency(optionalDependencyDetails.dependency),
|
|
152663
|
-
children: [
|
|
152664
|
-
"Install ",
|
|
152665
|
-
optionalDependencyDetails.dependency
|
|
152666
|
-
]
|
|
152667
|
-
}
|
|
152668
|
-
),
|
|
152669
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152670
|
-
"button",
|
|
152671
|
-
{
|
|
152672
|
-
onClick: () => updateTab(activeTab.id, { error: null, errorDetails: null }),
|
|
152673
|
-
"aria-label": "Close error message",
|
|
152674
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(CloseIcon, { size: 14 })
|
|
152675
|
-
}
|
|
152676
|
-
)
|
|
152677
|
-
]
|
|
152938
|
+
title: activeConfirmation.kind === "write" ? `This query will modify data (${activeConfirmation.keyword}). Run it anyway?` : activeConfirmation.kind === "multi_statement" ? `This query contains ${activeConfirmation.count} statements. Run it anyway?` : "The connection dialect could not be resolved, so Grain cannot verify this query. Run it anyway?",
|
|
152939
|
+
actions: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152940
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { ref: runAnywayRef, variant: "primary", onClick: handleConfirmRunAnyway, children: "Run anyway" }),
|
|
152941
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "ghost", onClick: handleCancelConfirmation, children: "Cancel" })
|
|
152942
|
+
] })
|
|
152678
152943
|
}
|
|
152679
152944
|
),
|
|
152680
|
-
activeTab.
|
|
152681
|
-
|
|
152682
|
-
|
|
152683
|
-
"
|
|
152684
|
-
|
|
152685
|
-
|
|
152686
|
-
|
|
152687
|
-
|
|
152688
|
-
|
|
152689
|
-
|
|
152690
|
-
|
|
152691
|
-
|
|
152945
|
+
activeTab.error && !showErrorState && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152946
|
+
Notice,
|
|
152947
|
+
{
|
|
152948
|
+
tone: optionalDependencyDetails ? "warning" : "error",
|
|
152949
|
+
title: activeTab.error,
|
|
152950
|
+
dismissLabel: "Close error message",
|
|
152951
|
+
onDismiss: () => updateTab(activeTab.id, { error: null, errorDetails: null }),
|
|
152952
|
+
actions: optionalDependencyDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
152953
|
+
Button,
|
|
152954
|
+
{
|
|
152955
|
+
variant: "primary",
|
|
152956
|
+
onClick: () => handleInstallOptionalDependency(optionalDependencyDetails.dependency),
|
|
152957
|
+
children: [
|
|
152958
|
+
"Install ",
|
|
152959
|
+
optionalDependencyDetails.dependency
|
|
152960
|
+
]
|
|
152961
|
+
}
|
|
152962
|
+
),
|
|
152963
|
+
children: optionalDependencyDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152964
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-error-guidance", children: optionalDependencyDetails.guidance }),
|
|
152965
|
+
optionalDependencyDetails.cause && /* @__PURE__ */ jsxRuntimeExports.jsxs("details", { className: "sp-error-details", children: [
|
|
152966
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("summary", { children: "Technical details" }),
|
|
152967
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: optionalDependencyDetails.cause })
|
|
152968
|
+
] })
|
|
152969
|
+
] })
|
|
152970
|
+
}
|
|
152971
|
+
),
|
|
152972
|
+
activeTab.cancelled && !activeTab.error && !activeTab.isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152973
|
+
Notice,
|
|
152974
|
+
{
|
|
152975
|
+
tone: "neutral",
|
|
152976
|
+
title: "Query cancelled",
|
|
152977
|
+
dismissLabel: "Dismiss cancelled notice",
|
|
152978
|
+
onDismiss: () => updateTab(activeTab.id, { cancelled: false })
|
|
152979
|
+
}
|
|
152980
|
+
),
|
|
152981
|
+
activeTab.result && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-result-header", children: [
|
|
152692
152982
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-result-header-left", children: [
|
|
152693
152983
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152694
|
-
|
|
152984
|
+
Button,
|
|
152695
152985
|
{
|
|
152696
|
-
|
|
152986
|
+
variant: "ghost",
|
|
152987
|
+
icon: "play",
|
|
152697
152988
|
onClick: handleRunQuery,
|
|
152698
152989
|
disabled: activeTab.isLoading,
|
|
152699
152990
|
"aria-label": "Re-run query",
|
|
@@ -152701,6 +152992,7 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152701
152992
|
}
|
|
152702
152993
|
),
|
|
152703
152994
|
activeTab.result && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152995
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-toolbar-sep", "aria-hidden": "true" }),
|
|
152704
152996
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "sp-row-count", children: [
|
|
152705
152997
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeTab.result.rowCount }),
|
|
152706
152998
|
" rows",
|
|
@@ -152710,7 +153002,7 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152710
153002
|
"span",
|
|
152711
153003
|
{
|
|
152712
153004
|
className: "sp-truncation-badge",
|
|
152713
|
-
title: "Result set was truncated. Use Export
|
|
153005
|
+
title: "Result set was truncated. Use Export to get the full data.",
|
|
152714
153006
|
children: "Truncated"
|
|
152715
153007
|
}
|
|
152716
153008
|
)
|
|
@@ -152725,18 +153017,20 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152725
153017
|
"aria-label": "Result representation",
|
|
152726
153018
|
children: [
|
|
152727
153019
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152728
|
-
|
|
153020
|
+
Button,
|
|
152729
153021
|
{
|
|
152730
|
-
|
|
153022
|
+
variant: (activeTab.representation ?? "grid") === "grid" ? "secondary" : "ghost",
|
|
153023
|
+
icon: "grid",
|
|
152731
153024
|
"aria-pressed": (activeTab.representation ?? "grid") === "grid",
|
|
152732
153025
|
onClick: () => setTabRepresentation(activeTab.id, "grid"),
|
|
152733
153026
|
children: "Grid"
|
|
152734
153027
|
}
|
|
152735
153028
|
),
|
|
152736
153029
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152737
|
-
|
|
153030
|
+
Button,
|
|
152738
153031
|
{
|
|
152739
|
-
|
|
153032
|
+
variant: activeTab.representation === "chart" ? "secondary" : "ghost",
|
|
153033
|
+
icon: "chart",
|
|
152740
153034
|
"aria-pressed": activeTab.representation === "chart",
|
|
152741
153035
|
onClick: () => setTabRepresentation(activeTab.id, "chart"),
|
|
152742
153036
|
children: "Chart"
|
|
@@ -152746,12 +153040,13 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152746
153040
|
}
|
|
152747
153041
|
),
|
|
152748
153042
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-visually-hidden", role: "status", children: copyFeedback ? "Copied to clipboard" : "" }),
|
|
152749
|
-
copyFeedback === "query" && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-copy-feedback", children: "Query copied" }),
|
|
153043
|
+
(copyFeedback === "query" || copyFeedback === "error") && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-copy-feedback", children: copyFeedback === "query" ? "Query copied" : "Error copied" }),
|
|
152750
153044
|
activeTab.result && activeTab.result.rows.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
152751
153045
|
activeTab.result.rowCount > 5 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152752
|
-
|
|
153046
|
+
Button,
|
|
152753
153047
|
{
|
|
152754
|
-
|
|
153048
|
+
variant: "ghost",
|
|
153049
|
+
icon: copyFeedback === "first" ? "check" : "copy",
|
|
152755
153050
|
onClick: () => {
|
|
152756
153051
|
var _a4;
|
|
152757
153052
|
return copyToClipboard(
|
|
@@ -152761,13 +153056,14 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152761
153056
|
},
|
|
152762
153057
|
title: "Copy first 5 rows as TSV",
|
|
152763
153058
|
"aria-label": "Copy first 5 rows as TSV",
|
|
152764
|
-
children: copyFeedback === "first" ? "Copied
|
|
153059
|
+
children: copyFeedback === "first" ? "Copied" : "Copy 5"
|
|
152765
153060
|
}
|
|
152766
153061
|
),
|
|
152767
153062
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152768
|
-
|
|
153063
|
+
Button,
|
|
152769
153064
|
{
|
|
152770
|
-
|
|
153065
|
+
variant: "ghost",
|
|
153066
|
+
icon: copyFeedback === "all" ? "check" : "copy",
|
|
152771
153067
|
onClick: () => {
|
|
152772
153068
|
var _a4;
|
|
152773
153069
|
return copyToClipboard(
|
|
@@ -152777,38 +153073,24 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152777
153073
|
},
|
|
152778
153074
|
title: "Copy all visible rows as TSV",
|
|
152779
153075
|
"aria-label": `Copy all ${activeTab.result.rowCount} rows as TSV`,
|
|
152780
|
-
children: copyFeedback === "all" ? "Copied
|
|
153076
|
+
children: copyFeedback === "all" ? "Copied" : "Copy all"
|
|
152781
153077
|
}
|
|
152782
153078
|
),
|
|
152783
153079
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152784
|
-
|
|
153080
|
+
Button,
|
|
152785
153081
|
{
|
|
152786
|
-
|
|
153082
|
+
variant: "ghost",
|
|
153083
|
+
icon: "download",
|
|
152787
153084
|
onClick: handleExportCsv,
|
|
152788
153085
|
title: "Export full results as CSV",
|
|
152789
153086
|
"aria-label": "Export full results as CSV",
|
|
152790
|
-
children: "Export
|
|
153087
|
+
children: "Export"
|
|
152791
153088
|
}
|
|
152792
153089
|
)
|
|
152793
153090
|
] }) : null
|
|
152794
153091
|
] })
|
|
152795
153092
|
] }),
|
|
152796
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-grid-container", children: activeTab.isLoading && !activeTab.result ? /* @__PURE__ */ jsxRuntimeExports.
|
|
152797
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-spinner sp-spinner-lg" }),
|
|
152798
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
|
|
152799
|
-
"Executing query…",
|
|
152800
|
-
activeTab.loadingStartedAt != null && /* @__PURE__ */ jsxRuntimeExports.jsx(ElapsedTime, { since: activeTab.loadingStartedAt })
|
|
152801
|
-
] }),
|
|
152802
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
152803
|
-
"button",
|
|
152804
|
-
{
|
|
152805
|
-
className: "sp-btn",
|
|
152806
|
-
onClick: handleCancelQuery,
|
|
152807
|
-
"aria-label": "Cancel query execution",
|
|
152808
|
-
children: "Cancel"
|
|
152809
|
-
}
|
|
152810
|
-
)
|
|
152811
|
-
] }) : activeTab.result ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-split-container", children: [
|
|
153093
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-grid-container", children: activeTab.isLoading && !activeTab.result ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoadingState, { since: activeTab.loadingStartedAt, onCancel: handleCancelQuery }) : activeTab.result ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-split-container", children: [
|
|
152812
153094
|
chartsEnabled && activeTab.representation === "chart" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
152813
153095
|
"div",
|
|
152814
153096
|
{
|
|
@@ -152919,7 +153201,16 @@ function MultiTabLayout({ emptyState } = {}) {
|
|
|
152919
153201
|
onCopy: handleSidePanelCopy
|
|
152920
153202
|
}
|
|
152921
153203
|
)
|
|
152922
|
-
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153204
|
+
] }) : showErrorState ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153205
|
+
QueryErrorState,
|
|
153206
|
+
{
|
|
153207
|
+
message: activeTab.errorDetails ? `${activeTab.error}
|
|
153208
|
+
|
|
153209
|
+
${activeTab.errorDetails}` : activeTab.error ?? "",
|
|
153210
|
+
onRerun: handleRunQuery,
|
|
153211
|
+
onCopy: handleCopyError
|
|
153212
|
+
}
|
|
153213
|
+
) : activeTab.notPersisted ? /* @__PURE__ */ jsxRuntimeExports.jsx(NotPersistedState, { onRerun: handleRunQuery }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-empty", children: "No results yet." }) })
|
|
152923
153214
|
]
|
|
152924
153215
|
}
|
|
152925
153216
|
),
|
|
@@ -152967,7 +153258,7 @@ const SIDEBAR_AUTO_COLLAPSE_QUERY = "(max-width: 640px)";
|
|
|
152967
153258
|
const SIDEBAR_WIDTH_STORAGE_KEY = "sql-preview:web-sidebar-width";
|
|
152968
153259
|
function WebApp({ viewHint }) {
|
|
152969
153260
|
var _a3;
|
|
152970
|
-
const { onMessage, isReady, sendMessage, callServerTool } = useHostContext();
|
|
153261
|
+
const { onMessage, isReady, sendMessage, callServerTool, track: track2 } = useHostContext();
|
|
152971
153262
|
const session = useWebSession();
|
|
152972
153263
|
const {
|
|
152973
153264
|
addTab,
|
|
@@ -152982,13 +153273,20 @@ function WebApp({ viewHint }) {
|
|
|
152982
153273
|
} = useAppStore();
|
|
152983
153274
|
const [connections, setConnections] = reactExports.useState([]);
|
|
152984
153275
|
const [setupOpen, setSetupOpen] = reactExports.useState(false);
|
|
153276
|
+
const [editingConnection, setEditingConnection] = reactExports.useState(null);
|
|
153277
|
+
const [openConnectionIds, setOpenConnectionIds] = reactExports.useState([]);
|
|
153278
|
+
const [activeConnectionId, setActiveConnectionId] = reactExports.useState(null);
|
|
153279
|
+
const [connectionStatus, setConnectionStatus] = reactExports.useState({});
|
|
152985
153280
|
const [descriptions, setDescriptions] = reactExports.useState({});
|
|
152986
153281
|
const [queryConnections, setQueryConnections] = reactExports.useState({});
|
|
152987
153282
|
const [closedQueries, setClosedQueries] = reactExports.useState([]);
|
|
152988
153283
|
const activeTab = tabs.find((tab) => tab.id === activeTabId);
|
|
152989
153284
|
const localConnection = connections.find((connection) => connection.id === "built-in-duckdb");
|
|
152990
153285
|
const selectedConnectionId = activeTab ? queryConnections[activeTab.id] ?? (localConnection == null ? void 0 : localConnection.id) ?? ((_a3 = connections[0]) == null ? void 0 : _a3.id) ?? "" : "";
|
|
152991
|
-
|
|
153286
|
+
reactExports.useEffect(() => {
|
|
153287
|
+
if (isReady) track2 == null ? void 0 : track2("ui_state_shown", { state: "workspace_ready" });
|
|
153288
|
+
}, [isReady, track2]);
|
|
153289
|
+
const newQuery = (connectionId = "built-in-duckdb") => {
|
|
152992
153290
|
const remoteId = crypto.randomUUID();
|
|
152993
153291
|
const id = addTab(
|
|
152994
153292
|
"SELECT 42;",
|
|
@@ -152997,7 +153295,32 @@ function WebApp({ viewHint }) {
|
|
|
152997
153295
|
void 0,
|
|
152998
153296
|
{ sessionId: WEB_SESSION_ID, remoteId }
|
|
152999
153297
|
);
|
|
153000
|
-
setQueryConnections((current2) => ({ ...current2, [id]:
|
|
153298
|
+
setQueryConnections((current2) => ({ ...current2, [id]: connectionId }));
|
|
153299
|
+
setActiveConnectionId(null);
|
|
153300
|
+
};
|
|
153301
|
+
const openConnection = (id) => {
|
|
153302
|
+
setOpenConnectionIds((current2) => current2.includes(id) ? current2 : [...current2, id]);
|
|
153303
|
+
setActiveConnectionId(id);
|
|
153304
|
+
};
|
|
153305
|
+
const testConnection = async (id) => {
|
|
153306
|
+
var _a4, _b3;
|
|
153307
|
+
setConnectionStatus((current2) => ({ ...current2, [id]: "Testing…" }));
|
|
153308
|
+
try {
|
|
153309
|
+
const result = await callServerTool("test_connection", { connectionId: id });
|
|
153310
|
+
const message = ((_b3 = (_a4 = result.content) == null ? void 0 : _a4.find((item) => item.type === "text")) == null ? void 0 : _b3.text) ?? "Connection test failed";
|
|
153311
|
+
setConnectionStatus((current2) => {
|
|
153312
|
+
var _a5;
|
|
153313
|
+
return {
|
|
153314
|
+
...current2,
|
|
153315
|
+
[id]: result.isError || ((_a5 = result.structuredContent) == null ? void 0 : _a5["success"]) === false ? message : "Connected"
|
|
153316
|
+
};
|
|
153317
|
+
});
|
|
153318
|
+
} catch (error) {
|
|
153319
|
+
setConnectionStatus((current2) => ({
|
|
153320
|
+
...current2,
|
|
153321
|
+
[id]: error instanceof Error ? error.message : "Connection test failed"
|
|
153322
|
+
}));
|
|
153323
|
+
}
|
|
153001
153324
|
};
|
|
153002
153325
|
const closeQuery = (id) => {
|
|
153003
153326
|
const tab = tabs.find((item) => item.id === id);
|
|
@@ -153056,12 +153379,22 @@ function WebApp({ viewHint }) {
|
|
|
153056
153379
|
connection: ((_b3 = connections.find((connection) => connection.id === selectedConnectionId)) == null ? void 0 : _b3.name) ?? selectedConnectionId
|
|
153057
153380
|
}
|
|
153058
153381
|
});
|
|
153382
|
+
track2 == null ? void 0 : track2("ui_action_performed", {
|
|
153383
|
+
state: "query_editor",
|
|
153384
|
+
ui_action: "run_query",
|
|
153385
|
+
outcome: "success"
|
|
153386
|
+
});
|
|
153059
153387
|
} catch (error) {
|
|
153060
153388
|
if ((_c3 = useAppStore.getState().tabs.find((tab) => tab.id === id)) == null ? void 0 : _c3.cancelled) return;
|
|
153061
153389
|
updateTab(id, {
|
|
153062
153390
|
isLoading: false,
|
|
153063
153391
|
error: error instanceof Error ? error.message : "Query failed"
|
|
153064
153392
|
});
|
|
153393
|
+
track2 == null ? void 0 : track2("ui_action_performed", {
|
|
153394
|
+
state: "query_editor",
|
|
153395
|
+
ui_action: "run_query",
|
|
153396
|
+
outcome: "error"
|
|
153397
|
+
});
|
|
153065
153398
|
}
|
|
153066
153399
|
};
|
|
153067
153400
|
const cancelQuery = async () => {
|
|
@@ -153331,7 +153664,7 @@ function WebApp({ viewHint }) {
|
|
|
153331
153664
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-no-tabs sp-web-empty-stack", children: [
|
|
153332
153665
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-empty-title", children: "Your workspace is ready" }),
|
|
153333
153666
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Run a query with Local Files, or connect a database. Your results and agent activity appear here." }),
|
|
153334
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-primary-button", onClick: newQuery, children: "New query" })
|
|
153667
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-primary-button", onClick: () => newQuery(), children: "New query" })
|
|
153335
153668
|
] });
|
|
153336
153669
|
if (session.state === "needs-relaunch") {
|
|
153337
153670
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(ReauthorizeNotice, { reason: session.reason ?? "no-session" });
|
|
@@ -153341,6 +153674,15 @@ function WebApp({ viewHint }) {
|
|
|
153341
153674
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-brand", children: [
|
|
153342
153675
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-brand-icon", "aria-hidden": "true" }),
|
|
153343
153676
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-wordmark", children: "Grain" }),
|
|
153677
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153678
|
+
"span",
|
|
153679
|
+
{
|
|
153680
|
+
className: "sp-web-beta-badge",
|
|
153681
|
+
"aria-label": "Beta feature",
|
|
153682
|
+
title: "The Grain workspace is in beta",
|
|
153683
|
+
children: "Beta"
|
|
153684
|
+
}
|
|
153685
|
+
),
|
|
153344
153686
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-header-divider" }),
|
|
153345
153687
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Workspace" })
|
|
153346
153688
|
] }),
|
|
@@ -153419,13 +153761,22 @@ function WebApp({ viewHint }) {
|
|
|
153419
153761
|
}
|
|
153420
153762
|
),
|
|
153421
153763
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-list", children: [
|
|
153422
|
-
connections.length ? connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153423
|
-
|
|
153424
|
-
|
|
153425
|
-
|
|
153426
|
-
|
|
153427
|
-
|
|
153428
|
-
|
|
153764
|
+
connections.length ? connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153765
|
+
"button",
|
|
153766
|
+
{
|
|
153767
|
+
type: "button",
|
|
153768
|
+
className: "sp-web-connection-item",
|
|
153769
|
+
onClick: () => openConnection(connection.id),
|
|
153770
|
+
children: [
|
|
153771
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "sp-web-connection-icon", "aria-hidden": "true", children: "▤" }),
|
|
153772
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
153773
|
+
connection.name ?? connection.id,
|
|
153774
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("small", { children: connection.type })
|
|
153775
|
+
] })
|
|
153776
|
+
]
|
|
153777
|
+
},
|
|
153778
|
+
connection.id
|
|
153779
|
+
)) : /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "sp-web-sidebar-helper", children: "No connections yet." }),
|
|
153429
153780
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153430
153781
|
"button",
|
|
153431
153782
|
{
|
|
@@ -153438,7 +153789,7 @@ function WebApp({ viewHint }) {
|
|
|
153438
153789
|
] }),
|
|
153439
153790
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-sidebar-section-title", children: "Queries" }),
|
|
153440
153791
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-session-list", children: [
|
|
153441
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-add-connection", onClick: newQuery, children: "+ New query" }),
|
|
153792
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-add-connection", onClick: () => newQuery(), children: "+ New query" }),
|
|
153442
153793
|
closedQueries.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-add-connection", onClick: reopenQuery, children: "Reopen closed query" }),
|
|
153443
153794
|
tabs.filter((tab) => tab.sessionId === WEB_SESSION_ID).map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153444
153795
|
"button",
|
|
@@ -153446,7 +153797,10 @@ function WebApp({ viewHint }) {
|
|
|
153446
153797
|
type: "button",
|
|
153447
153798
|
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
153448
153799
|
"aria-pressed": activeTabId === tab.id,
|
|
153449
|
-
onClick: () =>
|
|
153800
|
+
onClick: () => {
|
|
153801
|
+
setActiveTab(tab.id);
|
|
153802
|
+
setActiveConnectionId(null);
|
|
153803
|
+
},
|
|
153450
153804
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: tab.title })
|
|
153451
153805
|
},
|
|
153452
153806
|
tab.id
|
|
@@ -153458,7 +153812,10 @@ function WebApp({ viewHint }) {
|
|
|
153458
153812
|
type: "button",
|
|
153459
153813
|
className: `sp-web-session-item sp-web-session-button${activeTabId === tab.id ? " active" : ""}`,
|
|
153460
153814
|
"aria-pressed": activeTabId === tab.id,
|
|
153461
|
-
onClick: () =>
|
|
153815
|
+
onClick: () => {
|
|
153816
|
+
setActiveTab(tab.id);
|
|
153817
|
+
setActiveConnectionId(null);
|
|
153818
|
+
},
|
|
153462
153819
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-session-name", children: tab.title })
|
|
153463
153820
|
},
|
|
153464
153821
|
tab.id
|
|
@@ -153471,10 +153828,21 @@ function WebApp({ viewHint }) {
|
|
|
153471
153828
|
ConnectionSetupPage,
|
|
153472
153829
|
{
|
|
153473
153830
|
onDone: () => {
|
|
153831
|
+
if (!editingConnection) {
|
|
153832
|
+
track2 == null ? void 0 : track2("ui_action_performed", {
|
|
153833
|
+
state: "connection_manager",
|
|
153834
|
+
ui_action: "connection_created"
|
|
153835
|
+
});
|
|
153836
|
+
}
|
|
153474
153837
|
setSetupOpen(false);
|
|
153838
|
+
setEditingConnection(null);
|
|
153475
153839
|
void fetchConnections();
|
|
153476
153840
|
},
|
|
153477
|
-
onCancel: () =>
|
|
153841
|
+
onCancel: () => {
|
|
153842
|
+
setSetupOpen(false);
|
|
153843
|
+
setEditingConnection(null);
|
|
153844
|
+
},
|
|
153845
|
+
initialConnection: editingConnection ?? void 0
|
|
153478
153846
|
}
|
|
153479
153847
|
) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "sp-web-main", children: [
|
|
153480
153848
|
!monitorOpen && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-main-toolbar", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -153488,20 +153856,58 @@ function WebApp({ viewHint }) {
|
|
|
153488
153856
|
children: "Sessions"
|
|
153489
153857
|
}
|
|
153490
153858
|
) }),
|
|
153491
|
-
!settingsPanelTab && activeTab && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-workspace", children: [
|
|
153492
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-tabs", role: "tablist", "aria-label": "Open
|
|
153859
|
+
!settingsPanelTab && (activeTab || activeConnectionId) && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-workspace", children: [
|
|
153860
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-tabs", role: "tablist", "aria-label": "Open tabs", children: [
|
|
153861
|
+
openConnectionIds.map((id) => {
|
|
153862
|
+
const connection = connections.find((item) => item.id === id);
|
|
153863
|
+
if (!connection) return null;
|
|
153864
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153865
|
+
"div",
|
|
153866
|
+
{
|
|
153867
|
+
className: `sp-web-query-tab${activeConnectionId === id ? " active" : ""}`,
|
|
153868
|
+
children: [
|
|
153869
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153870
|
+
"button",
|
|
153871
|
+
{
|
|
153872
|
+
type: "button",
|
|
153873
|
+
role: "tab",
|
|
153874
|
+
"aria-selected": activeConnectionId === id,
|
|
153875
|
+
onClick: () => setActiveConnectionId(id),
|
|
153876
|
+
children: connection.name ?? id
|
|
153877
|
+
}
|
|
153878
|
+
),
|
|
153879
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153880
|
+
"button",
|
|
153881
|
+
{
|
|
153882
|
+
type: "button",
|
|
153883
|
+
"aria-label": `Close ${connection.name ?? id} tab`,
|
|
153884
|
+
onClick: () => {
|
|
153885
|
+
setOpenConnectionIds((current2) => current2.filter((item) => item !== id));
|
|
153886
|
+
if (activeConnectionId === id) setActiveConnectionId(null);
|
|
153887
|
+
},
|
|
153888
|
+
children: "×"
|
|
153889
|
+
}
|
|
153890
|
+
)
|
|
153891
|
+
]
|
|
153892
|
+
},
|
|
153893
|
+
`connection-${id}`
|
|
153894
|
+
);
|
|
153895
|
+
}),
|
|
153493
153896
|
tabs.map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
153494
153897
|
"div",
|
|
153495
153898
|
{
|
|
153496
|
-
className: `sp-web-query-tab${tab.id === activeTabId ? " active" : ""}`,
|
|
153899
|
+
className: `sp-web-query-tab${tab.id === activeTabId && !activeConnectionId ? " active" : ""}`,
|
|
153497
153900
|
children: [
|
|
153498
153901
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153499
153902
|
"button",
|
|
153500
153903
|
{
|
|
153501
153904
|
type: "button",
|
|
153502
153905
|
role: "tab",
|
|
153503
|
-
"aria-selected": tab.id === activeTabId,
|
|
153504
|
-
onClick: () =>
|
|
153906
|
+
"aria-selected": tab.id === activeTabId && !activeConnectionId,
|
|
153907
|
+
onClick: () => {
|
|
153908
|
+
setActiveTab(tab.id);
|
|
153909
|
+
setActiveConnectionId(null);
|
|
153910
|
+
},
|
|
153505
153911
|
children: tab.title
|
|
153506
153912
|
}
|
|
153507
153913
|
),
|
|
@@ -153523,93 +153929,141 @@ function WebApp({ viewHint }) {
|
|
|
153523
153929
|
{
|
|
153524
153930
|
type: "button",
|
|
153525
153931
|
className: "sp-web-query-tab-action",
|
|
153526
|
-
onClick: newQuery,
|
|
153932
|
+
onClick: () => newQuery(),
|
|
153527
153933
|
"aria-label": "New query",
|
|
153528
153934
|
children: "+"
|
|
153529
153935
|
}
|
|
153530
153936
|
),
|
|
153531
153937
|
closedQueries.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "sp-web-query-tab-action", onClick: reopenQuery, children: "Reopen closed query" })
|
|
153532
153938
|
] }),
|
|
153533
|
-
|
|
153534
|
-
|
|
153535
|
-
|
|
153536
|
-
|
|
153537
|
-
|
|
153538
|
-
|
|
153539
|
-
|
|
153540
|
-
|
|
153541
|
-
|
|
153542
|
-
|
|
153543
|
-
|
|
153544
|
-
{
|
|
153545
|
-
|
|
153546
|
-
|
|
153547
|
-
|
|
153548
|
-
|
|
153549
|
-
|
|
153550
|
-
|
|
153551
|
-
|
|
153552
|
-
|
|
153553
|
-
|
|
153554
|
-
|
|
153555
|
-
|
|
153556
|
-
|
|
153557
|
-
|
|
153558
|
-
|
|
153939
|
+
activeConnectionId ? (() => {
|
|
153940
|
+
const connection = connections.find((item) => item.id === activeConnectionId);
|
|
153941
|
+
if (!connection) return null;
|
|
153942
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-detail", children: [
|
|
153943
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h1", { children: connection.name ?? connection.id }),
|
|
153944
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
|
|
153945
|
+
connection.type ?? "Database",
|
|
153946
|
+
" ·",
|
|
153947
|
+
" ",
|
|
153948
|
+
connectionStatus[connection.id] ?? (connection.engineState === "ready" ? "Ready" : "Saved connection")
|
|
153949
|
+
] }),
|
|
153950
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-connection-actions", children: [
|
|
153951
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153952
|
+
"button",
|
|
153953
|
+
{
|
|
153954
|
+
type: "button",
|
|
153955
|
+
className: "sp-web-primary-button",
|
|
153956
|
+
"aria-label": `New query for ${connection.name ?? connection.id}`,
|
|
153957
|
+
onClick: () => newQuery(connection.id),
|
|
153958
|
+
children: "New query"
|
|
153959
|
+
}
|
|
153960
|
+
),
|
|
153961
|
+
!connection.builtIn && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153962
|
+
"button",
|
|
153963
|
+
{
|
|
153964
|
+
type: "button",
|
|
153965
|
+
className: "sp-web-secondary-button",
|
|
153966
|
+
onClick: () => {
|
|
153967
|
+
setEditingConnection(connection);
|
|
153968
|
+
setSetupOpen(true);
|
|
153969
|
+
},
|
|
153970
|
+
children: "Edit"
|
|
153971
|
+
}
|
|
153972
|
+
),
|
|
153973
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153974
|
+
"button",
|
|
153975
|
+
{
|
|
153976
|
+
type: "button",
|
|
153977
|
+
className: "sp-web-secondary-button",
|
|
153978
|
+
onClick: () => void testConnection(connection.id),
|
|
153979
|
+
children: "Test"
|
|
153980
|
+
}
|
|
153981
|
+
)
|
|
153982
|
+
] })
|
|
153983
|
+
] });
|
|
153984
|
+
})() : activeTab && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
153985
|
+
" ",
|
|
153986
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-heading", children: [
|
|
153559
153987
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153560
|
-
"
|
|
153988
|
+
"input",
|
|
153561
153989
|
{
|
|
153562
|
-
"aria-label": "Query
|
|
153563
|
-
value:
|
|
153564
|
-
onChange: (event) =>
|
|
153990
|
+
"aria-label": "Query title",
|
|
153991
|
+
value: activeTab.title,
|
|
153992
|
+
onChange: (event) => updateTab(activeTab.id, { title: event.target.value })
|
|
153993
|
+
}
|
|
153994
|
+
),
|
|
153995
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153996
|
+
"textarea",
|
|
153997
|
+
{
|
|
153998
|
+
"aria-label": "Query description",
|
|
153999
|
+
placeholder: "Add a description",
|
|
154000
|
+
value: descriptions[activeTab.id] ?? "",
|
|
154001
|
+
onChange: (event) => setDescriptions((current2) => ({
|
|
153565
154002
|
...current2,
|
|
153566
154003
|
[activeTab.id]: event.target.value
|
|
153567
154004
|
})),
|
|
153568
|
-
|
|
154005
|
+
rows: 1
|
|
153569
154006
|
}
|
|
153570
154007
|
)
|
|
153571
154008
|
] }),
|
|
153572
|
-
|
|
153573
|
-
"
|
|
153574
|
-
|
|
153575
|
-
|
|
153576
|
-
|
|
153577
|
-
|
|
153578
|
-
|
|
153579
|
-
|
|
153580
|
-
|
|
153581
|
-
|
|
154009
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sp-web-query-toolbar", children: [
|
|
154010
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
|
|
154011
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Connection" }),
|
|
154012
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
154013
|
+
"select",
|
|
154014
|
+
{
|
|
154015
|
+
"aria-label": "Query connection",
|
|
154016
|
+
value: selectedConnectionId,
|
|
154017
|
+
onChange: (event) => setQueryConnections((current2) => ({
|
|
154018
|
+
...current2,
|
|
154019
|
+
[activeTab.id]: event.target.value
|
|
154020
|
+
})),
|
|
154021
|
+
children: connections.map((connection) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: connection.id, children: connection.name ?? connection.id }, connection.id))
|
|
154022
|
+
}
|
|
154023
|
+
)
|
|
154024
|
+
] }),
|
|
154025
|
+
activeTab.isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
154026
|
+
"button",
|
|
154027
|
+
{
|
|
154028
|
+
type: "button",
|
|
154029
|
+
className: "sp-web-secondary-button",
|
|
154030
|
+
onClick: () => void cancelQuery(),
|
|
154031
|
+
children: "Cancel run"
|
|
154032
|
+
}
|
|
154033
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
154034
|
+
"button",
|
|
154035
|
+
{
|
|
154036
|
+
type: "button",
|
|
154037
|
+
className: "sp-web-primary-button",
|
|
154038
|
+
onClick: () => void runQuery(),
|
|
154039
|
+
disabled: !selectedConnectionId || !activeTab.sql.trim(),
|
|
154040
|
+
children: [
|
|
154041
|
+
"Run ",
|
|
154042
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("kbd", { children: "⌘↵" })
|
|
154043
|
+
]
|
|
154044
|
+
}
|
|
154045
|
+
)
|
|
154046
|
+
] }),
|
|
154047
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
154048
|
+
"textarea",
|
|
153582
154049
|
{
|
|
153583
|
-
|
|
153584
|
-
|
|
153585
|
-
|
|
153586
|
-
|
|
153587
|
-
|
|
153588
|
-
|
|
153589
|
-
|
|
153590
|
-
|
|
154050
|
+
className: "sp-web-sql-editor",
|
|
154051
|
+
"aria-label": "SQL editor",
|
|
154052
|
+
spellCheck: false,
|
|
154053
|
+
value: activeTab.sql,
|
|
154054
|
+
onChange: (event) => updateTab(activeTab.id, { sql: event.target.value }),
|
|
154055
|
+
onKeyDown: (event) => {
|
|
154056
|
+
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
154057
|
+
event.preventDefault();
|
|
154058
|
+
void runQuery();
|
|
154059
|
+
}
|
|
154060
|
+
}
|
|
153591
154061
|
}
|
|
153592
154062
|
)
|
|
153593
154063
|
] }),
|
|
153594
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
153595
|
-
"textarea",
|
|
153596
|
-
{
|
|
153597
|
-
className: "sp-web-sql-editor",
|
|
153598
|
-
"aria-label": "SQL editor",
|
|
153599
|
-
spellCheck: false,
|
|
153600
|
-
value: activeTab.sql,
|
|
153601
|
-
onChange: (event) => updateTab(activeTab.id, { sql: event.target.value }),
|
|
153602
|
-
onKeyDown: (event) => {
|
|
153603
|
-
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
153604
|
-
event.preventDefault();
|
|
153605
|
-
void runQuery();
|
|
153606
|
-
}
|
|
153607
|
-
}
|
|
153608
|
-
}
|
|
153609
|
-
),
|
|
153610
154064
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results-label", children: "Results" })
|
|
153611
154065
|
] }),
|
|
153612
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MultiTabLayout, { emptyState: resultsEmptyState }) })
|
|
154066
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sp-web-results", hidden: Boolean(activeConnectionId), children: /* @__PURE__ */ jsxRuntimeExports.jsx(MultiTabLayout, { emptyState: resultsEmptyState }) })
|
|
153613
154067
|
] })
|
|
153614
154068
|
] })
|
|
153615
154069
|
] });
|
|
@@ -162393,7 +162847,7 @@ button.ag-side-button-button:focus {
|
|
|
162393
162847
|
--sp-warning: var(--vscode-charts-yellow, #ca8a04);
|
|
162394
162848
|
|
|
162395
162849
|
--sp-font: var(
|
|
162396
|
-
--vscode-
|
|
162850
|
+
--vscode-font-family,
|
|
162397
162851
|
-apple-system,
|
|
162398
162852
|
BlinkMacSystemFont,
|
|
162399
162853
|
'Segoe UI',
|
|
@@ -162678,75 +163132,55 @@ body {
|
|
|
162678
163132
|
gap: 6px;
|
|
162679
163133
|
}
|
|
162680
163134
|
|
|
162681
|
-
.sp-
|
|
163135
|
+
.sp-chip {
|
|
162682
163136
|
display: inline-flex;
|
|
162683
163137
|
align-items: center;
|
|
162684
|
-
gap:
|
|
163138
|
+
gap: 5px;
|
|
162685
163139
|
max-width: 220px;
|
|
162686
|
-
|
|
162687
|
-
padding:
|
|
162688
|
-
border: 1px
|
|
162689
|
-
border-radius:
|
|
162690
|
-
background:
|
|
162691
|
-
color: var(--sp-
|
|
163140
|
+
height: 22px;
|
|
163141
|
+
padding: 0 8px;
|
|
163142
|
+
border: 1px dashed var(--sp-border);
|
|
163143
|
+
border-radius: 999px;
|
|
163144
|
+
background: transparent;
|
|
163145
|
+
color: var(--sp-muted-fg);
|
|
162692
163146
|
font: inherit;
|
|
162693
163147
|
font-size: 11px;
|
|
162694
163148
|
cursor: pointer;
|
|
162695
|
-
|
|
163149
|
+
transition:
|
|
163150
|
+
color 0.1s,
|
|
163151
|
+
background 0.1s,
|
|
163152
|
+
border-color 0.1s;
|
|
162696
163153
|
}
|
|
162697
|
-
|
|
162698
|
-
|
|
162699
|
-
|
|
162700
|
-
border-color: var(--sp-focus-border);
|
|
163154
|
+
.sp-chip:hover {
|
|
163155
|
+
color: var(--sp-fg);
|
|
163156
|
+
border-color: var(--sp-muted-fg);
|
|
162701
163157
|
}
|
|
162702
|
-
|
|
162703
|
-
|
|
162704
|
-
|
|
163158
|
+
.sp-chip.on {
|
|
163159
|
+
border-style: solid;
|
|
163160
|
+
border-color: color-mix(in srgb, var(--sp-focus-border) 55%, transparent);
|
|
163161
|
+
background: color-mix(in srgb, var(--sp-focus-border) 14%, transparent);
|
|
163162
|
+
color: var(--sp-fg);
|
|
162705
163163
|
}
|
|
162706
|
-
|
|
162707
|
-
|
|
163164
|
+
.sp-chip.on .sp-icon {
|
|
163165
|
+
color: var(--sp-focus-border);
|
|
163166
|
+
}
|
|
163167
|
+
.sp-chip:focus-visible {
|
|
163168
|
+
outline: 1px solid var(--sp-focus-border);
|
|
163169
|
+
outline-offset: 1px;
|
|
163170
|
+
}
|
|
163171
|
+
.sp-chip-label {
|
|
162708
163172
|
min-width: 0;
|
|
162709
163173
|
overflow: hidden;
|
|
162710
163174
|
text-overflow: ellipsis;
|
|
162711
163175
|
white-space: nowrap;
|
|
162712
163176
|
}
|
|
162713
163177
|
|
|
162714
|
-
.sp-active-file-state {
|
|
162715
|
-
color: var(--sp-muted-fg);
|
|
162716
|
-
flex-shrink: 0;
|
|
162717
|
-
}
|
|
162718
|
-
|
|
162719
|
-
/* Sibling of the file chip: states whether the tab list is narrowed to that file,
|
|
162720
|
-
and switches it. Quiet by default so it reads as status until hovered. */
|
|
162721
|
-
.sp-active-file-toggle {
|
|
162722
|
-
flex-shrink: 0;
|
|
162723
|
-
margin-right: 8px;
|
|
162724
|
-
padding: 2px 6px;
|
|
162725
|
-
border: 1px solid transparent;
|
|
162726
|
-
border-radius: var(--sp-radius);
|
|
162727
|
-
background: var(--sp-badge-bg);
|
|
162728
|
-
color: var(--sp-muted-fg);
|
|
162729
|
-
font: inherit;
|
|
162730
|
-
font-size: 11px;
|
|
162731
|
-
cursor: pointer;
|
|
162732
|
-
opacity: 0.9;
|
|
162733
|
-
}
|
|
162734
|
-
|
|
162735
|
-
.sp-active-file-toggle.on {
|
|
162736
|
-
color: var(--sp-badge-fg);
|
|
162737
|
-
}
|
|
162738
|
-
|
|
162739
|
-
.sp-active-file-toggle:hover {
|
|
162740
|
-
opacity: 1;
|
|
162741
|
-
border-color: var(--sp-focus-border);
|
|
162742
|
-
}
|
|
162743
|
-
|
|
162744
163178
|
.sp-tab {
|
|
162745
163179
|
display: flex;
|
|
162746
163180
|
align-items: center;
|
|
162747
|
-
gap:
|
|
162748
|
-
padding: 0 10px;
|
|
162749
|
-
height:
|
|
163181
|
+
gap: 6px;
|
|
163182
|
+
padding: 0 10px 0 12px;
|
|
163183
|
+
height: 30px;
|
|
162750
163184
|
cursor: pointer;
|
|
162751
163185
|
white-space: nowrap;
|
|
162752
163186
|
border-bottom: 2px solid transparent;
|
|
@@ -162917,8 +163351,8 @@ body {
|
|
|
162917
163351
|
padding: 0 10px;
|
|
162918
163352
|
border-bottom: 1px solid var(--sp-border);
|
|
162919
163353
|
flex-shrink: 0;
|
|
162920
|
-
height:
|
|
162921
|
-
background: var(--sp-
|
|
163354
|
+
height: 32px;
|
|
163355
|
+
background: var(--sp-bg);
|
|
162922
163356
|
gap: 8px;
|
|
162923
163357
|
}
|
|
162924
163358
|
|
|
@@ -162961,36 +163395,62 @@ body {
|
|
|
162961
163395
|
.sp-btn {
|
|
162962
163396
|
display: inline-flex;
|
|
162963
163397
|
align-items: center;
|
|
162964
|
-
|
|
162965
|
-
|
|
162966
|
-
|
|
163398
|
+
justify-content: center;
|
|
163399
|
+
gap: 5px;
|
|
163400
|
+
height: 24px;
|
|
163401
|
+
padding: 0 8px;
|
|
163402
|
+
font-size: 12px;
|
|
163403
|
+
font-weight: 500;
|
|
162967
163404
|
font-family: var(--sp-font);
|
|
162968
163405
|
cursor: pointer;
|
|
162969
|
-
border:
|
|
163406
|
+
border: 1px solid transparent;
|
|
162970
163407
|
border-radius: var(--sp-radius);
|
|
162971
163408
|
background: var(--sp-btn-sec-bg);
|
|
162972
163409
|
color: var(--sp-btn-sec-fg);
|
|
162973
163410
|
white-space: nowrap;
|
|
162974
|
-
transition:
|
|
162975
|
-
|
|
163411
|
+
transition:
|
|
163412
|
+
background 0.1s,
|
|
163413
|
+
color 0.1s,
|
|
163414
|
+
border-color 0.1s;
|
|
163415
|
+
line-height: 1;
|
|
162976
163416
|
}
|
|
162977
163417
|
.sp-btn:hover:not(:disabled) {
|
|
162978
163418
|
background: var(--sp-btn-sec-hover);
|
|
162979
163419
|
}
|
|
163420
|
+
.sp-btn:focus-visible {
|
|
163421
|
+
outline: 1px solid var(--sp-focus-border);
|
|
163422
|
+
outline-offset: 1px;
|
|
163423
|
+
}
|
|
162980
163424
|
.sp-btn:disabled {
|
|
162981
163425
|
opacity: 0.4;
|
|
162982
163426
|
cursor: default;
|
|
162983
163427
|
}
|
|
163428
|
+
.sp-btn .sp-icon {
|
|
163429
|
+
flex-shrink: 0;
|
|
163430
|
+
}
|
|
162984
163431
|
|
|
162985
163432
|
.sp-btn-primary {
|
|
162986
163433
|
background: var(--sp-btn-bg);
|
|
162987
163434
|
color: var(--sp-btn-fg);
|
|
162988
|
-
font-weight: 500;
|
|
162989
163435
|
}
|
|
162990
163436
|
.sp-btn-primary:hover:not(:disabled) {
|
|
162991
163437
|
background: var(--sp-btn-hover);
|
|
162992
163438
|
}
|
|
162993
163439
|
|
|
163440
|
+
.sp-btn-ghost {
|
|
163441
|
+
background: transparent;
|
|
163442
|
+
color: var(--sp-fg);
|
|
163443
|
+
}
|
|
163444
|
+
.sp-btn-ghost .sp-icon {
|
|
163445
|
+
color: var(--sp-muted-fg);
|
|
163446
|
+
}
|
|
163447
|
+
.sp-btn-ghost:hover:not(:disabled) {
|
|
163448
|
+
background: var(--sp-hover-bg);
|
|
163449
|
+
}
|
|
163450
|
+
.sp-btn-ghost:hover:not(:disabled) .sp-icon {
|
|
163451
|
+
color: var(--sp-fg);
|
|
163452
|
+
}
|
|
163453
|
+
|
|
162994
163454
|
.sp-btn-danger {
|
|
162995
163455
|
background: var(--sp-btn-danger-bg);
|
|
162996
163456
|
color: var(--sp-btn-danger-fg);
|
|
@@ -163060,14 +163520,14 @@ body {
|
|
|
163060
163520
|
.sp-icon-btn:hover {
|
|
163061
163521
|
color: var(--sp-fg);
|
|
163062
163522
|
background: var(--sp-hover-bg);
|
|
163063
|
-
|
|
163523
|
+
}
|
|
163524
|
+
.sp-icon-btn:focus-visible {
|
|
163525
|
+
outline: 1px solid var(--sp-focus-border);
|
|
163526
|
+
outline-offset: -1px;
|
|
163064
163527
|
}
|
|
163065
163528
|
.sp-icon-btn.active {
|
|
163066
|
-
color: var(--sp-
|
|
163529
|
+
color: var(--sp-fg);
|
|
163067
163530
|
background: var(--sp-hover-bg);
|
|
163068
|
-
border-color: transparent !important;
|
|
163069
|
-
outline: none !important;
|
|
163070
|
-
box-shadow: none !important;
|
|
163071
163531
|
}
|
|
163072
163532
|
|
|
163073
163533
|
/* ── Grid container ────────────────────────────────────────── */
|
|
@@ -163084,19 +163544,22 @@ body {
|
|
|
163084
163544
|
.sp-loading {
|
|
163085
163545
|
display: flex;
|
|
163086
163546
|
flex-direction: column;
|
|
163087
|
-
align-items: center;
|
|
163088
|
-
justify-content: center;
|
|
163089
163547
|
height: 100%;
|
|
163090
|
-
gap: 12px;
|
|
163091
163548
|
color: var(--sp-muted-fg);
|
|
163092
163549
|
font-size: 13px;
|
|
163093
163550
|
}
|
|
163551
|
+
.sp-loading .sp-empty-state {
|
|
163552
|
+
flex: 1;
|
|
163553
|
+
height: auto;
|
|
163554
|
+
}
|
|
163094
163555
|
.sp-loading p {
|
|
163095
163556
|
margin: 0;
|
|
163096
163557
|
}
|
|
163097
163558
|
/* Live elapsed readout; tabular digits so the count-up doesn't jitter horizontally. */
|
|
163098
163559
|
.sp-loading-elapsed {
|
|
163099
163560
|
margin-left: 6px;
|
|
163561
|
+
color: var(--sp-muted-fg);
|
|
163562
|
+
font-weight: 400;
|
|
163100
163563
|
font-variant-numeric: tabular-nums;
|
|
163101
163564
|
}
|
|
163102
163565
|
|
|
@@ -163414,9 +163877,40 @@ body {
|
|
|
163414
163877
|
--ag-row-height: 28px;
|
|
163415
163878
|
--ag-header-height: 32px;
|
|
163416
163879
|
--ag-icon-size: 14px;
|
|
163417
|
-
--ag-header-column-separator-display:
|
|
163418
|
-
--ag-header-column-
|
|
163419
|
-
--ag-header-column-
|
|
163880
|
+
--ag-header-column-separator-display: none;
|
|
163881
|
+
--ag-header-column-resize-handle-display: block;
|
|
163882
|
+
--ag-header-column-resize-handle-width: 1px;
|
|
163883
|
+
--ag-header-column-resize-handle-height: 40%;
|
|
163884
|
+
--ag-header-column-resize-handle-color: var(--sp-border);
|
|
163885
|
+
--ag-wrapper-border-radius: 0;
|
|
163886
|
+
--ag-borders: none;
|
|
163887
|
+
--ag-row-border-color: color-mix(in srgb, var(--sp-border) 60%, transparent);
|
|
163888
|
+
}
|
|
163889
|
+
|
|
163890
|
+
.sp-ag-grid .ag-header-cell-resize:hover::after {
|
|
163891
|
+
height: 100%;
|
|
163892
|
+
top: 0;
|
|
163893
|
+
background-color: var(--sp-focus-border);
|
|
163894
|
+
}
|
|
163895
|
+
|
|
163896
|
+
.sp-ag-grid .ag-header-cell-text {
|
|
163897
|
+
font-weight: 600;
|
|
163898
|
+
}
|
|
163899
|
+
|
|
163900
|
+
.sp-ag-grid .ag-header-cell .ag-header-cell-filter-button,
|
|
163901
|
+
.sp-ag-grid .ag-header-cell .ag-sort-indicator-icon {
|
|
163902
|
+
color: var(--sp-muted-fg);
|
|
163903
|
+
}
|
|
163904
|
+
|
|
163905
|
+
.sp-ag-grid .ag-header-cell .ag-header-cell-filter-button {
|
|
163906
|
+
opacity: 0;
|
|
163907
|
+
transition: opacity 0.1s;
|
|
163908
|
+
}
|
|
163909
|
+
|
|
163910
|
+
.sp-ag-grid .ag-header-cell:hover .ag-header-cell-filter-button,
|
|
163911
|
+
.sp-ag-grid .ag-header-cell:focus-within .ag-header-cell-filter-button,
|
|
163912
|
+
.sp-ag-grid .ag-header-cell-filtered .ag-header-cell-filter-button {
|
|
163913
|
+
opacity: 1;
|
|
163420
163914
|
}
|
|
163421
163915
|
|
|
163422
163916
|
.sp-ag-grid .ag-header-cell-filtered {
|
|
@@ -165563,6 +166057,322 @@ body.vscode-high-contrast .ag-theme-quartz {
|
|
|
165563
166057
|
opacity: 0.7;
|
|
165564
166058
|
}
|
|
165565
166059
|
}
|
|
166060
|
+
|
|
166061
|
+
/* ── Primitives: notice ────────────────────────────────────── */
|
|
166062
|
+
.sp-notice {
|
|
166063
|
+
display: flex;
|
|
166064
|
+
align-items: flex-start;
|
|
166065
|
+
gap: 8px;
|
|
166066
|
+
padding: 6px 8px 6px 12px;
|
|
166067
|
+
border-bottom: 1px solid var(--sp-border);
|
|
166068
|
+
background: var(--sp-header-bg);
|
|
166069
|
+
color: var(--sp-fg);
|
|
166070
|
+
font-size: 12px;
|
|
166071
|
+
line-height: 1.45;
|
|
166072
|
+
flex-shrink: 0;
|
|
166073
|
+
}
|
|
166074
|
+
.sp-notice-icon {
|
|
166075
|
+
display: inline-flex;
|
|
166076
|
+
padding-top: 2px;
|
|
166077
|
+
color: var(--sp-muted-fg);
|
|
166078
|
+
flex-shrink: 0;
|
|
166079
|
+
}
|
|
166080
|
+
.sp-notice-error .sp-notice-icon {
|
|
166081
|
+
color: var(--sp-error);
|
|
166082
|
+
}
|
|
166083
|
+
.sp-notice-warning .sp-notice-icon {
|
|
166084
|
+
color: var(--sp-warning);
|
|
166085
|
+
}
|
|
166086
|
+
.sp-notice-info .sp-notice-icon {
|
|
166087
|
+
color: var(--sp-focus-border);
|
|
166088
|
+
}
|
|
166089
|
+
.sp-notice-body {
|
|
166090
|
+
display: flex;
|
|
166091
|
+
flex: 1;
|
|
166092
|
+
flex-direction: column;
|
|
166093
|
+
gap: 2px;
|
|
166094
|
+
min-width: 0;
|
|
166095
|
+
padding-top: 1px;
|
|
166096
|
+
}
|
|
166097
|
+
.sp-notice-title {
|
|
166098
|
+
overflow-wrap: anywhere;
|
|
166099
|
+
}
|
|
166100
|
+
.sp-notice-detail {
|
|
166101
|
+
color: var(--sp-muted-fg);
|
|
166102
|
+
overflow-wrap: anywhere;
|
|
166103
|
+
}
|
|
166104
|
+
.sp-notice-actions {
|
|
166105
|
+
display: flex;
|
|
166106
|
+
align-items: center;
|
|
166107
|
+
gap: 6px;
|
|
166108
|
+
flex-shrink: 0;
|
|
166109
|
+
}
|
|
166110
|
+
.sp-notice-dismiss {
|
|
166111
|
+
width: 22px;
|
|
166112
|
+
height: 22px;
|
|
166113
|
+
flex-shrink: 0;
|
|
166114
|
+
}
|
|
166115
|
+
|
|
166116
|
+
/* ── Primitives: empty state ───────────────────────────────── */
|
|
166117
|
+
.sp-empty-state {
|
|
166118
|
+
display: flex;
|
|
166119
|
+
flex-direction: column;
|
|
166120
|
+
align-items: center;
|
|
166121
|
+
justify-content: center;
|
|
166122
|
+
gap: 6px;
|
|
166123
|
+
height: 100%;
|
|
166124
|
+
padding: 24px;
|
|
166125
|
+
color: var(--sp-muted-fg);
|
|
166126
|
+
font-size: 12px;
|
|
166127
|
+
text-align: center;
|
|
166128
|
+
}
|
|
166129
|
+
.sp-empty-state-icon {
|
|
166130
|
+
display: inline-flex;
|
|
166131
|
+
margin-bottom: 2px;
|
|
166132
|
+
color: var(--sp-muted-fg);
|
|
166133
|
+
}
|
|
166134
|
+
.sp-empty-state-error .sp-empty-state-icon {
|
|
166135
|
+
color: var(--sp-error);
|
|
166136
|
+
}
|
|
166137
|
+
.sp-empty-state-title {
|
|
166138
|
+
color: var(--sp-fg);
|
|
166139
|
+
font-size: 13px;
|
|
166140
|
+
font-weight: 600;
|
|
166141
|
+
}
|
|
166142
|
+
.sp-empty-state-detail {
|
|
166143
|
+
max-width: 60ch;
|
|
166144
|
+
line-height: 1.5;
|
|
166145
|
+
overflow-wrap: anywhere;
|
|
166146
|
+
}
|
|
166147
|
+
.sp-empty-state-detail code,
|
|
166148
|
+
.sp-empty-state-message {
|
|
166149
|
+
display: block;
|
|
166150
|
+
max-height: 40vh;
|
|
166151
|
+
overflow: auto;
|
|
166152
|
+
padding: 8px 10px;
|
|
166153
|
+
border: 1px solid var(--sp-border);
|
|
166154
|
+
border-radius: var(--sp-radius);
|
|
166155
|
+
background: var(--sp-header-bg);
|
|
166156
|
+
color: var(--sp-fg);
|
|
166157
|
+
font-family: var(--sp-font-mono, var(--vscode-editor-font-family, monospace));
|
|
166158
|
+
font-size: calc(var(--sp-font-size) - 1px);
|
|
166159
|
+
text-align: left;
|
|
166160
|
+
white-space: pre-wrap;
|
|
166161
|
+
word-break: break-word;
|
|
166162
|
+
user-select: text;
|
|
166163
|
+
}
|
|
166164
|
+
.sp-empty-state-actions {
|
|
166165
|
+
display: flex;
|
|
166166
|
+
align-items: center;
|
|
166167
|
+
gap: 6px;
|
|
166168
|
+
margin-top: 8px;
|
|
166169
|
+
}
|
|
166170
|
+
.sp-empty-state-meta {
|
|
166171
|
+
font-variant-numeric: tabular-nums;
|
|
166172
|
+
}
|
|
166173
|
+
|
|
166174
|
+
/* ── Primitives: progress ──────────────────────────────────── */
|
|
166175
|
+
@keyframes sp-progress-slide {
|
|
166176
|
+
0% {
|
|
166177
|
+
transform: translateX(-100%);
|
|
166178
|
+
}
|
|
166179
|
+
100% {
|
|
166180
|
+
transform: translateX(400%);
|
|
166181
|
+
}
|
|
166182
|
+
}
|
|
166183
|
+
.sp-progress {
|
|
166184
|
+
position: relative;
|
|
166185
|
+
height: 2px;
|
|
166186
|
+
overflow: hidden;
|
|
166187
|
+
flex-shrink: 0;
|
|
166188
|
+
}
|
|
166189
|
+
.sp-progress-bar {
|
|
166190
|
+
position: absolute;
|
|
166191
|
+
inset: 0 auto 0 0;
|
|
166192
|
+
width: 25%;
|
|
166193
|
+
background: var(--sp-focus-border);
|
|
166194
|
+
animation: sp-progress-slide 1.1s cubic-bezier(0.45, 0, 0.55, 1) infinite;
|
|
166195
|
+
}
|
|
166196
|
+
@keyframes sp-busy-pulse {
|
|
166197
|
+
0%,
|
|
166198
|
+
100% {
|
|
166199
|
+
opacity: 0.35;
|
|
166200
|
+
transform: scale(0.8);
|
|
166201
|
+
}
|
|
166202
|
+
50% {
|
|
166203
|
+
opacity: 1;
|
|
166204
|
+
transform: scale(1);
|
|
166205
|
+
}
|
|
166206
|
+
}
|
|
166207
|
+
.sp-busy-dot {
|
|
166208
|
+
display: inline-flex;
|
|
166209
|
+
align-items: center;
|
|
166210
|
+
justify-content: center;
|
|
166211
|
+
width: 8px;
|
|
166212
|
+
height: 8px;
|
|
166213
|
+
flex-shrink: 0;
|
|
166214
|
+
}
|
|
166215
|
+
.sp-busy-dot > span {
|
|
166216
|
+
width: 6px;
|
|
166217
|
+
height: 6px;
|
|
166218
|
+
border-radius: 50%;
|
|
166219
|
+
background: var(--sp-focus-border);
|
|
166220
|
+
animation: sp-busy-pulse 1s ease-in-out infinite;
|
|
166221
|
+
}
|
|
166222
|
+
@media (prefers-reduced-motion: reduce) {
|
|
166223
|
+
.sp-progress-bar {
|
|
166224
|
+
width: 100%;
|
|
166225
|
+
animation: none;
|
|
166226
|
+
opacity: 0.6;
|
|
166227
|
+
}
|
|
166228
|
+
.sp-busy-dot > span {
|
|
166229
|
+
animation: none;
|
|
166230
|
+
}
|
|
166231
|
+
}
|
|
166232
|
+
|
|
166233
|
+
/* ── Primitives: page header ───────────────────────────────── */
|
|
166234
|
+
.sp-page-header {
|
|
166235
|
+
display: flex;
|
|
166236
|
+
align-items: center;
|
|
166237
|
+
gap: 6px;
|
|
166238
|
+
min-height: 35px;
|
|
166239
|
+
padding: 0 10px;
|
|
166240
|
+
border-bottom: 1px solid var(--sp-border);
|
|
166241
|
+
background: var(--sp-header-bg);
|
|
166242
|
+
flex-shrink: 0;
|
|
166243
|
+
}
|
|
166244
|
+
.sp-page-back {
|
|
166245
|
+
display: inline-flex;
|
|
166246
|
+
align-items: center;
|
|
166247
|
+
gap: 4px;
|
|
166248
|
+
height: 24px;
|
|
166249
|
+
padding: 0 6px;
|
|
166250
|
+
border: none;
|
|
166251
|
+
border-radius: var(--sp-radius);
|
|
166252
|
+
background: transparent;
|
|
166253
|
+
color: var(--sp-muted-fg);
|
|
166254
|
+
font: inherit;
|
|
166255
|
+
font-size: 12px;
|
|
166256
|
+
cursor: pointer;
|
|
166257
|
+
}
|
|
166258
|
+
.sp-page-back:hover {
|
|
166259
|
+
color: var(--sp-fg);
|
|
166260
|
+
background: var(--sp-hover-bg);
|
|
166261
|
+
}
|
|
166262
|
+
.sp-page-back:focus-visible {
|
|
166263
|
+
outline: 1px solid var(--sp-focus-border);
|
|
166264
|
+
outline-offset: -1px;
|
|
166265
|
+
}
|
|
166266
|
+
.sp-page-header-sep {
|
|
166267
|
+
color: var(--sp-border);
|
|
166268
|
+
}
|
|
166269
|
+
.sp-page-title {
|
|
166270
|
+
margin: 0;
|
|
166271
|
+
font-size: 13px;
|
|
166272
|
+
font-weight: 600;
|
|
166273
|
+
color: var(--sp-fg);
|
|
166274
|
+
white-space: nowrap;
|
|
166275
|
+
overflow: hidden;
|
|
166276
|
+
text-overflow: ellipsis;
|
|
166277
|
+
}
|
|
166278
|
+
.sp-page-meta {
|
|
166279
|
+
display: flex;
|
|
166280
|
+
align-items: center;
|
|
166281
|
+
gap: 6px;
|
|
166282
|
+
}
|
|
166283
|
+
.sp-page-actions {
|
|
166284
|
+
display: flex;
|
|
166285
|
+
align-items: center;
|
|
166286
|
+
gap: 6px;
|
|
166287
|
+
margin-left: auto;
|
|
166288
|
+
}
|
|
166289
|
+
|
|
166290
|
+
/* ── Result toolbar ────────────────────────────────────────── */
|
|
166291
|
+
.sp-toolbar-sep {
|
|
166292
|
+
width: 1px;
|
|
166293
|
+
height: 14px;
|
|
166294
|
+
margin: 0 4px;
|
|
166295
|
+
background: var(--sp-border);
|
|
166296
|
+
flex-shrink: 0;
|
|
166297
|
+
}
|
|
166298
|
+
|
|
166299
|
+
/* ── Primitives: segmented control ─────────────────────────── */
|
|
166300
|
+
.sp-segmented {
|
|
166301
|
+
display: inline-flex;
|
|
166302
|
+
padding: 2px;
|
|
166303
|
+
gap: 2px;
|
|
166304
|
+
border: 1px solid var(--sp-border);
|
|
166305
|
+
border-radius: calc(var(--sp-radius) + 2px);
|
|
166306
|
+
background: var(--sp-bg);
|
|
166307
|
+
flex-shrink: 0;
|
|
166308
|
+
}
|
|
166309
|
+
.sp-segmented-item {
|
|
166310
|
+
height: 22px;
|
|
166311
|
+
padding: 0 8px;
|
|
166312
|
+
border: none;
|
|
166313
|
+
border-radius: var(--sp-radius);
|
|
166314
|
+
background: transparent;
|
|
166315
|
+
color: var(--sp-muted-fg);
|
|
166316
|
+
font: inherit;
|
|
166317
|
+
font-size: 12px;
|
|
166318
|
+
cursor: pointer;
|
|
166319
|
+
white-space: nowrap;
|
|
166320
|
+
transition:
|
|
166321
|
+
background 0.1s,
|
|
166322
|
+
color 0.1s;
|
|
166323
|
+
}
|
|
166324
|
+
.sp-segmented-item:hover {
|
|
166325
|
+
color: var(--sp-fg);
|
|
166326
|
+
}
|
|
166327
|
+
.sp-segmented-item.active {
|
|
166328
|
+
background: var(--sp-header-bg);
|
|
166329
|
+
color: var(--sp-fg);
|
|
166330
|
+
font-weight: 600;
|
|
166331
|
+
box-shadow: inset 0 0 0 1px var(--sp-border);
|
|
166332
|
+
}
|
|
166333
|
+
.sp-segmented-item:focus-visible {
|
|
166334
|
+
outline: 1px solid var(--sp-focus-border);
|
|
166335
|
+
outline-offset: -1px;
|
|
166336
|
+
}
|
|
166337
|
+
/* ── Connection subpage ── */
|
|
166338
|
+
.sp-settings-page-body.sp-settings-page-body-subpage {
|
|
166339
|
+
padding: 0;
|
|
166340
|
+
overflow: hidden;
|
|
166341
|
+
}
|
|
166342
|
+
|
|
166343
|
+
.sp-settings-conn-panel-subpage,
|
|
166344
|
+
.sp-conn-subpage {
|
|
166345
|
+
display: flex;
|
|
166346
|
+
flex: 1;
|
|
166347
|
+
flex-direction: column;
|
|
166348
|
+
min-height: 0;
|
|
166349
|
+
height: 100%;
|
|
166350
|
+
}
|
|
166351
|
+
|
|
166352
|
+
.sp-conn-subpage {
|
|
166353
|
+
width: 100%;
|
|
166354
|
+
}
|
|
166355
|
+
|
|
166356
|
+
.sp-conn-subpage-body {
|
|
166357
|
+
flex: 1;
|
|
166358
|
+
min-height: 0;
|
|
166359
|
+
overflow-y: auto;
|
|
166360
|
+
padding: 24px 32px 32px;
|
|
166361
|
+
}
|
|
166362
|
+
|
|
166363
|
+
.sp-conn-subpage-column {
|
|
166364
|
+
display: block;
|
|
166365
|
+
max-width: 720px;
|
|
166366
|
+
margin-inline: auto;
|
|
166367
|
+
}
|
|
166368
|
+
|
|
166369
|
+
.sp-conn-subpage .sp-conn-detail-body {
|
|
166370
|
+
padding: 0;
|
|
166371
|
+
}
|
|
166372
|
+
|
|
166373
|
+
.sp-conn-schema-error {
|
|
166374
|
+
color: var(--sp-error);
|
|
166375
|
+
}
|
|
165566
166376
|
@font-face {
|
|
165567
166377
|
font-family: 'Manrope';
|
|
165568
166378
|
src: url('data:font/woff2;base64,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') format('woff2');
|
|
@@ -166186,6 +166996,18 @@ body {
|
|
|
166186
166996
|
font-size: 21px;
|
|
166187
166997
|
font-weight: 600;
|
|
166188
166998
|
}
|
|
166999
|
+
.sp-web-beta-badge {
|
|
167000
|
+
align-self: center;
|
|
167001
|
+
margin-left: 8px;
|
|
167002
|
+
padding: 2px 6px;
|
|
167003
|
+
border: 1px solid var(--sp-focus-border, var(--grain-accent));
|
|
167004
|
+
border-radius: 4px;
|
|
167005
|
+
color: var(--sp-focus-border, var(--grain-accent));
|
|
167006
|
+
font-size: 11px;
|
|
167007
|
+
font-weight: 600;
|
|
167008
|
+
letter-spacing: 0.04em;
|
|
167009
|
+
text-transform: uppercase;
|
|
167010
|
+
}
|
|
166189
167011
|
.sp-web-header-divider {
|
|
166190
167012
|
width: 1px;
|
|
166191
167013
|
height: 22px;
|
|
@@ -166233,6 +167055,32 @@ body {
|
|
|
166233
167055
|
gap: 10px;
|
|
166234
167056
|
padding: 9px 10px;
|
|
166235
167057
|
font-size: 12px;
|
|
167058
|
+
width: 100%;
|
|
167059
|
+
border: 0;
|
|
167060
|
+
background: transparent;
|
|
167061
|
+
color: var(--sp-fg);
|
|
167062
|
+
text-align: left;
|
|
167063
|
+
cursor: pointer;
|
|
167064
|
+
}
|
|
167065
|
+
.sp-web-connection-item:hover {
|
|
167066
|
+
background: var(--sp-sidebar-bg);
|
|
167067
|
+
}
|
|
167068
|
+
.sp-web-connection-item:focus-visible {
|
|
167069
|
+
outline: 1px solid var(--sp-accent);
|
|
167070
|
+
}
|
|
167071
|
+
.sp-web-connection-detail {
|
|
167072
|
+
padding: 16px;
|
|
167073
|
+
}
|
|
167074
|
+
.sp-web-connection-detail h2 {
|
|
167075
|
+
margin: 0 0 8px;
|
|
167076
|
+
font-size: 13px;
|
|
167077
|
+
}
|
|
167078
|
+
.sp-web-connection-detail p {
|
|
167079
|
+
color: var(--sp-fg-muted);
|
|
167080
|
+
}
|
|
167081
|
+
.sp-web-connection-actions {
|
|
167082
|
+
display: flex;
|
|
167083
|
+
gap: 8px;
|
|
166236
167084
|
}
|
|
166237
167085
|
.sp-web-connection-item small {
|
|
166238
167086
|
display: block;
|
|
@@ -166504,6 +167352,44 @@ body {
|
|
|
166504
167352
|
--ag-input-background-color: var(--grain-ground);
|
|
166505
167353
|
--ag-input-foreground-color: var(--grain-ink);
|
|
166506
167354
|
--ag-input-border-color: var(--grain-border-subtle);
|
|
167355
|
+
}
|
|
167356
|
+
.sp-web-reauth-action {
|
|
167357
|
+
display: flex;
|
|
167358
|
+
align-items: center;
|
|
167359
|
+
gap: 8px;
|
|
167360
|
+
}
|
|
167361
|
+
.sp-web-reauth-detail {
|
|
167362
|
+
color: var(--sp-muted);
|
|
167363
|
+
font-size: 12px;
|
|
167364
|
+
}
|
|
167365
|
+
.sp-web-connection-item {
|
|
167366
|
+
width: 100%;
|
|
167367
|
+
border: 0;
|
|
167368
|
+
background: transparent;
|
|
167369
|
+
color: var(--grain-ink);
|
|
167370
|
+
font: inherit;
|
|
167371
|
+
text-align: left;
|
|
167372
|
+
cursor: pointer;
|
|
167373
|
+
}
|
|
167374
|
+
.sp-web-connection-item:hover,
|
|
167375
|
+
.sp-web-connection-item:focus-visible {
|
|
167376
|
+
background: var(--grain-surface);
|
|
167377
|
+
outline: 1px solid var(--grain-accent);
|
|
167378
|
+
}
|
|
167379
|
+
.sp-web-connection-detail {
|
|
167380
|
+
padding: 24px;
|
|
167381
|
+
}
|
|
167382
|
+
.sp-web-connection-detail h1 {
|
|
167383
|
+
margin: 0 0 8px;
|
|
167384
|
+
font-size: 18px;
|
|
167385
|
+
}
|
|
167386
|
+
.sp-web-connection-detail p {
|
|
167387
|
+
color: var(--grain-ink-muted);
|
|
167388
|
+
}
|
|
167389
|
+
.sp-web-connection-actions {
|
|
167390
|
+
display: flex;
|
|
167391
|
+
gap: 8px;
|
|
167392
|
+
margin-top: 16px;
|
|
166507
167393
|
}</style>
|
|
166508
167394
|
</head>
|
|
166509
167395
|
<body>
|